atom10feed.php 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316
  1. <?php
  2. /**
  3. * StatusNet, the distributed open-source microblogging tool
  4. *
  5. * Class for building an Atom feed in memory
  6. *
  7. * PHP version 5
  8. *
  9. * LICENCE: This program is free software: you can redistribute it and/or modify
  10. * it under the terms of the GNU Affero General Public License as published by
  11. * the Free Software Foundation, either version 3 of the License, or
  12. * (at your option) any later version.
  13. *
  14. * This program is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. * GNU Affero General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU Affero General Public License
  20. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  21. *
  22. * @category Feed
  23. * @package StatusNet
  24. * @author Zach Copley <zach@status.net>
  25. * @copyright 2010 StatusNet, Inc.
  26. * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
  27. * @link http://status.net/
  28. */
  29. if (!defined('STATUSNET'))
  30. {
  31. exit(1);
  32. }
  33. class Atom10FeedException extends Exception
  34. {
  35. }
  36. /**
  37. * Class for building an Atom feed in memory. Get the finished doc
  38. * as a string with Atom10Feed::getString().
  39. *
  40. * @category Feed
  41. * @package StatusNet
  42. * @author Zach Copley <zach@status.net>
  43. * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
  44. * @link http://status.net/
  45. */
  46. class Atom10Feed extends XMLStringer
  47. {
  48. public $xw;
  49. // @fixme most of these should probably be read-only properties
  50. private $namespaces;
  51. private $authors;
  52. private $subject;
  53. private $categories;
  54. private $contributors;
  55. private $generator;
  56. private $icon;
  57. private $links;
  58. private $selfLink;
  59. private $selfLinkType;
  60. public $logo;
  61. private $rights;
  62. public $subtitle;
  63. public $title;
  64. private $published;
  65. private $updated;
  66. private $entries;
  67. /**
  68. * Constructor
  69. *
  70. * @param boolean $indent flag to turn indenting on or off
  71. *
  72. * @return void
  73. */
  74. function __construct($indent = true) {
  75. parent::__construct($indent);
  76. $this->namespaces = array();
  77. $this->authors = array();
  78. $this->links = array();
  79. $this->entries = array();
  80. $this->addNamespace('', 'http://www.w3.org/2005/Atom');
  81. }
  82. /**
  83. * Add another namespace to the feed
  84. *
  85. * @param string $namespace the namespace
  86. * @param string $uri namspace uri
  87. *
  88. * @return void
  89. */
  90. function addNamespace($namespace, $uri)
  91. {
  92. $ns = array($namespace => $uri);
  93. $this->namespaces = array_merge($this->namespaces, $ns);
  94. }
  95. function addAuthor($name, $uri = null, $email = null)
  96. {
  97. $xs = new XMLStringer(true);
  98. $xs->elementStart('author');
  99. if (!empty($name)) {
  100. $xs->element('name', null, $name);
  101. } else {
  102. throw new Atom10FeedException(
  103. // TRANS: Atom feed exception thrown when an author element does not contain a name element.
  104. _('Author element must contain a name element.')
  105. );
  106. }
  107. if (isset($uri)) {
  108. $xs->element('uri', null, $uri);
  109. }
  110. if (isset($email)) {
  111. $xs->element('email', null, $email);
  112. }
  113. $xs->elementEnd('author');
  114. array_push($this->authors, $xs->getString());
  115. }
  116. /**
  117. * Add an Author to the feed via raw XML string
  118. *
  119. * @param string $xmlAuthor An XML string representation author
  120. *
  121. * @return void
  122. */
  123. function addAuthorRaw($xmlAuthor)
  124. {
  125. array_push($this->authors, $xmlAuthor);
  126. }
  127. function renderAuthors()
  128. {
  129. foreach ($this->authors as $author) {
  130. $this->raw($author);
  131. }
  132. }
  133. function getNamespaces()
  134. {
  135. return $this->namespaces;
  136. }
  137. function initFeed()
  138. {
  139. $this->startXML();
  140. $commonAttrs = array('xml:lang' => 'en-US');
  141. foreach ($this->namespaces as $prefix => $uri) {
  142. if ($prefix == '') {
  143. $attr = 'xmlns';
  144. } else {
  145. $attr = 'xmlns:' . $prefix;
  146. }
  147. $commonAttrs[$attr] = $uri;
  148. }
  149. $this->elementStart('feed', $commonAttrs);
  150. $this->element(
  151. 'generator', array(
  152. 'uri' => 'https://gnu.io/social',
  153. 'version' => GNUSOCIAL_VERSION
  154. ),
  155. 'GNU social'
  156. );
  157. $this->element('id', null, $this->id);
  158. $this->element('title', null, $this->title);
  159. $this->element('subtitle', null, $this->subtitle);
  160. if (!empty($this->logo)) {
  161. $this->element('logo', null, $this->logo);
  162. }
  163. $this->element('updated', null, $this->updated);
  164. $this->renderAuthors();
  165. if ($this->selfLink) {
  166. $this->addLink($this->selfLink, array('rel' => 'self',
  167. 'type' => $this->selfLinkType));
  168. }
  169. $this->renderLinks();
  170. }
  171. /**
  172. * Check that all required elements have been set, etc.
  173. * Throws an Atom10FeedException if something's missing.
  174. *
  175. * @return void
  176. */
  177. function validate()
  178. {
  179. }
  180. function renderLinks()
  181. {
  182. foreach ($this->links as $attrs)
  183. {
  184. $this->element('link', $attrs, null);
  185. }
  186. }
  187. function addEntryRaw($xmlEntry)
  188. {
  189. array_push($this->entries, $xmlEntry);
  190. }
  191. function addEntry($entry)
  192. {
  193. array_push($this->entries, $entry->getString());
  194. }
  195. function renderEntries()
  196. {
  197. foreach ($this->entries as $entry) {
  198. $this->raw($entry);
  199. }
  200. }
  201. function endFeed()
  202. {
  203. $this->elementEnd('feed');
  204. $this->xw->endDocument();
  205. }
  206. function getString()
  207. {
  208. if (Event::handle('StartApiAtom', array($this))) {
  209. $this->validate();
  210. $this->initFeed();
  211. if (!empty($this->subject)) {
  212. $this->raw($this->subject);
  213. }
  214. $this->renderEntries();
  215. $this->endFeed();
  216. Event::handle('EndApiAtom', array($this));
  217. }
  218. return $this->xw->outputMemory();
  219. }
  220. function setId($id)
  221. {
  222. $this->id = $id;
  223. }
  224. function setSelfLink($url, $type='application/atom+xml')
  225. {
  226. $this->selfLink = $url;
  227. $this->selfLinkType = $type;
  228. }
  229. function setTitle($title)
  230. {
  231. $this->title = $title;
  232. }
  233. function setSubtitle($subtitle)
  234. {
  235. $this->subtitle = $subtitle;
  236. }
  237. function setLogo($logo)
  238. {
  239. $this->logo = $logo;
  240. }
  241. function setUpdated($dt)
  242. {
  243. $this->updated = common_date_iso8601($dt);
  244. }
  245. function setPublished($dt)
  246. {
  247. $this->published = common_date_iso8601($dt);
  248. }
  249. /**
  250. * Adds a link element into the Atom document
  251. *
  252. * Assumes you want rel="alternate" and type="text/html" unless
  253. * you send in $otherAttrs.
  254. *
  255. * @param string $uri the uri the href needs to point to
  256. * @param array $otherAttrs other attributes to stick in
  257. *
  258. * @return void
  259. */
  260. function addLink($uri, $otherAttrs = null) {
  261. $attrs = array('href' => $uri);
  262. if (is_null($otherAttrs)) {
  263. $attrs['rel'] = 'alternate';
  264. $attrs['type'] = 'text/html';
  265. } else {
  266. $attrs = array_merge($attrs, $otherAttrs);
  267. }
  268. array_push($this->links, $attrs);
  269. }
  270. }