Overview

Namespaces

  • Mini
    • Config

Classes

  • Mini\Config\Config
  • Mini\Config\Utils
  • Overview
  • Namespace
  • Class
  • Tree
  1: <?php
  2: 
  3: namespace Mini\Config;
  4: 
  5: use ArrayAccess;
  6: use JsonSerializable;
  7: 
  8: /**
  9:  * Creates an array from the config files in the provided directories.
 10:  *
 11:  * @package Mini\Config
 12:  * @author Andrew Breksa (abreksa4@gmail.com)
 13:  */
 14: class Config implements ArrayAccess, JsonSerializable, \Serializable {
 15: 
 16:     /**
 17:      * The config array, holds the config from all merged config files.
 18:      *
 19:      * @var array
 20:      */
 21:     protected $config;
 22: 
 23:     /**
 24:      * The array of targets for Config to include in the the config array.
 25:      *
 26:      * @var array
 27:      */
 28:     protected $directories = [];
 29: 
 30:     /**
 31:      * The array of files for Config to include in the the config array.
 32:      *
 33:      * @var array
 34:      */
 35:     protected $files = [];
 36: 
 37:     /**
 38:      * The array of handlers, as 'extension' => 'callable'.
 39:      *
 40:      * @var array
 41:      */
 42:     protected $handlers;
 43: 
 44:     /**
 45:      * Config constructor.
 46:      *
 47:      * An array of startup options, currently supports the keys 'targets' which should contain an array of targets, and
 48:      * 'handlers' an array of handlers in the format [$extension, $handler].
 49:      *
 50:      * @param array $options
 51:      */
 52:     public function __construct($options = null) {
 53:         if (isset($options)) {
 54:             if (isset($options['targets'])) {
 55:                 if (is_array($options['targets'])) {
 56:                     foreach ($options['targets'] as $path) {
 57:                         $this->addTarget($path);
 58:                     }
 59:                 } else {
 60:                     $this->addTarget($options['targets']);
 61:                 }
 62:             }
 63:             if (isset($options['handlers'])) {
 64:                 foreach (array_keys($options['handlers']) as $ext) {
 65:                     $this->registerHandler($ext, $options['handlers'][$ext]);
 66:                 }
 67:             }
 68:         }
 69:         $this->registerDefaultHandlers();
 70:         $this->refresh();
 71:     }
 72: 
 73:     /**
 74:      * Adds a target to the target listing to include.
 75:      *
 76:      * @param string|array $target
 77:      */
 78:     public function addTarget($target) {
 79:         if (is_array($target)) {
 80:             foreach ($target as $p) {
 81:                 $this->addTarget($p);
 82:             }
 83:             return;
 84:         }
 85:         if (is_dir($target)) {
 86:             $this->directories[] = rtrim($target, '/');
 87:         } elseif (is_file($target)) {
 88:             $this->files[] = $target;
 89:         }
 90:     }
 91: 
 92:     /**
 93:      * Register a handler. Takes a file extension to match files by, and a function to process the file and return an
 94:      * array.
 95:      *
 96:      * @param string|array $extension
 97:      * @param callable $handler
 98:      */
 99:     public function registerHandler($extension, $handler) {
100:         if (is_array($extension)) {
101:             foreach ($extension as $ext) {
102:                 $this->handlers[$ext] = $handler;
103:             }
104:         } else {
105:             $this->handlers[$extension] = $handler;
106:         }
107:     }
108: 
109:     /**
110:      * Register the default handlers, 'php', 'xml', 'ini', and 'json'.
111:      */
112:     private function registerDefaultHandlers() {
113:         $this->registerHandler('xml', function ($file) {
114:             $xml2array = function ($xmlObject, $out = array()) use (&$xml2array) {
115:                 foreach ((array)$xmlObject as $index => $node) {
116:                     $out[$index] = (is_object($node)) ? $xml2array($node) : $node;
117:                 }
118:                 return $out;
119:             };
120:             return $xml2array(simplexml_load_string(file_get_contents($file)));
121:         });
122:         $this->registerHandler('php', function ($file) {
123:             $data = include($file);
124:             if ($data != null && is_array($data)) {
125:                 return $data;
126:             }
127:             return;
128:         });
129:         $this->registerHandler('ini', function ($file) {
130:             return parse_ini_file($file, true);
131:         });
132:         $this->registerHandler('json', function ($file) {
133:             return json_decode(file_get_contents($file), true);
134:         });
135:     }
136: 
137:     /**
138:      * Build the config array, call this after adding config directories after the constructor.
139:      */
140:     public function refresh() {
141:         $this->config = [];
142:         foreach ($this->directories as $dir) {
143:             foreach ($this->handlers as $ext => $function) {
144:                 foreach (glob($dir . "/*." . $ext, GLOB_NOSORT) as $file) {
145:                     $this->config = array_merge_recursive($this->config, $function($file));
146:                 }
147:             }
148:         }
149:         foreach ($this->files as $file) {
150:             $pathinfo = pathinfo($file);
151:             if (isset($pathinfo['extension'])) {
152:                 $ext = $pathinfo['extension'];
153:                 if (in_array($ext, array_keys($this->handlers))) {
154:                     $this->config = array_merge_recursive($this->config, $this->handlers[$ext]($file));
155:                 }
156:             }
157:         }
158:     }
159: 
160:     /**
161:      * Merges the provided array and config array into the config array
162:      *
163:      * @param array $config
164:      */
165:     public function merge(array $config) {
166:         $this->config = array_merge_recursive($this->config, $config);
167:     }
168: 
169:     /**
170:      * Removes a handler from the internal handler array, stopping the parsing of files with that extension.
171:      *
172:      * @param string $extension
173:      */
174:     public function removeHandler($extension) {
175:         unset($this->handlers[$extension]);
176:     }
177: 
178:     /**
179:      * @param mixed $offset
180:      * @return bool
181:      */
182:     public function offsetExists($offset) {
183:         return $this->__isset($offset);
184:     }
185: 
186:     /**
187:      * @param $key
188:      * @return bool
189:      */
190:     public function __isset($key) {
191:         return isset($this->config[$key]);
192:     }
193: 
194:     /**
195:      * @param mixed $offset
196:      * @return mixed
197:      */
198:     public function offsetGet($offset) {
199:         return $this->__get($offset);
200:     }
201: 
202:     /**
203:      * @param $key
204:      * @return mixed
205:      */
206:     public function __get($key) {
207:         if (isset($this->config[$key])) {
208:             return $this->config[$key];
209:         } else {
210:             return null;
211:         }
212:     }
213: 
214:     /**
215:      * @param $key
216:      * @param $value
217:      */
218:     public function __set($key, $value) {
219:         if ($key === null) {
220:             $this->config[] = $value;
221:         } else {
222:             $this->config[$key] = $value;
223:         }
224:     }
225: 
226:     /**
227:      * @param mixed $offset
228:      * @param mixed $data
229:      */
230:     public function offsetSet($offset, $data) {
231:         $this->__set($offset, $data);
232:     }
233: 
234:     /**
235:      * @param mixed $offset
236:      */
237:     public function offsetUnset($offset) {
238:         unset($this->config[$offset]);
239:     }
240: 
241:     /**
242:      * @param $name
243:      */
244:     public function __unset($name) {
245:         if (isset($this->config[$name])) {
246:             unset($this->config[$name]);
247:         }
248:     }
249: 
250:     /**
251:      * String representation of object
252:      * @link http://php.net/manual/en/serializable.serialize.php
253:      * @return string the string representation of the object or null
254:      * @since 5.1.0
255:      */
256:     public function serialize() {
257:         return $this->jsonSerialize();
258:     }
259: 
260:     /**
261:      * Specify data which should be serialized to JSON
262:      * @link http://php.net/manual/en/jsonserializable.jsonserialize.php
263:      * @return mixed data which can be serialized by <b>json_encode</b>,
264:      * which is a value of any type other than a resource.
265:      * @since 5.4.0
266:      */
267:     function jsonSerialize() {
268:         return $this->config;
269:     }
270: 
271:     /**
272:      * Constructs the object
273:      * @link http://php.net/manual/en/serializable.unserialize.php
274:      * @param string $serialized <p>
275:      * The string representation of the object.
276:      * </p>
277:      * @return void
278:      * @since 5.1.0
279:      */
280:     public function unserialize($serialized) {
281:         $this->config = json_decode($serialized, true);
282:     }
283: }
284: 
285: /**
286:  * Utils class for Mini\Config
287:  * @package Mini\Config
288:  * @author Andrew Breksa (abreksa4@gmail.com)
289:  */
290: class Utils {
291:     /**
292:      * Merges two arrays, and returns the result. Takes an optional $overwrite parameter to overwrite string value with
293:      * those in the second array, i.e.:
294:      * <code>
295:      * $this->_merge([
296:      *     'database'=>[
297:      *         'password' => 'toor'
298:      *     ]],[
299:      *     'database'=>[
300:      *         'password' => 'password'
301:      * ]], true);
302:      * </code>
303:      *
304:      * Will result in:
305:      * <code>
306:      * [
307:      *     'database' => [
308:      *         'password' => 'password
309:      *     ]
310:      * ]
311:      * </code>
312:      *
313:      * @param array $array1
314:      * @param array $array2
315:      * @param bool|false $overwrite
316:      * @return array
317:      */
318:     public static function merge($array1, $array2, $overwrite = false) {
319:         $array = $array1;
320:         foreach (array_keys($array2) as $key) {
321:             if (!isset($array1[$key])) {
322:                 $array[$key] = $array2[$key];
323:                 continue;
324:             }
325:             if (is_array($array1[$key])) {
326:                 $array[$key] = self::Merge($array1[$key], $array2[$key], $overwrite);
327:                 continue;
328:             }
329:             if ($overwrite) {
330:                 $array[$key] = $array2[$key];
331:             } else {
332:                 $array[$key] = [$array[$key], $array2[$key]];
333:             }
334:         }
335:         return $array;
336:     }
337: 
338: }
339: 
mini-config API documentation generated by ApiGen