Posted by moonray on March 16, 2009 at 8:41am
Based on the discussions we had at DrupalCon, I've written up the beginnings of an API with a standardized set of hooks and some functions.
The details of how, for instance, the block module would save an object to disc might start through using the not-so-desirable form API, due to lack of another option. In the future, however, this could be changed using a more optimal method.
Also included is a generalized function to fetch set of default objects that are embedded in PHP (like views module or context module implement).
Discussion is encouraged. :-)
io.module
<?php
/**
* Fetches a list of objects that are implemented using standardized i/o.
*
* @return
* An array of object types.
*/
function get_registered_objects() {
$types = module_invoke_all('register_objects');
return $types;
}
/**
* Load an object of type $type.
*
* @param $type
* Object type to load
* @param
* ... Arguments to pass to the hook that identify a specific object (i.e. nid).
*
* @return
* An object.
*/
function load($type) {
$object = module_invoke_all('load_'. $type);
drupal_alter('load_'. $type, $object);
return $object;
}
/**
* Save an object.
*/
function save($type, $object) {
module_invoke_all('verify_'. $type, $object);
drupal_alter('verify_'. $type, $object);
module_invoke_all('save_'. $type, $object);
drupal_alter('save_'. $type, $object);
}
/**
* Invokes hook_OBJECT_define() to collect all OBJECTS provided in code by modules.
*
* @return
* An array of default OBJECT objects.
*/
function defaults($type) {
static $cache = array();
if (!$cache[$type]) {
$cache[$type] = array();
foreach (module_implements($type .'_define') as $module) {
$function = $module .'_'. $type .'_define';
$cache[$type] = array_merge($cache[$type], $function());
}
foreach ($cache[$type] as $key => $object) {
$object = (object) $object;
$cache[$type][$key] = $object;
}
}
return $cache[$type];
}
?>An example for the block module.
modules/block.io.inc
<?php
/**
* Implementation of hook_register_objects().
*
* @return
* Returns an array of object names.
*/
function block_register_objects() {
$objects = array('block');
return $objects;
}
/**
* Implementation of hook_default_OBJECT().
*
* @return
* Returns object in its default state. This allows you to only pass in
* only the changes, resulting in shorter code.
*/
function block_default_block() {
$block = new stdClass;
$block->title = '';
$block->body = '';
... etc.;
return $block;
}
/**
* Implementation of hook_load_OBJECT().
*
* @param $module
* @param $delta
*
* @return
* Returns a block object.
*/
function block_load_block($module, $delta) {
// Do magic
return $object;
}
/**
* Implementation of hook_verify_OBJECT().
*
* @param $object
*/
function block_verify_block($object) {
// Probably use formapi and hook_verify to verify object
}
/**
* Implementation of hook_save_OBJECT().
*
* @param $object
*/
function block_save_block($object) {
// Save the block
}
?>
Comments
Thanks for pulling this
Thanks for pulling this together, though I would like some clarification on a few points.;
The purpose I see
So, what could it be used for? An import module would be able to use this to verify that all modules needed to import the object defined by a configuration file exist. Because the OBJECT in hook_load_OBJECT can be anything, there is no way to really know what OBJECTs are available without having to write some convoluted code (an issue we have with the variables right now, for instance).
Verify would eventually replace the current form_api version hook_validate(), and ensure an object is always valid before being written to db/disc, no matter if the object was created by code, or entered through a web form.
Having that same consistent way to load and save objects no matter whether they are nodes, views, configuration options, etc. will make for consistency and an easy way to write code to import/export.
shameless plug / call for collaboration
I took a shot at the same objectives, with the difference of breaking it down to a field level - the result is Field Tool. Perhaps with a couple of changes/additions, we could find a common approach for not only importing and exporting the fields of such an object but also the object itself?