web/lib/Zend/Queue.php
changeset 64 162c1de6545a
parent 19 1c2f13fd785c
child 68 ecaf28ffe26e
equal deleted inserted replaced
63:5b37998e522e 64:162c1de6545a
       
     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 license@zend.com so we can send you a copy immediately.
       
    14  *
       
    15  * @category   Zend
       
    16  * @package    Zend_Queue
       
    17  * @copyright  Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
       
    18  * @license    http://framework.zend.com/license/new-bsd     New BSD License
       
    19  * @version    $Id: Queue.php 20096 2010-01-06 02:05:09Z bkarwin $
       
    20  */
       
    21 
       
    22 /**
       
    23  * Class for connecting to queues performing common operations.
       
    24  *
       
    25  * @category   Zend
       
    26  * @package    Zend_Queue
       
    27  * @copyright  Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
       
    28  * @license    http://framework.zend.com/license/new-bsd     New BSD License
       
    29  */
       
    30 class Zend_Queue implements Countable
       
    31 {
       
    32     /**
       
    33      * Use the TIMEOUT constant in the config of a Zend_Queue
       
    34      */
       
    35     const TIMEOUT = 'timeout';
       
    36 
       
    37     /**
       
    38      * Default visibility passed to count
       
    39      */
       
    40     const VISIBILITY_TIMEOUT = 30;
       
    41 
       
    42     /**
       
    43      * Use the NAME constant in the config of Zend_Queue
       
    44      */
       
    45     const NAME = 'name';
       
    46 
       
    47     /**
       
    48      * @var Zend_Queue_Adapter_AdapterInterface
       
    49      */
       
    50     protected $_adapter = null;
       
    51 
       
    52     /**
       
    53      * User-provided configuration
       
    54      *
       
    55      * @var array
       
    56      */
       
    57     protected $_options = array();
       
    58 
       
    59     /**
       
    60      * Zend_Queue_Message class
       
    61      *
       
    62      * @var string
       
    63      */
       
    64     protected $_messageClass = 'Zend_Queue_Message';
       
    65 
       
    66     /**
       
    67      * Zend_Queue_Message_Iterator class
       
    68      *
       
    69      * @var string
       
    70      */
       
    71     protected $_messageSetClass = 'Zend_Queue_Message_Iterator';
       
    72 
       
    73     /**
       
    74      * @var Zend_Log
       
    75      */
       
    76     protected $_logger = null;
       
    77 
       
    78     /**
       
    79      * Constructor
       
    80      *
       
    81      * Can be called as
       
    82      * $queue = new Zend_Queue($config);
       
    83      * - or -
       
    84      * $queue = new Zend_Queue('array', $config);
       
    85      * - or -
       
    86      * $queue = new Zend_Queue(null, $config); // Zend_Queue->createQueue();
       
    87      *
       
    88      * @param  string|Zend_Queue_Adapter|array|Zend_Config|null String or adapter instance, or options array or Zend_Config instance
       
    89      * @param  Zend_Config|array $options Zend_Config or a configuration array
       
    90      * @return void
       
    91      */
       
    92     public function __construct($spec, $options = array())
       
    93     {
       
    94         $adapter = null;
       
    95         if ($spec instanceof Zend_Queue_Adapter_AdapterInterface) {
       
    96             $adapter = $spec;
       
    97         } elseif (is_string($spec)) {
       
    98             $adapter = $spec;
       
    99         } elseif ($spec instanceof Zend_Config) {
       
   100             $options = $spec->toArray();
       
   101         } elseif (is_array($spec)) {
       
   102             $options = $spec;
       
   103         }
       
   104 
       
   105         // last minute error checking
       
   106         if ((null === $adapter)
       
   107             && (!is_array($options) && (!$options instanceof Zend_Config))
       
   108         ) {
       
   109             require_once 'Zend/Queue/Exception.php';
       
   110             throw new Zend_Queue_Exception('No valid params passed to constructor');
       
   111         }
       
   112 
       
   113         // Now continue as we would if we were a normal constructor
       
   114         if ($options instanceof Zend_Config) {
       
   115             $options = $options->toArray();
       
   116         } elseif (!is_array($options)) {
       
   117             $options = array();
       
   118         }
       
   119 
       
   120         // Make sure we have some defaults to work with
       
   121         if (!isset($options[self::TIMEOUT])) {
       
   122             $options[self::TIMEOUT] = self::VISIBILITY_TIMEOUT;
       
   123         }
       
   124 
       
   125         // Make sure all defaults are appropriately set.
       
   126         if (!array_key_exists('timeout', $options)) {
       
   127             $options[self::TIMEOUT] = self::VISIBILITY_TIMEOUT;
       
   128         }
       
   129         if (array_key_exists('messageClass', $options)) {
       
   130             $this->setMessageClass($options['messageClass']);
       
   131         }
       
   132         if (array_key_exists('messageSetClass', $options)) {
       
   133             $this->setMessageSetClass($options['messageSetClass']);
       
   134         }
       
   135 
       
   136         $this->setOptions($options);
       
   137 
       
   138         // if we were passed an adapter we either build the $adapter or use it
       
   139         if (null !== $adapter) {
       
   140             $this->setAdapter($adapter);
       
   141         }
       
   142     }
       
   143 
       
   144     /**
       
   145      * Set queue options
       
   146      *
       
   147      * @param  array $options
       
   148      * @return Zend_Queue
       
   149      */
       
   150     public function setOptions(array $options)
       
   151     {
       
   152         $this->_options = array_merge($this->_options, $options);
       
   153         return $this;
       
   154     }
       
   155 
       
   156     /**
       
   157      * Set an individual configuration option
       
   158      *
       
   159      * @param  string $name
       
   160      * @param  mixed $value
       
   161      * @return Zend_Queue
       
   162      */
       
   163     public function setOption($name, $value)
       
   164     {
       
   165         $this->_options[(string) $name] = $value;
       
   166         return $this;
       
   167     }
       
   168 
       
   169     /**
       
   170      * Returns the configuration options for the queue
       
   171      *
       
   172      * @return array
       
   173      */
       
   174     public function getOptions()
       
   175     {
       
   176         return $this->_options;
       
   177     }
       
   178 
       
   179     /**
       
   180      * Determine if a requested option has been defined
       
   181      *
       
   182      * @param  string $name
       
   183      * @return bool
       
   184      */
       
   185     public function hasOption($name)
       
   186     {
       
   187         return array_key_exists($name, $this->_options);
       
   188     }
       
   189 
       
   190     /**
       
   191      * Retrieve a single option
       
   192      *
       
   193      * @param  string $name
       
   194      * @return null|mixed Returns null if option does not exist; option value otherwise
       
   195      */
       
   196     public function getOption($name)
       
   197     {
       
   198         if ($this->hasOption($name)) {
       
   199             return $this->_options[$name];
       
   200         }
       
   201         return null;
       
   202     }
       
   203 
       
   204     /**
       
   205      * Set the adapter for this queue
       
   206      *
       
   207      * @param  string|Zend_Queue_Adapter_AdapterInterface $adapter
       
   208      * @return Zend_Queue Provides a fluent interface
       
   209      */
       
   210     public function setAdapter($adapter)
       
   211     {
       
   212         if (is_string($adapter)) {
       
   213             if (null === ($adapterNamespace = $this->getOption('adapterNamespace'))) {
       
   214                 $adapterNamespace = 'Zend_Queue_Adapter';
       
   215             }
       
   216 
       
   217             $adapterName = str_replace(
       
   218                 ' ',
       
   219                 '_',
       
   220                 ucwords(
       
   221                     str_replace(
       
   222                         '_',
       
   223                         ' ',
       
   224                         strtolower($adapterNamespace . '_' . $adapter)
       
   225                     )
       
   226                 )
       
   227             );
       
   228 
       
   229             if (!class_exists($adapterName)) {
       
   230                 require_once 'Zend/Loader.php';
       
   231                 Zend_Loader::loadClass($adapterName);
       
   232             }
       
   233 
       
   234             /*
       
   235              * Create an instance of the adapter class.
       
   236              * Pass the configuration to the adapter class constructor.
       
   237              */
       
   238             $adapter = new $adapterName($this->getOptions(), $this);
       
   239         }
       
   240 
       
   241         if (!$adapter instanceof Zend_Queue_Adapter_AdapterInterface) {
       
   242             require_once 'Zend/Queue/Exception.php';
       
   243             throw new Zend_Queue_Exception("Adapter class '" . get_class($adapterName) . "' does not implement Zend_Queue_Adapter_AdapterInterface");
       
   244         }
       
   245 
       
   246         $this->_adapter = $adapter;
       
   247 
       
   248         $this->_adapter->setQueue($this);
       
   249 
       
   250         if (null !== ($name = $this->getOption(self::NAME))) {
       
   251             $this->_setName($name);
       
   252         }
       
   253 
       
   254         return $this;
       
   255     }
       
   256 
       
   257     /**
       
   258      * Get the adapter for this queue
       
   259      *
       
   260      * @return Zend_Queue_Adapter_AdapterInterface
       
   261      */
       
   262     public function getAdapter()
       
   263     {
       
   264         return $this->_adapter;
       
   265     }
       
   266 
       
   267     /**
       
   268      * @param  string $className
       
   269      * @return Zend_Queue Provides a fluent interface
       
   270      */
       
   271     public function setMessageClass($className)
       
   272     {
       
   273         $this->_messageClass = (string) $className;
       
   274         return $this;
       
   275     }
       
   276 
       
   277     /**
       
   278      * @return string
       
   279      */
       
   280     public function getMessageClass()
       
   281     {
       
   282         return $this->_messageClass;
       
   283     }
       
   284 
       
   285     /**
       
   286      * @param  string $className
       
   287      * @return Zend_Queue Provides a fluent interface
       
   288      */
       
   289     public function setMessageSetClass($className)
       
   290     {
       
   291         $this->_messageSetClass = (string) $className;
       
   292         return $this;
       
   293     }
       
   294 
       
   295     /**
       
   296      * @return string
       
   297      */
       
   298     public function getMessageSetClass()
       
   299     {
       
   300         return $this->_messageSetClass;
       
   301     }
       
   302 
       
   303     /**
       
   304      * Get the name of the queue
       
   305      *
       
   306      * Note: _setName() used to exist, but it caused confusion with createQueue
       
   307      * Will evaluate later to see if we should add it back in.
       
   308      *
       
   309      * @return string
       
   310      */
       
   311     public function getName()
       
   312     {
       
   313         return $this->getOption(self::NAME);
       
   314     }
       
   315 
       
   316     /**
       
   317      * Create a new queue
       
   318      *
       
   319      * @param  string           $name    queue name
       
   320      * @param  integer          $timeout default visibility timeout
       
   321      * @return Zend_Queue|false
       
   322      * @throws Zend_Queue_Exception
       
   323      */
       
   324     public function createQueue($name, $timeout = null)
       
   325     {
       
   326         if (!is_string($name)) {
       
   327             require_once 'Zend/Queue/Exception.php';
       
   328             throw new Zend_Queue_Exception('$name is not a string');
       
   329         }
       
   330 
       
   331         if ((null !== $timeout) && !is_integer($timeout)) {
       
   332             require_once 'Zend/Queue/Exception.php';
       
   333             throw new Zend_Queue_Exception('$timeout must be an integer');
       
   334         }
       
   335 
       
   336         // Default to standard timeout
       
   337         if (null === $timeout) {
       
   338             $timeout = $this->getOption(self::TIMEOUT);
       
   339         }
       
   340 
       
   341         // Some queues allow you to create on the fly, but cannot return
       
   342         // a list of queues.  Stomp protocol for example.
       
   343         if ($this->isSupported('create')) {
       
   344             if ($this->getAdapter()->isExists($name)) {
       
   345                 return false;
       
   346             }
       
   347 
       
   348             if (!$this->getAdapter()->create($name, $timeout)) {
       
   349                 return false;
       
   350             }
       
   351         }
       
   352 
       
   353         $options = array(
       
   354             self::NAME  => $name,
       
   355             'timeout'   => $timeout
       
   356         );
       
   357 
       
   358         return new self($this->getAdapter(), $options);
       
   359     }
       
   360 
       
   361     /**
       
   362      * Delete the queue this object is working on.
       
   363      *
       
   364      * This queue is disabled, regardless of the outcome of the deletion
       
   365      * of the queue, because the programmers intent is to disable this queue.
       
   366      *
       
   367      * @return boolean
       
   368      */
       
   369     public function deleteQueue()
       
   370     {
       
   371         if ($this->isSupported('delete')) {
       
   372             $deleted = $this->getAdapter()->delete($this->getName());
       
   373         }
       
   374         else {
       
   375             $deleted = true;
       
   376         }
       
   377 
       
   378         /**
       
   379          * @see Zend_Queue_Adapter_Null
       
   380          */
       
   381         require_once('Zend/Queue/Adapter/Null.php');
       
   382         $this->setAdapter(new Zend_Queue_Adapter_Null($this->getOptions()));
       
   383 
       
   384         return $deleted;
       
   385     }
       
   386 
       
   387     /**
       
   388      * Delete a message from the queue
       
   389      *
       
   390      * Returns true if the message is deleted, false if the deletion is
       
   391      * unsuccessful.
       
   392      *
       
   393      * Returns true if the adapter doesn't support message deletion.
       
   394      *
       
   395      * @param  Zend_Queue_Message $message
       
   396      * @return boolean
       
   397      * @throws Zend_Queue_Exception
       
   398      */
       
   399     public function deleteMessage(Zend_Queue_Message $message)
       
   400     {
       
   401         if ($this->getAdapter()->isSupported('deleteMessage')) {
       
   402             return $this->getAdapter()->deleteMessage($message);
       
   403         }
       
   404         return true;
       
   405     }
       
   406 
       
   407     /**
       
   408      * Send a message to the queue
       
   409      *
       
   410      * @param  mixed $message message
       
   411      * @return Zend_Queue_Message
       
   412      * @throws Zend_Queue_Exception
       
   413      */
       
   414     public function send($message)
       
   415     {
       
   416         return $this->getAdapter()->send($message);
       
   417     }
       
   418 
       
   419     /**
       
   420      * Returns the approximate number of messages in the queue
       
   421      *
       
   422      * @return integer
       
   423      */
       
   424     public function count()
       
   425     {
       
   426         if ($this->getAdapter()->isSupported('count')) {
       
   427             return $this->getAdapter()->count();
       
   428         }
       
   429         return 0;
       
   430     }
       
   431 
       
   432     /**
       
   433      * Return the first element in the queue
       
   434      *
       
   435      * @param  integer $maxMessages
       
   436      * @param  integer $timeout
       
   437      * @return Zend_Queue_Message_Iterator
       
   438      */
       
   439     public function receive($maxMessages=null, $timeout=null)
       
   440     {
       
   441         if (($maxMessages !== null) && !is_integer($maxMessages)) {
       
   442             require_once 'Zend/Queue/Exception.php';
       
   443             throw new Zend_Queue_Exception('$maxMessages must be an integer or null');
       
   444         }
       
   445 
       
   446         if (($timeout !== null) && !is_integer($timeout)) {
       
   447             require_once 'Zend/Queue/Exception.php';
       
   448             throw new Zend_Queue_Exception('$timeout must be an integer or null');
       
   449         }
       
   450 
       
   451         // Default to returning only one message
       
   452         if ($maxMessages === null) {
       
   453             $maxMessages = 1;
       
   454         }
       
   455 
       
   456         // Default to standard timeout
       
   457         if ($timeout === null) {
       
   458             $timeout = $this->getOption(self::TIMEOUT);
       
   459         }
       
   460 
       
   461         return $this->getAdapter()->receive($maxMessages, $timeout);
       
   462     }
       
   463 
       
   464     /**
       
   465      * Return a list of queue capabilities functions
       
   466      *
       
   467      * $array['function name'] = true or false
       
   468      * true is supported, false is not supported.
       
   469      *
       
   470      * @param  string $name
       
   471      * @return array
       
   472      */
       
   473     public function getCapabilities()
       
   474     {
       
   475         return $this->getAdapter()->getCapabilities();
       
   476     }
       
   477 
       
   478     /**
       
   479      * Indicates if a function is supported or not.
       
   480      *
       
   481      * @param  string $name
       
   482      * @return boolean
       
   483      */
       
   484     public function isSupported($name)
       
   485     {
       
   486         $translation = array(
       
   487             'deleteQueue' => 'delete',
       
   488             'createQueue' => 'create'
       
   489         );
       
   490 
       
   491         if (isset($translation[$name])) {
       
   492             $name = $translation[$name];
       
   493         }
       
   494 
       
   495         return $this->getAdapter()->isSupported($name);
       
   496     }
       
   497 
       
   498     /**
       
   499      * Get an array of all available queues
       
   500      *
       
   501      * @return array
       
   502      * @throws Zend_Queue_Exception
       
   503      */
       
   504     public function getQueues()
       
   505     {
       
   506         if (!$this->isSupported('getQueues')) {
       
   507             throw new Zend_Queue_Exception( __FUNCTION__ . '() is not supported by ' . get_class($this->getAdapter()));
       
   508         }
       
   509 
       
   510         return $this->getAdapter()->getQueues();
       
   511     }
       
   512 
       
   513     /**
       
   514      * Set the name of the queue
       
   515      *
       
   516      * This is AN UNSUPPORTED FUNCTION
       
   517      *
       
   518      * @param  string           $name
       
   519      * @return Zend_Queue|false Provides a fluent interface
       
   520      */
       
   521     protected function _setName($name)
       
   522     {
       
   523         if (!is_string($name)) {
       
   524             /**
       
   525              * @see Zend_Queue_Exception
       
   526              */
       
   527             require_once 'Zend/Queue/Exception.php';
       
   528             throw new Zend_Queue_Exception("$name is not a string");
       
   529         }
       
   530 
       
   531         if ($this->getAdapter()->isSupported('create')) {
       
   532             if (!$this->getAdapter()->isExists($name)) {
       
   533                 $timeout = $this->getOption(self::TIMEOUT);
       
   534 
       
   535                 if (!$this->getAdapter()->create($name, $timeout)) {
       
   536                     // Unable to create the new queue
       
   537                     return false;
       
   538                 }
       
   539             }
       
   540         }
       
   541 
       
   542         $this->setOption(self::NAME, $name);
       
   543 
       
   544         return $this;
       
   545     }
       
   546 
       
   547     /**
       
   548      * returns a listing of Zend_Queue details.
       
   549      * useful for debugging
       
   550      *
       
   551      * @return array
       
   552      */
       
   553     public function debugInfo()
       
   554     {
       
   555         $info = array();
       
   556         $info['self']                     = get_class($this);
       
   557         $info['adapter']                  = get_class($this->getAdapter());
       
   558         foreach ($this->getAdapter()->getCapabilities() as $feature => $supported) {
       
   559             $info['adapter-' . $feature]  = ($supported) ? 'yes' : 'no';
       
   560         }
       
   561         $info['options']                  = $this->getOptions();
       
   562         $info['options']['driverOptions'] = '[hidden]';
       
   563         $info['currentQueue']             = $this->getName();
       
   564         $info['messageClass']             = $this->getMessageClass();
       
   565         $info['messageSetClass']          = $this->getMessageSetClass();
       
   566 
       
   567         return $info;
       
   568     }
       
   569 }