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

Contents of /contributions/modules/adlib/adlib.module

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


Revision 1.15 - (show annotations) (download) (as text)
Mon May 25 16:27:18 2009 UTC (6 months ago) by nedjo
Branch: MAIN
CVS Tags: HEAD
Changes since 1.14: +5 -2 lines
File MIME type: text/x-php
Test for update perm when offering links for editing ToC.
1 <?php
2 // $Id: adlib.module,v 1.14 2009/05/21 15:44:01 nedjo Exp $
3
4 /**
5 * @file
6 * Enables conversion of forms into adlib (in place editable fill in the blanks
7 * style) inputs.
8 */
9
10 /**
11 * Allow adlibs only for node forms.
12 */
13 define('ADLIB_FORMS_NODE_ONLY', 1);
14
15 /**
16 * Allow adlibs for all forms.
17 */
18 define('ADLIB_FORMS_ALL', 2);
19
20 /**
21 * Implementation of hook_menu().
22 */
23 function adlib_perm() {
24 return array('use adlibs');
25 }
26
27 /**
28 * Implementation of hook_block().
29 */
30 function adlib_block($op = 'list', $delta = 0) {
31 if ($op == 'list') {
32 $blocks[0]['info'] = t('Ad lib');
33 return $blocks;
34 }
35 elseif ($op == 'view') {
36 if (arg(0) == 'node' && is_numeric(arg(1)) && $node = node_load(arg(1))) {
37 if (_adlib_get_adlib_node($node->type . '_node_form')) {
38 $node = node_build_content($node, $teaser, $page);
39 $block['subject'] = t('Ad lib');
40 $block['content'] = $node->content['body']['#value'];
41 return $block;
42 }
43 }
44 }
45 }
46
47 /**
48 * Implementation of hook_menu().
49 */
50 function adlib_menu($may_cache) {
51 $items = array();
52
53 if ($may_cache) {
54 // Add a settings menu item.
55 $items[] = array(
56 'path' => 'admin/settings/adlib',
57 'title' => t('Adlib'),
58 'description' => t('Select which content type to use for making adlibs.'),
59 'access' => user_access('administer site configuration'),
60 'type' => MENU_NORMAL_ITEM,
61 'callback' => 'drupal_get_form',
62 'callback arguments' => array('adlib_admin_settings_form'),
63 );
64 $items[] = array(
65 'path' => 'adlib/check-plain',
66 'title' => t('Adlib check plain'),
67 'description' => t('Select which content type to use for making adlibs.'),
68 'access' => user_access('use adlibs'),
69 'type' => MENU_CALLBACK,
70 'callback' => 'adlib_check_plain',
71 );
72 }
73 return $items;
74 }
75
76 /**
77 * Menu callback for check_plain() call.
78 */
79 function adlib_check_plain() {
80 $val = isset($_REQUEST['val']) ? $_REQUEST['val'] : '';
81 drupal_set_header('Content-Type: text/javascript; charset=utf-8');
82 echo drupal_to_js(array('val' => check_plain($val)));
83 }
84
85 /**
86 * Menu callback for admin settings form.
87 */
88 function adlib_admin_settings_form() {
89 // Load an array of node types that include a body field.
90 $options = node_get_types('names');
91 $types = node_get_types();
92 foreach ($types as $type => $data) {
93 if (!$data->has_body) {
94 unset($options[$type]);
95 }
96 }
97 $form = array();
98 $form['adlib_type'] = array(
99 '#type' => 'select',
100 '#title' => t('Adlib content type'),
101 '#default_value' => variable_get('adlib_type', 0),
102 '#options' => array_map('check_plain', array_merge(array(0 => t('select one')), $options)),
103 '#description' => t('Select a content type to use for adlibs. The content type must have a body field.'),
104 '#required' => TRUE,
105 );
106 $form['adlib_forms'] = array(
107 '#type' => 'radios',
108 '#title' => t('Forms available for adlibs'),
109 '#default_value' => variable_get('adlib_forms', ADLIB_FORMS_NODE_ONLY),
110 '#options' => array(ADLIB_FORMS_NODE_ONLY => t('Node forms only'), ADLIB_FORMS_ALL => t('All forms')),
111 '#description' => t('Select whether adlibs should be available for all forms or only for node forms. Adlibs for non-node forms are experimental and may not work for some forms.'),
112 );
113 return system_settings_form($form);
114 }
115
116 /**
117 * Implementation of hook_form_alter().
118 *
119 * Add an adlib fieldset to all forms except the adlib node type form.
120 * Also apply adlibs.
121 */
122 function adlib_form_alter($form_id, &$form) {
123 $adlib_type = variable_get('adlib_type', 'adlib');
124 $is_node_form = isset($form['type']) && isset($form['#node']) && $form['type']['#value'] .'_node_form' == $form_id;
125
126 // Alter the form of adlib content type.
127 if ($is_node_form && $form['type']['#value'] == $adlib_type) {
128 $form['title']['#disabled'] = TRUE;
129 $form['#pre_render'][] = 'adlib_edit_process';
130 }
131 elseif ($is_node_form || variable_get('adlib_forms', ADLIB_FORMS_NODE_ONLY) == ADLIB_FORMS_ALL) {
132 // If this form already has an adlib, apply it.
133 $language = isset($form['#node']) && isset($form['#node']->language)? $form['#node']->language : NULL;
134 if (user_access('use adlibs') && $adlib_node = adlib_get_adlib_node($form_id, $language, $form['#node'])) {
135 $form['#adlib'] = check_markup($adlib_node->body, $adlib_node->format);
136 $form['#adlib'] = $adlib_node->body;
137 $form['#pre_render'][] = 'adlib_add_adlib';
138 }
139 // If there is an adlib node, test for update access.
140 // Otherwise test for access to create an adlib node.
141 $access = $adlib_node? node_access('update', $adlib_node) : node_access('create', $adlib_type);
142 if ($access) {
143 // Add a fieldset for creating or editing an adlib form.
144 $form['adlib'] = array(
145 '#type' => 'fieldset',
146 '#collapsible' => TRUE,
147 '#collapsed' => TRUE,
148 );
149 // If no adlib node type is set, give a link to the settings page.
150 if (!$adlib_type) {
151 $form['adlib']['#title'] = t('Adlib');
152 $form['adlib']['edit_adlib'] = array(
153 '#type' => 'item',
154 '#title' => t('Adlib not yet configured'),
155 '#value' => t('To make an adlib for this form, you must first select an adlib content type on the <a href="!edit">Adlib configuration</a> page.', array('!edit' => url('admin/settings/adlib', drupal_get_destination()))),
156 );
157 }
158 elseif ($adlib_node && $adlib_node->body) {
159 $form['adlib']['#title'] = t('Adlib: enabled');
160 $form['adlib']['#description'] = t('Adlibs are enabled for this form.');
161 $form['adlib']['edit_adlib'] = array(
162 '#type' => 'item',
163 '#title' => t('Enabled adlib'),
164 '#value' => t('<a href="!edit">Edit</a> or <a href="!delete">delete</a> the existing adlib.', array('!edit' => url('node/' . $adlib_node->nid . '/edit', drupal_get_destination()), '!delete' => url('node/' . $adlib_node->nid . '/delete', drupal_get_destination()))),
165 );
166 }
167 else {
168 $form['adlib']['#title'] = t('Adlib: not enabled');
169 $form['adlib']['add_adlib'] = array(
170 '#value' => l(t('Design an adlib version of this form.'), 'node/add/' . $adlib_type . '/' . $form_id, array(), drupal_get_destination()),
171 );
172 }
173 }
174 }
175 }
176
177 /**
178 * Get the adlib node for a given form. If translation is available,
179 * a translation in the requested language will be returned if present.
180 */
181 function adlib_get_adlib_node($form_id, $language, $content_node) {
182
183 if ($node = _adlib_get_adlib_node($form_id)) {
184 // Look for an adlib translation in a requested language.
185 if ($language && isset($node->translation) && isset($node->translation[$language])) {
186 $node = node_load($node->translation[$language]->nid);
187 }
188 // Allow other modules to alter the adlib.
189 // When updating to D6, use drupal_alter().
190 adlib_alter($node, $form_id, $language, $content_node);
191 return $node;
192 }
193 return FALSE;
194 }
195
196 /**
197 * Get the adlib node for a given form, without translation support.
198 */
199 function _adlib_get_adlib_node($form_id) {
200 $adlib_type = variable_get('adlib_type', 'adlib');
201 return node_load(array('type' => $adlib_type, 'title' => $form_id));
202 }
203
204 /**
205 * Backport of drupal_alter().
206 */
207 function adlib_alter(&$data) {
208 // Hang onto a reference to the data array so that it isn't blown away later.
209 // Also, merge in any parameters that need to be passed by reference.
210 $args = array(&$data);
211 if (isset($by_ref_parameters)) {
212 $args = array_merge($args, $by_ref_parameters);
213 }
214
215 // Now, use func_get_args() to pull in any additional parameters passed into
216 // the drupal_alter() call.
217 $additional_args = func_get_args();
218 array_shift($additional_args);
219 $args = array_merge($args, $additional_args);
220
221 foreach (module_implements('adlib_alter') as $module) {
222 $function = $module . '_adlib_alter';
223 call_user_func_array($function, $args);
224 }
225 }
226
227 /**
228 * Implementation of hook_nodeapi().
229 *
230 * For content types with adlibs, display the adlib.
231 *
232 * @todo: enable filtering by filter format.
233 */
234 function adlib_nodeapi(&$node, $op, $teaser, $page) {
235 switch ($op) {
236 // Prevent duplicate adlibs.
237 case 'validate':
238 $adlib_type = variable_get('adlib_type', 'adlib');
239 if ($node->type == $adlib_type) {
240 if ($existing_node = node_load(array('type' => $adlib_type, 'title' => $node->title))) {
241 if ($existing_node->nid != $node->nid) {
242 form_set_error('title', t('An adlib already exists for this form.'));
243 }
244 }
245 }
246 break;
247 case 'view':
248 $adlib_type = variable_get('adlib_type', FALSE);
249 if ($node->type == $adlib_type) {
250 if (substr($node->title, -10) == '_node_form') {
251 $type = node_get_types('type', substr($node->title, 0, -10));
252 $help = t('The template below will be used to present to users with an adlib interface for entering data in the <a href="!link">@type form</a>.', array('!link' => url('node/add/' . $type->type), '@type' => $type->name));
253 $title = $type->name;
254 }
255 else {
256 $help = t('The template below will be used to give users an adlib interface for entering data in the %form form.', array('%form' => $node->title));
257 $title = $node->title;
258 }
259 drupal_set_title(t('@title form adlib template', array('@title' => $title)));
260
261 $node->content['body']['#value'] = theme('adlib_help', $help) . $node->content['body']['#value'];
262 }
263 else {
264 $form_id = $node->type . '_node_form';
265 // If this node type already has an adlib, apply it.
266 if ($adlib_type && $adlib_node = adlib_get_adlib_node($form_id, $node->language ? $node->language : NULL, $node)) {
267 $adlib = $adlib_node->body;
268 if ($matches = _adlib_get_matches($adlib)) {
269 foreach ($matches as $match) {
270 $keys = explode(':', $match[1]);
271 $property = _adlib_get_property($node, $keys);
272 $adlib = str_replace($match[0], theme('adlib_property', $property ? $property : t('(Not yet entered)'), $keys[0]), $adlib);
273 }
274 $node->content['body']['#value'] = theme('adlib_display', $adlib);
275 }
276 }
277 }
278 break;
279 // Support for i18n translation module.
280 // When updating to D6, change this to 'prepare translation' op.
281 // In D5 this is somewhat fragile as it depends on our changes
282 // happening after the translation module (by module weight).
283 case 'prepare':
284 if (isset($node->translation_source) && !empty($_GET['language']) && $node->type == variable_get('adlib_type', 'adlib')) {
285 // We are translating a node from a source node.
286 $node->title = $node->translation_source->title . ' ' . $_GET['language'];
287 }
288 break;
289 }
290
291 }
292
293 /**
294 * Form pre_render callback for the adlib node type edit form.
295 *
296 * If a form is set in the URL, use it as the title and present its available
297 * fields. Otherwise, offer a list of availalbe content type forms.
298 */
299 function adlib_edit_process($form_id, &$form) {
300 global $user;
301
302 $adlib_type = variable_get('adlib_type', FALSE);
303
304 // If we're translating a node, fetch the original's form ID.
305 if (isset($form['#node']) && isset($form['#node']->translation_source)) {
306 $source_form_id = $form['#node']->translation_source->title;
307 }
308 // If we've already set a title, use that.
309 elseif (isset($form['title']['#default_value']) && !empty($form['title']['#default_value'])) {
310 $source_form_id = $form['title']['#default_value'];
311 }
312 // Look for a form requested at node/add/adlib/form_id.
313 elseif (arg(3)) {
314 $source_form_id = arg(3);
315 }
316 else {
317 $source_form_id = NULL;
318 }
319 if ($source_form_id) {
320 if (!isset($form['title']['#default_value']) || empty($form['title']['#default_value'])) {
321 $form['title']['#value'] = $source_form_id;
322 }
323 if (substr($source_form_id, -10) == '_node_form') {
324 $node = array('uid' => $user->uid, 'name' => $user->name, 'type' => substr($source_form_id, 0, -10));
325 $source_form = drupal_retrieve_form($source_form_id, $node);
326 }
327 else {
328 $source_form = drupal_retrieve_form($source_form_id);
329 }
330 drupal_prepare_form($source_form_id, $source_form);
331 $elements = _adlib_get_elements($source_form);
332 foreach ($elements as $key => $value) {
333 if ($key != $value) {
334 $elements[$key] = t('[adlib:!key] (!value)', array('!key' => $key, '!value' => $value));
335 }
336 else {
337 $elements[$key] = "[adlib:$value]";
338 }
339 }
340 $form['body_filter']['body']['#description'] = (isset($form['body_filter']['body']['#description']) ? $form['body_filter']['body']['#description'] . ' ': '') . t('Convert the !form_id form into an adlib by referencing text fields here. Example: <em>[adlib:title] is a story about [adlib:subject].</em> The following elements are available for use in adlibs: @elements', array('!form_id' => $source_form_id, '@elements' => implode(', ', $elements)));
341 }
342 // Otherwise, offer appropriate node form options.
343 else {
344 $options = node_get_types('names');
345 // Exclude the adlib type.
346 unset($options[$adlib_type]);
347 // Exclude any types that already have adlibs.
348 $form_ids = array();
349 foreach (array_keys($options) as $type) {
350 $form_ids[]= "'" . $type . "_node_form'";
351 }
352 $result = db_query(db_rewrite_sql("SELECT n.nid, n.title FROM {node} n WHERE n.title IN (" . implode(', ', $form_ids) . ")"));
353 $existing_types = array();
354 while ($node = db_fetch_object($result)) {
355 $existing_types[substr($node->title, 0, -10)] = $node->nid;
356 }
357 foreach ($options as $type => $name) {
358 if (array_key_exists($type, $existing_types)) {
359 $options[$type] = l($name, 'node/'. $existing_types[$type] . '/edit');
360 }
361 else {
362 $options[$type] = l($name, 'node/add/'. $adlib_type . '/' . $type . '_node_form');
363 }
364 }
365
366 $form['#prefix'] = (isset($form['#prefix']) ? $form['#prefix'] .= ' ' : '') . t('Select a content type to construct an adlib form for: !links', array('!links' => implode(', ', $options)));
367 }
368 }
369
370 /**
371 * Form pre_render callback for forms with adlibs.
372 *
373 * Add an adlib to the form.
374 */
375 function adlib_add_adlib($form_id, &$form) {
376 if (isset($form['#adlib']) && $matches = _adlib_get_matches($form['#adlib'])) {
377 foreach ($matches as $match) {
378 if ($element = _adlib_get_element($form, explode(':', $match[1]))) {
379 $form['#adlib'] = str_replace($match[0], theme('adlib_element', $element), $form['#adlib']);
380 }
381 }
382 if (isset($form['#node'])) {
383 $type = node_get_types('type', $form['#node']->type);
384 $type = $type->name;
385 }
386 else {
387 $type = str_replace('_', ' ', $form_id);
388 }
389 $help = t('Below is a template for your %type. Click each bold area to enter the requested text.', array('%type' => $type));
390 $form['adlib_input'] = array(
391 '#value' => theme('adlib_form', $form['#adlib'], $help),
392 '#weight' => -3,
393 );
394 }
395 }
396
397 function _adlib_get_matches($adlib_raw) {
398 preg_match_all('/\[adlib:(.+)?\]/isU', $adlib_raw, $matches, PREG_SET_ORDER);
399 return $matches;
400 }
401
402 /**
403 * Theme an adlib help section.
404 */
405 function theme_adlib_help($help) {
406 return '<p class="adlib-help">' . $help . '</p>';
407 }
408
409 /**
410 * Theme an adlib element.
411 */
412 function theme_adlib_element($element) {
413 // Pass the title through t(). This is a misuse of t() and should be corrected, but
414 // doing so will have to wait for D6 and i18nstrings.
415 $value = !empty($element['#default_value']) ? $element['#default_value'] : t('(Click to insert @title)', array('@title' => isset($element['#title']) && !empty($element['#title']) ? t($element['#title']) : $element['#name']));
416 return '<span id="adlib-' . $element['#id'] . '" class="adlib-element"><span class="adlib-message">' . $value . '</span></span>';
417 }
418
419 /**
420 * Theme an adlib form.
421 */
422 function theme_adlib_form($adlib, $help) {
423 // Add javascript files.
424 ajaxsubmit_load();
425 $path = drupal_get_path('module', 'adlib');
426 drupal_add_js($path . '/adlib.js');
427 // Send strings.
428 // When updating to D6, use Drupal.t in the js file instead.
429 $settings = array('adlib' => array(
430 'submit' => t('OK'),
431 'cancel' => t('Cancel'),
432 'preview' => t('Preview'),
433 'checkPlainPath' => url('adlib/check-plain'),
434 'error' => t('An error occurred.'),
435 ));
436 drupal_add_js($settings, 'setting');
437 drupal_add_css($path . '/adlib.css');
438 return '<div class="adlib-form"><p class="adlib-help">' . $help . '</p>' . '<p class="adlib-body">' . $adlib . '</p></div>';
439 }
440
441 /**
442 * Theme an adlib property.
443 */
444 function theme_adlib_property($property, $key) {
445 return '<span class="adlib-property adlib-property-' . $key . '">' . $property . '</span>';
446 }
447
448 /**
449 * Theme an adlib display.
450 */
451 function theme_adlib_display($adlib) {
452 // Add javascript files.
453 $path = drupal_get_path('module', 'adlib');
454 drupal_add_css($path . '/adlib.css');
455 return '<div class="adlib-display">' . $adlib . '</div>';
456 }
457
458 /**
459 * Return an array of form elements suitable for adlib handling.
460 */
461 function _adlib_get_elements($form, $parents = array()) {
462 $elements = array();
463 foreach (element_children($form) as $key) {
464 $id = implode(':', array_merge($parents, array($key)));
465 // Only accept elements with a type set.
466 if (isset($form[$key]['#type']) && !in_array($form[$key]['#type'], array('value', 'hidden'))) {
467 // TODO: fix this misuse of t().
468 $elements[$id] = isset($form[$key]['#title']) ? t($form[$key]['#title']) : $id;
469 }
470 $elements = array_merge($elements, _adlib_get_elements($form[$key], array_merge($parents, array($key))));
471 }
472 return $elements;
473 }
474
475 /**
476 * Alter a form element.
477 *
478 * Not used.
479 * @todo: delete this function.
480 */
481 function _adlib_alter_element(&$element) {
482 if (!isset($element['#attributes'])) {
483 $element['#attributes'] = array();
484 }
485 }
486
487 /**
488 * Return specified element from a form.
489 */
490 function _adlib_get_element($form, $keys) {
491 $return = $form;
492 $title = NULL;
493 foreach ($keys as $key) {
494 if (isset($return[$key])) {
495 if (isset($return[$key]['#title'])) {
496 $title = $return[$key]['#title'];
497 }
498 $return = $return[$key];
499 }
500 else {
501 break;
502 }
503 }
504 if ($return == $form) {
505 return FALSE;
506 }
507 // If no title is set, accept one from the most immediate parent
508 // having a title. This is handy for CCK fields.
509 if (!empty($title) && !isset($return['#title'])) {
510 $return['#title'] = $title;
511 }
512 return $return;
513 }
514
515 /**
516 * Return specified property from a node.
517 */
518 function _adlib_get_property(&$node, $keys) {
519 $first_key = $keys[0];
520 $return = (array) $node;
521 // Special handling for node body.
522 $body = FALSE;
523 if ($first_key == 'body_filter') {
524 array_shift($keys);
525 $first_key = $keys[0];
526 $body = TRUE;
527 }
528 foreach ($keys as $key) {
529 if (isset($return[$key])) {
530 // Use CCK view values where available.
531 if ($key == 'value' && isset($return['view'])) {
532 $key = 'view';
533 }
534 elseif ($body && $return[$key] == 'body') {
535 $return[$key] = check_markup($node->body, $node->format);
536 }
537 // If we don't have CCK filtered content, filter now.
538 elseif (is_string($return[$key])) {
539 $return[$key] = check_plain($return[$key]);
540 }
541 $return = $return[$key];
542 }
543 else {
544 break;
545 }
546 }
547
548 // If we still have the original node, bail.
549 if ((object) $return == $node) {
550 return FALSE;
551 }
552
553 // If we've got an array, this isn't a usable result.
554 if (is_array($return)) {
555 $return = '';
556 }
557 // Empty the display for this field, since we're displaying
558 // it in the adlib.
559 if (isset($node->content[$first_key]) && isset($node->content[$first_key]['#value'])) {
560 $node->content[$first_key]['#value'] = '';
561 }
562 return $return;
563 }

  ViewVC Help
Powered by ViewVC 1.1.2