PluginProbe
FluentCommunity – Ultra-Fast High-Performance Social Network, Community, LMS & Online Courses / 2.6.0
FluentCommunity – Ultra-Fast High-Performance Social Network, Community, LMS & Online Courses v2.6.0
2.10.0 2.10.01 2.9.1 2.9.0 2.8.1 2.8.0 2.7.7 2.7.5 2.7.0 2.6.01 2.6.0 2.5.0 2.4.01 trunk 1.0.90 1.0.91 1.0.92 1.0.93 1.0.94 1.0.95 1.0.96 1.0.97 1.0.98 1.0.99 1.1.0 All 77 releases
fluent-community / vendor / wpfluent / framework / src / WPFluent / Support / Invoker.php

Invoker.php in FluentCommunity – Ultra-Fast High-Performance Social Network, Community, LMS & Online Courses 2.6.0, at vendor/wpfluent/framework/src/WPFluent/Support/Invoker.php

187 lines 6.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /**
4 * Invoker Class — Overview and Usage Guide
5 *
6 * What is the Invoker class?
7 *
8 * The Invoker class is a utility helper that allows you to access and
9 * manipulate private and protected properties and methods of PHP
10 * objects and classes at runtime. It uses PHP’s Closure
11 * binding and Reflection API under the hood.
12 *
13 * This is especially useful when working with third-party or legacy code where
14 * you don’t have control over visibility or public APIs, but still need to
15 * read/write internal state or call hidden methods for testing,
16 * debugging, or extending functionality.
17 *
18 * Key Features:
19 * - Access private/protected instance properties
20 * — read or modify values not exposed publicly.
21 *
22 * - Call private/protected instance methods
23 * — invoke internal methods not accessible otherwise.
24 *
25 * - Access private/protected static properties on classes.
26 * - Call private/protected static methods on classes.
27 * - Unified static API for all operations
28 * — no need to instantiate the Invoker class.
29 *
30 * - Direct closure binding through invoke() for custom, complex access scenarios.
31 *
32 * When to use the Invoker class?
33 * - When you need to test or debug classes with private/protected members.
34 * - When working with third-party libraries or legacy code where
35 * you can't change visibility.
36 *
37 * - For unit tests that require access to internal state or behaviors.
38 * - When you want to extend or patch behavior of an existing
39 * class without modifying its source.
40 *
41 * - When you want to inspect or manipulate class internals safely without
42 * reflection boilerplate scattered everywhere.
43 *
44 *
45 * Examples of using Invoker:
46 *
47 * // Access private/protected instance properties
48 * $value = Invoker::get($object, 'propertyName');
49 * Invoker::set($object, 'propertyName', $newValue);
50 *
51 * // Call private/protected instance methods
52 * $result = Invoker::call($object, 'methodName', [$arg1, $arg2]);
53 *
54 * // Access private/protected static properties
55 * $value = Invoker::getStatic(ClassName::class, 'staticProperty');
56 * Invoker::setStatic(ClassName::class, 'staticProperty', $newValue);
57 *
58 * // Call private/protected static methods
59 * $result = Invoker::callStatic(ClassName::class, 'staticMethod', [$arg1, $arg2]);
60 *
61 * // Use custom closure binding for complex scenarios
62 * $result = Invoker::invoke($object, function () {
63 * // $this references the bound object instance
64 * return $this->somePrivateProperty + 42;
65 * });
66 */
67
68
69 namespace FluentCommunity\Framework\Support;
70
71 use Closure;
72 use ReflectionClass;
73 use ReflectionMethod;
74
75 class Invoker
76 {
77 /**
78 * Get the value of a private or protected property from an object.
79 *
80 * @param object $object The object instance to read property from.
81 * @param string $property The property name to access.
82 * @return mixed The value of the property.
83 */
84 public static function get($object, $property)
85 {
86 return static::invoke($object, function () use ($property) {
87 // @phpstan-ignore-next-line
88 return $this->$property;
89 });
90 }
91
92 /**
93 * Set the value of a private or protected property on an object.
94 *
95 * @param object $object The object instance to set property on.
96 * @param string $property The property name to modify.
97 * @param mixed $value The value to assign to the property.
98 * @return void
99 */
100 public static function set($object, $property, $value)
101 {
102 static::invoke($object, function () use ($property, $value) {
103 // @phpstan-ignore-next-line
104 $this->$property = $value;
105 });
106 }
107
108 /**
109 * Call a private or protected method on an object.
110 *
111 * @param object $object The object instance to call method on.
112 * @param string $method The method name to invoke.
113 * @param array $args Optional array of arguments to pass to the method.
114 * @return mixed The result returned by the method.
115 */
116 public static function call($object, $method, $args = [])
117 {
118 return static::invoke($object, function () use ($method, $args) {
119 // @phpstan-ignore-next-line
120 return call_user_func_array([$this, $method], $args);
121 });
122 }
123
124 /**
125 * Get the value of a private or protected static property on a class.
126 *
127 * @param string $class The fully qualified class name.
128 * @param string $property The static property name.
129 * @return mixed The value of the static property.
130 * @throws \ReflectionException When the property does not exist.
131 */
132 public static function getStatic($class, $property)
133 {
134 $ref = new ReflectionClass($class);
135 $prop = $ref->getProperty($property);
136 $prop->setAccessible(true);
137 return $prop->getValue();
138 }
139
140 /**
141 * Set the value of a private or protected static property on a class.
142 *
143 * @param string $class The fully qualified class name.
144 * @param string $property The static property name.
145 * @param mixed $value The value to assign to the static property.
146 * @return void
147 * @throws \ReflectionException When the property does not exist.
148 */
149 public static function setStatic($class, $property, $value)
150 {
151 $ref = new ReflectionClass($class);
152 $prop = $ref->getProperty($property);
153 $prop->setAccessible(true);
154 $prop->setValue(null, $value);
155 }
156
157 /**
158 * Call a private or protected static method on a class.
159 *
160 * @param string $class The fully qualified class name.
161 * @param string $method The static method name to invoke.
162 * @param array $args Optional array of arguments to pass to the method.
163 * @return mixed The result returned by the static method.
164 * @throws \ReflectionException When the method does not exist.
165 */
166 public static function callStatic($class, $method, $args = [])
167 {
168 $ref = new ReflectionMethod($class, $method);
169 $ref->setAccessible(true);
170 return $ref->invokeArgs(null, $args);
171 }
172
173 /**
174 * Bind a closure to an object and invoke it with optional arguments.
175 *
176 * @param object $object The object to bind the closure to.
177 * @param Closure $closure The closure to bind and invoke.
178 * @param mixed ...$args Optional arguments to pass to the closure.
179 * @return mixed The result returned by the closure.
180 */
181 public static function invoke($object, $closure, ...$args)
182 {
183 $bound = Closure::bind($closure, $object, get_class($object));
184 return call_user_func_array($bound, $args);
185 }
186 }
187