Test Failed
Push — master ( ec757f...50d8c4 )
by Mike
03:07
created

AbstractEntryPoint::configureAuth()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 2

Importance

Changes 2
Bugs 0 Features 0
Metric Value
c 2
b 0
f 0
dl 0
loc 5
ccs 5
cts 5
cp 1
rs 9.4285
cc 2
eloc 3
nc 2
nop 0
crap 2
1
<?php
2
/**
3
 * ©[2016] SugarCRM Inc.  Licensed by SugarCRM under the Apache 2.0 license.
4
 */
5
6
namespace SugarAPI\SDK\EntryPoint\Abstracts;
7
8
9
use SugarAPI\SDK\EntryPoint\Interfaces\EPInterface;
10
use SugarAPI\SDK\Exception\EntryPoint\InvalidRequestException;
11
use SugarAPI\SDK\Exception\EntryPoint\InvalidURLException;
12
use SugarAPI\SDK\Exception\EntryPoint\RequiredDataException;
13
use SugarAPI\SDK\Exception\EntryPoint\RequiredOptionsException;
14
use SugarAPI\SDK\Response\Interfaces\ResponseInterface;
15
use SugarAPI\SDK\Request\Interfaces\RequestInterface;
16
17
/**
18
 * Class AbstractEntryPoint
19
 * @package SugarAPI\SDK\EntryPoint\Abstracts
20
 */
21
abstract class AbstractEntryPoint implements EPInterface {
22
23
    /**
24
     * Whether or not Authentication is Required
25
     * @var bool
26
     */
27
    protected $_AUTH_REQUIRED = true;
28
29
    /**
30
     * The URL for the EntryPoint
31
     * - When configuring URL you define URL Parameters with $variables
32
     *      Examples:
33
     *          - Forecasts/$record_id
34
     * - $module Variable is a keyword to place the Module property into the URL
35
     *      Examples:
36
     *          - $module/$record
37
     * - Options property is used to replace variables in the order in which they are passed
38
     *
39
     * @var string
40
     */
41
    protected $_URL;
42
43
    /**
44
     * An array of Required Data properties that should be passed in the Request
45
     * @var array
46
     */
47
    protected $_REQUIRED_DATA = array();
48
49
    /**
50
     * The required type of Data to be given to the EntryPoint. If none, different types can be passed in.
51
     * @var string
52
     */
53
    protected $_DATA_TYPE;
54
55
    /**
56
     * The configured URL for the EntryPoint
57
     * @var string
58
     */
59
    protected $Url;
60
61
    /**
62
     * The initial URL passed into the EntryPoint
63
     * @var
64
     */
65
    protected $baseUrl;
66
67
    /**
68
     * The passed in Options for the EntryPoint
69
     * - If $module variable is used in $_URL static property, then 1st option will be used as Module
70
     * @var array
71
     */
72
    protected $Options = array();
73
74
    /**
75
     * The data being passed to the API EntryPoint
76
     * @var mixed - array||stdClass
77
     */
78
    protected $Data;
79
80
    /**
81
     * The Request Object, used by the EntryPoint to submit the data
82
     * @var RequestInterface
83
     */
84
    protected $Request;
85
86
    /**
87
     * The Response Object, returned by the Request Object
88
     * @var ResponseInterface
89
     */
90
    protected $Response;
91
92
    /**
93
     * Access Token for authentication
94
     * @var string
95
     */
96
    protected $accessToken;
97
98
99 1
    public function __construct($baseUrl,array $options = array()){
100 1
        $this->baseUrl = $baseUrl;
101
102 1
        if (!empty($options)) {
103 1
            $this->setOptions($options);
104 1
        }
105 1
        $this->configureURL();
106 1
    }
107
108
    /**
109
     * @inheritdoc
110
     */
111 1
    public function setOptions(array $options){
112 1
        $this->Options = $options;
113 1
        $this->configureURL();
114 1
        return $this;
115
    }
116
117
    /**
118
     * @inheritdoc
119
     * @throws RequiredDataException - When passed in data contains issues
120
     */
121 1
    public function setData($data){
122 1
        $this->Data = $data;
123 1
        return $this;
124
    }
125
126
    /**
127
     * @inheritdoc
128
     */
129 1
    public function setAuth($accessToken) {
130 1
        $this->accessToken = $accessToken;
131 1
        return $this;
132
    }
133
134
    /**
135
     * @inheritdoc
136
     */
137 1
    public function setUrl($url) {
138 1
        $this->Url = $url;
139 1
        return $this;
140
    }
141
142
    /**
143
     * @inheritdoc
144
     */
145 1
    public function setRequest(RequestInterface $Request) {
146 1
        $this->Request = $Request;
147 1
        return $this;
148
    }
149
150
    /**
151
     * @inheritdoc
152
     */
153 2
    public function setResponse(ResponseInterface $Response) {
154 2
        $this->Response = $Response;
155 2
        return $this;
156
    }
157
158
    /**
159
     * @inheritdoc
160
     */
161 1
    public function getOptions(){
162 1
        return $this->Options;
163
    }
164
165
    /**
166
     * @inheritdoc
167
     */
168 1
    public function getData(){
169 1
        return $this->Data;
170
    }
171
172
    /**
173
     * @inheritdoc
174
     */
175 1
    public function getUrl(){
176 1
        return $this->Url;
177
    }
178
179
    /**
180
     * @inheritdoc
181
     */
182 1
    public function getResponse(){
183 1
        return $this->Response;
184
    }
185
186
    /**
187
     * @inheritdoc
188
     */
189 1
    public function getRequest(){
190 1
        return $this->Request;
191
    }
192
193
    /**
194
     * @inheritdoc
195
     * @param null $data - short form data for EntryPoint, which is configure by configureData method
196
     * @return $this
197
     * @throws InvalidRequestException
198
     * @throws InvalidURLException
199
     */
200 2
    public function execute($data = NULL){
201 2
        $data =  ($data === NULL?$this->Data:$data);
202 2
        $this->configureData($data);
203 2
        if (is_object($this->Request)) {
204 1
            $this->configureRequest();
205 1
            $this->Request->send();
206 1
            $this->configureResponse();
207 1
        }else{
208 1
            throw new InvalidRequestException(get_called_class(),"Request property not configured");
209
        }
210 1
        return $this;
211
    }
212
213
    /**
214
     * @inheritdoc
215
     */
216 1
    public function authRequired() {
217 1
        return $this->_AUTH_REQUIRED;
218
    }
219
220
    /**
221
     * Verifies URL and Data are setup, then sets them on the Request Object
222
     * @throws InvalidURLException
223
     * @throws RequiredDataException
224
     */
225 1
    protected function configureRequest(){
226 1
        if ($this->verifyUrl()) {
227 1
            $this->Request->setURL($this->Url);
228 1
        }
229 1
        if ($this->verifyData() && !empty($this->Data)) {
230 1
            $this->Request->setBody($this->Data);
231 1
        }
232 1
        $this->configureAuth();
233 1
    }
234
235
    /**
236
     * Verifies URL and Data are setup, then sets them on the Request Object
237
     * @throws InvalidURLException
238
     * @throws RequiredDataException
239
     */
240 1
    protected function configureResponse(){
241 1
        if (is_object($this->Response)){
242 1
            $this->Response->setCurlResponse($this->Request->getCurlResponse());
243 1
        }
244 1
    }
245
246
    /**
247
     * Configures the authentication header on the Request object
248
     */
249 1
    protected function configureAuth(){
250 1
        if ($this->authRequired()) {
251 1
            $this->Request->addHeader('OAuth-Token', $this->accessToken);
252 1
        }
253 1
    }
254
255
    /**
256
     * Configures Data for the EntryPoint. Used mainly as an override function on implemented EntryPoints.
257
     * @var $data
258
     */
259 1
    protected function configureData($data){
260 1
        if (!empty($this->_REQUIRED_DATA)&&is_array($data)){
261 1
            $data = $this->configureDefaultData($data);
262 1
        }
263 1
        $this->setData($data);
264 1
    }
265
266
    /**
267
     * Configure Defaults on a Data array based on the Required Data property
268
     * @param array $data
269
     * @return array
270
     */
271 1
    protected function configureDefaultData(array $data){
272 1
        foreach($this->_REQUIRED_DATA as $property => $value){
273 1
            if (!isset($data[$property]) && $value!==NULL){
274 1
                $data[$property] = $value;
275 1
            }
276 1
        }
277 1
        return $data;
278
    }
279
280
    /**
281
     * Configures the URL, by updating any variable placeholders in the URL property on the EntryPoint
282
     * - Replaces $module with $this->Module
283
     * - Replaces all other variables starting with $, with options in the order they were given
284
     */
285 2
    protected function configureURL(){
286 2
        $url = $this->_URL;
287 2
        if ($this->requiresOptions()) {
288 2
            foreach($this->Options as $key => $option){
289 2
                $url = preg_replace('/(\$.*?[^\/]*)/',$option,$url,1);
290 2
            }
291 2
        }
292 2
        $url = $this->baseUrl.$url;
293 2
        $this->setUrl($url);
294 2
    }
295 2
296 2
    /**
297 2
     * Verify if URL is configured properly
298 2
     * @return bool
299 2
     * @throws InvalidURLException
300 2
     */
301 2
    protected function verifyUrl(){
302 2
        $UrlArray = explode("?",$this->Url);
303
        if (strpos($UrlArray[0],"$") !== FALSE){
304
            throw new InvalidURLException(get_called_class(),"Configured URL is ".$this->Url);
305
        }
306
        return true;
307
    }
308
309 2
    /**
310 2
     * Validate the Data property on the EntryPoint
311 2
     * @return bool
312 1
     * @throws RequiredDataException
313
     */
314 1
    protected function verifyData(){
315
        if (isset($this->_DATA_TYPE)||!empty($this->_DATA_TYPE)) {
316
            $this->verifyDataType();
317
        }
318
        if (!empty($this->_REQUIRED_DATA)){
319
            $this->verifyRequiredData();
320
        }
321
        return true;
322 1
    }
323 1
324 1
    /**
325 1
     * Validate DataType on the EntryPoint object
326 1
     * @return bool
327 1
     * @throws RequiredDataException
328 1
     */
329 1
    protected function verifyDataType(){
330
        if (gettype($this->Data) !== $this->_DATA_TYPE) {
331
            throw new RequiredDataException(get_called_class(),"Valid DataType is {$this->_DATA_TYPE}");
332
        }
333
        return true;
334
    }
335
336
    /**
337 2
     * Validate Required Data for the EntryPoint
338 2
     * @return bool
339 1
     * @throws RequiredDataException
340
     */
341 1
    protected function verifyRequiredData(){
342
        $errors = array();
343
        foreach($this->_REQUIRED_DATA as $property => $defaultValue){
344
            if (!isset($this->Data[$property])){
345
                $errors[] = $property;
346
            }
347
        }
348
        if (count($errors)>0){
349 2
            throw new RequiredDataException(get_called_class(),"Missing data for ".implode(",",$errors));
350 2
        }
351 2
        return true;
352 2
    }
353 1
354 1
    /**
355 2
     * Checks if EntryPoint URL contains requires Options
356 2
     * @return bool
357 1
     */
358
    protected function requiresOptions(){
359 1
        return strpos($this->_URL,"$") === FALSE?FALSE:TRUE;
360
    }
361
362
}