[ Index ]

PHP Cross Reference of Joomla 4.2.2 documentation

title

Body

[close]

/administrator/components/com_installer/src/Helper/ -> InstallerHelper.php (source)

   1  <?php
   2  
   3  /**
   4   * @package     Joomla.Administrator
   5   * @subpackage  com_installer
   6   *
   7   * @copyright   (C) 2017 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\Helper;
  12  
  13  use Exception;
  14  use Joomla\CMS\Factory;
  15  use Joomla\CMS\HTML\HTMLHelper;
  16  use Joomla\CMS\Language\Text;
  17  use Joomla\CMS\Object\CMSObject;
  18  use Joomla\Database\DatabaseDriver;
  19  use Joomla\Database\ParameterType;
  20  use SimpleXMLElement;
  21  
  22  // phpcs:disable PSR1.Files.SideEffects
  23  \defined('_JEXEC') or die;
  24  // phpcs:enable PSR1.Files.SideEffects
  25  
  26  /**
  27   * Installer helper.
  28   *
  29   * @since  1.6
  30   */
  31  class InstallerHelper
  32  {
  33      /**
  34       * Get a list of filter options for the extension types.
  35       *
  36       * @return  array  An array of \stdClass objects.
  37       *
  38       * @since   3.0
  39       */
  40      public static function getExtensionTypes()
  41      {
  42          $db    = Factory::getDbo();
  43          $query = $db->getQuery(true)
  44              ->select('DISTINCT ' . $db->quoteName('type'))
  45              ->from($db->quoteName('#__extensions'));
  46          $db->setQuery($query);
  47          $types = $db->loadColumn();
  48  
  49          $options = array();
  50  
  51          foreach ($types as $type) {
  52              $options[] = HTMLHelper::_('select.option', $type, Text::_('COM_INSTALLER_TYPE_' . strtoupper($type)));
  53          }
  54  
  55          return $options;
  56      }
  57  
  58      /**
  59       * Get a list of filter options for the extension types.
  60       *
  61       * @return  array  An array of \stdClass objects.
  62       *
  63       * @since   3.0
  64       */
  65      public static function getExtensionGroups()
  66      {
  67          $nofolder = '';
  68          $db       = Factory::getDbo();
  69          $query    = $db->getQuery(true)
  70              ->select('DISTINCT ' . $db->quoteName('folder'))
  71              ->from($db->quoteName('#__extensions'))
  72              ->where($db->quoteName('folder') . ' != :folder')
  73              ->bind(':folder', $nofolder)
  74              ->order($db->quoteName('folder'));
  75          $db->setQuery($query);
  76          $folders = $db->loadColumn();
  77  
  78          $options = array();
  79  
  80          foreach ($folders as $folder) {
  81              $options[] = HTMLHelper::_('select.option', $folder, $folder);
  82          }
  83  
  84          return $options;
  85      }
  86  
  87      /**
  88       * Get a list of filter options for the application clients.
  89       *
  90       * @return  array  An array of \JHtmlOption elements.
  91       *
  92       * @since   3.5
  93       */
  94      public static function getClientOptions()
  95      {
  96          // Build the filter options.
  97          $options   = array();
  98          $options[] = HTMLHelper::_('select.option', '0', Text::_('JSITE'));
  99          $options[] = HTMLHelper::_('select.option', '1', Text::_('JADMINISTRATOR'));
 100          $options[] = HTMLHelper::_('select.option', '3', Text::_('JAPI'));
 101  
 102          return $options;
 103      }
 104  
 105      /**
 106       * Get a list of filter options for the application statuses.
 107       *
 108       * @return  array  An array of \JHtmlOption elements.
 109       *
 110       * @since   3.5
 111       */
 112      public static function getStateOptions()
 113      {
 114          // Build the filter options.
 115          $options   = array();
 116          $options[] = HTMLHelper::_('select.option', '0', Text::_('JDISABLED'));
 117          $options[] = HTMLHelper::_('select.option', '1', Text::_('JENABLED'));
 118          $options[] = HTMLHelper::_('select.option', '2', Text::_('JPROTECTED'));
 119          $options[] = HTMLHelper::_('select.option', '3', Text::_('JUNPROTECTED'));
 120  
 121          return $options;
 122      }
 123  
 124      /**
 125       * Get a list of filter options for extensions of the "package" type.
 126       *
 127       * @return  array
 128       * @since   4.2.0
 129       */
 130      public static function getPackageOptions(): array
 131      {
 132          $options = [];
 133  
 134          /** @var DatabaseDriver $db The application's database driver object */
 135          $db         = Factory::getContainer()->get(DatabaseDriver::class);
 136          $query      = $db->getQuery(true)
 137              ->select(
 138                  $db->quoteName(
 139                      [
 140                          'extension_id',
 141                          'name',
 142                          'element',
 143                      ]
 144                  )
 145              )
 146              ->from($db->quoteName('#__extensions'))
 147              ->where($db->quoteName('type') . ' = ' . $db->quote('package'));
 148          $extensions = $db->setQuery($query)->loadObjectList() ?: [];
 149  
 150          if (empty($extensions)) {
 151              return $options;
 152          }
 153  
 154          $language  = Factory::getApplication()->getLanguage();
 155          $arrayKeys = array_map(
 156              function (object $entry) use ($language): string {
 157                  $language->load($entry->element, JPATH_ADMINISTRATOR);
 158  
 159                  return Text::_($entry->name);
 160              },
 161              $extensions
 162          );
 163          $arrayValues = array_map(
 164              function (object $entry): int {
 165                  return $entry->extension_id;
 166              },
 167              $extensions
 168          );
 169  
 170          $extensions = array_combine($arrayKeys, $arrayValues);
 171          ksort($extensions);
 172  
 173          foreach ($extensions as $label => $id) {
 174              $options[] = HTMLHelper::_('select.option', $id, $label);
 175          }
 176  
 177          return $options;
 178      }
 179  
 180      /**
 181       * Get a list of filter options for the application statuses.
 182       *
 183       * @param   string   $element   element of an extension
 184       * @param   string   $type      type of an extension
 185       * @param   integer  $clientId  client_id of an extension
 186       * @param   string   $folder    folder of an extension
 187       *
 188       * @return  SimpleXMLElement
 189       *
 190       * @since   4.0.0
 191       */
 192      public static function getInstallationXML(
 193          string $element,
 194          string $type,
 195          int $clientId = 1,
 196          ?string $folder = null
 197      ): ?SimpleXMLElement {
 198          $path = [0 => JPATH_SITE, 1 => JPATH_ADMINISTRATOR, 3 => JPATH_API][$clientId] ?? JPATH_SITE;
 199  
 200          switch ($type) {
 201              case 'component':
 202                  $path .= '/components/' . $element . '/' . substr($element, 4) . '.xml';
 203                  break;
 204              case 'plugin':
 205                  $path .= '/plugins/' . $folder . '/' . $element . '/' . $element . '.xml';
 206                  break;
 207              case 'module':
 208                  $path .= '/modules/' . $element . '/' . $element . '.xml';
 209                  break;
 210              case 'template':
 211                  $path .= '/templates/' . $element . '/templateDetails.xml';
 212                  break;
 213              case 'library':
 214                  $path = JPATH_ADMINISTRATOR . '/manifests/libraries/' . $element . '.xml';
 215                  break;
 216              case 'file':
 217                  $path = JPATH_ADMINISTRATOR . '/manifests/files/' . $element . '.xml';
 218                  break;
 219              case 'package':
 220                  $path = JPATH_ADMINISTRATOR . '/manifests/packages/' . $element . '.xml';
 221                  break;
 222              case 'language':
 223                  $path .= '/language/' . $element . '/install.xml';
 224          }
 225  
 226          if (file_exists($path) === false) {
 227              return null;
 228          }
 229  
 230          $xmlElement = simplexml_load_file($path);
 231  
 232          return ($xmlElement !== false) ? $xmlElement : null;
 233      }
 234  
 235      /**
 236       * Get the download key of an extension going through their installation xml
 237       *
 238       * @param   CMSObject  $extension  element of an extension
 239       *
 240       * @return  array  An array with the prefix, suffix and value of the download key
 241       *
 242       * @since   4.0.0
 243       */
 244      public static function getDownloadKey(CMSObject $extension): array
 245      {
 246          $installXmlFile = self::getInstallationXML(
 247              $extension->get('element'),
 248              $extension->get('type'),
 249              $extension->get('client_id'),
 250              $extension->get('folder')
 251          );
 252  
 253          if (!$installXmlFile) {
 254              return [
 255                  'supported' => false,
 256                  'valid'     => false,
 257              ];
 258          }
 259  
 260          if (!isset($installXmlFile->dlid)) {
 261              return [
 262                  'supported' => false,
 263                  'valid'     => false,
 264              ];
 265          }
 266  
 267          $prefix = (string) $installXmlFile->dlid['prefix'];
 268          $suffix = (string) $installXmlFile->dlid['suffix'];
 269          $value  = substr($extension->get('extra_query'), strlen($prefix));
 270  
 271          if ($suffix) {
 272              $value = substr($value, 0, -strlen($suffix));
 273          }
 274  
 275          $downloadKey = [
 276              'supported' => true,
 277              'valid'     => $value ? true : false,
 278              'prefix'    => $prefix,
 279              'suffix'    => $suffix,
 280              'value'     => $value
 281          ];
 282  
 283          return $downloadKey;
 284      }
 285  
 286      /**
 287       * Get the download key of an extension given enough information to locate it in the #__extensions table
 288       *
 289       * @param   string       $element   Name of the extension, e.g. com_foo
 290       * @param   string       $type      The type of the extension, e.g. component
 291       * @param   int          $clientId  [optional] Joomla client for the extension, see the #__extensions table
 292       * @param   string|null  $folder    Extension folder, only applies for 'plugin' type
 293       *
 294       * @return  array
 295       *
 296       * @since   4.0.0
 297       */
 298      public static function getExtensionDownloadKey(
 299          string $element,
 300          string $type,
 301          int $clientId = 1,
 302          ?string $folder = null
 303      ): array {
 304          // Get the database driver. If it fails we cannot report whether the extension supports download keys.
 305          try {
 306              $db = Factory::getDbo();
 307          } catch (Exception $e) {
 308              return [
 309                  'supported' => false,
 310                  'valid'     => false,
 311              ];
 312          }
 313  
 314          // Try to retrieve the extension information as a CMSObject
 315          $query = $db->getQuery(true)
 316              ->select($db->quoteName('extension_id'))
 317              ->from($db->quoteName('#__extensions'))
 318              ->where($db->quoteName('type') . ' = :type')
 319              ->where($db->quoteName('element') . ' = :element')
 320              ->where($db->quoteName('folder') . ' = :folder')
 321              ->where($db->quoteName('client_id') . ' = :client_id');
 322          $query->bind(':type', $type, ParameterType::STRING);
 323          $query->bind(':element', $element, ParameterType::STRING);
 324          $query->bind(':client_id', $clientId, ParameterType::INTEGER);
 325          $query->bind(':folder', $folder, ParameterType::STRING);
 326  
 327          try {
 328              $extension = new CMSObject($db->setQuery($query)->loadAssoc());
 329          } catch (Exception $e) {
 330              return [
 331                  'supported' => false,
 332                  'valid'     => false,
 333              ];
 334          }
 335  
 336          // Use the getDownloadKey() method to return the download key information
 337          return self::getDownloadKey($extension);
 338      }
 339  
 340      /**
 341       * Returns a list of update site IDs which support download keys. By default this returns all qualifying update
 342       * sites, even if they are not enabled.
 343       *
 344       *
 345       * @param   bool  $onlyEnabled  [optional] Set true to only returned enabled update sites.
 346       *
 347       * @return  int[]
 348       * @since   4.0.0
 349       */
 350      public static function getDownloadKeySupportedSites($onlyEnabled = false): array
 351      {
 352          /**
 353           * NOTE: The closures are not inlined because in this case the Joomla Code Style standard produces two mutually
 354           * exclusive errors, making the file impossible to commit. Using closures in variables makes the code less
 355           * readable but works around that issue.
 356           */
 357  
 358          $extensions = self::getUpdateSitesInformation($onlyEnabled);
 359  
 360          $filterClosure = function (CMSObject $extension) {
 361              $dlidInfo = self::getDownloadKey($extension);
 362  
 363              return $dlidInfo['supported'];
 364          };
 365          $extensions = array_filter($extensions, $filterClosure);
 366  
 367          $mapClosure = function (CMSObject $extension) {
 368              return $extension->get('update_site_id');
 369          };
 370  
 371          return array_map($mapClosure, $extensions);
 372      }
 373  
 374      /**
 375       * Returns a list of update site IDs which are missing download keys. By default this returns all qualifying update
 376       * sites, even if they are not enabled.
 377       *
 378       * @param   bool  $exists       [optional] If true, returns update sites with a valid download key. When false,
 379       *                              returns update sites with an invalid / missing download key.
 380       * @param   bool  $onlyEnabled  [optional] Set true to only returned enabled update sites.
 381       *
 382       * @return  int[]
 383       * @since   4.0.0
 384       */
 385      public static function getDownloadKeyExistsSites(bool $exists = true, $onlyEnabled = false): array
 386      {
 387          /**
 388           * NOTE: The closures are not inlined because in this case the Joomla Code Style standard produces two mutually
 389           * exclusive errors, making the file impossible to commit. Using closures in variables makes the code less
 390           * readable but works around that issue.
 391           */
 392  
 393          $extensions = self::getUpdateSitesInformation($onlyEnabled);
 394  
 395          // Filter the extensions by what supports Download Keys
 396          $filterClosure = function (CMSObject $extension) use ($exists) {
 397              $dlidInfo = self::getDownloadKey($extension);
 398  
 399              if (!$dlidInfo['supported']) {
 400                  return false;
 401              }
 402  
 403              return $exists ? $dlidInfo['valid'] : !$dlidInfo['valid'];
 404          };
 405          $extensions = array_filter($extensions, $filterClosure);
 406  
 407          // Return only the update site IDs
 408          $mapClosure = function (CMSObject $extension) {
 409              return $extension->get('update_site_id');
 410          };
 411  
 412          return array_map($mapClosure, $extensions);
 413      }
 414  
 415  
 416      /**
 417       * Get information about the update sites
 418       *
 419       * @param   bool  $onlyEnabled  Only return enabled update sites
 420       *
 421       * @return  CMSObject[]  List of update site and linked extension information
 422       * @since   4.0.0
 423       */
 424      protected static function getUpdateSitesInformation(bool $onlyEnabled): array
 425      {
 426          try {
 427              $db = Factory::getDbo();
 428          } catch (Exception $e) {
 429              return [];
 430          }
 431  
 432          $query = $db->getQuery(true)
 433              ->select(
 434                  $db->quoteName(
 435                      [
 436                                  's.update_site_id',
 437                                  's.enabled',
 438                                  's.extra_query',
 439                                  'e.extension_id',
 440                                  'e.type',
 441                                  'e.element',
 442                                  'e.folder',
 443                                  'e.client_id',
 444                                  'e.manifest_cache',
 445                              ],
 446                      [
 447                                  'update_site_id',
 448                                  'enabled',
 449                                  'extra_query',
 450                                  'extension_id',
 451                                  'type',
 452                                  'element',
 453                                  'folder',
 454                                  'client_id',
 455                                  'manifest_cache',
 456                              ]
 457                  )
 458              )
 459              ->from($db->quoteName('#__update_sites', 's'))
 460              ->innerJoin(
 461                  $db->quoteName('#__update_sites_extensions', 'se'),
 462                  $db->quoteName('se.update_site_id') . ' = ' . $db->quoteName('s.update_site_id')
 463              )
 464              ->innerJoin(
 465                  $db->quoteName('#__extensions', 'e'),
 466                  $db->quoteName('e.extension_id') . ' = ' . $db->quoteName('se.extension_id')
 467              )
 468              ->where($db->quoteName('state') . ' = 0');
 469  
 470          if ($onlyEnabled) {
 471              $enabled = 1;
 472              $query->where($db->quoteName('s.enabled') . ' = :enabled')
 473                  ->bind(':enabled', $enabled, ParameterType::INTEGER);
 474          }
 475  
 476          // Try to get all of the update sites, including related extension information
 477          try {
 478              $items = [];
 479              $db->setQuery($query);
 480  
 481              foreach ($db->getIterator() as $item) {
 482                  $items[] = new CMSObject($item);
 483              }
 484  
 485              return $items;
 486          } catch (Exception $e) {
 487              return [];
 488          }
 489      }
 490  }


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