13 * to license@zend.com so we can send you a copy immediately. |
13 * to license@zend.com so we can send you a copy immediately. |
14 * |
14 * |
15 * @category Zend |
15 * @category Zend |
16 * @package Zend_Service_WindowsAzure |
16 * @package Zend_Service_WindowsAzure |
17 * @subpackage Storage |
17 * @subpackage Storage |
18 * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) |
18 * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) |
19 * @license http://framework.zend.com/license/new-bsd New BSD License |
19 * @license http://framework.zend.com/license/new-bsd New BSD License |
20 * @version $Id: Table.php 23170 2010-10-19 18:29:24Z mabe $ |
20 * @version $Id: Table.php 24697 2012-03-23 13:11:04Z ezimuel $ |
21 */ |
21 */ |
22 |
|
23 /** |
|
24 * @see Zend_Service_WindowsAzure_Credentials_CredentialsAbstract |
|
25 */ |
|
26 require_once 'Zend/Service/WindowsAzure/Credentials/CredentialsAbstract.php'; |
|
27 |
|
28 /** |
|
29 * @see Zend_Service_WindowsAzure_Credentials_SharedKey |
|
30 */ |
|
31 require_once 'Zend/Service/WindowsAzure/Credentials/SharedKey.php'; |
|
32 |
|
33 /** |
|
34 * @see Zend_Service_WindowsAzure_Credentials_SharedKeyLite |
|
35 */ |
|
36 require_once 'Zend/Service/WindowsAzure/Credentials/SharedKeyLite.php'; |
|
37 |
|
38 /** |
|
39 * @see Zend_Service_WindowsAzure_RetryPolicy_RetryPolicyAbstract |
|
40 */ |
|
41 require_once 'Zend/Service/WindowsAzure/RetryPolicy/RetryPolicyAbstract.php'; |
|
42 |
|
43 /** |
|
44 * @see Zend_Http_Client |
|
45 */ |
|
46 require_once 'Zend/Http/Client.php'; |
|
47 |
|
48 /** |
|
49 * @see Zend_Http_Response |
|
50 */ |
|
51 require_once 'Zend/Http/Response.php'; |
|
52 |
|
53 /** |
|
54 * @see Zend_Service_WindowsAzure_Storage |
|
55 */ |
|
56 require_once 'Zend/Service/WindowsAzure/Storage.php'; |
|
57 |
22 |
58 /** |
23 /** |
59 * @see Zend_Service_WindowsAzure_Storage_BatchStorageAbstract |
24 * @see Zend_Service_WindowsAzure_Storage_BatchStorageAbstract |
60 */ |
25 */ |
61 require_once 'Zend/Service/WindowsAzure/Storage/BatchStorageAbstract.php'; |
26 require_once 'Zend/Service/WindowsAzure/Storage/BatchStorageAbstract.php'; |
64 * @see Zend_Service_WindowsAzure_Storage_TableInstance |
29 * @see Zend_Service_WindowsAzure_Storage_TableInstance |
65 */ |
30 */ |
66 require_once 'Zend/Service/WindowsAzure/Storage/TableInstance.php'; |
31 require_once 'Zend/Service/WindowsAzure/Storage/TableInstance.php'; |
67 |
32 |
68 /** |
33 /** |
69 * @see Zend_Service_WindowsAzure_Storage_TableEntity |
34 * @see Zend_Service_WindowsAzure_Storage_TableEntityQuery |
70 */ |
35 */ |
71 require_once 'Zend/Service/WindowsAzure/Storage/TableEntity.php'; |
36 require_once 'Zend/Service/WindowsAzure/Storage/TableEntityQuery.php'; |
72 |
37 |
73 /** |
38 /** |
74 * @see Zend_Service_WindowsAzure_Storage_DynamicTableEntity |
39 * @see Zend_Service_WindowsAzure_Storage_DynamicTableEntity |
75 */ |
40 */ |
76 require_once 'Zend/Service/WindowsAzure/Storage/DynamicTableEntity.php'; |
41 require_once 'Zend/Service/WindowsAzure/Storage/DynamicTableEntity.php'; |
77 |
42 |
78 /** |
43 /** |
79 * @see Zend_Service_WindowsAzure_Storage_TableEntityQuery |
44 * @see Zend_Service_WindowsAzure_Credentials_SharedKeyLite |
80 */ |
45 */ |
81 require_once 'Zend/Service/WindowsAzure/Storage/TableEntityQuery.php'; |
46 require_once 'Zend/Service/WindowsAzure/Credentials/SharedKeyLite.php'; |
82 |
|
83 /** |
|
84 * @see Zend_Service_WindowsAzure_Exception |
|
85 */ |
|
86 require_once 'Zend/Service/WindowsAzure/Exception.php'; |
|
87 |
|
88 |
47 |
89 /** |
48 /** |
90 * @category Zend |
49 * @category Zend |
91 * @package Zend_Service_WindowsAzure |
50 * @package Zend_Service_WindowsAzure |
92 * @subpackage Storage |
51 * @subpackage Storage |
93 * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) |
52 * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) |
94 * @license http://framework.zend.com/license/new-bsd New BSD License |
53 * @license http://framework.zend.com/license/new-bsd New BSD License |
95 */ |
54 */ |
96 class Zend_Service_WindowsAzure_Storage_Table |
55 class Zend_Service_WindowsAzure_Storage_Table |
97 extends Zend_Service_WindowsAzure_Storage_BatchStorageAbstract |
56 extends Zend_Service_WindowsAzure_Storage_BatchStorageAbstract |
98 { |
57 { |
|
58 /** |
|
59 * Throw Zend_Service_WindowsAzure_Exception when a property is not specified in Windows Azure? |
|
60 * Defaults to true, making behaviour similar to Windows Azure StorageClient in .NET. |
|
61 * |
|
62 * @var boolean |
|
63 */ |
|
64 protected $_throwExceptionOnMissingData = true; |
|
65 |
|
66 /** |
|
67 * Throw Zend_Service_WindowsAzure_Exception when a property is not specified in Windows Azure? |
|
68 * Defaults to true, making behaviour similar to Windows Azure StorageClient in .NET. |
|
69 * |
|
70 * @param boolean $value |
|
71 */ |
|
72 public function setThrowExceptionOnMissingData($value = true) |
|
73 { |
|
74 $this->_throwExceptionOnMissingData = $value; |
|
75 } |
|
76 |
|
77 /** |
|
78 * Throw Zend_Service_WindowsAzure_Exception when a property is not specified in Windows Azure? |
|
79 */ |
|
80 public function getThrowExceptionOnMissingData() |
|
81 { |
|
82 return $this->_throwExceptionOnMissingData; |
|
83 } |
|
84 |
99 /** |
85 /** |
100 * Creates a new Zend_Service_WindowsAzure_Storage_Table instance |
86 * Creates a new Zend_Service_WindowsAzure_Storage_Table instance |
101 * |
87 * |
102 * @param string $host Storage host name |
88 * @param string $host Storage host name |
103 * @param string $accountName Account name for Windows Azure |
89 * @param string $accountName Account name for Windows Azure |
249 $entry = $this->_parseResponse($response); |
237 $entry = $this->_parseResponse($response); |
250 |
238 |
251 $tableName = $entry->xpath('.//m:properties/d:TableName'); |
239 $tableName = $entry->xpath('.//m:properties/d:TableName'); |
252 $tableName = (string)$tableName[0]; |
240 $tableName = (string)$tableName[0]; |
253 |
241 |
|
242 |
254 return new Zend_Service_WindowsAzure_Storage_TableInstance( |
243 return new Zend_Service_WindowsAzure_Storage_TableInstance( |
255 (string)$entry->id, |
244 (string)$entry->id, |
256 $tableName, |
245 $tableName, |
257 (string)$entry->link['href'], |
246 (string)$entry->link['href'], |
258 (string)$entry->updated |
247 (string)$entry->updated |
259 ); |
248 ); |
260 } else { |
249 } else { |
261 throw new Zend_Service_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.')); |
250 require_once 'Zend/Service/WindowsAzure/Exception.php'; |
|
251 throw new Zend_Service_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.')); |
|
252 } |
|
253 } |
|
254 |
|
255 /** |
|
256 * Create table if it does not exist |
|
257 * |
|
258 * @param string $tableName Table name |
|
259 * @throws Zend_Service_WindowsAzure_Exception |
|
260 */ |
|
261 public function createTableIfNotExists($tableName = '') |
|
262 { |
|
263 if (!$this->tableExists($tableName)) { |
|
264 $this->createTable($tableName); |
262 } |
265 } |
263 } |
266 } |
264 |
267 |
265 /** |
268 /** |
266 * Delete table |
269 * Delete table |
269 * @throws Zend_Service_WindowsAzure_Exception |
272 * @throws Zend_Service_WindowsAzure_Exception |
270 */ |
273 */ |
271 public function deleteTable($tableName = '') |
274 public function deleteTable($tableName = '') |
272 { |
275 { |
273 if ($tableName === '') { |
276 if ($tableName === '') { |
|
277 require_once 'Zend/Service/WindowsAzure/Exception.php'; |
274 throw new Zend_Service_WindowsAzure_Exception('Table name is not specified.'); |
278 throw new Zend_Service_WindowsAzure_Exception('Table name is not specified.'); |
275 } |
279 } |
276 |
280 |
277 // Add header information |
281 // Add header information |
278 $headers = array(); |
282 $headers = array(); |
279 $headers['Content-Type'] = 'application/atom+xml'; |
283 $headers['Content-Type'] = 'application/atom+xml'; |
280 |
284 |
281 // Perform request |
285 // Perform request |
282 $response = $this->_performRequest('Tables(\'' . $tableName . '\')', '', Zend_Http_Client::DELETE, $headers, true, null); |
286 $response = $this->_performRequest('Tables(\'' . $tableName . '\')', '', Zend_Http_Client::DELETE, $headers, true, null); |
283 if (!$response->isSuccessful()) { |
287 if (!$response->isSuccessful()) { |
|
288 require_once 'Zend/Service/WindowsAzure/Exception.php'; |
284 throw new Zend_Service_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.')); |
289 throw new Zend_Service_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.')); |
285 } |
290 } |
286 } |
291 } |
287 |
292 |
288 /** |
293 /** |
294 * @throws Zend_Service_WindowsAzure_Exception |
299 * @throws Zend_Service_WindowsAzure_Exception |
295 */ |
300 */ |
296 public function insertEntity($tableName = '', Zend_Service_WindowsAzure_Storage_TableEntity $entity = null) |
301 public function insertEntity($tableName = '', Zend_Service_WindowsAzure_Storage_TableEntity $entity = null) |
297 { |
302 { |
298 if ($tableName === '') { |
303 if ($tableName === '') { |
|
304 require_once 'Zend/Service/WindowsAzure/Exception.php'; |
299 throw new Zend_Service_WindowsAzure_Exception('Table name is not specified.'); |
305 throw new Zend_Service_WindowsAzure_Exception('Table name is not specified.'); |
300 } |
306 } |
301 if ($entity === null) { |
307 if (is_null($entity)) { |
|
308 require_once 'Zend/Service/WindowsAzure/Exception.php'; |
302 throw new Zend_Service_WindowsAzure_Exception('Entity is not specified.'); |
309 throw new Zend_Service_WindowsAzure_Exception('Entity is not specified.'); |
303 } |
310 } |
304 |
311 |
305 // Generate request body |
312 // Generate request body |
306 $requestBody = '<?xml version="1.0" encoding="utf-8" standalone="yes"?> |
313 $requestBody = '<?xml version="1.0" encoding="utf-8" standalone="yes"?> |
338 if ($response->isSuccessful()) { |
345 if ($response->isSuccessful()) { |
339 // Parse result |
346 // Parse result |
340 $result = $this->_parseResponse($response); |
347 $result = $this->_parseResponse($response); |
341 |
348 |
342 $timestamp = $result->xpath('//m:properties/d:Timestamp'); |
349 $timestamp = $result->xpath('//m:properties/d:Timestamp'); |
343 $timestamp = (string)$timestamp[0]; |
350 $timestamp = $this->_convertToDateTime( (string)$timestamp[0] ); |
344 |
351 |
345 $etag = $result->attributes('http://schemas.microsoft.com/ado/2007/08/dataservices/metadata'); |
352 $etag = $result->attributes('http://schemas.microsoft.com/ado/2007/08/dataservices/metadata'); |
346 $etag = (string)$etag['etag']; |
353 $etag = (string)$etag['etag']; |
347 |
354 |
348 // Update properties |
355 // Update properties |
349 $entity->setTimestamp($timestamp); |
356 $entity->setTimestamp($timestamp); |
350 $entity->setEtag($etag); |
357 $entity->setEtag($etag); |
351 |
358 |
352 return $entity; |
359 return $entity; |
353 } else { |
360 } else { |
|
361 require_once 'Zend/Service/WindowsAzure/Exception.php'; |
354 throw new Zend_Service_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.')); |
362 throw new Zend_Service_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.')); |
355 } |
363 } |
356 } |
364 } |
357 |
365 |
358 /** |
366 /** |
364 * @throws Zend_Service_WindowsAzure_Exception |
372 * @throws Zend_Service_WindowsAzure_Exception |
365 */ |
373 */ |
366 public function deleteEntity($tableName = '', Zend_Service_WindowsAzure_Storage_TableEntity $entity = null, $verifyEtag = false) |
374 public function deleteEntity($tableName = '', Zend_Service_WindowsAzure_Storage_TableEntity $entity = null, $verifyEtag = false) |
367 { |
375 { |
368 if ($tableName === '') { |
376 if ($tableName === '') { |
|
377 require_once 'Zend/Service/WindowsAzure/Exception.php'; |
369 throw new Zend_Service_WindowsAzure_Exception('Table name is not specified.'); |
378 throw new Zend_Service_WindowsAzure_Exception('Table name is not specified.'); |
370 } |
379 } |
371 if ($entity === null) { |
380 if (is_null($entity)) { |
|
381 require_once 'Zend/Service/WindowsAzure/Exception.php'; |
372 throw new Zend_Service_WindowsAzure_Exception('Entity is not specified.'); |
382 throw new Zend_Service_WindowsAzure_Exception('Entity is not specified.'); |
373 } |
383 } |
374 |
384 |
375 // Add header information |
385 // Add header information |
376 $headers = array(); |
386 $headers = array(); |
392 return null; |
402 return null; |
393 } else { |
403 } else { |
394 $response = $this->_performRequest($tableName . '(PartitionKey=\'' . $entity->getPartitionKey() . '\', RowKey=\'' . $entity->getRowKey() . '\')', '', Zend_Http_Client::DELETE, $headers, true, null); |
404 $response = $this->_performRequest($tableName . '(PartitionKey=\'' . $entity->getPartitionKey() . '\', RowKey=\'' . $entity->getRowKey() . '\')', '', Zend_Http_Client::DELETE, $headers, true, null); |
395 } |
405 } |
396 if (!$response->isSuccessful()) { |
406 if (!$response->isSuccessful()) { |
|
407 require_once 'Zend/Service/WindowsAzure/Exception.php'; |
397 throw new Zend_Service_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.')); |
408 throw new Zend_Service_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.')); |
398 } |
409 } |
399 } |
410 } |
400 |
411 |
401 /** |
412 /** |
406 * @param string $rowKey Row key |
417 * @param string $rowKey Row key |
407 * @param string $entityClass Entity class name* |
418 * @param string $entityClass Entity class name* |
408 * @return Zend_Service_WindowsAzure_Storage_TableEntity |
419 * @return Zend_Service_WindowsAzure_Storage_TableEntity |
409 * @throws Zend_Service_WindowsAzure_Exception |
420 * @throws Zend_Service_WindowsAzure_Exception |
410 */ |
421 */ |
411 public function retrieveEntityById($tableName = '', $partitionKey = '', $rowKey = '', $entityClass = 'Zend_Service_WindowsAzure_Storage_DynamicTableEntity') |
422 public function retrieveEntityById($tableName, $partitionKey, $rowKey, $entityClass = 'Zend_Service_WindowsAzure_Storage_DynamicTableEntity') |
412 { |
423 { |
413 if ($tableName === '') { |
424 if (is_null($tableName) || $tableName === '') { |
|
425 require_once 'Zend/Service/WindowsAzure/Exception.php'; |
414 throw new Zend_Service_WindowsAzure_Exception('Table name is not specified.'); |
426 throw new Zend_Service_WindowsAzure_Exception('Table name is not specified.'); |
415 } |
427 } |
416 if ($partitionKey === '') { |
428 if (is_null($partitionKey) || $partitionKey === '') { |
|
429 require_once 'Zend/Service/WindowsAzure/Exception.php'; |
417 throw new Zend_Service_WindowsAzure_Exception('Partition key is not specified.'); |
430 throw new Zend_Service_WindowsAzure_Exception('Partition key is not specified.'); |
418 } |
431 } |
419 if ($rowKey === '') { |
432 if (is_null($rowKey) || $rowKey === '') { |
|
433 require_once 'Zend/Service/WindowsAzure/Exception.php'; |
420 throw new Zend_Service_WindowsAzure_Exception('Row key is not specified.'); |
434 throw new Zend_Service_WindowsAzure_Exception('Row key is not specified.'); |
421 } |
435 } |
422 if ($entityClass === '') { |
436 if (is_null($entityClass) || $entityClass === '') { |
|
437 require_once 'Zend/Service/WindowsAzure/Exception.php'; |
423 throw new Zend_Service_WindowsAzure_Exception('Entity class is not specified.'); |
438 throw new Zend_Service_WindowsAzure_Exception('Entity class is not specified.'); |
424 } |
439 } |
425 |
440 |
426 |
441 |
427 // Check for combined size of partition key and row key |
442 // Check for combined size of partition key and row key |
428 // http://msdn.microsoft.com/en-us/library/dd179421.aspx |
443 // http://msdn.microsoft.com/en-us/library/dd179421.aspx |
429 if (strlen($partitionKey . $rowKey) >= 256) { |
444 if (strlen($partitionKey . $rowKey) >= 256) { |
430 // Start a batch if possible |
445 // Start a batch if possible |
431 if ($this->isInBatch()) { |
446 if ($this->isInBatch()) { |
|
447 require_once 'Zend/Service/WindowsAzure/Exception.php'; |
432 throw new Zend_Service_WindowsAzure_Exception('Entity cannot be retrieved. A transaction is required to retrieve the entity, but another transaction is already active.'); |
448 throw new Zend_Service_WindowsAzure_Exception('Entity cannot be retrieved. A transaction is required to retrieve the entity, but another transaction is already active.'); |
433 } |
449 } |
434 |
450 |
435 $this->startBatch(); |
451 $this->startBatch(); |
436 } |
452 } |
475 * @throws Zend_Service_WindowsAzure_Exception |
492 * @throws Zend_Service_WindowsAzure_Exception |
476 */ |
493 */ |
477 public function retrieveEntities($tableName = '', $filter = '', $entityClass = 'Zend_Service_WindowsAzure_Storage_DynamicTableEntity', $nextPartitionKey = null, $nextRowKey = null) |
494 public function retrieveEntities($tableName = '', $filter = '', $entityClass = 'Zend_Service_WindowsAzure_Storage_DynamicTableEntity', $nextPartitionKey = null, $nextRowKey = null) |
478 { |
495 { |
479 if ($tableName === '') { |
496 if ($tableName === '') { |
|
497 require_once 'Zend/Service/WindowsAzure/Exception.php'; |
480 throw new Zend_Service_WindowsAzure_Exception('Table name is not specified.'); |
498 throw new Zend_Service_WindowsAzure_Exception('Table name is not specified.'); |
481 } |
499 } |
482 if ($entityClass === '') { |
500 if ($entityClass === '') { |
|
501 require_once 'Zend/Service/WindowsAzure/Exception.php'; |
483 throw new Zend_Service_WindowsAzure_Exception('Entity class is not specified.'); |
502 throw new Zend_Service_WindowsAzure_Exception('Entity class is not specified.'); |
484 } |
503 } |
485 |
504 |
486 // Convenience... |
505 // Convenience... |
487 if (class_exists($filter)) { |
506 if (class_exists($filter)) { |
518 $queryString = $tableName->assembleQueryString(true); |
539 $queryString = $tableName->assembleQueryString(true); |
519 |
540 |
520 // Change $tableName |
541 // Change $tableName |
521 $tableName = $tableName->assembleFrom(true); |
542 $tableName = $tableName->assembleFrom(true); |
522 } else { |
543 } else { |
|
544 require_once 'Zend/Service/WindowsAzure/Exception.php'; |
523 throw new Zend_Service_WindowsAzure_Exception('Invalid argument: $tableName'); |
545 throw new Zend_Service_WindowsAzure_Exception('Invalid argument: $tableName'); |
524 } |
546 } |
525 |
547 |
526 // Add continuation querystring parameters? |
548 // Add continuation querystring parameters? |
527 if ($nextPartitionKey !== null && $nextRowKey !== null) { |
549 if (!is_null($nextPartitionKey) && !is_null($nextRowKey)) { |
528 if ($queryString !== '') { |
550 if ($queryString !== '') { |
529 $queryString .= '&'; |
551 $queryString .= '&'; |
|
552 } else { |
|
553 $queryString .= '?'; |
530 } |
554 } |
531 |
555 |
532 $queryString .= '&NextPartitionKey=' . rawurlencode($nextPartitionKey) . '&NextRowKey=' . rawurlencode($nextRowKey); |
556 $queryString .= 'NextPartitionKey=' . rawurlencode($nextPartitionKey) . '&NextRowKey=' . rawurlencode($nextRowKey); |
533 } |
557 } |
534 |
558 |
535 // Perform request |
559 // Perform request |
536 $response = null; |
560 $response = null; |
537 if ($this->isInBatch() && $this->getCurrentBatch()->getOperationCount() == 0) { |
561 if ($this->isInBatch() && $this->getCurrentBatch()->getOperationCount() == 0) { |
578 $properties = $entry->xpath('.//m:properties'); |
602 $properties = $entry->xpath('.//m:properties'); |
579 $properties = $properties[0]->children('http://schemas.microsoft.com/ado/2007/08/dataservices'); |
603 $properties = $properties[0]->children('http://schemas.microsoft.com/ado/2007/08/dataservices'); |
580 |
604 |
581 // Create entity |
605 // Create entity |
582 $entity = new $entityClass('', ''); |
606 $entity = new $entityClass('', ''); |
583 $entity->setAzureValues((array)$properties, true); |
607 $entity->setAzureValues((array)$properties, $this->_throwExceptionOnMissingData); |
584 |
608 |
585 // If we have a Zend_Service_WindowsAzure_Storage_DynamicTableEntity, make sure all property types are OK |
609 // If we have a Zend_Service_WindowsAzure_Storage_DynamicTableEntity, make sure all property types are set |
586 if ($entity instanceof Zend_Service_WindowsAzure_Storage_DynamicTableEntity) { |
610 if ($entity instanceof Zend_Service_WindowsAzure_Storage_DynamicTableEntity) { |
587 foreach ($properties as $key => $value) { |
611 foreach ($properties as $key => $value) { |
588 $attributes = $value->attributes('http://schemas.microsoft.com/ado/2007/08/dataservices/metadata'); |
612 $attributes = $value->attributes('http://schemas.microsoft.com/ado/2007/08/dataservices/metadata'); |
589 $type = (string)$attributes['type']; |
613 $type = (string)$attributes['type']; |
590 if ($type !== '') { |
614 if ($type !== '') { |
591 $entity->setAzurePropertyType($key, $type); |
615 $entity->setAzureProperty($key, (string)$value, $type); |
592 } |
616 } |
593 } |
617 } |
594 } |
618 } |
595 |
619 |
596 // Update etag |
620 // Update etag |
601 // Add to result |
625 // Add to result |
602 $returnValue[] = $entity; |
626 $returnValue[] = $entity; |
603 } |
627 } |
604 |
628 |
605 // More entities? |
629 // More entities? |
606 if ($response->getHeader('x-ms-continuation-NextPartitionKey') !== null && $response->getHeader('x-ms-continuation-NextRowKey') !== null) { |
630 if (!is_null($response->getHeader('x-ms-continuation-NextPartitionKey')) && !is_null($response->getHeader('x-ms-continuation-NextRowKey'))) { |
607 if (strpos($queryString, '$top') === false) { |
631 if (strpos($queryString, '$top') === false) { |
608 $returnValue = array_merge($returnValue, $this->retrieveEntities($tableName, $filter, $entityClass, $response->getHeader('x-ms-continuation-NextPartitionKey'), $response->getHeader('x-ms-continuation-NextRowKey'))); |
632 $returnValue = array_merge($returnValue, $this->retrieveEntities($tableName, $filter, $entityClass, $response->getHeader('x-ms-continuation-NextPartitionKey'), $response->getHeader('x-ms-continuation-NextRowKey'))); |
609 } |
633 } |
610 } |
634 } |
611 |
635 |
612 // Return |
636 // Return |
613 return $returnValue; |
637 return $returnValue; |
614 } else { |
638 } else { |
|
639 require_once 'Zend/Service/WindowsAzure/Exception.php'; |
615 throw new Zend_Service_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.')); |
640 throw new Zend_Service_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.')); |
616 } |
641 } |
617 } |
642 } |
618 |
643 |
619 /** |
644 /** |
640 */ |
665 */ |
641 public function mergeEntity($tableName = '', Zend_Service_WindowsAzure_Storage_TableEntity $entity = null, $verifyEtag = false, $properties = array()) |
666 public function mergeEntity($tableName = '', Zend_Service_WindowsAzure_Storage_TableEntity $entity = null, $verifyEtag = false, $properties = array()) |
642 { |
667 { |
643 $mergeEntity = null; |
668 $mergeEntity = null; |
644 if (is_array($properties) && count($properties) > 0) { |
669 if (is_array($properties) && count($properties) > 0) { |
|
670 |
645 // Build a new object |
671 // Build a new object |
646 $mergeEntity = new Zend_Service_WindowsAzure_Storage_DynamicTableEntity($entity->getPartitionKey(), $entity->getRowKey()); |
672 $mergeEntity = new Zend_Service_WindowsAzure_Storage_DynamicTableEntity($entity->getPartitionKey(), $entity->getRowKey()); |
647 |
673 |
648 // Keep only values mentioned in $properties |
674 // Keep only values mentioned in $properties |
649 $azureValues = $entity->getAzureValues(); |
675 $azureValues = $entity->getAzureValues(); |
653 } |
679 } |
654 } |
680 } |
655 } else { |
681 } else { |
656 $mergeEntity = $entity; |
682 $mergeEntity = $entity; |
657 } |
683 } |
658 |
|
659 // Ensure entity timestamp matches updated timestamp |
|
660 $entity->setTimestamp($this->isoDate()); |
|
661 |
684 |
|
685 // Ensure entity timestamp matches updated timestamp |
|
686 $entity->setTimestamp(new DateTime()); |
|
687 |
662 return $this->_changeEntity(Zend_Http_Client::MERGE, $tableName, $mergeEntity, $verifyEtag); |
688 return $this->_changeEntity(Zend_Http_Client::MERGE, $tableName, $mergeEntity, $verifyEtag); |
663 } |
689 } |
664 |
690 |
665 /** |
691 /** |
666 * Get error message from Zend_Http_Response |
692 * Get error message from Zend_Http_Response |
689 * @throws Zend_Service_WindowsAzure_Exception |
715 * @throws Zend_Service_WindowsAzure_Exception |
690 */ |
716 */ |
691 protected function _changeEntity($httpVerb = Zend_Http_Client::PUT, $tableName = '', Zend_Service_WindowsAzure_Storage_TableEntity $entity = null, $verifyEtag = false) |
717 protected function _changeEntity($httpVerb = Zend_Http_Client::PUT, $tableName = '', Zend_Service_WindowsAzure_Storage_TableEntity $entity = null, $verifyEtag = false) |
692 { |
718 { |
693 if ($tableName === '') { |
719 if ($tableName === '') { |
|
720 require_once 'Zend/Service/WindowsAzure/Exception.php'; |
694 throw new Zend_Service_WindowsAzure_Exception('Table name is not specified.'); |
721 throw new Zend_Service_WindowsAzure_Exception('Table name is not specified.'); |
695 } |
722 } |
696 if ($entity === null) { |
723 if (is_null($entity)) { |
|
724 require_once 'Zend/Service/WindowsAzure/Exception.php'; |
697 throw new Zend_Service_WindowsAzure_Exception('Entity is not specified.'); |
725 throw new Zend_Service_WindowsAzure_Exception('Entity is not specified.'); |
698 } |
726 } |
699 |
727 |
700 // Add header information |
728 // Add header information |
701 $headers = array(); |
729 $headers = array(); |
721 {tpl:Properties} |
749 {tpl:Properties} |
722 </m:properties> |
750 </m:properties> |
723 </content> |
751 </content> |
724 </entry>'; |
752 </entry>'; |
725 |
753 |
726 // Attempt to get timestamp from entity |
754 // Attempt to get timestamp from entity |
727 $timestamp = $entity->getTimestamp(); |
755 $timestamp = $entity->getTimestamp(); |
728 if ($timestamp == Zend_Service_WindowsAzure_Storage_TableEntity::DEFAULT_TIMESTAMP) { |
756 |
729 $timestamp = $this->isoDate(); |
|
730 } |
|
731 |
|
732 $requestBody = $this->_fillTemplate($requestBody, array( |
757 $requestBody = $this->_fillTemplate($requestBody, array( |
733 'Updated' => $timestamp, |
758 'Updated' => $this->_convertToEdmDateTime($timestamp), |
734 'Properties' => $this->_generateAzureRepresentation($entity) |
759 'Properties' => $this->_generateAzureRepresentation($entity) |
735 )); |
760 )); |
736 |
761 |
737 // Add header information |
762 // Add header information |
738 $headers = array(); |
763 $headers = array(); |
744 } |
769 } |
745 |
770 |
746 // Perform request |
771 // Perform request |
747 $response = null; |
772 $response = null; |
748 if ($this->isInBatch()) { |
773 if ($this->isInBatch()) { |
749 $this->getCurrentBatch()->enlistOperation($tableName . '(PartitionKey=\'' . $entity->getPartitionKey() . '\',RowKey=\'' . $entity->getRowKey() . '\')', '', $httpVerb, $headers, true, $requestBody); |
774 $this->getCurrentBatch()->enlistOperation($tableName . '(PartitionKey=\'' . $entity->getPartitionKey() . '\', RowKey=\'' . $entity->getRowKey() . '\')', '', $httpVerb, $headers, true, $requestBody); |
750 return null; |
775 return null; |
751 } else { |
776 } else { |
752 $response = $this->_performRequest($tableName . '(PartitionKey=\'' . $entity->getPartitionKey() . '\',RowKey=\'' . $entity->getRowKey() . '\')', '', $httpVerb, $headers, true, $requestBody); |
777 $response = $this->_performRequest($tableName . '(PartitionKey=\'' . $entity->getPartitionKey() . '\', RowKey=\'' . $entity->getRowKey() . '\')', '', $httpVerb, $headers, true, $requestBody); |
753 } |
778 } |
754 if ($response->isSuccessful()) { |
779 if ($response->isSuccessful()) { |
755 // Update properties |
780 // Update properties |
756 $entity->setEtag($response->getHeader('Etag')); |
781 $entity->setEtag($response->getHeader('Etag')); |
757 $entity->setTimestamp($response->getHeader('Last-modified')); |
782 $entity->setTimestamp( $this->_convertToDateTime($response->getHeader('Last-modified')) ); |
758 |
783 |
759 return $entity; |
784 return $entity; |
760 } else { |
785 } else { |
|
786 require_once 'Zend/Service/WindowsAzure/Exception.php'; |
761 throw new Zend_Service_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.')); |
787 throw new Zend_Service_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.')); |
762 } |
788 } |
763 } |
789 } |
764 |
790 |
765 /** |
791 /** |
802 $value = array(); |
828 $value = array(); |
803 $value[] = '<d:' . $azureValue->Name; |
829 $value[] = '<d:' . $azureValue->Name; |
804 if ($azureValue->Type != '') { |
830 if ($azureValue->Type != '') { |
805 $value[] = ' m:type="' . $azureValue->Type . '"'; |
831 $value[] = ' m:type="' . $azureValue->Type . '"'; |
806 } |
832 } |
807 if ($azureValue->Value === null) { |
833 if (is_null($azureValue->Value)) { |
808 $value[] = ' m:null="true"'; |
834 $value[] = ' m:null="true"'; |
809 } |
835 } |
810 $value[] = '>'; |
836 $value[] = '>'; |
811 |
837 |
812 if ($azureValue->Value !== null) { |
838 if (!is_null($azureValue->Value)) { |
813 if (strtolower($azureValue->Type) == 'edm.boolean') { |
839 if (strtolower($azureValue->Type) == 'edm.boolean') { |
814 $value[] = ($azureValue->Value == true ? '1' : '0'); |
840 $value[] = ($azureValue->Value == true ? '1' : '0'); |
|
841 } else if (strtolower($azureValue->Type) == 'edm.datetime') { |
|
842 $value[] = $this->_convertToEdmDateTime($azureValue->Value); |
815 } else { |
843 } else { |
816 $value[] = htmlspecialchars($azureValue->Value); |
844 $value[] = htmlspecialchars($azureValue->Value); |
817 } |
845 } |
818 } |
846 } |
819 |
847 |
860 $forTableStorage, |
888 $forTableStorage, |
861 $rawData, |
889 $rawData, |
862 $resourceType, |
890 $resourceType, |
863 $requiredPermission |
891 $requiredPermission |
864 ); |
892 ); |
865 } |
893 } |
|
894 |
|
895 /** |
|
896 * Converts a string to a DateTime object. Returns false on failure. |
|
897 * |
|
898 * @param string $value The string value to parse |
|
899 * @return DateTime|boolean |
|
900 */ |
|
901 protected function _convertToDateTime($value = '') |
|
902 { |
|
903 if ($value instanceof DateTime) { |
|
904 return $value; |
|
905 } |
|
906 |
|
907 try { |
|
908 if (substr($value, -1) == 'Z') { |
|
909 $value = substr($value, 0, strlen($value) - 1); |
|
910 } |
|
911 return new DateTime($value, new DateTimeZone('UTC')); |
|
912 } |
|
913 catch (Exception $ex) { |
|
914 return false; |
|
915 } |
|
916 } |
|
917 |
|
918 /** |
|
919 * Converts a DateTime object into an Edm.DaeTime value in UTC timezone, |
|
920 * represented as a string. |
|
921 * |
|
922 * @param DateTime $value |
|
923 * @return string |
|
924 */ |
|
925 protected function _convertToEdmDateTime(DateTime $value) |
|
926 { |
|
927 $cloned = clone $value; |
|
928 $cloned->setTimezone(new DateTimeZone('UTC')); |
|
929 return str_replace('+0000', 'Z', $cloned->format(DateTime::ISO8601)); |
|
930 } |
866 } |
931 } |