View source
<?php
function configuration_populate($items, $dependencies) {
$items = array_filter($items);
$items['dependencies'] = drupal_map_assoc(array_filter($dependencies));
$stub = array(
'configuration' => array(),
'dependencies' => array(),
'conflicts' => array(),
);
$export = _configuration_populate($items, $stub);
drupal_alter('configuration_export', $export);
foreach (array_keys($export['configuration']) as $k) {
ksort($export['configuration'][$k]);
}
ksort($export['configuration']);
ksort($export['dependencies']);
return $export;
}
function _configuration_populate($pipe, &$export) {
configuration_include();
foreach ($pipe as $component => $data) {
if ($function = configuration_hook($component, 'configuration_export')) {
$more = $function($data, $export, $component);
drupal_alter('configuration_pipe_' . $component, $more, $data, $export);
if (!empty($more)) {
_configuration_populate($more, $export);
}
}
}
return $export;
}
function _configuration_export_minimize_dependencies($dependencies, $module_name = '') {
if (!empty($module_name) && !empty($dependencies[$module_name])) {
unset($dependencies[$module_name]);
}
$required = drupal_required_modules();
foreach ($dependencies as $k => $v) {
if (empty($v) || in_array($v, $required)) {
unset($dependencies[$k]);
}
else {
$module = configuration_get_modules($v);
if ($module && !empty($module->info['dependencies'])) {
if (in_array($module_name, $module->info['dependencies'])) {
unset($dependencies[$k]);
}
else {
foreach ($module->info['dependencies'] as $j => $dependency) {
if (array_search($dependency, $dependencies) !== FALSE) {
$position = array_search($dependency, $dependencies);
unset($dependencies[$position]);
}
}
}
}
}
}
return drupal_map_assoc(array_unique($dependencies));
}
function _configuration_export_maximize_dependencies($dependencies, $module_name = '', $maximized = array(), $first = TRUE) {
foreach ($dependencies as $k => $v) {
$parsed_dependency = drupal_parse_dependency($v);
$name = $parsed_dependency['name'];
if (!in_array($name, $maximized)) {
$maximized[] = $name;
$module = configuration_get_modules($name);
if ($module && !empty($module->info['dependencies'])) {
$maximized = array_merge($maximized, _configuration_export_maximize_dependencies($module->info['dependencies'], $module_name, $maximized, FALSE));
}
}
}
return array_unique($maximized);
}
function configuration_export_prepare($export, $module_name, $reset = FALSE) {
$existing = configuration_get_modules($module_name, $reset);
$defaults = $existing ? $existing->info : array(
'core' => '7.x',
'package' => 'Features',
);
$export = array_merge($defaults, $export);
foreach ($export['configuration'] as $component => $data) {
$export['configuration'][$component] = array_keys($data);
}
if (isset($export['dependencies'])) {
$export['dependencies'] = array_values($export['dependencies']);
}
if (isset($export['conflicts'])) {
unset($export['conflicts']);
}
ksort($export);
return $export;
}
function configuration_export_render_hooks($export, $module_name, $reset = FALSE) {
configuration_include();
$code = array();
$export['reset'] = $reset;
ksort($export['configuration']);
foreach ($export['configuration'] as $component => $data) {
if (!empty($data)) {
asort($data);
if (configuration_hook($component, 'configuration_export_render')) {
$hooks = configuration_invoke($component, 'configuration_export_render', $module_name, $data, $export);
$code[$component] = $hooks;
}
}
}
return $code;
}
function configuration_export_render($export, $reset = FALSE) {
$code = array();
$module_name = 'configuration';
$component_hooks = configuration_export_render_hooks($export, $module_name, $reset);
$components = configuration_get_components();
foreach ($component_hooks as $component => $hooks) {
$file = array(
'name' => 'configuration',
);
if (isset($components[$component]['default_file'])) {
switch ($components[$component]['default_file']) {
case CONFIGURATION_DEFAULTS_INCLUDED:
$file['name'] = "configuration.{$component}";
break;
case CONFIGURATION_DEFAULTS_CUSTOM:
$file['name'] = $components[$component]['default_filename'];
break;
}
}
if (!isset($code[$file['name']])) {
$code[$file['name']] = array();
}
foreach ($hooks as $hook_name => $hook_code) {
$code[$file['name']][$hook_name] = configuration_export_render_defaults($module_name, $hook_name, $hook_code);
}
}
foreach ($code as $filename => $contents) {
$code[$filename] = "<?php\n/**\n * @file\n * {$filename}.inc\n */\n\n" . implode("\n\n", $contents) . "\n";
}
return $code;
}
function configuration_detect_overrides($component, $identifier) {
if (!($cache = cache_get("{$component}:{$identifier}", 'cache_configuration'))) {
drupal_set_message(t("Could not find diff {$component}:{$identifier}"), 'error');
return FALSE;
}
return $cache->data;
}
function configuration_get_default_hooks($component = NULL, $reset = FALSE) {
static $hooks;
if (!isset($hooks) || $reset) {
$hooks = array();
configuration_include();
foreach (module_implements('configuration_api') as $module) {
$info = module_invoke($module, 'configuration_api');
foreach ($info as $k => $v) {
if (isset($v['default_hook'])) {
$hooks[$k] = $v['default_hook'];
}
}
}
}
if (isset($component)) {
return isset($hooks[$component]) ? $hooks[$component] : FALSE;
}
return $hooks;
}
function configuration_export_render_defaults($module, $hook, $code) {
$output = array();
$output[] = "/**";
$output[] = " * Implements hook_{$hook}().";
$output[] = " */";
$output[] = "function {$module}_{$hook}() {";
$output[] = $code;
$output[] = "}";
return implode("\n", $output);
}
function configuration_export_info($info, $parents = array()) {
$output = '';
if (is_array($info)) {
foreach ($info as $k => $v) {
$child = $parents;
$child[] = $k;
$output .= configuration_export_info($v, $child);
}
}
elseif (!empty($info) && count($parents)) {
$line = array_shift($parents);
foreach ($parents as $key) {
$line .= is_numeric($key) ? "[]" : "[{$key}]";
}
$line .= " = \"{$info}\"\n";
return $line;
}
return $output;
}
function configuration_tar_create($name, $contents) {
$tar = '';
$binary_data_first = pack("a100a8a8a8a12A12", $name, '100644 ', ' 765 ', ' 765 ', sprintf("%11s ", decoct(strlen($contents))), sprintf("%11s", decoct(REQUEST_TIME)));
$binary_data_last = pack("a1a100a6a2a32a32a8a8a155a12", '', '', '', '', '', '', '', '', '', '');
$checksum = 0;
for ($i = 0; $i < 148; $i++) {
$checksum += ord(substr($binary_data_first, $i, 1));
}
for ($i = 148; $i < 156; $i++) {
$checksum += ord(' ');
}
for ($i = 156, $j = 0; $i < 512; $i++, $j++) {
$checksum += ord(substr($binary_data_last, $j, 1));
}
$tar .= $binary_data_first;
$tar .= pack("a8", sprintf("%6s ", decoct($checksum)));
$tar .= $binary_data_last;
$buffer = str_split($contents, 512);
foreach ($buffer as $item) {
$tar .= pack("a512", $item);
}
return $tar;
}
function configuration_var_export($var, $prefix = '', $init = TRUE) {
if (is_object($var)) {
$output = method_exists($var, 'export') ? $var
->export() : configuration_var_export((array) $var);
}
elseif (is_array($var)) {
if (empty($var)) {
$output = 'array()';
}
else {
$output = "array(\n";
foreach ($var as $key => $value) {
$output .= " " . var_export($key, TRUE) . " => " . configuration_var_export($value, ' ', FALSE) . ",\n";
}
$output .= ')';
}
}
elseif (is_bool($var)) {
$output = $var ? '1' : '0';
}
elseif (is_string($var) && strpos($var, "\n") !== FALSE) {
$var = str_replace("\n", "***BREAK***", $var);
$output = var_export($var, TRUE);
}
elseif (is_numeric($var)) {
$output = is_int($var) ? var_export((int) $var, TRUE) : var_export((double) $var, TRUE);
}
else {
$output = var_export($var, TRUE);
}
if ($prefix) {
$output = str_replace("\n", "\n{$prefix}", $output);
}
if ($init) {
$output = str_replace("***BREAK***", "\n", $output);
}
return $output;
}
function configuration_translatables_export($translatables, $indent = '') {
$output = '';
$translatables = array_filter(array_unique($translatables));
if (!empty($translatables)) {
$output .= "{$indent}// Translatables\n";
$output .= "{$indent}// Included for use with string extractors like potx.\n";
sort($translatables);
foreach ($translatables as $string) {
$output .= "{$indent}t(" . configuration_var_export($string) . ");\n";
}
}
return $output;
}
function configuration_get_storage($module_name) {
$states = configuration_get_component_states(array(
$module_name,
), FALSE);
$states = array_diff($states[$module_name], array(
CONFIGURATION_DEFAULT,
));
$storage = !empty($states) ? max($states) : CONFIGURATION_DEFAULT;
return $storage;
}
function configuration_get_signature($state = 'default', $module_name, $component, $reset = FALSE) {
switch ($state) {
case 'cache':
$codecache = variable_get('configuration_codecache', array());
return isset($codecache[$module_name][$component]) ? $codecache[$module_name][$component] : FALSE;
case 'default':
$objects = configuration_get_default($component, $module_name, TRUE, $reset);
break;
case 'normal':
$objects = configuration_get_normal($component, $module_name, $reset);
break;
}
if (!empty($objects)) {
$objects = (array) $objects;
_configuration_sanitize($objects);
return md5(_configuration_linetrim(configuration_var_export($objects)));
}
return FALSE;
}
function configuration_set_signature($module, $component, $signature = NULL) {
$var_codecache = variable_get('configuration_codecache', array());
$signature = isset($signature) ? $signature : configuration_get_signature('default', $module, $component, TRUE);
$var_codecache[$module][$component] = $signature;
variable_set('configuration_codecache', $var_codecache);
}
function configuration_semaphore($op, $component) {
$semaphore = db_query("SELECT value FROM {variable} WHERE name = :name", array(
':name' => 'configuration_semaphore',
))
->fetchField();
$semaphore = !empty($semaphore) ? unserialize($semaphore) : array();
switch ($op) {
case 'get':
return isset($semaphore[$component]) ? $semaphore[$component] : FALSE;
case 'set':
$semaphore[$component] = REQUEST_TIME;
variable_set('configuration_semaphore', $semaphore);
break;
case 'del':
if (isset($semaphore[$component])) {
unset($semaphore[$component]);
variable_set('configuration_semaphore', $semaphore);
}
break;
}
}
function configuration_get_normal($component, $module_name, $reset = FALSE) {
static $cache;
if (!isset($cache) || $reset) {
$cache = array();
}
if (!isset($cache[$module_name][$component])) {
configuration_include();
$code = NULL;
$module = configuration_get_configuration($module_name);
if ($component === 'dependencies') {
$cache[$module_name][$component] = isset($module->info['dependencies']) ? array_filter($module->info['dependencies'], 'module_exists') : array();
}
else {
$default_hook = configuration_get_default_hooks($component);
if ($module && $default_hook && isset($module->info['configuration'][$component]) && configuration_hook($component, 'configuration_export_render')) {
$code = configuration_invoke($component, 'configuration_export_render', $module_name, $module->info['configuration'][$component], NULL);
$cache[$module_name][$component] = isset($code[$default_hook]) ? eval($code[$default_hook]) : FALSE;
}
}
unset($code);
unset($module);
}
return isset($cache[$module_name][$component]) ? $cache[$module_name][$component] : FALSE;
}
function configuration_get_default($component, $module_name = NULL, $alter = TRUE, $reset = FALSE) {
static $cache = array();
configuration_include();
configuration_include_defaults($component);
$default_hook = configuration_get_default_hooks($component);
$components = configuration_get_components();
if (isset($module_name)) {
$modules = array(
$module_name,
);
}
else {
if ($component === 'dependencies') {
$modules = array_keys(configuration_get_configurations());
}
else {
$modules = array(
'configuration',
);
}
}
foreach ($modules as $m) {
if (!isset($cache[$component][$m]) || $reset) {
if ($component === 'dependencies') {
$module = configuration_get_configuration($m);
$cache[$component][$m] = isset($module->info['dependencies']) ? $module->info['dependencies'] : array();
unset($module);
}
else {
if ($default_hook && module_hook($m, $default_hook)) {
$cache[$component][$m] = call_user_func("{$m}_{$default_hook}");
if ($alter) {
drupal_alter($default_hook, $cache[$component][$m]);
}
}
elseif ($default_hook && module_exists('ctools') && _ctools_configuration_get_info()) {
$info = _ctools_configuration_get_info();
if (isset($info[$component])) {
$function = $module_name . '_configuration_' . $info[$component]['default_hook'];
if (function_exists($function)) {
$cache[$component][$m] = call_user_func($function);
}
if ($alter) {
drupal_alter($default_hook, $cache[$component][$m]);
}
}
}
else {
$cache[$component][$m] = FALSE;
}
}
}
}
if (isset($module_name)) {
return isset($cache[$component][$module_name]) ? $cache[$component][$module_name] : FALSE;
}
$all_defaults = array();
if (isset($cache[$component])) {
foreach (array_filter($cache[$component]) as $module_components) {
$all_defaults = array_merge($all_defaults, $module_components);
}
}
return $all_defaults;
}
function configuration_get_default_map($component, $attribute = NULL, $callback = NULL, $reset = FALSE) {
static $map = array();
configuration_include();
configuration_include_defaults($component);
if ((!isset($map[$component]) || $reset) && ($default_hook = configuration_get_default_hooks($component))) {
$map[$component] = array();
foreach (module_implements($default_hook) as $module) {
if ($defaults = configuration_get_default($component, $module)) {
foreach ($defaults as $key => $object) {
if (isset($callback)) {
if ($object_key = $callback($object)) {
$map[$component][$object_key] = $module;
}
}
elseif (isset($attribute)) {
if (is_object($object) && isset($object->{$attribute})) {
$map[$component][$object->{$attribute}] = $module;
}
elseif (is_array($object) && isset($object[$attribute])) {
$map[$component][$object[$attribute]] = $module;
}
}
elseif (!isset($attribute) && !isset($callback)) {
if (!is_numeric($key)) {
$map[$component][$key] = $module;
}
}
else {
return FALSE;
}
}
}
}
}
return isset($map[$component]) ? $map[$component] : FALSE;
}
function configuration_get_component_states($configuration = array(), $rebuild_only = TRUE, $reset = FALSE) {
static $cache;
if (!isset($cache) || $reset) {
$cache = array();
}
$configuration = !empty($configuration) ? $configuration : array_keys(configuration_get_configuration());
configuration_include();
$components = array_keys(configuration_get_components());
if ($rebuild_only) {
foreach ($components as $k => $component) {
if (!configuration_hook($component, 'configuration_rebuild')) {
unset($components[$k]);
}
}
}
foreach ($configuration as $feature) {
$cache[$feature] = isset($cache[$feature]) ? $cache[$feature] : array();
if (module_exists($feature)) {
foreach ($components as $component) {
if (!isset($cache[$feature][$component])) {
$normal = configuration_get_signature('normal', $feature, $component, $reset);
$default = configuration_get_signature('default', $feature, $component, $reset);
$codecache = configuration_get_signature('cache', $feature, $component, $reset);
$semaphore = configuration_semaphore('get', $component);
if ($normal == $default) {
$cache[$feature][$component] = CONFIGURATION_DEFAULT;
configuration_semaphore('del', $component);
if ($default != $codecache) {
configuration_set_signature($feature, $component, $default);
}
}
elseif (!configuration_hook($component, 'configuration_rebuild')) {
$cache[$feature][$component] = CONFIGURATION_OVERRIDDEN;
}
else {
if (empty($semaphore)) {
if ($component === 'dependencies') {
$cache[$feature][$component] = CONFIGURATION_REBUILDABLE;
}
else {
if ($codecache == $default) {
$cache[$feature][$component] = CONFIGURATION_OVERRIDDEN;
}
elseif ($codecache == $normal || empty($codecache)) {
$cache[$feature][$component] = CONFIGURATION_REBUILDABLE;
}
elseif ($codecache != $default) {
$cache[$feature][$component] = CONFIGURATION_NEEDS_REVIEW;
}
}
}
else {
if (REQUEST_TIME - $semaphore < CONFIGURATION_SEMAPHORE_TIMEOUT) {
$cache[$feature][$component] = CONFIGURATION_REBUILDING;
}
else {
$cache[$feature][$component] = CONFIGURATION_REBUILDABLE;
}
}
}
}
}
}
}
$return = $cache;
$return = array_intersect_key($return, array_flip($configuration));
foreach ($return as $k => $v) {
$return[$k] = array_intersect_key($return[$k], array_flip($components));
}
return $return;
}
function _configuration_linetrim($code) {
$code = explode("\n", $code);
foreach ($code as $k => $line) {
$code[$k] = trim($line);
}
return implode("\n", $code);
}
function _configuration_sanitize(&$array) {
if (is_array($array)) {
if (_configuration_is_assoc($array)) {
ksort($array);
$array = array_filter($array);
}
else {
sort($array);
}
foreach ($array as $k => $v) {
if (is_array($v)) {
_configuration_sanitize($array[$k]);
}
}
}
}
function _configuration_is_assoc($array) {
return is_array($array) && (0 !== count(array_diff_key($array, array_keys(array_keys($array)))) || count($array) == 0);
}
function _configuration_track_dependencies($export) {
$save_also = array();
if (isset($export['configuration_dependency']) && !empty($export['configuration_dependency'])) {
foreach ($export['configuration_dependency']['configuration'] as $component => $info) {
foreach ($info as $name => $parent) {
if (!configuration_is_tracked($component, $name)) {
$save_also[$component][$name] = array(
'parent' => $parent,
'modules' => $export['configuration_dependency']['modules'][$component][$name],
);
}
else {
db_update('config_export')
->fields(array(
'parent' => $parent,
))
->condition('name', $name)
->execute();
}
}
}
}
if (!empty($save_also)) {
configuration_save($save_also);
}
}
function configuration_write_export_file($config = NULL, $dest = NULL) {
if (!$config) {
cache_clear_all('config_export', 'cache');
}
$config = $config ? $config : configuration_get_configuration();
$dest = $dest ? $dest : 'config://config.export';
$h = fopen($dest, 'w');
foreach ($config as $owner => $component) {
if (is_array($component)) {
foreach ($component as $name => $settings) {
fwrite($h, 'config[' . $owner . '][' . $name . '][status] = ' . $settings['status'] . "\n");
if (!empty($settings['hash'])) {
fwrite($h, 'config[' . $owner . '][' . $name . '][hash] = \'' . $settings['hash'] . "'\n");
}
fwrite($h, 'config[' . $owner . '][' . $name . '][parent] = \'' . $settings['parent'] . "'\n");
if (!empty($settings['dependencies'])) {
fwrite($h, 'config[' . $owner . '][' . $name . '][dependencies] = \'' . $settings['dependencies'] . "'\n\n");
}
}
}
}
fclose($h);
}
function configuration_write_exports($components = NULL, $exclude = array()) {
$config = configuration_get_configuration();
try {
if (configuration_check_changed(CONFIGURATION_DATASTORE_ONLY, $components)) {
$config_populate = configuration_populate_sanitize($config);
$export = configuration_populate($config_populate, array());
_configuration_track_dependencies($export);
foreach ($exclude as $identifier => $component) {
unset($export['configuration'][$component][$identifier]);
}
foreach (array_keys($export['configuration']) as $export_component) {
if (!in_array($export_component, $components)) {
unset($export['configuration'][$export_component]);
}
}
if ($files = configuration_export_render($export, TRUE)) {
$filenames = array();
foreach ($files as $filename => $file_contents) {
if (!in_array($filename, array(
'module',
'info',
))) {
$filename .= '.inc';
}
file_put_contents('config://' . $filename, $file_contents);
drupal_set_message(t('Wrote %file to filesystem', array(
'%file' => $filename,
)));
}
}
configuration_write_export_file();
}
else {
return FALSE;
}
} catch (Exception $e) {
watchdog_exception('configuration', $e);
throw $e;
}
return TRUE;
}
function configuration_check_changed($changed, $components, $config = NULL) {
$config = is_null($config) ? configuration_get_configuration() : $config;
foreach ($components as $component) {
if (array_key_exists($component, $config)) {
foreach ($config[$component] as $info) {
if ($info['status'] & $changed) {
drupal_set_message(t('Unable to write exports. Your datastore has configs that would be lost in %component.', array(
'%component' => $component,
)), 'error');
return FALSE;
}
}
}
}
return TRUE;
}