[ Index ]

PHP Cross Reference of Joomla 4.2.2 documentation

title

Body

[close]

/administrator/components/com_installer/src/Model/ -> UpdatesitesModel.php (source)

   1  <?php
   2  
   3  /**
   4   * @package     Joomla.Administrator
   5   * @subpackage  com_installer
   6   *
   7   * @copyright   (C) 2014 Open Source Matters, Inc. <https://www.joomla.org>
   8   * @license     GNU General Public License version 2 or later; see LICENSE.txt
   9   */
  10  
  11  namespace Joomla\Component\Installer\Administrator\Model;
  12  
  13  use Exception;
  14  use Joomla\CMS\Factory;
  15  use Joomla\CMS\Filesystem\Folder;
  16  use Joomla\CMS\Installer\Installer;
  17  use Joomla\CMS\Language\Text;
  18  use Joomla\CMS\MVC\Factory\MVCFactoryInterface;
  19  use Joomla\CMS\Object\CMSObject;
  20  use Joomla\CMS\Plugin\PluginHelper;
  21  use Joomla\CMS\Router\Route;
  22  use Joomla\CMS\Table\UpdateSite as UpdateSiteTable;
  23  use Joomla\Component\Installer\Administrator\Helper\InstallerHelper;
  24  use Joomla\Database\ParameterType;
  25  use RuntimeException;
  26  
  27  // phpcs:disable PSR1.Files.SideEffects
  28  \defined('_JEXEC') or die;
  29  // phpcs:enable PSR1.Files.SideEffects
  30  
  31  /**
  32   * Installer Update Sites Model
  33   *
  34   * @since  3.4
  35   */
  36  class UpdatesitesModel extends InstallerModel
  37  {
  38      /**
  39       * Constructor.
  40       *
  41       * @param   array                $config   An optional associative array of configuration settings.
  42       * @param   MVCFactoryInterface  $factory  The factory.
  43       *
  44       * @since   1.6
  45       * @see     \Joomla\CMS\MVC\Model\ListModel
  46       */
  47      public function __construct($config = [], MVCFactoryInterface $factory = null)
  48      {
  49          if (empty($config['filter_fields'])) {
  50              $config['filter_fields'] = [
  51                  'update_site_name',
  52                  'name',
  53                  'client_id',
  54                  'client',
  55                  'client_translated',
  56                  'status',
  57                  'type',
  58                  'type_translated',
  59                  'folder',
  60                  'folder_translated',
  61                  'update_site_id',
  62                  'enabled',
  63                  'supported'
  64              ];
  65          }
  66  
  67          parent::__construct($config, $factory);
  68      }
  69  
  70      /**
  71       * Enable/Disable an extension.
  72       *
  73       * @param   array  $eid    Extension ids to un/publish
  74       * @param   int    $value  Publish value
  75       *
  76       * @return  boolean  True on success
  77       *
  78       * @throws  Exception on ACL error
  79       * @since   3.4
  80       *
  81       */
  82      public function publish(&$eid = [], $value = 1)
  83      {
  84          if (!Factory::getUser()->authorise('core.edit.state', 'com_installer')) {
  85              throw new Exception(Text::_('JLIB_APPLICATION_ERROR_EDITSTATE_NOT_PERMITTED'), 403);
  86          }
  87  
  88          $result = true;
  89  
  90          // Ensure eid is an array of extension ids
  91          if (!is_array($eid)) {
  92              $eid = [$eid];
  93          }
  94  
  95          // Get a table object for the extension type
  96          $table = new UpdateSiteTable($this->getDatabase());
  97  
  98          // Enable the update site in the table and store it in the database
  99          foreach ($eid as $i => $id) {
 100              $table->load($id);
 101              $table->enabled = $value;
 102  
 103              if (!$table->store()) {
 104                  $this->setError($table->getError());
 105                  $result = false;
 106              }
 107          }
 108  
 109          return $result;
 110      }
 111  
 112      /**
 113       * Deletes an update site.
 114       *
 115       * @param   array  $ids  Extension ids to delete.
 116       *
 117       * @return  void
 118       *
 119       * @throws  Exception on ACL error
 120       * @since   3.6
 121       *
 122       */
 123      public function delete($ids = [])
 124      {
 125          if (!Factory::getUser()->authorise('core.delete', 'com_installer')) {
 126              throw new Exception(Text::_('JLIB_APPLICATION_ERROR_DELETE_NOT_PERMITTED'), 403);
 127          }
 128  
 129          // Ensure eid is an array of extension ids
 130          if (!is_array($ids)) {
 131              $ids = [$ids];
 132          }
 133  
 134          $db  = $this->getDatabase();
 135          $app = Factory::getApplication();
 136  
 137          $count = 0;
 138  
 139          // Gets the update site names.
 140          $query = $db->getQuery(true)
 141              ->select($db->quoteName(['update_site_id', 'name']))
 142              ->from($db->quoteName('#__update_sites'))
 143              ->whereIn($db->quoteName('update_site_id'), $ids);
 144          $db->setQuery($query);
 145          $updateSitesNames = $db->loadObjectList('update_site_id');
 146  
 147          // Gets Joomla core update sites Ids.
 148          $joomlaUpdateSitesIds = $this->getJoomlaUpdateSitesIds(0);
 149  
 150          // Enable the update site in the table and store it in the database
 151          foreach ($ids as $i => $id) {
 152              // Don't allow to delete Joomla Core update sites.
 153              if (in_array((int) $id, $joomlaUpdateSitesIds)) {
 154                  $app->enqueueMessage(Text::sprintf('COM_INSTALLER_MSG_UPDATESITES_DELETE_CANNOT_DELETE', $updateSitesNames[$id]->name), 'error');
 155                  continue;
 156              }
 157  
 158              // Delete the update site from all tables.
 159              try {
 160                  $id = (int) $id;
 161                  $query = $db->getQuery(true)
 162                      ->delete($db->quoteName('#__update_sites'))
 163                      ->where($db->quoteName('update_site_id') . ' = :id')
 164                      ->bind(':id', $id, ParameterType::INTEGER);
 165                  $db->setQuery($query);
 166                  $db->execute();
 167  
 168                  $query = $db->getQuery(true)
 169                      ->delete($db->quoteName('#__update_sites_extensions'))
 170                      ->where($db->quoteName('update_site_id') . ' = :id')
 171                      ->bind(':id', $id, ParameterType::INTEGER);
 172                  $db->setQuery($query);
 173                  $db->execute();
 174  
 175                  $query = $db->getQuery(true)
 176                      ->delete($db->quoteName('#__updates'))
 177                      ->where($db->quoteName('update_site_id') . ' = :id')
 178                      ->bind(':id', $id, ParameterType::INTEGER);
 179                  $db->setQuery($query);
 180                  $db->execute();
 181  
 182                  $count++;
 183              } catch (RuntimeException $e) {
 184                  $app->enqueueMessage(
 185                      Text::sprintf(
 186                          'COM_INSTALLER_MSG_UPDATESITES_DELETE_ERROR',
 187                          $updateSitesNames[$id]->name,
 188                          $e->getMessage()
 189                      ),
 190                      'error'
 191                  );
 192              }
 193          }
 194  
 195          if ($count > 0) {
 196              $app->enqueueMessage(Text::plural('COM_INSTALLER_MSG_UPDATESITES_N_DELETE_UPDATESITES_DELETED', $count), 'message');
 197          }
 198      }
 199  
 200      /**
 201       * Fetch the Joomla update sites ids.
 202       *
 203       * @param   integer  $column  Column to return. 0 for update site ids, 1 for extension ids.
 204       *
 205       * @return  array  Array with joomla core update site ids.
 206       *
 207       * @since   3.6.0
 208       */
 209      protected function getJoomlaUpdateSitesIds($column = 0)
 210      {
 211          $db = $this->getDatabase();
 212  
 213          // Fetch the Joomla core update sites ids and their extension ids. We search for all except the core joomla extension with update sites.
 214          $query = $db->getQuery(true)
 215              ->select($db->quoteName(['use.update_site_id', 'e.extension_id']))
 216              ->from($db->quoteName('#__update_sites_extensions', 'use'))
 217              ->join(
 218                  'LEFT',
 219                  $db->quoteName('#__update_sites', 'us'),
 220                  $db->quoteName('us.update_site_id') . ' = ' . $db->quoteName('use.update_site_id')
 221              )
 222              ->join(
 223                  'LEFT',
 224                  $db->quoteName('#__extensions', 'e'),
 225                  $db->quoteName('e.extension_id') . ' = ' . $db->quoteName('use.extension_id')
 226              )
 227              ->where('('
 228                  . '(' . $db->quoteName('e.type') . ' = ' . $db->quote('file') .
 229                  ' AND ' . $db->quoteName('e.element') . ' = ' . $db->quote('joomla') . ')'
 230                  . ' OR (' . $db->quoteName('e.type') . ' = ' . $db->quote('package') . ' AND ' . $db->quoteName('e.element')
 231                  . ' = ' . $db->quote('pkg_en-GB') . ') OR (' . $db->quoteName('e.type') . ' = ' . $db->quote('component')
 232                  . ' AND ' . $db->quoteName('e.element') . ' = ' . $db->quote('com_joomlaupdate') . ')'
 233                  . ')');
 234  
 235          $db->setQuery($query);
 236  
 237          return $db->loadColumn($column);
 238      }
 239  
 240      /**
 241       * Rebuild update sites tables.
 242       *
 243       * @return  void
 244       *
 245       * @throws  Exception on ACL error
 246       * @since   3.6
 247       *
 248       */
 249      public function rebuild(): void
 250      {
 251          if (!Factory::getUser()->authorise('core.admin', 'com_installer')) {
 252              throw new Exception(Text::_('COM_INSTALLER_MSG_UPDATESITES_REBUILD_NOT_PERMITTED'), 403);
 253          }
 254  
 255          $db  = $this->getDatabase();
 256          $app = Factory::getApplication();
 257  
 258          // Check if Joomla Extension plugin is enabled.
 259          if (!PluginHelper::isEnabled('extension', 'joomla')) {
 260              $query = $db->getQuery(true)
 261                  ->select($db->quoteName('extension_id'))
 262                  ->from($db->quoteName('#__extensions'))
 263                  ->where($db->quoteName('type') . ' = ' . $db->quote('plugin'))
 264                  ->where($db->quoteName('element') . ' = ' . $db->quote('joomla'))
 265                  ->where($db->quoteName('folder') . ' = ' . $db->quote('extension'));
 266              $db->setQuery($query);
 267  
 268              $pluginId = (int) $db->loadResult();
 269  
 270              $link = Route::_('index.php?option=com_plugins&task=plugin.edit&extension_id=' . $pluginId);
 271              $app->enqueueMessage(Text::sprintf('COM_INSTALLER_MSG_UPDATESITES_REBUILD_EXTENSION_PLUGIN_NOT_ENABLED', $link), 'error');
 272  
 273              return;
 274          }
 275  
 276          $clients               = [JPATH_SITE, JPATH_ADMINISTRATOR, JPATH_API];
 277          $extensionGroupFolders = ['components', 'modules', 'plugins', 'templates', 'language', 'manifests'];
 278  
 279          $pathsToSearch = [];
 280  
 281          // Identifies which folders to search for manifest files.
 282          foreach ($clients as $clientPath) {
 283              foreach ($extensionGroupFolders as $extensionGroupFolderName) {
 284                  // Components, modules, plugins, templates, languages and manifest (files, libraries, etc)
 285                  if ($extensionGroupFolderName !== 'plugins') {
 286                      foreach (glob($clientPath . '/' . $extensionGroupFolderName . '/*', GLOB_NOSORT | GLOB_ONLYDIR) as $extensionFolderPath) {
 287                          $pathsToSearch[] = $extensionFolderPath;
 288                      }
 289                  } else {
 290                      // Plugins (another directory level is needed)
 291                      foreach (
 292                          glob(
 293                              $clientPath . '/' . $extensionGroupFolderName . '/*',
 294                              GLOB_NOSORT | GLOB_ONLYDIR
 295                          ) as $pluginGroupFolderPath
 296                      ) {
 297                          foreach (glob($pluginGroupFolderPath . '/*', GLOB_NOSORT | GLOB_ONLYDIR) as $extensionFolderPath) {
 298                              $pathsToSearch[] = $extensionFolderPath;
 299                          }
 300                      }
 301                  }
 302              }
 303          }
 304  
 305          // Gets Joomla core update sites Ids.
 306          $joomlaUpdateSitesIds = $this->getJoomlaUpdateSitesIds(0);
 307  
 308          // First backup any custom extra_query for the sites
 309          $query = $db->getQuery(true)
 310              ->select('TRIM(' . $db->quoteName('location') . ') AS ' . $db->quoteName('location') . ', ' . $db->quoteName('extra_query'))
 311              ->from($db->quoteName('#__update_sites'));
 312          $db->setQuery($query);
 313          $backupExtraQuerys = $db->loadAssocList('location');
 314  
 315          // Delete from all tables (except joomla core update sites).
 316          $query = $db->getQuery(true)
 317              ->delete($db->quoteName('#__update_sites'))
 318              ->whereNotIn($db->quoteName('update_site_id'), $joomlaUpdateSitesIds);
 319          $db->setQuery($query);
 320          $db->execute();
 321  
 322          $query = $db->getQuery(true)
 323              ->delete($db->quoteName('#__update_sites_extensions'))
 324              ->whereNotIn($db->quoteName('update_site_id'), $joomlaUpdateSitesIds);
 325          $db->setQuery($query);
 326          $db->execute();
 327  
 328          $query = $db->getQuery(true)
 329              ->delete($db->quoteName('#__updates'))
 330              ->whereNotIn($db->quoteName('update_site_id'), $joomlaUpdateSitesIds);
 331          $db->setQuery($query);
 332          $db->execute();
 333  
 334          $count = 0;
 335  
 336          // Gets Joomla core extension Ids.
 337          $joomlaCoreExtensionIds = $this->getJoomlaUpdateSitesIds(1);
 338  
 339          // Search for updateservers in manifest files inside the folders to search.
 340          foreach ($pathsToSearch as $extensionFolderPath) {
 341              $tmpInstaller = new Installer();
 342              $tmpInstaller->setDatabase($this->getDatabase());
 343  
 344              $tmpInstaller->setPath('source', $extensionFolderPath);
 345  
 346              // Main folder manifests (higher priority)
 347              $parentXmlfiles = Folder::files($tmpInstaller->getPath('source'), '.xml$', false, true);
 348  
 349              // Search for children manifests (lower priority)
 350              $allXmlFiles = Folder::files($tmpInstaller->getPath('source'), '.xml$', 1, true);
 351  
 352              // Create a unique array of files ordered by priority
 353              $xmlfiles = array_unique(array_merge($parentXmlfiles, $allXmlFiles));
 354  
 355              if (!empty($xmlfiles)) {
 356                  foreach ($xmlfiles as $file) {
 357                      // Is it a valid Joomla installation manifest file?
 358                      $manifest = $tmpInstaller->isManifest($file);
 359  
 360                      if ($manifest !== null) {
 361                          /**
 362                           * Search if the extension exists in the extensions table. Excluding Joomla
 363                           * core extensions and discovered but not yet installed extensions.
 364                           */
 365  
 366                          $name    = (string) $manifest->name;
 367                          $pkgName = (string) $manifest->packagename;
 368                          $type    = (string) $manifest['type'];
 369  
 370                          $query = $db->getQuery(true)
 371                              ->select($db->quoteName('extension_id'))
 372                              ->from($db->quoteName('#__extensions'))
 373                              ->where(
 374                                  [
 375                                      $db->quoteName('type') . ' = :type',
 376                                      $db->quoteName('state') . ' != -1',
 377                                  ]
 378                              )
 379                              ->extendWhere(
 380                                  'AND',
 381                                  [
 382                                      $db->quoteName('name') . ' = :name',
 383                                      $db->quoteName('name') . ' = :pkgname',
 384                                  ],
 385                                  'OR'
 386                              )
 387                              ->whereNotIn($db->quoteName('extension_id'), $joomlaCoreExtensionIds)
 388                              ->bind(':name', $name)
 389                              ->bind(':pkgname', $pkgName)
 390                              ->bind(':type', $type);
 391                          $db->setQuery($query);
 392  
 393                          $eid = (int) $db->loadResult();
 394  
 395                          if ($eid && $manifest->updateservers) {
 396                              // Set the manifest object and path
 397                              $tmpInstaller->manifest = $manifest;
 398                              $tmpInstaller->setPath('manifest', $file);
 399  
 400                              // Remove last extra_query as we are in a foreach
 401                              $tmpInstaller->extraQuery = '';
 402  
 403                              if (
 404                                  $tmpInstaller->manifest->updateservers
 405                                  && $tmpInstaller->manifest->updateservers->server
 406                                  && isset($backupExtraQuerys[trim((string) $tmpInstaller->manifest->updateservers->server)])
 407                              ) {
 408                                  $tmpInstaller->extraQuery = $backupExtraQuerys[trim((string) $tmpInstaller->manifest->updateservers->server)]['extra_query'];
 409                              }
 410  
 411                              // Load the extension plugin (if not loaded yet).
 412                              PluginHelper::importPlugin('extension', 'joomla');
 413  
 414                              // Fire the onExtensionAfterUpdate
 415                              $app->triggerEvent('onExtensionAfterUpdate', ['installer' => $tmpInstaller, 'eid' => $eid]);
 416  
 417                              $count++;
 418                          }
 419                      }
 420                  }
 421              }
 422          }
 423  
 424          if ($count > 0) {
 425              $app->enqueueMessage(Text::_('COM_INSTALLER_MSG_UPDATESITES_REBUILD_SUCCESS'), 'message');
 426          } else {
 427              $app->enqueueMessage(Text::_('COM_INSTALLER_MSG_UPDATESITES_REBUILD_MESSAGE'), 'message');
 428          }
 429  
 430          // Flush the system cache to ensure extra_query is correctly loaded next time.
 431          $this->cleanCache('_system');
 432      }
 433  
 434      /**
 435       * Method to get an array of data items.
 436       *
 437       * @return  mixed  An array of data items on success, false on failure.
 438       *
 439       * @since   4.0.0
 440       */
 441      public function getItems()
 442      {
 443          $items = parent::getItems();
 444  
 445          array_walk(
 446              $items,
 447              static function ($item) {
 448                  $data              = new CMSObject($item);
 449                  $item->downloadKey = InstallerHelper::getDownloadKey($data);
 450              }
 451          );
 452  
 453          return $items;
 454      }
 455  
 456      /**
 457       * Method to auto-populate the model state.
 458       *
 459       * Note. Calling getState in this method will result in recursion.
 460       *
 461       * @param   string  $ordering   An optional ordering field.
 462       * @param   string  $direction  An optional direction (asc|desc).
 463       *
 464       * @return  void
 465       *
 466       * @since   3.4
 467       */
 468      protected function populateState($ordering = 'name', $direction = 'asc')
 469      {
 470          // Load the filter state.
 471          $stateKeys = [
 472              'search'    => 'string',
 473              'client_id' => 'int',
 474              'enabled'   => 'string',
 475              'type'      => 'string',
 476              'folder'    => 'string',
 477              'supported' => 'int',
 478          ];
 479  
 480          foreach ($stateKeys as $key => $filterType) {
 481              $stateKey = 'filter.' . $key;
 482  
 483              switch ($filterType) {
 484                  case 'int':
 485                  case 'bool':
 486                      $default = null;
 487                      break;
 488  
 489                  default:
 490                      $default = '';
 491                      break;
 492              }
 493  
 494              $stateValue = $this->getUserStateFromRequest(
 495                  $this->context . '.' . $stateKey,
 496                  'filter_' . $key,
 497                  $default,
 498                  $filterType
 499              );
 500  
 501              $this->setState($stateKey, $stateValue);
 502          }
 503  
 504          parent::populateState($ordering, $direction);
 505      }
 506  
 507      protected function getStoreId($id = '')
 508      {
 509          $id .= ':' . $this->getState('search');
 510          $id .= ':' . $this->getState('client_id');
 511          $id .= ':' . $this->getState('enabled');
 512          $id .= ':' . $this->getState('type');
 513          $id .= ':' . $this->getState('folder');
 514          $id .= ':' . $this->getState('supported');
 515  
 516          return parent::getStoreId($id);
 517      }
 518  
 519      /**
 520       * Method to get the database query
 521       *
 522       * @return  \Joomla\Database\DatabaseQuery  The database query
 523       *
 524       * @since   3.4
 525       */
 526      protected function getListQuery()
 527      {
 528          $db    = $this->getDatabase();
 529          $query = $db->getQuery(true)
 530              ->select(
 531                  $db->quoteName(
 532                      [
 533                          's.update_site_id',
 534                          's.name',
 535                          's.type',
 536                          's.location',
 537                          's.enabled',
 538                          's.checked_out',
 539                          's.checked_out_time',
 540                          's.extra_query',
 541                          'e.extension_id',
 542                          'e.name',
 543                          'e.type',
 544                          'e.element',
 545                          'e.folder',
 546                          'e.client_id',
 547                          'e.state',
 548                          'e.manifest_cache',
 549                          'u.name'
 550                      ],
 551                      [
 552                          'update_site_id',
 553                          'update_site_name',
 554                          'update_site_type',
 555                          'location',
 556                          'enabled',
 557                          'checked_out',
 558                          'checked_out_time',
 559                          'extra_query',
 560                          'extension_id',
 561                          'name',
 562                          'type',
 563                          'element',
 564                          'folder',
 565                          'client_id',
 566                          'state',
 567                          'manifest_cache',
 568                          'editor'
 569                      ]
 570                  )
 571              )
 572              ->from($db->quoteName('#__update_sites', 's'))
 573              ->join(
 574                  'INNER',
 575                  $db->quoteName('#__update_sites_extensions', 'se'),
 576                  $db->quoteName('se.update_site_id') . ' = ' . $db->quoteName('s.update_site_id')
 577              )
 578              ->join(
 579                  'INNER',
 580                  $db->quoteName('#__extensions', 'e'),
 581                  $db->quoteName('e.extension_id') . ' = ' . $db->quoteName('se.extension_id')
 582              )
 583              ->join(
 584                  'LEFT',
 585                  $db->quoteName('#__users', 'u'),
 586                  $db->quoteName('s.checked_out') . ' = ' . $db->quoteName('u.id')
 587              )
 588              ->where($db->quoteName('state') . ' = 0');
 589  
 590          // Process select filters.
 591          $supported = $this->getState('filter.supported');
 592          $enabled   = $this->getState('filter.enabled');
 593          $type      = $this->getState('filter.type');
 594          $clientId  = $this->getState('filter.client_id');
 595          $folder    = $this->getState('filter.folder');
 596  
 597          if ($enabled !== '') {
 598              $enabled = (int) $enabled;
 599              $query->where($db->quoteName('s.enabled') . ' = :enabled')
 600                  ->bind(':enabled', $enabled, ParameterType::INTEGER);
 601          }
 602  
 603          if ($type) {
 604              $query->where($db->quoteName('e.type') . ' = :type')
 605                  ->bind(':type', $type);
 606          }
 607  
 608          if ($clientId !== null && $clientId !== '') {
 609              $clientId = (int) $clientId;
 610              $query->where($db->quoteName('e.client_id') . ' = :clientId')
 611                  ->bind(':clientId', $clientId, ParameterType::INTEGER);
 612          }
 613  
 614          if ($folder !== '' && in_array($type, ['plugin', 'library', ''], true)) {
 615              $folderForBinding = $folder === '*' ? '' : $folder;
 616              $query->where($db->quoteName('e.folder') . ' = :folder')
 617                  ->bind(':folder', $folderForBinding);
 618          }
 619  
 620          // Process search filter (update site id).
 621          $search = $this->getState('filter.search');
 622  
 623          if (!empty($search) && stripos($search, 'id:') === 0) {
 624              $uid = (int) substr($search, 3);
 625              $query->where($db->quoteName('s.update_site_id') . ' = :siteId')
 626                  ->bind(':siteId', $uid, ParameterType::INTEGER);
 627          }
 628  
 629          if (is_numeric($supported)) {
 630              switch ($supported) {
 631                  // Show Update Sites which support Download Keys
 632                  case 1:
 633                      $supportedIDs = InstallerHelper::getDownloadKeySupportedSites($enabled);
 634                      break;
 635  
 636                  // Show Update Sites which are missing Download Keys
 637                  case -1:
 638                      $supportedIDs = InstallerHelper::getDownloadKeyExistsSites(false, $enabled);
 639                      break;
 640  
 641                  // Show Update Sites which have valid Download Keys
 642                  case 2:
 643                      $supportedIDs = InstallerHelper::getDownloadKeyExistsSites(true, $enabled);
 644                      break;
 645              }
 646  
 647              if (!empty($supportedIDs)) {
 648                  // Don't remove array_values(). whereIn expect a zero-based array.
 649                  $query->whereIn($db->qn('s.update_site_id'), array_values($supportedIDs));
 650              } else {
 651                  // In case of an empty list of IDs we apply a fake filter to effectively return no data
 652                  $query->where($db->qn('s.update_site_id') . ' = 0');
 653              }
 654          }
 655  
 656          /**
 657           * Note: The search for name, ordering and pagination are processed by the parent InstallerModel class (in
 658           * extension.php).
 659           */
 660  
 661          return $query;
 662      }
 663  }


Generated: Wed Sep 7 05:41:13 2022 Chilli.vc Blog - For Webmaster,Blog-Writer,System Admin and Domainer