web/lib/Zend/Service/WindowsAzure/SessionHandler.php
changeset 807 877f952ae2bd
parent 207 621fa6caec0c
child 1230 68c69c656a2c
--- a/web/lib/Zend/Service/WindowsAzure/SessionHandler.php	Thu Mar 21 17:31:31 2013 +0100
+++ b/web/lib/Zend/Service/WindowsAzure/SessionHandler.php	Thu Mar 21 19:50:53 2013 +0100
@@ -15,62 +15,92 @@
  * @category   Zend
  * @package    Zend_Service_WindowsAzure
  * @subpackage Session
- * @copyright  Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
  * @license    http://framework.zend.com/license/new-bsd     New BSD License
- * @version    $Id: SessionHandler.php 20785 2010-01-31 09:43:03Z mikaelkael $
+ * @version    $Id: SessionHandler.php 24593 2012-01-05 20:35:02Z matthew $
  */
 
-/** Zend_Service_WindowsAzure_Storage_Table */
-require_once 'Zend/Service/WindowsAzure/Storage/Table.php';
-
-/**
- * @see Zend_Service_WindowsAzure_Exception
- */
-require_once 'Zend/Service/WindowsAzure/Exception.php';
-
 /**
  * @category   Zend
  * @package    Zend_Service_WindowsAzure
  * @subpackage Session
- * @copyright  Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
  * @license    http://framework.zend.com/license/new-bsd     New BSD License
  */
 class Zend_Service_WindowsAzure_SessionHandler
 {
+	/**
+	 * Maximal property size in table storage.
+	 * 
+	 * @var int
+	 * @see http://msdn.microsoft.com/en-us/library/dd179338.aspx
+	 */
+	const MAX_TS_PROPERTY_SIZE = 65536;
+	
+	/** Storage backend type */
+	const STORAGE_TYPE_TABLE = 'table';
+	const STORAGE_TYPE_BLOB = 'blob';
+	
     /**
-     * Table storage
+     * Storage back-end
      * 
-     * @var Zend_Service_WindowsAzure_Storage_Table
+     * @var Zend_Service_WindowsAzure_Storage_Table|Zend_Service_WindowsAzure_Storage_Blob
      */
-    protected $_tableStorage;
+    protected $_storage;
     
     /**
-     * Session table name
+     * Storage backend type
      * 
      * @var string
      */
-    protected $_sessionTable;
+    protected $_storageType;
     
     /**
-     * Session table partition
+     * Session container name
      * 
      * @var string
      */
-    protected $_sessionTablePartition;
+    protected $_sessionContainer;
+    
+    /**
+     * Session container partition
+     * 
+     * @var string
+     */
+    protected $_sessionContainerPartition;
 	
     /**
      * Creates a new Zend_Service_WindowsAzure_SessionHandler instance
      * 
-     * @param Zend_Service_WindowsAzure_Storage_Table $tableStorage Table storage
-     * @param string $sessionTable Session table name
-     * @param string $sessionTablePartition Session table partition
+     * @param Zend_Service_WindowsAzure_Storage_Table|Zend_Service_WindowsAzure_Storage_Blob $storage Storage back-end, can be table storage and blob storage
+     * @param string $sessionContainer Session container name
+     * @param string $sessionContainerPartition Session container partition
      */
-    public function __construct(Zend_Service_WindowsAzure_Storage_Table $tableStorage, $sessionTable = 'phpsessions', $sessionTablePartition = 'sessions')
+    public function __construct(Zend_Service_WindowsAzure_Storage $storage, $sessionContainer = 'phpsessions', $sessionContainerPartition = 'sessions')
 	{
+		// Validate $storage
+		if (!($storage instanceof Zend_Service_WindowsAzure_Storage_Table || $storage instanceof Zend_Service_WindowsAzure_Storage_Blob)) {
+			require_once 'Zend/Service/WindowsAzure/Exception.php';
+			throw new Zend_Service_WindowsAzure_Exception('Invalid storage back-end given. Storage back-end should be of type Zend_Service_WindowsAzure_Storage_Table or Zend_Service_WindowsAzure_Storage_Blob.');
+		}
+		
+		// Validate other parameters
+		if ($sessionContainer == '' || $sessionContainerPartition == '') {
+			require_once 'Zend/Service/WindowsAzure/Exception.php';
+			throw new Zend_Service_WindowsAzure_Exception('Session container and session partition should be specified.');
+		}
+		
+		// Determine storage type
+		$storageType = self::STORAGE_TYPE_TABLE;
+		if ($storage instanceof Zend_Service_WindowsAzure_Storage_Blob) {
+			$storageType = self::STORAGE_TYPE_BLOB;
+		}
+		
 	    // Set properties
-		$this->_tableStorage = $tableStorage;
-		$this->_sessionTable = $sessionTable;
-		$this->_sessionTablePartition = $sessionTablePartition;
+		$this->_storage = $storage;
+		$this->_storageType = $storageType;
+		$this->_sessionContainer = $sessionContainer;
+		$this->_sessionContainerPartition = $sessionContainerPartition;
 	}
 	
 	/**
@@ -96,12 +126,13 @@
      */
     public function open()
     {
-    	// Make sure table exists
-    	$tableExists = $this->_tableStorage->tableExists($this->_sessionTable);
-    	if (!$tableExists) {
-		    $this->_tableStorage->createTable($this->_sessionTable);
-		}
-		
+    	// Make sure storage container exists
+    	if ($this->_storageType == self::STORAGE_TYPE_TABLE) {
+    		$this->_storage->createTableIfNotExists($this->_sessionContainer);
+    	} else if ($this->_storageType == self::STORAGE_TYPE_BLOB) {
+    		$this->_storage->createContainerIfNotExists($this->_sessionContainer);
+    	}
+    	
 		// Ok!
 		return true;
     }
@@ -124,19 +155,37 @@
      */
     public function read($id)
     {
-        try
-        {
-            $sessionRecord = $this->_tableStorage->retrieveEntityById(
-                $this->_sessionTable,
-                $this->_sessionTablePartition,
-                $id
-            );
-            return base64_decode($sessionRecord->serializedData);
-        }
-        catch (Zend_Service_WindowsAzure_Exception $ex)
-        {
-            return '';
-        }
+    	// Read data
+       	if ($this->_storageType == self::STORAGE_TYPE_TABLE) {
+    		// In table storage
+	        try
+	        {
+	            $sessionRecord = $this->_storage->retrieveEntityById(
+	                $this->_sessionContainer,
+	                $this->_sessionContainerPartition,
+	                $id
+	            );
+	            return unserialize(base64_decode($sessionRecord->serializedData));
+	        }
+	        catch (Zend_Service_WindowsAzure_Exception $ex)
+	        {
+	            return '';
+	        }
+       	} else if ($this->_storageType == self::STORAGE_TYPE_BLOB) {
+    		// In blob storage
+    	    try
+	        {
+    			$data = $this->_storage->getBlobData(
+    				$this->_sessionContainer,
+    				$this->_sessionContainerPartition . '/' . $id
+    			);
+	            return unserialize(base64_decode($data));
+	        }
+	        catch (Zend_Service_WindowsAzure_Exception $ex)
+	        {
+	            return false;
+	        }
+    	}
     }
     
     /**
@@ -144,23 +193,42 @@
      * 
      * @param int $id Session Id
      * @param string $serializedData Serialized PHP object
+     * @throws Exception
      */
     public function write($id, $serializedData)
     {
-        $sessionRecord = new Zend_Service_WindowsAzure_Storage_DynamicTableEntity($this->_sessionTablePartition, $id);
-        $sessionRecord->sessionExpires = time();
-        $sessionRecord->serializedData = base64_encode($serializedData);
-        
-        $sessionRecord->setAzurePropertyType('sessionExpires', 'Edm.Int32');
-
-        try
-        {
-            $this->_tableStorage->updateEntity($this->_sessionTable, $sessionRecord);
-        }
-        catch (Zend_Service_WindowsAzure_Exception $unknownRecord)
-        {
-            $this->_tableStorage->insertEntity($this->_sessionTable, $sessionRecord);
-        }
+    	// Encode data
+    	$serializedData = base64_encode(serialize($serializedData));
+    	if (strlen($serializedData) >= self::MAX_TS_PROPERTY_SIZE && $this->_storageType == self::STORAGE_TYPE_TABLE) {
+    		throw new Zend_Service_WindowsAzure_Exception('Session data exceeds the maximum allowed size of ' . self::MAX_TS_PROPERTY_SIZE . ' bytes that can be stored using table storage. Consider switching to a blob storage back-end or try reducing session data size.');
+    	}
+    	
+    	// Store data
+       	if ($this->_storageType == self::STORAGE_TYPE_TABLE) {
+    		// In table storage
+       	    $sessionRecord = new Zend_Service_WindowsAzure_Storage_DynamicTableEntity($this->_sessionContainerPartition, $id);
+	        $sessionRecord->sessionExpires = time();
+	        $sessionRecord->serializedData = $serializedData;
+	        
+	        $sessionRecord->setAzurePropertyType('sessionExpires', 'Edm.Int32');
+	
+	        try
+	        {
+	            $this->_storage->updateEntity($this->_sessionContainer, $sessionRecord);
+	        }
+	        catch (Zend_Service_WindowsAzure_Exception $unknownRecord)
+	        {
+	            $this->_storage->insertEntity($this->_sessionContainer, $sessionRecord);
+	        }
+    	} else if ($this->_storageType == self::STORAGE_TYPE_BLOB) {
+    		// In blob storage
+    		$this->_storage->putBlobData(
+    			$this->_sessionContainer,
+    			$this->_sessionContainerPartition . '/' . $id,
+    			$serializedData,
+    			array('sessionexpires' => time())
+    		);
+    	}
     }
     
     /**
@@ -171,21 +239,40 @@
      */
     public function destroy($id)
     {
-        try
-        {
-            $sessionRecord = $this->_tableStorage->retrieveEntityById(
-                $this->_sessionTable,
-                $this->_sessionTablePartition,
-                $id
-            );
-            $this->_tableStorage->deleteEntity($this->_sessionTable, $sessionRecord);
-            
-            return true;
-        }
-        catch (Zend_Service_WindowsAzure_Exception $ex)
-        {
-            return false;
-        }
+		// Destroy data
+       	if ($this->_storageType == self::STORAGE_TYPE_TABLE) {
+    		// In table storage
+       	    try
+	        {
+	            $sessionRecord = $this->_storage->retrieveEntityById(
+	                $this->_sessionContainer,
+	                $this->_sessionContainerPartition,
+	                $id
+	            );
+	            $this->_storage->deleteEntity($this->_sessionContainer, $sessionRecord);
+	            
+	            return true;
+	        }
+	        catch (Zend_Service_WindowsAzure_Exception $ex)
+	        {
+	            return false;
+	        }
+    	} else if ($this->_storageType == self::STORAGE_TYPE_BLOB) {
+    		// In blob storage
+    	    try
+	        {
+    			$this->_storage->deleteBlob(
+    				$this->_sessionContainer,
+    				$this->_sessionContainerPartition . '/' . $id
+    			);
+	            
+	            return true;
+	        }
+	        catch (Zend_Service_WindowsAzure_Exception $ex)
+	        {
+	            return false;
+	        }
+    	}
     }
     
     /**
@@ -200,18 +287,38 @@
      */
     public function gc($lifeTime)
     {
-        try
-        {
-            $result = $this->_tableStorage->retrieveEntities($this->_sessionTable, 'PartitionKey eq \'' . $this->_sessionTablePartition . '\' and sessionExpires lt ' . (time() - $lifeTime));
-            foreach ($result as $sessionRecord)
-            {
-                $this->_tableStorage->deleteEntity($this->_sessionTable, $sessionRecord);
-            }
-            return true;
-        }
-        catch (Zend_Service_WindowsAzure_exception $ex)
-        {
-            return false;
-        }
+       	if ($this->_storageType == self::STORAGE_TYPE_TABLE) {
+    		// In table storage
+       	    try
+	        {
+	            $result = $this->_storage->retrieveEntities($this->_sessionContainer, 'PartitionKey eq \'' . $this->_sessionContainerPartition . '\' and sessionExpires lt ' . (time() - $lifeTime));
+	            foreach ($result as $sessionRecord)
+	            {
+	                $this->_storage->deleteEntity($this->_sessionContainer, $sessionRecord);
+	            }
+	            return true;
+	        }
+	        catch (Zend_Service_WindowsAzure_exception $ex)
+	        {
+	            return false;
+	        }
+    	} else if ($this->_storageType == self::STORAGE_TYPE_BLOB) {
+    		// In blob storage
+    	    try
+	        {
+	            $result = $this->_storage->listBlobs($this->_sessionContainer, $this->_sessionContainerPartition, '', null, null, 'metadata');
+	            foreach ($result as $sessionRecord)
+	            {
+	            	if ($sessionRecord->Metadata['sessionexpires'] < (time() - $lifeTime)) {
+	                	$this->_storage->deleteBlob($this->_sessionContainer, $sessionRecord->Name);
+	            	}
+	            }
+	            return true;
+	        }
+	        catch (Zend_Service_WindowsAzure_exception $ex)
+	        {
+	            return false;
+	        }
+    	}
     }
 }