Completed
Push — master ( 74c262...0b4843 )
by Théo
03:38 queued 01:33
created

functions.php ➔ deep_clone()   C

Complexity

Conditions 11
Paths 10

Size

Total Lines 67
Code Lines 36

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 11
eloc 36
nc 10
nop 1
dl 0
loc 67
rs 5.8904
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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\SelfUpdateCommand;
20
use Humbug\PhpScoper\Handler\HandleAddPrefix;
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\SelfUpdate\Exception\RuntimeException as SelfUpdateRuntimeException;
27
use Humbug\SelfUpdate\Updater;
28
use PackageVersions\Versions;
29
use PhpParser\Node;
30
use PhpParser\Parser;
31
use PhpParser\ParserFactory;
32
use Symfony\Component\Console\Application as SymfonyApplication;
33
use Symfony\Component\Filesystem\Filesystem;
34
use UnexpectedValueException;
35
36
/**
37
 * @private
38
 */
39
function create_application(): SymfonyApplication
40
{
41
    $app = new Application('PHP Scoper', get_version());
42
43
    $app->addCommands([
44
        new AddPrefixCommand(
45
            new Filesystem(),
46
            new HandleAddPrefix(
47
                create_scoper()
48
            )
49
        ),
50
    ]);
51
52
    if ('phar:' === substr(__FILE__, 0, 5)) {
53
        try {
54
            $updater = new Updater();
55
        } catch (SelfUpdateRuntimeException $e) {
56
            /* Allow E2E testing of unsigned phar */
57
            $updater = new Updater(null, false);
58
        }
59
        $app->add(
60
            new SelfUpdateCommand(
61
                $updater
62
            )
63
        );
64
    }
65
66
    return $app;
67
}
68
69
/**
70
 * @private
71
 */
72
function get_version(): string
73
{
74
    if ('phar:' === substr(__FILE__, 0, 5)) {
75
        $gitVersion = '@git-version@';
76
        $semanticVersion = preg_replace(
77
            ["/\.\d\-/", "/\-/"],
78
            ['-', '-dev+'],
79
            $gitVersion,
80
            1
81
        );
82
83
        return $semanticVersion;
84
    }
85
86
    $rawVersion = Versions::getVersion('humbug/php-scoper');
87
88
    list($prettyVersion, $commitHash) = explode('@', $rawVersion);
89
90
    return (1 === preg_match('/9{7}/', $prettyVersion)) ? $commitHash : $prettyVersion;
91
}
92
93
/**
94
 * @private
95
 */
96
function create_scoper(): Scoper
97
{
98
    return new PatchScoper(
99
        new JsonFileScoper(
100
            new InstalledPackagesScoper(
101
                new PhpScoper(
102
                    create_parser(),
103
                    new NullScoper()
104
                )
105
            )
106
        )
107
    );
108
}
109
110
/**
111
 * @private
112
 */
113
function create_parser(): Parser
114
{
115
    return (new ParserFactory())->create(ParserFactory::ONLY_PHP7);
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
    if ($node instanceof Node\Stmt\Namespace_) {
197
        return new Node\Stmt\Namespace_(
198
            deep_clone($node->name)
199
        );
200
    }
201
202
    if ($node instanceof Node\Name\Relative) {
203
        return new Node\Name\Relative(
204
            deep_clone($node->toString())
205
        );
206
    }
207
208
    if ($node instanceof Node\Name\FullyQualified) {
209
        return new Node\Name\FullyQualified(
210
            deep_clone($node->toString())
211
        );
212
    }
213
214
    if ($node instanceof Node\Name) {
215
        return new Node\Name(
216
            deep_clone($node->toString())
217
        );
218
    }
219
220
    if ($node instanceof Node\Stmt\Use_) {
221
        return new Node\Stmt\Use_(
222
            deep_clone($node->uses),
223
            $node->type
224
        );
225
    }
226
227
    if ($node instanceof Node\Stmt\UseUse) {
228
        return new Node\Stmt\UseUse(
229
            deep_clone($node->name),
230
            $node->alias,
231
            $node->type
232
        );
233
    }
234
235
    if ($node instanceof Node\Stmt\Class_) {
236
        return new Node\Stmt\Class_(
237
            deep_clone($node->name),
238
            [
239
                'flags' => deep_clone($node->flags),
240
                'extends' => deep_clone($node->extends),
241
                'implements' => deep_clone($node->implements),
242
            ]
243
        );
244
    }
245
246
    throw new UnexpectedValueException(
247
        sprintf(
248
            'Cannot clone element "%s".',
249
            get_class($node)
250
        )
251
    );
252
}
253