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