1: <?php
2: 3: 4: 5: 6: 7: 8: 9:
10:
11: namespace OpenCloud\ObjectStore\Resource;
12:
13: use Guzzle\Http\EntityBody;
14: use Guzzle\Http\Message\Response;
15: use Guzzle\Http\Url;
16: use OpenCloud\Common\Lang;
17: use OpenCloud\Common\Exceptions;
18: use OpenCloud\ObjectStore\Constants\UrlType;
19:
20: 21: 22: 23: 24: 25: 26:
27: class DataObject extends AbstractResource
28: {
29: const METADATA_LABEL = 'Object';
30:
31: 32: 33:
34: private $container;
35:
36: 37: 38:
39: protected $name;
40:
41: 42: 43:
44: protected $content;
45:
46: 47: 48: 49:
50: protected $directory = false;
51:
52: 53: 54:
55: protected $contentType;
56:
57: 58: 59:
60: protected $contentLength;
61:
62: 63: 64:
65: protected $lastModified;
66:
67: 68: 69:
70: protected $etag;
71:
72: 73: 74: 75: 76: 77: 78:
79: public function __construct(Container $container, $data = null)
80: {
81: $this->setContainer($container);
82:
83: parent::__construct($container->getService());
84:
85:
86: if (!empty($data->subdir)) {
87: $this->setName($data->subdir)->setDirectory(true);
88: return;
89: }
90:
91: $this->populate($data);
92: }
93:
94: 95: 96: 97: 98:
99: public function populate($info, $setObjects = true)
100: {
101: parent::populate($info, $setObjects);
102:
103: if (isset($info->bytes)) {
104: $this->setContentLength($info->bytes);
105: }
106: if (isset($info->last_modified)) {
107: $this->setLastModified($info->last_modified);
108: }
109: if (isset($info->content_type)) {
110: $this->setContentType($info->content_type);
111: }
112: if (isset($info->hash)) {
113: $this->setEtag($info->hash);
114: }
115: }
116:
117: 118: 119: 120: 121: 122:
123: public function populateFromResponse(Response $response)
124: {
125: $this->content = $response->getBody();
126:
127: $headers = $response->getHeaders();
128:
129: return $this->setMetadata($headers, true)
130: ->setContentType((string) $headers['Content-type'])
131: ->setLastModified((string) $headers['Last-Modified'])
132: ->setContentLength((string) $headers['Content-Length'])
133: ->setEtag((string) $headers['ETag']);
134: }
135:
136: public function refresh()
137: {
138: $response = $this->getService()->getClient()
139: ->get($this->getUrl())
140: ->send();
141:
142: return $this->populateFromResponse($response);
143: }
144:
145: 146: 147: 148:
149: public function setContainer(Container $container)
150: {
151: $this->container = $container;
152: return $this;
153: }
154:
155: 156: 157:
158: public function getContainer()
159: {
160: return $this->container;
161: }
162:
163: 164: 165: 166:
167: public function setName($name)
168: {
169: $this->name = $name;
170: return $this;
171: }
172:
173: 174: 175:
176: public function getName()
177: {
178: return $this->name;
179: }
180:
181: 182: 183: 184:
185: public function setDirectory($directory)
186: {
187: $this->directory = $directory;
188: return $this;
189: }
190:
191: 192: 193:
194: public function getDirectory()
195: {
196: return $this->directory;
197: }
198:
199: 200: 201:
202: public function isDirectory()
203: {
204: return (bool) $this->directory;
205: }
206:
207: 208: 209: 210:
211: public function setContent($content)
212: {
213: $this->content = EntityBody::factory($content);
214: return $this;
215: }
216:
217: 218: 219:
220: public function getContent()
221: {
222: return $this->content;
223: }
224:
225: 226: 227: 228:
229: public function setContentType($contentType)
230: {
231: $this->contentType = $contentType;
232: return $this;
233: }
234:
235: 236: 237:
238: public function getContentType()
239: {
240: return $this->contentType ?: $this->content->getContentType();
241: }
242:
243: 244: 245: 246:
247: public function setContentLength($contentLength)
248: {
249: $this->contentLength = $contentLength;
250: return $this;
251: }
252:
253: 254: 255:
256: public function getContentLength()
257: {
258: return $this->contentLength ?: $this->content->getContentLength();
259: }
260:
261: 262: 263: 264:
265: public function setEtag($etag)
266: {
267: $this->etag = $etag;
268: return $this;
269: }
270:
271: 272: 273:
274: public function getEtag()
275: {
276: return $this->etag ?: $this->content->getContentMd5();
277: }
278:
279: public function setLastModified($lastModified)
280: {
281: $this->lastModified = $lastModified;
282: return $this;
283: }
284:
285: public function getLastModified()
286: {
287: return $this->lastModified;
288: }
289:
290: public function primaryKeyField()
291: {
292: return 'name';
293: }
294:
295: public function getUrl($path = null, array $params = array())
296: {
297: if (!$this->name) {
298: throw new Exceptions\NoNameError(Lang::translate('Object has no name'));
299: }
300:
301: return $this->container->getUrl($this->name);
302: }
303:
304: public function update($params = array())
305: {
306: return $this->container->uploadObject($this->name, $this->content, $this->metadata->toArray());
307: }
308:
309: 310: 311: 312:
313: public function copy($destination)
314: {
315: return $this->getService()
316: ->getClient()
317: ->createRequest('COPY', $this->getUrl(), array(
318: 'Destination' => (string) $destination
319: ))
320: ->send();
321: }
322:
323: public function delete($params = array())
324: {
325: return $this->getService()->getClient()->delete($this->getUrl())->send();
326: }
327:
328: 329: 330: 331: 332: 333: 334: 335: 336: 337: 338: 339:
340: public function getTemporaryUrl($expires, $method)
341: {
342: $method = strtoupper($method);
343: $expiry = time() + (int) $expires;
344:
345:
346: if ($method != 'GET' && $method != 'PUT') {
347: throw new Exceptions\InvalidArgumentError(sprintf(
348: 'Bad method [%s] for TempUrl; only GET or PUT supported',
349: $method
350: ));
351: }
352:
353:
354: if (!($secret = $this->getService()->getAccount()->getTempUrlSecret())) {
355: throw new Exceptions\ObjectError('Cannot produce temporary URL without an account secret.');
356: }
357:
358:
359: $url = $this->getUrl();
360: $urlPath = urldecode($url->getPath());
361: $body = sprintf("%s\n%d\n%s", $method, $expiry, $urlPath);
362: $hash = hash_hmac('sha1', $body, $secret);
363:
364: return sprintf('%s?temp_url_sig=%s&temp_url_expires=%d', $url, $hash, $expiry);
365: }
366:
367: 368: 369: 370: 371: 372:
373: public function purge($email = null)
374: {
375: if (!$cdn = $this->getContainer()->getCdn()) {
376: return false;
377: }
378:
379: $url = clone $cdn->getUrl();
380: $url->addPath($this->name);
381:
382: $headers = ($email !== null) ? array('X-Purge-Email' => $email) : array();
383:
384: return $this->getService()
385: ->getClient()
386: ->delete($url, $headers)
387: ->send();
388: }
389:
390: 391: 392: 393:
394: public function getPublicUrl($type = UrlType::CDN)
395: {
396: $cdn = $this->container->getCdn();
397:
398: switch ($type) {
399: case UrlType::CDN:
400: $uri = $cdn->getCdnUri();
401: break;
402: case UrlType::SSL:
403: $uri = $cdn->getCdnSslUri();
404: break;
405: case UrlType::STREAMING:
406: $uri = $cdn->getCdnStreamingUri();
407: break;
408: case UrlType::IOS_STREAMING:
409: $uri = $cdn->getIosStreamingUri();
410: break;
411: }
412:
413: return (isset($uri)) ? Url::factory($uri)->addPath($this->name) : false;
414: }
415:
416: }