/[drupal]/contributions/modules/feed/feed.module
ViewVC logotype

Contents of /contributions/modules/feed/feed.module

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.2 - (show annotations) (download) (as text)
Mon Oct 16 11:51:39 2006 UTC (3 years, 1 month ago) by thegreenman
Branch: MAIN
CVS Tags: HEAD
Branch point for: DRUPAL-4-7
Changes since 1.1: +17 -34 lines
File MIME type: text/x-php
Documentation and comment update
1 <?php
2 /*
3 * Created on 13-Oct-2006
4 * This module creates some feed handling routines that are designed to be re-usable and themeable.
5 * There are two shared RSS functions in common.inc, these are format_rss_channel and format_rss_item,
6 * and there is a nodeapi hook 'rss item' that can modify individual items (this hook can also add namespaces).
7 * There is not however any way to modify the feed itself to add xsl stylesheets.
8 *
9 * The actual code for rendering an RSS feed is copied from node.module into a number of other modules,
10 * so, the idea here is to create a set of RSS functions that can maybe eventually be used by everything.
11 *
12 *
13 */
14
15 /**
16 * implementation of hook_help
17 */
18
19 function feed_help($section) {
20 switch ($section) {
21 case 'admin/modules#description':
22 return t('Replaces feed output functions for node and terms with a xsl themeable versions.');
23 break;
24 }
25 }
26
27 /**
28 * Implementation of hook_menu
29 */
30 function feed_menu($may_cache){
31 if ($may_cache) {
32 // Create an XSL Stylesheet handler.
33 // This callback will output an XSL stylesheet that can be used to theme styles.
34 // There is a little overhead in passing this through Drupal,
35 // but XSL stylesheets are not going to be called very often, and it makes it much easier to make them dynamic.
36
37 $items[] = array(
38 'path' => 'feed.xsl',
39 'title' => t('feed stylesheet'),
40 'callback' => 'feed_style',
41 'access' => user_access('access content'),
42 'callback arguments'=>array('rss'), // defaulting to RSS for now, will need to look at ATOM
43 'type' => MENU_CALLBACK
44 );
45
46 // we overrride the defualt feed handler for nodes
47 // this requires that the feed module have a greater weight than the node module
48 $items[] = array(
49 'path' => 'rss.xml',
50 'title' => t('rss feed'),
51 'callback' => 'feed_node_rss',
52 'access' => user_access('access content'),
53 'type' => MENU_CALLBACK
54 );
55
56 } else {
57 if ((arg(0)=='taxonomy') && (arg(1)=='term')) {
58 // print "over";
59 // we override the normal feed functionality for taxonomy
60 $items[] = array(
61 'path' => 'taxonomy/term/'.arg(2).'/'.arg(3).'/feed',
62 'title' => t('rss feed'),
63 'callback' => 'feed_term_rss',
64 'access' => user_access('access content'),
65 'callback arguments'=>array(arg(2),arg(3)),
66 'type' => MENU_CALLBACK
67 );
68 }
69 }
70
71 return $items;
72 }
73
74 /**
75 * A generic function for generating RSS feeds from a set of nodes.
76 * This function replaces the default node_feed to allow the feeds to be managed by themeable functions
77 *
78 * @param $nodes
79 * An object as returned by db_query() which contains the nid field.
80 * @param $channel
81 * An associative array containing title, link, description and other keys.
82 * The link should be an absolute URL.
83 */
84 function feed_node_rss($nodes = 0, $channel = array()) {
85 global $base_url, $locale;
86
87 if (!$nodes) {
88 $nodes = db_query_range(db_rewrite_sql('SELECT n.nid FROM {node} n WHERE n.promote = 1 AND n.status = 1 ORDER BY n.created DESC'), 0, variable_get('feed_default_items', 10));
89 }
90
91 $item_length = variable_get('feed_item_length', 'teaser');
92
93 while ($node = db_fetch_object($nodes)) {
94 // Load the specified node:
95 $item = node_load($node->nid);
96 $link = url("node/$node->nid", NULL, NULL, 1);
97
98 if ($item_length != 'title') {
99 $teaser = ($item_length == 'teaser') ? TRUE : FALSE;
100
101 // Filter and prepare node teaser
102 if (node_hook($item, 'view')) {
103 node_invoke($item, 'view', $teaser, FALSE);
104 }
105 else {
106 $item = node_prepare($item, $teaser);
107 }
108
109 // Allow modules to change $node->teaser before viewing.
110 node_invoke_nodeapi($item, 'view', $teaser, FALSE);
111 }
112
113 // Prepare the item description
114 switch ($item_length) {
115 case 'fulltext':
116 $item_text = $item->body;
117 break;
118 case 'teaser':
119 $item_text = $item->teaser;
120 if ($item->readmore) {
121 $item_text .= '<p>'. l(t('read more'), 'node/'. $item->nid, NULL, NULL, NULL, TRUE) .'</p>';
122 }
123 break;
124 case 'title':
125 $item_text = '';
126 break;
127 }
128
129 $namespaces=array();
130 // Allow modules to add additional item fields
131 $extra = node_invoke_nodeapi($item, 'rss item');
132 $extra = array_merge($extra, array(array('key' => 'pubDate', 'value' => date('r', $item->created)), array('key' => 'dc:creator', 'value' => $item->name), array('key' => 'guid', 'value' => $item->nid . ' at ' . $base_url, 'attributes' => array('isPermaLink' => 'false'))));
133 // check to see if any of our hooks added a namespace
134 foreach ($extra as $element) {
135 if ($element['namespace']) {
136 $namespaces = array_merge($namespaces, $element['namespace']);
137 }
138 }
139 $items .= format_rss_item($item->title, $link, $item_text, $extra);
140 }
141
142 $output=theme('rss',$items,$channel,$namespaces);
143 $feed_content_type= variable_get('feed_content_type', 'text/xml');
144 drupal_set_header("Content-Type: $feed_content_type; charset=utf-8");
145 print $output;
146 }
147
148
149
150 /**
151 * Generate an RSS feed for taxonomy term(s)
152 * @param string str_tids A list of tids, seperated by either comma (,)or plus (+), but not both. Commas means tersm are ANDed, Plusses mean terms are ORed
153 * @param int depth ham many levels of the term heirarchy should be included in this feed
154 * */
155
156
157 function feed_term_rss($str_tids = '', $depth = 0) {
158 $tid_data=_feed_taxonomy_parse_str_tids($str_tids);
159 if ($tid_data['names']) {
160 drupal_set_title($title = check_plain(implode(', ', $tid_data['names'])));
161 $term = taxonomy_get_term($tid_data['tids'][0]);
162 $channel['link'] = url('taxonomy/term/'. $str_tids .'/'. $depth, NULL, NULL, TRUE);
163 $channel['title'] = variable_get('site_name', 'drupal') .' - '. $title;
164 $channel['description'] = $term->description;
165
166 $result = taxonomy_select_nodes($tid_data['tids'], $tid_data['operator'], $depth, FALSE);
167 feed_node_rss($result, $channel);
168 exit;
169 } else {
170 drupal_not_found();
171 }
172 }
173
174 /**
175 * Parse the string of tids
176 * @return array An array with three elements 'operator' a string with the combination operator, 'tids' an array of tids and 'names', an array of the tid names in the same order as the tids
177 */
178 function _feed_taxonomy_parse_str_tids($str_tids) {
179 if (preg_match('/^([0-9]+[+ ])+[0-9]+$/', $str_tids)) {
180 $operator = 'or';
181 // The '+' character in a query string may be parsed as ' '.
182 $tids = preg_split('/[+ ]/', $str_tids);
183 }
184 else if (preg_match('/^([0-9]+,)*[0-9]+$/', $str_tids)) {
185 $operator = 'and';
186 $tids = explode(',', $str_tids);
187 }
188
189 if ($tids) {
190 $result = db_query(db_rewrite_sql('SELECT t.tid, t.name FROM {term_data} t WHERE t.tid IN (%s)', 't', 'tid'), implode(',', $tids));
191 $tids = array(); // we rebuild the $tids-array so it only contains terms the user has access to.
192 $names = array();
193 while ($term = db_fetch_object($result)) {
194 $tids[] = $term->tid;
195 $names[] = $term->name;
196 }
197 $result=array('operator'=>$operator, 'tids'=>$tids, 'names'=>$names);
198 }
199 return $result;
200 }
201
202
203
204 /**
205 * Create an XSL stylesheet to format a feed.
206 */
207 function feed_style($feed_type='rss') {
208 $output=theme("xslt_$feed_type");
209 drupal_set_header("Content-Type: text/xml; charset=utf-8");
210 print $output;
211 }
212
213
214
215 /**
216 * A replacement for the views_rss module that uses our new system.
217 * create your own template overrride to the theme_views_rss_feed and get it to call this method.
218 */
219 function feed_views_rss_feed($view, $nodes) {
220 global $base_url;
221
222 $channel = array(
223 'title' => check_plain(views_get_title($view, 'page')),
224 'link' => url($view->real_url, NULL, NULL, true),
225 'description' => check_plain($view->description),
226 );
227
228 $item_length = variable_get('feed_item_length', 'teaser');
229 $namespaces = array('xmlns:dc="http://purl.org/dc/elements/1.1/"');
230
231 // Except for the original being a while and this being a foreach, this is
232 // completely cut & pasted from node.module.
233 foreach ($nodes as $node) {
234 // Load the specified node:
235 $item = node_load($node->nid);
236 $link = url("node/$node->nid", NULL, NULL, 1);
237
238 if ($item_length != 'title') {
239 $teaser = ($item_length == 'teaser') ? TRUE : FALSE;
240
241 // Filter and prepare node teaser
242 if (node_hook($item, 'view')) {
243 node_invoke($item, 'view', $teaser, FALSE);
244 }
245 else {
246 $item = node_prepare($item, $teaser);
247 }
248
249 // Allow modules to change $node->teaser before viewing.
250 node_invoke_nodeapi($item, 'view', $teaser, FALSE);
251 }
252
253 // Prepare the item description
254 switch ($item_length) {
255 case 'fulltext':
256 $item_text = $item->body;
257 break;
258 case 'teaser':
259 $item_text = $item->teaser;
260 if ($item->readmore) {
261 $item_text .= '<p>'. l(t('read more'), 'node/'. $item->nid, NULL, NULL, NULL, TRUE) .'</p>';
262 }
263 break;
264 case 'title':
265 $item_text = '';
266 break;
267 }
268
269 // Allow modules to add additional item fields
270 $extra = node_invoke_nodeapi($item, 'rss item');
271 $extra = array_merge($extra, array(array('key' => 'pubDate', 'value' => date('r', $item->created)), array('key' => 'dc:creator', 'value' => $item->name), array('key' => 'guid', 'value' => $item->nid . ' at ' . $base_url, 'attributes' => array('isPermaLink' => 'false'))));
272 foreach ($extra as $element) {
273 if ($element['namespace']) {
274 $namespaces = array_merge($namespaces, $element['namespace']);
275 }
276 }
277 $items .= format_rss_item($item->title, $link, $item_text, $extra);
278 }
279
280 $output=theme('rss',$items,$channel,$namespaces);
281 $feed_content_type= variable_get('feed_content_type', 'text/xml');
282 drupal_set_header("Content-Type: $feed_content_type; charset=utf-8");
283 print $output;
284 exit;
285 }
286
287
288 include_once("feed.theme");

  ViewVC Help
Powered by ViewVC 1.1.2