Source for file jConfigCompiler.class.php

Documentation is available at jConfigCompiler.class.php

  1. <?php
  2. /**
  3. @package      jelix
  4. @subpackage   core
  5. @author       Laurent Jouanneau
  6. @contributor  Thibault Piront (nuKs), Christophe Thiriot, Philippe Schelté
  7. @copyright    2006-2009 Laurent Jouanneau
  8. @copyright    2007 Thibault Piront, 2008 Christophe Thiriot, 2008 Philippe Schelté
  9. @link         http://www.jelix.org
  10. @licence      GNU Lesser General Public Licence see LICENCE file or http://www.gnu.org/licenses/lgpl.html
  11. */
  12.  
  13. /**
  14.  * jConfigCompiler merge two ini file in a single array and store it in a temporary file
  15.  * This is a static class
  16.  * @package  jelix
  17.  * @subpackage core
  18.  * @static
  19.  */
  20. class jConfigCompiler {
  21.  
  22.     static protected $commonConfig;
  23.  
  24.     private function __construct ()}
  25.  
  26.     /**
  27.      * read the given ini file, for the current entry point, or for the entrypoint given
  28.      * in $pseudoScriptName. Merge it with the content of defaultconfig.ini.php
  29.      * It also calculates some options.
  30.      * If you are in a CLI script but you want to load a configuration file for a web entry point
  31.      * or vice-versa, you need to indicate the $pseudoScriptName parameter with the name of the entry point
  32.      * @param string $configFile the config file name
  33.      * @param boolean $allModuleInfo may be true for the installer, which needs all informations
  34.      *                                else should be false, these extra informations are
  35.      *                                not needed to run the application
  36.      * @param boolean $isCli  indicate if the configuration to read is for a CLI script or no
  37.      * @param string $pseudoScriptName the name of the entry point, relative to the base path,
  38.      *               corresponding to the readed configuration
  39.      * @return object an object which contains configuration values
  40.      */
  41.     static public function read($configFile$allModuleInfo false$isCli false$pseudoScriptName=''){
  42.  
  43.         if(JELIX_APP_TEMP_PATH=='/'){
  44.             // if it equals to '/', this is because realpath has returned false in the application.init.php
  45.             // so this is because the path doesn't exist.
  46.             throw new Exception('Application temp directory doesn\'t exist !'3);
  47.         }
  48.  
  49.         if(!is_writable(JELIX_APP_TEMP_PATH)){
  50.             throw new Exception('Application temp directory is not writable'4);
  51.         }
  52.  
  53.         self::$commonConfig jIniFile::read(JELIX_APP_CONFIG_PATH.'defaultconfig.ini.php',true);
  54.  
  55.         $config jIniFile::read(JELIX_LIB_CORE_PATH.'defaultconfig.ini.php');
  56.  
  57.         if (self::$commonConfig{
  58.             self::_mergeConfig($configself::$commonConfig);
  59.         }
  60.  
  61.         if($configFile !='defaultconfig.ini.php'){
  62.             if(!file_exists(JELIX_APP_CONFIG_PATH.$configFile))
  63.                 throw new Exception("Config file $configFile is missing !"5);
  64.             iffalse === ($userConfig parse_ini_file(JELIX_APP_CONFIG_PATH.$configFile,true)))
  65.                 throw new Exception("Syntax error in the config file $configFile !"6);
  66.             self::_mergeConfig($config$userConfig);
  67.         }
  68.         $config = (object) $config;
  69.  
  70.         self::prepareConfig($config$allModuleInfo$isCli$pseudoScriptName);
  71.         self::$commonConfig  null;
  72.         return $config;
  73.     }
  74.     
  75.     /**
  76.      * Identical to read(), but also stores the result in a temporary file
  77.      * @param string $configFile the config file name
  78.      * @param boolean $isCli 
  79.      * @param string $pseudoScriptName 
  80.      * @return object an object which contains configuration values
  81.      */
  82.     static public function readAndCache($configFile$isCli null$pseudoScriptName ''{
  83.         
  84.         if ($isCli === null)
  85.             $isCli (PHP_SAPI == 'cli');
  86.  
  87.         $config self::read($configFilefalse$isCli$pseudoScriptName);
  88.  
  89.         if(BYTECODE_CACHE_EXISTS){
  90.             $filename=JELIX_APP_TEMP_PATH.str_replace('/','~',$configFile).'.conf.php';
  91.             if ($f @fopen($filename'wb')) {
  92.                 fwrite($f'<?php $config = '.var_export(get_object_vars($config),true).";\n?>");
  93.                 fclose($f);
  94.             else {
  95.                 throw new Exception('(24)Error while writing config cache file '.$filename);
  96.             }
  97.         }else{
  98.             jIniFile::write(get_object_vars($config)JELIX_APP_TEMP_PATH.str_replace('/','~',$configFile).'.resultini.php'";<?php die('');?>\n");
  99.         }
  100.         return $config;
  101.     }
  102.  
  103.     /**
  104.      * fill some config properties with calculated values
  105.      * @param object $config  the config object
  106.      * @param boolean $allModuleInfo may be true for the installer, which needs all informations
  107.      *                                else should be false, these extra informations are
  108.      *                                not needed to run the application
  109.      * @param boolean $isCli  indicate if the configuration to read is for a CLI script or no
  110.      * @param string $pseudoScriptName the name of the entry point, relative to the base path,
  111.      *               corresponding to the readed configuration
  112.      */
  113.     static protected function prepareConfig($config$allModuleInfo$isCli$pseudoScriptName){
  114.  
  115.         $config->isWindows (DIRECTORY_SEPARATOR === '\\');
  116.         if(trim$config->startAction== ''{
  117.             $config->startAction ':';
  118.         }
  119.  
  120.         if ($config->domainName == "" && isset($_SERVER['SERVER_NAME']))
  121.             $config->domainName $_SERVER['SERVER_NAME'];
  122.  
  123.         $config->_allBasePath array();
  124.  
  125.         // retrieve the script path+name.
  126.         // for cli, it will be the path from the directory were we execute the script (given to the php exec).
  127.         // for web, it is the path from the root of the url
  128.  
  129.         if ($pseudoScriptName{
  130.             $config->urlengine['urlScript'$pseudoScriptName;
  131.         }
  132.         else {
  133.             if($config->urlengine['scriptNameServerVariable'== ''{
  134.                 $config->urlengine['scriptNameServerVariable'self::_findServerName($config->urlengine['entrypointExtension']$isCli);
  135.             }
  136.             $config->urlengine['urlScript'$_SERVER[$config->urlengine['scriptNameServerVariable']];
  137.         }
  138.         $lastslash strrpos ($config->urlengine['urlScript']'/');
  139.  
  140.         // now we separate the path and the name of the script, and then the basePath
  141.         if ($isCli{
  142.             if ($lastslash === false{
  143.                 $config->urlengine['urlScriptPath'($pseudoScriptNameJELIX_APP_PATH.'/scripts/'getcwd().'/');
  144.                 $config->urlengine['urlScriptName'$config->urlengine['urlScript'];
  145.             }
  146.             else {
  147.                 $config->urlengine['urlScriptPath'getcwd().'/'.substr ($config->urlengine['urlScript']0$lastslash ).'/';
  148.                 $config->urlengine['urlScriptName'substr ($config->urlengine['urlScript']$lastslash+1);
  149.             }
  150.             $basepath $config->urlengine['urlScriptPath'];
  151.             $snp $config->urlengine['urlScriptName'];
  152.             $config->urlengine['urlScript'$basepath.$snp;
  153.         }
  154.         else {
  155.             $config->urlengine['urlScriptPath'substr ($config->urlengine['urlScript']0$lastslash ).'/';
  156.             $config->urlengine['urlScriptName'substr ($config->urlengine['urlScript']$lastslash+1);
  157.  
  158.             $basepath $config->urlengine['basePath'];
  159.             if ($basepath == ''{
  160.                 // for beginners or simple site, we "guess" the base path
  161.                 $basepath $config->urlengine['urlScriptPath'];
  162.             }
  163.             elseif ($basepath != '/'{
  164.                 if($basepath[0!= '/'$basepath='/'.$basepath;
  165.                 if(substr($basepath,-1!= '/'$basepath.='/';
  166.  
  167.                 if ($pseudoScriptName{
  168.                     // with pseudoScriptName, we aren't in a true context, we could be in a cli context
  169.                     // (the installer), and we want the path as when we are in a web context.
  170.                     // $pseudoScriptName is supposed to be relative to the basePath
  171.                     $config->urlengine['urlScriptPath'substr($basepath,0,-1).$config->urlengine['urlScriptPath'];
  172.                     $config->urlengine['urlScript'$config->urlengine['urlScriptPath'].$config->urlengine['urlScriptName'];
  173.                 }
  174.                 elseif(strpos($config->urlengine['urlScriptPath']$basepath!== 0){
  175.                     throw new Exception('Jelix Error: basePath ('.$basepath.') in config file doesn\'t correspond to current base path. You should setup it to '.$config->urlengine['urlScriptPath']);
  176.                 }
  177.             }
  178.  
  179.             $config->urlengine['basePath'$basepath;
  180.  
  181.             if($config->urlengine['jelixWWWPath'][0!= '/')
  182.                 $config->urlengine['jelixWWWPath'$basepath.$config->urlengine['jelixWWWPath'];
  183.             if($config->urlengine['jqueryPath'][0!= '/')
  184.                 $config->urlengine['jqueryPath'$basepath.$config->urlengine['jqueryPath'];
  185.             $snp substr($config->urlengine['urlScript'],strlen($basepath));
  186.         }
  187.  
  188.         $pos strrpos($snp$config->urlengine['entrypointExtension']);
  189.         if($pos !== false){
  190.             $snp substr($snp,0,$pos);
  191.         }
  192.         $config->urlengine['urlScriptId'$snp;
  193.         $config->urlengine['urlScriptIdenc'rawurlencode($snp);
  194.  
  195.         self::_loadModuleInfo($config$allModuleInfo);
  196.         self::_loadPluginsPathList($config);
  197.  
  198.         $coordplugins array();
  199.         foreach ($config->coordplugins as $name=>$conf{
  200.             if (!isset($config->_pluginsPathList_coord[$name])) {
  201.                 throw new Exception("Error in the main configuration. The coord plugin $name doesn't exist!"7);
  202.             }
  203.             if ($conf{
  204.                 if ($conf != '1' && !file_exists(JELIX_APP_CONFIG_PATH.$conf)) {
  205.                     throw new Exception("Error in the main configuration. Configuration file '$conf' for coord plugin $name doesn't exist!"8);
  206.                 }
  207.                 $coordplugins[$name$conf;
  208.             }
  209.         }
  210.         $config->coordplugins $coordplugins;
  211.  
  212.         self::_initResponsesPath($config->responses);
  213.         self::_initResponsesPath($config->_coreResponses);
  214.  
  215.         if (trim($config->timeZone=== ''{
  216.             $tz ini_get('date.timezone');
  217.             if ($tz != '')
  218.                 $config->timeZone $tz;
  219.             else
  220.                 $config->timeZone "Europe/Paris";
  221.         }
  222.  
  223.         if($config->sessions['storage'== 'files'){
  224.             $config->sessions['files_path'str_replace(array('lib:','app:')array(LIB_PATHJELIX_APP_PATH)$config->sessions['files_path']);
  225.         }
  226.  
  227.         $config->sessions['_class_to_load'array();
  228.         if ($config->sessions['loadClasses'!= ''{
  229.             $list preg_split('/ *, */',$config->sessions['loadClasses']);
  230.             foreach($list as $sel{
  231.                 if(preg_match("/^([a-zA-Z0-9_\.]+)~([a-zA-Z0-9_\.\\/]+)$/"$sel$m)){
  232.                     if (!isset($config->_modulesPathList[$m[1]])) {
  233.                         throw new Exception('Error in config files, loadClasses: '.$m[1].' is not a valid or activated module');
  234.                     }
  235.  
  236.                     if( ($p=strrpos($m[2]'/')) !== false){
  237.                         $className substr($m[2],$p+1);
  238.                         $subpath substr($m[2],0,$p+1);
  239.                     }else{
  240.                         $className $m[2];
  241.                         $subpath ='';
  242.                     }
  243.                     
  244.                     $path $config->_modulesPathList[$m[1]].'classes/'.$subpath.$className.'.class.php';
  245.  
  246.                     if (!file_exists($path|| strpos($subpath,'..'!== false {
  247.                         throw new Exception('Error in config files, loadClasses, bad class selector: '.$sel);
  248.                     }
  249.                     $config->sessions['_class_to_load'][$path;
  250.                 }
  251.                 else
  252.                     throw new Exception('Error in config files, loadClasses, bad class selector: '.$sel);
  253.             }
  254.         }
  255.  
  256.         /*if(preg_match("/^([a-zA-Z]{2})(?:_([a-zA-Z]{2}))?$/",$config->locale,$m)){
  257.             if(!isset($m[2])){
  258.                 $m[2] = $m[1];
  259.             }
  260.             $config->defaultLang = strtolower($m[1]);
  261.             $config->defaultCountry = strtoupper($m[2]);
  262.             $config->locale = $config->defaultLang.'_'.$config->defaultCountry;
  263.         }else{
  264.             throw new Exception("Syntax error in the locale parameter in config file $configFile !", 14);
  265.         }*/
  266.     }
  267.  
  268.     /**
  269.      * Analyse and check the "lib:" and "app:" path.
  270.      * @param object $config  the config object
  271.      * @param boolean $allModuleInfo may be true for the installer, which needs all informations
  272.      *                                else should be false, these extra informations are
  273.      *                                not needed to run the application
  274.      */
  275.     static protected function _loadModuleInfo($config$allModuleInfo{
  276.  
  277.         if ($config->disableInstallers{
  278.             $installation array ();
  279.         }
  280.         else if (!file_exists(JELIX_APP_CONFIG_PATH.'installer.ini.php')) {
  281.             if ($allModuleInfo)
  282.                 $installation array ();
  283.             else
  284.                 throw new Exception("installer.ini.php doesn't exist! You must install your application.\n"9);
  285.         }
  286.         else
  287.             $installation parse_ini_file(JELIX_APP_CONFIG_PATH.'installer.ini.php',true);
  288.  
  289.         $section $config->urlengine['urlScriptId'];
  290.  
  291.         if (!isset($installation[$section]))
  292.             $installation[$sectionarray();
  293.  
  294.         $list preg_split('/ *, */',$config->modulesPath);
  295.         $list array_merge($listpreg_split('/ *, */',self::$commonConfig['modulesPath']));
  296.         array_unshift($listJELIX_LIB_PATH.'core-modules/');
  297.         $pathChecked array();
  298.  
  299.         foreach($list as $k=>$path){
  300.             if(trim($path== ''continue;
  301.             $p str_replace(array('lib:','app:')array(LIB_PATHJELIX_APP_PATH)$path);
  302.             if (!file_exists($p)) {
  303.                 throw new Exception('The path, '.$path.' given in the jelix config, doesn\'t exist !'10);
  304.             }
  305.             if (substr($p,-1!='/')
  306.                 $p.='/';
  307.             if (in_array($p$pathChecked))
  308.                 continue;
  309.             $pathChecked[$p;
  310.  
  311.              // don't include the core-modules into the list of base path. this list is to verify
  312.              // if modules have been modified into repositories
  313.             if ($k!=&& $config->compilation['checkCacheFiletime'])
  314.                 $config->_allBasePath[]=$p;
  315.  
  316.             if ($handle opendir($p)) {
  317.                 while (false !== ($f readdir($handle))) {
  318.                     if ($f[0!= '.' && is_dir($p.$f)) {
  319.  
  320.                         if ($config->disableInstallers)
  321.                             $installation[$section][$f.'.installed'1;
  322.                         else if (!isset($installation[$section][$f.'.installed']))
  323.                             $installation[$section][$f.'.installed'0;
  324.  
  325.                         if ($f == 'jelix'{
  326.                             $config->modules['jelix.access'2// the jelix module should always be public
  327.                         }
  328.                         else {
  329.                             if ($config->enableAllModules{
  330.                                 if ($config->disableInstallers
  331.                                     || $installation[$section][$f.'.installed']
  332.                                     || $allModuleInfo)
  333.                                     $config->modules[$f.'.access'2;
  334.                                 else
  335.                                     $config->modules[$f.'.access'0;
  336.                             }
  337.                             else if (!isset($config->modules[$f.'.access'])) {
  338.                                 // no given access in defaultconfig and ep config
  339.                                 $config->modules[$f.'.access'0;
  340.                             }
  341.                             else if($config->modules[$f.'.access'== 0){
  342.                                 // we want to activate the module if it is not activated
  343.                                 // for the entry point, but is declared activated
  344.                                 // in the default config file. In this case, it means
  345.                                 // that it is activated for an other entry point,
  346.                                 // and then we want the possibility to retrieve its
  347.                                 // urls, at least
  348.                                 if (isset(self::$commonConfig['modules'][$f.'.access'])
  349.                                     && self::$commonConfig['modules'][$f.'.access'0)
  350.                                     $config->modules[$f.'.access'3;
  351.                             }
  352.                             else if (!$installation[$section][$f.'.installed']{
  353.                                 // module is not installed.
  354.                                 // outside installation mode, we force the access to 0
  355.                                 // so the module is unusable until it is installed
  356.                                 if (!$allModuleInfo
  357.                                     $config->modules[$f.'.access'0;
  358.                             }
  359.                         }
  360.  
  361.                         if (!isset($installation[$section][$f.'.dbprofile']))
  362.                             $config->modules[$f.'.dbprofile''default';
  363.                         else
  364.                             $config->modules[$f.'.dbprofile'$installation[$section][$f.'.dbprofile'];
  365.  
  366.                         if ($allModuleInfo{
  367.                             if (!isset($installation[$section][$f.'.version']))
  368.                                 $installation[$section][$f.'.version''';
  369.     
  370.                             if (!isset($installation[$section][$f.'.dataversion']))
  371.                                 $installation[$section][$f.'.dataversion''';
  372.  
  373.                             if (!isset($installation['__modules_data'][$f.'.contexts']))
  374.                                 $installation['__modules_data'][$f.'.contexts''';
  375.                                 
  376.                             $config->modules[$f.'.version'$installation[$section][$f.'.version'];
  377.                             $config->modules[$f.'.dataversion'$installation[$section][$f.'.dataversion'];
  378.                             $config->modules[$f.'.installed'$installation[$section][$f.'.installed'];
  379.  
  380.                             $config->_allModulesPathList[$f]=$p.$f.'/';
  381.                         }
  382.                         
  383.                         if ($config->modules[$f.'.access'== 3{
  384.                             $config->_externalModulesPathList[$f]=$p.$f.'/';
  385.                         }
  386.                         elseif ($config->modules[$f.'.access'])
  387.                             $config->_modulesPathList[$f]=$p.$f.'/';
  388.                     }
  389.                 }
  390.                 closedir($handle);
  391.             }
  392.         }
  393.     }
  394.  
  395.     /**
  396.      * Analyse plugin paths
  397.      * @param object $config the config container
  398.      */
  399.     static protected function _loadPluginsPathList($config{
  400.         $list preg_split('/ *, */',$config->pluginsPath);
  401.         array_unshift($listJELIX_LIB_PATH.'plugins/');
  402.         foreach($list as $k=>$path){
  403.             if(trim($path== ''continue;
  404.             $p str_replace(array('lib:','app:')array(LIB_PATHJELIX_APP_PATH)$path);
  405.             if(!file_exists($p)){
  406.                 trigger_error('The path, '.$path.' given in the jelix config, doesn\'t exists !',E_USER_ERROR);
  407.                 exit;
  408.             }
  409.             if(substr($p,-1!='/')
  410.                 $p.='/';
  411.  
  412.             if ($handle opendir($p)) {
  413.                 while (false !== ($f readdir($handle))) {
  414.                     if ($f[0!= '.' && is_dir($p.$f)) {
  415.                         if($subdir opendir($p.$f)){
  416.                             if($k!=&& $config->compilation['checkCacheFiletime'])
  417.                                $config->_allBasePath[]=$p.$f.'/';
  418.                             while (false !== ($subf readdir($subdir))) {
  419.                                 if ($subf[0!= '.' && is_dir($p.$f.'/'.$subf)) {
  420.                                     if($f == 'tpl'){
  421.                                         $prop '_tplpluginsPathList_'.$subf;
  422.                                         $config->{$prop}[$p.$f.'/'.$subf.'/';
  423.                                     }else{
  424.                                         $prop '_pluginsPathList_'.$f;
  425.                                         $config->{$prop}[$subf$p.$f.'/'.$subf.'/';
  426.                                     }
  427.                                 }
  428.                             }
  429.                             closedir($subdir);
  430.                         }
  431.                     }
  432.                 }
  433.                 closedir($handle);
  434.             }
  435.         }
  436.     }
  437.  
  438.     static private function _findServerName($ext$isCli{
  439.         $varname '';
  440.         $extlen strlen($ext);
  441.  
  442.         if(strrpos($_SERVER['SCRIPT_NAME']$ext=== (strlen($_SERVER['SCRIPT_NAME']$extlen)
  443.            || $isCli{
  444.             return 'SCRIPT_NAME';
  445.         }else if (isset($_SERVER['REDIRECT_URL'])
  446.                   && strrpos$_SERVER['REDIRECT_URL']$ext=== (strlen$_SERVER['REDIRECT_URL']-$extlen)) {
  447.             return 'REDIRECT_URL';
  448.         }else if (isset($_SERVER['ORIG_SCRIPT_NAME'])
  449.                   && strrpos$_SERVER['ORIG_SCRIPT_NAME']$ext=== (strlen$_SERVER['ORIG_SCRIPT_NAME']$extlen)) {
  450.             return 'ORIG_SCRIPT_NAME';
  451.         }
  452.         throw new Exception('In config file the parameter urlengine:scriptNameServerVariable is empty and Jelix doesn\'t find
  453.             the variable in $_SERVER which contains the script name. You must see phpinfo and setup this parameter in your config file.'11);
  454.     }
  455.  
  456.     /**
  457.      * get all physical paths of responses file
  458.      */
  459.     static private function _initResponsesPath(&$list){
  460.         $copylist $list// because we modify $list and then it will search for "foo.path" responses...
  461.         foreach($copylist as $type=>$class){
  462.             if(file_exists($path=JELIX_LIB_CORE_PATH.'response/'.$class.'.class.php')){
  463.                 $list[$type.'.path']=$path;
  464.             }elseif(file_exists($path=JELIX_APP_PATH.'responses/'.$class.'.class.php')){
  465.                 $list[$type.'.path']=$path;
  466.             }else{
  467.                 throw new Exception('Configuration Error: the class file of the response type "'.$type.'" is not found ('.$path.')',12);
  468.             }
  469.         }
  470.     }
  471.  
  472.     /**
  473.      * merge two array which are the result of a parse_ini_file call
  474.      * @param array $array the main array
  475.      * @param array $tomerge the array to merge in the first one
  476.      */
  477.     static private function _mergeConfig(&$array$tomerge){
  478.  
  479.         foreach($tomerge as $k=>$v){
  480.             if(!isset($array[$k])){
  481.                 $array[$k$v;
  482.                 continue;
  483.             }
  484.             if($k[1== '_')
  485.                 continue;
  486.             if(is_array($v)){
  487.                 $array[$karray_merge($array[$k]$v);
  488.             }else{
  489.                 $array[$k$v;
  490.             }
  491.         }
  492.  
  493.     }
  494. }

Documentation generated on Thu, 19 Sep 2013 00:02:43 +0200 by phpDocumentor 1.4.3