AutoLoader.php 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. <?php
  2. /**
  3. * This defines autoloading handler for whole MediaWiki framework
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation; either version 2 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License along
  16. * with this program; if not, write to the Free Software Foundation, Inc.,
  17. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  18. * http://www.gnu.org/copyleft/gpl.html
  19. *
  20. * @file
  21. */
  22. /**
  23. * Locations of core classes
  24. * Extension classes are specified with $wgAutoloadClasses
  25. * This array is a global instead of a static member of AutoLoader to work around a bug in APC
  26. */
  27. require_once __DIR__ . '/../autoload.php';
  28. class AutoLoader {
  29. protected static $autoloadLocalClassesLower = null;
  30. /**
  31. * @private Only public for ExtensionRegistry
  32. * @var string[] Namespace (ends with \) => Path (ends with /)
  33. */
  34. public static $psr4Namespaces = [];
  35. /**
  36. * autoload - take a class name and attempt to load it
  37. *
  38. * @param string $className Name of class we're looking for.
  39. */
  40. static function autoload( $className ) {
  41. global $wgAutoloadClasses, $wgAutoloadLocalClasses,
  42. $wgAutoloadAttemptLowercase;
  43. $filename = false;
  44. if ( isset( $wgAutoloadLocalClasses[$className] ) ) {
  45. $filename = $wgAutoloadLocalClasses[$className];
  46. } elseif ( isset( $wgAutoloadClasses[$className] ) ) {
  47. $filename = $wgAutoloadClasses[$className];
  48. } elseif ( $wgAutoloadAttemptLowercase ) {
  49. /*
  50. * Try a different capitalisation.
  51. *
  52. * PHP 4 objects are always serialized with the classname coerced to lowercase,
  53. * and we are plagued with several legacy uses created by MediaWiki < 1.5, see
  54. * https://wikitech.wikimedia.org/wiki/Text_storage_data
  55. */
  56. $lowerClass = strtolower( $className );
  57. if ( self::$autoloadLocalClassesLower === null ) {
  58. self::$autoloadLocalClassesLower = array_change_key_case( $wgAutoloadLocalClasses, CASE_LOWER );
  59. }
  60. if ( isset( self::$autoloadLocalClassesLower[$lowerClass] ) ) {
  61. if ( function_exists( 'wfDebugLog' ) ) {
  62. wfDebugLog( 'autoloader', "Class {$className} was loaded using incorrect case" );
  63. }
  64. $filename = self::$autoloadLocalClassesLower[$lowerClass];
  65. }
  66. }
  67. if ( !$filename && strpos( $className, '\\' ) !== false ) {
  68. // This class is namespaced, so try looking at the namespace map
  69. $prefix = $className;
  70. while ( false !== $pos = strrpos( $prefix, '\\' ) ) {
  71. // Check to see if this namespace prefix is in the map
  72. $prefix = substr( $className, 0, $pos + 1 );
  73. if ( isset( self::$psr4Namespaces[$prefix] ) ) {
  74. $relativeClass = substr( $className, $pos + 1 );
  75. // Build the expected filename, and see if it exists
  76. $file = self::$psr4Namespaces[$prefix] . '/' .
  77. str_replace( '\\', '/', $relativeClass ) . '.php';
  78. if ( file_exists( $file ) ) {
  79. $filename = $file;
  80. break;
  81. }
  82. }
  83. // Remove trailing separator for next iteration
  84. $prefix = rtrim( $prefix, '\\' );
  85. }
  86. }
  87. if ( !$filename ) {
  88. // Class not found; let the next autoloader try to find it
  89. return;
  90. }
  91. // Make an absolute path, this improves performance by avoiding some stat calls
  92. if ( substr( $filename, 0, 1 ) != '/' && substr( $filename, 1, 1 ) != ':' ) {
  93. global $IP;
  94. $filename = "$IP/$filename";
  95. }
  96. require $filename;
  97. }
  98. /**
  99. * Method to clear the protected class property $autoloadLocalClassesLower.
  100. * Used in tests.
  101. */
  102. static function resetAutoloadLocalClassesLower() {
  103. self::$autoloadLocalClassesLower = null;
  104. }
  105. /**
  106. * Get a mapping of namespace => file path
  107. * The namespaces should follow the PSR-4 standard for autoloading
  108. *
  109. * @see <http://www.php-fig.org/psr/psr-4/>
  110. * @private Only public for usage in AutoloadGenerator
  111. * @codeCoverageIgnore
  112. * @since 1.31
  113. * @return string[]
  114. */
  115. public static function getAutoloadNamespaces() {
  116. return [
  117. 'MediaWiki\\Auth\\' => __DIR__ . '/auth/',
  118. 'MediaWiki\\Block\\' => __DIR__ . '/block/',
  119. 'MediaWiki\\Edit\\' => __DIR__ . '/edit/',
  120. 'MediaWiki\\EditPage\\' => __DIR__ . '/editpage/',
  121. 'MediaWiki\\Linker\\' => __DIR__ . '/linker/',
  122. 'MediaWiki\\Message\\' => __DIR__ . '/Message',
  123. 'MediaWiki\\Permissions\\' => __DIR__ . '/Permissions/',
  124. 'MediaWiki\\Preferences\\' => __DIR__ . '/preferences/',
  125. 'MediaWiki\\Rest\\' => __DIR__ . '/Rest/',
  126. 'MediaWiki\\Revision\\' => __DIR__ . '/Revision/',
  127. 'MediaWiki\\Session\\' => __DIR__ . '/session/',
  128. 'MediaWiki\\Shell\\' => __DIR__ . '/shell/',
  129. 'MediaWiki\\Sparql\\' => __DIR__ . '/sparql/',
  130. 'MediaWiki\\Storage\\' => __DIR__ . '/Storage/',
  131. 'MediaWiki\\Tidy\\' => __DIR__ . '/tidy/',
  132. 'Wikimedia\\Message\\' => __DIR__ . '/libs/Message/',
  133. 'Wikimedia\\ParamValidator\\' => __DIR__ . '/libs/ParamValidator/',
  134. 'Wikimedia\\Services\\' => __DIR__ . '/libs/services/',
  135. ];
  136. }
  137. }
  138. AutoLoader::$psr4Namespaces = AutoLoader::getAutoloadNamespaces();
  139. spl_autoload_register( [ 'AutoLoader', 'autoload' ] );