1: <?php
2:
3: namespace Guzzle\Service;
4:
5: use Guzzle\Common\Exception\InvalidArgumentException;
6: use Guzzle\Common\Exception\RuntimeException;
7:
8: 9: 10:
11: abstract class AbstractConfigLoader implements ConfigLoaderInterface
12: {
13: 14: 15:
16: protected $aliases = array();
17:
18: 19: 20:
21: protected $loadedFiles = array();
22:
23: 24: 25:
26: public function load($config, array $options = array())
27: {
28:
29: $this->loadedFiles = array();
30:
31: if (is_string($config)) {
32: $config = $this->loadFile($config);
33: } elseif (!is_array($config)) {
34: throw new InvalidArgumentException('Unknown type passed to configuration loader: ' . gettype($config));
35: } else {
36: $this->mergeIncludes($config);
37: }
38:
39: return $this->build($config, $options);
40: }
41:
42: 43: 44: 45: 46: 47: 48: 49:
50: public function addAlias($filename, $alias)
51: {
52: $this->aliases[$filename] = $alias;
53:
54: return $this;
55: }
56:
57: 58: 59: 60: 61: 62: 63:
64: public function removeAlias($alias)
65: {
66: unset($this->aliases[$alias]);
67:
68: return $this;
69: }
70:
71: 72: 73: 74: 75: 76: 77: 78:
79: protected abstract function build($config, array $options);
80:
81: 82: 83: 84: 85: 86: 87: 88: 89:
90: protected function loadFile($filename)
91: {
92: if (isset($this->aliases[$filename])) {
93: $filename = $this->aliases[$filename];
94: }
95:
96: switch (pathinfo($filename, PATHINFO_EXTENSION)) {
97: case 'js':
98: case 'json':
99: $level = error_reporting(0);
100: $json = file_get_contents($filename);
101: error_reporting($level);
102:
103: if ($json === false) {
104: $err = error_get_last();
105: throw new InvalidArgumentException("Unable to open {$filename}: " . $err['message']);
106: }
107:
108: $config = json_decode($json, true);
109:
110: if ($error = json_last_error()) {
111: throw new RuntimeException("Error loading JSON data from {$filename}: {$error}");
112: }
113: break;
114: case 'php':
115: if (!is_readable($filename)) {
116: throw new InvalidArgumentException("Unable to open {$filename} for reading");
117: }
118: $config = require $filename;
119: if (!is_array($config)) {
120: throw new InvalidArgumentException('PHP files must return an array of configuration data');
121: }
122: break;
123: default:
124: throw new InvalidArgumentException('Unknown file extension: ' . $filename);
125: }
126:
127:
128: $this->loadedFiles[$filename] = true;
129:
130:
131: $this->mergeIncludes($config, dirname($filename));
132:
133: return $config;
134: }
135:
136: 137: 138: 139: 140: 141: 142: 143:
144: protected function mergeIncludes(&$config, $basePath = null)
145: {
146: if (!empty($config['includes'])) {
147: foreach ($config['includes'] as &$path) {
148:
149: if ($path[0] != DIRECTORY_SEPARATOR && !isset($this->aliases[$path]) && $basePath) {
150: $path = "{$basePath}/{$path}";
151: }
152:
153: if (!isset($this->loadedFiles[$path])) {
154: $this->loadedFiles[$path] = true;
155: $config = $this->mergeData($this->loadFile($path), $config);
156: }
157: }
158: }
159: }
160:
161: 162: 163: 164: 165: 166: 167: 168:
169: protected function mergeData(array $a, array $b)
170: {
171: return array_merge_recursive($a, $b);
172: }
173: }
174: