Completed
Push — master ( 4720cc...98d1d1 )
by Dmitry
05:22
created

RemoteCartStorage::offsetGet()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 6
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 3
nc 1
nop 1
1
<?php
2
3
namespace hipanel\modules\finance\cart\storage;
4
5
use hipanel\components\SettingsStorage;
6
use hipanel\helpers\StringHelper;
7
use Yii;
8
use yii\base\NotSupportedException;
9
use yii\caching\CacheInterface;
10
use yii\helpers\Json;
11
use yii\web\MultiFieldSession;
12
use yii\web\User;
13
14
/**
15
 * Class RemoteCartStorage
16
 *
17
 * @author Dmytro Naumenko <[email protected]>
18
 */
19
class RemoteCartStorage extends MultiFieldSession implements CartStorageInterface
20
{
21
    const CACHE_DURATION = 60*60; // 1 hour
22
    /**
23
     * @var array
24
     */
25
    protected $data = [];
26
    /**
27
     * @var array
28
     */
29
    protected $oldData = [];
30
    /**
31
     * @var SettingsStorage
32
     */
33
    private $settingsStorage;
34
    /**
35
     * @var CacheInterface
36
     */
37
    private $cache;
38
    /**
39
     * @var User
40
     */
41
    private $user;
42
43
    public function __construct(User $user, SettingsStorage $settingsStorage, CacheInterface $cache, array $config = [])
44
    {
45
        parent::__construct($config);
46
47
        $this->settingsStorage = $settingsStorage;
48
        $this->cache = $cache;
49
        $this->user = $user;
50
    }
51
52
    protected function read()
53
    {
54
        try {
55
            $this->data = $this->cache->getOrSet($this->getCacheKey(), function () {
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->cache->getOrSet($..., self::CACHE_DURATION) of type * is incompatible with the declared type array of property $data.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
56
                return Json::decode(base64_decode($this->settingsStorage->getBounded($this->getStorageKey())));
57
            }, self::CACHE_DURATION);
58
        } catch (\Exception $exception) {
59
            Yii::error('Failed to read cart: ' . $exception->getMessage(), __METHOD__);
60
        }
61
    }
62
63
    protected function getCacheKey()
64
    {
65
        return [__CLASS__, $this->user->getId(), session_id()];
66
    }
67
68
    protected function getStorageKey()
69
    {
70
        return StringHelper::basename(__CLASS__);
71
    }
72
73
    protected function write()
74
    {
75
        if ($this->data === $this->oldData) {
76
            return;
77
        }
78
79
        try {
80
            $this->cache->set($this->getCacheKey(), $this->data);
81
            $this->settingsStorage->setBounded($this->getStorageKey(), base64_encode(Json::encode($this->data)));
82
        } catch (\Exception $exception) {
83
            Yii::error('Failed to save cart: ' . $exception->getMessage(), __METHOD__);
84
        }
85
    }
86
87
    /**
88
     * @var bool
89
     */
90
    private $_isActive;
91
    public function getIsActive()
92
    {
93
        return $this->_isActive;
94
    }
95
96
    /** {@inheritdoc} */
97
    public function open()
98
    {
99
        if ($this->getIsActive()) {
100
            return;
101
        }
102
103
        $this->read();
104
        $this->oldData = $this->data;
105
        $this->_isActive = true;
106
        $this->registerShutdownFunction();
107
    }
108
109
    /** {@inheritdoc} */
110
    public function offsetExists($offset)
111
    {
112
        $this->open();
113
114
        return isset($this->data[$offset]);
115
    }
116
117
    /** {@inheritdoc} */
118
    public function offsetGet($offset)
119
    {
120
        $this->open();
121
122
        return $this->data[$offset] ?? null;
123
    }
124
125
    /** {@inheritdoc} */
126
    public function offsetSet($offset, $item)
127
    {
128
        $this->open();
129
130
        $this->data[$offset] = $item;
131
    }
132
133
    /** {@inheritdoc} */
134
    public function offsetUnset($offset)
135
    {
136
        $this->open();
137
        unset($this->data[$offset]);
138
    }
139
140
    /**
141
     * @throws NotSupportedException
142
     * @void
143
     */
144
    private function throwShouldNotBeCalledException()
145
    {
146
        throw new NotSupportedException('Remote cart storage extends yii\web\Session, but it is not a session actually. This method should be never called.');
147
    }
148
149
    /** {@inheritdoc} */
150
    public function regenerateID($deleteOldSession = false)
151
    {
152
        $this->throwShouldNotBeCalledException();
153
    }
154
155
    /** {@inheritdoc} */
156
    public function readSession($id)
157
    {
158
        return $this->throwShouldNotBeCalledException();
159
    }
160
161
    /** {@inheritdoc} */
162
    public function writeSession($id, $data)
163
    {
164
        return $this->throwShouldNotBeCalledException();
165
    }
166
167
    /** {@inheritdoc} */
168
    public function destroySession($id)
169
    {
170
        return $this->throwShouldNotBeCalledException();
171
    }
172
173
    /** {@inheritdoc} */
174
    public function gcSession($maxLifetime)
175
    {
176
        return $this->throwShouldNotBeCalledException();
177
    }
178
179
    private function registerShutdownFunction()
180
    {
181
        register_shutdown_function(\Closure::fromCallable([$this, 'write']));
182
    }
183
}
184