Passed
Pull Request — develop (#27)
by Michiel
06:19
created

Tiqr_StateStorage_Pdo   A

Complexity

Total Complexity 17

Size/Duplication

Total Lines 104
Duplicated Lines 0 %

Test Coverage

Coverage 89.36%

Importance

Changes 4
Bugs 0 Features 0
Metric Value
wmc 17
eloc 41
c 4
b 0
f 0
dl 0
loc 104
ccs 42
cts 47
cp 0.8936
rs 10

6 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 9 3
A getValue() 0 17 4
A unsetValue() 0 5 2
A setValue() 0 15 4
A cleanExpired() 0 4 2
A keyExists() 0 7 2
1
<?php
2
3
use Psr\Log\LoggerInterface;
4
5
/**
6
 * This file is part of the tiqr project.
7
 * 
8
 * The tiqr project aims to provide an open implementation for 
9
 * authentication using mobile devices. It was initiated by 
10
 * SURFnet and developed by Egeniq.
11
 *
12
 * More information: http://www.tiqr.org
13
 *
14
 * @author Patrick Honing <[email protected]>
15
 * 
16
 * @package tiqr
17
 *
18
 * @license New BSD License - See LICENSE file for details.
19
 *
20
 * @copyright (C) 2010-2012 SURFnet BV
21
 * 
22
 * 
23
 * Create SQL table (MySQL):
24
 * CREATE TABLE `tiqrstate` (`key` varchar(255) PRIMARY KEY,`expire` int,`value` text);
25
 * 
26
 */
27
28
29
class Tiqr_StateStorage_Pdo extends Tiqr_StateStorage_Abstract
30
{
31
    /**
32
     * @var PDO
33
     */
34
    protected $handle;
35
36
    /**
37
     * @var string
38
     */
39
    private $tablename;
40
41
    /**
42
     * @var int
43
     */
44
    private $cleanupProbability;
45
46
    /**
47
     * @param PDO $pdoInstance The PDO instance where all state storage operations are performed on
48
     * @param LoggerInterface
49
     * @param string $tablename The tablename that is used for storing and retrieving the state storage
50
     * @param int $cleanupProbability The probability the expired state storage items are removed on a 'setValue' call. Example usage: 0 = never, 0.5 = 50% chance, 1 = always
51
     */
52 4
    public function __construct(PDO $pdoInstance, LoggerInterface $logger, string $tablename, float $cleanupProbability)
53
    {
54 4
        if ($cleanupProbability < 0 || $cleanupProbability > 1) {
55 2
            throw new RuntimeException('The probability for removing the expired state should be expressed in a floating point value between 0 and 1.');
56
        }
57 4
        $this->cleanupProbability = $cleanupProbability;
58 4
        $this->tablename = $tablename;
59 4
        $this->handle = $pdoInstance;
60 4
        $this->logger = $logger;
61 4
    }
62
63 2
    private function keyExists($key)
64
    {
65 2
        $sth = $this->handle->prepare("SELECT `key` FROM ".$this->tablename." WHERE `key` = ?");
66 2
        if ($sth->execute(array($key))) {
67 1
            return $sth->fetchColumn();
68
        }
69 1
        $this->logger->error('The state storage key could not be found in the database');
70 1
    }
71
72 2
    private function cleanExpired() {
73 2
        $sth = $this->handle->prepare("DELETE FROM ".$this->tablename." WHERE `expire` < ? AND NOT `expire` = 0");
74 2
        if (!$sth->execute(array(time()))){
75 1
            $this->logger->error('Unable to remove expired keys from the pdo state storage');
76
        }
77 2
    }
78
    
79
    /**
80
     * (non-PHPdoc)
81
     * @see library/tiqr/Tiqr/StateStorage/Tiqr_StateStorage_Abstract::setValue()
82
     */
83 2
    public function setValue($key, $value, $expire=0)
84
    {
85 2
        if (((float) rand() /(float) getrandmax()) < $this->cleanupProbability) {
86 2
            $this->cleanExpired();
87
        }
88 2
        if ($this->keyExists($key)) {
89 1
            $sth = $this->handle->prepare("UPDATE ".$this->tablename." SET `value` = ?, `expire` = ? WHERE `key` = ?");
90
        } else {
91 2
            $sth = $this->handle->prepare("INSERT INTO ".$this->tablename." (`value`,`expire`,`key`) VALUES (?,?,?)");
92
        }
93
        // $expire == 0 means never expire
94 2
        if ($expire != 0) {
95 2
            $expire+=time();    // Store unix timestamp after which the expires
96
        }
97 2
        $sth->execute(array(serialize($value),$expire,$key));
98 2
    }
99
        
100
    /**
101
     * (non-PHPdoc)
102
     * @see library/tiqr/Tiqr/StateStorage/Tiqr_StateStorage_Abstract::unsetValue()
103
     */
104 1
    public function unsetValue($key)
105
    {
106 1
        $sth = $this->handle->prepare("DELETE FROM ".$this->tablename." WHERE `key` = ?");
107 1
        if (!$sth->execute(array($key))) {
108
            $this->logger->error('Unable to unset key from the pdo state storage');
109
        }
110 1
    }
111
    
112
    /**
113
     * (non-PHPdoc)
114
     * @see library/tiqr/Tiqr/StateStorage/Tiqr_StateStorage_Abstract::getValue()
115
     */
116 1
    public function getValue($key)
117
    {
118 1
        if ($this->keyExists($key)) {
119 1
            $sth = $this->handle->prepare("SELECT `value` FROM ".$this->tablename." WHERE `key` = ? AND (`expire` >= ? OR `expire` = 0)");
120 1
            if (false === $sth) {
121
                $this->logger->error('Unable to prepare the get key statement');
122
                return NULL;
123
            }
124 1
            if (false === $sth->execute(array($key, time())) ) {
125
                $this->logger->error('Unable to get key from the pdo state storage');
126
                return NULL;
127
            }
128 1
            $result = $sth->fetchColumn();
129 1
            return  unserialize($result);
130
        }
131 1
        $this->logger->info('Unable to find key in the pdo state storage');
132 1
        return NULL;
133
    }
134
}
135