Completed
Push — master ( 2264f7...ee6db1 )
by Basil
02:53
created

ObjectHelper::fileToName()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 2
1
<?php
2
3
namespace luya\helpers;
4
5
use luya\Exception;
6
use ReflectionMethod;
7
use yii\base\Controller;
8
use luya\base\Module;
9
10
/**
11
 * Helper methods when dealing with Objects.
12
 *
13
 * @author Basil Suter <[email protected]>
14
 * @since 1.0.0
15
 */
16
class ObjectHelper
17
{
18
    /**
19
     * Checks a given variable if its an instance of an element in the $instances list.
20
     *
21
     * ```php
22
     * $object = new \Exception();
23
     * 
24
     * ObjectHelper::isInstanceOf($object, '\Exception');
25
     * ```
26
     * 
27
     * @param object $object The object to type check against haystack.
28
     * @param string|array|object $haystack A list of classes, a string for a given class, or an object.
29
     * @param boolean $throwException Whether an exception should be thrown or not.
30
     * @throws \luya\Exception
31
     * @return boolean
32
     * @since 1.0.3
33
     */
34
    public static function isInstanceOf($object, $haystack, $throwException = true)
35
    {
36
        // if instances is an object (compare object directly) we have to get the class name to compare with instanceof later
37
        if (is_object($haystack)) {
38
            $haystack = get_class($haystack);
39
        }
40
        
41
        $haystack = (array) $haystack;
42
        
43
        foreach ($haystack as $class) {
44
            if ($object instanceof $class) {
45
                return true;
46
            }
47
        }
48
        
49
        if ($throwException) {
50
            throw new Exception("The given object must be an instance of: " . implode(",", $haystack));
51
        }
52
        
53
        return false;
54
    }
55
56
    /**
57
     * Check whether a given object contains a trait.
58
     * 
59
     * ```php
60
     * trait XYZ {
61
     * 
62
     * }
63
     * 
64
     * class ABC {
65
     *    use XYZ;
66
     * }
67
     * 
68
     * $object = new ABC();
69
     * 
70
     * ObjectHelper::isTraitInstanceOf($object, XYZ::class);
71
     * ```
72
     *
73
     * @param object $object
74
     * @param string|array|object $haystack
75
     * @return boolean
76
     * @since 1.0.17
77
     */
78
    public static function isTraitInstanceOf($object, $haystack)
79
    {
80
        $traits = static::traitsList($object);
81
82
        // if its an object, the all traits for the given object.
83
        if (is_object($haystack)) {
84
            $haystack = static::traitsList($haystack);
85
        }
86
87
        foreach ((array) $haystack as $stack) {
88
            if (in_array($stack, $traits)) {
89
                return true;
90
            }
91
        }
92
93
        return false;
94
    }
95
96
    /**
97
     * Get an array with all traits for a given object
98
     *
99
     * @param object $object
100
     * @param boolean $autoload
101
     * @return array
102
     * @since 1.0.17
103
     * @see https://www.php.net/manual/en/function.class-uses.php#122427
104
     */
105
    public static function traitsList($object, $autoload = true)
106
    {
107
        $traits = [];
108
109
        // Get traits of all parent classes
110
        do {
111
            $traits = array_merge(class_uses($object, $autoload), $traits);
112
        } while ($object = get_parent_class($object));
113
114
        // Get traits of all parent traits
115
        $traitsToSearch = $traits;
116
        while (!empty($traitsToSearch)) {
117
            $newTraits = class_uses(array_pop($traitsToSearch), $autoload);
118
            $traits = array_merge($newTraits, $traits);
119
            $traitsToSearch = array_merge($newTraits, $traitsToSearch);
120
        };
121
122
        foreach ($traits as $trait => $same) {
123
            $traits = array_merge(class_uses($trait, $autoload), $traits);
124
        }
125
126
        return $traits;
127
    }
128
    
129
    /**
130
     * Convert Object to Array
131
     *
132
     * @param object $object
133
     * @return array
134
     */
135
    public static function toArray($object)
136
    {
137
        return (array) $object;
138
    }
139
    
140
    /**
141
     * Call a method and ensure arguments.
142
     *
143
     * Call a class method with arguments and verify the arguments if they are in the list of method arguments or not.
144
     *
145
     * ```php
146
     * ObjectHelper::callMethodSanitizeArguments(new MyClass(), 'methodToCall', ['paramName' => 'paramValue']);
147
     * ```
148
     *
149
     * The response is the return value from the called method of the object.
150
     *
151
     * @param object $object The class object where the method must be found.
152
     * @param string $method The class method to call inside the object.
153
     * @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.
154
     * @throws \luya\Exception Throws an exception if a argument coult not be found.
155
     * @return mixed
156
     */
157
    public static function callMethodSanitizeArguments($object, $method, array $argumentsList = [])
158
    {
159
        // get class reflection object
160
        $reflection = new ReflectionMethod($object, $method);
161
        // array where the sanitized arguemnts will be stored
162
        $methodArgs = [];
163
164
        foreach ($reflection->getParameters() as $param) {
165
            // add the argument into the method list when existing
166
            if (array_key_exists($param->name, $argumentsList)) {
167
                $methodArgs[] = $argumentsList[$param->name];
168
            }
169
            // check if the provided arguemnt is optional or not
170
            if (!$param->isOptional() && !array_key_exists($param->name, $argumentsList)) {
171
                throw new Exception(sprintf("The argument '%s' is required for method '%s' in class '%s'.", $param->name, $method, get_class($object)));
172
            }
173
        }
174
175
        return call_user_func_array([$object, $method], $methodArgs);
176
    }
177
178
    /**
179
     * Get all actions from a given controller.
180
     *
181
     * @param Controller $controller
182
     * @return array
183
     * @since 1.0.19
184
     */
185
    public function getActions(Controller $controller)
186
    {
187
        $actions = array_keys($controller->actions());
188
        $class = new \ReflectionClass($controller);
189
        foreach ($class->getMethods() as $method) {
190
            $name = $method->getName();
0 ignored issues
show
Bug introduced by
Consider using $method->name. There is an issue with getName() and APC-enabled PHP versions.
Loading history...
191
            if ($name !== 'actions' && $method->isPublic() && !$method->isStatic() && strncmp($name, 'action', 6) === 0) {
192
                $actions[] = Inflector::camel2id(substr($name, 6), '-', true);
193
            }
194
        }
195
        sort($actions);
196
        return array_unique($actions);
197
    }
198
199
    /**
200
     * Get all controllers for a given luya Module
201
     *
202
     * @param Module $module
203
     * @return array
204
     * @since 1.0.19
205
     */
206
    public function getControllers(Module $module)
207
    {
208
        $files = [];
209
        try { // https://github.com/yiisoft/yii2/blob/master/framework/base/Module.php#L253
210
            foreach (FileHelper::findFiles($module->controllerPath) as $file) {
211
                $files[self::fileToName($module->controllerPath, $file)] = $file;
212
            }
213
        } catch (InvalidParamException $e) {
0 ignored issues
show
Bug introduced by
The class luya\helpers\InvalidParamException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
214
            try {
215
                $staticPath = static::staticBasePath() . DIRECTORY_SEPARATOR . 'controllers';
0 ignored issues
show
Bug introduced by
The method staticBasePath() does not seem to exist on object<luya\helpers\ObjectHelper>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
216
                foreach (FileHelper::findFiles($staticPath) as $file) {
217
                    $files[self::fileToName($staticPath, $file)] = $file;
218
                }
219
            } catch (InvalidParamException $e) {
0 ignored issues
show
Bug introduced by
The class luya\helpers\InvalidParamException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
220
                // catch if folder not found.
221
            }
222
        };
223
        
224
        return $files;
225
    }
226
227
    /**
228
     * Namify a controller file
229
     *
230
     * @param string $prefix
231
     * @param string $file
232
     * @return string
233
     * @since 1.0.19
234
     */
235
    private static function fileToName($prefix, $file)
236
    {
237
        Inflector::camel2id(ltrim(str_replace([$prefix, 'Controller.php'], '', $file), DIRECTORY_SEPARATOR));
238
    }
239
}
240