Overview

Namespaces

  • None
  • OpenCloud
    • Autoscale
      • Resource
    • CloudMonitoring
      • Exception
      • Resource
    • Common
      • Exceptions
      • Log
      • Request
        • Response
    • Compute
    • Database
    • DNS
    • LoadBalancer
      • Resources
    • ObjectStore
      • Resource
    • Orchestration
    • Volume
  • PHP

Classes

  • Base
  • Collection
  • Lang
  • Metadata
  • Nova
  • PersistentObject
  • Service
  • ServiceCatalogItem
  • Overview
  • Namespace
  • Class
  • Tree
  • Download
  1: <?php
  2: /**
  3:  * @copyright 2012-2013 Rackspace Hosting, Inc.
  4:  * See COPYING for licensing information
  5:  * @package phpOpenCloud
  6:  * @version 1.0
  7:  * @author Glen Campbell <glen.campbell@rackspace.com>
  8:  * @author Jamie Hannaford <jamie.hannaford@rackspace.com>
  9:  */
 10: 
 11: namespace OpenCloud\Common;
 12: 
 13: use OpenCloud\Common\Lang;
 14: use OpenCloud\Common\Exceptions\AttributeError;
 15: use OpenCloud\Common\Exceptions\JsonError;
 16: use OpenCloud\Common\Exceptions\UrlError;
 17: 
 18: /**
 19:  * The root class for all other objects used or defined by this SDK.
 20:  *
 21:  * It contains common code for error handling as well as service functions that
 22:  * are useful. Because it is an abstract class, it cannot be called directly,
 23:  * and it has no publicly-visible properties.
 24:  */
 25: abstract class Base
 26: {
 27: 
 28:     private $http_headers = array();
 29:     private $_errors = array();
 30: 
 31:     /**
 32:      * Debug status.
 33:      *
 34:      * @var    LoggerInterface
 35:      * @access private
 36:      */
 37:     private $logger;
 38: 
 39:     /**
 40:      * Sets the Logger object.
 41:      * 
 42:      * @param \OpenCloud\Common\Log\LoggerInterface $logger
 43:      */
 44:     public function setLogger(Log\LoggerInterface $logger)
 45:     {
 46:         $this->logger = $logger;
 47:     }
 48: 
 49:     /**
 50:      * Returns the Logger object.
 51:      * 
 52:      * @return \OpenCloud\Common\Log\AbstractLogger
 53:      */
 54:     public function getLogger()
 55:     {
 56:         if (null === $this->logger) {
 57:             $this->setLogger(new Log\Logger);
 58:         }
 59:         return $this->logger;
 60:     }
 61: 
 62:     /**
 63:      * Returns the URL of the service/object
 64:      *
 65:      * The assumption is that nearly all objects will have a URL; at this
 66:      * base level, it simply throws an exception to enforce the idea that
 67:      * subclasses need to define this method.
 68:      *
 69:      * @throws UrlError
 70:      */
 71:     public function url($subresource = '')
 72:     {
 73:         throw new UrlError(Lang::translate(
 74:             'URL method must be overridden in class definition'
 75:         ));
 76:     }
 77: 
 78: /**
 79:      * Populates the current object based on an unknown data type.
 80:      * 
 81:      * @param  array|object|string|integer $info
 82:      * @throws Exceptions\InvalidArgumentError
 83:      */
 84:     public function populate($info, $setObjects = true)
 85:     {
 86:         if (is_string($info) || is_integer($info)) {
 87:             
 88:             // If the data type represents an ID, the primary key is set
 89:             // and we retrieve the full resource from the API
 90:             $this->{$this->primaryKeyField()} = (string) $info;
 91:             $this->refresh($info);
 92:             
 93:         } elseif (is_object($info) || is_array($info)) {
 94:             
 95:             foreach($info as $key => $value) {
 96:                 
 97:                 if ($key == 'metadata' || $key == 'meta') {
 98:                     
 99:                     if (empty($this->metadata) || !$this->metadata instanceof Metadata) {
100:                         $this->metadata = new Metadata;
101:                     }
102:                     
103:                     // Metadata
104:                     $this->$key->setArray($value);
105:                     
106:                 } elseif (!empty($this->associatedResources[$key]) && $setObjects === true) {
107:                     
108:                     // Associated resource
109:                     try {
110:                         $resource = $this->service()->resource($this->associatedResources[$key], $value);
111:                         $resource->setParent($this);
112:                         $this->$key = $resource;
113:                     } catch (Exception\ServiceException $e) {}
114:                     
115:                 } elseif (!empty($this->associatedCollections[$key]) && $setObjects === true) {
116:                     
117:                     // Associated collection
118:                     try {
119:                         $this->$key = $this->service()->resourceList($this->associatedCollections[$key], null, $this); 
120:                     } catch (Exception\ServiceException $e) {}
121:                     
122:                 } else {
123:                     
124:                     // Normal key/value pair
125:                     $this->$key = $value; 
126:                 }
127:             }
128:         } elseif (null !== $info) {
129:             throw new Exceptions\InvalidArgumentError(sprintf(
130:                 Lang::translate('Argument for [%s] must be string or object'), 
131:                 get_class()
132:             ));
133:         }
134:     }
135:     
136:     /**
137:      * Sets extended attributes on an object and validates them
138:      *
139:      * This function is provided to ensure that attributes cannot
140:      * arbitrarily added to an object. If this function is called, it
141:      * means that the attribute is not defined on the object, and thus
142:      * an exception is thrown.
143:      *
144:      * @codeCoverageIgnore
145:      * 
146:      * @param string $property the name of the attribute
147:      * @param mixed $value the value of the attribute
148:      * @return void
149:      */
150:     public function __set($property, $value)
151:     {
152:         $this->setProperty($property, $value);
153:     }
154: 
155:     /**
156:      * Sets an extended (unrecognized) property on the current object
157:      *
158:      * If RAXSDK_STRICT_PROPERTY_CHECKS is TRUE, then the prefix of the
159:      * property name must appear in the $prefixes array, or else an
160:      * exception is thrown.
161:      *
162:      * @param string $property the property name
163:      * @param mixed $value the value of the property
164:      * @param array $prefixes optional list of supported prefixes
165:      * @throws \OpenCloud\AttributeError if strict checks are on and
166:      *      the property prefix is not in the list of prefixes.
167:      */
168:     public function setProperty($property, $value, array $prefixes = array())
169:     {
170:         // if strict checks are off, go ahead and set it
171:         if (!RAXSDK_STRICT_PROPERTY_CHECKS 
172:             || $this->checkAttributePrefix($property, $prefixes)
173:         ) {
174:             $this->$property = $value;
175:         } else {
176:             // if that fails, then throw the exception
177:             throw new AttributeError(sprintf(
178:                 Lang::translate('Unrecognized attribute [%s] for [%s]'),
179:                 $property,
180:                 get_class($this)
181:             ));
182:         }
183:     }
184: 
185:     /**
186:      * Converts an array of key/value pairs into a single query string
187:      *
188:      * For example, array('A'=>1,'B'=>2) would become 'A=1&B=2'.
189:      *
190:      * @param array $arr array of key/value pairs
191:      * @return string
192:      */
193:     public function makeQueryString($array)
194:     {
195:         $queryString = '';
196: 
197:         foreach($array as $key => $value) {
198:             if ($queryString) {
199:                 $queryString .= '&';
200:             }
201:             $queryString .= urlencode($key) . '=' . urlencode($this->to_string($value));
202:         }
203: 
204:         return $queryString;
205:     }
206: 
207:     /**
208:      * Checks the most recent JSON operation for errors
209:      *
210:      * This function should be called after any `json_*()` function call.
211:      * This ensures that nasty JSON errors are detected and the proper
212:      * exception thrown.
213:      *
214:      * Example:
215:      *   `$obj = json_decode($string);`
216:      *   `if (check_json_error()) do something ...`
217:      *
218:      * @return boolean TRUE if an error occurred, FALSE if none
219:      * @throws JsonError
220:      * 
221:      * @codeCoverageIgnore
222:      */
223:     public function checkJsonError()
224:     {
225:         switch (json_last_error()) {
226:             case JSON_ERROR_NONE:
227:                 return;
228:             case JSON_ERROR_DEPTH:
229:                 $jsonError = 'JSON error: The maximum stack depth has been exceeded';
230:                 break;
231:             case JSON_ERROR_STATE_MISMATCH:
232:                 $jsonError = 'JSON error: Invalid or malformed JSON';
233:                 break;
234:             case JSON_ERROR_CTRL_CHAR:
235:                 $jsonError = 'JSON error: Control character error, possibly incorrectly encoded';
236:                 break;
237:             case JSON_ERROR_SYNTAX:
238:                 $jsonError = 'JSON error: Syntax error';
239:                 break;
240:             case JSON_ERROR_UTF8:
241:                 $jsonError = 'JSON error: Malformed UTF-8 characters, possibly incorrectly encoded';
242:                 break;
243:             default:
244:                 $jsonError = 'Unexpected JSON error';
245:                 break;
246:         }
247:         
248:         if (isset($jsonError)) {
249:             throw new JsonError(Lang::translate($jsonError));
250:         }
251:     }
252: 
253:     /**
254:      * Returns a class that implements the HttpRequest interface.
255:      *
256:      * This can be stubbed out for unit testing and avoid making live calls.
257:      */
258:     public function getHttpRequestObject($url, $method = 'GET', array $options = array())
259:     {
260:         return new Request\Curl($url, $method, $options);
261:     }
262: 
263:     /**
264:      * Checks the attribute $property and only permits it if the prefix is
265:      * in the specified $prefixes array
266:      *
267:      * This is to support extension namespaces in some services.
268:      *
269:      * @param string $property the name of the attribute
270:      * @param array $prefixes a list of prefixes
271:      * @return boolean TRUE if valid; FALSE if not
272:      */
273:     private function checkAttributePrefix($property, array $prefixes = array())
274:     {
275:         $prefix = strstr($property, ':', true);
276: 
277:         if (in_array($prefix, $prefixes)) {
278:             return true;
279:         } else {
280:             return false;
281:         }
282:     }
283: 
284:     /**
285:      * Converts a value to an HTTP-displayable string form
286:      *
287:      * @param mixed $x a value to convert
288:      * @return string
289:      */
290:     private function to_string($x)
291:     {
292:         if (is_bool($x) && $x) {
293:             return 'True';
294:         } elseif (is_bool($x)) {
295:             return 'False';
296:         } else {
297:             return (string) $x;
298:         }
299:     }
300: 
301: }
302: 
PHP OpenCloud API API documentation generated by ApiGen 2.8.0