FeaturedFlagsImpl::_getCacheModel()   A
last analyzed

Complexity

Conditions 4
Paths 4

Size

Total Lines 11
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 4

Importance

Changes 3
Bugs 0 Features 0
Metric Value
c 3
b 0
f 0
dl 0
loc 11
ccs 6
cts 6
cp 1
rs 9.2
cc 4
eloc 6
nc 4
nop 1
crap 4
1
<?php
2
3
namespace FeaturedFlags;
4
5
use PDO;
6
use Redis;
7
8
class FeaturedFlagsImpl implements FeaturedFlags
9
{
10
    protected $_pdo;
11
    protected $_redis;
12
    protected $_date;
13
14
    CONST TABLE_NAME = 'featured_flags';
15
    CONST ISENABLED_PREFIX = 'isEnabled_';
16
    CONST GETVALUES_PREFIX = 'getEnabledValues_';
17
18
    /**
19
     * FeaturedFlags constructor.
20
     * @param PDO $pdo
21
     * @param Redis|null $redis
22
     * @param string|null $date
23
     */
24 26
    public function __construct(PDO $pdo, Redis $redis = null, $date = null)
25 1
    {
26 26
        $this->_pdo = $pdo;
27 26
        if ($redis) {
28 26
            $this->_redis = $redis;
29 26
        }
30 26
        if (!is_null($date)) {
31 26
            $this->_date = $date;
32 26
        }
33 26
    }
34
35
    /**
36
     * @param PDO $pdo
37
     * @param Redis $redis
38
     * @return FeaturedFlags
39
     */
40 2
    public static function getInstance(PDO $pdo, Redis $redis = null) {
41 2
        return new self($pdo, $redis);
42
    }
43
44
    /**
45
     * @param string $flagName
46
     * @param null|array $filterParams
47
     * @return boolean
48
     */
49 17
    public function isEnabled($flagName, $filterParams = null)
50
    {
51 17
        $cacheKey = $this->_getKey($flagName, $filterParams, self::ISENABLED_PREFIX);
52 17
        $cacheModel = $this->_getCacheModel($cacheKey);
53 17
        if ($cacheModel instanceof FeaturedFlagsModel)
54 17
        {
55 2
            return $cacheModel->isEnabled();
56
        }
57
58 15
        $featureFlagModel = $this->_getBDFlag($flagName, $filterParams);
59 15
        $this->_setCacheKey($cacheKey, $featureFlagModel);
60 15
        return $featureFlagModel->isEnabled();
61
    }
62
63
    /**
64
     * @param string $flagName
65
     * @param null|array $filterParams
66
     * @return array
67
     */
68 7
    public function getEnabledValues($flagName, $filterParams = null)
69
    {
70 7
        $cacheKey = $this->_getKey($flagName, $filterParams, self::GETVALUES_PREFIX);
71 7
        $cacheValue = $this->_getCacheModel($cacheKey);
72 7
        if ($cacheValue instanceof FeaturedFlagsModel)
73 7
        {
74 1
            return $cacheValue->getParamsArray();
75
        }
76
77 6
        $featureFlagModel = $this->_getBDFlag($flagName, $filterParams);
78 6
        $this->_setCacheKey($cacheKey, $featureFlagModel);
79 6
        return $featureFlagModel->getParamsArray();
80
    }
81
82
    /**
83
     * @param Redis $redis
84
     */
85 3
    public function setRedis(Redis $redis)
86
    {
87 3
        $this->_redis = $redis;
88 3
    }
89
90
    /**
91
     * @param string $flagName
92
     * @param null|array $filterParams
93
     * @return FeaturedFlagsModel
94
     */
95 21
    private function _getBDFlag($flagName, $filterParams)
96
    {
97 21
        $flagsData = $this->_getDBFlagsData($flagName);
98 21
        foreach ($flagsData as $flag) {
99 13
            if ($this->_checkParams($flag['params'], $filterParams))
100 13
            {
101 9
                return new FeaturedFlagsModel(true, $flag['return_params'], $flag['end_date']);
102
            }
103 14
        }
104
105 12
        return new FeaturedFlagsModel(false);
106
    }
107
108
    /**
109
     * @param string $cacheKey
110
     * @return FeaturedFlagsModel
111
     */
112 24
    private function _getCacheModel($cacheKey)
113
    {
114
        try {
115 24
            if (!is_null($this->_redis) && $this->_redis->get($cacheKey))
116 24
            {
117 3
                return $this->_redis->get($cacheKey);
118
            }
119 21
        } catch (\Exception $exc) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
120
        }
121 21
        return null;
122
    }
123
124
    /**
125
     * @param string $cacheKey
126
     * @param FeaturedFlagsModel $featuredFlagsModel
127
     */
128 21
    private function _setCacheKey($cacheKey, FeaturedFlagsModel $featuredFlagsModel)
129
    {
130 21
        if (!is_null($this->_redis)) {
131
            try {
132 21
                $timeOut = $this->_getTimeout($featuredFlagsModel->getEndDate());
133 21
                $this->_redis->set($cacheKey, $featuredFlagsModel, $timeOut);
134 21
            } catch (\Exception $e){}
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
135 21
        }
136 21
    }
137
138
    /**
139
     * @param string $query
140
     * @param array $params
141
     * @return \mysqli_stmt
142
     */
143 21
    private function _getStmt($query, $params)
144
    {
145 21
        $stmt = $this->_pdo->prepare($query);
146 21
        foreach ($params as $field => $value) {
147 21
            $stmt->bindValue(":$field", $value);
148 21
        }
149 21
        return $stmt;
150
    }
151
152
    /**
153
     * @param string $flagName
154
     * @return array
155
     */
156 21
    private function _getDBFlagsData($flagName)
157
    {
158 21
        $query = "SELECT * FROM ".self::TABLE_NAME." WHERE 
159
        name = :flag AND 
160
        status = 1 AND
161
        (   (start_date IS NULL AND end_date IS NULL)
162
                OR
163
            (start_date <= :now AND :now <= end_date)
164
                OR
165
            (:now <= end_date AND (start_date IS NULL OR start_date = ''))
166
                OR
167
            (start_date <= :now AND (end_date IS NULL OR end_date = ''))
168 21
        )";
169
170
        $params = array(
171 21
            'flag' => $flagName,
172 21
            'now'  =>  $this->_getDate()
173 21
        );
174
175 21
        return $this->_executeForSelect($query, $params);
176
    }
177
178
    /**
179
     * @param string $query
180
     * @param array $params
181
     * @return array
182
     */
183 21
    private function _executeForSelect($query, $params = array())
184
    {
185 21
        $stmt = $this->_getStmt($query, $params);
186 21
        $stmt->execute();
187 21
        return $stmt->fetchAll();
188
    }
189
190
    /**
191
     * @return string
192
     */
193 21
    private function _getDate() {
194 21
        if ($this->_date) {
195 20
            return $this->_date;
196
        }
197
198 1
        return date("Y-m-d H:i:s");
199
    }
200
201
    /**
202
     * @param array $flagParams
203
     * @param array $filterParams
204
     * @return boolean
205
     */
206 7
    private function _compareParams($flagParams, $filterParams)
207
    {
208 7
        $checkParams = true;
209 7
        foreach ($filterParams as $key => $value)
210
        {
211 7
            $checkParams = $checkParams && isset($flagParams[$key]) && $flagParams[$key] == $value;
212 7
        }
213
214 7
        return $checkParams;
215
    }
216
217
    /**
218
     * @param string $flagParamsJson
219
     * @param null|array $filterParams
220
     * @return boolean
221
     */
222 13
    private function _checkParams($flagParamsJson, $filterParams = null)
223
    {
224 13
        if (is_null($filterParams)) {
225 6
            return true;
226
        }
227
228 7
        $flagParamsData = json_decode($flagParamsJson, true);
229 7
        if (!is_array($flagParamsData) || count($flagParamsData) === 0) {
230 5
            return false;
231
        }
232
233 7
        return $this->_compareParams($flagParamsData, $filterParams);
234
    }
235
236
    /**
237
     * @param string $flagName
238
     * @param array|null $filterParams
239
     * @param string $prefix
240
     * @return boolean
241
     */
242 24
    private function _getKey($flagName, $filterParams = null, $prefix = "")
243
    {
244 24
        return $prefix."FF_".$flagName.json_encode($filterParams);
245
    }
246
247
    /**
248
     * @param string $endDate
249
     * @return int
250
     */
251 21
    private function _getTimeout($endDate)
252
    {
253 21
        if (!$endDate) {
254 17
            return 0;
255
        }
256
257 4
        return strtotime($endDate) - strtotime($this->_getDate());
258
    }
259
}
260