Chris@16
|
1 <?php
|
Chris@16
|
2
|
Chris@16
|
3 /*
|
Chris@16
|
4 * This file is part of Psy Shell.
|
Chris@16
|
5 *
|
Chris@16
|
6 * (c) 2012-2018 Justin Hileman
|
Chris@16
|
7 *
|
Chris@16
|
8 * For the full copyright and license information, please view the LICENSE
|
Chris@16
|
9 * file that was distributed with this source code.
|
Chris@16
|
10 */
|
Chris@16
|
11
|
Chris@16
|
12 namespace Psy\Reflection;
|
Chris@16
|
13
|
Chris@16
|
14 /**
|
Chris@16
|
15 * Somehow the standard reflection library didn't include class constants until 7.1.
|
Chris@16
|
16 *
|
Chris@16
|
17 * ReflectionClassConstant corrects that omission.
|
Chris@16
|
18 */
|
Chris@16
|
19 class ReflectionClassConstant implements \Reflector
|
Chris@16
|
20 {
|
Chris@16
|
21 public $class;
|
Chris@16
|
22 public $name;
|
Chris@16
|
23 private $value;
|
Chris@16
|
24
|
Chris@16
|
25 /**
|
Chris@16
|
26 * Construct a ReflectionClassConstant object.
|
Chris@16
|
27 *
|
Chris@16
|
28 * @param string|object $class
|
Chris@16
|
29 * @param string $name
|
Chris@16
|
30 */
|
Chris@16
|
31 public function __construct($class, $name)
|
Chris@16
|
32 {
|
Chris@16
|
33 if (!$class instanceof \ReflectionClass) {
|
Chris@16
|
34 $class = new \ReflectionClass($class);
|
Chris@16
|
35 }
|
Chris@16
|
36
|
Chris@16
|
37 $this->class = $class;
|
Chris@16
|
38 $this->name = $name;
|
Chris@16
|
39
|
Chris@16
|
40 $constants = $class->getConstants();
|
Chris@17
|
41 if (!\array_key_exists($name, $constants)) {
|
Chris@16
|
42 throw new \InvalidArgumentException('Unknown constant: ' . $name);
|
Chris@16
|
43 }
|
Chris@16
|
44
|
Chris@16
|
45 $this->value = $constants[$name];
|
Chris@16
|
46 }
|
Chris@16
|
47
|
Chris@16
|
48 /**
|
Chris@16
|
49 * Exports a reflection.
|
Chris@16
|
50 *
|
Chris@16
|
51 * @param string|object $class
|
Chris@16
|
52 * @param string $name
|
Chris@16
|
53 * @param bool $return pass true to return the export, as opposed to emitting it
|
Chris@16
|
54 *
|
Chris@16
|
55 * @return null|string
|
Chris@16
|
56 */
|
Chris@16
|
57 public static function export($class, $name, $return = false)
|
Chris@16
|
58 {
|
Chris@16
|
59 $refl = new self($class, $name);
|
Chris@16
|
60 $value = $refl->getValue();
|
Chris@16
|
61
|
Chris@17
|
62 $str = \sprintf('Constant [ public %s %s ] { %s }', \gettype($value), $refl->getName(), $value);
|
Chris@16
|
63
|
Chris@16
|
64 if ($return) {
|
Chris@16
|
65 return $str;
|
Chris@16
|
66 }
|
Chris@16
|
67
|
Chris@16
|
68 echo $str . "\n";
|
Chris@16
|
69 }
|
Chris@16
|
70
|
Chris@16
|
71 /**
|
Chris@16
|
72 * Gets the declaring class.
|
Chris@16
|
73 *
|
Chris@16
|
74 * @return \ReflectionClass
|
Chris@16
|
75 */
|
Chris@16
|
76 public function getDeclaringClass()
|
Chris@16
|
77 {
|
Chris@16
|
78 $parent = $this->class;
|
Chris@16
|
79
|
Chris@16
|
80 // Since we don't have real reflection constants, we can't see where
|
Chris@16
|
81 // it's actually defined. Let's check for a constant that is also
|
Chris@16
|
82 // available on the parent class which has exactly the same value.
|
Chris@16
|
83 //
|
Chris@16
|
84 // While this isn't _technically_ correct, it's prolly close enough.
|
Chris@16
|
85 do {
|
Chris@16
|
86 $class = $parent;
|
Chris@16
|
87 $parent = $class->getParentClass();
|
Chris@16
|
88 } while ($parent && $parent->hasConstant($this->name) && $parent->getConstant($this->name) === $this->value);
|
Chris@16
|
89
|
Chris@16
|
90 return $class;
|
Chris@16
|
91 }
|
Chris@16
|
92
|
Chris@16
|
93 /**
|
Chris@16
|
94 * Get the constant's docblock.
|
Chris@16
|
95 *
|
Chris@16
|
96 * @return false
|
Chris@16
|
97 */
|
Chris@16
|
98 public function getDocComment()
|
Chris@16
|
99 {
|
Chris@16
|
100 return false;
|
Chris@16
|
101 }
|
Chris@16
|
102
|
Chris@16
|
103 /**
|
Chris@16
|
104 * Gets the class constant modifiers.
|
Chris@16
|
105 *
|
Chris@16
|
106 * Since this is only used for PHP < 7.1, we can just return "public". All
|
Chris@16
|
107 * the fancier modifiers are only available on PHP versions which have their
|
Chris@16
|
108 * own ReflectionClassConstant class :)
|
Chris@16
|
109 *
|
Chris@16
|
110 * @return int
|
Chris@16
|
111 */
|
Chris@16
|
112 public function getModifiers()
|
Chris@16
|
113 {
|
Chris@16
|
114 return \ReflectionMethod::IS_PUBLIC;
|
Chris@16
|
115 }
|
Chris@16
|
116
|
Chris@16
|
117 /**
|
Chris@16
|
118 * Gets the constant name.
|
Chris@16
|
119 *
|
Chris@16
|
120 * @return string
|
Chris@16
|
121 */
|
Chris@16
|
122 public function getName()
|
Chris@16
|
123 {
|
Chris@16
|
124 return $this->name;
|
Chris@16
|
125 }
|
Chris@16
|
126
|
Chris@16
|
127 /**
|
Chris@16
|
128 * Gets the value of the constant.
|
Chris@16
|
129 *
|
Chris@16
|
130 * @return mixed
|
Chris@16
|
131 */
|
Chris@16
|
132 public function getValue()
|
Chris@16
|
133 {
|
Chris@16
|
134 return $this->value;
|
Chris@16
|
135 }
|
Chris@16
|
136
|
Chris@16
|
137 /**
|
Chris@16
|
138 * Checks if class constant is private.
|
Chris@16
|
139 *
|
Chris@16
|
140 * @return bool false
|
Chris@16
|
141 */
|
Chris@16
|
142 public function isPrivate()
|
Chris@16
|
143 {
|
Chris@16
|
144 return false;
|
Chris@16
|
145 }
|
Chris@16
|
146
|
Chris@16
|
147 /**
|
Chris@16
|
148 * Checks if class constant is protected.
|
Chris@16
|
149 *
|
Chris@16
|
150 * @return bool false
|
Chris@16
|
151 */
|
Chris@16
|
152 public function isProtected()
|
Chris@16
|
153 {
|
Chris@16
|
154 return false;
|
Chris@16
|
155 }
|
Chris@16
|
156
|
Chris@16
|
157 /**
|
Chris@16
|
158 * Checks if class constant is public.
|
Chris@16
|
159 *
|
Chris@16
|
160 * @return bool true
|
Chris@16
|
161 */
|
Chris@16
|
162 public function isPublic()
|
Chris@16
|
163 {
|
Chris@16
|
164 return true;
|
Chris@16
|
165 }
|
Chris@16
|
166
|
Chris@16
|
167 /**
|
Chris@16
|
168 * To string.
|
Chris@16
|
169 *
|
Chris@16
|
170 * @return string
|
Chris@16
|
171 */
|
Chris@16
|
172 public function __toString()
|
Chris@16
|
173 {
|
Chris@16
|
174 return $this->getName();
|
Chris@16
|
175 }
|
Chris@16
|
176
|
Chris@16
|
177 /**
|
Chris@16
|
178 * Gets the constant's file name.
|
Chris@16
|
179 *
|
Chris@16
|
180 * Currently returns null, because if it returns a file name the signature
|
Chris@16
|
181 * formatter will barf.
|
Chris@16
|
182 */
|
Chris@16
|
183 public function getFileName()
|
Chris@16
|
184 {
|
Chris@16
|
185 return;
|
Chris@16
|
186 // return $this->class->getFileName();
|
Chris@16
|
187 }
|
Chris@16
|
188
|
Chris@16
|
189 /**
|
Chris@16
|
190 * Get the code start line.
|
Chris@16
|
191 *
|
Chris@16
|
192 * @throws \RuntimeException
|
Chris@16
|
193 */
|
Chris@16
|
194 public function getStartLine()
|
Chris@16
|
195 {
|
Chris@16
|
196 throw new \RuntimeException('Not yet implemented because it\'s unclear what I should do here :)');
|
Chris@16
|
197 }
|
Chris@16
|
198
|
Chris@16
|
199 /**
|
Chris@16
|
200 * Get the code end line.
|
Chris@16
|
201 *
|
Chris@16
|
202 * @throws \RuntimeException
|
Chris@16
|
203 */
|
Chris@16
|
204 public function getEndLine()
|
Chris@16
|
205 {
|
Chris@16
|
206 return $this->getStartLine();
|
Chris@16
|
207 }
|
Chris@16
|
208
|
Chris@16
|
209 /**
|
Chris@16
|
210 * Get a ReflectionClassConstant instance.
|
Chris@16
|
211 *
|
Chris@16
|
212 * In PHP >= 7.1, this will return a \ReflectionClassConstant from the
|
Chris@16
|
213 * standard reflection library. For older PHP, it will return this polyfill.
|
Chris@16
|
214 *
|
Chris@16
|
215 * @param string|object $class
|
Chris@16
|
216 * @param string $name
|
Chris@16
|
217 *
|
Chris@16
|
218 * @return ReflectionClassConstant|\ReflectionClassConstant
|
Chris@16
|
219 */
|
Chris@16
|
220 public static function create($class, $name)
|
Chris@16
|
221 {
|
Chris@17
|
222 if (\class_exists('\\ReflectionClassConstant')) {
|
Chris@16
|
223 return new \ReflectionClassConstant($class, $name);
|
Chris@16
|
224 }
|
Chris@16
|
225
|
Chris@16
|
226 return new self($class, $name);
|
Chris@16
|
227 }
|
Chris@16
|
228 }
|