PageRenderTime 79ms CodeModel.GetById 22ms RepoModel.GetById 1ms app.codeStats 0ms

/Config_Lite/Lite.php

https://github.com/saltybeagle/config_lite
PHP | 489 lines | 398 code | 4 blank | 87 comment | 10 complexity | 6c799b94fa52e55457f6123bd05bd4a8 MD5 | raw file
  1. <?php
  2. /**
  3. * Config_Lite (Config/Lite.php)
  4. *
  5. * PHP version 5
  6. *
  7. * @file Config/Lite.php
  8. * @category Configuration
  9. * @package Config_Lite
  10. * @author Patrick C. Engel <info@pc-e.org>
  11. * @copyright 2010 info@pc-e.org
  12. * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
  13. * @version Release: @package_version@
  14. * @link https://github.com/pce/config_lite
  15. */
  16. spl_autoload_register(array('Config_Lite', 'autoload'));
  17. if (class_exists('Config_Lite_UnexpectedValueException', true) === false) {
  18. throw new Exception('Config_Lite_UnexpectedValueException not found');
  19. }
  20. /**
  21. * Config_Lite Class
  22. *
  23. * read & save "INI-Style" Configuration Files,
  24. * fast and with the native php function under the hood.
  25. *
  26. * Inspired by Python's ConfigParser.
  27. *
  28. * A "Config_Lite" file consists of sections,
  29. * "[section]"
  30. * followed by "name = value" entries
  31. *
  32. * note: Config_Lite assumes that all name/value entries are in sections.
  33. *
  34. * @category Configuration
  35. * @package Config_Lite
  36. * @author Patrick C. Engel <info@pc-e.org>
  37. * @copyright 2010 info@pc-e.org
  38. * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
  39. * @version Release: @package_version@
  40. * @link https://github.com/pce/config_lite
  41. */
  42. class Config_Lite
  43. {
  44. /**
  45. * sections, holds the config sections
  46. *
  47. * @var array
  48. */
  49. protected $sections;
  50. /**
  51. * filename
  52. *
  53. * @var string
  54. */
  55. protected $filename;
  56. /**
  57. * _booleans - alias of bool in a representable Configuration String Format
  58. *
  59. * @var array
  60. */
  61. private $_booleans = array('1' => true, 'on' => true,
  62. 'true' => true, 'yes' => true,
  63. '0' => false, 'off' => false,
  64. 'false' => false, 'no' => false);
  65. /**
  66. * read, note: always assumes and works with sections
  67. *
  68. * @param string $filename Filename
  69. *
  70. * @return bool
  71. * @throws Config_Lite_Exception when file not exists
  72. */
  73. public function read($filename)
  74. {
  75. if (!file_exists($filename)) {
  76. throw new Config_Lite_RuntimeException('file not found: ' . $filename);
  77. }
  78. $this->filename = $filename;
  79. $this->sections = parse_ini_file($filename, true);
  80. if (false === $this->sections) {
  81. throw new Config_Lite_RuntimeException(
  82. 'failure, can not parse the file: ' . $filename);
  83. }
  84. }
  85. /**
  86. * save (active record style)
  87. *
  88. * @return bool
  89. */
  90. public function save()
  91. {
  92. return $this->write($this->filename, $this->sections);
  93. }
  94. /**
  95. * write INI-Style Config File
  96. *
  97. * prepends a php exit if suffix is php,
  98. * it is valid to write an empty Config file,
  99. * file locking is not part of this Class
  100. *
  101. * @param string $filename filename
  102. * @param array $sectionsarray array with sections
  103. *
  104. * @return bool
  105. * @throws Config_Lite_Exception when file is not writeable
  106. */
  107. public function write($filename, $sectionsarray)
  108. {
  109. $content = '';
  110. if ('.php' === substr($filename, -4)) {
  111. $content .= ';<?php exit; ?>' . "\n";
  112. }
  113. $sections = '';
  114. if (!empty($sectionsarray)) {
  115. foreach ($sectionsarray as $section => $item) {
  116. if (is_array($item)) {
  117. $sections.= "\n[{$section}]\n";
  118. foreach ($item as $key => $value) {
  119. if (is_bool($value)) {
  120. $value = $this->to('bool', $value);
  121. } elseif (is_string($value)) { // && strpos '|"
  122. $value = '"'. $value .'"';
  123. }
  124. $sections.= $key .' = '. $value ."\n";
  125. }
  126. }
  127. }
  128. $content.= $sections;
  129. }
  130. if (!$fp = fopen($filename, 'w')) {
  131. throw new Config_Lite_RuntimeException(
  132. "failed to open file `{$filename}' for writing.");
  133. }
  134. if (!fwrite($fp, $content)) {
  135. throw new Config_Lite_RuntimeException(
  136. "failed to write file `{$filename}'");
  137. }
  138. fclose($fp);
  139. return true;
  140. }
  141. /**
  142. * convert type to string or representable Config Format
  143. *
  144. * @param string $format `bool', `boolean'
  145. * @param string $value value
  146. *
  147. * @return mixed
  148. * @throws Config_Lite_Exception when format is unknown
  149. */
  150. public function to($format, $value)
  151. {
  152. switch ($format) {
  153. case 'bool':
  154. case 'boolean':
  155. if ($value === true) {
  156. return 'yes';
  157. }
  158. return 'no';
  159. break;
  160. default:
  161. // unknown format
  162. throw new Config_Lite_UnexpectedValueException(
  163. "no conversation made, unrecognized format `{$format}'");
  164. break;
  165. }
  166. }
  167. /**
  168. * getString
  169. *
  170. * @param string $sec Section
  171. * @param string $key Key
  172. * @param mixed $default default return value
  173. *
  174. * @return string
  175. * @throws Config_Lite_Exception when config is empty
  176. * and no default value is given
  177. * @throws Config_Lite_Exception key not found and no default value is given
  178. */
  179. public function getString($sec, $key, $default = null)
  180. {
  181. if (is_null($this->sections) && is_null($default)) {
  182. throw new Config_Lite_RuntimeException(
  183. 'configuration seems to be empty, no sections.');
  184. }
  185. if (array_key_exists($key, $this->sections[$sec])) {
  186. return stripslashes($this->sections[$sec][$key]);
  187. }
  188. if (!is_null($default)) {
  189. return $default;
  190. }
  191. throw new Config_Lite_UnexpectedValueException(
  192. 'key not found, no default value given.'
  193. );
  194. }
  195. /**
  196. * get
  197. *
  198. * @param string $sec Section
  199. * @param string $key Key
  200. * @param mixed $default default return value
  201. *
  202. * @return string
  203. * @throws Config_Lite_Exception when config is empty
  204. * and no default value is given
  205. * @throws Config_Lite_Exception key not found and no default value is given
  206. */
  207. public function get($sec, $key, $default = null)
  208. {
  209. if (is_null($this->sections) && is_null($default)) {
  210. throw new Config_Lite_RuntimeException(
  211. 'configuration seems to be empty, no sections.');
  212. }
  213. if (array_key_exists($key, $this->sections[$sec])) {
  214. return $this->sections[$sec][$key];
  215. }
  216. if (!is_null($default)) {
  217. return $default;
  218. }
  219. throw new Config_Lite_UnexpectedValueException(
  220. 'key not found, no default value given.'
  221. );
  222. }
  223. /**
  224. * getBool - returns on,yes,1,true as TRUE
  225. * and no given value or off,no,0,false as FALSE
  226. *
  227. * @param string $sec Section
  228. * @param string $key Key
  229. * @param bool $default default Value
  230. *
  231. * @return bool
  232. * @throws Config_Lite_Exception when the configuration is empty
  233. * and no default value is given
  234. */
  235. public function getBool($sec, $key, $default = null)
  236. {
  237. if (is_null($this->sections) && is_null($default)) {
  238. throw new Config_Lite_RuntimeException(
  239. 'configuration seems to be empty (no sections),'
  240. . 'and no default value given.');
  241. }
  242. if (array_key_exists($key, $this->sections[$sec])) {
  243. if (empty($this->sections[$sec][$key])) {
  244. return false;
  245. }
  246. $value = strtolower($this->sections[$sec][$key]);
  247. if (!in_array($value, $this->_booleans) && is_null($default)) {
  248. throw new Config_Lite_UnexpectedValueException(sprintf(
  249. 'Not a boolean: %s, and no default value given.', $value
  250. ));
  251. } else {
  252. return $this->_booleans[$value];
  253. }
  254. }
  255. if (!is_null($default)) {
  256. return $default;
  257. }
  258. throw new Config_Lite_UnexpectedValueException(
  259. 'option not found, no default value given.'
  260. );
  261. }
  262. /**
  263. * array get section
  264. *
  265. * @param string $sec Section
  266. * @param array $default default value
  267. *
  268. * @return array
  269. * @throws Config_Lite_Exception when config is empty
  270. * and no default array is given
  271. * @throws Config_Lite_Exception when key not found
  272. * and no default array is given
  273. */
  274. public function getSection($sec, $default = null)
  275. {
  276. if (is_null($this->sections) && is_null($default)) {
  277. throw new Config_Lite_RuntimeException(
  278. 'configuration seems to be empty, no sections.');
  279. }
  280. if (isset($this->sections[$sec])) {
  281. return $this->sections[$sec];
  282. }
  283. if (!is_null($default) && is_array($default)) {
  284. return $default;
  285. }
  286. throw new Config_Lite_UnexpectedValueException(
  287. 'section not found, no default array given.'
  288. );
  289. }
  290. /**
  291. * has option
  292. *
  293. * @param string $sec Section
  294. * @param string $key Key
  295. *
  296. * @return bool
  297. */
  298. public function has($sec, $key)
  299. {
  300. if (!$this->hasSection($sec)) {
  301. return false;
  302. }
  303. if (isset($this->sections[$sec][$key])) {
  304. return true;
  305. }
  306. return false;
  307. }
  308. /**
  309. * has section
  310. *
  311. * @param string $sec Section
  312. *
  313. * @return bool
  314. */
  315. public function hasSection($sec)
  316. {
  317. if (isset($this->sections[$sec])) {
  318. return true;
  319. }
  320. return false;
  321. }
  322. /**
  323. * Remove option
  324. *
  325. * @param string $sec Section
  326. * @param string $key Key
  327. *
  328. * @return void
  329. * @throws Config_Lite_Exception when given Section not exists
  330. */
  331. public function remove($sec, $key)
  332. {
  333. if (!isset($this->sections[$sec])) {
  334. throw new Config_Lite_UnexpectedValueException('No such Section.');
  335. }
  336. unset($this->sections[$sec][$key]);
  337. }
  338. /**
  339. * Remove section
  340. *
  341. * @param string $sec Section
  342. *
  343. * @return void
  344. * @throws Config_Lite_Exception when given Section not exists
  345. */
  346. public function removeSection($sec)
  347. {
  348. if (!isset($this->sections[$sec])) {
  349. throw new Config_Lite_UnexpectedValueException('No such Section.');
  350. }
  351. unset($this->sections[$sec]);
  352. }
  353. /**
  354. * Set (string) key - add key/doublequoted value pairs to a section,
  355. * creates new section if necessary and overrides existing keys
  356. *
  357. * @param string $sec Section
  358. * @param string $key Key
  359. * @param mixed $value Value
  360. *
  361. * @return void
  362. * @throws Config_Lite_UnexpectedValueException when given key is an array
  363. */
  364. public function setString($sec, $key, $value = null)
  365. {
  366. if (!is_array($this->sections)) {
  367. $this->sections = array();
  368. }
  369. if (is_array($key)) {
  370. throw new Config_Lite_UnexpectedValueException(
  371. 'string key expected, but array given.');
  372. }
  373. $this->sections[$sec][$key] = addslashes($value);
  374. return $this;
  375. }
  376. /**
  377. * Set key - add key/value pairs to a section,
  378. * creates new section if necessary and overrides existing keys
  379. *
  380. * @param string $sec Section
  381. * @param string $key Key
  382. * @param mixed $value Value
  383. *
  384. * @return void
  385. * @throws Config_Lite_Exception when given key is an array
  386. */
  387. public function set($sec, $key, $value = null)
  388. {
  389. if (!is_array($this->sections)) {
  390. $this->sections = array();
  391. }
  392. if (is_array($key)) {
  393. throw new Config_Lite_InvalidArgumentException(
  394. 'string key expected, but array given.');
  395. }
  396. $this->sections[$sec][$key] = $value;
  397. return $this;
  398. }
  399. /**
  400. * Set section - add key/value pairs to a section,
  401. * creates new section if necessary.
  402. *
  403. * @param string $sec Section
  404. * @param array $pairs Keys and Values as Array ('key' => 'value')
  405. *
  406. * @return void|PEAR_Error
  407. */
  408. public function setSection($sec, $pairs)
  409. {
  410. if (!is_array($this->sections)) {
  411. $this->sections = array();
  412. }
  413. if (!is_array($pairs)) {
  414. throw new Config_Lite_UnexpectedValueException('array expected.');
  415. }
  416. $this->sections[$sec] = $pairs;
  417. return $this;
  418. }
  419. /**
  420. * Text presentation of the Configuration, since empy config is valid,
  421. * theres no return of "The Configuration is empty.\n";
  422. *
  423. * @throws Config_Lite_RuntimeException
  424. * @return string
  425. */
  426. public function __toString()
  427. {
  428. $s = "";
  429. if ($this->sections != null) {
  430. foreach ($this->sections as $section => $name) {
  431. $s.= sprintf("[%s]\n", $section);
  432. if (is_array($name)) {
  433. foreach ($name as $key => $val) {
  434. $s.= sprintf("\t%s = %s\n", $key, $val);
  435. }
  436. }
  437. }
  438. return $s;
  439. }
  440. if (!isset($this->filename)) {
  441. throw new Config_Lite_RuntimeException(
  442. 'Did not read a Configuration File.'
  443. );
  444. }
  445. return $s;
  446. }
  447. /**
  448. * Autoload static method for loading classes and interfaces.
  449. * includes Code from the PHP_CodeSniffer package by
  450. * Greg Sherwood and Marc McIntyre
  451. *
  452. * @param string $className - name of the class or interface.
  453. *
  454. * @return void
  455. */
  456. public static function autoload($className)
  457. {
  458. $package = 'Config_';
  459. $packageLen = strlen($package);
  460. if (substr($className, 0, $packageLen) === $package) {
  461. $newClassName = substr($className, $packageLen);
  462. } else {
  463. $newClassName = $className;
  464. }
  465. $path = str_replace('_', '/', $newClassName).'.php';
  466. if (is_file(dirname(__FILE__).'/'.$path) === true) {
  467. include dirname(__FILE__).'/'.$path;
  468. } else {
  469. file_exists($path) && (include $path);
  470. }
  471. }
  472. /**
  473. * Constructor optional takes a filename
  474. *
  475. * @param string $filename - INI Style Config File
  476. */
  477. public function __construct($filename = null)
  478. {
  479. if (($filename != null) && (file_exists($filename))) {
  480. $this->read($filename);
  481. }
  482. }
  483. }