26417538cc2498b3f1c21eac478cb89ab7145086
6 * Enhances Drupal's core input format settings.
8 * Allows setting of defaults per role and content type,
9 * controls format display options, works with CCK fields.
13 * Implementation of hook_help().
15 function better_formats_help($path, $arg) {
17 case
'admin/help/better_formats':
18 $output = '<p>' .
t('See the module README.txt file in the better_formats module directory for help.') .
'</p>';
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>';
33 * Implementation of hook_perm().
35 function better_formats_perm() {
37 'show format selection',
39 'show more format tips link',
40 'collapse format fieldset by default',
41 'collapsible format selection',
46 * Implementation of hook_menu().
48 function better_formats_menu() {
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
,
59 'file' => 'better_formats_settings.admin.inc',
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
,
69 'file' => 'better_formats_defaults.admin.inc',
76 * Implementation of hook_theme().
78 function better_formats_theme() {
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
),
85 'better_formats_filter_tips_more_info' => array(
86 'arguments' => array(),
92 * Implementation of hook_form_alter().
94 function better_formats_form_alter(&$form, $form_state, $form_id) {
95 // alter new node and comment forms
96 // using $form['#id'] instead of $form_id because $form_id is in the form of
97 // 'contentType_node_form' which varies with the content type
98 // while $form['#id'] is always 'node-form'
99 switch ($form['#id']) {
101 better_formats_set_comment_format($form);
105 better_formats_set_node_format($form);
109 // alter role add or delete, and node type
111 case
'node_type_form':
112 if (variable_get('better_formats_per_node_type', FALSE
)) {
113 better_formats_node_type_form($form, $form_state);
117 case
'user_admin_new_role':
118 if ( ! in_array('better_formats_new_role', $form['#submit'])) {
119 $form['#submit'][] = 'better_formats_new_role';
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';
132 * FAPI form to add to the content type edit form.
134 * @see better_formats_node_type_form_validate()
135 * @see better_formats_node_type_form_submit()
137 function better_formats_node_type_form(&$form, $form_state) {
138 // add js to enhance form and fix a bug
139 drupal_add_js(drupal_get_path('module', 'better_formats') .
'/better_formats_node_type_form.js');
141 $node_type = $form['#node_type']->type
;
143 // build array of all formats for allowed checkboxes
144 $formats = filter_formats();
145 foreach ($formats as
$format) {
146 $format_boxes[$format->format
] = $format->name
;
149 $key = 'better_formats';
151 '#type' => 'fieldset',
152 '#title' => t('Input format settings'),
153 '#access' => user_access('administer filters'),
154 '#collapsible' => TRUE
,
155 // setting collapsed to false because the wieght will not be hidden otherwise
156 // the fieldset will be collapsed via JS if enabled
157 '#collapsed' => FALSE
,
158 '#attributes' => array('class' => 'input-format-settings'),
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.'),
167 '#attributes' => array('class' => 'bf-allowed-formats'),
172 '#theme' => 'better_formats_defaults_admin_form',
174 $nform = better_formats_get_role_default_fields('node', $node_type);
175 $cform = better_formats_get_role_default_fields('comment', $node_type);
177 $form[$key]['better_formats_defaults'] = array_merge($dform, $nform, $cform);
179 // Attach our validate and submit handlers.
180 // Prepending to the submit array because core will auto save the values in the
181 // variable table if the values are not removed before hand.
182 $form['#validate'][] = 'better_formats_node_type_form_validate';
183 $form['#submit'][] = 'better_formats_node_type_form_submit';
187 * Handles validatation of the addition to the content type edit form.
189 * @see better_formats_node_type_form()
190 * @see better_formats_node_type_form_submit()
192 function better_formats_node_type_form_validate($form, &$form_state) {
193 module_load_include('admin.inc', 'better_formats', 'better_formats_defaults');
194 better_formats_defaults_admin_form_validate($form, $form_state);
198 * Handles submition of the addition to the content type edit form.
200 * @see better_formats_node_type_form()
201 * @see better_formats_node_type_form_validate()
203 function better_formats_node_type_form_submit($form, &$form_state) {
204 $node_type = trim($form_state['values']['type']);
206 // remove current db entries
207 $sql = "DELETE FROM {better_formats_defaults}
208 WHERE type='comment/%s' OR type='node/%s'";
209 db_query($sql, $node_type, $node_type);
211 // insert defualt values into DB
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']);
221 // node module automatically stores all settings in variable table
222 // BF uses default settings from its own table
223 // so delete the unneeded variable
224 variable_del('better_formats_defaults_' .
$node_type);
228 * Creates base format default entry for a newly created role.
230 * @see better_formats_form_alter()
232 function better_formats_new_role($form, &$form_state) {
233 // get the rid for the role just created
237 $rid = db_fetch_object(db_query_range($sql, 0, 1))->rid
;
239 // create stubs in per role table
240 $sql = "INSERT INTO {better_formats_defaults}
241 VALUES (%d, '%s', %d, %d, %d)";
242 db_query($sql, $rid, 'node', 0, 1, 25);
243 db_query($sql, $rid, 'comment', 0, 1, 25);
247 * Deletes role format default entries for roles being deleted.
249 * @see better_formats_form_alter()
251 function better_formats_delete_role($form, &$form_state) {
252 // delete role from format manager table
253 $sql = "DELETE FROM {better_formats_defaults}
255 db_query($sql, $form['rid']['#value']);
259 * Implementation of hook_node_type().
261 function better_formats_node_type($op, $info) {
262 if ($op === 'delete') {
263 // delete per node type settings on node type delete
264 $sql = "DELETE FROM {better_formats_defaults}
265 WHERE type IN ('node/%s', 'comment/%s')";
266 db_query($sql, $info->type
, $info->type
);
268 // delete node type variables
269 variable_del('better_formats_allowed_' .
$info->type
);
274 * Implementation of hook_elements().
276 * Adds a process function to CCK's textarea FAPI element
278 function better_formats_elements() {
280 'text_textarea' => array(
281 '#process' => array('better_formats_textarea_process'),
287 * Processes a CCK textarea element.
289 * Resets the textareas filter area with bettter_formats default.
290 * This function is used to affect CCK textareas not core fields.
292 * @see text_textarea_process()
294 function better_formats_textarea_process($element, $edit, $form_state, $form) {
295 $debug = variable_get('better_formats_debug', FALSE
);
296 $field = $form['#field_info'][$element['#field_name']];
299 drupal_set_message('CCK textarea field: <br /><pre>' .
print_r($field, TRUE
) .
'</pre>');
302 if ( ! empty($field['text_processing'])) {
303 // get core default for new or selected format for existing
304 $filter_key = (count($element['#columns']) == 2) ?
$element['#columns'][1] : 'format';
305 $format = isset($element['#value'][$filter_key]) ?
$element['#value'][$filter_key] : FILTER_FORMAT_DEFAULT
;
306 $parents = array_merge($element['#parents'] , array($filter_key));
307 $default = better_formats_get_default_format('node', $form['type']['#value']);
309 // overwrite format default if new node
310 if ( ! isset($form_state['values']['nid'])) {
314 // set default format for cck textarea
315 $element['#value'][$filter_key] = $format;
316 // set filter selection form
317 $element[$filter_key] = better_formats_filter_form($format, $default, $form['type']['#value'], 1, $parents);
324 * Processes formats for core node body fields.
326 * @see better_formats_form_alter()
328 function better_formats_set_node_format(&$form) {
329 // set core body field
330 if (isset($form['body_field'])) {
331 // get default for new entries
332 $default = better_formats_get_default_format('node', $form['type']['#value']);
334 if (empty($form['nid']['#value'])) {
335 // set format to default for new entries
339 // get existing format for core body field
340 $format = better_formats_get_current_format($form['body_field']['format']);
343 // overwrite the filter form with our own
344 $form['body_field']['format'] = better_formats_filter_form($format, $default, $form['type']['#value']);
349 * Processes formats for core node comment form.
351 * @see better_formats_form_alter()
353 function better_formats_set_comment_format(&$form) {
354 if (isset($form['comment_filter']['format'])) {
355 $node = node_load($form['nid']['#value']);
357 // get bf default format
358 $default = better_formats_get_default_format('comment', $node->type
);
360 if (empty($form['cid']['#value'])) {
361 // set format to default for new entries
365 // get existing format for comment
366 $format = better_formats_get_current_format($form['comment_filter']['format']);
368 // overwrite the filter form with our own
369 $form['comment_filter']['format'] = better_formats_filter_form($format, $default, $node->type
);
374 * Returns the format for an existing node or comment.
381 * @see better_formats_set_node_format()
382 * @see better_formats_set_comment_format()
384 function better_formats_get_current_format($form) {
385 // default format to site default in case of error
386 $format = FILTER_FORMAT_DEFAULT
;
387 foreach (element_children($form) as
$key) {
388 $element = $form[$key];
389 if ($element['#type'] === 'radio' && isset($element['#default_value'])) {
390 $format = $element['#default_value'];
393 if ($element['#type'] === 'value' && isset($element['#value'])) {
394 $format = $element['#value'];
402 * Returns the default format for an new node or comment.
404 * @param string $mode
405 * 'node' or 'comment'. Describes the top level type of default.
409 * @see better_formats_set_node_format()
410 * @see better_formats_set_comment_format()
411 * @see better_formats_textarea_process()
413 function better_formats_get_default_format($mode, $node_type = '') {
416 // default our type to the mode (node or comment)
419 // check if per node type is enabled and set type accordingly
420 $per_node_type = variable_get('better_formats_per_node_type', FALSE
);
421 if ($per_node_type && $node_type) {
422 $type = $mode .
'/' .
$node_type;
425 // only pull from the DB if we have not already checked for this specific type
426 if ( ! isset($format[$type])) {
432 $roles = implode(',', array_keys($user->roles
));
434 if ($per_node_type && $node_type) {
435 $types .
= "','" .
$mode;
438 // get users lowest weight role default
439 $sql = "SELECT format
440 FROM {better_formats_defaults}
441 WHERE rid IN (%s) AND type IN ('$types')
442 ORDER BY type_weight DESC, weight ASC";
443 $value = db_fetch_object(db_query_range($sql, $roles, 0, 1))->format
;
444 $format[$type] = filter_resolve_format($value);
447 return $format[$type];
452 * Better Formats version of filter_form().
454 * Copied from filter.module with slight modification to
455 * handle options for hiding filter selection and/or tips.
456 * The $node_type param was added to the signature to
457 * enable condition by content type.
461 function better_formats_filter_form($value = FILTER_FORMAT_DEFAULT
, $default_format, $node_type = '', $weight = 1, $parents = array('format')) {
463 $debug = variable_get('better_formats_debug', FALSE
);
464 $value = filter_resolve_format($value);
465 $formats = filter_formats();
466 $show_selection = user_access('show format selection');
467 $show_tips = user_access('show format tips');
468 $show_tips_link = user_access('show more format tips link');
469 $per_node_type = variable_get('better_formats_per_node_type', FALSE
);
470 $allowed_formats = variable_get('better_formats_allowed_' .
$node_type, FALSE
);
472 if ($debug && ! $debug1) {
473 drupal_set_message('Default format value: ' .
$value);
474 drupal_set_message('Node type: ' .
$node_type);
475 drupal_set_message('Show format selection: ' .
$show_selection);
476 drupal_set_message('Show format tips: ' .
$show_tips);
477 drupal_set_message('Show more format tips link: ' .
$show_tips_link);
478 drupal_set_message('Control per node type: ' .
$per_node_type);
479 drupal_set_message('Node type allowed formats: <br /><pre>' .
print_r($allowed_formats, TRUE
) .
'</pre>');
480 drupal_set_message('Core allowed formats: <br /><pre>' .
print_r($formats, TRUE
) .
'</pre>');
483 // check if there are node type restrictions on allowed formats
484 // if there are no retrictions set we use the site globals as default
485 if ($per_node_type && $allowed_formats) {
486 foreach ($formats as
$key => $format) {
487 if ( ! in_array($format->format
, $allowed_formats)) {
488 unset($formats[$key]);
493 if ($debug && ! $debug1) {
494 drupal_set_message('BF allowed formats: <br /><pre>' .
print_r($formats, TRUE
) .
'</pre>');
497 // extra check to ensure default format is available to the user
498 // else we fall back to the site default format
499 $default = isset($formats[$value]) ?
$formats[$value]->format
: filter_resolve_format(FILTER_FORMAT_DEFAULT
);
501 if (isset($formats[$value])) {
502 // use existing or bf default value if available
505 else if (isset($formats[$default_format])) {
506 // use currently set bf default as a fallback
507 $default = $default_format;
510 // use core site default as a fallback if the previous two are not available
511 $default = filter_resolve_format(FILTER_FORMAT_DEFAULT
);
514 if (count($formats) > 1 && $show_selection) {
515 $collapsed = user_access('collapse format fieldset by default');
516 $collapsible = user_access('collapsible format selection');
517 $fieldset_title = variable_get('better_formats_fieldset_title', 'Input format');
519 if ($debug && ! $debug1) {
520 drupal_set_message('Collapsible format selection: ' .
$collapsible);
521 drupal_set_message('Collape format selection by default: ' .
$collapsed);
525 '#type' => 'fieldset',
526 '#title' => t('@title', array('@title' => $fieldset_title ?
$fieldset_title : 'Input format')),
527 '#collapsible' => $collapsible,
528 '#collapsed' => $collapsed,
529 '#weight' => $weight,
530 '#element_validate' => array('filter_form_validate'),
533 // Multiple formats available: display radio buttons with tips.
534 foreach ($formats as
$format) {
535 // Generate the parents as the autogenerator does, so we will have a
536 // unique id for each radio button.
537 $parents_for_id = array_merge($parents, array($format->format
));
538 $form[$format->format
] = array(
540 '#title' => $format->name
,
541 '#default_value' => $default,
542 '#return_value' => $format->format
,
543 '#parents' => $parents,
544 '#id' => form_clean_id('edit-'.
implode('-', $parents_for_id)),
547 $form[$format->format
]['#description'] = theme('filter_tips', _filter_tips($format->format
, FALSE
));
550 // this is to get around an issue with Wysiwyg API popping the last element
551 // should not be needed in D7
552 // see http://drupal.org/node/344169
553 $form[$format->format
]['#description'] = '';
557 if ($show_tips_link) {
558 $extra = theme('better_formats_filter_tips_more_info');
559 $form[] = array('#value' => $extra);
562 // this is to get around an issue with Wysiwyg API popping the last element
563 // should not be needed in D7
564 // see http://drupal.org/node/344169
565 $form[] = array('#value' => '');
569 // Only one format available or hiding the form: use a hidden form item.
570 $format = $formats[$default];
571 $form[$format->format
] = array(
573 '#value' => $format->format
,
574 '#parents' => $parents
578 $tips = _filter_tips($format->format
, FALSE
);
579 $form['format']['guidelines'] = array(
580 '#title' => t('Formatting guidelines'),
581 '#value' => theme('filter_tips', $tips, FALSE
),
585 // this is to get around an issue with Wysiwyg API looking for guidelines
586 // should not be needed in D7
587 // see http://drupal.org/node/344169
588 $form['format']['guidelines'] = array(
589 '#title' => t('Formatting guidelines'),
594 // only show long tips link if there are guidelines to the format
595 if ($show_tips_link) {
596 $extra = theme('better_formats_filter_tips_more_info');
597 $form[] = array('#value' => $extra);
599 // see http://drupal.org/node/344169
600 $form[] = array('#value' => '');
604 // set debug1 to true so that some debug info is only printed once
611 function theme_better_formats_filter_tips_more_info() {
612 $text = variable_get('better_formats_long_tips_link_text', '');
613 $text = $text ?
$text : t('More information about formatting options');
614 return '<p>' .
l($text, 'filter/tips') .
'</p>';
619 * Retrieves the formats available to users by role.
621 * Gets all formats then creates an array keyed by role IDs
622 * that lists the formats available to that role. This is determined
623 * by Drupal core's format permissions set at
624 * admin/settings/filters/[filter_id].
626 * @param string $default_title
627 * Allows configuration of the label of the default seletion
629 * Multi-dim array with role IDs for keys and list of allowed formats.
631 * @see better_formats_get_role_default_fields()
633 function better_formats_get_formats_per_role($default_title = 'Site') {
634 $formats = filter_formats();
635 $roles = user_roles();
637 // get roles that have administer filters permission
640 WHERE perm LIKE '%administer filters%'
642 $result = db_query($sql);
643 $admin_roles = array();
644 while ($row = db_fetch_object($result)) {
645 $admin_roles[] = $row->rid
;
648 $site_default_format = filter_resolve_format(FILTER_FORMAT_DEFAULT
);
650 foreach ($formats as
$format) {
651 $roles_allowed = $format->roles ?
explode(',', trim($format->roles
, ',')) : array();
652 foreach ($roles as
$rid => $role) {
653 $format_options[$rid][0] = $default_title .
' default';
654 if ($format->format
== $site_default_format ||
655 in_array($rid, $admin_roles) ||
656 in_array($rid, $roles_allowed)
658 $format_options[$rid][$format->format
] = $format->name
;
663 return $format_options;
667 * Builds FAPI form elements for the default format selection.
669 * @param string $mode
670 * 'node' or 'comment'. Top most level type for requested default.
671 * @param string $node_type
672 * Type of node this request is for.
674 * FAPI array for the default select field.
676 function better_formats_get_role_default_fields($mode, $node_type = '') {
678 $format_options = better_formats_get_formats_per_role();
679 $type = $types = $mode;
680 $per_node_type = variable_get('better_formats_per_node_type', FALSE
);
682 if ($per_node_type && $node_type) {
683 $type = $mode .
'/' .
$node_type;
684 $types = $type .
"','" .
$mode;
688 $sql = "SELECT bf.*, role.name
689 FROM {better_formats_defaults} AS bf
690 INNER JOIN {role} AS role
692 WHERE bf.type IN ('$types')
693 ORDER BY bf.type_weight DESC, bf.weight, role.rid";
694 $result = db_query($sql);
696 $roles_set = array();
698 while ($role = db_fetch_object($result)) {
699 if (in_array($role->rid
, $roles_set)) {
703 $roles_set[] = $role->rid
;
704 $key = $mode .
'-' .
$role->rid
;
706 $form[$key]['role'] = array(
707 '#value' => $role->name
,
709 $form[$key]['format'] = array(
711 '#title' => t('Format'),
712 '#options' => $format_options[$role->rid
],
713 '#default_value' => $role->format
,
714 '#attributes' => array('class' => 'bf-default-formats'),
716 $form[$key]['weight'] = array(
719 '#default_value' => $role->weight
,