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 }