      1: <?php
      2: /**
      3:  * Copyright 2012-2014 Rackspace US, Inc.
      4:  *
      5:  * Licensed under the Apache License, Version 2.0 (the "License");
      6:  * you may not use this file except in compliance with the License.
      7:  * You may obtain a copy of the License at
      8:  *
      9:  * http://www.apache.org/licenses/LICENSE-2.0
     10:  *
     11:  * Unless required by applicable law or agreed to in writing, software
     12:  * distributed under the License is distributed on an "AS IS" BASIS,
     13:  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14:  * See the License for the specific language governing permissions and
     15:  * limitations under the License.
     16:  */
     17:
     18: namespace OpenCloud\Common\Service;
     19:
     20: use Guzzle\Http\ClientInterface;
     21: use OpenCloud\Common\Base;
     22: use OpenCloud\Common\Collection\PaginatedIterator;
     23: use OpenCloud\Common\Exceptions;
     24:
     25: /**
     26:  * This class defines a cloud service; a relationship between a specific OpenStack
     27:  * and a provided service, represented by a URL in the service catalog.
     28:  *
     29:  * Because Service is an abstract class, it cannot be called directly. Provider
     30:  * services such as Rackspace Cloud Servers or OpenStack Swift are each
     31:  * subclassed from Service.
     32:  */
     33: abstract class AbstractService extends Base implements ServiceInterface
     34: {
     35:     /**
     36:      * @var \OpenCloud\Common\Http\Client The client which interacts with the API.
     37:      */
     38:     protected $client;
     39:
     40:     /**
     41:      * @var \OpenCloud\Common\Service\Endpoint The endpoint for this service.
     42:      */
     43:     protected $endpoint;
     44:
     45:     /**
     46:      * @var array A collection of resource models that this service has control over.
     47:      */
     48:     protected $resources = array();
     49:
     50:     /**
     51:      * @var array Namespaces for this service.
     52:      */
     53:     protected $namespaces = array();
     54:
     55:     /**
     56:      * @param ClientInterface $client
     57:      */
     58:     public function setClient(ClientInterface $client)
     59:     {
     60:         $this->client = $client;
     61:     }
     62:
     63:     /**
     64:      * @return \OpenCloud\Common\Http\Client
     65:      */
     66:     public function getClient()
     67:     {
     68:         return $this->client;
     69:     }
     70:
     71:     /**
     72:      * @param Endpoint $endpoint
     73:      */
     74:     public function setEndpoint($endpoint)
     75:     {
     76:         $this->endpoint = $endpoint;
     77:     }
     78:
     79:     /**
     80:      * @return \OpenCloud\Common\Service\Endpoint
     81:      */
     82:     public function getEndpoint()
     83:     {
     84:         return $this->endpoint;
     85:     }
     86:
     87:     /**
     88:      * Get all associated resources for this service.
     89:      *
     90:      * @access public
     91:      * @return array
     92:      */
     93:     public function getResources()
     94:     {
     95:         return $this->resources;
     96:     }
     97:
     98:     /**
     99:      * Internal method for accessing child namespace from parent scope.
    100:      *
    101:      * @return type
    102:      */
    103:     protected function getCurrentNamespace()
    104:     {
    105:         $namespace = get_class($this);
    106:
    107:         return substr($namespace, 0, strrpos($namespace, '\\'));
    108:     }
    109:
    110:     /**
    111:      * Resolves FQCN for local resource.
    112:      *
    113:      * @param  $resourceName
    114:      * @return string
    115:      * @throws \OpenCloud\Common\Exceptions\UnrecognizedServiceError
    116:      */
    117:     protected function resolveResourceClass($resourceName)
    118:     {
    119:         $className = substr_count($resourceName, '\\')
    120:             ? $resourceName
    121:             : $this->getCurrentNamespace() . '\\Resource\\' . ucfirst($resourceName);
    122:
    123:         if (!class_exists($className)) {
    124:             throw new Exceptions\UnrecognizedServiceError(sprintf(
    125:                 '%s resource does not exist, please try one of the following: %s',
    126:                 $resourceName,
    127:                 implode(', ', $this->getResources())
    128:             ));
    129:         }
    130:
    131:         return $className;
    132:     }
    133:
    134:     /**
    135:      * Factory method for instantiating resource objects.
    136:      *
    137:      * @param  string $resourceName
    138:      * @param  mixed  $info   (default: null)
    139:      * @param  mixed  $parent The parent object
    140:      * @return object
    141:      */
    142:     public function resource($resourceName, $info = null, $parent = null)
    143:     {
    144:         $className = $this->resolveResourceClass($resourceName);
    145:
    146:         $resource = new $className($this);
    147:
    148:         if ($parent) {
    149:             $resource->setParent($parent);
    150:         }
    151:
    152:         $resource->populate($info);
    153:
    154:         return $resource;
    155:     }
    156:
    157:     /**
    158:      * Factory method for instantiating a resource collection.
    159:      *
    160:      * @param string      $resourceName
    161:      * @param string|null $url
    162:      * @param string|null $parent
    163:      * @return PaginatedIterator
    164:      */
    165:     public function resourceList($resourceName, $url = null, $parent = null)
    166:     {
    167:         $className = $this->resolveResourceClass($resourceName);
    168:
    169:         return $this->collection($className, $url, $parent);
    170:     }
    171:
    172:     /**
    173:      * @codeCoverageIgnore
    174:      */
    175:     public function collection($class, $url = null, $parent = null, $data = null)
    176:     {
    177:         if (!$parent) {
    178:             $parent = $this;
    179:         }
    180:
    181:         if (!$url) {
    182:             $resource = $this->resolveResourceClass($class);
    183:             $url = $parent->getUrl($resource::resourceName());
    184:         }
    185:
    186:         $options = $this->makeResourceIteratorOptions($this->resolveResourceClass($class));
    187:         $options['baseUrl'] = $url;
    188:
    189:         return PaginatedIterator::factory($parent, $options, $data);
    190:     }
    191:
    192:     /**
    193:      * @deprecated
    194:      */
    195:     public function namespaces()
    196:     {
    197:         return $this->getNamespaces();
    198:     }
    199:
    200:     /**
    201:      * Returns a list of supported namespaces
    202:      *
    203:      * @return array
    204:      */
    205:     public function getNamespaces()
    206:     {
    207:         return (isset($this->namespaces) && is_array($this->namespaces))
    208:             ? $this->namespaces
    209:             : array();
    210:     }
    211: }
    212: