Passed
Push — master ( db8114...f9a48a )
by Mike
03:20
created

AbstractClient::getToken()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 3
ccs 2
cts 2
cp 1
rs 10
cc 1
eloc 2
nc 1
nop 0
crap 1
1
<?php
2
/**
3
 * ©[2016] SugarCRM Inc.  Licensed by SugarCRM under the Apache 2.0 license.
4
 */
5
6
namespace SugarAPI\SDK\Client\Abstracts;
7
8
use SugarAPI\SDK\Client\Interfaces\ClientInterface;
9
use SugarAPI\SDK\Exception\EntryPoint\EntryPointException;
10
use SugarAPI\SDK\Helpers\Helpers;
11
use SugarAPI\SDK\EntryPoint\POST\OAuth2Logout;
12
use SugarAPI\SDK\EntryPoint\POST\OAuth2Token;
13
use SugarAPI\SDK\EntryPoint\POST\RefreshToken;
14
use SugarAPI\SDK\Exception\Authentication\AuthenticationException;
15
16
abstract class AbstractClient implements ClientInterface {
17
18
    /**
19
     * Array of Statically Bound Tokens for SDK Clients
20
     * - Allows for reinstating objects in multiple areas, without needing to Sign-in
21
     * - Allows for multiple client_id's to be used between SDK Clients
22
     *
23
     * @var array = array(
24
     *      $client_id => $token
25
     * )
26
     */
27
    protected static $_STORED_TOKENS = array();
28
29
30
    /**
31
     * The configured server domain name/url on the SDK Client
32
     * @var string
33
     */
34
    protected $server = '';
35
36
    /**
37
     * The API Url configured on the SDK Client
38
     * @var string
39
     */
40
    protected $apiURL = '';
41
42
    /**
43
     * The full token object returned by the Login method
44
     * @var \stdClass
45
     */
46
    protected $token;
47
48
    /**
49
     * Array of OAuth Creds to be used by SDK Client
50
     * @var array
51
     */
52
    protected $credentials = array();
53
54
    /**
55
     * Token expiration time
56
     * @var
57
     */
58
    protected $expiration;
59
60
    /**
61
     * The list of registered EntryPoints
62
     * @var array
63
     */
64
    protected $entryPoints = array();
65
66 1
    public function __construct($server = '',array $credentials = array()){
67 1
        $server = (empty($server)?$this->server:$server);
68 1
        if (!empty($server)) {
69 1
            $this->setServer($server);
70 1
        }
71 1
        $credentials = (empty($credentials)?$this->credentials:$credentials);
72 1
        if (!empty($credentials)){
73 1
            $this->setCredentials($credentials);
74 1
        }
75 1
        $this->registerSDKEntryPoints();
76 1
    }
77
78
    /**
79
     * @inheritdoc
80
     * @param string $server
81
     */
82 1
    public function setServer($server) {
83 1
        $this->server = $server;
84 1
        $this->apiURL = Helpers::configureAPIURL($this->server);
85 1
        return $this;
86
    }
87
88
    /**
89
     * @inheritdoc
90
     */
91 1
    public function getAPIUrl() {
92 1
        return $this->apiURL;
93
    }
94
95
    /**
96
     * @inheritdoc
97
     * Retrieves stored token based on passed in Credentials
98
     */
99 2
    public function setCredentials(array $credentials){
100 2
        $this->credentials = $credentials;
101 2
        if (isset($this->credentials['client_id'])) {
102 2
            $token = static::getStoredToken($this->credentials['client_id']);
103 2
            if (!empty($token)) {
104 1
                $this->setToken($token);
105 1
            }
106 2
        }
107 2
        return $this;
108
    }
109
110
    /**
111
     * @inheritdoc
112
     */
113 1
    public function setToken(\stdClass $token){
114 1
        $this->token = $token;
115 1
        $this->expiration = time()+$token->expires_in;
116 1
        return $this;
117
    }
118
119
    /**
120
     * @inheritdoc
121
     */
122 2
    public function getToken(){
123 2
        return $this->token;
124
    }
125
126
    /**
127
     * @inheritdoc
128
     */
129 1
    public function getCredentials(){
130 1
        return $this->credentials;
131
    }
132
133
    /**
134
     * @inheritdoc
135
     */
136 1
    public function getServer() {
137 1
        return $this->server;
138
    }
139
140
    /**
141
     * @inheritdoc
142
     */
143 1
    public function authenticated(){
144 1
        return time() < $this->expiration;
145
    }
146
147
    /**
148
     * Register the defined EntryPoints in SDK, located in src/EntryPoint/registry.php file
149
     * @throws EntryPointException
150
     */
151 1
    protected function registerSDKEntryPoints(){
152 1
        $entryPoints = Helpers::getSDKEntryPointRegistry();
153 1
        foreach ($entryPoints as $funcName => $className){
154 1
            $this->registerEntryPoint($funcName, $className);
155 1
        }
156 1
    }
157
158
    /**
159
     * @param $funcName
160
     * @param $className
161
     * @return bool
0 ignored issues
show
Documentation introduced by
Should the return type not be AbstractClient?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
162
     * @throws EntryPointException
163
     */
164 2
    public function registerEntryPoint($funcName, $className){
165 2
        $implements = class_implements($className);
166 2
        if (is_array($implements) && in_array('SugarAPI\SDK\EntryPoint\Interfaces\EPInterface',$implements)){
167 1
            $this->entryPoints[$funcName] = $className;
168 1
        }else{
169 1
            throw new EntryPointException($className,'Class must extend SugarAPI\SDK\EntryPoint\Interfaces\EPInterface');
170
        }
171 1
        return $this;
172
    }
173
174
    /**
175
     * Generates the EntryPoint objects based on a Method name that was called
176
     * @param $name
177
     * @param $params
178
     * @return mixed
179
     * @throws EntryPointException
180
     */
181 2
    public function __call($name, $params){
182 2
        if (array_key_exists($name, $this->entryPoints)){
183 1
            $Class = $this->entryPoints[$name];
184 1
            $EntryPoint = new $Class($this->apiURL, $params);
185
186 1
            if ($EntryPoint->authRequired()){
187 1
                if (isset($this->token) && $this->authenticated()) {
188 1
                    $EntryPoint->setAuth($this->getToken()->access_token);
189 1
                }
190 1
            }
191 1
            return $EntryPoint;
192
        }else{
193 1
            throw new EntryPointException($name,'Unregistered EntryPoint');
194
        }
195
    }
196
197
    /**
198
     * @inheritdoc
199
     * @throws AuthenticationException - When Login request fails
200
     */
201 View Code Duplication
    public function login() {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
202
        $EP = new OAuth2Token($this->apiURL);
203
        $response = $EP->execute($this->credentials)->getResponse();
204
        if ($response->getStatus()=='200'){
205
            $this->setToken($response->getBody(FALSE));
0 ignored issues
show
Unused Code introduced by
The call to ResponseInterface::getBody() has too many arguments starting with FALSE.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
Documentation introduced by
$response->getBody(FALSE) is of type string, but the function expects a object<stdClass>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
206
            static::storeToken($this->token,$this->credentials['client_id']);
207
        } else {
208
            $error = $response->getBody();
209
            throw new AuthenticationException("Login Response [".$error['error']."] ".$error['error_message']);
210
        }
211
        return $this;
212
    }
213
214
    /**
215
     * @inheritdoc
216
     * @throws AuthenticationException - When Refresh Request fails
217
     */
218
    public function refreshToken(){
219
        $refreshOptions = array(
220
            'client_id' => $this->credentials->client_id,
221
            'client_secret' => $this->credentials->client_secret,
222
            'refresh_token' => $this->credentials->refresh_token
223
        );
224
        $EP = new RefreshToken($this->apiURL);
225
        $response = $EP->execute($refreshOptions)->getResponse();
226
        if ($response->getStatus()=='200'){
227
            $this->setToken($response->getBody(FALSE));
0 ignored issues
show
Unused Code introduced by
The call to ResponseInterface::getBody() has too many arguments starting with FALSE.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
Documentation introduced by
$response->getBody(FALSE) is of type string, but the function expects a object<stdClass>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
228
            static::storeToken($this->token,$this->credentials['client_id']);
229
        }else{
230
            $error = $response->getBody();
231
            throw new AuthenticationException("Refresh Response [".$error['error']."] ".$error['error_message']);
232
        }
233
        return $this;
234
    }
235
236
    /**
237
     * @inheritdoc
238
     * @throws AuthenticationException - When logout request fails
239
     */
240 View Code Duplication
    public function logout(){
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
241
        if ($this->authenticated()){
242
            $EP = new OAuth2Logout($this->apiURL);
243
            $response = $EP->execute()->getResponse();
244
            if ($response->getStatus()=='200'){
245
                unset($this->token);
246
                static::removeStoredToken($this->credentials['client_id']);
247
            }else{
248
                $error = $response->getBody();
249
                throw new AuthenticationException("Logout Response [".$error['error']."] ".$error['message']);
250
            }
251
        }
252
        return $this;
253
    }
254
255
    /**
256
     * @inheritdoc
257
     * @param \stdClass $token
258
     */
259 1
    public static function storeToken($token, $client_id) {
260 1
        static::$_STORED_TOKENS[$client_id] = $token;
261 1
        return TRUE;
262
    }
263
264
    /**
265
     * @inheritdoc
266
     */
267 1
    public static function getStoredToken($client_id) {
268 1
        return (isset(static::$_STORED_TOKENS[$client_id])?static::$_STORED_TOKENS[$client_id]:NULL);
269
    }
270
271
    /**
272
     * @inheritdoc
273
     */
274 1
    public static function removeStoredToken($client_id) {
275 1
        unset(static::$_STORED_TOKENS[$client_id]);
276 1
        return TRUE;
277
    }
278
279
}