File indexing completed on 2024-12-22 05:36:38

0001 <?php
0002 
0003 /**
0004  * Zend Framework
0005  *
0006  * LICENSE
0007  *
0008  * This source file is subject to the new BSD license that is bundled
0009  * with this package in the file LICENSE.txt.
0010  * It is also available through the world-wide-web at this URL:
0011  * http://framework.zend.com/license/new-bsd
0012  * If you did not receive a copy of the license and are unable to
0013  * obtain it through the world-wide-web, please send an email
0014  * to license@zend.com so we can send you a copy immediately.
0015  *
0016  * @category   Zend
0017  * @package    Zend_Feed
0018  * @copyright  Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
0019  * @license    http://framework.zend.com/license/new-bsd     New BSD License
0020  * @version    $Id$
0021  */
0022 
0023 
0024 /**
0025  * @see Zend_Feed_Entry_Abstract
0026  */
0027 // require_once 'Zend/Feed/Entry/Abstract.php';
0028 
0029 /** @see Zend_Xml_Security */
0030 // require_once 'Zend/Xml/Security.php';
0031 
0032 /**
0033  * Concrete class for working with Atom entries.
0034  *
0035  * @category   Zend
0036  * @package    Zend_Feed
0037  * @copyright  Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
0038  * @license    http://framework.zend.com/license/new-bsd     New BSD License
0039  */
0040 class Zend_Feed_Entry_Atom extends Zend_Feed_Entry_Abstract
0041 {
0042     /**
0043      * Content-Type
0044      */
0045     const CONTENT_TYPE = 'application/atom+xml';
0046 
0047     /**
0048      * Root XML element for Atom entries.
0049      *
0050      * @var string
0051      */
0052     protected $_rootElement = 'entry';
0053 
0054     /**
0055      * Root namespace for Atom entries.
0056      *
0057      * @var string
0058      */
0059     protected $_rootNamespace = 'atom';
0060 
0061 
0062     /**
0063      * Delete an atom entry.
0064      *
0065      * Delete tries to delete this entry from its feed. If the entry
0066      * does not contain a link rel="edit", we throw an error (either
0067      * the entry does not yet exist or this is not an editable
0068      * feed). If we have a link rel="edit", we do the empty-body
0069      * HTTP DELETE to that URI and check for a response of 2xx.
0070      * Usually the response would be 204 No Content, but the Atom
0071      * Publishing Protocol permits it to be 200 OK.
0072      *
0073      * @return void
0074      * @throws Zend_Feed_Exception
0075      */
0076     public function delete()
0077     {
0078         // Look for link rel="edit" in the entry object.
0079         $deleteUri = $this->link('edit');
0080         if (!$deleteUri) {
0081             /**
0082              * @see Zend_Feed_Exception
0083              */
0084             // require_once 'Zend/Feed/Exception.php';
0085             throw new Zend_Feed_Exception('Cannot delete entry; no link rel="edit" is present.');
0086         }
0087 
0088         // DELETE
0089         $client = Zend_Feed::getHttpClient();
0090         do {
0091             $client->setUri($deleteUri);
0092             if (Zend_Feed::getHttpMethodOverride()) {
0093                 $client->setHeader('X-HTTP-Method-Override', 'DELETE');
0094                 $response = $client->request('POST');
0095             } else {
0096                 $response = $client->request('DELETE');
0097             }
0098             $httpStatus = $response->getStatus();
0099             switch ((int) $httpStatus / 100) {
0100                 // Success
0101                 case 2:
0102                     return true;
0103                 // Redirect
0104                 case 3:
0105                     $deleteUri = $response->getHeader('Location');
0106                     continue;
0107                 // Error
0108                 default:
0109                     /**
0110                      * @see Zend_Feed_Exception
0111                      */
0112                     // require_once 'Zend/Feed/Exception.php';
0113                     throw new Zend_Feed_Exception("Expected response code 2xx, got $httpStatus");
0114             }
0115         } while (true);
0116     }
0117 
0118 
0119     /**
0120      * Save a new or updated Atom entry.
0121      *
0122      * Save is used to either create new entries or to save changes to
0123      * existing ones. If we have a link rel="edit", we are changing
0124      * an existing entry. In this case we re-serialize the entry and
0125      * PUT it to the edit URI, checking for a 200 OK result.
0126      *
0127      * For posting new entries, you must specify the $postUri
0128      * parameter to save() to tell the object where to post itself.
0129      * We use $postUri and POST the serialized entry there, checking
0130      * for a 201 Created response. If the insert is successful, we
0131      * then parse the response from the POST to get any values that
0132      * the server has generated: an id, an updated time, and its new
0133      * link rel="edit".
0134      *
0135      * @param  string $postUri Location to POST for creating new entries.
0136      * @return void
0137      * @throws Zend_Feed_Exception
0138      */
0139     public function save($postUri = null)
0140     {
0141         if ($this->id()) {
0142             // If id is set, look for link rel="edit" in the
0143             // entry object and PUT.
0144             $editUri = $this->link('edit');
0145             if (!$editUri) {
0146                 /**
0147                  * @see Zend_Feed_Exception
0148                  */
0149                 // require_once 'Zend/Feed/Exception.php';
0150                 throw new Zend_Feed_Exception('Cannot edit entry; no link rel="edit" is present.');
0151             }
0152 
0153             $client = Zend_Feed::getHttpClient();
0154             $client->setUri($editUri);
0155             if (Zend_Feed::getHttpMethodOverride()) {
0156                 $client->setHeaders(array('X-HTTP-Method-Override: PUT',
0157                     'Content-Type: ' . self::CONTENT_TYPE));
0158                 $client->setRawData($this->saveXML());
0159                 $response = $client->request('POST');
0160             } else {
0161                 $client->setHeaders('Content-Type', self::CONTENT_TYPE);
0162                 $client->setRawData($this->saveXML());
0163                 $response = $client->request('PUT');
0164             }
0165             if ($response->getStatus() !== 200) {
0166                 /**
0167                  * @see Zend_Feed_Exception
0168                  */
0169                 // require_once 'Zend/Feed/Exception.php';
0170                 throw new Zend_Feed_Exception('Expected response code 200, got ' . $response->getStatus());
0171             }
0172         } else {
0173             if ($postUri === null) {
0174                 /**
0175                  * @see Zend_Feed_Exception
0176                  */
0177                 // require_once 'Zend/Feed/Exception.php';
0178                 throw new Zend_Feed_Exception('PostURI must be specified to save new entries.');
0179             }
0180             $client = Zend_Feed::getHttpClient();
0181             $client->setUri($postUri);
0182             $client->setHeaders('Content-Type', self::CONTENT_TYPE);
0183             $client->setRawData($this->saveXML());
0184             $response = $client->request('POST');
0185 
0186             if ($response->getStatus() !== 201) {
0187                 /**
0188                  * @see Zend_Feed_Exception
0189                  */
0190                 // require_once 'Zend/Feed/Exception.php';
0191                 throw new Zend_Feed_Exception('Expected response code 201, got '
0192                                               . $response->getStatus());
0193             }
0194         }
0195 
0196         // Update internal properties using $client->responseBody;
0197         @ini_set('track_errors', 1);
0198         $newEntry = new DOMDocument;
0199         $newEntry = @Zend_Xml_Security::scan($response->getBody(), $newEntry);
0200         @ini_restore('track_errors');
0201 
0202         if (!$newEntry) {
0203             // prevent the class to generate an undefined variable notice (ZF-2590)
0204             if (!isset($php_errormsg)) {
0205                 if (function_exists('xdebug_is_enabled')) {
0206                     $php_errormsg = '(error message not available, when XDebug is running)';
0207                 } else {
0208                     $php_errormsg = '(error message not available)';
0209                 }
0210             }
0211 
0212             /**
0213              * @see Zend_Feed_Exception
0214              */
0215             // require_once 'Zend/Feed/Exception.php';
0216             throw new Zend_Feed_Exception('XML cannot be parsed: ' . $php_errormsg);
0217         }
0218 
0219         $newEntry = $newEntry->getElementsByTagName($this->_rootElement)->item(0);
0220         if (!$newEntry) {
0221             /**
0222              * @see Zend_Feed_Exception
0223              */
0224             // require_once 'Zend/Feed/Exception.php';
0225             throw new Zend_Feed_Exception('No root <feed> element found in server response:'
0226                                           . "\n\n" . $client->responseBody);
0227         }
0228 
0229         if ($this->_element->parentNode) {
0230             $oldElement = $this->_element;
0231             $this->_element = $oldElement->ownerDocument->importNode($newEntry, true);
0232             $oldElement->parentNode->replaceChild($this->_element, $oldElement);
0233         } else {
0234             $this->_element = $newEntry;
0235         }
0236     }
0237 
0238 
0239     /**
0240      * Easy access to <link> tags keyed by "rel" attributes.
0241      *
0242      * If $elt->link() is called with no arguments, we will attempt to
0243      * return the value of the <link> tag(s) like all other
0244      * method-syntax attribute access. If an argument is passed to
0245      * link(), however, then we will return the "href" value of the
0246      * first <link> tag that has a "rel" attribute matching $rel:
0247      *
0248      * $elt->link(): returns the value of the link tag.
0249      * $elt->link('self'): returns the href from the first <link rel="self"> in the entry.
0250      *
0251      * @param  string $rel The "rel" attribute to look for.
0252      * @return mixed
0253      */
0254     public function link($rel = null)
0255     {
0256         if ($rel === null) {
0257             return parent::__call('link', null);
0258         }
0259 
0260         // index link tags by their "rel" attribute.
0261         $links = parent::__get('link');
0262         if (!is_array($links)) {
0263             if ($links instanceof Zend_Feed_Element) {
0264                 $links = array($links);
0265             } else {
0266                 return $links;
0267             }
0268         }
0269 
0270         foreach ($links as $link) {
0271             if (empty($link['rel'])) {
0272                 $link['rel'] = 'alternate'; // see Atom 1.0 spec
0273             }
0274             if ($rel == $link['rel']) {
0275                 return $link['href'];
0276             }
0277         }
0278 
0279         return null;
0280     }
0281 
0282 }