Metadata, what for? - Introducing Entity Metadata!

Submitted by fago on Wed, 08/04/2010 - 13:20
Update 10.01.2011: In the meantime the Entity metadata module got merged into the main "entity" API module.+
Drupal 7 modules working with entities often face the same problems:
  • How to create/save/delete an entity?
  • How to get referenced entities?
  • Which properties are there and how can they be accessed or modified?
This is, what Entity Metadata tries to solve for Drupal 7. It collects metadata from modules, such that it knows how this things can be done and provides API functions for that purpose. There are API functions for full entity CRUD, for determining access, as well as data wrappers that simplify dealing with entity properties.

Metadata for data properties, why that?

You might think, we have fields. Yes we have, but not everything is a field. There are also entity properties, like the node title and author, the term hierarchy and lots of others. Entity metadata collects information about all that available properties - regardless whether they are fields or not - and makes them accessible the same way. For that you have to provide property info via a hook, e.g. this is the info the module provides for books:
<?php
 
/**
 * Implements hook_entity_property_info_alter() on top of book module.
 * @see entity_metadata_entity_property_info_alter()
 */
function entity_metadata_book_entity_property_info_alter(&$info) {
 
// Add meta-data about the added node properties.
 
$properties = &$info['node']['properties'];

 
$properties['book-id'] = array(
   
'label' =
?>
t("Book ID"), 'type' => 'integer', 'validation callback' => 'entity_metadata_validate_integer_positive', 'description' => t("If part of a book, the unique ID of this page's book."), 'getter callback' => 'entity_metadata_book_get_properties', ); $properties['book'] = array( 'label' => t("Book"), 'type' => 'node', 'description' => t("If part of a book, the book to which this book page belongs."), 'getter callback' => 'entity_metadata_book_get_properties', ); } ?> The 'getter callback' is used to get the actual value of the property as described in the metadata - this is important to ensure the data exactly looks the way it is described. Consider a date value: Entity metadata defines that a date is represented as timestamp in UTC as documented, thus modules can rely on that. Similarly it defines data types like 'text', 'integer', 'decimal', 'boolean', 'date', 'duration', 'uri', as well as 'struct' for arbitrary data structures and any entity as registered to the system. Additionally it supports a generic 'list' construct, as well as lists of a specific type, e.g. data of type list<text></text> is represented as an numerically indexed array of strings. Apart from getter callbacks there are other optional callbacks, like a 'setter callback' for writing back data, an 'access callback' or a 'setter permission' for establish property-level access control, etc. Also note that Entity metadata automatically adds in information for any field, as long as it knows about the field type. Thus, if you add a new field type, tell it once how to handle it, and any instance will be supported automatically.

Metadata? I've my own module integration!

Yes, you might have and of course it works. But the point about metadata is to avoid re-inventing the wheel to provide basic information lots of modules need again and again. Instead let people define the information once, but use it a couple of times! My need for metadata was Rules, however I decided to to go for a general, re-usable metadata format instead of doing it for Rules only. Why? To enable reuse and avoid duplication. That way other modules may benefit from the module as well, in turn Rules would benefit if more modules provide metadata. The metadata butterfly. As seen on the figure, many modules beside Rules could make use of the metadata. First off modules that want to export, import or transform data could easily make use of the metadata, but also search modules like the Search API or Services would be a natural fit. Oh, and apart from that Entity metadata also provides tokens for any textual property that has none yet. At this point, let me mention that the originating idea is from my friend jpetso, who created the fieldtool for Drupal 6. I just took the idea to D7 and entities.

Metadata Wrappers

Entity metadata provides some wrapper objects you may use just to easily make use of the metadata. With the help of the wrappers you can access the metadata, loop over known properties, or just get/set the described data values, etc. You can find some examples for using the wrappers in the README, but also in the tests. Oh and the nice thing about the wrappers and the way of describing metadata is, it is not limited to entities at all! Indeed I use it for Rules to deal with basically any data, what is needed is just the appropriate metadata that describes the data structures. E.g. Sebastian has written support for dealing with XML and CSV data based upon the metadata as part of his Google summer of code project transformers. Next, we are going to use that for making remote data accessible too - but more on that at the Rules Drupalcon session in Copenhagen...

Mark Robson (not verified)

Tue, 08/05/2014 - 16:33

First of all, thanks for your work on the RESTful module, it is great :) I created a custom module that we use to store images from cloudinary. When I view content that has this module, in json format for example, the fields are not being returned. I've created "cloudinary_entity_property_info_alter" in the .module file, as well as adding "cloudinary_entity_property_info" in there too, but the data is not returning. Any idea what I need to do?