Completed
Push — master ( 8ab2d4...aa139e )
by Basil
04:07
created

ObjectHelper::traitsList()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 23

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 23
rs 9.552
c 0
b 0
f 0
cc 4
nc 4
nop 2
1
<?php
2
3
namespace luya\helpers;
4
5
use luya\Exception;
6
use ReflectionMethod;
7
8
/**
9
 * Helper methods when dealing with Objects.
10
 *
11
 * @author Basil Suter <[email protected]>
12
 * @since 1.0.0
13
 */
14
class ObjectHelper
15
{
16
    /**
17
     * Checks a given variable if its an instance of an element in the $instances list.
18
     *
19
     * ```php
20
     * $object = new \Exception();
21
     * 
22
     * ObjectHelper::isInstanceOf($object, '\Exception');
23
     * ```
24
     * 
25
     * @param object $object The object to type check against haystack.
26
     * @param string|array|object $haystack A list of classes, a string for a given class, or an object.
27
     * @param boolean $throwException Whether an exception should be thrown or not.
28
     * @throws \luya\Exception
29
     * @return boolean
30
     * @since 1.0.3
31
     */
32
    public static function isInstanceOf($object, $haystack, $throwException = true)
33
    {
34
        // if instances is an object (compare object directly) we have to get the class name to compare with instanceof later
35
        if (is_object($haystack)) {
36
            $haystack = get_class($haystack);
37
        }
38
        
39
        $haystack = (array) $haystack;
40
        
41
        foreach ($haystack as $class) {
42
            if ($object instanceof $class) {
43
                return true;
44
            }
45
        }
46
        
47
        if ($throwException) {
48
            throw new Exception("The given object must be an instance of: " . implode(",", $haystack));
49
        }
50
        
51
        return false;
52
    }
53
54
    /**
55
     * Check whether a given object contains a trait.
56
     * 
57
     * ```php
58
     * trait XYZ {
59
     * 
60
     * }
61
     * 
62
     * class ABC {
63
     *    use XYZ;
64
     * }
65
     * 
66
     * $object = new ABC();
67
     * 
68
     * ObjectHelper::isTraitInstanceOf($object, XYZ::class);
69
     * ```
70
     *
71
     * @param object $object
72
     * @param string|array|object $haystack
73
     * @return boolean
74
     * @since 1.0.17
75
     */
76
    public static function isTraitInstanceOf($object, $haystack)
77
    {
78
        $traits = static::traitsList($object);
79
80
        // if its an object, the all traits for the given object.
81
        if (is_object($haystack)) {
82
            $haystack = static::traitsList($haystack);
83
        }
84
85
        foreach ((array) $haystack as $stack) {
86
            if (in_array($stack, $traits)) {
87
                return true;
88
            }
89
        }
90
91
        return false;
92
    }
93
94
    /**
95
     * Get an array with all traits for a given object
96
     *
97
     * @param object $object
98
     * @param boolean $autoload
99
     * @return array
100
     * @since 1.0.17
101
     * @see https://www.php.net/manual/en/function.class-uses.php#122427
102
     */
103
    public static function traitsList($object, $autoload = true)
104
    {
105
        $traits = [];
106
107
        // Get traits of all parent classes
108
        do {
109
            $traits = array_merge(class_uses($object, $autoload), $traits);
110
        } while ($object = get_parent_class($object));
111
112
        // Get traits of all parent traits
113
        $traitsToSearch = $traits;
114
        while (!empty($traitsToSearch)) {
115
            $newTraits = class_uses(array_pop($traitsToSearch), $autoload);
116
            $traits = array_merge($newTraits, $traits);
117
            $traitsToSearch = array_merge($newTraits, $traitsToSearch);
118
        };
119
120
        foreach ($traits as $trait => $same) {
121
            $traits = array_merge(class_uses($trait, $autoload), $traits);
122
        }
123
124
        return $traits;
125
    }
126
    
127
    /**
128
     * Convert Object to Array
129
     *
130
     * @param object $object
131
     * @return array
132
     */
133
    public static function toArray($object)
134
    {
135
        return (array) $object;
136
    }
137
    
138
    /**
139
     * Call a method and ensure arguments.
140
     *
141
     * Call a class method with arguments and verify the arguments if they are in the list of method arguments or not.
142
     *
143
     * ```php
144
     * ObjectHelper::callMethodSanitizeArguments(new MyClass(), 'methodToCall', ['paramName' => 'paramValue']);
145
     * ```
146
     *
147
     * The response is the return value from the called method of the object.
148
     *
149
     * @param object $object The class object where the method must be found.
150
     * @param string $method The class method to call inside the object.
151
     * @param array $argumentsList A massiv assigned list of array items, where the key is bind to the method argument and the value to be passed in the method on call.
152
     * @throws \luya\Exception Throws an exception if a argument coult not be found.
153
     * @return mixed
154
     */
155
    public static function callMethodSanitizeArguments($object, $method, array $argumentsList = [])
156
    {
157
        // get class reflection object
158
        $reflection = new ReflectionMethod($object, $method);
159
        // array where the sanitized arguemnts will be stored
160
        $methodArgs = [];
161
162
        foreach ($reflection->getParameters() as $param) {
163
            // add the argument into the method list when existing
164
            if (array_key_exists($param->name, $argumentsList)) {
165
                $methodArgs[] = $argumentsList[$param->name];
166
            }
167
            // check if the provided arguemnt is optional or not
168
            if (!$param->isOptional() && !array_key_exists($param->name, $argumentsList)) {
169
                throw new Exception(sprintf("The argument '%s' is required for method '%s' in class '%s'.", $param->name, $method, get_class($object)));
170
            }
171
        }
172
173
        return call_user_func_array([$object, $method], $methodArgs);
174
    }
175
}
176