web/lib/Zend/Feed/Entry/Atom.php
changeset 64 162c1de6545a
parent 19 1c2f13fd785c
child 68 ecaf28ffe26e
equal deleted inserted replaced
63:5b37998e522e 64:162c1de6545a
       
     1 <?php
       
     2 
       
     3 /**
       
     4  * Zend Framework
       
     5  *
       
     6  * LICENSE
       
     7  *
       
     8  * This source file is subject to the new BSD license that is bundled
       
     9  * with this package in the file LICENSE.txt.
       
    10  * It is also available through the world-wide-web at this URL:
       
    11  * http://framework.zend.com/license/new-bsd
       
    12  * If you did not receive a copy of the license and are unable to
       
    13  * obtain it through the world-wide-web, please send an email
       
    14  * to license@zend.com so we can send you a copy immediately.
       
    15  *
       
    16  * @category   Zend
       
    17  * @package    Zend_Feed
       
    18  * @copyright  Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
       
    19  * @license    http://framework.zend.com/license/new-bsd     New BSD License
       
    20  * @version    $Id: Atom.php 20096 2010-01-06 02:05:09Z bkarwin $
       
    21  */
       
    22 
       
    23 
       
    24 /**
       
    25  * @see Zend_Feed_Entry_Abstract
       
    26  */
       
    27 require_once 'Zend/Feed/Entry/Abstract.php';
       
    28 
       
    29 
       
    30 /**
       
    31  * Concrete class for working with Atom entries.
       
    32  *
       
    33  * @category   Zend
       
    34  * @package    Zend_Feed
       
    35  * @copyright  Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
       
    36  * @license    http://framework.zend.com/license/new-bsd     New BSD License
       
    37  */
       
    38 class Zend_Feed_Entry_Atom extends Zend_Feed_Entry_Abstract
       
    39 {
       
    40     /**
       
    41      * Content-Type
       
    42      */
       
    43     const CONTENT_TYPE = 'application/atom+xml';
       
    44 
       
    45     /**
       
    46      * Root XML element for Atom entries.
       
    47      *
       
    48      * @var string
       
    49      */
       
    50     protected $_rootElement = 'entry';
       
    51 
       
    52     /**
       
    53      * Root namespace for Atom entries.
       
    54      *
       
    55      * @var string
       
    56      */
       
    57     protected $_rootNamespace = 'atom';
       
    58 
       
    59 
       
    60     /**
       
    61      * Delete an atom entry.
       
    62      *
       
    63      * Delete tries to delete this entry from its feed. If the entry
       
    64      * does not contain a link rel="edit", we throw an error (either
       
    65      * the entry does not yet exist or this is not an editable
       
    66      * feed). If we have a link rel="edit", we do the empty-body
       
    67      * HTTP DELETE to that URI and check for a response of 2xx.
       
    68      * Usually the response would be 204 No Content, but the Atom
       
    69      * Publishing Protocol permits it to be 200 OK.
       
    70      *
       
    71      * @return void
       
    72      * @throws Zend_Feed_Exception
       
    73      */
       
    74     public function delete()
       
    75     {
       
    76         // Look for link rel="edit" in the entry object.
       
    77         $deleteUri = $this->link('edit');
       
    78         if (!$deleteUri) {
       
    79             /**
       
    80              * @see Zend_Feed_Exception
       
    81              */
       
    82             require_once 'Zend/Feed/Exception.php';
       
    83             throw new Zend_Feed_Exception('Cannot delete entry; no link rel="edit" is present.');
       
    84         }
       
    85 
       
    86         // DELETE
       
    87         $client = Zend_Feed::getHttpClient();
       
    88         do {
       
    89             $client->setUri($deleteUri);
       
    90             if (Zend_Feed::getHttpMethodOverride()) {
       
    91                 $client->setHeader('X-HTTP-Method-Override', 'DELETE');
       
    92                 $response = $client->request('POST');
       
    93             } else {
       
    94                 $response = $client->request('DELETE');
       
    95             }
       
    96             $httpStatus = $response->getStatus();
       
    97             switch ((int) $httpStatus / 100) {
       
    98                 // Success
       
    99                 case 2:
       
   100                     return true;
       
   101                 // Redirect
       
   102                 case 3:
       
   103                     $deleteUri = $response->getHeader('Location');
       
   104                     continue;
       
   105                 // Error
       
   106                 default:
       
   107                     /**
       
   108                      * @see Zend_Feed_Exception
       
   109                      */
       
   110                     require_once 'Zend/Feed/Exception.php';
       
   111                     throw new Zend_Feed_Exception("Expected response code 2xx, got $httpStatus");
       
   112             }
       
   113         } while (true);
       
   114     }
       
   115 
       
   116 
       
   117     /**
       
   118      * Save a new or updated Atom entry.
       
   119      *
       
   120      * Save is used to either create new entries or to save changes to
       
   121      * existing ones. If we have a link rel="edit", we are changing
       
   122      * an existing entry. In this case we re-serialize the entry and
       
   123      * PUT it to the edit URI, checking for a 200 OK result.
       
   124      *
       
   125      * For posting new entries, you must specify the $postUri
       
   126      * parameter to save() to tell the object where to post itself.
       
   127      * We use $postUri and POST the serialized entry there, checking
       
   128      * for a 201 Created response. If the insert is successful, we
       
   129      * then parse the response from the POST to get any values that
       
   130      * the server has generated: an id, an updated time, and its new
       
   131      * link rel="edit".
       
   132      *
       
   133      * @param  string $postUri Location to POST for creating new entries.
       
   134      * @return void
       
   135      * @throws Zend_Feed_Exception
       
   136      */
       
   137     public function save($postUri = null)
       
   138     {
       
   139         if ($this->id()) {
       
   140             // If id is set, look for link rel="edit" in the
       
   141             // entry object and PUT.
       
   142             $editUri = $this->link('edit');
       
   143             if (!$editUri) {
       
   144                 /**
       
   145                  * @see Zend_Feed_Exception
       
   146                  */
       
   147                 require_once 'Zend/Feed/Exception.php';
       
   148                 throw new Zend_Feed_Exception('Cannot edit entry; no link rel="edit" is present.');
       
   149             }
       
   150 
       
   151             $client = Zend_Feed::getHttpClient();
       
   152             $client->setUri($editUri);
       
   153             if (Zend_Feed::getHttpMethodOverride()) {
       
   154                 $client->setHeaders(array('X-HTTP-Method-Override: PUT',
       
   155                     'Content-Type: ' . self::CONTENT_TYPE));
       
   156                 $client->setRawData($this->saveXML());
       
   157                 $response = $client->request('POST');
       
   158             } else {
       
   159                 $client->setHeaders('Content-Type', self::CONTENT_TYPE);
       
   160                 $client->setRawData($this->saveXML());
       
   161                 $response = $client->request('PUT');
       
   162             }
       
   163             if ($response->getStatus() !== 200) {
       
   164                 /**
       
   165                  * @see Zend_Feed_Exception
       
   166                  */
       
   167                 require_once 'Zend/Feed/Exception.php';
       
   168                 throw new Zend_Feed_Exception('Expected response code 200, got ' . $response->getStatus());
       
   169             }
       
   170         } else {
       
   171             if ($postUri === null) {
       
   172                 /**
       
   173                  * @see Zend_Feed_Exception
       
   174                  */
       
   175                 require_once 'Zend/Feed/Exception.php';
       
   176                 throw new Zend_Feed_Exception('PostURI must be specified to save new entries.');
       
   177             }
       
   178             $client = Zend_Feed::getHttpClient();
       
   179             $client->setUri($postUri);
       
   180             $client->setHeaders('Content-Type', self::CONTENT_TYPE);
       
   181             $client->setRawData($this->saveXML());
       
   182             $response = $client->request('POST');
       
   183 
       
   184             if ($response->getStatus() !== 201) {
       
   185                 /**
       
   186                  * @see Zend_Feed_Exception
       
   187                  */
       
   188                 require_once 'Zend/Feed/Exception.php';
       
   189                 throw new Zend_Feed_Exception('Expected response code 201, got '
       
   190                                               . $response->getStatus());
       
   191             }
       
   192         }
       
   193 
       
   194         // Update internal properties using $client->responseBody;
       
   195         @ini_set('track_errors', 1);
       
   196         $newEntry = new DOMDocument;
       
   197         $status = @$newEntry->loadXML($response->getBody());
       
   198         @ini_restore('track_errors');
       
   199 
       
   200         if (!$status) {
       
   201             // prevent the class to generate an undefined variable notice (ZF-2590)
       
   202             if (!isset($php_errormsg)) {
       
   203                 if (function_exists('xdebug_is_enabled')) {
       
   204                     $php_errormsg = '(error message not available, when XDebug is running)';
       
   205                 } else {
       
   206                     $php_errormsg = '(error message not available)';
       
   207                 }
       
   208             }
       
   209 
       
   210             /**
       
   211              * @see Zend_Feed_Exception
       
   212              */
       
   213             require_once 'Zend/Feed/Exception.php';
       
   214             throw new Zend_Feed_Exception('XML cannot be parsed: ' . $php_errormsg);
       
   215         }
       
   216 
       
   217         $newEntry = $newEntry->getElementsByTagName($this->_rootElement)->item(0);
       
   218         if (!$newEntry) {
       
   219             /**
       
   220              * @see Zend_Feed_Exception
       
   221              */
       
   222             require_once 'Zend/Feed/Exception.php';
       
   223             throw new Zend_Feed_Exception('No root <feed> element found in server response:'
       
   224                                           . "\n\n" . $client->responseBody);
       
   225         }
       
   226 
       
   227         if ($this->_element->parentNode) {
       
   228             $oldElement = $this->_element;
       
   229             $this->_element = $oldElement->ownerDocument->importNode($newEntry, true);
       
   230             $oldElement->parentNode->replaceChild($this->_element, $oldElement);
       
   231         } else {
       
   232             $this->_element = $newEntry;
       
   233         }
       
   234     }
       
   235 
       
   236 
       
   237     /**
       
   238      * Easy access to <link> tags keyed by "rel" attributes.
       
   239      *
       
   240      * If $elt->link() is called with no arguments, we will attempt to
       
   241      * return the value of the <link> tag(s) like all other
       
   242      * method-syntax attribute access. If an argument is passed to
       
   243      * link(), however, then we will return the "href" value of the
       
   244      * first <link> tag that has a "rel" attribute matching $rel:
       
   245      *
       
   246      * $elt->link(): returns the value of the link tag.
       
   247      * $elt->link('self'): returns the href from the first <link rel="self"> in the entry.
       
   248      *
       
   249      * @param  string $rel The "rel" attribute to look for.
       
   250      * @return mixed
       
   251      */
       
   252     public function link($rel = null)
       
   253     {
       
   254         if ($rel === null) {
       
   255             return parent::__call('link', null);
       
   256         }
       
   257 
       
   258         // index link tags by their "rel" attribute.
       
   259         $links = parent::__get('link');
       
   260         if (!is_array($links)) {
       
   261             if ($links instanceof Zend_Feed_Element) {
       
   262                 $links = array($links);
       
   263             } else {
       
   264                 return $links;
       
   265             }
       
   266         }
       
   267 
       
   268         foreach ($links as $link) {
       
   269             if (empty($link['rel'])) {
       
   270                 $link['rel'] = 'alternate'; // see Atom 1.0 spec
       
   271             }
       
   272             if ($rel == $link['rel']) {
       
   273                 return $link['href'];
       
   274             }
       
   275         }
       
   276 
       
   277         return null;
       
   278     }
       
   279 
       
   280 }