Completed
Push — master ( 6939d3...c48be5 )
by Pedro García
02:38
created

FeaturedFlagsImpl::_getTimeout()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 8
ccs 4
cts 4
cp 1
rs 9.4285
cc 2
eloc 4
nc 2
nop 1
crap 2
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 25
    public function __construct(PDO $pdo, Redis $redis = null, $date = null)
25 1
    {
26 25
        $this->_pdo = $pdo;
27 25
        if ($redis) {
28 25
            $this->_redis = $redis;
29 25
        }
30 25
        if (!is_null($date)) {
31 25
            $this->_date = $date;
32 25
        }
33 25
    }
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 16
    public function isEnabled($flagName, $filterParams = null)
50
    {
51 16
        $cacheKey = $this->_getKey($flagName, $filterParams, self::ISENABLED_PREFIX);
52 16
        $cacheModel = $this->_getCacheModel($cacheKey);
53 16
        if ($cacheModel instanceof FeaturedFlagsModel)
54 16
        {
55 2
            return $cacheModel->isEnabled();
56
        }
57
58 14
        $featureFlagModel = $this->_getBDFlag($flagName, $filterParams);
59 14
        $this->_setCacheKey($cacheKey, $featureFlagModel);
60 14
        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 20
    private function _getBDFlag($flagName, $filterParams)
96
    {
97 20
        $flagsData = $this->_getDBFlagsData($flagName);
98 20
        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 13
        }
104
105 11
        return new FeaturedFlagsModel(false);
106
    }
107
108
    /**
109
     * @param string $cacheKey
110
     * @return FeaturedFlagsModel
111
     */
112 23
    private function _getCacheModel($cacheKey)
113
    {
114 23
        if (!is_null($this->_redis) && $this->_redis->get($cacheKey))
115 23
        {
116 3
            return $this->_redis->get($cacheKey);
117
        }
118
119 20
        return null;
120
    }
121
122
    /**
123
     * @param string $cacheKey
124
     * @param FeaturedFlagsModel $featuredFlagsModel
125
     */
126 20
    private function _setCacheKey($cacheKey, FeaturedFlagsModel $featuredFlagsModel)
127
    {
128 20
        if (!is_null($this->_redis)) {
129 20
            $timeOut = $this->_getTimeout($featuredFlagsModel->getEndDate());
130 20
            $this->_redis->set($cacheKey, $featuredFlagsModel, $timeOut);
131 20
        }
132 20
    }
133
134
    /**
135
     * @param string $query
136
     * @param array $params
137
     * @return \mysqli_stmt
138
     */
139 20
    private function _getStmt($query, $params)
140
    {
141 20
        $stmt = $this->_pdo->prepare($query);
142 20
        foreach ($params as $field => $value) {
143 20
            $stmt->bindValue(":$field", $value);
144 20
        }
145 20
        return $stmt;
146
    }
147
148
    /**
149
     * @param string $flagName
150
     * @return array
151
     */
152 20
    private function _getDBFlagsData($flagName)
153
    {
154 20
        $query = "SELECT * FROM ".self::TABLE_NAME." WHERE 
155
        name = :flag AND 
156
        status = 1 AND
157
        (   (start_date IS NULL AND end_date IS NULL)
158
                OR
159
            (start_date <= :now AND :now <= end_date)
160
                OR
161
            (:now <= end_date AND (start_date IS NULL OR start_date = ''))
162
                OR
163
            (start_date <= :now AND (end_date IS NULL OR end_date = ''))
164 20
        )";
165
166
        $params = array(
167 20
            'flag' => $flagName,
168 20
            'now'  =>  $this->_getDate()
169 20
        );
170
171 20
        return $this->_executeForSelect($query, $params);
172
    }
173
174
    /**
175
     * @param string $query
176
     * @param array $params
177
     * @return array
178
     */
179 20
    private function _executeForSelect($query, $params = array())
180
    {
181 20
        $stmt = $this->_getStmt($query, $params);
182 20
        $stmt->execute();
183 20
        return $stmt->fetchAll();
184
    }
185
186
    /**
187
     * @return string
188
     */
189 20
    private function _getDate() {
190 20
        if ($this->_date) {
191 20
            return $this->_date;
192
        }
193
194
        return date("Y-m-d H:i:s");
195
    }
196
197
    /**
198
     * @param array $flagParams
199
     * @param array $filterParams
200
     * @return boolean
201
     */
202 7
    private function _compareParams($flagParams, $filterParams)
203
    {
204 7
        $checkParams = true;
205 7
        foreach ($filterParams as $key => $value)
206
        {
207 7
            $checkParams = $checkParams && isset($flagParams[$key]) && $flagParams[$key] == $value;
208 7
        }
209
210 7
        return $checkParams;
211
    }
212
213
    /**
214
     * @param string $flagParamsJson
215
     * @param null|array $filterParams
216
     * @return boolean
217
     */
218 13
    private function _checkParams($flagParamsJson, $filterParams = null)
219
    {
220 13
        if (is_null($filterParams)) {
221 6
            return true;
222
        }
223
224 7
        $flagParamsData = json_decode($flagParamsJson, true);
225 7
        if (!is_array($flagParamsData) || count($flagParamsData) === 0) {
226 5
            return false;
227
        }
228
229 7
        return $this->_compareParams($flagParamsData, $filterParams);
230
    }
231
232
    /**
233
     * @param string $flagName
234
     * @param array|null $filterParams
235
     * @param string $prefix
236
     * @return boolean
237
     */
238 23
    private function _getKey($flagName, $filterParams = null, $prefix = "")
239
    {
240 23
        return $prefix."FF_".$flagName.json_encode($filterParams);
241
    }
242
243
    /**
244
     * @param string $endDate
245
     * @return int
246
     */
247 20
    private function _getTimeout($endDate)
248
    {
249 20
        if (!$endDate) {
250 16
            return 0;
251
        }
252
253 4
        return strtotime($endDate) - strtotime($this->_getDate());
254
    }
255
}
256