Passed
Pull Request — master (#2)
by Tharanga
02:26
created

MysqliThirdPartyStorageRepository::getByAppUser()   B

Complexity

Conditions 6
Paths 4

Size

Total Lines 37
Code Lines 24

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 6
eloc 24
nc 4
nop 1
dl 0
loc 37
rs 8.9137
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 mysqli;
14
15
/**
16
 * @codeCoverageIgnore
17
 * @package TSK\SSO\Storage
18
 *
19
 * This will connect to a MySQL database using the php-mysql driver to persist vendor data.
20
 */
21
class MysqliThirdPartyStorageRepository implements ThirdPartyStorageRepository
22
{
23
    /**
24
     * @var mysqli
25
     */
26
    private $dbConnection;
27
28
    /**
29
     * @var string
30
     */
31
    private $table;
32
33
    /**
34
     * @param mysqli $dbConnection
35
     * @param string $table name of the table in the MySQL database
36
     */
37
    public function __construct(mysqli $dbConnection, $table = 'thirdparty_connections')
38
    {
39
        $this->dbConnection = $dbConnection;
40
        $this->table = $table;
41
    }
42
43
    /**
44
     * Returns a mapped full user record for a given vendor email address or null.
45
     *
46
     * @param string $emailAddress email address used within the given vendor system
47
     * @param string|null $vendorName [optional] name of the third party vendor for vendor filtering
48
     * @return MappedUser|null
49
     */
50
    public function getUser($emailAddress, $vendorName = null)
51
    {
52
        if (is_null($vendorName)) {
53
            $stmt = $this->dbConnection->prepare(<<<SQL
54
                SELECT
55
                    `app_user_id`, `vendor_name`, `vendor_email`, `vendor_access_token`, `vendor_data`
56
                FROM `{$this->table}`
57
                WHERE
58
                    `vendor_email` = ?
59
                LIMIT 1
60
SQL
61
            );
62
            $stmt->bind_param('s', $emailAddress);
63
        } else {
64
            $stmt = $this->dbConnection->prepare(<<<SQL
65
                SELECT
66
                    `app_user_id`, `vendor_name`, `vendor_email`, `vendor_access_token`, `vendor_data`
67
                FROM `{$this->table}`
68
                WHERE
69
                    `vendor_email` = ?
70
                    AND `vendor_name` = ?
71
                LIMIT 1
72
SQL
73
            );
74
            $stmt->bind_param('ss', $emailAddress, $vendorName);
75
        }
76
77
        $stmt->execute();
78
        $stmt->bind_result($appUserId, $vendor, $vendorEmail, $vendorToken, $vendorData);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $vendorData does not exist. Did you maybe mean $vendorName?
Loading history...
Comprehensibility Best Practice introduced by
The variable $vendorToken seems to be never defined.
Loading history...
Comprehensibility Best Practice introduced by
The variable $vendorEmail does not exist. Did you maybe mean $vendorName?
Loading history...
79
        $stmt->fetch();
80
        $stmt->close();
81
        if (empty($appUserId)) {
82
            return null;
83
        }
84
85
        return new MappedUser($appUserId, $vendor, $vendorEmail, $vendorToken, $vendorData);
86
    }
87
88
    /**
89
     * Returns any vendor MappedUser list for a given Application user.
90
     *
91
     * @param AppUser $appUser
92
     * @return MappedUser[]
93
     */
94
    public function getByAppUser(AppUser $appUser)
95
    {
96
        $stmt = $this->dbConnection->prepare(<<<SQL
97
                SELECT
98
                    `app_user_id`, `vendor_name`, `vendor_email`, `vendor_access_token`, `vendor_data`
99
                FROM `{$this->table}`
100
                WHERE
101
                    `app_user_id` = ?
102
SQL
103
        );
104
        $appUserId = $appUser->id();
105
        if (is_numeric($appUserId)) {
106
            $stmt->bind_param('i', $appUserId);
107
        } else {
108
            $stmt->bind_param('s', $appUserId);
109
        }
110
111
        $connections = array();
112
        if ($stmt->execute() &&
113
            $stmt->store_result() &&
114
            $stmt->bind_result($appUserId, $vendor, $vendorEmail, $vendorToken, $vendorData)
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $vendorData seems to be never defined.
Loading history...
Comprehensibility Best Practice introduced by
The variable $vendorToken seems to be never defined.
Loading history...
Comprehensibility Best Practice introduced by
The variable $vendorEmail seems to be never defined.
Loading history...
115
        ) {
116
            while ($stmt->fetch()) {
117
                $connections[] = new MappedUser(
118
                    $appUserId,
119
                    $vendor,
120
                    $vendorEmail,
121
                    $vendorToken,
122
                    $vendorData
123
                );
124
            }
125
126
            $stmt->fetch();
127
            $stmt->close();
128
        }
129
130
        return $connections;
131
    }
132
133
    /**
134
     * @param AppUser $appUser
135
     * @param ThirdPartyUser $thirdPartyUser
136
     * @param CommonAccessToken $accessToken
137
     * @throws DataCannotBeStoredException
138
     */
139
    public function save(
140
        AppUser $appUser,
141
        ThirdPartyUser $thirdPartyUser,
142
        CommonAccessToken $accessToken
143
    ) {
144
        $sql = <<<SQL
145
INSERT INTO `{$this->table}`
146
(
147
    `app_user_id`,
148
    `vendor_name`,
149
    `vendor_email`,
150
    `vendor_access_token`,
151
    `vendor_data`,
152
    `created_at`
153
)
154
VALUES
155
(
156
    ?, ?, ?, ?, ?, NOW()
157
)
158
ON DUPLICATE KEY UPDATE
159
    `vendor_access_token` = VALUES(`vendor_access_token`),
160
    `vendor_data` = VALUES(`vendor_data`),
161
    `updated_at` = NOW()
162
SQL;
163
164
        $vendorData = json_encode($thirdPartyUser->toArray());
165
        $appUserId = $appUser->id();
166
        $vendorName = $accessToken->vendor();
167
        $vendorEmail = $thirdPartyUser->email();
168
        $vendorToken = $accessToken->token();
169
170
        $stmt = $this->dbConnection->prepare($sql);
171
        $stmt->bind_param('sssss', $appUserId, $vendorName, $vendorEmail, $vendorToken, $vendorData);
172
        $saved = $stmt->execute();
173
        if (!$saved) {
174
            throw new DataCannotBeStoredException(
175
                sprintf("Couldn't save the third party user data. Error : %s", $this->dbConnection->error)
176
            );
177
        }
178
    }
179
180
    /**
181
     * Use this to clean the storage after revoking access to a third party for example.
182
     *
183
     * @param string $emailAddress email address used within the given vendor system
184
     * @param string $vendorName name of the third party where the given email belongs to
185
     * @return bool
186
     */
187
    public function remove($emailAddress, $vendorName)
188
    {
189
        $sql = "DELETE FROM `{$this->table}` WHERE `vendor_email` = ? AND `vendor_name` = ? LIMIT 1";
190
        $stmt = $this->dbConnection->prepare($sql);
191
        $stmt->bind_param("ss", $emailAddress, $vendorName);
192
        $stmt->execute();
193
    }
194
}
195