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