FINAL suepr merge step : added all modules to this super repos
This commit is contained in:
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Implements hook_features_api().
|
||||
*/
|
||||
function block_features_api() {
|
||||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_features_export().
|
||||
*/
|
||||
function block_features_export($data, &$export) {
|
||||
$pipe = array();
|
||||
foreach ($data as $bid) {
|
||||
$split = explode('-', $bid);
|
||||
$module = array_shift($split);
|
||||
$delta = implode('-', $split);
|
||||
|
||||
$export['dependencies'][$module] = $module;
|
||||
|
||||
switch ($module) {
|
||||
case 'views':
|
||||
if (strlen($delta) == 32) {
|
||||
$hashes = variable_get('views_block_hashes', array());
|
||||
if (!empty($hashes[$delta])) {
|
||||
$delta = $hashes[$delta];
|
||||
}
|
||||
}
|
||||
|
||||
$delta_split = explode('-', $delta);
|
||||
$view_name = $delta_split[0];
|
||||
if (!empty($view_name)) {
|
||||
$pipe['views'][] = $view_name;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return $pipe;
|
||||
}
|
@@ -0,0 +1,54 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Implements hook_features_export().
|
||||
*/
|
||||
function context_features_export($data, &$export, $module_name = '') {
|
||||
$pipe = ctools_component_features_export('context', $data, $export, $module_name);
|
||||
|
||||
$contexts = context_load();
|
||||
foreach ($data as $identifier) {
|
||||
if (isset($contexts[$identifier])) {
|
||||
$context = $contexts[$identifier];
|
||||
// Conditions.
|
||||
// Currently only node and views conditions are supported.
|
||||
// @TODO: Should this be delegated to a method on the plugin?
|
||||
foreach (array('node', 'views') as $key) {
|
||||
if (!empty($context->conditions{$key}['values'])) {
|
||||
foreach ($context->conditions{$key}['values'] as $item) {
|
||||
// Special pipe for views
|
||||
if ($key === 'views') {
|
||||
$split = explode(':', $item);
|
||||
$view_name = array_shift($split);
|
||||
$pipe[$key][$view_name] = $view_name;
|
||||
}
|
||||
else {
|
||||
$pipe[$key][$item] = $item;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Reactions.
|
||||
if (!empty($context->reactions['block']['blocks'])) {
|
||||
foreach ($context->reactions['block']['blocks'] as $block) {
|
||||
$block = (array) $block;
|
||||
$bid = "{$block['module']}-{$block['delta']}";
|
||||
$pipe['block'][$bid] = $bid;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return $pipe;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_features_revert().
|
||||
*
|
||||
* @param $module
|
||||
* name of module to revert content for
|
||||
*/
|
||||
function context_features_revert($module = NULL) {
|
||||
$return = ctools_component_features_revert('context', $module);
|
||||
context_invalidate_cache();
|
||||
return $return;
|
||||
}
|
@@ -0,0 +1,378 @@
|
||||
<?php
|
||||
|
||||
function ctools_features_declare_functions($reset = FALSE) {
|
||||
/**
|
||||
* This is called by Features to ensure ctools component functions are defined
|
||||
* Dynamically declare functions under a ctools component's namespace if they are not already declared.
|
||||
*/
|
||||
if (function_exists('_ctools_features_get_info')) {
|
||||
foreach (_ctools_features_get_info(NULL, $reset) as $component => $info) {
|
||||
$code = '';
|
||||
if (!function_exists("{$info['module']}_features_api")) {
|
||||
$code .= 'function '. $info['module'] .'_features_api() { return ctools_component_features_api("'. $info['module'] .'"); }';
|
||||
}
|
||||
|
||||
// ctools component with owner defined as "ctools"
|
||||
if (!function_exists("{$component}_features_api") && $info['module'] === 'ctools') {
|
||||
$code .= 'function '. $component .'_features_api() { return ctools_component_features_api("'. $component .'"); }';
|
||||
}
|
||||
|
||||
if (!function_exists("{$component}_features_export")) {
|
||||
$code .= 'function '. $component .'_features_export($data, &$export, $module_name = "") { return ctools_component_features_export("'. $component .'", $data, $export, $module_name); }';
|
||||
}
|
||||
if (!function_exists("{$component}_features_export_options")) {
|
||||
$code .= 'function '. $component .'_features_export_options() { return ctools_component_features_export_options("'. $component .'"); }';
|
||||
}
|
||||
if (!function_exists("{$component}_features_export_render")) {
|
||||
$code .= 'function '. $component .'_features_export_render($module, $data, $export = NULL) { return ctools_component_features_export_render("'. $component .'", $module, $data, $export); }';
|
||||
}
|
||||
if (!function_exists("{$component}_features_revert")) {
|
||||
$code .= 'function '. $component .'_features_revert($module) { return ctools_component_features_revert("'. $component .'", $module); }';
|
||||
}
|
||||
eval($code);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_features_api().
|
||||
*/
|
||||
function ctools_features_api() {
|
||||
return array(
|
||||
'ctools' => array(
|
||||
'name' => 'CTools export API',
|
||||
'feature_source' => TRUE,
|
||||
'duplicates' => FEATURES_DUPLICATES_ALLOWED,
|
||||
// CTools API integration does not include a default hook declaration as
|
||||
// it is not a proper default hook.
|
||||
// 'default_hook' => 'ctools_plugin_api',
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_features_export().
|
||||
* Adds references to the ctools mothership hook, ctools_plugin_api().
|
||||
*/
|
||||
function ctools_features_export($data, &$export, $module_name = '') {
|
||||
// Add ctools dependency
|
||||
$export['dependencies']['ctools'] = 'ctools';
|
||||
|
||||
// Add the actual ctools components which will need to be accounted for in
|
||||
// hook_ctools_plugin_api(). The components are actually identified by a
|
||||
// delimited list of values: `module_name:api:current_version`
|
||||
foreach ($data as $component) {
|
||||
if ($info = _ctools_features_get_info($component)) {
|
||||
$identifier = "{$info['module']}:{$info['api']}:{$info['current_version']}";
|
||||
$export['features']['ctools'][$identifier] = $identifier;
|
||||
}
|
||||
}
|
||||
|
||||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_features_export_render().
|
||||
* Adds the ctools mothership hook, ctools_plugin_api().
|
||||
*/
|
||||
function ctools_features_export_render($module, $data) {
|
||||
$component_exports = array();
|
||||
foreach ($data as $component) {
|
||||
$code = array();
|
||||
if ($info = _ctools_features_get_info($component)) {
|
||||
// For background on why we change the output for hook_views_api()
|
||||
// see http://drupal.org/node/1459120.
|
||||
if ($info['module'] == 'views') {
|
||||
$code[] = ' return array("api" => "3.0");';
|
||||
}
|
||||
else {
|
||||
$code[] = ' if ($module == "'. $info['module'] .'" && $api == "'. $info['api'] .'") {';
|
||||
$code[] = ' return array("version" => "'. $info['current_version'] .'");';
|
||||
$code[] = ' }';
|
||||
}
|
||||
}
|
||||
ctools_include('plugins');
|
||||
$plugin_api_hook_name = ctools_plugin_api_get_hook($info['module'], $info['api']);
|
||||
|
||||
if (key_exists($plugin_api_hook_name, $component_exports)) {
|
||||
$component_exports[$plugin_api_hook_name]['code'] .= "\n" . implode("\n", $code);
|
||||
}
|
||||
else {
|
||||
$component_exports[$plugin_api_hook_name] = array(
|
||||
'code' => implode("\n", $code),
|
||||
'args' => '$module = NULL, $api = NULL',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return $component_exports;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Master implementation of hook_features_api() for all ctools components.
|
||||
*
|
||||
* Note that this master hook does not use $component like the others, but uses the
|
||||
* component module's namespace instead.
|
||||
*/
|
||||
function ctools_component_features_api($module_name) {
|
||||
$api = array();
|
||||
foreach (_ctools_features_get_info() as $component => $info) {
|
||||
// if module owner is set to "ctools" we need to compare the component
|
||||
if ($info['module'] == $module_name || ($info['module'] === 'ctools' && $component == $module_name) ) {
|
||||
$api[$component] = $info;
|
||||
}
|
||||
}
|
||||
return $api;
|
||||
}
|
||||
|
||||
/**
|
||||
* Master implementation of hook_features_export_options() for all ctools components.
|
||||
*/
|
||||
function ctools_component_features_export_options($component) {
|
||||
$options = array();
|
||||
|
||||
ctools_include('export');
|
||||
$schema = ctools_export_get_schema($component);
|
||||
if ($schema && $schema['export']['bulk export']) {
|
||||
if (!empty($schema['export']['list callback']) && function_exists($schema['export']['list callback'])) {
|
||||
$options = $schema['export']['list callback']();
|
||||
}
|
||||
else {
|
||||
$options = _ctools_features_export_default_list($component, $schema);
|
||||
}
|
||||
}
|
||||
asort($options);
|
||||
return $options;
|
||||
}
|
||||
|
||||
/**
|
||||
* Master implementation of hook_features_export() for all ctools components.
|
||||
*/
|
||||
function ctools_component_features_export($component, $data, &$export, $module_name = '') {
|
||||
// Add the actual implementing module as a dependency
|
||||
$info = _ctools_features_get_info();
|
||||
if ($module_name !== $info[$component]['module']) {
|
||||
$export['dependencies'][$info[$component]['module']] = $info[$component]['module'];
|
||||
}
|
||||
|
||||
// Add the components
|
||||
foreach ($data as $object_name) {
|
||||
if ($object = _ctools_features_export_crud_load($component, $object_name)) {
|
||||
// If this object is provided as a default by a different module, don't
|
||||
// export and add that module as a dependency instead.
|
||||
if (!empty($object->export_module) && $object->export_module !== $module_name) {
|
||||
$export['dependencies'][$object->export_module] = $object->export_module;
|
||||
if (isset($export['features'][$component][$object_name])) {
|
||||
unset($export['features'][$component][$object_name]);
|
||||
}
|
||||
}
|
||||
// Otherwise, add the component.
|
||||
else {
|
||||
$export['features'][$component][$object_name] = $object_name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Let CTools handle API integration for this component.
|
||||
return array('ctools' => array($component));
|
||||
}
|
||||
|
||||
/**
|
||||
* Master implementation of hook_features_export_render() for all ctools components.
|
||||
*/
|
||||
function ctools_component_features_export_render($component, $module, $data) {
|
||||
// Reset the export display static to prevent clashes.
|
||||
drupal_static_reset('panels_export_display');
|
||||
|
||||
ctools_include('export');
|
||||
$schema = ctools_export_get_schema($component);
|
||||
|
||||
if (function_exists($schema['export']['to hook code callback'])) {
|
||||
$export = $schema['export']['to hook code callback']($data, $module);
|
||||
$code = explode("{\n", $export);
|
||||
array_shift($code);
|
||||
$code = explode('}', implode($code, "{\n"));
|
||||
array_pop($code);
|
||||
$code = implode('}', $code);
|
||||
}
|
||||
else {
|
||||
$code = ' $export = array();'."\n\n";
|
||||
foreach ($data as $object_name) {
|
||||
if ($object = _ctools_features_export_crud_load($component, $object_name)) {
|
||||
$identifier = $schema['export']['identifier'];
|
||||
$code .= _ctools_features_export_crud_export($component, $object, ' ');
|
||||
$code .= " \$export[" . ctools_var_export($object_name) . "] = \${$identifier};\n\n";
|
||||
}
|
||||
}
|
||||
$code .= ' return $export;';
|
||||
}
|
||||
|
||||
return array($schema['export']['default hook'] => $code);
|
||||
}
|
||||
|
||||
/**
|
||||
* Master implementation of hook_features_revert() for all ctools components.
|
||||
*/
|
||||
function ctools_component_features_revert($component, $module) {
|
||||
if ($objects = features_get_default($component, $module)) {
|
||||
foreach ($objects as $name => $object) {
|
||||
// Some things (like views) do not use the machine name as key
|
||||
// and need to be loaded explicitly in order to be deleted.
|
||||
$object = ctools_export_crud_load($component, $name);
|
||||
if ($object && ($object->export_type & EXPORT_IN_DATABASE)) {
|
||||
_ctools_features_export_crud_delete($component, $object);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to return various ctools information for components.
|
||||
*/
|
||||
function _ctools_features_get_info($identifier = NULL, $reset = FALSE) {
|
||||
static $components;
|
||||
if (!isset($components) || $reset) {
|
||||
$components = array();
|
||||
$modules = features_get_info();
|
||||
ctools_include('export');
|
||||
drupal_static('ctools_export_get_schemas', NULL, $reset);
|
||||
foreach (ctools_export_get_schemas_by_module() as $module => $schemas) {
|
||||
foreach ($schemas as $table => $schema) {
|
||||
if ($schema['export']['bulk export']) {
|
||||
// Let the API owner take precedence as the owning module.
|
||||
$api_module = isset($schema['export']['api']['owner']) ? $schema['export']['api']['owner'] : $module;
|
||||
$components[$table] = array(
|
||||
'name' => isset($modules[$api_module]->info['name']) ? $modules[$api_module]->info['name'] : $api_module,
|
||||
'default_hook' => $schema['export']['default hook'],
|
||||
'default_file' => FEATURES_DEFAULTS_CUSTOM,
|
||||
'module' => $api_module,
|
||||
'feature_source' => TRUE,
|
||||
);
|
||||
if (isset($schema['export']['api'])) {
|
||||
$components[$table] += array(
|
||||
'api' => $schema['export']['api']['api'],
|
||||
'default_filename' => $schema['export']['api']['api'],
|
||||
'current_version' => $schema['export']['api']['current_version'],
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Return information specific to a particular component.
|
||||
if (isset($identifier)) {
|
||||
// Identified by the table name.
|
||||
if (isset($components[$identifier])) {
|
||||
return $components[$identifier];
|
||||
}
|
||||
// New API identifier. Allows non-exportables related CTools APIs to be
|
||||
// supported by an explicit `module:api:current_version` key.
|
||||
else if (substr_count($identifier, ':') === 2) {
|
||||
list($module, $api, $current_version) = explode(':', $identifier);
|
||||
// If a schema component matches the provided identifier, provide that
|
||||
// information. This also ensures that the version number is up to date.
|
||||
foreach ($components as $table => $info) {
|
||||
if ($info['module'] == $module && $info['api'] == $api && $info['current_version'] >= $current_version) {
|
||||
return $info;
|
||||
}
|
||||
}
|
||||
// Fallback to just giving back what was provided to us.
|
||||
return array('module' => $module, 'api' => $api, 'current_version' => $current_version);
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return $components;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper around ctools_export_crud_export() for < 1.7 compatibility.
|
||||
*/
|
||||
function _ctools_features_export_crud_export($table, $object, $indent = '') {
|
||||
return ctools_api_version('1.7') ? ctools_export_crud_export($table, $object, $indent) : ctools_export_object($table, $object, $indent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper around ctools_export_crud_load() for < 1.7 compatibility.
|
||||
*/
|
||||
function _ctools_features_export_crud_load($table, $name) {
|
||||
if (ctools_api_version('1.7')) {
|
||||
return ctools_export_crud_load($table, $name);
|
||||
}
|
||||
elseif ($objects = ctools_export_load_object($table, 'names', array($name))) {
|
||||
return array_shift($objects);
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper around ctools_export_default_list() for < 1.7 compatibility.
|
||||
*/
|
||||
function _ctools_features_export_default_list($table, $schema) {
|
||||
if (ctools_api_version('1.7')) {
|
||||
return ctools_export_default_list($table, $schema);
|
||||
}
|
||||
elseif ($objects = ctools_export_load_object($table, 'all')) {
|
||||
return drupal_map_assoc(array_keys($objects));
|
||||
}
|
||||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper around ctools_export_crud_delete() for < 1.7 compatibility.
|
||||
*/
|
||||
function _ctools_features_export_crud_delete($table, $object) {
|
||||
if (ctools_api_version('1.7')) {
|
||||
ctools_export_crud_delete($table, $object);
|
||||
}
|
||||
else {
|
||||
$schema = ctools_export_get_schema($table);
|
||||
$export = $schema['export'];
|
||||
db_query("DELETE FROM {{$table}} WHERE {$export['key']} = '%s'", $object->{$export['key']});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_features_export_render() for page_manager.
|
||||
*/
|
||||
function page_manager_pages_features_export_render($module, $data) {
|
||||
// Reset the export display static to prevent clashes.
|
||||
drupal_static_reset('panels_export_display');
|
||||
|
||||
// Ensure that handlers have their code included before exporting.
|
||||
page_manager_get_tasks();
|
||||
return ctools_component_features_export_render('page_manager_pages', $module, $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_features_revert() for page_manager.
|
||||
*/
|
||||
function page_manager_pages_features_revert($module) {
|
||||
if ($pages = features_get_default('page_manager_pages', $module)) {
|
||||
require_once drupal_get_path('module', 'ctools') . '/page_manager/plugins/tasks/page.inc';
|
||||
foreach ($pages as $page) {
|
||||
page_manager_page_delete($page);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_features_pipe_COMPONENT_alter() for views_view.
|
||||
*/
|
||||
function views_features_pipe_views_view_alter(&$pipe, $data, $export) {
|
||||
// @todo Remove this check before next stable release.
|
||||
if (!function_exists('views_plugin_list')) {
|
||||
return;
|
||||
}
|
||||
|
||||
$map = array_flip($data);
|
||||
foreach (views_plugin_list() as $plugin) {
|
||||
foreach ($plugin['views'] as $view_name) {
|
||||
if (isset($map[$view_name])) {
|
||||
$pipe['dependencies'][$plugin['module']] = $plugin['module'];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,73 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Implements hook_features_api().
|
||||
*/
|
||||
function features_features_api() {
|
||||
return array(
|
||||
'dependencies' => array(
|
||||
'name' => 'Dependencies',
|
||||
'feature_source' => TRUE,
|
||||
'duplicates' => FEATURES_DUPLICATES_ALLOWED,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_features_export_options().
|
||||
*/
|
||||
function dependencies_features_export_options() {
|
||||
// Excluded modules.
|
||||
$excluded = drupal_required_modules();
|
||||
$options = array();
|
||||
foreach (features_get_modules() as $module_name => $info) {
|
||||
if (!in_array($module_name, $excluded) && $info->status && !empty($info->info)) {
|
||||
$options[$module_name] = $info->info['name'];
|
||||
}
|
||||
}
|
||||
return $options;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_features_export().
|
||||
*/
|
||||
function dependencies_features_export($data, &$export, $module_name = '') {
|
||||
// Don't allow a module to depend upon itself.
|
||||
if (!empty($data[$module_name])) {
|
||||
unset($data[$module_name]);
|
||||
}
|
||||
|
||||
// Clean up existing dependencies and merge.
|
||||
$export['dependencies'] = _features_export_minimize_dependencies($export['dependencies'], $module_name);
|
||||
$export['dependencies'] = array_merge($data, $export['dependencies']);
|
||||
$export['dependencies'] = array_unique($export['dependencies']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_features_revert().
|
||||
*/
|
||||
function dependencies_features_revert($module) {
|
||||
dependencies_features_rebuild($module);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_features_rebuild().
|
||||
* Ensure that all of a feature's dependencies are enabled.
|
||||
*/
|
||||
function dependencies_features_rebuild($module) {
|
||||
$feature = features_get_features($module);
|
||||
if (!empty($feature->info['dependencies'])) {
|
||||
$install = array();
|
||||
foreach ($feature->info['dependencies'] as $dependency) {
|
||||
// Parse the dependency string into the module name and version information.
|
||||
$parsed_dependency = drupal_parse_dependency($dependency);
|
||||
$dependency = $parsed_dependency['name'];
|
||||
if (!module_exists($dependency)) {
|
||||
$install[] = $dependency;
|
||||
}
|
||||
}
|
||||
if (!empty($install)) {
|
||||
features_install_modules($install);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,530 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Implements hook_features_api().
|
||||
*/
|
||||
function field_features_api() {
|
||||
return array(
|
||||
'field' => array(
|
||||
// this is deprecated by field_base and field_instance
|
||||
// but retained for compatibility with older exports
|
||||
'name' => t('Fields'),
|
||||
'default_hook' => 'field_default_fields',
|
||||
'default_file' => FEATURES_DEFAULTS_INCLUDED,
|
||||
'feature_source' => FALSE,
|
||||
),
|
||||
'field_base' => array(
|
||||
'name' => t('Field Bases'),
|
||||
'default_hook' => 'field_default_field_bases',
|
||||
'default_file' => FEATURES_DEFAULTS_INCLUDED,
|
||||
'feature_source' => TRUE,
|
||||
'supersedes' => 'field',
|
||||
),
|
||||
'field_instance' => array(
|
||||
'name' => t('Field Instances'),
|
||||
'default_hook' => 'field_default_field_instances',
|
||||
'default_file' => FEATURES_DEFAULTS_INCLUDED,
|
||||
'feature_source' => TRUE,
|
||||
'supersedes' => 'field',
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_features_export_options().
|
||||
*/
|
||||
function field_base_features_export_options() {
|
||||
$options = array();
|
||||
$fields = field_info_fields();
|
||||
foreach ($fields as $field_name => $field) {
|
||||
$options[$field_name] = $field_name;
|
||||
}
|
||||
return $options;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_features_export_options().
|
||||
*/
|
||||
function field_instance_features_export_options() {
|
||||
$options = array();
|
||||
foreach (field_info_fields() as $field_name => $field) {
|
||||
foreach ($field['bundles'] as $entity_type => $bundles) {
|
||||
foreach ($bundles as $bundle) {
|
||||
$identifier = "{$entity_type}-{$bundle}-{$field_name}";
|
||||
$options[$identifier] = $identifier;
|
||||
}
|
||||
}
|
||||
}
|
||||
ksort($options);
|
||||
return $options;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_features_export().
|
||||
*/
|
||||
function field_base_features_export($data, &$export, $module_name = '') {
|
||||
$pipe = array();
|
||||
$map = features_get_default_map('field_base');
|
||||
|
||||
// The field_default_field_bases() hook integration is provided by the
|
||||
// features module so we need to add it as a dependency.
|
||||
$export['dependencies']['features'] = 'features';
|
||||
|
||||
foreach ($data as $identifier) {
|
||||
if ($base = features_field_base_load($identifier)) {
|
||||
// If this field is already provided by another module, remove the field
|
||||
// and add the other module as a dependency.
|
||||
if (isset($map[$identifier]) && $map[$identifier] != $module_name) {
|
||||
if (isset($export['features']['field_base'][$identifier])) {
|
||||
unset($export['features']['field_base'][$identifier]);
|
||||
}
|
||||
$module = $map[$identifier];
|
||||
$export['dependencies'][$module] = $module;
|
||||
}
|
||||
// If the field has not yet been exported, add it
|
||||
else {
|
||||
$export['features']['field_base'][$identifier] = $identifier;
|
||||
$export['dependencies'][$base['module']] = $base['module'];
|
||||
if ($base['storage']['type'] != variable_get('field_storage_default', 'field_sql_storage')) {
|
||||
$export['dependencies'][$base['storage']['module']] = $base['storage']['module'];
|
||||
}
|
||||
// If taxonomy field, add in the vocabulary
|
||||
if ($base['type'] == 'taxonomy_term_reference' && !empty($base['settings']['allowed_values'])) {
|
||||
foreach ($base['settings']['allowed_values'] as $allowed_values) {
|
||||
if (!empty($allowed_values['vocabulary'])) {
|
||||
$pipe['taxonomy'][] = $allowed_values['vocabulary'];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return $pipe;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_features_export().
|
||||
*/
|
||||
function field_instance_features_export($data, &$export, $module_name = '') {
|
||||
$pipe = array('field_base' => array());
|
||||
$map = features_get_default_map('field_instance');
|
||||
|
||||
// The field_default_field_instances() hook integration is provided by the
|
||||
// features module so we need to add it as a dependency.
|
||||
$export['dependencies']['features'] = 'features';
|
||||
|
||||
foreach ($data as $identifier) {
|
||||
if ($instance = features_field_instance_load($identifier)) {
|
||||
// If this field is already provided by another module, remove the field
|
||||
// and add the other module as a dependency.
|
||||
if (isset($map[$identifier]) && $map[$identifier] != $module_name) {
|
||||
if (isset($export['features']['field_instance'][$identifier])) {
|
||||
unset($export['features']['field_instance'][$identifier]);
|
||||
}
|
||||
$module = $map[$identifier];
|
||||
$export['dependencies'][$module] = $module;
|
||||
}
|
||||
// If the field has not yet been exported, add it
|
||||
else {
|
||||
$export['features']['field_instance'][$identifier] = $identifier;
|
||||
$export['dependencies'][$instance['widget']['module']] = $instance['widget']['module'];
|
||||
foreach ($instance['display'] as $key => $display) {
|
||||
if (isset($display['module'])) {
|
||||
$export['dependencies'][$display['module']] = $display['module'];
|
||||
// @TODO: handle the pipe to image styles
|
||||
}
|
||||
}
|
||||
$pipe['field_base'][] = $instance['field_name'];
|
||||
}
|
||||
}
|
||||
}
|
||||
return $pipe;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_features_export_render().
|
||||
*/
|
||||
function field_base_features_export_render($module, $data, $export = NULL) {
|
||||
$translatables = $code = array();
|
||||
$code[] = ' $field_bases = array();';
|
||||
$code[] = '';
|
||||
foreach ($data as $identifier) {
|
||||
if ($field = features_field_base_load($identifier)) {
|
||||
unset($field['columns']);
|
||||
// unset($field['locked']);
|
||||
// Only remove the 'storage' declaration if the field is using the default
|
||||
// storage type.
|
||||
if ($field['storage']['type'] == variable_get('field_storage_default', 'field_sql_storage')) {
|
||||
unset($field['storage']);
|
||||
}
|
||||
// If we still have a storage declaration here it means that a non-default
|
||||
// storage type was altered into to the field definition. And noone would
|
||||
// never need to change the 'details' key, so don't render it.
|
||||
if (isset($field['storage']['details'])) {
|
||||
unset($field['storage']['details']);
|
||||
}
|
||||
|
||||
_field_instance_features_export_sort($field);
|
||||
$field_export = features_var_export($field, ' ');
|
||||
$field_identifier = features_var_export($identifier);
|
||||
$code[] = " // Exported field_base: {$field_identifier}";
|
||||
$code[] = " \$field_bases[{$field_identifier}] = {$field_export};";
|
||||
$code[] = "";
|
||||
}
|
||||
}
|
||||
$code[] = ' return $field_bases;';
|
||||
$code = implode("\n", $code);
|
||||
return array('field_default_field_bases' => $code);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_features_export_render().
|
||||
*/
|
||||
function field_instance_features_export_render($module, $data, $export = NULL) {
|
||||
$translatables = $code = array();
|
||||
|
||||
$code[] = ' $field_instances = array();';
|
||||
$code[] = '';
|
||||
|
||||
foreach ($data as $identifier) {
|
||||
if ($instance = features_field_instance_load($identifier)) {
|
||||
_field_instance_features_export_sort($instance);
|
||||
$field_export = features_var_export($instance, ' ');
|
||||
$instance_identifier = features_var_export($identifier);
|
||||
$code[] = " // Exported field_instance: {$instance_identifier}";
|
||||
$code[] = " \$field_instances[{$instance_identifier}] = {$field_export};";
|
||||
$code[] = "";
|
||||
|
||||
if (!empty($instance['label'])) {
|
||||
$translatables[] = $instance['label'];
|
||||
}
|
||||
if (!empty($instance['description'])) {
|
||||
$translatables[] = $instance['description'];
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!empty($translatables)) {
|
||||
$code[] = features_translatables_export($translatables, ' ');
|
||||
}
|
||||
$code[] = ' return $field_instances;';
|
||||
$code = implode("\n", $code);
|
||||
return array('field_default_field_instances' => $code);
|
||||
}
|
||||
|
||||
// Helper to enforce consistency in field export arrays.
|
||||
function _field_instance_features_export_sort(&$field, $sort = TRUE) {
|
||||
|
||||
// Some arrays are not sorted to preserve order (for example allowed_values).
|
||||
static $sort_blacklist = array(
|
||||
'allowed_values',
|
||||
'format_handlers',
|
||||
);
|
||||
|
||||
if ($sort) {
|
||||
uksort($field, 'strnatcmp');
|
||||
}
|
||||
foreach ($field as $k => $v) {
|
||||
if (is_array($v)) {
|
||||
_field_instance_features_export_sort($field[$k], !in_array($k, $sort_blacklist));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_features_revert().
|
||||
*/
|
||||
function field_base_features_revert($module) {
|
||||
field_base_features_rebuild($module);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_features_revert().
|
||||
*/
|
||||
function field_instance_features_revert($module) {
|
||||
field_instance_features_rebuild($module);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements of hook_features_rebuild().
|
||||
* Rebuilds fields from code defaults.
|
||||
*/
|
||||
function field_base_features_rebuild($module) {
|
||||
if ($fields = features_get_default('field_base', $module)) {
|
||||
field_info_cache_clear();
|
||||
|
||||
// Load all the existing field bases up-front so that we don't
|
||||
// have to rebuild the cache all the time.
|
||||
$existing_fields = field_info_fields();
|
||||
|
||||
foreach ($fields as $field) {
|
||||
// Create or update field.
|
||||
if (isset($existing_fields[$field['field_name']])) {
|
||||
$existing_field = $existing_fields[$field['field_name']];
|
||||
if ($field + $existing_field !== $existing_field) {
|
||||
field_update_field($field);
|
||||
}
|
||||
}
|
||||
else {
|
||||
field_create_field($field);
|
||||
$existing_fields[$field['field_name']] = $field;
|
||||
}
|
||||
variable_set('menu_rebuild_needed', TRUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements of hook_features_rebuild().
|
||||
* Rebuilds field instances from code defaults.
|
||||
*/
|
||||
function field_instance_features_rebuild($module) {
|
||||
if ($instances = features_get_default('field_instance', $module)) {
|
||||
field_info_cache_clear();
|
||||
|
||||
// Load all the existing instances up-front so that we don't
|
||||
// have to rebuild the cache all the time.
|
||||
$existing_instances = field_info_instances();
|
||||
|
||||
foreach ($instances as $field_instance) {
|
||||
// If the field base information does not exist yet, cancel out.
|
||||
if (!field_info_field($field_instance['field_name'])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Create or update field instance.
|
||||
if (isset($existing_instances[$field_instance['entity_type']][$field_instance['bundle']][$field_instance['field_name']])) {
|
||||
$existing_instance = $existing_instances[$field_instance['entity_type']][$field_instance['bundle']][$field_instance['field_name']];
|
||||
if ($field_instance + $existing_instance !== $existing_instance) {
|
||||
try {
|
||||
field_update_instance($field_instance);
|
||||
}
|
||||
catch (FieldException $e) {
|
||||
watchdog('features', 'Attempt to update field instance %label (in %entity entity type %bundle bundle) failed: %message', array('%label' => $field_instance['field_name'], '%entity' => $field_instance['entity_type'], '%bundle' => $field_instance['bundle'], '%message' => $e->getMessage()), WATCHDOG_ERROR);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
try {
|
||||
field_create_instance($field_instance);
|
||||
}
|
||||
catch (FieldException $e) {
|
||||
watchdog('features', 'Attempt to create field instance %label (in %entity entity type %bundle bundle) failed: %message', array('%label' => $field_instance['field_name'], '%entity' => $field_instance['entity_type'], '%bundle' => $field_instance['bundle'], '%message' => $e->getMessage()), WATCHDOG_ERROR);
|
||||
}
|
||||
$existing_instances[$field_instance['entity_type']][$field_instance['bundle']][$field_instance['field_name']] = $field_instance;
|
||||
}
|
||||
}
|
||||
|
||||
if ($instances) {
|
||||
variable_set('menu_rebuild_needed', TRUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a field base configuration by a field_name identifier.
|
||||
*/
|
||||
function features_field_base_load($field_name) {
|
||||
if ($field_info = field_info_field($field_name)) {
|
||||
unset($field_info['id']);
|
||||
unset($field_info['bundles']);
|
||||
return $field_info;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a field's instance configuration by an entity_type-bundle-field_name
|
||||
* identifier.
|
||||
*/
|
||||
function features_field_instance_load($identifier) {
|
||||
list($entity_type, $bundle, $field_name) = explode('-', $identifier);
|
||||
if ($instance_info = field_info_instance($entity_type, $field_name, $bundle)) {
|
||||
unset($instance_info['id']);
|
||||
unset($instance_info['field_id']);
|
||||
return $instance_info;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* ----- DEPRECATED FIELD EXPORT -----
|
||||
* keep this code for backward compatibility with older exports
|
||||
* until v3.x
|
||||
*/
|
||||
|
||||
/**
|
||||
* Implements hook_features_export_options().
|
||||
*/
|
||||
function field_features_export_options() {
|
||||
$options = array();
|
||||
$instances = field_info_instances();
|
||||
foreach ($instances as $entity_type => $bundles) {
|
||||
foreach ($bundles as $bundle => $fields) {
|
||||
foreach ($fields as $field) {
|
||||
$identifier = "{$entity_type}-{$bundle}-{$field['field_name']}";
|
||||
$options[$identifier] = $identifier;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $options;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_features_export().
|
||||
*/
|
||||
function field_features_export($data, &$export, $module_name = '') {
|
||||
$pipe = array();
|
||||
// Convert 'field' to 'field_instance' on features-update.
|
||||
$pipe['field_instance'] = $data;
|
||||
return $pipe;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_features_export_render().
|
||||
*/
|
||||
function field_features_export_render($module, $data, $export = NULL) {
|
||||
$translatables = $code = array();
|
||||
|
||||
$code[] = ' $fields = array();';
|
||||
$code[] = '';
|
||||
foreach ($data as $identifier) {
|
||||
if ($field = features_field_load($identifier)) {
|
||||
unset($field['field_config']['columns']);
|
||||
// Only remove the 'storage' declaration if the field is using the default
|
||||
// storage type.
|
||||
if ($field['field_config']['storage']['type'] == variable_get('field_storage_default', 'field_sql_storage')) {
|
||||
unset($field['field_config']['storage']);
|
||||
}
|
||||
// If we still have a storage declaration here it means that a non-default
|
||||
// storage type was altered into to the field definition. And noone would
|
||||
// never need to change the 'details' key, so don't render it.
|
||||
if (isset($field['field_config']['storage']['details'])) {
|
||||
unset($field['field_config']['storage']['details']);
|
||||
}
|
||||
|
||||
_field_features_export_sort($field);
|
||||
$field_export = features_var_export($field, ' ');
|
||||
$field_identifier = features_var_export($identifier);
|
||||
$code[] = " // Exported field: {$field_identifier}.";
|
||||
$code[] = " \$fields[{$field_identifier}] = {$field_export};";
|
||||
$code[] = "";
|
||||
|
||||
// Add label and description to translatables array.
|
||||
if (!empty($field['field_instance']['label'])) {
|
||||
$translatables[] = $field['field_instance']['label'];
|
||||
}
|
||||
if (!empty($field['field_instance']['description'])) {
|
||||
$translatables[] = $field['field_instance']['description'];
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!empty($translatables)) {
|
||||
$code[] = features_translatables_export($translatables, ' ');
|
||||
}
|
||||
$code[] = ' return $fields;';
|
||||
$code = implode("\n", $code);
|
||||
return array('field_default_fields' => $code);
|
||||
}
|
||||
|
||||
// Helper to enforce consistency in field export arrays.
|
||||
function _field_features_export_sort(&$field, $sort = TRUE) {
|
||||
|
||||
// Some arrays are not sorted to preserve order (for example allowed_values).
|
||||
static $sort_blacklist = array(
|
||||
'allowed_values',
|
||||
'format_handlers',
|
||||
);
|
||||
|
||||
if ($sort) {
|
||||
ksort($field);
|
||||
}
|
||||
foreach ($field as $k => $v) {
|
||||
if (is_array($v)) {
|
||||
_field_features_export_sort($field[$k], !in_array($k, $sort_blacklist));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_features_revert().
|
||||
*/
|
||||
function field_features_revert($module) {
|
||||
field_features_rebuild($module);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements of hook_features_rebuild().
|
||||
* Rebuilds fields from code defaults.
|
||||
*/
|
||||
function field_features_rebuild($module) {
|
||||
if ($fields = features_get_default('field', $module)) {
|
||||
field_info_cache_clear();
|
||||
|
||||
// Load all the existing fields and instance up-front so that we don't
|
||||
// have to rebuild the cache all the time.
|
||||
$existing_fields = field_info_fields();
|
||||
$existing_instances = field_info_instances();
|
||||
|
||||
foreach ($fields as $field) {
|
||||
// Create or update field.
|
||||
$field_config = $field['field_config'];
|
||||
if (isset($existing_fields[$field_config['field_name']])) {
|
||||
$existing_field = $existing_fields[$field_config['field_name']];
|
||||
if ($field_config + $existing_field !== $existing_field) {
|
||||
try {
|
||||
field_update_field($field_config);
|
||||
}
|
||||
catch (FieldException $e) {
|
||||
watchdog('features', 'Attempt to update field %label failed: %message', array('%label' => $field_config['field_name'], '%message' => $e->getMessage()), WATCHDOG_ERROR);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
try {
|
||||
field_create_field($field_config);
|
||||
}
|
||||
catch (FieldException $e) {
|
||||
watchdog('features', 'Attempt to create field %label failed: %message', array('%label' => $field_config['field_name'], '%message' => $e->getMessage()), WATCHDOG_ERROR);
|
||||
}
|
||||
$existing_fields[$field_config['field_name']] = $field_config;
|
||||
}
|
||||
|
||||
// Create or update field instance.
|
||||
$field_instance = $field['field_instance'];
|
||||
if (isset($existing_instances[$field_instance['entity_type']][$field_instance['bundle']][$field_instance['field_name']])) {
|
||||
$existing_instance = $existing_instances[$field_instance['entity_type']][$field_instance['bundle']][$field_instance['field_name']];
|
||||
if ($field_instance + $existing_instance !== $existing_instance) {
|
||||
field_update_instance($field_instance);
|
||||
}
|
||||
}
|
||||
else {
|
||||
field_create_instance($field_instance);
|
||||
$existing_instances[$field_instance['entity_type']][$field_instance['bundle']][$field_instance['field_name']] = $field_instance;
|
||||
}
|
||||
}
|
||||
|
||||
if ($fields) {
|
||||
variable_set('menu_rebuild_needed', TRUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a field's configuration and instance configuration by an
|
||||
* entity_type-bundle-field_name identifier.
|
||||
*/
|
||||
function features_field_load($identifier) {
|
||||
list($entity_type, $bundle, $field_name) = explode('-', $identifier);
|
||||
$field_info = field_info_field($field_name);
|
||||
$instance_info = field_info_instance($entity_type, $field_name, $bundle);
|
||||
if ($field_info && $instance_info) {
|
||||
unset($field_info['id']);
|
||||
unset($field_info['bundles']);
|
||||
unset($instance_info['id']);
|
||||
unset($instance_info['field_id']);
|
||||
return array(
|
||||
'field_config' => $field_info,
|
||||
'field_instance' => $instance_info,
|
||||
);
|
||||
}
|
||||
return FALSE;
|
||||
}
|
@@ -0,0 +1,120 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Implements hook_features_api().
|
||||
*/
|
||||
function filter_features_api() {
|
||||
return array(
|
||||
'filter' => array(
|
||||
'name' => t('Text formats'),
|
||||
'default_hook' => 'filter_default_formats',
|
||||
'default_file' => FEATURES_DEFAULTS_INCLUDED,
|
||||
'feature_source' => TRUE
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_features_export_options().
|
||||
*/
|
||||
function filter_features_export_options() {
|
||||
$options = array();
|
||||
foreach (filter_formats() as $format => $info) {
|
||||
$options[$format] = $info->name;
|
||||
}
|
||||
return $options;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_features_export().
|
||||
*/
|
||||
function filter_features_export($data, &$export, $module_name = '') {
|
||||
// The filter_default_formats() hook integration is provided by the
|
||||
// features module so we need to add it as a dependency.
|
||||
$export['dependencies']['features'] = 'features';
|
||||
|
||||
$filter_info = filter_get_filters();
|
||||
foreach ($data as $name) {
|
||||
if ($format = features_filter_format_load($name)) {
|
||||
// Add format to exports
|
||||
$export['features']['filter'][$format->format] = $format->format;
|
||||
|
||||
// Iterate through filters and ensure each filter's module is included as a dependency
|
||||
foreach (array_keys($format->filters) as $name) {
|
||||
if (isset($filter_info[$name], $filter_info[$name]['module'])) {
|
||||
$module = $filter_info[$name]['module'];
|
||||
$export['dependencies'][$module] = $module;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$pipe = array();
|
||||
return $pipe;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_features_export_render().
|
||||
*/
|
||||
function filter_features_export_render($module, $data, $export = NULL) {
|
||||
$code = array();
|
||||
$code[] = ' $formats = array();';
|
||||
$code[] = '';
|
||||
|
||||
foreach ($data as $name) {
|
||||
if ($format = features_filter_format_load($name)) {
|
||||
$format_export = features_var_export($format, ' ');
|
||||
$format_identifier = features_var_export($format->format);
|
||||
$code[] = " // Exported format: {$format->name}.";
|
||||
$code[] = " \$formats[{$format_identifier}] = {$format_export};";
|
||||
$code[] = "";
|
||||
}
|
||||
}
|
||||
|
||||
$code[] = ' return $formats;';
|
||||
$code = implode("\n", $code);
|
||||
return array('filter_default_formats' => $code);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_features_revert().
|
||||
*/
|
||||
function filter_features_revert($module) {
|
||||
return filter_features_rebuild($module);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_features_rebuild().
|
||||
*/
|
||||
function filter_features_rebuild($module) {
|
||||
if ($defaults = features_get_default('filter', $module)) {
|
||||
foreach ($defaults as $format) {
|
||||
$format = (object) $format;
|
||||
filter_format_save($format);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a filter format by its name.
|
||||
*/
|
||||
function features_filter_format_load($name) {
|
||||
// Use machine name for retrieving the format if available.
|
||||
$query = db_select('filter_format');
|
||||
$query->fields('filter_format');
|
||||
$query->condition('format', $name);
|
||||
|
||||
// Retrieve filters for the format and attach.
|
||||
if ($format = $query->execute()->fetchObject()) {
|
||||
$format->filters = array();
|
||||
foreach (filter_list_format($format->format) as $filter) {
|
||||
if (!empty($filter->status)) {
|
||||
$format->filters[$filter->name]['weight'] = $filter->weight;
|
||||
$format->filters[$filter->name]['status'] = $filter->status;
|
||||
$format->filters[$filter->name]['settings'] = $filter->settings;
|
||||
}
|
||||
}
|
||||
return $format;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
@@ -0,0 +1,101 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Implements hook_features_api().
|
||||
*/
|
||||
function image_features_api() {
|
||||
return array(
|
||||
'image' => array(
|
||||
'name' => t('Image styles'),
|
||||
'feature_source' => TRUE,
|
||||
'default_hook' => 'image_default_styles',
|
||||
'alter_hook' => 'image_styles',
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_features_export_options().
|
||||
*/
|
||||
function image_features_export_options() {
|
||||
$options = array();
|
||||
foreach (image_styles() as $name => $style) {
|
||||
$options[$name] = $style['name'];
|
||||
}
|
||||
return $options;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_features_export().
|
||||
*/
|
||||
function image_features_export($data, &$export, $module_name = '') {
|
||||
$pipe = array();
|
||||
$map = features_get_default_map('image');
|
||||
foreach ($data as $style) {
|
||||
$export['dependencies']['image'] = 'image';
|
||||
// If another module provides this style, add it as a dependency
|
||||
if (isset($map[$style]) && $map[$style] != $module_name) {
|
||||
$module = $map[$style];
|
||||
$export['dependencies'][$module] = $module;
|
||||
}
|
||||
// Otherwise, export the style
|
||||
elseif (image_style_load($style)) {
|
||||
$export['features']['image'][$style] = $style;
|
||||
}
|
||||
}
|
||||
return $pipe;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_features_export_render().
|
||||
*/
|
||||
function image_features_export_render($module_name, $data, $export = NULL) {
|
||||
$code = array();
|
||||
$code[] = ' $styles = array();';
|
||||
$code[] = '';
|
||||
foreach ($data as $name) {
|
||||
if ($style = image_style_load($name)) {
|
||||
_image_features_style_sanitize($style);
|
||||
$style_export = features_var_export($style, ' ');
|
||||
$style_identifier = features_var_export($name);
|
||||
$code[] = " // Exported image style: {$name}.";
|
||||
$code[] = " \$styles[{$style_identifier}] = {$style_export};";
|
||||
$code[] = "";
|
||||
}
|
||||
}
|
||||
$code[] = ' return $styles;';
|
||||
$code = implode("\n", $code);
|
||||
return array('image_default_styles' => $code);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_features_revert().
|
||||
*/
|
||||
function image_features_revert($module) {
|
||||
if ($default_styles = features_get_default('image', $module)) {
|
||||
foreach (array_keys($default_styles) as $default_style) {
|
||||
if ($style = image_style_load($default_style)) {
|
||||
if ($style['storage'] != IMAGE_STORAGE_DEFAULT) {
|
||||
image_default_style_revert($style);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove unnecessary keys for export.
|
||||
*/
|
||||
function _image_features_style_sanitize(&$style, $child = FALSE) {
|
||||
$omit = $child ? array('isid', 'ieid', 'storage') : array('isid', 'ieid', 'storage', 'module');
|
||||
if (is_array($style)) {
|
||||
foreach ($style as $k => $v) {
|
||||
if (in_array($k, $omit, TRUE)) {
|
||||
unset($style[$k]);
|
||||
}
|
||||
else if (is_array($v)) {
|
||||
_image_features_style_sanitize($style[$k], TRUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,162 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Features hooks for language.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Implements of hook_features_api().
|
||||
*/
|
||||
function locale_features_api() {
|
||||
return array(
|
||||
'language' => array(
|
||||
'name' => t('Languages'),
|
||||
'default_hook' => 'locale_default_languages',
|
||||
'feature_source' => TRUE,
|
||||
'default_file' => FEATURES_DEFAULTS_INCLUDED,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_features_export_options().
|
||||
*/
|
||||
function language_features_export_options() {
|
||||
return locale_language_list('native', TRUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_features_export().
|
||||
*/
|
||||
function language_features_export($data, &$export, $module_name = '') {
|
||||
$export['dependencies']['features'] = 'features';
|
||||
$export['dependencies']['locale'] = 'locale';
|
||||
|
||||
$language_list = locale_language_list('native', TRUE);
|
||||
|
||||
foreach ($data as $name) {
|
||||
// Only export existing languages.
|
||||
if (!empty($language_list[$name])) {
|
||||
// Add language to exports.
|
||||
$export['features']['language'][$name] = $name;
|
||||
}
|
||||
}
|
||||
|
||||
// No pipe to return.
|
||||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_features_export_render().
|
||||
*/
|
||||
function language_features_export_render($module, $data, $export = NULL) {
|
||||
$code = array();
|
||||
$code[] = ' $languages = array();';
|
||||
$code[] = '';
|
||||
|
||||
$language_list = language_list();
|
||||
|
||||
foreach ($data as $name) {
|
||||
// Only render existing languages.
|
||||
if (!empty($language_list[$name])) {
|
||||
|
||||
$var = (array) $language_list[$name];
|
||||
// Unset javascript hash
|
||||
unset($var['javascript']);
|
||||
|
||||
$lang_export = features_var_export($var, ' ');
|
||||
$lang_identifier = features_var_export($name);
|
||||
$code[] = " // Exported language: $name.";
|
||||
$code[] = " \$languages[{$lang_identifier}] = {$lang_export};";
|
||||
}
|
||||
}
|
||||
|
||||
$code[] = ' return $languages;';
|
||||
$code = implode("\n", $code);
|
||||
return array('locale_default_languages' => $code);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_features_revert().
|
||||
*/
|
||||
function language_features_revert($module) {
|
||||
return language_features_rebuild($module);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_features_rebuild().
|
||||
*/
|
||||
function language_features_rebuild($module) {
|
||||
if ($defaults = features_get_default('language', $module)) {
|
||||
foreach ($defaults as $key => $language) {
|
||||
_features_language_save((object) $language);
|
||||
}
|
||||
|
||||
// Set correct language count.
|
||||
$enabled_languages = db_select('languages')
|
||||
->condition('enabled', 1)
|
||||
->fields('languages')
|
||||
->execute()
|
||||
->rowCount();
|
||||
variable_set('language_count', $enabled_languages);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to save the language to database.
|
||||
*
|
||||
* @see locale_languages_edit_form_submit()
|
||||
*/
|
||||
function _features_language_save($language) {
|
||||
|
||||
$current_language = db_select('languages')
|
||||
->condition('language', $language->language)
|
||||
->fields('languages')
|
||||
->execute()
|
||||
->fetchAssoc();
|
||||
|
||||
// Set the default language when needed.
|
||||
$default = language_default();
|
||||
|
||||
// Insert new language via api function.
|
||||
if (empty($current_language)) {
|
||||
locale_add_language($language->language,
|
||||
$language->name,
|
||||
$language->native,
|
||||
$language->direction,
|
||||
$language->domain,
|
||||
$language->prefix,
|
||||
$language->enabled,
|
||||
($language->language == $default->language));
|
||||
// Additional params, locale_add_language does not implement.
|
||||
db_update('languages')
|
||||
->fields(array(
|
||||
'plurals' => empty($language->plurals) ? 0 : $language->plurals,
|
||||
'formula' => empty($language->formula) ? '' : $language->formula,
|
||||
))
|
||||
->condition('language', $language->language)
|
||||
->execute();
|
||||
}
|
||||
// Update Existing language.
|
||||
else {
|
||||
// @TODO: get properties from schema.
|
||||
$properties = array('language', 'name', 'native', 'direction', 'enabled', 'plurals', 'formula', 'domain', 'prefix', 'weight', 'javascript');
|
||||
// The javascript hash is not in the imported data but should be empty
|
||||
if (!isset($language->javascript)) {
|
||||
$language->javascript = '';
|
||||
}
|
||||
|
||||
$fields = array_intersect_key((array) $language, array_flip($properties));
|
||||
db_update('languages')
|
||||
->fields($fields)
|
||||
->condition('language', $language->language)
|
||||
->execute();
|
||||
|
||||
// Set the default language when needed.
|
||||
$default = language_default();
|
||||
if ($default->language == $language->language) {
|
||||
variable_set('language_default', (object) $fields);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,414 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Implements hook_features_api().
|
||||
*/
|
||||
function menu_features_api() {
|
||||
return array(
|
||||
'menu_custom' => array(
|
||||
'name' => t('Menus'),
|
||||
'default_hook' => 'menu_default_menu_custom',
|
||||
'feature_source' => TRUE,
|
||||
'default_file' => FEATURES_DEFAULTS_INCLUDED,
|
||||
),
|
||||
'menu_links' => array(
|
||||
'name' => t('Menu links'),
|
||||
'default_hook' => 'menu_default_menu_links',
|
||||
'feature_source' => TRUE,
|
||||
'default_file' => FEATURES_DEFAULTS_INCLUDED,
|
||||
),
|
||||
// DEPRECATED
|
||||
'menu' => array(
|
||||
'name' => t('Menu items'),
|
||||
'default_hook' => 'menu_default_items',
|
||||
'default_file' => FEATURES_DEFAULTS_INCLUDED,
|
||||
'feature_source' => FALSE,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_features_export().
|
||||
* DEPRECATED: This implementation simply migrates deprecated `menu` items
|
||||
* to the `menu_links` type.
|
||||
*/
|
||||
function menu_features_export($data, &$export, $module_name = '') {
|
||||
$pipe = array();
|
||||
foreach ($data as $path) {
|
||||
$pipe['menu_links'][] = "features:{$path}";
|
||||
}
|
||||
return $pipe;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_features_export_options().
|
||||
*/
|
||||
function menu_custom_features_export_options() {
|
||||
$options = array();
|
||||
$result = db_query("SELECT * FROM {menu_custom} ORDER BY title", array(), array('fetch' => PDO::FETCH_ASSOC));
|
||||
foreach ($result as $menu) {
|
||||
$options[$menu['menu_name']] = $menu['title'];
|
||||
}
|
||||
return $options;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_features_export().
|
||||
*/
|
||||
function menu_custom_features_export($data, &$export, $module_name = '') {
|
||||
// Default hooks are provided by the feature module so we need to add
|
||||
// it as a dependency.
|
||||
$export['dependencies']['features'] = 'features';
|
||||
$export['dependencies']['menu'] = 'menu';
|
||||
|
||||
// Collect a menu to module map
|
||||
$pipe = array();
|
||||
$map = features_get_default_map('menu_custom', 'menu_name');
|
||||
foreach ($data as $menu_name) {
|
||||
// If this menu is provided by a different module, add it as a dependency.
|
||||
if (isset($map[$menu_name]) && $map[$menu_name] != $module_name) {
|
||||
$export['dependencies'][$map[$menu_name]] = $map[$menu_name];
|
||||
}
|
||||
else {
|
||||
$export['features']['menu_custom'][$menu_name] = $menu_name;
|
||||
}
|
||||
}
|
||||
return $pipe;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_features_export_render()
|
||||
*/
|
||||
function menu_custom_features_export_render($module, $data) {
|
||||
$code = array();
|
||||
$code[] = ' $menus = array();';
|
||||
$code[] = '';
|
||||
|
||||
$translatables = array();
|
||||
foreach ($data as $menu_name) {
|
||||
$row = db_select('menu_custom')
|
||||
->fields('menu_custom')
|
||||
->condition('menu_name', $menu_name)
|
||||
->execute()
|
||||
->fetchAssoc();
|
||||
if ($row) {
|
||||
$export = features_var_export($row, ' ');
|
||||
$code[] = " // Exported menu: {$menu_name}.";
|
||||
$code[] = " \$menus['{$menu_name}'] = {$export};";
|
||||
$translatables[] = $row['title'];
|
||||
$translatables[] = $row['description'];
|
||||
}
|
||||
}
|
||||
if (!empty($translatables)) {
|
||||
$code[] = features_translatables_export($translatables, ' ');
|
||||
}
|
||||
|
||||
$code[] = '';
|
||||
$code[] = ' return $menus;';
|
||||
$code = implode("\n", $code);
|
||||
return array('menu_default_menu_custom' => $code);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_features_revert().
|
||||
*/
|
||||
function menu_custom_features_revert($module) {
|
||||
menu_custom_features_rebuild($module);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_features_rebuild().
|
||||
*/
|
||||
function menu_custom_features_rebuild($module) {
|
||||
if ($defaults = features_get_default('menu_custom', $module)) {
|
||||
foreach ($defaults as $menu) {
|
||||
menu_save($menu);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_features_export_options().
|
||||
*/
|
||||
function menu_links_features_export_options() {
|
||||
global $menu_admin;
|
||||
// Need to set this to TRUE in order to get menu links that the
|
||||
// current user may not have access to (i.e. user/login)
|
||||
$menu_admin = TRUE;
|
||||
$use_menus = array_intersect_key(menu_get_menus(), array_flip(array_filter(variable_get('features_admin_menu_links_menus', array_keys(menu_get_menus())))));
|
||||
$menu_links = menu_parent_options($use_menus, array('mlid' => 0));
|
||||
$options = array();
|
||||
foreach ($menu_links as $key => $name) {
|
||||
list($menu_name, $mlid) = explode(':', $key, 2);
|
||||
if ($mlid != 0) {
|
||||
$link = menu_link_load($mlid);
|
||||
$identifier = menu_links_features_identifier($link, TRUE);
|
||||
$options[$identifier] = "{$menu_name}: {$name}";
|
||||
}
|
||||
}
|
||||
$menu_admin = FALSE;
|
||||
return $options;
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback for generating the menu link exportable identifier.
|
||||
*/
|
||||
function menu_links_features_identifier($link, $old = FALSE) {
|
||||
// Add some uniqueness to these identifiers, allowing multiple links with the same path, but different titles.
|
||||
$clean_title = features_clean_title(isset($link['title']) ? $link['title'] : $link['link_title']);
|
||||
|
||||
// The old identifier is requested.
|
||||
if ($old) {
|
||||
// if identifier already exists
|
||||
if (isset($link['options']['identifier'])) {
|
||||
return $link['options']['identifier'];
|
||||
}
|
||||
// providing backward compatibility and allowing/enabling multiple links with same paths
|
||||
else {
|
||||
$identifier = isset($link['menu_name'], $link['link_path']) ? "{$link['menu_name']}:{$link['link_path']}" : FALSE;
|
||||
// Checking if there are multiples of this identifier
|
||||
if (features_menu_link_load($identifier) !== FALSE) {
|
||||
// this is where we return the upgrade posibility for links.
|
||||
return $identifier;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return isset($link['menu_name'], $link['link_path']) ? "{$link['menu_name']}_{$clean_title}:{$link['link_path']}" : FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_features_export().
|
||||
*/
|
||||
function menu_links_features_export($data, &$export, $module_name = '') {
|
||||
// Default hooks are provided by the feature module so we need to add
|
||||
// it as a dependency.
|
||||
$export['dependencies']['features'] = 'features';
|
||||
$export['dependencies']['menu'] = 'menu';
|
||||
|
||||
// Collect a link to module map
|
||||
$pipe = array();
|
||||
$map = features_get_default_map('menu_links', 'menu_links_features_identifier');
|
||||
foreach ($data as $key => $identifier) {
|
||||
if ($link = features_menu_link_load($identifier)) {
|
||||
// If this link is provided by a different module, add it as a dependency.
|
||||
$new_identifier = menu_links_features_identifier($link, empty($export));
|
||||
if (isset($map[$identifier]) && $map[$identifier] != $module_name) {
|
||||
$export['dependencies'][$map[$identifier]] = $map[$identifier];
|
||||
}
|
||||
else {
|
||||
$export['features']['menu_links'][$new_identifier] = $new_identifier;
|
||||
}
|
||||
// For now, exclude a variety of common menus from automatic export.
|
||||
// They may still be explicitly included in a Feature if the builder
|
||||
// chooses to do so.
|
||||
if (!in_array($link['menu_name'], array('features', 'primary-links', 'secondary-links', 'navigation', 'admin', 'devel'))) {
|
||||
$pipe['menu_custom'][] = $link['menu_name'];
|
||||
}
|
||||
}
|
||||
}
|
||||
return $pipe;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_features_export_render()
|
||||
*/
|
||||
function menu_links_features_export_render($module, $data, $export = NULL) {
|
||||
$code = array();
|
||||
$code[] = ' $menu_links = array();';
|
||||
$code[] = '';
|
||||
|
||||
$translatables = array();
|
||||
foreach ($data as $identifier) {
|
||||
|
||||
if ($link = features_menu_link_load($identifier)) {
|
||||
$new_identifier = menu_links_features_identifier($link, empty($export));
|
||||
|
||||
// Replace plid with a parent path.
|
||||
if (!empty($link['plid']) && $parent = menu_link_load($link['plid'])) {
|
||||
// If the new identifier is different than the old, maintain
|
||||
// 'parent_path' for backwards compatibility.
|
||||
if ($new_identifier != menu_links_features_identifier($link)) {
|
||||
$link['parent_path'] = $parent['link_path'];
|
||||
}
|
||||
else {
|
||||
$clean_title = features_clean_title($parent['title']);
|
||||
$link['parent_identifier'] = "{$parent['menu_name']}_{$clean_title}:{$parent['link_path']}";
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($export)) {
|
||||
// Don't show new identifier unless we are actually exporting.
|
||||
$link['options']['identifier'] = $new_identifier;
|
||||
// identifiers are renewed, => that means we need to update them in the db
|
||||
menu_link_save($temp = $link);
|
||||
}
|
||||
|
||||
unset($link['plid']);
|
||||
unset($link['mlid']);
|
||||
|
||||
$code[] = " // Exported menu link: {$new_identifier}";
|
||||
$code[] = " \$menu_links['{$new_identifier}'] = ". features_var_export($link, ' ') .";";
|
||||
$translatables[] = $link['link_title'];
|
||||
}
|
||||
}
|
||||
if (!empty($translatables)) {
|
||||
$code[] = features_translatables_export($translatables, ' ');
|
||||
}
|
||||
|
||||
$code[] = '';
|
||||
$code[] = ' return $menu_links;';
|
||||
$code = implode("\n", $code);
|
||||
return array('menu_default_menu_links' => $code);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_features_revert().
|
||||
*/
|
||||
function menu_links_features_revert($module) {
|
||||
menu_links_features_rebuild($module);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_features_rebuild().
|
||||
*/
|
||||
function menu_links_features_rebuild($module) {
|
||||
if ($menu_links = features_get_default('menu_links', $module)) {
|
||||
menu_links_features_rebuild_ordered($menu_links);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a depth tree of all menu links.
|
||||
*/
|
||||
function menu_links_features_rebuild_ordered($menu_links, $reset = FALSE) {
|
||||
static $ordered;
|
||||
static $all_links;
|
||||
if (!isset($ordered) || $reset) {
|
||||
$ordered = array();
|
||||
$unordered = features_get_default('menu_links');
|
||||
|
||||
// Order all links by depth.
|
||||
if ($unordered) {
|
||||
do {
|
||||
$current = count($unordered);
|
||||
foreach ($unordered as $key => $link) {
|
||||
$identifier = menu_links_features_identifier($link);
|
||||
$parent = isset($link['parent_identifier']) ? $link['parent_identifier'] : '';
|
||||
if (empty($parent)) {
|
||||
$ordered[$identifier] = 0;
|
||||
$all_links[$identifier] = $link;
|
||||
unset($unordered[$key]);
|
||||
}
|
||||
elseif (isset($ordered[$parent])) {
|
||||
$ordered[$identifier] = $ordered[$parent] + 1;
|
||||
$all_links[$identifier] = $link;
|
||||
unset($unordered[$key]);
|
||||
}
|
||||
}
|
||||
} while (count($unordered) < $current);
|
||||
}
|
||||
asort($ordered);
|
||||
}
|
||||
|
||||
// Ensure any default menu items that do not exist are created.
|
||||
foreach (array_keys($ordered) as $identifier) {
|
||||
$link = $all_links[$identifier];
|
||||
|
||||
$existing = features_menu_link_load($identifier);
|
||||
if (!$existing || in_array($link, $menu_links)) {
|
||||
// Retrieve the mlid if this is an existing item.
|
||||
if ($existing) {
|
||||
$link['mlid'] = $existing['mlid'];
|
||||
}
|
||||
// Retrieve the plid for a parent link.
|
||||
if (!empty($link['parent_identifier']) && $parent = features_menu_link_load($link['parent_identifier'])) {
|
||||
$link['plid'] = $parent['mlid'];
|
||||
}
|
||||
// This if for backwards compatibility.
|
||||
elseif (!empty($link['parent_path']) && $parent = features_menu_link_load("{$link['menu_name']}:{$link['parent_path']}")) {
|
||||
$link['plid'] = $parent['mlid'];
|
||||
}
|
||||
else {
|
||||
$link['plid'] = 0;
|
||||
}
|
||||
menu_link_save($link);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a menu link by its menu_name_cleantitle:link_path identifier.
|
||||
* Also matches links with unique menu_name:link_path
|
||||
*/
|
||||
function features_menu_link_load($identifier) {
|
||||
$menu_name = '';
|
||||
$link_path = '';
|
||||
// This gets variables for menu_name_cleantitle:link_path format.
|
||||
if (strstr($identifier, "_")) {
|
||||
$link_path = substr($identifier, strpos($identifier, ":") + 1);
|
||||
list($menu_name) = explode('_', $identifier, 2);
|
||||
$clean_title = substr($identifier, strpos($identifier, "_") + 1, strpos($identifier, ":") - strpos($identifier, "_") - 1);
|
||||
}
|
||||
// This gets variables for traditional identifier format.
|
||||
else {
|
||||
$clean_title = '';
|
||||
list($menu_name, $link_path) = explode(':', $identifier, 2);
|
||||
}
|
||||
$links = db_select('menu_links')
|
||||
->fields('menu_links', array('menu_name', 'mlid', 'plid', 'link_path', 'router_path', 'link_title', 'options', 'module', 'hidden', 'external', 'has_children', 'expanded', 'weight', 'customized'))
|
||||
->condition('menu_name', $menu_name)
|
||||
->condition('link_path', $link_path)
|
||||
->execute()
|
||||
->fetchAllAssoc('mlid');
|
||||
|
||||
foreach($links as $link) {
|
||||
$link->options = unserialize($link->options);
|
||||
|
||||
// Title or previous identifier matches.
|
||||
if ((isset($link->options['identifier']) && strcmp($link->options['identifier'], $identifier) == 0)
|
||||
|| (isset($clean_title) && strcmp(features_clean_title($link->link_title), $clean_title) == 0)) {
|
||||
|
||||
return (array)$link;
|
||||
}
|
||||
}
|
||||
|
||||
// Only one link with the requested menu_name and link_path does exists,
|
||||
// -- providing an upgrade possibility for links saved in a feature before the
|
||||
// new identifier-pattern was added.
|
||||
if (count($links) == 1 && empty($clean_title)) {
|
||||
$link = reset($links); // get the first item
|
||||
return (array)$link;
|
||||
}
|
||||
// If link_path was changed on an existing link, we need to find it by
|
||||
// searching for link_title.
|
||||
else if (isset($clean_title)) {
|
||||
$links = db_select('menu_links')
|
||||
->fields('menu_links', array('menu_name', 'mlid', 'plid', 'link_path', 'router_path', 'link_title', 'options', 'module', 'hidden', 'external', 'has_children', 'expanded', 'weight'))
|
||||
->condition('menu_name', $menu_name)
|
||||
->execute()
|
||||
->fetchAllAssoc('mlid');
|
||||
|
||||
foreach($links as $link) {
|
||||
$link->options = unserialize($link->options);
|
||||
|
||||
// title or previous identifier matches
|
||||
if ((isset($link->options['identifier']) && strcmp($link->options['identifier'], $identifier) == 0)
|
||||
|| (isset($clean_title) && strcmp(features_clean_title($link->link_title), $clean_title) == 0)) {
|
||||
|
||||
return (array)$link;
|
||||
}
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a lowercase clean string with only letters, numbers and dashes
|
||||
*/
|
||||
function features_clean_title($str) {
|
||||
return strtolower(preg_replace_callback('/(\s)|([^a-zA-Z\-0-9])/i', create_function(
|
||||
'$matches',
|
||||
'return $matches[1]?"-":"";'
|
||||
), $str));
|
||||
}
|
@@ -0,0 +1,161 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Implements hook_features_api().
|
||||
*/
|
||||
function node_features_api() {
|
||||
return array(
|
||||
'node' => array(
|
||||
'name' => t('Content types'),
|
||||
'feature_source' => TRUE,
|
||||
'default_hook' => 'node_info',
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_features_export_options().
|
||||
*/
|
||||
function node_features_export_options() {
|
||||
return node_type_get_names();
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_features_export.
|
||||
*/
|
||||
function node_features_export($data, &$export, $module_name = '') {
|
||||
$pipe = array();
|
||||
$map = features_get_default_map('node');
|
||||
|
||||
foreach ($data as $type) {
|
||||
// Poll node module to determine who provides the node type.
|
||||
if ($info = node_type_get_type($type)) {
|
||||
// If this node type is provided by a different module, add it as a dependency
|
||||
if (isset($map[$type]) && $map[$type] != $module_name) {
|
||||
$export['dependencies'][$map[$type]] = $map[$type];
|
||||
}
|
||||
// Otherwise export the node type.
|
||||
elseif (in_array($info->base, array('node_content', 'features'))) {
|
||||
$export['features']['node'][$type] = $type;
|
||||
$export['dependencies']['node'] = 'node';
|
||||
$export['dependencies']['features'] = 'features';
|
||||
}
|
||||
|
||||
$fields = field_info_instances('node', $type);
|
||||
foreach ($fields as $name => $field) {
|
||||
$pipe['field_instance'][] = "node-{$field['bundle']}-{$field['field_name']}";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $pipe;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_features_export_render().
|
||||
*/
|
||||
function node_features_export_render($module, $data, $export = NULL) {
|
||||
$elements = array(
|
||||
'name' => TRUE,
|
||||
'base' => FALSE,
|
||||
'description' => TRUE,
|
||||
'has_title' => FALSE,
|
||||
'title_label' => TRUE,
|
||||
'help' => TRUE,
|
||||
);
|
||||
$output = array();
|
||||
$output[] = ' $items = array(';
|
||||
foreach ($data as $type) {
|
||||
if ($info = node_type_get_type($type)) {
|
||||
// Force module name to be 'features' if set to 'node. If we leave as
|
||||
// 'node' the content type will be assumed to be database-stored by
|
||||
// the node module.
|
||||
$info->base = ($info->base === 'node') ? 'features' : $info->base;
|
||||
$output[] = " '{$type}' => array(";
|
||||
foreach ($elements as $key => $t) {
|
||||
if ($t) {
|
||||
$text = str_replace("'", "\'", $info->$key);
|
||||
$text = !empty($text) ? "t('{$text}')" : "''";
|
||||
$output[] = " '{$key}' => {$text},";
|
||||
}
|
||||
else {
|
||||
$output[] = " '{$key}' => '{$info->$key}',";
|
||||
}
|
||||
}
|
||||
$output[] = " ),";
|
||||
}
|
||||
}
|
||||
$output[] = ' );';
|
||||
$output[] = ' return $items;';
|
||||
$output = implode("\n", $output);
|
||||
return array('node_info' => $output);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_features_revert().
|
||||
*
|
||||
* @param $module
|
||||
* name of module to revert content for
|
||||
*/
|
||||
function node_features_revert($module = NULL) {
|
||||
if ($default_types = features_get_default('node', $module)) {
|
||||
foreach ($default_types as $type_name => $type_info) {
|
||||
// Delete node types
|
||||
// We don't use node_type_delete() because we do not actually
|
||||
// want to delete the node type (and invoke hook_node_type()).
|
||||
// This can lead to bad consequences like CCK deleting field
|
||||
// storage in the DB.
|
||||
db_delete('node_type')
|
||||
->condition('type', $type_name)
|
||||
->execute();
|
||||
}
|
||||
node_types_rebuild();
|
||||
menu_rebuild();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_features_disable().
|
||||
*
|
||||
* When a features module is disabled, modify any node types it provides so
|
||||
* they can be deleted manually through the content types UI.
|
||||
*
|
||||
* @param $module
|
||||
* Name of module that has been disabled.
|
||||
*/
|
||||
function node_features_disable($module) {
|
||||
if ($default_types = features_get_default('node', $module)) {
|
||||
foreach ($default_types as $type_name => $type_info) {
|
||||
$type_info = node_type_load($type_name);
|
||||
$type_info->module = 'node';
|
||||
$type_info->custom = 1;
|
||||
$type_info->modified = 1;
|
||||
$type_info->locked = 0;
|
||||
node_type_save($type_info);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_features_enable().
|
||||
*
|
||||
* When a features module is enabled, modify any node types it provides so
|
||||
* they can no longer be deleted manually through the content types UI.
|
||||
*
|
||||
* @param $module
|
||||
* Name of module that has been enabled.
|
||||
*/
|
||||
function node_features_enable($module) {
|
||||
if ($default_types = features_get_default('node', $module)) {
|
||||
foreach ($default_types as $type_name => $type_info) {
|
||||
// Ensure the type exists.
|
||||
if ($type_info = node_type_load($type_name)) {
|
||||
$type_info->module = $module;
|
||||
$type_info->custom = 0;
|
||||
$type_info->modified = 0;
|
||||
$type_info->locked = 1;
|
||||
node_type_save($type_info);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,105 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Implements hook_features_api().
|
||||
*/
|
||||
function taxonomy_features_api() {
|
||||
return array(
|
||||
'taxonomy' => array(
|
||||
'name' => t('Taxonomy'),
|
||||
'feature_source' => TRUE,
|
||||
'default_hook' => 'taxonomy_default_vocabularies',
|
||||
'default_file' => FEATURES_DEFAULTS_INCLUDED,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_features_export_options().
|
||||
*/
|
||||
function taxonomy_features_export_options() {
|
||||
$vocabularies = array();
|
||||
foreach (taxonomy_get_vocabularies() as $vocabulary) {
|
||||
$vocabularies[$vocabulary->machine_name] = $vocabulary->name;
|
||||
}
|
||||
return $vocabularies;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_features_export().
|
||||
*
|
||||
* @todo Test adding existing dependencies.
|
||||
*/
|
||||
function taxonomy_features_export($data, &$export, $module_name = '') {
|
||||
$pipe = array();
|
||||
|
||||
// taxonomy_default_vocabularies integration is provided by Features.
|
||||
$export['dependencies']['features'] = 'features';
|
||||
$export['dependencies']['taxonomy'] = 'taxonomy';
|
||||
|
||||
// Add dependencies for each vocabulary.
|
||||
$map = features_get_default_map('taxonomy');
|
||||
foreach ($data as $machine_name) {
|
||||
if (isset($map[$machine_name]) && $map[$machine_name] != $module_name) {
|
||||
$export['dependencies'][$map[$machine_name]] = $map[$machine_name];
|
||||
}
|
||||
else {
|
||||
$export['features']['taxonomy'][$machine_name] = $machine_name;
|
||||
|
||||
$fields = field_info_instances('taxonomy_term', $machine_name);
|
||||
foreach ($fields as $name => $field) {
|
||||
$pipe['field'][] = "taxonomy_term-{$field['bundle']}-{$field['field_name']}";
|
||||
$pipe['field_instance'][] = "taxonomy_term-{$field['bundle']}-{$field['field_name']}";
|
||||
}
|
||||
}
|
||||
}
|
||||
return $pipe;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_features_export_render().
|
||||
*/
|
||||
function taxonomy_features_export_render($module, $data) {
|
||||
$vocabularies = taxonomy_get_vocabularies();
|
||||
$code = array();
|
||||
foreach ($data as $machine_name) {
|
||||
foreach ($vocabularies as $vocabulary) {
|
||||
if ($vocabulary->machine_name == $machine_name) {
|
||||
// We don't want to break the entity cache, so we need to clone the
|
||||
// vocabulary before unsetting the id.
|
||||
$vocabulary = clone $vocabulary;
|
||||
unset($vocabulary->vid);
|
||||
$code[$machine_name] = $vocabulary;
|
||||
}
|
||||
}
|
||||
}
|
||||
$code = " return ". features_var_export($code, ' ') .";";
|
||||
return array('taxonomy_default_vocabularies' => $code);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_features_revert().
|
||||
*/
|
||||
function taxonomy_features_revert($module) {
|
||||
taxonomy_features_rebuild($module);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_features_rebuild().
|
||||
*
|
||||
* Rebuilds Taxonomy vocabularies from code defaults.
|
||||
*/
|
||||
function taxonomy_features_rebuild($module) {
|
||||
if ($vocabularies = features_get_default('taxonomy', $module)) {
|
||||
$existing = taxonomy_get_vocabularies();
|
||||
foreach ($vocabularies as $vocabulary) {
|
||||
$vocabulary = (object) $vocabulary;
|
||||
foreach ($existing as $existing_vocab) {
|
||||
if ($existing_vocab->machine_name === $vocabulary->machine_name) {
|
||||
$vocabulary->vid = $existing_vocab->vid;
|
||||
}
|
||||
}
|
||||
taxonomy_vocabulary_save($vocabulary);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,290 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Implements hook_features_api().
|
||||
*/
|
||||
function user_features_api() {
|
||||
return array(
|
||||
'user_role' => array(
|
||||
'name' => t('Roles'),
|
||||
'feature_source' => TRUE,
|
||||
'default_hook' => 'user_default_roles',
|
||||
'default_file' => FEATURES_DEFAULTS_INCLUDED,
|
||||
),
|
||||
'user_permission' => array(
|
||||
'name' => t('Permissions'),
|
||||
'feature_source' => TRUE,
|
||||
'default_hook' => 'user_default_permissions',
|
||||
'default_file' => FEATURES_DEFAULTS_INCLUDED,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_features_export().
|
||||
*/
|
||||
function user_permission_features_export($data, &$export, $module_name = '') {
|
||||
$export['dependencies']['features'] = 'features';
|
||||
|
||||
// Ensure the modules that provide the given permissions are included as dependencies.
|
||||
$map = user_permission_get_modules();
|
||||
foreach ($data as $perm) {
|
||||
$perm_name = $perm;
|
||||
// Export vocabulary permissions using the machine name, instead of
|
||||
// vocabulary id.
|
||||
_user_features_change_term_permission($perm_name, 'machine_name');
|
||||
if (isset($map[$perm_name])) {
|
||||
$perm_module = $map[$perm_name];
|
||||
$export['dependencies'][$perm_module] = $perm_module;
|
||||
$export['features']['user_permission'][$perm] = $perm;
|
||||
}
|
||||
}
|
||||
|
||||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_features_export_options().
|
||||
*/
|
||||
function user_permission_features_export_options() {
|
||||
$modules = array();
|
||||
$module_info = system_get_info('module');
|
||||
foreach (module_implements('permission') as $module) {
|
||||
$modules[$module_info[$module]['name']] = $module;
|
||||
}
|
||||
ksort($modules);
|
||||
|
||||
$options = array();
|
||||
foreach ($modules as $display_name => $module) {
|
||||
if ($permissions = module_invoke($module, 'permission')) {
|
||||
foreach ($permissions as $perm => $perm_item) {
|
||||
// Export vocabulary permissions using the machine name, instead of
|
||||
// vocabulary id.
|
||||
_user_features_change_term_permission($perm);
|
||||
$options[$perm] = strip_tags("{$display_name}: {$perm_item['title']}");
|
||||
}
|
||||
}
|
||||
}
|
||||
return $options;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_features_export_render().
|
||||
*/
|
||||
function user_permission_features_export_render($module, $data) {
|
||||
$perm_modules = &drupal_static(__FUNCTION__ . '_perm_modules');
|
||||
if (!isset($perm_modules)) {
|
||||
$perm_modules = user_permission_get_modules();
|
||||
}
|
||||
|
||||
$code = array();
|
||||
$code[] = ' $permissions = array();';
|
||||
$code[] = '';
|
||||
|
||||
$permissions = _user_features_get_permissions();
|
||||
|
||||
foreach ($data as $perm_name) {
|
||||
$permission = array();
|
||||
// Export vocabulary permissions using the machine name, instead of
|
||||
// vocabulary id.
|
||||
$perm = $perm_name;
|
||||
_user_features_change_term_permission($perm_name, 'machine_name');
|
||||
$permission['name'] = $perm;
|
||||
if (!empty($permissions[$perm_name])) {
|
||||
sort($permissions[$perm_name]);
|
||||
$permission['roles'] = drupal_map_assoc($permissions[$perm_name]);
|
||||
}
|
||||
else {
|
||||
$permission['roles'] = array();
|
||||
}
|
||||
if (isset($perm_modules[$perm_name])) {
|
||||
$permission['module'] = $perm_modules[$perm_name];
|
||||
}
|
||||
$perm_identifier = features_var_export($perm);
|
||||
$perm_export = features_var_export($permission, ' ');
|
||||
$code[] = " // Exported permission: {$perm_identifier}.";
|
||||
$code[] = " \$permissions[{$perm_identifier}] = {$perm_export};";
|
||||
$code[] = "";
|
||||
}
|
||||
|
||||
$code[] = ' return $permissions;';
|
||||
$code = implode("\n", $code);
|
||||
return array('user_default_permissions' => $code);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_features_revert().
|
||||
*/
|
||||
function user_permission_features_revert($module) {
|
||||
user_permission_features_rebuild($module);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_features_rebuild().
|
||||
* Iterate through default permissions and update the permissions map.
|
||||
*
|
||||
* @param $module
|
||||
* The module whose default user permissions should be rebuilt.
|
||||
*/
|
||||
function user_permission_features_rebuild($module) {
|
||||
if ($defaults = features_get_default('user_permission', $module)) {
|
||||
// Make sure the list of available node types is up to date, especially when
|
||||
// installing multiple features at once, for example from an install profile
|
||||
// or via drush.
|
||||
node_types_rebuild();
|
||||
|
||||
$modules = user_permission_get_modules();
|
||||
$roles = _user_features_get_roles();
|
||||
$permissions_by_role = _user_features_get_permissions(FALSE);
|
||||
foreach ($defaults as $permission) {
|
||||
$perm = $permission['name'];
|
||||
_user_features_change_term_permission($perm, 'machine_name');
|
||||
if (empty($modules[$perm])) {
|
||||
$args = array('!name' => $perm, '!module' => $module,);
|
||||
$msg = t('Warning in features rebuild of !module. No module defines permission "!name".', $args);
|
||||
drupal_set_message($msg, 'warning');
|
||||
continue;
|
||||
}
|
||||
// Export vocabulary permissions using the machine name, instead of
|
||||
// vocabulary id.
|
||||
foreach ($roles as $role) {
|
||||
if (in_array($role, $permission['roles'])) {
|
||||
$permissions_by_role[$role][$perm] = TRUE;
|
||||
}
|
||||
else {
|
||||
$permissions_by_role[$role][$perm] = FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Write the updated permissions.
|
||||
foreach ($roles as $rid => $role) {
|
||||
if (isset($permissions_by_role[$role])) {
|
||||
user_role_change_permissions($rid, $permissions_by_role[$role]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_features_export().
|
||||
*/
|
||||
function user_role_features_export($data, &$export, $module_name = '') {
|
||||
$export['dependencies']['features'] = 'features';
|
||||
$map = features_get_default_map('user_role', 'name');
|
||||
foreach ($data as $role) {
|
||||
// Role is provided by another module. Add dependency.
|
||||
if (isset($map[$role]) && $map[$role] != $module_name) {
|
||||
$export['dependencies'][$map[$role]] = $map[$role];
|
||||
}
|
||||
// Export.
|
||||
elseif(user_role_load_by_name($role)) {
|
||||
$export['features']['user_role'][$role] = $role;
|
||||
}
|
||||
}
|
||||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_features_export_options().
|
||||
*/
|
||||
function user_role_features_export_options() {
|
||||
return drupal_map_assoc(_user_features_get_roles(FALSE));
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_features_export_render().
|
||||
*/
|
||||
function user_role_features_export_render($module, $data) {
|
||||
$code = array();
|
||||
$code[] = ' $roles = array();';
|
||||
$code[] = '';
|
||||
|
||||
foreach ($data as $name) {
|
||||
if ($role = user_role_load_by_name($name)) {
|
||||
unset($role->rid);
|
||||
$role_identifier = features_var_export($name);
|
||||
$role_export = features_var_export($role , ' ');
|
||||
$code[] = " // Exported role: {$name}.";
|
||||
$code[] = " \$roles[{$role_identifier}] = {$role_export};";
|
||||
$code[] = "";
|
||||
}
|
||||
}
|
||||
|
||||
$code[] = ' return $roles;';
|
||||
$code = implode("\n", $code);
|
||||
return array('user_default_roles' => $code);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_features_revert().
|
||||
*/
|
||||
function user_role_features_revert($module) {
|
||||
user_role_features_rebuild($module);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_features_rebuild().
|
||||
*/
|
||||
function user_role_features_rebuild($module) {
|
||||
if ($defaults = features_get_default('user_role', $module)) {
|
||||
foreach ($defaults as $role) {
|
||||
$role = (object) $role;
|
||||
if ($existing = user_role_load_by_name($role->name)) {
|
||||
$role->rid = $existing->rid;
|
||||
}
|
||||
user_role_save($role);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate $rid => $role with role names untranslated.
|
||||
*/
|
||||
function _user_features_get_roles($builtin = TRUE) {
|
||||
$roles = array();
|
||||
foreach (user_roles() as $rid => $name) {
|
||||
switch ($rid) {
|
||||
case DRUPAL_ANONYMOUS_RID:
|
||||
if ($builtin) {
|
||||
$roles[$rid] = 'anonymous user';
|
||||
}
|
||||
break;
|
||||
case DRUPAL_AUTHENTICATED_RID:
|
||||
if ($builtin) {
|
||||
$roles[$rid] = 'authenticated user';
|
||||
}
|
||||
break;
|
||||
default:
|
||||
$roles[$rid] = $name;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return $roles;
|
||||
}
|
||||
|
||||
/**
|
||||
* Represent the current state of permissions as a perm to role name array map.
|
||||
*/
|
||||
function _user_features_get_permissions($by_role = TRUE) {
|
||||
$map = user_permission_get_modules();
|
||||
$roles = _user_features_get_roles();
|
||||
$permissions = array();
|
||||
foreach (user_role_permissions($roles) as $rid => $role_permissions) {
|
||||
if ($by_role) {
|
||||
foreach (array_keys(array_filter($role_permissions)) as $permission) {
|
||||
if (isset($map[$permission])) {
|
||||
$permissions[$permission][] = $roles[$rid];
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
$permissions[$roles[$rid]] = array();
|
||||
foreach ($role_permissions as $permission => $status) {
|
||||
if (isset($map[$permission])) {
|
||||
$permissions[$roles[$rid]][$permission] = $status;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return $permissions;
|
||||
}
|
Reference in New Issue
Block a user