PageRenderTime 43ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/include/api/feed.php

https://github.com/mysnip/Core
PHP | 341 lines | 151 code | 37 blank | 153 comment | 26 complexity | 0109e10a9f1b75453011302f8f486161 MD5 | raw file
  1. <?php
  2. ////////////////////////////////////////////////////////////////////////////////
  3. // //
  4. // Copyright (C) 2011 Phorum Development Team //
  5. // http://www.phorum.org //
  6. // //
  7. // This program is free software. You can redistribute it and/or modify //
  8. // it under the terms of either the current Phorum License (viewable at //
  9. // phorum.org) or the Phorum License that was distributed with this file //
  10. // //
  11. // This program is distributed in the hope that it will be useful, //
  12. // but WITHOUT ANY WARRANTY, without even the implied warranty of //
  13. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. //
  14. // //
  15. // You should have received a copy of the Phorum License //
  16. // along with this program. //
  17. // //
  18. ////////////////////////////////////////////////////////////////////////////////
  19. /**
  20. * This script implements syndication feeds for Phorum.
  21. * There are multiple output adapters available for generating
  22. * various output formats (currently RSS, Atom, HTML en JavaScript).
  23. *
  24. * @package PhorumAPI
  25. * @subpackage Feed
  26. * @copyright 2011, Phorum Development Team
  27. * @license Phorum License, http://www.phorum.org/license.txt
  28. */
  29. require_once PHORUM_PATH.'/include/api/format/messages.php';
  30. // {{{ Constant definition
  31. /**
  32. * Function call flag, which tells {@link phorum_api_feed()} that
  33. * a feed has to be generated for all (readable) forums in the
  34. * current (v)root.
  35. */
  36. define('PHORUM_FEED_VROOT', 0);
  37. /**
  38. * Function call flag, which tells {@link phorum_api_feed()} that
  39. * a feed has to be generated for a single forum.
  40. */
  41. define('PHORUM_FEED_FORUM', 1);
  42. /**
  43. * Function call flag, which tells {@link phorum_api_feed()} that
  44. * a feed has to be generated for a single thread.
  45. */
  46. define('PHORUM_FEED_THREAD', 2);
  47. // }}}
  48. // {{{ Function: phorum_api_feed()
  49. /**
  50. * Collect the data that is used for the feed and pass this information
  51. * on to the requested output adapter.
  52. *
  53. * @param string $adapter
  54. * The output adapter to use. The adapters that are available are:
  55. * - rss
  56. * - atom
  57. * - html
  58. * - js
  59. *
  60. * @param integer $source_type
  61. * The type of source. This is one of:
  62. * - {@link PHORUM_FEED_VROOT}
  63. * - {@link PHORUM_FEED_FORUM}
  64. * - {@link PHORUM_FEED_THREAD}
  65. *
  66. * @param integer $id
  67. * This parameter has a different meaning for each $source_type:
  68. * - For {@link PHORUM_FEED_VROOT}: the forum_id of the (v)root.
  69. * - For {@link PHORUM_FEED_FORUM}: the forum_id of the forum.
  70. * - For {@link PHORUM_FEED_THREAD}: the message_id of the thread.
  71. *
  72. * @param integer $count
  73. * The number of messages to include in the feed.
  74. *
  75. * @param boolean $replies
  76. * TRUE to include reply messages in the feed, FALSE otherwise.
  77. * This parameter is forced to TRUE for {@link PHORUM_FEED_THREAD}.
  78. */
  79. function phorum_api_feed($adapter, $source_type, $id, $count, $replies)
  80. {
  81. global $PHORUM;
  82. settype($id, 'int');
  83. settype($count, 'int');
  84. settype($source_type, 'int');
  85. $replies = $replies ? 1 : 0;
  86. $adapter = basename($adapter);
  87. if (!preg_match('/^[a-z][\w_]*$/', $adapter)) trigger_error(
  88. 'phorum_api_feed(): Illegal feed adapter name ' .
  89. '"'.htmlspecialchars($adapter).'" used',
  90. E_USER_ERROR
  91. );
  92. if (!file_exists(PHORUM_PATH.'/include/api/feed/'.$adapter.'.php')) {
  93. trigger_error(
  94. 'phorum_api_feed(): Unknown feed adapter ' .
  95. '"'.htmlspecialchars($adapter).'" used',
  96. E_USER_ERROR
  97. );
  98. }
  99. // ----------------------------------------------------------------------
  100. // Prepare the data for the requested feed type
  101. // ----------------------------------------------------------------------
  102. // Prepare data for handling a vroot feed.
  103. if ($source_type === PHORUM_FEED_VROOT)
  104. {
  105. $forums = phorum_api_forums_by_vroot($id);
  106. $thread_id = NULL;
  107. $forum_ids = array_keys($forums);
  108. $cache_part = implode(',', array_keys($forums));
  109. }
  110. // Prepare data for handling a forum based feed.
  111. elseif ($source_type === PHORUM_FEED_FORUM)
  112. {
  113. if ($PHORUM['forum_id'] == $id) {
  114. $forum = $PHORUM; // contains all required data already
  115. } else {
  116. $forum = phorum_api_forums_by_forum_id($id);
  117. if (empty($forum)) trigger_error(
  118. "phorum_api_feed(): Forum for forum_id \"$id\" not found.",
  119. E_USER_ERROR
  120. );
  121. }
  122. $forums = array($id => $forum);
  123. $thread_id = NULL;
  124. $forum_ids = array_keys($forums);
  125. $cache_part = $forum['forum_id'];
  126. }
  127. // Prepare data for handling a thread based feed.
  128. elseif ($source_type === PHORUM_FEED_THREAD)
  129. {
  130. // When a feed for a thread is requested, we always include the
  131. // reply messages for that thread in the feed.
  132. $replies = 1;
  133. // Retrieve the thread starter message.
  134. $thread = $PHORUM['DB']->get_message($id);
  135. if (empty($thread)) trigger_error(
  136. "phorum_api_feed(): Thread for message_id \"$id\" not found.",
  137. E_USER_ERROR
  138. );
  139. if (!empty($thread['parent_id'])) trigger_error(
  140. "phorum_api_feed(): Message for message_id \"$id\" is not " .
  141. "the start message of a thread.",
  142. E_USER_ERROR
  143. );
  144. $thread_id = $id;
  145. $forum_ids = NULL;
  146. $cache_part = $id;
  147. }
  148. // Unknown feed type requested.
  149. else trigger_error(
  150. "phorum_api_feed(): Illegal value \"$source_type\" used " .
  151. "for parameter \$source_type.",
  152. E_USER_ERROR
  153. );
  154. // ----------------------------------------------------------------------
  155. // Retrieve the data for the requested feed
  156. // ----------------------------------------------------------------------
  157. $data = NULL;
  158. $content_type = NULL;
  159. // Try to retrieve the data from cache.
  160. if (!empty($PHORUM['cache_rss']))
  161. {
  162. // Build the cache key that uniquely identifies the requested feed.
  163. $cache_key = $PHORUM['user']['user_id'] . '|' .
  164. $adapter . '|' . $source_type . '|' . $cache_part . '|' .
  165. $replies . '|' . $count;
  166. $cache = phorum_api_cache_get('feed', $cache_key);
  167. if (!empty($cache)) {
  168. list ($data, $content_type) = $cache;
  169. }
  170. }
  171. // No data from cache. Load the recent threads / messages
  172. // directly from the database and generate the feed data.
  173. if (empty($data))
  174. {
  175. // ----------------------------------------------------------------
  176. // Retrieve the messages to show
  177. // ----------------------------------------------------------------
  178. $messages = $PHORUM['DB']->get_recent_messages(
  179. $count, // get $count messages
  180. 0, // on the first page
  181. $forum_ids, // from these forums
  182. $thread_id, // or from this thread
  183. $replies ? LIST_RECENT_MESSAGES : LIST_RECENT_THREADS
  184. );
  185. // Temporarily, remove the user list from the messages array.
  186. $users = $messages['users'];
  187. unset($messages['users']);
  188. // Apply the "read" hook(s) to the messages.
  189. if (isset($PHORUM['hooks']['read'])) {
  190. $messages = phorum_api_hook('read', $messages);
  191. }
  192. // Apply formatting to the messages.
  193. $messages = phorum_api_format_messages($messages);
  194. // Put the array of users back in the messages array.
  195. $messages['users'] = $users;
  196. // ----------------------------------------------------------------
  197. // Setup the feed URL, title and description based on
  198. // the type of feed that was requested.
  199. // ----------------------------------------------------------------
  200. if ($source_type === PHORUM_FEED_VROOT)
  201. {
  202. $feed_url = phorum_api_url(PHORUM_INDEX_URL);
  203. $feed_title = strip_tags($PHORUM['DATA']['TITLE']);
  204. $feed_description = (!empty($PHORUM['description']))
  205. ? $PHORUM['description'] : '';
  206. }
  207. if ($source_type === PHORUM_FEED_FORUM)
  208. {
  209. $feed_url = phorum_api_url(PHORUM_LIST_URL);
  210. /**
  211. * @todo The formatting of the forum base feed data should
  212. * be based on the data in $forum and not the common.php
  213. * $PHORUM contents. This is left as is for now, because
  214. * the wrong data will only be shown for threads that
  215. * were moved to a different forum.
  216. */
  217. $feed_title = strip_tags(
  218. $PHORUM['DATA']['TITLE'].' - '.$PHORUM['DATA']['NAME']);
  219. $feed_description = strip_tags($PHORUM['DATA']['DESCRIPTION']);
  220. }
  221. if ($source_type === PHORUM_FEED_THREAD)
  222. {
  223. // Retrieve the information for the forum to which the thread
  224. // belongs. Normally, this should be in $PHORUM already, but
  225. // let's make sure that the caller is using the correct forum id
  226. // in the URL here (since the thread might have been moved to
  227. // a different forum).
  228. $forum_id = $thread['forum_id'];
  229. if ($PHORUM['forum_id'] == $forum_id) {
  230. $forum = $PHORUM; // contains all required data already
  231. } else {
  232. $forum = phorum_api_forums_by_forum_id($forum_id);
  233. if (empty($forum)) trigger_error(
  234. "phorum_api_feed(): Forum for forum_id \"$id\" not found.",
  235. E_USER_ERROR
  236. );
  237. }
  238. $forums = array($forum_id => $forum);
  239. $feed_url = phorum_api_url(
  240. PHORUM_FOREIGN_READ_URL,
  241. $thread['forum_id'], $thread_id, $thread_id
  242. );
  243. $feed_title = strip_tags($thread['subject']);
  244. $feed_description = strip_tags($thread['body']);
  245. }
  246. // ----------------------------------------------------------------
  247. // All data has been collected. Now the feed is generated.
  248. // ----------------------------------------------------------------
  249. require_once PHORUM_PATH.'/include/api/feed/'.$adapter.'.php';
  250. $adapter_function = 'phorum_api_feed_'.$adapter;
  251. list ($data, $content_type) = $adapter_function(
  252. $messages, $forums,
  253. $feed_url, $feed_title, $feed_description, $replies
  254. );
  255. // Store the feed data in the cache for future use.
  256. if (!empty($PHORUM['cache_rss'])) {
  257. phorum_api_cache_put(
  258. 'feed', $cache_key,
  259. array($data, $content_type, 600)
  260. );
  261. }
  262. }
  263. // ----------------------------------------------------------------------
  264. // Output the feed data to the client
  265. // ----------------------------------------------------------------------
  266. header("Content-Type: $content_type");
  267. print $data;
  268. /*
  269. * [hook]
  270. * feed_sent
  271. *
  272. * [description]
  273. * This hook is called whenever the feed has been sent to the client
  274. * (regardless of the cache setting). This can be used to add internal
  275. * server side tracking code.
  276. *
  277. * [category]
  278. * Feed
  279. *
  280. * [when]
  281. * Feed sent to the client
  282. *
  283. * [input]
  284. * None
  285. *
  286. * [output]
  287. * None
  288. *
  289. * [example]
  290. * <hookcode>
  291. * function phorum_mod_foo_feed_after ()
  292. * {
  293. * # E.g. do server side tracking
  294. * @file_get_contents('your tracking service');
  295. * }
  296. * </hookcode>
  297. */
  298. phorum_api_hook('feed_sent');
  299. // Exit explicitly here, for not giving back control to portable and
  300. // embedded Phorum setups.
  301. exit(0);
  302. }
  303. // }}}
  304. ?>