1: <?php
2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16:
17:
18: namespace OpenCloud\Common\Service;
19:
20: use Guzzle\Http\ClientInterface;
21: use Guzzle\Http\Exception\BadResponseException;
22: use Guzzle\Http\Url;
23: use OpenCloud\Common\Exceptions;
24: use OpenCloud\Common\Http\Message\Formatter;
25: use Symfony\Component\EventDispatcher\EventSubscriberInterface;
26:
27: abstract class CatalogService extends AbstractService
28: {
29: const DEFAULT_URL_TYPE = 'publicURL';
30:
31: 32: 33:
34: private $type;
35:
36: 37: 38:
39: private $name;
40:
41: 42: 43:
44: private $region;
45:
46: 47: 48:
49: private $urlType;
50:
51: 52: 53: 54:
55: protected $regionless = false;
56:
57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70:
71: public function __construct(ClientInterface $client, $type = null, $name = null, $region = null, $urlType = null)
72: {
73: $this->setClient($client);
74:
75: $this->name = $name ? : static::DEFAULT_NAME;
76: $this->region = $region;
77:
78: $this->region = $region;
79: if ($this->regionless !== true && !$this->region) {
80: throw new Exceptions\ServiceException(sprintf(
81: 'The %s service must have a region set. You can either pass in a region string as an argument param, or'
82: . ' set a default region for your user account by executing User::setDefaultRegion and ::update().',
83: $this->name
84: ));
85: }
86:
87: $this->type = $type ? : static::DEFAULT_TYPE;
88: $this->urlType = $urlType ? : static::DEFAULT_URL_TYPE;
89: $this->setEndpoint($this->findEndpoint());
90:
91: $this->client->setBaseUrl($this->getBaseUrl());
92:
93: if ($this instanceof EventSubscriberInterface) {
94: $this->client->getEventDispatcher()->addSubscriber($this);
95: }
96: }
97:
98: 99: 100:
101: public function getType()
102: {
103: return $this->type;
104: }
105:
106: 107: 108:
109: public function getRegion()
110: {
111: return $this->region;
112: }
113:
114: 115: 116:
117: public function getName()
118: {
119: return $this->name;
120: }
121:
122: 123: 124:
125: public function getUrlType()
126: {
127: return $this->urlType;
128: }
129:
130: 131: 132:
133: public function region()
134: {
135: return $this->getRegion();
136: }
137:
138: 139: 140:
141: public function name()
142: {
143: return $this->name;
144: }
145:
146: 147: 148: 149: 150: 151: 152:
153: public function getUrl($path = null, array $query = array())
154: {
155: return Url::factory($this->getBaseUrl())
156: ->addPath($path)
157: ->setQuery($query);
158: }
159:
160: 161: 162:
163: public function url($path = null, array $query = array())
164: {
165: return $this->getUrl($path, $query);
166: }
167:
168: 169: 170: 171: 172: 173:
174: public function getExtensions()
175: {
176: $ext = $this->getMetaUrl('extensions');
177:
178: return (is_object($ext) && isset($ext->extensions)) ? $ext->extensions : array();
179: }
180:
181: 182: 183: 184: 185:
186: public function limits()
187: {
188: $limits = $this->getMetaUrl('limits');
189:
190: return (is_object($limits)) ? $limits->limits : array();
191: }
192:
193: 194: 195: 196: 197: 198: 199:
200: private function findEndpoint()
201: {
202: if (!$this->getClient()->getCatalog()) {
203: $this->getClient()->authenticate();
204: }
205:
206: $catalog = $this->getClient()->getCatalog();
207:
208:
209: foreach ($catalog->getItems() as $service) {
210: if ($service->hasType($this->type) && $service->hasName($this->name)) {
211: return Endpoint::factory($service->getEndpointFromRegion($this->region));
212: }
213: }
214:
215: throw new Exceptions\EndpointError(sprintf(
216: 'No endpoints for service type [%s], name [%s], region [%s] and urlType [%s]',
217: $this->type,
218: $this->name,
219: $this->region,
220: $this->urlType
221: ));
222: }
223:
224: 225: 226: 227: 228: 229: 230: 231: 232: 233:
234: private function getMetaUrl($resource)
235: {
236: $url = clone $this->getBaseUrl();
237: $url->addPath($resource);
238: try {
239: $response = $this->getClient()->get($url)->send();
240:
241: return Formatter::decode($response);
242: } catch (BadResponseException $e) {
243:
244: return array();
245:
246: }
247: }
248:
249: 250: 251: 252: 253:
254: public function getBaseUrl()
255: {
256: $url = ($this->urlType == 'publicURL')
257: ? $this->endpoint->getPublicUrl()
258: : $this->endpoint->getPrivateUrl();
259:
260: if ($url === null) {
261: throw new Exceptions\ServiceException(sprintf(
262: 'The base %s could not be found. Perhaps the service '
263: . 'you are using requires a different URL type, or does '
264: . 'not support this region.',
265: $this->urlType
266: ));
267: }
268:
269: return $url;
270: }
271: }
272: