SqLiteStorage::delete()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 4
nc 1
nop 1
dl 0
loc 7
ccs 5
cts 5
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * PhPsst.
4
 *
5
 * @copyright Copyright (c) 2018 Felix Sandström
6
 * @license   MIT
7
 */
8
9
namespace PhPsst\Storage;
10
11
use PhPsst\Password;
12
use PhPsst\PhPsstException;
13
use SQLite3;
14
15
/**
16
 * @author Felix Sandström <http://github.com/felixsand>
17
 */
18
class SqLiteStorage extends Storage
19
{
20
    /**
21
     * @var int
22
     */
23
    protected $gcProbability;
24
25
    /**
26
     * @var SQLite3
27
     */
28
    protected $db;
29
30 2
    public function __construct(SQLite3 $db, int $gcProbability)
31
    {
32 2
        if ($gcProbability < 0) {
33 1
            throw new \LogicException('Invalid value for gcProbability');
34
        }
35 1
        $this->gcProbability = $gcProbability;
36
37 1
        $this->db = $db;
38 1
        if (method_exists(SQLite3::class, 'enableExceptions')) {
39
            // Method not available on HHVM
40 1
            $this->db->enableExceptions(true);
41
        }
42 1
        $sql = <<<'SQL'
43
CREATE TABLE IF NOT EXISTS `phPsst` (
44
  id VARCHAR(13) PRIMARY KEY NOT NULL,
45
  password TEXT NOT NULL,
46
  ttl INT NOT NULL,
47
  views INT NOT NULL
48
);
49
SQL;
50 1
        $this->db->exec($sql);
51
    }
52
53 7
    public function store(Password $password, bool $allowOverwrite = false): void
54
    {
55 7
        if ($this->get($password->getId())) {
56 2
            if (!$allowOverwrite) {
57 1
                throw new PhPsstException('The ID already exists', PhPsstException::ID_IS_ALREADY_TAKEN);
58
            }
59
60 1
            $this->delete($password);
61
        }
62
63 7
        $stmt = $this->db->prepare('INSERT INTO phPsst VALUES (:id, :password, :ttl, :views)');
64 7
        $stmt->bindValue(':id', $password->getId(), SQLITE3_TEXT);
65 7
        $stmt->bindValue(':password', $password->getPassword(), SQLITE3_TEXT);
66 7
        $stmt->bindValue(':ttl', $password->getTtl(), SQLITE3_INTEGER);
67 7
        $stmt->bindValue(':views', $password->getViews(), SQLITE3_INTEGER);
68 7
        $stmt->execute();
69
70 7
        $this->garbageCollection();
71
    }
72
73 4
    public function get(string $key): ?Password
74
    {
75 4
        $password = null;
76
77 4
        $stmt = $this->db->prepare('SELECT * FROM phPsst WHERE ID = :id');
78 4
        $stmt->bindValue(':id', $key, SQLITE3_TEXT);
79 4
        $result = $stmt->execute();
80 4
        if (($row = $result->fetchArray())) {
81 4
            $password = new Password($row['id'], $row['password'], $row['ttl'], $row['views']);
82 4
            if ($row['ttl'] < time()) {
83 1
                $this->delete($password);
84 1
                $password = null;
85
            }
86
        }
87
88 4
        return $password;
89
    }
90
91 2
    public function delete(Password $password): void
92
    {
93 2
        $stmt = $this->db->prepare('DELETE FROM phPsst WHERE ID = :id');
94 2
        $stmt->bindValue(':id', $password->getId(), SQLITE3_TEXT);
95 2
        $stmt->execute();
96
97 2
        $this->garbageCollection();
98
    }
99
100 7
    protected function garbageCollection(): void
101
    {
102 7
        if (!$this->gcProbability || rand(1, $this->gcProbability) !== 1) {
103 3
            return;
104
        }
105
106 4
        $stmt = $this->db->prepare('DELETE FROM phPsst WHERE ttl < :time');
107 4
        $stmt->bindValue(':time', time(), SQLITE3_INTEGER);
108 4
        $stmt->execute();
109
    }
110
}
111