[ Index ]

PHP Cross Reference of Joomla 4.2.2 documentation

title

Body

[close]

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

   1  <?php
   2  
   3  /**
   4   * @package     Joomla.Administrator
   5   * @subpackage  com_installer
   6   *
   7   * @copyright   (C) 2008 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 Joomla\CMS\Changelog\Changelog;
  14  use Joomla\CMS\Extension\ExtensionHelper;
  15  use Joomla\CMS\Factory;
  16  use Joomla\CMS\Installer\Installer;
  17  use Joomla\CMS\Language\Text;
  18  use Joomla\CMS\Layout\FileLayout;
  19  use Joomla\CMS\MVC\Factory\MVCFactoryInterface;
  20  use Joomla\CMS\Plugin\PluginHelper;
  21  use Joomla\CMS\Table\Extension;
  22  use Joomla\Component\Templates\Administrator\Table\StyleTable;
  23  use Joomla\Database\DatabaseQuery;
  24  use Joomla\Database\ParameterType;
  25  
  26  // phpcs:disable PSR1.Files.SideEffects
  27  \defined('_JEXEC') or die;
  28  // phpcs:enable PSR1.Files.SideEffects
  29  
  30  /**
  31   * Installer Manage Model
  32   *
  33   * @since  1.5
  34   */
  35  class ManageModel extends InstallerModel
  36  {
  37      /**
  38       * Constructor.
  39       *
  40       * @param   array                $config   An optional associative array of configuration settings.
  41       * @param   MVCFactoryInterface  $factory  The factory.
  42       *
  43       * @see     \Joomla\CMS\MVC\Model\ListModel
  44       * @since   1.6
  45       */
  46      public function __construct($config = array(), MVCFactoryInterface $factory = null)
  47      {
  48          if (empty($config['filter_fields'])) {
  49              $config['filter_fields'] = array(
  50                  'status',
  51                  'name',
  52                  'client_id',
  53                  'client', 'client_translated',
  54                  'type', 'type_translated',
  55                  'folder', 'folder_translated',
  56                  'package_id',
  57                  'extension_id',
  58                  'creationDate',
  59              );
  60          }
  61  
  62          parent::__construct($config, $factory);
  63      }
  64  
  65      /**
  66       * Method to auto-populate the model state.
  67       *
  68       * Note. Calling getState in this method will result in recursion.
  69       *
  70       * @param   string  $ordering   An optional ordering field.
  71       * @param   string  $direction  An optional direction (asc|desc).
  72       *
  73       * @return  void
  74       *
  75       * @throws  \Exception
  76       *
  77       * @since   1.6
  78       */
  79      protected function populateState($ordering = 'name', $direction = 'asc')
  80      {
  81          $app = Factory::getApplication();
  82  
  83          // Load the filter state.
  84          $this->setState('filter.search', $this->getUserStateFromRequest($this->context . '.filter.search', 'filter_search', '', 'string'));
  85          $this->setState('filter.client_id', $this->getUserStateFromRequest($this->context . '.filter.client_id', 'filter_client_id', null, 'int'));
  86          $this->setState('filter.package_id', $this->getUserStateFromRequest($this->context . '.filter.package_id', 'filter_package_id', null, 'int'));
  87          $this->setState('filter.status', $this->getUserStateFromRequest($this->context . '.filter.status', 'filter_status', '', 'string'));
  88          $this->setState('filter.type', $this->getUserStateFromRequest($this->context . '.filter.type', 'filter_type', '', 'string'));
  89          $this->setState('filter.folder', $this->getUserStateFromRequest($this->context . '.filter.folder', 'filter_folder', '', 'string'));
  90          $this->setState('filter.core', $this->getUserStateFromRequest($this->context . '.filter.core', 'filter_core', '', 'string'));
  91  
  92          $this->setState('message', $app->getUserState('com_installer.message'));
  93          $this->setState('extension_message', $app->getUserState('com_installer.extension_message'));
  94          $app->setUserState('com_installer.message', '');
  95          $app->setUserState('com_installer.extension_message', '');
  96  
  97          parent::populateState($ordering, $direction);
  98      }
  99  
 100      /**
 101       * Enable/Disable an extension.
 102       *
 103       * @param   array  $eid    Extension ids to un/publish
 104       * @param   int    $value  Publish value
 105       *
 106       * @return  boolean  True on success
 107       *
 108       * @throws  \Exception
 109       *
 110       * @since   1.5
 111       */
 112      public function publish(&$eid = array(), $value = 1)
 113      {
 114          if (!Factory::getUser()->authorise('core.edit.state', 'com_installer')) {
 115              Factory::getApplication()->enqueueMessage(Text::_('JLIB_APPLICATION_ERROR_EDITSTATE_NOT_PERMITTED'), 'error');
 116  
 117              return false;
 118          }
 119  
 120          $result = true;
 121  
 122          /*
 123           * Ensure eid is an array of extension ids
 124           * @todo: If it isn't an array do we want to set an error and fail?
 125           */
 126          if (!is_array($eid)) {
 127              $eid = array($eid);
 128          }
 129  
 130          // Get a table object for the extension type
 131          $table = new Extension($this->getDatabase());
 132  
 133          // Enable the extension in the table and store it in the database
 134          foreach ($eid as $i => $id) {
 135              $table->load($id);
 136  
 137              if ($table->type == 'template') {
 138                  $style = new StyleTable($this->getDatabase());
 139  
 140                  if ($style->load(array('template' => $table->element, 'client_id' => $table->client_id, 'home' => 1))) {
 141                      Factory::getApplication()->enqueueMessage(Text::_('COM_INSTALLER_ERROR_DISABLE_DEFAULT_TEMPLATE_NOT_PERMITTED'), 'notice');
 142                      unset($eid[$i]);
 143                      continue;
 144                  }
 145  
 146                  // Parent template cannot be disabled if there are children
 147                  if ($style->load(['parent' => $table->element, 'client_id' => $table->client_id])) {
 148                      Factory::getApplication()->enqueueMessage(Text::_('COM_INSTALLER_ERROR_DISABLE_PARENT_TEMPLATE_NOT_PERMITTED'), 'notice');
 149                      unset($eid[$i]);
 150                      continue;
 151                  }
 152              }
 153  
 154              if ($table->protected == 1) {
 155                  $result = false;
 156                  Factory::getApplication()->enqueueMessage(Text::_('JLIB_APPLICATION_ERROR_EDITSTATE_NOT_PERMITTED'), 'error');
 157              } else {
 158                  $table->enabled = $value;
 159              }
 160  
 161              $context = $this->option . '.' . $this->name;
 162  
 163              PluginHelper::importPlugin('extension');
 164              Factory::getApplication()->triggerEvent('onExtensionChangeState', array($context, $eid, $value));
 165  
 166              if (!$table->store()) {
 167                  $this->setError($table->getError());
 168                  $result = false;
 169              }
 170          }
 171  
 172          // Clear the cached extension data and menu cache
 173          $this->cleanCache('_system');
 174          $this->cleanCache('com_modules');
 175          $this->cleanCache('mod_menu');
 176  
 177          return $result;
 178      }
 179  
 180      /**
 181       * Refreshes the cached manifest information for an extension.
 182       *
 183       * @param   int|int[]  $eid  extension identifier (key in #__extensions)
 184       *
 185       * @return  boolean  result of refresh
 186       *
 187       * @since   1.6
 188       */
 189      public function refresh($eid)
 190      {
 191          if (!is_array($eid)) {
 192              $eid = array($eid => 0);
 193          }
 194  
 195          // Get an installer object for the extension type
 196          $installer = Installer::getInstance();
 197          $result    = 0;
 198  
 199          // Uninstall the chosen extensions
 200          foreach ($eid as $id) {
 201              $result |= $installer->refreshManifestCache($id);
 202          }
 203  
 204          return $result;
 205      }
 206  
 207      /**
 208       * Remove (uninstall) an extension
 209       *
 210       * @param   array  $eid  An array of identifiers
 211       *
 212       * @return  boolean  True on success
 213       *
 214       * @throws  \Exception
 215       *
 216       * @since   1.5
 217       */
 218      public function remove($eid = array())
 219      {
 220          if (!Factory::getUser()->authorise('core.delete', 'com_installer')) {
 221              Factory::getApplication()->enqueueMessage(Text::_('JERROR_CORE_DELETE_NOT_PERMITTED'), 'error');
 222  
 223              return false;
 224          }
 225  
 226          /*
 227           * Ensure eid is an array of extension ids in the form id => client_id
 228           * @todo: If it isn't an array do we want to set an error and fail?
 229           */
 230          if (!is_array($eid)) {
 231              $eid = array($eid => 0);
 232          }
 233  
 234          // Get an installer object for the extension type
 235          $installer = Installer::getInstance();
 236          $row       = new \Joomla\CMS\Table\Extension($this->getDatabase());
 237  
 238          // Uninstall the chosen extensions
 239          $msgs   = array();
 240          $result = false;
 241  
 242          foreach ($eid as $id) {
 243              $id = trim($id);
 244              $row->load($id);
 245              $result = false;
 246  
 247              // Do not allow to uninstall locked extensions.
 248              if ((int) $row->locked === 1) {
 249                  $msgs[] = Text::sprintf('COM_INSTALLER_UNINSTALL_ERROR_LOCKED_EXTENSION', $row->name, $id);
 250  
 251                  continue;
 252              }
 253  
 254              $langstring = 'COM_INSTALLER_TYPE_TYPE_' . strtoupper($row->type);
 255              $rowtype    = Text::_($langstring);
 256  
 257              if (strpos($rowtype, $langstring) !== false) {
 258                  $rowtype = $row->type;
 259              }
 260  
 261              if ($row->type) {
 262                  $result = $installer->uninstall($row->type, $id);
 263  
 264                  // Build an array of extensions that failed to uninstall
 265                  if ($result === false) {
 266                      // There was an error in uninstalling the package
 267                      $msgs[] = Text::sprintf('COM_INSTALLER_UNINSTALL_ERROR', $rowtype);
 268  
 269                      continue;
 270                  }
 271  
 272                  // Package uninstalled successfully
 273                  $msgs[] = Text::sprintf('COM_INSTALLER_UNINSTALL_SUCCESS', $rowtype);
 274                  $result = true;
 275  
 276                  continue;
 277              }
 278  
 279              // There was an error in uninstalling the package
 280              $msgs[] = Text::sprintf('COM_INSTALLER_UNINSTALL_ERROR', $rowtype);
 281          }
 282  
 283          $msg = implode('<br>', $msgs);
 284          $app = Factory::getApplication();
 285          $app->enqueueMessage($msg);
 286          $this->setState('action', 'remove');
 287          $this->setState('name', $installer->get('name'));
 288          $app->setUserState('com_installer.message', $installer->message);
 289          $app->setUserState('com_installer.extension_message', $installer->get('extension_message'));
 290  
 291          // Clear the cached extension data and menu cache
 292          $this->cleanCache('_system');
 293          $this->cleanCache('com_modules');
 294          $this->cleanCache('com_plugins');
 295          $this->cleanCache('mod_menu');
 296  
 297          return $result;
 298      }
 299  
 300      /**
 301       * Method to get the database query
 302       *
 303       * @return  DatabaseQuery  The database query
 304       *
 305       * @since   1.6
 306       */
 307      protected function getListQuery()
 308      {
 309          $db = $this->getDatabase();
 310          $query = $db->getQuery(true)
 311              ->select('*')
 312              ->select('2*protected+(1-protected)*enabled AS status')
 313              ->from('#__extensions')
 314              ->where('state = 0');
 315  
 316          // Process select filters.
 317          $status    = $this->getState('filter.status', '');
 318          $type      = $this->getState('filter.type');
 319          $clientId  = $this->getState('filter.client_id', '');
 320          $folder    = $this->getState('filter.folder');
 321          $core      = $this->getState('filter.core', '');
 322          $packageId = $this->getState('filter.package_id', '');
 323  
 324          if ($status !== '') {
 325              if ($status === '2') {
 326                  $query->where('protected = 1');
 327              } elseif ($status === '3') {
 328                  $query->where('protected = 0');
 329              } else {
 330                  $status = (int) $status;
 331                  $query->where($db->quoteName('protected') . ' = 0')
 332                      ->where($db->quoteName('enabled') . ' = :status')
 333                      ->bind(':status', $status, ParameterType::INTEGER);
 334              }
 335          }
 336  
 337          if ($type) {
 338              $query->where($db->quoteName('type') . ' = :type')
 339                  ->bind(':type', $type);
 340          }
 341  
 342          if ($clientId !== '') {
 343              $clientId = (int) $clientId;
 344              $query->where($db->quoteName('client_id') . ' = :clientid')
 345                  ->bind(':clientid', $clientId, ParameterType::INTEGER);
 346          }
 347  
 348          if ($packageId !== '') {
 349              $packageId = (int) $packageId;
 350              $query->where(
 351                  '((' . $db->quoteName('package_id') . ' = :packageId1) OR '
 352                  . '(' . $db->quoteName('extension_id') . ' = :packageId2))'
 353              )
 354                  ->bind([':packageId1',':packageId2'], $packageId, ParameterType::INTEGER);
 355          }
 356  
 357          if ($folder) {
 358              $folder = $folder === '*' ? '' : $folder;
 359              $query->where($db->quoteName('folder') . ' = :folder')
 360                  ->bind(':folder', $folder);
 361          }
 362  
 363          // Filter by core extensions.
 364          if ($core === '1' || $core === '0') {
 365              $coreExtensionIds = ExtensionHelper::getCoreExtensionIds();
 366              $method = $core === '1' ? 'whereIn' : 'whereNotIn';
 367              $query->$method($db->quoteName('extension_id'), $coreExtensionIds);
 368          }
 369  
 370          // Process search filter (extension id).
 371          $search = $this->getState('filter.search');
 372  
 373          if (!empty($search) && stripos($search, 'id:') === 0) {
 374              $ids = (int) substr($search, 3);
 375              $query->where($db->quoteName('extension_id') . ' = :eid')
 376                  ->bind(':eid', $ids, ParameterType::INTEGER);
 377          }
 378  
 379          // Note: The search for name, ordering and pagination are processed by the parent InstallerModel class (in extension.php).
 380  
 381          return $query;
 382      }
 383  
 384      /**
 385       * Load the changelog details for a given extension.
 386       *
 387       * @param   integer  $eid     The extension ID
 388       * @param   string   $source  The view the changelog is for, this is used to determine which version number to show
 389       *
 390       * @return  string  The output to show in the modal.
 391       *
 392       * @since   4.0.0
 393       */
 394      public function loadChangelog($eid, $source)
 395      {
 396          // Get the changelog URL
 397          $eid = (int) $eid;
 398          $db    = $this->getDatabase();
 399          $query = $db->getQuery(true)
 400              ->select(
 401                  $db->quoteName(
 402                      [
 403                          'extensions.element',
 404                          'extensions.type',
 405                          'extensions.folder',
 406                          'extensions.changelogurl',
 407                          'extensions.manifest_cache',
 408                          'extensions.client_id'
 409                      ]
 410                  )
 411              )
 412              ->select($db->quoteName('updates.version', 'updateVersion'))
 413              ->from($db->quoteName('#__extensions', 'extensions'))
 414              ->join(
 415                  'LEFT',
 416                  $db->quoteName('#__updates', 'updates'),
 417                  $db->quoteName('updates.extension_id') . ' = ' . $db->quoteName('extensions.extension_id')
 418              )
 419              ->where($db->quoteName('extensions.extension_id') . ' = :eid')
 420              ->bind(':eid', $eid, ParameterType::INTEGER);
 421          $db->setQuery($query);
 422  
 423          $extensions = $db->loadObjectList();
 424          $this->translate($extensions);
 425          $extension = array_shift($extensions);
 426  
 427          if (!$extension->changelogurl) {
 428              return '';
 429          }
 430  
 431          $changelog = new Changelog();
 432          $changelog->setVersion($source === 'manage' ? $extension->version : $extension->updateVersion);
 433          $changelog->loadFromXml($extension->changelogurl);
 434  
 435          // Read all the entries
 436          $entries = array(
 437              'security' => array(),
 438              'fix'      => array(),
 439              'addition' => array(),
 440              'change'   => array(),
 441              'remove'   => array(),
 442              'language' => array(),
 443              'note'     => array()
 444          );
 445  
 446          array_walk(
 447              $entries,
 448              function (&$value, $name) use ($changelog) {
 449                  if ($field = $changelog->get($name)) {
 450                      $value = $changelog->get($name)->data;
 451                  }
 452              }
 453          );
 454  
 455          $layout = new FileLayout('joomla.installer.changelog');
 456          $output = $layout->render($entries);
 457  
 458          return $output;
 459      }
 460  }


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