1 | <?php |
||
2 | |||
3 | /* |
||
4 | * Pickle |
||
5 | * |
||
6 | * |
||
7 | * @license |
||
8 | * |
||
9 | * New BSD License |
||
10 | * |
||
11 | * Copyright © 2015-2015, Pickle community. All rights reserved. |
||
12 | * |
||
13 | * Redistribution and use in source and binary forms, with or without |
||
14 | * modification, are permitted provided that the following conditions are met: |
||
15 | * * Redistributions of source code must retain the above copyright |
||
16 | * notice, this list of conditions and the following disclaimer. |
||
17 | * * Redistributions in binary form must reproduce the above copyright |
||
18 | * notice, this list of conditions and the following disclaimer in the |
||
19 | * documentation and/or other materials provided with the distribution. |
||
20 | * * Neither the name of the Hoa nor the names of its contributors may be |
||
21 | * used to endorse or promote products derived from this software without |
||
22 | * specific prior written permission. |
||
23 | * |
||
24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
||
25 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
||
26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
||
27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND CONTRIBUTORS BE |
||
28 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
||
29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
||
30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
||
31 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
||
32 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
||
33 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
||
34 | * POSSIBILITY OF SUCH DAMAGE. |
||
35 | */ |
||
36 | |||
37 | namespace Pickle\Package\PHP; |
||
38 | |||
39 | use CallbackFilterIterator; |
||
40 | use Exception; |
||
41 | use Pickle\Base\Abstracts; |
||
42 | use Pickle\Base\Util\GitIgnore; |
||
43 | use RecursiveDirectoryIterator; |
||
44 | use RecursiveIteratorIterator; |
||
45 | |||
46 | class Package extends Abstracts\Package implements \Pickle\Base\Interfaces\Package |
||
47 | { |
||
48 | /** |
||
49 | * @var string Package's root directory |
||
50 | */ |
||
51 | protected $path; |
||
52 | |||
53 | /** |
||
54 | * Get the package's root directory. |
||
55 | * |
||
56 | * @return string |
||
57 | */ |
||
58 | public function getRootDir() |
||
59 | { |
||
60 | 1 | return $this->path; |
|
61 | } |
||
62 | |||
63 | /** |
||
64 | * Get the package's root directory. |
||
65 | * |
||
66 | * @return string |
||
67 | */ |
||
68 | public function getSourceDir() |
||
69 | { |
||
70 | 1 | $path = $this->getRootDir(); |
|
71 | 1 | $release = $path . DIRECTORY_SEPARATOR . $this->getPrettyName() . '-' . $this->getPrettyVersion(); |
|
72 | |||
73 | 1 | if (is_dir($release)) { |
|
74 | 1 | $path = $release; |
|
75 | } |
||
76 | |||
77 | /* Do subdir search */ |
||
78 | 1 | if (!$this->extConfigIsIn($path)) { |
|
79 | 1 | $path = $this->locateSourceDirByExtConfig($path); |
|
80 | |||
81 | 1 | if ($path === null) { |
|
82 | throw new Exception('config*.(m4|w32) not found'); |
||
83 | } |
||
84 | } |
||
85 | |||
86 | 1 | return $path; |
|
87 | } |
||
88 | |||
89 | /** |
||
90 | * Set the package's source directory, containing config.m4/config.w32. |
||
91 | * |
||
92 | * @param string $path |
||
93 | */ |
||
94 | public function setRootDir($path) |
||
95 | { |
||
96 | 1 | $this->path = $path; |
|
97 | 1 | } |
|
98 | |||
99 | public function setStability($stability) |
||
100 | { |
||
101 | $this->stability = $stability; |
||
102 | } |
||
103 | |||
104 | /** |
||
105 | * @return array |
||
106 | */ |
||
107 | public function getConfigureOptions() |
||
108 | { |
||
109 | 1 | $options = []; |
|
110 | |||
111 | 1 | if (defined('PHP_WINDOWS_VERSION_MAJOR')) { |
|
112 | 1 | $config_file = $this->getSourceDir() . '/config.w32'; |
|
113 | |||
114 | 1 | if (!file_exists($config_file)) { |
|
115 | throw new Exception('cnofig.w32 not found'); |
||
116 | } |
||
117 | |||
118 | 1 | $config = file_get_contents($config_file); |
|
119 | |||
120 | 1 | $options = array_merge( |
|
121 | 1 | $this->fetchArgWindows('ARG_WITH', $config), |
|
122 | 1 | $this->fetchArgWindows('ARG_ENABLE', $config) |
|
123 | ); |
||
124 | } else { |
||
125 | 1 | $configs = glob($this->getSourceDir() . '/' . 'config*.m4'); |
|
126 | |||
127 | 1 | if (!empty($configs)) { |
|
128 | 1 | foreach ($configs as $config) { |
|
129 | 1 | $options = array_merge($options, $this->getConfigureOptionsFromFile($config)); |
|
130 | } |
||
131 | } |
||
132 | } |
||
133 | |||
134 | 1 | return $options; |
|
135 | } |
||
136 | |||
137 | public function getConfigureOptionsFromFile($file) |
||
138 | { |
||
139 | 1 | $config = file_get_contents($file); |
|
140 | |||
141 | 1 | return array_merge( |
|
142 | 1 | $this->fetchArg('PHP_ARG_WITH', $config), |
|
143 | 1 | $this->fetchArgAc('AC_ARG_WITH', $config), |
|
144 | 1 | $this->fetchArg('PHP_ARG_ENABLE', $config), |
|
145 | 1 | $this->fetchArgAc('AC_ARG_ENABLE', $config) |
|
146 | ); |
||
147 | } |
||
148 | |||
149 | /** |
||
150 | * Get files, will not return gitignore files. |
||
151 | * |
||
152 | * @return CallbackFilterIterator |
||
153 | */ |
||
154 | public function getFiles() |
||
155 | { |
||
156 | return new CallbackFilterIterator( |
||
157 | new RecursiveIteratorIterator( |
||
158 | new RecursiveDirectoryIterator($this->getSourceDir()) |
||
159 | ), |
||
160 | new GitIgnore($this) |
||
161 | ); |
||
162 | } |
||
163 | |||
164 | public function getVersionFromHeader() |
||
165 | { |
||
166 | $headers = glob($this->path . DIRECTORY_SEPARATOR . '*.h'); |
||
167 | $version_define = 'PHP_' . strtoupper($this->getSimpleName()) . '_VERSION'; |
||
168 | foreach ($headers as $header) { |
||
169 | $contents = @file_get_contents($header); |
||
170 | if (!$contents) { |
||
171 | throw new Exception("Cannot read header <{$header}>"); |
||
172 | } |
||
173 | $pos_version = strpos($contents, $version_define); |
||
174 | if ($pos_version !== false) { |
||
175 | $nl = strpos($contents, "\n", $pos_version); |
||
176 | $version_line = trim(substr($contents, $pos_version, $nl - $pos_version)); |
||
177 | [$version_define, $version] = explode(' ', $version_line); |
||
178 | $version = trim(str_replace('"', '', $version)); |
||
179 | break; |
||
180 | } |
||
181 | } |
||
182 | if (empty($version)) { |
||
183 | throw new Exception('No ' . $version_define . ' can be found'); |
||
184 | } |
||
185 | |||
186 | return [trim($version_define), $version]; |
||
187 | } |
||
188 | |||
189 | /** |
||
190 | * @param string $which |
||
191 | * @param string $config |
||
192 | * |
||
193 | * @return array |
||
194 | */ |
||
195 | protected function fetchArgWindows($which, $config) |
||
196 | { |
||
197 | 1 | $next = 0; |
|
198 | 1 | $options = []; |
|
199 | 1 | $type = strpos($which, 'ENABLE') !== false ? 'enable' : 'with'; |
|
200 | 1 | while (false !== ($s = strpos($config, $which, $next))) { |
|
201 | 1 | $s = strpos($config, '(', $s); |
|
202 | 1 | $e = strpos($config, ')', $s + 1); |
|
203 | 1 | $option = substr($config, $s + 1, $e - $s); |
|
204 | |||
205 | 1 | $elems = explode(',', $option); |
|
206 | 1 | array_walk($elems, function (&$a) { |
|
207 | 1 | $a = str_replace([')', "'"], ['', ''], $a); |
|
208 | 1 | $a = trim($a); |
|
209 | 1 | }); |
|
210 | |||
211 | 1 | @[$name, $prompt, $default] = $elems; |
|
212 | 1 | $name = str_replace('"', '', $name); |
|
213 | 1 | $options[$name] = (object) [ |
|
214 | 1 | 'prompt' => $prompt, |
|
215 | 1 | 'type' => $type, |
|
216 | 1 | 'default' => $default, |
|
217 | ]; |
||
218 | 1 | $next = $e + 1; |
|
219 | } |
||
220 | |||
221 | 1 | return $options; |
|
222 | } |
||
223 | |||
224 | protected function isWithOrEnable($option, $type) |
||
225 | { |
||
226 | 1 | if ($type == 'enable') { |
|
227 | 1 | $default = (strpos($option, '-disable-') !== false) ? true : false; |
|
228 | 1 | } elseif ($type == 'with') { |
|
229 | 1 | $default = (strpos($option, '-without-') !== false) ? true : false; |
|
230 | } |
||
231 | 1 | return $default; |
|
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
![]() |
|||
232 | } |
||
233 | |||
234 | /** |
||
235 | * @param string $which |
||
236 | * @param string $config |
||
237 | * |
||
238 | * @return array |
||
239 | */ |
||
240 | protected function fetchArgAc($which, $config) |
||
241 | { |
||
242 | 1 | $next = 0; |
|
243 | 1 | $options = []; |
|
244 | 1 | $type = strpos($which, 'ENABLE') !== false ? 'enable' : 'with'; |
|
245 | 1 | while (false !== ($s = strpos($config, $which, $next))) { |
|
246 | 1 | $default = true; |
|
0 ignored issues
–
show
|
|||
247 | 1 | $s = strpos($config, '(', $s); |
|
248 | 1 | $e = strpos($config, ')', $s + 1); |
|
249 | 1 | $option = substr($config, $s + 1, $e - $s); |
|
250 | |||
251 | 1 | $default = $this->isWithOrEnable($option, $type); |
|
252 | 1 | [$name, $desc] = explode(',', $option); |
|
253 | |||
254 | 1 | $desc = preg_replace('/\s+/', ' ', trim($desc)); |
|
255 | 1 | $desc = trim(substr($desc, 1, strlen($desc) - 2)); |
|
256 | 1 | $s_a = strpos($desc, ' '); |
|
257 | 1 | $desc = trim(substr($desc, $s_a)); |
|
258 | |||
259 | 1 | $options[$name] = (object) [ |
|
260 | 1 | 'prompt' => $desc, |
|
261 | 1 | 'type' => $type, |
|
262 | 1 | 'default' => $default, |
|
263 | ]; |
||
264 | |||
265 | 1 | $next = $e + 1; |
|
266 | } |
||
267 | |||
268 | 1 | return $options; |
|
269 | } |
||
270 | |||
271 | /** |
||
272 | * @param string $which |
||
273 | * @param string $config |
||
274 | * |
||
275 | * @return array |
||
276 | */ |
||
277 | protected function fetchArg($which, $config) |
||
278 | { |
||
279 | 1 | $next = 0; |
|
280 | 1 | $options = []; |
|
281 | |||
282 | 1 | $type = strpos($which, 'ENABLE') !== false ? 'enable' : 'with'; |
|
283 | 1 | while (false !== ($s = strpos($config, $which, $next))) { |
|
284 | 1 | $default = 'y'; |
|
0 ignored issues
–
show
|
|||
285 | 1 | $s = strpos($config, '(', $s); |
|
286 | 1 | $e = strpos($config, ')', $s + 1); |
|
287 | 1 | $option = substr($config, $s + 1, $e - $s); |
|
288 | |||
289 | 1 | [$name, $desc] = explode(',', $option); |
|
290 | |||
291 | /* Description can be part of the 3rd argument */ |
||
292 | 1 | if (empty($desc) || $desc === '[]') { |
|
293 | 1 | [$name, , $desc] = explode(',', $option); |
|
294 | 1 | $desc = preg_replace('/\s+/', ' ', trim($desc)); |
|
295 | 1 | $desc = trim(substr($desc, 1, strlen($desc) - 2)); |
|
296 | 1 | $desc = trim(str_replace(['[', ']'], ['', ''], $desc)); |
|
297 | 1 | $s_a = strpos($desc, ' '); |
|
298 | 1 | $desc = trim(substr($desc, $s_a)); |
|
299 | } |
||
300 | |||
301 | 1 | $default = $this->isWithOrEnable($option, $type); |
|
302 | 1 | $name = str_replace(['[', ']'], ['', ''], $name); |
|
303 | 1 | $options[$name] = (object) [ |
|
304 | 1 | 'prompt' => trim($desc), |
|
305 | 1 | 'type' => $type, |
|
306 | 1 | 'default' => $default, |
|
307 | ]; |
||
308 | 1 | $next = $e + 1; |
|
309 | } |
||
310 | |||
311 | 1 | return $options; |
|
312 | } |
||
313 | |||
314 | protected function extConfigIsIn($path) |
||
315 | { |
||
316 | 1 | if (defined('PHP_WINDOWS_VERSION_MAJOR') !== false) { |
|
317 | 1 | return file_exists(realpath($path) . DIRECTORY_SEPARATOR . 'config.w32'); |
|
318 | } |
||
319 | 1 | $r = glob("{$path}/config*.m4"); |
|
320 | |||
321 | 1 | return is_array($r) && !empty($r); |
|
322 | } |
||
323 | |||
324 | protected function locateSourceDirByExtConfig($path) |
||
325 | { |
||
326 | 1 | $it = new RecursiveIteratorIterator( |
|
327 | 1 | new RecursiveDirectoryIterator($path), |
|
328 | 1 | RecursiveIteratorIterator::SELF_FIRST |
|
329 | ); |
||
330 | |||
331 | 1 | foreach ($it as $fl_obj) { |
|
332 | 1 | if ($fl_obj->isFile() && preg_match(',config*.(m4|w32),', $fl_obj->getBasename())) { |
|
333 | 1 | return $fl_obj->getPath(); |
|
334 | } |
||
335 | } |
||
336 | } |
||
337 | } |
||
338 | |||
339 | /* vim: set tabstop=4 shiftwidth=4 expandtab: fdm=marker */ |
||
340 |