116905344SAndreas Gohr<?php 2d4f83172SAndreas Gohr 316905344SAndreas Gohr/** 416905344SAndreas Gohr * Load all internal libraries and setup class autoloader 516905344SAndreas Gohr * 616905344SAndreas Gohr * @author Andreas Gohr <andi@splitbrain.org> 716905344SAndreas Gohr */ 816905344SAndreas Gohr 94602718bSAndreas Gohrnamespace dokuwiki; 104602718bSAndreas Gohr 111935a891SAndreas Gohruse dokuwiki\Extension\PluginController; 121935a891SAndreas Gohr 134602718bSAndreas Gohrreturn new class { 144602718bSAndreas Gohr /** @var string[] Common libraries that are always loaded */ 154602718bSAndreas Gohr protected array $commonLibs = [ 164602718bSAndreas Gohr 'defines.php', 174602718bSAndreas Gohr 'actions.php', 184602718bSAndreas Gohr 'changelog.php', 194602718bSAndreas Gohr 'common.php', 204602718bSAndreas Gohr 'confutils.php', 214602718bSAndreas Gohr 'pluginutils.php', 224602718bSAndreas Gohr 'form.php', 234602718bSAndreas Gohr 'html.php', 244602718bSAndreas Gohr 'httputils.php', 254602718bSAndreas Gohr 'infoutils.php', 264602718bSAndreas Gohr 'io.php', 274602718bSAndreas Gohr 'mail.php', 284602718bSAndreas Gohr 'media.php', 294602718bSAndreas Gohr 'pageutils.php', 304602718bSAndreas Gohr 'parserutils.php', 314602718bSAndreas Gohr 'search.php', 324602718bSAndreas Gohr 'template.php', 334602718bSAndreas Gohr 'toolbar.php', 344602718bSAndreas Gohr 'utf8.php', 354602718bSAndreas Gohr 'auth.php', 364602718bSAndreas Gohr 'compatibility.php', 374602718bSAndreas Gohr 'deprecated.php', 384602718bSAndreas Gohr 'legacy.php', 394602718bSAndreas Gohr ]; 4016905344SAndreas Gohr 414602718bSAndreas Gohr /** @var string[] Classname to file mappings */ 424602718bSAndreas Gohr protected array $fixedClassNames = [ 434602718bSAndreas Gohr 'Diff' => 'DifferenceEngine.php', 444602718bSAndreas Gohr 'UnifiedDiffFormatter' => 'DifferenceEngine.php', 454602718bSAndreas Gohr 'TableDiffFormatter' => 'DifferenceEngine.php', 464602718bSAndreas Gohr 'cache' => 'cache.php', 474602718bSAndreas Gohr 'cache_parser' => 'cache.php', 484602718bSAndreas Gohr 'cache_instructions' => 'cache.php', 494602718bSAndreas Gohr 'cache_renderer' => 'cache.php', 504602718bSAndreas Gohr 'JpegMeta' => 'JpegMeta.php', 514602718bSAndreas Gohr 'FeedParser' => 'FeedParser.php', 524602718bSAndreas Gohr 'SafeFN' => 'SafeFN.class.php', 534602718bSAndreas Gohr 'Mailer' => 'Mailer.class.php', 544602718bSAndreas Gohr 'Doku_Renderer' => 'parser/renderer.php', 554602718bSAndreas Gohr 'Doku_Renderer_xhtml' => 'parser/xhtml.php', 564602718bSAndreas Gohr 'Doku_Renderer_code' => 'parser/code.php', 574602718bSAndreas Gohr 'Doku_Renderer_xhtmlsummary' => 'parser/xhtmlsummary.php', 584602718bSAndreas Gohr 'Doku_Renderer_metadata' => 'parser/metadata.php' 594602718bSAndreas Gohr ]; 604602718bSAndreas Gohr 614602718bSAndreas Gohr /** 624602718bSAndreas Gohr * Load common libs and register autoloader 634602718bSAndreas Gohr */ 644602718bSAndreas Gohr public function __construct() 654602718bSAndreas Gohr { 664602718bSAndreas Gohr require_once(DOKU_INC . 'vendor/autoload.php'); 67*093fe67eSAndreas Gohr spl_autoload_register($this->autoload(...)); 684602718bSAndreas Gohr $this->loadCommonLibs(); 694602718bSAndreas Gohr } 704602718bSAndreas Gohr 714602718bSAndreas Gohr /** 724602718bSAndreas Gohr * require all the common libraries 734602718bSAndreas Gohr * 744602718bSAndreas Gohr * @return true 754602718bSAndreas Gohr */ 764602718bSAndreas Gohr public function loadCommonLibs() 774602718bSAndreas Gohr { 784602718bSAndreas Gohr foreach ($this->commonLibs as $lib) { 794602718bSAndreas Gohr require_once(DOKU_INC . 'inc/' . $lib); 804602718bSAndreas Gohr } 814602718bSAndreas Gohr return true; 824602718bSAndreas Gohr } 8316905344SAndreas Gohr 8416905344SAndreas Gohr /** 8516905344SAndreas Gohr * spl_autoload_register callback 8616905344SAndreas Gohr * 874602718bSAndreas Gohr * @param string $className 88f50a239bSTakamura * @return bool 8916905344SAndreas Gohr */ 904602718bSAndreas Gohr public function autoload($className) 91d868eb89SAndreas Gohr { 92b89dfc20SAndreas Gohr // namespace to directory conversion 934602718bSAndreas Gohr $classPath = str_replace('\\', '/', $className); 94e7a32b17SAndreas Gohr 954602718bSAndreas Gohr return $this->autoloadFixedClass($className) 964602718bSAndreas Gohr || $this->autoloadTestMockClass($classPath) 974602718bSAndreas Gohr || $this->autoloadTestClass($classPath) 984602718bSAndreas Gohr || $this->autoloadPluginClass($classPath) 994602718bSAndreas Gohr || $this->autoloadTemplateClass($classPath) 1004602718bSAndreas Gohr || $this->autoloadCoreClass($classPath) 1014602718bSAndreas Gohr || $this->autoloadNamedPluginClass($className); 1024602718bSAndreas Gohr } 1034602718bSAndreas Gohr 1044602718bSAndreas Gohr /** 1054602718bSAndreas Gohr * Check if the class is one of the fixed names 1064602718bSAndreas Gohr * 1074602718bSAndreas Gohr * @param string $className 1084602718bSAndreas Gohr * @return bool true if the class was loaded, false otherwise 1094602718bSAndreas Gohr */ 1104602718bSAndreas Gohr protected function autoloadFixedClass($className) 1114602718bSAndreas Gohr { 1124602718bSAndreas Gohr if (isset($this->fixedClassNames[$className])) { 1134602718bSAndreas Gohr require($this->fixedClassNames[$className]); 1144602718bSAndreas Gohr return true; 1154602718bSAndreas Gohr } 1164602718bSAndreas Gohr return false; 1174602718bSAndreas Gohr } 1184602718bSAndreas Gohr 1194602718bSAndreas Gohr /** 1204602718bSAndreas Gohr * Check if the class is a test mock class 1214602718bSAndreas Gohr * 1224602718bSAndreas Gohr * @param string $classPath The class name using forward slashes as namespace separators 1234602718bSAndreas Gohr * @return bool true if the class was loaded, false otherwise 1244602718bSAndreas Gohr */ 1254602718bSAndreas Gohr protected function autoloadTestMockClass($classPath) 1264602718bSAndreas Gohr { 1274602718bSAndreas Gohr if ($this->prefixStrip($classPath, 'dokuwiki/test/mock/')) { 1284602718bSAndreas Gohr $file = DOKU_INC . '_test/mock/' . $classPath . '.php'; 129a087da71SAndreas Gohr if (file_exists($file)) { 130a087da71SAndreas Gohr require $file; 131a087da71SAndreas Gohr return true; 132a087da71SAndreas Gohr } 133a087da71SAndreas Gohr } 1344602718bSAndreas Gohr return false; 1354602718bSAndreas Gohr } 136a087da71SAndreas Gohr 1374602718bSAndreas Gohr /** 1384602718bSAndreas Gohr * Check if the class is a test mock class 1394602718bSAndreas Gohr * 1404602718bSAndreas Gohr * @param string $classPath The class name using forward slashes as namespace separators 1414602718bSAndreas Gohr * @return bool true if the class was loaded, false otherwise 1424602718bSAndreas Gohr */ 1434602718bSAndreas Gohr protected function autoloadTestClass($classPath) 1444602718bSAndreas Gohr { 1454602718bSAndreas Gohr if ($this->prefixStrip($classPath, 'dokuwiki/test/')) { 1464602718bSAndreas Gohr $file = DOKU_INC . '_test/tests/' . $classPath . '.php'; 147600fb65eSAndreas Gohr if (file_exists($file)) { 148600fb65eSAndreas Gohr require $file; 149600fb65eSAndreas Gohr return true; 150600fb65eSAndreas Gohr } 151600fb65eSAndreas Gohr } 1524602718bSAndreas Gohr return false; 1534602718bSAndreas Gohr } 154600fb65eSAndreas Gohr 1554602718bSAndreas Gohr /** 1564602718bSAndreas Gohr * Check if the class is a namespaced plugin class 1574602718bSAndreas Gohr * 1584602718bSAndreas Gohr * @param string $classPath The class name using forward slashes as namespace separators 1594602718bSAndreas Gohr * @return bool true if the class was loaded, false otherwise 1604602718bSAndreas Gohr */ 1614602718bSAndreas Gohr protected function autoloadPluginClass($classPath) 1624602718bSAndreas Gohr { 1634602718bSAndreas Gohr global $plugin_controller; 1644602718bSAndreas Gohr 1654602718bSAndreas Gohr if ($this->prefixStrip($classPath, 'dokuwiki/plugin/')) { 1664602718bSAndreas Gohr $classPath = str_replace('/test/', '/_test/', $classPath); // no underscore in test namespace 1674602718bSAndreas Gohr $file = DOKU_PLUGIN . $classPath . '.php'; 168600fb65eSAndreas Gohr if (file_exists($file)) { 1694602718bSAndreas Gohr $plugin = substr($classPath, 0, strpos($classPath, '/')); 1704602718bSAndreas Gohr // don't load disabled plugin classes (only if plugin controller is available) 171ff136773SAndreas Gohr if (!defined('DOKU_UNITTEST') && $plugin_controller && plugin_isdisabled($plugin)) return false; 1724602718bSAndreas Gohr 173ffa84f81SAndreas Gohr try { 174600fb65eSAndreas Gohr require $file; 175ffa84f81SAndreas Gohr } catch (\Throwable $e) { 1764602718bSAndreas Gohr ErrorHandler::showExceptionMsg($e, "Error loading plugin $plugin"); 177ffa84f81SAndreas Gohr } 178600fb65eSAndreas Gohr return true; 179600fb65eSAndreas Gohr } 180600fb65eSAndreas Gohr } 1814602718bSAndreas Gohr return false; 1824602718bSAndreas Gohr } 183600fb65eSAndreas Gohr 1844602718bSAndreas Gohr /** 1854602718bSAndreas Gohr * Check if the class is a namespaced template class 1864602718bSAndreas Gohr * 1874602718bSAndreas Gohr * @param string $classPath The class name using forward slashes as namespace separators 1884602718bSAndreas Gohr * @return bool true if the class was loaded, false otherwise 1894602718bSAndreas Gohr */ 1904602718bSAndreas Gohr protected function autoloadTemplateClass($classPath) 1914602718bSAndreas Gohr { 192f83f0fd0SAndreas Gohr // template namespace 1934602718bSAndreas Gohr if ($this->prefixStrip($classPath, 'dokuwiki/template/')) { 1944602718bSAndreas Gohr $classPath = str_replace('/test/', '/_test/', $classPath); // no underscore in test namespace 1954602718bSAndreas Gohr $file = DOKU_INC . 'lib/tpl/' . $classPath . '.php'; 196f83f0fd0SAndreas Gohr if (file_exists($file)) { 1974602718bSAndreas Gohr $template = substr($classPath, 0, strpos($classPath, '/')); 1984602718bSAndreas Gohr 199ffa84f81SAndreas Gohr try { 200f83f0fd0SAndreas Gohr require $file; 201ffa84f81SAndreas Gohr } catch (\Throwable $e) { 2024602718bSAndreas Gohr ErrorHandler::showExceptionMsg($e, "Error loading template $template"); 203ffa84f81SAndreas Gohr } 204f83f0fd0SAndreas Gohr return true; 205f83f0fd0SAndreas Gohr } 206f83f0fd0SAndreas Gohr } 2074602718bSAndreas Gohr return false; 2084602718bSAndreas Gohr } 209f83f0fd0SAndreas Gohr 2104602718bSAndreas Gohr /** 2114602718bSAndreas Gohr * Check if the class is a namespaced DokuWiki core class 2124602718bSAndreas Gohr * 2134602718bSAndreas Gohr * @param string $classPath The class name using forward slashes as namespace separators 2144602718bSAndreas Gohr * @return bool true if the class was loaded, false otherwise 2154602718bSAndreas Gohr */ 2164602718bSAndreas Gohr protected function autoloadCoreClass($classPath) 2174602718bSAndreas Gohr { 2184602718bSAndreas Gohr if ($this->prefixStrip($classPath, 'dokuwiki/')) { 2194602718bSAndreas Gohr $file = DOKU_INC . 'inc/' . $classPath . '.php'; 220b16ddc6eSAndreas Gohr if (file_exists($file)) { 221b16ddc6eSAndreas Gohr require $file; 222b89dfc20SAndreas Gohr return true; 223b89dfc20SAndreas Gohr } 224b16ddc6eSAndreas Gohr } 2254602718bSAndreas Gohr return false; 2264602718bSAndreas Gohr } 227b89dfc20SAndreas Gohr 2284602718bSAndreas Gohr /** 2294602718bSAndreas Gohr * Check if the class is a un-namespaced plugin class following our naming scheme 2304602718bSAndreas Gohr * 2314602718bSAndreas Gohr * @param string $className 2324602718bSAndreas Gohr * @return bool true if the class was loaded, false otherwise 2334602718bSAndreas Gohr */ 2344602718bSAndreas Gohr protected function autoloadNamedPluginClass($className) 2354602718bSAndreas Gohr { 2364602718bSAndreas Gohr global $plugin_controller; 2374602718bSAndreas Gohr 2387d34963bSAndreas Gohr if ( 2397d34963bSAndreas Gohr preg_match( 2401935a891SAndreas Gohr '/^(' . implode('|', PluginController::PLUGIN_TYPES) . ')_plugin_(' . 24164159a61SAndreas Gohr DOKU_PLUGIN_NAME_REGEX . 24264159a61SAndreas Gohr ')(?:_([^_]+))?$/', 2434602718bSAndreas Gohr $className, 24464159a61SAndreas Gohr $m 2457d34963bSAndreas Gohr ) 2467d34963bSAndreas Gohr ) { 247d54ac877SAdrian Lang $c = ((count($m) === 4) ? "/{$m[3]}" : ''); 2485a9866e9SAndreas Gohr $plg = DOKU_PLUGIN . "{$m[2]}/{$m[1]}$c.php"; 24979e79377SAndreas Gohr if (file_exists($plg)) { 2504602718bSAndreas Gohr // don't load disabled plugin classes (only if plugin controller is available) 251ff136773SAndreas Gohr if (!defined('DOKU_UNITTEST') && $plugin_controller && plugin_isdisabled($m[2])) return false; 252ffa84f81SAndreas Gohr try { 253ce949263SAndreas Gohr require $plg; 254ffa84f81SAndreas Gohr } catch (\Throwable $e) { 25524870174SAndreas Gohr ErrorHandler::showExceptionMsg($e, "Error loading plugin {$m[2]}"); 256ffa84f81SAndreas Gohr } 2575a9866e9SAndreas Gohr } 2588a58013eSDavid Stone return true; 259d54ac877SAdrian Lang } 260ce949263SAndreas Gohr return false; 26116905344SAndreas Gohr } 26216905344SAndreas Gohr 2634602718bSAndreas Gohr /** 2644602718bSAndreas Gohr * Check if the given string starts with the given prefix and strip it 2654602718bSAndreas Gohr * 2664602718bSAndreas Gohr * @param string $string 2674602718bSAndreas Gohr * @param string $prefix 2684602718bSAndreas Gohr * @return bool true if the prefix was found and stripped, false otherwise 2694602718bSAndreas Gohr */ 2704602718bSAndreas Gohr protected function prefixStrip(&$string, $prefix) 2714602718bSAndreas Gohr { 2724602718bSAndreas Gohr if (str_starts_with($string, $prefix)) { 2734602718bSAndreas Gohr $string = substr($string, strlen($prefix)); 2744602718bSAndreas Gohr return true; 2754602718bSAndreas Gohr } 2764602718bSAndreas Gohr return false; 2774602718bSAndreas Gohr } 2784602718bSAndreas Gohr}; 279