Simpletest Coverage - modules/field/modules/text/text.module

1 <?php
2 // $Id: text.module,v 1.17 2009/08/04 06:38:56 webchick Exp $
3
4 /**
5 * @file
6 * Defines simple text field types.
7 */
8
9 /**
10 * Implement hook_theme().
11 */
12 function text_theme() {
13 return array(
14 'text_textarea' => array(
15 'arguments' => array('element' => NULL),
16 ),
17 'text_textarea_with_summary' => array(
18 'arguments' => array('element' => NULL),
19 ),
20 'text_textfield' => array(
21 'arguments' => array('element' => NULL),
22 ),
23 'field_formatter_text_default' => array(
24 'arguments' => array('element' => NULL),
25 ),
26 'field_formatter_text_plain' => array(
27 'arguments' => array('element' => NULL),
28 ),
29 'field_formatter_text_trimmed' => array(
30 'arguments' => array('element' => NULL),
31 ),
32 'field_formatter_text_summary_or_trimmed' => array(
33 'arguments' => array('element' => NULL),
34 ),
35 );
36 }
37
38 /**
39 * Implement hook_field_info().
40 *
41 * Field settings:
42 * - max_length: the maximum length for a varchar field.
43 * Instance settings:
44 * - text_processing: whether text input filters should be used.
45 * - display_summary: whether the summary field should be displayed.
46 * When empty and not displayed the summary will take its value from the
47 * trimmed value of the main text field.
48 */
49 function text_field_info() {
50 return array(
51 'text' => array(
52 'label' => t('Text'),
53 'description' => t('This field stores varchar text in the database.'),
54 'settings' => array('max_length' => 255),
55 'instance_settings' => array('text_processing' => 0),
56 'default_widget' => 'text_textfield',
57 'default_formatter' => 'text_default',
58 ),
59 'text_long' => array(
60 'label' => t('Long text'),
61 'description' => t('This field stores long text in the database.'),
62 'settings' => array('max_length' => ''),
63 'instance_settings' => array('text_processing' => 0),
64 'default_widget' => 'text_textarea',
65 'default_formatter' => 'text_default',
66 ),
67 'text_with_summary' => array(
68 'label' => t('Long text and summary'),
69 'description' => t('This field stores long text in the database along with optional summary text.'),
70 'settings' => array('max_length' => ''),
71 'instance_settings' => array('text_processing' => 1, 'display_summary' => 0),
72 'default_widget' => 'text_textarea_with_summary',
73 'default_formatter' => 'text_summary_or_trimmed',
74 ),
75 );
76 }
77
78 /**
79 * Implement hook_field_schema().
80 */
81 function text_field_schema($field) {
82 switch ($field['type']) {
83 case 'text':
84 $columns = array(
85 'value' => array(
86 'type' => 'varchar',
87 'length' => $field['settings']['max_length'],
88 'not null' => FALSE,
89 ),
90 );
91 break;
92 case 'text_long':
93 $columns = array(
94 'value' => array(
95 'type' => 'text',
96 'size' => 'big',
97 'not null' => FALSE,
98 ),
99 );
100 break;
101 case 'text_with_summary':
102 $columns = array(
103 'value' => array(
104 'type' => 'text',
105 'size' => 'big',
106 'not null' => FALSE,
107 ),
108 'summary' => array(
109 'type' => 'text',
110 'size' => 'big',
111 'not null' => FALSE,
112 ),
113 );
114 break;
115 }
116 $columns += array(
117 'format' => array(
118 'type' => 'int',
119 'unsigned' => TRUE,
120 'not null' => FALSE,
121 ),
122 );
123 return array(
124 'columns' => $columns,
125 'indexes' => array(
126 'format' => array('format'),
127 ),
128 );
129 }
130
131 /**
132 * Implement hook_field_validate().
133 *
134 * Possible error codes:
135 * - 'text_value_max_length': The value exceeds the maximum length.
136 * - 'text_summary_max_length': The summary exceeds the maximum length.
137 */
138 function text_field_validate($obj_type, $object, $field, $instance, $items, &$errors) {
139 foreach ($items as $delta => $item) {
140 foreach (array('value' => t('full text'), 'summary' => t('summary')) as $column => $desc) {
141 if (!empty($item[$column])) {
142 if (!empty($field['settings']['max_length']) && drupal_strlen($item[$column]) > $field['settings']['max_length']) {
143 switch ($column) {
144 case 'value':
145 $message = t('%name: the text may not be longer than %max characters.', array('%name' => $instance['label'], '%max' => $field['settings']['max_length']));
146 break;
147 case 'summary':
148 $message = t('%name: the summary may not be longer than %max characters.', array('%name' => $instance['label'], '%max' => $field['settings']['max_length']));
149 break;
150 }
151 $errors[$field['field_name']][$delta][] = array(
152 'error' => "text_{$column}_length",
153 'message' => $message,
154 );
155 }
156 }
157 }
158 }
159 }
160
161 /**
162 * Implement hook_field_load().
163 *
164 * Where possible, generate the sanitized version of each field early so that
165 * it is cached in the field cache. This avoids looking up from the filter cache
166 * separately.
167 * @see text_field_sanitize().
168 */
169 function text_field_load($obj_type, $objects, $field, $instances, &$items) {
170 global $language;
171
172 foreach ($objects as $id => $object) {
173 foreach ($items[$id] as $delta => $item) {
174 if (!empty($instances[$id]['settings']['text_processing'])) {
175 // Only process items with a cacheable format, the rest will be
176 // handled by text_field_sanitize().
177 $format = $item['format'];
178 if (filter_format_allowcache($format)) {
179 $lang = isset($object->language) ? $object->language : $language->language;
180 $items[$id][$delta]['safe'] = isset($item['value']) ? check_markup($item['value'], $format, $lang, FALSE, FALSE) : '';
181 if ($field['type'] == 'text_with_summary') {
182 $items[$id][$delta]['safe_summary'] = isset($item['summary']) ? check_markup($item['summary'], $format, $lang, FALSE, FALSE) : '';
183 }
184 }
185 }
186 else {
187 $items[$id][$delta]['safe'] = check_plain($item['value']);
188 if ($field['type'] == 'text_with_summary') {
189 $items[$id][$delta]['safe_summary'] = check_plain($item['summary']);
190 }
191 }
192 }
193 }
194 }
195
196 /**
197 * Implement hook_field_sanitize().
198 *
199 * @see text_field_load()
200 */
201 function text_field_sanitize($obj_type, $object, $field, $instance, &$items) {
202 global $language;
203 foreach ($items as $delta => $item) {
204 // Only sanitize items which were not already processed inside
205 // text_field_load(), i.e. items with uncacheable text formats, or coming
206 // from a form preview.
207 if (!isset($items[$delta]['safe'])) {
208 if (!empty($instance['settings']['text_processing'])) {
209 $format = $item['format'];
210 $lang = isset($object->language) ? $object->language : $language->language;
211 $items[$delta]['safe'] = isset($item['value']) ? check_markup($item['value'], $format, $lang, FALSE) : '';
212 if ($field['type'] == 'text_with_summary') {
213 $items[$delta]['safe_summary'] = isset($item['summary']) ? check_markup($item['summary'], $format, $lang, FALSE) : '';
214 }
215 }
216 else {
217 $items[$delta]['safe'] = check_plain($item['value']);
218 if ($field['type'] == 'text_with_summary') {
219 $items[$delta]['safe_summary'] = check_plain($item['summary']);
220 }
221 }
222 }
223 }
224 }
225
226 /**
227 * Implement hook_field_is_empty().
228 */
229 function text_field_is_empty($item, $field) {
230 if (empty($item['value']) && (string)$item['value'] !== '0') {
231 return TRUE;
232 }
233 return FALSE;
234 }
235
236 /**
237 * Implement hook_field_formatter_info().
238 */
239 function text_field_formatter_info() {
240 return array(
241 'text_default' => array(
242 'label' => t('Default'),
243 'field types' => array('text', 'text_long', 'text_with_summary'),
244 ),
245 'text_plain' => array(
246 'label' => t('Plain text'),
247 'field types' => array('text', 'text_long', 'text_with_summary'),
248 ),
249
250 // The text_trimmed formatter displays the trimmed version of the
251 // full element of the field. It is intended to be used with text
252 // and text_long fields. It also works with text_with_summary
253 // fields though the text_summary_or_trimmed formatter makes more
254 // sense for that field type.
255 'text_trimmed' => array(
256 'label' => t('Trimmed'),
257 'field types' => array('text', 'text_long', 'text_with_summary'),
258 ),
259
260 // The 'summary or trimmed' field formatter for text_with_summary
261 // fields displays returns the summary element of the field or, if
262 // the summary is empty, the trimmed version of the full element
263 // of the field.
264 'text_summary_or_trimmed' => array(
265 'label' => t('Summary or trimmed'),
266 'field types' => array('text_with_summary'),
267 ),
268 );
269 }
270
271 /**
272 * Theme function for 'default' text field formatter.
273 */
274 function theme_field_formatter_text_default($element) {
275 return $element['#item']['safe'];
276 }
277
278 /**
279 * Theme function for 'plain' text field formatter.
280 */
281 function theme_field_formatter_text_plain($element) {
282 return strip_tags($element['#item']['safe']);
283 }
284
285 /**
286 * Theme function for 'trimmed' text field formatter.
287 */
288 function theme_field_formatter_text_trimmed($element) {
289 $field = field_info_field($element['#field_name']);
290 $instance = field_info_instance($element['#field_name'], $element['#bundle']);
291 return text_summary($element['#item']['safe'], $instance['settings']['text_processing'] ? $element['#item']['format'] : NULL);
292 }
293
294 /**
295 * Theme function for 'summary or trimmed' field formatter for
296 * text_with_summary fields. This formatter returns the summary
297 * element of the field or, if the summary is empty, the trimmed
298 * version of the full element of the field.
299 */
300 function theme_field_formatter_text_summary_or_trimmed($element) {
301 $field = field_info_field($element['#field_name']);
302 $instance = field_info_instance($element['#field_name'], $element['#bundle']);
303
304 if (!empty($element['#item']['safe_summary'])) {
305 return $element['#item']['safe_summary'];
306 }
307 else {
308 $size = variable_get('teaser_length_' . $element['#bundle'], 600);
309 return text_summary($element['#item']['safe'], $instance['settings']['text_processing'] ? $element['#item']['format'] : NULL, $size);
310 }
311 }
312
313 /**
314 * Generate a trimmed, formatted version of a text field value.
315 *
316 * If the end of the summary is not indicated using the <!--break--> delimiter
317 * then we generate the summary automatically, trying to end it at a sensible
318 * place such as the end of a paragraph, a line break, or the end of a
319 * sentence (in that order of preference).
320 *
321 * @param $text
322 * The content for which a summary will be generated.
323 * @param $format
324 * The format of the content.
325 * If the PHP filter is present and $text contains PHP code, we do not
326 * split it up to prevent parse errors.
327 * If the line break filter is present then we treat newlines embedded in
328 * $text as line breaks.
329 * If the htmlcorrector filter is present, it will be run on the generated
330 * summary (if different from the incoming $text).
331 * @param $size
332 * The desired character length of the summary. If omitted, the default
333 * value will be used. Ignored if the special delimiter is present
334 * in $text.
335 * @return
336 * The generated summary.
337 */
338 function text_summary($text, $format = NULL, $size = NULL) {
339
340 if (!isset($size)) {
341 // What used to be called 'teaser' is now called 'summary', but
342 // the variable 'teaser_length' is preserved for backwards compatibility.
343 $size = variable_get('teaser_length', 600);
344 }
345
346 // Find where the delimiter is in the body
347 $delimiter = strpos($text, '<!--break-->');
348
349 // If the size is zero, and there is no delimiter, the entire body is the summary.
350 if ($size == 0 && $delimiter === FALSE) {
351 return $text;
352 }
353
354 // If a valid delimiter has been specified, use it to chop off the summary.
355 if ($delimiter !== FALSE) {
356 return substr($text, 0, $delimiter);
357 }
358
359 // We check for the presence of the PHP evaluator filter in the current
360 // format. If the body contains PHP code, we do not split it up to prevent
361 // parse errors.
362 if (isset($format)) {
363 $filters = filter_list_format($format);
364 if (isset($filters['php/0']) && strpos($text, '<?') !== FALSE) {
365 return $text;
366 }
367 }
368
369 // If we have a short body, the entire body is the summary.
370 if (drupal_strlen($text) <= $size) {
371 return $text;
372 }
373
374 // If the delimiter has not been specified, try to split at paragraph or
375 // sentence boundaries.
376
377 // The summary may not be longer than maximum length specified. Initial slice.
378 $summary = truncate_utf8($text, $size);
379
380 // Store the actual length of the UTF8 string -- which might not be the same
381 // as $size.
382 $max_rpos = strlen($summary);
383
384 // How much to cut off the end of the summary so that it doesn't end in the
385 // middle of a paragraph, sentence, or word.
386 // Initialize it to maximum in order to find the minimum.
387 $min_rpos = $max_rpos;
388
389 // Store the reverse of the summary. We use strpos on the reversed needle and
390 // haystack for speed and convenience.
391 $reversed = strrev($summary);
392
393 // Build an array of arrays of break points grouped by preference.
394 $break_points = array();
395
396 // A paragraph near the end of sliced summary is most preferable.
397 $break_points[] = array('</p>' => 0);
398
399 // If no complete paragraph then treat line breaks as paragraphs.
400 $line_breaks = array('<br />' => 6, '<br>' => 4);
401 // Newline only indicates a line break if line break converter
402 // filter is present.
403 if (isset($filters['filter/1'])) {
404 $line_breaks["\n"] = 1;
405 }
406 $break_points[] = $line_breaks;
407
408 // If the first paragraph is too long, split at the end of a sentence.
409 $break_points[] = array('. ' => 1, '! ' => 1, '? ' => 1, '。' => 0, '؟ ' => 1);
410
411 // Iterate over the groups of break points until a break point is found.
412 foreach ($break_points as $points) {
413 // Look for each break point, starting at the end of the summary.
414 foreach ($points as $point => $offset) {
415 // The summary is already reversed, but the break point isn't.
416 $rpos = strpos($reversed, strrev($point));
417 if ($rpos !== FALSE) {
418 $min_rpos = min($rpos + $offset, $min_rpos);
419 }
420 }
421
422 // If a break point was found in this group, slice and stop searching.
423 if ($min_rpos !== $max_rpos) {
424 // Don't slice with length 0. Length must be <0 to slice from RHS.
425 $summary = ($min_rpos === 0) ? $summary : substr($summary, 0, 0 - $min_rpos);
426 break;
427 }
428 }
429
430 // If the htmlcorrector filter is present, apply it to the generated summary.
431 if (isset($filters['filter/3'])) {
432 $summary = _filter_htmlcorrector($summary);
433 }
434
435 return $summary;
436 }
437
438 /**
439 * Implement hook_field_widget_info().
440 *
441 * Here we indicate that the field module will handle
442 * the default value and multiple values for these widgets.
443 *
444 * Callbacks can be omitted if default handing is used.
445 * They're included here just so this module can be used
446 * as an example for custom modules that might do things
447 * differently.
448 */
449 function text_field_widget_info() {
450 return array(
451 'text_textfield' => array(
452 'label' => t('Text field'),
453 'field types' => array('text'),
454 'settings' => array('size' => 60),
455 ),
456 'text_textarea' => array(
457 'label' => t('Text area (multiple rows)'),
458 'field types' => array('text_long'),
459 'settings' => array('rows' => 5),
460 ),
461 'text_textarea_with_summary' => array(
462 'label' => t('Text area with a summary'),
463 'field types' => array('text_with_summary'),
464 'settings' => array('rows' => 20, 'summary_rows' => 5),
465 ),
466 );
467 }
468
469 /**
470 * Implement FAPI hook_elements().
471 *
472 * Any FAPI callbacks needed for individual widgets can be declared here,
473 * and the element will be passed to those callbacks for processing.
474 *
475 * Drupal will automatically theme the element using a theme with
476 * the same name as the hook_elements key.
477 *
478 * Autocomplete_path is not used by text_field_widget but other
479 * widgets can use it (see nodereference and userreference).
480 */
481 function text_elements() {
482 return array(
483 'text_textfield' => array(
484 '#input' => TRUE,
485 '#columns' => array('value'), '#delta' => 0,
486 '#process' => array('text_textfield_elements_process'),
487 '#theme_wrappers' => array('text_textfield'),
488 '#autocomplete_path' => FALSE,
489 ),
490 'text_textarea' => array(
491 '#input' => TRUE,
492 '#columns' => array('value', 'format'), '#delta' => 0,
493 '#process' => array('text_textarea_elements_process'),
494 '#theme_wrappers' => array('text_textarea'),
495 '#filter_value' => FILTER_FORMAT_DEFAULT,
496 ),
497 'text_textarea_with_summary' => array(
498 '#input' => TRUE,
499 '#columns' => array('value', 'format', 'summary'), '#delta' => 0,
500 '#process' => array('text_textarea_with_summary_process'),
501 '#theme_wrappers' => array('text_textarea_with_summary'),
502 '#filter_value' => FILTER_FORMAT_DEFAULT,
503 ),
504 );
505 }
506
507 /**
508 * Implement hook_field_widget().
509 *
510 * Attach a single form element to the form. It will be built out and
511 * validated in the callback(s) listed in hook_elements. We build it
512 * out in the callbacks rather than here in hook_field_widget so it can be
513 * plugged into any module that can provide it with valid
514 * $field information.
515 *
516 * Field module will set the weight, field name and delta values
517 * for each form element.
518 *
519 * If there are multiple values for this field, the field module will
520 * call this function as many times as needed.
521 *
522 * @param $form
523 * the entire form array, $form['#node'] holds node information
524 * @param $form_state
525 * the form_state, $form_state['values'][$field['field_name']]
526 * holds the field's form values.
527 * @param $field
528 * The field structure.
529 * @param $instance
530 * the field instance array
531 * @param $items
532 * array of default values for this field
533 * @param $delta
534 * the order of this item in the array of subelements (0, 1, 2, etc)
535 *
536 * @return
537 * the form item for a single element for this field
538 */
539 function text_field_widget(&$form, &$form_state, $field, $instance, $items, $delta = 0) {
540 $element = array(
541 '#type' => $instance['widget']['type'],
542 '#default_value' => isset($items[$delta]) ? $items[$delta] : '',
543 );
544 if (!empty($instance['settings']['text_processing'])) {
545 $element['#value_callback'] = 'text_field_widget_formatted_text_value';
546 }
547
548 return $element;
549 }
550
551 /**
552 * Implement hook_field_widget_error().
553 */
554 function text_field_widget_error($element, $error) {
555 switch ($error['error']) {
556 case 'text_summary_max_length':
557 $error_element = $element[$element['#columns'][1]];
558 break;
559
560 default:
561 $error_element = $element[$element['#columns'][0]];
562 break;
563 }
564
565 form_error($error_element, $error['message']);
566 }
567
568 /**
569 * Process an individual element.
570 *
571 * Build the form element. When creating a form using FAPI #process,
572 * note that $element['#value'] is already set.
573 *
574 * The $field and $instance arrays are in $form['#fields'][$element['#field_name']].
575 *
576 * TODO: For widgets to be actual FAPI 'elements', reusable outside of a
577 * 'field' context, they shoudn't rely on $field and $instance. The bits of
578 * information needed to adjust the behavior of the 'element' should be
579 * extracted in hook_field_widget() above.
580 */
581 function text_textfield_elements_process($element, $form_state, $form) {
582 $field = $form['#fields'][$element['#field_name']]['field'];
583 $instance = $form['#fields'][$element['#field_name']]['instance'];
584 $field_key = $element['#columns'][0];
585 $delta = $element['#delta'];
586
587 $element[$field_key] = array(
588 '#type' => 'textfield',
589 '#default_value' => isset($element['#value'][$field_key]) ? $element['#value'][$field_key] : NULL,
590 '#autocomplete_path' => $element['#autocomplete_path'],
591 '#size' => $instance['widget']['settings']['size'],
592 '#attributes' => array('class' => 'text'),
593 '#title' => $element['#title'],
594 '#description' => $element['#description'],
595 '#required' => $element['#required'],
596 );
597
598 $element[$field_key]['#maxlength'] = !empty($field['settings']['max_length']) ? $field['settings']['max_length'] : NULL;
599
600 if (!empty($instance['settings']['text_processing'])) {
601 $filter_key = (count($element['#columns']) == 2) ? $element['#columns'][1] : 'format';
602 $format = isset($element['#value'][$filter_key]) ? $element['#value'][$filter_key] : FILTER_FORMAT_DEFAULT;
603 $element[$field_key]['#text_format'] = $format;
604 }
605
606 return $element;
607 }
608
609 /**
610 * Process an individual element.
611 *
612 * Build the form element. When creating a form using FAPI #process,
613 * note that $element['#value'] is already set.
614 *
615 * The $field and $instance arrays are in $form['#fields'][$element['#field_name']].
616 */
617 function text_textarea_elements_process($element, $form_state, $form) {
618 $field = $form['#fields'][$element['#field_name']]['field'];
619 $instance = $form['#fields'][$element['#field_name']]['instance'];
620 $field_key = $element['#columns'][0];
621 $delta = $element['#delta'];
622
623 $element[$field_key] = array(
624 '#type' => 'textarea',
625 '#default_value' => isset($element['#value'][$field_key]) ? $element['#value'][$field_key] : NULL,
626 '#rows' => $instance['widget']['settings']['rows'],
627 '#weight' => 0,
628 '#title' => $element['#title'],
629 '#description' => $element['#description'],
630 '#required' => $element['#required'],
631 );
632
633 if (!empty($instance['settings']['text_processing'])) {
634 $filter_key = (count($element['#columns']) == 2) ? $element['#columns'][1] : 'format';
635 $format = isset($element['#value'][$filter_key]) ? $element['#value'][$filter_key] : FILTER_FORMAT_DEFAULT;
636 $element[$field_key]['#text_format'] = $format;
637 }
638
639 return $element;
640 }
641
642 /**
643 * Process an individual element.
644 *
645 * Build the form element. When creating a form using FAPI #process,
646 * note that $element['#value'] is already set.
647 *
648 * The $field and $instance arrays are in $form['#fields'][$element['#field_name']].
649 */
650 function text_textarea_with_summary_process($element, $form_state, $form) {
651 $field = $form['#fields'][$element['#field_name']]['field'];
652 $instance = $form['#fields'][$element['#field_name']]['instance'];
653 $delta = $element['#delta'];
654
655 $field_key = $element['#columns'][1];
656 $display = !empty($element['#value'][$field_key]) || !empty($instance['settings']['display_summary']);
657 $element[$field_key] = array(
658 '#title' => t('Summary'),
659 '#type' => $display ? 'textarea' : 'value',
660 '#default_value' => isset($element['#value'][$field_key]) ? $element['#value'][$field_key] : NULL,
661 '#rows' => $instance['widget']['settings']['summary_rows'],
662 '#weight' => 0,
663 '#title' => t('Summary'),
664 '#description' => t('Leave blank to use trimmed value of full text as the summary.'),
665 '#required' => $element['#required'],
666 '#display' => $display,
667 );
668
669 $field_key = $element['#columns'][0];
670 $element[$field_key] = array(
671 '#type' => 'textarea',
672 '#default_value' => isset($element['#value'][$field_key]) ? $element['#value'][$field_key] : NULL,
673 '#rows' => $instance['widget']['settings']['rows'],
674 '#weight' => 1,
675 '#title' => $display ? t('Full text') : $element['#title'],
676 '#description' => $element['#description'],
677 '#required' => $element['#required'],
678 '#required' => $instance['required'],
679 );
680
681 if (!empty($instance['settings']['text_processing'])) {
682 $filter_key = (count($element['#columns']) == 2) ? $element['#columns'][1] : 'format';
683 $format = isset($element['#value'][$filter_key]) ? $element['#value'][$filter_key] : FILTER_FORMAT_DEFAULT;
684 $element[$field_key]['#text_format'] = $format;
685 }
686
687 return $element;
688 }
689
690 /**
691 * Helper function to determine the value for a formatted text widget.
692 *
693 * '#text_format' puts the format in '[column 0]_format' in incoming values,
694 * while we need it in '[column 1]'.
695 */
696 function text_field_widget_formatted_text_value($form, $edit = FALSE) {
697 if ($edit !== FALSE) {
698 $field_key = $form['#columns'][0];
699 $filter_key = (count($form['#columns']) == 2) ? $form['#columns'][1] : 'format';
700 $default_key = $field_key . '_format';
701 // The format selector uses #access = FALSE if only one format is
702 // available. In this case, we don't receive its value, and need to
703 // manually set it.
704 $edit['format'] = !empty($edit[$default_key]) ? $edit[$default_key] : filter_resolve_format(FILTER_FORMAT_DEFAULT);
705 unset($edit[$default_key]);
706 return $edit;
707 }
708 }
709
710 /**
711 * FAPI theme for an individual text elements.
712 *
713 * The textfield or textarea is already rendered by the
714 * textfield or textarea themes and the html output
715 * lives in $element['#children']. Override this theme to
716 * make custom changes to the output.
717 *
718 * $element['#field_name'] contains the field name
719 * $element['#delta] is the position of this element in the group
720 */
721 function theme_text_textfield($element) {
722 return $element['#children'];
723 }
724
725 function theme_text_textarea($element) {
726 return $element['#children'];
727 }
728
729 function theme_text_textarea_with_summary($element) {
730 // If displaying both a textarea and a summary field, wrap them
731 // in a fieldset to make it clear they belong together.
732 $field_key = $element['#columns'][1];
733 if (!empty($element[$field_key]['#display'])) {
734 $fieldset = array(
735 '#title' => $element['#title'],
736 '#value' => $element['#children'],
737 '#attributes' => array('class' => 'text-textarea'),
738 '#id' => str_replace('_', '-', $element['#field_name']) . '-summary-wrapper',
739 );
740 return theme('fieldset', $fieldset);
741 }
742 else {
743 return $element['#children'];
744 }
745 }
746
747

Legend

Missed
lines code that were not excersized during program execution.
Covered
lines code were excersized during program execution.
Comment/non executable
Comment or non-executable line of code.
Dead
lines of code that according to xdebug could not be executed. This is counted as coverage code because in almost all cases it is code that runnable.