Overview
  • Namespace
  • Class

Namespaces

  • OpenCloud
    • Autoscale
      • Resource
    • CloudMonitoring
      • Collection
      • 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
      • Collection
      • Enum
      • Resource
    • Networking
      • Resource
    • ObjectStore
      • Constants
      • Exception
      • Resource
      • Upload
    • Orchestration
      • Resource
    • Queues
      • Collection
      • Exception
      • Resource
    • Volume
      • Resource

Classes

  • OpenCloud\Volume\Resource\Snapshot
  • OpenCloud\Volume\Resource\Volume
  • OpenCloud\Volume\Resource\VolumeType
  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 
API documentation generated by ApiGen