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

Contents of /contributions/modules/cck_redirection/cck_redirection.module

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


Revision 1.2 - (show annotations) (download) (as text)
Thu Jun 25 15:16:57 2009 UTC (5 months ago) by robinmonks
Branch: MAIN
CVS Tags: HEAD
Changes since 1.1: +620 -306 lines
File MIME type: text/x-php
Bring HEAD up to snuff.  -RM
1 <?php
2 // $Id: cck_redirection.module,v 1.1.4.2 2008/10/31 21:51:55 morrissinger Exp $
3
4 /**
5 * @file
6 * Provides a CCK field and widget for providing a URL to which to redirect the user.
7 */
8
9 /*********************************************************************
10 * Constants
11 */
12
13 define('CCK_REDIRECTION_DIVERT', 0x000);
14 define('CCK_REDIRECTION_DELAY', 0x001);
15 define('CCK_REDIRECTION_FRAMESET', 0x002);
16 define('CCK_REDIRECTION_NONE', 0x003);
17
18 /*********************************************************************
19 * Drupal Hooks
20 */
21
22 /**
23 * Implementation of hook_menu().
24 */
25 function cck_redirection_menu() {
26 // JS
27 $items['cck_redirection/js'] = array(
28 'page callback' => 'cck_redirection_js',
29 'access arguments' => array('access content'),
30 'type' => MENU_CALLBACK,
31 );
32
33 // Frameset Redirection
34 $items['redirect'] = array(
35 'page callback' => 'cck_redirection_frameset',
36 'access arguments' => array('access content'),
37 'type' => MENU_CALLBACK,
38 );
39
40 // Header page in frameset redirection
41 $items['cck_redirection/header'] = array(
42 'page callback' => 'cck_redirection_frameset_header',
43 'access arguments' => array('access content'),
44 'type' => MENU_CALLBACK,
45 );
46 return $items;
47 }
48
49 /**
50 * Implementation of hook_theme().
51 */
52 function cck_redirection_theme() {
53 return array(
54 'cck_redirection' => array(
55 'arguments' => array('element' => NULL),
56 ),
57 'cck_redirection_frameset' => array( // Show the new page in the bottom half of a frameset (think Google Images)
58 'template' => 'cck-redirection-frameset',
59 'arguments' => array('uri' => NULL, 'element' => NULL),
60 ),
61 'cck_redirection_frameset_header' => array( // Theme the header on a frameset
62 'template' => 'cck-redirection-frameset-header',
63 ),
64 'cck_redirection_delay_msg' => array( // Themes a JS Delay message (i.e. "This node will redirect to ___ in five seconds...")
65 'arguments' => array('element' => NULL)
66 ),
67 'cck_redirection_formatter_default' => array( // Suppress
68 'arguments' => array('element' => NULL),
69 ),
70 'cck_redirection_formatter_link' => array( // Show as link
71 'arguments' => array('element' => NULL),
72 ),
73 'cck_redirection_formatter_plain' => array( // Show as plain text
74 'arguments' => array('element' => NULL),
75 ),
76 );
77 }
78
79 /**
80 * Implementation of hook_perm().
81 */
82 function cck_redirection_perm() {
83 return array('bypass redirection');
84 }
85
86 /**
87 * Implementation of hook_nodeapi().
88 */
89 function cck_redirection_nodeapi(&$node, $op, $a3 = NULL, $a4 = NULL) {
90 if ($op == 'view') {
91 $GLOBALS['cck_redirection_teaser'] = $a3;
92 $GLOBALS['cck_redirection_page'] = $a4;
93 }
94 }
95
96 /**
97 * Implementation of hook_form_alter().
98 *
99 * This hook is used to add custom validation to the addition of new or
100 * existing fields to a node type. This is to make sure that a user
101 * does not add two or more cck_redirection fields to a given node type.
102 * While this does not present any inherent danger, this should be
103 * prevented because the cck_redirection field module will only look at
104 * one cck_redirection field anyway. After all, we will never have the
105 * opportunity to redirect the same user to two different sites
106 * at the same time in the same browser window.
107 */
108 function cck_redirection_form_alter(&$form, $form_state, $form_id) {
109 if ($form_id == 'content_admin_field_main') {
110 $form['#validate'][] = 'cck_redirection_content_admin_field_main_validate';
111 }
112
113 // We don't want the user to be able to have this field work with multiple values, so we will
114 // hide this option from the admin when he is configuring the field.
115 if ($form_id == '_content_admin_field' && $form['main']['type']['#value'] == 'cck_redirection') {
116 $form['field']['multiple']['#type'] = 'hidden';
117 $form['field']['multiple']['#value'] = $form['field']['multiple']['#default_value'];
118 }
119 }
120
121 /*********************************************************************
122 * FAPI Hooks
123 */
124
125 /**
126 * Implementation of FAPI hook_elements().
127 */
128 function cck_redirection_elements() {
129 return array(
130 'cck_redirection' => array(
131 '#input' => TRUE,
132 '#columns' => array('value'),
133 '#delta' => 0,
134 '#process' => array('cck_redirection_process'),
135 '#autocomplete_path' => FALSE,
136 ),
137 );
138
139 }
140
141 /*********************************************************************
142 * CCK Hooks: Fields
143 */
144
145 /**
146 * Implementation of hook_field_info().
147 */
148 function cck_redirection_field_info() {
149 return array(
150 'cck_redirection' => array(
151 'label' => 'Redirection',
152 'description' => t('Store a URI in the database (up to 255 characters).'),
153 ),
154 );
155 }
156
157 /**
158 * Implementation of hook_field_settings().
159 */
160 function cck_redirection_field_settings($op, $field) {
161 switch ($op) {
162 case 'form':
163 return array();
164 case 'validate':
165 break;
166 case 'save':
167 return array();
168 case 'database columns':
169 $columns = array(
170 'value' => array(
171 'type' => 'varchar',
172 'length' => 255,
173 'not null' => FALSE,
174 'sortable' => TRUE,
175 'default value' => NULL,
176 ),
177 );
178 return $columns;
179 case 'filters':
180 return array();
181 }
182 }
183
184 /**
185 * Implementation of hook_field().
186 */
187 function cck_redirection_field($op, &$node, $field, &$items, $teaser, $page) {
188 switch ($op) {
189 case 'validate':
190 // TODO: Do URI validation here.
191 break;
192 }
193 }
194
195 /*********************************************************************
196 * CCK Hooks: Field Formatters
197 */
198
199 /**
200 * Implementation of hook_field_formatter_info().
201 */
202 function cck_redirection_field_formatter_info() {
203 return array(
204 'default' => array(
205 'label' => t('Suppress'),
206 'field types' => array('cck_redirection'),
207 ),
208 'link' => array(
209 'label' => t('Show as Link'),
210 'field types' => array('cck_redirection'),
211 ),
212 'plain' => array(
213 'label' => t('Show as Plain Text'),
214 'field types' => array('cck_redirection'),
215 ),
216 );
217 }
218
219 /*********************************************************************
220 * CCK Hooks: Widgets
221 */
222
223 /**
224 * Implementation of hook_widget_info().
225 */
226 function cck_redirection_widget_info() {
227 return array(
228 'cck_redirection' => array(
229 'label' => 'Text field',
230 'field types' => array('cck_redirection'),
231 'multiple values' => CONTENT_HANDLE_CORE,
232 'callbacks' => array(
233 'default value' => CONTENT_CALLBACK_DEFAULT,
234 ),
235 ),
236 );
237 }
238
239 /**
240 * Implementation of hook_widget_settings().
241 */
242 function cck_redirection_widget_settings($op, $widget) {
243 switch ($op) {
244 case 'form':
245 $form = array();
246
247 $description = NULL;
248 $description .= t('Select the manner in which redirection should take place. Options are:') . '<ul>';
249 $description .= '<li>' . t('Divert: Show the target URI page, instead of the node.') . '</li>';
250 $description .= '<li>' . t('Delay: Show the node, and redirect after five seconds.') . ' <strong>' . t('Note: You should display this field in %d, to give the user some warning of redirection.', array('%d' => t('Display fields'))) . '</strong></li>';
251 $description .= '<li>' . t('Frameset: Show a frameset with some basic site information at the top, and the target URI page in the main frame.') . '</li>';
252 $description .= '<li>' . t('None: Do not redirect. This may be useful for theming or other development purposes.') . '</li</ul>';
253
254
255 $form['redirect_type'] = array(
256 '#type' => 'select',
257 '#title' => t('Redirection type'),
258 '#default_value' => is_numeric($widget['redirect_type']) ? $widget['redirect_type'] : CCK_REDIRECTION_DIVERT,
259 '#description' => $description,
260 '#options' => _cck_redirection_redirect_types(),
261 );
262
263 return $form;
264 case 'validate':
265 break;
266 case 'save':
267 return array('redirect_type');
268 }
269 }
270
271
272 /**
273 * Implementation of hook_widget().
274 */
275 function cck_redirection_widget(&$form, &$form_state, $field, $items, $delta = 0) {
276 $element = array(
277 '#type' => 'cck_redirection',
278 '#default_value' => isset($items[$delta]['value']) ? $items[$delta]['value'] : NULL,
279 );
280
281 return $element;
282 }
283
284 /*********************************************************************
285 * CCK Hooks: Misc.
286 */
287
288 /**
289 * Implementation of hook_content_is_empty().
290 */
291 function cck_redirection_content_is_empty($item, $field) {
292 if (empty($item['value'])) {
293 return TRUE;
294 }
295 return FALSE;
296 }
297
298 /*********************************************************************
299 * CCK Hooks: Installation, etc.
300 */
301
302 /**
303 * Implementation of hook_install().
304 */
305 function cck_redirection_install() {
306 content_notify('install', 'cck_redirection');
307 }
308
309 /**
310 * Implementation of hook_uninstall().
311 */
312 function cck_redirection_uninstall() {
313 content_notify('uninstall', 'cck_redirection');
314 }
315
316 /**
317 * Implementation of hook_enable().
318 */
319 function cck_redirection_enable() {
320 content_notify('enable', 'cck_redirection');
321 }
322
323 /**
324 * Implementation of hook_disable().
325 */
326 function cck_redirection_disable() {
327 content_notify('disable', 'cck_redirection');
328 }
329
330 /*********************************************************************
331 * Page Callbacks
332 */
333
334 /**
335 * CCK Redirection Javascript
336 *
337 * @param $uri
338 * A valid URI to redirect to,
339 */
340 function cck_redirection_js() {
341 $uri = $_SESSION['cck_redirection']['#item']['value'];
342 $field_name = $_SESSION['cck_redirection']['#field_name'];
343 $element = $_SESSION['cck_redirection'];
344
345 $id = str_replace("_", "-", "field-$field_name");
346
347 unset($_SESSION['cck_redirection']);
348
349 echo '
350 $(document).ready(function(){
351 $(".' . $id . ' .field-items .field-item").text("' . theme('cck_redirection_delay_msg', $element) . '");
352 setTimeout("cck_redirection_redirect()", 5000);
353 });
354
355 function cck_redirection_redirect() {
356 window.location=\'' . $uri . '\';
357 }
358 ';
359 }
360
361 /**
362 * CCK Redirection with Frameset
363 */
364 function cck_redirection_frameset() {
365 $uri = urldecode(check_plain($_GET['uri']));
366 $element = $_SESSION['cck_redirection'];
367 unset($_SESSION['cck_redirection']);
368
369 print theme('cck_redirection_frameset', $uri, $element);
370 exit();
371 }
372
373 /**
374 * Header for CCK Redirection with Frameset
375 */
376 function cck_redirection_frameset_header() {
377 print theme('cck_redirection_frameset_header');
378 exit();
379 }
380
381 /*********************************************************************
382 * Form Callbacks
383 */
384
385 /**
386 * Process an individual element.
387 *
388 * Build the form element. When creating a form using FAPI #process,
389 * note that $element['#value'] is already set.
390 *
391 * The $fields array is in $form['#field_info'][$element['#field_name']].
392 */
393 function cck_redirection_process($element, $edit, $form_state, $form) {
394 $field = $form['#field_info'][$element['#field_name']];
395 $field_key = $element['#columns'][0];
396 $delta = $element['#delta'];
397 $element[$field_key] = array(
398 '#type' => 'textfield',
399 '#title' => $element['#title'],
400 '#description' => $element['#description'],
401 '#required' => $element['#required'],
402 '#default_value' => isset($element['#value']) ? $element['#value'] : NULL,
403 '#autocomplete_path' => $element['#autocomplete_path'],
404 );
405
406 if (!empty($field['max_length'])) {
407 $element[$field_key]['#maxlength'] = $field['max_length'];
408 }
409 if (!empty($field['text_processing'])) {
410 $filter_key = $element['#columns'][1];
411 $format = isset($element['#value'][$filter_key]) ? $element['#value'][$filter_key] : FILTER_FORMAT_DEFAULT;
412 $parents = array_merge($element['#parents'] , array($filter_key));
413 $element[$filter_key] = filter_form($format, 1, $parents);
414 }
415
416 return $element;
417 }
418
419 /**
420 * Validates the addition of a new or existing field to a content type.
421 *
422 * Ensures that only one cck_redirection field exists per node type.
423 */
424 function cck_redirection_content_admin_field_main_validate($form, $form_state) {
425 $values = $form_state['values'];
426 $fields = _cck_redirection_get_redirect_fields($values['type_name']); // $values['type_name'] is the node type.
427
428 if(!empty($fields) && $values['type'] == 'cck_redirection') { //$values['type'] is the field type.
429 form_set_error('field_name', t('A Redirection field already exists for this node type. You may only redirect the browser to one site at a time.'));
430 }
431 }
432
433 /*********************************************************************
434 * Theme Functions
435 */
436
437 /**
438 * Theme a cck redirection widget.
439 */
440 function theme_cck_redirection($element) {
441 return $element['#children'];
442 }
443
444 /**
445 * Theme a message to display to the user when using the "delay" redirect method.
446 */
447 function theme_cck_redirection_delay_msg($element) {
448 return t('This page will redirect to !url in five seconds...', array('!url' => $element['#item']['value']));
449 }
450
451 /**
452 * Theme a frameset.
453 */
454 function template_preprocess_cck_redirection_frameset(&$vars) {
455 global $base_url;
456 $element = $vars['element'];
457 $vars['node'] = $element['#node'];
458 $vars['header_uri'] = $base_url . '/cck_redirection/header';
459 }
460
461 /**
462 * Theme a frameset header.
463 */
464 function template_preprocess_cck_redirection_frameset_header(&$vars) {
465 template_preprocess_page($vars);
466 }
467
468 /**
469 * Theme function for 'default' CCK_Redirection field formatter.
470 */
471 function theme_cck_redirection_formatter_default($element) {
472 $method = _cck_redirection_redirect($element);
473
474 return NULL;
475 }
476
477 /**
478 * Theme function for 'link' CCK_Redirection field formatter.
479 */
480 function theme_cck_redirection_formatter_link($element) {
481 $method = _cck_redirection_redirect($element);
482
483 $text = $element['#item']['value'];
484 return l(check_plain($text), $text);
485 }
486
487 /**
488 * Theme function for 'plain' CCK_Redirection field formatter.
489 */
490 function theme_cck_redirection_formatter_plain($element) {
491 $method = _cck_redirection_redirect($element);
492
493 $text = $element['#item']['value'];
494 return check_plain($text);
495 }
496
497 /*********************************************************************
498 * Helper Functions
499 */
500
501 /**
502 * Returns all redirect fields for a given node type.
503 *
504 * @param $type
505 * A node type.
506 * @ return
507 * An array of fields, as returned by _content_type_info, keyed
508 * by field name.
509 */
510 function _cck_redirection_get_redirect_fields($type) {
511 $info = _content_type_info();
512 $fields = array();
513 $fields = $info['content types'][$type]['fields'];
514
515 $cck_redirection_fields = array();
516
517 foreach((array)$fields as $key => $field) {
518 if ($field['type'] == 'cck_redirection') {
519 $cck_redirection_fields[$key] = $field;
520 }
521 }
522
523 return $cck_redirection_fields;
524 }
525
526 /**
527 * Returns whether or not $value is a valid URI.
528 *
529 * @param $value
530 * A value to check.
531 * @return
532 * TRUE if a valid URI. FALSE if not.
533 */
534 function _cck_redirection_validate_uri($value) {
535 $pattern = "/https?:\/\/[-\w.]+(:\d+)?(\/([\w\/_.]*)?)?/";
536 $works = preg_match($pattern, $value);
537 return $works;
538 }
539
540 /**
541 * Return an array of CCK Redirection types.
542 */
543 function _cck_redirection_redirect_types() {
544 return array(
545 CCK_REDIRECTION_DIVERT => t('Divert'),
546 CCK_REDIRECTION_DELAY => t('Delay'),
547 CCK_REDIRECTION_FRAMESET => t('Frameset'),
548 CCK_REDIRECTION_NONE => t('None'),
549 );
550 }
551
552 /**
553 * Accomplish redirection using the widget settings.
554 */
555 function _cck_redirection_redirect(&$element) {
556 $teaser = $GLOBALS['cck_redirection_teaser'];
557 $page = $GLOBALS['cck_redirection_page'];
558
559 $method = NULL;
560
561 if ($page) {
562 $node = $element['#node'];
563 $field = content_fields($element['#field_name'], $node->type);
564 $widget = $field['widget'];
565
566 $method = is_numeric($widget['redirect_type']) ? $widget['redirect_type'] : NULL;
567
568 if (user_access('bypass redirection')) {
569 if (!empty($element['#item']['value'])) {
570 drupal_set_message(t('This node is redirected to a !r.', array('!r' => l(t('remote URI'), $element['#item']['value']))));
571 }
572 } else {
573 switch ($widget['redirect_type']) {
574 case CCK_REDIRECTION_DIVERT:
575 _cck_redirection_divert($element);
576 break;
577 case CCK_REDIRECTION_DELAY:
578 _cck_redirection_delay($element);
579 break;
580 case CCK_REDIRECTION_FRAMESET:
581 _cck_redirection_frameset($element);
582 break;
583 default:
584 // This takes care of CCK_REDIRECTION_NONE by doing nothing
585 break;
586 }
587 }
588 }
589
590 return $method;
591 }
592
593 /**
594 * Diverts the browser to the target URI page.
595 */
596 function _cck_redirection_divert($element) {
597 if (!empty($element['#item']['value'])) {
598 drupal_goto($element['#item']['value']);
599 }
600 }
601
602 /**
603 * Uses JS to delay redirection by five seconds, and then diverts the browser to the target URI page.
604 */
605 function _cck_redirection_delay($element) {
606 if (!empty($element['#item']['value'])) {
607 $_SESSION['cck_redirection'] = $element;
608 drupal_add_js('cck_redirection/js');
609 }
610 }
611
612 /**
613 * Displays the target URI inside of a frameset.
614 */
615 function _cck_redirection_frameset($element) {
616 if (!empty($element['#item']['value'])) {
617 $_SESSION['cck_redirection'] = $element;
618 drupal_goto('redirect', 'uri=' . drupal_urlencode($element['#item']['value']));
619 }
620 }

  ViewVC Help
Powered by ViewVC 1.1.2