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