Completed
Pull Request — master (#200)
by Aleksander
09:18
created

RedisAdapter::addHashPrefix()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 8
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 5
nc 1
nop 3
1
<?php
2
/**
3
 * Yandex PHP Library
4
 *
5
 * @copyright NIX Solutions Ltd.
6
 * @link https://github.com/nixsolutions/yandex-php-library
7
 */
8
9
/**
10
 * @namespace
11
 */
12
namespace Yandex\SafeBrowsing\Adapter;
13
14
use Predis\Client;
15
16
/**
17
 * Class RedisAdapter
18
 *
19
 * @category Yandex
20
 * @package SafeBrowsing
21
 */
22
class RedisAdapter
23
{
24
    const KEY_SHA_VARS = 'sha_vars';
25
    const KEY_SHA_VAR = 'sha_var';
26
27
    const KEY_HASH_PREFIXES = 'hash_prefixes';
28
    const KEY_HASH_PREFIX = 'hash_prefix';
29
30
    const KEY_CHUNK_NUMS = 'chunk_nums';
31
    const KEY_CHUNK_NUM = 'chunk_num';
32
33
    /**
34
     * @var Client
35
     */
36
    private $client;
37
38
    public function __construct($dsn = '', $options = [])
39
    {
40
        $this->client = $this->initClient($dsn, $options);
41
    }
42
43
    /**
44
     * @param string $dsn
45
     * @param array $options
46
     * @param bool $reset
47
     * @return Client
48
     */
49
    public function initClient($dsn = '', $options = [], $reset = false)
50
    {
51
        if (!$this->client || $reset) {
52
            $this->client = new Client($dsn, $options);
53
            $this->client->ping();
54
        }
55
56
        return $this->client;
57
    }
58
59
    /**
60
     * @param string $shaVar
61
     */
62
    public function addShaVar($shaVar)
63
    {
64
        $this->client->sadd(self::KEY_SHA_VARS, [$shaVar]);
65
    }
66
67
    /**
68
     * @param string $shaVar
69
     * @param string $chunkNum
70
     */
71
    public function addChunkNum($shaVar, $chunkNum)
72
    {
73
        $this->client->sadd(sprintf('%s:%s:%s', self::KEY_SHA_VAR, $shaVar, self::KEY_CHUNK_NUMS), [$chunkNum]);
74
    }
75
76
    /**
77
     * @param string $shaVar
78
     * @param string $chunkNum
79
     * @param string $hashPrefix
80
     */
81
    public function addHashPrefix($shaVar, $chunkNum, $hashPrefix)
82
    {
83
        $this->client->sadd(sprintf('%s:%s:%s', self::KEY_SHA_VAR, $shaVar, $chunkNum), [$hashPrefix]);
84
        $this->client->set(sprintf('%s:%s', self::KEY_HASH_PREFIX, $hashPrefix), json_encode([
85
            'sha_var' => $shaVar,
86
            'chunk_num' => $chunkNum,
87
        ]));
88
    }
89
90
    /**
91
     * @param string $shaVar
92
     * @param string $chunkNum
93
     * @param string $hashPrefix
94
     */
95
    public function saveHashPrefix($shaVar, $chunkNum, $hashPrefix)
96
    {
97
        $this->addShaVar($shaVar);
98
        $this->addChunkNum($shaVar, $chunkNum);
99
        $this->addHashPrefix($shaVar, $chunkNum, $hashPrefix);
100
    }
101
102
    public function getShaVars()
103
    {
104
        return $this->client->smembers(self::KEY_SHA_VARS);
105
    }
106
107
    /**
108
     * @param string $shaVar
109
     * @return array
110
     */
111
    public function getChunkNums($shaVar)
112
    {
113
        return $this->client->smembers(sprintf('%s:%s:%s', self::KEY_SHA_VAR, $shaVar, self::KEY_CHUNK_NUMS));
114
    }
115
116
    /**
117
     * @param string $shaVar
118
     * @param string $chunkNum
119
     * @return array
120
     */
121
    public function getHashPrefixes($shaVar, $chunkNum)
122
    {
123
        return $this->client->smembers(sprintf('%s:%s:%s', self::KEY_SHA_VAR, $shaVar, $chunkNum));
124
    }
125
126
    /**
127
     * @param string $hashPrefix
128
     * @return string|null
129
     */
130
    public function getHashPrefix($hashPrefix)
131
    {
132
        return $this->client->get(sprintf('%s:%s', self::KEY_HASH_PREFIX, $hashPrefix));
133
    }
134
135
    /**
136
     * @param string $shaVar
137
     * @param string $chunkNum
138
     */
139
    public function removeChunkNum($shaVar, $chunkNum)
140
    {
141
        $this->client->srem(sprintf('%s:%s:%s', self::KEY_SHA_VAR, $shaVar, self::KEY_CHUNK_NUMS), $chunkNum);
142
        $this->client->del(sprintf('%s:%s:%s', self::KEY_SHA_VAR, $shaVar, $chunkNum));
143
        //todo: Remove sha_var if its last chunk_num removed
144
    }
145
146
    /**
147
     * @param string $shaVar
148
     * @param string $chunkNum
149
     * @param string $hashPrefix
150
     */
151
    public function removeHashPrefix($shaVar, $chunkNum, $hashPrefix)
152
    {
153
        $this->client->srem(sprintf('%s:%s:%s', self::KEY_SHA_VAR, $shaVar, $chunkNum), $hashPrefix);
154
        $this->client->del(sprintf('%s:%s', self::KEY_HASH_PREFIX, $hashPrefix));
155
        //todo: Remove chunk_num if its last hashPrefix removed
156
    }
157
158
    /**
159
     * @param array $hashes
160
     * @return bool
161
     */
162
    public function hasHashes($hashes)
163
    {
164
        if (!is_array($hashes)) {
165
            return false;
166
        }
167
168
        foreach ($hashes as $hash) {
169
            if (!empty($hash['prefix']) && $this->getHashPrefix($hash['prefix'])) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->getHashPrefix($hash['prefix']) of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
170
                var_dump($this->getHashPrefix($hash['prefix']));exit;
0 ignored issues
show
Security Debugging Code introduced by
var_dump($this->getHashPrefix($hash['prefix'])); looks like debug code. Are you sure you do not want to remove it? This might expose sensitive data.
Loading history...
171
                return true;
0 ignored issues
show
Unused Code introduced by
return true; does not seem to be reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
172
            }
173
        }
174
175
        return false;
176
    }
177
}
178