Overview

Namespaces

  • OpenCloud
    • Autoscale
      • Resource
    • CloudMonitoring
      • Exception
      • Resource
    • Common
      • Collection
      • Constants
      • Exceptions
      • Http
        • Message
      • Log
      • Resource
      • Service
    • Compute
      • Constants
      • Exception
      • Resource
    • Database
      • Resource
    • DNS
      • Collection
      • Resource
    • Identity
      • Constants
      • Resource
    • Image
      • Enum
      • Resource
        • JsonPatch
        • Schema
    • LoadBalancer
      • Enum
      • Resource
    • ObjectStore
      • Constants
      • Exception
      • Resource
      • Upload
    • Orchestration
    • Queues
      • Exception
      • Resource
    • Volume
      • Resource
  • PHP

Classes

  • AbstractContainer
  • AbstractResource
  • Account
  • CDNContainer
  • Container
  • ContainerMetadata
  • DataObject
  • Overview
  • Namespace
  • Class
  • Tree
  • Download
  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\ObjectStore\Resource;
 19: 
 20: use Guzzle\Http\EntityBody;
 21: use Guzzle\Http\Message\Response;
 22: use Guzzle\Http\Url;
 23: use OpenCloud\Common\Constants\Header as HeaderConst;
 24: use OpenCloud\Common\Exceptions;
 25: use OpenCloud\Common\Lang;
 26: use OpenCloud\ObjectStore\Constants\UrlType;
 27: 
 28: /**
 29:  * Objects are the basic storage entities in Cloud Files. They represent the
 30:  * files and their optional metadata you upload to the system. When you upload
 31:  * objects to Cloud Files, the data is stored as-is (without compression or
 32:  * encryption) and consists of a location (container), the object's name, and
 33:  * any metadata you assign consisting of key/value pairs.
 34:  */
 35: class DataObject extends AbstractResource
 36: {
 37:     const METADATA_LABEL = 'Object';
 38: 
 39:     /**
 40:      * @var Container
 41:      */
 42:     private $container;
 43: 
 44:     /**
 45:      * @var The file name of the object
 46:      */
 47:     protected $name;
 48: 
 49:     /**
 50:      * @var EntityBody
 51:      */
 52:     protected $content;
 53: 
 54:     /**
 55:      * @var bool Whether or not this object is a "pseudo-directory"
 56:      * @link http://docs.openstack.org/trunk/openstack-object-storage/developer/content/pseudo-hierarchical-folders-directories.html
 57:      */
 58:     protected $directory = false;
 59: 
 60:     /**
 61:      * @var string The object's content type
 62:      */
 63:     protected $contentType;
 64: 
 65:     /**
 66:      * @var The size of this object.
 67:      */
 68:     protected $contentLength;
 69: 
 70:     /**
 71:      * @var string Date of last modification.
 72:      */
 73:     protected $lastModified;
 74: 
 75:     /**
 76:      * @var string Etag.
 77:      */
 78:     protected $etag;
 79: 
 80:     /**
 81:      * Also need to set Container parent and handle pseudo-directories.
 82:      * {@inheritDoc}
 83:      *
 84:      * @param Container $container
 85:      * @param null      $data
 86:      */
 87:     public function __construct(Container $container, $data = null)
 88:     {
 89:         $this->setContainer($container);
 90: 
 91:         parent::__construct($container->getService());
 92: 
 93:         // For pseudo-directories, we need to ensure the name is set
 94:         if (!empty($data->subdir)) {
 95:             $this->setName($data->subdir)->setDirectory(true);
 96: 
 97:             return;
 98:         }
 99: 
100:         $this->populate($data);
101:     }
102: 
103:     /**
104:      * A collection list of DataObjects contains a different data structure than the one returned for the
105:      * "Retrieve Object" operation. So we need to stock the values differently.
106:      * {@inheritDoc}
107:      */
108:     public function populate($info, $setObjects = true)
109:     {
110:         parent::populate($info, $setObjects);
111: 
112:         if (isset($info->bytes)) {
113:             $this->setContentLength($info->bytes);
114:         }
115:         if (isset($info->last_modified)) {
116:             $this->setLastModified($info->last_modified);
117:         }
118:         if (isset($info->content_type)) {
119:             $this->setContentType($info->content_type);
120:         }
121:         if (isset($info->hash)) {
122:             $this->setEtag($info->hash);
123:         }
124:     }
125: 
126:     /**
127:      * Takes a response and stocks common values from both the body and the headers.
128:      *
129:      * @param Response $response
130:      * @return $this
131:      */
132:     public function populateFromResponse(Response $response)
133:     {
134:         $this->content = $response->getBody();
135: 
136:         $headers = $response->getHeaders();
137: 
138:         return $this->setMetadata($headers, true)
139:             ->setContentType((string) $headers[HeaderConst::CONTENT_TYPE])
140:             ->setLastModified((string) $headers[HeaderConst::LAST_MODIFIED])
141:             ->setContentLength((string) $headers[HeaderConst::CONTENT_LENGTH])
142:             ->setEtag((string) $headers[HeaderConst::ETAG]);
143:     }
144: 
145:     public function refresh()
146:     {
147:         $response = $this->getService()->getClient()
148:             ->get($this->getUrl())
149:             ->send();
150: 
151:         return $this->populateFromResponse($response);
152:     }
153: 
154:     /**
155:      * @param Container $container
156:      * @return $this
157:      */
158:     public function setContainer(Container $container)
159:     {
160:         $this->container = $container;
161: 
162:         return $this;
163:     }
164: 
165:     /**
166:      * @return Container
167:      */
168:     public function getContainer()
169:     {
170:         return $this->container;
171:     }
172: 
173:     /**
174:      * @param $name string
175:      * @return $this
176:      */
177:     public function setName($name)
178:     {
179:         $this->name = $name;
180: 
181:         return $this;
182:     }
183: 
184:     /**
185:      * @return string
186:      */
187:     public function getName()
188:     {
189:         return $this->name;
190:     }
191: 
192:     /**
193:      * @param $directory bool
194:      * @return $this
195:      */
196:     public function setDirectory($directory)
197:     {
198:         $this->directory = $directory;
199: 
200:         return $this;
201:     }
202: 
203:     /**
204:      * @return bool
205:      */
206:     public function getDirectory()
207:     {
208:         return $this->directory;
209:     }
210: 
211:     /**
212:      * @return bool Is this data object a pseudo-directory?
213:      */
214:     public function isDirectory()
215:     {
216:         return (bool) $this->directory;
217:     }
218: 
219:     /**
220:      * @param  mixed $content
221:      * @return $this
222:      */
223:     public function setContent($content)
224:     {
225:         $this->etag = null;
226:         $this->contentType = null;
227:         $this->content = EntityBody::factory($content);
228: 
229:         return $this;
230:     }
231: 
232:     /**
233:      * @return EntityBody
234:      */
235:     public function getContent()
236:     {
237:         return $this->content;
238:     }
239: 
240:     /**
241:      * @param  string $contentType
242:      * @return $this
243:      */
244:     public function setContentType($contentType)
245:     {
246:         $this->contentType = $contentType;
247: 
248:         return $this;
249:     }
250: 
251:     /**
252:      * @return null|string
253:      */
254:     public function getContentType()
255:     {
256:         return $this->contentType ? : $this->content->getContentType();
257:     }
258: 
259:     /**
260:      * @param $contentType int
261:      * @return $this
262:      */
263:     public function setContentLength($contentLength)
264:     {
265:         $this->contentLength = $contentLength;
266: 
267:         return $this;
268:     }
269: 
270:     /**
271:      * @return int
272:      */
273:     public function getContentLength()
274:     {
275:         return $this->contentLength !== null ? $this->contentLength : $this->content->getContentLength();
276:     }
277: 
278:     /**
279:      * @param $etag
280:      * @return $this
281:      */
282:     public function setEtag($etag)
283:     {
284:         $this->etag = $etag;
285: 
286:         return $this;
287:     }
288: 
289:     /**
290:      * @return null|string
291:      */
292:     public function getEtag()
293:     {
294:         return $this->etag ? : $this->content->getContentMd5();
295:     }
296: 
297:     public function setLastModified($lastModified)
298:     {
299:         $this->lastModified = $lastModified;
300: 
301:         return $this;
302:     }
303: 
304:     public function getLastModified()
305:     {
306:         return $this->lastModified;
307:     }
308: 
309:     public function primaryKeyField()
310:     {
311:         return 'name';
312:     }
313: 
314:     public function getUrl($path = null, array $params = array())
315:     {
316:         if (!$this->name) {
317:             throw new Exceptions\NoNameError(Lang::translate('Object has no name'));
318:         }
319: 
320:         return $this->container->getUrl($this->name);
321:     }
322: 
323:     public function update($params = array())
324:     {
325:         $metadata = is_array($this->metadata) ? $this->metadata : $this->metadata->toArray();
326:         $metadata = self::stockHeaders($metadata);
327: 
328:         // merge specific properties with metadata
329:         $metadata += array(
330:             HeaderConst::CONTENT_TYPE   => $this->contentType,
331:             HeaderConst::LAST_MODIFIED  => $this->lastModified,
332:             HeaderConst::CONTENT_LENGTH => $this->contentLength,
333:             HeaderConst::ETAG           => $this->etag
334:         );
335: 
336:         return $this->container->uploadObject($this->name, $this->content, $metadata);
337:     }
338: 
339:     /**
340:      * @param string $destination Path (`container/object') of new object
341:      * @return \Guzzle\Http\Message\Response
342:      */
343:     public function copy($destination)
344:     {
345:         return $this->getService()
346:             ->getClient()
347:             ->createRequest('COPY', $this->getUrl(), array(
348:                 'Destination' => (string) $destination
349:             ))
350:             ->send();
351:     }
352: 
353:     public function delete($params = array())
354:     {
355:         return $this->getService()->getClient()->delete($this->getUrl())->send();
356:     }
357: 
358:     /**
359:      * Get a temporary URL for this object.
360:      *
361:      * @link http://docs.rackspace.com/files/api/v1/cf-devguide/content/TempURL-d1a4450.html
362:      *
363:      * @param $expires Expiration time in seconds
364:      * @param $method  What method can use this URL? (`GET' or `PUT')
365:      * @return string
366:      * @throws \OpenCloud\Common\Exceptions\InvalidArgumentError
367:      * @throws \OpenCloud\Common\Exceptions\ObjectError
368:      *
369:      */
370:     public function getTemporaryUrl($expires, $method)
371:     {
372:         $method = strtoupper($method);
373:         $expiry = time() + (int) $expires;
374: 
375:         // check for proper method
376:         if ($method != 'GET' && $method != 'PUT') {
377:             throw new Exceptions\InvalidArgumentError(sprintf(
378:                 'Bad method [%s] for TempUrl; only GET or PUT supported',
379:                 $method
380:             ));
381:         }
382: 
383:         // @codeCoverageIgnoreStart
384:         if (!($secret = $this->getService()->getAccount()->getTempUrlSecret())) {
385:             throw new Exceptions\ObjectError('Cannot produce temporary URL without an account secret.');
386:         }
387:         // @codeCoverageIgnoreEnd
388: 
389:         $url = $this->getUrl();
390:         $urlPath = urldecode($url->getPath());
391:         $body = sprintf("%s\n%d\n%s", $method, $expiry, $urlPath);
392:         $hash = hash_hmac('sha1', $body, $secret);
393: 
394:         return sprintf('%s?temp_url_sig=%s&temp_url_expires=%d', $url, $hash, $expiry);
395:     }
396: 
397:     /**
398:      * Remove this object from the CDN.
399:      *
400:      * @param null $email
401:      * @return mixed
402:      */
403:     public function purge($email = null)
404:     {
405:         if (!$cdn = $this->getContainer()->getCdn()) {
406:             return false;
407:         }
408: 
409:         $url = clone $cdn->getUrl();
410:         $url->addPath($this->name);
411: 
412:         $headers = ($email !== null) ? array('X-Purge-Email' => $email) : array();
413: 
414:         return $this->getService()
415:             ->getClient()
416:             ->delete($url, $headers)
417:             ->send();
418:     }
419: 
420:     /**
421:      * @param string $type
422:      * @return bool|Url
423:      */
424:     public function getPublicUrl($type = UrlType::CDN)
425:     {
426:         $cdn = $this->container->getCdn();
427: 
428:         switch ($type) {
429:             case UrlType::CDN:
430:                 $uri = $cdn->getCdnUri();
431:                 break;
432:             case UrlType::SSL:
433:                 $uri = $cdn->getCdnSslUri();
434:                 break;
435:             case UrlType::STREAMING:
436:                 $uri = $cdn->getCdnStreamingUri();
437:                 break;
438:             case UrlType::IOS_STREAMING:
439:                 $uri = $cdn->getIosStreamingUri();
440:                 break;
441:         }
442: 
443:         return (isset($uri)) ? Url::factory($uri)->addPath($this->name) : false;
444:     }
445: 
446:     protected static function headerIsValidMetadata($header)
447:     {
448:         $pattern = sprintf('#^%s-%s-Meta-#i', self::GLOBAL_METADATA_PREFIX, self::METADATA_LABEL);
449: 
450:         return preg_match($pattern, $header);
451:     }
452: }
453: 
PHP OpenCloud API API documentation generated by ApiGen 2.8.0