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

Contents of /contributions/modules/g2/g2.module

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


Revision 1.19 - (show annotations) (download) (as text)
Sun Aug 19 21:24:39 2007 UTC (2 years, 3 months ago) by fgm
Branch: MAIN
CVS Tags: HEAD
Branch point for: DRUPAL-6--1
Changes since 1.18: +352 -447 lines
File MIME type: text/x-php
First experimental version for Drupal 6
1 <?php
2 /**
3 * This defines a node-based glossary module,
4 * as opposed to the term-based glossary module in drupal 4.6/4.7
5 * Copyright (C) 2005-2006 Frederic G. MARAND
6 * Licensed under the CeCILL, version 2
7 * $Id: g2.module,v 1.18 2007/05/20 15:40:34 fgm Exp $
8 * @todo split settings form with local tabs
9 * @todo convert to class format, rename constants
10 */
11
12 $_g2_er = error_reporting(E_ALL | E_STRICT);
13
14 /**
15 * Constants missing from older node.module versions (still missing from node.module 1.582, see http://drupal.org/node/43355)
16 */
17 if (!defined('NODE_PUBLISHED'))
18 {
19 define('NODE_NOT_PUBLISHED', 0);
20 define('NODE_PUBLISHED', 1) ;
21 define('NODE_NOT_IN_MODERATION', 0); // moderate
22 define('NODE_IN_MODERATION', 1);
23 define('NODE_NOT_PROMOTED', 0); // promote
24 define('NODE_PROMOTED', 1);
25 define('NODE_NOT_STICKY', 0); // sticky
26 define('NODE_STICKY', 1);
27 }
28
29 /**
30 * G2 various constants
31 */
32 define('G2NODETYPE', 'g2_entry');
33 define('G2PERMVIEW', 'view g2 entries');
34 define('G2PERMADMIN', 'administer g2 entries');
35 define('G2VERSION', '$Id: g2.module,v 1.18 2007/05/20 15:40:34 fgm Exp $');
36
37 /**
38 * G2 menu information
39 */
40 define('G2PATHSETTINGS', 'admin/settings/g2');
41 define('G2PATHAUTOCOMPLETE', 'g2/autocomplete');
42 define('G2PATHENTRIES', 'g2/entries');
43 define('G2PATHINITIAL', 'g2/initial');
44 define('G2PATHNODEADD', 'node/add/' . G2NODETYPE); /// @see g2_form
45 define('G2PATHWOTDFEED', 'g2/wotd/feed');
46 define('G2PATHREFERERWIPE', 'g2/wipe');
47 define('G2TITLEAUTOCOMPLETE', t('entry autocomplete'));
48 define('G2TITLEENTRIES', t('G2 entries by name'));
49 define('G2TITLEINITIAL', t('entries starting by initial %initial'));
50 define('G2TITLEMAIN', t('G2 glossary main page'));
51 define('G2TITLEWOTDFEED', t('G2 word of the day RSS feed'));
52 define('G2TITLEREFERERWIPE', t('Wipe all G2 referer information'));
53
54 /**
55 * G2 settings and block configuration, persisted in {variable}
56 */
57 define('G2VARALPHABAR', 'g2_alphabar'); // Alphabar block: list of the one-symbol initials being displayed
58 define('G2VARALPHABARROWLEN', 'g2_alphabar_rowlen');// Alphabar block: row length of the themed alphabar
59 define('G2VARALPHABARTITLE', 'g2_alphabar_title'); // Alphabar block: title
60 define('G2VARGOTOSINGLE', 'g2_goto_single'); // Automatically go to the match on an "entries" page if only one exists
61 define('G2VARHIDDENTITLE', 'g2_hidden_title'); // Does hook_view include a hidden version of title for hook_update_index
62 define('G2VARHOMONYMS', 'g2_homonyms'); // disambiguation page for homonyms
63 define('G2VARHOMONYMSREDIRECT', 'g2_homonyms_redirect');// The HTTP 30x code to be used for automatic redirects
64 define('G2VARHOMONYMSVID', 'g2_homonyms_vid'); // disambiguation vocabulary id for homonyms
65 define('G2VARLATESTITEMCOUNT', 'g2_latest_item_count');// Latest(x) block: value of x
66 define('G2VARLATESTTITLE', 'g2_latest_title'); // Latest(x) block: title
67 define('G2VARMAIN', 'g2_main'); // nid of the node used as main page for G2
68 define('G2VARPAGETITLE', 'g2_page_title'); // Override for default site title on G2 pages
69 define('G2VARPATHMAIN', 'g2_pathmain'); // path for the G2 main page
70 define('G2VARNOFREETAGGING', 'g2_nofreetagging'); // Hide information from freetagging vocabularies to non-G2 admin
71 define('G2VARRANDOMENTRY', 'g2_random_entry'); // Random block: latest pseudo-random entry displayed
72 define('G2VARRANDOMSTORE', 'g2_random_store'); // Random block: store the latest random entry
73 define('G2VARRANDOMTERMS', 'g2_random_terms'); // Random block: show terms bound to entry
74 define('G2VARRANDOMTITLE', 'g2_random_title'); // Random block: title
75 define('G2VARREMOTEG2', 'g2_remote_g2'); // Base URL of remote G2 instance
76 define('G2VARRPCTHROTTLE', 'g2_rpc_throttle'); // Coefficient limit for XML-RPC operations over block settings
77 define('G2VARWOTDAUTOCHANGE', 'g2_wotd_autochange');// WOTD block: automatically change the WOTD once a day
78 define('G2VARWOTDBODYSIZE', 'g2_wotd_bodysize'); // WOTD block: number of body characters to be displayed in the block
79 define('G2VARWOTDDATE', 'g2_wotd_date'); // WOTD block: date for which this WOTD entry is current
80 define('G2VARWOTDENTRY', 'g2_wotd_entry'); // WOTD block: current entry
81 define('G2VARWOTDFEEDLINK', 'g2_wotd_feed_link'); // WOTD block feed: include a link to the WOTD RSS feed in the block
82 define('G2VARWOTDFEEDTITLE', 'g2_wotd_feed_title');// WOTD block feed: the title for the WOTD RSS feed
83 define('G2VARWOTDFEEDDESCR', 'g2_wotd_feed_descr');// WOTD block feed: the description for the WOTD RSS feed
84 define('G2VARWOTDFEEDAUTHOR', 'g2_wotd_feed_author');//WOTD block feed: include the author in the feed entries
85 define('G2VARWOTDTITLE', 'g2_wotd_title'); // WOTD block: title
86 define('G2VARWOTDTERMS', 'g2_wotd_terms'); // WOTD block: show terms bound to entry
87 define('G2VARTOPITEMCOUNT', 'g2_top_item_count'); // Top(x) block: value of x
88 define('G2VARTOPTITLE', 'g2_top_title'); // Top(x) block: title
89 define('G2VARXMLRPC', 'g2_xmlrpc'); // Is the XML-RPC server enabled ?
90
91 /**
92 * G2 default values for some of the persistent variables above
93 */
94 define('G2DEFAULTALPHABAR', '0123456789abcdefghijklmnopqrstuvwxyz');
95 define('G2DEFAULTHOMONYMSREDIRECT', '302');// The HTTP 30x code to be used for automatic redirects
96 define('G2DEFAULTPATHMAIN', 'g2');
97 define('G2DEFAULTRPCTHROTTLE', 10);
98 define('G2DEFAULTPAGETITLE', t('G2 Glossary on %title'));
99 define('G2DEFAULTREMOTEG2', 'http://www.riff.org/g2/entries');
100 define('G2DEFAULTREMOTENO', '<local>');
101 define('G2DEFAULTWOTDTITLE', t('Word of the day in the G2 glossary'));
102 define('G2DEFAULTWOTDFEEDDESCR', t("A daily definition from the G2 Glossary at %site")); // see _g2_wotd_feed()
103 define('G2DEFAULTWOTDFEEDAUTHOR', "%author"); // This default will use the actual node author
104
105 /**
106 * ========== Unimplemented hooks below: ==========
107 **/
108 /*
109 function g2_execute(&$node)
110 function g2_prepare(&$node)
111 function g2_comment($comment, $op)
112 function g2_db_rewrite_sql($query, $primary_table, $primary_field, $args)
113 function g2_elements()
114 function g2_exit($destination = NULL)
115 function g2_file_download($file)
116 function g2_footer($main = 0)
117 function g2_form_alter($form_id, &$form_values)
118 function g2_init()
119 function g2_link($type, $node = NULL, $teaser = FALSE)
120 function g2_user($op, &$edit, &$user, $category = NULL)
121 function g2_onload()
122 function g2_node_grants($user, $op)
123 function g2_ping($name = '', $url = '') {
124 function g2_search($op = 'search', $keys = null) {}
125 function g2_search_item($item) {}
126 function g2_search_preprocess($text) -- for Asian languages only ?
127 function g2_update_index()
128 function g2_taxonomy($op, $type, $object = NULL)
129 */
130
131 /**
132 * Return alphabar data
133 */
134 function _g2_alphabar()
135 {
136 $rawalphabar = variable_get(G2VARALPHABAR, G2DEFAULTALPHABAR);
137 $ret = array();
138 for ($i = 0 ; $i < strlen($rawalphabar) ; $i++)
139 {
140 $c = drupal_substr($rawalphabar, $i, 1);
141 $path = _g2_terminal_encode($c);
142 $link = array
143 (
144 'title' => $c,
145 'href' => G2PATHINITIAL . "/$path",
146 'absolute' => true, // new in 6.0, was always relative in 5.x
147 'html' => true,
148 );
149 $ret[] = $link;
150 }
151 return $ret;
152 }
153
154 /**
155 * AJAX autocomplete for entry
156 *
157 * @param string $string The beginning of the entry
158 * @see g2_menu()
159 * @see g2_block()
160 */
161 function _g2_autocomplete($string = NULL)
162 {
163 $matches = array();
164 if (isset($string))
165 {
166 $q = db_query_range("SELECT title FROM {node} WHERE LOWER(title) LIKE LOWER('%s%%') and type = '" . G2NODETYPE . "' and (status = 1)", $string, 0, 10);
167 while ($result = db_fetch_object($q)) {
168 $matches[$result->title] = check_plain($result->title);
169 // watchdog('g2', "string = $string, matches: " . print_r($matches, TRUE), WATCHDOG_NOTICE);
170 }
171 }
172 print drupal_to_js($matches);
173 exit();
174 }
175
176 /**
177 * Provides the block-specific contents common to each G2 block: ability to rename the block and change its title
178 *
179 * @param array $form The current form for which this is built
180 * @param string $infotitle Block information: the title
181 * @param string $infovar Block information: the config variable name
182 * @param string $infodefault Block information: the default name
183 * @param string $titletitle Block title: the title
184 * @param string $titlevar Block title: the config variable name
185 * @param string $titledefault Block title: the default title
186 * @return void
187 */
188 function _g2_block_settings_show(&$form, $infotitle, $infovar, $infodefault, $titletitle, $titlevar, $titledefault)
189 {
190 $form['info'] = array
191 (
192 '#type' => 'textfield',
193 '#title' => $infotitle,
194 '#default_value' => variable_get('g2_' . $infovar . '_info', $infodefault),
195 '#weight' => -2,
196 );
197 $form['title'] = array
198 (
199 '#type' => 'textfield',
200 '#title' => $titletitle,
201 '#default_value' => variable_get('g2_' . $titlevar . '_title', $titledefault),
202 '#weight' => -1,
203 );
204 }
205
206 function _g2_block_settings_save($edit, $blockname)
207 {
208 variable_set('g2_' . $blockname . '_info', $edit['info' ]);
209 variable_set('g2_' . $blockname . '_title', $edit['title']);
210 }
211
212 /**
213 * Remove unwanted terms from a taxonomy array
214 *
215 * @param array $taxonomy array of fully loaded terms (tid, vid, weight..)
216 */
217 function _g2_comb_taxonomy($taxonomy)
218 {
219 $vocabs = array();
220 if (variable_get(G2VARNOFREETAGGING, true)) // These are hidden by default
221 {
222 // We still hide the terms within freetagging vocabularies to allow partial display
223 foreach ($taxonomy as $key => $value)
224 {
225 // Is the current term in a freetagging vocabulary ?
226 if (!array_key_exists($value->vid, $vocabs))
227 {
228 $vocab = taxonomy_get_vocabulary($value->vid);
229 $vocabs[$value->vid] = $vocab->tags;
230 }
231
232 if ($vocabs[$value->vid] == true)
233 unset($taxonomy[$key]);
234 }
235 }
236 return $taxonomy;
237 }
238
239 /**
240 * Return a span containing links to taxonomy terms, or nothing
241 * if node information contains no terms. The "node" passed must
242 * contain full term information, not just tids.
243 * @param object $node imitation of a node
244 */
245 function _g2_entry_terms($node)
246 {
247 if (sizeof($node->taxonomy) > 0)
248 {
249 $ret = ' <span class="taxonomy">' ;
250 foreach ($node->taxonomy as $term)
251 {
252 $ret .= l($term->name, "taxonomy/term/$term->tid",
253 array('attributes' => array('rel' => 'tag', 'title' => $term->title)))
254 . ' | ';
255 }
256 $ret = substr($ret, 0, strlen($ret) - 3);
257 $ret .= '</span>' ;
258 }
259 return $ret;
260 }
261
262 /**
263 * Return a list of words starting by an initial segment
264 * (typically one letter, but this can be any starting substring)
265 * The logic is different from the one in _g2_entries because
266 * we don't care for the case of "/" as an initial segment
267 *
268 * @param string $initial
269 * @return string HTML
270 */
271 function _g2_initial($initial)
272 {
273 $initial = check_plain($initial);
274 $arTotal = _g2_stats();
275 $arInitial = _g2_stats(0, $initial);
276 $ret = t("<p>Displaying %count entries starting by '%initial' from a total number of %total entries.</p>",
277 array(
278 // Since _g2_stats() no longer returns empty arrays, we no longer need to check values
279 '%count' => $arInitial[NODE_PUBLISHED],
280 '%initial' => $initial,
281 '%total' => $arTotal [NODE_PUBLISHED],
282 )
283 );
284 if (user_access(G2PERMADMIN))
285 {
286 $ret .= t('<p>Admin info: there are also %count unpublished matching entries from a total number of %total unpublished entries.</p>',
287 array(
288 '%count' => $arInitial[NODE_NOT_PUBLISHED],
289 '%total' => $arTotal[NODE_NOT_PUBLISHED],
290 )
291 );
292 }
293 unset($arInitial);
294 unset($arTotal);
295
296 $sq = "select n.nid, v.title, v.teaser from {node} n inner join {node_revisions} v on n.vid = v.vid "
297 . " where (n.type='%s') and (v.title like '%s%%') and (n.status = 1) "
298 . "order by v.title ";
299 $q = db_query($sq, G2NODETYPE, $initial);
300 $ar = array();
301 while ($result = db_fetch_object($q))
302 {
303 $teaser = strip_tags($result->teaser);
304 $ar[] = l($result->title, "node/$result->nid", array('html' => true))
305 . t(': %teaser', array('%teaser' => $teaser))
306 . l(' (+)', "node/$result->nid", array('attributes' => array('class' => 'read-more')));
307 }
308 $ret .= theme('item_list', $ar);
309 return $ret;
310 }
311
312 function _g2_ip_ban()
313 {
314 return xmlrpc_error();
315 }
316
317 /**
318 * Returns a list of the latest n nodes
319 * as counted by time of update
320 * @return array
321 */
322 function _g2_latest($max = null)
323 {
324 $defmax = variable_get(G2VARLATESTITEMCOUNT, 10);
325 $rpcthrottle = variable_get(G2VARRPCTHROTTLE, G2DEFAULTRPCTHROTTLE);
326 if (empty($max) or ($max > $rpcthrottle*$defmax)) // Limit extraction
327 {
328 $max = $defmax;
329 }
330 $sq = "select n.title, n.nid, n.status from {node} n where (n.type = '" . G2NODETYPE . "') order by n.changed desc";
331 $q = db_query_range($sq, 0, $max);
332 $ret = array();
333 while ($row = db_fetch_object($q))
334 {
335 $ret[] = $row;
336 }
337 return $ret;
338 }
339
340 /**
341 * Ancillary function for g2_block to return a pseudo-random entry
342 * selected to be different from the current WOTD and, in the
343 * default setting, from the latest pseudo-random result returned.
344 * Only works for glossaries with 3 entries or more.
345 * @return object title / nid / teaser
346 */
347 function _g2_random()
348 {
349 $wotd = variable_get(G2VARWOTDENTRY, '');
350
351 // Count the allowed nodes
352 if (variable_get(G2VARRANDOMSTORE, True))
353 {
354 $random = variable_get(G2VARRANDOMENTRY, '');
355 $sq = 'select count(*) cnt '
356 . 'from {node} n '
357 . "where n.type = '" . G2NODETYPE . "' and (n.status = 1) and not (n.title = '%s' or n.nid = %d)" ;
358 $q = db_query($sq, $random, $wotd);
359 }
360 else
361 {
362 $random = '';
363 $sq = "select count(*) cnt from {node} n where n.type = '" . G2NODETYPE . "' and (n.status = 1) and not (n.nid = %d)" ;
364 $q = db_query($sq, $wotd);
365 }
366 $ret = db_fetch_object($q);
367 $n = $ret->cnt;
368 $rand = rand(0, $n - 1);
369
370 // Select from the exact same list of nodes, assuming none was inserted/deleted in the meantime
371 $sq = 'select n.title, n.nid, v.teaser '
372 . 'from {node} n inner join {node_revisions} v on n.vid = v.vid '
373 . "where n.type = '" . G2NODETYPE . "' and (n.status = 1) and not (n.title = '%s' or n.nid = %d)" ;
374 $q = db_query_range($sq, $random, $wotd, $rand, 1);
375 $ret = db_fetch_object($q);
376
377 if (variable_get(G2VARRANDOMTERMS, FALSE))
378 {
379 $taxonomy = taxonomy_node_get_terms($ret->nid);
380
381 // Currently an OSInet.fr private extension. Ignored on other sites.
382 if (function_exists('_osinode_comb_taxonomy'))
383 {
384 $taxonomy = _osinode_comb_taxonomy($taxonomy);
385 }
386 $ret->taxonomy = $taxonomy;
387 unset($taxonomy);
388 }
389 // echo "<pre>ret = " . print_r($ret, TRUE) . ", terms: " . print_r($x, TRUE) . "</pre>";
390 if (variable_get(G2VARRANDOMSTORE, True))
391 {
392 variable_set(G2VARRANDOMENTRY, $ret->title);
393 }
394 return $ret;
395 }
396
397 /**
398 * Counts the number of entries matching two criteria:
399 * @param int $tid Term Id (ignored if 0)
400 * @param string $initial Start of entry (ignored if null)
401 * @return string HTML
402 * @todo check referer wipe: it may have been damaged in the D6 port
403 */
404 function _g2_referer_links()
405 {
406 $nid = arg(1);
407 $sq = "SELECT gr.referer, gr.incoming "
408 . "FROM {g2_referer} gr "
409 . "WHERE gr.nid = %d "
410 . "ORDER BY gr.incoming DESC";
411 $q = db_query($sq, $nid);
412 $ar = array();
413 while ($o = db_fetch_object($q))
414 {
415 $ar[] = l(
416 t("%link : %incoming incoming clicks", array('%link' => $o->referer, '%incoming' => $o->incoming)),
417 $o->referer,
418 array('absolute' => true)
419 );
420 }
421 $ret = theme('item_list', $ar, '');
422 $ret .= t('WARNING: just because a click came from a node doesn\'t mean the node has a link.
423 The click may have come from a block on the page. These stats are just a hint for editors.');
424 $ret = theme('box', t('Local referers for this node'), $ret);
425
426 $form = array();
427 $form['#action'] = url(G2PATHREFERERWIPE . '/' . $nid, array('absolute' => true));
428 $form['submit'] = array(
429 '#type' => 'submit',
430 '#value' => t('Wipe referer info for this entry'),
431 );
432
433 $ret .= drupal_get_form('g2_referer_wipe', $form);
434 return $ret;
435 }
436
437 /**
438 * Erase the referer counts on g2 entries
439 *
440 * Difference from the 4.7 version: it no longer includes a goto when erasing all
441 *
442 * @param int $nid Node from which to erase referers, or null to erase all g2 referers
443 * @return void
444 */
445 function _g2_referer_wipe($nid = NULL)
446 {
447 if (isset($nid))
448 {
449 $sq .= 'DELETE from {g2_referer} WHERE nid = %d';
450 db_query($sq, check_plain($nid));
451 drupal_goto(drupal_get_path_alias("node/$nid"));
452 }
453 else
454 {
455 $sq .= 'DELETE from {g2_referer}';
456 db_query($sq);
457 }
458 }
459
460 /**
461 * Extract statistics from the G2 glossary
462 * - g2 entries having chosen taxonomy term
463 * - g2 entries starting by chosen initial segment
464 *
465 * @param int $tid Taxonomy term id
466 * @param string $initial Initial segment
467 * @return array
468 */
469 function _g2_stats($tid = 0, $initial = NULL)
470 {
471 $test1 = false;
472 $test2 = false;
473
474 $sq = "SELECT status, count(distinct n.nid) cnt FROM {node} n ";
475 $sq_test = ' n.type = \'' . G2NODETYPE . "' ";
476 if (isset($tid) && $tid > 0)
477 {
478 $sq .= "INNER JOIN {term_node} tn ON n.nid = tn.nid WHERE tn.tid = %d AND $sq_test ";
479 $test1 = true;
480 }
481 else
482 {
483 $sq .= "WHERE $sq_test ";
484 }
485 if (isset($initial) && $initial <> '')
486 {
487 $sq .= "AND n.title like '%s%%' ";
488 $test2 = true;
489 }
490 $sq .= 'GROUP BY status';
491 if ($test1 && $test2)
492 $q = db_query($sq, $tid, $initial);
493 elseif ($test1)
494 $q = db_query($sq, $tid);
495 elseif ($test2)
496 $q = db_query($sq, $initial);
497 else
498 $q = db_query($sq);
499
500 // Avoid empty returns
501 $ret = array(NODE_NOT_PUBLISHED => 0, NODE_PUBLISHED => 0) ;
502
503 while ($o = db_fetch_object($q))
504 {
505 $ret[$o->status] = $o->cnt;
506 }
507 return $ret;
508 }
509
510 /**
511 * Returns a list of the top n nodes
512 * as counted by statistics.module
513 * @param $max
514 * @return array
515 */
516 function _g2_top($max = null)
517 {
518 $defmax = variable_get(G2VARTOPITEMCOUNT, 10);
519 $rpcthrottle = variable_get(G2VARRPCTHROTTLE, G2DEFAULTRPCTHROTTLE);
520 if (empty($max) or ($max > $rpcthrottle*$defmax)) // Limit extraction
521 {
522 $max = $defmax;
523 }
524 $sq = "select n.title, n.nid, n.status from {node} n inner join {node_counter} c on n.nid = c.nid where (n.type = '" . G2NODETYPE . "') and (c.totalcount is not null) order by c.totalcount desc, n.changed desc";
525 $q = db_query_range($sq, 0, $max);
526 $ret = array();
527 while ($row = db_fetch_object($q))
528 {
529 $ret[] = $row;
530 }
531 return $ret;
532 }
533
534 /**
535 * Returns a structure for the WOTD.
536 * Limitation: always returns just the FIRST entry for a given word
537 * @param int $bodysize
538 * @return object title / nid / teaser
539 */
540 function _g2_wotd($bodysize = 0)
541 {
542 // No need for a static: this function is normally never called twice
543
544 $sqhead = 'select n.title, n.nid, v.teaser' ;
545 $entrynid = variable_get(G2VARWOTDENTRY, 0);
546
547 if ($bodysize > 0)
548 $sqhead .= ', v.body';
549 $sq = $sqhead
550 . " from {node} n inner join {node_revisions} v on n.vid = v.vid where n.type='"
551 . G2NODETYPE
552 . "' and (n.status = 1) and (n.nid=%d)";
553 $q = db_query_range($sq, $entrynid, 0, 1);
554 $ret = db_fetch_object($q);
555 if (variable_get(G2VARWOTDTERMS, FALSE))
556 {
557 $ret->taxonomy = _g2_comb_taxonomy(taxonomy_node_get_terms($ret->nid));
558 }
559 return $ret;
560 }
561
562 /**
563 * Generate an RSS feed containing the latest WOTD
564 * @return string XML in UTF-8 encoding
565 */
566 function _g2_wotd_feed()
567 {
568 global $base_url;
569
570 $channelinfo = array
571 (
572 // Link element: Drupal 4.7 defaults to $base url
573 // Language: Drupal 4.7 defaults to $locale
574 'title' => variable_get(G2VARWOTDFEEDTITLE, variable_get(G2VARWOTDTITLE, G2DEFAULTWOTDTITLE)), // Drupal defaults to site name - site slogan
575 'description' => strtr(variable_get(G2VARWOTDFEEDDESCR, G2DEFAULTWOTDFEEDDESCR), array('%site' => $base_url)), // Drupal defaults to $site_mission
576 'managingEditor' => variable_get('site_mail', 'nobody@example.com'),
577 );
578 $items = array(variable_get(G2VARWOTDENTRY, 0));
579 $ret = node_feed($items, $channelinfo);
580 return $ret;
581 }
582
583 /**
584 * implement hook_access
585 *
586 * @param $op string
587 * @param $node int
588 * The node on which the operation is to be performed, or, if it does
589 * not yet exist, the type of node to be created.
590 * @return boolean
591 * TRUE if the operation may be performed; FALSE if the operation may not be
592 * returned; NULL to not override the settings in the node_access table.
593 */
594 function g2_access($op, $node)
595 {
596 global $user;
597
598 switch ($op)
599 {
600 case 'create':
601 case 'delete':
602 case 'update':
603 $ret = user_access(G2PERMADMIN);
604 break;
605 case 'view':
606 $ret = user_access(G2PERMVIEW);
607 break;
608 }
609 return $ret;
610 }
611
612 /**
613 * implement hook_block
614 *
615 * @param $op string
616 * What kind of information to retrieve about the block or blocks.
617 * - 'list': A list of all blocks defined by the module.
618 * - 'configure': A configuration form.
619 * - 'save': Save the configuration options.
620 * - 'view': Information about a particular block.
621 * @param $delta int
622 * Which block to return (not applicable if $op is 'list').
623 * @param $edit array
624 * If $op is 'save', the submitted form data from the configuration form.
625 * @return mixed
626 * If $op is 'list', return an array of arrays, each of which must define an
627 * 'info' element describing the block. If $op is 'configure', optionally
628 * return a string containing the configuration form. If $op is 'save',
629 * return nothing, If $op is 'view', return an array which must define a
630 * 'subject' element and a 'content' element defining the block indexed by
631 * $delta.
632 */
633 function g2_block($op = 'list', $delta = 0, $edit = array()) {
634 if ($op == 'list')
635 {
636 $blocks[0]['info'] = variable_get('g2_alphabar_info', t('G2 Alphabar'));
637 $blocks[1]['info'] = variable_get('g2_random_info', t('G2 Random'));
638 $blocks[2]['info'] = variable_get('g2_top_info', t('G2 Top'));
639 $blocks[3]['info'] = variable_get('g2_wotd_info', t('G2 Word of the day'));
640 $blocks[4]['info'] = variable_get('g2_latest_info', t('G2 Latest'));
641 return $blocks;
642 }
643 elseif ($op == 'configure')
644 {
645 switch ($delta)
646 {
647 case 0: // Alphabar
648 $form['alphabar'] = array
649 (
650 '#type' => 'textfield',
651 '#title' => t('List of initials to be included in alphabar'),
652 '#default_value' => variable_get(G2VARALPHABAR, G2DEFAULTALPHABAR),
653 '#description' => t('The alphabar lists the initials for which links to initial pages will be included.')
654 );
655 $form['rowlen'] = array
656 (
657 '#type' => 'textfield',
658 '#title' => t('Maximum length of lines in the alphabar'),
659 '#default_value' => variable_get(G2VARALPHABARROWLEN, 13),
660 '#size' => 3,
661 '#description' => t('Each line except the last one will have exactly that number of links.')
662 );
663 _g2_block_settings_show($form,
664 t('Name of the block in the block list'), 'alphabar', t('G2 Alphabar'),
665 t('Title of the block when displayed'), 'alphabar', t('G2 Glossary pages'));
666 break;
667 case 1: // Random
668 $form['random_store'] = array
669 (
670 '#type' => 'checkbox',
671 '#title' => t('Store latest random entry'),
672 '#default_value' => variable_get(G2VARRANDOMSTORE, TRUE),
673 '#description' => t('When this setting is true (default value),
674 the latest random value is kept in the DB to avoid showing the same pseudo-random
675 value on consecutive page displays.
676 For small sites, it is usually best to keep it saved.
677 For larger sites, unchecking this setting will remove one database write with locking.'),
678 );
679 $form['random_terms'] = array(
680 '#type' => 'checkbox',
681 '#title' => t('Return taxonomy terms for the current entry'),
682 '#default_value' => variable_get(G2VARRANDOMTERMS, FALSE),
683 '#description' => t('The taxonomy terms will be returned by XML-RPC and made available to the theme.
684 Default G2 themeing will display them.'),
685 );
686 _g2_block_settings_show($form,
687 t('Name of the block in the block list'), 'random', t('G2 Random'),
688 t('Title of the block when displayed'), 'random', t('Random G2 glossary entry'));
689 break ;
690 case 2: // Top
691 $topcount = variable_get(G2VARTOPITEMCOUNT, 10);
692 $form['itemcount'] = array
693 (
694 '#type' => 'select',
695 '#title' => t('Number of items'),
696 '#default_value' => $topcount,
697 '#options' => array('1' => '1', '2' => '2', '5' => '5', '10' => '10')
698 );
699 _g2_block_settings_show($form,
700 t('Name of the block in the block list'), 'top', sprintf(t('G2 Top %d'), $topcount),
701 t('Title of the block when displayed'), 'top', t('%d most popular G2 glossary entries'));
702 break;
703 case 3: // WOTD
704 /**
705 * @see _g2_autocomplete()
706 */
707 $node = node_load(variable_get(G2VARWOTDENTRY, 0));
708 $form['wotd_entry'] = array
709 (
710 '#type' => 'textfield',
711 '#title' => t('Entry for the day'),
712 '#maxlength' => 60,
713 '#autocomplete_path' => G2PATHAUTOCOMPLETE,
714 '#required' => TRUE,
715 '#default_value' => $node->title,
716 );
717 $form['wotd_bodysize'] = array
718 (
719 '#type' => 'textfield',
720 '#title' => t('Number of text characters to be displayed from entry definition body, if one exists'),
721 '#size' => 4,
722 '#maxlength' => 4,
723 '#required' => TRUE,
724 '#default_value' => variable_get(G2VARWOTDBODYSIZE, '')
725 );
726 $form['wotd_autochange'] = array
727 (
728 '#type' => 'checkbox',
729 '#title' => t('Auto-change daily'),
730 '#required' => TRUE,
731 '#default_value' => variable_get(G2VARWOTDAUTOCHANGE, TRUE),
732 '#description' => t('This setting will only work if cron or poormanscron is used.')
733 );
734
735 $form['wotd_terms'] = array(
736 '#type' => 'checkbox',
737 '#title' => t('Return taxonomy terms for the current entry'),
738 '#default_value' => variable_get(G2VARWOTDTERMS, FALSE),
739 '#description' => t('The taxonomy terms will be returned by XML-RPC and made available to the theme.
740 Default G2 themeing will display them.'),
741 );
742 $form['wotd_feed'] = array(
743 '#type' => 'fieldset',
744 '#title' => 'RSS Feed',
745 );
746 $form['wotd_feed']['wotd_feed_link'] = array(
747 '#type' => 'checkbox',
748 '#title' => t('Display feed link'),
749 '#default_value' => variable_get(G2VARWOTDFEEDLINK, TRUE),
750 '#description' => t('Should the theme display the link to the RSS feed for this block ?'),
751 );
752 $form['wotd_feed']['wotd_feed_title'] = array(
753 '#type' => 'textfield',
754 '#title' => t('The feed title'),
755 '#size' => 60,
756 '#maxlength' => 60,
757 '#required' => TRUE,
758 '#default_value' => variable_get(G2VARWOTDFEEDTITLE, variable_get(G2VARWOTDTITLE, G2DEFAULTWOTDTITLE)),
759 '#description' => t('The title for the feed itself.
760 This will typically be used by aggregators to remind users of the feed and link to it.
761 If nulled, G2 will reset it to the title of the block.'),
762 );
763 $form['wotd_feed']['wotd_feed_author'] = array(
764 '#type' => 'textfield',
765 '#title' => t('The feed item author'),
766 '#size' => 60,
767 '#maxlength' => 60,
768 '#required' => TRUE,
769 '#default_value' => variable_get(G2VARWOTDFEEDAUTHOR, G2DEFAULTWOTDFEEDAUTHOR),
770 '#description' => t('The author name to be included in the feed entries.
771 In this string %author will be replaced by the actual author information.
772 Defaults to %author.'),
773 );
774 $form['wotd_feed']['wotd_feed_descr'] = array(
775 '#type' => 'textfield',
776 '#title' => t('The feed description'),
777 '#size' => 60,
778 '#maxlength' => 60,
779 '#required' => TRUE,
780 '#default_value' => variable_get(G2VARWOTDFEEDDESCR, G2DEFAULTWOTDFEEDDESCR),
781 '#description' => t('The description for the feed itself.
782 This will typically be used by aggregators when describing the feed prior to subscription.
783 It may contain %site, which will dynamically be replaced by the site base URL.
784 If nulled, G2 will reset it to a default description.'),
785 );
786
787 _g2_block_settings_show($form,
788 t('Name of the block in the block list'), 'wotd', t('G2 Word of the day'),
789 t('Title of the block when displayed'), 'wotd', t('Word of the day in the G2 glossary'));
790 break;
791 case 4: // Latest
792 $latestcount = variable_get(G2VARLATESTITEMCOUNT, 10);
793 $form['itemcount'] = array
794 (
795 '#type' => 'select',
796 '#title' => t('Number of items'),
797 '#default_value' => $latestcount,
798 '#options' => array('1' => '1', '2' => '2', '5' => '5', '10' => '10')
799 );
800 _g2_block_settings_show($form,
801 t('Name of the block in the block list'), 'latest', sprintf(t('G2 Latest %d'), $latestcount),
802 t('Title of the block when displayed'), 'latest', t('%d most recently updated G2 glossary entries'));
803 break;
804 default:
805 break;
806 }
807 return $form;
808 }
809 elseif ($op == 'save')
810 {
811 //echo "<pre>block/SAVE" . print_r($edit, TRUE) . "</pre>";
812 switch ($delta)
813 {
814 case 0: // Alphabar
815 variable_set(G2VARALPHABAR, $edit['alphabar']);
816 variable_set(G2VARALPHABARROWLEN, $edit['rowlen']);
817 _g2_block_settings_save($edit, 'alphabar');
818 break;
819 case 1: // Random
820 variable_set(G2VARRANDOMTERMS, $edit['random_terms']);
821 _g2_block_settings_save($edit, 'random');
822 break;
823 case 2: // Top
824 variable_set(G2VARTOPITEMCOUNT, $edit['itemcount']);
825 _g2_block_settings_save($edit, 'top');
826 break;
827 case 3: // WOTD
828 $node = node_load(array('title' => $edit['wotd_entry']));
829 variable_set(G2VARWOTDENTRY, $node->nid);
830 variable_set(G2VARWOTDBODYSIZE, $edit['wotd_bodysize']);
831 variable_set(G2VARWOTDAUTOCHANGE, $edit['wotd_autochange']);
832 variable_set(G2VARWOTDDATE, mktime());
833 variable_set(G2VARWOTDTERMS, $edit['wotd_terms']);
834 variable_set(G2VARWOTDFEEDLINK, $edit['wotd_feed_link']);
835 variable_set(G2VARWOTDFEEDTITLE, $edit['wotd_feed_title']);
836 variable_set(G2VARWOTDFEEDDESCR, $edit['wotd_feed_descr']);
837 variable_set(G2VARWOTDFEEDAUTHOR, $edit['wotd_feed_author']);
838 _g2_block_settings_save($edit, 'wotd');
839 break;
840 case 4: // Top
841 variable_set(G2VARLATESTITEMCOUNT, $edit['itemcount']);
842 _g2_block_settings_save($edit, 'latest');
843 default:
844 break;
845 }
846 }
847 elseif ($op == 'view')
848 {
849 // watchdog('g2', "hook_block/view/$delta");
850 switch ($delta)
851 {
852 case 0:
853 $block['subject'] = variable_get(G2VARALPHABARTITLE, t('G2 Glossary pages'));
854 $block['content'] = theme('g2_block_alphabar');
855 break;
856 case 1:
857 $block['subject'] = variable_get(G2VARRANDOMTITLE, t('Random G2 glossary entry'));
858 $block['content'] = theme('g2_block_random');
859 break;
860 case 2:
861 $block['subject'] = sprintf(
862 variable_get(G2VARTOPTITLE, t('%d most popular G2 glossary entries')),
863 variable_get(G2VARTOPITEMCOUNT, 10));
864 $block['content'] = theme('g2_block_top');
865 break;
866 case 3:
867 $block['subject'] = variable_get(G2VARWOTDTITLE, G2DEFAULTWOTDTITLE);
868 $block['content'] = theme('g2_block_wotd');
869 break;
870 case 4:
871 $block['subject'] = sprintf(
872 variable_get(G2VARLATESTTITLE, t('%d most recently updated G2 glossary entries')),
873 variable_get(G2VARLATESTITEMCOUNT, 10));
874 $block['content'] = theme('g2_block_latest');
875 break;
876 }
877 return $block;
878 }
879 }
880
881 /**
882 * In G2's case, change the WOTD once a day if this feature
883 * is enabled, which is the default case.
884 *
885 * @return void
886 *
887 * This hook will only be called if cron.php is run (e.g. by crontab).
888 */
889 function g2_cron()
890 {
891 if (variable_get(G2VARWOTDAUTOCHANGE, TRUE))
892 {
893 $date0 = date('z', variable_get(G2VARWOTDDATE, mktime()));
894 $date1 = date('z');
895 if ($date1 <> $date0)
896 {
897 $random = _g2_random();
898 // watchdog("g2_cron", "d0 = $date0, d1 = $date1, random : " . print_r($random,TRUE) . "</pre>", null, WATCHDOG_INFO);
899 variable_set(G2VARWOTDENTRY, $random->nid);
900 variable_set(G2VARWOTDDATE, mktime());
901 }
902 }
903 }
904
905 /**
906 * Respond to node deletion.
907 *
908 * This is a hook used by node modules. It is called to allow the module
909 * to take action when a node is being deleted from the database by, for
910 * example, deleting information from related tables.
911 *
912 * @param &$node int
913 * The node being deleted.
914 * @return void
915 *
916 * To take action when nodes of any type are deleted (not just nodes of
917 * the type defined by this module), use hook_nodeapi() instead.
918 */
919 function g2_delete(&$node) {
920 db_query('DELETE FROM {g2_node} WHERE nid = %d', $node->nid);
921 }
922
923 /**
924 * implement hook_filter
925 *
926 * @param string $op
927 * Which filtering operation to perform. Possible values:
928 * - list: provide a list of available filters.
929 * Returns an associative array of filter names with numerical keys.
930 * These keys are used for subsequent operations and passed back through
931 * the $delta parameter.
932 * - no cache: Return true if caching should be disabled for this filter.
933 * - description: Return a short description of what this filter does.
934 * - prepare: Return the prepared version of the content in $text.
935 * - process: Return the processed version of the content in $text.
936 * - settings: Return HTML form controls for the filter's settings. These
937 * settings are stored with variable_set() when the form is submitted.
938 * Remember to use the $format identifier in the variable and control names
939 * to store settings per input format (e.g. "mymodule_setting_$format").
940 * @param int $delta
941 * Which of the module's filters to use (applies to every operation except
942 * 'list'). Modules that only contain one filter can ignore this parameter.
943 * @param int $format
944 * Which input format the filter is being used in (applies to 'prepare',
945 * 'process' and 'settings').
946 * @param string $text
947 * The content to filter (applies to 'prepare' and 'process').
948 * @return string
949 * The return value depends on $op. The filter hook is designed so that a
950 * module can return $text for operations it does not use/need.
951 */
952 function g2_filter($op, $delta = 0, $format = -1, $text = '') {
953 switch ($op) {
954 case 'list':
955 return array(0 => t('G2 Glossary filter'));
956
957 case 'description':
958 return t('Allows users to link to G2 entries using &lt;dfn&gt; elements.');
959
960 case 'prepare':
961 // Note: we use the bytes 0xFE and 0xFF to replace < > during the filtering process.
962 // These bytes are not valid in UTF-8 data and thus least likely to cause problems.
963 $text = preg_replace('@<dfn>(.+?)</dfn>@s', "\xFEdfn\xFF\\1\xFE/dfn\xFF", $text);
964 return $text;
965
966 case "process":
967 $text = preg_replace('@\xFEdfn\xFF(.+?)\xFE/dfn\xFF@se', "_g2_filter_process('$1')", $text);
968 return $text;
969
970 default:
971 return $text;
972 }
973 }
974
975 /**
976 * implement hook_filter_tips
977 *
978 * @param $delta
979 * Which of this module's filters to use. Modules which only implement one
980 * filter can ignore this parameter.
981 * @param $format
982 * Which format we are providing tips for.
983 * @param $long
984 * If set to true, long tips are requested, otherwise short tips are needed.
985 * @return stringe
986 * The text of the filter tip.
987 *
988 *
989 */
990 function g2_filter_tips($delta, $format, $long = false) {
991 if ($long) {
992 return t('Wrap <dfn> elements around the terms for which you want a link to the available G2 definition(s).');
993 }
994 else {
995 return t('You may link to G2 definitions using &lt;dfn&gt; elements.');
996 }
997 }
998
999 /**
1000 * Translate glossary linking elements (<dfn>) to actual links)
1001 *
1002 * This function generates absolute links, for the benefit of the WOTD RSS feed
1003 * If this feed is not used, it is possible to use the (shorter) relative URLs
1004 * by swapping comments.
1005 * @param string $entry An entry
1006 * @return string HTML
1007 */
1008 function _g2_filter_process($entry)
1009 {
1010 $target = variable_get(G2VARREMOTEG2, G2DEFAULTREMOTEG2);
1011 if ($target == G2DEFAULTREMOTENO) /* Then we are not using a remote glossary */
1012 {
1013 $target = G2PATHENTRIES;
1014 }
1015 // $ret = l($entry, G2PATHENTRIES ."/$entry");
1016 $path = urlencode(_g2_terminal_encode($entry));
1017 $ret = l($entry, "$target/$path", array('absolute' => true, 'html' => false));
1018 return $ret;
1019 }
1020
1021 /**
1022 * Display a node editing form.
1023 *
1024 * This hook, implemented by node modules, is called to retrieve the form
1025 * that is displayed when one attempts to "create/edit" an item. This form is
1026 * displayed at the URI http://www.example.com/?q=node/<add|edit>/nodetype.
1027 *
1028 * @param $node int
1029 * The node being added or edited.
1030 * @param $param array
1031 * The hook can set this variable to an associative array of attributes
1032 * to add to the enclosing \<form\> tag.
1033 * @return array
1034 * An array containing the form elements to be displayed in the node
1035 * edit form.
1036 *
1037 * The submit and preview buttons, taxonomy controls, and administrative
1038 * accoutrements are displayed automatically by node.module. This hook
1039 * needs to return the node title, the body text area, and fields
1040 * specific to the node type.
1041 *
1042 * For a detailed usage example, see node_example.module.
1043 */
1044 function g2_form(&$node, &$param)
1045 {
1046 if (!isset($node->title))
1047 {
1048 $node->title = check_plain(substr($_REQUEST['q'], strlen(G2PATHNODEADD) + 1)) ;
1049 }
1050
1051 $form['content'] = array(
1052 '#type' => 'fieldset',
1053 '#title' => 'Contents',
1054 '#collapsible' => TRUE,
1055 '#collapsed' => FALSE,
1056 '#weight' => -10
1057 );
1058 $form['content']['title'] = array(
1059 '#type' => 'textfield',
1060 '#title' => t('Title'),
1061 '#required' => TRUE,
1062 '#default_value' => $node->title
1063 );
1064 $form['content']['teaser'] = array(
1065 '#type' => 'textfield',
1066 '#title' => t('Entry expansion (for acronyms) or translation'),
1067 '#required' => FALSE,
1068 '#default_value' => $node->teaser
1069 );
1070 $form['content']['body'] = array(
1071 '#type' => 'textarea',
1072 '#title' => t('Entry definition'),
1073 '#rows' => 10,
1074 '#required' => TRUE,
1075 '#default_value' => $node->body
1076 );
1077 $form['content']['period'] = array(
1078 '#type' => 'textfield',
1079 '#title' => t('Life period of this entry'),
1080 '#required' => FALSE,
1081 '#description' => t('This is the period of time during which the entity described by the term was actually alive, not the lifetime of the term itself, since any term is immortal to some extent.'),
1082 '#default_value' => $node->period
1083 );
1084 $form['publishing'] = array(
1085 '#type' => 'fieldset',
1086 '#title' => 'Editor-only information',
1087 '#collapsible' => TRUE,
1088 '#collapsed' => TRUE,
1089 '#description' => 'Information in this box is not published in view mode, only during node edition.',
1090 '#weight' => 0
1091 );
1092 $form['publishing']['complement'] = array(
1093 '#type' => 'textarea',
1094 '#title' => t('Complement'),
1095 '#rows' => 10,
1096 '#required' => FALSE,
1097 '#description' => t('Information not pertaining to origin of document: comments, notes...'),
1098 '#default_value' => $node->complement
1099 );
1100 $form['publishing']['origin'] = array(
1101 '#type' => 'textarea',
1102 '#title' => t('Origin/I.P.'),
1103 '#rows' => 10,
1104 '#required' => FALSE,
1105 '#description' => t('Informations about the origin/IP licensing of the definition'),
1106 '#default_value' => $node->origin
1107 );
1108
1109 $form['format'] = filter_form($node->format);
1110 return $form;
1111 }
1112
1113 /**
1114 * implement hook_help
1115 *
1116 * Modified in D6.
1117 * @todo API doc on 2007-08-19 seems wrong. Review after D6 release
1118 */
1119 function g2_help($path, $arg)
1120 {
1121 $ret = '';
1122 switch ($path)
1123 {
1124 case 'admin/build/modules#name':
1125 $ret = 'g2';
1126 break;
1127 case 'admin/help#g2': // works in D6
1128 $ret = t('<p>G2 defines a glossary service for Drupal sites. To compare it with the default Drupal glossary:
1129 <ul><li>G2 content is node-based, not term-based</li>
1130 <li>G2 leverages existing code from glossary for input filtering and node marking</li>
1131 <li>G2 RAM use does not significantly increase with larger entry counts, which makes is more suitable for larger glossaries</li>
1132 <li>G2 requests much less from the database than the default glossary</li>
1133 <li>G2 uses three taxonomy vocabularies: context, period, and grammatical nature.</li>
1134 <li>G2 defines optional blocks</li>
1135 <li>G2 is remotely usable via XML-RPC</li>
1136 <li>G2 does not provide term feeds</li>
1137 <li>G2 access control is simplistic, targeted to non-community sites</ul></p>');
1138 break;
1139 case 'admin/modules#description': // seems useless since D5
1140 $ret = t('G2 manages a node-based glossary.');
1141 break;
1142 case 'admin/build/block/configure/g2/0':
1143 $ret = t('This block displays a clickable list of initials from the G2 glossary.');
1144 break;
1145 case 'admin/build/block/configure/g2/1':
1146 $ret = t('This block displays a pseudo-random entry (different each time) from the G2 glossary.');
1147 break;
1148 case 'admin/build/block/configure/g2/2':
1149 $stats = module_exists('statistics');
1150 $count = variable_get('statistics_count_content_views', NULL);
1151 $ar = array();
1152 $ar[] = $stats
1153 ? t('Statistics module installed and activated: OK.')
1154 : t('Statistics module not installed or not activated. Install and activate it and try again.');
1155 $ret .= '"' . t('Count content views') . '" ' . t('setting is ') ;
1156 $ret .= ($count > 0)
1157 ? 'ON: OK'
1158 : 'OFF: Error. Please enabled this counter in admin/settings/statistics';
1159 $ar[] = $ret;
1160 $ret = theme('item_list', $ar, t("Dependencies checklist"));
1161 break;
1162 case 'admin/build/block/configure/g2/3':
1163 $ret = t('This block displays a once-a-day entry from the G2 glossary.');
1164 break;
1165 default: // ignore, this hook is called all over the place in 4.7b1
1166 //$ret = "g2_help($path)";
1167 }
1168 return $ret;
1169 }
1170
1171 /**
1172 * Respond to node insertion.
1173 *
1174 * This is a hook used by node modules. It is called to allow the module
1175 * to take action when a new node is being inserted in the database by,
1176 * for example, inserting information into related tables.
1177 *
1178 * @param $node int
1179 * @return void
1180 *
1181 * To take action when nodes of any type are inserted (not just nodes of
1182 * the type(s) defined by this module), use hook_nodeapi() instead.
1183 */
1184 function g2_insert($node)
1185 {
1186 db_query("INSERT INTO {g2_node} (nid, period, complement, origin) VALUES (%d, '%s', '%s', '%s')",
1187 $node->nid, $node->period, $node->complement, $node->origin);
1188 }
1189
1190 /**
1191 * implement hook_load
1192 *
1193 * @param int $node
1194 * @return object
1195 */
1196 function g2_load($node)
1197 {
1198 $ret = db_fetch_object(db_query('SELECT * FROM {g2_node} WHERE nid = %s', $node->nid));
1199 return $ret;
1200 }
1201
1202 /**
1203 * implement hook_menu
1204 *
1205 * Note: restructured in Drupal 6
1206 *
1207 * @return array
1208 */
1209 function g2_menu()
1210 {
1211 global $user;
1212 $items = array();
1213
1214 /**
1215 * @todo why arg(1) ?
1216 $view_access = (user_access(G2PERMVIEW) || ($user->uid == arg(1)));
1217 $admin_access = (user_access(G2PERMADMIN) || ($user->uid == arg(1)));
1218 */
1219
1220 $items[G2PATHSETTINGS] = array
1221 (
1222 'title' => 'G2 glossary',
1223 'description' => 'Define the various parameters used by the G2 module',
1224 'page callback' => 'drupal_get_form',
1225 'page arguments' => array('g2_admin_settings'),
1226 'access arguments' => array('administer site configuration'),
1227 'type' => MENU_NORMAL_ITEM,