Overview

Namespaces

  • TokenReflection
    • Broker
      • Backend
    • Dummy
    • Exception
    • Invalid
    • Php
    • Stream

Classes

  • Broker
  • ReflectionAnnotation
  • ReflectionBase
  • ReflectionClass
  • ReflectionConstant
  • ReflectionElement
  • ReflectionFile
  • ReflectionFileNamespace
  • ReflectionFunction
  • ReflectionFunctionBase
  • ReflectionMethod
  • ReflectionNamespace
  • ReflectionParameter
  • ReflectionProperty
  • Resolver

Interfaces

  • IReflection
  • IReflectionClass
  • IReflectionConstant
  • IReflectionExtension
  • IReflectionFunction
  • IReflectionFunctionBase
  • IReflectionMethod
  • IReflectionNamespace
  • IReflectionParameter
  • IReflectionProperty
  • Overview
  • Namespace
  • Class
  • Tree
  • Download
  1: <?php
  2: /**
  3:  * PHP Token Reflection
  4:  *
  5:  * Version 1.3.1
  6:  *
  7:  * LICENSE
  8:  *
  9:  * This source file is subject to the new BSD license that is bundled
 10:  * with this library in the file license.txt.
 11:  *
 12:  * @author Ondřej Nešpor
 13:  * @author Jaroslav Hanslík
 14:  */
 15: 
 16: namespace TokenReflection;
 17: 
 18: /**
 19:  * TokenReflection Resolver class.
 20:  */
 21: class Resolver
 22: {
 23:     /**
 24:      * Placeholder for non-existen constants.
 25:      *
 26:      * @var null
 27:      */
 28:     const CONSTANT_NOT_FOUND = '~~NOT RESOLVED~~';
 29: 
 30:     /**
 31:      * Constructor.
 32:      *
 33:      * Prevents from creating instances.
 34:      *
 35:      * @throws LogicException When trying to create a class instance.
 36:      */
 37:     final public function __construct()
 38:     {
 39:         throw new \LogicException('Static class cannot be instantiated.');
 40:     }
 41: 
 42:     /**
 43:      * Returns a fully qualified name of a class using imported/aliased namespaces.
 44:      *
 45:      * @param string $className Input class name
 46:      * @param array $aliases Namespace import aliases
 47:      * @param string $namespaceName Context namespace name
 48:      * @return string
 49:      */
 50:     final public static function resolveClassFQN($className, array $aliases, $namespaceName = null)
 51:     {
 52:         if ($className{0} == '\\') {
 53:             // FQN
 54:             return ltrim($className, '\\');
 55:         }
 56: 
 57:         if (false === ($position = strpos($className, '\\'))) {
 58:             // Plain class name
 59:             if (isset($aliases[$className])) {
 60:                 return $aliases[$className];
 61:             }
 62:         } else {
 63:             // Namespaced class name
 64:             $alias = substr($className, 0, $position);
 65:             if (isset($aliases[$alias])) {
 66:                 return $aliases[$alias] . '\\' . substr($className, $position + 1);
 67:             }
 68:         }
 69: 
 70:         return null === $namespaceName || '' === $namespaceName || $namespaceName === ReflectionNamespace::NO_NAMESPACE_NAME ? $className : $namespaceName . '\\' . $className;
 71:     }
 72: 
 73:     /**
 74:      * Returns a property/parameter/constant/static variable value definition.
 75:      *
 76:      * @param array $tokens Tokenized definition
 77:      * @param \TokenReflection\ReflectionElement $reflection Caller reflection
 78:      * @return string
 79:      * @throws \TokenReflection\Exception\RuntimeException If an invalid reflection object was provided.
 80:      * @throws \TokenReflection\Exception\RuntimeException If an invalid source code was provided.
 81:      */
 82:     final public static function getValueDefinition(array $tokens, ReflectionElement $reflection)
 83:     {
 84:         if ($reflection instanceof ReflectionConstant || $reflection instanceof ReflectionFunction) {
 85:             $namespace = $reflection->getNamespaceName();
 86:         } elseif ($reflection instanceof ReflectionParameter) {
 87:             $namespace = $reflection->getDeclaringFunction()->getNamespaceName();
 88:         } elseif ($reflection instanceof ReflectionProperty || $reflection instanceof ReflectionMethod) {
 89:             $namespace = $reflection->getDeclaringClass()->getNamespaceName();
 90:         } else {
 91:             throw new Exception\RuntimeException('Invalid reflection object given.', Exception\RuntimeException::INVALID_ARGUMENT, $reflection);
 92:         }
 93: 
 94:         // Process __LINE__ constants; replace with the line number of the corresponding token
 95:         foreach ($tokens as $index => $token) {
 96:             if (T_LINE === $token[0]) {
 97:                 $tokens[$index] = array(
 98:                     T_LNUMBER,
 99:                     $token[2],
100:                     $token[2]
101:                 );
102:             }
103:         }
104: 
105:         $source = self::getSourceCode($tokens);
106: 
107:         $constants = self::findConstants($tokens, $reflection);
108:         if (!empty($constants)) {
109:             foreach (array_reverse($constants, true) as $offset => $constant) {
110:                 $value = '';
111: 
112:                 try {
113:                     switch ($constant) {
114:                         case '__LINE__':
115:                             throw new Exception\RuntimeException('__LINE__ constant cannot be resolved this way.', Exception\RuntimeException::UNSUPPORTED, $reflection);
116:                         case '__FILE__':
117:                             $value = $reflection->getFileName();
118:                             break;
119:                         case '__DIR__':
120:                             $value = dirname($reflection->getFileName());
121:                             break;
122:                         case '__FUNCTION__':
123:                             if ($reflection instanceof IReflectionParameter) {
124:                                 $value = $reflection->getDeclaringFunctionName();
125:                             } elseif ($reflection instanceof IReflectionFunctionBase) {
126:                                 $value = $reflection->getName();
127:                             }
128:                             break;
129:                         case '__CLASS__':
130:                             if ($reflection instanceof IReflectionConstant || $reflection instanceof IReflectionParameter || $reflection instanceof IReflectionProperty || $reflection instanceof IReflectionMethod) {
131:                                 $value = $reflection->getDeclaringClassName() ?: '';
132:                             }
133:                             break;
134:                         case '__TRAIT__':
135:                             if ($reflection instanceof IReflectionMethod || $reflection instanceof IReflectionProperty) {
136:                                 $value = $reflection->getDeclaringTraitName() ?: '';
137:                             } elseif ($reflection instanceof IReflectionParameter) {
138:                                 $method = $reflection->getDeclaringFunction();
139:                                 if ($method instanceof IReflectionMethod) {
140:                                     $value = $method->getDeclaringTraitName() ?: '';
141:                                 }
142:                             }
143:                             break;
144:                         case '__METHOD__':
145:                             if ($reflection instanceof IReflectionParameter) {
146:                                 if (null !== $reflection->getDeclaringClassName()) {
147:                                     $value = $reflection->getDeclaringClassName() . '::' . $reflection->getDeclaringFunctionName();
148:                                 } else {
149:                                     $value = $reflection->getDeclaringFunctionName();
150:                                 }
151:                             } elseif ($reflection instanceof IReflectionConstant || $reflection instanceof IReflectionProperty) {
152:                                 $value = $reflection->getDeclaringClassName() ?: '';
153:                             } elseif ($reflection instanceof IReflectionMethod) {
154:                                 $value = $reflection->getDeclaringClassName() . '::' . $reflection->getName();
155:                             } elseif ($reflection instanceof IReflectionFunction) {
156:                                 $value = $reflection->getName();
157:                             }
158:                             break;
159:                         case '__NAMESPACE__':
160:                             if (($reflection instanceof IReflectionConstant && null !== $reflection->getDeclaringClassName()) || $reflection instanceof IReflectionProperty) {
161:                                 $value = $reflection->getDeclaringClass()->getNamespaceName();
162:                             } elseif ($reflection instanceof IReflectionParameter) {
163:                                 if (null !== $reflection->getDeclaringClassName()) {
164:                                     $value = $reflection->getDeclaringClass()->getNamespaceName();
165:                                 } else {
166:                                     $value = $reflection->getDeclaringFunction()->getNamespaceName();
167:                                 }
168:                             } elseif ($reflection instanceof IReflectionMethod) {
169:                                 $value = $reflection->getDeclaringClass()->getNamespaceName();
170:                             } else {
171:                                 $value = $reflection->getNamespaceName();
172:                             }
173:                             break;
174:                         default:
175:                             if (0 === stripos($constant, 'self::') || 0 === stripos($constant, 'parent::')) {
176:                                 // Handle self:: and parent:: definitions
177: 
178:                                 if ($reflection instanceof ReflectionConstant) {
179:                                     throw new Exception\RuntimeException('Constants cannot use self:: and parent:: references.', Exception\RuntimeException::UNSUPPORTED, $reflection);
180:                                 } elseif ($reflection instanceof ReflectionParameter && null === $reflection->getDeclaringClassName()) {
181:                                     throw new Exception\RuntimeException('Function parameters cannot use self:: and parent:: references.', Exception\RuntimeException::UNSUPPORTED, $reflection);
182:                                 }
183: 
184:                                 if (0 === stripos($constant, 'self::')) {
185:                                     $className = $reflection->getDeclaringClassName();
186:                                 } else {
187:                                     $declaringClass = $reflection->getDeclaringClass();
188:                                     $className = $declaringClass->getParentClassName() ?: self::CONSTANT_NOT_FOUND;
189:                                 }
190: 
191:                                 $constantName = $className . substr($constant, strpos($constant, '::'));
192:                             } else {
193:                                 $constantName = self::resolveClassFQN($constant, $reflection->getNamespaceAliases(), $namespace);
194:                                 if ($cnt = strspn($constant, '\\')) {
195:                                     $constantName = str_repeat('\\', $cnt) . $constantName;
196:                                 }
197:                             }
198: 
199:                             $reflection = $reflection->getBroker()->getConstant($constantName);
200:                             $value = $reflection->getValue();
201:                     }
202:                 } catch (Exception\RuntimeException $e) {
203:                     $value = self::CONSTANT_NOT_FOUND;
204:                 }
205: 
206:                 $source = substr_replace($source, var_export($value, true), $offset, strlen($constant));
207:             }
208:         }
209: 
210:         return self::evaluate(sprintf("return %s;\n", $source));
211:     }
212: 
213:     /**
214:      * Returns a part of the source code defined by given tokens.
215:      *
216:      * @param array $tokens Tokens array
217:      * @return array
218:      */
219:     final public static function getSourceCode(array $tokens)
220:     {
221:         if (empty($tokens)) {
222:             return null;
223:         }
224: 
225:         $source = '';
226:         foreach ($tokens as $token) {
227:             $source .= $token[1];
228:         }
229:         return $source;
230:     }
231: 
232:     /**
233:      * Finds constant names in the token definition.
234:      *
235:      * @param array $tokens Tokenized source code
236:      * @param \TokenReflection\ReflectionElement $reflection Caller reflection
237:      * @return array
238:      */
239:     final public static function findConstants(array $tokens, ReflectionElement $reflection)
240:     {
241:         static $accepted = array(
242:             T_DOUBLE_COLON => true,
243:             T_STRING => true,
244:             T_NS_SEPARATOR => true,
245:             T_CLASS_C => true,
246:             T_DIR => true,
247:             T_FILE => true,
248:             T_LINE => true,
249:             T_FUNC_C => true,
250:             T_METHOD_C => true,
251:             T_NS_C => true,
252:             T_TRAIT_C => true
253:         );
254:         static $dontResolve = array('true' => true, 'false' => true, 'null' => true);
255: 
256:         // Adding a dummy token to the end
257:         $tokens[] = array(null);
258: 
259:         $constants = array();
260:         $constant = '';
261:         $offset = 0;
262:         foreach ($tokens as $token) {
263:             if (isset($accepted[$token[0]])) {
264:                 $constant .= $token[1];
265:             } elseif ('' !== $constant) {
266:                 if (!isset($dontResolve[strtolower($constant)])) {
267:                     $constants[$offset - strlen($constant)] = $constant;
268:                 }
269:                 $constant = '';
270:             }
271: 
272:             if (null !== $token[0]) {
273:                 $offset += strlen($token[1]);
274:             }
275:         }
276:         return $constants;
277:     }
278: 
279:     /**
280:      * Evaluates a source code.
281:      *
282:      * @param string $source Source code
283:      * @return mixed
284:      */
285:     final private static function evaluate($source) {
286:         return eval($source);
287:     }
288: }
289: 
PHP Token Reflection API documentation generated by ApiGen 2.8.0