PHP4 compat fix
[project/better_formats.git] / better_formats.module
CommitLineData
fb6665a5 1<?php
2// $Id$
3
fb6665a5 4/**
b254b0b1 5 * @file
6 * Enhances Drupal's core input format settings.
7 *
b3a2894b 8 * Allows setting of defaults per role and content type,
9 * controls format display options, works with CCK fields.
b254b0b1 10 */
11
12/**
b3a2894b 13 * Implementation of hook_help().
fb6665a5 14 */
15function better_formats_help($path, $arg) {
fb6665a5 16 switch ($path) {
17 case 'admin/help/better_formats':
b254b0b1 18 $output = '<p>' . t('See the module README.txt file in the better_formats module directory for help.') . '</p>';
19 break;
312a75cb 20
21 case 'admin/settings/filters/defaults':
22 $output = '<p>' . t('Set the global default formats per role for NEW nodes and comments. These settings will be applied to all nodes and comments in the site unless overriden by specific content type defaults.') . '</p>';
23 $output .= '<p>' . t('Arrange the roles to provide weight that will determine what format is selected when a user has more than one role. Remember, that all logged in users are automatically given the authenticated user role in addition to their other assigned roles. For example, if you have an admin role place it at the top and generally you would want your anonymous user role at the bottom.') . '</p>';
24 break;
25
b254b0b1 26 default:
27 $output = '';
fb6665a5 28 }
29 return $output;
30}
31
b3a2894b 32/**
33 * Implementation of hook_perm().
34 */
57a7f758 35function better_formats_perm() {
36 return array(
37 'show format selection',
38 'show format tips',
84f95b35 39 'show more format tips link',
57a7f758 40 'collapse format fieldset by default',
41 'collapsible format selection',
42 );
43}
44
fb6665a5 45/**
b3a2894b 46 * Implementation of hook_menu().
fb6665a5 47 */
48function better_formats_menu() {
49 $items = array();
50
51 $items['admin/settings/filters/settings'] = array(
52 'title' => 'Settings',
53 'description' => 'Manage input formats',
54 'page callback' => 'drupal_get_form',
55 'page arguments' => array('better_formats_settings_admin_form'),
56 'access arguments' => array('administer filters'),
57 'type' => MENU_LOCAL_TASK,
58 'weight' => 3,
59 'file' => 'better_formats_settings.admin.inc',
d04e5103 60 );
fb6665a5 61 $items['admin/settings/filters/defaults'] = array(
62 'title' => 'Defaults',
63 'description' => 'Manage input formats',
64 'page callback' => 'drupal_get_form',
65 'page arguments' => array('better_formats_defaults_admin_form'),
66 'access arguments' => array('administer filters'),
67 'type' => MENU_LOCAL_TASK,
68 'weight' => 2,
69 'file' => 'better_formats_defaults.admin.inc',
d04e5103 70 );
fb6665a5 71
72 return $items;
73}
74
75/**
b3a2894b 76 * Implementation of hook_theme().
fb6665a5 77 */
78function better_formats_theme() {
79 return array(
80 'better_formats_defaults_admin_form' => array(
81 'template' => 'better-formats-defaults-admin-form',
82 'file' => 'better_formats_defaults.admin.inc',
83 'arguments' => array('form' => NULL),
84 ),
06a489fa 85 'better_formats_filter_tips_more_info' => array(
86 'arguments' => array(),
87 ),
fb6665a5 88 );
89}
90
91/**
b3a2894b 92 * Implementation of hook_form_alter().
93 */
fb6665a5 94function better_formats_form_alter(&$form, $form_state, $form_id) {
d04e5103 95 // Alter new node and comment forms.
96 // Using $form['#id'] instead of $form_id because $form_id is in the form of
97 // 'TYPE_node_form' which varies with the content type while $form['#id']
98 // is always 'node-form'.
fb6665a5 99 switch ($form['#id']) {
100 case 'comment-form':
9c419c1d 101 better_formats_set_comment_format($form);
fb6665a5 102 break;
103
104 case 'node-form':
9c419c1d 105 better_formats_set_node_format($form);
fb6665a5 106 break;
107 }
108
d04e5103 109 // Alter role add/delete and node type forms.
fb6665a5 110 switch ($form_id) {
111 case 'node_type_form':
112 if (variable_get('better_formats_per_node_type', FALSE)) {
2fff5669 113 better_formats_node_type_form($form, $form_state);
fb6665a5 114 }
115 break;
116
117 case 'user_admin_new_role':
d04e5103 118 if (!in_array('better_formats_new_role', $form['#submit'])) {
fb6665a5 119 $form['#submit'][] = 'better_formats_new_role';
120 }
121 break;
122
123 case 'user_admin_role':
124 if (isset($form_state['post']['op']) && $form_state['post']['op'] == 'Delete role') {
125 $form['#submit'][] = 'better_formats_delete_role';
126 }
127 break;
128 }
129}
130
b3a2894b 131/**
132 * FAPI form to add to the content type edit form.
133 *
2fff5669 134 * @see better_formats_node_type_form_validate()
135 * @see better_formats_node_type_form_submit()
b3a2894b 136 */
2fff5669 137function better_formats_node_type_form(&$form, $form_state) {
d04e5103 138 // Add JS to enhance form.
4b9acb64 139 drupal_add_js(drupal_get_path('module', 'better_formats') . '/better_formats_node_type_form.js');
140
fb6665a5 141 $node_type = $form['#node_type']->type;
142
d04e5103 143 // Build array of all formats for allowed checkboxes.
fb6665a5 144 $formats = filter_formats();
145 foreach ($formats as $format) {
146 $format_boxes[$format->format] = $format->name;
147 }
148
fb6665a5 149 $key = 'better_formats';
150 $form[$key] = array(
151 '#type' => 'fieldset',
152 '#title' => t('Input format settings'),
153 '#access' => user_access('administer filters'),
154 '#collapsible' => TRUE,
d04e5103 155 // Setting collapsed to false because the wieght will not be hidden otherwise
156 // the fieldset will be collapsed via JS if enabled.
4b9acb64 157 '#collapsed' => FALSE,
158 '#attributes' => array('class' => 'input-format-settings'),
fb6665a5 159 );
160 $allowed_key = $key . '_allowed';
161 $form[$key][$allowed_key] = array(
162 '#type' => 'checkboxes',
163 '#title' => t('Allowed formats'),
164 '#default_value' => variable_get($allowed_key . '_' . $node_type, array()),
165 '#options' => $format_boxes,
166 '#description' => t('Limit the formats users have to choose from even if they have permission to use that format. This will NOT allow a user to use a format they do not have access rights to use. It will only hide additional formats they do have access rights to. If no boxes are checked, all formats that the user has permission to use will be allowed.'),
4b9acb64 167 '#attributes' => array('class' => 'bf-allowed-formats'),
fb6665a5 168 );
169
170 $dform = array(
171 '#tree' => TRUE,
172 '#theme' => 'better_formats_defaults_admin_form',
173 );
24a34382 174
175 module_load_include('admin.inc', 'better_formats', 'better_formats_defaults');
fb6665a5 176 $nform = better_formats_get_role_default_fields('node', $node_type);
177 $cform = better_formats_get_role_default_fields('comment', $node_type);
178
179 $form[$key]['better_formats_defaults'] = array_merge($dform, $nform, $cform);
180
2835d06a 181 // Attach our validate and submit handlers.
2fff5669 182 $form['#validate'][] = 'better_formats_node_type_form_validate';
183 $form['#submit'][] = 'better_formats_node_type_form_submit';
fb6665a5 184}
185
b3a2894b 186/**
d04e5103 187 * Handles validation of the addition to the content type edit form.
b3a2894b 188 *
2fff5669 189 * @see better_formats_node_type_form()
190 * @see better_formats_node_type_form_submit()
b3a2894b 191 */
2fff5669 192function better_formats_node_type_form_validate($form, &$form_state) {
193 module_load_include('admin.inc', 'better_formats', 'better_formats_defaults');
2835d06a 194 better_formats_defaults_admin_form_validate($form, $form_state);
195}
196
b3a2894b 197/**
d04e5103 198 * Handles submission of the addition to the content type edit form.
b3a2894b 199 *
2fff5669 200 * @see better_formats_node_type_form()
201 * @see better_formats_node_type_form_validate()
b3a2894b 202 */
2fff5669 203function better_formats_node_type_form_submit($form, &$form_state) {
204 $node_type = trim($form_state['values']['type']);
fb6665a5 205
d04e5103 206 // Remove current db entries.
fb6665a5 207 $sql = "DELETE FROM {better_formats_defaults}
208 WHERE type='comment/%s' OR type='node/%s'";
209 db_query($sql, $node_type, $node_type);
210
d04e5103 211 // Insert defualt values into DB.
fb6665a5 212 $sql = "INSERT INTO {better_formats_defaults}
213 VALUES (%d, '%s', %d, %d, %d)";
214 foreach ($form_state['values']['better_formats_defaults'] as $key => $values) {
215 if (strpos($key, 'node-') === 0 || strpos($key, 'comment-') === 0) {
216 list($type, $rid) = explode('-', $key);
217 db_query($sql, $rid, $type . '/' . $node_type, $values['format'], 2, $values['weight']);
218 }
219 }
220
d04e5103 221 // Node module automatically stores all settings in variable table.
222 // BF saves format defaults to its own table so delete the unneeded variable.
2fff5669 223 variable_del('better_formats_defaults_' . $node_type);
fb6665a5 224}
225
fb6665a5 226/**
b3a2894b 227 * Creates base format default entry for a newly created role.
228 *
229 * @see better_formats_form_alter()
fb6665a5 230 */
231function better_formats_new_role($form, &$form_state) {
d04e5103 232 // Get the ID for the role just created.
fb6665a5 233 $sql = "SELECT rid
234 FROM {role}
235 ORDER BY rid DESC";
1256395a 236 $row = db_fetch_object(db_query_range($sql, 0, 1));
237 $rid = $row->rid;
fb6665a5 238
d04e5103 239 // Create stubs in per role table.
840425d5 240 $sql = "INSERT INTO {better_formats_defaults}
6900896e 241 VALUES (%d, '%s', %d, %d, %d)";
840425d5 242 db_query($sql, $rid, 'node', 0, 1, 25);
243 db_query($sql, $rid, 'comment', 0, 1, 25);
fb6665a5 244}
245
246/**
b3a2894b 247 * Deletes role format default entries for roles being deleted.
248 *
249 * @see better_formats_form_alter()
fb6665a5 250 */
251function better_formats_delete_role($form, &$form_state) {
d04e5103 252 // Delete role from format manager table.
fb6665a5 253 $sql = "DELETE FROM {better_formats_defaults}
254 WHERE rid = %d";
255 db_query($sql, $form['rid']['#value']);
256}
257
fb6665a5 258/**
6900896e 259 * Implementation of hook_node_type().
260 */
261function better_formats_node_type($op, $info) {
262 if ($op === 'delete') {
d04e5103 263 // Delete per node type settings on node type delete.
6900896e 264 $sql = "DELETE FROM {better_formats_defaults}
265 WHERE type IN ('node/%s', 'comment/%s')";
266 db_query($sql, $info->type, $info->type);
267
d04e5103 268 // Delete node type variables.
6900896e 269 variable_del('better_formats_allowed_' . $info->type);
270 }
271}
272
273/**
b3a2894b 274 * Implementation of hook_elements().
fb6665a5 275 *
d04e5103 276 * Adds a process function to CCK's textarea FAPI element.
fb6665a5 277 */
278function better_formats_elements() {
b254b0b1 279 return array(
fb6665a5 280 'text_textarea' => array(
281 '#process' => array('better_formats_textarea_process'),
282 ),
b254b0b1 283 );
fb6665a5 284}
285
286/**
b3a2894b 287 * Processes a CCK textarea element.
fb6665a5 288 *
289 * Resets the textareas filter area with bettter_formats default.
290 * This function is used to affect CCK textareas not core fields.
b3a2894b 291 *
292 * @see text_textarea_process()
fb6665a5 293 */
294function better_formats_textarea_process($element, $edit, $form_state, $form) {
b254b0b1 295 $field = $form['#field_info'][$element['#field_name']];
d04e5103 296
297 if (!empty($field['text_processing'])) {
298 // Get core default for new or selected format for existing.
fb6665a5 299 $filter_key = (count($element['#columns']) == 2) ? $element['#columns'][1] : 'format';
300 $format = isset($element['#value'][$filter_key]) ? $element['#value'][$filter_key] : FILTER_FORMAT_DEFAULT;
301 $parents = array_merge($element['#parents'] , array($filter_key));
d7acf486 302 $default = better_formats_get_default_format('node', $form['type']['#value']);
fb6665a5 303
d04e5103 304 // Overwrite format default if new node.
305 if (!isset($form_state['values']['nid'])) {
d7acf486 306 $format = $default;
9c419c1d 307 }
308
d04e5103 309 // Set default format for cck textarea.
9c419c1d 310 $element['#value'][$filter_key] = $format;
d04e5103 311 // Set filter selection form.
d7acf486 312 $element[$filter_key] = better_formats_filter_form($format, $default, $form['type']['#value'], 1, $parents);
fb6665a5 313 }
b254b0b1 314
315 return $element;
fb6665a5 316}
317
b3a2894b 318/**
319 * Processes formats for core node body fields.
320 *
321 * @see better_formats_form_alter()
322 */
fb6665a5 323function better_formats_set_node_format(&$form) {
d04e5103 324 // Set core body field.
fb6665a5 325 if (isset($form['body_field'])) {
d04e5103 326 // Get default for new entries.
d7acf486 327 $default = better_formats_get_default_format('node', $form['type']['#value']);
328
9c419c1d 329 if (empty($form['nid']['#value'])) {
d04e5103 330 // Set format to default for new entries.
d7acf486 331 $format = $default;
b254b0b1 332 }
333 else {
d04e5103 334 // Get existing format for core body field.
166e78b8 335 $format = better_formats_get_current_format($form['body_field']['format']);
9c419c1d 336 }
d7acf486 337
d04e5103 338 // Overwrite the filter form with our own.
d7acf486 339 $form['body_field']['format'] = better_formats_filter_form($format, $default, $form['type']['#value']);
fb6665a5 340 }
341}
342
b3a2894b 343/**
344 * Processes formats for core node comment form.
345 *
346 * @see better_formats_form_alter()
347 */
fb6665a5 348function better_formats_set_comment_format(&$form) {
fb6665a5 349 if (isset($form['comment_filter']['format'])) {
2aecb113 350 $node = node_load($form['nid']['#value']);
d7acf486 351
d04e5103 352 // Get BF default format.
d7acf486 353 $default = better_formats_get_default_format('comment', $node->type);
2aecb113 354
9c419c1d 355 if (empty($form['cid']['#value'])) {
d04e5103 356 // Set format to default for new entries.
d7acf486 357 $format = $default;
b254b0b1 358 }
359 else {
d04e5103 360 // Get existing format for comment.
166e78b8 361 $format = better_formats_get_current_format($form['comment_filter']['format']);
9c419c1d 362 }
d04e5103 363 // Overwrite the filter form with our own.
d7acf486 364 $form['comment_filter']['format'] = better_formats_filter_form($format, $default, $node->type);
fb6665a5 365 }
366}
367
b3a2894b 368/**
369 * Returns the format for an existing node or comment.
370 *
d04e5103 371 * @param $form
372 * FAPI form array.
373 * @return
374 * Format ID.
b3a2894b 375 *
376 * @see better_formats_set_node_format()
377 * @see better_formats_set_comment_format()
378 */
166e78b8 379function better_formats_get_current_format($form) {
d04e5103 380 // Default format to site default in case of error.
3fdd7f62 381 $format = FILTER_FORMAT_DEFAULT;
166e78b8 382 foreach (element_children($form) as $key) {
3fdd7f62 383 $element = $form[$key];
166e78b8 384 if ($element['#type'] === 'radio' && isset($element['#default_value'])) {
385 $format = $element['#default_value'];
386 break;
387 }
388 if ($element['#type'] === 'value' && isset($element['#value'])) {
389 $format = $element['#value'];
390 break;
391 }
392 }
393 return $format;
394}
395
b3a2894b 396/**
397 * Returns the default format for an new node or comment.
398 *
d04e5103 399 * @param $mode
b3a2894b 400 * 'node' or 'comment'. Describes the top level type of default.
d04e5103 401 * @return
402 * Format ID.
b3a2894b 403 *
404 * @see better_formats_set_node_format()
405 * @see better_formats_set_comment_format()
406 * @see better_formats_textarea_process()
407 */
fb6665a5 408function better_formats_get_default_format($mode, $node_type = '') {
409 static $format;
410
d04e5103 411 // Default our type to the mode (node or comment).
fb6665a5 412 $type = $mode;
413
d04e5103 414 // Check if per node type is enabled and set type accordingly.
b254b0b1 415 $per_node_type = variable_get('better_formats_per_node_type', FALSE);
fb6665a5 416 if ($per_node_type && $node_type) {
417 $type = $mode . '/' . $node_type;
418 }
419
d04e5103 420 // Only pull from the DB if we have not already checked for this specific type.
421 if (!isset($format[$type])) {
fb6665a5 422 global $user;
423
424 $types = $type;
425 $format = array();
426 $roles = implode(',', array_keys($user->roles));
427
d04e5103 428 // Prepare types for SQL.
fb6665a5 429 if ($per_node_type && $node_type) {
430 $types .= "','" . $mode;
431 }
432
d04e5103 433 // Get user's lowest weight role default.
fb6665a5 434 $sql = "SELECT format
435 FROM {better_formats_defaults}
436 WHERE rid IN (%s) AND type IN ('$types')
437 ORDER BY type_weight DESC, weight ASC";
d04e5103 438 $row = db_fetch_object(db_query_range($sql, $roles, 0, 1));
439 $format[$type] = filter_resolve_format($row->format);
fb6665a5 440 }
441
442 return $format[$type];
443}
444
445
446/**
447 * Better Formats version of filter_form().
fb6665a5 448 *
d04e5103 449 * Copied from filter.module with slight modification to handle options for
450 * hiding filter selection and/or tips.
451 * The $node_type param was added to the signature to enable condition by
452 * content type.
b3a2894b 453 *
454 * @see filter_form()
fb6665a5 455 */
d7acf486 456function better_formats_filter_form($value = FILTER_FORMAT_DEFAULT, $default_format, $node_type = '', $weight = 1, $parents = array('format')) {
4b02af90 457 $value = filter_resolve_format($value);
458 $formats = filter_formats();
459 $show_selection = user_access('show format selection');
460 $show_tips = user_access('show format tips');
84f95b35 461 $show_tips_link = user_access('show more format tips link');
4b02af90 462 $per_node_type = variable_get('better_formats_per_node_type', FALSE);
463 $allowed_formats = variable_get('better_formats_allowed_' . $node_type, FALSE);
464
d04e5103 465 // Check if there are node type restrictions on allowed formats.
466 // If there are no retrictions set, we use the site globals as default.
2aecb113 467 if ($per_node_type && $allowed_formats) {
fb6665a5 468 foreach ($formats as $key => $format) {
d04e5103 469 if (!in_array($format->format, $allowed_formats)) {
fb6665a5 470 unset($formats[$key]);
471 }
472 }
473 }
4b02af90 474
d04e5103 475 // Ensure that our default value is allowed or change default to one that is.
d7acf486 476 if (isset($formats[$value])) {
d04e5103 477 // Use existing or BF default value if available.
d7acf486 478 $default = $value;
479 }
480 else if (isset($formats[$default_format])) {
d04e5103 481 // Use currently set BF default as a fallback.
d7acf486 482 $default = $default_format;
d04e5103 483 } else if (!empty($formats)) {
484 // Current and default format are not allowed, so use first allowed format.
ee83d130 485 reset($formats);
486 $default = key($formats);
d7acf486 487 }
488 else {
d04e5103 489 // Use core site default as a fallback if all else fails.
d7acf486 490 $default = filter_resolve_format(FILTER_FORMAT_DEFAULT);
491 }
492
57a7f758 493 if (count($formats) > 1 && $show_selection) {
494 $collapsed = user_access('collapse format fieldset by default');
495 $collapsible = user_access('collapsible format selection');
25df2486 496 $fieldset_title = variable_get('better_formats_fieldset_title', '');
497
498 if (module_exists('i18n_strings') && $fieldset_title) {
499 $fieldset_title = tt($fieldset_title);
500 }
501 else {
502 $fieldset_title = $fieldset_title ? $fieldset_title : t('Input format');
4b02af90 503 }
504
fb6665a5 505 $form = array(
506 '#type' => 'fieldset',
25df2486 507 '#title' => $fieldset_title,
57a7f758 508 '#collapsible' => $collapsible,
509 '#collapsed' => $collapsed,
fb6665a5 510 '#weight' => $weight,
511 '#element_validate' => array('filter_form_validate'),
512 );
513
514 // Multiple formats available: display radio buttons with tips.
515 foreach ($formats as $format) {
516 // Generate the parents as the autogenerator does, so we will have a
517 // unique id for each radio button.
518 $parents_for_id = array_merge($parents, array($format->format));
519 $form[$format->format] = array(
520 '#type' => 'radio',
521 '#title' => $format->name,
522 '#default_value' => $default,
523 '#return_value' => $format->format,
524 '#parents' => $parents,
d04e5103 525 '#id' => form_clean_id('edit-' . implode('-', $parents_for_id)),
fb6665a5 526 );
ee83d130 527
57a7f758 528 if ($show_tips) {
9c419c1d 529 $form[$format->format]['#description'] = theme('filter_tips', _filter_tips($format->format, FALSE));
fb6665a5 530 }
59ed6416 531 else {
d04e5103 532 // Ensure expected filter_form() structure.
b3a2894b 533 // see http://drupal.org/node/344169
40acc2ca 534 $form[$format->format]['#description'] = '';
59ed6416 535 }
fb6665a5 536 }
7c4e513d 537
84f95b35 538 if ($show_tips_link) {
06a489fa 539 $extra = theme('better_formats_filter_tips_more_info');
7c4e513d 540 $form[] = array('#value' => $extra);
541 }
542 else {
d04e5103 543 // Ensure expected filter_form() structure.
7c4e513d 544 // see http://drupal.org/node/344169
545 $form[] = array('#value' => '');
546 }
b254b0b1 547 }
548 else {
9c419c1d 549 // Only one format available or hiding the form: use a hidden form item.
fb6665a5 550 $format = $formats[$default];
551 $form[$format->format] = array(
b254b0b1 552 '#type' => 'value',
553 '#value' => $format->format,
d04e5103 554 '#parents' => $parents,
fb6665a5 555 );
84f95b35 556
57a7f758 557 if ($show_tips) {
84f95b35 558 $tips = _filter_tips($format->format, FALSE);
b254b0b1 559 $form['format']['guidelines'] = array(
560 '#title' => t('Formatting guidelines'),
84f95b35 561 '#value' => theme('filter_tips', $tips, FALSE),
b254b0b1 562 );
b254b0b1 563 }
564 else {
d04e5103 565 // Ensure expected filter_form() structure.
b3a2894b 566 // see http://drupal.org/node/344169
166e78b8 567 $form['format']['guidelines'] = array(
568 '#title' => t('Formatting guidelines'),
569 '#value' => '',
570 );
84f95b35 571 }
572
d04e5103 573 // Only show long tips link if there are guidelines to the format.
84f95b35 574 if ($show_tips_link) {
575 $extra = theme('better_formats_filter_tips_more_info');
576 $form[] = array('#value' => $extra);
d04e5103 577 }
578 else {
579 // Ensure expected filter_form() structure.
84f95b35 580 // see http://drupal.org/node/344169
40acc2ca 581 $form[] = array('#value' => '');
166e78b8 582 }
fb6665a5 583 }
4b02af90 584
fb6665a5 585 return $form;
586}
587
d04e5103 588/**
589 * Theme function for fitler tips more info.
590 *
591 * This is copied from theme_fitler_tips_more_info() with small modifications.
592 *
593 * @return
594 * Filter tips more info HTML.
595 */
06a489fa 596function theme_better_formats_filter_tips_more_info() {
597 $text = variable_get('better_formats_long_tips_link_text', '');
25df2486 598 if (module_exists('i18n_strings') && $text) {
599 $text = tt($text);
600 }
601 else {
602 $text = $text ? $text : t('More information about formatting options');
603 }
06a489fa 604 return '<p>' . l($text, 'filter/tips') . '</p>';
605}