Passed
Pull Request — develop (#24)
by Stephen
02:42
created

Client::parseDataConfigs()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 9
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 7
c 1
b 0
f 0
nc 1
nop 0
dl 0
loc 9
rs 10
ccs 7
cts 7
cp 1
crap 1
1
<?php
2
3
namespace Spinen\QuickBooks;
4
5
use Exception;
6
use QuickBooksOnline\API\DataService\DataService;
7
use QuickBooksOnline\API\Exception\SdkException;
8
use QuickBooksOnline\API\Exception\ServiceException;
9
use QuickBooksOnline\API\ReportService\ReportService;
10
11
/**
12
 * Class Client
13
 *
14
 * @package Spinen\QuickBooks
15
 */
16
class Client
17
{
18
    /**
19
     * The configs to set up a DataService
20
     *
21
     * @var array
22
     */
23
    protected $configs;
24
25
    /**
26
     * The DataService instance
27
     *
28
     * @var DataService
29
     */
30
    protected $data_service;
31
32
    /**
33
     * The ReportService instance
34
     *
35
     * @var ReportService
36
     */
37
    protected $report_service;
38
39
    /**
40
     * The Token instance
41
     *
42
     * @var Token
43
     */
44
    protected $token;
45
46
    /**
47
     * Client constructor.
48
     *
49
     * @param array $configs
50
     * @param Token $token
51
     */
52 6
    public function __construct(array $configs, Token $token)
53
    {
54 6
        $this->configs = $configs;
55
56 6
        $this->setToken($token);
57 6
    }
58
59
    /**
60
     * Build URI to request authorization
61
     *
62
     * @return String
63
     * @throws SdkException
64
     * @throws ServiceException
65
     */
66
    public function authorizationUri()
67
    {
68
        return $this->getDataService()
69
                    ->getOAuth2LoginHelper()
70
                    ->getAuthorizationCodeURL();
71
    }
72
73
    /**
74
     * Configure the logging per config/quickbooks.php
75
     *
76
     * @return DataService
77
     */
78 3
    public function configureLogging()
79
    {
80
        // In case any of the keys are not in the configs, just disable logging
81
        try {
82 3
            if ($this->configs['logging']['enabled'] && dir($this->configs['logging']['location'])) {
83
                $this->data_service->setLogLocation($this->configs['logging']['location']);
84
85
                return $this->data_service->enableLog();
86
            }
87 3
        } catch (Exception $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
88
        }
89
90 3
        return $this->data_service->disableLog();
91
    }
92
93
    /**
94
     * Delete the token
95
     *
96
     * @return $this
97
     * @throws Exception
98
     */
99 1
    public function deleteToken()
100
    {
101 1
        $this->setToken($this->token->remove());
102
103 1
        return $this;
104
    }
105
106
    /**
107
     * Convert code to an access token
108
     *
109
     * Upon the user allowing access to their account, there is a code sent to
110
     * over that needs to be converted to an OAuth token.
111
     *
112
     * @param string $code
113
     * @param integer $realm_id
114
     *
115
     * @return $this
116
     * @throws SdkException
117
     * @throws ServiceException
118
     */
119
    public function exchangeCodeForToken($code, $realm_id)
120
    {
121
        $oauth_token = $this->getDataService()
122
                            ->getOAuth2LoginHelper()
123
                            ->exchangeAuthorizationCodeForToken($code, $realm_id);
124
125
        $this->getDataService()
126
             ->updateOAuth2Token($oauth_token);
127
128
        $this->token->parseOauthToken($oauth_token)
129
                    ->save();
130
131
        return $this;
132
    }
133
134
    /**
135
     * Getter for the DataService
136
     *
137
     * Makes sure that it is setup & ready to be used.
138
     *
139
     * @return DataService
140
     * @throws SdkException
141
     * @throws ServiceException
142
     */
143 4
    public function getDataService()
144
    {
145 4
        if (!$this->hasValidAccessToken() || !isset($this->data_service)) {
146 4
            $this->data_service = $this->makeDataService();
147
148 3
            $this->configureLogging();
149
        }
150
151 3
        return $this->data_service;
152
    }
153
154
    /**
155
     * Getter for the ReportService
156
     *
157
     * Makes sure that it is setup & ready to be used.
158
     *
159
     * @return ReportService
160
     * @throws SdkException
161
     * @throws ServiceException
162
     */
163
    public function getReportService()
164
    {
165
        if (!$this->hasValidAccessToken() || !isset($this->report_service)) {
166
            $this->report_service = new ReportService(
167
                $this->getDataService()
168
                     ->getServiceContext()
169
            );
170
        }
171
172
        return $this->report_service;
173
    }
174
175
    /**
176
     * Check to see if the token has a valid access token
177
     *
178
     * @return boolean
179
     */
180 4
    public function hasValidAccessToken()
181
    {
182 4
        return $this->token->hasValidAccessToken;
183
    }
184
185
    /**
186
     * Check to see if the token has a valid refresh token
187
     *
188
     * @return boolean
189
     */
190 3
    public function hasValidRefreshToken()
191
    {
192 3
        return $this->token->hasValidRefreshToken;
193
    }
194
195
    /**
196
     * Factory to make DataService
197
     *
198
     * There are 3 use cases for making a DataService....
199
     *
200
     *      1) Have valid access token, so ready to be used
201
     *      2) Have valid refresh token, so renew access token & then use
202
     *      3) No existing token, so need to link account
203
     *
204
     * @return DataService
205
     * @throws SdkException
206
     * @throws ServiceException
207
     */
208 4
    protected function makeDataService()
209
    {
210
        // Associative array to use to filter out only the needed config keys when using existing token
211
        $existing_keys = [
212 4
            'auth_mode'    => null,
213
            'baseUrl'      => null,
214
            'ClientID'     => null,
215
            'ClientSecret' => null,
216
        ];
217
218
        // Have good access & refresh, so allow app to run
219 4
        if ($this->hasValidAccessToken()) {
220
            // Pull in the configs from the token into needed keys from the configs
221 1
            return DataService::Configure(
222 1
                array_merge(
223 1
                    array_intersect_key($this->parseDataConfigs(), $existing_keys),
224
                    [
225 1
                        'accessTokenKey'  => $this->token->access_token,
226 1
                        'QBORealmID'      => $this->token->realm_id,
227 1
                        'refreshTokenKey' => $this->token->refresh_token,
228
                    ]
229
                )
230
            );
231
        }
232
233
        // Have refresh, so update access & allow app to run
234 3
        if ($this->hasValidRefreshToken()) {
235
            // Pull in the configs from the token into needed keys from the configs
236 1
            $data_service = DataService::Configure(
237 1
                array_merge(
238 1
                    array_intersect_key($this->parseDataConfigs(), $existing_keys),
239
                    [
240 1
                        'QBORealmID'      => $this->token->realm_id,
241 1
                        'refreshTokenKey' => $this->token->refresh_token,
242
                    ]
243
                )
244
            );
245
246 1
            $oauth_token = $data_service->getOAuth2LoginHelper()
247 1
                                        ->refreshToken();
248
249
            $data_service->updateOAuth2Token($oauth_token);
250
251
            $this->token->parseOauthToken($oauth_token)
252
                        ->save();
253
254
            return $data_service;
255
        }
256
257
        // Create new...
258 2
        return DataService::Configure($this->parseDataConfigs());
259
    }
260
261
    /**
262
     * QuickBooks is not consistent on their naming of variables, so map them
263
     */
264 4
    protected function parseDataConfigs()
265
    {
266
        return [
267 4
            'auth_mode'    => $this->configs['data_service']['auth_mode'],
268 4
            'baseUrl'      => $this->configs['data_service']['base_url'],
269 4
            'ClientID'     => $this->configs['data_service']['client_id'],
270 4
            'ClientSecret' => $this->configs['data_service']['client_secret'],
271 4
            'RedirectURI'  => route('quickbooks.token'),
272 4
            'scope'        => $this->configs['data_service']['scope'],
273
        ];
274
    }
275
276
    /**
277
     * Allow setting a token to switch "user"
278
     *
279
     * @param Token $token
280
     *
281
     * @return $this
282
     */
283 6
    public function setToken(Token $token)
284
    {
285 6
        $this->token = $token;
286
287
        // The DataService is tied to a specific token, so remove it when using a new one
288 6
        unset($this->data_service);
289
290 6
        return $this;
291
    }
292
}
293