1919 * - access to undeclared members throws exceptions
2020 * - support for @property annotations
2121 * - support for calling event handlers stored in $onEvent via onEvent()
22- * - compatible with Nette\Object
2322 */
2423trait SmartObject
2524{
@@ -31,12 +30,8 @@ trait SmartObject
3130 public function __call ($ name , $ args )
3231 {
3332 $ class = get_class ($ this );
34- $ isProp = ObjectMixin::hasProperty ($ class , $ name );
3533
36- if ($ name === '' ) {
37- throw new MemberAccessException ("Call to class ' $ class' method without name. " );
38-
39- } elseif ($ isProp === 'event ' ) { // calling event handlers
34+ if (ObjectMixin::hasProperty ($ class , $ name ) === 'event ' ) { // calling event handlers
4035 if (is_array ($ this ->$ name ) || $ this ->$ name instanceof \Traversable) {
4136 foreach ($ this ->$ name as $ handler ) {
4237 Callback::invokeArgs ($ handler , $ args );
@@ -45,35 +40,6 @@ public function __call($name, $args)
4540 throw new UnexpectedValueException ("Property $ class::$ $ name must be array or NULL, " . gettype ($ this ->$ name ) . ' given. ' );
4641 }
4742
48- } elseif ($ isProp && $ this ->$ name instanceof \Closure) { // closure in property
49- trigger_error ("Invoking closure in property via \$obj-> $ name() is deprecated " . ObjectMixin::getSource (), E_USER_DEPRECATED );
50- return call_user_func_array ($ this ->$ name , $ args );
51-
52- } elseif (($ methods = &ObjectMixin::getMethods ($ class )) && isset ($ methods [$ name ]) && is_array ($ methods [$ name ])) { // magic @methods
53- trigger_error ("Magic methods such as $ class:: $ name() are deprecated " . ObjectMixin::getSource (), E_USER_DEPRECATED );
54- list ($ op , $ rp , $ type ) = $ methods [$ name ];
55- if (count ($ args ) !== ($ op === 'get ' ? 0 : 1 )) {
56- throw new InvalidArgumentException ("$ class:: $ name() expects " . ($ op === 'get ' ? 'no ' : '1 ' ) . ' argument, ' . count ($ args ) . ' given. ' );
57-
58- } elseif ($ type && $ args && !ObjectMixin::checkType ($ args [0 ], $ type )) {
59- throw new InvalidArgumentException ("Argument passed to $ class:: $ name() must be $ type, " . gettype ($ args [0 ]) . ' given. ' );
60- }
61-
62- if ($ op === 'get ' ) {
63- return $ rp ->getValue ($ this );
64- } elseif ($ op === 'set ' ) {
65- $ rp ->setValue ($ this , $ args [0 ]);
66- } elseif ($ op === 'add ' ) {
67- $ val = $ rp ->getValue ($ this );
68- $ val [] = $ args [0 ];
69- $ rp ->setValue ($ this , $ val );
70- }
71- return $ this ;
72-
73- } elseif ($ cb = ObjectMixin::getExtensionMethod ($ class , $ name )) { // extension methods
74- trigger_error ("Extension methods such as $ class:: $ name() are deprecated " . ObjectMixin::getSource (), E_USER_DEPRECATED );
75- return Callback::invoke ($ cb , $ this , ...$ args );
76-
7743 } else {
7844 ObjectMixin::strictCall ($ class , $ name );
7945 }
@@ -97,43 +63,18 @@ public static function __callStatic($name, $args)
9763 public function &__get ($ name )
9864 {
9965 $ class = get_class ($ this );
100- $ uname = ucfirst ($ name );
10166
102- if ($ prop = ObjectMixin::getMagicProperty ($ class, $ name) ) { // property getter
67+ if ($ prop = ObjectMixin::getMagicProperties ($ class)[ $ name] ?? NULL ) { // property getter
10368 if (!($ prop & 0b0001 )) {
10469 throw new MemberAccessException ("Cannot read a write-only property $ class:: \$$ name. " );
10570 }
106- $ m = ($ prop & 0b0010 ? 'get ' : 'is ' ) . $ uname ;
71+ $ m = ($ prop & 0b0010 ? 'get ' : 'is ' ) . $ name ;
10772 if ($ prop & 0b0100 ) { // return by reference
10873 return $ this ->$ m ();
10974 } else {
11075 $ val = $ this ->$ m ();
11176 return $ val ;
11277 }
113-
114- } elseif ($ name === '' ) {
115- throw new MemberAccessException ("Cannot read a class ' $ class' property without name. " );
116-
117- } elseif (($ methods = &ObjectMixin::getMethods ($ class )) && isset ($ methods [$ m = 'get ' . $ uname ]) || isset ($ methods [$ m = 'is ' . $ uname ])) { // old property getter
118- trigger_error ("Add annotation @property for $ class:: \$$ name or use $ m() " . ObjectMixin::getSource (), E_USER_DEPRECATED );
119- if ($ methods [$ m ] === 0 ) {
120- $ methods [$ m ] = (new \ReflectionMethod ($ class , $ m ))->returnsReference ();
121- }
122- if ($ methods [$ m ] === TRUE ) {
123- return $ this ->$ m ();
124- } else {
125- $ val = $ this ->$ m ();
126- return $ val ;
127- }
128-
129- } elseif (isset ($ methods [$ name ])) { // public method as closure getter
130- trigger_error ("Accessing methods as properties via \$obj-> $ name is deprecated " . ObjectMixin::getSource (), E_USER_DEPRECATED );
131- $ val = Callback::closure ($ this , $ name );
132- return $ val ;
133-
134- } elseif (isset ($ methods ['set ' . $ uname ])) { // property getter
135- throw new MemberAccessException ("Cannot read a write-only property $ class:: \$$ name. " );
136-
13778 } else {
13879 ObjectMixin::strictGet ($ class , $ name );
13980 }
@@ -147,27 +88,16 @@ public function &__get($name)
14788 public function __set ($ name , $ value )
14889 {
14990 $ class = get_class ($ this );
150- $ uname = ucfirst ($ name );
15191
15292 if (ObjectMixin::hasProperty ($ class , $ name )) { // unsetted property
15393 $ this ->$ name = $ value ;
15494
155- } elseif ($ prop = ObjectMixin::getMagicProperty ($ class, $ name) ) { // property setter
95+ } elseif ($ prop = ObjectMixin::getMagicProperties ($ class)[ $ name] ?? NULL ) { // property setter
15696 if (!($ prop & 0b1000 )) {
15797 throw new MemberAccessException ("Cannot write to a read-only property $ class:: \$$ name. " );
15898 }
15999 $ this ->{'set ' . $ name }($ value );
160100
161- } elseif ($ name === '' ) {
162- throw new MemberAccessException ("Cannot write to a class ' $ class' property without name. " );
163-
164- } elseif (($ methods = &ObjectMixin::getMethods ($ class )) && isset ($ methods [$ m = 'set ' . $ uname ])) { // old property setter
165- trigger_error ("Add annotation @property for $ class:: \$$ name or use $ m() " . ObjectMixin::getSource (), E_USER_DEPRECATED );
166- $ this ->$ m ($ value );
167-
168- } elseif (isset ($ methods ['get ' . $ uname ]) || isset ($ methods ['is ' . $ uname ])) { // property setter
169- throw new MemberAccessException ("Cannot write to a read-only property $ class:: \$$ name. " );
170-
171101 } else {
172102 ObjectMixin::strictSet ($ class , $ name );
173103 }
@@ -192,42 +122,7 @@ public function __unset($name)
192122 */
193123 public function __isset ($ name )
194124 {
195- $ uname = ucfirst ($ name );
196- return ObjectMixin::getMagicProperty (get_class ($ this ), $ name )
197- || ($ name !== '' && ($ methods = ObjectMixin::getMethods (get_class ($ this ))) && (isset ($ methods ['get ' . $ uname ]) || isset ($ methods ['is ' . $ uname ])));
198- }
199-
200-
201- /**
202- * @return Reflection\ClassType|\ReflectionClass
203- * @deprecated
204- */
205- public static function getReflection (): \ReflectionClass
206- {
207- trigger_error (get_called_class () . '::getReflection() is deprecated ' . ObjectMixin::getSource (), E_USER_DEPRECATED );
208- $ class = class_exists (Reflection \ClassType::class) ? Reflection \ClassType::class : \ReflectionClass::class;
209- return new $ class (get_called_class ());
210- }
211-
212-
213- /**
214- * @return mixed
215- * @deprecated use Nette\Utils\ObjectMixin::setExtensionMethod()
216- */
217- public static function extensionMethod (string $ name , $ callback = NULL )
218- {
219- if (strpos ($ name , ':: ' ) === FALSE ) {
220- $ class = get_called_class ();
221- } else {
222- list ($ class , $ name ) = explode (':: ' , $ name );
223- $ class = (new \ReflectionClass ($ class ))->getName ();
224- }
225- trigger_error ("Extension methods such as $ class:: $ name() are deprecated " . ObjectMixin::getSource (), E_USER_DEPRECATED );
226- if ($ callback === NULL ) {
227- return ObjectMixin::getExtensionMethod ($ class , $ name );
228- } else {
229- ObjectMixin::setExtensionMethod ($ class , $ name , $ callback );
230- }
125+ return isset (ObjectMixin::getMagicProperties (get_class ($ this ))[$ name ]);
231126 }
232127
233128}
0 commit comments