Advanced Custom Fields in Display Suite

A while ago I wrote an article about using custom fields in Display Suite, which focused on what can be done using the DS custom fields interface. While those tools are indispensable, sometimes you may need a bit more control or logic in your fields. You could enable the core PHP Filter module, create a code field and use whatever text format allows for PHP. You could, but you really shouldn’t.

Instead, you could dig into the DS API and start creating your own fields from scratch. This gives you much greater control over the field’s contents than you can get from a code field. You can also give each field its own settings, allowing for configuration that isn’t possible in a Preprocess field.

Display Suite API

First, let me point out the file where you can find all of this information and so much more. Inside the module folder for Display Suite, usually found in /sites/all/modules/ds, there is a file named "ds.api.php". I suggest giving this file a once through as it also comes with a bunch of hooks not only for custom fields, but any aspect of Display Suite. Honestly, it’s not a bad idea to check out any module’s version of this file. A lot of the bigger modules should have one.

The Hook

In order for DS to recognize our new field, we need to define it. As is customary in most things Drupal, this involves calling a hook and creating a large array. The hook we want is hook_ds_fields_info() and it accepts one argument, $entity_type. This hook returns an array of entity types we can attach to our fields.

[prism:php] /** * Implements hook_ds_fields_info() */ function MY_MODULE_ds_fields_info($entity_type) { $fields = array(); return array(‘node’ => $fields); } [/prism:php]

It's worth mentioning in this example we’re only adding fields to the "node" entities. However, you can create as many variables as needed for different entities.

The Definition

From here, we start creating elements in our $fields array for each field we want to define. There are a bunch of options you can add to this element, and all of them are defined in the DS api file.

[prism:php] /** * Implements hook_ds_fields_info() */ function MY_MODULE_ds_fields_info($entity_type) { $fields = array(); $fields['custom_field’] = array( 'title' => t('Our Custom Field'), 'field_type' => DS_FIELD_TYPE_FUNCTION, 'ui_limit' => array('bundle|view_mode'), 'function' => 'MY_MODULE_custom_field_render', ); return array(‘node’ => $fields); } [/prism:php]

Above, we are creating a new field with the machine name 'custom_field'. DS_FIELD_TYPE_FUNCTION is a constant that tells DS to use the callback function, defined in 'function', to render this field. 'ui_limit', like the "Limit field" text area in the UI, restricts this field to specific entity bundles and view modes. Also, like "Limit field", this expects the format of "bundle|view_mode". Remember, both values can take the "*" wildcard if you don’t want to specify a limit. The only real difference is each limit is defined as an array element when defining the field in code.

Field Settings and Summary

You can also create settings for your field on the “Manage Display” tab. This is useful if you want to create a field with different options per view mode. To do this, add a ‘properties’ element with your settings and their default values defined.

[prism:php] /** * Implements hook_ds_fields_info() */ function MY_MODULE_ds_fields_info($entity_type) { $fields = array(); $fields['custom_field’'] = array( 'title' => t('Our Custom Field'), 'field_type' => DS_FIELD_TYPE_FUNCTION, 'ui_limit' => array('bundle|view_mode'), 'function' => 'MY_MODULE_custom_field_render', 'properties' => array( 'settings' => array( 'field text' => array( 'type' => 'textfield', ), ), 'default' => array('field text' => 'This is my field'), ), ); return array(‘node’ => $fields); } [/prism:php]

Above, we’re creating a textfield, where the site builder can provide some text they want to use in the field, and giving it the default value of “This is my field”. The gotcha here is that DS needs two more hooks in order to render the field and its settings summary.

[prism:php] /** * Implements hook_ds_field_settings_form(). */ function MY_MODULE_ds_field_settings_form($field) { return ds_ds_field_settings_form($field); } /** * Implements hook_ds_field_format_summary(). */ function MY_MODULE_ds_field_format_summary($field) { return ds_ds_field_format_summary($field); } [/prism:php]

The two hooks above can just be pasted in your file with “MY_MODULE” changed to whatever your module name is.

The Callback

The last bit of code we need to get this working is the callback function that renders our field. We defined the function name ‘MY_MODULE_custom_field_render’, which will accept an argument for all the data about our field. This includes any custom settings and information about the specific entity on which it’s being rendered. This function should return the flattened markup to create the field.

[prism:php] function MY_MODULE_custom_field_render($field) { return t(‘Field returned value’); } [/prism:php]

Putting It All Together

With everything all said and done, our module file should look like this:

[prism:php] /** * Implements hook_ds_fields_info() */ function MY_MODULE_ds_fields_info($entity_type) { $fields = array(); $fields['custom_field’'] = array( 'title' => t('Our Custom Field'), 'field_type' => DS_FIELD_TYPE_FUNCTION, 'ui_limit' => array('bundle|view_mode'), 'function' => 'MY_MODULE_custom_field_render', 'properties' => array( 'settings' => array( 'field text' => array( 'type' => 'textfield', ), ), 'default' => array('field text' => 'This is my field'), ), ); return array(‘node’ => $fields); } /** * Implements hook_ds_field_settings_form(). */ function MY_MODULE_ds_field_settings_form($field) { return ds_ds_field_settings_form($field); } /** * Implements hook_ds_field_format_summary(). */ function MY_MODULE_ds_field_format_summary($field) { return ds_ds_field_format_summary($field); } function MY_MODULE_custom_field_render($field) { return t(‘Field returned value’); } [/prism:php]

You should be able to clear your cache and visit the "Manage Display" tab of your entity bundle to place your custom field, or change any configuration options that you created.