1: <?php
  2: 
  3:   4:   5:   6:   7:   8:   9:  10: 
 11: 
 12: namespace Nette\Config;
 13: 
 14: use Nette;
 15: 
 16: 
 17: 
 18:  19:  20:  21:  22: 
 23: class Config extends Nette\Collections\Hashtable
 24: {
 25:     
 26:     const READONLY = 1;
 27:     const EXPAND = 2;
 28:     
 29: 
 30:     
 31:     private static $extensions = array(
 32:         'ini' => 'Nette\Config\ConfigAdapterIni',
 33:     );
 34: 
 35: 
 36: 
 37:      38:  39:  40:  41:  42: 
 43:     public static function registerExtension($extension, $class)
 44:     {
 45:         if (!class_exists($class)) {
 46:             throw new \InvalidArgumentException("Class '$class' was not found.");
 47:         }
 48: 
 49:         if (!Nette\Reflection\ClassReflection::from($class)->implementsInterface('Nette\Config\IConfigAdapter')) {
 50:             throw new \InvalidArgumentException("Configuration adapter '$class' is not Nette\\Config\\IConfigAdapter implementor.");
 51:         }
 52: 
 53:         self::$extensions[strtolower($extension)] = $class;
 54:     }
 55: 
 56: 
 57: 
 58:      59:  60:  61:  62:  63:  64: 
 65:     public static function fromFile($file, $section = NULL, $flags = self::READONLY)
 66:     {
 67:         $extension = strtolower(pathinfo($file, PATHINFO_EXTENSION));
 68:         if (isset(self::$extensions[$extension])) {
 69:             $arr = call_user_func(array(self::$extensions[$extension], 'load'), $file, $section);
 70:             return new static($arr, $flags);
 71: 
 72:         } else {
 73:             throw new \InvalidArgumentException("Unknown file extension '$file'.");
 74:         }
 75:     }
 76: 
 77: 
 78: 
 79:      80:  81:  82: 
 83:     public function __construct($arr = NULL, $flags = self::READONLY)
 84:     {
 85:         parent::__construct($arr);
 86: 
 87:         if ($arr !== NULL) {
 88:             if ($flags & self::EXPAND) {
 89:                 $this->expand();
 90:             }
 91: 
 92:             if ($flags & self::READONLY) {
 93:                 $this->freeze();
 94:             }
 95:         }
 96:     }
 97: 
 98: 
 99: 
100:     101: 102: 103: 104: 105: 
106:     public function save($file, $section = NULL)
107:     {
108:         $extension = strtolower(pathinfo($file, PATHINFO_EXTENSION));
109:         if (isset(self::$extensions[$extension])) {
110:             return call_user_func(array(self::$extensions[$extension], 'save'), $this, $file, $section);
111: 
112:         } else {
113:             throw new \InvalidArgumentException("Unknown file extension '$file'.");
114:         }
115:     }
116: 
117: 
118: 
119:     
120: 
121: 
122: 
123:     124: 125: 126: 
127:     public function expand()
128:     {
129:         $this->updating();
130: 
131:         $data = $this->getArrayCopy();
132:         foreach ($data as $key => $val) {
133:             if (is_string($val)) {
134:                 $data[$key] = Nette\Environment::expand($val);
135:             } elseif ($val instanceof self) {
136:                 $val->expand();
137:             }
138:         }
139:         $this->setArray($data);
140:     }
141: 
142: 
143: 
144:     145: 146: 147: 148: 149: 
150:     public function import($arr)
151:     {
152:         $this->updating();
153: 
154:         foreach ($arr as $key => $val) {
155:             if (is_array($val)) {
156:                 $arr[$key] = $obj = clone $this;
157:                 $obj->import($val);
158:             }
159:         }
160:         $this->setArray($arr);
161:     }
162: 
163: 
164: 
165:     166: 167: 168: 
169:     public function toArray()
170:     {
171:         $res = $this->getArrayCopy();
172:         foreach ($res as $key => $val) {
173:             if ($val instanceof self) {
174:                 $res[$key] = $val->toArray();
175:             }
176:         }
177:         return $res;
178:     }
179: 
180: 
181: 
182:     183: 184: 185: 
186:     public function freeze()
187:     {
188:         parent::freeze();
189:         foreach ($this->getArrayCopy() as $val) {
190:             if ($val instanceof self) {
191:                 $val->freeze();
192:             }
193:         }
194:     }
195: 
196: 
197: 
198:     199: 200: 201: 
202:     public function __clone()
203:     {
204:         parent::__clone();
205:         $data = $this->getArrayCopy();
206:         foreach ($data as $key => $val) {
207:             if ($val instanceof self) {
208:                 $data[$key] = clone $val;
209:             }
210:         }
211:         $this->setArray($data);
212:     }
213: 
214: 
215: 
216:     
217: 
218: 
219: 
220:     221: 222: 223: 224: 
225:     public function &__get($key)
226:     {
227:         $val = $this->offsetGet($key);
228:         return $val;
229:     }
230: 
231: 
232: 
233:     234: 235: 236: 237: 238: 
239:     public function __set($key, $item)
240:     {
241:         $this->offsetSet($key, $item);
242:     }
243: 
244: 
245: 
246:     247: 248: 249: 250: 
251:     public function __isset($key)
252:     {
253:         return $this->offsetExists($key);
254:     }
255: 
256: 
257: 
258:     259: 260: 261: 262: 
263:     public function __unset($key)
264:     {
265:         $this->offsetUnset($key);
266:     }
267: 
268: }
269: