Completed
Push — master ( 0f5459...b9fce4 )
by Max
01:22
created

GetterHelper::getKeys()   A

Complexity

Conditions 6
Paths 5

Size

Total Lines 17

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 17
rs 9.0777
c 0
b 0
f 0
cc 6
nc 5
nop 1
1
<?php
2
3
/*
4
 *  @copyright (c) 2019 Mendel <[email protected]>
5
 *  @license see license.txt
6
 */
7
8
namespace drycart\data;
9
10
/**
11
 * Wrapper for pretty access to field
12
 * Used for deep access to some data at some unknown data
13
 *
14
 * fieldName for example forum.moderators.first().name work correct for any of this sence:
15
 * $data->forum->moderators->first()->name
16
 * $data['forum']['moderators']->first()['name']
17
 * $data['forum']->moderators->first()['name']
18
 * etc...
19
 *
20
 * Object field is priority option, second is array, after this we try method,
21
 * so if exist something like this, it will be used
22
 * $data['forum']->moderators['first()']['name']
23
 *
24
 * methods parameters not supports at any format
25
 */
26
class GetterHelper
27
{
28
    /**
29
     * Get some data by pretty name
30
     * 
31
     * @param array|object $data data for pretty access
32
     * @param string $name name for access
33
     * @param bool $safe if true - Exception for not exist fields
34
     * @param mixed $default used for non safe request, if we dont find answer
35
     * @return mixed
36
     * @throws \Exception
37
     */
38
    public static function get($data, string $name, bool $safe = true, $default = null)
39
    {
40
        $fields = explode('.', $name);
41
        foreach ($fields as $key) {
42
            $data = static::subGet($data, $key, $safe, $default);
43
        }
44
        return $data;
45
    }
46
47
    /**
48
     * Get iterator for data
49
     * 
50
     * @param mixed $data
51
     * @return \Traversable
52
     */
53
    public static function getIterator($data): \Traversable
54
    {
55
        if(is_a($data, \Traversable::class)) {
56
            return $data;
57
        } elseif(is_array($data)) {
58
            return new \ArrayIterator($data);
59
        } else {
60
            return new \ArrayIterator((array) $data);
61
        }
62
    }
63
64
    /**
65
     * Get keys list for data
66
     * 
67
     * @param mixed $data
68
     * @return array
69
     */
70
    public static function getKeys($data) : array
71
    {
72
        if(is_object($data) and is_a($data, ModelInterface::class)) {
73
            return $data->keys();
74
        } elseif(is_array($data)) {
75
            return array_keys($data);
76
        } elseif(is_a($data, \ArrayObject::class)) {
77
            $arr = $data->getArrayCopy();
78
            return array_keys($arr);
79
        } elseif(is_a($data, \Traversable::class)) {
80
            $arr = iterator_to_array($data);
81
            return array_keys($arr);
82
        } else {
83
            $arr = (array) $data;
84
            return array_keys($arr);
85
        }
86
    }
87
88
    /**
89
     * One level get
90
     * 
91
     * @param type $data
92
     * @param string $key
93
     * @param bool $safe
94
     * @param type $default
95
     * @return mixed
96
     * @throws \Exception
97
     */
98
    protected static function subGet($data, string $key, bool $safe = true, $default = null)
99
    {
100
        if (is_array($data)) { // Just array, because ArrayAccess can have his own logic as object field
101
            $data = (object) $data;
102
        }
103
        //
104
        if (isset($data->{$key})) { // simple
105
            return $data->{$key};
106
        } elseif (is_a($data, \ArrayAccess::class) and isset($data[$key])) { // for ArrayAccess obj
107
            return $data[$key];
108
            // Methods magic...
109
        } elseif ((substr($key, -2) == '()') and method_exists($data, substr($key, 0, -2))) {
110
            return call_user_func_array([$data, substr($key, 0, -2)], []);
111
        } elseif ($safe) {
112
            throw new \Exception("Bad field name $key");
113
        } else {
114
            return $default;
115
        }
116
    }
117
}
118