PageRenderTime 279ms CodeModel.GetById 129ms app.highlight 81ms RepoModel.GetById 63ms app.codeStats 0ms

/vendor/Microsoft/WindowsAzure/Storage/Queue.php

https://bitbucket.org/ktos/tinyshare
PHP | 556 lines | 306 code | 52 blank | 198 comment | 86 complexity | 02f22adeb2cb245fc5e1b916cbdeda2a MD5 | raw file
  1<?php
  2/**
  3 * Copyright (c) 2009 - 2011, RealDolmen
  4 * All rights reserved.
  5 *
  6 * Redistribution and use in source and binary forms, with or without
  7 * modification, are permitted provided that the following conditions are met:
  8 *     * Redistributions of source code must retain the above copyright
  9 *       notice, this list of conditions and the following disclaimer.
 10 *     * Redistributions in binary form must reproduce the above copyright
 11 *       notice, this list of conditions and the following disclaimer in the
 12 *       documentation and/or other materials provided with the distribution.
 13 *     * Neither the name of RealDolmen nor the
 14 *       names of its contributors may be used to endorse or promote products
 15 *       derived from this software without specific prior written permission.
 16 *
 17 * THIS SOFTWARE IS PROVIDED BY RealDolmen ''AS IS'' AND ANY
 18 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 20 * DISCLAIMED. IN NO EVENT SHALL RealDolmen BE LIABLE FOR ANY
 21 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 26 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 27 *
 28 * @category   Microsoft
 29 * @package    Microsoft_WindowsAzure
 30 * @subpackage Storage
 31 * @copyright  Copyright (c) 2009 - 2011, RealDolmen (http://www.realdolmen.com)
 32 * @license    http://todo     name_todo
 33 * @version    $Id: Blob.php 24241 2009-07-22 09:43:13Z unknown $
 34 */
 35
 36/**
 37 * @see Microsoft_AutoLoader
 38 */
 39require_once dirname(__FILE__) . '/../../AutoLoader.php';
 40
 41
 42/**
 43 * @category   Microsoft
 44 * @package    Microsoft_WindowsAzure
 45 * @subpackage Storage
 46 * @copyright  Copyright (c) 2009 - 2011, RealDolmen (http://www.realdolmen.com)
 47 * @license    http://phpazure.codeplex.com/license
 48 */
 49class Microsoft_WindowsAzure_Storage_Queue extends Microsoft_WindowsAzure_Storage
 50{
 51	/**
 52	 * Maximal message size (in bytes)
 53	 */
 54	const MAX_MESSAGE_SIZE = 8388608;
 55	
 56	/**
 57	 * Maximal message ttl (in seconds)
 58	 */
 59	const MAX_MESSAGE_TTL = 604800;
 60	
 61	/**
 62	 * Creates a new Microsoft_WindowsAzure_Storage_Queue instance
 63	 *
 64	 * @param string $host Storage host name
 65	 * @param string $accountName Account name for Windows Azure
 66	 * @param string $accountKey Account key for Windows Azure
 67	 * @param boolean $usePathStyleUri Use path-style URI's
 68	 * @param Microsoft_WindowsAzure_RetryPolicy_RetryPolicyAbstract $retryPolicy Retry policy to use when making requests
 69	 */
 70	public function __construct($host = Microsoft_WindowsAzure_Storage::URL_DEV_QUEUE, $accountName = Microsoft_WindowsAzure_Credentials_CredentialsAbstract::DEVSTORE_ACCOUNT, $accountKey = Microsoft_WindowsAzure_Credentials_CredentialsAbstract::DEVSTORE_KEY, $usePathStyleUri = false, Microsoft_WindowsAzure_RetryPolicy_RetryPolicyAbstract $retryPolicy = null)
 71	{
 72		parent::__construct($host, $accountName, $accountKey, $usePathStyleUri, $retryPolicy);
 73		
 74		// API version
 75		$this->_apiVersion = '2009-09-19';
 76	}
 77	
 78	/**
 79	 * Check if a queue exists
 80	 * 
 81	 * @param string $queueName Queue name
 82	 * @return boolean
 83	 */
 84	public function queueExists($queueName = '')
 85	{
 86		if ($queueName === '') {
 87			throw new Microsoft_WindowsAzure_Exception('Queue name is not specified.');
 88		}
 89		if (!self::isValidQueueName($queueName)) {
 90		    throw new Microsoft_WindowsAzure_Exception('Queue name does not adhere to queue naming conventions. See http://msdn.microsoft.com/en-us/library/dd179349.aspx for more information.');
 91		}
 92			
 93		// List queues
 94        $queues = $this->listQueues($queueName, 1);
 95        foreach ($queues as $queue) {
 96            if ($queue->Name == $queueName) {
 97                return true;
 98            }
 99        }
100        
101        return false;
102	}
103	
104	/**
105	 * Create queue
106	 *
107	 * @param string $queueName Queue name
108	 * @param array  $metadata  Key/value pairs of meta data
109	 * @return object Queue properties
110	 * @throws Microsoft_WindowsAzure_Exception
111	 */
112	public function createQueue($queueName = '', $metadata = array())
113	{
114		if ($queueName === '') {
115			throw new Microsoft_WindowsAzure_Exception('Queue name is not specified.');
116		}
117		if (!self::isValidQueueName($queueName)) {
118		    throw new Microsoft_WindowsAzure_Exception('Queue name does not adhere to queue naming conventions. See http://msdn.microsoft.com/en-us/library/dd179349.aspx for more information.');
119		}
120			
121		// Create metadata headers
122		$headers = array();
123		$headers = array_merge($headers, $this->_generateMetadataHeaders($metadata)); 
124		
125		// Perform request
126		$response = $this->_performRequest($queueName, array(), Microsoft_Http_Client::PUT, $headers);	
127		if ($response->isSuccessful()) {
128		    return new Microsoft_WindowsAzure_Storage_QueueInstance(
129		        $queueName,
130		        $metadata
131		    );
132		} else {
133			throw new Microsoft_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
134		}
135	}
136	
137	/**
138	 * Create queue if it does not exist
139	 *
140	 * @param string $queueName Queue name
141	 * @param array  $metadata  Key/value pairs of meta data
142	 * @throws Microsoft_WindowsAzure_Exception
143	 */
144	public function createQueueIfNotExists($queueName = '', $metadata = array())
145	{
146		if (!$this->queueExists($queueName)) {
147			$this->createQueue($queueName, $metadata);
148		}
149	}
150	
151	/**
152	 * Get queue
153	 * 
154	 * @param string $queueName  Queue name
155	 * @return Microsoft_WindowsAzure_Storage_QueueInstance
156	 * @throws Microsoft_WindowsAzure_Exception
157	 */
158	public function getQueue($queueName = '')
159	{
160		if ($queueName === '') {
161			throw new Microsoft_WindowsAzure_Exception('Queue name is not specified.');
162		}
163		if (!self::isValidQueueName($queueName)) {
164		    throw new Microsoft_WindowsAzure_Exception('Queue name does not adhere to queue naming conventions. See http://msdn.microsoft.com/en-us/library/dd179349.aspx for more information.');
165		}
166		    
167		// Perform request
168		$response = $this->_performRequest($queueName, array('comp' => 'metadata'), Microsoft_Http_Client::GET);	
169		if ($response->isSuccessful()) {
170		    // Parse metadata
171		    $metadata = $this->_parseMetadataHeaders($response->getHeaders());
172
173		    // Return queue
174		    $queue = new Microsoft_WindowsAzure_Storage_QueueInstance(
175		        $queueName,
176		        $metadata
177		    );
178		    $queue->ApproximateMessageCount = intval($response->getHeader('x-ms-approximate-message-count'));
179		    return $queue;
180		} else {
181		    throw new Microsoft_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
182		}
183	}
184	
185	/**
186	 * Get queue metadata
187	 * 
188	 * @param string $queueName  Queue name
189	 * @return array Key/value pairs of meta data
190	 * @throws Microsoft_WindowsAzure_Exception
191	 */
192	public function getQueueMetadata($queueName = '')
193	{
194		if ($queueName === '') {
195			throw new Microsoft_WindowsAzure_Exception('Queue name is not specified.');
196		}
197		if (!self::isValidQueueName($queueName)) {
198		    throw new Microsoft_WindowsAzure_Exception('Queue name does not adhere to queue naming conventions. See http://msdn.microsoft.com/en-us/library/dd179349.aspx for more information.');
199		}
200			
201	    return $this->getQueue($queueName)->Metadata;
202	}
203	
204	/**
205	 * Set queue metadata
206	 * 
207	 * Calling the Set Queue Metadata operation overwrites all existing metadata that is associated with the queue. It's not possible to modify an individual name/value pair.
208	 *
209	 * @param string $queueName  Queue name
210	 * @param array  $metadata       Key/value pairs of meta data
211	 * @throws Microsoft_WindowsAzure_Exception
212	 */
213	public function setQueueMetadata($queueName = '', $metadata = array())
214	{
215		if ($queueName === '') {
216			throw new Microsoft_WindowsAzure_Exception('Queue name is not specified.');
217		}
218		if (!self::isValidQueueName($queueName)) {
219		    throw new Microsoft_WindowsAzure_Exception('Queue name does not adhere to queue naming conventions. See http://msdn.microsoft.com/en-us/library/dd179349.aspx for more information.');
220		}
221		if (count($metadata) == 0) {
222		    return;
223		}
224		    
225		// Create metadata headers
226		$headers = array();
227		$headers = array_merge($headers, $this->_generateMetadataHeaders($metadata)); 
228		
229		// Perform request
230		$response = $this->_performRequest($queueName, array('comp' => 'metadata'), Microsoft_Http_Client::PUT, $headers);
231
232		if (!$response->isSuccessful()) {
233			throw new Microsoft_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
234		}
235	}
236	
237	/**
238	 * Delete queue
239	 *
240	 * @param string $queueName Queue name
241	 * @throws Microsoft_WindowsAzure_Exception
242	 */
243	public function deleteQueue($queueName = '')
244	{
245		if ($queueName === '') {
246			throw new Microsoft_WindowsAzure_Exception('Queue name is not specified.');
247		}
248		if (!self::isValidQueueName($queueName)) {
249		    throw new Microsoft_WindowsAzure_Exception('Queue name does not adhere to queue naming conventions. See http://msdn.microsoft.com/en-us/library/dd179349.aspx for more information.');
250		}
251			
252		// Perform request
253		$response = $this->_performRequest($queueName, array(), Microsoft_Http_Client::DELETE);
254		if (!$response->isSuccessful()) {
255			throw new Microsoft_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
256		}
257	}
258	
259	/**
260	 * List queues
261	 *
262	 * @param string $prefix     Optional. Filters the results to return only queues whose name begins with the specified prefix.
263	 * @param int    $maxResults Optional. Specifies the maximum number of queues to return per call to Azure storage. This does NOT affect list size returned by this function. (maximum: 5000)
264	 * @param string $marker     Optional string value that identifies the portion of the list to be returned with the next list operation.
265	 * @param string $include    Optional. Include this parameter to specify that the queue's metadata be returned as part of the response body. (allowed values: '', 'metadata')
266	 * @param int    $currentResultCount Current result count (internal use)
267	 * @return array
268	 * @throws Microsoft_WindowsAzure_Exception
269	 */
270	public function listQueues($prefix = null, $maxResults = null, $marker = null, $include = null, $currentResultCount = 0)
271	{
272	    // Build query string
273		$query = array('comp' => 'list');
274        if (!is_null($prefix)) {
275	        $query['prefix'] = $prefix;
276        }
277	    if (!is_null($maxResults)) {
278	        $query['maxresults'] = $maxResults;
279	    }
280	    if (!is_null($marker)) {
281	        $query['marker'] = $marker;
282	    }
283		if (!is_null($include)) {
284	        $query['include'] = $include;
285	    }
286	        
287		// Perform request
288		$response = $this->_performRequest('', $query, Microsoft_Http_Client::GET);	
289		if ($response->isSuccessful()) {
290			$xmlQueues = $this->_parseResponse($response)->Queues->Queue;
291			$xmlMarker = (string)$this->_parseResponse($response)->NextMarker;
292
293			$queues = array();
294			if (!is_null($xmlQueues)) {
295				for ($i = 0; $i < count($xmlQueues); $i++) {
296					$queues[] = new Microsoft_WindowsAzure_Storage_QueueInstance(
297						(string)$xmlQueues[$i]->Name,
298						$this->_parseMetadataElement($xmlQueues[$i])
299					);
300				}
301			}
302			$currentResultCount = $currentResultCount + count($queues);
303			if (!is_null($maxResults) && $currentResultCount < $maxResults) {
304    			if (!is_null($xmlMarker) && $xmlMarker != '') {
305    			    $queues = array_merge($queues, $this->listQueues($prefix, $maxResults, $xmlMarker, $include, $currentResultCount));
306    			}
307			}
308			if (!is_null($maxResults) && count($queues) > $maxResults) {
309			    $queues = array_slice($queues, 0, $maxResults);
310			}
311			    
312			return $queues;
313		} else {
314			throw new Microsoft_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
315		}
316	}
317	
318	/**
319	 * Put message into queue
320	 *
321	 * @param string $queueName  Queue name
322	 * @param string $message    Message
323	 * @param int    $ttl        Message Time-To-Live (in seconds). Defaults to 7 days if the parameter is omitted.
324	 * @throws Microsoft_WindowsAzure_Exception
325	 */
326	public function putMessage($queueName = '', $message = '', $ttl = null)
327	{
328		if ($queueName === '') {
329			throw new Microsoft_WindowsAzure_Exception('Queue name is not specified.');
330		}
331		if (!self::isValidQueueName($queueName)) {
332		    throw new Microsoft_WindowsAzure_Exception('Queue name does not adhere to queue naming conventions. See http://msdn.microsoft.com/en-us/library/dd179349.aspx for more information.');
333		}
334		if (strlen($message) > self::MAX_MESSAGE_SIZE) {
335		    throw new Microsoft_WindowsAzure_Exception('Message is too big. Message content should be < 8KB.');
336		}
337		if ($message == '') {
338		    throw new Microsoft_WindowsAzure_Exception('Message is not specified.');
339		}
340		if (!is_null($ttl) && ($ttl <= 0 || $ttl > self::MAX_MESSAGE_SIZE)) {
341		    throw new Microsoft_WindowsAzure_Exception('Message TTL is invalid. Maximal TTL is 7 days (' . self::MAX_MESSAGE_SIZE . ' seconds) and should be greater than zero.');
342		}
343		    
344	    // Build query string
345		$query = array();
346        if (!is_null($ttl)) {
347	        $query['messagettl'] = $ttl;
348        }
349	        
350	    // Build body
351	    $rawData = '';
352	    $rawData .= '<QueueMessage>';
353	    $rawData .= '    <MessageText>' . base64_encode($message) . '</MessageText>';
354	    $rawData .= '</QueueMessage>';
355	        
356		// Perform request
357		$response = $this->_performRequest($queueName . '/messages', $query, Microsoft_Http_Client::POST, array(), false, $rawData);
358
359		if (!$response->isSuccessful()) {
360			throw new Microsoft_WindowsAzure_Exception('Error putting message into queue.');
361		}
362	}
363	
364	/**
365	 * Get queue messages
366	 *
367	 * @param string $queueName         Queue name
368	 * @param string $numOfMessages     Optional. A nonzero integer value that specifies the number of messages to retrieve from the queue, up to a maximum of 32. By default, a single message is retrieved from the queue with this operation.
369	 * @param int    $visibilityTimeout Optional. An integer value that specifies the message's visibility timeout in seconds. The maximum value is 2 hours. The default message visibility timeout is 30 seconds.
370	 * @param string $peek              Peek only?
371	 * @return array
372	 * @throws Microsoft_WindowsAzure_Exception
373	 */
374	public function getMessages($queueName = '', $numOfMessages = 1, $visibilityTimeout = null, $peek = false)
375	{
376		if ($queueName === '') {
377			throw new Microsoft_WindowsAzure_Exception('Queue name is not specified.');
378		}
379		if (!self::isValidQueueName($queueName)) {
380		    throw new Microsoft_WindowsAzure_Exception('Queue name does not adhere to queue naming conventions. See http://msdn.microsoft.com/en-us/library/dd179349.aspx for more information.');
381		}
382		if ($numOfMessages < 1 || $numOfMessages > 32 || intval($numOfMessages) != $numOfMessages) {
383		    throw new Microsoft_WindowsAzure_Exception('Invalid number of messages to retrieve.');
384		}
385		if (!is_null($visibilityTimeout) && ($visibilityTimeout <= 0 || $visibilityTimeout > 7200)) {
386		    throw new Microsoft_WindowsAzure_Exception('Visibility timeout is invalid. Maximum value is 2 hours (7200 seconds) and should be greater than zero.');
387		}
388		    
389	    // Build query string
390		$query = array();
391    	if ($peek) {
392    	    $query['peekonly'] = 'true';
393    	}
394    	if ($numOfMessages > 1) {
395	        $query['numofmessages'] = $numOfMessages;
396    	}
397    	if (!$peek && !is_null($visibilityTimeout)) {
398	        $query['visibilitytimeout'] = $visibilityTimeout;
399    	}  
400	        
401		// Perform request
402		$response = $this->_performRequest($queueName . '/messages', $query, Microsoft_Http_Client::GET);	
403		if ($response->isSuccessful()) {
404		    // Parse results
405			$result = $this->_parseResponse($response);
406		    if (!$result) {
407		        return array();
408		    }
409
410		    $xmlMessages = null;
411		    if (count($result->QueueMessage) > 1) {
412    		    $xmlMessages = $result->QueueMessage;
413    		} else {
414    		    $xmlMessages = array($result->QueueMessage);
415    		}
416
417			$messages = array();
418			for ($i = 0; $i < count($xmlMessages); $i++) {
419				$messages[] = new Microsoft_WindowsAzure_Storage_QueueMessage(
420					(string)$xmlMessages[$i]->MessageId,
421					(string)$xmlMessages[$i]->InsertionTime,
422					(string)$xmlMessages[$i]->ExpirationTime,
423					($peek ? '' : (string)$xmlMessages[$i]->PopReceipt),
424					($peek ? '' : (string)$xmlMessages[$i]->TimeNextVisible),
425					(string)$xmlMessages[$i]->DequeueCount,
426					base64_decode((string)$xmlMessages[$i]->MessageText)
427			    );
428			}
429			    
430			return $messages;
431		} else {
432			throw new Microsoft_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
433		}
434	}
435	
436	/**
437	 * Peek queue messages
438	 *
439	 * @param string $queueName         Queue name
440	 * @param string $numOfMessages     Optional. A nonzero integer value that specifies the number of messages to retrieve from the queue, up to a maximum of 32. By default, a single message is retrieved from the queue with this operation.
441	 * @return array
442	 * @throws Microsoft_WindowsAzure_Exception
443	 */
444	public function peekMessages($queueName = '', $numOfMessages = 1)
445	{
446	    return $this->getMessages($queueName, $numOfMessages, null, true);
447	}
448	
449	/**
450	 * Checks to see if a given queue has messages
451	 *
452	 * @param string $queueName         Queue name
453	 * @return boolean
454	 * @throws Microsoft_WindowsAzure_Exception
455	 */
456	public function hasMessages($queueName = '')
457	{
458		return count($this->peekMessages($queueName)) > 0;
459	}
460	
461	/**
462	 * Clear queue messages
463	 *
464	 * @param string $queueName         Queue name
465	 * @throws Microsoft_WindowsAzure_Exception
466	 */
467	public function clearMessages($queueName = '')
468	{
469		if ($queueName === '') {
470			throw new Microsoft_WindowsAzure_Exception('Queue name is not specified.');
471		}
472		if (!self::isValidQueueName($queueName)) {
473		    throw new Microsoft_WindowsAzure_Exception('Queue name does not adhere to queue naming conventions. See http://msdn.microsoft.com/en-us/library/dd179349.aspx for more information.');
474		}
475
476		// Perform request
477		$response = $this->_performRequest($queueName . '/messages', array(), Microsoft_Http_Client::DELETE);	
478		if (!$response->isSuccessful()) {
479			throw new Microsoft_WindowsAzure_Exception('Error clearing messages from queue.');
480		}
481	}
482	
483	/**
484	 * Delete queue message
485	 *
486	 * @param string $queueName         					Queue name
487	 * @param Microsoft_WindowsAzure_Storage_QueueMessage $message Message to delete from queue. A message retrieved using "peekMessages" can NOT be deleted!
488	 * @throws Microsoft_WindowsAzure_Exception
489	 */
490	public function deleteMessage($queueName = '', Microsoft_WindowsAzure_Storage_QueueMessage $message)
491	{
492		if ($queueName === '') {
493			throw new Microsoft_WindowsAzure_Exception('Queue name is not specified.');
494		}
495		if (!self::isValidQueueName($queueName)) {
496		    throw new Microsoft_WindowsAzure_Exception('Queue name does not adhere to queue naming conventions. See http://msdn.microsoft.com/en-us/library/dd179349.aspx for more information.');
497		}
498		if ($message->PopReceipt == '') {
499		    throw new Microsoft_WindowsAzure_Exception('A message retrieved using "peekMessages" can NOT be deleted! Use "getMessages" instead.');
500		}
501
502		// Perform request
503		$response = $this->_performRequest($queueName . '/messages/' . $message->MessageId, array('popreceipt' => $message->PopReceipt), Microsoft_Http_Client::DELETE);	
504		if (!$response->isSuccessful()) {
505			throw new Microsoft_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
506		}
507	}
508	
509	/**
510	 * Is valid queue name?
511	 *
512	 * @param string $queueName Queue name
513	 * @return boolean
514	 */
515    public static function isValidQueueName($queueName = '')
516    {
517        if (preg_match("/^[a-z0-9][a-z0-9-]*$/", $queueName) === 0) {
518            return false;
519        }
520    
521        if (strpos($queueName, '--') !== false) {
522            return false;
523        }
524    
525        if (strtolower($queueName) != $queueName) {
526            return false;
527        }
528    
529        if (strlen($queueName) < 3 || strlen($queueName) > 63) {
530            return false;
531        }
532            
533        if (substr($queueName, -1) == '-') {
534            return false;
535        }
536    
537        return true;
538    }
539    
540	/**
541	 * Get error message from Microsoft_Http_Response
542	 * 
543	 * @param Microsoft_Http_Response $response Repsonse
544	 * @param string $alternativeError Alternative error message
545	 * @return string
546	 */
547	protected function _getErrorMessage(Microsoft_Http_Response $response, $alternativeError = 'Unknown error.')
548	{
549		$response = $this->_parseResponse($response);
550		if ($response && $response->Message) {
551		    return (string)$response->Message;
552		} else {
553		    return $alternativeError;
554		}
555	}
556}