Completed
Push — master ( 008f67...9b7c09 )
by Pedro García
02:30
created

FeaturedFlagsImpl::setRedis()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 4
ccs 3
cts 3
cp 1
rs 10
cc 1
eloc 2
nc 1
nop 1
crap 1
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 21
            $timeOut = $this->_getTimeout($featuredFlagsModel->getEndDate());
132 21
            $this->_redis->set($cacheKey, $featuredFlagsModel, $timeOut);
133 21
        }
134 21
    }
135
136
    /**
137
     * @param string $query
138
     * @param array $params
139
     * @return \mysqli_stmt
140
     */
141 21
    private function _getStmt($query, $params)
142
    {
143 21
        $stmt = $this->_pdo->prepare($query);
144 21
        foreach ($params as $field => $value) {
145 21
            $stmt->bindValue(":$field", $value);
146 21
        }
147 21
        return $stmt;
148
    }
149
150
    /**
151
     * @param string $flagName
152
     * @return array
153
     */
154 21
    private function _getDBFlagsData($flagName)
155
    {
156 21
        $query = "SELECT * FROM ".self::TABLE_NAME." WHERE 
157
        name = :flag AND 
158
        status = 1 AND
159
        (   (start_date IS NULL AND end_date IS NULL)
160
                OR
161
            (start_date <= :now AND :now <= end_date)
162
                OR
163
            (:now <= end_date AND (start_date IS NULL OR start_date = ''))
164
                OR
165
            (start_date <= :now AND (end_date IS NULL OR end_date = ''))
166 21
        )";
167
168
        $params = array(
169 21
            'flag' => $flagName,
170 21
            'now'  =>  $this->_getDate()
171 21
        );
172
173 21
        return $this->_executeForSelect($query, $params);
174
    }
175
176
    /**
177
     * @param string $query
178
     * @param array $params
179
     * @return array
180
     */
181 21
    private function _executeForSelect($query, $params = array())
182
    {
183 21
        $stmt = $this->_getStmt($query, $params);
184 21
        $stmt->execute();
185 21
        return $stmt->fetchAll();
186
    }
187
188
    /**
189
     * @return string
190
     */
191 21
    private function _getDate() {
192 21
        if ($this->_date) {
193 20
            return $this->_date;
194
        }
195
196 1
        return date("Y-m-d H:i:s");
197
    }
198
199
    /**
200
     * @param array $flagParams
201
     * @param array $filterParams
202
     * @return boolean
203
     */
204 7
    private function _compareParams($flagParams, $filterParams)
205
    {
206 7
        $checkParams = true;
207 7
        foreach ($filterParams as $key => $value)
208
        {
209 7
            $checkParams = $checkParams && isset($flagParams[$key]) && $flagParams[$key] == $value;
210 7
        }
211
212 7
        return $checkParams;
213
    }
214
215
    /**
216
     * @param string $flagParamsJson
217
     * @param null|array $filterParams
218
     * @return boolean
219
     */
220 13
    private function _checkParams($flagParamsJson, $filterParams = null)
221
    {
222 13
        if (is_null($filterParams)) {
223 6
            return true;
224
        }
225
226 7
        $flagParamsData = json_decode($flagParamsJson, true);
227 7
        if (!is_array($flagParamsData) || count($flagParamsData) === 0) {
228 5
            return false;
229
        }
230
231 7
        return $this->_compareParams($flagParamsData, $filterParams);
232
    }
233
234
    /**
235
     * @param string $flagName
236
     * @param array|null $filterParams
237
     * @param string $prefix
238
     * @return boolean
239
     */
240 24
    private function _getKey($flagName, $filterParams = null, $prefix = "")
241
    {
242 24
        return $prefix."FF_".$flagName.json_encode($filterParams);
243
    }
244
245
    /**
246
     * @param string $endDate
247
     * @return int
248
     */
249 21
    private function _getTimeout($endDate)
250
    {
251 21
        if (!$endDate) {
252 17
            return 0;
253
        }
254
255 4
        return strtotime($endDate) - strtotime($this->_getDate());
256
    }
257
}
258