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