Вход Регистрация
Файл: protected/modules/install/extensions/Config_Lite/Config_Lite.php
Строк: 1009
<?php
/**
 * Config_Lite (Config/Lite.php)
 *
 * PHP version 5
 *
 * @file      Config/Lite.php
 * @category  Configuration
 * @package   Config_Lite
 * @author    Patrick C. Engel <pce@php.net>
 * @copyright 2010-2011 <pce@php.net>
 * @license   http://www.gnu.org/copyleft/lesser.html  LGPL License 2.1
 * @version   SVN: $Id$
 * @link      https://github.com/pce/config_lite
 */

/*
require_once 'Config/Lite/Exception.php';
require_once 'Config/Lite/Exception/InvalidArgument.php';
require_once 'Config/Lite/Exception/Runtime.php';
require_once 'Config/Lite/Exception/UnexpectedValue.php';
 */

/**
 * Config_Lite Class
 *
 * read and save ini text files.
 * Config_Lite has the native PHP function 
 * `parse_ini_file' under the hood.
 * The API is inspired by Python's ConfigParser.
 * A "Config_Lite" file consists of 
 * "name = value" entries and sections,
 * "[section]"
 * followed by "name = value" entries
 *
 * @category  Configuration
 * @package   Config_Lite
 * @author    Patrick C. Engel <pce@php.net>
 * @copyright 2010-2011 <pce@php.net>
 * @license   http://www.gnu.org/copyleft/lesser.html  LGPL License 2.1
 * @link      https://github.com/pce/config_lite
 */
class Config_Lite implements ArrayAccessIteratorAggregateCountable
{
    
/**
     * sections, holds the config sections
     *
     * @var array
     */
    
protected $sections;
    
/**
     * filename
     *
     * @var string
     */
    
protected $filename;
    
/**
     * _booleans - alias of bool in a representable Configuration String Format
     *
     * @var array
     */
    
private $_booleans = array('1' => true'on' => true
                               
'true' => true'yes' => true
                               
'0' => false'off' => false
                               
'false' => false'no' => false);
                               
    
/**
     * line-break chars, default *x: "n", windows: "rn"
     *
     * @var string
     */
    
protected $linebreak "n";

    
/**
     * parseSections - if true, sections will be processed
     * 
     * @var bool
     */
    
protected $processSections true;
    
    
/**
     * the read method parses the optional given filename 
     * or already setted filename.
     * 
     * this method uses the native PHP function 
     * parse_ini_file behind the scenes. 
     *
     * @param string $filename Filename
     *
     * @return void
     * @throws Config_Lite_Exception_Runtime when file not found
     * @throws Config_Lite_Exception_Runtime when file is not readable
     * @throws Config_Lite_Exception_Runtime when parse ini file failed
     */
    
public function read($filename null
    {
        if (
null === $filename) {
            
$filename $this->filename;
        } else {
            
$this->filename $filename;
        }
        if (!
file_exists($filename)) {
            throw new 
Config_Lite_Exception_Runtime('file not found: ' $filename);
        }
        if (!
is_readable($filename)) {
            throw new 
Config_Lite_Exception_Runtime('file not readable: '
                
$filename
            
);
        }
        
$this->sections parse_ini_file($filename$this->processSections);
        if (
false === $this->sections) {
            throw new 
Config_Lite_Exception_Runtime(
                
'failure, can not parse the file: ' $filename
            
);
        }
    }
    
/**
     * save the object to the already setted filename 
     * (active record style)
     *
     * @return bool
     */
    
public function save() 
    {
        return 
$this->write($this->filename$this->sections);
    }
    
/**
     * sync the file to the object
     *
     * like `save',
     * but after written the data, reads the data back into the object.
     * The method is inspired by QTSettings.
     * Ideal for testing.
     *
     * @return void
     * @throws Config_Lite_Exception_Runtime when file is not set, 
     *         write or readable
     */
    
public function sync() 
    {
        if (!isset(
$this->filename)) {
            throw new 
Config_Lite_Exception_Runtime('no filename set.');
        }
        if (!
is_array($this->sections)) {
            
$this->sections = array();
        }
        if (
$this->write($this->filename$this->sections)) {
            
$this->read($this->filename);
        }
    }
    
    
/**
     * detect Type "bool" by String Value to keep those "untouched"
     *
     * @param string $value value
     *
     * @return bool
     */
    
protected function isBool($value
    {
        return 
in_array($value$this->_booleans);
    }
    
    
/**
     * normalize a Value by determining the Type
     *
     * @param string $value value
     *
     * @return string
     */
    
protected function normalizeValue($value
    {
        if (
is_bool($value)) {
            
$value $this->to('bool'$value);
            return 
$value;
        } elseif (
is_numeric($value)) {
            return 
$value;
        }
        
// if (is_string($value) && !$this->isBool($value))
        
$value '"' $value '"';
        return 
$value;
    }
    
    
/**
     * generic write ini config file, to save use `save'.
     *
     * writes the global options and sections with normalized Values, 
     * that means "bool" values to human readable representation, 
     * doublequotes strings and numeric values without any quotes.
     * prepends a php exit if suffix is php,
     * it is valid to write an empty Config file,
     * this method is used by save and is public for explicit usage,
     * eg. if you do not want to hold the whole configuration in the object.
     *
     * @param string $filename      filename
     * @param array  $sectionsarray array with sections
     *
     * @return bool
     * @throws Config_Lite_Exception_Runtime when file is not writeable
     * @throws Config_Lite_Exception_Runtime when write failed
     */
    
public function write($filename$sectionsarray
    {
        
$content $this->buildOutputString($sectionsarray);
        if (
false === file_put_contents($filename$contentLOCK_EX)) {
            throw new 
Config_Lite_Exception_Runtime(
                
sprintf(
                    
'failed to write file `%s' for writing.', $filename
                )
            );
        }
        return true;
    }

    /**
     * Generated the output of the ini file, suitable for echo'
ing or
     * 
writing back to the ini file.
     * 
     * @
param string $sectionsarray array of ini data
     

     * @return 
string
     
*/
    protected function 
buildOutputString($sectionsarray)
    {
        
$content '';
        
$sections '';
        
$globals  '';
        if (!empty(
$sectionsarray)) {
            
// 2 loops to write `globals' on top, alternative: buffer
            
foreach ($sectionsarray as $section => $item) {
                if (!
is_array($item)) {
                    
$value    $this->normalizeValue($item);
                    
$globals .= $section ' = ' $value $this->linebreak;
                }
            }
            
$content .= $globals;
            foreach (
$sectionsarray as $section => $item) {
                if (
is_array($item)) {
                    
$sections .= "n[" $section "]n";
                    foreach (
$item as $key => $value) {
                        if (
is_array($value)) {
                            foreach (
$value as $arrkey => $arrvalue) {
                                
$arrvalue  $this->normalizeValue($arrvalue);
                                
$arrkey    $key '[' $arrkey ']';
                                
$sections .= $arrkey ' = ' $arrvalue 
                                            
$this->linebreak;
                            }
                        } else {
                            
$value     $this->normalizeValue($value);
                            
$sections .= $key ' = ' $value $this->linebreak;
                        }
                    }
                }
            }
            
$content .= $sections;
        }
        return 
$content;
    }

    
/**
     * converts type (format) to string or representable Config Format
     *
     * @param string $format "bool", "boolean"
     * @param string $value  value
     *
     * @return string
     * @throws Config_Lite_Exception_UnexpectedValue when format is unknown
     */
    
public function to($format$value
    {
        switch (
$format) {
        case 
'bool':
        case 
'boolean':
            if (
$value === true) {
                return 
'yes';
            }
            return 
'no';
            break;
        default:
            
// unknown format
            
throw new Config_Lite_Exception_UnexpectedValue(
                
sprintf('no conversation made, unrecognized format: `%s'', $format)
            );
            break;
        }
    }
    
    /**
     * returns a stripslashed string
     *
     * @param string $sec     Section
     * @param string $key     Key
     * @param mixed  $default default return value
     *
     * @return string
     * @throws Config_Lite_Exception_Runtime when config is empty
     *         and no default value is given
     * @throws Config_Lite_Exception_UnexpectedValue key not found 
     *         and no default value is given
     */
    public function getString($sec, $key, $default = null) 
    {
        if ((null === $this->sections) && (null === $default)) {
            throw new Config_Lite_Exception_Runtime(
                '
configuration seems to be empty, no sections.'
            );
        }
        if ((null === $sec) && array_key_exists($key, $this->sections)) {
            return stripslashes($this->sections[$key]);
        }
        if (array_key_exists($key, $this->sections[$sec])) {
            return stripslashes($this->sections[$sec][$key]);
        }
        if (null !== $default) {
            return $default;
        }
        throw new Config_Lite_Exception_UnexpectedValue(
            '
key not foundno default value given.'
        );
    }
    
    /**
     * get an option by section, a global option or all sections and options
     * 
     * to get an option by section, call get with a section and the option.
     * To get a global option call `get' 
with null as section.
     * 
Just call `get' without any parameters to get all sections and options. 
     * The third parameter is an optional default value to return, 
     * if the option is not set, this is practical when dealing with 
     * editable files, to keep an application stable with default settings.
     *
     * @param string 
$sec     Section|null - null to get global option
     * @param string 
$key     Key
     * @param mixed  
$default return default value if is $key is not set
     *
     * @return mixed
     * @throws Config_Lite_Exception when config is empty
     *         and no default value is given
     * @throws Config_Lite_Exception_UnexpectedValue key not found 
     *         and no default value is given
     */
    public function get(
$sec = null, $key = null, $default = null)
    {
        if ((null !== 
$sec) && array_key_exists($key$this->sections[$sec])) {
            return 
$this->sections[$sec][$key];
        }
        // global value
        if ((null === 
$sec) && array_key_exists($key$this->sections)) {
            return 
$this->sections[$key];
        }
        // section
        if ((null === 
$key) && array_key_exists($sec$this->sections)) {
            return 
$this->sections[$sec];
        }
        // all sections
        if ((null === 
$sec) && array_key_exists($sec$this->sections)) {
            return 
$this->sections;
        }
        if (null !== 
$default) {
            return 
$default;
        }
        throw new Config_Lite_Exception_UnexpectedValue(
            'key not found, no default value given.'
        );
    }
    
    /**
     * returns a boolean for strict equality comparison 
     * 
     * returns "on", "yes", 1, "true" as TRUE
     * and no given value or "off", "no", 0, "false" as FALSE
     *
     * @param string 
$sec     Section
     * @param string 
$key     Key
     * @param bool   
$default return default value if is $key is not set
     *
     * @return bool
     * @throws Config_Lite_Exception_Runtime when the configuration is empty
     *         and no default value is given
     * @throws Config_Lite_Exception_InvalidArgument when is not a boolean
     *         and no default array is given
     * @throws Config_Lite_Exception_UnexpectedValue when key not found
     *         and no default array is given
     */
    public function getBool(
$sec$key$default = null) 
    {
        if ((null === 
$this->sections) && (null === $default)) {
            throw new Config_Lite_Exception_Runtime(
                'configuration seems to be empty (no sections),' 
                . 'and no default value given.'
            );
        }
        if ((null === 
$sec)) {
            if (array_key_exists(
$key$this->sections)) {
                if (empty(
$this->sections[$key])) {
                    return false;
                }
                
$value = strtolower($this->sections[$key]);
                if (!in_array(
$value$this->_booleans) && (null === $default)) {
                    throw new Config_Lite_Exception_InvalidArgument(
                        sprintf(
                            'Not a boolean: %s, and no default value given.', 
                            
$value
                        )
                    );
                } else {
                    return 
$this->_booleans[$value];
                }
            }
        }
        if (array_key_exists(
$key$this->sections[$sec])) {
            if (empty(
$this->sections[$sec][$key])) {
                return false;
            }
            
$value = strtolower($this->sections[$sec][$key]);
            if (!in_array(
$value$this->_booleans) && (null === $default)) {
                throw new Config_Lite_Exception_InvalidArgument(
                    sprintf(
                        'Not a boolean: %s, and no default value given.', 
                        
$value
                    )
                );
            } else {
                return 
$this->_booleans[$value];
            }
        }
        if (null !== 
$default) {
            return 
$default;
        }
        throw new Config_Lite_Exception_UnexpectedValue(
            'option not found, no default value given.'
        );
    }
    
    /**
     * returns an array of options of the given section
     * 
     * @param string 
$sec     Section
     * @param array  
$default return default array if $sec is not set
     *
     * @return array
     * @throws Config_Lite_Exception_Runtime when config is empty
     *         and no default array is given
     * @throws Config_Lite_Exception_UnexpectedValue when key not found
     *         and no default array is given
     */
    public function getSection(
$sec$default = null) 
    {
        if ((null === 
$this->sections) && (null === $default)) {
            throw new Config_Lite_Exception_Runtime(
                'configuration seems to be empty, no sections.'
            );
        }
        if (isset(
$this->sections[$sec])) {
            return 
$this->sections[$sec];
        }
        if ((null !== 
$default) && is_array($default)) {
            return 
$default;
        }
        throw new Config_Lite_Exception_UnexpectedValue(
            'section not found, no default array given.'
        );
    }

    /**
     * returns true if the given section exists, otherwise false
     *
     * @param string 
$sec Section
     *
     * @return bool
     */
    public function hasSection(
$sec
    {
        if (isset(
$this->sections[$sec]) && is_array($this->sections[$sec])) {
            return true;
        }
        return false;
    }
    
    /**
     * tests if a section or an option of a section exists
     *
     * @param string 
$sec Section
     * @param string 
$key Key
     *
     * @return bool
     */
    public function has(
$sec$key=null)
    {
        if (!
$this->hasSection($sec)) {
            return false;
        }
        if ((null !== 
$key) && isset($this->sections[$sec][$key])) {
            return true;
        }
        return false;
    }
    
    /**
     * remove a section or an option of a section
     *
     * @param string 
$sec Section
     * @param string 
$key Key
     *
     * @return void
     * @throws Config_Lite_Exception_UnexpectedValue when given Section not exists
     */
    public function remove(
$sec$key=null) 
    {
        if ((null === 
$key)) {
            
$this->removeSection($sec);
        }
        if (!isset(
$this->sections[$sec])) {
            throw new Config_Lite_Exception_UnexpectedValue('No such Section.');
        }
        unset(
$this->sections[$sec][$key]);
    }
    
    /**
     * remove section by name
     *
     * @param string 
$sec Section
     *
     * @return void
     * @throws Config_Lite_Exception_UnexpectedValue when given Section not exists
     */
    public function removeSection(
$sec
    {
        if (!isset(
$this->sections[$sec])) {
            throw new Config_Lite_Exception_UnexpectedValue('No such Section.');
        }
        unset(
$this->sections[$sec]);
    }
    
    /**
     * removes all sections and global options
     *
     * @return void
     */
    public function clear() 
    {
        
$this->sections = array();
    }
    
    /**
     * like set, but adds slashes to the value
     * 
     * creates new section if necessary and overrides existing keys.
     *
     * @param string 
$sec   Section
     * @param string 
$key   Key
     * @param mixed  
$value Value
     *
     * @return 
$this
     * @throws Config_Lite_Exception_InvalidArgument when given key is an array
     */
    public function setString(
$sec$key$value = null) 
    {
        if (null !== 
$value) {
            
$value = addslashes($value);
        }
        
$this->set($sec$key$value); 
        return 
$this;
    }

    /**
     *  to add key/value pairs 
     * 
     * creates new section if necessary and overrides existing keys.
     * To set a global, "sectionless" value, call set with null as section.
     *
     * @param string 
$sec   Section
     * @param string 
$key   Key
     * @param mixed  
$value Value
     *
     * @throws Config_Lite_Exception when given key is an array
     * @return 
$this
     */
    public function set(
$sec$key$value = null) 
    {
        if (!is_array(
$this->sections)) {
            
$this->sections = array();
        }
        if (is_array(
$key) || is_array($sec)) {
            throw new Config_Lite_Exception_InvalidArgument(
                'string key expected, but array given.'
            );
        }
        if (null === 
$sec) {
            
$this->sections[$key] = $value;
        } else {
            
$this->sections[$sec][$key] = $value;
        }
        return 
$this;
    }
    
    /**
     * set a given array with key/value pairs to a section,
     * creates a new section if necessary.
     *
     * @param string 
$sec   Section
     * @param array  
$pairs Keys and Values as Array ('key' => 'value')
     *
     * @throws Config_Lite_Exception_InvalidArgument array 
$pairs expected
     * @return 
$this
     */
    public function setSection(
$sec$pairs
    {
        if (!is_array(
$this->sections)) {
            
$this->sections = array();
        }
        if (!is_array(
$pairs)) {
            throw new Config_Lite_Exception_InvalidArgument('array expected.');
        }
        
$this->sections[$sec] = $pairs;
        return 
$this;
    }
    
    /**
     * filename to read or save
     *
     * the full filename with suffix, ie. 
`[PATH/]<ApplicationName>.ini'.
     * you can also set the filename as parameter to the constructor.
     * 
     * @param string $filename Filename
     *
     * @return $this
     */
    public function setFilename($filename) 
    {
        $this->filename = $filename;
        return $this;
    }

    /**
     * returns the current filename
     * 
     * @return string
     */
    public function getFilename()
    {
        return $this->filename;
    }

    /**
     * set the line break (newline) chars 
     *
     * line-break defaults to Unix Newline "n", 
     * set to support other linebreaks, eg. windows user 
     * textfiles "rn"
     * 
     * @param string $linebreakchars chars
     *
     * @return $this
     */
    public function setLinebreak($linebreakchars)
    {
        $this->linebreak = $linebreakchars;
        return $this;
    }

    /**
     * Sets whether or not sections should be processed
     * 
     * If true, values for each section will be placed into
     * a sub-array for the section. If false, all values will
     * be placed in the global scope.
     * 
     * @param bool $processSections - if true, sections will be processed
     * 
     * @return $this
     */
    public function setProcessSections($processSections)
    {
        $this->processSections = $processSections;
        return $this;
    }
    
    /**
     * text presentation of the config object
     *
     * since a empty config is valid,
     * it would return a empty string in that case. 
     *
     * @throws Config_Lite_Exception_Runtime
     * @return string
     */
    public function __toString() 
    {
        return $this->buildOutputString($this->sections);
    }
    
    /**
     * implemented for interface ArrayAccess
     *
     * @param string $offset section, implemented by ArrayAccess
     * @param mixed  $value  KVP, implemented by ArrayAccess
     * 
     * @return void
     */
    public function offsetSet($offset, $value) 
    {
        $this->sections[$offset] = $value;
    }
    
    /**
     * implemented for interface ArrayAccess
     * 
     * @param string $offset - section, implemented by ArrayAccess
     *
     * @return bool
     */
    public function offsetExists($offset) 
    {
        return isset($this->sections[$offset]);
    }
    
    /**
     * implemented for interface ArrayAccess
     * 
     * @param string $offset - section, implemented by ArrayAccess
     *
     * @return void
     */
    public function offsetUnset($offset) 
    {
        unset($this->sections[$offset]);
    }
    
    /**
     * implemented for interface ArrayAccess
     *
     * @param string $offset - section, implemented by ArrayAccess
     * 
     * @return mixed
     */
    public function offsetGet($offset) 
    {
        if (array_key_exists($offset, $this->sections)) {
            return $this->sections[$offset];
        }
        return null;
    }
    /**
     * implemented for interface IteratorAggregate
     * 
     * @see http://www.php.net/~helly/php/ext/spl/interfaceIterator.html
     * @return Iterator 
     */
    public function getIterator() 
    {
        return new ArrayIterator($this->sections);
    }

    /**
     * implemented for interface Countable
     * 
     * @see http://php.net.countable
     * @return int
     */
    public function count()
    {
        return count($this->sections);
    }
    
    /**
     * takes an optional filename, if the file exists, also reads it.
     *
     * the `save' 
and `read' methods relies on a setted filename, 
     * but you can also use 
`setFilename' to set the filename.
     * 
     * @param string $filename - "INI Style" Text Config File
     */
    public function __construct($filename = null) 
    {
        $this->sections = array();
        if (null !== $filename) {
            $this->setFilename($filename);
            if (file_exists($filename)) {
                $this->read($filename);
            }
        }
    }
}
Онлайн: 1
Реклама