3

I've been looking into the Feature module to move changes from Dev to Staging without redoing everything.

On my Dev site I made changes in the content types (added new fields, deleted some field). Then I exported all content types as a feature and imported in to Staging. But still I see the deleted fields on staging.

I thought to delete all content types on staging and enable the module exported by feature but there is no delete option in content types.

Am I doing it in the correct way?

enter image description here enter image description here

2
  • "Delete content type" appeared after i disabled the feature generated module.
    – brainHax
    Commented Dec 6, 2015 at 15:17
  • i deleted all content types, and then enabled the features generated module of content types. All the content has empty "body" and the webforms are empty aswell.
    – brainHax
    Commented Dec 6, 2015 at 15:40

4 Answers 4

2

The answer to your question boils down to what is mentioned by the Features maintainer in this comment, i.e.:

FInally going to mark this as "won't fix" until somebody proposes something better.

1) Features will never do anything that might cause content to be lost on your site. This includes deleting fields. Just because you remove a field from a feature doesn't mean you might not still have content stored that would be lost if features auto-deleted it. I've never been in favor of any sort of auto-deletion.

2) Now that fields are split into bases and instances, this gets even more complicated.

The next comment in that same issue includes a link to a 32 steps process, which describes Deleting a Drupal Field Saved in Features. IMHO this is "as good as it gets" today (and my recommended work around until further notice).

1
  • Okay so for the mean time I will go for deleting the fields manually from the content type before enabling a feature. As long as the features is adding new fields, I don't have a problem . any how just one thing to confirm " I should not delete the content types on stag site , instead I should enable the feature and revert. ? "
    – brainHax
    Commented Dec 6, 2015 at 21:26
1

The right way of deploying the changes between the environment including delete operations can be achieved by drush command or hook_update() as part of your deployment, since auto-deletion of any content by Features module is not possible to avoid any content lost (which is the last thing that you want to do on your production). See: #649298 for further details.

hook_update

Here is example by using hook_update():

/** 
 * Deletes fields.
 */
function MYMODULE_update_7001() {
  $fields = array(
    'field_foo',
    'field_bar',
  );
  foreach($fields as $field) {
    if (field_info_field($field)) { 
      field_delete_field($field);
      field_purge_batch(10);
      drupal_is_cli() ? drush_log("Deleting field $field", "ok") : NULL;
    };
  }
}
?>

or this one posted at GH gist by insparrow:

<?php
/**
 * Remove a shared field from a content type.
 */
function custom_module_update_7027() {

  // Fetch instance info.
  $entity_type = drush_field_get_entity_from_bundle('custom_content_type');
  $instance = field_info_instance($entity_type, 'field_to_remove', 'custom_content_type');

  // Mark field for deletion.
  field_delete_instance($instance);

  // Remove field marked for deletion.
  field_purge_batch(10);

  watchdog('custom_module', 'Removed field_to_remove instance from custom_content_type', array(), WATCHDOG_INFO);
}
  • field_delete_field

    Marks a field and its instances and data for deletion.

  • field_purge_batch

    This function will purge deleted field data in batches. If a deleted field instance with no remaining data records is found, the instance itself will be purged. If a deleted field with no remaining field instances is found, the field itself will be purged.

drush

Use drush which can be invoked as part of your deployment process and its field-delete command.

For example:

drush field-delete field_name

to delete a field and its instances.

To delete only instance attached to specific bundle, try:

field-delete field_name --bundle=bundle

Alternatively you can consider to implement your own drush command which find all abandoned fields and removes them.

Here is example code posted by Chi:

<?php

/**
 * @file
 * Drush command to find all abandoned fields.
 *
 * @see http://drupal.org/node/649298
 */

/**
 * Implements hook_drush_command().
 */
function abandoned_fields_drush_command() {

  $items['abandoned-fields'] = array(
    'description' => 'Find all abandoned fields',
    'drupal dependencies' => array('features'),
    'aliases' => array('af'),
  );

  return $items;
}

/**
 * Drush command callback;
 */
function drush_abandoned_fields() {
  module_load_include('inc', 'features', 'features.export');

  $commited_fields = array();
  foreach (features_get_default('field') as $id => $field) {
    if (!in_array($field['field_config']['field_name'], $commited_fields)) {
      $commited_fields[] = $field['field_config']['field_name'];
    }
  }

  $rows[] = array('Field name', 'Location');
  $rows[] = array('-------------', '----------');
  foreach (field_info_fields() as $field_name => $field) {
    if (!in_array($field_name, $commited_fields)) {
      $bundle_strs = array();
      foreach ($field['bundles'] as $entity_type => $bundles) {
        $bundle_strs[] = $entity_type . ' (' . implode(',', $bundles) . ')';
      }
      $rows[]= array(
        $field_name,
        implode(' ', $bundle_strs),
      );
    }
  }
  drush_print_table($rows);
}

For further details, you may want to read Deleting a Drupal Field Saved in Features.

0

So on staging, you updated the custom content type feature folder/files and did drush fr machine_name_of_your_content_type_feature -y right? This assumes that you already have the custom content type feature installed in your staging site.

drush fr should apply all the new changes from code into your staging site's DB.

Also if your deleting fields in the staging site, might want to double check if you need to manually delete the field using hook_upadte_N. An example and discussion can be found here https://www.drupal.org/node/649298#comment-10219951. It can also be the basis for the code you want to execute.

6
  • I am not using Drush on staging. I just packed all content types in a feature module and placed it on staging. Enabled the module and i was able to see the fields on staging, which were not on dev ( means were deleted on the dev )
    – brainHax
    Commented Dec 6, 2015 at 15:48
  • Oh ok. Did you try to do Revert Components? Commented Dec 6, 2015 at 16:06
  • Yes i selected "Field Base" as shown above in the picture # 2 and clicked on revert. but nothing changed.
    – brainHax
    Commented Dec 6, 2015 at 16:09
  • So just to see if I understand you correctly, in staging, all your desired new configurations were applied including adding new fields but the issue is only the removed fields still exists? Am I right? If yes then you may need to do the recommendation I specified on the last sentence where you need to delete them manually. I have updated my answer for a reference on this. Commented Dec 6, 2015 at 16:21
  • Okay I will give it a try. But is it suppose to work this way ? . I will be doing changes in the content types every now and then and exporting and importing it to the staging site . every Time I won't get what I am expecting ?
    – brainHax
    Commented Dec 6, 2015 at 17:31
0

You may try Features Cleanup sandbox module (GH fork) as add-on to Features which can do cleanup of fields, vocabularies, panel nodes, mini panels, and image styles that are in the database, but not in any enabled features module.

This is potentially dangerous module, since it can irreversibly delete database components once they got removed from the Features, so you should test it first if that meets your expectations and it has been tested with your deployment plan and scripts.

This module is separated into two different tasks:

  • Resolve Overrides

    You will have new option Resolve All Overrides at the bottom of Feature's overview screen which will attempt to cleanup all overrides by deleting existing database components (mainly fields). After that, it will revert this feature.

  • Delete existing components that are not in any Features modules

    This includes: content types, mini panels, node panels, taxonomy vocabularies, image styles, etc.

    Before doing it, you need to enable all features that you want to compare against. Then click on Features Cleanup in the Features listing screen.

This module also has drush integration and provides the following commands:

  • drush fca/drush features-cleanup-all

    Cleans out all content types, panel pages, mini panels, vocabularies, and image styles from database based on existing enabled features and run features-revert-all afterwards. This is useful to include as part of your deployment process before you backup your database.

  • drush fcf/drush features-cleanup-feature [feature name] [component list]

    Attempts to resolves all overrides on a single feature module. Run features-revert afterwards.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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