Passed
Push — master ( f9a48a...945dc8 )
by Mike
03:01
created

AbstractClient::setServer()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 5
ccs 4
cts 4
cp 1
rs 9.4285
cc 1
eloc 4
nc 1
nop 1
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
        $this->setServer($server);
69 1
        $credentials = (empty($credentials)?$this->credentials:$credentials);
70 1
        $this->setCredentials($credentials);
71 1
        $this->registerSDKEntryPoints();
72 1
    }
73
74
    /**
75
     * @inheritdoc
76
     * @param string $server
77
     */
78 1
    public function setServer($server) {
79 1
        $this->server = $server;
80 1
        $this->apiURL = Helpers::configureAPIURL($this->server);
81 1
        return $this;
82
    }
83
84
    /**
85
     * @inheritdoc
86
     */
87 1
    public function getAPIUrl() {
88 1
        return $this->apiURL;
89
    }
90
91
    /**
92
     * @inheritdoc
93
     * Retrieves stored token based on passed in Credentials
94
     */
95 2
    public function setCredentials(array $credentials){
96 2
        $this->credentials = $credentials;
97 2
        if (isset($this->credentials['client_id'])) {
98 2
            $token = static::getStoredToken($this->credentials['client_id']);
99 2
            if (!empty($token)) {
100 1
                $this->setToken($token);
101 1
            }
102 2
        }
103 2
        return $this;
104
    }
105
106
    /**
107
     * @inheritdoc
108
     */
109 1
    public function setToken(\stdClass $token){
110 1
        $this->token = $token;
111 1
        $this->expiration = time()+$token->expires_in;
112 1
        return $this;
113
    }
114
115
    /**
116
     * @inheritdoc
117
     */
118 2
    public function getToken(){
119 2
        return $this->token;
120
    }
121
122
    /**
123
     * @inheritdoc
124
     */
125 1
    public function getCredentials(){
126 1
        return $this->credentials;
127
    }
128
129
    /**
130
     * @inheritdoc
131
     */
132 1
    public function getServer() {
133 1
        return $this->server;
134
    }
135
136
    /**
137
     * @inheritdoc
138
     */
139 1
    public function authenticated(){
140 1
        return time() < $this->expiration;
141
    }
142
143
    /**
144
     * Register the defined EntryPoints in SDK, located in src/EntryPoint/registry.php file
145
     * @throws EntryPointException
146
     */
147 1
    protected function registerSDKEntryPoints(){
148 1
        $entryPoints = Helpers::getSDKEntryPointRegistry();
149 1
        foreach ($entryPoints as $funcName => $className){
150 1
            $this->registerEntryPoint($funcName, $className);
151 1
        }
152 1
    }
153
154
    /**
155
     * @param $funcName
156
     * @param $className
157
     * @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...
158
     * @throws EntryPointException
159
     */
160 2
    public function registerEntryPoint($funcName, $className){
161 2
        $implements = class_implements($className);
162 2
        if (is_array($implements) && in_array('SugarAPI\SDK\EntryPoint\Interfaces\EPInterface',$implements)){
163 1
            $this->entryPoints[$funcName] = $className;
164 1
        }else{
165 1
            throw new EntryPointException($className,'Class must extend SugarAPI\SDK\EntryPoint\Interfaces\EPInterface');
166
        }
167 1
        return $this;
168
    }
169
170
    /**
171
     * Generates the EntryPoint objects based on a Method name that was called
172
     * @param $name
173
     * @param $params
174
     * @return mixed
175
     * @throws EntryPointException
176
     */
177 2
    public function __call($name, $params){
178 2
        if (array_key_exists($name, $this->entryPoints)){
179 1
            $Class = $this->entryPoints[$name];
180 1
            $EntryPoint = new $Class($this->apiURL, $params);
181
182 1
            if ($EntryPoint->authRequired()){
183 1
                if (isset($this->token) && $this->authenticated()) {
184 1
                    $EntryPoint->setAuth($this->getToken()->access_token);
185 1
                }
186 1
            }
187 1
            return $EntryPoint;
188
        }else{
189 1
            throw new EntryPointException($name,'Unregistered EntryPoint');
190
        }
191
    }
192
193
    /**
194
     * @inheritdoc
195
     * @throws AuthenticationException - When Login request fails
196
     */
197 1 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...
198 1
        $EP = new OAuth2Token($this->apiURL);
199 1
        $response = $EP->execute($this->credentials)->getResponse();
200 1
        if ($response->getStatus()=='200'){
201
            $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...
202
            static::storeToken($this->token,$this->credentials['client_id']);
203
        } else {
204 1
            $error = $response->getBody();
205 1
            throw new AuthenticationException("Login Response [".$error['error']."] ".$error['error_message']);
206
        }
207
        return TRUE;
208
    }
209
210
    /**
211
     * @inheritdoc
212
     * @throws AuthenticationException - When Refresh Request fails
213
     */
214 1
    public function refreshToken(){
215 1
        if (isset($this->credentials['client_id'])&&
216 1
            isset($this->credentials['client_secret'])&&
217 1
            isset($this->token)) {
218
            $refreshOptions = array(
219 1
                'client_id' => $this->credentials['client_id'],
220 1
                'client_secret' => $this->credentials['client_secret'],
221 1
                'refresh_token' => $this->token->refresh_token
222 1
            );
223 1
            $EP = new RefreshToken($this->apiURL);
224 1
            $response = $EP->execute($refreshOptions)->getResponse();
225 1
            if ($response->getStatus() == '200') {
226
                $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...
227
                static::storeToken($this->token, $this->credentials['client_id']);
228
                return TRUE;
229
            } else {
230 1
                $error = $response->getBody();
231 1
                throw new AuthenticationException("Refresh Response [" . $error['error'] . "] " . $error['error_message']);
232
            }
233
        }
234 1
        return FALSE;
235
    }
236
237
    /**
238
     * @inheritdoc
239
     * @throws AuthenticationException - When logout request fails
240
     */
241 1 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...
242 1
        if ($this->authenticated()){
243 1
            $EP = new OAuth2Logout($this->apiURL);
244 1
            $response = $EP->execute()->getResponse();
245 1
            if ($response->getStatus()=='200'){
246
                unset($this->token);
247
                static::removeStoredToken($this->credentials['client_id']);
248
                return TRUE;
249
            }else{
250 1
                $error = $response->getBody();
251 1
                throw new AuthenticationException("Logout Response [".$error['error']."] ".$error['message']);
252
            }
253
        }
254 1
        return FALSE;
255
    }
256
257
    /**
258
     * @inheritdoc
259
     * @param \stdClass $token
260
     */
261 1
    public static function storeToken($token, $client_id) {
262 1
        static::$_STORED_TOKENS[$client_id] = $token;
263 1
        return TRUE;
264
    }
265
266
    /**
267
     * @inheritdoc
268
     */
269 1
    public static function getStoredToken($client_id) {
270 1
        return (isset(static::$_STORED_TOKENS[$client_id])?static::$_STORED_TOKENS[$client_id]:NULL);
271
    }
272
273
    /**
274
     * @inheritdoc
275
     */
276 1
    public static function removeStoredToken($client_id) {
277 1
        unset(static::$_STORED_TOKENS[$client_id]);
278 1
        return TRUE;
279
    }
280
281
}