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