Completed
Push — master ( d52614...d96638 )
by Pedro García
02:43
created

FeaturedFlagsImpl::_getDate()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
c 2
b 0
f 0
dl 0
loc 7
rs 9.4285
cc 2
eloc 4
nc 2
nop 0
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 array $filterParams
47
     * @return boolean
48
     */
49
    public function isEnabled($flagName, $filterParams = null)
50
    {
51
        $cacheKey = self::ISENABLED_PREFIX.$this->_getKey($flagName, $filterParams);
52
        $cacheModel = $this->_getCacheModel($cacheKey);
53
        if ($cacheModel instanceof FeaturedFlagsModel)
54
        {
55
            return $cacheModel->isEnabled();
56
        }
57
58
        $featureFlagModel = $this->_getBDFlag($flagName, $filterParams);
0 ignored issues
show
Bug introduced by
It seems like $filterParams defined by parameter $filterParams on line 49 can also be of type null; however, FeaturedFlags\FeaturedFlagsImpl::_getBDFlag() does only seem to accept array, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
59
        $this->_setCacheKey($cacheKey, $featureFlagModel);
60
        return $featureFlagModel->isEnabled();
61
    }
62
63
    /**
64
     * @param $flagName
65
     * @param $filterParams
66
     * @return array
67
     */
68
    public function getEnabledValues($flagName, $filterParams = null)
69
    {
70
        $cacheKey = self::GETVALUES_PREFIX.$this->_getKey($flagName, $filterParams);
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 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 $flagName
136
     * @return array
137
     */
138
    private function _getDBFlagsData($flagName)
139
    {
140
        $query = "SELECT * FROM ".self::TABLE_NAME." WHERE 
141
        name = :flag AND 
142
        status = 1 AND
143
        (   (start_date IS NULL AND end_date IS NULL)
144
                OR
145
            (start_date <= :now AND :now <= end_date)
146
                OR
147
            (:now <= end_date AND (start_date IS NULL OR start_date = ''))
148
                OR
149
            (start_date <= :now AND (end_date IS NULL OR end_date = ''))
150
        )";
151
152
        $params = array(
153
            'flag' => $flagName,
154
            'now'  =>  $this->_getDate()
155
        );
156
157
        $stmt = $this->_pdo->prepare($query);
158
        foreach ($params as $field => $value) {
159
            $stmt->bindValue(":$field", $value);
160
        }
161
        $stmt->execute();
162
        return $stmt->fetchAll();
163
    }
164
165
    /**
166
     * @return string
167
     */
168
    private function _getDate() {
169
        if ($this->_date) {
170
            return $this->_date;
171
        }
172
173
        return date("Y-m-d H:i:s");
174
    }
175
176
    /**
177
     * @param array $flagParams
178
     * @param array $filterParams
179
     * @return boolean
180
     */
181
    private function _compareParams($flagParams, $filterParams)
182
    {
183
        $checkParams = true;
184
        foreach($filterParams as $key => $value)
185
        {
186
            $checkParams = $checkParams && isset($flagParams[$key]) && $flagParams[$key] == $value;
187
        }
188
189
        return $checkParams;
190
    }
191
192
    /**
193
     * @param string $flagParamsJson
194
     * @param array $filterParams
195
     * @return boolean
196
     */
197
    private function _checkParams($flagParamsJson, $filterParams = null)
198
    {
199
        if (!$filterParams) {
200
            return true;
201
        }
202
203
        $flagParamsData = json_decode($flagParamsJson, true);
204
        if (!is_array($flagParamsData) || count($flagParamsData) === 0) {
205
            return false;
206
        }
207
208
        return $this->_compareParams($flagParamsData, $filterParams);
209
    }
210
211
    /**
212
     * @param string $flagName
213
     * @param array|null $filterParams
214
     * @return boolean
215
     */
216
    private function _getKey($flagName, $filterParams = null)
217
    {
218
        return "FF_".$flagName.json_encode($filterParams);
219
    }
220
221
    /**
222
     * @param string $endDate
223
     * @return int
224
     */
225
    private function _getTimeout($endDate)
226
    {
227
        if (!$endDate) {
228
            return 0;
229
        }
230
231
        return strtotime($endDate) - strtotime($this->_getDate());
232
    }
233
}
234