[ Index ]

PHP Cross Reference of DokuWiki

title

Body

[close]

/inc/ -> load.php (source)

   1  <?php
   2  
   3  /**
   4   * Load all internal libraries and setup class autoloader
   5   *
   6   * @author Andreas Gohr <andi@splitbrain.org>
   7   */
   8  
   9  namespace dokuwiki;
  10  
  11  use dokuwiki\Extension\PluginController;
  12  
  13  return new class {
  14      /** @var string[] Common libraries that are always loaded */
  15      protected array $commonLibs = [
  16          'defines.php',
  17          'actions.php',
  18          'changelog.php',
  19          'common.php',
  20          'confutils.php',
  21          'pluginutils.php',
  22          'form.php',
  23          'fulltext.php',
  24          'html.php',
  25          'httputils.php',
  26          'indexer.php',
  27          'infoutils.php',
  28          'io.php',
  29          'mail.php',
  30          'media.php',
  31          'pageutils.php',
  32          'parserutils.php',
  33          'search.php',
  34          'template.php',
  35          'toolbar.php',
  36          'utf8.php',
  37          'auth.php',
  38          'compatibility.php',
  39          'deprecated.php',
  40          'legacy.php',
  41      ];
  42  
  43      /** @var string[] Classname to file mappings */
  44      protected array $fixedClassNames = [
  45          'Diff' => 'DifferenceEngine.php',
  46          'UnifiedDiffFormatter' => 'DifferenceEngine.php',
  47          'TableDiffFormatter' => 'DifferenceEngine.php',
  48          'cache' => 'cache.php',
  49          'cache_parser' => 'cache.php',
  50          'cache_instructions' => 'cache.php',
  51          'cache_renderer' => 'cache.php',
  52          'Input' => 'Input.class.php',
  53          'JpegMeta' => 'JpegMeta.php',
  54          'SimplePie' => 'SimplePie.php',
  55          'FeedParser' => 'FeedParser.php',
  56          'SafeFN' => 'SafeFN.class.php',
  57          'Mailer' => 'Mailer.class.php',
  58          'Doku_Handler' => 'parser/handler.php',
  59          'Doku_Renderer' => 'parser/renderer.php',
  60          'Doku_Renderer_xhtml' => 'parser/xhtml.php',
  61          'Doku_Renderer_code' => 'parser/code.php',
  62          'Doku_Renderer_xhtmlsummary' => 'parser/xhtmlsummary.php',
  63          'Doku_Renderer_metadata' => 'parser/metadata.php'
  64      ];
  65  
  66      /**
  67       * Load common libs and register autoloader
  68       */
  69      public function __construct()
  70      {
  71          require_once (DOKU_INC . 'vendor/autoload.php');
  72          spl_autoload_register([$this, 'autoload']);
  73          $this->loadCommonLibs();
  74      }
  75  
  76      /**
  77       * require all the common libraries
  78       *
  79       * @return true
  80       */
  81      public function loadCommonLibs()
  82      {
  83          foreach ($this->commonLibs as $lib) {
  84              require_once(DOKU_INC . 'inc/' . $lib);
  85          }
  86          return true;
  87      }
  88  
  89      /**
  90       * spl_autoload_register callback
  91       *
  92       * @param string $className
  93       * @return bool
  94       */
  95      public function autoload($className)
  96      {
  97          // namespace to directory conversion
  98          $classPath = str_replace('\\', '/', $className);
  99  
 100          return $this->autoloadFixedClass($className)
 101              || $this->autoloadTestMockClass($classPath)
 102              || $this->autoloadTestClass($classPath)
 103              || $this->autoloadPluginClass($classPath)
 104              || $this->autoloadTemplateClass($classPath)
 105              || $this->autoloadCoreClass($classPath)
 106              || $this->autoloadNamedPluginClass($className);
 107      }
 108  
 109      /**
 110       * Check if the class is one of the fixed names
 111       *
 112       * @param string $className
 113       * @return bool true if the class was loaded, false otherwise
 114       */
 115      protected function autoloadFixedClass($className)
 116      {
 117          if (isset($this->fixedClassNames[$className])) {
 118              require($this->fixedClassNames[$className]);
 119              return true;
 120          }
 121          return false;
 122      }
 123  
 124      /**
 125       * Check if the class is a test mock class
 126       *
 127       * @param string $classPath The class name using forward slashes as namespace separators
 128       * @return bool true if the class was loaded, false otherwise
 129       */
 130      protected function autoloadTestMockClass($classPath)
 131      {
 132          if ($this->prefixStrip($classPath, 'dokuwiki/test/mock/')) {
 133              $file = DOKU_INC . '_test/mock/' . $classPath . '.php';
 134              if (file_exists($file)) {
 135                  require $file;
 136                  return true;
 137              }
 138          }
 139          return false;
 140      }
 141  
 142      /**
 143       * Check if the class is a test mock class
 144       *
 145       * @param string $classPath The class name using forward slashes as namespace separators
 146       * @return bool true if the class was loaded, false otherwise
 147       */
 148      protected function autoloadTestClass($classPath)
 149      {
 150          if ($this->prefixStrip($classPath, 'dokuwiki/test/')) {
 151              $file = DOKU_INC . '_test/tests/' . $classPath . '.php';
 152              if (file_exists($file)) {
 153                  require $file;
 154                  return true;
 155              }
 156          }
 157          return false;
 158      }
 159  
 160      /**
 161       * Check if the class is a namespaced plugin class
 162       *
 163       * @param string $classPath The class name using forward slashes as namespace separators
 164       * @return bool true if the class was loaded, false otherwise
 165       */
 166      protected function autoloadPluginClass($classPath)
 167      {
 168          global $plugin_controller;
 169  
 170          if ($this->prefixStrip($classPath, 'dokuwiki/plugin/')) {
 171              $classPath = str_replace('/test/', '/_test/', $classPath); // no underscore in test namespace
 172              $file = DOKU_PLUGIN . $classPath . '.php';
 173              if (file_exists($file)) {
 174                  $plugin = substr($classPath, 0, strpos($classPath, '/'));
 175                  // don't load disabled plugin classes (only if plugin controller is available)
 176                  if (!defined('DOKU_UNITTEST') && $plugin_controller && plugin_isdisabled($plugin)) return false;
 177  
 178                  try {
 179                      require $file;
 180                  } catch (\Throwable $e) {
 181                      ErrorHandler::showExceptionMsg($e, "Error loading plugin $plugin");
 182                  }
 183                  return true;
 184              }
 185          }
 186          return false;
 187      }
 188  
 189      /**
 190       * Check if the class is a namespaced template class
 191       *
 192       * @param string $classPath The class name using forward slashes as namespace separators
 193       * @return bool true if the class was loaded, false otherwise
 194       */
 195      protected function autoloadTemplateClass($classPath)
 196      {
 197          // template namespace
 198          if ($this->prefixStrip($classPath, 'dokuwiki/template/')) {
 199              $classPath = str_replace('/test/', '/_test/', $classPath); // no underscore in test namespace
 200              $file = DOKU_INC . 'lib/tpl/' . $classPath . '.php';
 201              if (file_exists($file)) {
 202                  $template = substr($classPath, 0, strpos($classPath, '/'));
 203  
 204                  try {
 205                      require $file;
 206                  } catch (\Throwable $e) {
 207                      ErrorHandler::showExceptionMsg($e, "Error loading template $template");
 208                  }
 209                  return true;
 210              }
 211          }
 212          return false;
 213      }
 214  
 215      /**
 216       * Check if the class is a namespaced DokuWiki core class
 217       *
 218       * @param string $classPath The class name using forward slashes as namespace separators
 219       * @return bool true if the class was loaded, false otherwise
 220       */
 221      protected function autoloadCoreClass($classPath)
 222      {
 223          if ($this->prefixStrip($classPath, 'dokuwiki/')) {
 224              $file = DOKU_INC . 'inc/' . $classPath . '.php';
 225              if (file_exists($file)) {
 226                  require $file;
 227                  return true;
 228              }
 229          }
 230          return false;
 231      }
 232  
 233      /**
 234       * Check if the class is a un-namespaced plugin class following our naming scheme
 235       *
 236       * @param string $className
 237       * @return bool true if the class was loaded, false otherwise
 238       */
 239      protected function autoloadNamedPluginClass($className)
 240      {
 241          global $plugin_controller;
 242  
 243          if (
 244              preg_match(
 245                  '/^(' . implode('|', PluginController::PLUGIN_TYPES) . ')_plugin_(' .
 246                  DOKU_PLUGIN_NAME_REGEX .
 247                  ')(?:_([^_]+))?$/',
 248                  $className,
 249                  $m
 250              )
 251          ) {
 252              $c = ((count($m) === 4) ? "/{$m[3]}" : '');
 253              $plg = DOKU_PLUGIN . "{$m[2]}/{$m[1]}$c.php";
 254              if (file_exists($plg)) {
 255                  // don't load disabled plugin classes (only if plugin controller is available)
 256                  if (!defined('DOKU_UNITTEST') && $plugin_controller && plugin_isdisabled($m[2])) return false;
 257                  try {
 258                      require $plg;
 259                  } catch (\Throwable $e) {
 260                      ErrorHandler::showExceptionMsg($e, "Error loading plugin {$m[2]}");
 261                  }
 262              }
 263              return true;
 264          }
 265          return false;
 266      }
 267  
 268      /**
 269       * Check if the given string starts with the given prefix and strip it
 270       *
 271       * @param string $string
 272       * @param string $prefix
 273       * @return bool true if the prefix was found and stripped, false otherwise
 274       */
 275      protected function prefixStrip(&$string, $prefix)
 276      {
 277          if (str_starts_with($string, $prefix)) {
 278              $string = substr($string, strlen($prefix));
 279              return true;
 280          }
 281          return false;
 282      }
 283  };