Completed
Push — master ( 7f400a...960c3d )
by Maxim
03:59
created

ArrayHelper::getValue()   C

Complexity

Conditions 12
Paths 27

Size

Total Lines 34
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 34
rs 5.1612
cc 12
eloc 17
nc 27
nop 3

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace WebComplete\core\utils\helpers;
4
5
class ArrayHelper
6
{
7
8
    /**
9
     * Retrieves the value of an array element or object property with the given key or property name.
10
     * If the key does not exist in the array or object, the default value will be returned instead.
11
     *
12
     * The key may be specified in a dot format to retrieve the value of a sub-array or the property
13
     * of an embedded object. In particular, if the key is `x.y.z`, then the returned value would
14
     * be `$array['x']['y']['z']` or `$array->x->y->z` (if `$array` is an object). If `$array['x']`
15
     * or `$array->x` is neither an array nor an object, the default value will be returned.
16
     * Note that if the array already has an element `x.y.z`, then its value will be returned
17
     * instead of going through the sub-arrays. So it is better to be done specifying an array of key names
18
     * like `['x', 'y', 'z']`.
19
     *
20
     * Below are some usage examples,
21
     *
22
     * ```php
23
     * // working with array
24
     * $username = \yii\helpers\ArrayHelper::getValue($_POST, 'username');
25
     * // working with object
26
     * $username = \yii\helpers\ArrayHelper::getValue($user, 'username');
27
     * // working with anonymous function
28
     * $fullName = \yii\helpers\ArrayHelper::getValue($user, function ($user, $defaultValue) {
29
     *     return $user->firstName . ' ' . $user->lastName;
30
     * });
31
     * // using dot format to retrieve the property of embedded object
32
     * $street = \yii\helpers\ArrayHelper::getValue($users, 'address.street');
33
     * // using an array of keys to retrieve the value
34
     * $value = \yii\helpers\ArrayHelper::getValue($versions, ['1.0', 'date']);
35
     * ```
36
     *
37
     * @param array|object $array array or object to extract value from
38
     * @param string|\Closure|array $key key name of the array element, an array of keys or property name of the object,
39
     * or an anonymous function returning the value. The anonymous function signature should be:
40
     * `function($array, $defaultValue)`.
41
     * The possibility to pass an array of keys is available since version 2.0.4.
42
     * @param mixed $default the default value to be returned if the specified array key does not exist. Not used when
43
     * getting value from an object.
44
     * @return mixed the value of the element if found, default value otherwise
45
     */
46
    public function getValue($array, $key, $default = null)
47
    {
48
        if ($key instanceof \Closure) {
49
            return $key($array, $default);
50
        }
51
52
        if (\is_array($key)) {
53
            $lastKey = \array_pop($key);
54
            foreach ((array)$key as $keyPart) {
55
                $array = $this->getValue($array, $keyPart);
56
            }
57
            $key = $lastKey;
58
        }
59
60
        if (\is_array($array) && (isset($array[$key]) || \array_key_exists($key, $array))) {
61
            return $array[$key];
62
        }
63
64
        if (($pos = \strrpos($key, '.')) !== false) {
0 ignored issues
show
introduced by
The condition $pos = strrpos($key, '.') !== false can never be false.
Loading history...
65
            $array = $this->getValue($array, \substr($key, 0, $pos), $default);
66
            $key = (string)\substr($key, $pos + 1);
67
        }
68
69
        if (\is_object($array)) {
70
            // this is expected to fail if the property does not exist, or __get() is not implemented
71
            // it is not reliably possible to check whether a property is accessible beforehand
72
            return $array->$key;
73
        }
74
75
        if (\is_array($array)) {
76
            return (isset($array[$key]) || \array_key_exists($key, $array)) ? $array[$key] : $default;
77
        }
78
79
        return $default;
80
    }
81
82
    /**
83
     * Writes a value into an associative array at the key path specified.
84
     * If there is no such key path yet, it will be created recursively.
85
     * If the key exists, it will be overwritten.
86
     *
87
     * ```php
88
     *  $array = [
89
     *      'key' => [
90
     *          'in' => [
91
     *              'val1',
92
     *              'key' => 'val'
93
     *          ]
94
     *      ]
95
     *  ];
96
     * ```
97
     *
98
     * The result of `ArrayHelper::setValue($array, 'key.in.0', ['arr' => 'val']);` will be the following:
99
     *
100
     * ```php
101
     *  [
102
     *      'key' => [
103
     *          'in' => [
104
     *              ['arr' => 'val'],
105
     *              'key' => 'val'
106
     *          ]
107
     *      ]
108
     *  ]
109
     *
110
     * ```
111
     *
112
     * The result of
113
     * `ArrayHelper::setValue($array, 'key.in', ['arr' => 'val']);` or
114
     * `ArrayHelper::setValue($array, ['key', 'in'], ['arr' => 'val']);`
115
     * will be the following:
116
     *
117
     * ```php
118
     *  [
119
     *      'key' => [
120
     *          'in' => [
121
     *              'arr' => 'val'
122
     *          ]
123
     *      ]
124
     *  ]
125
     * ```
126
     *
127
     * @param array $array the array to write the value to
128
     * @param string|array|null $path the path of where do you want to write a value to `$array`
129
     * the path can be described by a string when each key should be separated by a dot
130
     * you can also describe the path as an array of keys
131
     * if the path is null then `$array` will be assigned the `$value`
132
     * @param mixed $value the value to be written
133
     * @since 2.0.13
134
     */
135
    public function setValue(&$array, $path, $value)
136
    {
137
        if ($path === null) {
138
            $array = $value;
139
            return;
140
        }
141
142
        $keys = \is_array($path) ? $path : \explode('.', $path);
143
144
        while (\count($keys) > 1) {
145
            $key = \array_shift($keys);
146
            if (!isset($array[$key])) {
147
                $array[$key] = [];
148
            }
149
            if (!\is_array($array[$key])) {
150
                $array[$key] = [$array[$key]];
151
            }
152
            $array = &$array[$key];
153
        }
154
155
        $array[\array_shift($keys)] = $value;
156
    }
157
}
158