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

Contents of /contributions/modules/article/article.module

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


Revision 1.23 - (show annotations) (download) (as text)
Sun Jun 25 16:14:33 2006 UTC (3 years, 5 months ago) by msameer
Branch: MAIN
CVS Tags: HEAD
Branch point for: DRUPAL-4-7
Changes since 1.22: +2 -1 lines
File MIME type: text/x-php
$form['article_vocab'] should get a size
1 <?php
2 // $Id: article.module,v 1.22 2006/06/25 16:11:36 msameer Exp $
3
4 /**
5 Article Module - an easy to use intergrated article management module.
6
7 The article module allows for articles to be organized and displayed in
8 a cenrtalized location. In essence it is a specialized taxonomy display
9 module with some specific features that make it sutible for articles.
10
11 @author Nicholas Young-Soares
12 @package module_article
13
14 @defgroup module_article an easy to use intergrated article management module.
15 @{
16 **/
17
18 /**
19 Hook Block - displays the latest articles list in a block.
20
21 @param op the operation to be preformed. (default="list")
22 @param delta the block to be displayed. (default=0)
23
24 @return an array containin the block output.
25 **/
26 function article_block($op = 'list', $delta = 0, $edit = array()) {
27 if ($op == 'list') {
28 $blocks[0]['info'] = t('Latest Articles');
29 return $blocks;
30 }
31 elseif ($op == 'view' && user_access('access content')) {
32 $content = module_invoke('node', 'title_list', article_get_latest(variable_get('article_recent_block', '5')));
33
34 if ($content) {
35 $content .= theme('more_info', l(t('more'), 'article', array('title' => t('Read more articles.'))));
36 }
37
38 $blocks['subject'] = t(variable_get('article_block_title', t('Latest Articles')));
39 $blocks['content'] = $content;
40 return $blocks;
41 }
42 elseif ($op == 'configure' && $delta == 0) {
43 $form['article_block_title'] = array(
44 '#type' => 'textfield',
45 '#title' => t('Block Title'),
46 '#default_value' => variable_get('article_block_title', t('Latest Articles')),
47 '#size' => 35,
48 '#maxlength' => 255,
49 '#description' => t('Title of the Articles block.')
50 );
51 $form['article_recent_block'] = array(
52 '#type' => 'select',
53 '#title' => t('Recent Articles to Display'),
54 '#options' => drupal_map_assoc(array(5, 10, 15, 20)),
55 '#default_value' => variable_get('article_recent_block', 5),
56 '#description' => t('Sets the number of recent articles that will be displayed in the Recent Articles block.'),
57 '#multiple' => false
58 );
59 return $form;
60 }
61 elseif ($op == 'save' && $delta == 0) {
62 variable_set('article_recent_block', $edit['article_recent_block']);
63 variable_set('article_block_title', $edit['article_block_title']);
64 }
65 }
66
67
68 /**
69 Hook Help - displays help and general information about the module.
70
71 @param section specifies the section to display help for.
72
73 @return a formated string containing the help output.
74 **/
75 function article_help($section) {
76 global $base_url;
77
78 $output = '';
79 switch ($section) {
80 case 'admin/help#article':
81 case 'admin/modules#description':
82 $output = t('Allow users to view nodes of multiple types in a central location.');
83 break;
84 }
85
86 return $output;
87 }
88
89 /**
90 Hook Link - returns links to the article module.
91
92 @param type specifies the type of link to display. (page or admin)
93 @param node
94
95 @return an array of links.
96 **/
97 function article_link($type, $node = 0) {
98
99 $links = array();
100
101 if ($type == 'page' && user_access('access content')) {
102 $links[] = l(t(variable_get('article_title', 'articles')), 'article', array('title' => t('Article listings.')));
103 }
104
105 return $links;
106 }
107
108 /**
109 Hook Menu - sets up article entries in the main menu..
110
111 @return an array of menu items.
112 **/
113 function article_menu($may_cache) {
114 $items = array();
115
116 $items[] = array('path' => 'article', 'title' => t('Article listings'), 'callback' => 'article_page', 'access' => user_access('access content'), 'type' => MENU_CALLBACK);
117
118 return $items;
119 }
120
121 /**
122 Hook Settings - admin settings for the article module.
123
124 @return a formatted settings form.
125 **/
126 function article_settings() {
127 $select = array();
128
129 $vocabularies = module_invoke('taxonomy', 'get_vocabularies');
130 if (is_array($vocabularies) && count($vocabularies) > 0) {
131 foreach ($vocabularies as $vocabulary) {
132 $select[$vocabulary->vid] = $vocabulary->name;
133 }
134 }
135
136 $form['article_vocab'] = array(
137 '#type' => 'select',
138 '#title' => t('Article Vocabularies'),
139 '#size' => min(9, count($select)),
140 '#options' => $select,
141 '#multiple' => TRUE,
142 '#default_value' => variable_get('article_vocab', ''),
143 '#description' => t('Select the vocabularies which contain the Article categories. All the vocabularies you select here will show up on the Article index.'),
144 );
145 $form['article_title'] = array(
146 '#type' => 'textfield',
147 '#title' => t('Overview Title'),
148 '#default_value' => variable_get('article_title', t('Articles')),
149 '#size' => 35,
150 '#maxlength' => 255,
151 '#description' => t('Title of the Articles box.')
152 );
153 $form['article_index_depth'] = array(
154 '#type' => 'select',
155 '#title' => t('Index Depth'),
156 '#options' => array(0 => 'All Terms', 1 => 1, 2 => 2, 3 => 3, 4 => 4, 5 => 5, 6 => 6),
157 '#default_value' => variable_get('article_index_depth', 0),
158 '#description' => t('Defines how many levels of terms should be displayed on any given article index page. For example, if you select 1 then only one level of the Article index tree will be displayed at a time.'),
159 '#multiple' => false
160 );
161 $form['recent_group'] = array('#type' => 'fieldset', '#title' => t('Recent Box Settings'));
162 $form['recent_group']['article_recent_box_enable'] = array(
163 '#type' => 'radios',
164 '#title' => t('Recent Articles Box'),
165 '#options' => array(t('Disabled'), t('Enabled')),
166 '#default_value' => variable_get('article_recent_box_enable', 1),
167 '#description' => t('Enables or Disables the recent articles box on the article index page.'),
168 '#required' => false
169 );
170 $form['recent_group']['article_recent_box_title'] = array(
171 '#type' => 'textfield',
172 '#title' => 'Box Title',
173 '#default_value' => variable_get('article_recent_box_title', t('Latest Articles')),
174 '#size' => 35,
175 '#maxlength' => 255,
176 '#description' => t('Title of the Recent Articles Box on the Article index page.')
177 );
178 $form['recent_group']['article_recent_display'] = array(
179 '#type' => 'select',
180 '#options' => drupal_map_assoc(array(5, 10, 15)),
181 '#default_value' => variable_get('article_recent_display', '5'),
182 '#title' => t('Articles to Display'),
183 '#description' => t('Sets the number of recent articles that will be displayed in the Recent Articles box. (0 = not displayed).'),
184 '#multiple' => false
185 );
186
187 return $form;
188 }
189
190 /**
191 Hook Page - displays the main article page.
192
193 @return null.
194 **/
195 function article_page() {
196 $body = '';
197
198 if (arg(1) == 'feed') {
199 module_invoke('node', 'feed', module_invoke('taxonomy', 'select_nodes', article_get_article_terms(), 'or', 0, FALSE));
200 }
201 else {
202 if (arg(1) != NULL) {
203 $breadcrumb = drupal_get_breadcrumb();
204 $term = article_build_breadcrumbs($breadcrumb);
205 drupal_set_breadcrumb($breadcrumb);
206
207 if ($term != NULL) {
208 $content = article_index($term->tid);
209 if ($content != '') {
210 $body = theme('box', $term->name . '- '. t('Sub Categories'), $content);
211 }
212
213 $terms = array_merge(array($term->tid), array_map('_article_get_tid_from_term', module_invoke('taxonomy', 'get_children', $term->tid)));
214 print theme('page', $body . module_invoke('taxonomy', 'render_nodes', module_invoke('taxonomy', 'select_nodes', $terms)));
215 }
216 }
217 else {
218 $body = '';
219
220 if (variable_get('article_recent_box_enable', 1)) {
221 $body = theme('box', variable_get('article_recent_box_title', t('Latest Articles')), module_invoke('node', 'title_list', article_get_latest(variable_get('article_recent_display', '5'))) . theme('more_info', theme_feed_icon("article/feed")));
222 }
223 $content = article_index();
224 if ($content != '') {
225 print theme('page', $body . theme('box', t('Article Categories'), $content));
226 }
227 }
228 }
229 }
230
231 /**
232 Constructs a url from the current url arguments list.
233
234 @return a string containing a formated URL.
235 **/
236 function article_get_current_url() {
237 $arg_index = 1;
238 $url = arg(0);
239 while ($argument = arg($arg_index)) {
240 $url .= '/'. urlencode($argument);
241 $arg_index++;
242 }
243 return $url;
244 }
245
246
247 /**
248 Constructs the article index page, using theme functions.
249
250 @return a string containing the output ready for display.
251 **/
252 function article_index($tid = 0) {
253 $output = '';
254
255 $vocabularies = article_get_vocabularies();
256 foreach ($vocabularies as $vocab) {
257 $max_depth = variable_get('article_index_depth', 0);
258 $vocab_tree = module_invoke('taxonomy', 'get_tree', $vocab->vid, $tid, -1, ($max_depth <= 0) ? NULL : $max_depth);
259 $content = '';
260
261 while (current($vocab_tree) != NULL) {
262 $content .= article_build_index($vocab_tree, article_get_current_url());
263 }
264
265 if ($content != '') {
266 $output .= theme('article_index', $vocab->name, $content);
267 }
268 }
269
270 return $output;
271 }
272
273
274 /**
275 Recursivly traverses the term tree to construct the index.
276
277 @return string the output for this tree.
278 **/
279 function article_build_index(&$tree, $parent_url) {
280 $output = '';
281
282 if ($tree == array()) {
283 return '';
284 }
285
286 do {
287 $cur = current($tree);
288 $nex = next($tree);
289 if ($nex === false) {
290 $next_depth = -1;
291 }
292 else {
293 $next_depth = $nex->depth;
294 }
295
296 $cur->link = $parent_url . '/' . urlencode(trim($cur->name));
297
298 $cur->children = '';
299 if ($next_depth > $cur->depth) {
300 $cur->children = article_build_index($tree, $cur->link);
301
302 // sync $next_depth, because 'next item' may be shoved forward
303 // Thanks for the patch Roderik.
304 $nex = current($tree);
305 if ($nex === false) {
306 $next_depth = -1;
307 }
308 else {
309 $next_depth = $nex->depth;
310 }
311 }
312
313 $cur->count = module_invoke('taxonomy', 'term_count_nodes', ($cur->tid));
314
315 $output .= theme('article_index_item', $cur);
316 } while ($cur->depth == $next_depth);
317
318 return theme('article_list', $output);
319 }
320
321
322 /**
323 Gets all the vocabularies that are associated with the article module.
324
325 @return array the vocabularies.
326 **/
327 function article_get_vocabularies() {
328 $allvocabularies = module_invoke('taxonomy', 'get_vocabularies');
329 $article_vocabs = variable_get('article_vocab', array());
330 $vocabularies = array();
331 foreach ($article_vocabs as $vocab) {
332 $vocabularies[] = $allvocabularies[$vocab];
333 }
334 return $vocabularies;
335 }
336
337
338 /**
339 Get all the terms associated with Articles.
340
341 @return an array of unique term ids.
342 **/
343 function article_get_article_terms() {
344 $vocabs = article_get_vocabularies();
345 $tids = array();
346 foreach ($vocabs as $vocab) {
347 $tids = array_merge($tids, article_tax_get_terms($vocab->vid));
348 }
349 return array_unique($tids);
350 }
351
352
353 /**
354 Get all the terms in a given vocabulary.
355
356 @return an array of unique term ids.
357 **/
358 function article_tax_get_terms($vid) {
359 $result = db_query('SELECT tid FROM {term_data} WHERE vid = %d', $vid);
360 $tids = array();
361 while ($term = db_fetch_array($result)) {
362 $tids[] = $term['tid'];
363 }
364 return array_unique($tids);
365 }
366
367
368 /**
369 Get the latest articles
370
371 @return a database query result.
372 **/
373 function article_get_latest($count = 0) {
374 $tids = article_get_article_terms();
375 return article_select_nodes($tids, 'or', 0, FALSE, $count);
376 }
377
378 /**
379 * Finds all nodes that match selected taxonomy conditions.
380 * This is just a copy of taxonomy_select_nodes() but
381 * includes node title field in the selection.
382 * Is this useful or try to find a taxonomy function
383 * to achieve this?
384 *
385 * @param $tids
386 * An array of term IDs to match.
387 * @param $operator
388 * How to interpret multiple IDs in the array. Can be "or" or "and".
389 * @param $depth
390 * How many levels deep to traverse the taxonomy tree. Can be a nonnegative
391 * integer or "all".
392 * @param $pager
393 * Whether the nodes are to be used with a pager (the case on most Drupal
394 * pages) or not (in an XML feed, for example).
395 * @return
396 * A resource identifier pointing to the query results.
397 */
398 function article_select_nodes($tids = array(), $operator = 'or', $depth = 0, $pager = TRUE, $count = 0) {
399 if (count($tids) > 0) {
400 // For each term ID, generate an array of descendant term IDs to the right depth.
401 $descendant_tids = array();
402 if ($depth === 'all') {
403 $depth = NULL;
404 }
405 foreach ($tids as $index => $tid) {
406 $term = module_invoke('taxonomy', 'get_term', $tid);
407 $tree = module_invoke('taxonomy', 'get_tree', $term->vid, $tid, -1, $depth);
408 $descendant_tids[] = array_merge(array($tid), array_map('_article_get_tid_from_term', $tree));
409 }
410
411 if ($operator == 'or') {
412 $str_tids = implode(',', call_user_func_array('array_merge', $descendant_tids));
413 $sql = 'SELECT DISTINCT n.nid, n.title, n.sticky, n.created FROM {node} n INNER JOIN {term_node} tn ON n.nid = tn.nid WHERE tn.tid IN ('. $str_tids .') AND n.status = 1 ORDER BY n.sticky DESC, n.created DESC';
414 $sql_count = 'SELECT COUNT(n.nid) FROM {node} n INNER JOIN {term_node} tn ON n.nid = tn.nid WHERE tn.tid IN ('. $str_tids .') AND n.status = 1';
415 }
416 else {
417 $joins = '';
418 $wheres = '';
419 foreach ($descendant_tids as $index => $tids) {
420 $joins .= ' INNER JOIN {term_node} tn'. $index .' ON n.nid = tn'. $index .'.nid';
421 $wheres .= ' AND tn'. $index .'.tid IN ('. implode(',', $tids) .')';
422 }
423 $sql = 'n.nid, n.title, n.sticky, n.created FROM {node} n '. $joins .' WHERE n.status = 1 AND '. $wheres .' ORDER BY n.sticky DESC, n.created DESC';
424 $sql_count = 'SELECT COUNT(n.nid) FROM {node} n '. $joins .' WHERE n.status = 1 AND '. $wheres;
425 }
426
427 if ($pager && ($count > 0)) {
428 $result = pager_query(db_rewrite_sql($sql), variable_get('default_nodes_main', 10) , 0, db_rewrite_sql($sql_count));
429 }
430 else {
431 $count = ($count > 0) ? $count : 15;
432 $result = db_query_range(db_rewrite_sql($sql), 0, $count);
433 }
434 }
435
436 return $result;
437 }
438
439 /**
440 Builds a breadcrumb list.
441
442 @param breadcrumb a reference to the breadcrumb array. New items will be appending to this array.
443
444 @return returns a term object if the last item in the url is a term, otherwise returns NULL.
445 **/
446 function article_build_breadcrumbs(&$breadcrumb) {
447 if (arg(1) != NULL) {
448 $i = 1;
449 $url = 'article';
450 $breadcrumb[] = l(drupal_ucfirst(variable_get('article_title', t('Article'))), $url);
451 while (arg($i) != NULL) {
452 $last_term = urldecode(arg($i));
453 $url = $url . '/' . urlencode($last_term);
454 $breadcrumb[] = l(drupal_ucfirst($last_term), $url);
455 $i++;
456 }
457
458 $term = current(module_invoke('taxonomy', 'get_term_by_name', $last_term));
459 return $term;
460 }
461 return NULL;
462 }
463
464 /**
465 Helper function for array map purposes.
466 @param term the term object from which the tid will be extracted.
467
468 @return the tid member of $term.
469 **/
470 function _article_get_tid_from_term($term) {
471 return $term->tid;
472 }
473 /** @} End of the module_article group **/
474
475
476 /**
477 @addtogroup theme_system
478
479 Article module specific theme functions.
480 @{
481 **/
482
483
484 /**
485 Controls the output of the rendered index list.
486
487 @return string the output for the index list.
488 **/
489 function theme_article_index(&$name, &$index_list) {
490 if ($index_list != '') {
491 return "<div class=\"item-list\">\n$index_list\n</div>\n";
492 }
493 return '';
494 }
495
496
497 /**
498 Displays a single one level list. Called for each group of items at the same depth.
499
500 @return string the output for this list.
501 **/
502 function theme_article_list(&$output) {
503 if ($output != '') {
504 return "<ul>$output</ul>\n";
505 }
506 return '';
507 }
508
509
510 /**
511 Displays a single index item.
512
513 @return string the output for this item.
514 **/
515 function theme_article_index_item(&$term) {
516 $description = ($term->description != '') ? '<p class="article-desc">'. $term->description .'</p>' : '';
517 if ($term->count > 0) {
518 return '<li><div class="article-title">'. l($term->name ." ($term->count)", $term->link) .'</div>'. $description.$term->children .'</li>';
519 }
520 else {
521 return '<li><div class="article-title">'. $term->name ." ($term->count)</div>". $description.$term->children .'</li>';
522 }
523 }
524
525
526 /**
527 Displays more information content, suck as "more" links, and
528 feed images.
529
530 @return formatted string containint the output.
531 **/
532 function theme_more_info($content) {
533 return "<div class=\"more-link\">$content</div>";
534 }
535
536 /** @} End of addtogroup theme_system **/
537
538 ?>

  ViewVC Help
Powered by ViewVC 1.1.2