Skip to content
Snippets Groups Projects
Commit 8d710337 authored by Earl Miles's avatar Earl Miles
Browse files

Add the ability to automatically do .inc files for default objects like Views...

Add the ability to automatically do .inc files for default objects like Views does as well as more powerful version controls.
parent 6143532f
No related branches found
No related tags found
No related merge requests found
......@@ -24,6 +24,12 @@ function delegator_schema_1() {
$schema['delegator_handlers'] = array(
'export' => array(
'identifier' => 'handler',
'api' => array(
'owner' => 'delegator',
'api' => 'delegator_default',
'minimum_version' => 1,
'current_version' => 1,
),
),
'fields' => array(
'did' => array(
......@@ -97,6 +103,12 @@ function delegator_schema_1() {
'description' => 'Contains page subtasks for implementing pages with arbitrary tasks.',
'export' => array(
'identifier' => 'page',
'api' => array(
'owner' => 'delegator',
'api' => 'delegator_default',
'minimum_version' => 1,
'current_version' => 1,
),
),
'fields' => array(
'pid' => array(
......
......@@ -377,6 +377,7 @@ function delegator_page_load($name) {
*/
function delegator_page_load_all($task = NULL) {
ctools_include('export');
if (empty($task)) {
return ctools_export_load_object('delegator_pages');
}
......
......@@ -47,8 +47,7 @@ define('EXPORT_IN_CODE', 0x02);
*/
function ctools_export_load_object($table, $type = 'all', $args = array()) {
static $cache = array();
static $cached_defaults = FALSE;
static $cached_database = FALSE;
static $cached_database = array();
$schema = ctools_export_get_schema($table);
$export = $schema['export'];
......@@ -57,6 +56,11 @@ function ctools_export_load_object($table, $type = 'all', $args = array()) {
$cache[$table] = array();
}
// If fetching all and cached all, we've done so and we are finished.
if ($type == 'all' && !empty($cached_database[$table])) {
return $cache[$table];
}
$return = array();
// Don't load anything we've already cached.
......@@ -79,50 +83,42 @@ function ctools_export_load_object($table, $type = 'all', $args = array()) {
$conditions = array();
$query_args = array();
// We do not have to load anything if we have already cached everything.
if ($type != 'all' || !$cached_database) {
// If they passed in names, add them to the query.
if ($type == 'names') {
$conditions[] = "$export[key] IN (" . db_placeholders($args, $schema['fields'][$export['key']]['type']) . ")";
$query_args = $args;
}
else if ($type == 'conditions') {
foreach ($args as $key => $value) {
if (isset($schema['fields'][$key])) {
$conditions[] = "$key = " . db_type_placeholder($schema['fields'][$key]['type']);
$query_args[] = $value;
}
// If they passed in names, add them to the query.
if ($type == 'names') {
$conditions[] = "$export[key] IN (" . db_placeholders($args, $schema['fields'][$export['key']]['type']) . ")";
$query_args = $args;
}
else if ($type == 'conditions') {
foreach ($args as $key => $value) {
if (isset($schema['fields'][$key])) {
$conditions[] = "$key = " . db_type_placeholder($schema['fields'][$key]['type']);
$query_args[] = $value;
}
}
}
// Make a string out of the conditions.
if ($conditions) {
$query .= " WHERE " . implode(' AND ', $conditions);
}
// Make a string out of the conditions.
if ($conditions) {
$query .= " WHERE " . implode(' AND ', $conditions);
}
$result = db_query($query, $query_args);
$result = db_query($query, $query_args);
// Unpack the results of the query onto objects and cache them.
while ($data = db_fetch_object($result)) {
$object = _ctools_export_unpack_object($schema, $data, $export['object']);
$object->type = t('Normal');
$object->export_type = EXPORT_IN_DATABASE;
// Unpack the results of the query onto objects and cache them.
while ($data = db_fetch_object($result)) {
$object = _ctools_export_unpack_object($schema, $data, $export['object']);
$object->type = t('Normal');
$object->export_type = EXPORT_IN_DATABASE;
$cache[$table][$object->{$export['key']}] = $object;
if ($type == 'conditions') {
$return[$object->{$export['key']}] = $object;
}
$cache[$table][$object->{$export['key']}] = $object;
if ($type == 'conditions') {
$return[$object->{$export['key']}] = $object;
}
}
if ($type == 'all') {
$cached_database = TRUE;
}
// @todo Load subrecords.
if ($export['default hook'] && !$cached_defaults) {
// @todo add a method to load .inc files for this.
$defaults = module_invoke_all($export['default hook']);
if ($defaults = _ctools_export_get_defaults($table, $export)) {
$status = variable_get($export['status'], array());
foreach ($defaults as $object) {
......@@ -162,22 +158,12 @@ function ctools_export_load_object($table, $type = 'all', $args = array()) {
$return[$object->name] = $object;
}
}
}
// We only actually force this when retrieving all, because we may not
// have retrieved an object from the database and could thus incorrectly
// identify one as being a 'default' object when it is actually
// overridden. So we settle for a potential minor performance decrease
// in order to get this correct.
if ($type == 'all') {
// Make sure we don't run that again later on.
$cached_defaults = TRUE;
}
}
// If fetching all, we've done so and we are finished.
if ($type == 'all') {
$cached_database[$table] = TRUE;
return $cache[$table];
}
......@@ -211,7 +197,7 @@ function ctools_get_default_object($table, $name) {
}
// @todo add a method to load .inc files for this.
$defaults = module_invoke_all($export['default hook']);
$defaults = _ctools_export_get_defaults($table, $export);
$status = variable_get($export['status'], array());
if (!isset($defaults[$name])) {
......@@ -232,6 +218,53 @@ function ctools_get_default_object($table, $name) {
return $object;
}
/**
* Call the hook to get all default objects of the given type from the
* export. If configured properly, this could include loading up an API
* to get default objects.
*/
function _ctools_export_get_defaults($table, $export) {
static $cache = array();
if (!isset($cache[$table])) {
$cache[$table] = array();
if ($export['default hook']) {
if (!empty($export['api'])) {
$info = ctools_plugin_api_include($export['api']['owner'], $export['api']['api'],
$export['api']['minimum_version'], $export['api']['current_version']);
$modules = array_keys($info);
}
else {
$modules = module_implements($export['default hook']);
}
foreach ($modules as $module) {
$function = $module . '_' . $export['default hook'];
if (function_exists($function)) {
if (empty($export['api'])) {
$cache[$table] += (array) $function($export);
}
else {
foreach ((array) $function($export) as $name => $object) {
// If version checking is enabled, ensure that the object can be used.
if (isset($object->api_version) &&
$object->api_version >= $export['api']['minimum_version'] &&
$object->api_version <= $export['api']['current_version']) {
$cache[$table][$name] = $object;
}
}
}
}
}
drupal_alter($export['default hook'], $cache[$table]);
}
}
return $cache[$table];
}
/**
* Unpack data loaded from the database onto an object.
*
......@@ -321,7 +354,10 @@ function ctools_export_object($table, $object, $indent = '', $identifier = NULL,
$output = $indent . '$' . $identifier . ' = new ' . get_class($object) . ";\n";
if ($schema['export']['can disable']) {
$output .= $indent . '$' . $identifier . '->disabled' . ' = FALSE; /* Edit this to true to make a default ' . $identifier . ' disabled initially */' . "\n";
$output .= $indent . '$' . $identifier . '->disabled = FALSE; /* Edit this to true to make a default ' . $identifier . ' disabled initially */' . "\n";
}
if (!empty($schema['export']['api']['current_version'])) {
$output .= $indent . '$' . $identifier . '->api_version = ' . $schema['export']['api']['current_version'] . ";\n";
}
// Put top additions here:
......
......@@ -11,16 +11,23 @@
*/
/**
* Load a group of API files.
* Get an array of information about modules that support an API.
*
* This will ask each module if they support the given API, and if they do
* it will load the specified file name. The API and the file name
* coincide by design.
* it will return an array of information about the modules that do.
*
* This function invokes hook_ctools_api. This invokation is statically
* cached, so feel free to call it as often per page run as you like, it
* will cost very little.
*
* This function can be used as an alternative to module_implements and can
* thus be used to find a precise list of modules that not only support
* a given hook (aka 'api') but also restrict to only modules that use
* the given version. This will allow multiple modules moving at different
* paces to still be able to work together and, in the event of a mismatch,
* either fall back to older behaviors or simply cease loading, which is
* still better than a crash.
*
* @param $owner
* The name of the module that controls the API.
* @param $api
......@@ -36,9 +43,19 @@
* during operation.
*
* @return
* The API information, in case you need it.
* An array of API information, keyed by module. Each module's information will
* contain:
* - 'version': The version of the API required by the module. The module
* should use the lowest number it can support so that the widest range
* of supported versions can be used.
* - 'path': If not provided, this will be the module's path. This is
* where the module will store any subsidiary files. This differs from
* plugin paths which are figured separately.
*
* APIs can request any other information to be placed here that they might
* need. This should be in the documentation for that particular API.
*/
function ctools_plugin_api_include($owner, $api, $minimum_version, $current_version) {
function ctools_plugin_api_info($owner, $api, $minimum_version, $current_version) {
static $cache = array();
if (!isset($cache[$owner][$api])) {
$cache[$owner][$api] = array();
......@@ -54,23 +71,56 @@ function ctools_plugin_api_include($owner, $api, $minimum_version, $current_vers
if (!isset($info['path'])) {
$info['path'] = drupal_get_path('module', $module);
}
if (!isset($info['file'])) {
$info['file'] = "$module.$api.inc";
}
$cache[$owner][$api][$module] = $info;
}
}
}
return $cache[$owner][$api];
}
/**
* Load a group of API files.
*
* This will ask each module if they support the given API, and if they do
* it will load the specified file name. The API and the file name
* coincide by design.
*
* @param $owner
* The name of the module that controls the API.
* @param $api
* The name of the api. The api name forms the file name:
* $module.$api.inc, though this can be overridden by the module's response.
* @param $minimum_version
* The lowest version API that is compatible with this one. If a module
* reports its API as older than this, its files will not be loaded. This
* should never change during operation.
* @param $current_version
* The current version of the api. If a module reports its minimum API as
* higher than this, its files will not be loaded. This should never change
* during operation.
*
* @return
* The API information, in case you need it.
*/
function ctools_plugin_api_include($owner, $api, $minimum_version, $current_version) {
static $already_done = array();
// Now that we have a list, do our includes.
foreach ($cache[$owner][$api] as $module => $info) {
$info = ctools_plugin_api_info($owner, $api, $minimum_version, $current_version);
if (!isset($already_done[$owner][$api])) {
foreach ($info as $module => $info) {
if (!isset($info['file'])) {
$info['file'] = "$module.$api.inc";
}
if (file_exists("./$info[path]/$info[file]")) {
$cache[$owner][$api][$module]['included'] = TRUE;
$info[$module]['included'] = TRUE;
require_once "./$info[path]/$info[file]";
}
}
$already_done[$owner][$api] = TRUE;
}
return $cache[$owner][$api];
return $info;
}
/**
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment