Completed
Push — master ( a18f70...f9f508 )
by Théo
03:58 queued 01:19
created

functions.php ➔ create_application()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 14
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 8
nc 1
nop 0
dl 0
loc 14
rs 9.4285
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\PhpParser\TraverserFactory;
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 Iterator;
27
use PackageVersions\Versions;
28
use PhpParser\Node;
29
use PhpParser\Parser;
30
use PhpParser\ParserFactory;
31
use Roave\BetterReflection\Reflector\ClassReflector;
32
use Roave\BetterReflection\Reflector\FunctionReflector;
33
use Roave\BetterReflection\SourceLocator\Ast\Locator;
34
use Roave\BetterReflection\SourceLocator\Type\MemoizingSourceLocator;
35
use Roave\BetterReflection\SourceLocator\Type\PhpInternalSourceLocator;
36
use Symfony\Component\Console\Application as SymfonyApplication;
37
use Symfony\Component\Filesystem\Filesystem;
38
39
// TODO: register this file to the list of functions if possible to be autoloaded
40
41
/**
42
 * @private
43
 */
44
function create_application(): SymfonyApplication
45
{
46
    $app = new Application('PHP Scoper', get_version());
47
48
    $app->addCommands([
49
        new AddPrefixCommand(
50
            new Filesystem(),
51
            create_scoper()
52
        ),
53
        new InitCommand(),
54
    ]);
55
56
    return $app;
57
}
58
59
/**
60
 * @private
61
 */
62
function get_version(): string
63
{
64
    $rawVersion = Versions::getVersion('humbug/php-scoper');
65
66
    list($prettyVersion, $commitHash) = explode('@', $rawVersion);
67
68
    return (1 === preg_match('/9{7}/', $prettyVersion)) ? $commitHash : $prettyVersion;
69
}
70
71
/**
72
 * @private
73
 */
74
function create_scoper(): Scoper
75
{
76
    return new PatchScoper(
77
        new PhpScoper(
78
            create_parser(),
79
            new JsonFileScoper(
80
                new InstalledPackagesScoper(
81
                    new NullScoper()
82
                )
83
            ),
84
            new TraverserFactory(create_reflector())
85
        )
86
    );
87
}
88
89
/**
90
 * @private
91
 */
92
function create_parser(): Parser
93
{
94
    return (new ParserFactory())->create(ParserFactory::ONLY_PHP7);
95
}
96
97
function create_reflector(): Reflector
98
{
99
    $phpParser = create_parser();
100
    $astLocator = new Locator($phpParser);
101
102
    $sourceLocator = new MemoizingSourceLocator(
103
        new PhpInternalSourceLocator($astLocator)
104
    );
105
    $classReflector = new ClassReflector($sourceLocator);
106
107
    return new Reflector(
108
        $classReflector,
109
        new FunctionReflector($sourceLocator, $classReflector)
110
    );
111
}
112
113
/**
114
 * @param string[] $paths Absolute paths
115
 *
116
 * @return string
117
 */
118
function get_common_path(array $paths): string
119
{
120
    if (0 === count($paths)) {
121
        return '';
122
    }
123
124
    $lastOffset = 1;
125
    $common = DIRECTORY_SEPARATOR;
126
127
    while (false !== ($index = strpos($paths[0], DIRECTORY_SEPARATOR, $lastOffset))) {
128
        $dirLen = $index - $lastOffset + 1;
129
        $dir = substr($paths[0], $lastOffset, $dirLen);
130
131
        foreach ($paths as $path) {
132
            if (substr($path, $lastOffset, $dirLen) !== $dir) {
133 View Code Duplication
                if (0 < strlen($common) && DIRECTORY_SEPARATOR === $common[strlen($common) - 1]) {
134
                    $common = substr($common, 0, strlen($common) - 1);
135
                }
136
137
                return $common;
138
            }
139
        }
140
141
        $common .= $dir;
142
        $lastOffset = $index + 1;
143
    }
144
145
    $common = substr($common, 0, -1);
146
147 View Code Duplication
    if (0 < strlen($common) && DIRECTORY_SEPARATOR === $common[strlen($common) - 1]) {
148
        $common = substr($common, 0, strlen($common) - 1);
149
    }
150
151
    return $common;
152
}
153
154
/**
155
 * In-house clone functions. Does a partial clone that should be enough to provide the immutability required in some
156
 * places for the scoper. It however does not guarantee a deep cloning as would be horribly slow for no good reasons.
157
 * A better alternative would be to find a way to push immutability upstream in PHP-Parser directly.
158
 *
159
 * @param Node $node
160
 *
161
 * @return Node
162
 */
163
function clone_node(Node $node): Node
164
{
165
    $clone = deep_clone($node);
166
167
    foreach ($node->getAttributes() as $key => $attribute) {
168
        $clone->setAttribute($key, $attribute);
169
    }
170
171
    return $clone;
172
}
173
174
/**
175
 * @param mixed $node
176
 *
177
 * @return mixed
178
 *
179
 * @internal
180
 */
181
function deep_clone($node)
182
{
183
    if (is_array($node)) {
184
        return array_map(__FUNCTION__, $node);
185
    }
186
187
    if (null === $node || is_scalar($node)) {
188
        return $node;
189
    }
190
191
    return unserialize(serialize($node));
192
}
193
194
function chain(iterable ...$iterables): Iterator
195
{
196
    foreach ($iterables as $iterable) {
197
        foreach ($iterable as $key => $value) {
198
            yield $key => $value;
199
        }
200
    }
201
}
202