Programmatic overriding of Display Suite layouts

Sometimes, for some reason, Display Suite layouts exported by features just don't display. As far as I can tell, this might be to do with special extra configuration in Display Suite, like custom region-to-block regions, or fields in code. But there wasn't time to look into it too closely; just to fix it post hoc!

You can get the defaults for a CTools exportable using the private function _ctools_export_get_defaults():

// Get the database schema for the exportable
$schema = ctools_export_get_schema('ds_layout_settings');
$export = $schema['export'];
 
// Use this schema to get the defaults - from the feature's pickled PHP objects
$defaults = _ctools_export_get_defaults('ds_layout_settings', $export);
 
// Extract the layout we want
$layout = $defaults['node|CONTENT_TYPE|full'];

This returns the Display Suite layout, as stored in the feature, for CONTENT_TYPE, which you can then mergeback into the ds_layout_settings table with:

// Overwrite existing entry with this layout ID
$q = db_merge('ds_layout_settings');
$q->key(array('id' => $layout->id));
 
// Fields to overwrite
$q->fields(array(
  'entity_type' => $layout->entity_type,
  'bundle' => $layout->bundle,
  'view_mode' => $layout->view_mode,
  'settings' => serialize($layout->settings),
  'layout' => $layout->layout,
));
 
// Go!
$q->execute();

Occasionally, we found we had to do the same thing with Display Suite field settings: it's exactly the same principle; here's the full code snippet for doing that:

// Get the database schema for the exportable
$schema = ctools_export_get_schema('ds_field_settings');
$export = $schema['export'];
 
// Use this schema to get the defaults - from the feature's pickled PHP objects
$fields_instances = _ctools_export_get_defaults('ds_field_settings', $export);
 
// Extract the layout we want
$fields_instance = $fields_instances['node|CONTENT_TYPE|full'];
 
// Overwrite existing entry with this fields instance ID
$q = db_merge('ds_field_settings');
$q->key(array('id' => $fields_instance->id));
 
// Fields to overwrite
$q->fields(array(
  'entity_type' => $fields_instance->entity_type,
  'bundle' => $fields_instance->bundle,
  'view_mode' => $fields_instance->view_mode,
  'settings' => serialize($fields_instance->settings),
));
 
// Go!
$q->execute();

We encapsulated both of these snippets in a single Drush command, making it very straightforward to run over and over again, and tweak as required.