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

MysqliThirdPartyStorageRepository::getByAppUser()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 21
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 12
nc 2
nop 1
dl 0
loc 21
rs 9.8666
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
        if (is_numeric($appUser->id())) {
105
            $stmt->bind_param('i', $appUser->id());
0 ignored issues
show
Bug introduced by
$appUser->id() cannot be passed to mysqli_stmt::bind_param() as the parameter $var1 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

105
            $stmt->bind_param('i', /** @scrutinizer ignore-type */ $appUser->id());
Loading history...
106
        } else {
107
            $stmt->bind_param('s', $appUser->id());
108
        }
109
110
        $stmt->execute();
111
        // TODO: loop through and return
112
//        $stmt->bind_result($appUserId, $vendor, $vendorEmail, $vendorToken, $vendorData);
113
        $stmt->fetch();
114
        $stmt->close();
115
    }
116
117
    /**
118
     * @param AppUser $appUser
119
     * @param ThirdPartyUser $thirdPartyUser
120
     * @param CommonAccessToken $accessToken
121
     * @throws DataCannotBeStoredException
122
     */
123
    public function save(
124
        AppUser $appUser,
125
        ThirdPartyUser $thirdPartyUser,
126
        CommonAccessToken $accessToken
127
    ) {
128
        $sql = <<<SQL
129
INSERT INTO `{$this->table}`
130
(
131
    `app_user_id`,
132
    `vendor_name`,
133
    `vendor_email`,
134
    `vendor_access_token`,
135
    `vendor_data`,
136
    `created_at`
137
)
138
VALUES
139
(
140
    ?, ?, ?, ?, ?, NOW()
141
)
142
ON DUPLICATE KEY UPDATE
143
    `vendor_access_token` = VALUES(`vendor_access_token`),
144
    `vendor_data` = VALUES(`vendor_data`),
145
    `updated_at` = NOW()
146
SQL;
147
148
        $vendorData = json_encode($thirdPartyUser->toArray());
149
        $appUserId = $appUser->id();
150
        $vendorName = $accessToken->vendor();
151
        $vendorEmail = $thirdPartyUser->email();
152
        $vendorToken = $accessToken->token();
153
154
        $stmt = $this->dbConnection->prepare($sql);
155
        $stmt->bind_param('sssss', $appUserId, $vendorName, $vendorEmail, $vendorToken, $vendorData);
156
        $saved = $stmt->execute();
157
        if (!$saved) {
158
            throw new DataCannotBeStoredException(
159
                sprintf("Couldn't save the third party user data. Error : %s", $this->dbConnection->error)
160
            );
161
        }
162
    }
163
164
    /**
165
     * Use this to clean the storage after revoking access to a third party for example.
166
     *
167
     * @param string $emailAddress email address used within the given vendor system
168
     * @param string $vendorName name of the third party where the given email belongs to
169
     * @return bool
170
     */
171
    public function remove($emailAddress, $vendorName)
172
    {
173
        $sql = "DELETE FROM `{$this->table}` WHERE `vendor_email` = ? AND `vendor_name` = ? LIMIT 1";
174
        $stmt = $this->dbConnection->prepare($sql);
175
        $stmt->bind_param("ss", $emailAddress, $vendorName);
176
        $stmt->execute();
177
    }
178
}
179