PdoLockerStore   A
last analyzed

Complexity

Total Complexity 17

Size/Duplication

Total Lines 197
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
dl 0
loc 197
rs 10
c 0
b 0
f 0
wmc 17

10 Methods

Rating   Name   Duplication   Size   Complexity  
A update() 0 20 2
A getAll() 0 10 1
A acquire() 0 16 1
A __construct() 0 4 1
A createSchema() 0 10 1
A get() 0 21 2
A executeQueryInATransaction() 0 21 4
A clear() 0 5 1
A exists() 0 9 2
A delete() 0 14 2
1
<?php
2
/**
3
 * This file is part of the LockerManager package.
4
 *
5
 * (c) Mauro Cassani<https://github.com/mauretto78>
6
 *
7
 * For the full copyright and license information, please view the LICENSE
8
 * file that was distributed with this source code.
9
 */
10
11
namespace LockerManager\Infrastructure;
12
13
use Cocur\Slugify\Slugify;
14
use LockerManager\Domain\Lock;
15
use LockerManager\Infrastructure\Exception\ExistingKeyException;
16
use LockerManager\Infrastructure\Exception\InvalidArgumentException;
17
use LockerManager\Infrastructure\Exception\LockingKeyException;
18
use LockerManager\Infrastructure\Exception\NotExistingKeyException;
19
20
class PdoLockerStore implements LockerStoreInterface
21
{
22
    const LOCKERSTORE_TABLE_NAME = 'lockerstore';
23
24
    /**
25
     * @var \PDO
26
     */
27
    private $pdo;
28
29
    /**
30
     * PdoLockerStore constructor.
31
     * @param \PDO $pdo
32
     */
33
    public function __construct(\PDO $pdo)
34
    {
35
        $this->pdo = $pdo;
36
        $this->createSchema();
37
    }
38
39
    /**
40
     * createSchema
41
     */
42
    private function createSchema()
43
    {
44
        $query = "CREATE TABLE IF NOT EXISTS `".self::LOCKERSTORE_TABLE_NAME."` (
45
          `id` int(11) NOT NULL AUTO_INCREMENT,
46
          `key` varchar(255) NOT NULL UNIQUE,
47
          `body` text DEFAULT NULL,
48
          PRIMARY KEY (`id`)
49
        ) ENGINE=InnoDB DEFAULT CHARSET=utf8;";
50
51
        $this->pdo->exec($query);
52
    }
53
54
    /**
55
     * @param Lock $lock
56
     */
57
    public function acquire(Lock $lock)
58
    {
59
        $sql = 'INSERT INTO `'.self::LOCKERSTORE_TABLE_NAME.'` (
60
                    `key`,
61
                    `body`
62
                  ) VALUES (
63
                    :key,
64
                    :body
65
            )';
66
67
        $data = [
68
            'key' => $lock->key(),
69
            'body' => serialize($lock)
70
        ];
71
72
        $this->executeQueryInATransaction($sql, $data);
73
    }
74
75
    /**
76
     * @param $sql
77
     * @param array|null $data
78
     */
79
    private function executeQueryInATransaction($sql, array $data = null)
80
    {
81
        try {
82
            $this->pdo->setAttribute(\PDO::ATTR_ERRMODE,\PDO::ERRMODE_EXCEPTION);
83
            $this->pdo->beginTransaction();
84
85
            $stmt = $this->pdo->prepare($sql);
86
87
            if ($data) {
88
                foreach ($data as $key => &$value){
89
                    $stmt->bindParam(':'.$key, $value);
90
                }
91
            }
92
93
            $stmt->execute();
94
95
            $this->pdo->commit();
96
        } catch(\PDOException $e){
97
            $this->pdo->rollBack();
98
99
            throw $e;
100
        }
101
    }
102
103
    /**
104
     * clear all locks
105
     */
106
    public function clear()
107
    {
108
        $sql = 'DELETE FROM `'.self::LOCKERSTORE_TABLE_NAME.'`';
109
110
        $this->executeQueryInATransaction($sql);
111
    }
112
113
    /**
114
     * @param $key
115
     * @throws NotExistingKeyException
116
     */
117
    public function delete($key)
118
    {
119
        if (!$this->exists($key)) {
120
            throw new NotExistingKeyException(sprintf('The key "%s" does not exists.', $key));
121
        }
122
123
        $key = (new Slugify())->slugify($key);
124
        $sql = 'DELETE FROM `'.self::LOCKERSTORE_TABLE_NAME.'` WHERE `key` = :key';
125
126
        $data = [
127
            'key' => $key
128
        ];
129
130
        $this->executeQueryInATransaction($sql, $data);
131
    }
132
133
    /**
134
     * @param $key
135
     * @return bool
136
     */
137
    public function exists($key)
138
    {
139
        $key = (new Slugify())->slugify($key);
140
        $sql = 'SELECT id FROM `'.self::LOCKERSTORE_TABLE_NAME.'` WHERE `key` = :key';
141
        $stmt = $this->pdo->prepare($sql);
142
        $stmt->bindParam(':key', $key);
143
        $stmt->execute();
144
145
        return ($stmt->rowCount() > 0) ? true : false;
146
    }
147
148
    /**
149
     * @param $key
150
     * @return mixed
151
     * @throws NotExistingKeyException
152
     */
153
    public function get($key)
154
    {
155
        if (!$this->exists($key)) {
156
            throw new NotExistingKeyException(sprintf('The key "%s" does not exists.', $key));
157
        }
158
159
        $key = (new Slugify())->slugify($key);
160
        $query = 'SELECT
161
                  `key`,
162
                  `body`
163
                FROM `'.self::LOCKERSTORE_TABLE_NAME.'` 
164
                WHERE `key` = :key';
165
        $stmt = $this->pdo->prepare($query);
166
        $stmt->bindParam(':key', $key);
167
        $stmt->execute();
168
169
        $row = $stmt->fetchAll(
170
            \PDO::FETCH_ASSOC
171
        );
172
173
        return unserialize($row[0]['body']);
174
    }
175
176
    /**
177
     * @return array
178
     */
179
    public function getAll()
180
    {
181
        $query = 'SELECT
182
                  `key`,
183
                  `body`
184
                FROM `'.self::LOCKERSTORE_TABLE_NAME.'`';
185
        $stmt = $this->pdo->prepare($query);
186
        $stmt->execute();
187
188
        return $stmt->fetchAll(\PDO::FETCH_ASSOC);
189
    }
190
191
    /**
192
     * @param $key
193
     * @param $payload
194
     *
195
     * @throws NotExistingKeyException
196
     */
197
    public function update($key, $payload)
198
    {
199
        if (!$this->exists($key)) {
200
            throw new NotExistingKeyException(sprintf('The key "%s" does not exists.', $key));
201
        }
202
203
        /** @var Lock $lock */
204
        $lock = $this->get($key);
205
        $lock->update($payload);
206
207
        $sql = "UPDATE `".self::LOCKERSTORE_TABLE_NAME."` 
208
                SET `body` = :lock 
209
                WHERE `key` = :key";
210
211
        $data = [
212
            'key' => $lock->key(),
213
            'lock' => serialize($lock)
214
        ];
215
216
        $this->executeQueryInATransaction($sql, $data);
217
    }
218
}
219