Sometimes we want to uninstall a module from our Drupal site but we can't do it because we get this dependency: "Required by: Drupal (Field type(s) in use - see Field list)". Even if you delete the fields provided by the module via the UI or programmatically by executing field_delete_field() function you will get a new dependency "Required by: Drupal (Fields pending deletion)".
These dependencies are created by Drupal core to avoid a module being uninstalled until all the data related to its fields is removed from the database, in order to maintain consistency.
This has several drawbacks, the first one being that you can't uninstall your module when you want, and you have to wait until all the field data values are removed from the database (the rather strangely named field_deleted_data_XX and field_deleted_revision_XX tables) and the meta-information stored in field_config and field_config_instance tables is removed. And most importantly, nobody actually knows when this is going to happen! These database rows are removed in batches on each cron task execution. So depending on our cron regularity and the amount of data stored in our field tables, these tasks can last for minutes to weeks.
This is a problem because, naturally, we want to uninstall our module now and not be forced to check our production database repeatedly to see if we are allowed to uninstall the module once all that information has been removed from the database.
To avoid such situations and regain control, you can perform all these tasks in a hook_update_N() function, forcing the deletion of all the information and finally uninstalling the module. You can check the code in the gist below:
The job is divided in three parts: The data definition, field data purge and module list clean.
In the data definition task we provide all the required data we need to perform the task, the name of the field to delete, and given that information, we get the field_info array and the name of the module to be uninstalled. Finally, field_delete_field() is executed.
After that the field data is purged in the batch body, and since we don't know how much data we will have to purge, we remove just 100 database rows per batch execution. After each purge we check if all the data has been removed to decide if we have to remove more data from the database or continue to the final part.
Once all the data and metadata related to the module is removed from the database, the Drupal field types dependency is gone and we are granted the ability to disable and uninstall our module cleanly. Finally, we can drop the empty field_deleted_data_XX and field_deleted_revision_XX tables to keep our database clean.
Using this approach, we have two key benefits: a. we are sure that the module is disabled and our database is clean, and b. we are confident that we can remove the module from our repository, given that in the next deploy we won't get any dependency conflict with that module.
We'd love to partner with you on your next project!
Since we’re big on relationships, we’re all about finding the right fit. Will you take the next step with us to see if we’re a match?