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

Tiqr_UserStorage_Pdo   A

Complexity

Total Complexity 41

Size/Duplication

Total Lines 185
Duplicated Lines 0 %

Test Coverage

Coverage 71.84%

Importance

Changes 6
Bugs 0 Features 0
Metric Value
wmc 41
eloc 81
c 6
b 0
f 0
dl 0
loc 185
ccs 74
cts 103
cp 0.7184
rs 9.1199

16 Methods

Rating   Name   Duplication   Size   Complexity  
A createUser() 0 11 3
A isBlocked() 0 14 6
A getNotificationAddress() 0 7 2
A getTemporaryBlockAttempts() 0 9 3
A setLoginAttempts() 0 5 2
A getNotificationType() 0 7 2
A setTemporaryBlockTimestamp() 0 5 2
A getTemporaryBlockTimestamp() 0 13 3
A setBlocked() 0 6 3
A setNotificationType() 0 5 2
A getDisplayName() 0 7 2
A userExists() 0 8 2
A __construct() 0 9 3
A getLoginAttempts() 0 7 2
A setNotificationAddress() 0 5 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
        $this->logger->error('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->error('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->error('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->error('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
            $this->logger->error('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->error('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
            $this->logger->error('Unable to set the notification address in user storage for a given user (PDO)');
128
        }
129
    }
130
    
131 2
    public function getLoginAttempts($userId)
132
    {
133 2
        $sth = $this->handle->prepare("SELECT loginattempts FROM ".$this->tablename." WHERE userid = ?");
134 2
        if ($sth->execute(array($userId))) {
135 2
            return $sth->fetchColumn();
136
        }
137
        $this->logger->error('Unable to retrieve login attempts from user storage (PDO)');
138
    }
139
    
140 2
    public function setLoginAttempts($userId, $amount)
141
    {
142 2
        $sth = $this->handle->prepare("UPDATE ".$this->tablename." SET loginattempts = ? WHERE userid = ?");
143 2
        if (!$sth->execute(array($amount,$userId))) {
144
            $this->logger->error('Unable to set login attempts in user storage for a given user (PDO)');
145
        }
146 2
    }
147
    
148 2
    public function isBlocked($userId, $duration)
149
    {
150 2
        if ($this->userExists($userId)) {
151 2
            $sth = $this->handle->prepare("SELECT blocked FROM ".$this->tablename." WHERE userid = ?");
152 2
            $sth->execute(array($userId));
153 2
            $blocked = ($sth->fetchColumn() == 1);
154 2
            $timestamp = $this->getTemporaryBlockTimestamp($userId);
155
            // if not blocked or block is expired, return false
156 2
            if (!$blocked || (false !== $timestamp && false != $duration && (strtotime($timestamp) + $duration * 60) < time())) {
157 2
                return false;
158
            }
159 2
            return true;
160
        } else {
161
            return false;
162
        }
163
    }
164
    
165 2
    public function setBlocked($userId, $blocked)
166
    {
167 2
        $sth = $this->handle->prepare("UPDATE ".$this->tablename." SET blocked = ? WHERE userid = ?");
168 2
        $isBlocked = ($blocked) ? "1" : "0";
169 2
        if (!$sth->execute([$isBlocked, $userId])) {
170
            $this->logger->error('Unable to block the user in the user storage (PDO)');
171
        }
172 2
    }
173
    
174 2
    public function setTemporaryBlockAttempts($userId, $amount) {
175 2
        $sth = $this->handle->prepare("UPDATE ".$this->tablename." SET tmpblockattempts = ? WHERE userid = ?");
176 2
        if (!$sth->execute(array($amount,$userId))) {
177
            $this->logger->error('Unable to set temp login attempts in user storage for a given user (PDO)');
178
        }
179 2
    }
180
181
    /**
182
     * @param $userId
183
     * @return int
184
     * @throws RuntimeException when the query fails, a runtime exception is raised. As continuing execution from that
185
     *                          point would either throw an error, or return 0
186
     */
187 2
    public function getTemporaryBlockAttempts($userId) {
188 2
        if ($this->userExists($userId)) {
189 2
            $sth = $this->handle->prepare("SELECT tmpblockattempts FROM ".$this->tablename." WHERE userid = ?");
190 2
            if (!$sth->execute(array($userId))) {
191
                throw new RuntimeException('Unable to get temp login attempts in user storage for a given user (PDO)');
192
            }
193 2
            return (int) $sth->fetchColumn();
194
        }
195
        return 0;
196
    }
197
    
198 2
    public function setTemporaryBlockTimestamp($userId, $timestamp)
199
    {
200 2
        $sth = $this->handle->prepare("UPDATE ".$this->tablename." SET tmpblocktimestamp = ? WHERE userid = ?");
201 2
        if (!$sth->execute(array($timestamp,$userId))) {
202
            $this->logger->error('Unable to update temp lock timestamp in user storage for a given user (PDO)');
203
        }
204 2
    }
205
            
206 2
    public function getTemporaryBlockTimestamp($userId)
207
    {
208 2
        if ($this->userExists($userId)) {
209 2
            $sth = $this->handle->prepare("SELECT tmpblocktimestamp FROM ".$this->tablename." WHERE userid = ?");
210 2
            $sth->execute(array($userId));
211 2
            $timestamp = $sth->fetchColumn(); 
212 2
            if (null !== $timestamp) {
213 2
                return $timestamp;
214
            } else {
215 2
                $this->logger->info('No temp lock timestamp found in user storage for a given user (PDO)');
216
            }
217
        }
218 2
        return false;
219
    }
220
    
221
}
222