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

Classes

  • Configurator
  • Framework
  • Object

Traits

  • SmartObject
  • StaticClass

Exceptions

  • ArgumentOutOfRangeException
  • DeprecatedException
  • DirectoryNotFoundException
  • FileNotFoundException
  • InvalidArgumentException
  • InvalidStateException
  • IOException
  • MemberAccessException
  • NotImplementedException
  • NotSupportedException
  • OutOfRangeException
  • StaticClassException
  • UnexpectedValueException
  • 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;
  9: 
 10: use Nette\Utils\Callback;
 11: use Nette\Utils\ObjectMixin;
 12: 
 13: 
 14: /**
 15:  * Strict class for better experience.
 16:  * - 'did you mean' hints
 17:  * - access to undeclared members throws exceptions
 18:  * - support for @property annotations
 19:  * - support for calling event handlers stored in $onEvent via onEvent()
 20:  * - compatible with Nette\Object
 21:  */
 22: trait SmartObject
 23: {
 24: 
 25:     /**
 26:      * @return mixed
 27:      * @throws MemberAccessException
 28:      */
 29:     public function __call($name, $args)
 30:     {
 31:         $class = get_class($this);
 32:         $isProp = ObjectMixin::hasProperty($class, $name);
 33: 
 34:         if ($name === '') {
 35:             throw new MemberAccessException("Call to class '$class' method without name.");
 36: 
 37:         } elseif ($isProp === 'event') { // calling event handlers
 38:             if (is_array($this->$name) || $this->$name instanceof \Traversable) {
 39:                 foreach ($this->$name as $handler) {
 40:                     Callback::invokeArgs($handler, $args);
 41:                 }
 42:             } elseif ($this->$name !== null) {
 43:                 throw new UnexpectedValueException("Property $class::$$name must be array or null, " . gettype($this->$name) . ' given.');
 44:             }
 45: 
 46:         } elseif ($isProp && $this->$name instanceof \Closure) { // closure in property
 47:             trigger_error("Invoking closure in property via \$obj->$name() is deprecated" . ObjectMixin::getSource(), E_USER_DEPRECATED);
 48:             return call_user_func_array($this->$name, $args);
 49: 
 50:         } elseif (($methods = &ObjectMixin::getMethods($class)) && isset($methods[$name]) && is_array($methods[$name])) { // magic @methods
 51:             trigger_error("Magic methods such as $class::$name() are deprecated" . ObjectMixin::getSource(), E_USER_DEPRECATED);
 52:             list($op, $rp, $type) = $methods[$name];
 53:             if (count($args) !== ($op === 'get' ? 0 : 1)) {
 54:                 throw new InvalidArgumentException("$class::$name() expects " . ($op === 'get' ? 'no' : '1') . ' argument, ' . count($args) . ' given.');
 55: 
 56:             } elseif ($type && $args && !ObjectMixin::checkType($args[0], $type)) {
 57:                 throw new InvalidArgumentException("Argument passed to $class::$name() must be $type, " . gettype($args[0]) . ' given.');
 58:             }
 59: 
 60:             if ($op === 'get') {
 61:                 return $rp->getValue($this);
 62:             } elseif ($op === 'set') {
 63:                 $rp->setValue($this, $args[0]);
 64:             } elseif ($op === 'add') {
 65:                 $val = $rp->getValue($this);
 66:                 $val[] = $args[0];
 67:                 $rp->setValue($this, $val);
 68:             }
 69:             return $this;
 70: 
 71:         } elseif ($cb = ObjectMixin::getExtensionMethod($class, $name)) { // extension methods
 72:             trigger_error("Extension methods such as $class::$name() are deprecated" . ObjectMixin::getSource(), E_USER_DEPRECATED);
 73:             return Callback::invoke($cb, $this, ...$args);
 74: 
 75:         } else {
 76:             ObjectMixin::strictCall($class, $name);
 77:         }
 78:     }
 79: 
 80: 
 81:     /**
 82:      * @return void
 83:      * @throws MemberAccessException
 84:      */
 85:     public static function __callStatic($name, $args)
 86:     {
 87:         ObjectMixin::strictStaticCall(get_called_class(), $name);
 88:     }
 89: 
 90: 
 91:     /**
 92:      * @return mixed   property value
 93:      * @throws MemberAccessException if the property is not defined.
 94:      */
 95:     public function &__get($name)
 96:     {
 97:         $class = get_class($this);
 98:         $uname = ucfirst($name);
 99: 
100:         if ($prop = ObjectMixin::getMagicProperty($class, $name)) { // property getter
101:             if (!($prop & 0b0001)) {
102:                 throw new MemberAccessException("Cannot read a write-only property $class::\$$name.");
103:             }
104:             $m = ($prop & 0b0010 ? 'get' : 'is') . $uname;
105:             if ($prop & 0b0100) { // return by reference
106:                 return $this->$m();
107:             } else {
108:                 $val = $this->$m();
109:                 return $val;
110:             }
111: 
112:         } elseif ($name === '') {
113:             throw new MemberAccessException("Cannot read a class '$class' property without name.");
114: 
115:         } elseif (($methods = &ObjectMixin::getMethods($class)) && isset($methods[$m = 'get' . $uname]) || isset($methods[$m = 'is' . $uname])) { // old property getter
116:             trigger_error("Use $m() or add annotation @property for $class::\$$name" . ObjectMixin::getSource(), E_USER_DEPRECATED);
117:             if ($methods[$m] === 0) {
118:                 $methods[$m] = (new \ReflectionMethod($class, $m))->returnsReference();
119:             }
120:             if ($methods[$m] === true) {
121:                 return $this->$m();
122:             } else {
123:                 $val = $this->$m();
124:                 return $val;
125:             }
126: 
127:         } elseif (isset($methods[$name])) { // public method as closure getter
128:             trigger_error("Accessing methods as properties via \$obj->$name is deprecated" . ObjectMixin::getSource(), E_USER_DEPRECATED);
129:             $val = Callback::closure($this, $name);
130:             return $val;
131: 
132:         } elseif (isset($methods['set' . $uname])) { // property getter
133:             throw new MemberAccessException("Cannot read a write-only property $class::\$$name.");
134: 
135:         } else {
136:             ObjectMixin::strictGet($class, $name);
137:         }
138:     }
139: 
140: 
141:     /**
142:      * @return void
143:      * @throws MemberAccessException if the property is not defined or is read-only
144:      */
145:     public function __set($name, $value)
146:     {
147:         $class = get_class($this);
148:         $uname = ucfirst($name);
149: 
150:         if (ObjectMixin::hasProperty($class, $name)) { // unsetted property
151:             $this->$name = $value;
152: 
153:         } elseif ($prop = ObjectMixin::getMagicProperty($class, $name)) { // property setter
154:             if (!($prop & 0b1000)) {
155:                 throw new MemberAccessException("Cannot write to a read-only property $class::\$$name.");
156:             }
157:             $this->{'set' . $name}($value);
158: 
159:         } elseif ($name === '') {
160:             throw new MemberAccessException("Cannot write to a class '$class' property without name.");
161: 
162:         } elseif (($methods = &ObjectMixin::getMethods($class)) && isset($methods[$m = 'set' . $uname])) { // old property setter
163:             trigger_error("Use $m() or add annotation @property for $class::\$$name" . ObjectMixin::getSource(), E_USER_DEPRECATED);
164:             $this->$m($value);
165: 
166:         } elseif (isset($methods['get' . $uname]) || isset($methods['is' . $uname])) { // property setter
167:             throw new MemberAccessException("Cannot write to a read-only property $class::\$$name.");
168: 
169:         } else {
170:             ObjectMixin::strictSet($class, $name);
171:         }
172:     }
173: 
174: 
175:     /**
176:      * @return void
177:      * @throws MemberAccessException
178:      */
179:     public function __unset($name)
180:     {
181:         $class = get_class($this);
182:         if (!ObjectMixin::hasProperty($class, $name)) {
183:             throw new MemberAccessException("Cannot unset the property $class::\$$name.");
184:         }
185:     }
186: 
187: 
188:     /**
189:      * @return bool
190:      */
191:     public function __isset($name)
192:     {
193:         $uname = ucfirst($name);
194:         return ObjectMixin::getMagicProperty(get_class($this), $name)
195:             || ($name !== '' && ($methods = ObjectMixin::getMethods(get_class($this))) && (isset($methods['get' . $uname]) || isset($methods['is' . $uname])));
196:     }
197: 
198: 
199:     /**
200:      * @return Reflection\ClassType|\ReflectionClass
201:      * @deprecated
202:      */
203:     public static function getReflection()
204:     {
205:         trigger_error(get_called_class() . '::getReflection() is deprecated' . ObjectMixin::getSource(), E_USER_DEPRECATED);
206:         $class = class_exists(Reflection\ClassType::class) ? Reflection\ClassType::class : \ReflectionClass::class;
207:         return new $class(get_called_class());
208:     }
209: 
210: 
211:     /**
212:      * @return mixed
213:      * @deprecated use Nette\Utils\ObjectMixin::setExtensionMethod()
214:      */
215:     public static function extensionMethod($name, $callback = null)
216:     {
217:         if (strpos($name, '::') === false) {
218:             $class = get_called_class();
219:         } else {
220:             list($class, $name) = explode('::', $name);
221:             $class = (new \ReflectionClass($class))->getName();
222:         }
223:         trigger_error("Extension methods such as $class::$name() are deprecated" . ObjectMixin::getSource(), E_USER_DEPRECATED);
224:         if ($callback === null) {
225:             return ObjectMixin::getExtensionMethod($class, $name);
226:         } else {
227:             ObjectMixin::setExtensionMethod($class, $name, $callback);
228:         }
229:     }
230: }
231: 
Nette 2.4-20170829 API API documentation generated by ApiGen 2.8.0