Overview

Packages

  • Feed

Classes

  • Horde_Feed
  • Horde_Feed_Atom
  • Horde_Feed_Base
  • Horde_Feed_Blogroll
  • Horde_Feed_Entry_Atom
  • Horde_Feed_Entry_Base
  • Horde_Feed_Entry_Blogroll
  • Horde_Feed_Entry_Rss
  • Horde_Feed_Exception
  • Horde_Feed_Rss
  • Overview
  • Package
  • Class
  • Tree
  1: <?php
  2: /**
  3:  * Portions Copyright 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
  4:  * Copyright 2007-2012 Horde LLC (http://www.horde.org/)
  5:  *
  6:  * @category Horde
  7:  * @package  Feed
  8:  */
  9: 
 10: /**
 11:  * Concrete class for working with Atom entries.
 12:  *
 13:  * @category Horde
 14:  * @package  Feed
 15:  */
 16: class Horde_Feed_Entry_Atom extends Horde_Feed_Entry_Base
 17: {
 18:     /**
 19:      * The XML string for an "empty" Atom entry.
 20:      *
 21:      * @var string
 22:      */
 23:     protected $_emptyXml = '<atom:entry/>';
 24: 
 25:     /**
 26:      * Name of the XML element for Atom entries. Subclasses can
 27:      * override this to something other than "entry" if necessary.
 28:      *
 29:      * @var string
 30:      */
 31:     protected $_entryElementName = 'entry';
 32: 
 33:     /**
 34:      * Delete an atom entry.
 35:      *
 36:      * Delete tries to delete this entry from its feed. If the entry
 37:      * does not contain a link rel="edit", we throw an error (either
 38:      * the entry does not yet exist or this is not an editable
 39:      * feed). If we have a link rel="edit", we do the empty-body
 40:      * HTTP DELETE to that URI and check for a response of 2xx.
 41:      * Usually the response would be 204 No Content, but the Atom
 42:      * Publishing Protocol permits it to be 200 OK.
 43:      *
 44:      * @throws Horde_Feed_Exception If an error occurs, an Horde_Feed_Exception will
 45:      * be thrown.
 46:      */
 47:     public function delete()
 48:     {
 49:         // Look for link rel="edit" in the entry object.
 50:         $deleteUri = $this->link('edit');
 51:         if (!$deleteUri) {
 52:             throw new Horde_Feed_Exception('Cannot delete entry; no link rel="edit" is present.');
 53:         }
 54: 
 55:         // DELETE
 56:         do {
 57:             $response = $this->_httpClient->delete($deleteUri);
 58:             switch ((int)$response->code / 100) {
 59:             // Success
 60:             case 2:
 61:                 return true;
 62: 
 63:             // Redirect
 64:             case 3:
 65:                 $deleteUri = $response->getHeader('Location');
 66:                 continue;
 67: 
 68:             // Error
 69:             default:
 70:                 throw new Horde_Feed_Exception('Expected response code 2xx, got ' . $response->code);
 71:             }
 72:         } while (true);
 73:     }
 74: 
 75:     /**
 76:      * Save a new or updated Atom entry.
 77:      *
 78:      * Save is used to either create new entries or to save changes to existing
 79:      * ones. If we have a link rel="edit", we are changing an existing entry. In
 80:      * this case we re-serialize the entry and PUT it to the edit URI, checking
 81:      * for a 200 OK result.
 82:      *
 83:      * For posting new entries, you must specify the $postUri parameter to
 84:      * save() to tell the object where to post itself.  We use $postUri and POST
 85:      * the serialized entry there, checking for a 201 Created response. If the
 86:      * insert is successful, we then parse the response from the POST to get any
 87:      * values that the server has generated: an id, an updated time, and its new
 88:      * link rel="edit".
 89:      *
 90:      * @param string $postUri Location to POST for creating new entries.
 91:      * @param array  $headers Additional headers to transmit while posting.
 92:      *
 93:      * @throws Horde_Feed_Exception If an error occurs, a Horde_Feed_Exception
 94:      * will be thrown.
 95:      */
 96:     public function save($postUri = null, $headers = array())
 97:     {
 98:         $headers = array_merge(
 99:             array('Content-Type' => 'application/atom+xml'),
100:             $headers
101:         );
102: 
103:         if ($this->id()) {
104:             // If id is set, look for link rel="edit" in the
105:             // entry object and PUT.
106:             $editUri = $this->link('edit');
107:             if (!$editUri) {
108:                 throw new Horde_Feed_Exception('Cannot edit entry; no link rel="edit" is present.');
109:             }
110: 
111:             $response = $this->_httpClient->put($editUri, $this->saveXml(), $headers);
112:             if ($response->code !== 200) {
113:                 throw new Horde_Feed_Exception('Expected response code 200, got ' . $response->code);
114:             }
115:         } else {
116:             if ($postUri === null) {
117:                 throw new Horde_Feed_Exception('PostURI must be specified to save new entries.');
118:             }
119:             $response = $this->_httpClient->post($postUri, $this->saveXml(), $headers);
120:             if ($response->code !== 201) {
121:                 throw new Horde_Feed_Exception('Expected response code 201, got ' . $response->code);
122:             }
123:         }
124: 
125:         // Update internal properties using the response body.
126:         $body = $response->getBody();
127:         $newEntry = new DOMDocument;
128:         $parsed = @$newEntry->loadXML($body);
129:         if (!$parsed) {
130:             throw new Horde_Feed_Exception('DOMDocument cannot parse XML: ', error_get_last());
131:         }
132: 
133:         $newEntry = $newEntry->getElementsByTagName($this->_entryElementName)->item(0);
134:         if (!$newEntry) {
135:             throw new Horde_Feed_Exception('No root <feed> element found in server response:' . "\n\n" . $body);
136:         }
137: 
138:         if ($this->_element->parentNode) {
139:             $oldElement = $this->_element;
140:             $this->_element = $oldElement->ownerDocument->importNode($newEntry, true);
141:             $oldElement->parentNode->replaceChild($this->_element, $oldElement);
142:         } else {
143:             $this->_element = $newEntry;
144:         }
145: 
146:         $this->_expireCachedChildren();
147:     }
148: 
149:     /**
150:      * Easy access to <link> tags keyed by "rel" attributes.
151:      * @TODO rationalize this with other __get/__call access
152:      *
153:      * If $elt->link() is called with no arguments, we will attempt to
154:      * return the value of the <link> tag(s) like all other
155:      * method-syntax attribute access. If an argument is passed to
156:      * link(), however, then we will return the "href" value of the
157:      * first <link> tag that has a "rel" attribute matching $rel:
158:      *
159:      * $elt->link(): returns the value of the link tag.
160:      * $elt->link('self'): returns the href from the first <link rel="self"> in the entry.
161:      *
162:      * @param string $rel The "rel" attribute to look for.
163:      * @return mixed
164:      */
165:     public function link($rel = null)
166:     {
167:         if ($rel === null) {
168:             return parent::__call('link', null);
169:         }
170: 
171:         // index link tags by their "rel" attribute.
172:         $links = parent::__get('link');
173:         if (!is_array($links)) {
174:             if ($links instanceof Horde_Xml_Element) {
175:                 $links = array($links);
176:             } else {
177:                 return $links;
178:             }
179:         }
180: 
181:         foreach ($links as $link) {
182:             if (empty($link['rel'])) {
183:                 continue;
184:             }
185:             if ($rel == $link['rel']) {
186:                 return $link['href'];
187:             }
188:         }
189: 
190:         return null;
191:     }
192: }
193: 
API documentation generated by ApiGen