PageRenderTime 51ms CodeModel.GetById 23ms RepoModel.GetById 1ms 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
Possible License(s): BSD-3-Clause
  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. * @see Microsoft_AutoLoader
  37. */
  38. require_once dirname(__FILE__) . '/../../AutoLoader.php';
  39. /**
  40. * @category Microsoft
  41. * @package Microsoft_WindowsAzure
  42. * @subpackage Storage
  43. * @copyright Copyright (c) 2009 - 2011, RealDolmen (http://www.realdolmen.com)
  44. * @license http://phpazure.codeplex.com/license
  45. */
  46. class Microsoft_WindowsAzure_Storage_Queue extends Microsoft_WindowsAzure_Storage
  47. {
  48. /**
  49. * Maximal message size (in bytes)
  50. */
  51. const MAX_MESSAGE_SIZE = 8388608;
  52. /**
  53. * Maximal message ttl (in seconds)
  54. */
  55. const MAX_MESSAGE_TTL = 604800;
  56. /**
  57. * Creates a new Microsoft_WindowsAzure_Storage_Queue instance
  58. *
  59. * @param string $host Storage host name
  60. * @param string $accountName Account name for Windows Azure
  61. * @param string $accountKey Account key for Windows Azure
  62. * @param boolean $usePathStyleUri Use path-style URI's
  63. * @param Microsoft_WindowsAzure_RetryPolicy_RetryPolicyAbstract $retryPolicy Retry policy to use when making requests
  64. */
  65. 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)
  66. {
  67. parent::__construct($host, $accountName, $accountKey, $usePathStyleUri, $retryPolicy);
  68. // API version
  69. $this->_apiVersion = '2009-09-19';
  70. }
  71. /**
  72. * Check if a queue exists
  73. *
  74. * @param string $queueName Queue name
  75. * @return boolean
  76. */
  77. public function queueExists($queueName = '')
  78. {
  79. if ($queueName === '') {
  80. throw new Microsoft_WindowsAzure_Exception('Queue name is not specified.');
  81. }
  82. if (!self::isValidQueueName($queueName)) {
  83. 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.');
  84. }
  85. // List queues
  86. $queues = $this->listQueues($queueName, 1);
  87. foreach ($queues as $queue) {
  88. if ($queue->Name == $queueName) {
  89. return true;
  90. }
  91. }
  92. return false;
  93. }
  94. /**
  95. * Create queue
  96. *
  97. * @param string $queueName Queue name
  98. * @param array $metadata Key/value pairs of meta data
  99. * @return object Queue properties
  100. * @throws Microsoft_WindowsAzure_Exception
  101. */
  102. public function createQueue($queueName = '', $metadata = array())
  103. {
  104. if ($queueName === '') {
  105. throw new Microsoft_WindowsAzure_Exception('Queue name is not specified.');
  106. }
  107. if (!self::isValidQueueName($queueName)) {
  108. 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.');
  109. }
  110. // Create metadata headers
  111. $headers = array();
  112. $headers = array_merge($headers, $this->_generateMetadataHeaders($metadata));
  113. // Perform request
  114. $response = $this->_performRequest($queueName, array(), Microsoft_Http_Client::PUT, $headers);
  115. if ($response->isSuccessful()) {
  116. return new Microsoft_WindowsAzure_Storage_QueueInstance(
  117. $queueName,
  118. $metadata
  119. );
  120. } else {
  121. throw new Microsoft_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
  122. }
  123. }
  124. /**
  125. * Create queue if it does not exist
  126. *
  127. * @param string $queueName Queue name
  128. * @param array $metadata Key/value pairs of meta data
  129. * @throws Microsoft_WindowsAzure_Exception
  130. */
  131. public function createQueueIfNotExists($queueName = '', $metadata = array())
  132. {
  133. if (!$this->queueExists($queueName)) {
  134. $this->createQueue($queueName, $metadata);
  135. }
  136. }
  137. /**
  138. * Get queue
  139. *
  140. * @param string $queueName Queue name
  141. * @return Microsoft_WindowsAzure_Storage_QueueInstance
  142. * @throws Microsoft_WindowsAzure_Exception
  143. */
  144. public function getQueue($queueName = '')
  145. {
  146. if ($queueName === '') {
  147. throw new Microsoft_WindowsAzure_Exception('Queue name is not specified.');
  148. }
  149. if (!self::isValidQueueName($queueName)) {
  150. 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.');
  151. }
  152. // Perform request
  153. $response = $this->_performRequest($queueName, array('comp' => 'metadata'), Microsoft_Http_Client::GET);
  154. if ($response->isSuccessful()) {
  155. // Parse metadata
  156. $metadata = $this->_parseMetadataHeaders($response->getHeaders());
  157. // Return queue
  158. $queue = new Microsoft_WindowsAzure_Storage_QueueInstance(
  159. $queueName,
  160. $metadata
  161. );
  162. $queue->ApproximateMessageCount = intval($response->getHeader('x-ms-approximate-message-count'));
  163. return $queue;
  164. } else {
  165. throw new Microsoft_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
  166. }
  167. }
  168. /**
  169. * Get queue metadata
  170. *
  171. * @param string $queueName Queue name
  172. * @return array Key/value pairs of meta data
  173. * @throws Microsoft_WindowsAzure_Exception
  174. */
  175. public function getQueueMetadata($queueName = '')
  176. {
  177. if ($queueName === '') {
  178. throw new Microsoft_WindowsAzure_Exception('Queue name is not specified.');
  179. }
  180. if (!self::isValidQueueName($queueName)) {
  181. 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.');
  182. }
  183. return $this->getQueue($queueName)->Metadata;
  184. }
  185. /**
  186. * Set queue metadata
  187. *
  188. * 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.
  189. *
  190. * @param string $queueName Queue name
  191. * @param array $metadata Key/value pairs of meta data
  192. * @throws Microsoft_WindowsAzure_Exception
  193. */
  194. public function setQueueMetadata($queueName = '', $metadata = array())
  195. {
  196. if ($queueName === '') {
  197. throw new Microsoft_WindowsAzure_Exception('Queue name is not specified.');
  198. }
  199. if (!self::isValidQueueName($queueName)) {
  200. 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.');
  201. }
  202. if (count($metadata) == 0) {
  203. return;
  204. }
  205. // Create metadata headers
  206. $headers = array();
  207. $headers = array_merge($headers, $this->_generateMetadataHeaders($metadata));
  208. // Perform request
  209. $response = $this->_performRequest($queueName, array('comp' => 'metadata'), Microsoft_Http_Client::PUT, $headers);
  210. if (!$response->isSuccessful()) {
  211. throw new Microsoft_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
  212. }
  213. }
  214. /**
  215. * Delete queue
  216. *
  217. * @param string $queueName Queue name
  218. * @throws Microsoft_WindowsAzure_Exception
  219. */
  220. public function deleteQueue($queueName = '')
  221. {
  222. if ($queueName === '') {
  223. throw new Microsoft_WindowsAzure_Exception('Queue name is not specified.');
  224. }
  225. if (!self::isValidQueueName($queueName)) {
  226. 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.');
  227. }
  228. // Perform request
  229. $response = $this->_performRequest($queueName, array(), Microsoft_Http_Client::DELETE);
  230. if (!$response->isSuccessful()) {
  231. throw new Microsoft_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
  232. }
  233. }
  234. /**
  235. * List queues
  236. *
  237. * @param string $prefix Optional. Filters the results to return only queues whose name begins with the specified prefix.
  238. * @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)
  239. * @param string $marker Optional string value that identifies the portion of the list to be returned with the next list operation.
  240. * @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')
  241. * @param int $currentResultCount Current result count (internal use)
  242. * @return array
  243. * @throws Microsoft_WindowsAzure_Exception
  244. */
  245. public function listQueues($prefix = null, $maxResults = null, $marker = null, $include = null, $currentResultCount = 0)
  246. {
  247. // Build query string
  248. $query = array('comp' => 'list');
  249. if (!is_null($prefix)) {
  250. $query['prefix'] = $prefix;
  251. }
  252. if (!is_null($maxResults)) {
  253. $query['maxresults'] = $maxResults;
  254. }
  255. if (!is_null($marker)) {
  256. $query['marker'] = $marker;
  257. }
  258. if (!is_null($include)) {
  259. $query['include'] = $include;
  260. }
  261. // Perform request
  262. $response = $this->_performRequest('', $query, Microsoft_Http_Client::GET);
  263. if ($response->isSuccessful()) {
  264. $xmlQueues = $this->_parseResponse($response)->Queues->Queue;
  265. $xmlMarker = (string)$this->_parseResponse($response)->NextMarker;
  266. $queues = array();
  267. if (!is_null($xmlQueues)) {
  268. for ($i = 0; $i < count($xmlQueues); $i++) {
  269. $queues[] = new Microsoft_WindowsAzure_Storage_QueueInstance(
  270. (string)$xmlQueues[$i]->Name,
  271. $this->_parseMetadataElement($xmlQueues[$i])
  272. );
  273. }
  274. }
  275. $currentResultCount = $currentResultCount + count($queues);
  276. if (!is_null($maxResults) && $currentResultCount < $maxResults) {
  277. if (!is_null($xmlMarker) && $xmlMarker != '') {
  278. $queues = array_merge($queues, $this->listQueues($prefix, $maxResults, $xmlMarker, $include, $currentResultCount));
  279. }
  280. }
  281. if (!is_null($maxResults) && count($queues) > $maxResults) {
  282. $queues = array_slice($queues, 0, $maxResults);
  283. }
  284. return $queues;
  285. } else {
  286. throw new Microsoft_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
  287. }
  288. }
  289. /**
  290. * Put message into queue
  291. *
  292. * @param string $queueName Queue name
  293. * @param string $message Message
  294. * @param int $ttl Message Time-To-Live (in seconds). Defaults to 7 days if the parameter is omitted.
  295. * @throws Microsoft_WindowsAzure_Exception
  296. */
  297. public function putMessage($queueName = '', $message = '', $ttl = null)
  298. {
  299. if ($queueName === '') {
  300. throw new Microsoft_WindowsAzure_Exception('Queue name is not specified.');
  301. }
  302. if (!self::isValidQueueName($queueName)) {
  303. 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.');
  304. }
  305. if (strlen($message) > self::MAX_MESSAGE_SIZE) {
  306. throw new Microsoft_WindowsAzure_Exception('Message is too big. Message content should be < 8KB.');
  307. }
  308. if ($message == '') {
  309. throw new Microsoft_WindowsAzure_Exception('Message is not specified.');
  310. }
  311. if (!is_null($ttl) && ($ttl <= 0 || $ttl > self::MAX_MESSAGE_SIZE)) {
  312. 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.');
  313. }
  314. // Build query string
  315. $query = array();
  316. if (!is_null($ttl)) {
  317. $query['messagettl'] = $ttl;
  318. }
  319. // Build body
  320. $rawData = '';
  321. $rawData .= '<QueueMessage>';
  322. $rawData .= ' <MessageText>' . base64_encode($message) . '</MessageText>';
  323. $rawData .= '</QueueMessage>';
  324. // Perform request
  325. $response = $this->_performRequest($queueName . '/messages', $query, Microsoft_Http_Client::POST, array(), false, $rawData);
  326. if (!$response->isSuccessful()) {
  327. throw new Microsoft_WindowsAzure_Exception('Error putting message into queue.');
  328. }
  329. }
  330. /**
  331. * Get queue messages
  332. *
  333. * @param string $queueName Queue name
  334. * @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.
  335. * @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.
  336. * @param string $peek Peek only?
  337. * @return array
  338. * @throws Microsoft_WindowsAzure_Exception
  339. */
  340. public function getMessages($queueName = '', $numOfMessages = 1, $visibilityTimeout = null, $peek = false)
  341. {
  342. if ($queueName === '') {
  343. throw new Microsoft_WindowsAzure_Exception('Queue name is not specified.');
  344. }
  345. if (!self::isValidQueueName($queueName)) {
  346. 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.');
  347. }
  348. if ($numOfMessages < 1 || $numOfMessages > 32 || intval($numOfMessages) != $numOfMessages) {
  349. throw new Microsoft_WindowsAzure_Exception('Invalid number of messages to retrieve.');
  350. }
  351. if (!is_null($visibilityTimeout) && ($visibilityTimeout <= 0 || $visibilityTimeout > 7200)) {
  352. throw new Microsoft_WindowsAzure_Exception('Visibility timeout is invalid. Maximum value is 2 hours (7200 seconds) and should be greater than zero.');
  353. }
  354. // Build query string
  355. $query = array();
  356. if ($peek) {
  357. $query['peekonly'] = 'true';
  358. }
  359. if ($numOfMessages > 1) {
  360. $query['numofmessages'] = $numOfMessages;
  361. }
  362. if (!$peek && !is_null($visibilityTimeout)) {
  363. $query['visibilitytimeout'] = $visibilityTimeout;
  364. }
  365. // Perform request
  366. $response = $this->_performRequest($queueName . '/messages', $query, Microsoft_Http_Client::GET);
  367. if ($response->isSuccessful()) {
  368. // Parse results
  369. $result = $this->_parseResponse($response);
  370. if (!$result) {
  371. return array();
  372. }
  373. $xmlMessages = null;
  374. if (count($result->QueueMessage) > 1) {
  375. $xmlMessages = $result->QueueMessage;
  376. } else {
  377. $xmlMessages = array($result->QueueMessage);
  378. }
  379. $messages = array();
  380. for ($i = 0; $i < count($xmlMessages); $i++) {
  381. $messages[] = new Microsoft_WindowsAzure_Storage_QueueMessage(
  382. (string)$xmlMessages[$i]->MessageId,
  383. (string)$xmlMessages[$i]->InsertionTime,
  384. (string)$xmlMessages[$i]->ExpirationTime,
  385. ($peek ? '' : (string)$xmlMessages[$i]->PopReceipt),
  386. ($peek ? '' : (string)$xmlMessages[$i]->TimeNextVisible),
  387. (string)$xmlMessages[$i]->DequeueCount,
  388. base64_decode((string)$xmlMessages[$i]->MessageText)
  389. );
  390. }
  391. return $messages;
  392. } else {
  393. throw new Microsoft_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
  394. }
  395. }
  396. /**
  397. * Peek queue messages
  398. *
  399. * @param string $queueName Queue name
  400. * @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.
  401. * @return array
  402. * @throws Microsoft_WindowsAzure_Exception
  403. */
  404. public function peekMessages($queueName = '', $numOfMessages = 1)
  405. {
  406. return $this->getMessages($queueName, $numOfMessages, null, true);
  407. }
  408. /**
  409. * Checks to see if a given queue has messages
  410. *
  411. * @param string $queueName Queue name
  412. * @return boolean
  413. * @throws Microsoft_WindowsAzure_Exception
  414. */
  415. public function hasMessages($queueName = '')
  416. {
  417. return count($this->peekMessages($queueName)) > 0;
  418. }
  419. /**
  420. * Clear queue messages
  421. *
  422. * @param string $queueName Queue name
  423. * @throws Microsoft_WindowsAzure_Exception
  424. */
  425. public function clearMessages($queueName = '')
  426. {
  427. if ($queueName === '') {
  428. throw new Microsoft_WindowsAzure_Exception('Queue name is not specified.');
  429. }
  430. if (!self::isValidQueueName($queueName)) {
  431. 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.');
  432. }
  433. // Perform request
  434. $response = $this->_performRequest($queueName . '/messages', array(), Microsoft_Http_Client::DELETE);
  435. if (!$response->isSuccessful()) {
  436. throw new Microsoft_WindowsAzure_Exception('Error clearing messages from queue.');
  437. }
  438. }
  439. /**
  440. * Delete queue message
  441. *
  442. * @param string $queueName Queue name
  443. * @param Microsoft_WindowsAzure_Storage_QueueMessage $message Message to delete from queue. A message retrieved using "peekMessages" can NOT be deleted!
  444. * @throws Microsoft_WindowsAzure_Exception
  445. */
  446. public function deleteMessage($queueName = '', Microsoft_WindowsAzure_Storage_QueueMessage $message)
  447. {
  448. if ($queueName === '') {
  449. throw new Microsoft_WindowsAzure_Exception('Queue name is not specified.');
  450. }
  451. if (!self::isValidQueueName($queueName)) {
  452. 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.');
  453. }
  454. if ($message->PopReceipt == '') {
  455. throw new Microsoft_WindowsAzure_Exception('A message retrieved using "peekMessages" can NOT be deleted! Use "getMessages" instead.');
  456. }
  457. // Perform request
  458. $response = $this->_performRequest($queueName . '/messages/' . $message->MessageId, array('popreceipt' => $message->PopReceipt), Microsoft_Http_Client::DELETE);
  459. if (!$response->isSuccessful()) {
  460. throw new Microsoft_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
  461. }
  462. }
  463. /**
  464. * Is valid queue name?
  465. *
  466. * @param string $queueName Queue name
  467. * @return boolean
  468. */
  469. public static function isValidQueueName($queueName = '')
  470. {
  471. if (preg_match("/^[a-z0-9][a-z0-9-]*$/", $queueName) === 0) {
  472. return false;
  473. }
  474. if (strpos($queueName, '--') !== false) {
  475. return false;
  476. }
  477. if (strtolower($queueName) != $queueName) {
  478. return false;
  479. }
  480. if (strlen($queueName) < 3 || strlen($queueName) > 63) {
  481. return false;
  482. }
  483. if (substr($queueName, -1) == '-') {
  484. return false;
  485. }
  486. return true;
  487. }
  488. /**
  489. * Get error message from Microsoft_Http_Response
  490. *
  491. * @param Microsoft_Http_Response $response Repsonse
  492. * @param string $alternativeError Alternative error message
  493. * @return string
  494. */
  495. protected function _getErrorMessage(Microsoft_Http_Response $response, $alternativeError = 'Unknown error.')
  496. {
  497. $response = $this->_parseResponse($response);
  498. if ($response && $response->Message) {
  499. return (string)$response->Message;
  500. } else {
  501. return $alternativeError;
  502. }
  503. }
  504. }