type-tools-php

Форк
0
/
MapAccess.php 
215 строк · 5.7 Кб
1
<?php
2

3
declare(strict_types=1);
4

5
namespace Smoren\TypeTools;
6

7
use ArrayAccess;
8
use Smoren\TypeTools\Exceptions\KeyError;
9
use stdClass;
10

11
/**
12
 * Tool for map-like accessing of different containers by string keys.
13
 *
14
 * Can access:
15
 *  - properties of objects (by name or by getter);
16
 *  - elements of arrays and ArrayAccess objects (by key).
17
 */
18
class MapAccess
19
{
20
    /**
21
     * Returns value from the container by key or default value if key does not exist or not accessible.
22
     *
23
     * @template T
24
     *
25
     * @param array<string, T>|ArrayAccess<string, T>|object|mixed $container
26
     * @param string $key
27
     * @param T|null $defaultValue
28
     *
29
     * @return T|null
30
     *
31
     * @throws KeyError
32
     */
33
    public static function get($container, string $key, $defaultValue = null)
34
    {
35
        switch(true) {
36
            case is_array($container):
37
                return static::getFromArray($container, $key, $defaultValue);
38
            case $container instanceof ArrayAccess:
39
                return static::getFromArrayAccess($container, $key, $defaultValue);
40
            case is_object($container):
41
                return static::getFromObject($container, $key, $defaultValue);
42
        }
43

44
        return $defaultValue;
45
    }
46

47
    /**
48
     * Sets value to the container by key.
49
     *
50
     * @template T
51
     *
52
     * @param array<string, T>|ArrayAccess<string, T>|object|mixed $container
53
     * @param string $key
54
     * @param T $value
55
     *
56
     * @return void
57
     *
58
     * @throws KeyError
59
     */
60
    public static function set(&$container, string $key, $value): void
61
    {
62
        switch(true) {
63
            case is_array($container):
64
            case $container instanceof ArrayAccess:
65
                $container[$key] = $value;
66
                break;
67
            case is_object($container):
68
                static::setToObject($container, $key, $value);
69
                break;
70
        }
71
    }
72

73
    /**
74
     * Returns true if the accessible key exists in the container.
75
     *
76
     * @param array<string, mixed>|ArrayAccess<string, mixed>|object|mixed $container
77
     * @param string $key
78
     *
79
     * @return bool
80
     */
81
    public static function exists($container, string $key): bool
82
    {
83
        switch(true) {
84
            case is_array($container):
85
                return static::existsInArray($container, $key);
86
            case $container instanceof ArrayAccess:
87
                return static::existsInArrayAccess($container, $key);
88
            case is_object($container):
89
                return static::existsInObject($container, $key);
90
        }
91
        return false;
92
    }
93

94
    /**
95
     * Returns value from the array by key or default value if key does not exist.
96
     *
97
     * @template T
98
     *
99
     * @param array<string, T> $container
100
     * @param string $key
101
     * @param T|null $defaultValue
102
     *
103
     * @return T|null
104
     */
105
    protected static function getFromArray(array $container, string $key, $defaultValue)
106
    {
107
        if(static::existsInArray($container, $key)) {
108
            return $container[$key];
109
        }
110

111
        return $defaultValue ?? null;
112
    }
113

114
    /**
115
     * Returns true if the key exists in the array.
116
     *
117
     * @template T
118
     * @param array<string, T> $container
119
     * @param string $key
120
     *
121
     * @return bool
122
     */
123
    protected static function existsInArray(array $container, string $key): bool
124
    {
125
        return array_key_exists($key, $container);
126
    }
127

128
    /**
129
     * Returns value from the ArrayAccess object by key or default value if key does not exist.
130
     *
131
     * @template T
132
     *
133
     * @param ArrayAccess<string, T> $container
134
     * @param string $key
135
     * @param T|null $defaultValue
136
     *
137
     * @return T|null
138
     */
139
    protected static function getFromArrayAccess(ArrayAccess $container, string $key, $defaultValue)
140
    {
141
        if(static::existsInArrayAccess($container, $key)) {
142
            return $container[$key];
143
        }
144

145
        return $defaultValue ?? null;
146
    }
147

148
    /**
149
     * Returns true if the key exists in the ArrayAccess object.
150
     *
151
     * @template T
152
     *
153
     * @param ArrayAccess<string, T> $container
154
     * @param string $key
155
     *
156
     * @return bool
157
     */
158
    protected static function existsInArrayAccess(ArrayAccess $container, string $key): bool
159
    {
160
        return $container->offsetExists($key);
161
    }
162

163
    /**
164
     * Returns value from the object by key or default value if key does not exist.
165
     *
166
     * @param object $container
167
     * @param string $key
168
     * @param mixed|null $defaultValue
169
     *
170
     * @return mixed|null
171
     *
172
     * @throws KeyError
173
     */
174
    protected static function getFromObject(object $container, string $key, $defaultValue)
175
    {
176
        if(ObjectAccess::hasReadableProperty($container, $key)) {
177
            return ObjectAccess::getPropertyValue($container, $key);
178
        }
179

180
        return $defaultValue;
181
    }
182

183
    /**
184
     * Sets property value to the object if it is writable by name or by setter.
185
     *
186
     * @param object $container
187
     * @param string $key
188
     * @param mixed $value
189
     *
190
     * @return void
191
     *
192
     * @throws KeyError
193
     */
194
    protected static function setToObject(object $container, string $key, $value): void
195
    {
196
        if(!ObjectAccess::hasWritableProperty($container, $key) && !($container instanceof stdClass)) {
197
            throw new KeyError("property ".get_class($container)."::{$key} is not writable");
198
        }
199

200
        ObjectAccess::setPropertyValue($container, $key, $value);
201
    }
202

203
    /**
204
     * Returns true if the key exists in the object.
205
     *
206
     * @param object $container
207
     * @param string $key
208
     *
209
     * @return bool
210
     */
211
    protected static function existsInObject(object $container, string $key): bool
212
    {
213
        return ObjectAccess::hasReadableProperty($container, $key);
214
    }
215
}
216

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.