/package/app/html5/html5lib/v1.3.3/includes/NamedResourceLoader.php

https://github.com/richhl/kalturaCE · PHP · 301 lines · 162 code · 45 blank · 94 comment · 29 complexity · 7777ddf6f33f76333645dc46f7513cbc MD5 · raw file

  1. <?php
  2. /**
  3. * The javascript resource loader handles loading lists of available
  4. * javascript classes into php from their defined locations in javascript.
  5. */
  6. if ( !defined( 'MEDIAWIKI' ) ) die( 1 );
  7. class NamedResourceLoader {
  8. // The list of mwEmbed core components that make up the base mwEmbed class
  9. private static $coreComponentsList = array();
  10. // The list of mwEmbed modules that are enabled
  11. private static $moduleList = array();
  12. // Stores the contents of the combined loader.js files
  13. private static $combinedLoadersJs = '';
  14. // Reg Exp that supports extracting classes from loaders
  15. private static $classReplaceExp = '/mw\.addResourcePaths\s*\(\s*{(.*)}\s*\)\s*[\;\n]/siU';
  16. // Flag to specify if the javascript resource paths have been loaded.
  17. private static $classesLoaded = false;
  18. // The current directory context. Used in loading javascript modules outside of the mwEmbed folder
  19. private static $directoryContext = '';
  20. // Stores resource parent moduleName
  21. private static $resourceParentModuleName = array();
  22. // The current module name used for callback functions in regular expressions
  23. private static $currentModuleName = '';
  24. /**
  25. * Get the javascript resource paths from javascript files
  26. */
  27. public static function loadResourcePaths(){
  28. global $wgMwEmbedDirectory, $wgExtensionJavascriptModules, $wgMwEmbedEnabledModules,
  29. $wgResourceLoaderNamedPaths, $wgExtensionMessagesFiles, $IP;
  30. // Only run once
  31. if( self::$classesLoaded ) {
  32. return true;
  33. }
  34. self::$classesLoaded = true;
  35. // Start the profiler if running
  36. $fname = 'NamedResourceLoader::loadResourcePaths';
  37. wfProfileIn( $fname );
  38. $mwEmbedAbsolutePath = ( $wgMwEmbedDirectory == '' ) ? $IP : $IP .'/' .$wgMwEmbedDirectory;
  39. // Add the mwEmbed localizations
  40. $wgExtensionMessagesFiles[ 'mwEmbed' ] = $mwEmbedAbsolutePath . '/mwEmbed.i18n.php';
  41. // Load javascript classes from mwEmbed.js
  42. if ( !is_file( $mwEmbedAbsolutePath . '/loader.js' ) ) {
  43. // throw error no mwEmbed found
  44. throw new MWException( "mwEmbed loader.js missing check \$wgMwEmbedDirectory path\n" );
  45. return false;
  46. }
  47. // Process the mwEmbed loader file:
  48. $fileContent = file_get_contents( $mwEmbedAbsolutePath . '/loader.js' );
  49. self::$directoryContext = $wgMwEmbedDirectory;
  50. self::proccessLoaderContent( $fileContent , 'mwEmbed' );
  51. // Get the list of core component into self::$coreComponentsList
  52. preg_replace_callback(
  53. '/mwCoreComponentList\s*\=\s*\[(.*)\]/siU',
  54. 'NamedResourceLoader::preg_buildComponentList',
  55. $fileContent
  56. );
  57. // Check if we should load module list from mwEmbed loader.js
  58. if( $wgMwEmbedEnabledModules ) {
  59. // Get the list of enabled modules into $moduleList
  60. self::validateModuleList( $wgMwEmbedEnabledModules );
  61. }
  62. // Change to the root mediawiki directory ( loader.js paths are relative to root mediawiki directory )
  63. // ( helpful for when running maintenance scripts )
  64. if( defined( 'DO_MAINTENANCE' ) ) {
  65. $initialPath = getcwd();
  66. chdir( $IP );
  67. }
  68. // Get all the classes from the enabled mwEmbed modules folder
  69. foreach( self::$moduleList as $na => $moduleName ) {
  70. $relativeSlash = ( $wgMwEmbedDirectory == '' )? '' : '/';
  71. $modulePath = $wgMwEmbedDirectory . $relativeSlash . 'modules/' . $moduleName;
  72. self::proccessModulePath( $moduleName, $modulePath );
  73. }
  74. if( ! isset( $wgExtensionJavascriptModules )) {
  75. $wgExtensionJavascriptModules = array();
  76. }
  77. // Get all the extension loader paths registered mwEmbed modules
  78. foreach( $wgExtensionJavascriptModules as $moduleName => $modulePath ){
  79. self::proccessModulePath( $moduleName, $modulePath );
  80. }
  81. if( defined( 'DO_MAINTENANCE' ) ) {
  82. chdir( $initialPath );
  83. }
  84. wfProfileOut( $fname );
  85. }
  86. /**
  87. * Process a loader path, passes off to proccessLoaderContent
  88. *
  89. * @param String $moduleName Name of module to be processed
  90. * @param String $modulePath Path to module to be processed
  91. */
  92. private static function proccessModulePath( $moduleName, $modulePath ){
  93. global $wgExtensionMessagesFiles;
  94. // Get the module name
  95. $modulePathComponents = explode('/', $modulePath );
  96. $moduleName = end( $modulePathComponents );
  97. // Set the directory context for relative js/css paths
  98. self::$directoryContext = $modulePath;
  99. // Check for the loader.js
  100. if( !is_file( $modulePath . '/loader.js' ) ){
  101. throw new MWException( "Javascript Module $moduleName missing loader.js file\n" );
  102. return false;
  103. }
  104. $fileContent = file_get_contents( $modulePath . '/loader.js');
  105. self::proccessLoaderContent( $fileContent, $moduleName );
  106. $i18nPath = realpath( $modulePath . '/' . $moduleName . '.i18n.php' );
  107. // Add the module localization file if present:
  108. if( is_file( $i18nPath ) ) {
  109. $wgExtensionMessagesFiles[ $moduleName ] = $i18nPath;
  110. } else {
  111. // Module has no message file
  112. }
  113. }
  114. /**
  115. * Process loader content
  116. *
  117. * parses the loader files and adds
  118. *
  119. * @param String $fileContent content of loader.js file
  120. */
  121. private static function proccessLoaderContent( & $fileContent , $moduleName){
  122. // Add the mwEmbed loader js to its global collector:
  123. self::$combinedLoadersJs .= $fileContent;
  124. // Is there a way to pass arguments in preg_replace_callback ?
  125. self::$currentModuleName = $moduleName;
  126. // Run the replace callback:
  127. preg_replace_callback(
  128. self::$classReplaceExp,
  129. 'NamedResourceLoader::preg_classPathLoader',
  130. $fileContent
  131. );
  132. }
  133. /**
  134. * Get the language file javascript
  135. * @param String $languageJs The language file javascript
  136. */
  137. public static function getLanguageJs( $langKey = 'en' ){
  138. global $wgMwEmbedDirectory;
  139. $path = $wgMwEmbedDirectory . '/languages/classes/Language' . ucfirst( $langKey ) . '.js';
  140. if( is_file( $path ) ){
  141. $languageJs = file_get_contents( $path );
  142. return $languageJs;
  143. }
  144. return '';
  145. }
  146. /**
  147. * Get the combined loader javascript
  148. *
  149. * @return the combined loader jss
  150. */
  151. public static function getCombinedLoaderJs(){
  152. self::loadResourcePaths();
  153. return self::$combinedLoadersJs;
  154. }
  155. /**
  156. * Get the list of enabled modules
  157. */
  158. public static function getModuleList(){
  159. self::loadResourcePaths();
  160. return self::$moduleList;
  161. }
  162. /**
  163. * Get the list of enabled components
  164. */
  165. public static function getComponentsList(){
  166. self::loadResourcePaths();
  167. return self::$coreComponentsList;
  168. }
  169. /**
  170. * Build a list of components to be included with mwEmbed
  171. */
  172. private static function preg_buildComponentList( $jsvar ){
  173. if(! isset( $jsvar[1] )){
  174. return false;
  175. }
  176. $componentSet = explode(',', $jsvar[1] );
  177. foreach( $componentSet as $na => $componentName ) {
  178. $componentName = str_replace( array( '../', '\'', '"'), '', trim( $componentName ));
  179. // Add the component to the $coreComponentsList
  180. if( trim( $componentName ) != '' ) {
  181. array_push( self::$coreComponentsList, trim( $componentName ) );
  182. }
  183. }
  184. }
  185. /**
  186. * Build the list of modules from the mwEnabledModuleList replace callback
  187. * @param String $moduleSet array of modules to be validated
  188. */
  189. private static function validateModuleList( $moduleSet ){
  190. global $IP, $wgMwEmbedDirectory;
  191. $mwEmbedAbsolutePath = ( $wgMwEmbedDirectory == '' )? $IP: $IP .'/' .$wgMwEmbedDirectory;
  192. foreach( $moduleSet as $na => $moduleName ) {
  193. // Skip empty module names
  194. if(trim( $moduleName ) == '' ){
  195. continue;
  196. }
  197. $moduleName = str_replace( array( '../', '\'', '"'), '', trim( $moduleName ));
  198. // Check if there is there are module loader files
  199. if( is_file( $mwEmbedAbsolutePath . '/modules/' . $moduleName . '/loader.js' )){
  200. array_push( self::$moduleList, $moduleName );
  201. } else {
  202. // Not valid module ( missing loader.js )
  203. throw new MWException( "Module: $moduleName missing loader.js \n" );
  204. }
  205. }
  206. }
  207. /**
  208. * Adds javascript autoloader resource names and paths
  209. * to $wgResourceLoaderNamedPaths global
  210. *
  211. * @param string $jvar Json string with resource name list
  212. */
  213. private static function preg_classPathLoader( $jsvar ) {
  214. global $wgResourceLoaderNamedPaths;
  215. if ( !isset( $jsvar[1] ) ) {
  216. return false;
  217. }
  218. $jClassSet = FormatJson::decode( '{' . $jsvar[1] . '}', true );
  219. // Check for null json decode:
  220. if( $jClassSet == NULL ){
  221. throw new MWException( "Error could not decode javascript resource list for module: " + self::$currentModuleName + "\n" );
  222. return false;
  223. }
  224. foreach ( $jClassSet as $resourceName => $classPath ) {
  225. // Strip $ from resource (as they are stripped on URL request parameter input)
  226. $resourceName = str_replace( '$', '', $resourceName );
  227. $classPath = ( self::$directoryContext == '' )? $classPath : self::$directoryContext . '/' . $classPath;
  228. // Throw an error if we already have defined this class:
  229. // This prevents a module from registering a shared class
  230. // or multiple modules using the same className
  231. if( isset( $wgResourceLoaderNamedPaths[ $resourceName ] ) ){
  232. // Presently extensions don't register were the named path parent module
  233. // so we just have a general extension error.
  234. $setInModuleError = ( self::$resourceParentModuleName [ $resourceName ] )
  235. ? " set in module: " . self::$resourceParentModuleName [ $resourceName ]
  236. : " set in an extension ";
  237. throw new MWException( "Error resource $resourceName already $setInModuleError \n" );
  238. }
  239. // Else update the global $wgResourceLoaderNamedPaths ( all scriptloader named paths )
  240. $wgResourceLoaderNamedPaths[ $resourceName ] = $classPath;
  241. // Register the parent module ( javascript module specific )
  242. self::$resourceParentModuleName [ $resourceName ] = self::$currentModuleName ;
  243. }
  244. }
  245. /**
  246. * Return the module name for a given resource or false if not found
  247. * @param $resourceName resource to get the module for
  248. */
  249. public static function getModuleNameForResource( $resourceName ){
  250. if( isset( self::$resourceParentModuleName [ $resourceName ] ) ){
  251. return self::$resourceParentModuleName [ $resourceName ];
  252. } else {
  253. return false;
  254. }
  255. }
  256. }