[ Index ]

PHP Cross Reference of Joomla 4.2.2 documentation

title

Body

[close]

/libraries/ -> namespacemap.php (source)

   1  <?php
   2  
   3  /**
   4   * Joomla! Content Management System
   5   *
   6   * @copyright  (C) 2017 Open Source Matters, Inc. <https://www.joomla.org>
   7   * @license    GNU General Public License version 2 or later; see LICENSE.txt
   8  
   9   * @phpcs:disable PSR1.Classes.ClassDeclaration.MissingNamespace
  10   */
  11  
  12  use Joomla\CMS\Log\Log;
  13  use Joomla\Filesystem\File;
  14  use Joomla\Filesystem\Folder;
  15  
  16  // phpcs:disable PSR1.Files.SideEffects
  17  \defined('_JEXEC') or die;
  18  // phpcs:enable PSR1.Files.SideEffects
  19  
  20  /**
  21   * Class JNamespacePsr4Map
  22   *
  23   * @since  4.0.0
  24   */
  25  class JNamespacePsr4Map
  26  {
  27      /**
  28       * Path to the autoloader
  29       *
  30       * @var    string
  31       * @since  4.0.0
  32       */
  33      protected $file = JPATH_CACHE . '/autoload_psr4.php';
  34  
  35      /**
  36       * @var array|null
  37       * @since 4.0.0
  38       */
  39      private $cachedMap = null;
  40  
  41      /**
  42       * Check if the file exists
  43       *
  44       * @return  boolean
  45       *
  46       * @since   4.0.0
  47       */
  48      public function exists()
  49      {
  50          return is_file($this->file);
  51      }
  52  
  53      /**
  54       * Check if the namespace mapping file exists, if not create it
  55       *
  56       * @return  void
  57       *
  58       * @since   4.0.0
  59       */
  60      public function ensureMapFileExists()
  61      {
  62          if (!$this->exists()) {
  63              $this->create();
  64          }
  65      }
  66  
  67      /**
  68       * Create the namespace file
  69       *
  70       * @return  boolean
  71       *
  72       * @since   4.0.0
  73       */
  74      public function create()
  75      {
  76          $extensions = array_merge(
  77              $this->getNamespaces('component'),
  78              $this->getNamespaces('module'),
  79              $this->getNamespaces('plugin'),
  80              $this->getNamespaces('library')
  81          );
  82  
  83          ksort($extensions);
  84  
  85          $this->writeNamespaceFile($extensions);
  86  
  87          return true;
  88      }
  89  
  90      /**
  91       * Load the PSR4 file
  92       *
  93       * @return  boolean
  94       *
  95       * @since   4.0.0
  96       */
  97      public function load()
  98      {
  99          if (!$this->exists()) {
 100              $this->create();
 101          }
 102  
 103          $map = $this->cachedMap ?: require $this->file;
 104  
 105          $loader = include  JPATH_LIBRARIES . '/vendor/autoload.php';
 106  
 107          foreach ($map as $namespace => $path) {
 108              $loader->setPsr4($namespace, $path);
 109          }
 110  
 111          return true;
 112      }
 113  
 114      /**
 115       * Write the Namespace mapping file
 116       *
 117       * @param   array  $elements  Array of elements
 118       *
 119       * @return  void
 120       *
 121       * @since   4.0.0
 122       */
 123      protected function writeNamespaceFile($elements)
 124      {
 125          $content   = array();
 126          $content[] = "<?php";
 127          $content[] = 'defined(\'_JEXEC\') or die;';
 128          $content[] = 'return [';
 129  
 130          foreach ($elements as $namespace => $path) {
 131              $content[] = "\t'" . $namespace . "'" . ' => [' . $path . '],';
 132          }
 133  
 134          $content[] = '];';
 135  
 136          /**
 137           * Backup the current error_reporting level and set a new level
 138           *
 139           * We do this because file_put_contents can raise a Warning if it cannot write the autoload_psr4.php file
 140           * and this will output to the response BEFORE the session has started, causing the session start to fail
 141           * and ultimately leading us to a 500 Internal Server Error page just because of the output warning, which
 142           * we can safely ignore as we can use an in-memory autoload_psr4 map temporarily, and display real errors later.
 143           */
 144          $error_reporting = error_reporting(0);
 145  
 146          try {
 147              File::write($this->file, implode("\n", $content));
 148          } catch (Exception $e) {
 149              Log::add('Could not save ' . $this->file, Log::WARNING);
 150  
 151              $map = [];
 152              $constants = ['JPATH_ADMINISTRATOR', 'JPATH_API', 'JPATH_SITE', 'JPATH_PLUGINS'];
 153  
 154              foreach ($elements as $namespace => $path) {
 155                  foreach ($constants as $constant) {
 156                      $path = preg_replace(['/^(' . $constant . ")\s\.\s\'/", '/\'$/'], [constant($constant), ''], $path);
 157                  }
 158  
 159                  $namespace = str_replace('\\\\', '\\', $namespace);
 160                  $map[$namespace] = [ $path ];
 161              }
 162  
 163              $this->cachedMap = $map;
 164          }
 165  
 166          // Restore previous value of error_reporting
 167          error_reporting($error_reporting);
 168      }
 169  
 170      /**
 171       * Get an array of namespaces with their respective path for the given extension type.
 172       *
 173       * @param   string  $type  The extension type
 174       *
 175       * @return  array
 176       *
 177       * @since   4.0.0
 178       */
 179      private function getNamespaces(string $type): array
 180      {
 181          if (!in_array($type, ['component', 'module', 'plugin', 'library'], true)) {
 182              return [];
 183          }
 184  
 185          // Select directories containing extension manifest files.
 186          if ($type === 'component') {
 187              $directories = [JPATH_ADMINISTRATOR . '/components'];
 188          } elseif ($type === 'module') {
 189              $directories = [JPATH_SITE . '/modules', JPATH_ADMINISTRATOR . '/modules'];
 190          } elseif ($type === 'plugin') {
 191              try {
 192                  $directories = Folder::folders(JPATH_PLUGINS, '.', false, true);
 193              } catch (Exception $e) {
 194                  $directories = [];
 195              }
 196          } else {
 197              $directories = [JPATH_LIBRARIES];
 198          }
 199  
 200          $extensions = [];
 201  
 202          foreach ($directories as $directory) {
 203              try {
 204                  $extensionFolders = Folder::folders($directory);
 205              } catch (Exception $e) {
 206                  continue;
 207              }
 208  
 209              foreach ($extensionFolders as $extension) {
 210                  // Compile the extension path
 211                  $extensionPath = $directory . '/' . $extension . '/';
 212  
 213                  // Strip the com_ from the extension name for components
 214                  $name = str_replace('com_', '', $extension, $count);
 215                  $file = $extensionPath . $name . '.xml';
 216  
 217                  // If there is no manifest file, ignore. If it was a component check if the xml was named with the com_ prefix.
 218                  if (!is_file($file)) {
 219                      if (!$count) {
 220                          continue;
 221                      }
 222  
 223                      $file = $extensionPath . $extension . '.xml';
 224  
 225                      if (!is_file($file)) {
 226                          continue;
 227                      }
 228                  }
 229  
 230                  // Load the manifest file
 231                  $xml = simplexml_load_file($file);
 232  
 233                  // When invalid, ignore
 234                  if (!$xml) {
 235                      continue;
 236                  }
 237  
 238                  // The namespace node
 239                  $namespaceNode = $xml->namespace;
 240  
 241                  // The namespace string
 242                  $namespace = (string) $namespaceNode;
 243  
 244                  // Ignore when the string is empty
 245                  if (!$namespace) {
 246                      continue;
 247                  }
 248  
 249                  // Normalize the namespace string
 250                  $namespace     = str_replace('\\', '\\\\', $namespace) . '\\\\';
 251                  $namespacePath = rtrim($extensionPath . $namespaceNode->attributes()->path, '/');
 252  
 253                  if ($type === 'plugin' || $type === 'library') {
 254                      $baseDir = $type === 'plugin' ? 'JPATH_PLUGINS . \'' : 'JPATH_LIBRARIES . \'';
 255                      $path    = str_replace($type === 'plugin' ? JPATH_PLUGINS : JPATH_LIBRARIES, '', $namespacePath);
 256  
 257                      // Set the namespace
 258                      $extensions[$namespace] = $baseDir . $path . '\'';
 259  
 260                      continue;
 261                  }
 262  
 263                  // Check if we need to use administrator path
 264                  $isAdministrator = strpos($namespacePath, JPATH_ADMINISTRATOR) === 0;
 265                  $path            = str_replace($isAdministrator ? JPATH_ADMINISTRATOR : JPATH_SITE, '', $namespacePath);
 266  
 267                  // Add the site path when a component
 268                  if ($type === 'component') {
 269                      if (is_dir(JPATH_SITE . $path)) {
 270                          $extensions[$namespace . 'Site\\\\'] = 'JPATH_SITE . \'' . $path . '\'';
 271                      }
 272  
 273                      if (is_dir(JPATH_API . $path)) {
 274                          $extensions[$namespace . 'Api\\\\'] = 'JPATH_API . \'' . $path . '\'';
 275                      }
 276                  }
 277  
 278                  // Add the application specific segment when a component or module
 279                  $baseDir    = $isAdministrator ? 'JPATH_ADMINISTRATOR . \'' : 'JPATH_SITE . \'';
 280                  $namespace .= $isAdministrator ? 'Administrator\\\\' : 'Site\\\\';
 281  
 282                  // Set the namespace
 283                  $extensions[$namespace] = $baseDir . $path . '\'';
 284              }
 285          }
 286  
 287          // Return the namespaces
 288          return $extensions;
 289      }
 290  }


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