public static function Features::revert in Hook Update Deploy Tools 8
Same name and namespace in other branches
- 7 src/Features.php \HookUpdateDeployTools\Features::revert()
Safely revert an array of Features and provide feedback.
The safety steps include: a) Making sure the Feature exists (is enabled). b) Checks to see if the Feature is overridden.
Parameters
string[]|string $feature_names: One or more features or feature.component pairs. (in order)
bool $force: Force revert even if Features assumes components' state are default.
Return value
string Messsage indicating progress of feature reversions.
Throws
\DrupalUpdateException Calls the update a failure, preventing it from registering the update_N.
File
- src/
Features.php, line 27
Class
- Features
- Public method for reverting Features only if needed.
Namespace
HookUpdateDeployToolsCode
public static function revert($feature_names, $force = FALSE) {
$feature_names = (array) $feature_names;
$completed = array();
$message = '';
$total_requested = count($feature_names);
$t = get_t();
try {
Check::canUse('features');
module_load_include('inc', 'features', 'features.export');
// Check all functions that we plan to call are available.
// Exceptions are preferable to fatal errors.
Check::canCall('features_include');
Check::canCall('features_load_feature');
Check::canCall('features_hook');
// Pick up new files that may have been added to existing Features.
features_include(TRUE);
$feature_names = self::parseFeatureNames($feature_names);
// See if the feature needs to be reverted.
foreach ($feature_names as $feature_name => $components_needed) {
self::hasComponent($feature_name, $components_needed);
$variables = array(
'@feature_name' => $feature_name,
);
// If the Feature exists, process it.
if (Check::canUse($feature_name) && ($feature = features_load_feature($feature_name, TRUE))) {
$components = array();
if ($force) {
// Forcefully revert all components of the Feature.
// Gather the components to revert them all.
foreach (array_keys($feature->info['features']) as $component) {
if (features_hook($component, 'features_revert')) {
$components[] = $component;
}
}
$message = "Revert (forced): @feature_name.";
Message::make($message, $variables, WATCHDOG_INFO, 2);
}
else {
// Only revert components that are detected to be
// Overridden || Needs review || Rebuildable.
$message = "Revert: @feature_name.";
$states = features_get_component_states(array(
$feature->name,
), FALSE);
// Build list of components that can be reverted and need to be.
foreach ($states[$feature->name] as $component => $state) {
$revertable_states = array(
FEATURES_OVERRIDDEN,
FEATURES_NEEDS_REVIEW,
FEATURES_REBUILDABLE,
);
// If they are revertable, add them to the list.
if (in_array($state, $revertable_states) && features_hook($component, 'features_revert')) {
$components[] = $component;
}
}
}
if (!empty($components_needed) && is_array($components_needed)) {
// From list of components that need to be reverted, keep only the
// components that were requested.
$components = array_intersect($components, $components_needed);
}
if (empty($components)) {
// Not overridden, no revert required.
$message = 'Skipped - not currently overridden.';
$completed[$feature_name] = $message;
}
// Process the revert on each component.
foreach ($components as $component) {
$variables['@component'] = $component;
if (features_feature_is_locked($feature_name, $component)) {
// Trying to revert a locked component should raise an exception,
// but it may have been caused by a blanket revert, so just raise
// a warning instead of failing the update.
$message = 'Revert @feature_name.@component: Skipped - locked.';
Message::make($message, $variables, WATCHDOG_WARNING);
$completed[$feature_name][$component] = 'Skipped - locked.';
}
else {
// Ok to proceed by reverting this component.
features_revert(array(
$feature_name => array(
$component,
),
));
// Now check to see if it actually reverted.
if (self::isOverridden($feature_name, $component)) {
$message = '@feature_name.@component: Remains overridden. Check for issues.';
global $base_url;
$link = $base_url . '/admin/structure/features';
Message::make($message, $variables, WATCHDOG_WARNING, 1, $link);
$message = "Overridden - Check for issues.";
}
else {
// Not shown as overridden so most likely a success.
$message = "Success";
}
$completed[$feature_name][$component] = format_string($message, $variables);
}
}
$variables['!completed'] = $completed[$feature_name];
// Log a message about the entire Feature.
$message = "Reverted @feature_name : !completed";
Message::make($message, $variables, WATCHDOG_INFO);
}
}
} catch (\Exception $e) {
$vars = array(
'!error' => method_exists($e, 'logMessage') ? $e
->logMessage() : $e
->getMessage(),
);
if (!method_exists($e, 'logMessage')) {
// Not logged yet, so log it.
$message = 'Feature revert denied because: !error';
Message::make($message, $vars, WATCHDOG_ERROR);
}
// Output a summary before shutting this down.
$done = HudtInternal::getSummary($completed, $total_requested, 'Reverted');
Message::make($done, array(), FALSE, 1);
throw new HudtException('Caught Exception: Update aborted! !error', $vars, WATCHDOG_ERROR, FALSE);
}
// Log and output a summary of all the requests.
$done = HudtInternal::getSummary($completed, $total_requested, 'Reverted');
$message = Message::make('The requested reverts were processed. !done', array(
'!done' => $done,
), WATCHDOG_INFO);
return $message;
}