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;
11: use Nette\Utils\ObjectMixin;
12:
13:
14: /**
15: * Nette\Object is the ultimate ancestor of all instantiable classes.
16: *
17: * It defines some handful methods and enhances object core of PHP:
18: * - access to undeclared members throws exceptions
19: * - support for conventional properties with getters and setters
20: * - support for event raising functionality
21: * - ability to add new methods to class (extension methods)
22: *
23: * Properties is a syntactic sugar which allows access public getter and setter
24: * methods as normal object variables. A property is defined by a getter method
25: * or setter method (no setter method means read-only property).
26: * <code>
27: * $val = $obj->label; // equivalent to $val = $obj->getLabel();
28: * $obj->label = 'Nette'; // equivalent to $obj->setLabel('Nette');
29: * </code>
30: * Property names are case-sensitive, and they are written in the camelCaps
31: * or PascalCaps.
32: *
33: * Event functionality is provided by declaration of property named 'on{Something}'
34: * Multiple handlers are allowed.
35: * <code>
36: * public $onClick; // declaration in class
37: * $this->onClick[] = 'callback'; // attaching event handler
38: * if (!empty($this->onClick)) ... // are there any handlers?
39: * $this->onClick($sender, $arg); // raises the event with arguments
40: * </code>
41: *
42: * Adding method to class (i.e. to all instances) works similar to JavaScript
43: * prototype property. The syntax for adding a new method is:
44: * <code>
45: * MyClass::extensionMethod('newMethod', function (MyClass $obj, $arg, ...) { ... });
46: * $obj = new MyClass;
47: * $obj->newMethod($x);
48: * </code>
49: *
50: * @author David Grudl
51: *
52: * @property-read Nette\Reflection\ClassType|\ReflectionClass $reflection
53: */
54: abstract class Object
55: {
56:
57: /**
58: * Access to reflection.
59: * @return Nette\Reflection\ClassType|\ReflectionClass
60: */
61: public static function getReflection()
62: {
63: $class = class_exists('Nette\Reflection\ClassType') ? 'Nette\Reflection\ClassType' : 'ReflectionClass';
64: return new $class(get_called_class());
65: }
66:
67:
68: /**
69: * Call to undefined method.
70: * @param string method name
71: * @param array arguments
72: * @return mixed
73: * @throws MemberAccessException
74: */
75: public function __call($name, $args)
76: {
77: return ObjectMixin::call($this, $name, $args);
78: }
79:
80:
81: /**
82: * Call to undefined static method.
83: * @param string method name (in lower case!)
84: * @param array arguments
85: * @return mixed
86: * @throws MemberAccessException
87: */
88: public static function __callStatic($name, $args)
89: {
90: return ObjectMixin::callStatic(get_called_class(), $name, $args);
91: }
92:
93:
94: /**
95: * Adding method to class.
96: * @param string method name
97: * @param callable
98: * @return mixed
99: */
100: public static function extensionMethod($name, $callback = NULL)
101: {
102: if (strpos($name, '::') === FALSE) {
103: $class = get_called_class();
104: } else {
105: list($class, $name) = explode('::', $name);
106: $rc = new \ReflectionClass($class);
107: $class = $rc->getName();
108: }
109: if ($callback === NULL) {
110: return ObjectMixin::getExtensionMethod($class, $name);
111: } else {
112: ObjectMixin::setExtensionMethod($class, $name, $callback);
113: }
114: }
115:
116:
117: /**
118: * Returns property value. Do not call directly.
119: * @param string property name
120: * @return mixed property value
121: * @throws MemberAccessException if the property is not defined.
122: */
123: public function &__get($name)
124: {
125: return ObjectMixin::get($this, $name);
126: }
127:
128:
129: /**
130: * Sets value of a property. Do not call directly.
131: * @param string property name
132: * @param mixed property value
133: * @return void
134: * @throws MemberAccessException if the property is not defined or is read-only
135: */
136: public function __set($name, $value)
137: {
138: ObjectMixin::set($this, $name, $value);
139: }
140:
141:
142: /**
143: * Is property defined?
144: * @param string property name
145: * @return bool
146: */
147: public function __isset($name)
148: {
149: return ObjectMixin::has($this, $name);
150: }
151:
152:
153: /**
154: * Access to undeclared property.
155: * @param string property name
156: * @return void
157: * @throws MemberAccessException
158: */
159: public function __unset($name)
160: {
161: ObjectMixin::remove($this, $name);
162: }
163:
164: }
165: