This a great module with one minor feature missing (at least for me!). :o)

I have a site with lots of nodes for particular content types and I would prefer not to set up a contextual view mode for each node. Would it be possible to set a default set of view modes for a content type that would be inherited by each node if they don't have their own setting?

Thanks

Comments

sherakama’s picture

Your request makes complete sense.

Shouldn't be too difficult to do. I will see if I can find some time over the holidays to add this functionality.

Thanks for the idea.

PedroKTFC’s picture

Thanks for the encouragement! :o)

I've had a go at putting something together (my first attempt at php of any significance!). I used your module and view_mode_modal as guides and came up with my attempt below. It works for me but it obviously needs a proper review and testing. It's also untidy so far. For example, if you delete a context or view mode, I don't clean up what's stored for the content type. It doesn't seem to cause problems (Drupal seems to handle the case with reasonable defaults) but ideally it would be better tidied up.

Anyway, comments welcome!

/**
 *  Hook to set up the context view mode options for each of the possible display modes.
 *  The user chooses a context for each of the view modes if wanted.
 *
 */

function mymodule_form_field_ui_display_overview_form_alter(&$form, $form_state, $form_id) {

  $entity_type = $form['#entity_type'];
  $bundle = $form['#bundle'];

  $bundle_settings = field_bundle_settings ($entity_type, $bundle);
  //load entity information
  $entity = entity_get_info($entity_type);

  // Load current settings if any
  $context_view_modes_saved = isset($bundle_settings['context_view_modes']) ? $bundle_settings['context_view_modes'] : '';
  
  // Add additional settings vertical tab if not already there.
  if (!isset($form['additional_settings'])) {
    $form['additional_settings'] = array(
      '#type' => 'vertical_tabs',
      '#theme_wrappers' => array('vertical_tabs'),
      '#prefix' => '<div>',
      '#suffix' => '</div>',
      '#tree' => TRUE,
    );
    $form['#attached']['js'][] = 'misc/form.js';
    $form['#attached']['js'][] = 'misc/collapse.js';
  }
  
  $form['additional_settings']['context_view_modes'] = array(
    '#type' => 'fieldset',
    '#title' => t('Contextual display mode settings'),
    '#description' => t('You can link view modes to specific contexts but be aware they will be overridden if the nodes have their own settings.'),
    '#collapsible' => TRUE,
    '#collapsed' => TRUE,
    '#parents' => array('additional_settings'),
    '#weight' => 100,    
  );

  $contexts = array('default' => '-Default-');
  $contexts += context_context_list();

  $ds_modes = ds_entity_view_modes('node');

  foreach($ds_modes as $key => $mode) {
    $form['additional_settings']['context_view_modes'][$key] = array(
      '#type' => 'select',
      '#title' => t("Use ") . $mode['label'] . t(' when context:'),
      '#options' => $contexts,
      '#default_value' => isset($context_view_modes_saved[$key]) ? $context_view_modes_saved[$key] : '',
    );
  }
  
  //add a custom submit handler
  $form['#submit'][] = 'mymodule_field_ui_display_overview_form_submit';
  
}


/**
 * Submit handler for field_ui_display_overview_form form
 */
function mymodule_field_ui_display_overview_form_submit($form, &$form_state) {

  $form_values = $form_state['values'];
  $entity_type = $form['#entity_type'];
  $bundle = $form['#bundle'];
  $view_mode = $form['#view_mode'];

/*
*  We need to know all the possible view modes so we can loop over them and read what the user has set for them
*/
  $ds_modes = ds_entity_view_modes('node');

  $context_view_modes_new = array ();
  foreach($ds_modes as $key => $mode) {
    $context_view_modes_new[$key] = $form_values['additional_settings'][$key];
  }
  
  // Get current bundle settings and update them with the new context view modes (if any)
  $bundle_settings = field_bundle_settings($entity_type, $bundle);
  $bundle_settings['context_view_modes'] = $context_view_modes_new;

  // Save updated bundle settings.
  field_bundle_settings($entity_type, $bundle, $bundle_settings);

}

/**
 *  Now choose the mode to use to display the node
 * @param  $build  The build array that drupal_render() expects
 */
function mymodule_node_view_alter(&$build) {

 // To avoid an endless loop do this v
  static $call_once;
  $call_once++;
  if($call_once >= 2) { return; }

  // Only work with nodes when on page view
  $a0 = arg(0);
  $a1 = arg(1);
  if($a0 !== "node" || !is_numeric($a1)) { return; }

  // Get current node
  $node = $build['#node'];

  // If v is not set then we want to run our version of ds_extras display switch
  if(isset($_GET['v'])) { return; } // v is set. Dont eff with that

  if(!isset($node->cvw)) {  // **** I to change this from your version as it didn't seem to work for me ****

    //Get bundle and entity type then get the settings that include the contextual display modes for the content type (if any)
    $bundle = $build['#bundle'];
    $entity_type = $build['#entity_type'];
    $bundle_settings = field_bundle_settings($entity_type, $bundle);

    if (!isset($bundle_settings['context_view_modes'])) { return;}  // Nothing to do!
    else {
  	 
    	 /*
      *  We need to know all the possible view modes so we can loop over them and match them with the active context
      *  (if more that one use the first)!
      */
      $ds_modes = ds_entity_view_modes('node');
      $contexts = context_active_contexts();

      $context_view_modes_new = array ();
      foreach($contexts as $context_name => $context) {
        foreach($ds_modes as $key => $mode) {
          if ($bundle_settings['context_view_modes'][$key] == $context_name) {
            $build = node_view($node, $key);
            return; // take only the first match
            }  
          }
        }
  	   }
  	 }

  // The content type has no context display modes so check if the node itself has  	 
  	 
  // Get all of the contexts that have a match
  $contexts = context_active_contexts();

  // Loop through each context and see if this node has a view mode assigned
  // to a valid context
  foreach($contexts as $context_name => $context) {
   if(isset($node->cvw[$context_name]) && count($node->cvw[$context_name]) && $node->cvw[$context_name] !== "default") {
      $node->ds_switch = $node->cvw[$context_name];
      $build = node_view($node, $node->ds_switch);
      return; // take only the first match
    }
  }

}
sherakama’s picture

Hmm. Interesting approach.

I'm not so sure adding it to the field ui was the right choice.

You have also given me some inspiration to actually make this properly instead of a bunch of variables loaded into a node. I think I will go about creating a proper settings page where users can enable which content types they would like to have available to use the CVM as well as turn the select fields into a real field instead of a hackey bunch of form settings.

On that configuration page we can also have the default settings for the enabled content types.

7.x-1.2 will be the release for these.

Thanks!

PedroKTFC’s picture

As I said, I used view_mode_modal as a guide as well as your original. I'll be happy with whatever you decide. Just need to be sure that there's a hierarchy of settings so that if you set it up for, say, an individual article, it "trumps" the setting for articles in general.

I'm using my approach at the moment but I'll move over to yours when you release it.

Fun, fun, fun!

kingswoodute’s picture

Subscribe - would love to use this feature or to be able to bulk apply the setting to all existing nodes of a content type.

Thanks very much for the work you're doing!

sherakama’s picture

Assigned: Unassigned » sherakama
Status: Active » Needs review

This is now available in the 7.x-1.2 release.

Enjoy!

sherakama’s picture

Status: Needs review » Fixed
dman’s picture

Thankyou. I was looking for this and couldn't find it at first.
It turns up on the global config screen admin/structure/cvm *after* we've selected the content type to work with.

Conceptually, I was really expecting this to turn up to be managed through context UI.
- if this context is set
- then use this layout

But I can see how this works too.

I got into the code, and found it's still really assuming that we'll be using the per-node settings. As my only use case is global, that might be overhead that could be optional.

sherakama’s picture

You raise good points. I don't really like the way that the admin form works anyhow. It was a bit of a rush implementation to begin with. I think a context managed plugin would be a good idea. I will create a new ticket for that.

dman’s picture

I had to patch it three times to get it working as needed for me. (including an alternate parsing fix for #1887908: Error when trying to set global settings)

I've not got a clean patch, mostly because the way settings form currently works with the concatenated tokens - is pretty awful.
I'd prefer we refactored it and used a $form['#tree']=TRUE then the global settings array would be more consistent. It would also mean we don't have to unpack it when saving.
I've got some dirty patches that I'll try to clean up a little maybe.

My current work is a quick&dirty proof-of-concept - using this for some A/B user testing on a site - "Which of the display layouts works best". This is handy to set a global switch to change the displays, but client doesn't want to invest in really fixing it beyond "works enough".
But I've got the issues in my hot-patched code...

BUT, this does do a good job at what I think is a really handy idea, so I'm interested in following up a little.

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for 2 weeks with no activity.