Passed
Pull Request — develop (#37)
by Pieter van der
03:21
created

Tiqr_UserStorage_Pdo   A

Complexity

Total Complexity 41

Size/Duplication

Total Lines 186
Duplicated Lines 0 %

Test Coverage

Coverage 72.55%

Importance

Changes 8
Bugs 0 Features 0
Metric Value
wmc 41
eloc 81
c 8
b 0
f 0
dl 0
loc 186
ccs 74
cts 102
cp 0.7255
rs 9.1199

16 Methods

Rating   Name   Duplication   Size   Complexity  
A createUser() 0 11 3
A getNotificationAddress() 0 7 2
A getNotificationType() 0 7 2
A setNotificationType() 0 5 2
A getDisplayName() 0 7 2
A userExists() 0 8 2
A __construct() 0 9 3
A setNotificationAddress() 0 5 2
A getTemporaryBlockAttempts() 0 9 3
A setLoginAttempts() 0 5 2
A isBlocked() 0 14 6
A setTemporaryBlockTimestamp() 0 5 2
A getTemporaryBlockTimestamp() 0 13 3
A setBlocked() 0 6 3
A getLoginAttempts() 0 7 2
A setTemporaryBlockAttempts() 0 4 2

How to fix   Complexity   

Complex Class

Complex classes like Tiqr_UserStorage_Pdo often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Tiqr_UserStorage_Pdo, and based on these observations, apply Extract Interface, too.

1
<?php
2
/**
3
 * This file is part of the tiqr project.
4
 * 
5
 * The tiqr project aims to provide an open implementation for 
6
 * authentication using mobile devices. It was initiated by 
7
 * SURFnet and developed by Egeniq.
8
 *
9
 * More information: http://www.tiqr.org
10
 *
11
 * @author Patrick Honing <[email protected]>
12
 * 
13
 * @package tiqr
14
 *
15
 * @license New BSD License - See LICENSE file for details.
16
 *
17
 * @copyright (C) 2010-2012 SURFnet BV
18
 * 
19
 * Create SQL table (MySQL):
20
 * CREATE TABLE `tiqruser` (`userid` varchar(10) PRIMARY KEY, `displayname` varchar(45),`blocked` int,`loginattempts` int,
21
 * `tmpblockattempts` int,`tmpblocktimestamp` varchar(45) default NULL,`notificationtype` varchar(10),`notificationaddress` varchar(45))
22
 * 
23
 */
24
25
use Psr\Log\LoggerInterface;
26
27
28
/**
29
 * This user storage implementation implements a user storage using PDO.
30
 * It is usable for any database with a PDO driver
31
 * 
32
 * @author Patrick Honing <[email protected]>
33
 */
34
class Tiqr_UserStorage_Pdo extends Tiqr_UserStorage_Abstract
35
{
36
    protected $handle = null;
37
    protected $tablename;
38
    
39
    /**
40
     * Create an instance
41
     * @param array $config
42
     * @param array $secretconfig
43
     */
44 2
    public function __construct($config, LoggerInterface $logger)
45
    {
46 2
        parent::__construct($config, $logger);
47 2
        $this->tablename = isset($config['table']) ? $config['table'] : 'tiqruser';
48
        try {
49 2
            $this->handle = new PDO($config['dsn'],$config['username'],$config['password']);
50
        } catch (PDOException $e) {
51
            $this->logger->error(
52
                sprintf('Unable to establish a PDO connection. Error message from PDO: %s', $e->getMessage())
53
            );
54
        }
55 2
    }
56
57 2
    public function createUser($userId, $displayName)
58
    {
59 2
        if ($this->userExists($userId)) {
60
            $sth = $this->handle->prepare("UPDATE ".$this->tablename." SET displayname = ? WHERE userid = ?");
61
        } else {
62 2
            $sth = $this->handle->prepare("INSERT INTO ".$this->tablename." (displayname,userid) VALUES (?,?)");
63
        }
64 2
        if ($sth->execute(array($displayName,$userId))){
65 2
            return $this->userExists($userId);
66
        }
67
        throw new ReadWriteException('The user could not be saved in the user storage (PDO)');
68
    }
69
70
    /**
71
     * Be carefull! This method does not return an expected boolean value. Instead it returns:
72
     * - void (if user was not found)
73
     * - userid (if user was found)
74
     *
75
     * @param $userId
76
     * @return mixed
77
     */
78 2
    public function userExists($userId)
79
    {
80 2
        $sth = $this->handle->prepare("SELECT userid FROM ".$this->tablename." WHERE userid = ?");
81 2
        if ($sth->execute(array($userId))) {
82
            // TODO: this method should return a boolean value on all possible outcomes or throw an exception
83 2
            return $sth->fetchColumn();
84
        }
85
        $this->logger->notice('Unable to find user in user storage (PDO)');
86
    }
87
    
88 2
    public function getDisplayName($userId)
89
    {
90 2
        $sth = $this->handle->prepare("SELECT displayname FROM ".$this->tablename." WHERE userid = ?");
91 2
        if ($sth->execute(array($userId))) {
92 2
            return $sth->fetchColumn();
93
        }
94
        $this->logger->notice('Retrieving the users display name failed in the user storage (PDO)');
95
    }
96
97 2
    public function getNotificationType($userId)
98
    {
99 2
        $sth = $this->handle->prepare("SELECT notificationtype FROM ".$this->tablename." WHERE userid = ?");
100 2
        if ($sth->execute(array($userId))) {
101 2
            return $sth->fetchColumn();
102
        }
103
        $this->logger->notice('Unable to retrieve notification type from user storage (PDO)');
104
    }
105
    
106 2
    public function setNotificationType($userId, $type)
107
    {
108 2
        $sth = $this->handle->prepare("UPDATE ".$this->tablename." SET notificationtype = ? WHERE userid = ?");
109 2
        if (!$sth->execute(array($type,$userId))) {
110
            throw new ReadWriteException('Unable to set the notification type in user storage for a given user (PDO)');
111
        }
112 2
    }
113
    
114 2
    public function getNotificationAddress($userId)
115
    {
116 2
        $sth = $this->handle->prepare("SELECT notificationaddress FROM ".$this->tablename." WHERE userid = ?");
117 2
        if ($sth->execute(array($userId))) {
118 2
            return $sth->fetchColumn();
119
        }
120
        $this->logger->notice('Unable to retrieve notification address from user storage (PDO)');
121
    }
122
    
123
    public function setNotificationAddress($userId, $address)
124
    {
125
        $sth = $this->handle->prepare("UPDATE ".$this->tablename." SET notificationaddress = ?  WHERE userid = ?");
126
        if (!$sth->execute(array($address,$userId))) {
127
            throw new ReadWriteException('Unable to set the notification address in user storage for a given user (PDO)');
128
129
        }
130
    }
131
    
132 2
    public function getLoginAttempts($userId)
133
    {
134 2
        $sth = $this->handle->prepare("SELECT loginattempts FROM ".$this->tablename." WHERE userid = ?");
135 2
        if ($sth->execute(array($userId))) {
136 2
            return $sth->fetchColumn();
137
        }
138
        $this->logger->notice('Unable to retrieve login attempts from user storage (PDO)');
139
    }
140
    
141 2
    public function setLoginAttempts($userId, $amount)
142
    {
143 2
        $sth = $this->handle->prepare("UPDATE ".$this->tablename." SET loginattempts = ? WHERE userid = ?");
144 2
        if (!$sth->execute(array($amount,$userId))) {
145
            throw new ReadWriteException('Unable to set login attempts in user storage for a given user (PDO)');
146
        }
147 2
    }
148
    
149 2
    public function isBlocked($userId, $duration)
150
    {
151 2
        if ($this->userExists($userId)) {
152 2
            $sth = $this->handle->prepare("SELECT blocked FROM ".$this->tablename." WHERE userid = ?");
153 2
            $sth->execute(array($userId));
154 2
            $blocked = ($sth->fetchColumn() == 1);
155 2
            $timestamp = $this->getTemporaryBlockTimestamp($userId);
156
            // if not blocked or block is expired, return false
157 2
            if (!$blocked || (false !== $timestamp && false != $duration && (strtotime($timestamp) + $duration * 60) < time())) {
158 2
                return false;
159
            }
160 2
            return true;
161
        } else {
162
            return false;
163
        }
164
    }
165
    
166 2
    public function setBlocked($userId, $blocked)
167
    {
168 2
        $sth = $this->handle->prepare("UPDATE ".$this->tablename." SET blocked = ? WHERE userid = ?");
169 2
        $isBlocked = ($blocked) ? "1" : "0";
170 2
        if (!$sth->execute([$isBlocked, $userId])) {
171
            throw new ReadWriteException('Unable to block the user in the user storage (PDO)');
172
        }
173 2
    }
174
    
175 2
    public function setTemporaryBlockAttempts($userId, $amount) {
176 2
        $sth = $this->handle->prepare("UPDATE ".$this->tablename." SET tmpblockattempts = ? WHERE userid = ?");
177 2
        if (!$sth->execute(array($amount,$userId))) {
178
            throw new ReadWriteException('Unable to set temp login attempts in user storage for a given user (PDO)');
179
        }
180 2
    }
181
182
    /**
183
     * @param $userId
184
     * @return int
185
     * @throws RuntimeException when the query fails, a runtime exception is raised. As continuing execution from that
186
     *                          point would either throw an error, or return 0
187
     */
188 2
    public function getTemporaryBlockAttempts($userId) {
189 2
        if ($this->userExists($userId)) {
190 2
            $sth = $this->handle->prepare("SELECT tmpblockattempts FROM ".$this->tablename." WHERE userid = ?");
191 2
            if (!$sth->execute(array($userId))) {
192
                throw new RuntimeException('Unable to get temp login attempts in user storage for a given user (PDO)');
193
            }
194 2
            return (int) $sth->fetchColumn();
195
        }
196
        return 0;
197
    }
198
    
199 2
    public function setTemporaryBlockTimestamp($userId, $timestamp)
200
    {
201 2
        $sth = $this->handle->prepare("UPDATE ".$this->tablename." SET tmpblocktimestamp = ? WHERE userid = ?");
202 2
        if (!$sth->execute(array($timestamp,$userId))) {
203
            throw new ReadWriteException('Unable to update temp lock timestamp in user storage for a given user (PDO)');
204
        }
205 2
    }
206
            
207 2
    public function getTemporaryBlockTimestamp($userId)
208
    {
209 2
        if ($this->userExists($userId)) {
210 2
            $sth = $this->handle->prepare("SELECT tmpblocktimestamp FROM ".$this->tablename." WHERE userid = ?");
211 2
            $sth->execute(array($userId));
212 2
            $timestamp = $sth->fetchColumn(); 
213 2
            if (null !== $timestamp) {
214 2
                return $timestamp;
215
            } else {
216 2
                $this->logger->notice('No temp lock timestamp found in user storage for a given user (PDO)');
217
            }
218
        }
219 2
        return false;
220
    }
221
}
222