PageRenderTime 62ms CodeModel.GetById 25ms RepoModel.GetById 1ms app.codeStats 0ms

/system/configuration.php

https://github.com/nguyennamtien/appleseed
PHP | 485 lines | 260 code | 116 blank | 109 comment | 54 complexity | 44661b3837c23df57b591fc879a1301a MD5 | raw file
  1. <?php
  2. /**
  3. * @version $Id$
  4. * @package Appleseed.Framework
  5. * @subpackage System
  6. * @copyright Copyright (C) 2004 - 2010 Michael Chisari. All rights reserved.
  7. * @link http://opensource.appleseedproject.org
  8. * @license GNU General Public License version 2.0 (See LICENSE.txt)
  9. */
  10. // Restrict direct access
  11. defined( 'APPLESEED' ) or die( 'Direct Access Denied' );
  12. /** Configuration Class
  13. *
  14. * Base class for configurations
  15. *
  16. * @package Appleseed.Framework
  17. * @subpackage System
  18. */
  19. class cConfiguration extends cBase {
  20. protected $_Data;
  21. protected $_Cleared;
  22. public $Child;
  23. /**
  24. * Constructor
  25. *
  26. * @access public
  27. */
  28. public function __construct ( ) {
  29. }
  30. /**
  31. * Load a configuration file, using inheritance if necessary
  32. *
  33. * @access public
  34. * @param string pFilename
  35. * @param array pDirectories
  36. */
  37. public function Load ( $pDirectory, $pInheritance = true ) {
  38. // Global variables
  39. eval (GLOBALS);
  40. $location = $zApp->GetPath () . DS . $pDirectory;
  41. # Production mode by default.
  42. $mode = null;
  43. if ( isset ( $zApp->Config ) ) {
  44. $mode = $zApp->Config->GetConfiguration ( 'mode' );
  45. }
  46. // Check for other configuration directories
  47. $dirs = scandirs ($location);
  48. // Load all enabled configurations
  49. foreach ( $dirs as $d => $dir ) {
  50. $configurations[$dir] = new stdClass ();
  51. $configurations[$dir]->Directory = $dir;
  52. $file = $zApp->GetPath () . DS . $pDirectory . DS . $dir . DS . $dir . '.conf';
  53. if ( !$configurations[$dir]->_Data = $this->Parse ($file, $mode) ) {
  54. // Load failed. Set a warning and unset value
  55. unset ($configurations[$dir]);
  56. continue;
  57. }
  58. if ( ( strtolower ( $configurations[$dir]->_Data['enabled'] ) != 'true' ) ) {
  59. unset ($configurations[$dir]);
  60. continue;
  61. }
  62. }
  63. // Set inheritance
  64. $dirs = $configurations;
  65. // If no configurations were found, error out
  66. if ( count ( $dirs ) == 0 ) {
  67. die ( "No configurations were found or enabled: $pDirectory");
  68. }
  69. // Count inheritance levels
  70. $inheritancecount = 0;
  71. do {
  72. foreach ( $dirs as $dir => $values ) {
  73. $inherit = isset ( $configurations[$dir]->_Data['inherit'] ) ? $configurations[$dir]->_Data['inherit'] : false;
  74. $inheritanceflag = false;
  75. if ( $inherit ) {
  76. // If inheriting from self, continue
  77. if ($configurations[$dir]->Directory == $inherit) {
  78. $configurations[$dir]->Warnings[] = " Cannot Inherit $inherit From Itself. ";
  79. continue;
  80. }
  81. // Check if the inherited parent exists
  82. if ( !isset ( $configurations[$inherit] ) ) {
  83. // Set a warning and continue
  84. $configurations[$dir]->Warnings[] = " Cannot Inherit Values From '$inherit'. Does Not Exist Or Is Disabled.";
  85. continue;
  86. }
  87. $inheritancecount++;
  88. // Limit inheritance to three levels deep
  89. if ($inheritancecount > 3) {
  90. die ( "Error: Configuration Inheritance Greater Than 3 Levels. Please Resolve." );
  91. }
  92. // Set the values as a child of parent
  93. $configurations[$inherit]->Child = $configurations[$dir];
  94. unset ($configurations[$dir]);
  95. $inheritanceflag = true;
  96. }
  97. }
  98. } while ( $inheritanceflag );
  99. // Check to see if there's more than one parent left
  100. if ( count ( $configurations ) > 1 ) {
  101. die ( 'More Than One Parent Configuration (' . ucwords ( $pDirectory ) . ') Is Enabled. Please Resolve.' );
  102. }
  103. $parent = key ( $configurations );
  104. // Traverse and inherit values
  105. $final = $this->_Inherit ( $configurations[$parent] );
  106. $config = $final->_Data;
  107. // Internal list of the path to the final configuration
  108. $config['_path'] = array_reverse ( $this->_path );
  109. // Internal list of variables which were cleared and by which configuration
  110. if ( count ( $this->_Cleared ) > 0 ) $config['_cleared'] = array_reverse ( $this->_Cleared );
  111. unset ( $final->Directory );
  112. unset ( $config['enabled'] );
  113. return ( $config );
  114. }
  115. /**
  116. * Loads a configuration value
  117. *
  118. * @access public
  119. * @param array pVariable
  120. */
  121. function GetConfiguration ( $pVariable, $pDefault = null ) {
  122. if ( !isset ( $this->_Data[$pVariable] ) ) return ( $pDefault );
  123. return ( $this->_Data[$pVariable] );
  124. }
  125. /**
  126. * Loads the ordered path to the child configuration
  127. *
  128. * @access public
  129. */
  130. function GetPath ( ) {
  131. return ( $this->_Data['_path'] );
  132. }
  133. /**
  134. * Recursively inherit values
  135. *
  136. * @access private
  137. * @param object pConfiguration
  138. */
  139. private function _Inherit ( $pConfiguration ) {
  140. $parent = $pConfiguration;
  141. if ( isset ( $parent->Child ) ) $child = $parent->Child;
  142. $clear = isset ( $child->_Data['clear'] ) ? $configurations->_Data['clear'] : false;
  143. if ( $clear ) {
  144. $parent = $this->_Clear ( $parent, $child );
  145. }
  146. if ( isset ($child ) ) {
  147. $child = $this->_Inherit ($child);
  148. // Move all parent values to child
  149. foreach ( $child->_Data as $key => $value ) {
  150. if ( isset ( $parent->_Data[$key] ) && ( is_array ( $parent->_Data[$key] ) ) ) {
  151. $parent->_Data[$key] = array_merge ( $parent->_Data[$key], $value );
  152. } else {
  153. $parent->_Data[$key] = $value;
  154. }
  155. }
  156. $this->_path[] = $parent->Directory;
  157. unset ( $parent->_Data['inherit'] );
  158. unset ( $parent->Child );
  159. return ( $parent );
  160. } else {
  161. $this->_path[] = $parent->Directory;
  162. return ( $parent );
  163. }
  164. }
  165. /**
  166. * Clear parent values as specified by child
  167. *
  168. * @access private
  169. * @param object pParent
  170. * @param object pChild
  171. */
  172. private function _Clear ( $pParent, $pChild ) {
  173. $clearlist = array_filter ( split ( ' ', $pChild->_Data['clear'] ) );
  174. if ( count ( $clearlist ) < 1 ) {
  175. return ( false );
  176. }
  177. foreach ( $clearlist as $c => $clear ) {
  178. // Special variables which cannot be cleared
  179. if ( in_array ( $clear, array ( "inherit", "clear" ) ) ) continue;
  180. $this->_Cleared[] = $clear . ' [by ' . $pChild->Directory . '] ';
  181. unset ( $pParent->_Data[$clear] );
  182. }
  183. return ( $pParent );
  184. }
  185. /**
  186. * Loads all of the component configuration files
  187. *
  188. * @access public
  189. */
  190. public function LoadComponents ( ) {
  191. eval ( GLOBALS );
  192. $Config = $this->GetSys ( "Config" );
  193. $configpaths = $Config->GetPath();
  194. $componentdir = $zApp->GetPath() . DS . 'components';
  195. $components = scandirs ( $componentdir );
  196. $config = array ();
  197. foreach ( $components as $comp => $component ) {
  198. $filename = $componentdir . DS . $component . DS . $component . '.conf';
  199. if ( is_file ( $filename ) ) {
  200. $path[$component][] = $filename;
  201. }
  202. foreach ( $configpaths as $cpath => $configpath ) {
  203. $filename = $zApp->GetPath() . DS . 'configurations' . DS . $configpath . DS . 'components' . DS . $component . '.conf';
  204. if ( is_file ( $filename ) ) {
  205. $path[$component][] = $filename;
  206. }
  207. }
  208. // No configuration files found, continue loop
  209. if ( !isset ( $path[$component] ) ) continue;
  210. $config[$component] = array();
  211. foreach ( $path[$component] as $p => $filename ) {
  212. $currentvalues = $config[$component];
  213. $configvalues = $this->Parse ( $filename );
  214. $clearall = isset ( $configvalues['clearall'] ) ? $configvalues['clearall'] : false;
  215. if ( $clearall == 'true' ) {
  216. $currentvalues = array ();
  217. unset ( $configvalues['clearall'] );
  218. }
  219. $config[$component] = array_merge ( $currentvalues, $configvalues );
  220. }
  221. // If the component isn't enabled, then unset the values and continue
  222. if ($config[$component]['enabled'] != 'true' ) {
  223. unset ($config[$component]);
  224. continue;
  225. } else {
  226. $this->_Components[] = $component;
  227. }
  228. }
  229. return ($config);
  230. }
  231. /**
  232. * Loads all of the hook configuration files
  233. *
  234. * @access public
  235. */
  236. public function LoadHooks ( ) {
  237. eval ( GLOBALS );
  238. $Config = $this->GetSys ( "Config" );
  239. $configpaths = $Config->GetPath();
  240. $hooksdir = $zApp->GetPath() . DS . 'hooks';
  241. $hooks = scandirs ( $hooksdir );
  242. $config = array ();
  243. foreach ( $hooks as $h => $hook ) {
  244. $hookdir = $zApp->GetPath() . DS . 'hooks' . DS . $hook;
  245. $filename = $hookdir . DS . $hook . '.conf';
  246. if ( is_file ( $filename ) ) {
  247. $path[$hook][] = $filename;
  248. }
  249. foreach ( $configpaths as $cpath => $configpath ) {
  250. $filename = $zApp->GetPath() . DS . 'configurations' . DS . $configpath . DS . 'hooks' . DS . $hook . DS . $hook . '.conf';
  251. if ( is_file ( $filename ) ) {
  252. $path[$hook][] = $filename;
  253. }
  254. }
  255. }
  256. foreach ( $path as $hook=> $paths ) {
  257. $config[$hook] = array();
  258. foreach ( $paths as $p => $filename ) {
  259. $currentvalues = $config[$hook];
  260. $configvalues = $this->Parse ( $filename );
  261. $clearall = isset ( $configvalues['clearall'] ) ? $configvalues['clearall'] : false;
  262. if ( $clearall == 'true' ) {
  263. $currentvalues = array ();
  264. unset ( $configvalues['clearall'] );
  265. }
  266. $config[$hook] = array_merge ( $currentvalues, $configvalues );
  267. }
  268. // If the hook isn't enabled, then unset the values and continue
  269. if ($config[$hook]['enabled'] != 'true' ) {
  270. unset ($config[$hook]);
  271. continue;
  272. } else {
  273. $this->_Hooks[] = $hook;
  274. }
  275. }
  276. if ( count ( $config ) < 1 ) {
  277. unset ( $config );
  278. }
  279. return ($config);
  280. }
  281. /**
  282. * Parses an ini file depending on which PHP version is being used
  283. *
  284. * @access public
  285. * @var string $pFilename Full path of file to parse
  286. */
  287. function Parse ( $pFilename, $pMode = null ) {
  288. $version = phpversion();
  289. list ( $major, $minor, $micro ) = explode ( '.', $version );
  290. // PHP 5.2 doesn't support associative arrays in ini files, so a hack is necessary
  291. if ( ( $major >= 5 ) && ( $minor >= 3 ) ) {
  292. $return = parse_ini_file ( $pFilename );
  293. } else {
  294. $data = file_get_contents ( $pFilename );
  295. // Check if we're using associative arrays
  296. if ($match = preg_match ( '/\[\S+\]=/', $data ) ) {
  297. $datalines = split ( "\n", $data );
  298. $counter = array ();
  299. foreach ( $datalines as $l => $line ) {
  300. // Skip over comments
  301. if ( preg_match ( '/^;/', $line ) ) continue;
  302. // Retrieve the regular expression key
  303. if ( preg_match ( '/\[(\S+)\]=/', $line, $retrieved ) ) {
  304. // Retrieve the variable name
  305. if ( preg_match ( '/^(\S+)\[/', $line, $name ) ) {
  306. list ( $name, $null ) = explode ( '[', $line, 2 );
  307. $regexp = rtrim ( ltrim ( $retrieved[1], '"' ), '"' );
  308. $c = (int)$counter[$name];
  309. $expressions[$name][$c] = $regexp;
  310. $counter[$name]++;
  311. }
  312. }
  313. $modified[] = preg_replace ( '/\[\S+\]=/', "[]=", $line);
  314. }
  315. $modified_data = join ("\n", $modified);
  316. // Create the temporary ini file for parsing
  317. $tmpfname = tempnam(sys_get_temp_dir(), 'temporary_ini_file');
  318. $handle = fopen ( $tmpfname, "w" );
  319. fwrite ( $handle, $modified_data );
  320. fclose ( $handle );
  321. $original = parse_ini_file ( $tmpfname );
  322. // Delete the temporary ini file
  323. unlink ( $tmpfname );
  324. // Merge the original data with the associative array data
  325. foreach ( $original as $variable => $value ) {
  326. if ( is_array ($value ) ) {
  327. foreach ( $value as $k => $v ) {
  328. $key = $expressions[$variable][$k];
  329. $final[$variable][$key] = preg_replace ( '/\\\\\$$/', '$', $v );
  330. }
  331. } else {
  332. $final[$variable] = preg_replace ( '/\\\\\$$/', '$', $value );
  333. }
  334. }
  335. $return = $final;
  336. } else {
  337. // No associative arrays are used, so parse normally
  338. $return = parse_ini_file ( $pFilename );
  339. }
  340. }
  341. // Allow the current configuration file to specify a mode.
  342. foreach ( $return as $key => $value ) {
  343. if ( $key == 'mode' ) {
  344. $pMode = $value;
  345. }
  346. }
  347. if ( $pMode ) {
  348. $mode = '.' . $pMode;
  349. // Check for .mode modifiers
  350. foreach ( $return as $key => $value ) {
  351. if ( strstr ( $key, $mode ) ) {
  352. $key = str_replace ( $mode, '', $key );
  353. $return[$key] = $value;
  354. // We no longer need the .mode key/value
  355. unset ( $return[$key . $mode] );
  356. }
  357. }
  358. }
  359. return ( $return );
  360. }
  361. }
  362. /** Conf Class
  363. *
  364. * Alias class for cConfigurations
  365. *
  366. * @package Appleseed.Framework
  367. * @subpackage System
  368. */
  369. class cConf extends cConfiguration { }