1 <?php
2
3 4 5 6 7 8 9 10
11
12 namespace ICanBoogie\AutoConfig;
13
14 use Composer\Util\Filesystem;
15 use Composer\Json\JsonFile;
16
17 class Config implements \IteratorAggregate
18 {
19 protected $pathname;
20 protected $filesystem;
21 protected $fragments = [];
22 protected $weights = [];
23 protected $validator;
24
25 public function __construct($pathname)
26 {
27 $this->pathname = $pathname;
28 $this->filesystem = new Filesystem;
29 $this->validator = new ConfigValidator;
30 }
31
32 public function add_fragment($path, $weight)
33 {
34 $pathname = $path . DIRECTORY_SEPARATOR . 'icanboogie.json';
35 $json = new JsonFile($pathname);
36
37 if (!$json->exists())
38 {
39 return;
40 }
41
42 $this->validator->validate($pathname);
43
44 $this->fragments[$path] = $json->read();
45 $this->weights[$path] = $weight;
46 }
47
48 public function synthesize(Filesystem $filesystem=null)
49 {
50 if (!$filesystem)
51 {
52 $filesystem = $this->filesystem;
53 }
54
55 $config = [
56
57 'config-constructor' => [],
58 'config-path' => [],
59 'locale-path' => [],
60 'module-path' => []
61 ];
62
63 foreach ($this as $path => $fragment)
64 {
65 foreach ($fragment as $key => $value)
66 {
67 switch ($key)
68 {
69 case 'config-constructor':
70
71 $config[$key] = array_merge($config[$key], $value);
72
73 break;
74
75 case 'config-path':
76
77 foreach ((array) $value as $v)
78 {
79 $config[$key][] = [
80
81 $filesystem->findShortestPathCode($this->pathname, "$path/$v"),
82 $this->weights[$path]
83
84 ];
85 }
86
87 break;
88
89 case 'locale-path':
90 case 'module-path':
91
92 foreach ((array) $value as $v)
93 {
94 $config[$key][] = $filesystem->findShortestPathCode($this->pathname, "$path/$v");
95 }
96
97 break;
98 }
99 }
100 }
101
102 return $config;
103 }
104
105 public function getIterator()
106 {
107 return new \ArrayIterator($this->fragments);
108 }
109
110 public function render($synthesized_config=null)
111 {
112 if (!$synthesized_config)
113 {
114 $synthesized_config = $this->synthesize();
115 }
116
117 $class = __CLASS__;
118
119 $config_constructor = $this->render_config_constructor($synthesized_config['config-constructor']);
120 $config_path = $this->render_config_path($synthesized_config['config-path']);
121
122
123 $locale_path = implode(",\n\t\t", $synthesized_config['locale-path']);
124 $module_path = implode(",\n\t\t", $synthesized_config['module-path']);
125
126 return <<<EOT
127 <?php
128
129 // auto-config.php @generated by $class
130
131 return [
132
133 'config-constructor' => [
134
135 $config_constructor
136
137 ],
138
139 'config-path' => [
140
141 $config_path
142
143 ],
144
145 'locale-path' => [
146
147 $locale_path
148
149 ],
150
151 'module-path' => [
152
153 $module_path
154
155 ]
156 ];
157 EOT;
158 }
159
160 protected function render_config_constructor($synthesized)
161 {
162 $lines = array();
163
164 ksort($synthesized);
165
166 foreach ($synthesized as $name => $constructor)
167 {
168 list($callback, $from) = explode('#', $constructor) + [ 1 => null ];
169
170 $lines[] = "'$name' => [ '$callback'" . ($from ? ", '$from'" : '') . " ]";
171 }
172
173 return implode(",\n\t\t", $lines);
174 }
175
176 protected function render_config_path($synthesized)
177 {
178 $lines = array();
179
180 foreach ($synthesized as $data)
181 {
182 list($pathcode, $weight) = $data;
183
184 $lines[] = "[ {$pathcode}, 'weight' => {$weight} ]";
185 }
186
187 return implode(",\n\t\t", $lines);
188 }
189
190 public function write()
191 {
192 try
193 {
194 file_put_contents($this->pathname, $this->render());
195
196 echo "Created auto-config in {$this->pathname}\n";
197 }
198 catch (\Exception $e)
199 {
200 echo $e;
201
202 throw $e;
203 }
204 }
205 }