Completed
Push — master ( 550011...0647fd )
by Théo
16:20 queued 07:57
created

Reflector::getInternalConstants()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 14

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 2

Importance

Changes 0
Metric Value
cc 2
nc 2
nop 0
dl 0
loc 14
ccs 7
cts 7
cp 1
crap 2
rs 9.7998
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 ReflectionException;
18
use ReflectionFunction;
19
use Roave\BetterReflection\Identifier\Exception\InvalidIdentifierName;
20
use Roave\BetterReflection\Reflector\ClassReflector;
21
use Roave\BetterReflection\Reflector\Exception\IdentifierNotFound;
22
use function array_key_exists;
23
use function array_values;
24
use function get_defined_constants;
25
use function strtoupper;
26
27
/**
28
 * Main class used to determine if a given symbol is internal or not. As of the time of writing, it leverages
29
 * Roave\BetterReflection to determine if given class is internal or not which allows to do reflection:.
30
 *
31
 * - Without loading the code scanned code at all
32
 * - Do reliable reflection against non-loaded APIs, i.e. a class from a non-loaded extension will properly appear
33
 *   as internal whereas the regular reflection would not.
34
 *
35
 * However Roave\BetterReflection is still not supporting constants and functions hence requires some hacks here
36
 * meanwhile.
37
 *
38
 * @private
39
 */
40
final class Reflector
41
{
42
    private const KNOWN_INTERNAL_CONSTANTS = [
43
        'CURLM_ADDED_ALREADY' => true,
44
        'JSON_UNESCAPED_LINE_TERMINATORS' => true,
45
        'OPENSSL_DONT_ZERO_PAD_KEY' => true,
46
        'PHP_FD_SETSIZE' => true,
47
        'PHP_INT_MIN' => true,
48
        'PHP_OS_FAMILY' => true,
49
    ];
50
51
    private const KNOWN_INTERNAL_FUNCTIONS = [
52
        'deflate_add' => true,
53
        'deflate_init' => true,
54
        'error_clear_last' => true,
55
        'ftp_append' => true,
56
        'hash_hkdf' => true,
57
        'inflate_add' => true,
58
        'inflate_init' => true,
59
        'intdiv' => true,
60
        'is_iterable' => true,
61
        'openssl_pkcs7_read' => true,
62
        'pcntl_signal_get_handler' => true,
63
        'preg_replace_callback_array' => true,
64
        'sapi_windows_vt100_support' => true,
65
        'socket_export_stream' => true,
66
        'spl_object_id' => true,
67
        'stream_isatty' => true,
68
        'utf8_decode' => true,
69
        'utf8_encode' => true,
70
    ];
71
72
    private $classReflector;
73
    private $constants;
74
75 32
    public function __construct(ClassReflector $classReflector)
76
    {
77 32
        $this->classReflector = $classReflector;
78
    }
79
80 6
    public function isClassInternal(string $name): bool
81
    {
82
        try {
83 6
            return $this->classReflector->reflect($name)->isInternal();
84 1
        } catch (IdentifierNotFound | InvalidIdentifierName $exception) {
85 1
            return false;
86
        }
87
    }
88
89 11
    public function isFunctionInternal(string $name): bool
90
    {
91 11
        if (array_key_exists($name, self::KNOWN_INTERNAL_FUNCTIONS)) {
92 2
            return true;
93
        }
94
95
        try {
96 9
            return (new ReflectionFunction($name))->isInternal();
97 7
        } catch (ReflectionException $exception) {
98 7
            return false;
99
        }
100
    }
101
102 9
    public function isConstantInternal(string $name): bool
103
    {
104 9
        if (array_key_exists($name, self::KNOWN_INTERNAL_CONSTANTS)) {
105 1
            return true;
106
        }
107
108 8
        return array_key_exists(strtoupper($name), $this->getInternalConstants());
109
    }
110
111 8
    private function getInternalConstants(): array
112
    {
113 8
        if (null !== $this->constants) {
114 4
            return $this->constants;
115
        }
116
117 8
        $constants = get_defined_constants(true);
118
119 8
        unset($constants['user']);
120
121 8
        $this->constants = array_merge(...array_values($constants));
122
123 8
        return $this->constants;
124
    }
125
}
126