0

We have a medium-sized Drupal 7 site whose configuration is almost entirely stored in code, in a single Features module. In order to permit automated testing and a cleaner development workflow, I'd like to make it possible to install a new instance of the site from scratch without cloning the database. To that end, I've created a simple install profile (based on the standard profile) which enables our themes and configuration module. This mostly seems to work, but I've found that some feature components are not immediately reverted on the newly-installed site: specifically, blocks exported with fe_block_settings, user permissions, and variables. All these are applied if I run drush fra -y from the command line after installing the new site, but I would like to do everything programmatically to make writing tests easier.

There is some discussion of the problem with blocks at https://www.drupal.org/node/1901116, but I've tried the fix given there (calling module_install in the hook_install implementation instead of listing a dependency in the .info file), without successs so far. That page also doesn't address the issues I'm seeing with variables and user permissions.

Is it possible to successfully apply all of these exported feature components from an install hook, or do I need some other mechanism?

1

In short: the workaround is to call drupal_flush_all_caches() and drupal_static_reset() before reverting the module containing exported features again from an install task.

In detail: The main symptom observed was that blocks (exported as fe_block_settings components), were not correctly applied on the new site when they depended on a Views block display defined in the same features module. This remained true even after adding an additional call to features_revert_module() in an installation task. (There were also problems at one point with variables and permissions, but these were cleared up more easily by the addition of the call to features_revert_module()).

The problem with settings for views blocks is that Views caches all views loaded from the database in a static variable, making any views loaded or enabled for the first time during a single request or drush command invisible to later calls to views_block_info(). One possible (tested) workaround is the following:

views_get_all_views(TRUE);
drupal_flush_all_caches();
features_revert_module('xyz');

Supplying TRUE for the $reset parameter to views_get_all_views() forces the module to discard its static cache and re-compute the list of blocks from scratch. This allows the revert of block settings to go through correctly.

Because I suspect this will not be the only problem caused by invalid static variable caches, I am trying the more drastic approach of resetting all static variables and clearing all caches before reverting the module:

drupal_static_reset();
drupal_flush_all_caches();
features_revert_module('xyz');

(Resetting all static variables does produce a few extra PHP warnings, which hopefully are spurious.)

The above lines are run as an installation task, and are combined with the approach described in https://www.drupal.org/node/1901116: i.e., remove the module with exported blocks from the dependencies[] list, and enable it manually in hook_install() after enabling themes for the site. The complete implementation in the profile .install file then looks more like this, where the installation profile is named foo, the features module is named xyz and the site theme quux:

/**
 * Implements hook_install().
 */
function foo_install() {

  // ... other setup code here ...

  // Enable themes
  theme_enable(array('seven', 'quux'));
  variable_set('admin_theme', 'seven');
  variable_set('node_admin_theme', '1');
  variable_set('theme_default', 'quux');

  // Enable module containing features-exported block settings
  module_enable(array('xyz'));
}

/**
 * Implements hook_install_tasks().
 */
function foo_install_tasks(&$install_state) {
  $tasks = array(
    'foo_revert_xyz' => array(
      'display_name' => st('Apply all settings in "xyz" module'),
      'type' => 'normal',
    ),
  );
  return $tasks;
}

function foo_revert_xyz() {
  drupal_flush_all_caches();
  drupal_static_reset();
  features_revert_module('xyz');
}

Tracking this down was a real headache, so I hope the solution is useful to someone else.

0

Here is approach that I am using to automate creation of the Drupal site from scratch:

  1. Create new installation profile and add all required modules and features as dependencies to the profile .info file
  2. Run drush site-install {{ profile }} -y to install site
  3. Run drush features-revert-all -y to revert all features
  4. Run drush cache-clear all to clear all caches

I've noticed that if simply install feature as a module, then not all feature components are reverted, that is why step #3 is required.

If you install feature by running module_install then you should run features_revert afterwards http://drupalcontrib.org/api/drupal/contributions%21features%21features.module/function/features_revert/7

  • Thanks for your answer, which confirms that others have seen the same problem. Indeed, if I follow these three steps with drush, there are no issues. However, I'd like to be able to rely on these settings from automated SimpleTests, for which manually running drush is not possible. I will see if it works to call features_revert from the setup method of the test case class. – Jon O. Dec 7 '14 at 18:48
  • Does it work for you with feature-revert()? – Eugene Fidelin Dec 11 '14 at 12:31
  • I haven't had the time to find out if it works in a SimpleTest yet. I do know that calling features_revert or features_revert_module from hook_install or from an install task doesn't seem to work. I know that API functions which depend on the database schema are advertised not to work during hook_install, so I wonder if the problems are related to that. – Jon O. Dec 11 '14 at 20:09
  • It does work to call features_revert() from an installation task, but you have to reset static variables and clear caches first to make some settings (notably blocks) be applied consistently. Please have a look at my answer. – Jon O. Dec 13 '14 at 19:21

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.