Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Apress.Pro.Drupal.7.Development.3rd.Edition.Dec.2010.pdf
Скачиваний:
74
Добавлен:
14.03.2016
Размер:
13 Мб
Скачать
☆

CHAPTER 8 ■ WORKING WITH FIELDS

set the cardinality or number of values that can be created—our requirements call for only one value, whether there will be a “from” and “to” date, the granularity of the date and time, and the ability to override whether Drupal should covert the time entered when it is displayed based on various options. For the Event date, I’ll leave all of the values set to their default value and will save the field by clicking the “Save settings” button. I now have all of the required fields for the Event content type and

can begin authoring Events using the node creation form, as shown in Figure 8-7.

Figure 8-7. Creating a new Event

■ Note At the time the book was authored, the Date module was going through major rework due to changes to Drupal core. I suggest you check http://drupal.org/project/date for any updates to the approach or forms used to configure a date field.

Creating a Custom Field

Drupal 7 core comes with several generic field types that you can use for a wide variety of purposes. You can use the predefined field types to capture, store, and display values for a wide variety of purposes, but there may be instances where the standard field types (see Table 8-1) just don’t meet your needs. That’s

169

Download from Wow! eBook <www.wowebook.com>

CHAPTER 8 ■ WORKING WITH FIELDS

where the Field API comes into play, enabling the creation of custom field types that can be used in any content type created on your site.

Table 8-1. Standard Field Types in Drupal 7 Core

Field type

Usage

Boolean

Used to collect true/false values using check boxes or radio buttons

Decimal

Used to collect numeric values that include a decimal point

File

Provides a file upload field that allows authors to attach a file to an instance of your

 

content type

Float

Provides a text field for capturing numbers that contain decimal points

Image

Provides an image upload field that allows authors to attach images to an instance of

 

your content type

Integer

Provides a text field that an author can enter an integer value into

List

Provides the ability to create a select list (drop-down or a list of values to select from)

List (numeric)

or check boxes/radio buttons that allow a user to select one or more values from a

List (text)

number of predefined values

Long text

Provides a multi-line text area that authors can enter information into (as opposed to a

 

single line text box)

Long text and

Provides a multi-line text area and a multi-line summary area where an author can

summary

enter information

Term

Provides the ability to select a taxonomy term(s)

reference

 

Text

A simple text box

With the Field API, you have the ability to construct a custom field type for virtually any type of data input that you can think of. As an example, we will use the field type example from Drupal.org (http://api.drupal.org/api/drupal/developer--examples--color_example--color_example.module/7), which defines a custom field that renders text in a color specified in the field settings for that field type. We’ll use that field type to capture and display the color that event participants should wear when they attend an upcoming event.

The first step is to create a new directory named color_example in sites/all/modules/custom. In that directory, create a new file named color_example.info and place the following content into the

.info file.

170

CHAPTER 8 ■ WORKING WITH FIELDS

name = Color Example

description = "Creates a custom field for inputting and displaying text in a colorful fashion."

package = Pro Drupal Development core = 7.x

files[] = color_example.module php = 5.2

Next create another file named color_example.module and place the following content into that file.

<?php

/**

*@file

*An example field using the Field API.

*/

Save the files and enable the module. We are now ready to construct the details of the new RGB field type.

The first step is to call hook_field_info(), which defines the basic attributes of our new field. We define the field as color_example_rgb() and assign a label, description, default widget, and default formatter to the new field type.

/**

*Implements hook_field_info().

*Provides the description of the field.

*/

function color_example_field_info() { return array(

'color_example_rgb' => array( 'label' => t('Example Color RGB'),

'description' => t('Demonstrates a field composed of an RGB color.'), 'default_widget' => 'color_example_3text',

'default_formatter' => 'color_example_simple_text',

),

);

}

The next step is to define how the data collected in the field will be stored in the Drupal database. Prior to Drupal 7 and the Field API, we would have had to define the tables and schema ourselves in the modules that defined our content type and the custom fields within that content type. In Drupal 7 with the Field API, that task is handled for us through hook_field_schema(). For our example, we’ll store a seven-character field that represents the HTML hex color code that we want to use to render the text on the screen—for example, using #FF0000 renders the text in red. In the example here, we create a single column that stores the RGB value entered by the site administrator when he or she assigns the field to a content type.

171

CHAPTER 8 ■ WORKING WITH FIELDS

/**

* Implements hook_field_schema(). */

function color_example_field_schema($field) { $columns = array(

'rgb' => array('type' => 'varchar', 'length' => 7, 'not null' => FALSE),

);

$indexes = array(

'rgb' => array('rgb'),

);

return array(

'columns' => $columns, 'indexes' => $indexes,

);

}

The next step is to validate the user’s input by using hook_field_validate(). I’ll tell Drupal to validate that the user entered a value that matches a pattern of a typical HTML color code using preg_match(). I’ll check to see that the first character is a # and the following six characters are either a numeric digit or an alpha character that is between “a” and “f.” If the value entered doesn’t match that pattern, I’ll display an error.

/**

*Implements hook_field_validate().

*Verifies that the RGB field as combined is valid

*(6 hex digits with a # at the beginning).

*/

function color_example_field_validate($entity_type, $entity, $field, $instance, $langcode, $items, &$errors) {

foreach($items as $delta => $item) { if(!empty($item['rgb'])) {

if(! preg_match('@^#[0-9a-f]{6}$@', $item['rgb'])) { $errors[$field['field_name']][$langcode][$delta][] = array(

'error' => 'color_example_invalid',

'message' => t('Color must be in the HTML format #abcdef.'),

);

}

}

}

}

The next function defines what constitutes an empty field of this type. In this case, we use the PHP empty function to return either true or false depending on whether the field is empty.

/**

* Implements hook_field_is_empty(). */

function color_example_field_is_empty($item, $field) { return empty($item['rgb']);

}

172

CHAPTER 8 ■ WORKING WITH FIELDS

1.Field formatters are functions that define how the contents of a field are displayed. The hook_field_formatter_info() function identifies the types of formatters that are used to display the text and background in our example.

/**

* Implements hook_field_formatter_info(). */

function color_example_field_formatter_info() { return array(

//This formatter just displays the hex value in the color indicated. 'color_example_simple_text' => array(

'label' => t('Simple text-based formatter'), 'field types' => array('color_example_rgb'),

),

//This formatter changes the background color of the content region. 'color_example_color_background' => array(

'label' => t('Change the background of the output text'), 'field types' => array('color_example_rgb'),

),

);

}

Next I’ll build the renderable output for each of the two formatters just defined:

1.color_example_simple_text just outputs markup indicating the color that was entered and uses an inline style to set the text color to that value.

2.color_example_color_background does the same but also changes the background color of div.region-content.

/**

* Implements hook_field_formatter_view(). */

function color_example_field_formatter_view($entity_type, $entity, $field, $instance, $langcode, $items, $display) {

$element = array();

switch ($display['type']) {

// This formatter simply outputs the field as text and with a color. case 'color_example_simple_text':

foreach ($items as $delta => $item) {

$element[$delta]['#markup'] = '<p style="color: ' . $item['rgb']. '">'

. t('The color for this event is @code', array('@code' => $item['rgb']))

. '</p>';

}

break;

173

CHAPTER 8 ■ WORKING WITH FIELDS

//This formatter adds css to the page changing the '.region-content' area's

//background color. If there are many fields, the last one will win.

case 'color_example_color_background': foreach ($items as $delta => $item) {

drupal_add_css('div.region-content { background-color:' . $item['rgb']

.';}', array('type' => 'inline') ); $element[$delta]['#markup'] = '<p>'

. t('The color for this event has been changed to @code', array('@code' => $item['rgb'])) . '</p>';

}

break;

}

return $element;

}

The next set of functions defines the widget that will be used to display the field on the node edit form. For the RGB field, I’ll create three different types of widgets that the site administrator can select from.

1.A simple text-only widget where the user enters the “#ffffff”

2.A three–text field widget that gathers the red, green, and blue values separately

3.A farbtastic colorpicker widget that chooses the value graphically

I’ll use the hook_field_widget_info() function to define the three widgets.

/**

* Implements hook_field_widget_info(). */

function color_example_field_widget_info() { return array(

'color_example_text' => array(

'label' => t('RGB value as #ffffff'), 'field types' => array('color_example_rgb'),

),

'color_example_3text' => array( 'label' => t('RGB text fields'),

'field types' => array('color_example_rgb'),

),

'color_example_colorpicker' => array( 'label' => t('Color Picker'),

'field types' => array('color_example_rgb'),

),

);

}

174

CHAPTER 8 ■ WORKING WITH FIELDS

The hook_widget_form() function defines the actual structure of how the widgets will be displayed to the user. Three different forms are provided, for the three widget types.

1.color_example_text provides a text box to enter the HTML color code (e.g., #FFFFFF)

2.color_example_colorpicker – is essentially the same as color_example_text , but color_example_colorpicker adds a JavaScript colorpicker helper.

3.color_example_3text displays three text fields, one each for red, green, and blue. However, the field type defines a single text column, rgb, which needs an HTML color code. Define an element validate handler that converts our r, g, and b fields into a simulated single “rgb” form element.

/**

* Implements hook_field_widget_form(). */

function color_example_field_widget_form(&$form, &$form_state, $field, $instance, $langcode, $items, $delta, $element) {

$value = isset($items[$delta]['rgb']) ? $items[$delta]['rgb'] : ''; $element += array(

'#delta' => $delta,

);

$element['rgb'] = array();

switch ($instance['widget']['type']) {

case 'color_example_colorpicker': $element['rgb'] += array(

'#suffix' => '<div class="field-example-colorpicker"></div>', '#attributes' => array('class' => array('edit-field-example-

colorpicker')),

'#attached' => array(

//Add Farbtastic color picker. 'library' => array(

array('system', 'farbtastic'),

),

//Add javascript to trigger the colorpicker.

'js' => array(drupal_get_path('module', 'color_example') . '/color_example.js'),

),

);

//DELIBERATE fall-through: From here on the color_example_text and

//color_example_colorpicker are exactly the same.

case 'color_example_text': $element['rgb'] += array(

'#title' => t('Event\’s RGB Color'), '#type' => 'textfield', '#default_value' => $value,

//Allow a slightly larger size than the field length to allow for some

//configurations where all characters won't fit in input field. '#size' => 7,

175

CHAPTER 8 ■ WORKING WITH FIELDS

'#maxlength' => 7,

);

break;

case 'color_example_3text':

//Convert rgb value into r, g, and b for #default_value. if (isset($items[$delta]['rgb'])) {

preg_match_all('@..@', substr($items[$delta]['rgb'], 1), $match);

}

else {

$match = array(array());

}

//A fieldset to hold the three text fields.

$element += array( '#type' => 'fieldset',

'#element_validate' => array('color_example_3text_validate'),

//The following is set so that the validation function will be able

//to access external value information that otherwise would be

//unavailable.

'#delta' => $delta, '#attached' => array(

'css' => array(drupal_get_path('module', 'color_example') . '/color_example.css'),

),

);

// Create a textfield for saturation values for Red, Green, and Blue. foreach (array('r' => t('Red'), 'g' => t('Green'), 'b' => t('Blue')) as $key

=> $title) {

$element[$key] = array( '#type' => 'textfield', '#title' => $title, '#size' => 2,

'#default_value' => array_shift($match[0]), '#attributes' => array('class' => array('rgb-entry')),

// '#description' => t('The 2-digit hexadecimal representation of the @color saturation, like "a1" or "ff"', array('@color' => $title)),

);

}

break;

}

return $element;

}

The next function defines the validations that will be performed against the data entered by the user.

/**

*Validate the individual fields and then convert them into a single HTML RGB

*value as text.

176

CHAPTER 8 ■ WORKING WITH FIELDS

*/

function color_example_3text_validate($element, &$form_state) { $delta = $element['#delta'];

$field = $form_state['field'][$element['#field_name']][$element['#language']]['field']; $field_name = $field['field_name'];

if (isset($form_state['values'][$field_name][$element['#language']][$delta])) { $values = $form_state['values'][$field_name][$element['#language']][$delta]; foreach (array('r', 'g', 'b') as $colorfield) {

$val = hexdec($values[$colorfield]);

//If they left any empty, we'll set the value empty and quit. if (strlen($values[$colorfield]) == 0) {

form_set_value($element, array('rgb' => NULL), $form_state); return;

}

//If they gave us anything that's not hex, reject it.

if ( (strlen($values[$colorfield]) != 2) || $val < 0 || $val > 255) { form_error($element[$colorfield], t("Saturation value must be a 2-digit hexadecimal

value between 00 and ff."));

}

}

$value = sprintf('#%02s%02s%02s', $values['r'], $values['g'], $values['b']); form_set_value($element, array('rgb' => $value), $form_state);

}

}

And lastly I’ll use hook_field_error() to display an error message when the user enters something incorrectly.

/**

* Implements hook_field_error(). */

function color_example_field_widget_error($element, $error, $form, &$form_state) { switch ($error['error']) {

case 'color_example_invalid': form_error($element, $error['message']); break;

}

}

The next file to create is the JavaScript file that provides a farbtastic colorpicker for the fancier widget. Create another file in the module directory named color_example.js and include the following code:

/**

*@file

*Javascript for Color Example.

*/

177

CHAPTER 8 ■ WORKING WITH FIELDS

/**

* Provide a farbtastic colorpicker for the fancier widget. */

(function ($) { Drupal.behaviors.color_example_colorpicker = {

attach: function(context) { $(".edit-field-example-colorpicker").live("focus", function(event) {

var edit_field = this;

var picker = $(this).closest('tr').find(".field-example-colorpicker");

// Hide all color pickers except this one. $(".field-example-colorpicker").hide(); $(picker).show();

$.farbtastic(picker, function(color) { edit_field.value = color;

}).setColor(edit_field.value); });

}

}

})(jQuery);

The last file required for the color example module is the CSS file. Create a new file named color_example.css and include the following CSS:

/**

*@file

*CSS for Color Example.

*/

div.form-item table .form-type-textfield, div.form-item table .form-type-textfield * {

display: inline-block;

}

After saving the module, the field is ready to add to a content type. I’ll add the color field to Event by navigating to Structure -> Content Types and clicking the Manage Fields tabfor the Event content type as shown in Figure 8-8.

Figure 8-8. Adding the new Event Color field

178

CHAPTER 8 ■ WORKING WITH FIELDS

After clicking the Save button, I am taken to the next field settings page, which shows that there aren’t any field settings assigned to the Event Color field (e.g., maximum length). Click the “Save settings” button to display the overall settings page for the Event (see Figure 8-9). There on this form, I’ll enter the help text I want displayed below the field on the form and the default color value that will be used when the node edit form is displayed. I’ll click the “Save settings” button to finish the process of adding the field to the node edit form for Events.

Figure 8-9. Setting the configuration options for the new Event Color field

With the field added to the Event content type, I’m ready to test it out. Navigating to Add content -> Event reveals the new Event’s RGB Color field on the form with the default value (see Figure 8-10).

179

Download from Wow! eBook <www.wowebook.com>

CHAPTER 8 ■ WORKING WITH FIELDS

Figure 8-10. The new Event RGB Color field on the node edit form

After saving the Event, the new field is displayed formatted as defined in the module’s formatter functions. The image in Figure 8-11 displays the text in the color defined when the node was created, which in the example I created is red.

Figure 8-11. The new field is displayed in the color defined by the author.

So far I’ve shown you how to use the standard Drupal field types to create a new content type and how to create a field type that can be added to a content type. Next I’ll show you how to use the Field API to programmatically add fields using the Field API in a module.

180

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]