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

Contents of /contributions/modules/wikitools/wikitools.module

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


Revision 1.4 - (show annotations) (download) (as text)
Mon Dec 31 23:35:06 2007 UTC (22 months, 3 weeks ago) by cwgordon7
Branch: MAIN
CVS Tags: DRUPAL-6--1-0-Beta1, HEAD
Branch point for: DRUPAL-6--1
Changes since 1.3: +193 -98 lines
File MIME type: text/x-php
Initial port to Drupal 6.
1 <?php
2 // $Id: wikitools.module,v 1.1.2.2 2007/03/12 01:18:08 roetzi Exp $
3
4 /**
5 * @file
6 * A non-intrusive module to have some wiki-like behaviour.
7 */
8
9 /**
10 * Implementation of hook_help().
11 */
12 function wikitools_help($path, $arg) {
13 switch ($path) {
14 case 'admin/help#wikitools':
15 $output = '<p>'. t('The wikitools module allows you to set several options for your content to get a more wiki-like behaviour.') .'</p>';
16 return $output;
17 break;
18 }
19 }
20
21 /*
22 * Setup functions
23 */
24
25 /**
26 * Implementation of hook_menu().
27 */
28 function wikitools_menu() {
29 $items = array();
30 $items['admin/settings/wikitools'] = array(
31 'title' => t('Wikitools'),
32 'description' => t('Settings for wiki-like behaviour.'),
33 'access arguments' => array('administer site configuration'),
34 'page callback' => 'drupal_get_form',
35 'page arguments' => array('wikitools_admin_settings'),
36 'type' => MENU_NORMAL_ITEM
37 );
38 $wiki_path = wikitools_wiki_path();
39 if ($wiki_path) {
40 $items[$wiki_path] = array(
41 'page callback' => 'wikitools_handle_request',
42 'access arguments' => array('access content'),
43 'type' => MENU_CALLBACK
44 );
45 }
46 // Override the callback for node deletion if the delete protection option is set.
47 if (wikitools_delete_protection()) {
48 // Hijack delete callback and call custom handler.
49 $items['node/%node/delete'] = array(
50 'title' => t('Delete'),
51 'page callback' => 'wikitools_delete_protection_delete_confirm',
52 'page arguments' => array(1),
53 'access callback' => 'node_access',
54 'access arguments' => array('delete', 1),
55 'weight' => 1,
56 'type' => MENU_CALLBACK
57 );
58 }
59 // Only hijack freelinking path if an argument is specified, otherwise let the freelinking page show.
60 if (wikitools_hijack_freelinking()) {
61 $items['freelinking/%'] = array(
62 'page callback' => 'wikitools_handle_request',
63 'access arguments' => array('access content'),
64 'type' => MENU_CALLBACK
65 );
66 }
67 return $items;
68 }
69
70 /**
71 * Builder function for settings form.
72 */
73 function wikitools_admin_settings() {
74 $form = array();
75
76 $form['wikitools_path'] = array(
77 '#type' => 'textfield',
78 '#title' => t('Wiki path'),
79 '#default_value' => wikitools_wiki_path(),
80 '#description' => t('The drupal path for the wiki. Do not include a trailing slash. Leave empty to disable the wiki path.'),
81 '#field_prefix' => url(NULL, array('absolute' => FALSE)) . (variable_get('clean_url', 0) ? '' : '?q=')
82 );
83 $form['wikitools_main_page_title'] = array(
84 '#type' => 'textfield',
85 '#title' => t('Title of main page'),
86 '#default_value' => wikitools_main_page_title(),
87 '#description' => t('The main page is shown if you type in the wiki path. Leave empty to disable the main page.'),
88 );
89 $form['wikitools_node_types'] = array(
90 '#type' => 'select',
91 '#title' => t('Wiki node types'),
92 '#options' => node_get_types('names'),
93 '#size' => count(node_get_types('names')),
94 '#default_value' => wikitools_node_types(),
95 '#multiple' => TRUE,
96 '#description' => t('Select the node types which will be affected by the specified options. If you select multiple node types, all nodes of these types will be searched for when a wikipath is entered. If a wikipage doesn\'t exist, an option to create any of these types will be given.'),
97 );
98 $form['wikitools_options'] = array(
99 '#type' => 'checkboxes',
100 '#title' => t('Options'),
101 '#options' => array(
102 'node creation' => t('Node Creation: Let users create new nodes when they type in a node name which does not exist.'),
103 'node search' => t('Node Search: Let users search for nodes when they type in a node name which does not exist.'),
104 'auto redirect' => t('Automatic Redirect: If a title of a moved page is entered, redirect automatically.'),
105 'unique titles' => t('Unique Titles: Enforce that titles are unique over all wiki node types'),
106 'move protection' => t('Move Protection: Disallow change of node titles for users without <em>administer nodes</em> permission.'),
107 'delete protection' => t('Delete Protection: Disallow deletion of nodes for users without <em>administer nodes</em> permission.'),
108 'underscore as space' => t('Treat underscores as spaces when looking for node titles.'),
109 'dash as space' => t('Treat dashes as spaces when looking for node titles.'),
110 ),
111 '#default_value' => wikitools_options(),
112 '#description' => '<ul><li>'.
113 t('To take full advantage of the options <em>Node Creation</em>, <em>Node Search</em> and <em>Automatic Redirect</em> you should use an input format which creates wikilinks which point to the wiki path set. For exapmle a wikilink [[Page Name]] should be linked to <em>wikipath/Page Name</em>.') .'</li><li>'.
114 t('The options <em>Node Creation</em>, <em>Node Search</em> and <em>Automatic Redirect</em> work only if a wiki path is set or if freelinking hijacking is enabled. They take the page name from the path after the wiki path, i.e. <em>wikipath/Page Name</em>, or the page name of a freelinking link, i.e. <em>freelinking/Page Name</em>.') .'</li><li>'.
115 t('The option <em>Automatic Redirect</em> works only if node revisions are created.') .'</li></ul>',
116 );
117 $form['wikitools_404_type'] = array(
118 '#type' => 'select',
119 '#title' => t('Wiki 404 type'),
120 '#description' => t('Select the 404 (page not found) type for all pages under the wiki path.'),
121 '#multiple' => TRUE,
122 '#options' => array(
123 'Link to search' => t('Link to search'),
124 'Link to creation' => t('Link to creation'),
125 'Creation form' => t('Creation form'),
126 ),
127 '#default_value' => wikitools_404(),
128 );
129 $form['title_disallowed_characters'] = array(
130 '#type' => 'textfield',
131 '#title' => t('Disallowed characters in titles'),
132 '#description' => t('A list of characters which are not allowed in the title of a wiki page. This setting is important for the wikilink feature to work. Set it so that your input syntax will not be confused by titles. Make sure you don\'t enter a space character unless you really want to disallow spaces in titles. Leave empty to disable this feature.'),
133 '#default_value' => wikitools_disallowed_characters(),
134 );
135 $form['wikitools_hijack_freelinking'] = array(
136 '#type' => 'checkbox',
137 '#title' => t('Hijack freelinking filter'),
138 '#default_value' => wikitools_hijack_freelinking(),
139 '#description' => t('If you activate this option, the links of the freelinking filter will be processed by the wikitools module rather than the freelinking module. When active, a link to <em>freelinking/Page Name</em> behaves exactly as a link to <em>wikipath/Page Name</em>.'),
140 );
141 return system_settings_form($form);
142 }
143
144 /**
145 * Implementation of hook_requirements().
146 */
147 function wikitools_requirements($phase) {
148 // Don't check when installing
149 if ($phase == 'install') {
150 return;
151 }
152 if (wikitools_hijack_freelinking()) {
153 wikitools_autoadjust();
154 }
155 }
156
157 /**
158 * Adjust the module weights for wikitools to load after freelinking module.
159 */
160 function wikitools_autoadjust() {
161 $modules = array_keys(module_list());
162 if (array_search('wikitools', $modules) <= array_search('freelinking', $modules)) {
163 $freelinking_module_weight = db_result(db_query("SELECT weight FROM {system} WHERE name='freelinking'"));
164 db_query("UPDATE {system} SET weight=%d WHERE name='wikitools'", $freelinking_module_weight + 1);
165 drupal_set_message(t('Weight of %wikitools module set to %weight.', array('%wikitools' => t('wikitools'), '%weight' => $wikitools_module_weight + 1)));
166 }
167 }
168
169 /*
170 * Settings
171 */
172
173 /**
174 * Drupal path of wiki.
175 */
176 function wikitools_wiki_path($value = NULL) {
177 if (is_null($value)) {
178 return variable_get('wikitools_path', 'wiki');
179 }
180 variable_set('wikitools_path', $value);
181 }
182
183 /**
184 * Title of node on root path of wiki.
185 */
186 function wikitools_main_page_title($value = NULL) {
187 if (is_null($value)) {
188 return variable_get('wikitools_main_page_title', 'Main Page');
189 }
190 variable_set('wikitools_main_page_title', $value);
191 }
192
193 /**
194 * Node types of wiki pages.
195 */
196 function wikitools_node_types($value = NULL) {
197 if (is_null($value)) {
198 return variable_get('wikitools_node_types', array());
199 }
200 variable_set('wikitools_node_types', $value);
201 }
202
203 /**
204 * Is node type affected by wikitool options?
205 */
206 function wikitools_type_affected($type) {
207 static $node_types = NULL;
208 if (is_null($node_types)) {
209 $node_types = wikitools_node_types();
210 }
211 return isset($node_types[$type]) && $node_types[$type];
212 }
213
214 /**
215 * What 404 error settings are set?
216 */
217 function wikitools_404($value = NULL) {
218 if (is_null($value)) {
219 return variable_get('wikitools_404_type', array('Link to search', 'Creation form'));
220 }
221 variable_set('wikitools_404_type', $values);
222 }
223
224 /**
225 * String of characters which are not allowed in a wiki page title.
226 */
227 function wikitools_disallowed_characters($value = NULL) {
228 if (is_null($value)) {
229 return variable_get('wikitools_disallowed_characters', '[]{}|');
230 }
231 variable_set('wikitools_disallowed_characters', $value);
232 }
233
234 /**
235 * Various wikitool options.
236 */
237 function wikitools_options($value = NULL) {
238 if (is_null($value)) {
239 return variable_get('wikitools_options', array('node creation' => FALSE, 'node search' => FALSE, 'delete protection' => FALSE, 'move protection' => FALSE, 'unique titles' => FALSE, 'auto redirect' => FALSE, 'underscore as space' => FALSE, 'dash as space' => FALSE));
240 }
241 return variable_set('wikitools_options', $value);
242 }
243
244 /**
245 * Is node creation activated?
246 */
247 function wikitools_node_creation() {
248 $options = wikitools_options();
249 return $options['node creation'];
250 }
251
252 /**
253 * Is node search activated?
254 */
255 function wikitools_node_search() {
256 $options = wikitools_options();
257 return $options['node search'];
258 }
259
260 /**
261 * Is delete protection activated?
262 */
263 function wikitools_delete_protection() {
264 $options = wikitools_options();
265 return $options['delete protection'];
266 }
267
268 /**
269 * Is move protection activated?
270 */
271 function wikitools_move_protection() {
272 $options = wikitools_options();
273 return $options['move protection'];
274 }
275
276 /**
277 * Is automatic redirection activated?
278 */
279 function wikitools_auto_redirect() {
280 $options = wikitools_options();
281 return $options['auto redirect'];
282 }
283
284 /**
285 * Are unique titles enforced?
286 */
287 function wikitools_enforce_unique_titles() {
288 $options = wikitools_options();
289 return $options['unique titles'];
290 }
291
292 /**
293 * Are underscore characters treated as spaces?
294 */
295 function wikitools_treat_underscore_as_space() {
296 $options = wikitools_options();
297 return $options['underscore as space'];
298 }
299
300 /**
301 * Are dashes treated as spaces?
302 */
303 function wikitools_treat_dash_as_space() {
304 $options = wikitools_options();
305 return $options['dash as space'];
306 }
307
308 /**
309 * Is the freelinking path hijacked?
310 */
311 function wikitools_hijack_freelinking($value = NULL) {
312 if (is_null($value)) {
313 return variable_get('wikitools_hijack_freelinking', FALSE);
314 }
315 variable_set('wikitools_hijack_freelinking', $value);
316 }
317
318 /*
319 * Operations
320 */
321
322 /**
323 * Menu callback for wiki path.
324 * This function is called if a page without an alias is called below the wiki path.
325 */
326 function wikitools_handle_request() {
327 // Calculate index of first path argument after wiki path if specific position wasn't passed in.
328 if (arg(0) != 'freelinking') {
329 $i = count(explode('/', wikitools_wiki_path()));
330 }
331 else {
332 $i = 1;
333 }
334 if (arg($i)) {
335 // Save the path arguments after the wiki path as page name and put the slashes back.
336 $page_name = arg($i++);
337 while (arg($i)) {
338 $page_name .= '/'. arg($i);
339 $i++;
340 }
341 }
342 else {
343 // Use default page title if only wiki path is entered.
344 $page_name = wikitools_main_page_title();
345 }
346 // Decode page name and remove white space.
347 $page_name = trim(urldecode($page_name));
348 if (wikitools_treat_underscore_as_space()) {
349 $page_name = str_replace('_', ' ', $page_name);
350 }
351 if (wikitools_treat_dash_as_space()) {
352 $page_name = str_replace('-', ' ', $page_name);
353 }
354 $node_types = wikitools_node_types();
355 $output = '';
356 // Don't do anything if no node types are active or no page name is available
357 if (count($node_types) && $page_name) {
358 // Try to find the current page with this name.
359 $result = db_query("SELECT nid, type FROM {node} WHERE LOWER(title) = LOWER('%s')", $page_name);
360 $found_nodes = array();
361 while ($node = db_fetch_object($result)) {
362 if (wikitools_type_affected($node->type)) {
363 $found_nodes[] = $node;
364 }
365 }
366 if (count($found_nodes) == 1) {
367 // Single match for title.
368 $node = current($found_nodes);
369 drupal_goto("node/$node->nid");
370 }
371 else if (count($found_nodes) > 1) {
372 // Multiple match for title.
373 drupal_set_title('Page found: '. $page_name);
374 $output .= theme('wikitools_page_found', $page_name, $found_nodes);
375 }
376 else {
377 // No match for title. Try to find an old page with this name
378 $result = db_query("SELECT n.nid, n.type, n.title FROM {node} n LEFT JOIN {node_revisions} r ON n.nid = r.nid WHERE LOWER(r.title) = LOWER('%s') ORDER BY n.vid DESC", $page_name);
379 $moved_nodes = array();
380 while ($node = db_fetch_object($result)) {
381 if (wikitools_type_affected($node->type)) {
382 $moved_nodes[] = $node;
383 }
384 }
385 if (count($moved_nodes) > 0 && wikitools_auto_redirect() && !isset($_REQUEST['noredirect'])) {
386 $node = current($moved_nodes);
387 drupal_set_message(t('Redirected from <a href="@url">%page</a>', array('%page' => $page_name, '@url' => wikitools_wikilink_url($page_name, 'noredirect'))));
388 drupal_goto("node/$node->nid");
389 }
390 else if (count($moved_nodes) > 0) {
391 drupal_set_title('Page moved: '. $page_name);
392 $output = theme('wikitools_page_moved', $page_name, $moved_nodes);
393 }
394 else {
395 drupal_set_title('Page does not exist: '. $page_name);
396 $output = theme('wikitools_page_does_not_exist', $page_name);
397 }
398 }
399 }
400 return $output;
401 }
402
403 /**
404 * Implementation of hook_nodeapi().
405 */
406 function wikitools_nodeapi(&$node, $op, $form = NULL, $a4 = NULL) {
407 switch ($op) {
408 case 'validate':
409 wikitools_node_validate($node);
410 break;
411 }
412 }
413
414 /**
415 * Validate check of node edit form.
416 */
417 function wikitools_node_validate($node) {
418 if (wikitools_type_affected($node->type)) {
419 if (wikitools_enforce_unique_titles()) {
420 $nid = db_result(db_query("SELECT nid FROM {node} WHERE LOWER(title) = LOWER('%s')", $node->title));
421 if (!$nid && wikitools_treat_underscore_as_space()) {
422 $nid = db_result(db_query("SELECT nid FROM {node} WHERE LOWER(REPLACE(title, '_', ' ')) = LOWER(REPLACE('%s', '_', ' '))", $node->title));
423 }
424 if (!$nid && wikitools_treat_dash_as_space()) {
425 $nid = db_result(db_query("SELECT nid FROM {node} WHERE LOWER(REPLACE(title, '-', ' ')) = LOWER(REPLACE('%s', '-', ' '))", $node->title));
426 }
427 // It is only an error if the node which alredy exists is not the currently edited node.
428 if ($nid && $nid != $node->nid) {
429 form_set_error('title', t('A <a href="@page_url">page</a> with this name alredy exists.', array('@page_url' => url("node/$nid"))));
430 }
431 }
432 $disallowed_characters = wikitools_disallowed_characters();
433 if ($disallowed_characters) {
434 for ($i = 0; $i < strlen($node->title); $i++) {
435 if (strpos($disallowed_characters, $node->title[$i]) !== FALSE) {
436 form_set_error('title', t('The character %c is not allowed in a title', array('%c' => $node->title[$i])));
437 break;
438 }
439 }
440 }
441 }
442 }
443
444 /**
445 * Implementation of hook_form_alter().
446 */
447 function wikitools_form_alter(&$form, $form_state, $form_id) {
448 // Check if it is a node editing form of an affected type.
449 if (isset($form['type']) && $form['type']['#value'] .'_node_form' == $form_id) {
450 if (wikitools_type_affected($form['type']['#value'])) {
451 if ($form['nid']['#value']) {
452 // Node is edited.
453 if (wikitools_delete_protection() && !user_access('administer nodes')) {
454 unset($form['buttons']['delete']);
455 }
456 if (wikitools_move_protection() && !user_access('administer nodes')) {
457 $form['title']['#attributes'] = array('readonly' => 'readonly');
458 }
459 }
460 else {
461 // Node is new.
462 if (isset($_GET['edit'])) {
463 $form['title']['#default_value'] = urldecode($_GET['edit']['title']);
464 }
465 }
466 }
467 }
468 }
469
470 /**
471 * Callback of node delete action in protected mode.
472 */
473 function wikitools_delete_protection_delete_confirm(&$node) {
474 if (!wikitools_type_affected($node->type) || user_access('administer nodes')) {
475 // Call original function.
476 return drupal_get_form('node_delete_confirm', $node);
477 }
478 else {
479 return drupal_access_denied();
480 }
481 }
482
483 /**
484 * Build an url to create a new node.
485 * @param $type
486 * type of new node
487 * @param $title
488 * title of new node
489 */
490 function wikitools_create_url($type, $title) {
491 return url("node/add/$type", array('query' => 'edit[title]='. urlencode($title)));
492 }
493
494 /**
495 * Build an url to search for a title.
496 * @param $title
497 * title to search for
498 */
499 function wikitools_search_url($title) {
500 return url('search/node/'. urlencode($title));
501 }
502
503 /**
504 * Build an url to link to a page.
505 * @param $title
506 * title to link to
507 * @param $query
508 * an optional query string to append to the link
509 */
510 function wikitools_wikilink_url($title, $query = NULL) {
511 $drupal_path = wikitools_wikilink_drupal_path($title);
512 if ($drupal_path) {
513 return url($drupal_path, array('query' => $query));
514 }
515 }
516
517 /**
518 * Build a Drupal path to link to a page.
519 * @param $title
520 * title to link to
521 * @param $query
522 * an optional query string to append to the link
523 */
524 function wikitools_wikilink_drupal_path($title) {
525 if (wikitools_treat_underscore_as_space()) {
526 $title = str_replace(' ', '_', $title);
527 }
528 if (wikitools_treat_dash_as_space()) {
529 $title = str_replace(' ', '-', $title);
530 }
531 if ($wiki_path = wikitools_wiki_path()) {
532 return $wiki_path .'/'. urlencode($title);
533 }
534 elseif (wikitools_hijack_freelinking()) {
535 return 'freelinking/'. urlencode($title);
536 }
537 else {
538 // Neither wikitools nor freelinking will handle the link.
539 // Try to find a node with the given name and link directly to the first match.
540 $result = db_query("SELECT nid, type FROM {node} WHERE LOWER(title) = LOWER('%s')", $title);
541 $found_nodes = array();
542 while ($node = db_fetch_object($result)) {
543 if (wikitools_type_affected($node->type)) {
544 return "node/$node->nid";
545 }
546 }
547 }
548 }
549
550 /**
551 * Implementation of hook_theme().
552 */
553 function wikitools_theme() {
554 return array(
555 'wikitools_page_found' => array(
556 'arguments' => array('page_name' => NULL, 'found_nodes' => NULL),
557 ),
558 'wikitools_page_moved' => array(
559 'arguments' => array('page_name' => NULL, 'moved_nodes' => NULL),
560 ),
561 'wikitools_page_does_not_exist' => array(
562 'arguments' => array('page_name' => NULL),
563 ),
564 'wikitools_search_notice' => array(
565 'arguments' => array('page_name' => NULL),
566 ),
567 'wikitools_create_notice' => array(
568 'arguments' => array('page_name' => NULL),
569 ),
570 'wikitools_create' => array(
571 'arguments' => array('page_name' => NULL),
572 ),
573 );
574 }
575
576 /**
577 * @ingroup themeable
578 */
579
580 function theme_wikitools_page_found($page_name, $found_nodes) {
581 $output = '<p>'. t('Multiple pages have this name:') .'</p>';
582 foreach ($found_nodes as $info) {
583 $node = node_load($info->nid);
584 $output .= node_view($node, TRUE, FALSE, FALSE);
585 }
586 $output .= theme('wikitools_search_notice', $page_name);
587 if (!wikitools_enforce_unique_titles()) {
588 $output .= theme('wikitools_create_notice', $page_name);
589 }
590 return $output;
591 }
592
593 function theme_wikitools_page_moved($page_name, $moved_nodes) {
594 $output = '<p>'. t('The page %page_name has been moved.', array('%page_name' => $page_name)) .'</p>';
595 $node = current($moved_nodes);
596 $output .= '<p>'. t('The new page name is !new_name', array('!new_name' => l($node->title, "node/$node->nid"))) .'</p>';
597 // Todo: show all moved pages
598 $output .= theme('wikitools_search_notice', $page_name);
599 $output .= theme('wikitools_create_notice', $page_name);
600 return $output;
601 }
602
603 function theme_wikitools_page_does_not_exist($page_name) {
604 $output = '<p>'. t('The page %page_name does not exist.', array('%page_name' => $page_name)) .'</p>';
605 $settings = wikitools_404();
606 if (isset($settings['Link to search'])) {
607 $output .= theme('wikitools_search_notice', $page_name);
608 }
609 if (isset($settings['Link to creation'])) {
610 $output .= theme('wikitools_create_notice', $page_name);
611 }
612 if (isset($settings['Creation form'])) {
613 $output .= theme('wikitools_create', $page_name);
614 }
615 return $output;
616 }
617
618 function theme_wikitools_search_notice($page_name) {
619 $output = '';
620 if (module_exists('search') && user_access('search content') && wikitools_node_search()) {
621 $output .= '<p>'. t('You can <a href="@url">search for %page_name</a>', array('@url' => wikitools_search_url($page_name), '%page_name' => $page_name)) .'</p>';
622 }
623 return $output;
624 }
625
626 function theme_wikitools_create_notice($page_name) {
627 $output = '';
628 $node_types = wikitools_node_types();
629 if (wikitools_node_creation() && count($node_types)) {
630 $create = '';
631 $count = 0;
632 foreach ($node_types as $type) {
633 $type = node_get_types('type', $type);
634 if (node_access('create', $type->type)) {
635 $create .= '<dt><a href="'. wikitools_create_url($type->type, $page_name) .'">'. $type->name .'</a></dt>';
636 $create .= '<dd>'. filter_xss_admin($type->description) .'</dd>';
637 }
638 }
639 if ($create) {
640 $output .= '<p>'. t('You can create the page as:') .'</p>';
641 $output .= '<dl>'. $create .'</dl>';
642 }
643 }
644 return $output;
645 }
646
647 function theme_wikitools_create($page_name) {
648 $node_types = wikitools_node_types();
649 $form = array();
650 $output = '';
651 if (wikitools_node_creation() && count($node_types)) {
652 foreach ($node_types as $type) {
653 drupal_add_js('misc/collapse.js');
654 $type = node_get_types('type', $type);
655 if (node_access('create', $type->type)) {
656 $output .= '<p>'. t('You can create the page as:') .'</p>';
657 $output .= '<fieldset class="collapsible"><legend>'. $type->name .'</legend>';
658 if ($router_item = menu_get_item('node/add/'. $type->type)) {
659 if ($router_item['file']) {
660 require_once($router_item['file']);
661 }
662 $output .= call_user_func_array($router_item['page_callback'], $router_item['page_arguments']);
663 }
664 }
665 }
666 }
667 return $output;
668 }

  ViewVC Help
Powered by ViewVC 1.1.2