Moodle  2.2.1
http://www.collinsharper.com
C:/xampp/htdocs/moodle/lib/yui/phploader/phploader/loader.php
Go to the documentation of this file.
00001 <?PHP
00017 define('YUI_AFTER',      'after');
00018 define('YUI_BASE',       'base');
00019 define('YUI_CSS',        'css');
00020 define('YUI_DATA',       'DATA');
00021 define('YUI_DEPCACHE',   'depCache');
00022 define('YUI_DEBUG',      'DEBUG');
00023 define('YUI_EMBED',      'EMBED');
00024 define('YUI_FILTERS',    'filters');
00025 define('YUI_FULLPATH',   'fullpath');
00026 define('YUI_FULLJSON',   'FULLJSON');
00027 define('YUI_GLOBAL',     'global');
00028 define('YUI_JS',         'js');
00029 define('YUI_JSON',       'JSON');
00030 define('YUI_MODULES',    'modules');
00031 define('YUI_SUBMODULES', 'submodules');
00032 define('YUI_EXPOUND',    'expound');
00033 define('YUI_NAME',       'name');
00034 define('YUI_OPTIONAL',   'optional');
00035 define('YUI_OVERRIDES',  'overrides');
00036 define('YUI_PATH',       'path');
00037 define('YUI_PKG',        'pkg');
00038 define('YUI_PREFIX',     'prefix');
00039 define('YUI_PROVIDES',   'provides');
00040 define('YUI_RAW',        'RAW');
00041 define('YUI_REPLACE',    'replace');
00042 define('YUI_REQUIRES',   'requires');
00043 define('YUI_ROLLUP',     'rollup');
00044 define('YUI_SATISFIES',  'satisfies');
00045 define('YUI_SEARCH',     'search');
00046 define('YUI_SKIN',       'skin');
00047 define('YUI_SKINNABLE',  'skinnable');
00048 define('YUI_SUPERSEDES', 'supersedes');
00049 define('YUI_TAGS',       'TAGS');
00050 define('YUI_TYPE',       'type');
00051 define('YUI_URL',        'url');
00052 
00053 
00059 class YAHOO_util_Loader {
00060     
00067     var $base = "";
00068 
00078     var $filter = "";
00079     
00086     var $filters = array();
00087     
00095     var $filterList = null;
00096 
00103     var $allowRollups = true;
00104 
00111     var $loadOptional = false;
00112 
00120     var $rollupsToTop = false;
00121 
00129     var $processedModuleTypes = array();
00130 
00137     var $requests = array();
00138 
00145     var $loaded = array();
00146 
00153     var $superceded = array();
00154 
00161     var $undefined = array();
00162     
00169     var $dirty = true;
00170     
00177     var $sorted = null;
00178     
00185     var $accountedFor = array();
00186 
00193     var $skins = array();
00194     
00201     var $modules = array();
00202 
00209     var $fullCacheKey = null;
00210 
00217     var $baseOverrides = array();
00218     
00225     var $cacheFound = false;
00226     
00233     var $delayCache = false;
00234     
00235     /* If the version is set, a querystring parameter is appended to the
00236     * end of all generated URLs.  This is a cache busting hack for environments
00237     * that always use the same path for the current version of the library.
00238     * @property version
00239     * @type string
00240     * @default null
00241     */
00242     var $version = null;
00243     var $versionKey = "_yuiversion";
00244 
00245     /* Holds the calculated skin definition
00246     * @property skin
00247     * @type array
00248     * @default
00249     */
00250     var $skin = array();
00251     
00252     /* Holds the module rollup metadata
00253     * @property rollupModules
00254     * @type array
00255     * @default
00256     */
00257     var $rollupModules = array();
00258     
00259     /* Holds global module information.  Used for global dependency support.
00260     * Note: Does not appear to be in use by recent metadata.  Might be deprecated?
00261     * @property globalModules
00262     * @type array
00263     * @default
00264     */
00265     var $globalModules = array();
00266     
00267     /* Holds information about what modules satisfy the requirements of others
00268     * @property satisfactionMap
00269     * @type array
00270     * @default
00271     */
00272     var $satisfactionMap = array();
00273     
00274     /* Holds a cached module dependency list
00275     * @property depCache
00276     * @type array
00277     * @default
00278     */
00279     var $depCache = array();
00280     
00288     var $combine = false;
00289 
00298     var $comboBase = "http://yui.yahooapis.com/combo?";
00299     
00308     var $cssComboLocation = null;
00309     
00318     var $jsComboLocation  = null;
00319 
00330     function YAHOO_util_Loader($yuiVersion, $cacheKey=null, $modules=null, $noYUI=false) {
00331         if (!isset($yuiVersion)) {
00332             die("Error: The first parameter of YAHOO_util_Loader must specify which version of YUI to use!");
00333         }
00334         
00335         /* 
00336         * Include the metadata config file that corresponds to the requested YUI version
00337         * Note: we attempt to find a prebuilt config_{version}.php file which contains an associative array,
00338         * but if not available we'll attempt to find and parse the YUI json dependency file.
00339         */
00340         $parentDir = dirname(dirname(__FILE__));
00341         $phpConfigFile = $parentDir . '/lib/meta/config_' . $yuiVersion . '.php';
00342         $jsonConfigFile = $parentDir . '/lib/meta/json_' . $yuiVersion . '.txt';
00343         
00344         if (file_exists($phpConfigFile) && is_readable($phpConfigFile)) {
00345             require($phpConfigFile);
00346         } else if (file_exists($jsonConfigFile) && is_readable($jsonConfigFile) && function_exists('json_encode')) {
00347             $jsonConfigString = file_get_contents($jsonConfigFile);
00348             $inf = json_decode($jsonConfigString, true);
00349             $GLOBALS['yui_current'] = $inf;
00350         } else {
00351             die("Unable to find a suitable YUI metadata file!");
00352         }
00353         
00354         global $yui_current;
00355 
00356         $this->apcttl = 0;
00357         $this->curlAvail  = function_exists('curl_exec');
00358         $this->apcAvail   = function_exists('apc_fetch');
00359         $this->jsonAvail  = function_exists('json_encode');
00360         $this->customModulesInUse = empty($modules) ? false : true;
00361         $this->base = $yui_current[YUI_BASE];
00362         $this->comboDefaultVersion = $yuiVersion;
00363         $this->fullCacheKey = null;
00364         $cache = null;
00365 
00366         if ($cacheKey && $this->apcAvail) {
00367             $this->fullCacheKey = $this->base . $cacheKey;
00368             $cache = apc_fetch($this->fullCacheKey);
00369         } 
00370         
00371         if ($cache) {
00372             $this->cacheFound = true;
00373             $this->modules = $cache[YUI_MODULES];
00374             $this->skin = $cache[YUI_SKIN];
00375             $this->rollupModules = $cache[YUI_ROLLUP];
00376             $this->globalModules = $cache[YUI_GLOBAL];
00377             $this->satisfactionMap = $cache[YUI_SATISFIES];
00378             $this->depCache = $cache[YUI_DEPCACHE];
00379             $this->filters = $cache[YUI_FILTERS];
00380         } else {
00381             // set up the YUI info for the current version of the lib
00382             if ($noYUI) {
00383                 $this->modules = array();
00384             } else {
00385                 $this->modules = $yui_current['moduleInfo'];
00386             }
00387 
00388             if ($modules) {
00389                 $this->modules = array_merge_recursive($this->modules, $modules);
00390             }
00391 
00392             $this->skin = $yui_current[YUI_SKIN];
00393             $this->skin['overrides'] = array();
00394             $this->skin[YUI_PREFIX] = "skin-";
00395             $this->filters = array(
00396                     YUI_RAW => array(
00397                             YUI_SEARCH => "/-min\.js/",
00398                             YUI_REPLACE => ".js"
00399                         ),
00400                     YUI_DEBUG => array(
00401                             YUI_SEARCH => "/-min\.js/",
00402                             YUI_REPLACE => "-debug.js"
00403                         )
00404                );
00405 
00406             foreach ($this->modules as $name=>$m) {
00407 
00408                 if (isset($m[YUI_GLOBAL])) {
00409                     $this->globalModules[$name] = true;
00410                 }
00411 
00412                 if (isset($m[YUI_SUPERSEDES])) {
00413                     $this->rollupModules[$name] = $m;
00414                     foreach ($m[YUI_SUPERSEDES] as $sup) {
00415                         $this->mapSatisfyingModule($sup, $name);
00416                     }
00417                 }
00418             }
00419         }
00420     }
00421     
00426     function updateCache() {
00427         if ($this->fullCacheKey) {
00428             $cache = array();
00429             $cache[YUI_MODULES] = $this->modules;
00430             $cache[YUI_SKIN] = $this->skin;
00431             $cache[YUI_ROLLUP] = $this->rollupModules;
00432             $cache[YUI_GLOBAL] = $this->globalModules;
00433             $cache[YUI_DEPCACHE] = $this->depCache;
00434             $cache[YUI_SATISFIES] = $this->satisfactionMap;
00435             $cache[YUI_FILTERS] = $this->filters;
00436             apc_store($this->fullCacheKey, $cache, $this->apcttl);
00437         }
00438     }
00439 
00445     function load() {
00446         //Expects N-number of named components to load 
00447         $args = func_get_args();
00448         foreach ($args as $arg) {
00449             $this->loadSingle($arg);
00450         }
00451     }
00452     
00458     function setProcessedModuleType($moduleType='ALL') {
00459         $this->processedModuleTypes[$moduleType] = true;
00460     }
00461     
00467     function hasProcessedModuleType($moduleType='ALL') {
00468         return isset($this->processedModuleTypes[$moduleType]);
00469     }
00470 
00476     function setLoaded() {
00477         $args = func_get_args();
00478 
00479         foreach ($args as $arg) {
00480             if (isset($this->modules[$arg])) {
00481                 $this->loaded[$arg] = $arg;
00482                 $mod = $this->modules[$arg];
00483 
00484                 $sups = $this->getSuperceded($arg);
00485                 // accounting for by way of supersede
00486                 foreach ($sups as $supname=>$val) {
00487                     $this->loaded[$supname] = $supname;
00488                 }
00489 
00490                 // prevent rollups for this module type
00491                 $this->setProcessedModuleType($mod[YUI_TYPE]);
00492             } else {
00493                 $msg = "YUI_LOADER: undefined module name provided to setLoaded(): " . $arg;
00494                 error_log($msg, 0);
00495             }
00496         }
00497     }
00498     
00505     function skinSetup($name) {
00506         $skinName = null;
00507         $dep = $this->modules[$name];
00508 
00509         if ($dep && isset($dep[YUI_SKINNABLE])) {
00510             $s = $this->skin;
00511             
00512             if (isset($s[YUI_OVERRIDES][$name])) {
00513                 foreach ($s[YUI_OVERRIDES][$name] as $name2 => $over2) {
00514                     $skinName = $this->formatSkin($over2, $name);
00515                 }
00516             } else {
00517                 $skinName = $this->formatSkin($s["defaultSkin"], $name);
00518             }
00519 
00520             // adding new skin module
00521             $this->skins[] = $skinName;
00522             $skin = $this->parseSkin($skinName);
00523 
00524             // module-specific
00525             if (isset($skin[2])) {
00526                 $dep = $this->modules[$skin[2]];
00527                 $package = (isset($dep[YUI_PKG])) ? $dep[YUI_PKG] : $skin[2];
00528                 $path = $package . '/' . $s[YUI_BASE] . $skin[1] . '/' . $skin[2] . '.css';
00529                 $this->modules[$skinName] = array(
00530                         "name" => $skinName,
00531                         "type" => YUI_CSS,
00532                         "path" => $path,
00533                         "after" => $s[YUI_AFTER]
00534                     );
00535 
00536             // rollup skin
00537             } else {
00538                 $path = $s[YUI_BASE] . $skin[1] . '/' . $s[YUI_PATH];
00539                 $newmod = array(
00540                         "name" => $skinName,
00541                         "type" => YUI_CSS,
00542                         "path" => $path,
00543                         "rollup" => 3,
00544                         "after" => $s[YUI_AFTER]
00545                     );
00546                 $this->modules[$skinName] = $newmod;
00547                 $this->rollupModules[$skinName] = $newmod;
00548             }
00549 
00550         }    
00551 
00552         return $skinName;
00553     }
00554     
00561     function parseSkin($moduleName) {
00562         if (strpos( $moduleName, $this->skin[YUI_PREFIX] ) === 0) {
00563             return explode('-', $moduleName);
00564         }
00565 
00566         return null;
00567     }
00568     
00576     function formatSkin($skin, $moduleName) {
00577         $prefix = $this->skin[YUI_PREFIX];
00578         $s = $prefix . $skin;
00579         if ($moduleName) {
00580             $s = $s . '-' . $moduleName;
00581         }
00582 
00583         return $s;
00584     }
00585     
00592     function loadSingle($name) {
00593         $skin = $this->parseSkin($name);
00594 
00595         if ($skin) {
00596             $this->skins[] = $name;
00597             $this->dirty = true;
00598             return true;
00599         }
00600 
00601         if (!isset($this->modules[$name])) {
00602             $this -> undefined[$name] = $name;
00603             return false;
00604         }
00605 
00606         if (isset($this->loaded[$name]) || isset($this->accountedFor[$name])) {
00607             // skip
00608         } else {
00609             $this->requests[$name] = $name;
00610             $this->dirty = true;
00611         }
00612         
00613         return true;
00614     }
00615 
00621     function script() {
00622         return $this->tags(YUI_JS);
00623     }
00624     
00630     function css() {
00631         return $this->tags(YUI_CSS);
00632     }
00633 
00641     function tags($moduleType=null, $skipSort=false) {
00642         return $this->processDependencies(YUI_TAGS, $moduleType, $skipSort);
00643     }
00644     
00650     function script_embed() {
00651         return $this->embed(YUI_JS);
00652     }
00653     
00659     function css_embed() {
00660         return $this->embed(YUI_CSS);
00661     }
00662 
00670     function embed($moduleType=null, $skipSort=false) {
00671         return $this->processDependencies(YUI_EMBED, $moduleType, $skipSort);
00672     }
00673 
00679     function script_data() {
00680         return $this->data(YUI_JS);
00681     }
00682 
00688     function css_data() {
00689         return $this->data(YUI_CSS);
00690     }
00691     
00700     function data($moduleType=null, $allowRollups=false, $skipSort=false) {
00701         if (!$allowRollups) {
00702             $this->setProcessedModuleType($moduleType);
00703         }
00704 
00705         $type = YUI_DATA;
00706 
00707         return $this->processDependencies($type, $moduleType, $skipSort);
00708     }
00709 
00715     function script_json() {
00716         return $this->json(YUI_JS);
00717     }
00718     
00724     function css_json() {
00725         return $this->json(YUI_CSS);
00726     }
00727 
00737     function json($moduleType=null, $allowRollups=false, $skipSort=false, $full=false) {
00738         if (!$allowRollups) {
00739             $this->setProcessedModuleType($moduleType);
00740         }
00741 
00742         // the original JSON output only sent the provides data, not the requires
00743         $type = YUI_JSON;
00744 
00745         if ($full) {
00746             $type = YUI_FULLJSON;
00747         }
00748 
00749         return $this->processDependencies($type, $moduleType, $skipSort);
00750     }
00751  
00757     function script_raw() {
00758         return $this->raw(YUI_JS);
00759     }
00760 
00766     function css_raw() {
00767         return $this->raw(YUI_CSS);
00768     }
00769 
00778     function raw($moduleType=null, $allowRollups=false, $skipSort=false) {
00779         return $this->processDependencies(YUI_RAW, $moduleType, $skipSort);
00780     }
00781     
00787     function log($msg) {
00788         error_log($msg, 0);
00789     }
00790     
00796     function accountFor($name) {
00797         $this->accountedFor[$name] = $name;
00798         
00799         if (isset($this->modules[$name])) {
00800             $dep = $this->modules[$name];
00801             $sups = $this->getSuperceded($name);
00802             foreach ($sups as $supname=>$val) {
00803                 // accounting for by way of supersede package
00804                 $this->accountedFor[$supname] = true;
00805             }
00806         }
00807     }
00808 
00816     function prune($deps, $moduleType) {
00817         if ($moduleType) {
00818             $newdeps = array();
00819             foreach ($deps as $name=>$val) {
00820                 $dep = $this->modules[$name];
00821                 if ($dep[YUI_TYPE] == $moduleType) {
00822                     $newdeps[$name] = true;
00823                 }
00824             }
00825             return $newdeps;
00826         } else {
00827             return $deps;
00828         }
00829    }
00830    
00837    function getSuperceded($name) {
00838         $key = YUI_SUPERSEDES . $name;
00839 
00840         if (isset($this->depCache[$key])) {
00841             return $this->depCache[$key];
00842         }
00843 
00844         $sups = array();
00845 
00846         if (isset($this->modules[$name])) {
00847             $m = $this->modules[$name];
00848             if (isset($m[YUI_SUPERSEDES])) {
00849                 foreach ($m[YUI_SUPERSEDES] as $supName) {
00850                     $sups[$supName] = true;
00851                     if (isset($this->modules[$supName])) {
00852                         $supsups = $this->getSuperceded($supName);
00853                         if (count($supsups) > 0) {
00854                             $sups = array_merge($sups, $supsups);
00855                         }
00856                     } 
00857                 }
00858             }
00859         }
00860 
00861         $this->depCache[$key] = $sups;
00862         return $sups;
00863     }
00864     
00873     function getAllDependencies($mname, $loadOptional=false, $completed=array()) {
00874         $key = YUI_REQUIRES . $mname;
00875         if ($loadOptional) {
00876             $key .= YUI_OPTIONAL;
00877         }
00878         
00879         if (isset($this->depCache[$key])) {
00880             return $this->depCache[$key];
00881         }
00882         
00883         $m = $this->modules[$mname];
00884         $mProvides = $this->getProvides($mname);
00885         $reqs = array();
00886     
00887             //Some modules pretend to be others (override if this is the case)
00888         if (isset($this->modules[$mname][YUI_EXPOUND])) {
00889                         if (!isset($completed[$mname])) {
00890                                 $reqs = array_merge($completed, $this->getAllDependencies($this->modules[$mname][YUI_EXPOUND], $loadOptional, array($mname => true)));
00891                         }
00892         }
00893 
00894         //Add any requirements defined on the module itself
00895         if (isset($m[YUI_REQUIRES])) {
00896             $origreqs = $m[YUI_REQUIRES];
00897             foreach($origreqs as $r) {
00898                 if (!isset($reqs[$r])) {
00899                         $reqs[$r] = true;
00900                         $reqs = array_merge($reqs, $this->getAllDependencies($r, $loadOptional, $reqs));
00901                 }
00902             }
00903         }
00904          
00905         //Add any submodule requirements not provided by the rollups
00906         if (isset($m[YUI_SUBMODULES])) {
00907             foreach($m[YUI_SUBMODULES] as $submodule) {
00908                 $subreqs = $submodule[YUI_REQUIRES];
00909                 foreach($subreqs as $sr) {     
00910                     if (!in_array($sr, $mProvides) && !in_array($sr, $this->accountedFor)) {
00911                                 if (!isset($reqs[$sr])) {
00912                                 $reqs[$sr] = true; 
00913                                 $reqs = array_merge($reqs, $this->getAllDependencies($sr, $loadOptional, $reqs));
00914                                 }
00915                     }
00916                 }
00917             }
00918         }
00919         
00920         //Add any superseded requirements not provided by the rollup and/or rollup submodules
00921         if (isset($m[YUI_SUPERSEDES])) {
00922             foreach($m[YUI_SUPERSEDES] as $supersededModule) {
00923                 if (isset($this->modules[$supersededModule][YUI_REQUIRES])) {
00924                     foreach($this->modules[$supersededModule][YUI_REQUIRES] as $supersededModuleReq) {
00925                         if (!in_array($supersededModuleReq, $mProvides)) {
00926                                         if (!isset($reqs[$supersededModuleReq])) {
00927                                     $reqs[$supersededModuleReq] = true;
00928                                     $reqs = array_merge($reqs, $this->getAllDependencies($supersededModuleReq, $loadOptional, $reqs));
00929                                         }
00930                         }
00931                     }
00932                 }
00933                 
00934                 //Add any submodule requirements not provided by the rollup or originally requested module
00935                 if (isset($this->modules[$supersededModule][YUI_SUBMODULES])) {
00936                     foreach($this->modules[$supersededModule][YUI_SUBMODULES] as $supersededSubmodule) {
00937                         $ssmProvides = $this->getProvides($supersededModule);
00938                         $supersededSubreqs = $supersededSubmodule[YUI_REQUIRES];
00939                         foreach($supersededSubreqs as $ssr) {     
00940                             if (!in_array($ssr, $ssmProvides)) {
00941                                                 if (!isset($reqs[$ssr])) {
00942                                         $reqs[$ssr] = true;
00943                                         $reqs = array_merge($reqs, $this->getAllDependencies($ssr, $loadOptional, $reqs));
00944                                                 }
00945                             }
00946                         }
00947                     }
00948                 }
00949             }
00950         }
00951 
00952         if ($loadOptional && isset($m[YUI_OPTIONAL])) {
00953             $o = $m[YUI_OPTIONAL];
00954             foreach($o as $opt) {
00955                 $reqs[$opt] = true;
00956             }
00957         }
00958 
00959         $this->depCache[$key] = $reqs;
00960         
00961         return $reqs;
00962     }
00963 
00964     // @todo restore global dependency support
00965     function getGlobalDependencies() {
00966         return $this->globalModules;
00967     }
00968 
00973     function moduleSatisfies($satisfied, $satisfier) {
00974         if($satisfied == $satisfier) {
00975             return true;
00976         }
00977 
00978         if (isset($this->satisfactionMap[$satisfied])) {
00979             $satisfiers = $this->satisfactionMap[$satisfied];
00980             return isset($satisfiers[$satisfier]);
00981         }
00982 
00983         return false;
00984     }
00985 
00992     function overrideBase($base, $modules) {
00993         foreach ($modules as $name) {
00994             $this->baseOverrides[$name] = $base;
00995         }
00996     }
00997     
01005     function listSatisfies($satisfied, $moduleList) {
01006         if (isset($moduleList[$satisfied])) {
01007             return true;
01008         } else {
01009             if (isset($this->satisfactionMap[$satisfied])) {
01010                 $satisfiers = $this->satisfactionMap[$satisfied];
01011                 foreach ($satisfiers as $name=>$val) {
01012                     if (isset($moduleList[$name])) {
01013                         return true;
01014                     }
01015                 }
01016             }
01017         }
01018 
01019         return false;
01020     }
01021     
01029     function checkThreshold($module, $moduleList) {
01030         if (count($moduleList) > 0 && isset($module[YUI_ROLLUP])) {
01031             $matched = 0;
01032             $thresh = $module[YUI_ROLLUP];
01033             foreach ($moduleList as $moduleName=>$moddef) {
01034                 if (in_array($moduleName, $module[YUI_SUPERSEDES])) {
01035                     $matched++;
01036                 }
01037             }
01038             
01039             return ($matched >= $thresh);
01040         }
01041 
01042         return false;
01043     }
01044     
01052     function sortDependencies($moduleType, $skipSort=false) {
01053         $reqs = array();
01054         $top = array();
01055         $bot = array();
01056         $notdone = array();
01057         $sorted = array();
01058         $found = array();
01059 
01060         // add global dependenices so they are included when calculating rollups
01061         $globals = $this->getGlobalDependencies($moduleType);
01062         
01063         foreach ($globals as $name=>$dep) {
01064             $reqs[$name] = true;
01065         }
01066         
01067         // get and store the full list of dependencies.
01068         foreach ($this->requests as $name=>$val) {
01069             $reqs[$name] = true;
01070             $dep = $this->modules[$name];
01071             $newreqs = $this->getAllDependencies($name, $this->loadOptional);
01072             
01073             foreach ($newreqs as $newname=>$newval) {
01074                 if (!isset($reqs[$newname])) {
01075                     $reqs[$newname] = true;
01076                 }
01077             }
01078         }
01079 
01080         // if we skip the sort, we just return the list that includes everything that
01081         // was requested, all of their requirements, and global modules.  This is
01082         // filtered by module type if supplied
01083         if ($skipSort) {
01084             return $this->prune($reqs, $moduleType);
01085         }
01086 
01087         // if we are sorting again after new modules have been requested, we
01088         // do not rollup, and we can remove the accounted for modules
01089         if (count($this->accountedFor) > 0 || count($this->loaded) > 0) {
01090             foreach ($this->accountedFor as $name=>$val) {
01091                 if (isset($reqs[$name])) {
01092                     unset($reqs[$name]);
01093                 }
01094             }
01095             
01096             // removing satisfied req (loaded)
01097             foreach ($this->loaded as $name=>$val) {
01098                 if (isset($reqs[$name])) {
01099                     unset($reqs[$name]);
01100                 }
01101             }
01102         } else if ($this->allowRollups) {
01103             // First we go through the meta-modules we know about to 
01104             // see if the replacement threshold has been met.
01105             $rollups = $this->rollupModules;
01106 
01107             if (count($rollups > 0)) {
01108                 foreach ($rollups as $name => $rollup) {
01109                     if (!isset($reqs[$name]) && $this->checkThreshold($rollup, $reqs) ) {
01110                         $reqs[$name] = true;
01111                         $dep = $this->modules[$name];
01112                         $newreqs = $this->getAllDependencies($name, $this->loadOptional, $reqs);
01113                         foreach ($newreqs as $newname=>$newval) {
01114                             if (!isset($reqs[$newname])) {
01115                                 $reqs[$newname] = true;
01116                             }
01117                         }
01118                     }
01119                 }
01120             }
01121         }
01122 
01123         // clear out superceded packages
01124         foreach ($reqs as $name => $val) {
01125             $dep = $this->modules[$name];
01126 
01127             if (isset($dep[YUI_SUPERSEDES])) {
01128                 $override = $dep[YUI_SUPERSEDES];
01129                 
01130                 foreach ($override as $i=>$val) {
01131                     if (isset($reqs[$val])) {
01132                         unset($reqs[$val]);
01133                     }
01134 
01135                     if (isset($reqs[$i])) {
01136                         unset($reqs[$i]);
01137                     }
01138                 }
01139             }
01140         }
01141 
01142         // move globals to the top
01143         foreach ($reqs as $name => $val) {
01144             $dep = $this->modules[$name];
01145             if (isset($dep[YUI_GLOBAL]) && $dep[YUI_GLOBAL]) {
01146                 $top[$name] = $name;
01147             } else {
01148                 $notdone[$name] = $name;
01149             }
01150         }
01151 
01152         // merge new order if we have globals   
01153         if (count($top > 0)) {
01154             $notdone = array_merge($top, $notdone);
01155         }
01156 
01157         // keep track of what is accounted for
01158         foreach ($this->loaded as $name=>$module) {
01159             $this->accountFor($name);
01160         }
01161 
01162         // keep going until everything is sorted
01163         $count = 0;
01164         while (count($notdone) > 0) {
01165             if ($count++ > 200) {
01166                 $msg = "YUI_LOADER ERROR: sorting could not be completed, there may be a circular dependency";
01167                 error_log($msg, 0);
01168                 return array_merge($sorted, $notdone);
01169             }
01170             
01171             // each pass only processed what has not been completed
01172             foreach ($notdone as $name => $val) {
01173                 $dep = $this->modules[$name];                
01174                 $newreqs = $this->getAllDependencies($name, $this->loadOptional);
01175                 $this->accountFor($name);    
01176                 
01177                 //Detect if this module needs to be included after another one of the upcoming dependencies
01178                 if (isset($dep[YUI_AFTER])) {
01179                     $after = $dep[YUI_AFTER];
01180                     
01181                     foreach($after as $a) {
01182                         if (in_array($a, $notdone)) {
01183                             $newreqs[$a] = true;
01184                         }
01185                     }
01186                 }
01187 
01188                 if (!empty($newreqs)) {
01189                     foreach ($newreqs as $depname=>$depval) {
01190                         // check if the item is accounted for in the $done list
01191                         if (isset($this->accountedFor[$depname]) || $this->listSatisfies($depname, $sorted)) {
01192                                 //unset($notdone[$depname]);
01193                         } else {
01194                             $tmp = array();
01195                             $found = false;
01196                             foreach ($notdone as $newname => $newval) {
01197                                 if ($this->moduleSatisfies($depname, $newname)) {
01198                                     $tmp[$newname] = $newname;
01199                                     unset($notdone[$newname]);
01200                                     $found = true;
01201                                     break; // found something that takes care of the dependency, so jump out
01202                                 }
01203                             }
01204                             
01205                             if ($found) {
01206                                 // this should put the module that handles the dependency on top, immediately
01207                                 // over the the item with the missing dependency
01208                                 $notdone = array_merge($tmp, $notdone);
01209                             } else {
01210                                 //Requirement was missing and not found within the current notdone list.  Add and try again.
01211                                 $notdone[$depname] = $depname;
01212                             }
01213                             
01214                             break(2); // break out of this iteration so we can get the missed dependency
01215                         }
01216                     }
01217                 }
01218             
01219                 $sorted[$name] = $name;
01220                 unset($notdone[$name]);
01221             }
01222         }
01223         
01224         //Deal with module skins
01225         foreach ($sorted as $name => $val) {
01226             $skinName = $this->skinSetup($name);
01227         }
01228 
01229         if ( count($this->skins) > 0 ) {
01230             foreach ($this->skins as $name => $val) {
01231                 $sorted[$val] = true;
01232             }
01233         }
01234 
01235         $this->dirty = false;
01236         $this->sorted = $sorted;
01237 
01238         // store the results, set clear the diry flag
01239         return $this->prune($sorted, $moduleType);
01240     }
01241  
01242     function mapSatisfyingModule($satisfied, $satisfier) {
01243         if (!isset($this->satisfactionMap[$satisfied])) {
01244             $this->satisfactionMap[$satisfied] = array();
01245         }
01246 
01247         $this->satisfactionMap[$satisfied][$satisfier] = true;
01248     }
01249     
01260     function processDependencies($outputType, $moduleType, $skipSort=false, $showLoaded=false) {
01261         $html = '';
01262 
01263         // sort the output with css on top unless the output type is json
01264         if ((!$moduleType) && (strpos($outputType, YUI_JSON) === false) && $outputType != YUI_DATA) {
01265             $this->delayCache = true;
01266             $css = $this->processDependencies($outputType, YUI_CSS, $skipSort, $showLoaded);
01267             $js  = $this->processDependencies($outputType, YUI_JS, $skipSort, $showLoaded);
01268 
01269             // If the data has not been cached, cache what we have
01270             if (!$this->cacheFound) {
01271                 $this->updateCache();
01272             }
01273 
01274             return $css . $js;
01275         }
01276         
01277         $json = array();
01278 
01279         if ($showLoaded || (!$this->dirty && count($this->sorted) > 0)) {
01280             $sorted = $this->prune($this->sorted, $moduleType);
01281         } else {
01282             $sorted = $this->sortDependencies($moduleType, $skipSort);
01283         }
01284 
01285         foreach ($sorted as $name => $val) {
01286             if ($showLoaded || !isset($this->loaded[$name])) {
01287                 $dep = $this->modules[$name];
01288                 // only generate the tag once
01289                 switch ($outputType) {
01290                     case YUI_EMBED:
01291                         $html .= $this->getContent($name, $dep[YUI_TYPE])."\n";
01292                         break;
01293                     case YUI_RAW:
01294                         $html .= $this->getRaw($name)."\n";
01295                         break;
01296                     case YUI_JSON:
01297                     case YUI_DATA:
01298                         //$json[$dep[YUI_TYPE]][$this->getUrl($name)] = $this->getProvides($name);
01299                         $json[$dep[YUI_TYPE]][] = array(
01300                                 $this->getUrl($name) => $this->getProvides($name)
01301                             );
01302                         break;
01303                     case YUI_FULLJSON:
01304                         $json[$dep[YUI_NAME]] = array();
01305                         $item = $json[$dep[YUI_NAME]];
01306                         $item[YUI_TYPE] = $dep[YUI_TYPE];
01307                         $item[YUI_URL] = $this->getUrl($name);
01308                         $item[YUI_PROVIDES] = $this->getProvides($name);
01309                         $item[YUI_REQUIRES] = $dep[YUI_REQUIRES];
01310                         $item[YUI_OPTIONAL] = $dep[YUI_OPTIONAL];
01311                         break;
01312                     case YUI_TAGS:
01313                     default:
01314                         if ($this->combine === true && $this->customModulesInUse === false) {
01315                             $this->addToCombo($name, $dep[YUI_TYPE]);
01316                             $html = $this->getComboLink($dep[YUI_TYPE]);
01317                         } else {
01318                            $html .= $this->getLink($name, $dep[YUI_TYPE])."\n";
01319                         }
01320                 }
01321             }
01322         }
01323 
01324         // If the data has not been cached, and we are not running two
01325         // rotations for separating css and js, cache what we have
01326         if (!$this->cacheFound && !$this->delayCache) {
01327             $this->updateCache();
01328         }
01329 
01330         if (!empty($json)) {
01331             if ($this->canJSON()) {
01332                 $html .= json_encode($json);
01333             } else {
01334                 $html .= "<!-- JSON not available, request failed -->";
01335             }
01336         }
01337 
01338         // after the first pass we no longer try to use meta modules
01339         $this->setProcessedModuleType($moduleType);
01340 
01341         // keep track of all the stuff we loaded so that we don't reload 
01342         // scripts if the page makes multiple calls to tags
01343         $this->loaded = array_merge($this->loaded, $sorted);
01344         if ($this->combine === true) {
01345             $this->clearComboLink($outputType);
01346         }
01347 
01348         // return the raw data structure
01349         if ($outputType == YUI_DATA) {
01350             return $json;
01351         }
01352 
01353         if ( count($this->undefined) > 0 ) {
01354             $html .= "<!-- The following modules were requested but are not defined: " . join($this -> undefined, ",") . " -->\n";
01355         }
01356 
01357         return $html;
01358     }
01359 
01365     function getUrl($name) {
01366         // figure out how to set targets and filters
01367         $url = "";
01368         $b = $this->base;
01369         if (isset($this->baseOverrides[$name])) {
01370             $b = $this->baseOverrides[$name];
01371         }
01372 
01373         if (isset($this->modules[$name])) {
01374             $m = $this->modules[$name];
01375             if (isset($m[YUI_FULLPATH])) {
01376                 $url = $m[YUI_FULLPATH];
01377             } else {
01378                 $url = $b . $m[YUI_PATH];
01379             }
01380         } else {
01381             $url = $b . $name;
01382         }
01383 
01384         if ($this->filter) {
01385             if (count($this->filterList) > 0 && !isset($this->filterList[$name])) {
01386                 // skip the filter
01387             } else if (isset($this->filters[$this->filter])) {
01388                 $filter = $this->filters[$this->filter];
01389                 $url = preg_replace($filter[YUI_SEARCH], $filter[YUI_REPLACE], $url);
01390             }
01391         }
01392 
01393         if ($this->version) {
01394             $pre = (strstr($url, '?')) ? '&' : '?';
01395             $url .= $pre . $this->versionKey . '=' . $this->version;
01396         }
01397         
01398         return $url;
01399     }
01400 
01407     function getRemoteContent($url) {
01408         $remote_content = null;
01409         if ($this->apcAvail === true) {
01410             $remote_content = apc_fetch($url);
01411         }        
01412 
01413         if (!$remote_content) {
01414             if($this->curlAvail === true) {
01415                 $ch = curl_init();
01416                 curl_setopt($ch, CURLOPT_URL, $url);
01417                 curl_setopt($ch, CURLOPT_FAILONERROR, 1); 
01418 
01419                 //Doesn't work in safe mode or with openbase_dir enabled, see http://au.php.net/manual/ro/function.curl-setopt.php#71313.
01420                 $open_basedir = ini_get("open_basedir");
01421                 if (empty($open_basedir) && !ini_get('safe_mode')) {
01422                     curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);// allow redirects
01423                 }
01424 
01425                 curl_setopt($ch, CURLOPT_RETURNTRANSFER,1); // return into a variable 
01426                 // curl_setopt($ch, CURLOPT_TIMEOUT, 3); // times out after 4s
01427 
01428                 $remote_content = curl_exec($ch);
01429 
01430                 // save the contents of the remote url for 30 minutes
01431                 if ($this->apcAvail === true) {
01432                     apc_store($url, $remote_content, $this->apcttl);
01433                 }
01434 
01435                 curl_close ($ch);
01436             } else {
01437                 $remote_content = "<!--// cURL was not detected, so the content cannot be fetched -->";
01438             }   
01439         }
01440 
01441         return $remote_content;
01442     }
01443     
01450     function getRaw($name) {        
01451         if(!$this->curlAvail) {
01452             return "<!--// cURL was not detected, so the content cannot be fetched -->";
01453         }
01454 
01455         $url = $this->getUrl($name);
01456         return $this->getRemoteContent($url);
01457     }
01458 
01466     function getContent($name, $type) {
01467         if(!$this->curlAvail) {
01468             return "<!--// cURL was not detected, so the content cannot be fetched/embedded -->" . $this->getLink($name, $type);
01469         }
01470 
01471         $url = $this->getUrl($name);
01472 
01473         if (!$url) {
01474             return '<!-- PATH FOR "'. $name . '" NOT SPECIFIED -->';
01475         } else if ($type == YUI_CSS) {
01476             return '<style type="text/css">' . $this->getRemoteContent($url) . '</style>';
01477         } else {
01478             return '<script type="text/javascript">' . $this->getRemoteContent($url) . '</script>'; 
01479         }
01480     }
01481     
01489     function getLink($name, $type) {
01490         $url = $this->getUrl($name);
01491 
01492         if (!$url) {
01493             return '<!-- PATH FOR "'. $name . '" NOT SPECIFIED -->';
01494         } else if ($type == YUI_CSS) {
01495             return '<link rel="stylesheet" type="text/css" href="' . $url . '" />';
01496         } else {
01497             return '<script type="text/javascript" src="' . $url . '"></script>';
01498         }
01499     }
01500   
01507     function getComboLink($type) {
01508         $url = '';
01509         
01510         if ($type == YUI_CSS) {
01511             if ($this->cssComboLocation !== null) {
01512                 $url = "<link rel=\"stylesheet\" type=\"text/css\" href=\"{$this->cssComboLocation}\" />";
01513             } else {
01514                 $url = "<!-- NO YUI CSS COMPONENTS IDENTIFIED -->";
01515             }
01516         } else if ($type == YUI_JS) {
01517             if ($this->jsComboLocation !== null) {
01518                 if ($this->cssComboLocation !== null) {
01519                     $url = "\n";
01520                 }
01521                 $url .= "<script type=\"text/javascript\" src=\"{$this->jsComboLocation}\"></script>";
01522             } else {
01523                 $url = "<!-- NO YUI JAVASCRIPT COMPONENTS IDENTIFIED -->";
01524             }
01525         }
01526         
01527         //Allow for RAW & DEBUG over minified default
01528         if ($this->filter) {
01529             if (count($this->filterList) > 0 && !isset($this->filterList[$name])) {
01530                 // skip the filter
01531             } else if (isset($this->filters[$this->filter])) {
01532                 $filter = $this->filters[$this->filter];
01533                 $url = preg_replace($filter[YUI_SEARCH], $filter[YUI_REPLACE], $url);
01534             }
01535         }
01536         
01537         return $url;
01538     }
01539     
01546     function clearComboLink($type) {
01547         if ($type == YUI_CSS) {
01548             $this->cssComboLocation = null;
01549         } else if ($type == YUI_JS) {
01550             $this->jsComboLocation = null;
01551         } else {
01552             $this->cssComboLocation = null;
01553             $this->jsComboLocation  = null;
01554         }
01555     }
01556     
01563     function addToCombo($name, $type) {
01564         $pathToModule = $this->comboDefaultVersion . '/build/' . $this->modules[$name][YUI_PATH];
01565         if ($type == YUI_CSS) {
01566             //If this is the first css component then add the combo base path
01567             if ($this->cssComboLocation === null) {
01568                 $this->cssComboLocation = $this->comboBase . $pathToModule;
01569             } else {
01570                 //Prep for next component
01571                 $this->cssComboLocation .= '&' . $pathToModule;
01572             }
01573         } else {
01574             //If this is the first js component then add the combo base path
01575             if ($this->jsComboLocation === null) {
01576                 $this->jsComboLocation = $this->comboBase . $pathToModule;
01577             } else {
01578                 //Prep for next component
01579                 $this->jsComboLocation .= '&' . $pathToModule;
01580             }
01581         }
01582     }
01583   
01589     function canJSON() {
01590         return $this->jsonAvail;
01591     }
01592     
01599     function getProvides($name) {
01600         $p = array($name);
01601         if (isset($this->modules[$name])) {
01602             $m = $this->modules[$name];
01603             if (isset($m[YUI_SUPERSEDES])) {
01604                 foreach ($m[YUI_SUPERSEDES] as $i) {
01605                     $p[] = $i;
01606                 }
01607             }
01608         }
01609 
01610         return $p;
01611     }
01612     
01618     function getLoadedModules() {
01619         $loaded = array();
01620         foreach ($this->loaded as $i=>$value) {
01621             if (isset($this->modules[$i])) {
01622                 $dep = $this->modules[$i];
01623                 $loaded[$dep[YUI_TYPE]][] = array(
01624                         $this->getUrl($i) => $this->getProvides($i)
01625                     );
01626             } else {
01627                 $msg = "YUI_LOADER ERROR: encountered undefined module: " . $i;
01628                 error_log($msg, 0);
01629             }
01630         }
01631         return $loaded;
01632     }
01633 
01639     function getLoadedModulesAsJSON() {
01640         if (!$this->canJSON()) {
01641             return "{\"Error\", \"json library not available\"}";
01642         }
01643 
01644         return json_encode($this->getLoadedModules());
01645     }
01646 }
01647 
01648 ?>
 All Data Structures Namespaces Files Functions Variables Enumerations