Creating Custom Fields In Drupal Using Display Suite
Drupal is a really powerful content management system that has an insane amount of contributed modules that can help you perform certain tasks very easily. Display Suite is one of my default modules of choice to help with content layouts that you can combine with field formatters like Image Class and Linked Field to help carry out some more complicated functions. Sometimes though we need to create custom fields to retrieve data that can’t be handled any other way.
Now, Display Suite does have the feature where you can create extra fields by using the Code Field with the DS Format text format, but the issue with that is that the code is then stored in the database. While it’s simple and effective, it can be hard to manage, the Display Suite fields list starts to get pretty cluttered, and it can bring up security issues. To address this, we can just create new fields in a simple module using hook_ds_fields_info().
Ideally the easiest scenario would be to use Features to package up your content type and related settings and use the empty module file. In my particular case, I needed a custom field to aggregate ratings on a node. Rate by default averages the rating from all users who have rated a node, but I want only the average of the ratings from the users who are my “Friends”.
First we declare our custom field.
/** * Implements hook_ds_fields_info(). */ function MYMODULE_ds_fields_info($entity_type) { $fields = []; $fields['friend_like_count'] = [ 'title' => t('Friends: Like Count'), 'field_type' => DS_FIELD_TYPE_FUNCTION, 'function' => '_MYMODULE_ds_field_like_count', 'properties' => [ 'formatters' => [ 'average_number_rating' => 'Number Rating', 'average_star_rating' => 'Star Rating', ], ], ]; return ['node' => $fields,]; }
You can see we declared a field name, title, type, some formatters, and a function that will output whatever we need. Currently, this field will be available on all nodes. We can restrict or expand this by entity type by making it accessible for comments or other entities.
Now we can create the function that will query and return the rating from only our friends.
/** * Show only likes from my friends. */ function _MYMODULE_ds_field_like_count($field) { // Get information about the entity being rated and the formatter we're using. $formatter = $field['formatter']; $output = ''; // Run query, get results. For the sake of education, // let's just say we returned a rating of 3.5. $friend_rating = 3.5; // Change the output display based on the formatter being used. if ($formatter == 'average_number_rating') { // Just print the number. $output = '<div class="average-rating-friends-value">' . $friend_rating . ' Stars</div>'; } elseif ($formatter == 'average_star_rating') { // See if there needs to be a half star. $half_star = (strpos($friend_rating, '.')) ? '<i class="fa fa-star-half" aria-hidden="true"></i>' : ''; // Now make the whole stars. $friend_rating = floor($friend_rating); $whole_stars = ''; for ($i = 0; $i < $friend_rating; $i++) { $whole_stars .= '<i class="fa fa-star" aria-hidden="true"></i>'; } // Combine the whole stars and half star (if available). $output .= '<div class="average-rating-friends-stars">' . $whole_stars . $half_star . '</div>'; } return $output; }
Awesome, now we have a new pseudo field that computes the ratings only for the friends of the current user and displays them in two different ways. You can now see the field in your Display Suite view with the formatters you provided.
And the output will look something like the following. For demonstration, I put both field outputs together.
And that’s it! You can add additional settings such as text values or options for adding additional information, but this is just the basic implementation.