6 * Defines simple text field types.
10 * Implementation of hook_theme().
12 function text_theme() {
14 'text_textarea' => array(
15 'arguments' => array('element' => NULL
),
17 'text_textfield' => array(
18 'arguments' => array('element' => NULL
),
20 'text_formatter_default' => array(
21 'arguments' => array('element' => NULL
),
23 'text_formatter_plain' => array(
24 'arguments' => array('element' => NULL
),
26 'text_formatter_trimmed' => array(
27 'arguments' => array('element' => NULL
),
29 'text_formatter_foo' => array(
30 'arguments' => array('element' => NULL
),
36 * Implementation of hook_field_info().
38 function text_field_info() {
42 'description' => t('Store text in the database.'),
43 // 'content_icon' => 'icon_content_text.png',
49 * Implementation of hook_field_settings().
51 function text_field_settings($op, $field) {
55 $options = array(0 => t('Plain text'), 1 => t('Filtered text (user selects input format)'));
56 $form['text_processing'] = array(
58 '#title' => t('Text processing'),
59 '#default_value' => is_numeric($field['text_processing']) ?
$field['text_processing'] : 0,
60 '#options' => $options,
62 $form['max_length'] = array(
63 '#type' => 'textfield',
64 '#title' => t('Maximum length'),
65 '#default_value' => is_numeric($field['max_length']) ?
$field['max_length'] : '',
67 '#element_validate' => array('_element_validate_integer_positive'),
68 '#description' => t('The maximum length of the field in characters. Leave blank for an unlimited size.'),
70 $form['allowed_values_fieldset'] = array(
71 '#type' => 'fieldset',
72 '#title' => t('Allowed values'),
73 '#collapsible' => TRUE
,
76 $form['allowed_values_fieldset']['allowed_values'] = array(
77 '#type' => 'textarea',
78 '#title' => t('Allowed values list'),
79 '#default_value' => !empty($field['allowed_values']) ?
$field['allowed_values'] : '',
82 '#description' => t('The possible values this field can contain. Enter one value per line, in the format key|label. The key is the value that will be stored in the database, and it must match the field storage type (%type). The label is optional, and the key will be used as the label if no label is specified.<br />Allowed HTML tags: @tags', array('%type' => $field['type'], '@tags' => _content_filter_xss_display_allowed_tags())),
84 $form['allowed_values_fieldset']['advanced_options'] = array(
85 '#type' => 'fieldset',
86 '#title' => t('PHP code'),
87 '#collapsible' => TRUE
,
88 '#collapsed' => empty($field['allowed_values_php']),
90 if (user_access('Use PHP input for field settings (dangerous - grant with care)')) {
91 $form['allowed_values_fieldset']['advanced_options']['allowed_values_php'] = array(
92 '#type' => 'textarea',
93 '#title' => t('Code'),
94 '#default_value' => !empty($field['allowed_values_php']) ?
$field['allowed_values_php'] : '',
96 '#description' => t('Advanced usage only: PHP code that returns a keyed array of allowed values. Should not include <?php ?> delimiters. If this field is filled out, the array returned by this code will override the allowed values list above.'),
100 $form['allowed_values_fieldset']['advanced_options']['markup_allowed_values_php'] = array(
102 '#title' => t('Code'),
103 '#value' => !empty($field['allowed_values_php']) ?
'<code>'.
check_plain($field['allowed_values_php']) .
'</code>' : t('<none>'),
104 '#description' => empty($field['allowed_values_php']) ?
t("You're not allowed to input PHP code.") : t('This PHP code was set by an administrator and will override the allowed values list above.'),
110 return array('text_processing', 'max_length', 'allowed_values', 'allowed_values_php');
112 case
'database columns':
113 if (empty($field['max_length']) || $field['max_length'] > 255) {
114 $columns['value'] = array('type' => 'text', 'size' => 'big', 'not null' => FALSE
, 'sortable' => TRUE
, 'views' => TRUE
);
117 $columns['value'] = array('type' => 'varchar', 'length' => $field['max_length'], 'not null' => FALSE
, 'sortable' => TRUE
, 'views' => TRUE
);
119 if (!empty($field['text_processing'])) {
120 $columns['format'] = array('type' => 'int', 'unsigned' => TRUE
, 'not null' => FALSE
, 'views' => FALSE
);
125 $allowed_values = content_allowed_values($field);
126 if (count($allowed_values)) {
127 $data = content_views_field_views_data($field);
128 $db_info = content_database_info($field);
129 $table_alias = content_views_tablename($field);
131 // Filter: Add a 'many to one' filter.
132 $copy = $data[$table_alias][$field['field_name'] .
'_value'];
133 $copy['title'] = t('@label (!name) - Allowed values', array('@label' => t($field['widget']['label']), '!name' => $field['field_name']));
134 $copy['filter']['handler'] = 'content_handler_filter_many_to_one';
135 unset($copy['field'], $copy['argument'], $copy['sort']);
136 $data[$table_alias][$field['field_name'] .
'_value_many_to_one'] = $copy;
137 // Argument : swap the handler to the 'many to one' operator.
138 $data[$table_alias][$field['field_name'] .
'_value']['argument']['handler'] = 'content_handler_argument_many_to_one';
145 * Implementation of hook_field().
147 function text_field($op, &$node, $field, &$items, $teaser, $page) {
150 $allowed_values = content_allowed_values($field);
151 if (is_array($items)) {
152 foreach ($items as
$delta => $item) {
153 $error_element = isset($item['_error_element']) ?
$item['_error_element'] : '';
154 if (is_array($item) && isset($item['_error_element'])) unset($item['_error_element']);
155 if (!empty($item['value'])) {
156 if (count($allowed_values) && !array_key_exists($item['value'], $allowed_values)) {
157 form_set_error($error_element, t('%name: illegal value.', array('%name' => t($field['widget']['label']))));
159 if (!empty($field['max_length']) && drupal_strlen($item['value']) > $field['max_length']) {
160 form_set_error($error_element, t('%name: the value may not be longer than %max characters.', array('%name' => $field['widget']['label'], '%max' => $field['max_length'])));
168 foreach ($items as
$delta => $item) {
169 if (!empty($field['text_processing'])) {
170 $check = is_null($node) || (isset($node->build_mode
) && $node->build_mode
== NODE_BUILD_PREVIEW
);
171 $text = isset($item['value']) ?
check_markup($item['value'], $item['format'], $check) : '';
174 $text = isset($item['value']) ?
check_plain($item['value']) : '';
176 $items[$delta]['safe'] = $text;
182 * Implementation of hook_content_is_empty().
184 function text_content_is_empty($item, $field) {
185 if (empty($item['value']) && (string)$item['value'] !== '0') {
192 * Implementation of hook_field_formatter_info().
194 function text_field_formatter_info() {
197 'label' => t('Default'),
198 'field types' => array('text'),
199 'multiple values' => CONTENT_HANDLE_CORE
,
202 'label' => t('Plain text'),
203 'field types' => array('text'),
204 'multiple values' => CONTENT_HANDLE_CORE
,
207 'label' => t('Trimmed'),
208 'field types' => array('text'),
209 'multiple values' => CONTENT_HANDLE_CORE
,
215 * Theme function for 'default' text field formatter.
217 function theme_text_formatter_default($element) {
218 return ($allowed =_text_allowed_values($element)) ?
$allowed : $element['#item']['safe'];
222 * Theme function for 'plain' text field formatter.
224 function theme_text_formatter_plain($element) {
225 return ($allowed =_text_allowed_values($element)) ?
$allowed : strip_tags($element['#item']['safe']);
229 * Theme function for 'trimmed' text field formatter.
231 function theme_text_formatter_trimmed($element) {
232 $field = content_fields($element['#field_name'], $element['#type_name']);
233 return ($allowed =_text_allowed_values($element)) ?
$allowed : node_teaser($element['#item']['safe'], $field['text_processing'] ?
$element['#item']['format'] : NULL
);
236 function _text_allowed_values($element) {
237 $field = content_fields($element['#field_name'], $element['#type_name']);
238 if (($allowed_values = content_allowed_values($field)) && isset($allowed_values[$element['#item']['value']])) {
239 return $allowed_values[$element['#item']['value']];
244 * Implementation of hook_widget_info().
246 * Here we indicate that the content module will handle
247 * the default value and multiple values for these widgets.
249 * Callbacks can be omitted if default handing is used.
250 * They're included here just so this module can be used
251 * as an example for custom modules that might do things
254 function text_widget_info() {
256 'text_textfield' => array(
257 'label' => t('Text field'),
258 'field types' => array('text'),
259 'multiple values' => CONTENT_HANDLE_CORE
,
260 'callbacks' => array(
261 'default value' => CONTENT_CALLBACK_DEFAULT
,
264 'text_textarea' => array(
265 'label' => t('Text area (multiple rows)'),
266 'field types' => array('text'),
267 'multiple values' => CONTENT_HANDLE_CORE
,
268 'callbacks' => array(
269 'default value' => CONTENT_CALLBACK_DEFAULT
,
276 * Implementation of FAPI hook_elements().
278 * Any FAPI callbacks needed for individual widgets can be declared here,
279 * and the element will be passed to those callbacks for processing.
281 * Drupal will automatically theme the element using a theme with
282 * the same name as the hook_elements key.
284 * Autocomplete_path is not used by text_widget but other widgets can use it
285 * (see nodereference and userreference).
287 function text_elements() {
289 'text_textfield' => array(
291 '#columns' => array('value'), '#delta' => 0,
292 '#process' => array('text_textfield_process'),
293 '#autocomplete_path' => FALSE
,
295 'text_textarea' => array(
297 '#columns' => array('value', 'format'), '#delta' => 0,
298 '#process' => array('text_textarea_process'),
299 '#filter_value' => FILTER_FORMAT_DEFAULT
,
305 * Implementation of hook_widget_settings().
307 function text_widget_settings($op, $widget) {
311 $rows = (isset($widget['rows']) && is_numeric($widget['rows'])) ?
$widget['rows'] : 5;
312 $size = (isset($widget['size']) && is_numeric($widget['size'])) ?
$widget['size'] : 60;
313 if ($widget['type'] == 'text_textfield') {
314 $form['rows'] = array('#type' => 'hidden', '#value' => $rows);
315 $form['size'] = array(
316 '#type' => 'textfield',
317 '#title' => t('Size of textfield'),
318 '#default_value' => $size,
319 '#element_validate' => array('_element_validate_integer_positive'),
324 $form['rows'] = array(
325 '#type' => 'textfield',
326 '#title' => t('Rows'),
327 '#default_value' => $rows,
328 '#element_validate' => array('_element_validate_integer_positive'),
331 $form['size'] = array('#type' => 'hidden', '#value' => $size);
336 return array('rows', 'size');
341 * Implementation of hook_widget().
343 * Attach a single form element to the form. It will be built out and
344 * validated in the callback(s) listed in hook_elements. We build it
345 * out in the callbacks rather than here in hook_widget so it can be
346 * plugged into any module that can provide it with valid
347 * $field information.
349 * Content module will set the weight, field name and delta values
350 * for each form element. This is a change from earlier CCK versions
351 * where the widget managed its own multiple values.
353 * If there are multiple values for this field, the content module will
354 * call this function as many times as needed.
357 * the entire form array, $form['#node'] holds node information
359 * the form_state, $form_state['values'][$field['field_name']]
360 * holds the field's form values.
364 * array of default values for this field
366 * the order of this item in the array of subelements (0, 1, 2, etc)
369 * the form item for a single element for this field
371 function text_widget(&$form, &$form_state, $field, $items, $delta = 0) {
373 '#type' => $field['widget']['type'],
374 '#default_value' => isset($items[$delta]) ?
$items[$delta] : '',
380 * Process an individual element.
382 * Build the form element. When creating a form using FAPI #process,
383 * note that $element['#value'] is already set.
385 * The $fields array is in $form['#field_info'][$element['#field_name']].
387 function text_textfield_process($element, $edit, $form_state, $form) {
388 $field = $form['#field_info'][$element['#field_name']];
389 $field_key = $element['#columns'][0];
390 $delta = $element['#delta'];
391 $element[$field_key] = array(
392 '#type' => 'textfield',
393 '#default_value' => isset($element['#value'][$field_key]) ?
$element['#value'][$field_key] : NULL
,
394 '#autocomplete_path' => $element['#autocomplete_path'],
395 '#size' => !empty($field['widget']['size']) ?
$field['widget']['size'] : 60,
396 '#attributes' => array('class' => 'text'),
397 // The following values were set by the content module and need
398 // to be passed down to the nested element.
399 '#title' => $element['#title'],
400 '#description' => $element['#description'],
401 '#required' => $element['#required'],
402 '#field_name' => $element['#field_name'],
403 '#type_name' => $element['#type_name'],
404 '#delta' => $element['#delta'],
405 '#columns' => $element['#columns'],
408 $element[$field_key]['#maxlength'] = !empty($field['max_length']) ?
$field['max_length'] : NULL
;
410 if (!empty($field['text_processing'])) {
411 $filter_key = $element['#columns'][1];
412 $format = isset($element['#value'][$filter_key]) ?
$element['#value'][$filter_key] : FILTER_FORMAT_DEFAULT
;
413 $parents = array_merge($element['#parents'] , array($filter_key));
414 $element[$filter_key] = filter_form($format, 1, $parents);
417 // Used so that hook_field('validate') knows where to flag an error.
418 $element['_error_element'] = array(
420 '#value' => implode('][', array_merge($element['#parents'], array($field_key))),
427 * Process an individual element.
429 * Build the form element. When creating a form using FAPI #process,
430 * note that $element['#value'] is already set.
432 * The $fields array is in $form['#field_info'][$element['#field_name']].
434 function text_textarea_process($element, $edit, $form_state, $form) {
435 $field = $form['#field_info'][$element['#field_name']];
436 $field_key = $element['#columns'][0];
437 $element[$field_key] = array(
438 '#type' => 'textarea',
439 '#default_value' => isset($element['#value'][$field_key]) ?
$element['#value'][$field_key] : NULL
,
440 '#rows' => !empty($field['widget']['rows']) ?
$field['widget']['rows'] : 10,
442 // The following values were set by the content module and need
443 // to be passed down to the nested element.
444 '#title' => $element['#title'],
445 '#description' => $element['#description'],
446 '#required' => $element['#required'],
447 '#field_name' => $element['#field_name'],
448 '#type_name' => $element['#type_name'],
449 '#delta' => $element['#delta'],
450 '#columns' => $element['#columns'],
453 if (!empty($field['text_processing'])) {
454 $filter_key = (count($element['#columns']) == 2) ?
$element['#columns'][1] : 'format';
455 $format = isset($element['#value'][$filter_key]) ?
$element['#value'][$filter_key] : FILTER_FORMAT_DEFAULT
;
456 $parents = array_merge($element['#parents'] , array($filter_key));
457 $element[$filter_key] = filter_form($format, 1, $parents);
460 // Used so that hook_field('validate') knows where to flag an error.
461 $element['_error_element'] = array(
463 '#value' => implode('][', array_merge($element['#parents'], array($field_key))),
470 * FAPI theme for an individual text elements.
472 * The textfield or textarea is already rendered by the
473 * textfield or textarea themes and the html output
474 * lives in $element['#children']. Override this theme to
475 * make custom changes to the output.
477 * $element['#field_name'] contains the field name
478 * $element['#delta] is the position of this element in the group
480 function theme_text_textfield($element) {
481 return $element['#children'];
484 function theme_text_textarea($element) {
485 return $element['#children'];