MyAllocator PMS PHP SDK
  • Namespace
  • Class
  • Tree

Namespaces

  • MyAllocator
    • phpsdk
      • src
        • Api
        • Exception
        • Object
        • Util
  • PHP

Classes

  • AmenityList
  • ARIRulesList
  • ARIRulesUpdate
  • ARIUpdate
  • ARIUpdateStatus
  • AssociatePropertyToPMS
  • AssociateUserToPMS
  • BookingAction
  • BookingList
  • BookingPaymentDownload
  • BookingPaymentPasswordValidate
  • ChannelList
  • HelloUser
  • HelloVendor
  • HelloVendorUser
  • HelloWorld
  • LoopARIList
  • LoopBookingAction
  • LoopBookingCreate
  • LoopBookingList
  • MaApi
  • NotificationEmailsList
  • PropertyBillingList
  • PropertyChannelList
  • PropertyCreate
  • PropertyImageCreate
  • PropertyImageList
  • PropertyImageRemove
  • PropertyList
  • PropertyModify
  • RoomAvailabilityList
  • RoomCreate
  • RoomImageCreate
  • RoomImageList
  • RoomImageRemove
  • RoomList
  • RoomRemove
  • RoomUpdate
  • UserCreate
  • UserExists
  • VendorSet
  1 <?php
  2 /**
  3  * Copyright (C) 2014 MyAllocator
  4  *
  5  * A copy of the LICENSE can be found in the LICENSE file within
  6  * the root directory of this library.  
  7  *
  8  * Permission is hereby granted, free of charge, to any person obtaining a
  9  * copy of this software and associated documentation files (the "Software"),
 10  * to deal in the Software without restriction, including without limitation
 11  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 12  * and/or sell copies of the Software, and to permit persons to whom the
 13  * Software is furnished to do so, subject to the following conditions:
 14  *
 15  * The above copyright notice and this permission notice shall be included
 16  * in all copies or substantial portions of the Software.
 17  *
 18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 19  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 20  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 21  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 22  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 23  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 24  * IN THE SOFTWARE.
 25  */
 26 
 27 namespace MyAllocator\phpsdk\src\Api;
 28 use MyAllocator\phpsdk\src\MaBaseClass;
 29 use MyAllocator\phpsdk\src\Object\Auth;
 30 use MyAllocator\phpsdk\src\Util\Requestor;
 31 use MyAllocator\phpsdk\src\Util\Common;
 32 use MyAllocator\phpsdk\src\Exception\ApiException;
 33 use MyAllocator\phpsdk\src\Exception\ApiAuthenticationException;
 34 
 35 /**
 36  * The Base API class.
 37  */
 38 class MaApi extends MaBaseClass
 39 {
 40     /**
 41      * @var boolean Whether or not the API is currently enabled/supported.
 42      */
 43     protected $enabled = true;
 44 
 45     /**
 46      * @var string The api method.
 47      */
 48     protected $id = 'MaApi';
 49 
 50     /**
 51      * @var \MyAllocator\Object\Auth Authentication object for requester.
 52      */
 53     private $auth = null;
 54 
 55     /**
 56      * @var array API request parameters to be included in API request.
 57      */
 58     private $params = null;
 59 
 60     /**
 61      * @var mixed The response from the last request.
 62      */
 63     private $lastApiResponse = null;
 64 
 65     /**
 66      * @var array Array of required and optional authentication and argument 
 67      *      keys (string) for API method.
 68      */
 69     protected $keys = array(
 70         'auth' => array(
 71             'req' => array(),
 72             'opt' => array()
 73         ),
 74         'args' => array(
 75             'req' => array(),
 76             'opt' => array()
 77         )
 78     );
 79 
 80     /**
 81      * Class contructor attempts to assign authentication parameters
 82      * from $cfg argument. Authentication parameters may be configured
 83      * via Auth object or array. The parent constructor handles
 84      * the included configuration parameters.
 85      *
 86      * @param mixed $cfg API configuration potentially containing an 
 87      *        'auth' key with authentication parameters/object or a
 88      *        'cfg' key containing configurations to overwrite Config/Config.php.
 89      */
 90     public function __construct($cfg = null)
 91     {
 92         parent::__construct($cfg);
 93 
 94         // Load auth information if provided
 95         if (isset($cfg) && isset($cfg['auth'])) {
 96             if (is_object($cfg['auth']) &&
 97                 is_a($cfg['auth'], 'MyAllocator\phpsdk\src\Object\Auth')
 98             ) {
 99                 $this->auth = $cfg['auth'];
100             } else if (is_array($cfg['auth'])) {
101                 $auth = new Auth();
102                 $auth_refl = new \ReflectionClass($auth);
103                 $props = $auth_refl->getProperties(\ReflectionProperty::IS_PUBLIC);
104 
105                 foreach ($props as $prop) {
106                     $name = $prop->getName();
107                     if (isset($cfg['auth'][$name])) {
108                         $auth->$name = $cfg['auth'][$name];
109                     }
110                 }
111                 $this->auth = $auth;
112             }
113         }
114     }
115 
116     /**
117      * Set the parameters to be used in the API request. Parameters may
118      * also be set at the time of API call via callApiWithParams().
119      *
120      * @param array $params API request parameters.
121      */
122     public function setParams($params)
123     {
124         $this->params = $params;
125     }
126 
127     /**
128      * Call the API using previously set parameters (if any).
129      *
130      * @return mixed API response.
131      */
132     public function callApi()
133     {
134         return $this->processRequest($this->params);
135     }
136 
137     /**
138      * Call the API using provided parameters (if any).
139      *
140      * @param array $params API request parameters.
141      * @return mixed API response.
142      */
143     public function callApiWithParams($params = null)
144     {
145         return $this->processRequest($params);
146     }
147 
148     /**
149      * Get the authentication object.
150      *
151      * @param string $errorOnNull If true, throw an exception if auth null.
152      *
153      * @return MyAllocator\phpsdk\src\Object\Auth API Authentication object.
154      *
155      * @throws MyAllocator\phpsdk\src\Exception\ApiException
156      */
157     public function getAuth($errorOnNull = false)
158     {
159         if ($errorOnNull && !$this->auth) {
160             $msg = 'No Auth object provided.  (HINT: Set your Auth data using '
161                  . '"$API->setAuth(Auth $auth)" or $API\' constructor.  '
162                  . 'See https://TODO for details.';
163             throw new ApiException($msg);
164         }
165 
166         return $this->auth;
167     }
168 
169     /**
170      * Set the authentication object for the API.
171      *
172      * @param MyAllocator\phpsdk\src\Object\Auth API Authentication object.
173      */
174     public function setAuth(Auth $auth)
175     {
176         $this->auth = $auth;
177     }
178 
179     /**
180      * Determine if the API is enabled.
181      *
182      * @return booleam True if the API is enabled.
183      */
184     public function isEnabled()
185     {
186         return $this->enabled;
187     }
188 
189     /**
190      * Get the last API response as array($rbody, $rcode).
191      *
192      * @return mixed The last API response.
193      */
194     public function getLastApiResponse()
195     {
196         return $this->lastApiResponse;
197     }
198 
199     /**
200      * Validate and process/send the API request.
201      *
202      * @param array $params API request parameters.
203      * @return mixed API response.
204      */
205     private function processRequest($params = null)
206     {
207         // Ensure this api is currently enabled/supported
208         $this->assertEnabled();
209 
210         // Instantiate requester
211         $requestor = new Requestor($this->config);
212 
213         switch ($this->config['dataFormat']) {
214             case 'xml':
215                 // Do nothing special for XML
216                 break;
217             case 'json':
218                 // Validate and sanitize parameters (json decode/encode)
219                 if ($this->config['paramValidationEnabled']) {
220                     $params_decoded = json_decode($params, TRUE);
221                     $params_decoded = $this->validateApiParameters($this->keys, $params_decoded);
222                     // Add URI method and version to payload
223                     $params['_method'] = $this->id;
224                     $params['_version'] = $requestor->version;
225                     $params = json_encode($params_decoded);
226                 }
227                 break;
228             case 'array':
229                 // Validate and sanitize parameters
230                 if ($this->config['paramValidationEnabled']) {
231                     $params = $this->validateApiParameters($this->keys, $params);
232                 } else {
233                     $params = $this->setAuthenticationParametersNoValidation($params);
234                 }
235                 // Add URI method and version to payload
236                 $params['_method'] = $this->id;
237                 $params['_version'] = $requestor->version;
238                 break;
239             default:
240                 throw new ApiException(
241                     'Invalid dataFormat: '.$this->config['dataFormat']
242                 );
243         }
244 
245         // Send request
246         $response = $requestor->request('post', $this->id, $params);
247 
248         // Return result
249         $this->lastApiResponse = $response;
250         return $response;
251     }
252 
253     /**
254      * Assert the API is enabled.
255      */
256     private function assertEnabled()
257     {
258         if (!$this->enabled) {
259             $msg = 'This API is not currently enabled/supported.';
260             throw new ApiException($msg);
261         }
262     }
263 
264     /**
265      * Validate authentication and argument parameters for an API.
266      *
267      * @param array $keys Array of required and optional 
268      *  authentication and argument keys (string) for API method.
269      * @param array $params API specific parameters.
270      *
271      * @return array Validated API parameters.
272      */
273     private function validateApiParameters($keys = null, $params = null)
274     {
275         // Assert API has defined an id/endpoint
276         $this->assertApiId();
277 
278         // Assert API keys array structure is valid
279         $this->assertKeysArrayValid($keys);
280 
281         // Assert keys array has minimum required optional parameters
282         $this->assertKeysHasMinOptParams($keys, $params);
283 
284         // Assert and set authentication parameters from Auth object
285         $params = $this->setAuthenticationParameters($keys, $params, 'req');
286         $params = $this->setAuthenticationParameters($keys, $params, 'opt');
287 
288         // Assert required argument parameters exist (non-authentication)
289         $this->assertReqParameters($keys, $params);
290 
291         // Remove extra parameters not defined in keys array
292         $this->removeUnknownParameters($keys, $params);
293 
294         return $params;
295     }
296 
297     /**
298      * Assert the API id is set by the API class.
299      */
300     private function assertApiId()
301     {
302         // Assert minimum number of optional args exist if requirement exists
303         if (!$this->id) {
304             $msg = 'The API id has not be set in the API class.';
305             throw new ApiException($msg);
306         }
307     }
308 
309     /**
310      * Assert required API keys exist and are valid.
311      *
312      * @param array $keys Array of required and optional 
313      *  authentication and argument keys (string) for API method.
314      */
315     private function assertKeysArrayValid($keys = null)
316     {
317         if ((!$keys) ||
318             (!is_array($keys)) ||
319             (!isset($keys['auth'])) || 
320             (!is_array($keys['auth'])) ||
321             (!isset($keys['auth']['req'])) || 
322             (!is_array($keys['auth']['req'])) ||
323             (!isset($keys['auth']['opt'])) || 
324             (!is_array($keys['auth']['opt'])) ||
325             (!isset($keys['args'])) || 
326             (!is_array($keys['args'])) ||
327             (!isset($keys['args']['req'])) || 
328             (!is_array($keys['auth']['req'])) ||
329             (!isset($keys['args']['opt'])) || 
330             (!is_array($keys['auth']['opt']))
331         ) {
332             $msg = 'Invalid API keys provided. (HINT: Each '
333                  . 'API class must define a $keys array with '
334                  . 'specific key requirements. (HINT: View an /Api/[file] '
335                  . 'for an example.)';
336             throw new ApiException($msg);
337         }
338     }
339 
340     /**
341      * Assert parameters include minimum number of optional
342      * parameters as configured/defined by the API.
343      *
344      * @param array $keys Array of required and optional 
345      *  authentication and argument keys (string) for API method.
346      * @param array $params API specific parameters.
347      *
348      * @throws MyAllocator\phpsdk\src\Exception\ApiException
349      */
350     private function assertKeysHasMinOptParams($keys, $params)
351     {
352         // Assert minimum number of optional args exist if requirement exists
353         if ((isset($keys['args']['optMin'])) && 
354             (!$params || count($params) < $keys['args']['optMin'])
355         ) {
356             $msg = 'API requires at least '.$keys['args']['optMin'].' optional '
357                  . 'parameter(s). (HINT: Reference the $keys '
358                  . 'property at the top of the API class file for '
359                  . 'required and optional parameters.)';
360             throw new ApiException($msg);
361         }
362     }
363 
364     /**
365      * Validate and set required authentication parameters from Auth object.
366      *
367      * @param array $keys Array of required and optional 
368      *  authentication and argument keys (string) for API method.
369      * @param array $params API specific parameters.
370      * @param string $type The type of authentication parameters to
371      *  process (optional or required).
372      *
373      * @return array Paramters with authentication parameters of $type set.
374      *
375      * @throws MyAllocator\phpsdk\src\Exception\ApiAuthenticationException
376      */
377     private function setAuthenticationParameters(
378         $keys = null,
379         $params = null,
380         $type = 'req'
381     ) {
382         if (!empty($keys['auth'][$type])) {
383             if ($this->auth == null) {
384                 $msg = 'No Auth object provided.  (HINT: Set your Auth data using '
385                      . '"$API->setAuth(Auth $auth)" or $API\' constructor.  '
386                      . 'See https://TODO for details.';
387                 throw new ApiAuthenticationException($msg);
388             }
389 
390             // Set authentication parameters
391             $auth_group = false;
392             foreach ($keys['auth'][$type] as $k) {
393                 if (is_array($k) && !empty($k)) {
394                     /*
395                      * Different auth key groups may be required.
396                      * In these situations, must assert that each
397                      * key within an auth key group exists. Exits
398                      * once the first auth key group is validated.
399                      */
400 
401                     if ($auth_group && $auth_group_validated) {
402                         /*
403                         * At this point an authentication group has been satisfied
404                         * and we don't need to process additional groups.
405                         */
406                         continue;
407                     }
408 
409                     $auth_group = true;
410                     $auth_group_validated = true;
411                     foreach ($k as $g) {
412                         if (!isset($params[$g])) {
413                             $v = $this->auth->getAuthKeyVar($g);
414                             if (!$v) {
415                                 $auth_group_validated = false;
416                                 break;
417                             }
418                             $params[$g] = $v;
419                         }
420                     }
421                 } else {
422                     if (!isset($params[$k])) {
423                         $v = $this->auth->getAuthKeyVar($k);
424                         if (!$v) {
425                             if ($type == 'req') {
426                                 $msg = 'Authentication key `'.$k.'` is required. '
427                                      . 'HINT: Set your Auth data using "$API->'
428                                      . 'setAuth(Auth $auth)" or $API\' constructor. '
429                                      . 'See https://TODO for details.';
430                                 throw new ApiAuthenticationException($msg);
431                             } else {
432                                 // optional
433                                 continue;
434                             }
435                         }
436                         $params[$k] = $v;
437                     }
438                 }
439             }
440 
441             // If keys configured with authentication groups, verify one was validated
442             if ($auth_group && !$auth_group_validated) {
443                 $msg = 'A required authentication key group was not satisfied. '
444                      . '(HINT: Reference the $keys '
445                      . 'property at the top of the API class file for '
446                      . 'required and optional parameters.)';
447                 throw new ApiAuthenticationException($msg);
448             }
449         }
450 
451         return $params;
452     }
453 
454     /**
455      * Set authentication parameters if authentication property set.
456      * This only runs if parameter validation is disabled and does
457      * not validate $keys.
458      *
459      * @param array $params API specific parameters.
460      *
461      * @return array Paramters with authentication parameters set.
462      */
463     private function setAuthenticationParametersNoValidation($params = null)
464     {
465         // Return if authentication property not set
466         if ($this->auth == null) {
467             return $params;
468         }
469 
470         // Set parameters for previously configured auth properties
471         // Get property list from auth class
472         $auth_refl = new \ReflectionClass($this->auth);
473         $props = $auth_refl->getProperties(\ReflectionProperty::IS_PUBLIC);
474 
475         /*
476          * Loop through property names to determine if configured in auth object.
477          * Add to parameters if set and does not already exist.
478          */
479         foreach ($props as $prop) {
480             $name = $prop->getName();
481             if (isset($this->auth->$name)) {
482                 // Do not overwrite if parameter already included
483                 $key = $this->auth->getAuthKeyByVar($name);
484                 if (!isset($params[$key])) {
485                     $params[$key] = $this->auth->$name;
486                 }
487             }
488         }
489 
490         return $params;
491     }
492 
493     /**
494      * Validate required parameters for API.
495      *
496      * @param array $keys Array of required and optional 
497      *  authentication and argument keys (string) for API method.
498      * @param array $params API specific parameters.
499      *
500      * @throws MyAllocator\phpsdk\src\Exception\ApiException
501      */
502     private function assertReqParameters($keys, $params = null)
503     {
504         if (!empty($keys['args']['req'])) {
505             if (!$params) {
506                 $msg = 'No parameters provided. (HINT: Reference the $keys '
507                      . 'property at the top of the API class file for '
508                      . 'required and optional parameters.)';
509                 throw new ApiException($msg);
510             }
511 
512             foreach ($keys['args']['req'] as $k) {
513                 if (!isset($params[$k])) {
514                     $msg = 'Required parameter `'.$k.'` not provided. '
515                          . '(HINT: Reference the $keys '
516                          . 'property at the top of the API class file for '
517                          . 'required and optional parameters.)';
518                     throw new ApiException($msg);
519                 }
520             }
521         }
522     }
523 
524     /**
525      * Strip parameters not defined in API keys array.
526      *
527      * @param array $keys Array of required and optional 
528      *  authentication and argument keys (string) for API method.
529      * @param array $params API specific parameters.
530      *
531      * @return array API parameters with unknown parameters
532      *  removed.
533      */
534     private function removeUnknownParameters($keys, $params)
535     {
536         $valid_keys = array_merge(
537             $keys['auth']['req'],
538             $keys['auth']['opt'],
539             $keys['args']['req'],
540             $keys['args']['opt']
541         );
542 
543         foreach ($params as $k => $v) {
544             if (!in_array($k, $valid_keys)) {
545                 unset($params[$k]);
546             }
547         }
548 
549         return $params;
550     }
551 }
552 
MyAllocator PMS PHP SDK API documentation generated by ApiGen