PageRenderTime 66ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 0ms

/administrator/components/com_akeeba/akeeba/configuration.php

https://gitlab.com/endomorphosis/OLAAaction
PHP | 408 lines | 328 code | 17 blank | 63 comment | 24 complexity | 63c5721ea7dda596295e88d5f636c764 MD5 | raw file
  1. <?php
  2. /**
  3. * Akeeba Engine
  4. * The modular PHP5 site backup engine
  5. * @copyright Copyright (c)2009-2011 Nicholas K. Dionysopoulos
  6. * @license GNU GPL version 3 or, at your option, any later version
  7. * @package akeebaengine
  8. * @version $Id: configuration.php 409 2011-01-24 09:30:22Z nikosdion $
  9. */
  10. // Protection against direct access
  11. defined('AKEEBAENGINE') or die('Restricted access');
  12. /**
  13. * The Akeeba Engine configuration registry class
  14. */
  15. class AEConfiguration {
  16. /** @var string Default NameSpace */
  17. private $defaultNameSpace = 'global';
  18. /** @var array Array keys which may contain stock directory definitions */
  19. private $directory_containing_keys = array(
  20. 'akeeba.basic.output_directory',
  21. 'akeeba.basic.temporary_directory'
  22. );
  23. /** @var array The registry data */
  24. private $registry = array();
  25. /** @var int The currently loaded profile */
  26. public $activeProfile = null;
  27. /**
  28. * Constructor
  29. */
  30. public function __construct()
  31. {
  32. // Assisted Singleton pattern
  33. if(function_exists('debug_backtrace'))
  34. {
  35. $caller=debug_backtrace();
  36. $caller = $caller[1];
  37. if($caller['class'] != 'AEFactory') trigger_error("You can't create a direct descendant of ".__CLASS__, E_USER_ERROR);
  38. }
  39. // Create the default namespace
  40. $this->makeNameSpace($this->defaultNameSpace);
  41. // Create a default configuration
  42. $this->reset();
  43. }
  44. /**
  45. * Create a namespace
  46. * @param string $namespace Name of the namespace to create
  47. */
  48. public function makeNameSpace($namespace)
  49. {
  50. $this->registry[$namespace] = array('data' => new stdClass());
  51. }
  52. /**
  53. * Get the list of namespaces
  54. * @return array List of namespaces
  55. */
  56. public function getNameSpaces()
  57. {
  58. return array_keys($this->registry);
  59. }
  60. /**
  61. * Get a registry value
  62. * @param string $regpath Registry path (e.g. global.directory.temporary)
  63. * @param mixed $default Optional default value
  64. * @param bool $process_special_vars Optional. If true (default), it processes special variables, e.g. [SITEROOT] in folder names
  65. * @return mixed Value of entry or null
  66. */
  67. public function get($regpath, $default=null, $process_special_vars = true)
  68. {
  69. // Cache the platform-specific stock directories
  70. static $stock_directories = array();
  71. if(empty($stock_directories))
  72. {
  73. $stock_directories = AEPlatform::get_stock_directories();
  74. }
  75. $result = $default;
  76. // Explode the registry path into an array
  77. if ($nodes = explode('.', $regpath))
  78. {
  79. // Get the namespace
  80. $count = count($nodes);
  81. if ($count < 2) {
  82. $namespace = $this->defaultNameSpace;
  83. $nodes[1] = $nodes[0];
  84. } else {
  85. $namespace = $nodes[0];
  86. }
  87. if (isset($this->registry[$namespace])) {
  88. $ns = $this->registry[$namespace]['data'];
  89. $pathNodes = $count - 1;
  90. for ($i = 1; $i < $pathNodes; $i ++) {
  91. if((isset($ns->$nodes[$i]))) $ns =& $ns->$nodes[$i];
  92. }
  93. if(isset($ns->$nodes[$i])) {
  94. $result = $ns->$nodes[$i];
  95. }
  96. }
  97. }
  98. // Post-process certain directory-containing variables
  99. if( $process_special_vars && in_array($regpath, $this->directory_containing_keys) )
  100. {
  101. if(!empty($stock_directories))
  102. {
  103. foreach($stock_directories as $tag => $content)
  104. {
  105. $result = str_replace($tag, $content, $result);
  106. }
  107. }
  108. }
  109. return $result;
  110. }
  111. /**
  112. * Set a registry value
  113. * @param string $regpath Registry Path (e.g. global.directory.temporary)
  114. * @param mixed $value Value of entry
  115. * @param bool $process_special_vars Optional. If true (default), it processes special variables, e.g. [SITEROOT] in folder names
  116. * @return mixed Value of old value or boolean false if operation failed
  117. */
  118. public function set($regpath, $value, $process_special_vars = true)
  119. {
  120. // Cache the platform-specific stock directories
  121. static $stock_directories = array();
  122. if(empty($stock_directories))
  123. {
  124. $stock_directories = AEPlatform::get_stock_directories();
  125. }
  126. // Explode the registry path into an array
  127. $nodes = explode('.', $regpath);
  128. // Get the namespace
  129. $count = count($nodes);
  130. if ($count < 2) {
  131. $namespace = $this->defaultNameSpace;
  132. } else {
  133. $namespace = array_shift($nodes);
  134. $count--;
  135. }
  136. if (!isset($this->registry[$namespace])) {
  137. $this->makeNameSpace($namespace);
  138. }
  139. $ns = $this->registry[$namespace]['data'];
  140. $pathNodes = $count - 1;
  141. if ($pathNodes < 0) {
  142. $pathNodes = 0;
  143. }
  144. for ($i = 0; $i < $pathNodes; $i ++)
  145. {
  146. // If any node along the registry path does not exist, create it
  147. if (!isset($ns->$nodes[$i])) {
  148. $ns->$nodes[$i] = new stdClass();
  149. }
  150. $ns = $ns->$nodes[$i];
  151. }
  152. // Set the new values
  153. if(is_string($value))
  154. {
  155. if(substr($value,0,10) == '###json###')
  156. {
  157. $value = json_decode(substr($value,10));
  158. }
  159. }
  160. // Post-process certain directory-containing variables
  161. if( $process_special_vars && in_array($regpath, $this->directory_containing_keys) )
  162. {
  163. if(!empty($stock_directories))
  164. {
  165. $data = $value;
  166. foreach($stock_directories as $tag => $content)
  167. {
  168. $data = str_replace($tag, $content, $data);
  169. }
  170. $ns->$nodes[$i] = $data;
  171. return $ns->$nodes[$i];
  172. }
  173. }
  174. // This is executed if any of the previous two if's is false
  175. $ns->$nodes[$i] = $value;
  176. return $ns->$nodes[$i];
  177. }
  178. /**
  179. * Resets the registry to the default values
  180. */
  181. public function reset()
  182. {
  183. // Load the Akeeba Engine INI files
  184. $ds = DIRECTORY_SEPARATOR;
  185. $root_path = dirname(__FILE__);
  186. $plugin_path = $root_path.$ds.'plugins';
  187. $paths = array(
  188. $root_path.$ds.'core',
  189. $root_path.$ds.'engines'.$ds.'archiver',
  190. $root_path.$ds.'engines'.$ds.'dump',
  191. $root_path.$ds.'engines'.$ds.'scan',
  192. $root_path.$ds.'engines'.$ds.'writer',
  193. $root_path.$ds.'engines'.$ds.'proc',
  194. $root_path.$ds.'platform'.$ds.'filters'.$ds.'stack',
  195. $root_path.$ds.'filters'.$ds.'stack',
  196. $plugin_path.$ds.'engines'.$ds.'archiver',
  197. $plugin_path.$ds.'engines'.$ds.'dump',
  198. $plugin_path.$ds.'engines'.$ds.'scan',
  199. $plugin_path.$ds.'engines'.$ds.'writer',
  200. $plugin_path.$ds.'engines'.$ds.'proc',
  201. $plugin_path.$ds.'filters'.$ds.'stack'
  202. );
  203. foreach($paths as $root)
  204. {
  205. $handle = @opendir($root);
  206. if($handle !== false)
  207. {
  208. while( false !== ($file = @readdir($handle)) )
  209. {
  210. if(substr($file,-4) == '.ini')
  211. {
  212. $this->mergeEngineINI($root.DIRECTORY_SEPARATOR.$file);
  213. }
  214. }
  215. closedir($handle);
  216. }
  217. }
  218. }
  219. /**
  220. * Merges an associative array of key/value pairs into the registry.
  221. * If noOverride is set, only non set or null values will be applied.
  222. * @param array $array An associative array. Its keys are registry paths.
  223. * @param bool $noOverride [optional] Do not override pre-set values.
  224. * @param bool $process_special_vars Optional. If true (default), it processes special variables, e.g. [SITEROOT] in folder names
  225. */
  226. public function mergeArray($array, $noOverride = false, $process_special_vars = true)
  227. {
  228. if(!$noOverride)
  229. {
  230. foreach($array as $key => $value)
  231. {
  232. $this->set($key, $value, $process_special_vars);
  233. }
  234. }
  235. else
  236. {
  237. foreach($array as $key => $value)
  238. {
  239. if( is_null($this->get($key, null)) )
  240. $this->set($key, $value, $process_special_vars);
  241. }
  242. }
  243. }
  244. /**
  245. * Merges an INI-style file into the registry. Its sections are registry paths,
  246. * keys are appended to the section-defined paths and then set equal to the
  247. * values. If noOverride is set, only non set or null values will be applied.
  248. * Sections beginning with an underscore will be ignored.
  249. * @param string $inifile The full path to the INI file to load
  250. * @param bool $noOverride [optional] Do not override pre-set values.
  251. * @return bool True on success
  252. */
  253. public function mergeINI($inifile, $noOverride = false)
  254. {
  255. if(!file_exists($inifile)) return false;
  256. $inidata = AEUtilINI::parse_ini_file($inifile, true);
  257. foreach($inidata as $rootkey => $rootvalue)
  258. {
  259. if(!is_array($rootvalue))
  260. {
  261. if(!$noOverride)
  262. {
  263. $this->set($rootkey, $rootvalue);
  264. }
  265. elseif( is_null($this->get($rootkey, null)) )
  266. {
  267. $this->set($rootkey, $rootvalue);
  268. }
  269. }
  270. elseif( substr($rootkey,0,1) != '_' )
  271. {
  272. foreach($rootvalue as $key => $value)
  273. {
  274. if(!$noOverride)
  275. {
  276. $this->set($rootkey.'.'.$key, $rootvalue);
  277. }
  278. elseif( is_null($this->get($rootkey.'.'.$key, null)) )
  279. {
  280. $this->set($rootkey.'.'.$key, $rootvalue);
  281. }
  282. }
  283. }
  284. }
  285. return true;
  286. }
  287. /**
  288. * Merges an engine INI file to the configuration. Each section defines a full
  289. * registry path (section.subsection.key). It searches each section for the
  290. * key named "default" and merges its value to the configuration. The other keys
  291. * are simply ignored.
  292. * @param string $inifile The absolute path to an INI file
  293. * @param bool $noOverride [optional] If true, values from the INI will not override the configuration
  294. * @return bool True on success
  295. */
  296. public function mergeEngineINI($inifile, $noOverride = false)
  297. {
  298. if(!file_exists($inifile)) return false;
  299. $inidata = AEUtilINI::parse_ini_file($inifile, true);
  300. foreach($inidata as $section => $nodes)
  301. {
  302. if(is_array($nodes))
  303. {
  304. if( substr($section,0,1) != '_' )
  305. {
  306. if(isset($nodes['default']))
  307. {
  308. if(!$noOverride)
  309. {
  310. $this->set($section, $nodes['default']);
  311. }
  312. elseif( is_null($this->get($section, null)) )
  313. {
  314. $this->set($section, $nodes['default']);
  315. }
  316. }
  317. }
  318. }
  319. }
  320. return true;
  321. }
  322. /**
  323. * Exports the current registry snapshot as an INI file. Each namespace is
  324. * placed in a section of its own.
  325. * @param bool $dump_global Set to true to dump the "global" namespace, false to dump everything EXCEPT the [global] namespace
  326. * @return string INI representation of the registry
  327. */
  328. public function exportAsINI()
  329. {
  330. $inidata = '';
  331. $namespaces = $this->getNameSpaces();
  332. foreach($namespaces as $namespace)
  333. {
  334. $inidata .= "[$namespace]\n";
  335. $ns = $this->registry[$namespace]['data'];
  336. $inidata .= $this->dumpObject($ns);
  337. }
  338. return $inidata;
  339. }
  340. /**
  341. * Internal function to dump an object as INI-formatted data
  342. * @param object $object
  343. * @param object $prefix [optional]
  344. * @return
  345. */
  346. private function dumpObject($object, $prefix = '')
  347. {
  348. $data = '';
  349. $vars = get_object_vars($object);
  350. foreach( $vars as $key => $value )
  351. {
  352. if(!is_object($value))
  353. {
  354. if(is_array($value))
  355. {
  356. $value = '###json###'.json_encode($value);
  357. }
  358. $data .= (empty($prefix) ? '' : $prefix.'.').$key.
  359. '="'.addcslashes($value,"\n\r\t\"")."\"\n";
  360. }
  361. else
  362. {
  363. $data .= $this->dumpObject($value, (empty($prefix) ? '' : $prefix.'.').$key );
  364. }
  365. }
  366. return $data;
  367. }
  368. }
  369. ?>