Completed
Push — master ( fec521...a1295e )
by Pierre
17s queued 10s
created

Package::extConfigIsIn()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 8
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 3

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 5
c 1
b 0
f 0
dl 0
loc 8
rs 10
ccs 4
cts 4
cp 1
cc 3
nc 3
nop 1
crap 3
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 Pickle\Base\Abstracts;
40
use Pickle\Base\Util\GitIgnore;
41
42
class Package extends Abstracts\Package implements \Pickle\Base\Interfaces\Package
43
{
44
    /**
45
     * @var string Package's root directory
46
     */
47
    protected $path;
48
49
    /**
50
     * Get the package's root directory.
51
     *
52
     * @return string
53
     */
54
    public function getRootDir()
55
    {
56 1
        return $this->path;
57
    }
58
59
    /**
60
     * Get the package's root directory.
61
     *
62
     * @return string
63
     */
64
    public function getSourceDir()
65
    {
66 1
        $path = $this->getRootDir();
67 1
        $release = $path.DIRECTORY_SEPARATOR.$this->getPrettyName().'-'.$this->getPrettyVersion();
68
69 1
        if (is_dir($release)) {
70 1
            $path = $release;
71
        }
72
73
        /* Do subdir search */
74 1
        if (!$this->extConfigIsIn($path)) {
75 1
            $path = $this->locateSourceDirByExtConfig($path);
76
77 1
            if (null === $path) {
78
                throw new \Exception('config*.(m4|w32) not found');
79
            }
80
        }
81
82 1
        return $path;
83
    }
84
85
    /**
86
     * Set the package's source directory, containing config.m4/config.w32.
87
     *
88
     * @param string $path
89
     */
90
    public function setRootDir($path)
91
    {
92 1
        $this->path = $path;
93 1
    }
94
95
    public function setStability($stability)
96
    {
97
        $this->stability = $stability;
98
    }
99
100
    /**
101
     * @return array
102
     */
103
    public function getConfigureOptions()
104
    {
105 1
        $options = [];
106
107 1
        if (defined('PHP_WINDOWS_VERSION_MAJOR')) {
108 1
            $config_file = $this->getSourceDir().'/config.w32';
109
110 1
            if (!file_exists($config_file)) {
111
                throw new \Exception('cnofig.w32 not found');
112
            }
113
114 1
            $config = file_get_contents($config_file);
115
116 1
            $options = array_merge(
117 1
                $this->fetchArgWindows('ARG_WITH', $config),
118 1
                $this->fetchArgWindows('ARG_ENABLE', $config)
119
            );
120
        } else {
121 1
            $configs = glob($this->getSourceDir().'/'.'config*.m4');
122
123 1
            if (!empty($configs)) {
124 1
                foreach ($configs as $config) {
125 1
                    $options = array_merge($options, $this->getConfigureOptionsFromFile($config));
126
                }
127
            }
128
        }
129
130 1
        return $options;
131
    }
132
133
    public function getConfigureOptionsFromFile($file)
134
    {
135 1
        $config = file_get_contents($file);
136
137 1
        return array_merge(
138 1
            $this->fetchArg('PHP_ARG_WITH', $config),
139 1
            $this->fetchArgAc('AC_ARG_WITH', $config),
140 1
            $this->fetchArg('PHP_ARG_ENABLE', $config),
141 1
            $this->fetchArgAc('AC_ARG_ENABLE', $config)
142
        );
143
    }
144
145
    /**
146
     * @param string $which
147
     * @param string $config
148
     *
149
     * @return array
150
     */
151
    protected function fetchArgWindows($which, $config)
152
    {
153 1
        $next = 0;
154 1
        $options = [];
155 1
        $type = false !== strpos($which, 'ENABLE') ? 'enable' : 'with';
156 1
        while (false !== ($s = strpos($config, $which, $next))) {
157 1
            $s = strpos($config, '(', $s);
158 1
            $e = strpos($config, ')', $s + 1);
159 1
            $option = substr($config, $s + 1, $e - $s);
160
161 1
            $elems = explode(',', $option);
162 1
            array_walk($elems, function (&$a) {
163 1
                $a = str_replace([')', "'"], ['', ''], $a);
164 1
                $a = trim($a);
165 1
            });
166
167 1
            @list($name, $prompt, $default) = $elems;
168 1
            $name = str_replace('"', '', $name);
169
            $options[$name] = (object) [
170 1
                'prompt' => $prompt,
171 1
                'type' => $type,
172 1
                'default' => $default,
173
            ];
174 1
            $next = $e + 1;
175
        }
176
177 1
        return $options;
178
    }
179
180
    protected function isWithOrEnable($option, $type) {
181 1
        if ('enable' == $type) {
182 1
            $default = (false !== strpos($option, '-disable-')) ? true : false;
183 1
        } elseif ('with' == $type) {
184 1
            $default = (false !== strpos($option, '-without-')) ? true : false;
185
        }
186 1
        return $default;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $default does not seem to be defined for all execution paths leading up to this point.
Loading history...
187
    }
188
189
    /**
190
     * @param string $which
191
     * @param string $config
192
     *
193
     * @return array
194
     */
195
    protected function fetchArgAc($which, $config)
196
    {
197 1
        $next = 0;
198 1
        $options = [];
199 1
        $type = false !== strpos($which, 'ENABLE') ? 'enable' : 'with';
200 1
        while (false !== ($s = strpos($config, $which, $next))) {
201 1
            $default = true;
0 ignored issues
show
Unused Code introduced by
The assignment to $default is dead and can be removed.
Loading history...
202 1
            $s = strpos($config, '(', $s);
203 1
            $e = strpos($config, ')', $s + 1);
204 1
            $option = substr($config, $s + 1, $e - $s);
205
206
207 1
            $default = $this->isWithOrEnable($option, $type);
208 1
            list($name, $desc) = explode(',', $option);
209
210 1
            $desc = preg_replace('/\s+/', ' ', trim($desc));
211 1
            $desc = trim(substr($desc, 1, strlen($desc) - 2));
212 1
            $s_a = strpos($desc, ' ');
213 1
            $desc = trim(substr($desc, $s_a));
214
215
            $options[$name] = (object) [
216 1
                'prompt' => $desc,
217 1
                'type' => $type,
218 1
                'default' => $default,
219
            ];
220
221 1
            $next = $e + 1;
222
        }
223
224 1
        return $options;
225
    }
226
227
    /**
228
     * @param string $which
229
     * @param string $config
230
     *
231
     * @return array
232
     */
233
    protected function fetchArg($which, $config)
234
    {
235 1
        $next = 0;
236 1
        $options = [];
237
238 1
        $type = false !== strpos($which, 'ENABLE') ? 'enable' : 'with';
239 1
        while (false !== ($s = strpos($config, $which, $next))) {
240 1
            $default = 'y';
0 ignored issues
show
Unused Code introduced by
The assignment to $default is dead and can be removed.
Loading history...
241 1
            $s = strpos($config, '(', $s);
242 1
            $e = strpos($config, ')', $s + 1);
243 1
            $option = substr($config, $s + 1, $e - $s);
244
245 1
            list($name, $desc) = explode(',', $option);
246
247
            /* Description can be part of the 3rd argument */
248 1
            if (empty($desc) || $desc === '[]') {
249 1
                list($name, , $desc) = explode(',', $option);
250 1
                $desc = preg_replace('/\s+/', ' ', trim($desc));
251 1
                $desc = trim(substr($desc, 1, strlen($desc) - 2));
252 1
                $desc = trim(str_replace(['[', ']'], ['', ''], $desc));
253 1
                $s_a = strpos($desc, ' ');
254 1
                $desc = trim(substr($desc, $s_a));
255
            }
256
257 1
            $default = $this->isWithOrEnable($option, $type);
258 1
            $name = str_replace(['[', ']'], ['', ''], $name);
259
            $options[$name] = (object) [
260 1
                'prompt' => trim($desc),
261 1
                'type' => $type,
262 1
                'default' => $default,
263
            ];
264 1
            $next = $e + 1;
265
        }
266
267 1
        return $options;
268
    }
269
270
    /**
271
     * Get files, will not return gitignore files.
272
     *
273
     * @return \CallbackFilterIterator
274
     */
275
    public function getFiles()
276
    {
277
        return new \CallbackFilterIterator(
278
            new \RecursiveIteratorIterator(
279
                new \RecursiveDirectoryIterator($this->getSourceDir())
280
            ),
281
            new GitIgnore($this)
282
        );
283
    }
284
285
    public function getVersionFromHeader()
286
    {
287
        $headers = glob($this->path.DIRECTORY_SEPARATOR.'*.h');
288
        $version_define = 'PHP_'.strtoupper($this->getSimpleName()).'_VERSION';
289
        foreach ($headers as $header) {
290
            $contents = @file_get_contents($header);
291
            if (!$contents) {
292
                throw new \Exception("Cannot read header <$header>");
293
            }
294
            $pos_version = strpos($contents, $version_define);
295
            if ($pos_version !== false) {
296
                $nl = strpos($contents, "\n", $pos_version);
297
                $version_line = trim(substr($contents, $pos_version, $nl - $pos_version));
298
                list($version_define, $version) = explode(' ', $version_line);
299
                $version = trim(str_replace('"', '', $version));
300
                break;
301
            }
302
        }
303
        if (empty($version)) {
304
            throw new \Exception('No '.$version_define.' can be found');
305
        }
306
307
        return [trim($version_define), $version];
308
    }
309
310
    protected function extConfigIsIn($path)
311
    {
312 1
        if (defined('PHP_WINDOWS_VERSION_MAJOR') !== false) {
313 1
            return file_exists(realpath($path).DIRECTORY_SEPARATOR.'config.w32');
314
        } else {
315 1
            $r = glob("$path/config*.m4");
316
317 1
            return is_array($r) && !empty($r);
318
        }
319
    }
320
321
    protected function locateSourceDirByExtConfig($path)
322
    {
323 1
        $it = new \RecursiveIteratorIterator(
324 1
        new \RecursiveDirectoryIterator($path),
325 1
        \RecursiveIteratorIterator::SELF_FIRST
326
    );
327
328 1
        foreach ($it as $fl_obj) {
329 1
            if ($fl_obj->isFile() && preg_match(',config*.(m4|w32),', $fl_obj->getBasename())) {
330 1
                return $fl_obj->getPath();
331
            }
332
        }
333
334
        return;
335
    }
336
}
337
338
/* vim: set tabstop=4 shiftwidth=4 expandtab: fdm=marker */
339