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

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

Interfaces

  • IHtmlString

Exceptions

  • AssertionException
  • ImageException
  • JsonException
  • RegexpException
  • TokenizerException
  • UnknownImageFileException
  • 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\Utils;
  9: 
 10: use Nette;
 11: use Nette\MemberAccessException;
 12: 
 13: 
 14: /**
 15:  * Nette\SmartObject helpers.
 16:  */
 17: final class ObjectHelpers
 18: {
 19:     use Nette\StaticClass;
 20: 
 21:     /**
 22:      * @throws MemberAccessException
 23:      */
 24:     public static function strictGet($class, $name)
 25:     {
 26:         $rc = new \ReflectionClass($class);
 27:         $hint = self::getSuggestion(array_merge(
 28:             array_filter($rc->getProperties(\ReflectionProperty::IS_PUBLIC), function ($p) { return !$p->isStatic(); }),
 29:             self::parseFullDoc($rc, '~^[ \t*]*@property(?:-read)?[ \t]+(?:\S+[ \t]+)??\$(\w+)~m')
 30:         ), $name);
 31:         throw new MemberAccessException("Cannot read an undeclared property $class::\$$name" . ($hint ? ", did you mean \$$hint?" : '.'));
 32:     }
 33: 
 34: 
 35:     /**
 36:      * @throws MemberAccessException
 37:      */
 38:     public static function strictSet($class, $name)
 39:     {
 40:         $rc = new \ReflectionClass($class);
 41:         $hint = self::getSuggestion(array_merge(
 42:             array_filter($rc->getProperties(\ReflectionProperty::IS_PUBLIC), function ($p) { return !$p->isStatic(); }),
 43:             self::parseFullDoc($rc, '~^[ \t*]*@property(?:-write)?[ \t]+(?:\S+[ \t]+)??\$(\w+)~m')
 44:         ), $name);
 45:         throw new MemberAccessException("Cannot write to an undeclared property $class::\$$name" . ($hint ? ", did you mean \$$hint?" : '.'));
 46:     }
 47: 
 48: 
 49:     /**
 50:      * @throws MemberAccessException
 51:      */
 52:     public static function strictCall($class, $method, $additionalMethods = [])
 53:     {
 54:         $hint = self::getSuggestion(array_merge(
 55:             get_class_methods($class),
 56:             self::parseFullDoc(new \ReflectionClass($class), '~^[ \t*]*@method[ \t]+(?:\S+[ \t]+)??(\w+)\(~m'),
 57:             $additionalMethods
 58:         ), $method);
 59: 
 60:         if (method_exists($class, $method)) { // called parent::$method()
 61:             $class = 'parent';
 62:         }
 63:         throw new MemberAccessException("Call to undefined method $class::$method()" . ($hint ? ", did you mean $hint()?" : '.'));
 64:     }
 65: 
 66: 
 67:     /**
 68:      * @throws MemberAccessException
 69:      */
 70:     public static function strictStaticCall($class, $method)
 71:     {
 72:         $hint = self::getSuggestion(
 73:             array_filter((new \ReflectionClass($class))->getMethods(\ReflectionMethod::IS_PUBLIC), function ($m) { return $m->isStatic(); }),
 74:             $method
 75:         );
 76:         throw new MemberAccessException("Call to undefined static method $class::$method()" . ($hint ? ", did you mean $hint()?" : '.'));
 77:     }
 78: 
 79: 
 80:     /**
 81:      * Returns array of magic properties defined by annotation @property.
 82:      * @return array of [name => bit mask]
 83:      * @internal
 84:      */
 85:     public static function getMagicProperties($class)
 86:     {
 87:         static $cache;
 88:         $props = &$cache[$class];
 89:         if ($props !== null) {
 90:             return $props;
 91:         }
 92: 
 93:         $rc = new \ReflectionClass($class);
 94:         preg_match_all(
 95:             '~^  [ \t*]*  @property(|-read|-write)  [ \t]+  [^\s$]+  [ \t]+  \$  (\w+)  ()~mx',
 96:             (string) $rc->getDocComment(), $matches, PREG_SET_ORDER
 97:         );
 98: 
 99:         $props = [];
100:         foreach ($matches as list(, $type, $name)) {
101:             $uname = ucfirst($name);
102:             $write = $type !== '-read'
103:                 && $rc->hasMethod($nm = 'set' . $uname)
104:                 && ($rm = $rc->getMethod($nm)) && $rm->getName() === $nm && !$rm->isPrivate() && !$rm->isStatic();
105:             $read = $type !== '-write'
106:                 && ($rc->hasMethod($nm = 'get' . $uname) || $rc->hasMethod($nm = 'is' . $uname))
107:                 && ($rm = $rc->getMethod($nm)) && $rm->getName() === $nm && !$rm->isPrivate() && !$rm->isStatic();
108: 
109:             if ($read || $write) {
110:                 $props[$name] = $read << 0 | ($nm[0] === 'g') << 1 | $rm->returnsReference() << 2 | $write << 3;
111:             }
112:         }
113: 
114:         foreach ($rc->getTraits() as $trait) {
115:             $props += self::getMagicProperties($trait->getName());
116:         }
117: 
118:         if ($parent = get_parent_class($class)) {
119:             $props += self::getMagicProperties($parent);
120:         }
121:         return $props;
122:     }
123: 
124: 
125:     /**
126:      * Finds the best suggestion (for 8-bit encoding).
127:      * @param  (\ReflectionFunctionAbstract|\ReflectionParameter|\ReflectionClass|\ReflectionProperty|string)[]
128:      * @internal
129:      */
130:     public static function getSuggestion(array $possibilities, $value)
131:     {
132:         $norm = preg_replace($re = '#^(get|set|has|is|add)(?=[A-Z])#', '', $value);
133:         $best = null;
134:         $min = (strlen($value) / 4 + 1) * 10 + .1;
135:         foreach (array_unique($possibilities, SORT_REGULAR) as $item) {
136:             $item = $item instanceof \Reflector ? $item->getName() : $item;
137:             if ($item !== $value && (
138:                 ($len = levenshtein($item, $value, 10, 11, 10)) < $min
139:                 || ($len = levenshtein(preg_replace($re, '', $item), $norm, 10, 11, 10) + 20) < $min
140:             )) {
141:                 $min = $len;
142:                 $best = $item;
143:             }
144:         }
145:         return $best;
146:     }
147: 
148: 
149:     private static function parseFullDoc(\ReflectionClass $rc, $pattern)
150:     {
151:         do {
152:             $doc[] = $rc->getDocComment();
153:             $traits = $rc->getTraits();
154:             while ($trait = array_pop($traits)) {
155:                 $doc[] = $trait->getDocComment();
156:                 $traits += $trait->getTraits();
157:             }
158:         } while ($rc = $rc->getParentClass());
159:         return preg_match_all($pattern, implode($doc), $m) ? $m[1] : [];
160:     }
161: 
162: 
163:     /**
164:      * Checks if the public non-static property exists.
165:      * @return bool|string returns 'event' if the property exists and has event like name
166:      * @internal
167:      */
168:     public static function hasProperty($class, $name)
169:     {
170:         static $cache;
171:         $prop = &$cache[$class][$name];
172:         if ($prop === null) {
173:             $prop = false;
174:             try {
175:                 $rp = new \ReflectionProperty($class, $name);
176:                 if ($rp->isPublic() && !$rp->isStatic()) {
177:                     $prop = $name >= 'onA' && $name < 'on_' ? 'event' : true;
178:                 }
179:             } catch (\ReflectionException $e) {
180:             }
181:         }
182:         return $prop;
183:     }
184: }
185: 
Nette 2.4-20180918 API API documentation generated by ApiGen 2.8.0