Last active
September 2, 2021 21:27
-
-
Save goodevilgenius/c34b5027dc5d6fe6677d81b32bdd397d to your computer and use it in GitHub Desktop.
Revisions
-
goodevilgenius revised this gist
Sep 2, 2021 . 1 changed file with 12 additions and 15 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -49,41 +49,38 @@ public function __construct($classOrObject) [null, $classOrObject] : [null, null] ); } /** * Get the closure used by $this->__call. */ protected function getCaller(): \Closure { return $this->caller ??= ( $this->object ? fn (string $method, array $args) => $this->$method(...$args) : fn (string $method, array $args) => static::$method($args) )->bindTo($this->object, $this->class); } /** * Get the closure used by $this->__get. */ protected function getGetter(): \Closure { return $this->getter ??= ( $this->object ? fn (string $key) => $this->$key : fn (string $key) => static::$$key )->bindTo($this->object, $this->class); } /** * Get the closure used by $this->__set. */ protected function getSetter(): \Closure { return $this->setter ??= ( $this->object ? fn (string $key, $value) => $this->$key = $value : fn (string $key, $value) => static::$$key = $value @@ -100,17 +97,17 @@ public function call(callable $cb, ...$args) public function __call(string $method, array $args) { return ($this->getCaller())($method, $args); } public function __get(string $key) { return ($this->getGetter())($key); } public function __set(string $key, $value) { return ($this->getSetter())($key, $value); } } -
goodevilgenius revised this gist
Sep 2, 2021 . 1 changed file with 49 additions and 0 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,7 +1,34 @@ <?php /** * Method for accessing private/protected properties/methods without Reflection. * * This is particularly useful when debugging from the command-line, for example, with psysh. * * Static methods/properties can be accessed by passing the class instead. * Constants are not acccessible. * * Usage: * $object; * spy($object)->prop; // Return private prop on $object * * // These two lines are equivalent * $objSpy = spy($object); * $objSpy = new ClassProxy($object); * * $objSpy->protectedMethod($param1); * $objSpy->call(fn () => strtolower($this->prop)); // Returns lowercased version of private prop on $object * * spy(SomeClass::class)->staticProjectedProperty; */ declare(strict_types=1); /** * Proxies all calls to another object/class, via Closures. * * This allows access to private/protected methods and properties without Reflection. */ class ClassProxy { protected ?string $class; @@ -10,6 +37,9 @@ class ClassProxy protected Closure $getter; protected Closure $setter; /** * @param string|object $classOrObject */ public function __construct($classOrObject) { [$this->object, $this->class] = is_object($classOrObject) ? @@ -24,6 +54,9 @@ public function __construct($classOrObject) $this->initSetter(); } /** * Initialize the closure used by $this->__call. */ protected function initCaller(): void { $this->caller = ( @@ -33,6 +66,9 @@ protected function initCaller(): void )->bindTo($this->object, $this->class); } /** * Initialize the closure used by $this->__get. */ protected function initGetter(): void { $this->getter = ( @@ -42,6 +78,9 @@ protected function initGetter(): void )->bindTo($this->object, $this->class); } /** * Initialize the closure used by $this->__set. */ protected function initSetter(): void { $this->setter = ( @@ -51,6 +90,9 @@ protected function initSetter(): void )->bindTo($this->object, $this->class); } /** * Run arbitry code on object, with access to private/protected props/methods. */ public function call(callable $cb, ...$args) { return (\Closure::fromCallable($cb)->bindTo($this->object, $this->class))(...$args); @@ -72,6 +114,13 @@ public function __set(string $key, $value) } } /** * Instantiates a ClassProxy. * * Useful for quick spying. * * @param string|object $classOrObject */ function spy($classOrObject): ClassProxy { return new ClassProxy($classOrObject); -
goodevilgenius created this gist
Sep 2, 2021 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,78 @@ <?php declare(strict_types=1); class ClassProxy { protected ?string $class; protected ?object $object; protected Closure $caller; protected Closure $getter; protected Closure $setter; public function __construct($classOrObject) { [$this->object, $this->class] = is_object($classOrObject) ? [$classOrObject, get_class($classOrObject)] : ( is_string($classOrObject) && class_exists($classOrObject) ? [null, $classOrObject] : [null, null] ); $this->initCaller(); $this->initGetter(); $this->initSetter(); } protected function initCaller(): void { $this->caller = ( $this->object ? fn (string $method, array $args) => $this->$method(...$args) : fn (string $method, array $args) => static::$method($args) )->bindTo($this->object, $this->class); } protected function initGetter(): void { $this->getter = ( $this->object ? fn (string $key) => $this->$key : fn (string $key) => static::$$key )->bindTo($this->object, $this->class); } protected function initSetter(): void { $this->setter = ( $this->object ? fn (string $key, $value) => $this->$key = $value : fn (string $key, $value) => static::$$key = $value )->bindTo($this->object, $this->class); } public function call(callable $cb, ...$args) { return (\Closure::fromCallable($cb)->bindTo($this->object, $this->class))(...$args); } public function __call(string $method, array $args) { return ($this->caller)($method, $args); } public function __get(string $key) { return ($this->getter)($key); } public function __set(string $key, $value) { return ($this->setter)($key, $value); } } function spy($classOrObject): ClassProxy { return new ClassProxy($classOrObject); }