Completed
Push — master ( 74281d...6be5c0 )
by Théo
02:25
created

functions.php ➔ deep_clone()   A

Complexity

Conditions 4
Paths 3

Size

Total Lines 12
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

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