Completed
Pull Request — master (#2)
by Tharanga
02:11
created

PdoThirdPartyStorageRepository::getByAppUser()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 22
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 15
nc 4
nop 1
dl 0
loc 22
rs 9.7666
c 0
b 0
f 0
1
<?php
2
/**
3
 * @author Tharanga Kothalawala <[email protected]>
4
 * @date 30-12-2018
5
 */
6
7
namespace TSK\SSO\Storage;
8
9
use TSK\SSO\AppUser\AppUser;
10
use TSK\SSO\Storage\Exception\DataCannotBeStoredException;
11
use TSK\SSO\ThirdParty\CommonAccessToken;
12
use TSK\SSO\ThirdParty\ThirdPartyUser;
13
use PDOException;
14
use PDO;
15
16
/**
17
 * @codeCoverageIgnore
18
 * @package TSK\SSO\Storage
19
 *
20
 * This will connect to a MySQL database using the php-pdo driver to persist vendor data.
21
 */
22
class PdoThirdPartyStorageRepository implements ThirdPartyStorageRepository
23
{
24
    /**
25
     * @var PDO
26
     */
27
    private $dbConnection;
28
29
    /**
30
     * @var string
31
     */
32
    private $table;
33
34
    /**
35
     * @param PDO $dbConnection
36
     * @param string $table name of the table in the MySQL database
37
     */
38
    public function __construct(PDO $dbConnection, $table = 'thirdparty_connections')
39
    {
40
        $this->dbConnection = $dbConnection;
41
        $this->table = $table;
42
    }
43
44
    /**
45
     * Returns a mapped full user record for a given vendor email address or null.
46
     *
47
     * @param string $emailAddress email address used within the given vendor system
48
     * @param string|null $vendorName [optional] name of the third party vendor for vendor filtering
49
     * @return MappedUser|null
50
     */
51
    public function getUser($emailAddress, $vendorName = null)
52
    {
53
        if (is_null($vendorName)) {
54
            $sql = "SELECT * FROM `{$this->table}` WHERE `vendor_email` = :email LIMIT 1";
55
            $stmt = $this->dbConnection->prepare($sql);
56
        } else {
57
            $sql = "SELECT * FROM `{$this->table}` WHERE `vendor_email` = :email AND `vendor_name` = :vendor LIMIT 1";
58
            $stmt = $this->dbConnection->prepare($sql);
59
            $stmt->bindParam(':vendor', $vendorName, PDO::PARAM_STR);
60
        }
61
62
        $stmt->bindParam(':email', $emailAddress, PDO::PARAM_STR);
63
        $stmt->execute();
64
65
        $userMap = $stmt->fetch(PDO::FETCH_ASSOC);
66
        if (empty($userMap)) {
67
            return null;
68
        }
69
70
        return new MappedUser(
71
            $userMap['app_user_id'],
72
            $userMap['vendor_name'],
73
            $userMap['vendor_email'],
74
            $userMap['vendor_access_token'],
75
            $userMap['vendor_data']
76
        );
77
    }
78
79
    /**
80
     * Returns any vendor MappedUser list for a given Application user.
81
     *
82
     * @param AppUser $appUser
83
     * @return MappedUser[]
84
     */
85
    public function getByAppUser(AppUser $appUser)
86
    {
87
        $stmt = $this->dbConnection->prepare("SELECT * FROM `{$this->table}` WHERE `app_user_id` = :appUserId");
88
        if (is_numeric($appUser->id())) {
89
            $stmt->bindParam(':appUserId', $appUser->id(), PDO::PARAM_INT);
0 ignored issues
show
Bug introduced by
$appUser->id() cannot be passed to PDOStatement::bindParam() as the parameter $variable expects a reference. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

89
            $stmt->bindParam(':appUserId', /** @scrutinizer ignore-type */ $appUser->id(), PDO::PARAM_INT);
Loading history...
90
        } else {
91
            $stmt->bindParam(':appUserId', $appUser->id(), PDO::PARAM_STR);
92
        }
93
        $stmt->execute();
94
95
        $connections = array();
96
        while ($mappedUser = $stmt->fetch(PDO::FETCH_ASSOC)) {
97
            $connections[] = new MappedUser(
98
                $mappedUser['app_user_id'],
99
                $mappedUser['vendor_name'],
100
                $mappedUser['vendor_email'],
101
                $mappedUser['vendor_access_token'],
102
                $mappedUser['vendor_data']
103
            );
104
        }
105
106
        return $connections;
107
    }
108
109
    /**
110
     * @param AppUser $appUser
111
     * @param ThirdPartyUser $thirdPartyUser
112
     * @param CommonAccessToken $accessToken
113
     * @throws DataCannotBeStoredException
114
     */
115
    public function save(
116
        AppUser $appUser,
117
        ThirdPartyUser $thirdPartyUser,
118
        CommonAccessToken $accessToken
119
    ) {
120
        $sql = <<<SQL
121
INSERT INTO `{$this->table}`
122
(
123
    `app_user_id`,
124
    `vendor_name`,
125
    `vendor_email`,
126
    `vendor_access_token`,
127
    `vendor_data`,
128
    `created_at`
129
)
130
VALUES
131
(
132
    :appUserId,
133
    :vendorName,
134
    :vendorEmail,
135
    :vendorToken,
136
    :vendorData,
137
    NOW()
138
)
139
ON DUPLICATE KEY UPDATE
140
    `vendor_access_token` = VALUES(`vendor_access_token`),
141
    `vendor_data` = VALUES(`vendor_data`),
142
    `updated_at` = NOW()
143
SQL;
144
        try {
145
            $vendorData = json_encode($thirdPartyUser->toArray());
146
            $appUserId = $appUser->id();
147
            $vendorName = $accessToken->vendor();
148
            $vendorEmail = $thirdPartyUser->email();
149
            $vendorToken = $accessToken->token();
150
151
            $stmt = $this->dbConnection->prepare($sql);
152
            $stmt->bindParam(':appUserId', $appUserId, PDO::PARAM_STR);
153
            $stmt->bindParam(':vendorName', $vendorName, PDO::PARAM_STR);
154
            $stmt->bindParam(':vendorEmail', $vendorEmail, PDO::PARAM_STR);
155
            $stmt->bindParam(':vendorToken', $vendorToken, PDO::PARAM_STR);
156
            $stmt->bindParam(':vendorData', $vendorData, PDO::PARAM_STR);
157
            $stmt->execute();
158
        } catch (PDOException $ex) {
159
            throw new DataCannotBeStoredException(
160
                sprintf("Couldn't save the third party user data. Error : %s", $ex->getMessage()),
161
                $ex->getCode(),
162
                $ex
163
            );
164
        }
165
    }
166
167
    /**
168
     * Use this to clean the storage after revoking access to a third party for example.
169
     *
170
     * @param string $emailAddress email address used within the given vendor system
171
     * @param string $vendorName name of the third party where the given email belongs to
172
     * @return bool
173
     */
174
    public function remove($emailAddress, $vendorName)
175
    {
176
        $sql = "DELETE FROM `{$this->table}` WHERE `vendor_email` = :email AND `vendor_name` = :vendor LIMIT 1";
177
        $stmt = $this->dbConnection->prepare($sql);
178
        $stmt->bindParam(':email', $emailAddress, PDO::PARAM_STR);
179
        $stmt->bindParam(':vendor', $vendorName, PDO::PARAM_STR);
180
        return $stmt->execute();
181
    }
182
}
183