Completed
Branch develop (876d53)
by Nate
01:53
created

ElementAccessorByString::findCache()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 12
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

Changes 0
Metric Value
dl 0
loc 12
ccs 0
cts 10
cp 0
rs 9.4285
c 0
b 0
f 0
cc 3
eloc 6
nc 3
nop 2
crap 12
1
<?php
2
3
/**
4
 * @copyright  Copyright (c) Flipbox Digital Limited
5
 * @license    https://github.com/flipboxfactory/craft-ember/blob/master/LICENSE
6
 * @link       https://github.com/flipboxfactory/craft-ember
7
 */
8
9
namespace flipbox\ember\services\traits;
10
11
use craft\base\Element;
12
use craft\base\ElementInterface;
13
use craft\elements\db\ElementQuery;
14
use craft\errors\ElementNotFoundException;
15
use flipbox\ember\helpers\SiteHelper;
16
17
/**
18
 * @author Flipbox Factory <[email protected]>
19
 * @since 1.0.0
20
 *
21
 * @method ElementInterface parentFind($identifier, int $siteId = null, string $toScenario = null)
22
 * @method ElementInterface parentFindCache($identifier, int $siteId = null)
23
 */
24
trait ElementAccessorByString
25
{
26
    use ElementAccessor {
27
        find as parentFind;
28
        findCache as parentFindCache;
29
    }
30
31
    /**
32
     * @var [ElementInterface[]]
33
     */
34
    protected $cacheByString = [];
35
36
    /**
37
     * @return string
38
     */
39
    abstract protected function stringProperty(): string;
40
41
    /*******************************************
42
     * STRING
43
     *******************************************/
44
45
    /**
46
     * @param ElementInterface $element
47
     * @return string
48
     */
49
    protected function stringValue(ElementInterface $element)
50
    {
51
        $property = $this->stringProperty();
52
53
        return $element->{$property};
54
    }
55
56
57
    /*******************************************
58
     * FIND OVERRIDES
59
     *******************************************/
60
61
    /**
62
     * @inheritdoc
63
     */
64
    public function find($identifier, int $siteId = null, string $toScenario = null)
65
    {
66
        if ($element = $this->parentFind($identifier, $siteId, $toScenario)) {
67
            return $element;
68
        }
69
70
        if (!is_string($identifier)) {
71
            return null;
72
        }
73
74
        return $this->findByString($identifier, $siteId, $toScenario);
75
    }
76
77
    /*******************************************
78
     * CACHE OVERRIDES
79
     *******************************************/
80
81
    /**
82
     * @inheritdoc
83
     */
84
    public function findCache($identifier, int $siteId = null)
85
    {
86
        if ($element = $this->parentFindCache($identifier, $siteId)) {
87
            return $element;
88
        }
89
90
        if (!is_string($identifier)) {
91
            return null;
92
        }
93
94
        return $this->findCacheByString($identifier, $siteId);
95
    }
96
97
    /**
98
     * @inheritdoc
99
     */
100
    public function addToCache(ElementInterface $element)
101
    {
102
        $this->cacheById($element);
103
        $this->cacheByString($element);
104
        return $this;
105
    }
106
107
108
    /*******************************************
109
     * FIND/GET BY STRING
110
     *******************************************/
111
112
    /**
113
     * @param string $string
114
     * @param int|null $siteId
115
     * @param string|null $toScenario
116
     * @return ElementInterface|null
117
     */
118
    public function findByString(string $string, int $siteId = null, string $toScenario = null)
119
    {
120
        $siteId = SiteHelper::ensureSiteId($siteId);
121
122
        if (!$element = $this->findCacheByString($string, $siteId)) {
123
            if (!$element = $this->freshFindByString($string, $siteId)) {
124
                $this->cacheByString[$siteId][$string] = null;
125
                return null;
126
            }
127
128
            $this->addToCache($element);
129
        }
130
131
        return $this->applyScenario($element, $toScenario);
132
    }
133
134
    /**
135
     * @param string $string
136
     * @param string|null $toScenario
137
     * @return ElementInterface|null
138
     * @throws ElementNotFoundException
139
     */
140
    public function getByString(string $string, string $toScenario = null): ElementInterface
141
    {
142
        if (!$element = $this->findByString($string, $toScenario)) {
143
            $this->notFoundByStringException($string);
144
        }
145
146
        return $element;
147
    }
148
149
    /**
150
     * @param string $string
151
     * @param int|null $siteId
152
     * @param string $toScenario
153
     * @return ElementInterface|null
154
     */
155
    public function freshFindByString(string $string, int $siteId = null, string $toScenario = null)
156
    {
157
        /** @var ElementQuery $query */
158
        $query = $this->getQuery();
159
        $query->{$this->stringProperty()} = $string;
160
        $query->siteId = $siteId;
161
        $query->status = null;
162
        $query->enabledForSite = false;
163
164
        if (!$element = $query->one()) {
165
            return null;
166
        }
167
168
        return $this->applyScenario($element, $toScenario);
169
    }
170
171
    /**
172
     * @param string $string
173
     * @param string|null $toScenario
174
     * @return ElementInterface
175
     * @throws ElementNotFoundException
176
     */
177
    public function freshGetByString(string $string, string $toScenario = null): ElementInterface
178
    {
179
        if (!$element = $this->freshFindByString($string, $toScenario)) {
180
            $this->notFoundByStringException($string);
181
        }
182
183
        return $element;
184
    }
185
186
187
    /*******************************************
188
     * CACHE BY STRING
189
     *******************************************/
190
191
    /**
192
     * Find an existing cache by ID
193
     *
194
     * @param string $string
195
     * @param int|null $siteId
196
     * @return ElementInterface|null
197
     */
198
    public function findCacheByString(string $string, int $siteId = null)
199
    {
200
        $siteId = SiteHelper::ensureSiteId($siteId);
201
202
        if ($this->isCachedByString($string, $siteId)) {
203
            return $this->cacheByString[$siteId][$string];
204
        }
205
206
        return null;
207
    }
208
209
    /**
210
     * Identify whether in cached by ID
211
     *
212
     * @param string $string
213
     * @param int|null $siteId
214
     * @return bool
215
     */
216
    protected function isCachedByString(string $string, int $siteId = null): bool
217
    {
218
        $siteId = SiteHelper::ensureSiteId($siteId);
219
220
        if (!array_key_exists($siteId, $this->cacheByString)) {
221
            $this->cacheByString[$siteId] = [];
222
        }
223
224
        return array_key_exists($string, $this->cacheByString[$siteId]);
225
    }
226
227
    /**
228
     * @param ElementInterface $element
229
     * @return $this
230
     */
231
    protected function cacheByString(ElementInterface $element)
232
    {
233
        /** @var Element $element */
234
        $stringValue = $this->stringValue($element);
235
236
        if (null === $stringValue) {
237
            return $this;
238
        }
239
240
        $siteId = SiteHelper::ensureSiteId($element->siteId);
241
242
        // Check if already in cache
243
        if (!$this->isCachedByString($stringValue, $siteId)) {
244
            $this->cacheByString[$siteId][$stringValue] = $element;
245
        }
246
247
        return $this;
248
    }
249
250
    /*******************************************
251
     * EXCEPTIONS
252
     *******************************************/
253
254
    /**
255
     * @param string|null $string
256
     * @throws ElementNotFoundException
257
     */
258
    protected function notFoundByStringException(string $string = null)
259
    {
260
        throw new ElementNotFoundException(
261
            sprintf(
262
                'Element does not exist with the string "%s".',
263
                (string)$string
264
            )
265
        );
266
    }
267
}
268