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
    • Reflection
    • Security
    • Utils
  • none
  • Tracy
    • Bridges
      • Nette

Classes

  • ArrayHash
  • ArrayList
  • Arrays
  • Callback
  • DateTime
  • FileSystem
  • Finder
  • Html
  • Image
  • Json
  • LimitedScope
  • MimeTypeDetector
  • ObjectMixin
  • Paginator
  • Random
  • Reflection
  • Strings
  • TokenIterator
  • Tokenizer
  • Validators

Interfaces

  • IHtmlString

Exceptions

  • AssertionException
  • ImageException
  • JsonException
  • RegexpException
  • TokenizerException
  • UnknownImageFileException
  • Overview
  • Namespace
  • Class
  • Tree
  • Deprecated
  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\Utils;
  9: 
 10: use Nette;
 11: 
 12: 
 13: /**
 14:  * PHP reflection helpers.
 15:  */
 16: class Reflection
 17: {
 18:     use Nette\StaticClass;
 19: 
 20:     private static $builtinTypes = [
 21:         'string' => 1, 'int' => 1, 'float' => 1, 'bool' => 1, 'array' => 1,
 22:         'callable' => 1, 'iterable' => 1, 'void' => 1
 23:     ];
 24: 
 25: 
 26:     /**
 27:      * @param  string
 28:      * @return bool
 29:      */
 30:     public static function isBuiltinType($type)
 31:     {
 32:         return isset(self::$builtinTypes[strtolower($type)]);
 33:     }
 34: 
 35: 
 36:     /**
 37:      * @return string|NULL
 38:      */
 39:     public static function getReturnType(\ReflectionFunctionAbstract $func)
 40:     {
 41:         if (PHP_VERSION_ID >= 70000 && $func->hasReturnType()) {
 42:             $type = (string) $func->getReturnType();
 43:             return strtolower($type) === 'self' ? $func->getDeclaringClass()->getName() : $type;
 44:         }
 45:     }
 46: 
 47: 
 48:     /**
 49:      * @return string|NULL
 50:      */
 51:     public static function getParameterType(\ReflectionParameter $param)
 52:     {
 53:         if (PHP_VERSION_ID >= 70000) {
 54:             $type = $param->hasType() ? (string) $param->getType() : NULL;
 55:             return strtolower($type) === 'self' ? $param->getDeclaringClass()->getName() : $type;
 56:         } elseif ($param->isArray() || $param->isCallable()) {
 57:             return $param->isArray() ? 'array' : 'callable';
 58:         } else {
 59:             try {
 60:                 return ($ref = $param->getClass()) ? $ref->getName() : NULL;
 61:             } catch (\ReflectionException $e) {
 62:                 if (preg_match('#Class (.+) does not exist#', $e->getMessage(), $m)) {
 63:                     return $m[1];
 64:                 }
 65:                 throw $e;
 66:             }
 67:         }
 68:     }
 69: 
 70: 
 71:     /**
 72:      * @return mixed
 73:      * @throws \ReflectionException when default value is not available or resolvable
 74:      */
 75:     public static function getParameterDefaultValue(\ReflectionParameter $param)
 76:     {
 77:         if ($param->isDefaultValueConstant()) {
 78:             $const = $orig = $param->getDefaultValueConstantName();
 79:             $pair = explode('::', $const);
 80:             if (isset($pair[1]) && strtolower($pair[0]) === 'self') {
 81:                 $const = $param->getDeclaringClass()->getName() . '::' . $pair[1];
 82:             }
 83:             if (!defined($const)) {
 84:                 $const = substr((string) strrchr($const, '\\'), 1);
 85:                 if (isset($pair[1]) || !defined($const)) {
 86:                     $name = self::toString($param);
 87:                     throw new \ReflectionException("Unable to resolve constant $orig used as default value of $name.");
 88:                 }
 89:             }
 90:             return constant($const);
 91:         }
 92:         return $param->getDefaultValue();
 93:     }
 94: 
 95: 
 96:     /**
 97:      * Returns declaring class or trait.
 98:      * @return \ReflectionClass
 99:      */
100:     public static function getPropertyDeclaringClass(\ReflectionProperty $prop)
101:     {
102:         foreach ($prop->getDeclaringClass()->getTraits() as $trait) {
103:             if ($trait->hasProperty($prop->getName())) {
104:                 return self::getPropertyDeclaringClass($trait->getProperty($prop->getName()));
105:             }
106:         }
107:         return $prop->getDeclaringClass();
108:     }
109: 
110: 
111:     /**
112:      * Are documentation comments available?
113:      * @return bool
114:      */
115:     public static function areCommentsAvailable()
116:     {
117:         static $res;
118:         return $res === NULL
119:             ? $res = (bool) (new \ReflectionMethod(__METHOD__))->getDocComment()
120:             : $res;
121:     }
122: 
123: 
124:     /**
125:      * @return string
126:      */
127:     public static function toString(\Reflector $ref)
128:     {
129:         if ($ref instanceof \ReflectionClass) {
130:             return $ref->getName();
131:         } elseif ($ref instanceof \ReflectionMethod) {
132:             return $ref->getDeclaringClass()->getName() . '::' . $ref->getName();
133:         } elseif ($ref instanceof \ReflectionFunction) {
134:             return $ref->getName();
135:         } elseif ($ref instanceof \ReflectionProperty) {
136:             return self::getPropertyDeclaringClass($ref)->getName() . '::$' . $ref->getName();
137:         } elseif ($ref instanceof \ReflectionParameter) {
138:             return '$' . $ref->getName() . ' in ' . self::toString($ref->getDeclaringFunction()) . '()';
139:         } else {
140:             throw new Nette\InvalidArgumentException;
141:         }
142:     }
143: 
144: 
145:     /**
146:      * Expands class name into full name.
147:      * @param  string
148:      * @return string  full name
149:      * @throws Nette\InvalidArgumentException
150:      */
151:     public static function expandClassName($name, \ReflectionClass $rc)
152:     {
153:         $lower = strtolower($name);
154:         if (empty($name)) {
155:             throw new Nette\InvalidArgumentException('Class name must not be empty.');
156: 
157:         } elseif (isset(self::$builtinTypes[$lower])) {
158:             return $lower;
159: 
160:         } elseif ($lower === 'self') {
161:             return $rc->getName();
162: 
163:         } elseif ($name[0] === '\\') { // fully qualified name
164:             return ltrim($name, '\\');
165:         }
166: 
167:         $uses = self::getUseStatements($rc);
168:         $parts = explode('\\', $name, 2);
169:         if (isset($uses[$parts[0]])) {
170:             $parts[0] = $uses[$parts[0]];
171:             return implode('\\', $parts);
172: 
173:         } elseif ($rc->inNamespace()) {
174:             return $rc->getNamespaceName() . '\\' . $name;
175: 
176:         } else {
177:             return $name;
178:         }
179:     }
180: 
181: 
182:     /**
183:      * @return array of [alias => class]
184:      */
185:     public static function getUseStatements(\ReflectionClass $class)
186:     {
187:         static $cache = [];
188:         if (!isset($cache[$name = $class->getName()])) {
189:             if ($class->isInternal()) {
190:                 $cache[$name] = [];
191:             } else {
192:                 $code = file_get_contents($class->getFileName());
193:                 $cache = self::parseUseStatements($code, $name) + $cache;
194:             }
195:         }
196:         return $cache[$name];
197:     }
198: 
199: 
200:     /**
201:      * Parses PHP code.
202:      * @param  string
203:      * @return array of [class => [alias => class, ...]]
204:      */
205:     private static function parseUseStatements($code, $forClass = NULL)
206:     {
207:         $tokens = token_get_all($code);
208:         $namespace = $class = $classLevel = $level = NULL;
209:         $res = $uses = [];
210: 
211:         while (list(, $token) = each($tokens)) {
212:             switch (is_array($token) ? $token[0] : $token) {
213:                 case T_NAMESPACE:
214:                     $namespace = ltrim(self::fetch($tokens, [T_STRING, T_NS_SEPARATOR]) . '\\', '\\');
215:                     $uses = [];
216:                     break;
217: 
218:                 case T_CLASS:
219:                 case T_INTERFACE:
220:                 case T_TRAIT:
221:                     if ($name = self::fetch($tokens, T_STRING)) {
222:                         $class = $namespace . $name;
223:                         $classLevel = $level + 1;
224:                         $res[$class] = $uses;
225:                         if ($class === $forClass) {
226:                             return $res;
227:                         }
228:                     }
229:                     break;
230: 
231:                 case T_USE:
232:                     while (!$class && ($name = self::fetch($tokens, [T_STRING, T_NS_SEPARATOR]))) {
233:                         $name = ltrim($name, '\\');
234:                         if (self::fetch($tokens, '{')) {
235:                             while ($suffix = self::fetch($tokens, [T_STRING, T_NS_SEPARATOR])) {
236:                                 if (self::fetch($tokens, T_AS)) {
237:                                     $uses[self::fetch($tokens, T_STRING)] = $name . $suffix;
238:                                 } else {
239:                                     $tmp = explode('\\', $suffix);
240:                                     $uses[end($tmp)] = $name . $suffix;
241:                                 }
242:                                 if (!self::fetch($tokens, ',')) {
243:                                     break;
244:                                 }
245:                             }
246: 
247:                         } elseif (self::fetch($tokens, T_AS)) {
248:                             $uses[self::fetch($tokens, T_STRING)] = $name;
249: 
250:                         } else {
251:                             $tmp = explode('\\', $name);
252:                             $uses[end($tmp)] = $name;
253:                         }
254:                         if (!self::fetch($tokens, ',')) {
255:                             break;
256:                         }
257:                     }
258:                     break;
259: 
260:                 case T_CURLY_OPEN:
261:                 case T_DOLLAR_OPEN_CURLY_BRACES:
262:                 case '{':
263:                     $level++;
264:                     break;
265: 
266:                 case '}':
267:                     if ($level === $classLevel) {
268:                         $class = $classLevel = NULL;
269:                     }
270:                     $level--;
271:             }
272:         }
273: 
274:         return $res;
275:     }
276: 
277: 
278:     private static function fetch(&$tokens, $take)
279:     {
280:         $res = NULL;
281:         while ($token = current($tokens)) {
282:             list($token, $s) = is_array($token) ? $token : [$token, $token];
283:             if (in_array($token, (array) $take, TRUE)) {
284:                 $res .= $s;
285:             } elseif (!in_array($token, [T_DOC_COMMENT, T_WHITESPACE, T_COMMENT], TRUE)) {
286:                 break;
287:             }
288:             next($tokens);
289:         }
290:         return $res;
291:     }
292: 
293: }
294: 
Nette 2.4-20170119 API API documentation generated by ApiGen 2.8.0