Subversion-Projekte lars-tiefland.laravel_shop

Revision

Revision 148 | Details | Vergleich mit vorheriger | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
148 lars 1
<?php
2
 
3
/*
4
 * This file is part of Psy Shell.
5
 *
200 lars 6
 * (c) 2012-2023 Justin Hileman
148 lars 7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
 
12
namespace Psy;
13
 
14
/**
15
 * Helpers for bypassing visibility restrictions, mostly used in code generated
16
 * by the `sudo` command.
17
 */
18
class Sudo
19
{
20
    /**
21
     * Fetch a property of an object, bypassing visibility restrictions.
22
     *
23
     * @param object $object
24
     * @param string $property property name
25
     *
26
     * @return mixed Value of $object->property
27
     */
28
    public static function fetchProperty($object, string $property)
29
    {
30
        $prop = self::getProperty(new \ReflectionObject($object), $property);
31
 
32
        return $prop->getValue($object);
33
    }
34
 
35
    /**
36
     * Assign the value of a property of an object, bypassing visibility restrictions.
37
     *
38
     * @param object $object
39
     * @param string $property property name
40
     * @param mixed  $value
41
     *
42
     * @return mixed Value of $object->property
43
     */
44
    public static function assignProperty($object, string $property, $value)
45
    {
46
        $prop = self::getProperty(new \ReflectionObject($object), $property);
47
        $prop->setValue($object, $value);
48
 
49
        return $value;
50
    }
51
 
52
    /**
53
     * Call a method on an object, bypassing visibility restrictions.
54
     *
55
     * @param object $object
56
     * @param string $method  method name
57
     * @param mixed  $args...
58
     *
59
     * @return mixed
60
     */
61
    public static function callMethod($object, string $method, ...$args)
62
    {
63
        $refl = new \ReflectionObject($object);
64
        $reflMethod = $refl->getMethod($method);
65
        $reflMethod->setAccessible(true);
66
 
67
        return $reflMethod->invokeArgs($object, $args);
68
    }
69
 
70
    /**
71
     * Fetch a property of a class, bypassing visibility restrictions.
72
     *
73
     * @param string|object $class    class name or instance
74
     * @param string        $property property name
75
     *
76
     * @return mixed Value of $class::$property
77
     */
78
    public static function fetchStaticProperty($class, string $property)
79
    {
80
        $prop = self::getProperty(new \ReflectionClass($class), $property);
81
        $prop->setAccessible(true);
82
 
83
        return $prop->getValue();
84
    }
85
 
86
    /**
87
     * Assign the value of a static property of a class, bypassing visibility restrictions.
88
     *
89
     * @param string|object $class    class name or instance
90
     * @param string        $property property name
91
     * @param mixed         $value
92
     *
93
     * @return mixed Value of $class::$property
94
     */
95
    public static function assignStaticProperty($class, string $property, $value)
96
    {
97
        $prop = self::getProperty(new \ReflectionClass($class), $property);
98
        $prop->setValue($value);
99
 
100
        return $value;
101
    }
102
 
103
    /**
104
     * Call a static method on a class, bypassing visibility restrictions.
105
     *
106
     * @param string|object $class   class name or instance
107
     * @param string        $method  method name
108
     * @param mixed         $args...
109
     *
110
     * @return mixed
111
     */
112
    public static function callStatic($class, string $method, ...$args)
113
    {
114
        $refl = new \ReflectionClass($class);
115
        $reflMethod = $refl->getMethod($method);
116
        $reflMethod->setAccessible(true);
117
 
118
        return $reflMethod->invokeArgs(null, $args);
119
    }
120
 
121
    /**
122
     * Fetch a class constant, bypassing visibility restrictions.
123
     *
124
     * @param string|object $class class name or instance
125
     * @param string        $const constant name
126
     *
127
     * @return mixed
128
     */
129
    public static function fetchClassConst($class, string $const)
130
    {
131
        $refl = new \ReflectionClass($class);
132
 
133
        do {
134
            if ($refl->hasConstant($const)) {
135
                return $refl->getConstant($const);
136
            }
137
 
138
            $refl = $refl->getParentClass();
139
        } while ($refl !== false);
140
 
141
        return false;
142
    }
143
 
144
    /**
145
     * Construct an instance of a class, bypassing private constructors.
146
     *
147
     * @param string $class   class name
148
     * @param mixed  $args...
149
     */
150
    public static function newInstance(string $class, ...$args)
151
    {
152
        $refl = new \ReflectionClass($class);
153
        $instance = $refl->newInstanceWithoutConstructor();
154
 
155
        $constructor = $refl->getConstructor();
156
        $constructor->setAccessible(true);
157
        $constructor->invokeArgs($instance, $args);
158
 
159
        return $instance;
160
    }
161
 
162
    /**
163
     * Get a ReflectionProperty from an object (or its parent classes).
164
     *
165
     * @throws \ReflectionException if neither the object nor any of its parents has this property
166
     *
167
     * @param \ReflectionClass $refl
168
     * @param string           $property property name
169
     *
170
     * @return \ReflectionProperty
171
     */
172
    private static function getProperty(\ReflectionClass $refl, string $property): \ReflectionProperty
173
    {
174
        $firstException = null;
175
        do {
176
            try {
177
                $prop = $refl->getProperty($property);
178
                $prop->setAccessible(true);
179
 
180
                return $prop;
181
            } catch (\ReflectionException $e) {
182
                if ($firstException === null) {
183
                    $firstException = $e;
184
                }
185
 
186
                $refl = $refl->getParentClass();
187
            }
188
        } while ($refl !== false);
189
 
190
        throw $firstException;
191
    }
192
}