File indexing completed on 2024-12-22 05:37:17
0001 <?php 0002 /** 0003 * Zend Framework 0004 * 0005 * LICENSE 0006 * 0007 * This source file is subject to the new BSD license that is bundled 0008 * with this package in the file LICENSE.txt. 0009 * It is also available through the world-wide-web at this URL: 0010 * http://framework.zend.com/license/new-bsd 0011 * If you did not receive a copy of the license and are unable to 0012 * obtain it through the world-wide-web, please send an email 0013 * to license@zend.com so we can send you a copy immediately. 0014 * 0015 * @category Zend 0016 * @package Zend_Queue 0017 * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) 0018 * @license http://framework.zend.com/license/new-bsd New BSD License 0019 * @version $Id$ 0020 */ 0021 0022 /** 0023 * Class for connecting to queues performing common operations. 0024 * 0025 * @category Zend 0026 * @package Zend_Queue 0027 * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) 0028 * @license http://framework.zend.com/license/new-bsd New BSD License 0029 */ 0030 class Zend_Queue implements Countable 0031 { 0032 /** 0033 * Use the TIMEOUT constant in the config of a Zend_Queue 0034 */ 0035 const TIMEOUT = 'timeout'; 0036 0037 /** 0038 * Default visibility passed to count 0039 */ 0040 const VISIBILITY_TIMEOUT = 30; 0041 0042 /** 0043 * Use the NAME constant in the config of Zend_Queue 0044 */ 0045 const NAME = 'name'; 0046 0047 /** 0048 * @var Zend_Queue_Adapter_AdapterInterface 0049 */ 0050 protected $_adapter = null; 0051 0052 /** 0053 * User-provided configuration 0054 * 0055 * @var array 0056 */ 0057 protected $_options = array(); 0058 0059 /** 0060 * Zend_Queue_Message class 0061 * 0062 * @var string 0063 */ 0064 protected $_messageClass = 'Zend_Queue_Message'; 0065 0066 /** 0067 * Zend_Queue_Message_Iterator class 0068 * 0069 * @var string 0070 */ 0071 protected $_messageSetClass = 'Zend_Queue_Message_Iterator'; 0072 0073 /** 0074 * @var Zend_Log 0075 */ 0076 protected $_logger = null; 0077 0078 /** 0079 * Constructor 0080 * 0081 * Can be called as 0082 * $queue = new Zend_Queue($config); 0083 * - or - 0084 * $queue = new Zend_Queue('array', $config); 0085 * - or - 0086 * $queue = new Zend_Queue(null, $config); // Zend_Queue->createQueue(); 0087 * 0088 * @param string|Zend_Queue_Adapter|array|Zend_Config|null String or adapter instance, or options array or Zend_Config instance 0089 * @param Zend_Config|array $options Zend_Config or a configuration array 0090 * @return void 0091 */ 0092 public function __construct($spec, $options = array()) 0093 { 0094 $adapter = null; 0095 if ($spec instanceof Zend_Queue_Adapter_AdapterInterface) { 0096 $adapter = $spec; 0097 } elseif (is_string($spec)) { 0098 $adapter = $spec; 0099 } elseif ($spec instanceof Zend_Config) { 0100 $options = $spec->toArray(); 0101 } elseif (is_array($spec)) { 0102 $options = $spec; 0103 } 0104 0105 // last minute error checking 0106 if ((null === $adapter) 0107 && (!is_array($options) && (!$options instanceof Zend_Config)) 0108 ) { 0109 // require_once 'Zend/Queue/Exception.php'; 0110 throw new Zend_Queue_Exception('No valid params passed to constructor'); 0111 } 0112 0113 // Now continue as we would if we were a normal constructor 0114 if ($options instanceof Zend_Config) { 0115 $options = $options->toArray(); 0116 } elseif (!is_array($options)) { 0117 $options = array(); 0118 } 0119 0120 // Make sure we have some defaults to work with 0121 if (!isset($options[self::TIMEOUT])) { 0122 $options[self::TIMEOUT] = self::VISIBILITY_TIMEOUT; 0123 } 0124 0125 // Make sure all defaults are appropriately set. 0126 if (!array_key_exists('timeout', $options)) { 0127 $options[self::TIMEOUT] = self::VISIBILITY_TIMEOUT; 0128 } 0129 if (array_key_exists('messageClass', $options)) { 0130 $this->setMessageClass($options['messageClass']); 0131 } 0132 if (array_key_exists('messageSetClass', $options)) { 0133 $this->setMessageSetClass($options['messageSetClass']); 0134 } 0135 0136 $this->setOptions($options); 0137 0138 // if we were passed an adapter we either build the $adapter or use it 0139 if (null !== $adapter) { 0140 $this->setAdapter($adapter); 0141 } 0142 } 0143 0144 /** 0145 * Set queue options 0146 * 0147 * @param array $options 0148 * @return Zend_Queue 0149 */ 0150 public function setOptions(array $options) 0151 { 0152 $this->_options = array_merge($this->_options, $options); 0153 return $this; 0154 } 0155 0156 /** 0157 * Set an individual configuration option 0158 * 0159 * @param string $name 0160 * @param mixed $value 0161 * @return Zend_Queue 0162 */ 0163 public function setOption($name, $value) 0164 { 0165 $this->_options[(string) $name] = $value; 0166 return $this; 0167 } 0168 0169 /** 0170 * Returns the configuration options for the queue 0171 * 0172 * @return array 0173 */ 0174 public function getOptions() 0175 { 0176 return $this->_options; 0177 } 0178 0179 /** 0180 * Determine if a requested option has been defined 0181 * 0182 * @param string $name 0183 * @return bool 0184 */ 0185 public function hasOption($name) 0186 { 0187 return array_key_exists($name, $this->_options); 0188 } 0189 0190 /** 0191 * Retrieve a single option 0192 * 0193 * @param string $name 0194 * @return null|mixed Returns null if option does not exist; option value otherwise 0195 */ 0196 public function getOption($name) 0197 { 0198 if ($this->hasOption($name)) { 0199 return $this->_options[$name]; 0200 } 0201 return null; 0202 } 0203 0204 /** 0205 * Set the adapter for this queue 0206 * 0207 * @param string|Zend_Queue_Adapter_AdapterInterface $adapter 0208 * @return Zend_Queue Provides a fluent interface 0209 */ 0210 public function setAdapter($adapter) 0211 { 0212 if (is_string($adapter)) { 0213 if (null === ($adapterNamespace = $this->getOption('adapterNamespace'))) { 0214 $adapterNamespace = 'Zend_Queue_Adapter'; 0215 } 0216 0217 $adapterName = str_replace( 0218 ' ', 0219 '_', 0220 ucwords( 0221 str_replace( 0222 '_', 0223 ' ', 0224 strtolower($adapterNamespace . '_' . $adapter) 0225 ) 0226 ) 0227 ); 0228 0229 if (!class_exists($adapterName)) { 0230 // require_once 'Zend/Loader.php'; 0231 Zend_Loader::loadClass($adapterName); 0232 } 0233 0234 /* 0235 * Create an instance of the adapter class. 0236 * Pass the configuration to the adapter class constructor. 0237 */ 0238 $adapter = new $adapterName($this->getOptions(), $this); 0239 } 0240 0241 if (!$adapter instanceof Zend_Queue_Adapter_AdapterInterface) { 0242 // require_once 'Zend/Queue/Exception.php'; 0243 throw new Zend_Queue_Exception("Adapter class '" . get_class($adapterName) . "' does not implement Zend_Queue_Adapter_AdapterInterface"); 0244 } 0245 0246 $this->_adapter = $adapter; 0247 0248 $this->_adapter->setQueue($this); 0249 0250 if (null !== ($name = $this->getOption(self::NAME))) { 0251 $this->_setName($name); 0252 } 0253 0254 return $this; 0255 } 0256 0257 /** 0258 * Get the adapter for this queue 0259 * 0260 * @return Zend_Queue_Adapter_AdapterInterface 0261 */ 0262 public function getAdapter() 0263 { 0264 return $this->_adapter; 0265 } 0266 0267 /** 0268 * @param string $className 0269 * @return Zend_Queue Provides a fluent interface 0270 */ 0271 public function setMessageClass($className) 0272 { 0273 $this->_messageClass = (string) $className; 0274 return $this; 0275 } 0276 0277 /** 0278 * @return string 0279 */ 0280 public function getMessageClass() 0281 { 0282 return $this->_messageClass; 0283 } 0284 0285 /** 0286 * @param string $className 0287 * @return Zend_Queue Provides a fluent interface 0288 */ 0289 public function setMessageSetClass($className) 0290 { 0291 $this->_messageSetClass = (string) $className; 0292 return $this; 0293 } 0294 0295 /** 0296 * @return string 0297 */ 0298 public function getMessageSetClass() 0299 { 0300 return $this->_messageSetClass; 0301 } 0302 0303 /** 0304 * Get the name of the queue 0305 * 0306 * Note: _setName() used to exist, but it caused confusion with createQueue 0307 * Will evaluate later to see if we should add it back in. 0308 * 0309 * @return string 0310 */ 0311 public function getName() 0312 { 0313 return $this->getOption(self::NAME); 0314 } 0315 0316 /** 0317 * Create a new queue 0318 * 0319 * @param string $name queue name 0320 * @param integer $timeout default visibility timeout 0321 * @return Zend_Queue|false 0322 * @throws Zend_Queue_Exception 0323 */ 0324 public function createQueue($name, $timeout = null) 0325 { 0326 if (!is_string($name)) { 0327 // require_once 'Zend/Queue/Exception.php'; 0328 throw new Zend_Queue_Exception('$name is not a string'); 0329 } 0330 0331 if ((null !== $timeout) && !is_integer($timeout)) { 0332 // require_once 'Zend/Queue/Exception.php'; 0333 throw new Zend_Queue_Exception('$timeout must be an integer'); 0334 } 0335 0336 // Default to standard timeout 0337 if (null === $timeout) { 0338 $timeout = $this->getOption(self::TIMEOUT); 0339 } 0340 0341 // Some queues allow you to create on the fly, but cannot return 0342 // a list of queues. Stomp protocol for example. 0343 if ($this->isSupported('create')) { 0344 if ($this->getAdapter()->isExists($name)) { 0345 return false; 0346 } 0347 0348 if (!$this->getAdapter()->create($name, $timeout)) { 0349 return false; 0350 } 0351 } 0352 0353 $options = array( 0354 self::NAME => $name, 0355 'timeout' => $timeout 0356 ); 0357 0358 return new self($this->getAdapter(), $options); 0359 } 0360 0361 /** 0362 * Delete the queue this object is working on. 0363 * 0364 * This queue is disabled, regardless of the outcome of the deletion 0365 * of the queue, because the programmers intent is to disable this queue. 0366 * 0367 * @return boolean 0368 */ 0369 public function deleteQueue() 0370 { 0371 if ($this->isSupported('delete')) { 0372 $deleted = $this->getAdapter()->delete($this->getName()); 0373 } 0374 else { 0375 $deleted = true; 0376 } 0377 0378 /** 0379 * @see Zend_Queue_Adapter_Null 0380 */ 0381 // require_once('Zend/Queue/Adapter/Null.php'); 0382 $this->setAdapter(new Zend_Queue_Adapter_Null($this->getOptions())); 0383 0384 return $deleted; 0385 } 0386 0387 /** 0388 * Delete a message from the queue 0389 * 0390 * Returns true if the message is deleted, false if the deletion is 0391 * unsuccessful. 0392 * 0393 * Returns true if the adapter doesn't support message deletion. 0394 * 0395 * @param Zend_Queue_Message $message 0396 * @return boolean 0397 * @throws Zend_Queue_Exception 0398 */ 0399 public function deleteMessage(Zend_Queue_Message $message) 0400 { 0401 if ($this->getAdapter()->isSupported('deleteMessage')) { 0402 return $this->getAdapter()->deleteMessage($message); 0403 } 0404 return true; 0405 } 0406 0407 /** 0408 * Send a message to the queue 0409 * 0410 * @param mixed $message message 0411 * @return Zend_Queue_Message 0412 * @throws Zend_Queue_Exception 0413 */ 0414 public function send($message) 0415 { 0416 return $this->getAdapter()->send($message); 0417 } 0418 0419 /** 0420 * Returns the approximate number of messages in the queue 0421 * 0422 * @return integer 0423 */ 0424 public function count() 0425 { 0426 if ($this->getAdapter()->isSupported('count')) { 0427 return $this->getAdapter()->count(); 0428 } 0429 return 0; 0430 } 0431 0432 /** 0433 * Return the first element in the queue 0434 * 0435 * @param integer $maxMessages 0436 * @param integer $timeout 0437 * @return Zend_Queue_Message_Iterator 0438 */ 0439 public function receive($maxMessages=null, $timeout=null) 0440 { 0441 if (($maxMessages !== null) && !is_integer($maxMessages)) { 0442 // require_once 'Zend/Queue/Exception.php'; 0443 throw new Zend_Queue_Exception('$maxMessages must be an integer or null'); 0444 } 0445 0446 if (($timeout !== null) && !is_integer($timeout)) { 0447 // require_once 'Zend/Queue/Exception.php'; 0448 throw new Zend_Queue_Exception('$timeout must be an integer or null'); 0449 } 0450 0451 // Default to returning only one message 0452 if ($maxMessages === null) { 0453 $maxMessages = 1; 0454 } 0455 0456 // Default to standard timeout 0457 if ($timeout === null) { 0458 $timeout = $this->getOption(self::TIMEOUT); 0459 } 0460 0461 return $this->getAdapter()->receive($maxMessages, $timeout); 0462 } 0463 0464 /** 0465 * Return a list of queue capabilities functions 0466 * 0467 * $array['function name'] = true or false 0468 * true is supported, false is not supported. 0469 * 0470 * @param string $name 0471 * @return array 0472 */ 0473 public function getCapabilities() 0474 { 0475 return $this->getAdapter()->getCapabilities(); 0476 } 0477 0478 /** 0479 * Indicates if a function is supported or not. 0480 * 0481 * @param string $name 0482 * @return boolean 0483 */ 0484 public function isSupported($name) 0485 { 0486 $translation = array( 0487 'deleteQueue' => 'delete', 0488 'createQueue' => 'create' 0489 ); 0490 0491 if (isset($translation[$name])) { 0492 $name = $translation[$name]; 0493 } 0494 0495 return $this->getAdapter()->isSupported($name); 0496 } 0497 0498 /** 0499 * Get an array of all available queues 0500 * 0501 * @return array 0502 * @throws Zend_Queue_Exception 0503 */ 0504 public function getQueues() 0505 { 0506 if (!$this->isSupported('getQueues')) { 0507 throw new Zend_Queue_Exception( __FUNCTION__ . '() is not supported by ' . get_class($this->getAdapter())); 0508 } 0509 0510 return $this->getAdapter()->getQueues(); 0511 } 0512 0513 /** 0514 * Set the name of the queue 0515 * 0516 * This is AN UNSUPPORTED FUNCTION 0517 * 0518 * @param string $name 0519 * @return Zend_Queue|false Provides a fluent interface 0520 */ 0521 protected function _setName($name) 0522 { 0523 if (!is_string($name)) { 0524 /** 0525 * @see Zend_Queue_Exception 0526 */ 0527 // require_once 'Zend/Queue/Exception.php'; 0528 throw new Zend_Queue_Exception("$name is not a string"); 0529 } 0530 0531 if ($this->getAdapter()->isSupported('create')) { 0532 if (!$this->getAdapter()->isExists($name)) { 0533 $timeout = $this->getOption(self::TIMEOUT); 0534 0535 if (!$this->getAdapter()->create($name, $timeout)) { 0536 // Unable to create the new queue 0537 return false; 0538 } 0539 } 0540 } 0541 0542 $this->setOption(self::NAME, $name); 0543 0544 return $this; 0545 } 0546 0547 /** 0548 * returns a listing of Zend_Queue details. 0549 * useful for debugging 0550 * 0551 * @return array 0552 */ 0553 public function debugInfo() 0554 { 0555 $info = array(); 0556 $info['self'] = get_class($this); 0557 $info['adapter'] = get_class($this->getAdapter()); 0558 foreach ($this->getAdapter()->getCapabilities() as $feature => $supported) { 0559 $info['adapter-' . $feature] = ($supported) ? 'yes' : 'no'; 0560 } 0561 $info['options'] = $this->getOptions(); 0562 $info['options']['driverOptions'] = '[hidden]'; 0563 $info['currentQueue'] = $this->getName(); 0564 $info['messageClass'] = $this->getMessageClass(); 0565 $info['messageSetClass'] = $this->getMessageSetClass(); 0566 0567 return $info; 0568 } 0569 }