Completed
Push — master ( df062e...3563b3 )
by Tharanga
02:22
created

MysqliThirdPartyStorageRepository::getByAppUser()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 32
Code Lines 21

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 21
nc 2
nop 1
dl 0
loc 32
rs 9.584
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
        $stmt->bind_param(is_numeric($appUserId) ? 'i' : 's', $appUserId);
106
        $stmt->execute();
107
108
        $stmt->store_result();
109
        $vendor = $vendorEmail = $vendorToken = $vendorData = null;
110
        $stmt->bind_result($appUserId, $vendor, $vendorEmail, $vendorToken, $vendorData);
111
112
        $connections = array();
113
        while ($stmt->fetch()) {
114
            $connections[] = new MappedUser(
115
                $appUserId,
116
                $vendor,
117
                $vendorEmail,
118
                $vendorToken,
119
                $vendorData
120
            );
121
        }
122
123
        $stmt->close();
124
125
        return $connections;
126
    }
127
128
    /**
129
     * @param AppUser $appUser
130
     * @param ThirdPartyUser $thirdPartyUser
131
     * @param CommonAccessToken $accessToken
132
     * @throws DataCannotBeStoredException
133
     */
134
    public function save(
135
        AppUser $appUser,
136
        ThirdPartyUser $thirdPartyUser,
137
        CommonAccessToken $accessToken
138
    ) {
139
        $sql = <<<SQL
140
            INSERT INTO `{$this->table}`
141
            (
142
                `app_user_id`,
143
                `vendor_name`,
144
                `vendor_email`,
145
                `vendor_access_token`,
146
                `vendor_data`,
147
                `created_at`
148
            )
149
            VALUES
150
            (
151
                ?, ?, ?, ?, ?, NOW()
152
            )
153
            ON DUPLICATE KEY UPDATE
154
                `vendor_access_token` = VALUES(`vendor_access_token`),
155
                `vendor_data` = VALUES(`vendor_data`),
156
                `updated_at` = NOW()
157
SQL;
158
159
        $vendorData = json_encode($thirdPartyUser->toArray());
160
        $appUserId = $appUser->id();
161
        $vendorName = $accessToken->vendor();
162
        $vendorEmail = $thirdPartyUser->email();
163
        $vendorToken = $accessToken->token();
164
165
        $stmt = $this->dbConnection->prepare($sql);
166
        $stmt->bind_param('sssss', $appUserId, $vendorName, $vendorEmail, $vendorToken, $vendorData);
167
        $saved = $stmt->execute();
168
        if (!$saved) {
169
            throw new DataCannotBeStoredException(
170
                sprintf("Couldn't save the third party user data. Error : %s", $this->dbConnection->error)
171
            );
172
        }
173
    }
174
175
    /**
176
     * Use this to clean the storage after revoking access to a third party for example.
177
     *
178
     * @param string $emailAddress email address used within the given vendor system
179
     * @param string $vendorName name of the third party where the given email belongs to
180
     * @return bool
181
     */
182
    public function remove($emailAddress, $vendorName)
183
    {
184
        $sql = "DELETE FROM `{$this->table}` WHERE `vendor_email` = ? AND `vendor_name` = ? LIMIT 1";
185
        $stmt = $this->dbConnection->prepare($sql);
186
        $stmt->bind_param("ss", $emailAddress, $vendorName);
187
        return $stmt->execute();
188
    }
189
}
190