[ create a new paste ] login | about

Link: http://codepad.org/t71yrLvb    [ raw code | output | fork ]

PHP, pasted on Mar 14:
<?php

class Config{



  protected

    $_level      = 0,
    $_parent     = null,
    $_data       = array(),
    $_output     = null;



  public function __construct(array $array, $level = 0, $parent = null){

    $this->_level = $level;
    $this->_parent = $parent;

    foreach($array as $key => $value)
      $this->_data[$key] = is_array($value) ? new self($value, $level + 1, $this) : $value;

  }


  public static function load($file){
    $config = new self(parse_ini_file($file, true));
    $config->setOutput($file);
    return $config;
  }


  public function setOutput($file){
    $this->_output = $file;
  }


  public function __get($name){

    if($this->_level > 1)
      throw new Exception('Unsupported nesting level');

    if(array_key_exists($name, $this->_data))
      return $this->_data[$name];

    if($this->_level < 1){
      $this->_data[$name] = new self(array(), $this->_level + 1, $this);

      return $this->_data[$name];
    }

    throw new Exception('Invalid request');
  }


  public function __set($name, $value){

    if($this->_level > 1)
      throw new Exception('Unsupported nesting level');

    elseif($this->_level < 1)
      throw new Exception('You cannot assign values to sections');

    if(!isset($this->_data[$name]) || ($this->_data[$name] !== $value)){
      $this->_data[$name] = is_array($value) ? new self($value, $this->_level + 1, $this) : $value;

      ($this->_level > 0 && isset($this->_parent)) ? $this->_parent->write() : $this->write();
    }
  }


  public function __isset($name){
    return isset($this->_data[$name]);
  }




  public function __clone(){
    $array = array();
    foreach($this->_data as $key => $value)
      $array[$key] = ($value instanceof Config) ? clone $value : $value;

    $this->_data = $array;
  }



  public function __unset($name){
    unset($this->_data[$name]);
  }


  // from Zend
  public function toArray(){

    $array = array();
    $data = $this->_data;

    foreach($data as $key => $value)
      $array[$key] = ($value instanceof Config) ? $value->toArray() : $value;

    return $array;
  }


  // from Zend
  public function merge(Config $merge){
    foreach($merge as $key => $item){
      if(array_key_exists($key, $this->_data))
        $this->$key = ($item instanceof Config && $this->$key instanceof Config) ? $this->$key->merge(new self($item->toArray(), $this->_level + 1)) : $item;

      else
        $this->$key = ($item instanceof Config) ? new self($item->toArray(), $this->_level + 1) : $item;
    }

    return $this;
  }


  public function write($exclusive_lock = true){

    if(empty($this->_output))
      throw new Exception('You need to set an output location before write');

    $flags = 0;

    if($exclusive_lock)
      $flags |= LOCK_EX;

    $result = @file_put_contents($this->_output, $this->__toString(), $flags);

    if($result === false)
      throw new Exception('Could not write configuration to file "'.$this->_output.'"');

    return true;
  }


  public function __toString(){

    $meta = $temp_meta = array();

    if(isset($this->_output)){
      $section = $last_key = '';

      foreach(file($this->_output) as $line){

        // extra stuff (comments, new lines etc.)
        if(preg_match('/^\s*(;.*)?$/', $line)){
          // extra stuff (comments, new lines etc.)
          $temp_meta[] = $line;

        // section
        }elseif(preg_match('/\[(.*)\]/', $line, $match)){
          $section = $match[1];

          // add any meta data we got up to this point
          $meta[$section]['_before'] = implode('', $temp_meta);
          $temp_meta = array();

        // entry
        }elseif(preg_match('/^\s*(.*?)\s*=\s*(.*?)\s*$/', $line, $match)){
          $last_key = $match[1];

          // if we have recorded meta so far, it means it needs to be placed before an entry
          if($temp_meta){
            $meta[$section][$last_key] = implode('', $temp_meta);
            $temp_meta = array();
          }

        }

      }
    }

    $ini_string = '';
    $config = $this->toArray();

    if($this->_level < 1){
      foreach($config as $group => $keys){

        if(isset($meta[$group]['_before']))
          $ini_string .= $meta[$group]['_before'];

        $ini_string .= '['.$group.']'."\n";

        $max_length = $keys ? max(array_map('strlen', array_keys($keys))) : 0;

        foreach($keys as $key => $value){

          if(isset($meta[$group][$key]))
            $ini_string .= $meta[$group][$key];

          $ini_string .= str_pad($key, $max_length).' = '.$this->_prepareValue($value)."\n";
        }

      }

    }else{
      $max_length = max(array_map('strlen', array_keys($config)));

      foreach($config as $key => $value)
        $ini_string .= str_pad($key, $max_length).' = '.$this->_prepareValue($value)."\n";

    }

    return $ini_string;
  }


  protected function _prepareValue($value){

    if(is_integer($value) || is_float($value))
      return $value;

    elseif(is_bool($value))
      return ($value ? 'true' : 'false');

    elseif(strpos($value, '"') === false)
      return '"'.$value.'"';

    throw new Exception('Value can not contain double quotes');
  }

}


$config = Config::load('file.ini');

print $config;

// add new branch and entry
$config->foo->setting1 = 'abc';
$config->foo->setting2 = 'def';


Output:
1
2
3
4
5
6
7
8
9
10
11
12
13

Warning: parse_ini_file(file.ini): failed to open stream: No such file or directory on line 28

Warning: file(file.ini): failed to open stream: No such file or directory on line 148

Warning: Invalid argument supplied for foreach() on line 148

Fatal error: Uncaught exception 'Exception' with message 'Could not write configuration to file "file.ini"' in /t.php:135
Stack trace:
#0 /t.php(68): Config->write()
#1 /t.php(235): Config->__set('setting1', 'abc')
#2 {main}
  thrown in /t.php on line 135


Create a new paste based on this one


Comments: