annotate sites/all/modules/features/includes/features.ctools.inc @ 4:ce11bbd8f642

added modules
author danieleb <danielebarchiesi@me.com>
date Thu, 19 Sep 2013 10:38:44 +0100
parents
children
rev   line source
danielebarchiesi@4 1 <?php
danielebarchiesi@4 2
danielebarchiesi@4 3 function ctools_features_declare_functions($reset = FALSE) {
danielebarchiesi@4 4 /**
danielebarchiesi@4 5 * This is called by Features to ensure ctools component functions are defined
danielebarchiesi@4 6 * Dynamically declare functions under a ctools component's namespace if they are not already declared.
danielebarchiesi@4 7 */
danielebarchiesi@4 8 if (function_exists('_ctools_features_get_info')) {
danielebarchiesi@4 9 foreach (_ctools_features_get_info(NULL, $reset) as $component => $info) {
danielebarchiesi@4 10 $code = '';
danielebarchiesi@4 11 if (!function_exists("{$info['module']}_features_api")) {
danielebarchiesi@4 12 $code .= 'function '. $info['module'] .'_features_api() { return ctools_component_features_api("'. $info['module'] .'"); }';
danielebarchiesi@4 13 }
danielebarchiesi@4 14
danielebarchiesi@4 15 // ctools component with owner defined as "ctools"
danielebarchiesi@4 16 if (!function_exists("{$component}_features_api") && $info['module'] === 'ctools') {
danielebarchiesi@4 17 $code .= 'function '. $component .'_features_api() { return ctools_component_features_api("'. $component .'"); }';
danielebarchiesi@4 18 }
danielebarchiesi@4 19
danielebarchiesi@4 20 if (!function_exists("{$component}_features_export")) {
danielebarchiesi@4 21 $code .= 'function '. $component .'_features_export($data, &$export, $module_name = "") { return ctools_component_features_export("'. $component .'", $data, $export, $module_name); }';
danielebarchiesi@4 22 }
danielebarchiesi@4 23 if (!function_exists("{$component}_features_export_options")) {
danielebarchiesi@4 24 $code .= 'function '. $component .'_features_export_options() { return ctools_component_features_export_options("'. $component .'"); }';
danielebarchiesi@4 25 }
danielebarchiesi@4 26 if (!function_exists("{$component}_features_export_render")) {
danielebarchiesi@4 27 $code .= 'function '. $component .'_features_export_render($module, $data, $export = NULL) { return ctools_component_features_export_render("'. $component .'", $module, $data, $export); }';
danielebarchiesi@4 28 }
danielebarchiesi@4 29 if (!function_exists("{$component}_features_revert")) {
danielebarchiesi@4 30 $code .= 'function '. $component .'_features_revert($module) { return ctools_component_features_revert("'. $component .'", $module); }';
danielebarchiesi@4 31 }
danielebarchiesi@4 32 eval($code);
danielebarchiesi@4 33 }
danielebarchiesi@4 34 }
danielebarchiesi@4 35 }
danielebarchiesi@4 36
danielebarchiesi@4 37 /**
danielebarchiesi@4 38 * Implements hook_features_api().
danielebarchiesi@4 39 */
danielebarchiesi@4 40 function ctools_features_api() {
danielebarchiesi@4 41 return array(
danielebarchiesi@4 42 'ctools' => array(
danielebarchiesi@4 43 'name' => 'CTools export API',
danielebarchiesi@4 44 'feature_source' => TRUE,
danielebarchiesi@4 45 'duplicates' => FEATURES_DUPLICATES_ALLOWED,
danielebarchiesi@4 46 // CTools API integration does not include a default hook declaration as
danielebarchiesi@4 47 // it is not a proper default hook.
danielebarchiesi@4 48 // 'default_hook' => 'ctools_plugin_api',
danielebarchiesi@4 49 ),
danielebarchiesi@4 50 );
danielebarchiesi@4 51 }
danielebarchiesi@4 52
danielebarchiesi@4 53 /**
danielebarchiesi@4 54 * Implements hook_features_export().
danielebarchiesi@4 55 * Adds references to the ctools mothership hook, ctools_plugin_api().
danielebarchiesi@4 56 */
danielebarchiesi@4 57 function ctools_features_export($data, &$export, $module_name = '') {
danielebarchiesi@4 58 // Add ctools dependency
danielebarchiesi@4 59 $export['dependencies']['ctools'] = 'ctools';
danielebarchiesi@4 60
danielebarchiesi@4 61 // Add the actual ctools components which will need to be accounted for in
danielebarchiesi@4 62 // hook_ctools_plugin_api(). The components are actually identified by a
danielebarchiesi@4 63 // delimited list of values: `module_name:api:current_version`
danielebarchiesi@4 64 foreach ($data as $component) {
danielebarchiesi@4 65 if ($info = _ctools_features_get_info($component)) {
danielebarchiesi@4 66 $identifier = "{$info['module']}:{$info['api']}:{$info['current_version']}";
danielebarchiesi@4 67 $export['features']['ctools'][$identifier] = $identifier;
danielebarchiesi@4 68 }
danielebarchiesi@4 69 }
danielebarchiesi@4 70
danielebarchiesi@4 71 return array();
danielebarchiesi@4 72 }
danielebarchiesi@4 73
danielebarchiesi@4 74 /**
danielebarchiesi@4 75 * Implements hook_features_export_render().
danielebarchiesi@4 76 * Adds the ctools mothership hook, ctools_plugin_api().
danielebarchiesi@4 77 */
danielebarchiesi@4 78 function ctools_features_export_render($module, $data) {
danielebarchiesi@4 79 $component_exports = array();
danielebarchiesi@4 80 foreach ($data as $component) {
danielebarchiesi@4 81 $code = array();
danielebarchiesi@4 82 if ($info = _ctools_features_get_info($component)) {
danielebarchiesi@4 83 // For background on why we change the output for hook_views_api()
danielebarchiesi@4 84 // see http://drupal.org/node/1459120.
danielebarchiesi@4 85 if ($info['module'] == 'views') {
danielebarchiesi@4 86 $code[] = ' return array("api" => "3.0");';
danielebarchiesi@4 87 }
danielebarchiesi@4 88 else {
danielebarchiesi@4 89 $code[] = ' if ($module == "'. $info['module'] .'" && $api == "'. $info['api'] .'") {';
danielebarchiesi@4 90 $code[] = ' return array("version" => "'. $info['current_version'] .'");';
danielebarchiesi@4 91 $code[] = ' }';
danielebarchiesi@4 92 }
danielebarchiesi@4 93 }
danielebarchiesi@4 94 ctools_include('plugins');
danielebarchiesi@4 95 $plugin_api_hook_name = ctools_plugin_api_get_hook($info['module'], $info['api']);
danielebarchiesi@4 96
danielebarchiesi@4 97 if (key_exists($plugin_api_hook_name, $component_exports)) {
danielebarchiesi@4 98 $component_exports[$plugin_api_hook_name]['code'] .= "\n" . implode("\n", $code);
danielebarchiesi@4 99 }
danielebarchiesi@4 100 else {
danielebarchiesi@4 101 $component_exports[$plugin_api_hook_name] = array(
danielebarchiesi@4 102 'code' => implode("\n", $code),
danielebarchiesi@4 103 'args' => '$module = NULL, $api = NULL',
danielebarchiesi@4 104 );
danielebarchiesi@4 105 }
danielebarchiesi@4 106 }
danielebarchiesi@4 107
danielebarchiesi@4 108 return $component_exports;
danielebarchiesi@4 109
danielebarchiesi@4 110 }
danielebarchiesi@4 111
danielebarchiesi@4 112 /**
danielebarchiesi@4 113 * Master implementation of hook_features_api() for all ctools components.
danielebarchiesi@4 114 *
danielebarchiesi@4 115 * Note that this master hook does not use $component like the others, but uses the
danielebarchiesi@4 116 * component module's namespace instead.
danielebarchiesi@4 117 */
danielebarchiesi@4 118 function ctools_component_features_api($module_name) {
danielebarchiesi@4 119 $api = array();
danielebarchiesi@4 120 foreach (_ctools_features_get_info() as $component => $info) {
danielebarchiesi@4 121 // if module owner is set to "ctools" we need to compare the component
danielebarchiesi@4 122 if ($info['module'] == $module_name || ($info['module'] === 'ctools' && $component == $module_name) ) {
danielebarchiesi@4 123 $api[$component] = $info;
danielebarchiesi@4 124 }
danielebarchiesi@4 125 }
danielebarchiesi@4 126 return $api;
danielebarchiesi@4 127 }
danielebarchiesi@4 128
danielebarchiesi@4 129 /**
danielebarchiesi@4 130 * Master implementation of hook_features_export_options() for all ctools components.
danielebarchiesi@4 131 */
danielebarchiesi@4 132 function ctools_component_features_export_options($component) {
danielebarchiesi@4 133 $options = array();
danielebarchiesi@4 134
danielebarchiesi@4 135 ctools_include('export');
danielebarchiesi@4 136 $schema = ctools_export_get_schema($component);
danielebarchiesi@4 137 if ($schema && $schema['export']['bulk export']) {
danielebarchiesi@4 138 if (!empty($schema['export']['list callback']) && function_exists($schema['export']['list callback'])) {
danielebarchiesi@4 139 $options = $schema['export']['list callback']();
danielebarchiesi@4 140 }
danielebarchiesi@4 141 else {
danielebarchiesi@4 142 $options = _ctools_features_export_default_list($component, $schema);
danielebarchiesi@4 143 }
danielebarchiesi@4 144 }
danielebarchiesi@4 145 asort($options);
danielebarchiesi@4 146 return $options;
danielebarchiesi@4 147 }
danielebarchiesi@4 148
danielebarchiesi@4 149 /**
danielebarchiesi@4 150 * Master implementation of hook_features_export() for all ctools components.
danielebarchiesi@4 151 */
danielebarchiesi@4 152 function ctools_component_features_export($component, $data, &$export, $module_name = '') {
danielebarchiesi@4 153 // Add the actual implementing module as a dependency
danielebarchiesi@4 154 $info = _ctools_features_get_info();
danielebarchiesi@4 155 if ($module_name !== $info[$component]['module']) {
danielebarchiesi@4 156 $export['dependencies'][$info[$component]['module']] = $info[$component]['module'];
danielebarchiesi@4 157 }
danielebarchiesi@4 158
danielebarchiesi@4 159 // Add the components
danielebarchiesi@4 160 foreach ($data as $object_name) {
danielebarchiesi@4 161 if ($object = _ctools_features_export_crud_load($component, $object_name)) {
danielebarchiesi@4 162 // If this object is provided as a default by a different module, don't
danielebarchiesi@4 163 // export and add that module as a dependency instead.
danielebarchiesi@4 164 if (!empty($object->export_module) && $object->export_module !== $module_name) {
danielebarchiesi@4 165 $export['dependencies'][$object->export_module] = $object->export_module;
danielebarchiesi@4 166 if (isset($export['features'][$component][$object_name])) {
danielebarchiesi@4 167 unset($export['features'][$component][$object_name]);
danielebarchiesi@4 168 }
danielebarchiesi@4 169 }
danielebarchiesi@4 170 // Otherwise, add the component.
danielebarchiesi@4 171 else {
danielebarchiesi@4 172 $export['features'][$component][$object_name] = $object_name;
danielebarchiesi@4 173 }
danielebarchiesi@4 174 }
danielebarchiesi@4 175 }
danielebarchiesi@4 176
danielebarchiesi@4 177 // Let CTools handle API integration for this component.
danielebarchiesi@4 178 return array('ctools' => array($component));
danielebarchiesi@4 179 }
danielebarchiesi@4 180
danielebarchiesi@4 181 /**
danielebarchiesi@4 182 * Master implementation of hook_features_export_render() for all ctools components.
danielebarchiesi@4 183 */
danielebarchiesi@4 184 function ctools_component_features_export_render($component, $module, $data) {
danielebarchiesi@4 185 // Reset the export display static to prevent clashes.
danielebarchiesi@4 186 drupal_static_reset('panels_export_display');
danielebarchiesi@4 187
danielebarchiesi@4 188 ctools_include('export');
danielebarchiesi@4 189 $schema = ctools_export_get_schema($component);
danielebarchiesi@4 190
danielebarchiesi@4 191 if (function_exists($schema['export']['to hook code callback'])) {
danielebarchiesi@4 192 $export = $schema['export']['to hook code callback']($data, $module);
danielebarchiesi@4 193 $code = explode("{\n", $export);
danielebarchiesi@4 194 array_shift($code);
danielebarchiesi@4 195 $code = explode('}', implode($code, "{\n"));
danielebarchiesi@4 196 array_pop($code);
danielebarchiesi@4 197 $code = implode('}', $code);
danielebarchiesi@4 198 }
danielebarchiesi@4 199 else {
danielebarchiesi@4 200 $code = ' $export = array();'."\n\n";
danielebarchiesi@4 201 foreach ($data as $object_name) {
danielebarchiesi@4 202 if ($object = _ctools_features_export_crud_load($component, $object_name)) {
danielebarchiesi@4 203 $identifier = $schema['export']['identifier'];
danielebarchiesi@4 204 $code .= _ctools_features_export_crud_export($component, $object, ' ');
danielebarchiesi@4 205 $code .= " \$export[" . ctools_var_export($object_name) . "] = \${$identifier};\n\n";
danielebarchiesi@4 206 }
danielebarchiesi@4 207 }
danielebarchiesi@4 208 $code .= ' return $export;';
danielebarchiesi@4 209 }
danielebarchiesi@4 210
danielebarchiesi@4 211 return array($schema['export']['default hook'] => $code);
danielebarchiesi@4 212 }
danielebarchiesi@4 213
danielebarchiesi@4 214 /**
danielebarchiesi@4 215 * Master implementation of hook_features_revert() for all ctools components.
danielebarchiesi@4 216 */
danielebarchiesi@4 217 function ctools_component_features_revert($component, $module) {
danielebarchiesi@4 218 if ($objects = features_get_default($component, $module)) {
danielebarchiesi@4 219 foreach ($objects as $name => $object) {
danielebarchiesi@4 220 // Some things (like views) do not use the machine name as key
danielebarchiesi@4 221 // and need to be loaded explicitly in order to be deleted.
danielebarchiesi@4 222 $object = ctools_export_crud_load($component, $name);
danielebarchiesi@4 223 if ($object && ($object->export_type & EXPORT_IN_DATABASE)) {
danielebarchiesi@4 224 _ctools_features_export_crud_delete($component, $object);
danielebarchiesi@4 225 }
danielebarchiesi@4 226 }
danielebarchiesi@4 227 }
danielebarchiesi@4 228 }
danielebarchiesi@4 229
danielebarchiesi@4 230 /**
danielebarchiesi@4 231 * Helper function to return various ctools information for components.
danielebarchiesi@4 232 */
danielebarchiesi@4 233 function _ctools_features_get_info($identifier = NULL, $reset = FALSE) {
danielebarchiesi@4 234 static $components;
danielebarchiesi@4 235 if (!isset($components) || $reset) {
danielebarchiesi@4 236 $components = array();
danielebarchiesi@4 237 $modules = features_get_info();
danielebarchiesi@4 238 ctools_include('export');
danielebarchiesi@4 239 drupal_static('ctools_export_get_schemas', NULL, $reset);
danielebarchiesi@4 240 foreach (ctools_export_get_schemas_by_module() as $module => $schemas) {
danielebarchiesi@4 241 foreach ($schemas as $table => $schema) {
danielebarchiesi@4 242 if ($schema['export']['bulk export']) {
danielebarchiesi@4 243 // Let the API owner take precedence as the owning module.
danielebarchiesi@4 244 $api_module = isset($schema['export']['api']['owner']) ? $schema['export']['api']['owner'] : $module;
danielebarchiesi@4 245 $components[$table] = array(
danielebarchiesi@4 246 'name' => isset($modules[$api_module]->info['name']) ? $modules[$api_module]->info['name'] : $api_module,
danielebarchiesi@4 247 'default_hook' => $schema['export']['default hook'],
danielebarchiesi@4 248 'default_file' => FEATURES_DEFAULTS_CUSTOM,
danielebarchiesi@4 249 'module' => $api_module,
danielebarchiesi@4 250 'feature_source' => TRUE,
danielebarchiesi@4 251 );
danielebarchiesi@4 252 if (isset($schema['export']['api'])) {
danielebarchiesi@4 253 $components[$table] += array(
danielebarchiesi@4 254 'api' => $schema['export']['api']['api'],
danielebarchiesi@4 255 'default_filename' => $schema['export']['api']['api'],
danielebarchiesi@4 256 'current_version' => $schema['export']['api']['current_version'],
danielebarchiesi@4 257 );
danielebarchiesi@4 258 }
danielebarchiesi@4 259 }
danielebarchiesi@4 260 }
danielebarchiesi@4 261 }
danielebarchiesi@4 262 }
danielebarchiesi@4 263
danielebarchiesi@4 264 // Return information specific to a particular component.
danielebarchiesi@4 265 if (isset($identifier)) {
danielebarchiesi@4 266 // Identified by the table name.
danielebarchiesi@4 267 if (isset($components[$identifier])) {
danielebarchiesi@4 268 return $components[$identifier];
danielebarchiesi@4 269 }
danielebarchiesi@4 270 // New API identifier. Allows non-exportables related CTools APIs to be
danielebarchiesi@4 271 // supported by an explicit `module:api:current_version` key.
danielebarchiesi@4 272 else if (substr_count($identifier, ':') === 2) {
danielebarchiesi@4 273 list($module, $api, $current_version) = explode(':', $identifier);
danielebarchiesi@4 274 // If a schema component matches the provided identifier, provide that
danielebarchiesi@4 275 // information. This also ensures that the version number is up to date.
danielebarchiesi@4 276 foreach ($components as $table => $info) {
danielebarchiesi@4 277 if ($info['module'] == $module && $info['api'] == $api && $info['current_version'] >= $current_version) {
danielebarchiesi@4 278 return $info;
danielebarchiesi@4 279 }
danielebarchiesi@4 280 }
danielebarchiesi@4 281 // Fallback to just giving back what was provided to us.
danielebarchiesi@4 282 return array('module' => $module, 'api' => $api, 'current_version' => $current_version);
danielebarchiesi@4 283 }
danielebarchiesi@4 284 return FALSE;
danielebarchiesi@4 285 }
danielebarchiesi@4 286
danielebarchiesi@4 287 return $components;
danielebarchiesi@4 288 }
danielebarchiesi@4 289
danielebarchiesi@4 290 /**
danielebarchiesi@4 291 * Wrapper around ctools_export_crud_export() for < 1.7 compatibility.
danielebarchiesi@4 292 */
danielebarchiesi@4 293 function _ctools_features_export_crud_export($table, $object, $indent = '') {
danielebarchiesi@4 294 return ctools_api_version('1.7') ? ctools_export_crud_export($table, $object, $indent) : ctools_export_object($table, $object, $indent);
danielebarchiesi@4 295 }
danielebarchiesi@4 296
danielebarchiesi@4 297 /**
danielebarchiesi@4 298 * Wrapper around ctools_export_crud_load() for < 1.7 compatibility.
danielebarchiesi@4 299 */
danielebarchiesi@4 300 function _ctools_features_export_crud_load($table, $name) {
danielebarchiesi@4 301 if (ctools_api_version('1.7')) {
danielebarchiesi@4 302 return ctools_export_crud_load($table, $name);
danielebarchiesi@4 303 }
danielebarchiesi@4 304 elseif ($objects = ctools_export_load_object($table, 'names', array($name))) {
danielebarchiesi@4 305 return array_shift($objects);
danielebarchiesi@4 306 }
danielebarchiesi@4 307 return FALSE;
danielebarchiesi@4 308 }
danielebarchiesi@4 309
danielebarchiesi@4 310 /**
danielebarchiesi@4 311 * Wrapper around ctools_export_default_list() for < 1.7 compatibility.
danielebarchiesi@4 312 */
danielebarchiesi@4 313 function _ctools_features_export_default_list($table, $schema) {
danielebarchiesi@4 314 if (ctools_api_version('1.7')) {
danielebarchiesi@4 315 return ctools_export_default_list($table, $schema);
danielebarchiesi@4 316 }
danielebarchiesi@4 317 elseif ($objects = ctools_export_load_object($table, 'all')) {
danielebarchiesi@4 318 return drupal_map_assoc(array_keys($objects));
danielebarchiesi@4 319 }
danielebarchiesi@4 320 return array();
danielebarchiesi@4 321 }
danielebarchiesi@4 322
danielebarchiesi@4 323 /**
danielebarchiesi@4 324 * Wrapper around ctools_export_crud_delete() for < 1.7 compatibility.
danielebarchiesi@4 325 */
danielebarchiesi@4 326 function _ctools_features_export_crud_delete($table, $object) {
danielebarchiesi@4 327 if (ctools_api_version('1.7')) {
danielebarchiesi@4 328 ctools_export_crud_delete($table, $object);
danielebarchiesi@4 329 }
danielebarchiesi@4 330 else {
danielebarchiesi@4 331 $schema = ctools_export_get_schema($table);
danielebarchiesi@4 332 $export = $schema['export'];
danielebarchiesi@4 333 db_query("DELETE FROM {{$table}} WHERE {$export['key']} = '%s'", $object->{$export['key']});
danielebarchiesi@4 334 }
danielebarchiesi@4 335 }
danielebarchiesi@4 336
danielebarchiesi@4 337 /**
danielebarchiesi@4 338 * Implements hook_features_export_render() for page_manager.
danielebarchiesi@4 339 */
danielebarchiesi@4 340 function page_manager_pages_features_export_render($module, $data) {
danielebarchiesi@4 341 // Reset the export display static to prevent clashes.
danielebarchiesi@4 342 drupal_static_reset('panels_export_display');
danielebarchiesi@4 343
danielebarchiesi@4 344 // Ensure that handlers have their code included before exporting.
danielebarchiesi@4 345 page_manager_get_tasks();
danielebarchiesi@4 346 return ctools_component_features_export_render('page_manager_pages', $module, $data);
danielebarchiesi@4 347 }
danielebarchiesi@4 348
danielebarchiesi@4 349 /**
danielebarchiesi@4 350 * Implements hook_features_revert() for page_manager.
danielebarchiesi@4 351 */
danielebarchiesi@4 352 function page_manager_pages_features_revert($module) {
danielebarchiesi@4 353 if ($pages = features_get_default('page_manager_pages', $module)) {
danielebarchiesi@4 354 require_once drupal_get_path('module', 'ctools') . '/page_manager/plugins/tasks/page.inc';
danielebarchiesi@4 355 foreach ($pages as $page) {
danielebarchiesi@4 356 page_manager_page_delete($page);
danielebarchiesi@4 357 }
danielebarchiesi@4 358 }
danielebarchiesi@4 359 }
danielebarchiesi@4 360
danielebarchiesi@4 361 /**
danielebarchiesi@4 362 * Implements hook_features_pipe_COMPONENT_alter() for views_view.
danielebarchiesi@4 363 */
danielebarchiesi@4 364 function views_features_pipe_views_view_alter(&$pipe, $data, $export) {
danielebarchiesi@4 365 // @todo Remove this check before next stable release.
danielebarchiesi@4 366 if (!function_exists('views_plugin_list')) {
danielebarchiesi@4 367 return;
danielebarchiesi@4 368 }
danielebarchiesi@4 369
danielebarchiesi@4 370 $map = array_flip($data);
danielebarchiesi@4 371 foreach (views_plugin_list() as $plugin) {
danielebarchiesi@4 372 foreach ($plugin['views'] as $view_name) {
danielebarchiesi@4 373 if (isset($map[$view_name])) {
danielebarchiesi@4 374 $pipe['dependencies'][$plugin['module']] = $plugin['module'];
danielebarchiesi@4 375 }
danielebarchiesi@4 376 }
danielebarchiesi@4 377 }
danielebarchiesi@4 378 }