Completed
Push — master ( 5e59d9...c7bab4 )
by Théo
06:51 queued 10s
created

functions.php ➔ iterables_to_iterator()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 17
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 10
nc 4
nop 1
dl 0
loc 17
rs 9.2
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of the humbug/php-scoper package.
7
 *
8
 * Copyright (c) 2017 Théo FIDRY <[email protected]>,
9
 *                    Pádraic Brady <[email protected]>
10
 *
11
 * For the full copyright and license information, please view the LICENSE
12
 * file that was distributed with this source code.
13
 */
14
15
namespace Humbug\PhpScoper;
16
17
use Humbug\PhpScoper\Console\Application;
18
use Humbug\PhpScoper\Console\Command\AddPrefixCommand;
19
use Humbug\PhpScoper\Console\Command\InitCommand;
20
use Humbug\PhpScoper\Console\Command\SelfUpdateCommand;
21
use Humbug\PhpScoper\Scoper\Composer\InstalledPackagesScoper;
22
use Humbug\PhpScoper\Scoper\Composer\JsonFileScoper;
23
use Humbug\PhpScoper\Scoper\NullScoper;
24
use Humbug\PhpScoper\Scoper\PatchScoper;
25
use Humbug\PhpScoper\Scoper\PhpScoper;
26
use Humbug\PhpScoper\Scoper\TraverserFactory;
27
use Humbug\SelfUpdate\Exception\RuntimeException as SelfUpdateRuntimeException;
28
use Humbug\SelfUpdate\Updater;
29
use Iterator;
30
use PackageVersions\Versions;
31
use PhpParser\Node;
32
use PhpParser\Parser;
33
use PhpParser\ParserFactory;
34
use Roave\BetterReflection\Reflector\ClassReflector;
35
use Roave\BetterReflection\Reflector\FunctionReflector;
36
use Roave\BetterReflection\SourceLocator\Ast\Locator;
37
use Roave\BetterReflection\SourceLocator\Type\MemoizingSourceLocator;
38
use Roave\BetterReflection\SourceLocator\Type\PhpInternalSourceLocator;
39
use Symfony\Component\Console\Application as SymfonyApplication;
40
use Symfony\Component\Filesystem\Filesystem;
41
42
// TODO: register this file to the list of functions if possible to be autoloaded
43
44
/**
45
 * @private
46
 */
47
function create_application(): SymfonyApplication
48
{
49
    $app = new Application('PHP Scoper', get_version());
50
51
    $app->addCommands([
52
        new AddPrefixCommand(
53
            new Filesystem(),
54
            create_scoper()
55
        ),
56
        new InitCommand(),
57
    ]);
58
59
    if ('phar:' === substr(__FILE__, 0, 5)) {
60
        try {
61
            $updater = new Updater();
62
        } catch (SelfUpdateRuntimeException $e) {
63
            /* Allow E2E testing of unsigned phar */
64
            $updater = new Updater(null, false);
65
        }
66
        $app->add(
67
            new SelfUpdateCommand(
68
                $updater
69
            )
70
        );
71
    }
72
73
    return $app;
74
}
75
76
/**
77
 * @private
78
 */
79
function get_version(): string
80
{
81
    $rawVersion = Versions::getVersion('humbug/php-scoper');
82
83
    list($prettyVersion, $commitHash) = explode('@', $rawVersion);
84
85
    return (1 === preg_match('/9{7}/', $prettyVersion)) ? $commitHash : $prettyVersion;
86
}
87
88
/**
89
 * @private
90
 */
91
function create_scoper(): Scoper
92
{
93
    return new PatchScoper(
94
        new PhpScoper(
95
            create_parser(),
96
            new JsonFileScoper(
97
                new InstalledPackagesScoper(
98
                    new NullScoper()
99
                )
100
            ),
101
            new TraverserFactory(create_reflector())
102
        )
103
    );
104
}
105
106
/**
107
 * @private
108
 */
109
function create_parser(): Parser
110
{
111
    return (new ParserFactory())->create(ParserFactory::ONLY_PHP7);
112
}
113
114
function create_reflector(): Reflector
115
{
116
    $phpParser = create_parser();
117
    $astLocator = new Locator($phpParser);
118
119
    $sourceLocator = new MemoizingSourceLocator(
120
        new PhpInternalSourceLocator($astLocator)
121
    );
122
    $classReflector = new ClassReflector($sourceLocator);
123
124
    return new Reflector(
125
        $classReflector,
126
        new FunctionReflector($sourceLocator, $classReflector)
127
    );
128
}
129
130
/**
131
 * @param string[] $paths Absolute paths
132
 *
133
 * @return string
134
 */
135
function get_common_path(array $paths): string
136
{
137
    if (0 === count($paths)) {
138
        return '';
139
    }
140
141
    $lastOffset = 1;
142
    $common = DIRECTORY_SEPARATOR;
143
144
    while (false !== ($index = strpos($paths[0], DIRECTORY_SEPARATOR, $lastOffset))) {
145
        $dirLen = $index - $lastOffset + 1;
146
        $dir = substr($paths[0], $lastOffset, $dirLen);
147
148
        foreach ($paths as $path) {
149
            if (substr($path, $lastOffset, $dirLen) !== $dir) {
150 View Code Duplication
                if (0 < strlen($common) && DIRECTORY_SEPARATOR === $common[strlen($common) - 1]) {
151
                    $common = substr($common, 0, strlen($common) - 1);
152
                }
153
154
                return $common;
155
            }
156
        }
157
158
        $common .= $dir;
159
        $lastOffset = $index + 1;
160
    }
161
162
    $common = substr($common, 0, -1);
163
164 View Code Duplication
    if (0 < strlen($common) && DIRECTORY_SEPARATOR === $common[strlen($common) - 1]) {
165
        $common = substr($common, 0, strlen($common) - 1);
166
    }
167
168
    return $common;
169
}
170
171
/**
172
 * In-house clone functions. Does a partial clone that should be enough to provide the immutability required in some
173
 * places for the scoper. It however does not guarantee a deep cloning as would be horribly slow for no good reasons.
174
 * A better alternative would be to find a way to push immutability upstream in PHP-Parser directly.
175
 *
176
 * @param Node $node
177
 *
178
 * @return Node
179
 */
180
function clone_node(Node $node): Node
181
{
182
    $clone = deep_clone($node);
183
184
    foreach ($node->getAttributes() as $key => $attribute) {
185
        $clone->setAttribute($key, $attribute);
186
    }
187
188
    return $clone;
189
}
190
191
/**
192
 * @param mixed $node
193
 *
194
 * @return mixed
195
 *
196
 * @internal
197
 */
198
function deep_clone($node)
199
{
200
    if (is_array($node)) {
201
        return array_map(__FUNCTION__, $node);
202
    }
203
204
    if (null === $node || is_scalar($node)) {
205
        return $node;
206
    }
207
208
    return unserialize(serialize($node));
209
}
210
211
function chain(iterable ...$iterables): Iterator
212
{
213
    foreach ($iterables as $iterable) {
214
        foreach ($iterable as $key => $value) {
215
            yield $key => $value;
216
        }
217
    }
218
}
219