[ Index ]

PHP Cross Reference of moodle-2.8

title

Body

[close]

/lib/zend/Zend/Service/WindowsAzure/Storage/ -> Table.php (source)

   1  <?php
   2  /**
   3   * Zend Framework
   4   *
   5   * LICENSE
   6   *
   7   * This source file is subject to the new BSD license that is bundled
   8   * with this package in the file LICENSE.txt.
   9   * It is also available through the world-wide-web at this URL:
  10   * http://framework.zend.com/license/new-bsd
  11   * If you did not receive a copy of the license and are unable to
  12   * obtain it through the world-wide-web, please send an email
  13   * to [email protected] so we can send you a copy immediately.
  14   *
  15   * @category   Zend
  16   * @package    Zend_Service_WindowsAzure
  17   * @subpackage Storage
  18   * @copyright  Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
  19   * @license    http://framework.zend.com/license/new-bsd     New BSD License
  20   * @version    $Id$
  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  
  58  /**
  59   * @see Zend_Service_WindowsAzure_Storage_BatchStorageAbstract
  60   */
  61  require_once 'Zend/Service/WindowsAzure/Storage/BatchStorageAbstract.php';
  62  
  63  /**
  64   * @see Zend_Service_WindowsAzure_Storage_TableInstance
  65   */
  66  require_once 'Zend/Service/WindowsAzure/Storage/TableInstance.php';
  67  
  68  /**
  69   * @see Zend_Service_WindowsAzure_Storage_TableEntity
  70   */
  71  require_once 'Zend/Service/WindowsAzure/Storage/TableEntity.php';
  72  
  73  /**
  74   * @see Zend_Service_WindowsAzure_Storage_DynamicTableEntity
  75   */
  76  require_once 'Zend/Service/WindowsAzure/Storage/DynamicTableEntity.php';
  77  
  78  /**
  79   * @see Zend_Service_WindowsAzure_Storage_TableEntityQuery
  80   */
  81  require_once 'Zend/Service/WindowsAzure/Storage/TableEntityQuery.php';
  82  
  83  /**
  84   * @see Zend_Service_WindowsAzure_Exception
  85   */
  86  require_once 'Zend/Service/WindowsAzure/Exception.php';
  87  
  88  
  89  /**
  90   * @category   Zend
  91   * @package    Zend_Service_WindowsAzure
  92   * @subpackage Storage
  93   * @copyright  Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
  94   * @license    http://framework.zend.com/license/new-bsd     New BSD License
  95   */
  96  class Zend_Service_WindowsAzure_Storage_Table
  97      extends Zend_Service_WindowsAzure_Storage_BatchStorageAbstract
  98  {
  99      /**
 100       * Creates a new Zend_Service_WindowsAzure_Storage_Table instance
 101       *
 102       * @param string $host Storage host name
 103       * @param string $accountName Account name for Windows Azure
 104       * @param string $accountKey Account key for Windows Azure
 105       * @param boolean $usePathStyleUri Use path-style URI's
 106       * @param Zend_Service_WindowsAzure_RetryPolicy_RetryPolicyAbstract $retryPolicy Retry policy to use when making requests
 107       */
 108  	public function __construct($host = Zend_Service_WindowsAzure_Storage::URL_DEV_TABLE, $accountName = Zend_Service_WindowsAzure_Credentials_CredentialsAbstract::DEVSTORE_ACCOUNT, $accountKey = Zend_Service_WindowsAzure_Credentials_CredentialsAbstract::DEVSTORE_KEY, $usePathStyleUri = false, Zend_Service_WindowsAzure_RetryPolicy_RetryPolicyAbstract $retryPolicy = null)
 109      {
 110          parent::__construct($host, $accountName, $accountKey, $usePathStyleUri, $retryPolicy);
 111  
 112          // Always use SharedKeyLite authentication
 113          $this->_credentials = new Zend_Service_WindowsAzure_Credentials_SharedKeyLite($accountName, $accountKey, $this->_usePathStyleUri);
 114          
 115          // API version
 116          $this->_apiVersion = '2009-04-14';
 117      }
 118      
 119      /**
 120       * Check if a table exists
 121       * 
 122       * @param string $tableName Table name
 123       * @return boolean
 124       */
 125  	public function tableExists($tableName = '')
 126      {
 127          if ($tableName === '') {
 128              throw new Zend_Service_WindowsAzure_Exception('Table name is not specified.');
 129          }
 130              
 131          // List tables
 132          $tables = $this->listTables($tableName);
 133          foreach ($tables as $table) {
 134              if ($table->Name == $tableName) {
 135                  return true;
 136              }
 137          }
 138          
 139          return false;
 140      }
 141      
 142      /**
 143       * List tables
 144       *
 145       * @param  string $nextTableName Next table name, used for listing tables when total amount of tables is > 1000.
 146       * @return array
 147       * @throws Zend_Service_WindowsAzure_Exception
 148       */
 149  	public function listTables($nextTableName = '')
 150      {
 151          // Build query string
 152          $queryString = '';
 153          if ($nextTableName != '') {
 154              $queryString = '?NextTableName=' . $nextTableName;
 155          }
 156          
 157          // Perform request
 158          $response = $this->_performRequest('Tables', $queryString, Zend_Http_Client::GET, null, true);
 159          if ($response->isSuccessful()) {        
 160              // Parse result
 161              $result = $this->_parseResponse($response);    
 162              
 163              if (!$result || !$result->entry) {
 164                  return array();
 165              }
 166              
 167              $entries = null;
 168              if (count($result->entry) > 1) {
 169                  $entries = $result->entry;
 170              } else {
 171                  $entries = array($result->entry);
 172              }
 173  
 174              // Create return value
 175              $returnValue = array();            
 176              foreach ($entries as $entry) {
 177                  $tableName = $entry->xpath('.//m:properties/d:TableName');
 178                  $tableName = (string)$tableName[0];
 179                  
 180                  $returnValue[] = new Zend_Service_WindowsAzure_Storage_TableInstance(
 181                      (string)$entry->id,
 182                      $tableName,
 183                      (string)$entry->link['href'],
 184                      (string)$entry->updated
 185                  );
 186              }
 187              
 188              // More tables?
 189              if (!is_null($response->getHeader('x-ms-continuation-NextTableName'))) {
 190                  $returnValue = array_merge($returnValue, $this->listTables($response->getHeader('x-ms-continuation-NextTableName')));
 191              }
 192  
 193              return $returnValue;
 194          } else {
 195              throw new Zend_Service_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
 196          }
 197      }
 198      
 199      /**
 200       * Create table
 201       *
 202       * @param string $tableName Table name
 203       * @return Zend_Service_WindowsAzure_Storage_TableInstance
 204       * @throws Zend_Service_WindowsAzure_Exception
 205       */
 206  	public function createTable($tableName = '')
 207      {
 208          if ($tableName === '') {
 209              throw new Zend_Service_WindowsAzure_Exception('Table name is not specified.');
 210          }
 211              
 212          // Generate request body
 213          $requestBody = '<?xml version="1.0" encoding="utf-8" standalone="yes"?>
 214                          <entry
 215                              xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices"
 216                              xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata"
 217                              xmlns="http://www.w3.org/2005/Atom">
 218                            <title />
 219                            <updated>{tpl:Updated}</updated>
 220                            <author>
 221                              <name />
 222                            </author>
 223                            <id />
 224                            <content type="application/xml">
 225                              <m:properties>
 226                                <d:TableName>{tpl:TableName}</d:TableName>
 227                              </m:properties>
 228                            </content>
 229                          </entry>';
 230          
 231          $requestBody = $this->_fillTemplate($requestBody, array(
 232              'BaseUrl' => $this->getBaseUrl(),
 233              'TableName' => htmlspecialchars($tableName),
 234              'Updated' => $this->isoDate(),
 235              'AccountName' => $this->_accountName
 236          ));
 237          
 238          // Add header information
 239          $headers = array();
 240          $headers['Content-Type'] = 'application/atom+xml';
 241          $headers['DataServiceVersion'] = '1.0;NetFx';
 242          $headers['MaxDataServiceVersion'] = '1.0;NetFx';        
 243  
 244          // Perform request
 245          $response = $this->_performRequest('Tables', '', Zend_Http_Client::POST, $headers, true, $requestBody);
 246          if ($response->isSuccessful()) {
 247              // Parse response
 248              $entry = $this->_parseResponse($response);
 249              
 250              $tableName = $entry->xpath('.//m:properties/d:TableName');
 251              $tableName = (string)$tableName[0];
 252                  
 253              return new Zend_Service_WindowsAzure_Storage_TableInstance(
 254                  (string)$entry->id,
 255                  $tableName,
 256                  (string)$entry->link['href'],
 257                  (string)$entry->updated
 258              );
 259          } else {
 260              throw new Zend_Service_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
 261          }
 262      }
 263      
 264      /**
 265       * Delete table
 266       *
 267       * @param string $tableName Table name
 268       * @throws Zend_Service_WindowsAzure_Exception
 269       */
 270  	public function deleteTable($tableName = '')
 271      {
 272          if ($tableName === '') {
 273              throw new Zend_Service_WindowsAzure_Exception('Table name is not specified.');
 274          }
 275  
 276          // Add header information
 277          $headers = array();
 278          $headers['Content-Type'] = 'application/atom+xml';
 279  
 280          // Perform request
 281          $response = $this->_performRequest('Tables(\'' . $tableName . '\')', '', Zend_Http_Client::DELETE, $headers, true, null);
 282          if (!$response->isSuccessful()) {
 283              throw new Zend_Service_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
 284          }
 285      }
 286      
 287      /**
 288       * Insert entity into table
 289       * 
 290       * @param string                              $tableName   Table name
 291       * @param Zend_Service_WindowsAzure_Storage_TableEntity $entity      Entity to insert
 292       * @return Zend_Service_WindowsAzure_Storage_TableEntity
 293       * @throws Zend_Service_WindowsAzure_Exception
 294       */
 295  	public function insertEntity($tableName = '', Zend_Service_WindowsAzure_Storage_TableEntity $entity = null)
 296      {
 297          if ($tableName === '') {
 298              throw new Zend_Service_WindowsAzure_Exception('Table name is not specified.');
 299          }
 300          if (is_null($entity)) {
 301              throw new Zend_Service_WindowsAzure_Exception('Entity is not specified.');
 302          }
 303                               
 304          // Generate request body
 305          $requestBody = '<?xml version="1.0" encoding="utf-8" standalone="yes"?>
 306                          <entry xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xmlns="http://www.w3.org/2005/Atom">
 307                            <title />
 308                            <updated>{tpl:Updated}</updated>
 309                            <author>
 310                              <name />
 311                            </author>
 312                            <id />
 313                            <content type="application/xml">
 314                              <m:properties>
 315                                {tpl:Properties}
 316                              </m:properties>
 317                            </content>
 318                          </entry>';
 319          
 320          $requestBody = $this->_fillTemplate($requestBody, array(
 321              'Updated'    => $this->isoDate(),
 322              'Properties' => $this->_generateAzureRepresentation($entity)
 323          ));
 324  
 325          // Add header information
 326          $headers = array();
 327          $headers['Content-Type'] = 'application/atom+xml';
 328  
 329          // Perform request
 330          $response = null;
 331          if ($this->isInBatch()) {
 332              $this->getCurrentBatch()->enlistOperation($tableName, '', Zend_Http_Client::POST, $headers, true, $requestBody);
 333              return null;
 334          } else {
 335              $response = $this->_performRequest($tableName, '', Zend_Http_Client::POST, $headers, true, $requestBody);
 336          }
 337          if ($response->isSuccessful()) {
 338              // Parse result
 339              $result = $this->_parseResponse($response);
 340              
 341              $timestamp = $result->xpath('//m:properties/d:Timestamp');
 342              $timestamp = (string)$timestamp[0];
 343  
 344              $etag      = $result->attributes('http://schemas.microsoft.com/ado/2007/08/dataservices/metadata');
 345              $etag      = (string)$etag['etag'];
 346              
 347              // Update properties
 348              $entity->setTimestamp($timestamp);
 349              $entity->setEtag($etag);
 350  
 351              return $entity;
 352          } else {
 353              throw new Zend_Service_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
 354          }
 355      }
 356      
 357      /**
 358       * Delete entity from table
 359       * 
 360       * @param string                              $tableName   Table name
 361       * @param Zend_Service_WindowsAzure_Storage_TableEntity $entity      Entity to delete
 362       * @param boolean                             $verifyEtag  Verify etag of the entity (used for concurrency)
 363       * @throws Zend_Service_WindowsAzure_Exception
 364       */
 365  	public function deleteEntity($tableName = '', Zend_Service_WindowsAzure_Storage_TableEntity $entity = null, $verifyEtag = false)
 366      {
 367          if ($tableName === '') {
 368              throw new Zend_Service_WindowsAzure_Exception('Table name is not specified.');
 369          }
 370          if (is_null($entity)) {
 371              throw new Zend_Service_WindowsAzure_Exception('Entity is not specified.');
 372          }
 373                               
 374          // Add header information
 375          $headers = array();
 376          if (!$this->isInBatch()) {
 377              // http://social.msdn.microsoft.com/Forums/en-US/windowsazure/thread/9e255447-4dc7-458a-99d3-bdc04bdc5474/
 378              $headers['Content-Type']   = 'application/atom+xml';
 379          }
 380          $headers['Content-Length'] = 0;
 381          if (!$verifyEtag) {
 382              $headers['If-Match']       = '*';
 383          } else {
 384              $headers['If-Match']       = $entity->getEtag();
 385          }
 386  
 387          // Perform request
 388          $response = null;
 389          if ($this->isInBatch()) {
 390              $this->getCurrentBatch()->enlistOperation($tableName . '(PartitionKey=\'' . $entity->getPartitionKey() . '\', RowKey=\'' . $entity->getRowKey() . '\')', '', Zend_Http_Client::DELETE, $headers, true, null);
 391              return null;
 392          } else {
 393              $response = $this->_performRequest($tableName . '(PartitionKey=\'' . $entity->getPartitionKey() . '\', RowKey=\'' . $entity->getRowKey() . '\')', '', Zend_Http_Client::DELETE, $headers, true, null);
 394          }
 395          if (!$response->isSuccessful()) {
 396              throw new Zend_Service_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
 397          }
 398      }
 399      
 400      /**
 401       * Retrieve entity from table, by id
 402       * 
 403       * @param string $tableName    Table name
 404       * @param string $partitionKey Partition key
 405       * @param string $rowKey       Row key
 406       * @param string $entityClass  Entity class name* 
 407       * @return Zend_Service_WindowsAzure_Storage_TableEntity
 408       * @throws Zend_Service_WindowsAzure_Exception
 409       */
 410  	public function retrieveEntityById($tableName = '', $partitionKey = '', $rowKey = '', $entityClass = 'Zend_Service_WindowsAzure_Storage_DynamicTableEntity')
 411      {
 412          if ($tableName === '') {
 413              throw new Zend_Service_WindowsAzure_Exception('Table name is not specified.');
 414          }
 415          if ($partitionKey === '') {
 416              throw new Zend_Service_WindowsAzure_Exception('Partition key is not specified.');
 417          }
 418          if ($rowKey === '') {
 419              throw new Zend_Service_WindowsAzure_Exception('Row key is not specified.');
 420          }
 421          if ($entityClass === '') {
 422              throw new Zend_Service_WindowsAzure_Exception('Entity class is not specified.');
 423          }
 424  
 425              
 426          // Check for combined size of partition key and row key
 427          // http://msdn.microsoft.com/en-us/library/dd179421.aspx
 428          if (strlen($partitionKey . $rowKey) >= 256) {
 429              // Start a batch if possible
 430              if ($this->isInBatch()) {
 431                  throw new Zend_Service_WindowsAzure_Exception('Entity cannot be retrieved. A transaction is required to retrieve the entity, but another transaction is already active.');
 432              }
 433                  
 434              $this->startBatch();
 435          }
 436          
 437          // Fetch entities from Azure
 438          $result = $this->retrieveEntities(
 439              $this->select()
 440                   ->from($tableName)
 441                   ->wherePartitionKey($partitionKey)
 442                   ->whereRowKey($rowKey),
 443              '',
 444              $entityClass
 445          );
 446          
 447          // Return
 448          if (count($result) == 1) {
 449              return $result[0];
 450          }
 451          
 452          return null;
 453      }
 454      
 455      /**
 456       * Create a new Zend_Service_WindowsAzure_Storage_TableEntityQuery
 457       * 
 458       * @return Zend_Service_WindowsAzure_Storage_TableEntityQuery
 459       */
 460  	public function select()
 461      {
 462          return new Zend_Service_WindowsAzure_Storage_TableEntityQuery();
 463      }
 464      
 465      /**
 466       * Retrieve entities from table
 467       * 
 468       * @param string $tableName|Zend_Service_WindowsAzure_Storage_TableEntityQuery    Table name -or- Zend_Service_WindowsAzure_Storage_TableEntityQuery instance
 469       * @param string $filter                                                Filter condition (not applied when $tableName is a Zend_Service_WindowsAzure_Storage_TableEntityQuery instance)
 470       * @param string $entityClass                                           Entity class name
 471       * @param string $nextPartitionKey                                      Next partition key, used for listing entities when total amount of entities is > 1000.
 472       * @param string $nextRowKey                                            Next row key, used for listing entities when total amount of entities is > 1000.
 473       * @return array Array of Zend_Service_WindowsAzure_Storage_TableEntity
 474       * @throws Zend_Service_WindowsAzure_Exception
 475       */
 476  	public function retrieveEntities($tableName = '', $filter = '', $entityClass = 'Zend_Service_WindowsAzure_Storage_DynamicTableEntity', $nextPartitionKey = null, $nextRowKey = null)
 477      {
 478          if ($tableName === '') {
 479              throw new Zend_Service_WindowsAzure_Exception('Table name is not specified.');
 480          }
 481          if ($entityClass === '') {
 482              throw new Zend_Service_WindowsAzure_Exception('Entity class is not specified.');
 483          }
 484  
 485          // Convenience...
 486          if (class_exists($filter)) {
 487              $entityClass = $filter;
 488              $filter = '';
 489          }
 490              
 491          // Query string
 492          $queryString = '';
 493  
 494          // Determine query
 495          if (is_string($tableName)) {
 496              // Option 1: $tableName is a string
 497              
 498              // Append parentheses
 499              $tableName .= '()';
 500              
 501              // Build query
 502              $query = array();
 503              
 504              // Filter?
 505              if ($filter !== '') {
 506                  $query[] = '$filter=' . rawurlencode($filter);
 507              }
 508                  
 509              // Build queryString
 510              if (count($query) > 0)  {
 511                  $queryString = '?' . implode('&', $query);
 512              }
 513          } else if (get_class($tableName) == 'Zend_Service_WindowsAzure_Storage_TableEntityQuery') {
 514              // Option 2: $tableName is a Zend_Service_WindowsAzure_Storage_TableEntityQuery instance
 515  
 516              // Build queryString
 517              $queryString = $tableName->assembleQueryString(true);
 518  
 519              // Change $tableName
 520              $tableName = $tableName->assembleFrom(true);
 521          } else {
 522              throw new Zend_Service_WindowsAzure_Exception('Invalid argument: $tableName');
 523          }
 524          
 525          // Add continuation querystring parameters?
 526          if (!is_null($nextPartitionKey) && !is_null($nextRowKey)) {
 527              if ($queryString !== '') {
 528                  $queryString .= '&';
 529              }
 530                  
 531              $queryString .= '&NextPartitionKey=' . rawurlencode($nextPartitionKey) . '&NextRowKey=' . rawurlencode($nextRowKey);
 532          }
 533  
 534          // Perform request
 535          $response = null;
 536          if ($this->isInBatch() && $this->getCurrentBatch()->getOperationCount() == 0) {
 537              $this->getCurrentBatch()->enlistOperation($tableName, $queryString, Zend_Http_Client::GET, array(), true, null);
 538              $response = $this->getCurrentBatch()->commit();
 539              
 540              // Get inner response (multipart)
 541              $innerResponse = $response->getBody();
 542              $innerResponse = substr($innerResponse, strpos($innerResponse, 'HTTP/1.1 200 OK'));
 543              $innerResponse = substr($innerResponse, 0, strpos($innerResponse, '--batchresponse'));
 544              $response = Zend_Http_Response::fromString($innerResponse);
 545          } else {
 546              $response = $this->_performRequest($tableName, $queryString, Zend_Http_Client::GET, array(), true, null);
 547          }
 548          
 549          if ($response->isSuccessful()) {
 550              // Parse result
 551              $result = $this->_parseResponse($response);
 552              if (!$result) {
 553                  return array();
 554              }
 555  
 556              $entries = null;
 557              if ($result->entry) {
 558                  if (count($result->entry) > 1) {
 559                      $entries = $result->entry;
 560                  } else {
 561                      $entries = array($result->entry);
 562                  }
 563              } else {
 564                  // This one is tricky... If we have properties defined, we have an entity.
 565                  $properties = $result->xpath('//m:properties');
 566                  if ($properties) {
 567                      $entries = array($result);
 568                  } else {
 569                      return array();
 570                  }
 571              }
 572  
 573              // Create return value
 574              $returnValue = array();            
 575              foreach ($entries as $entry) {
 576                  // Parse properties
 577                  $properties = $entry->xpath('.//m:properties');
 578                  $properties = $properties[0]->children('http://schemas.microsoft.com/ado/2007/08/dataservices');
 579                  
 580                  // Create entity
 581                  $entity = new $entityClass('', '');
 582                  $entity->setAzureValues((array)$properties, true);
 583                  
 584                  // If we have a Zend_Service_WindowsAzure_Storage_DynamicTableEntity, make sure all property types are OK
 585                  if ($entity instanceof Zend_Service_WindowsAzure_Storage_DynamicTableEntity) {
 586                      foreach ($properties as $key => $value) {  
 587                          $attributes = $value->attributes('http://schemas.microsoft.com/ado/2007/08/dataservices/metadata');
 588                          $type = (string)$attributes['type'];
 589                          if ($type !== '') {
 590                              $entity->setAzurePropertyType($key, $type);
 591                          }
 592                      }
 593                  }
 594      
 595                  // Update etag
 596                  $etag      = $entry->attributes('http://schemas.microsoft.com/ado/2007/08/dataservices/metadata');
 597                  $etag      = (string)$etag['etag'];
 598                  $entity->setEtag($etag);
 599                  
 600                  // Add to result
 601                  $returnValue[] = $entity;
 602              }
 603  
 604              // More entities?
 605              if (!is_null($response->getHeader('x-ms-continuation-NextPartitionKey')) && !is_null($response->getHeader('x-ms-continuation-NextRowKey'))) {
 606                  if (strpos($queryString, '$top') === false) {
 607                      $returnValue = array_merge($returnValue, $this->retrieveEntities($tableName, $filter, $entityClass, $response->getHeader('x-ms-continuation-NextPartitionKey'), $response->getHeader('x-ms-continuation-NextRowKey')));
 608                  }
 609              }
 610              
 611              // Return
 612              return $returnValue;
 613          } else {
 614              throw new Zend_Service_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
 615          }
 616      }
 617      
 618      /**
 619       * Update entity by replacing it
 620       * 
 621       * @param string                              $tableName   Table name
 622       * @param Zend_Service_WindowsAzure_Storage_TableEntity $entity      Entity to update
 623       * @param boolean                             $verifyEtag  Verify etag of the entity (used for concurrency)
 624       * @throws Zend_Service_WindowsAzure_Exception
 625       */
 626  	public function updateEntity($tableName = '', Zend_Service_WindowsAzure_Storage_TableEntity $entity = null, $verifyEtag = false)
 627      {
 628          return $this->_changeEntity(Zend_Http_Client::PUT, $tableName, $entity, $verifyEtag);
 629      }
 630      
 631      /**
 632       * Update entity by adding or updating properties
 633       * 
 634       * @param string                              $tableName   Table name
 635       * @param Zend_Service_WindowsAzure_Storage_TableEntity $entity      Entity to update
 636       * @param boolean                             $verifyEtag  Verify etag of the entity (used for concurrency)
 637       * @param array                               $properties  Properties to merge. All properties will be used when omitted.
 638       * @throws Zend_Service_WindowsAzure_Exception
 639       */
 640  	public function mergeEntity($tableName = '', Zend_Service_WindowsAzure_Storage_TableEntity $entity = null, $verifyEtag = false, $properties = array())
 641      {
 642          $mergeEntity = null;
 643          if (is_array($properties) && count($properties) > 0) {
 644              // Build a new object
 645              $mergeEntity = new Zend_Service_WindowsAzure_Storage_DynamicTableEntity($entity->getPartitionKey(), $entity->getRowKey());
 646              
 647              // Keep only values mentioned in $properties
 648              $azureValues = $entity->getAzureValues();
 649              foreach ($azureValues as $key => $value) {
 650                  if (in_array($value->Name, $properties)) {
 651                      $mergeEntity->setAzureProperty($value->Name, $value->Value, $value->Type);
 652                  }
 653              }
 654          } else {
 655              $mergeEntity = $entity;
 656          }
 657          
 658          return $this->_changeEntity(Zend_Http_Client::MERGE, $tableName, $mergeEntity, $verifyEtag);
 659      }
 660      
 661      /**
 662       * Get error message from Zend_Http_Response
 663       * 
 664       * @param Zend_Http_Response $response Repsonse
 665       * @param string $alternativeError Alternative error message
 666       * @return string
 667       */
 668  	protected function _getErrorMessage(Zend_Http_Response $response, $alternativeError = 'Unknown error.')
 669      {
 670          $response = $this->_parseResponse($response);
 671          if ($response && $response->message) {
 672              return (string)$response->message;
 673          } else {
 674              return $alternativeError;
 675          }
 676      }
 677      
 678      /**
 679       * Update entity / merge entity
 680       * 
 681       * @param string                              $httpVerb    HTTP verb to use (PUT = update, MERGE = merge)
 682       * @param string                              $tableName   Table name
 683       * @param Zend_Service_WindowsAzure_Storage_TableEntity $entity      Entity to update
 684       * @param boolean                             $verifyEtag  Verify etag of the entity (used for concurrency)
 685       * @throws Zend_Service_WindowsAzure_Exception
 686       */
 687  	protected function _changeEntity($httpVerb = Zend_Http_Client::PUT, $tableName = '', Zend_Service_WindowsAzure_Storage_TableEntity $entity = null, $verifyEtag = false)
 688      {
 689          if ($tableName === '') {
 690              throw new Zend_Service_WindowsAzure_Exception('Table name is not specified.');
 691          }
 692          if (is_null($entity)) {
 693              throw new Zend_Service_WindowsAzure_Exception('Entity is not specified.');
 694          }
 695                               
 696          // Add header information
 697          $headers = array();
 698          $headers['Content-Type']   = 'application/atom+xml';
 699          $headers['Content-Length'] = 0;
 700          if (!$verifyEtag) {
 701              $headers['If-Match']       = '*';
 702          } else {
 703              $headers['If-Match']       = $entity->getEtag();
 704          }
 705  
 706          // Generate request body
 707          $requestBody = '<?xml version="1.0" encoding="utf-8" standalone="yes"?>
 708                          <entry xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xmlns="http://www.w3.org/2005/Atom">
 709                            <title />
 710                            <updated>{tpl:Updated}</updated>
 711                            <author>
 712                              <name />
 713                            </author>
 714                            <id />
 715                            <content type="application/xml">
 716                              <m:properties>
 717                                {tpl:Properties}
 718                              </m:properties>
 719                            </content>
 720                          </entry>';
 721          
 722          $requestBody = $this->_fillTemplate($requestBody, array(
 723              'Updated'    => $this->isoDate(),
 724              'Properties' => $this->_generateAzureRepresentation($entity)
 725          ));
 726  
 727          // Add header information
 728          $headers = array();
 729          $headers['Content-Type'] = 'application/atom+xml';
 730          if (!$verifyEtag) {
 731              $headers['If-Match']       = '*';
 732          } else {
 733              $headers['If-Match']       = $entity->getEtag();
 734          }
 735          
 736          // Perform request
 737          $response = null;
 738          if ($this->isInBatch()) {
 739              $this->getCurrentBatch()->enlistOperation($tableName . '(PartitionKey=\'' . $entity->getPartitionKey() . '\', RowKey=\'' . $entity->getRowKey() . '\')', '', $httpVerb, $headers, true, $requestBody);
 740              return null;
 741          } else {
 742              $response = $this->_performRequest($tableName . '(PartitionKey=\'' . $entity->getPartitionKey() . '\', RowKey=\'' . $entity->getRowKey() . '\')', '', $httpVerb, $headers, true, $requestBody);
 743          }
 744          if ($response->isSuccessful()) {
 745              // Update properties
 746              $entity->setEtag($response->getHeader('Etag'));
 747              $entity->setTimestamp($response->getHeader('Last-modified'));
 748  
 749              return $entity;
 750          } else {
 751              throw new Zend_Service_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
 752          }
 753      }
 754      
 755      /**
 756       * Generate RFC 1123 compliant date string
 757       * 
 758       * @return string
 759       */
 760  	protected function _rfcDate()
 761      {
 762          return gmdate('D, d M Y H:i:s', time()) . ' GMT'; // RFC 1123
 763      }
 764      
 765      /**
 766       * Fill text template with variables from key/value array
 767       * 
 768       * @param string $templateText Template text
 769       * @param array $variables Array containing key/value pairs
 770       * @return string
 771       */
 772  	protected function _fillTemplate($templateText, $variables = array())
 773      {
 774          foreach ($variables as $key => $value) {
 775              $templateText = str_replace('{tpl:' . $key . '}', $value, $templateText);
 776          }
 777          return $templateText;
 778      }
 779      
 780      /**
 781       * Generate Azure representation from entity (creates atompub markup from properties)
 782       * 
 783       * @param Zend_Service_WindowsAzure_Storage_TableEntity $entity
 784       * @return string
 785       */
 786  	protected function _generateAzureRepresentation(Zend_Service_WindowsAzure_Storage_TableEntity $entity = null)
 787      {
 788          // Generate Azure representation from entity
 789          $azureRepresentation = array();
 790          $azureValues         = $entity->getAzureValues();
 791          foreach ($azureValues as $azureValue) {
 792              $value = array();
 793              $value[] = '<d:' . $azureValue->Name;
 794              if ($azureValue->Type != '') {
 795                  $value[] = ' m:type="' . $azureValue->Type . '"';
 796              }
 797              if (is_null($azureValue->Value)) {
 798                  $value[] = ' m:null="true"'; 
 799              }
 800              $value[] = '>';
 801              
 802              if (!is_null($azureValue->Value)) {
 803                  if (strtolower($azureValue->Type) == 'edm.boolean') {
 804                      $value[] = ($azureValue->Value == true ? '1' : '0');
 805                  } else {
 806                      $value[] = htmlspecialchars($azureValue->Value);
 807                  }
 808              }
 809              
 810              $value[] = '</d:' . $azureValue->Name . '>';
 811              $azureRepresentation[] = implode('', $value);
 812          }
 813  
 814          return implode('', $azureRepresentation);
 815      }
 816  }


Generated: Fri Nov 28 20:29:05 2014 Cross-referenced by PHPXref 0.7.1