Index: includes/common.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/common.inc,v
retrieving revision 1.1041
diff -u -p -r1.1041 common.inc
--- includes/common.inc 5 Nov 2009 16:19:25 -0000 1.1041
+++ includes/common.inc 6 Nov 2009 23:59:35 -0000
@@ -5513,9 +5513,6 @@ function drupal_common_theme() {
'form_required_marker' => array(
'arguments' => array('element' => NULL),
),
- 'text_format_wrapper' => array(
- 'render element' => 'element',
- ),
'vertical_tabs' => array(
'render element' => 'element',
),
Index: includes/form.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/form.inc,v
retrieving revision 1.393
diff -u -p -r1.393 form.inc
--- includes/form.inc 4 Nov 2009 05:39:14 -0000 1.393
+++ includes/form.inc 6 Nov 2009 23:58:56 -0000
@@ -1992,110 +1992,6 @@ function form_process_radios($element) {
}
/**
- * Add text format selector to text elements with the #text_format property.
- *
- * The #text_format property should be the ID of an text format, found in
- * {filter_format}.format, which gets passed to filter_form().
- *
- * If the property #text_format is set, the form element will be expanded into
- * two separate form elements, one holding the content of the element, and the
- * other holding the text format selector. The original element is shifted into
- * a child element, but is otherwise unaltered, so that the format selector is
- * at the same level as the text field which it affects.
- *
- * For example:
- * @code
- * // A simple textarea, such as a node body.
- * $form['body'] = array(
- * '#type' => 'textarea',
- * '#title' => t('Body'),
- * '#text_format' => isset($node->format) ? $node->format : filter_default_format(),
- * );
- * @endcode
- *
- * Becomes:
- * @code
- * $form['body'] = array(
- * // Type switches to 'markup', as we're only interested in submitting the child elements.
- * '#type' => 'markup',
- * // 'value' holds the original element.
- * 'value' => array(
- * '#type' => 'textarea',
- * '#title' => t('Body'),
- * '#parents' => array('body'),
- * ),
- * // 'format' holds the text format selector.
- * 'format' => array(
- * '#parents' => array('body_format'),
- * ...
- * ),
- * );
- * @endcode
- *
- * And would result in:
- * @code
- * // Original, unaltered form element value.
- * $form_state['values']['body'] = 'Example content';
- * // Chosen text format.
- * $form_state['values']['body_format'] = 1;
- * @endcode
- *
- * @see system_element_info(), filter_form()
- */
-function form_process_text_format($element) {
- if (isset($element['#text_format'])) {
- // Determine the form element parents and element name to use for the input
- // format widget. This simulates the 'element' and 'element_format' pair of
- // parents that filter_form() expects.
- $element_parents = $element['#parents'];
- $element_name = array_pop($element_parents);
- $element_parents[] = $element_name . '_format';
-
- // We need to break references, otherwise form_builder recurses infinitely.
- $element['value'] = (array)$element;
- $element['value']['#weight'] = 0;
- unset($element['value']['#description']);
- $element['#type'] = 'markup';
- $element['#theme'] = NULL;
- $element['#theme_wrappers'] = array('text_format_wrapper');
- $element['format'] = filter_form($element['#text_format'], 1, $element_parents);
-
- // We need to clear the #text_format from the new child otherwise we
- // would get into an infinite loop.
- unset($element['value']['#text_format']);
- }
- return $element;
-}
-
-/**
- * Theme a text format form element.
- *
- * @param $variables
- * An associative array containing:
- * - element: An associative array containing the properties of the element.
- * Properties used: #children, #description
- *
- * @return
- * A string representing the form element.
- *
- * @ingroup themeable
- */
-function theme_text_format_wrapper($variables) {
- $element = $variables['element'];
- $output = '
' . "\n";
-
- $output .= $element['#children'] . "\n";
-
- if (!empty($element['#description'])) {
- $output .= '
' . $element['#description'] . "
\n";
- }
-
- $output .= "
\n";
-
- return $output;
-}
-
-/**
* Theme a checkbox form element.
*
* @param $variables
Index: modules/block/block.admin.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/block/block.admin.inc,v
retrieving revision 1.61
diff -u -p -r1.61 block.admin.inc
--- modules/block/block.admin.inc 3 Nov 2009 05:27:18 -0000 1.61
+++ modules/block/block.admin.inc 6 Nov 2009 23:58:56 -0000
@@ -446,9 +446,9 @@ function block_add_block_form_validate($
function block_add_block_form_submit($form, &$form_state) {
$delta = db_insert('block_custom')
->fields(array(
- 'body' => $form_state['values']['body'],
+ 'body' => $form_state['values']['body']['value'],
'info' => $form_state['values']['info'],
- 'format' => $form_state['values']['body_format'],
+ 'format' => $form_state['values']['body']['format'],
))
->execute();
Index: modules/block/block.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/block/block.module,v
retrieving revision 1.394
diff -u -p -r1.394 block.module
--- modules/block/block.module 23 Oct 2009 22:24:11 -0000 1.394
+++ modules/block/block.module 6 Nov 2009 23:58:56 -0000
@@ -186,7 +186,7 @@ function block_block_info() {
* Implement hook_block_configure().
*/
function block_block_configure($delta = 0) {
- $custom_block = array('format' => filter_default_format());
+ $custom_block = array('format' => filter_format_default());
if ($delta) {
$custom_block = block_custom_block_get($delta);
}
@@ -423,10 +423,10 @@ function block_custom_block_form($edit =
);
$form['body_field']['#weight'] = -17;
$form['body_field']['body'] = array(
- '#type' => 'textarea',
+ '#type' => 'textarea_format',
'#title' => t('Block body'),
'#default_value' => $edit['body'],
- '#text_format' => isset($edit['format']) ? $edit['format'] : filter_default_format(),
+ '#format' => isset($edit['format']) ? $edit['format'] : NULL,
'#rows' => 15,
'#description' => t('The content of the block as shown to the user.'),
'#required' => TRUE,
@@ -453,9 +453,9 @@ function block_custom_block_form($edit =
function block_custom_block_save($edit, $delta) {
db_update('block_custom')
->fields(array(
- 'body' => $edit['body'],
+ 'body' => $edit['body']['value'],
'info' => $edit['info'],
- 'format' => $edit['body_format'],
+ 'format' => $edit['body']['format'],
))
->condition('bid', $delta)
->execute();
Index: modules/block/block.test
===================================================================
RCS file: /cvs/drupal/drupal/modules/block/block.test,v
retrieving revision 1.30
diff -u -p -r1.30 block.test
--- modules/block/block.test 16 Oct 2009 23:48:37 -0000 1.30
+++ modules/block/block.test 21 Oct 2009 05:38:08 -0000
@@ -78,8 +78,8 @@ class BlockTestCase extends DrupalWebTes
$custom_block = array();
$custom_block['info'] = $this->randomName(8);
$custom_block['title'] = $this->randomName(8);
- $custom_block['body'] = 'Full HTML
';
- $custom_block['body_format'] = 2;
+ $custom_block['body[value]'] = 'Full HTML
';
+ $custom_block['body[format]'] = 2;
$this->drupalPost('admin/structure/block/add', $custom_block, t('Save block'));
// Set the created custom block to a specific region.
@@ -119,7 +119,7 @@ class BlockTestCase extends DrupalWebTes
$custom_block = array();
$custom_block['info'] = $this->randomName(8);
$custom_block['title'] = $title;
- $custom_block['body'] = $this->randomName(32);
+ $custom_block['body[value]'] = $this->randomName(32);
$this->drupalPost('admin/structure/block/add', $custom_block, t('Save block'));
$bid = db_query("SELECT bid FROM {block_custom} WHERE info = :info", array(':info' => $custom_block['info']))->fetchField();
Index: modules/comment/comment.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/comment/comment.module,v
retrieving revision 1.801
diff -u -p -r1.801 comment.module
--- modules/comment/comment.module 6 Nov 2009 03:59:06 -0000 1.801
+++ modules/comment/comment.module 6 Nov 2009 23:58:57 -0000
@@ -1289,7 +1289,7 @@ function comment_save($comment) {
'changed' => $comment->changed,
'subject' => $comment->subject,
'comment' => $comment->comment,
- 'format' => $comment->comment_format,
+ 'format' => $comment->format,
'uid' => $comment->uid,
'name' => $comment->name,
'mail' => $comment->mail,
@@ -1365,7 +1365,7 @@ function comment_save($comment) {
'uid' => $comment->uid,
'subject' => $comment->subject,
'comment' => $comment->comment,
- 'format' => $comment->comment_format,
+ 'format' => $comment->format,
'hostname' => ip_address(),
'created' => $comment->created,
'changed' => $comment->changed,
@@ -1842,11 +1842,11 @@ function comment_form($form, &$form_stat
}
$form['comment'] = array(
- '#type' => 'textarea',
+ '#type' => 'textarea_format',
'#title' => t('Comment'),
'#rows' => 15,
'#default_value' => $default,
- '#text_format' => isset($comment->format) ? $comment->format : filter_default_format(),
+ '#format' => isset($comment->format) ? $comment->format : NULL,
'#required' => TRUE,
);
@@ -1924,7 +1924,8 @@ function comment_preview($comment) {
$node = node_load($comment->nid);
if (!form_get_errors()) {
- $comment->format = $comment->comment_format;
+ $comment->format = $comment->comment['format'];
+ $comment->comment = $comment->comment['value'];
// Attach the user and time information.
if (!empty($comment->author)) {
@@ -2054,7 +2055,7 @@ function comment_submit($comment) {
// 1) Filter it into HTML
// 2) Strip out all HTML tags
// 3) Convert entities back to plain-text.
- $comment['subject'] = truncate_utf8(trim(decode_entities(strip_tags(check_markup($comment['comment'], $comment['comment_format'])))), 29, TRUE);
+ $comment['subject'] = truncate_utf8(trim(decode_entities(strip_tags(check_markup($comment['comment']['value'], $comment['comment']['format'])))), 29, TRUE);
// Edge cases where the comment body is populated only by HTML tags will
// require a default subject.
if ($comment['subject'] == '') {
Index: modules/comment/comment.pages.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/comment/comment.pages.inc,v
retrieving revision 1.28
diff -u -p -r1.28 comment.pages.inc
--- modules/comment/comment.pages.inc 1 Nov 2009 12:11:10 -0000 1.28
+++ modules/comment/comment.pages.inc 6 Nov 2009 23:58:57 -0000
@@ -108,7 +108,8 @@ function comment_reply(stdClass $node, $
*/
function comment_approve($comment) {
$comment->status = COMMENT_PUBLISHED;
- $comment->comment_format = $comment->format;
+ $comment->format = $comment->comment['format'];
+ $comment->comment = $comment->comment['value'];
comment_save($comment);
drupal_set_message(t('Comment approved.'));
Index: modules/comment/comment.test
===================================================================
RCS file: /cvs/drupal/drupal/modules/comment/comment.test,v
retrieving revision 1.52
diff -u -p -r1.52 comment.test
--- modules/comment/comment.test 20 Oct 2009 17:33:42 -0000 1.52
+++ modules/comment/comment.test 21 Oct 2009 05:42:01 -0000
@@ -24,7 +24,7 @@ class CommentHelperCase extends DrupalWe
*/
function postComment($node, $comment, $subject = '', $contact = NULL) {
$edit = array();
- $edit['comment'] = $comment;
+ $edit['comment[value]'] = $comment;
$preview_mode = variable_get('comment_preview_article', DRUPAL_OPTIONAL);
$subject_mode = variable_get('comment_subject_field_article', 1);
@@ -413,17 +413,17 @@ class CommentPreviewTest extends Comment
$this->drupalLogin($this->web_user);
$edit = array();
$edit['subject'] = $this->randomName(8);
- $edit['comment'] = $this->randomName(16);
+ $edit['comment[value]'] = $this->randomName(16);
$this->drupalPost('node/' . $this->node->nid, $edit, t('Preview'));
// Check that the preview is displaying the title and body.
$this->assertTitle(t('Preview comment | Drupal'), t('Page title is "Preview comment".'));
$this->assertText($edit['subject'], t('Subject displayed.'));
- $this->assertText($edit['comment'], t('Comment displayed.'));
+ $this->assertText($edit['comment[value]'], t('Comment displayed.'));
// Check that the title and body fields are displayed with the correct values.
$this->assertFieldByName('subject', $edit['subject'], t('Subject field displayed.'));
- $this->assertFieldByName('comment', $edit['comment'], t('Comment field displayed.'));
+ $this->assertFieldByName('comment', $edit['comment[value]'], t('Comment field displayed.'));
}
/**
@@ -439,23 +439,23 @@ class CommentPreviewTest extends Comment
$edit = array();
$edit['subject'] = $this->randomName(8);
- $edit['comment'] = $this->randomName(16);
+ $edit['comment[value]'] = $this->randomName(16);
$edit['author'] = $web_user->name;
$edit['date'] = '2008-03-02 17:23 +0300';
$expected_date = format_date(strtotime($edit['date']));
- $comment = $this->postComment($this->node, $edit['subject'], $edit['comment'], TRUE);
+ $comment = $this->postComment($this->node, $edit['subject'], $edit['comment[value]'], TRUE);
$this->drupalPost('comment/' . $comment->id . '/edit', $edit, t('Preview'));
// Check that the preview is displaying the subject, comment, author and date correctly.
$this->assertTitle(t('Preview comment | Drupal'), t('Page title is "Preview comment".'));
$this->assertText($edit['subject'], t('Subject displayed.'));
- $this->assertText($edit['comment'], t('Comment displayed.'));
+ $this->assertText($edit['comment[value]'], t('Comment displayed.'));
$this->assertText($edit['author'], t('Author displayed.'));
$this->assertText($expected_date, t('Date displayed.'));
// Check that the title and body fields are displayed with the correct values.
$this->assertFieldByName('subject', $edit['subject'], t('Subject field displayed.'));
- $this->assertFieldByName('comment', $edit['comment'], t('Comment field displayed.'));
+ $this->assertFieldByName('comment', $edit['comment[value]'], t('Comment field displayed.'));
$this->assertFieldByName('author', $edit['author'], t('Author field displayed.'));
$this->assertFieldByName('date', $edit['date'], t('Date field displayed.'));
}
Index: modules/field/modules/text/text.js
===================================================================
RCS file: /cvs/drupal/drupal/modules/field/modules/text/text.js,v
retrieving revision 1.1
diff -u -p -r1.1 text.js
--- modules/field/modules/text/text.js 11 Sep 2009 13:30:49 -0000 1.1
+++ modules/field/modules/text/text.js 20 Oct 2009 22:58:37 -0000
@@ -5,9 +5,9 @@
/**
* Auto-hide summary textarea if empty and show hide and unhide links.
*/
-Drupal.behaviors.textTextareaSummary = {
+Drupal.behaviors.textSummary = {
attach: function (context, settings) {
- $('textarea.text-textarea-summary:not(.text-textarea-summary-processed)', context).addClass('text-textarea-summary-processed').each(function () {
+ $('textarea.text-summary', context).once('text-summary', function () {
var $fieldset = $(this).closest('#body-wrapper');
var $summary = $fieldset.find('div.text-summary-wrapper');
var $summaryLabel = $summary.find('div.form-type-textarea label');
Index: modules/field/modules/text/text.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/field/modules/text/text.module,v
retrieving revision 1.35
diff -u -p -r1.35 text.module
--- modules/field/modules/text/text.module 1 Nov 2009 14:05:31 -0000 1.35
+++ modules/field/modules/text/text.module 7 Nov 2009 00:19:34 -0000
@@ -146,7 +146,7 @@ function text_field_instance_settings_fo
'#default_value' => $settings['text_processing'],
'#options' => array(
t('Plain text'),
- t('Filtered text (user selects input format)'),
+ t('Filtered text (user selects text format)'),
),
);
if ($field['type'] == 'text_with_summary') {
@@ -154,7 +154,7 @@ function text_field_instance_settings_fo
'#type' => 'checkbox',
'#title' => t('Summary input'),
'#default_value' => $settings['display_summary'],
- '#description' => t('This allows authors to input an explicit summary, to be displayed instead of the automatically trimmed text when using the "Summary or trimmed" display format.'),
+ '#description' => t('This allows authors to input an explicit summary, to be displayed instead of the automatically trimmed text when using the "Summary or trimmed" display type.'),
);
}
@@ -170,13 +170,16 @@ function text_field_instance_settings_fo
*/
function text_field_validate($obj_type, $object, $field, $instance, $langcode, $items, &$errors) {
foreach ($items as $delta => $item) {
- foreach (array('value' => t('full text'), 'summary' => t('summary')) as $column => $desc) {
+ // @todo Length is counted separately for summary and value, so the maximum
+ // length can be exceeded very easily.
+ foreach (array('value', 'summary') as $column) {
if (!empty($item[$column])) {
if (!empty($field['settings']['max_length']) && drupal_strlen($item[$column]) > $field['settings']['max_length']) {
switch ($column) {
case 'value':
$message = t('%name: the text may not be longer than %max characters.', array('%name' => $instance['label'], '%max' => $field['settings']['max_length']));
break;
+
case 'summary':
$message = t('%name: the summary may not be longer than %max characters.', array('%name' => $instance['label'], '%max' => $field['settings']['max_length']));
break;
@@ -205,11 +208,11 @@ function text_field_load($obj_type, $obj
if (!empty($instances[$id]['settings']['text_processing'])) {
// Only process items with a cacheable format, the rest will be
// handled by text_field_sanitize().
- $format = $item['format'];
- if (filter_format_allowcache($format)) {
- $items[$id][$delta]['safe'] = isset($item['value']) ? check_markup($item['value'], $format, $langcode) : '';
+ $format_id = $item['format'];
+ if (filter_format_allowcache($format_id)) {
+ $items[$id][$delta]['safe'] = isset($item['value']) ? check_markup($item['value'], $format_id, $langcode) : '';
if ($field['type'] == 'text_with_summary') {
- $items[$id][$delta]['safe_summary'] = isset($item['summary']) ? check_markup($item['summary'], $format, $langcode) : '';
+ $items[$id][$delta]['safe_summary'] = isset($item['summary']) ? check_markup($item['summary'], $format_id, $langcode) : '';
}
}
}
@@ -235,10 +238,10 @@ function text_field_sanitize($obj_type,
// from a form preview.
if (!isset($items[$delta]['safe'])) {
if (!empty($instance['settings']['text_processing'])) {
- $format = $item['format'];
- $items[$delta]['safe'] = isset($item['value']) ? check_markup($item['value'], $format, $langcode, TRUE) : '';
+ $format_id = $item['format'];
+ $items[$delta]['safe'] = isset($item['value']) ? check_markup($item['value'], $format_id, $langcode, TRUE) : '';
if ($field['type'] == 'text_with_summary') {
- $items[$delta]['safe_summary'] = isset($item['summary']) ? check_markup($item['summary'], $format, $langcode, TRUE) : '';
+ $items[$delta]['safe_summary'] = isset($item['summary']) ? check_markup($item['summary'], $format_id, $langcode, TRUE) : '';
}
}
else {
@@ -469,14 +472,6 @@ function text_summary($text, $format = N
/**
* Implement hook_field_widget_info().
- *
- * Here we indicate that the field module will handle
- * the default value and multiple values for these widgets.
- *
- * Callbacks can be omitted if default handing is used.
- * They're included here just so this module can be used
- * as an example for custom modules that might do things
- * differently.
*/
function text_field_widget_info() {
return array(
@@ -528,40 +523,6 @@ function text_field_widget_settings_form
}
/**
- * Implement hook_element_info().
- *
- * Autocomplete_path is not used by text_field_widget but other
- * widgets can use it (see nodereference and userreference).
- */
-function text_element_info() {
- $types['text_textfield'] = array(
- '#input' => TRUE,
- '#columns' => array('value'),
- '#delta' => 0,
- '#process' => array('text_textfield_elements_process'),
- '#theme_wrappers' => array('text_textfield'),
- '#autocomplete_path' => FALSE,
- );
- $types['text_textarea'] = array(
- '#input' => TRUE,
- '#columns' => array('value', 'format'),
- '#delta' => 0,
- '#process' => array('text_textarea_elements_process'),
- '#theme_wrappers' => array('text_textarea'),
- '#filter_value' => filter_default_format(),
- );
- $types['text_textarea_with_summary'] = array(
- '#input' => TRUE,
- '#columns' => array('value', 'format', 'summary'),
- '#delta' => 0,
- '#process' => array('text_textarea_with_summary_process'),
- '#theme_wrappers' => array('text_textarea'),
- '#filter_value' => filter_default_format(),
- );
- return $types;
-}
-
-/**
* Implement hook_field_widget().
*/
function text_field_widget(&$form, &$form_state, $field, $instance, $langcode, $items, $delta, $element) {
@@ -569,8 +530,60 @@ function text_field_widget(&$form, &$for
'#type' => $instance['widget']['type'],
'#default_value' => isset($items[$delta]) ? $items[$delta] : '',
);
+
+ if (isset($element['#columns'][1]) && $element['#columns'][1] == 'summary') {
+ $field_key = $element['#columns'][1];
+ $display = !empty($items[$delta][$field_key]) || !empty($instance['settings']['display_summary']);
+ $element[$field_key] = array(
+ '#title' => t('Summary'),
+ '#type' => $display ? 'textarea' : 'value',
+ '#default_value' => isset($items[$delta][$field_key]) ? $items[$delta][$field_key] : NULL,
+ '#rows' => $instance['widget']['settings']['summary_rows'],
+ '#title' => t('Summary'),
+ '#description' => t('Leave blank to use trimmed value of full text as the summary.'),
+ '#attached' => array('js' => array(drupal_get_path('module', 'text') . '/text.js')),
+ '#attributes' => array('class' => array('text-summary')),
+ '#prefix' => '',
+ '#suffix' => '
',
+ );
+ }
+
+ $field_key = $element['#columns'][0];
+ switch ($instance['widget']['type']) {
+ case 'text_textfield':
+ $element[$field_key] = array(
+ '#type' => 'textfield',
+ '#default_value' => isset($items[$delta][$field_key]) ? $items[$delta][$field_key] : NULL,
+ '#size' => $instance['widget']['settings']['size'],
+ '#title' => $instance['label'],
+ '#description' => $instance['description'],
+ '#required' => $instance['required'],
+ '#attributes' => array('class' => array('text-textfield')),
+ );
+ break;
+
+ default:
+ $element[$field_key] = array(
+ '#type' => 'textarea',
+ '#default_value' => isset($items[$delta][$field_key]) ? $items[$delta][$field_key] : NULL,
+ '#rows' => $instance['widget']['settings']['rows'],
+ '#title' => $instance['label'],
+ '#description' => $instance['description'],
+ '#required' => $instance['required'],
+ '#attributes' => array('class' => array('text-textarea')),
+ '#prefix' => '',
+ '#suffix' => '
',
+ );
+ break;
+ }
+
+ // Conditionally alter the form element's type if text processing is enabled.
if (!empty($instance['settings']['text_processing'])) {
- $element['#value_callback'] = 'text_field_widget_formatted_text_value';
+ $element[$field_key]['#type'] .= '_format';
+ $element[$field_key]['#format'] = isset($items[$delta]['format']) ? $items[$delta]['format'] : NULL;
+ // Signal filter_process_form() to not expand the form element into 'value'
+ // and 'format', since we need all submitted form values on one level.
+ $element[$field_key]['#format_tree'] = FALSE;
}
return $element;
@@ -593,170 +606,3 @@ function text_field_widget_error($elemen
form_error($error_element, $error['message']);
}
-/**
- * Process an individual element.
- *
- * Build the form element. When creating a form using FAPI #process,
- * note that $element['#value'] is already set.
- *
- * The $field and $instance arrays are in $form['#fields'][$element['#field_name']].
- *
- * TODO: For widgets to be actual FAPI 'elements', reusable outside of a
- * 'field' context, they shoudn't rely on $field and $instance. The bits of
- * information needed to adjust the behavior of the 'element' should be
- * extracted in hook_field_widget() above.
- */
-function text_textfield_elements_process($element, $form_state, $form) {
- $field = $form['#fields'][$element['#field_name']]['field'];
- $instance = $form['#fields'][$element['#field_name']]['instance'];
- $field_key = $element['#columns'][0];
- $delta = $element['#delta'];
-
- $element[$field_key] = array(
- '#type' => 'textfield',
- '#default_value' => isset($element['#value'][$field_key]) ? $element['#value'][$field_key] : NULL,
- '#autocomplete_path' => $element['#autocomplete_path'],
- '#size' => $instance['widget']['settings']['size'],
- '#attributes' => array('class' => array('text')),
- '#title' => $element['#title'],
- '#description' => $element['#description'],
- '#required' => $element['#required'],
- );
-
- $element[$field_key]['#maxlength'] = !empty($field['settings']['max_length']) ? $field['settings']['max_length'] : NULL;
-
- if (!empty($instance['settings']['text_processing'])) {
- $filter_key = (count($element['#columns']) == 2) ? $element['#columns'][1] : 'format';
- $format = isset($element['#value'][$filter_key]) ? $element['#value'][$filter_key] : filter_default_format();
- $element[$field_key]['#text_format'] = $format;
- }
-
- return $element;
-}
-
-/**
- * Process an individual element.
- *
- * Build the form element. When creating a form using FAPI #process,
- * note that $element['#value'] is already set.
- *
- * The $field and $instance arrays are in $form['#fields'][$element['#field_name']].
- */
-function text_textarea_elements_process($element, $form_state, $form) {
- $field = $form['#fields'][$element['#field_name']]['field'];
- $instance = $form['#fields'][$element['#field_name']]['instance'];
- $field_key = $element['#columns'][0];
- $delta = $element['#delta'];
-
- $element[$field_key] = array(
- '#type' => 'textarea',
- '#default_value' => isset($element['#value'][$field_key]) ? $element['#value'][$field_key] : NULL,
- '#rows' => $instance['widget']['settings']['rows'],
- '#weight' => 0,
- '#title' => $element['#title'],
- '#description' => $element['#description'],
- '#required' => $element['#required'],
- );
-
- if (!empty($instance['settings']['text_processing'])) {
- $filter_key = (count($element['#columns']) == 2) ? $element['#columns'][1] : 'format';
- $format = isset($element['#value'][$filter_key]) ? $element['#value'][$filter_key] : filter_default_format();
- $element[$field_key]['#text_format'] = $format;
- }
-
- return $element;
-}
-
-/**
- * Process an individual element.
- *
- * Build the form element. When creating a form using FAPI #process,
- * note that $element['#value'] is already set.
- *
- * The $field and $instance arrays are in $form['#fields'][$element['#field_name']].
- */
-function text_textarea_with_summary_process($element, $form_state, $form) {
- $field = $form['#fields'][$element['#field_name']]['field'];
- $instance = $form['#fields'][$element['#field_name']]['instance'];
- $delta = $element['#delta'];
-
- $field_key = $element['#columns'][1];
- $display = !empty($element['#value'][$field_key]) || !empty($instance['settings']['display_summary']);
- $element[$field_key] = array(
- '#title' => t('Summary'),
- '#type' => $display ? 'textarea' : 'value',
- '#default_value' => isset($element['#value'][$field_key]) ? $element['#value'][$field_key] : NULL,
- '#rows' => $instance['widget']['settings']['summary_rows'],
- '#weight' => 0,
- '#title' => t('Summary'),
- '#description' => t('Leave blank to use trimmed value of full text as the summary.'),
- '#display' => $display,
- '#attached' => array('js' => array(drupal_get_path('module', 'text') . '/text.js')),
- '#attributes' => array('class' => array('text-textarea-summary')),
- '#prefix' => '',
- '#suffix' => '
',
- );
-
- $field_key = $element['#columns'][0];
- $element[$field_key] = array(
- '#type' => 'textarea',
- '#default_value' => isset($element['#value'][$field_key]) ? $element['#value'][$field_key] : NULL,
- '#rows' => $instance['widget']['settings']['rows'],
- '#weight' => 1,
- '#title' => $display ? t('Full text') : $element['#title'],
- '#description' => $element['#description'],
- '#required' => $element['#required'],
- '#attributes' => array('class' => array('text-full-textarea')),
- '#prefix' => '',
- '#suffix' => '
',
- );
-
- if (!empty($instance['settings']['text_processing'])) {
- $filter_key = (count($element['#columns']) == 2) ? $element['#columns'][1] : 'format';
- $format = isset($element['#value'][$filter_key]) ? $element['#value'][$filter_key] : filter_default_format();
- $element[$field_key]['#text_format'] = $format;
- }
-
- return $element;
-}
-
-/**
- * Helper function to determine the value for a formatted text widget.
- *
- * '#text_format' puts the format in '[column 0]_format' in incoming values,
- * while we need it in '[column 1]'.
- */
-function text_field_widget_formatted_text_value($form, $edit = FALSE) {
- if ($edit !== FALSE) {
- $field_key = $form['#columns'][0];
- $filter_key = (count($form['#columns']) == 2) ? $form['#columns'][1] : 'format';
- $default_key = $field_key . '_format';
- // The format selector uses #access = FALSE if only one format is
- // available. In this case, we don't receive its value, and need to
- // manually set it.
- $edit['format'] = !empty($edit[$default_key]) ? $edit[$default_key] : filter_default_format();
- unset($edit[$default_key]);
- return $edit;
- }
-}
-
-/**
- * FAPI theme for an individual text elements.
- *
- * The textfield or textarea is already rendered by the
- * textfield or textarea themes and the html output
- * lives in $variables['element']['#children']. Override this theme to
- * make custom changes to the output.
- *
- * $variables['element']['#field_name'] contains the field name
- * $variables['element']['#delta] is the position of this element in the group
- */
-function theme_text_textfield($variables) {
- $element = $variables['element'];
- return $element['#children'];
-}
-
-function theme_text_textarea($variables) {
- $element = $variables['element'];
- return $element['#children'];
-}
Index: modules/filter/filter.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/filter/filter.module,v
retrieving revision 1.300
diff -u -p -r1.300 filter.module
--- modules/filter/filter.module 23 Oct 2009 22:24:14 -0000 1.300
+++ modules/filter/filter.module 7 Nov 2009 00:05:07 -0000
@@ -49,6 +49,9 @@ function filter_theme() {
'variables' => array('tips' => NULL, 'long' => FALSE),
'file' => 'filter.pages.inc',
),
+ 'filter_format_wrapper' => array(
+ 'render element' => 'element',
+ ),
'filter_tips_more_info' => array(
'variables' => array(),
),
@@ -59,6 +62,24 @@ function filter_theme() {
}
/**
+ * Implement of hook_elements().
+ *
+ * Elements defined by Filter module are wrappers around the respective,
+ * non-prefixed elements and are expanded by filter_process_format().
+ *
+ * @see filter_process_format()
+ */
+function filter_element_info() {
+ $type['textfield_format'] = array(
+ '#process' => array('filter_process_format'),
+ );
+ $type['textarea_format'] = array(
+ '#process' => array('filter_process_format'),
+ );
+ return $type;
+}
+
+/**
* Implement hook_menu().
*/
function filter_menu() {
@@ -428,7 +449,7 @@ function filter_get_formats_by_role($rid
*
* @see filter_fallback_format()
*/
-function filter_default_format($account = NULL) {
+function filter_format_default($account = NULL) {
global $user;
if (!isset($account)) {
$account = $user;
@@ -617,69 +638,164 @@ function check_markup($text, $format_id
/**
* Generates a selector for choosing a format in a form.
*
- * @param $selected_format
- * The ID of the format that is currently selected; uses the default format
- * for the current user if not provided.
- * @param $weight
- * The weight of the form element within the form.
- * @param $parents
- * The parents array of the element. Required when defining multiple text
- * formats on a single form or having a different parent than 'format'.
+ * The form element will be expanded into two separate form elements, one
+ * holding the content of the element, and the other holding the text format
+ * selector. The original element is shifted into a child element, but is
+ * otherwise unaltered, so that the format selector is at the same level as the
+ * text field which it affects.
+ *
+ * The optional #format property should be the ID of an text format, found in
+ * {filter_format}.format, or NULL to use the default format for the current
+ * user. For example:
+ * @code
+ * $form['body'] = array(
+ * '#type' => 'textarea_format',
+ * '#title' => t('Body'),
+ * '#format' => isset($node->format) ? $node->format : NULL,
+ * );
+ * @endcode
+ *
+ * Becomes:
+ * @code
+ * $form['body'] = array(
+ * '#type' => 'markup',
+ * // 'value' holds the original element.
+ * 'value' => array(
+ * '#type' => 'textarea',
+ * '#title' => t('Body'),
+ * '#parents' => array('body', 'value'),
+ * ),
+ * // 'format' holds the text format widget.
+ * 'format' => array(
+ * '#parents' => array('body', 'format'),
+ * ),
+ * );
+ * @endcode
+ *
+ * Which results in the submitted form values:
+ * @code
+ * // Original, unaltered form element value.
+ * $form_state['values']['body']['value'] = 'Example content';
+ * // Chosen text format.
+ * $form_state['values']['body']['format'] = 1;
+ * @endcode
*
- * @return
- * Form API array for the form element.
+ * @param $element
+ * The form element to process.
*
- * @ingroup forms
+ * @return
+ * The expanded element.
*/
-function filter_form($selected_format = NULL, $weight = NULL, $parents = array('format')) {
+function filter_process_format($element) {
global $user;
- // Use the default format for this user if none was selected.
- if (empty($selected_format)) {
- $selected_format = filter_default_format($user);
- }
+ // By default, the new child values 'value' and 'format' should end up as
+ // sub-keys of the original element in the submitted form values, so we enable
+ // #tree. However, if the original element explicitly defined #format_tree as
+ // FALSE, then this will override the #parents (i.e. #tree behavior).
+ // @see text_field_widget()
+ // We cannot re-use #tree itself here, because form_builder() recursively
+ // takes over the parent element's #tree property automatically.
+ $tree = (isset($element['#format_tree']) ? $element['#format_tree'] : TRUE);
+
+ $format_parents = $element['#parents'];
+ if (!$tree) {
+ array_pop($format_parents);
+ }
+ $format_parents[] = 'format';
+ $element_id = drupal_html_id('edit-' . implode('-', $format_parents));
+
+ // Move this element into sub-element 'value'.
+ // Break references and remove this #process function to prevent
+ // form_builder() to recurse infinitely.
+ $element['value'] = (array) $element;
+ $process_key = array_search('filter_process_format', $element['value']['#process']);
+ unset($element['value']['#process'][$process_key]);
+ if ($tree) {
+ $element['value']['#parents'][] = 'value';
+ }
+
+ // Setup new child element.
+ $element['value']['#type'] = strtr($element['#type'], array('_format' => ''));
+ $element['value'] += element_info($element['value']['#type']);
+ // Description is handled by theme_text_format_wrapper().
+ unset($element['value']['#description']);
+ // Reset child's weight to ensure proper ordering.
+ $element['value']['#weight'] = 0;
+
+ // Turn this element into a text format wrapper.
+ $element['#type'] = 'markup';
+ $element['#theme_wrappers'] = array('filter_format_wrapper');
+ $element['#attached']['js'][] = 'misc/form.js';
+ $element['#attached']['css'][] = drupal_get_path('module', 'filter') . '/filter.css';
+
+ // Add text format selector widget.
+ $element['format']['#type'] = 'fieldset';
+ $element['format'] += element_info($element['format']['#type']);
+ $element['format']['#attributes'] = array('class' => array('filter-wrapper'));
- // Get a list of formats that the current user has access to.
- $formats = filter_formats($user);
-
- drupal_add_js('misc/form.js');
- drupal_add_css(drupal_get_path('module', 'filter') . '/filter.css');
- $element_id = drupal_html_id('edit-' . implode('-', $parents));
-
- $form = array(
- '#type' => 'fieldset',
- '#weight' => $weight,
- '#attributes' => array('class' => array('filter-wrapper')),
- );
- $form['format_guidelines'] = array(
+ $element['format']['format_guidelines'] = array(
'#prefix' => '',
'#suffix' => '
',
- '#weight' => 2,
+ '#weight' => 20,
);
+ // Get a list of formats that the current user has access to.
+ $formats = filter_formats($user);
foreach ($formats as $format) {
$options[$format->format] = $format->name;
- $form['format_guidelines'][$format->format] = array(
- '#markup' => theme('filter_guidelines', array('format' => $format)),
+ $element['format']['format_guidelines'][$format->format] = array(
+ '#theme' => 'filter_guidelines',
+ '#format' => $format,
);
}
- $form['format'] = array(
+ // Use the default format for this user if none was selected.
+ if (empty($element['#format'])) {
+ $element['#format'] = filter_format_default($user);
+ }
+ $element['format']['format'] = array(
'#type' => 'select',
'#title' => t('Text format'),
'#options' => $options,
- '#default_value' => $selected_format,
- '#parents' => $parents,
+ '#default_value' => $element['#format'],
'#access' => count($formats) > 1,
- '#id' => $element_id,
+ '#weight' => 10,
'#attributes' => array('class' => array('filter-list')),
+ '#parents' => $format_parents,
);
- $form['format_help'] = array(
+
+ $element['format']['format_help'] = array(
'#prefix' => '',
- '#markup' => theme('filter_tips_more_info'),
+ '#theme' => 'filter_tips_more_info',
'#suffix' => '
',
- '#weight' => 1,
+ '#weight' => 0,
);
- return $form;
+ return $element;
+}
+
+/**
+ * Theme a text format form element.
+ *
+ * @param $variables
+ * An associative array containing:
+ * - element: An associative array containing the properties of the element.
+ * Properties used: #children, #description
+ *
+ * @return
+ * A string representing the form element.
+ *
+ * @ingroup themeable
+ */
+function theme_filter_format_wrapper($variables) {
+ $element = $variables['element'];
+ $output = '';
+ $output .= $element['#children'];
+ if (!empty($element['#description'])) {
+ $output .= '
' . $element['#description'] . '
';
+ }
+ $output .= "
\n";
+
+ return $output;
}
/**
Index: modules/filter/filter.test
===================================================================
RCS file: /cvs/drupal/drupal/modules/filter/filter.test,v
retrieving revision 1.46
diff -u -p -r1.46 filter.test
--- modules/filter/filter.test 13 Oct 2009 15:39:41 -0000 1.46
+++ modules/filter/filter.test 18 Oct 2009 03:32:57 -0000
@@ -496,8 +496,8 @@ class FilterDefaultFormatTestCase extend
// Check that each user's default format is the lowest weighted format that
// the user has access to.
- $this->assertEqual(filter_default_format($first_user), $first_format->format, t("The first user's default format is the lowest weighted format that the user has access to."));
- $this->assertEqual(filter_default_format($second_user), $second_format->format, t("The second user's default format is the lowest weighted format that the user has access to, and is different than the first user's."));
+ $this->assertEqual(filter_format_default($first_user), $first_format->format, t("The first user's default format is the lowest weighted format that the user has access to."));
+ $this->assertEqual(filter_format_default($second_user), $second_format->format, t("The second user's default format is the lowest weighted format that the user has access to, and is different than the first user's."));
// Reorder the two formats, and check that both users now have the same
// default.
@@ -505,7 +505,7 @@ class FilterDefaultFormatTestCase extend
$edit['formats[' . $second_format->format . '][weight]'] = $minimum_weight - 3;
$this->drupalPost('admin/config/content/formats', $edit, t('Save changes'));
$this->resetFilterCaches();
- $this->assertEqual(filter_default_format($first_user), filter_default_format($second_user), t('After the formats are reordered, both users have the same default format.'));
+ $this->assertEqual(filter_format_default($first_user), filter_format_default($second_user), t('After the formats are reordered, both users have the same default format.'));
}
/**
Index: modules/profile/profile.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/profile/profile.module,v
retrieving revision 1.281
diff -u -p -r1.281 profile.module
--- modules/profile/profile.module 1 Nov 2009 21:26:44 -0000 1.281
+++ modules/profile/profile.module 6 Nov 2009 23:59:00 -0000
@@ -280,7 +280,7 @@ function profile_view_field($account, $f
if (isset($account->{$field->name}) && $value = $account->{$field->name}) {
switch ($field->type) {
case 'textarea':
- return check_markup($value, filter_default_format($account), '', TRUE);
+ return check_markup($value, filter_format_default($account), '', TRUE);
case 'textfield':
case 'selection':
return $browse ? l($value, 'profile/' . $field->name . '/' . $value) : check_plain($value);
Index: modules/simpletest/drupal_web_test_case.php
===================================================================
RCS file: /cvs/drupal/drupal/modules/simpletest/drupal_web_test_case.php,v
retrieving revision 1.168
diff -u -p -r1.168 drupal_web_test_case.php
--- modules/simpletest/drupal_web_test_case.php 2 Nov 2009 03:12:05 -0000 1.168
+++ modules/simpletest/drupal_web_test_case.php 6 Nov 2009 23:59:00 -0000
@@ -728,7 +728,7 @@ class DrupalWebTestCase extends DrupalTe
// Merge body field value and format separately.
$body = array(
'value' => $this->randomName(32),
- 'format' => filter_default_format(),
+ 'format' => filter_format_default(),
);
$langcode = !empty($settings['language']) ? $settings['language'] : FIELD_LANGUAGE_NONE;
$settings['body'][$langcode][0] += $body;
Index: modules/system/system.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/system/system.module,v
retrieving revision 1.836
diff -u -p -r1.836 system.module
--- modules/system/system.module 3 Nov 2009 06:47:23 -0000 1.836
+++ modules/system/system.module 6 Nov 2009 23:59:01 -0000
@@ -350,7 +350,7 @@ function system_element_info() {
'#size' => 60,
'#maxlength' => 128,
'#autocomplete_path' => FALSE,
- '#process' => array('form_process_text_format', 'ajax_process_form'),
+ '#process' => array('ajax_process_form'),
'#theme' => 'textfield',
'#theme_wrappers' => array('form_element'),
);
@@ -372,7 +372,7 @@ function system_element_info() {
'#cols' => 60,
'#rows' => 5,
'#resizable' => TRUE,
- '#process' => array('form_process_text_format', 'ajax_process_form'),
+ '#process' => array('ajax_process_form'),
'#theme' => 'textarea',
'#theme_wrappers' => array('form_element'),
);