Last updated January 14, 2013. Created by fmizzell on December 14, 2011.
Edited by jedihe, mducharme, Kristen Pol, kolier. Log in to edit this page.

Creating a property behavior is done by implementing the plugin architecture from the CTools module. For any developer to add new "property behavior", all they have to do are two things:

  1. Let the plugin system know that you want to provide some property behaviors.
  2. Create one file per behavior you want to provide.

Ok, so let's go into a little more detail on what each of these steps entail. We will use the code already in ECK to demonstrate how everything works.

Inform the plugin system

To let the plugin system know that you are providing a plugin, all you have to do is implement the hook: hook_ctools_plugin_directory().

Here is what that implementation looks like in ECK:

function eck_ctools_plugin_directory($owner, $plugin_type) {
  if ($owner == 'eck' && $plugin_type == 'property_behavior') {
    return 'plugins/' . $plugin_type;
  }
}

In this function, we are simply letting the system know where the plugins of a given type will be stored. The property behavior plugins are of type "property behavior". So, in this short piece of code we are telling the plugin system that we will store our property behavior plugins in the folder <eck_path>/plugins/property_behavior. The owner, I believe, is the module that defined that plugin type, so it will be ECK since that is the module that knows how to use the plugins.

That is it. Now we can start creating our behaviors.

Writing a property behavior

$plugin = array(
  'label' => "Title",
  'entity_save' => 'eck_title_property_entity_save',
  'entity_info' => 'eck_title_property_entity_info',
  'default_widget' => 'eck_title_property_widget',
);
/* Possible hooks */
/*
$plugin = array(
  'property_info' => 'callback',
  'default_widget' => 'callback',
  'default_formatter' => 'callback',
  'entity_info' => 'callback',
  'entity_save' => 'callback',
  'entity_insert' => 'callback',
  'entity_update' => 'callback',
  'entity_delete' => 'callback',
  'entity_view' => 'callback',
);
*/
function eck_title_property_entity_save($property, $vars){
  $value = $vars['form_value'];
  $entity = $vars['entity'];
  $entity->{$property} = $value;
}
function eck_title_property_widget($property, $vars){
  $entity = $vars['entity'];
  // renderable array
  return array();
}
function eck_title_property_entity_info($property, $var){
  $info = $var;
  ...
  return $info;
}

Here is some of the code used to implement the "Title" property behavior in ECK. As we can see, a behavior is composed of an array and a set of functions.

The plugin array is very simple; it just contains a label to be displayed in the GUI, and some callback functions. The machine name of the behavior is abstracted from the file name in which this code is in. If you look in the folder /plugins/property_behavior in the ECK module, you will see that this code is in a file called title.inc, so the machine name for this behavior is title.

As you could have already guess, the callbacks are called at different times during the life of an entity that contains a property that is implementing our behavior. We currently have 3 kinds of callbacks: subhooks, renderables, and alters.

Subhooks

Subhooks are simply called within some of the entity api hooks, but only when the behavior is being used. The 4 examples of this type of callback are entity_save, entity_insert, entity_update and entity_view.

The main use of this function is to modify or make use of the entity at this point. As we can see from the code above, a $vars array is passed to the function, and the only $vars in there is the relevant $entity. Since an entity is an object and objects are passed by reference, we can do any manipulations to the entity as we need. The save, update, and insert callbacks also get an extra $vars called 'form_value' which of course is the value inputted in the properties widget if one was defined with a renderable callback.

Renderables

Renderables are simply meant to return a renderable array. There are 2 renderable callbacks default_widget and default_fomatter. To those that have worked with the Field API this will sound awfully familiar. Like in the Field API, a widget is the input mechanism (generally a form element) used to set the value of the property, and the formatter is used for displaying the property (theme function, straight html, etc). Once again the entity gets passed to the function callback through the $vars array, so it could be manipulated, but that is not the purpose of these callbacks.

Alter

An alter callback in our behavior, like any hook_alter in drupal is meant to modify an array. The only alter callback available at the moment is the entity_info callback. Only one thing is passed to these types of callbacks, and that is the array to alter. In the case of entity_info, the entity_info array section for the relevant entity type is passed to be manipulated as necessary. Unlike the real alter hooks in Drupal, I was not able to figure out how to get everything working by reference, so after the array is altered, it needs to be returned, and ECK takes care of getting everything in order and modified.

Conclusion

Well, I hope it is clear how easy it is to add functionality that can be used in any property created with ECK for any entity type created with ECK. The current callbacks were defined because those were the ones I needed, but I look forward to people letting me know their use cases and what other callbacks would be useful to be implemented as part of the property behavior system.

Looking for support? Visit the Drupal.org forums, or join #drupal-support in IRC.