PageRenderTime 47ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/lib/config/cfConfig.class.php

https://bitbucket.org/cyberfox/cyberfox-php-framework
PHP | 508 lines | 314 code | 18 blank | 176 comment | 11 complexity | 724ab5854b80b7bbba05697c97ca071e MD5 | raw file
Possible License(s): LGPL-3.0
  1. <?php
  2. /**
  3. -----------------------------------------------------------------------------
  4. * CONFIG MANAGEMENT
  5. *
  6. * Read one or more config files an put the settings into defined categories.
  7. * Your application can take the settings via static method getEntry().
  8. *
  9. * Only files with the defined file types defined by the registered config readers will be read. (Default are .php and .ini)
  10. * The settings from the files will be stored in the designated category defined by the filename itself.
  11. * e.g.: database.ini will be stored in the category "database"
  12. *
  13. *
  14. * Example:
  15. * 1. cfConfig::addIncludePath('full qualified path to your config files');
  16. * 2. cfConfig::scanIncludePath() ... scan the includes and read all defined config files defined by the registered config readers.
  17. * 3. cfConfig::getEntry('mySetting', 'Categoryname'); e.g: cfConfig::getEntry('hostname', 'database');
  18. *
  19. -----------------------------------------------------------------------------
  20. -----------------------------------------------------------------------------
  21. * @copyright (C) 2011 Cyberfox Software Solutions e.U.
  22. * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License version 3 (LGPLv3)
  23. * @author Christian Graf <christian.graf@cyberfox.at>
  24. -----------------------------------------------------------------------------
  25. -----------------------------------------------------------------------------
  26. * @package redfox
  27. * @subpackage dataset
  28. * @category data
  29. -----------------------------------------------------------------------------
  30. -----------------------------------------------------------------------------
  31. * @version $Id: cfConfig.class.php 89 2012-05-22 11:19:33Z cgraf $
  32. * @date $Date: 2012-05-22 13:19:33 +0200 (Di, 22 Mai 2012) $
  33. * @svnauthor $Author: cgraf $
  34. -----------------------------------------------------------------------------
  35. */
  36. class cfConfig
  37. {
  38. /**
  39. * Stores the config setting data.
  40. * array('category' => array(settings))
  41. *
  42. * @var array
  43. * @access private
  44. * @static
  45. */
  46. private static $data = null;
  47. /**
  48. * Associated array of defined categories.
  49. * array('categoryname' => 'description')
  50. *
  51. * @var array
  52. * @access private
  53. * @static
  54. */
  55. private static $categories = array();
  56. /**
  57. * Name of the default categorie. Uses if the assigment of settings could not be taken.
  58. * Default name is "misc".
  59. *
  60. * @var string
  61. * @access private
  62. * @static
  63. */
  64. private static $defaultCategory = 'misc';
  65. /**
  66. * List of full qualified file path to the config files.
  67. *
  68. * @var array
  69. * @access private
  70. * @static
  71. */
  72. private static $include_path = array();
  73. /**
  74. * List of registered config readers. (Classnames)
  75. *
  76. * @var array
  77. * @access private
  78. * @static
  79. */
  80. private static $configReaders = array();
  81. /**
  82. * GetAllCategories()
  83. *
  84. * Returns an associated array of all defined categories.
  85. * array('categoryname' => 'description')
  86. *
  87. * If not categories defined, the follow predefined list will be returned:
  88. * 1. 'core' => 'Framework Settings',
  89. * 2. 'database' => 'Database Connectivity Settings',
  90. * 3. 'session' => 'Session Managment Settings',
  91. * 4. 'error' => 'Error Management Settings',
  92. * 5. 'template' => 'Template Settings',
  93. * 6. 'application' => 'Application Settings',
  94. * 7. 'misc' => 'All other stuff, also default'
  95. *
  96. * @return array An associated array of all defined categories
  97. * @access public
  98. * @final
  99. * @static
  100. */
  101. public static function GetAllCategories()
  102. {
  103. if(empty(self::$categories))
  104. {
  105. self::$categories = array(
  106. 'core' => 'Framework Settings',
  107. 'database' => 'Database Connectivity Settings',
  108. 'session' => 'Session Managment Settings',
  109. 'error' => 'Error Management Settings',
  110. 'template' => 'Template Settings',
  111. 'application' => 'Application Settings',
  112. '_application_state' => 'Dynamic Application Settings made by the application itselfs',
  113. 'misc' => 'All other stuff, also default'
  114. );
  115. }
  116. return self::$categories;
  117. }
  118. /**
  119. * getDefaultCategory()
  120. *
  121. * Returns the name of the default category. Default is "misc".
  122. *
  123. * @return string The name of the default category
  124. * @access public
  125. * @final
  126. * @static
  127. */
  128. final public static function GetDefaultCategory()
  129. {
  130. return self::$defaultCategory;
  131. }
  132. /**
  133. * GetDataObject()
  134. *
  135. * Returns the data object array.
  136. * Each category has it's own cfDataObject to store the settings.
  137. * array('categoryname' => cfDataObject)
  138. *
  139. * @return array Array of data objects
  140. * @access protected
  141. * @final
  142. * @static
  143. */
  144. final protected static function &GetData()
  145. {
  146. if(is_null(self::$data))
  147. {
  148. $categories = self::GetAllCategories();
  149. self::$data = array();
  150. foreach(array_keys($categories) as $categ)
  151. {
  152. self::$data[$categ] = array();
  153. }
  154. }
  155. return self::$data;
  156. }
  157. /**
  158. * SetEntry()
  159. *
  160. * Set one setting-entry to a category.
  161. *
  162. * @param string $Name Name of the setting
  163. * @param mixed $Value Value of the setting
  164. * @param string $Category (optional) Name of the selected category, if it is empty the defualt category will be taken.
  165. * @return void
  166. * @access public
  167. * @final
  168. * @static
  169. */
  170. final public static function SetEntry($Name, $Value, $Category = null)
  171. {
  172. if(empty($Category))
  173. $Category = self::GetDefaultCategory();
  174. $data =& self::GetData();
  175. if(!isset($data[$Category]))
  176. $data[$Category] = array();
  177. $data[$Category][$Name] = $Value;
  178. }
  179. /**
  180. * IsEntrySet()
  181. *
  182. * Checks if an entry has been set.
  183. *
  184. * @param string $Name Name of the setting
  185. * @param string $Category (optional) Name of the selected category, if it is empty the defualt category will be taken.
  186. * @return bool TRUE if an entry has been set
  187. * @access public
  188. * @final
  189. * @static
  190. */
  191. final public static function IsEntrySet($Name, $Category = null)
  192. {
  193. if(empty($Category))
  194. $Category = self::GetDefaultCategory();
  195. $data =& self::GetData();
  196. return isset($data[$Category][$Name]);
  197. }
  198. /**
  199. * GetEntry()
  200. *
  201. * Returns the value of an setting entry
  202. *
  203. * @param string $Name Name of the setting
  204. * @param string $Category (optional) Name of the selected category, if it is empty the defualt category will be taken.
  205. * @return mixed The value of the designated setting entry. Returns NULL if no setting available.
  206. * @access public
  207. * @final
  208. * @static
  209. */
  210. final public static function GetEntry($Name, $Category = null)
  211. {
  212. if(empty($Category))
  213. $Category = self::GetDefaultCategory();
  214. $data =& self::GetData();
  215. if(isset($data[$Category][$Name]))
  216. {
  217. return $data[$Category][$Name];
  218. }
  219. return null;
  220. }
  221. /**
  222. * GetAllEntries()
  223. *
  224. * Returns an associated array of all settings which have been set in a category
  225. * array('setting' => value)
  226. * or
  227. * array('category' => array('setting' => value))
  228. *
  229. * @param string $Category (optional) Name of the selected category, if it is empty ALL settings from ALL categories will be returned.
  230. * @return array Array of available settings
  231. * @access public
  232. * @final
  233. * @static
  234. */
  235. final public static function GetAllEntries($Category = null)
  236. {
  237. $returnArr = array();
  238. $data =& self::GetData();
  239. if(empty($Category))
  240. {
  241. $categories = self::GetAllCategories();
  242. foreach(array_keys($categories) as $categ)
  243. {
  244. if(isset($data[$categ]))
  245. $returnArr[$categ] = $data[$categ];
  246. else
  247. $returnArr[$categ] = array();
  248. }
  249. }
  250. else
  251. {
  252. if(isset($data[$Category]))
  253. $returnArr = $data[$Category];
  254. }
  255. return $returnArr;
  256. }
  257. /**
  258. * AddIncludePath()
  259. *
  260. * Add a path to the config include path
  261. *
  262. * @param string $Path A full qualified path for inclusion
  263. * @return void
  264. * @access public
  265. * @static
  266. * @final
  267. */
  268. final public static function AddIncludePath($Path)
  269. {
  270. $Path = str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, trim($Path));
  271. if(!empty($Path) && !in_array($Path, self::$include_path))
  272. {
  273. self::$include_path[] = $Path;
  274. }
  275. }
  276. /**
  277. * GetIncludePath()
  278. *
  279. * Get an array of all include paths
  280. * array('path1', 'path2')
  281. *
  282. * @return array Array of the include paths
  283. * @access public
  284. * @static
  285. * @final
  286. */
  287. final public static function GetIncludePath()
  288. {
  289. return self::$include_path;
  290. }
  291. /**
  292. * scanIncludePath()
  293. *
  294. * Scan all include path to find and inlcude necessary files.
  295. * Hidden files will be ignored for inclusion, also files with names containes ~, bak or -dist will be ignored.
  296. * Recursive directory searching will not be supported.
  297. *
  298. * @return void
  299. * @access public
  300. * @static
  301. * @final
  302. */
  303. final public static function ScanIncludePath()
  304. {
  305. $includePath = self::GetIncludePath();
  306. foreach($includePath as $i => $path)
  307. {
  308. if(is_dir($path))
  309. {
  310. $tmpDir = dir($path);
  311. while(($entry = $tmpDir->read()) !== false)
  312. {
  313. $fullFilename = $path .DIRECTORY_SEPARATOR .$entry;
  314. if(
  315. $entry == '.'
  316. || $entry == '..'
  317. || strpos($entry, '.') === 0 //hidden file or dirctory
  318. || is_dir($fullFilename)
  319. || substr($entry, -1) == '~' //unix "backup" files e.g. from VIM
  320. || substr($entry, -3) == 'bak' //.bak ... also backpfiles
  321. || strpos($entry, '-dist.') > 0
  322. )
  323. {
  324. continue; //ignore this file
  325. }
  326. else
  327. {
  328. self::ReadConfigFile($fullFilename);
  329. }
  330. }
  331. $tmpDir->close();
  332. }
  333. }
  334. }
  335. /**
  336. * RegisterConfigFileReader()
  337. *
  338. * Register a config reader for one file extension.
  339. * The registered reader have to be an instance of cfConfigFileReader class.
  340. * Beware: One extension for one reader. If you want to use one reader for more extensions you have to register it
  341. * separately for each extension.
  342. *
  343. * The reader class will be loaded via autoloader automaticly or you can include the class file befor loading the config.
  344. *
  345. * @param string $Extension File extension for the reader. e.g.: txt, ini, php, xml, ...
  346. * @return void
  347. * @access public
  348. * @static
  349. * @final
  350. */
  351. final public static function RegisterConfigFileReader($Extension, $Classname)
  352. {
  353. self::$configReaders[trim($Extension)] = trim($Classname);
  354. }
  355. /**
  356. * GetConfigFileReader()
  357. *
  358. * Get an instance of cfConfigFileReader for the defined file extension.
  359. * If not reader are defined the default reader will be registered. (Only for ini and php files).
  360. *
  361. * If not reader defined for the selected extension, so FALSE will be returned.
  362. *
  363. * @param string $Extension File extension for the reader. e.g.: txt, ini, php, xml, ...
  364. * @return cfConfigFileReader The instance of cfConfigFileReader for the designated file extension.
  365. * @access private
  366. * @static
  367. * @final
  368. */
  369. final private static function &GetConfigFileReader($Extension)
  370. {
  371. $ret = false;
  372. if(empty(self::$configReaders)) //set default values
  373. {
  374. self::RegisterConfigFileReader('php', 'cfConfigFileReader_PHP');
  375. self::RegisterConfigFileReader('ini', 'cfConfigFileReader_INI');
  376. }
  377. if(isset(self::$configReaders[$Extension]))
  378. {
  379. if(is_string(self::$configReaders[$Extension]))
  380. {
  381. $classname = self::$configReaders[$Extension];
  382. self::$configReaders[$Extension] = new $classname();
  383. }
  384. if(is_object(self::$configReaders[$Extension]) && self::$configReaders[$Extension] instanceof cfConfigFileReader)
  385. {
  386. $ret =& self::$configReaders[$Extension];
  387. }
  388. }
  389. return $ret;
  390. }
  391. /**
  392. * ReadConfigFile()
  393. *
  394. * Include one file and pars the settings.
  395. * Based on the filename, the category will be determined. Default = misc
  396. * File format: <category>[-_.]<qualifier>.<extension>
  397. *
  398. * @param string $FullFilename Filename to include and parse for settings
  399. * @return bool TRUE if the files was successfully readed
  400. * @access private
  401. * @static
  402. * @final
  403. */
  404. final private static function ReadConfigFile($FullFilename)
  405. {
  406. $FullFilename = trim($FullFilename);
  407. $path = dirname($FullFilename);
  408. $filename = basename($FullFilename);
  409. $options = array(
  410. 'filename' => '',
  411. 'category' => self::GetDefaultCategory(),
  412. 'qualifier' => '',
  413. 'extension' => ''
  414. );
  415. $matches = array();
  416. $result = preg_match('/^(?P<category>[^-_\.]+)(?:[-_\.]+(?P<qualifier>[^-_\.]+))?\.(?P<extension>[a-zA-Z]{3,4})/', $filename, $matches);
  417. if($result)
  418. {
  419. if(isset($matches['category']) && !empty($matches['category']))
  420. {
  421. $options['category'] = trim($matches['category']);
  422. }
  423. else $options['category'] = self::GetDefaultCategory();
  424. if(isset($matches['qualifier']) && !empty($matches['qualifier']))
  425. {
  426. $options['qualifier'] = trim($matches['qualifier']);
  427. }
  428. if(isset($matches['extension']) && !empty($matches['extension']))
  429. {
  430. $options['extension'] = trim($matches['extension']);
  431. }
  432. else
  433. {
  434. $options['extension'] = substr($filename, -3);
  435. }
  436. $options['filename'] = $filename;
  437. }
  438. if(($readerObj = self::GetConfigFileReader($options['extension'])) !== false)
  439. {
  440. $readerObj->SetFile($FullFilename);
  441. $settings = $readerObj->ReadFile();
  442. if(!empty($settings))
  443. {
  444. foreach($settings as $entry => $value)
  445. {
  446. self::SetEntry($entry, $value, $options['category']);
  447. }
  448. }
  449. }
  450. else
  451. {
  452. throw new cfException(__METHOD__ .': Could not get instance of cfConfigFileReader for ".' .$options['extension'] .'"');
  453. }
  454. }
  455. /**
  456. * dump()
  457. *
  458. * Dumps the complete config array direclty on screen.
  459. *
  460. * @return void
  461. * @access public
  462. */
  463. public function dump()
  464. {
  465. if(php_sapi_name() == 'cli')
  466. { //for command line output
  467. echo "\n" .print_r(self::$data, true) ."\n";
  468. }
  469. else
  470. { //for html output
  471. echo '<pre>' .print_r(self::$data, true) .'</pre>';
  472. }
  473. }
  474. }
  475. ?>