File indexing completed on 2024-06-16 05:30:01

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_Feed_Pubsubhubbub
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  * @see Zend_Feed_Pubsubhubbub
0024  */
0025 // require_once 'Zend/Feed/Pubsubhubbub.php';
0026 
0027 /**
0028  * @category   Zend
0029  * @package    Zend_Feed_Pubsubhubbub
0030  * @copyright  Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
0031  * @license    http://framework.zend.com/license/new-bsd     New BSD License
0032  */
0033 class Zend_Feed_Pubsubhubbub_Publisher
0034 {
0035     /**
0036      * An array of URLs for all Hub Servers used by the Publisher, and to
0037      * which all topic update notifications will be sent.
0038      *
0039      * @var array
0040      */
0041     protected $_hubUrls = array();
0042 
0043     /**
0044      * An array of topic (Atom or RSS feed) URLs which have been updated and
0045      * whose updated status will be notified to all Hub Servers.
0046      *
0047      * @var array
0048      */
0049     protected $_updatedTopicUrls = array();
0050 
0051     /**
0052      * An array of any errors including keys for 'response', 'hubUrl'.
0053      * The response is the actual Zend_Http_Response object.
0054      *
0055      * @var array
0056      */
0057     protected $_errors = array();
0058 
0059     /**
0060      * An array of topic (Atom or RSS feed) URLs which have been updated and
0061      * whose updated status will be notified to all Hub Servers.
0062      *
0063      * @var array
0064      */
0065     protected $_parameters = array();
0066 
0067     /**
0068      * Constructor; accepts an array or Zend_Config instance to preset
0069      * options for the Publisher without calling all supported setter
0070      * methods in turn.
0071      *
0072      * @param  array|Zend_Config $config Options array or Zend_Config instance
0073      * @throws Zend_Feed_Pubsubhubbub_Exception
0074      */
0075     public function __construct($config = null)
0076     {
0077         if ($config !== null) {
0078             $this->setConfig($config);
0079         }
0080     }
0081 
0082     /**
0083      * Process any injected configuration options
0084      *
0085      * @param  array|Zend_Config $config Options array or Zend_Config instance
0086      * @throws Zend_Feed_Pubsubhubbub_Exception
0087      * @return Zend_Feed_Pubsubhubbub_Publisher
0088      */
0089     public function setConfig($config)
0090     {
0091         if ($config instanceof Zend_Config) {
0092             $config = $config->toArray();
0093         } elseif (!is_array($config)) {
0094             // require_once 'Zend/Feed/Pubsubhubbub/Exception.php';
0095             throw new Zend_Feed_Pubsubhubbub_Exception('Array or Zend_Config object'
0096                 . 'expected, got ' . gettype($config));
0097         }
0098         if (array_key_exists('hubUrls', $config)) {
0099             $this->addHubUrls($config['hubUrls']);
0100         }
0101         if (array_key_exists('updatedTopicUrls', $config)) {
0102             $this->addUpdatedTopicUrls($config['updatedTopicUrls']);
0103         }
0104         if (array_key_exists('parameters', $config)) {
0105             $this->setParameters($config['parameters']);
0106         }
0107         return $this;
0108     }
0109 
0110     /**
0111      * Add a Hub Server URL supported by Publisher
0112      *
0113      * @param  string $url
0114      * @throws Zend_Feed_Pubsubhubbub_Exception
0115      * @return Zend_Feed_Pubsubhubbub_Publisher
0116      */
0117     public function addHubUrl($url)
0118     {
0119         if (empty($url) || !is_string($url) || !Zend_Uri::check($url)) {
0120             // require_once 'Zend/Feed/Pubsubhubbub/Exception.php';
0121             throw new Zend_Feed_Pubsubhubbub_Exception('Invalid parameter "url"'
0122                 .' of "' . $url . '" must be a non-empty string and a valid'
0123                 .'URL');
0124         }
0125         $this->_hubUrls[] = $url;
0126         return $this;
0127     }
0128 
0129     /**
0130      * Add an array of Hub Server URLs supported by Publisher
0131      *
0132      * @param  array $urls
0133      * @return Zend_Feed_Pubsubhubbub_Publisher
0134      */
0135     public function addHubUrls(array $urls)
0136     {
0137         foreach ($urls as $url) {
0138             $this->addHubUrl($url);
0139         }
0140         return $this;
0141     }
0142 
0143     /**
0144      * Remove a Hub Server URL
0145      *
0146      * @param  string $url
0147      * @return Zend_Feed_Pubsubhubbub_Publisher
0148      */
0149     public function removeHubUrl($url)
0150     {
0151         if (!in_array($url, $this->getHubUrls())) {
0152             return $this;
0153         }
0154         $key = array_search($url, $this->_hubUrls);
0155         unset($this->_hubUrls[$key]);
0156         return $this;
0157     }
0158 
0159     /**
0160      * Return an array of unique Hub Server URLs currently available
0161      *
0162      * @return array
0163      */
0164     public function getHubUrls()
0165     {
0166         $this->_hubUrls = array_unique($this->_hubUrls);
0167         return $this->_hubUrls;
0168     }
0169 
0170     /**
0171      * Add a URL to a topic (Atom or RSS feed) which has been updated
0172      *
0173      * @param  string $url
0174      * @throws Zend_Feed_Pubsubhubbub_Exception
0175      * @return Zend_Feed_Pubsubhubbub_Publisher
0176      */
0177     public function addUpdatedTopicUrl($url)
0178     {
0179         if (empty($url) || !is_string($url) || !Zend_Uri::check($url)) {
0180             // require_once 'Zend/Feed/Pubsubhubbub/Exception.php';
0181             throw new Zend_Feed_Pubsubhubbub_Exception('Invalid parameter "url"'
0182                 .' of "' . $url . '" must be a non-empty string and a valid'
0183                 .'URL');
0184         }
0185         $this->_updatedTopicUrls[] = $url;
0186         return $this;
0187     }
0188 
0189     /**
0190      * Add an array of Topic URLs which have been updated
0191      *
0192      * @param  array $urls
0193      * @return Zend_Feed_Pubsubhubbub_Publisher
0194      */
0195     public function addUpdatedTopicUrls(array $urls)
0196     {
0197         foreach ($urls as $url) {
0198             $this->addUpdatedTopicUrl($url);
0199         }
0200         return $this;
0201     }
0202 
0203     /**
0204      * Remove an updated topic URL
0205      *
0206      * @param  string $url
0207      * @return Zend_Feed_Pubsubhubbub_Publisher
0208      */
0209     public function removeUpdatedTopicUrl($url)
0210     {
0211         if (!in_array($url, $this->getUpdatedTopicUrls())) {
0212             return $this;
0213         }
0214         $key = array_search($url, $this->_updatedTopicUrls);
0215         unset($this->_updatedTopicUrls[$key]);
0216         return $this;
0217     }
0218 
0219     /**
0220      * Return an array of unique updated topic URLs currently available
0221      *
0222      * @return array
0223      */
0224     public function getUpdatedTopicUrls()
0225     {
0226         $this->_updatedTopicUrls = array_unique($this->_updatedTopicUrls);
0227         return $this->_updatedTopicUrls;
0228     }
0229 
0230     /**
0231      * Notifies a single Hub Server URL of changes
0232      *
0233      * @param  string $url The Hub Server's URL
0234      * @return void
0235      * @throws Zend_Feed_Pubsubhubbub_Exception Thrown on failure
0236      */
0237     public function notifyHub($url)
0238     {
0239         if (empty($url) || !is_string($url) || !Zend_Uri::check($url)) {
0240             // require_once 'Zend/Feed/Pubsubhubbub/Exception.php';
0241             throw new Zend_Feed_Pubsubhubbub_Exception('Invalid parameter "url"'
0242                 .' of "' . $url . '" must be a non-empty string and a valid'
0243                 .'URL');
0244         }
0245         $client = $this->_getHttpClient();
0246         $client->setUri($url);
0247         $response = $client->request();
0248         if ($response->getStatus() !== 204) {
0249             // require_once 'Zend/Feed/Pubsubhubbub/Exception.php';
0250             throw new Zend_Feed_Pubsubhubbub_Exception('Notification to Hub Server '
0251                 . 'at "' . $url . '" appears to have failed with a status code of "'
0252                 . $response->getStatus() . '" and message "'
0253                 . $response->getMessage() . '"');
0254         }
0255     }
0256 
0257     /**
0258      * Notifies all Hub Server URLs of changes
0259      *
0260      * If a Hub notification fails, certain data will be retained in an
0261      * an array retrieved using getErrors(), if a failure occurs for any Hubs
0262      * the isSuccess() check will return FALSE. This method is designed not
0263      * to needlessly fail with an Exception/Error unless from Zend_Http_Client.
0264      *
0265      * @return void
0266      * @throws Zend_Feed_Pubsubhubbub_Exception Thrown if no hubs attached
0267      */
0268     public function notifyAll()
0269     {
0270         $client = $this->_getHttpClient();
0271         $hubs   = $this->getHubUrls();
0272         if (empty($hubs)) {
0273             // require_once 'Zend/Feed/Pubsubhubbub/Exception.php';
0274             throw new Zend_Feed_Pubsubhubbub_Exception('No Hub Server URLs'
0275                 . ' have been set so no notifcations can be sent');
0276         }
0277         $this->_errors = array();
0278         foreach ($hubs as $url) {
0279             $client->setUri($url);
0280             $response = $client->request();
0281             if ($response->getStatus() !== 204) {
0282                 $this->_errors[] = array(
0283                     'response' => $response,
0284                     'hubUrl' => $url
0285                 );
0286             }
0287         }
0288     }
0289 
0290     /**
0291      * Add an optional parameter to the update notification requests
0292      *
0293      * @param  string      $name
0294      * @param  string|null $value
0295      * @throws Zend_Feed_Pubsubhubbub_Exception
0296      * @return Zend_Feed_Pubsubhubbub_Publisher
0297      */
0298     public function setParameter($name, $value = null)
0299     {
0300         if (is_array($name)) {
0301             $this->setParameters($name);
0302             return $this;
0303         }
0304         if (empty($name) || !is_string($name)) {
0305             // require_once 'Zend/Feed/Pubsubhubbub/Exception.php';
0306             throw new Zend_Feed_Pubsubhubbub_Exception('Invalid parameter "name"'
0307                 .' of "' . $name . '" must be a non-empty string');
0308         }
0309         if ($value === null) {
0310             $this->removeParameter($name);
0311             return $this;
0312         }
0313         if (empty($value) || (!is_string($value) && $value !== null)) {
0314             // require_once 'Zend/Feed/Pubsubhubbub/Exception.php';
0315             throw new Zend_Feed_Pubsubhubbub_Exception('Invalid parameter "value"'
0316                 .' of "' . $value . '" must be a non-empty string');
0317         }
0318         $this->_parameters[$name] = $value;
0319         return $this;
0320     }
0321 
0322     /**
0323      * Add an optional parameter to the update notification requests
0324      *
0325      * @param  array $parameters
0326      * @return Zend_Feed_Pubsubhubbub_Publisher
0327      */
0328     public function setParameters(array $parameters)
0329     {
0330         foreach ($parameters as $name => $value) {
0331             $this->setParameter($name, $value);
0332         }
0333         return $this;
0334     }
0335 
0336     /**
0337      * Remove an optional parameter for the notification requests
0338      *
0339      * @param  string $name
0340      * @throws Zend_Feed_Pubsubhubbub_Exception
0341      * @return Zend_Feed_Pubsubhubbub_Publisher
0342      */
0343     public function removeParameter($name)
0344     {
0345         if (empty($name) || !is_string($name)) {
0346             // require_once 'Zend/Feed/Pubsubhubbub/Exception.php';
0347             throw new Zend_Feed_Pubsubhubbub_Exception('Invalid parameter "name"'
0348                 .' of "' . $name . '" must be a non-empty string');
0349         }
0350         if (array_key_exists($name, $this->_parameters)) {
0351             unset($this->_parameters[$name]);
0352         }
0353         return $this;
0354     }
0355 
0356     /**
0357      * Return an array of optional parameters for notification requests
0358      *
0359      * @return array
0360      */
0361     public function getParameters()
0362     {
0363         return $this->_parameters;
0364     }
0365 
0366     /**
0367      * Returns a boolean indicator of whether the notifications to Hub
0368      * Servers were ALL successful. If even one failed, FALSE is returned.
0369      *
0370      * @return bool
0371      */
0372     public function isSuccess()
0373     {
0374         if (count($this->_errors) > 0) {
0375             return false;
0376         }
0377         return true;
0378     }
0379 
0380     /**
0381      * Return an array of errors met from any failures, including keys:
0382      * 'response' => the Zend_Http_Response object from the failure
0383      * 'hubUrl' => the URL of the Hub Server whose notification failed
0384      *
0385      * @return array
0386      */
0387     public function getErrors()
0388     {
0389         return $this->_errors;
0390     }
0391 
0392     /**
0393      * Get a basic prepared HTTP client for use
0394      *
0395      * @throws Zend_Feed_Pubsubhubbub_Exception
0396      * @throws Zend_Http_Client_Exception
0397      * @return Zend_Http_Client
0398      */
0399     protected function _getHttpClient()
0400     {
0401         $client = Zend_Feed_Pubsubhubbub::getHttpClient();
0402         $client->setMethod(Zend_Http_Client::POST);
0403         $client->setConfig(array(
0404             'useragent' => 'Zend_Feed_Pubsubhubbub_Publisher/' . Zend_Version::VERSION,
0405         ));
0406         $params   = array();
0407         $params[] = 'hub.mode=publish';
0408         $topics   = $this->getUpdatedTopicUrls();
0409         if (empty($topics)) {
0410             // require_once 'Zend/Feed/Pubsubhubbub/Exception.php';
0411             throw new Zend_Feed_Pubsubhubbub_Exception('No updated topic URLs'
0412                 . ' have been set');
0413         }
0414         foreach ($topics as $topicUrl) {
0415             $params[] = 'hub.url=' . urlencode($topicUrl);
0416         }
0417         $optParams = $this->getParameters();
0418         foreach ($optParams as $name => $value) {
0419             $params[] = urlencode($name) . '=' . urlencode($value);
0420         }
0421         $paramString = implode('&', $params);
0422         $client->setRawData($paramString, 'application/x-www-form-urlencoded');
0423         return $client;
0424     }
0425 }