1: <?php
2: /**
3: * PHP OpenCloud library.
4: *
5: * @copyright Copyright 2013 Rackspace US, Inc. See COPYING for licensing information.
6: * @license https://www.apache.org/licenses/LICENSE-2.0 Apache 2.0
7: * @version 1.6.0
8: * @author Glen Campbell <glen.campbell@rackspace.com>
9: * @author Jamie Hannaford <jamie.hannaford@rackspace.com>
10: */
11:
12: namespace OpenCloud\ObjectStore\Resource;
13:
14: use OpenCloud\Common\Exceptions;
15: use OpenCloud\Common\Lang;
16:
17: /**
18: * A container is a storage compartment for your data and provides a way for you
19: * to organize your data. You can think of a container as a folder in Windows®
20: * or a directory in UNIX®. The primary difference between a container and these
21: * other file system concepts is that containers cannot be nested.
22: *
23: * A container can also be CDN-enabled (for public access), in which case you
24: * will need to interact with a CDNContainer object instead of this one.
25: */
26: class Container extends CDNContainer
27: {
28:
29: /**
30: * CDN container (if set).
31: *
32: * @var CDNContainer|null
33: */
34: private $cdn;
35:
36: /**
37: * Sets the CDN container.
38: *
39: * @param OpenCloud\ObjectStore\Resource\CDNContainer $cdn
40: */
41: public function setCDN(CDNContainer $cdn)
42: {
43: $this->cdn = $cdn;
44: }
45:
46: /**
47: * Returns the CDN container.
48: *
49: * @returns CDNContainer
50: */
51: public function getCDN()
52: {
53: if (!$this->cdn) {
54: throw new Exceptions\CdnNotAvailableError(
55: Lang::translate('CDN-enabled container is not available')
56: );
57: }
58:
59: return $this->cdn;
60: }
61:
62: /**
63: * Backwards compatability.
64: */
65: public function CDN()
66: {
67: return $this->getCDN();
68: }
69:
70: /**
71: * Makes the container public via the CDN
72: *
73: * @api
74: * @param integer $TTL the Time-To-Live for the CDN container; if NULL,
75: * then the cloud's default value will be used for caching.
76: * @throws CDNNotAvailableError if CDN services are not available
77: * @return CDNContainer
78: */
79: public function enableCDN($ttl = null)
80: {
81: $url = $this->getService()->CDN()->url() . '/' . rawurlencode($this->name);
82:
83: $headers = $this->metadataHeaders();
84:
85: if ($ttl) {
86:
87: // Make sure we're dealing with a real figure
88: if (!is_integer($ttl)) {
89: throw new Exceptions\CdnTtlError(sprintf(
90: Lang::translate('TTL value [%s] must be an integer'),
91: $ttl
92: ));
93: }
94:
95: $headers['X-TTL'] = $ttl;
96: }
97:
98: $headers['X-Log-Retention'] = 'True';
99: $headers['X-CDN-Enabled'] = 'True';
100:
101: // PUT to the CDN container
102: $response = $this->getService()->request($url, 'PUT', $headers);
103:
104: // check the response status
105: // @codeCoverageIgnoreStart
106: if ($response->httpStatus() > 202) {
107: throw new Exceptions\CdnHttpError(sprintf(
108: Lang::translate('HTTP error publishing to CDN, status [%d] response [%s]'),
109: $response->httpStatus(),
110: $response->httpBody()
111: ));
112: }
113: // @codeCoverageIgnoreEnd
114:
115: // refresh the data
116: $this->refresh();
117:
118: // return the CDN container object
119: $cdn = new CDNContainer($this->getService()->getCDNService(), $this->name);
120: $this->setCDN($cdn);
121:
122: return $cdn;
123: }
124:
125: /**
126: * Backwards compatability.
127: */
128: public function publishToCDN($ttl = null)
129: {
130: return $this->enableCDN($ttl);
131: }
132:
133: /**
134: * Disables the containers CDN function.
135: *
136: * Note that the container will still be available on the CDN until
137: * its TTL expires.
138: *
139: * @api
140: * @return void
141: */
142: public function disableCDN()
143: {
144: // Set necessary headers
145: $headers['X-Log-Retention'] = 'False';
146: $headers['X-CDN-Enabled'] = 'False';
147:
148: // PUT it to the CDN service
149: $response = $this->getService()->request($this->CDNURL(), 'PUT', $headers);
150:
151: // check the response status
152: // @codeCoverageIgnoreStart
153: if ($response->httpStatus() != 201) {
154: throw new Exceptions\CdnHttpError(sprintf(
155: Lang::translate('HTTP error disabling CDN, status [%d] response [%s]'),
156: $response->httpStatus(),
157: $response->httpBody()
158: ));
159: }
160: // @codeCoverageIgnoreEnd
161:
162: return true;
163: }
164:
165: /**
166: * Creates a static website from the container
167: *
168: * @api
169: * @link http://docs.rackspace.com/files/api/v1/cf-devguide/content/Create_Static_Website-dle4000.html
170: * @param string $index the index page (starting page) of the website
171: * @return \OpenCloud\HttpResponse
172: */
173: public function createStaticSite($indexHtml)
174: {
175: $headers = array('X-Container-Meta-Web-Index' => $indexHtml);
176: $response = $this->getService()->request($this->url(), 'POST', $headers);
177:
178: // check return code
179: // @codeCoverageIgnoreStart
180: if ($response->HttpStatus() > 204) {
181: throw new Exceptions\ContainerError(sprintf(
182: Lang::translate('Error creating static website for [%s], status [%d] response [%s]'),
183: $this->name,
184: $response->httpStatus(),
185: $response->httpBody()
186: ));
187: }
188: // @codeCoverageIgnoreEnd
189:
190: return $response;
191: }
192:
193: /**
194: * Sets the error page(s) for the static website
195: *
196: * @api
197: * @link http://docs.rackspace.com/files/api/v1/cf-devguide/content/Set_Error_Pages_for_Static_Website-dle4005.html
198: * @param string $name the name of the error page
199: * @return \OpenCloud\HttpResponse
200: */
201: public function staticSiteErrorPage($name)
202: {
203: $headers = array('X-Container-Meta-Web-Error' => $name);
204: $response = $this->getService()->request($this->url(), 'POST', $headers);
205:
206: // check return code
207: // @codeCoverageIgnoreStart
208: if ($response->httpStatus() > 204) {
209: throw new Exceptions\ContainerError(sprintf(
210: Lang::translate('Error creating static site error page for [%s], status [%d] response [%s]'),
211: $this->name,
212: $response->httpStatus(),
213: $response->httpBody()
214: ));
215: }
216:
217: return $response;
218: // @codeCoverageIgnoreEnd
219: }
220:
221: /**
222: * Returns the CDN URL of the container (if enabled)
223: *
224: * The CDNURL() is used to manage the container. Note that it is different
225: * from the PublicURL() of the container, which is the publicly-accessible
226: * URL on the network.
227: *
228: * @api
229: * @return string
230: */
231: public function CDNURL()
232: {
233: return $this->getCDN()->url();
234: }
235:
236: /**
237: * Returns the Public URL of the container (on the CDN network)
238: *
239: */
240: public function publicURL()
241: {
242: return $this->CDNURI();
243: }
244:
245: /**
246: * Returns the CDN info about the container
247: *
248: * @api
249: * @return stdClass
250: */
251: public function CDNinfo($property = null)
252: {
253: // Not quite sure why this is here...
254: // @codeCoverageIgnoreStart
255: if ($this->getService() instanceof CDNService) {
256: return $this->metadata;
257: }
258: // @codeCoverageIgnoreEnd
259:
260: // return NULL if the CDN container is not enabled
261: if (!isset($this->getCDN()->metadata->Enabled)
262: || $this->getCDN()->metadata->Enabled == 'False'
263: ) {
264: return null;
265: }
266:
267: // check to see if it's set
268: if (isset($this->getCDN()->metadata->$property)) {
269: return trim($this->getCDN()->metadata->$property);
270: } elseif ($property !== null) {
271: return null;
272: }
273:
274: // otherwise, return the whole metadata object
275: return $this->getCDN()->metadata;
276: }
277:
278: /**
279: * Returns the CDN container URI prefix
280: *
281: * @api
282: * @return string
283: */
284: public function CDNURI()
285: {
286: return $this->CDNinfo('Uri');
287: }
288:
289: /**
290: * Returns the SSL URI for the container
291: *
292: * @api
293: * @return string
294: */
295: public function SSLURI()
296: {
297: return $this->CDNinfo('Ssl-Uri');
298: }
299:
300: /**
301: * Returns the streaming URI for the container
302: *
303: * @api
304: * @return string
305: */
306: public function streamingURI()
307: {
308: return $this->CDNinfo('Streaming-Uri');
309: }
310:
311: /**
312: * Returns the IOS streaming URI for the container
313: *
314: * @api
315: * @link http://docs.rackspace.com/files/api/v1/cf-devguide/content/iOS-Streaming-d1f3725.html
316: * @return string
317: */
318: public function iosStreamingURI()
319: {
320: return $this->CDNinfo('Ios-Uri');
321: }
322:
323: /**
324: * Creates a Collection of objects in the container
325: *
326: * @param array $params associative array of parameter values.
327: * * account/tenant - The unique identifier of the account/tenant.
328: * * container- The unique identifier of the container.
329: * * limit (Optional) - The number limit of results.
330: * * marker (Optional) - Value of the marker, that the object names
331: * greater in value than are returned.
332: * * end_marker (Optional) - Value of the marker, that the object names
333: * less in value than are returned.
334: * * prefix (Optional) - Value of the prefix, which the returned object
335: * names begin with.
336: * * format (Optional) - Value of the serialized response format, either
337: * json or xml.
338: * * delimiter (Optional) - Value of the delimiter, that all the object
339: * names nested in the container are returned.
340: * @link http://api.openstack.org for a list of possible parameter
341: * names and values
342: * @return OpenCloud\Collection
343: * @throws ObjFetchError
344: */
345: public function objectList($params = array())
346: {
347: // construct a query string out of the parameters
348: $params['format'] = 'json';
349:
350: $queryString = $this->makeQueryString($params);
351:
352: // append the query string to the URL
353: $url = $this->url();
354: if (strlen($queryString) > 0) {
355: $url .= '?' . $queryString;
356: }
357:
358: return $this->getService()->collection(
359: 'OpenCloud\ObjectStore\Resource\DataObject', $url, $this
360: );
361: }
362:
363: /**
364: * Returns a new DataObject associated with this container
365: *
366: * @param string $name if supplied, the name of the object to return
367: * @return DataObject
368: */
369: public function dataObject($name = null)
370: {
371: return new DataObject($this, $name);
372: }
373:
374: /**
375: * Refreshes, then associates the CDN container
376: */
377: public function refresh($id = null, $url = null)
378: {
379: parent::refresh($id, $url);
380:
381: // @codeCoverageIgnoreStart
382: if ($this->getService() instanceof CDNService) {
383: return;
384: }
385:
386:
387: if (null !== ($cdn = $this->getService()->CDN())) {
388: try {
389: $this->cdn = new CDNContainer(
390: $cdn,
391: $this->name
392: );
393: } catch (Exceptions\ContainerNotFoundError $e) {
394: $this->cdn = new CDNContainer($cdn);
395: $this->cdn->name = $this->name;
396: }
397: }
398: // @codeCoverageIgnoreEnd
399: }
400:
401: }
402: