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

AbstractEntryPoint::setData()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 2
Bugs 0 Features 0
Metric Value
c 2
b 0
f 0
dl 0
loc 4
ccs 3
cts 3
cp 1
rs 10
cc 1
eloc 3
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\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 1
    public function setResponse(ResponseInterface $Response) {
154 1
        $this->Response = $Response;
155 1
        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
        }else{
207 1
            throw new InvalidRequestException(get_called_class(),"Request property not configured");
208
        }
209 1
        return $this;
210
    }
211
212
    /**
213
     * @inheritdoc
214
     */
215 1
    public function authRequired() {
216 1
        return $this->_AUTH_REQUIRED;
217
    }
218
219
    /**
220
     * Verifies URL and Data are setup, then sets them on the Request Object
221
     * @throws InvalidURLException
222
     * @throws RequiredDataException
223
     */
224 1
    protected function configureRequest(){
225 1
        if ($this->verifyUrl()) {
226 1
            $this->Request->setURL($this->Url);
227 1
        }
228 1
        if ($this->verifyData() && !empty($this->Data)) {
229 1
            $this->Request->setBody($this->Data);
230 1
        }
231 1
        $this->configureAuth();
232 1
    }
233
234
    /**
235
     * Configures the authentication header on the Request object
236
     */
237 1
    protected function configureAuth(){
238 1
        if ($this->authRequired()) {
239 1
            $this->Request->addHeader('OAuth-Token', $this->accessToken);
240 1
        }
241 1
    }
242
243
    /**
244
     * Configures Data for the EntryPoint. Used mainly as an override function on implemented EntryPoints.
245
     * @var $data
246
     */
247 1
    protected function configureData($data){
248 1
        if (!empty($this->_REQUIRED_DATA)&&is_array($data)){
249 1
            $data = $this->configureDefaultData($data);
250 1
        }
251 1
        $this->setData($data);
252 1
    }
253
254
    /**
255
     * Configure Defaults on a Data array based on the Required Data property
256
     * @param array $data
257
     * @return array
258
     */
259 1
    protected function configureDefaultData(array $data){
260 1
        foreach($this->_REQUIRED_DATA as $property => $value){
261 1
            if (!isset($data[$property]) && $value!==NULL){
262 1
                $data[$property] = $value;
263 1
            }
264 1
        }
265 1
        return $data;
266
    }
267
268
    /**
269
     * Configures the URL, by updating any variable placeholders in the URL property on the EntryPoint
270
     * - Replaces $module with $this->Module
271
     * - Replaces all other variables starting with $, with options in the order they were given
272
     */
273 1
    protected function configureURL(){
274 1
        $url = $this->_URL;
275 1
        if ($this->requiresOptions()) {
276 1
            $urlParts = explode("/", $this->_URL);
277 1
            $o = 0;
278 1
            foreach ($urlParts as $key => $part) {
279 1
                if (strpos($part, "$") !== FALSE) {
280 1
                    if (isset($this->Options[$o])) {
281 1
                        $urlParts[$key] = $this->Options[$o];
282 1
                        $o++;
283 1
                    }
284 1
                }
285 1
            }
286 1
            $url = implode($urlParts,"/");
287 1
        }
288 1
        $url = $this->baseUrl.$url;
289 1
        $this->setUrl($url);
290 1
    }
291
292
    /**
293
     * Verify if URL is configured properly
294
     * @return bool
295
     * @throws InvalidURLException
296
     */
297 2
    protected function verifyUrl(){
298 2
        $UrlArray = explode("?",$this->Url);
299 2
        if (strpos($UrlArray[0],"$") !== FALSE){
300 1
            throw new InvalidURLException(get_called_class(),"Configured URL is ".$this->Url);
301
        }
302 1
        return true;
303
    }
304
305
    /**
306
     * Validate the Data property on the EntryPoint
307
     * @return bool
308
     * @throws RequiredDataException
309
     */
310 1
    protected function verifyData(){
311 1
        if (isset($this->_DATA_TYPE)||!empty($this->_DATA_TYPE)) {
312 1
            $this->verifyDataType();
313 1
        }
314 1
        if (!empty($this->_REQUIRED_DATA)){
315 1
            $this->verifyRequiredData();
316 1
        }
317 1
        return true;
318
    }
319
320
    /**
321
     * Validate DataType on the EntryPoint object
322
     * @return bool
323
     * @throws RequiredDataException
324
     */
325 2
    protected function verifyDataType(){
326 2
        if (gettype($this->Data) !== $this->_DATA_TYPE) {
327 1
            throw new RequiredDataException(get_called_class(),"Valid DataType is {$this->_DATA_TYPE}");
328
        }
329 1
        return true;
330
    }
331
332
    /**
333
     * Validate Required Data for the EntryPoint
334
     * @return bool
335
     * @throws RequiredDataException
336
     */
337 2
    protected function verifyRequiredData(){
338 2
        $errors = array();
339 2
        foreach($this->_REQUIRED_DATA as $property => $defaultValue){
340 2
            if (!isset($this->Data[$property])){
341 1
                $errors[] = $property;
342 1
            }
343 2
        }
344 2
        if (count($errors)>0){
345 1
            throw new RequiredDataException(get_called_class(),"Missing data for ".implode(",",$errors));
346
        }
347 1
        return true;
348
    }
349
350
    /**
351
     * Checks if EntryPoint URL contains requires Options
352
     * @return bool
353
     */
354 1
    protected function requiresOptions(){
355 1
        return strpos($this->_URL,"$") === FALSE?FALSE:TRUE;
356
    }
357
358
}