Subversion-Projekte lars-tiefland.laravel_shop

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
148 lars 1
<?php declare(strict_types=1);
2
 
3
namespace PhpParser\Node;
4
 
5
use PhpParser\NodeAbstract;
6
 
7
class Name extends NodeAbstract
8
{
9
    /** @var string[] Parts of the name */
10
    public $parts;
11
 
12
    private static $specialClassNames = [
13
        'self'   => true,
14
        'parent' => true,
15
        'static' => true,
16
    ];
17
 
18
    /**
19
     * Constructs a name node.
20
     *
21
     * @param string|string[]|self $name       Name as string, part array or Name instance (copy ctor)
22
     * @param array                $attributes Additional attributes
23
     */
24
    public function __construct($name, array $attributes = []) {
25
        $this->attributes = $attributes;
26
        $this->parts = self::prepareName($name);
27
    }
28
 
29
    public function getSubNodeNames() : array {
30
        return ['parts'];
31
    }
32
 
33
    /**
34
     * Gets the first part of the name, i.e. everything before the first namespace separator.
35
     *
36
     * @return string First part of the name
37
     */
38
    public function getFirst() : string {
39
        return $this->parts[0];
40
    }
41
 
42
    /**
43
     * Gets the last part of the name, i.e. everything after the last namespace separator.
44
     *
45
     * @return string Last part of the name
46
     */
47
    public function getLast() : string {
48
        return $this->parts[count($this->parts) - 1];
49
    }
50
 
51
    /**
52
     * Checks whether the name is unqualified. (E.g. Name)
53
     *
54
     * @return bool Whether the name is unqualified
55
     */
56
    public function isUnqualified() : bool {
57
        return 1 === count($this->parts);
58
    }
59
 
60
    /**
61
     * Checks whether the name is qualified. (E.g. Name\Name)
62
     *
63
     * @return bool Whether the name is qualified
64
     */
65
    public function isQualified() : bool {
66
        return 1 < count($this->parts);
67
    }
68
 
69
    /**
70
     * Checks whether the name is fully qualified. (E.g. \Name)
71
     *
72
     * @return bool Whether the name is fully qualified
73
     */
74
    public function isFullyQualified() : bool {
75
        return false;
76
    }
77
 
78
    /**
79
     * Checks whether the name is explicitly relative to the current namespace. (E.g. namespace\Name)
80
     *
81
     * @return bool Whether the name is relative
82
     */
83
    public function isRelative() : bool {
84
        return false;
85
    }
86
 
87
    /**
88
     * Returns a string representation of the name itself, without taking the name type into
89
     * account (e.g., not including a leading backslash for fully qualified names).
90
     *
91
     * @return string String representation
92
     */
93
    public function toString() : string {
94
        return implode('\\', $this->parts);
95
    }
96
 
97
    /**
98
     * Returns a string representation of the name as it would occur in code (e.g., including
99
     * leading backslash for fully qualified names.
100
     *
101
     * @return string String representation
102
     */
103
    public function toCodeString() : string {
104
        return $this->toString();
105
    }
106
 
107
    /**
108
     * Returns lowercased string representation of the name, without taking the name type into
109
     * account (e.g., no leading backslash for fully qualified names).
110
     *
111
     * @return string Lowercased string representation
112
     */
113
    public function toLowerString() : string {
114
        return strtolower(implode('\\', $this->parts));
115
    }
116
 
117
    /**
118
     * Checks whether the identifier is a special class name (self, parent or static).
119
     *
120
     * @return bool Whether identifier is a special class name
121
     */
122
    public function isSpecialClassName() : bool {
123
        return count($this->parts) === 1
124
            && isset(self::$specialClassNames[strtolower($this->parts[0])]);
125
    }
126
 
127
    /**
128
     * Returns a string representation of the name by imploding the namespace parts with the
129
     * namespace separator.
130
     *
131
     * @return string String representation
132
     */
133
    public function __toString() : string {
134
        return implode('\\', $this->parts);
135
    }
136
 
137
    /**
138
     * Gets a slice of a name (similar to array_slice).
139
     *
140
     * This method returns a new instance of the same type as the original and with the same
141
     * attributes.
142
     *
143
     * If the slice is empty, null is returned. The null value will be correctly handled in
144
     * concatenations using concat().
145
     *
146
     * Offset and length have the same meaning as in array_slice().
147
     *
148
     * @param int      $offset Offset to start the slice at (may be negative)
149
     * @param int|null $length Length of the slice (may be negative)
150
     *
151
     * @return static|null Sliced name
152
     */
153
    public function slice(int $offset, int $length = null) {
154
        $numParts = count($this->parts);
155
 
156
        $realOffset = $offset < 0 ? $offset + $numParts : $offset;
157
        if ($realOffset < 0 || $realOffset > $numParts) {
158
            throw new \OutOfBoundsException(sprintf('Offset %d is out of bounds', $offset));
159
        }
160
 
161
        if (null === $length) {
162
            $realLength = $numParts - $realOffset;
163
        } else {
164
            $realLength = $length < 0 ? $length + $numParts - $realOffset : $length;
165
            if ($realLength < 0 || $realLength > $numParts - $realOffset) {
166
                throw new \OutOfBoundsException(sprintf('Length %d is out of bounds', $length));
167
            }
168
        }
169
 
170
        if ($realLength === 0) {
171
            // Empty slice is represented as null
172
            return null;
173
        }
174
 
175
        return new static(array_slice($this->parts, $realOffset, $realLength), $this->attributes);
176
    }
177
 
178
    /**
179
     * Concatenate two names, yielding a new Name instance.
180
     *
181
     * The type of the generated instance depends on which class this method is called on, for
182
     * example Name\FullyQualified::concat() will yield a Name\FullyQualified instance.
183
     *
184
     * If one of the arguments is null, a new instance of the other name will be returned. If both
185
     * arguments are null, null will be returned. As such, writing
186
     *     Name::concat($namespace, $shortName)
187
     * where $namespace is a Name node or null will work as expected.
188
     *
189
     * @param string|string[]|self|null $name1      The first name
190
     * @param string|string[]|self|null $name2      The second name
191
     * @param array                     $attributes Attributes to assign to concatenated name
192
     *
193
     * @return static|null Concatenated name
194
     */
195
    public static function concat($name1, $name2, array $attributes = []) {
196
        if (null === $name1 && null === $name2) {
197
            return null;
198
        } elseif (null === $name1) {
199
            return new static(self::prepareName($name2), $attributes);
200
        } elseif (null === $name2) {
201
            return new static(self::prepareName($name1), $attributes);
202
        } else {
203
            return new static(
204
                array_merge(self::prepareName($name1), self::prepareName($name2)), $attributes
205
            );
206
        }
207
    }
208
 
209
    /**
210
     * Prepares a (string, array or Name node) name for use in name changing methods by converting
211
     * it to an array.
212
     *
213
     * @param string|string[]|self $name Name to prepare
214
     *
215
     * @return string[] Prepared name
216
     */
217
    private static function prepareName($name) : array {
218
        if (\is_string($name)) {
219
            if ('' === $name) {
220
                throw new \InvalidArgumentException('Name cannot be empty');
221
            }
222
 
223
            return explode('\\', $name);
224
        } elseif (\is_array($name)) {
225
            if (empty($name)) {
226
                throw new \InvalidArgumentException('Name cannot be empty');
227
            }
228
 
229
            return $name;
230
        } elseif ($name instanceof self) {
231
            return $name->parts;
232
        }
233
 
234
        throw new \InvalidArgumentException(
235
            'Expected string, array of parts or Name instance'
236
        );
237
    }
238
 
239
    public function getType() : string {
240
        return 'Name';
241
    }
242
}