Zend_Feed_Writer.xml 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!-- Reviewed: no -->
  3. <sect1 id="zend.feed.writer">
  4. <title>Zend_Feed_Writer</title>
  5. <sect2 id="zend.feed.writer.introduction">
  6. <title>Introduction</title>
  7. <para>
  8. <classname>Zend_Feed_Writer</classname> is the sibling component to
  9. <classname>Zend_Feed_Reader</classname> responsible for generating feeds for output. It
  10. supports the Atom 1.0 specification (RFC 4287) and RSS 2.0 as specified by the RSS
  11. Advisory Board (RSS 2.0.11). It does not deviate from these standards. It does, however,
  12. offer a simple Extension system which allows for any extension/module for either of
  13. these two specifications to be implemented if they are not provided out of the box.
  14. </para>
  15. <para>
  16. In many ways, <classname>Zend_Feed_Writer</classname> is the inverse of
  17. <classname>Zend_Feed_Reader</classname>. Where <classname>Zend_Feed_Reader</classname>
  18. focused on providing an easy to use architecture fronted by getter methods,
  19. <classname>Zend_Feed_Writer</classname> is fronted by similarly named setters or
  20. mutators. This ensures the API won't pose a learning curve to anyone familiar with
  21. <classname>Zend_Feed_Reader</classname>.
  22. </para>
  23. <para>
  24. As a result of this design, the rest may even be obvious. Behind the scenes, data set on
  25. any <classname>Zend_Feed_Reader</classname> object is translated at render time onto a
  26. <classname>DOMDocument</classname> object using the necessary feed elements. For each
  27. supported feed type there is both an Atom 1.0 and RSS 2.0 renderer. Using a
  28. <classname>DOMDocument</classname> rather a templating solution has numerous advantages,
  29. the most obvious being the ability to export the <classname>DOMDocument</classname> for
  30. additional processing and relying on PHP DOM for correct and valid rendering.
  31. </para>
  32. <para>
  33. As with <classname>Zend_Feed_Reader</classname>, <classname>Zend_Feed_Writer</classname>
  34. is a standalone replacement for <classname>Zend_Feed</classname>'s Builder architecture
  35. and is not compatible with those classes.
  36. </para>
  37. </sect2>
  38. <sect2 id="zend.feed.writer.architecture">
  39. <title>Architecture</title>
  40. <para>
  41. The architecture of <classname>Zend_Feed_Writer</classname> is very simple. It has two
  42. core sets of classes: containers and renderers.
  43. </para>
  44. <para>
  45. The containers include the <classname>Zend_Feed_Writer_Feed</classname> and
  46. <classname>Zend_Feed_Writer_Entry</classname> classes. The Entry classes can be attached
  47. to any Feed class. The sole purpose of these containers is to collect data about the
  48. feed to generate using a simple interface of setter methods. These methods perform some
  49. data validity testing. For example, it will validate any passed URIs, dates, etc. These
  50. checks are not tied to any of the feed standards. The container objects also contain
  51. methods to allow for fast rendering and export of the final feed, and these can be
  52. reused at will.
  53. </para>
  54. <para>
  55. While there are two data containers, there are four renderers - two matching container
  56. renderers per support feed type. The renderer accept a container, and based on its
  57. content attempt to generate a valid feed. If the renderer is unable to generate a valid
  58. feed, perhaps due to the container missing an obligatory data point, it will report this
  59. by throwing an <classname>Exception</classname>. While it is possible to ignore
  60. <classname>Exception</classname>s, this removes the default safeguard of ensuring you
  61. have sufficient data set to render a wholly valid feed.
  62. </para>
  63. <para>
  64. Due to the system being divided between data containers and renderers, it can make
  65. Extensions somewhat interesting. A typical Extension offering namespaced feed and entry
  66. level elements, must itself reflect the exact same architecture, i.e. offer feed and
  67. entry level data containers, and matching renderers. There is, fortunately, no complex
  68. integration work required since all Extension classes are simply registered and
  69. automatically used by the core classes. We'll meet Extensions in more detail at the end
  70. of this section.
  71. </para>
  72. </sect2>
  73. <sect2 id="zend.feed.writer.getting.started">
  74. <title>Getting Started</title>
  75. <para>
  76. Using <classname>Zend_Feed_Reader</classname> is as simple as setting data and
  77. triggering the renderer. Here is an example to generate a minimal Atom 1.0 feed.
  78. </para>
  79. <programlisting language="php"><![CDATA[
  80. /**
  81. * Create the parent feed
  82. */
  83. $feed = new Zend_Feed_Writer_Feed;
  84. $feed->setTitle('Paddy\'s Blog');
  85. $feed->setLink('http://www.example.com');
  86. $feed->setFeedLink('http://www.example.com/atom', 'atom');
  87. $feed->addAuthor(array(
  88. 'name' => 'Paddy',
  89. 'email' => 'paddy@example.com',
  90. 'uri' => 'http://www.example.com',
  91. ));
  92. $feed->setDateModified(time());
  93. $feed->addHub('http://pubsubhubbub.appspot.com/');
  94. /**
  95. * Add one or more entries. Note that entries must
  96. * be manually added once created.
  97. */
  98. $entry = $feed->createEntry();
  99. $entry->setTitle('All Your Base Are Belong To Us');
  100. $entry->setLink('http://www.example.com/all-your-base-are-belong-to-us');
  101. $entry->addAuthor(array(
  102. 'name' => 'Paddy',
  103. 'email' => 'paddy@example.com',
  104. 'uri' => 'http://www.example.com',
  105. ));
  106. $entry->setDateModified(time());
  107. $entry->setDateCreated(time());
  108. $entry->setDescription('Exposing the difficultly of porting games to English.');
  109. $entry->setContent('I am not writing the article. The example is long enough as is ;).');
  110. $feed->addEntry($entry);
  111. /**
  112. * Render the resulting feed to Atom 1.0 and assign to $out.
  113. * You can substitute "atom" with "rss" to generate an RSS 2.0 feed.
  114. */
  115. $out = $feed->export('atom');
  116. ]]></programlisting>
  117. <para>
  118. The output rendered should be as follows:
  119. </para>
  120. <programlisting language="xml">
  121. &#60;?xml version="1.0" encoding="utf-8"?&#62;
  122. &#60;feed xmlns="http://www.w3.org/2005/Atom"&#62;
  123. &#60;title type="text"&#62;Paddy's Blog&#60;/title&#62;
  124. &#60;subtitle type="text"&#62;Writing about PC Games since 176 BC.&#60;/subtitle&#62;
  125. &#60;updated&#62;2009-12-14T20:28:18+00:00&#60;/updated&#62;
  126. &#60;generator uri="http://framework.zend.com" version="1.10.0alpha"&#62;
  127. Zend_Feed_Writer
  128. &#60;/generator&#62;
  129. &#60;link rel="alternate" type="text/html" href="http://www.example.com"/&#62;
  130. &#60;link rel="self" type="application/atom+xml" href="http://www.example.com/atom"/&#62;
  131. &#60;id&#62;http://www.example.com&#60;/id&#62;
  132. &#60;author&#62;
  133. &#60;name&#62;Paddy&#60;/name&#62;
  134. &#60;email&#62;paddy@example.com&#60;/email&#62;
  135. &#60;uri&#62;http://www.example.com&#60;/uri&#62;
  136. &#60;/author&#62;
  137. &#60;link rel="hub" href="http://pubsubhubbub.appspot.com/"/&#62;
  138. &#60;entry&#62;
  139. &#60;title type="html"&#62;&#60;![CDATA[All Your Base Are Belong To Us]]&#62;&#60;/title&#62;
  140. &#60;summary type="html"&#62;
  141. &#60;![CDATA[Exposing the difficultly of porting games to English.]]&#62;
  142. &#60;/summary&#62;
  143. &#60;published&#62;2009-12-14T20:28:18+00:00&#60;/published&#62;
  144. &#60;updated&#62;2009-12-14T20:28:18+00:00&#60;/updated&#62;
  145. &#60;link rel="alternate" type="text/html" href="http://www.example.com/all-your-base-are-belong-to-us"/&#62;
  146. &#60;id&#62;http://www.example.com/all-your-base-are-belong-to-us&#60;/id&#62;
  147. &#60;author&#62;
  148. &#60;name&#62;Paddy&#60;/name&#62;
  149. &#60;email&#62;paddy@example.com&#60;/email&#62;
  150. &#60;uri&#62;http://www.example.com&#60;/uri&#62;
  151. &#60;/author&#62;
  152. &#60;content type="html"&#62;
  153. &#60;![CDATA[I am not writing the article. The example is long enough as is ;).]]&#62;
  154. &#60;/content&#62;
  155. &#60;/entry&#62;
  156. &#60;/feed&#62;
  157. </programlisting>
  158. <para>
  159. This is a perfectly valid Atom 1.0 example. It should be noted that omitting an obligatory point
  160. of data, such as a title, will trigger an <classname>Exception</classname> when
  161. rendering as Atom 1.0. This will differ for RSS 2.0 since a title may be omitted so long
  162. as a description is present. This gives rise to Exceptions that differ between the two
  163. standards depending on the renderer in use. By design,
  164. <classname>Zend_Feed_Writer</classname> will not render an invalid feed for either
  165. standard unless the end-user deliberately elects to ignore all Exceptions.
  166. </para>
  167. </sect2>
  168. <sect2 id="zend.feed.writer.setting.feed.data.points">
  169. <title>Setting Feed Data Points</title>
  170. <para>
  171. Before you can render a feed, you must first setup the data necessary for
  172. the feed being rendered. This utilises a simple setter style API which doubles
  173. as an initial method for validating the data being set. By design, the API
  174. closely matches that for <classname>Zend_Feed_Reader</classname> to avoid
  175. undue confusion and uncertainty.
  176. </para>
  177. <para>
  178. <classname>Zend_Feed_Writer</classname> offers this API via its data container
  179. classes <classname>Zend_Feed_Writer_Feed</classname> and
  180. <classname>Zend_Feed_Writer_Entry</classname>. These classes merely store
  181. all feed data in type-agnostic manner, meaning you may reuse any data
  182. container with any renderer without requiring additional work. Both classes
  183. are also amenable to Extensions, meaning that an Extension may define its own
  184. container classes which are registered to the base container classes as extensions, and
  185. are checked when any method call triggers the base container's
  186. <methodname>__call()</methodname> method.
  187. </para>
  188. <para>
  189. Here's a summary of the Core <acronym>API</acronym> for Feeds. You should note it
  190. comprises not only the basic <acronym>RSS</acronym> and Atom standards, but also
  191. accounts for a number of included Extensions bundled with
  192. <classname>Zend_Feed_Writer</classname>. The naming of these
  193. Extension sourced methods remain fairly generic - all Extension
  194. methods operate at the same level as the Core <acronym>API</acronym> though we do allow
  195. you to retrieve any specific Extension object separately if required.
  196. </para>
  197. <table>
  198. <title>Feed Level API Methods</title>
  199. <tgroup cols="2">
  200. <tbody>
  201. <row>
  202. <entry><methodname>setId()</methodname></entry>
  203. <entry>Set a unique ID associated with this feed. For Atom 1.0
  204. this is an atom:id element, whereas for RSS 2.0 it is added
  205. as a guid element. These are optional so long as a link is
  206. added, i.e. the link is set as the ID.</entry>
  207. </row>
  208. <row>
  209. <entry><methodname>setTitle()</methodname></entry>
  210. <entry>Set the title of the feed.</entry>
  211. </row>
  212. <row>
  213. <entry><methodname>setDescription()</methodname></entry>
  214. <entry>Set the text description of the feed.</entry>
  215. </row>
  216. <row>
  217. <entry><methodname>setLink()</methodname></entry>
  218. <entry>
  219. Set a <acronym>URI</acronym> to the <acronym>HTML</acronym> website
  220. containing the same or
  221. similar information as this feed (i.e. if the feed is from a blog,
  222. it should provide the blog's <acronym>URI</acronym> where the
  223. <acronym>HTML</acronym> version of the entries can be read).
  224. </entry>
  225. </row>
  226. <row>
  227. <entry><methodname>setFeedLinks()</methodname></entry>
  228. <entry>
  229. Add a link to an XML feed, whether the feed being generated or
  230. an alternate URI pointing to the same feed but in a different
  231. format. At a minimum, it is recommended to include a link to
  232. the feed being generated so it has an identifiable final
  233. URI allowing a client to track its location changes without
  234. necessitating constant redirects. The parameter is an array of
  235. arrays, where each sub-array contains the keys "type" and "uri".
  236. The type should be one of "atom", "rss", or "rdf". If a type is
  237. omitted, it defaults to the type used when rendering the feed.
  238. </entry>
  239. </row>
  240. <row>
  241. <entry><methodname>setAuthors()</methodname></entry>
  242. <entry>
  243. Sets the data for authors. The parameter is an array of arrays
  244. where each sub-array may contain the keys "name", "email" and
  245. "uri". The "uri" value is only applicable for Atom feeds since
  246. RSS contains no facility to show it. For RSS 2.0, rendering will
  247. create two elements - an author element containing the email
  248. reference with the name in brackets, and a Dublin Core creator
  249. element only containing the name.
  250. </entry>
  251. </row>
  252. <row>
  253. <entry><methodname>setAuthor()</methodname></entry>
  254. <entry>
  255. Sets the data for a single author following the same
  256. format as described above for a single sub-array.
  257. </entry>
  258. </row>
  259. <row>
  260. <entry><methodname>setDateCreated()</methodname></entry>
  261. <entry>
  262. Sets the date on which this feed was created. Generally
  263. only applicable to Atom where it represents the date the resource
  264. described by an Atom 1.0 document was created. The expected parameter
  265. may be a UNIX timestamp or a <classname>Zend_Date</classname> object.
  266. </entry>
  267. </row>
  268. <row>
  269. <entry><methodname>getDateModified()</methodname></entry>
  270. <entry>
  271. Sets the date on which this feed was last modified. The expected parameter
  272. may be a UNIX timestamp or a <classname>Zend_Date</classname> object.
  273. </entry>
  274. </row>
  275. <row>
  276. <entry><methodname>setLanguage()</methodname></entry>
  277. <entry>
  278. Sets the language of the feed. This will be omitted unless set.
  279. </entry>
  280. </row>
  281. <row>
  282. <entry><methodname>getGenerator()</methodname></entry>
  283. <entry>
  284. Allows the setting of a generator. The parameter should be an
  285. array containing the keys "name", "version" and "uri". If omitted
  286. a default generator will be added referencing
  287. <classname>Zend_Feed_Writer</classname>, the current Zend Framework
  288. version and the Framework's URI.
  289. </entry>
  290. </row>
  291. <row>
  292. <entry><methodname>setCopyright()</methodname></entry>
  293. <entry>
  294. Sets a copyright notice associated with the feed.
  295. </entry>
  296. </row>
  297. <row>
  298. <entry><methodname>setHubs()</methodname></entry>
  299. <entry>
  300. Accepts an array of Pubsubhubbub Hub Endpoints to be rendered in
  301. the feed as Atom links so that PuSH Subscribers may subscribe to
  302. your feed. Note that you must implement a Pubsubhubbub Publisher in
  303. order for real-time updates to be enabled. A Publisher may be implemented
  304. using <classname>Zend_Feed_Pubsubhubbub_Publisher</classname>.
  305. </entry>
  306. </row>
  307. <row>
  308. <entry><methodname>setCategories()</methodname></entry>
  309. <entry>
  310. Accepts an array of categories for rendering, where each element is itself
  311. an array whose possible keys include "term", "label" and "scheme". The "term"
  312. is a typically a category name suitable for inclusion in a URI. The "label"
  313. may be a human readable category name supporting special characters (it is encoded
  314. during rendering) and is a required key. The "scheme" (called the domain in RSS)
  315. is optional but must be a valid URI.
  316. </entry>
  317. </row>
  318. </tbody>
  319. </tgroup>
  320. </table>
  321. </sect2>
  322. <sect2 id="zend.feed.writer.setting.entry.data.points">
  323. <title>Setting Entry Data Points</title>
  324. <para>
  325. Here's a summary of the Core <acronym>API</acronym> for Entries/Items. You should note it
  326. comprises not only the basic <acronym>RSS</acronym> and Atom standards, but also
  327. accounts for a number of included Extensions bundled with
  328. <classname>Zend_Feed_Writer</classname>. The naming of these
  329. Extension sourced methods remain fairly generic - all Extension
  330. methods operate at the same level as the Core <acronym>API</acronym> though we do allow
  331. you to retrieve any specific Extension object separately if required.
  332. </para>
  333. <table>
  334. <title>Entry Level API Methods</title>
  335. <tgroup cols="2">
  336. <tbody>
  337. <row>
  338. <entry><methodname>setId()</methodname></entry>
  339. <entry>Set a unique ID associated with this feed. For Atom 1.0
  340. this is an atom:id element, whereas for RSS 2.0 it is added
  341. as a guid element. These are optional so long as a link is
  342. added, i.e. the link is set as the ID.</entry>
  343. </row>
  344. <row>
  345. <entry><methodname>setTitle()</methodname></entry>
  346. <entry>Set the title of the feed.</entry>
  347. </row>
  348. <row>
  349. <entry><methodname>setDescription()</methodname></entry>
  350. <entry>Set the text description of the feed.</entry>
  351. </row>
  352. <row>
  353. <entry><methodname>setLink()</methodname></entry>
  354. <entry>
  355. Set a <acronym>URI</acronym> to the <acronym>HTML</acronym> website
  356. containing the same or
  357. similar information as this feed (i.e. if the feed is from a blog,
  358. it should provide the blog's <acronym>URI</acronym> where the
  359. <acronym>HTML</acronym> version of the entries can be read).
  360. </entry>
  361. </row>
  362. <row>
  363. <entry><methodname>setFeedLinks()</methodname></entry>
  364. <entry>
  365. Add a link to an XML feed, whether the feed being generated or
  366. an alternate URI pointing to the same feed but in a different
  367. format. At a minimum, it is recommended to include a link to
  368. the feed being generated so it has an identifiable final
  369. URI allowing a client to track its location changes without
  370. necessitating constant redirects. The parameter is an array of
  371. arrays, where each sub-array contains the keys "type" and "uri".
  372. The type should be one of "atom", "rss", or "rdf". If a type is
  373. omitted, it defaults to the type used when rendering the feed.
  374. </entry>
  375. </row>
  376. <row>
  377. <entry><methodname>setAuthors()</methodname></entry>
  378. <entry>
  379. Sets the data for authors. The parameter is an array of arrays
  380. where each sub-array may contain the keys "name", "email" and
  381. "uri". The "uri" value is only applicable for Atom feeds since
  382. RSS contains no facility to show it. For RSS 2.0, rendering will
  383. create two elements - an author element containing the email
  384. reference with the name in brackets, and a Dublin Core creator
  385. element only containing the name.
  386. </entry>
  387. </row>
  388. <row>
  389. <entry><methodname>setAuthor()</methodname></entry>
  390. <entry>
  391. Sets the data for a single author following the same
  392. format as described above for a single sub-array.
  393. </entry>
  394. </row>
  395. <row>
  396. <entry><methodname>setDateCreated()</methodname></entry>
  397. <entry>
  398. Sets the date on which this feed was created. Generally
  399. only applicable to Atom where it represents the date the resource
  400. described by an Atom 1.0 document was created. The expected parameter
  401. may be a UNIX timestamp or a <classname>Zend_Date</classname> object.
  402. </entry>
  403. </row>
  404. <row>
  405. <entry><methodname>getDateModified()</methodname></entry>
  406. <entry>
  407. Sets the date on which this feed was last modified. The expected parameter
  408. may be a UNIX timestamp or a <classname>Zend_Date</classname> object.
  409. </entry>
  410. </row>
  411. <row>
  412. <entry><methodname>setLanguage()</methodname></entry>
  413. <entry>
  414. Sets the language of the feed. This will be omitted unless set.
  415. </entry>
  416. </row>
  417. <row>
  418. <entry><methodname>getGenerator()</methodname></entry>
  419. <entry>
  420. Allows the setting of a generator. The parameter should be an
  421. array containing the keys "name", "version" and "uri". If omitted
  422. a default generator will be added referencing
  423. <classname>Zend_Feed_Writer</classname>, the current Zend Framework
  424. version and the Framework's URI.
  425. </entry>
  426. </row>
  427. <row>
  428. <entry><methodname>setCopyright()</methodname></entry>
  429. <entry>
  430. Sets a copyright notice associated with the feed.
  431. </entry>
  432. </row>
  433. <row>
  434. <entry><methodname>setHubs()</methodname></entry>
  435. <entry>
  436. Accepts an array of Pubsubhubbub Hub Endpoints to be rendered in
  437. the feed as Atom links so that PuSH Subscribers may subscribe to
  438. your feed. Note that you must implement a Pubsubhubbub Publisher in
  439. order for real-time updates to be enabled. A Publisher may be implemented
  440. using <classname>Zend_Feed_Pubsubhubbub_Publisher</classname>.
  441. </entry>
  442. </row>
  443. <row>
  444. <entry><methodname>setCategories()</methodname></entry>
  445. <entry>
  446. Accepts an array of categories for rendering, where each element is itself
  447. an array whose possible keys include "term", "label" and "scheme". The "term"
  448. is a typically a category name suitable for inclusion in a URI. The "label"
  449. may be a human readable category name supporting special characters (it is encoded
  450. during rendering) and is a required key. The "scheme" (called the domain in RSS)
  451. is optional but must be a valid URI.
  452. </entry>
  453. </row>
  454. </tbody>
  455. </tgroup>
  456. </table>
  457. </sect2>
  458. </sect1>