Download & Extend

Deleting inactive fields/instances may fail

Project:Update API
Version:6.x-1.x-dev
Component:Code
Category:task
Priority:normal
Assigned:Unassigned
Status:needs review

Issue Summary

If a field or instance is inactive, the normal CCK crud function used by update_api_content_field_delete() won't delete it. This can be an issue when using the Features module, for instance, where a field that is removed from a feature gets marked inactive but not totally deleted, especially if you have changed your mind about a field and added, but then removed, it from a feature.

You could get around this by adding the following code to update_api_content_field_delete before attempting to delete the field which will re-active the field and instance before attempting to delete them. If it is already active it won't hurt anything, but if it is inactive it will ensure the delete will work as you expect it to. You have to clear the content type cache after updating the database or the new values won't get used:

<?php
  db_query
("UPDATE {content_node_field} SET active=1 WHERE field_name='%s'", $field_name);
 
db_query("UPDATE {content_node_field_instance} SET widget_active=1 WHERE field_name='%s' and type_name='%s'", $field_name, $type_name);
 
content_clear_type_cache();
?>

Comments

#1

I had to solve the same problem yesterday, but without knowledge that any Update API exists. Here is my approach. The code is bit ugly since I needed to fix the site asap and I was writing it just for internal use.

The code is bit safer than just updating the "active property". It checks if the field's and widget's modules exists before reactivation and deletion.

<?php
/**
* Helper function to delete field instances.
*
* Similar to content_field_instance_delete() but it tries to handle inactive fields.
*/
function _site_content_field_instance_delete($field_name, $content_type) {
 
$ret = array();
 
$content_fields_table = content_field_tablename();
 
$content_instance_table = content_instance_tablename();
 
$field = db_fetch_object(db_query("SELECT * FROM {". $content_fields_table ."} WHERE field_name='%s'", $field_name));
 
$widget = db_fetch_object(db_query("SELECT * FROM {". $content_instance_table ."} WHERE field_name='%s' AND type_name='%s'", $field_name, $content_type));
  if (empty(
$field->module)) {
   
$ret = array('success' => FALSE, 'query' => sprintf('Field to remove **%s** wasn\'t found.', $field_name));
  }
  elseif(empty(
$widget->widget_module)) {
   
$ret = array('success' => FALSE, 'query' => sprintf('Field instance to remove **%s** at **%s** content type wasn\'t found.', $field_name, $content_type));
  }
  elseif (
$field->active && $widget->widget_active) {
   
content_field_instance_delete($field_name, $content_type, FALSE);
   
$ret = array('success' => TRUE, 'query' => sprintf('Field %s provided by the **%s** module was removed from the **%s** content type.', $field_name, $field->module, $content_type));
  }
  elseif (
module_exists($field->module) && module_exists($widget->widget_module)) {
   
db_query("UPDATE {". $content_fields_table ."} SET active=1  WHERE field_name='%s'", $field_name);
   
db_query("UPDATE {". $content_instance_table ."} SET widget_active=1 WHERE field_name='%s' AND type_name='%s'", $field_name, $content_type);
   
content_field_instance_delete($field_name, $content_type, FALSE);
   
// recover previous state if content_field_instance_delete failed
   
if (!$field->active) {
     
db_query("UPDATE {". $content_fields_table ."} SET active=0 WHERE field_name='%s'", $field_name);
    }
    if (!
$widget->widget_active) {
     
db_query("UPDATE {". $content_instance_table ."} SET widget_active=0 WHERE field_name='%s' AND type_name='%s'", $field_name, $content_type);
    }
   
$ret = array('success' => TRUE, 'query' => sprintf('Inactive field **%s** provided by the **%s** module was removed from the **%s** content type.', $field_name, $field->module, $content_type));
  }

  return
$ret;
}

/**
* Removes field_header_image, field_tell_me_more_links
*
* Fixes the updates site_content_update_6001 and site_content_update_6003 - fields were not
* deleted if the feature was reverted before the update.
*/
function site_content_update_6004() {
 
$ret = array();

 
// Load up cck crud interface
 
module_load_include('inc', 'content', 'includes/content.crud');

 
// Remove old fields from the page
 
$ret[] = _site_content_field_instance_delete('field_header_image', 'page');
 
$ret[] = _site_content_field_instance_delete('field_tell_me_more_links', 'page');

 
// Flush caches
 
content_clear_type_cache(TRUE);
 
menu_rebuild();

  return
$ret;
}
?>
nobody click here