ReflectionUtilities::setProperty()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 13
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 2

Importance

Changes 2
Bugs 1 Features 1
Metric Value
cc 2
eloc 8
c 2
b 1
f 1
nc 2
nop 3
dl 0
loc 13
ccs 8
cts 8
cp 1
crap 2
rs 9.4285
1
<?php namespace BuildR\TestTools\Traits;
2
3
use BuildR\Foundation\Exception\Exception;
4
use ReflectionClass;
5
use ReflectionObject;
6
7
/**
8
 * Common trait that contains helper function to working with PHP reflection API
9
 *
10
 * BuildR PHP Framework
11
 *
12
 * @author Zoltán Borsos <[email protected]>
13
 * @package TestTools
14
 * @subpackage Traits
15
 *
16
 * @copyright    Copyright 2016, Zoltán Borsos.
17
 * @license      https://github.com/BuildrPHP/Test-Tools/blob/master/LICENSE.md
18
 * @link         https://github.com/BuildrPHP/Test-Tools
19
 */
20
trait ReflectionUtilities {
21
22
    /**
23
     * Read a property value from a given class or concrete object. This function can handle automatic creation
24
     * of new instances of the given class.
25
     *
26
     * If no concrete object provided and the 'callConstructor' option is FALSE reads the property default value
27
     * from the class.
28
     *
29
     * If a concrete object is provided returns the property value from the given concrete object.
30
     *
31
     * If the 'callConstructor' is TRUE and concrete object is not provided this method try to instantiate a
32
     * new object from thi given class using the 'constructorParams' option.
33
     *
34
     * options:
35
     * 'callConstructor' => bool
36
     * 'constructorParams' => array (key is variable name, value is the value of the variable)
37
     *
38
     * @param string $className The FQCN
39
     * @param string $propertyName The property name
40
     * @param object|NULL $concreteClass Optionally concrete class
41
     * @param array $options Options defined as an array
42
     *
43
     * @return NULL|mixed
44
     */
45 2
    public function getPropertyValue($className, $propertyName, $concreteClass = NULL, $options = []) {
46 2
        $callConstructor = (isset($options['callConstructor'])) ? (bool) $options['callConstructor'] : FALSE;
47 2
        $reflector = new ReflectionClass($className);
48
49
        //This is a default property
50 2
        if($concreteClass === NULL && $callConstructor === FALSE) {
51 1
            $properties = $reflector->getDefaultProperties();
52
53 1
            return (isset($properties[$propertyName])) ? $properties[$propertyName] : NULL;
54
        }
55
56
        //Return NULL if this class not has the given property
57 2
        if(!$reflector->hasProperty($propertyName)) {
58 1
            return NULL;
59
        }
60
61
        //Get reflector for property and set it accessible
62 2
        $propertyReflector = $reflector->getProperty($propertyName);
63 2
        $propertyReflector->setAccessible(TRUE);
64
65
        //If we give a concrete class returns the value from this class
66 2
        if($concreteClass !== NULL) {
67 2
            return $propertyReflector->getValue($concreteClass);
68
        }
69
70
        //Needs to call the class constructor
71 1
        if($callConstructor === TRUE) {
72 1
            $constructorParams = (isset($options['constructorParams'])) ? (array) $options['constructorParams'] : [];
73
74 1
            return $propertyReflector->getValue($reflector->newInstanceArgs($constructorParams));
75
        }
76
77
        //This should never happen
78
        //@codeCoverageIgnoreStart
79
        return NULL;
80
        //@codeCoverageIgnoreEnd
81
    }
82
83
    /**
84
     * Returns a static property from the given class. You can pass this function an object or
85
     * a FQCN as string.
86
     *
87
     * @param object|string $object A concrete class or a FQCN
88
     * @param string $propertyName The property name
89
     *
90
     * @return NULL|mixed
91
     */
92 2
    public function getStaticPropertyValue($object, $propertyName) {
93 2
        $className = $object;
94
95 2
        if(is_object($className)) {
96 2
            $className = get_class($object);
97 2
        }
98
99 2
        $reflector = new ReflectionClass($className);
100 2
        $properties = $reflector->getStaticProperties();
101
102 2
        return (isset($properties[$propertyName])) ? $properties[$propertyName] : NULL;
103
    }
104
105
    /**
106
     * Set a property value on the given object. If the property is not found in the given object
107
     * an Exception will be thrown.
108
     *
109
     * @param object $object A concrete object
110
     * @param string $property The property name
111
     * @param mixed $value The property new value
112
     *
113
     * @return bool
114
     *
115
     * @throws \BuildR\Foundation\Exception\Exception
116
     */
117 1
    public function setProperty($object, $property, $value) {
118 1
        $objectReflector = new ReflectionObject($object);
119
120 1
        if(!$objectReflector->hasProperty($property)) {
121 1
            throw new Exception('Property cannot be set! This property not exist inside the given object!');
122
        }
123
124 1
        $propertyReflector = $objectReflector->getProperty($property);
125 1
        $propertyReflector->setAccessible(TRUE);
126 1
        $propertyReflector->setValue($object, $value);
127
128 1
        return TRUE;
129
    }
130
131
    /**
132
     * @param $className
133
     * @param $methodName
134
     * @param null $concreteClass
135
     * @param array $options
136
     *
137
     * options:
138
     * 'callConstructor' => bool
139
     * 'constructorParams' => array (key is variable name, value is the value of the variable)
140
     * 'methodParams' => array (key is variable name, value is the value of the variable)
141
     *
142
     * @return mixed
143
     *
144
     * @throws \BuildR\Foundation\Exception\Exception
145
     */
146 1
    public function invokeMethod($className, $methodName, $concreteClass = NULL, array $options = []) {
147 1
        $callClassConstructor = (isset($options['callConstructor'])) ? (bool) $options['callConstructor'] : FALSE;
148 1
        $methodParams = (isset($options['methodParams'])) ? (array) $options['methodParams'] : [];
149 1
        $objectReflector = new ReflectionClass($className);
150
151 1
        if(!$objectReflector->hasMethod($methodName)) {
152 1
            throw new Exception('Cannot invoke method! Method not found!');
153
        }
154
155 1
        $methodReflector = $objectReflector->getMethod($methodName);
156 1
        $methodReflector->setAccessible(TRUE);
157
158
        //If this is a static method we simply call it without object creation
159 1
        if($methodReflector->isStatic()) {
160 1
            return $methodReflector->invokeArgs(NULL, $methodParams);
161
        }
162
163
        //If concrete is given
164 1
        if($concreteClass !== NULL) {
165 1
            return $methodReflector->invokeArgs($concreteClass, $methodParams);
166
        }
167
168 1
        $calledObject = $objectReflector->newInstanceWithoutConstructor();
169 1
        if($callClassConstructor === TRUE) {
170 1
            $constructorParams = (isset($options['constructorParams'])) ? (array) $options['constructorParams'] : [];
171 1
            $calledObject = $objectReflector->newInstanceArgs($constructorParams);
172 1
        }
173
174 1
        return $methodReflector->invokeArgs($calledObject, $methodParams);
175
    }
176
177
}
178