Completed
Push — master ( d7c058...80cfce )
by Pedro García
02:35
created

FeaturedFlagsImpl::_getStmt()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
c 2
b 0
f 0
dl 0
loc 8
rs 9.4285
cc 2
eloc 5
nc 2
nop 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
    public function __construct(PDO $pdo, Redis $redis = null, $date = null)
25
    {
26
        $this->_pdo = $pdo;
27
        if ($redis) {
28
            $this->_redis = $redis;
29
        }
30
        if (!is_null($date)) {
31
            $this->_date = $date;
32
        }
33
    }
34
35
    /**
36
     * @param PDO $pdo
37
     * @param Redis $redis
38
     * @return FeaturedFlags
39
     */
40
    public static function getInstance(PDO $pdo, Redis $redis = null) {
41
        return new self($pdo, $redis);
42
    }
43
44
    /**
45
     * @param string $flagName
46
     * @param null|array $filterParams
47
     * @return boolean
48
     */
49
    public function isEnabled($flagName, $filterParams = null)
50
    {
51
        $cacheKey = $this->_getKey($flagName, $filterParams, self::ISENABLED_PREFIX);
52
        $cacheModel = $this->_getCacheModel($cacheKey);
53
        if ($cacheModel instanceof FeaturedFlagsModel)
54
        {
55
            return $cacheModel->isEnabled();
56
        }
57
58
        $featureFlagModel = $this->_getBDFlag($flagName, $filterParams);
59
        $this->_setCacheKey($cacheKey, $featureFlagModel);
60
        return $featureFlagModel->isEnabled();
61
    }
62
63
    /**
64
     * @param string $flagName
65
     * @param null|array $filterParams
66
     * @return array
67
     */
68
    public function getEnabledValues($flagName, $filterParams = null)
69
    {
70
        $cacheKey = $this->_getKey($flagName, $filterParams, self::GETVALUES_PREFIX);
71
        $cacheValue = $this->_getCacheModel($cacheKey);
72
        if ($cacheValue instanceof FeaturedFlagsModel)
73
        {
74
            return $cacheValue->getParamsArray();
75
        }
76
77
        $featureFlagModel = $this->_getBDFlag($flagName, $filterParams);
78
        $this->_setCacheKey($cacheKey, $featureFlagModel);
79
        return $featureFlagModel->getParamsArray();
80
    }
81
82
    /**
83
     * @param Redis $redis
84
     */
85
    public function setRedis(Redis $redis)
86
    {
87
        $this->_redis = $redis;
88
    }
89
90
    /**
91
     * @param string $flagName
92
     * @param null|array $filterParams
93
     * @return FeaturedFlagsModel
94
     */
95
    private function _getBDFlag($flagName, $filterParams)
96
    {
97
        $flagsData = $this->_getDBFlagsData($flagName);
98
        foreach ($flagsData as $flag) {
99
            if ($this->_checkParams($flag['params'], $filterParams))
100
            {
101
                return new FeaturedFlagsModel(true, $flag['return_params'], $flag['end_date']);
102
            }
103
        }
104
105
        return new FeaturedFlagsModel(false);
106
    }
107
108
    /**
109
     * @param string $cacheKey
110
     * @return FeaturedFlagsModel
111
     */
112
    private function _getCacheModel($cacheKey)
113
    {
114
        if (!is_null($this->_redis) && $this->_redis->get($cacheKey))
115
        {
116
            return $this->_redis->get($cacheKey);
117
        }
118
119
        return null;
120
    }
121
122
    /**
123
     * @param string $cacheKey
124
     * @param FeaturedFlagsModel $featuredFlagsModel
125
     */
126
    private function _setCacheKey($cacheKey, FeaturedFlagsModel $featuredFlagsModel)
127
    {
128
        if (!is_null($this->_redis)) {
129
            $timeOut = $this->_getTimeout($featuredFlagsModel->getEndDate());
130
            $this->_redis->set($cacheKey, $featuredFlagsModel, $timeOut);
131
        }
132
    }
133
134
    /**
135
     * @param string $query
136
     * @param array $params
137
     * @return \mysqli_stmt
138
     */
139
    private function _getStmt($query, $params)
140
    {
141
        $stmt = $this->_pdo->prepare($query);
142
        foreach ($params as $field => $value) {
143
            $stmt->bindValue(":$field", $value);
144
        }
145
        return $stmt;
146
    }
147
148
    /**
149
     * @param string $flagName
150
     * @return array
151
     */
152
    private function _getDBFlagsData($flagName)
153
    {
154
        $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
        )";
165
166
        $params = array(
167
            'flag' => $flagName,
168
            'now'  =>  $this->_getDate()
169
        );
170
171
        return $this->_executeForSelect($query, $params);
172
    }
173
174
    /**
175
     * @param string $query
176
     * @param array $params
177
     * @return array
178
     */
179
    private function _executeForSelect($query, $params = array())
180
    {
181
        $stmt = $this->_getStmt($query, $params);
182
        $stmt->execute();
183
        return $stmt->fetchAll();
184
    }
185
186
    /**
187
     * @return string
188
     */
189
    private function _getDate() {
190
        if ($this->_date) {
191
            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
    private function _compareParams($flagParams, $filterParams)
203
    {
204
        $checkParams = true;
205
        foreach ($filterParams as $key => $value)
206
        {
207
            $checkParams = $checkParams && isset($flagParams[$key]) && $flagParams[$key] == $value;
208
        }
209
210
        return $checkParams;
211
    }
212
213
    /**
214
     * @param string $flagParamsJson
215
     * @param null|array $filterParams
216
     * @return boolean
217
     */
218
    private function _checkParams($flagParamsJson, $filterParams = null)
219
    {
220
        if (is_null($filterParams)) {
221
            return true;
222
        }
223
224
        $flagParamsData = json_decode($flagParamsJson, true);
225
        if (!is_array($flagParamsData) || count($flagParamsData) === 0) {
226
            return false;
227
        }
228
229
        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
    private function _getKey($flagName, $filterParams = null, $prefix = "")
239
    {
240
        return $prefix."FF_".$flagName.json_encode($filterParams);
241
    }
242
243
    /**
244
     * @param string $endDate
245
     * @return int
246
     */
247
    private function _getTimeout($endDate)
248
    {
249
        if (!$endDate) {
250
            return 0;
251
        }
252
253
        return strtotime($endDate) - strtotime($this->_getDate());
254
    }
255
}
256