Namespaces

  • Latte
    • Loaders
    • Macros
    • Runtime
  • Nette
    • Application
      • Responses
      • Routers
      • UI
    • Bridges
      • ApplicationDI
      • ApplicationLatte
      • ApplicationTracy
      • CacheDI
      • CacheLatte
      • DatabaseDI
      • DatabaseTracy
      • DITracy
      • FormsDI
      • FormsLatte
      • Framework
      • HttpDI
      • HttpTracy
      • MailDI
      • ReflectionDI
      • SecurityDI
      • SecurityTracy
    • Caching
      • Storages
    • ComponentModel
    • Database
      • Conventions
      • Drivers
      • Table
    • DI
      • Config
        • Adapters
      • Extensions
    • Forms
      • Controls
      • Rendering
    • Http
    • Iterators
    • Loaders
    • Localization
    • Mail
    • Neon
    • PhpGenerator
      • Traits
    • Reflection
    • Security
    • Tokenizer
    • Utils
  • Tracy
    • Bridges
      • Nette
  • none

Classes

  • Compiler
  • CompilerExtension
  • Container
  • ContainerBuilder
  • ContainerLoader
  • DependencyChecker
  • Helpers
  • PhpGenerator
  • PhpReflection
  • ServiceDefinition
  • Statement

Exceptions

  • MissingServiceException
  • ServiceCreationException
  • Overview
  • Namespace
  • Class
  • Tree
  • Deprecated
  • Other releases
  1: <?php
  2: 
  3: /**
  4:  * This file is part of the Nette Framework (https://nette.org)
  5:  * Copyright (c) 2004 David Grudl (https://davidgrudl.com)
  6:  */
  7: 
  8: namespace Nette\DI;
  9: 
 10: use Nette;
 11: 
 12: 
 13: /**
 14:  * PHP reflection helpers.
 15:  * @internal
 16:  * @deprecated
 17:  */
 18: class PhpReflection
 19: {
 20:     use Nette\StaticClass;
 21: 
 22:     /**
 23:      * Returns an annotation value.
 24:      * @return string|null
 25:      */
 26:     public static function parseAnnotation(\Reflector $ref, $name)
 27:     {
 28:         static $ok;
 29:         if (!$ok) {
 30:             if (!(new \ReflectionMethod(__METHOD__))->getDocComment()) {
 31:                 throw new Nette\InvalidStateException('You have to enable phpDoc comments in opcode cache.');
 32:             }
 33:             $ok = true;
 34:         }
 35:         $name = preg_quote($name, '#');
 36:         if ($ref->getDocComment() && preg_match("#[\\s*]@$name(?:\\s++([^@]\\S*)?|$)#", trim($ref->getDocComment(), '/*'), $m)) {
 37:             return isset($m[1]) ? $m[1] : '';
 38:         }
 39:     }
 40: 
 41: 
 42:     /**
 43:      * Returns declaring class or trait.
 44:      * @return \ReflectionClass
 45:      */
 46:     public static function getDeclaringClass(\ReflectionProperty $prop)
 47:     {
 48:         foreach ($prop->getDeclaringClass()->getTraits() as $trait) {
 49:             if ($trait->hasProperty($prop->getName())) {
 50:                 return self::getDeclaringClass($trait->getProperty($prop->getName()));
 51:             }
 52:         }
 53:         return $prop->getDeclaringClass();
 54:     }
 55: 
 56: 
 57:     /**
 58:      * @return string|null
 59:      */
 60:     public static function getParameterType(\ReflectionParameter $param)
 61:     {
 62:         if (PHP_VERSION_ID >= 70000) {
 63:             $type = $param->hasType() ? (string) $param->getType() : null;
 64:             return strtolower($type) === 'self' ? $param->getDeclaringClass()->getName() : $type;
 65:         } elseif ($param->isArray() || $param->isCallable()) {
 66:             return $param->isArray() ? 'array' : 'callable';
 67:         } else {
 68:             try {
 69:                 return ($ref = $param->getClass()) ? $ref->getName() : null;
 70:             } catch (\ReflectionException $e) {
 71:                 if (preg_match('#Class (.+) does not exist#', $e->getMessage(), $m)) {
 72:                     return $m[1];
 73:                 }
 74:                 throw $e;
 75:             }
 76:         }
 77:     }
 78: 
 79: 
 80:     /**
 81:      * @return string|null
 82:      */
 83:     public static function getReturnType(\ReflectionFunctionAbstract $func)
 84:     {
 85:         if (PHP_VERSION_ID >= 70000 && $func->hasReturnType()) {
 86:             $type = (string) $func->getReturnType();
 87:             return strtolower($type) === 'self' ? $func->getDeclaringClass()->getName() : $type;
 88:         }
 89:         $type = preg_replace('#[|\s].*#', '', (string) self::parseAnnotation($func, 'return'));
 90:         if ($type) {
 91:             return $func instanceof \ReflectionMethod
 92:                 ? self::expandClassName($type, $func->getDeclaringClass())
 93:                 : ltrim($type, '\\');
 94:         }
 95:     }
 96: 
 97: 
 98:     /**
 99:      * @param  string
100:      * @return bool
101:      */
102:     public static function isBuiltinType($type)
103:     {
104:         return in_array(strtolower($type), ['string', 'int', 'float', 'bool', 'array', 'callable'], true);
105:     }
106: 
107: 
108:     /**
109:      * Returns class and all its descendants.
110:      * @return string[]
111:      */
112:     public static function getClassTree(\ReflectionClass $class)
113:     {
114:         $addTraits = function ($types) use (&$addTraits) {
115:             if ($traits = array_merge(...array_map('class_uses', array_values($types)))) {
116:                 $types += $traits + $addTraits($traits);
117:             }
118:             return $types;
119:         };
120:         $class = $class->getName();
121:         return array_values($addTraits([$class] + class_parents($class) + class_implements($class)));
122:     }
123: 
124: 
125:     /**
126:      * Expands class name into full name.
127:      * @param  string
128:      * @return string  full name
129:      * @throws Nette\InvalidArgumentException
130:      */
131:     public static function expandClassName($name, \ReflectionClass $rc)
132:     {
133:         $lower = strtolower($name);
134:         if (empty($name)) {
135:             throw new Nette\InvalidArgumentException('Class name must not be empty.');
136: 
137:         } elseif (self::isBuiltinType($lower)) {
138:             return $lower;
139: 
140:         } elseif ($lower === 'self' || $lower === 'static' || $lower === '$this') {
141:             return $rc->getName();
142: 
143:         } elseif ($name[0] === '\\') { // fully qualified name
144:             return ltrim($name, '\\');
145:         }
146: 
147:         $uses = self::getUseStatements($rc);
148:         $parts = explode('\\', $name, 2);
149:         if (isset($uses[$parts[0]])) {
150:             $parts[0] = $uses[$parts[0]];
151:             return implode('\\', $parts);
152: 
153:         } elseif ($rc->inNamespace()) {
154:             return $rc->getNamespaceName() . '\\' . $name;
155: 
156:         } else {
157:             return $name;
158:         }
159:     }
160: 
161: 
162:     /**
163:      * @return array of [alias => class]
164:      */
165:     public static function getUseStatements(\ReflectionClass $class)
166:     {
167:         static $cache = [];
168:         if (!isset($cache[$name = $class->getName()])) {
169:             if ($class->isInternal()) {
170:                 $cache[$name] = [];
171:             } else {
172:                 $code = file_get_contents($class->getFileName());
173:                 $cache = self::parseUseStatements($code, $name) + $cache;
174:             }
175:         }
176:         return $cache[$name];
177:     }
178: 
179: 
180:     /**
181:      * Parses PHP code.
182:      * @param  string
183:      * @return array of [class => [alias => class, ...]]
184:      */
185:     public static function parseUseStatements($code, $forClass = null)
186:     {
187:         $tokens = token_get_all($code);
188:         $namespace = $class = $classLevel = $level = null;
189:         $res = $uses = [];
190: 
191:         while ($token = current($tokens)) {
192:             next($tokens);
193:             switch (is_array($token) ? $token[0] : $token) {
194:                 case T_NAMESPACE:
195:                     $namespace = ltrim(self::fetch($tokens, [T_STRING, T_NS_SEPARATOR]) . '\\', '\\');
196:                     $uses = [];
197:                     break;
198: 
199:                 case T_CLASS:
200:                 case T_INTERFACE:
201:                 case T_TRAIT:
202:                     if ($name = self::fetch($tokens, T_STRING)) {
203:                         $class = $namespace . $name;
204:                         $classLevel = $level + 1;
205:                         $res[$class] = $uses;
206:                         if ($class === $forClass) {
207:                             return $res;
208:                         }
209:                     }
210:                     break;
211: 
212:                 case T_USE:
213:                     while (!$class && ($name = self::fetch($tokens, [T_STRING, T_NS_SEPARATOR]))) {
214:                         $name = ltrim($name, '\\');
215:                         if (self::fetch($tokens, '{')) {
216:                             while ($suffix = self::fetch($tokens, [T_STRING, T_NS_SEPARATOR])) {
217:                                 if (self::fetch($tokens, T_AS)) {
218:                                     $uses[self::fetch($tokens, T_STRING)] = $name . $suffix;
219:                                 } else {
220:                                     $tmp = explode('\\', $suffix);
221:                                     $uses[end($tmp)] = $name . $suffix;
222:                                 }
223:                                 if (!self::fetch($tokens, ',')) {
224:                                     break;
225:                                 }
226:                             }
227: 
228:                         } elseif (self::fetch($tokens, T_AS)) {
229:                             $uses[self::fetch($tokens, T_STRING)] = $name;
230: 
231:                         } else {
232:                             $tmp = explode('\\', $name);
233:                             $uses[end($tmp)] = $name;
234:                         }
235:                         if (!self::fetch($tokens, ',')) {
236:                             break;
237:                         }
238:                     }
239:                     break;
240: 
241:                 case T_CURLY_OPEN:
242:                 case T_DOLLAR_OPEN_CURLY_BRACES:
243:                 case '{':
244:                     $level++;
245:                     break;
246: 
247:                 case '}':
248:                     if ($level === $classLevel) {
249:                         $class = $classLevel = null;
250:                     }
251:                     $level--;
252:             }
253:         }
254: 
255:         return $res;
256:     }
257: 
258: 
259:     private static function fetch(&$tokens, $take)
260:     {
261:         $res = null;
262:         while ($token = current($tokens)) {
263:             list($token, $s) = is_array($token) ? $token : [$token, $token];
264:             if (in_array($token, (array) $take, true)) {
265:                 $res .= $s;
266:             } elseif (!in_array($token, [T_DOC_COMMENT, T_WHITESPACE, T_COMMENT], true)) {
267:                 break;
268:             }
269:             next($tokens);
270:         }
271:         return $res;
272:     }
273: }
274: 
Nette 2.4-20180918 API API documentation generated by ApiGen 2.8.0