AutoLoader.php 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  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. static protected $autoloadLocalClassesLower = null;
  30. /**
  31. * @private Only public for ExtensionRegistry
  32. * @var string[] Namespace (ends with \) => Path (ends with /)
  33. */
  34. static public $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. * @since 1.31
  112. * @return string[]
  113. */
  114. public static function getAutoloadNamespaces() {
  115. return [
  116. 'MediaWiki\\Linker\\' => __DIR__ .'/linker/'
  117. ];
  118. }
  119. }
  120. AutoLoader::$psr4Namespaces = AutoLoader::getAutoloadNamespaces();
  121. spl_autoload_register( [ 'AutoLoader', 'autoload' ] );