Test Setup Failed
Push — master ( 58c170...8423ed )
by Théo
02:31
created

functions.php ➔ is_stringable()   A

Complexity

Conditions 6
Paths 9

Size

Total Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

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