You are here

ds_extras.module in Display Suite 7

Display Suite extras main functions.

File

modules/ds_extras/ds_extras.module
View source
<?php

/**
 * @file
 * Display Suite extras main functions.
 */

/**
 * Implements hook_menu().
 */
function ds_extras_menu() {
  $items = array();
  $items['admin/structure/ds/extras'] = array(
    'title' => 'Extras',
    'description' => 'Configure extra functionality for Display suite.',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'ds_extras_settings',
    ),
    'access arguments' => array(
      'admin_display_suite',
    ),
    'file' => 'ds_extras.admin.inc',
  );
  if (variable_get('ds_extras_switch_field')) {
    $items['ds-switch-view-mode'] = array(
      'title' => 'Switch view',
      'description' => 'Switches a view mode inline.',
      'page callback' => 'ds_switch_view_mode_inline',
      'access arguments' => array(
        'access content',
      ),
      'file' => 'ds_extras.pages.inc',
      'type' => MENU_CALLBACK,
    );
  }
  if (variable_get('ds_extras_vd', FALSE) && module_exists('field_ui') && module_exists('views')) {
    $items['admin/structure/ds/vd'] = array(
      'title' => 'Views displays',
      'description' => 'Manage your views templates.',
      'page callback' => 'ds_extras_vd_overview',
      'file' => 'ds_extras.vd.inc',
      'access arguments' => array(
        'admin_display_suite',
      ),
    );
    $items['admin/structure/ds/vd/manage'] = array(
      'title' => 'Manage layout',
      'description' => 'Manage your views templates.',
      'page callback' => 'ds_extras_vd_manage',
      'file' => 'ds_extras.vd.inc',
      'access arguments' => array(
        'admin_display_suite',
      ),
    );
  }
  if (variable_get('ds_extras_contextual', FALSE) && module_exists('contextual') && module_exists('field_ui')) {
    $items['node/%node/display'] = array(
      'title' => 'Manage display',
      'description' => 'Manage display of this content.',
      'page callback' => 'ds_extras_contextual_page_tab',
      'page arguments' => array(
        1,
        'node',
      ),
      'file' => 'ds_extras.pages.inc',
      'access arguments' => array(
        'administer content types',
      ),
      'type' => MENU_LOCAL_TASK,
    );
    $items['user/%user/display'] = array(
      'title' => 'Manage display',
      'description' => 'Manage display of this user profile.',
      'page callback' => 'ds_extras_contextual_page_tab',
      'page arguments' => array(
        1,
        'user',
      ),
      'file' => 'ds_extras.pages.inc',
      'access arguments' => array(
        'administer users',
      ),
      'type' => MENU_LOCAL_TASK,
    );
    if (module_exists('taxonomy')) {
      $items['taxonomy/term/%taxonomy_term/display'] = array(
        'title' => 'Manage display',
        'description' => 'Manage display of this term.',
        'page callback' => 'ds_extras_contextual_page_tab',
        'page arguments' => array(
          2,
          'taxonomy_term',
        ),
        'access arguments' => array(
          'administer taxonomy',
        ),
        'type' => MENU_LOCAL_TASK,
        'weight' => 11,
        'file' => 'ds_extras.pages.inc',
      );
    }
  }

  // Panel view modes.
  if (variable_get('ds_extras_panel_view_modes')) {
    $items['admin/structure/panels/settings/ds-panels'] = array(
      'title' => 'Panel view modes',
      'description' => 'Configure which content is available to add to panel view mode displays.',
      'access arguments' => array(
        'admin_display_suite',
      ),
      'page callback' => 'ds_panels_view_mode_settings',
      'file' => 'ds_extras.panels.inc',
      'type' => MENU_LOCAL_TASK,
    );
  }
  return $items;
}

/**
 * Implements hook_theme().
 */
function ds_extras_theme() {
  $theme_functions = array();
  $field_functions = module_invoke_all('ds_field_theme_functions_info');
  foreach ($field_functions as $key => $label) {
    $theme_functions[$key] = array(
      'render element' => 'element',
      'function' => $key,
    );
  }
  return $theme_functions;
}

/**
 * Implements hook_entity_info().
 */
function ds_extras_entity_info() {
  module_load_include('inc', 'ds_extras', 'ds_extras.registry');
  return _ds_extras_entity_info();
}

/**
 * Implements hook_entity_info_alter().
 */
function ds_extras_entity_info_alter(&$entity_info) {
  module_load_include('inc', 'ds_extras', 'ds_extras.registry');
  return _ds_extras_entity_info_alter($entity_info);
}

/**
 * Implements hook_ds_layout_info_alter().
 */
function ds_extras_ds_layout_info_alter(&$layouts) {
  if (variable_get('ds_extras_hidden_region')) {
    foreach ($layouts as $key => $layout) {
      $layouts[$key]['regions']['ds_hidden'] = t('Hidden');
    }
  }
}

/**
 * Implements hook_permission().
 */
function ds_extras_permission() {
  $permissions = array();

  // Extra check to make sure this doesn't get fired on install.
  if (variable_get('ds_extras_switch_view_mode', FALSE)) {
    $permissions = array();
    foreach (node_type_get_names() as $key => $name) {
      $permissions['ds_switch ' . $key] = array(
        'title' => t('Switch view modes on :type', array(
          ':type' => $name,
        )),
      );
    }
  }
  return $permissions;
}

/**
 * Implements hook_admin_paths().
 */
function ds_extras_admin_paths() {
  if (variable_get('node_admin_theme')) {
    return array(
      'node/*/display' => TRUE,
      'user/*/display' => TRUE,
      'taxonomy/term/*/display' => TRUE,
    );
  }
}

/**
 * Implements hook_menu_alter().
 */
function ds_extras_menu_alter(&$items) {
  module_load_include('inc', 'ds_extras', 'ds_extras.registry');
  _ds_extras_menu_alter($items);
}

/**
 * Implements hook_theme_registry_alter().
 */
function ds_extras_theme_registry_alter(&$theme_registry) {
  module_load_include('inc', 'ds_extras', 'ds_extras.registry');
  _ds_extras_theme_registry_alter($theme_registry);
}

/**
 * Implements hook_module_implements_alter().
 */
function ds_extras_module_implements_alter(&$implementations, $hook) {
  module_load_include('inc', 'ds_extras', 'ds_extras.registry');
  _ds_extras_module_implements_alter($implementations, $hook);
}

/**
 * Implements hook_form_FORM_ID_alter().
 */
function ds_extras_form_field_ui_display_overview_form_alter(&$form, &$form_state) {
  form_load_include($form_state, 'inc', 'ds_extras', 'ds_extras.admin');
  ds_extras_field_ui_alter($form, $form_state);
}

/**
 * Implements hook_field_attach_view_alter().
 */
function ds_extras_field_attach_view_alter(&$build, $context) {

  // If views and core doesn't send information along on the entity,
  // Display suite doesn't have a context to render the fields.
  if (!isset($build['#entity_type']) && !isset($build['#bundle'])) {
    return;
  }
  $block_data =& drupal_static('ds_block_region');
  $region_blocks = variable_get('ds_extras_region_blocks', array());
  if (empty($region_blocks)) {
    return;
  }
  $entity_type = $build['#entity_type'];
  $bundle = $build['#bundle'];
  $view_mode = $context['view_mode'];
  $properties = array();
  foreach (element_properties($build) as $property) {
    $properties[$property] = $build[$property];
  }
  $properties['#view_mode'] = $view_mode;
  if ($layout = ds_get_layout($entity_type, $bundle, $view_mode)) {
    foreach ($region_blocks as $block_key => $block) {
      if ($block['info'] == "{$entity_type}_{$bundle}_{$view_mode}" && isset($layout['settings']['regions'][$block_key]) && !empty($layout['settings']['regions'][$block_key])) {
        foreach ($layout['settings']['regions'][$block_key] as $key => $field) {
          if (isset($build[$field])) {
            $block_data[$block_key][$field] = $build[$field];
            unset($build[$field]);
          }
        }
        if (isset($block_data[$block_key]) && is_array($block_data[$block_key])) {
          $block_data[$block_key] += $properties;
        }
      }
    }
  }
}

/**
 * Implements hook_ds_field_theme_functions_info().
 */
function ds_extras_ds_field_theme_functions_info() {
  return array(
    'theme_field' => t('Default'),
    'theme_ds_field_reset' => t('Full Reset'),
    'theme_ds_field_minimal' => t('Minimal'),
    'theme_ds_field_expert' => t('Expert'),
  );
}

/**
 * Implements hook_form_FORM_ID_alter().
 */
function ds_extras_form_field_ui_field_edit_form_alter(&$form, &$form_state, $form_id) {
  $theme_functions = module_invoke_all('ds_field_theme_functions_info');
  unset($theme_functions['theme_ds_field_expert']);
  $form['instance']['ds_extras_field_template'] = array(
    '#type' => 'select',
    '#title' => t('Field Template'),
    '#default_value' => isset($form['#instance']['ds_extras_field_template']) ? $form['#instance']['ds_extras_field_template'] : '',
    '#options' => $theme_functions,
    '#description' => t('Choose the default HTML for this field.'),
    '#empty_option' => t('Use sitewide default'),
  );
}

/**
 * Implements hook_form_FORM_ID_alter().
 */
function ds_extras_form_ds_styles_form_alter(&$form, &$form_state) {
  $form['ds_styles_fields'] = array(
    '#type' => 'textarea',
    '#title' => t('Styles for fields'),
    '#default_value' => variable_get('ds_styles_fields', ''),
    '#description' => t('Configure styles which you can add to fields on the "manage display" screens. Add multiple styles line per line.<br />If you want to have a friendly name, separate class and friendly name by |, but this is not required. eg:<br /><em>class_name_1<br />class_name_2|Friendly name<br />class_name_3</em>'),
  );
}

/**
 * Implements hook_preprocess_field().
 */
function ds_preprocess_field(&$variables) {

  // We need to be sure this field is in a layout which is rendered by DS.
  if (!ds_get_layout($variables['element']['#entity_type'], $variables['element']['#bundle'], $variables['element']['#view_mode'])) {
    return;
  }
  $config = array();
  static $field_settings = array();
  if (!isset($field_settings[$variables['element']['#entity_type']][$variables['element']['#bundle']][$variables['element']['#view_mode']])) {
    $layout = ds_get_layout($variables['element']['#entity_type'], $variables['element']['#bundle'], $variables['element']['#view_mode']);
    $field_settings[$variables['element']['#entity_type']][$variables['element']['#bundle']][$variables['element']['#view_mode']] = ds_get_field_settings($variables['element']['#entity_type'], $variables['element']['#bundle'], $layout['view_mode']);
  }

  // Get the field name and field instance info - if available.
  $field_name = $variables['element']['#field_name'];
  $field_instance_info = field_info_instance($variables['element']['#entity_type'], $field_name, $variables['element']['#bundle']);

  // Check if this field has custom output settings.
  $variables['ds-config'] = array();
  if (isset($field_settings[$variables['element']['#entity_type']][$variables['element']['#bundle']][$variables['element']['#view_mode']][$field_name]['ft'])) {
    $config = $field_settings[$variables['element']['#entity_type']][$variables['element']['#bundle']][$variables['element']['#view_mode']][$field_name]['ft'];
    $variables['ds-config'] = $config;
  }

  // Styles
  if (isset($config['styles'])) {
    $variables['classes_array'][] = $config['styles'];
  }

  // Alter the label if configured.
  if (!$variables['label_hidden']) {
    if (isset($config['lb'])) {
      $variables['label'] = t(check_plain($config['lb']));
    }
  }

  // Determine the field template. In case it's something different
  // than theme_field, we'll add that function as a suggestion.
  if (isset($config['func']) && $config['func'] != 'theme_field') {
    $variables['ds-config'] = $config;
    $variables['theme_hook_suggestions'] = array();

    // Either it uses the function.
    $variables['theme_hook_suggestions'][] = $config['func'];

    // Or the template file(s).
    $suggestion = 'field__' . str_replace('theme_ds_field_', '', $config['func']);
    $variables['theme_hook_suggestions'][] = $suggestion;
    $variables['theme_hook_suggestions'][] = $suggestion . '__' . $field_name;
    $variables['theme_hook_suggestions'][] = $suggestion . '__' . $variables['element']['#bundle'];
    $variables['theme_hook_suggestions'][] = $suggestion . '__' . $field_name . '__' . $variables['element']['#bundle'];
  }
  elseif (isset($field_instance_info['ds_extras_field_template']) && !empty($field_instance_info['ds_extras_field_template']) && $field_instance_info['ds_extras_field_template'] != 'theme_field') {
    $variables['theme_hook_suggestions'] = array();

    // Either it uses the function.
    $variables['theme_hook_suggestions'][] = $field_instance_info['ds_extras_field_template'];

    // Or the template file(s).
    $suggestion = 'field__' . str_replace('theme_ds_field_', '', $field_instance_info['ds_extras_field_template']);
    $variables['theme_hook_suggestions'][] = $suggestion;
    $variables['theme_hook_suggestions'][] = $suggestion . '__' . $field_name;
    $variables['theme_hook_suggestions'][] = $suggestion . '__' . $variables['element']['#bundle'];
    $variables['theme_hook_suggestions'][] = $suggestion . '__' . $field_name . '__' . $variables['element']['#bundle'];
  }
  elseif (!isset($config['func']) || empty($config['func'])) {
    $field_theme_function = variable_get('ft-default', 'theme_field');
    if ($field_theme_function != 'theme_field') {
      $variables['theme_hook_suggestions'] = array();
      $variables['ds-config'] = $config;

      // Either it uses the function.
      $variables['theme_hook_suggestions'][] = $field_theme_function;

      // Or the template file(s).
      $suggestion = 'field__' . str_replace('theme_ds_field_', '', $field_theme_function);
      $variables['theme_hook_suggestions'][] = $suggestion;
      $variables['theme_hook_suggestions'][] = $suggestion . '__' . $field_name;
      $variables['theme_hook_suggestions'][] = $suggestion . '__' . $variables['element']['#bundle'];
      $variables['theme_hook_suggestions'][] = $suggestion . '__' . $field_name . '__' . $variables['element']['#bundle'];
    }
  }
}

/**
 * Reset all HTML for the field.
 */
function theme_ds_field_reset($variables) {
  $output = '';

  // Render the label.
  if (!$variables['label_hidden']) {
    $output .= '<div class="label-' . $variables['element']['#label_display'] . '">' . $variables['label'];
    if (!variable_get('ft-kill-colon', FALSE)) {
      $output .= ':&nbsp;';
    }
    $output .= '</div>';
  }

  // Render the items.
  foreach ($variables['items'] as $delta => $item) {
    $output .= drupal_render($item);
  }
  return $output;
}

/**
 * Provide minimal HTML for the field.
 */
function theme_ds_field_minimal($variables) {
  $output = '';
  $config = $variables['ds-config'];

  // Add a simple wrapper.
  $output .= '<div class="field field-name-' . strtr($variables['element']['#field_name'], '_', '-') . '">';

  // Render the label.
  if (!$variables['label_hidden']) {
    $output .= '<div class="label-' . $variables['element']['#label_display'] . '">' . $variables['label'];
    if (!isset($config['lb-col'])) {
      $output .= ':&nbsp;';
    }
    $output .= '</div>';
  }

  // Render the items.
  foreach ($variables['items'] as $delta => $item) {
    $output .= drupal_render($item);
  }
  $output .= "</div>";
  return $output;
}

/**
 * Custom output all HTML for the field.
 */
function theme_ds_field_expert($variables) {
  $output = '';
  $config = $variables['ds-config'];

  // Render the label if it's not hidden
  if (!$variables['label_hidden']) {
    if (isset($config['lb-el'])) {
      if (!empty($config['lb-cl'])) {
        $class = ' class="label-' . $variables['element']['#label_display'] . ' ' . $config['lb-cl'] . '"';
      }
      else {
        $class = ' class="label-' . $variables['element']['#label_display'] . '"';
      }
      $output .= '<' . $config['lb-el'] . $class . '>' . $variables['label'];
      if (!isset($config['lb-col'])) {
        $output .= ':&nbsp;';
      }
      $output .= '</' . $config['lb-el'] . '>';
    }
    else {
      $output .= '<div class="label-' . $variables['element']['#label_display'] . '">' . $variables['label'];
      if (!isset($config['lb-col'])) {
        $output .= ':&nbsp;';
      }
      $output .= '</div>';
    }
  }

  // Field items wrapper
  if (isset($config['fis'])) {
    $fis_wrapper = $config['fis-el'];
    $class = !empty($config['fis-cl']) ? ' class="' . $config['fis-cl'] . '"' : '';
    $output .= '<' . $fis_wrapper . $class . '>';
  }

  // Field item wrapper.
  if (isset($config['fi'])) {
    $fi_wrapper = $config['fi-el'];
  }

  // Render items.
  foreach ($variables['items'] as $delta => $item) {

    // Field item wrapper.
    if (isset($config['fi'])) {
      $classes = $delta % 2 ? 'odd' : 'even';
      if (!empty($config['fi-cl'])) {
        $classes .= ' ' . $config['fi-cl'];
      }
      $output .= '<' . $fi_wrapper . ' class="' . $classes . '">';
    }

    // Render field content.
    $output .= drupal_render($item);

    // Closing field item wrapper.
    if (isset($config['fi'])) {
      $output .= '</' . $fi_wrapper . '>';
    }
  }

  // Closing field items wrapper.
  if (isset($config['fis'])) {
    $output .= '</' . $fis_wrapper . '>';
  }

  // Outer wrapper.
  if (isset($config['ow'])) {
    $ow_wrapper = $config['ow-el'];
    $class = !empty($config['ow-cl']) ? ' class="' . $config['ow-cl'] . '"' : '';
    $output = '<' . $ow_wrapper . $class . '>' . $output . '</' . $ow_wrapper . '>';
  }
  return $output;
}

/**
 * Utility funtion to return the view mode for the current entity.
 *
 * The drupal_static is called in ds_extras_node_show to set
 * the current view mode. Through this technique, the hide page
 * title functionality can also work across other view modes
 * if another one is chosen for the full page of the node.
 */
function ds_extras_get_view_mode() {
  return drupal_static('ds_extras_view_mode');
}

/**
 * Get view modes for an entity bundle.
 */
function ds_extras_get_bundle_view_modes($type, $bundle) {
  $view_modes = array(
    'default' => t('Default'),
  );
  $view_mode_settings = field_view_mode_settings($type, $bundle);
  $ds_vm = ds_entity_view_modes($type);
  foreach ($ds_vm as $key => $item) {
    $overriden = !empty($view_mode_settings[$key]['custom_settings']) ? TRUE : FALSE;
    if ($overriden) {
      $view_modes[$key] = $item['label'];
    }
  }
  return $view_modes;
}

/**
 * Page title options for a full entity page view.
 */
function ds_extras_process_page_title(&$variables) {
  $page_title = drupal_static('ds_page_title');
  if (!empty($page_title)) {
    $variables['title'] = $page_title['title'];
    if (!empty($page_title['head_title'])) {
      drupal_set_title($page_title['head_title']);
    }
  }
}

/**
 * Implements hook_ds_layout_settings_alter().
 */
function ds_extras_ds_layout_settings_alter($record, $form_state) {
  if (isset($form_state['values']['additional_settings']['ds_page_title_options']['page_option_type']) || isset($form_state['values']['page_option_type'])) {
    $record->settings['hide_page_title'] = isset($form_state['values']['additional_settings']['ds_page_title_options']['page_option_type']) ? $form_state['values']['additional_settings']['ds_page_title_options']['page_option_type'] : $form_state['values']['page_option_type'];
    $record->settings['page_option_title'] = isset($form_state['values']['additional_settings']['ds_page_title_options']['page_option_title']) ? $form_state['values']['additional_settings']['ds_page_title_options']['page_option_title'] : $form_state['values']['page_option_title'];
  }
}

/**
 * Switch view mode field.
 */
function ds_extras_switch_view_mode_field($field) {
  $output = '';
  static $added = FALSE;
  if (isset($field['formatter_settings'])) {
    $entity = $field['entity'];
    $id = $entity->nid;
    $url = $field['entity_type'] . '-' . $field['view_mode'] . '-' . $id . '-';
    $switch = array();
    foreach ($field['formatter_settings'] as $key => $value) {
      if (!empty($value)) {
        $class = 'switch-' . $key;
        if ($key == $field['view_mode']) {
          $switch[] = '<span class="' . $class . '">' . check_plain(t($value)) . '</span>';
        }
        else {
          $switch[] = '<span class="' . $class . '"><a href="" class="' . $url . $key . '">' . check_plain(t($value)) . '</a></span>';
        }
      }
    }
    if (!empty($switch)) {
      if (!$added) {
        $add = TRUE;
        drupal_add_js(drupal_get_path('module', 'ds_extras') . '/ds_extras.js');
      }
      $output = '<div class="switch-view-mode-field">' . implode(' ', $switch) . '</div>';
    }
  }
  return $output;
}

/**
 * Implements hook_contextual_links_view_alter().
 */
function ds_extras_contextual_links_view_alter(&$element, $items) {
  if (isset($element['#element']['#entity_type']) && user_access('administer content types') && module_exists('field_ui')) {
    $entity_type = $element['#element']['#entity_type'];
    $bundle = $element['#element']['#bundle'];
    $view_mode = isset($element['#element']['#view_mode']) ? $element['#element']['#view_mode'] : 'default';

    // Check if we have a configured layout. Do not fallback to default.
    $layout = ds_get_layout($entity_type, $bundle, $view_mode, FALSE);

    // Get the manage display URI.
    $admin_path = _field_ui_bundle_admin_path($entity_type, $bundle);

    // Check view mode settings.
    $view_mode_settings = field_view_mode_settings($entity_type, $bundle);
    $overriden = !empty($view_mode_settings[$view_mode]['custom_settings']) ? TRUE : FALSE;
    if (empty($layout) && !$overriden) {
      $admin_path .= '/display';
    }
    else {
      $admin_path .= '/display/' . $view_mode;
    }
    $element['#links']['manage-display'] = array(
      'title' => t('Manage display'),
      'href' => $admin_path,
      'query' => drupal_get_destination(),
    );
  }
}

/**
 * Implements hook_form_FORM_ID_alter().
 */
function ds_extras_form_node_form_alter(&$form, $form_state, $form_id) {

  // Switch full view mode.
  if (user_access('ds_switch ' . $form['#node']->type)) {
    $view_mode_settings = field_view_mode_settings('node', $form['#node']->type);

    // Get the view modes.
    $options = array(
      '' => t('Default'),
    );
    $ds_vm = ds_entity_view_modes('node');
    foreach ($ds_vm as $key => $item) {
      $overriden = !empty($view_mode_settings[$key]['custom_settings']) ? TRUE : FALSE;
      if ($overriden) {
        $options[$key] = $item['label'];
      }
    }

    // Only fire if we have more than 1 option.
    if (count($options) > 1) {
      $node = $form['#node'];
      if (!isset($form['ds_extras'])) {
        $form['ds_extras'] = array(
          '#type' => 'fieldset',
          '#title' => t('Display settings'),
          '#collapsible' => TRUE,
          '#collapsed' => TRUE,
          '#group' => 'additional_settings',
          '#weight' => 100,
        );
      }
      $form['ds_extras']['ds_switch'] = array(
        '#type' => 'select',
        '#title' => t('View mode'),
        '#options' => $options,
        '#default_value' => isset($node->ds_switch) ? $node->ds_switch : '',
        '#description' => t('Switch to a different view mode to display the full page view of this node.'),
        '#weight' => -1,
      );
    }
  }
}

/**
 * Implements hook_block_info().
 */
function ds_extras_block_info() {
  $region_blocks = variable_get('ds_extras_region_blocks', array());
  if (empty($region_blocks)) {
    return array();
  }
  foreach ($region_blocks as $key => $block) {
    $blocks[$key] = array(
      'info' => $block['title'],
      'cache' => DRUPAL_NO_CACHE,
    );
  }
  return $blocks;
}

/**
 * Implements hook_block_view().
 */
function ds_extras_block_view($delta = '') {
  $data = drupal_static('ds_block_region');
  $region_blocks = variable_get('ds_extras_region_blocks', array());
  if (!empty($data[$delta])) {
    $block = array();
    $block['subject'] = $region_blocks[$delta]['title'];
    $block['content'] = $data[$delta];
    return $block;
  }
}

/**
 * Implements hook_ds_layout_region_alter().
 */
function ds_extras_ds_layout_region_alter($context, &$region_info) {
  $region_blocks = variable_get('ds_extras_region_blocks', array());

  // Bail out if region_blocks is empty or we are working on default view mode.
  if (empty($region_blocks) || $context['view_mode'] == 'default') {
    return;
  }
  $entity_type = $context['entity_type'];
  $bundle = $context['bundle'];
  $view_mode = $context['view_mode'];
  foreach ($region_blocks as $block_key => $block) {
    if ($block['info'] == "{$entity_type}_{$bundle}_{$view_mode}") {
      $region_info['region_options'][$block_key] = $block['title'];
      if (isset($region_info['table_regions'])) {
        $region_info['table_regions'][$block_key] = array(
          'title' => check_plain($block['title']),
          'message' => t('No fields are displayed in this region'),
        );
      }
    }
  }
}

/**
 * Implements hook_ctools_plugin_api().
 */
function ds_extras_ctools_plugin_api($owner, $api) {
  if ($owner == 'ds_extras' && $api == 'ds_extras') {
    return array(
      'version' => 1,
    );
  }
}

/**
 * Implements hook_ctools_plugin_directory().
 */
function ds_extras_ctools_plugin_directory($module, $plugin) {
  if ($plugin == 'cache') {
    return 'plugins/' . $plugin;
  }
}

/**
 * Implements hook_ctools_plugin_type().
 */
function ds_extras_ctools_plugin_type() {
  return array(
    'cache' => array(),
  );
}

/**
 * Implements hook_field_extra_fields().
 */
function ds_extras_field_extra_fields() {
  $extra = array();

  // Register a single field so fields for vd are
  // picked up nicely in the display overview form.
  if (variable_get('ds_extras_vd')) {
    ctools_include('export');
    $vd_settings = ctools_export_crud_load_all('ds_vd');
    foreach ($vd_settings as $vd) {
      $extra['ds_views'][$vd->vd] = array(
        'display' => array(
          'title' => array(
            'label' => t('Title'),
            'description' => t('Title'),
            'weight' => 10,
          ),
        ),
      );
    }
  }
  if (variable_get('ds_extras_fields_extra')) {
    $fields = explode("\n", variable_get('ds_extras_fields_extra_list', FALSE));
    foreach ($fields as $field) {
      $field = trim($field);
      if (!empty($field)) {
        list($entity, $bundle, $field_name) = explode('|', $field);
        $extra[check_plain($entity)][check_plain($bundle)]['display'][$field_name] = array(
          'label' => drupal_ucfirst(str_replace('_', ' ', check_plain($field_name))),
          'description' => drupal_ucfirst(str_replace('_', ' ', check_plain($field_name))),
          'weight' => 0,
        );
      }
    }
  }
  return $extra;
}

/**
 * Implements hook_preprocess_views_view().
 */
function ds_extras_preprocess_view_layout(&$variables) {
  if ($layout = ds_get_layout('ds_views', $variables['view']->name . '-' . $variables['view']->current_display, 'default')) {
    $variables['elements']['#entity_type'] = $variables['#entity_type'] = 'ds_views';
    $variables['elements']['#bundle'] = $variables['#bundle'] = $variables['view']->name . '-' . $variables['view']->current_display;
    $variables['elements']['#view_mode'] = 'default';
    $variables['ds_views'] = $variables['view'];
    ds_field_attach_view_alter($variables, array(
      'view_mode' => 'default',
      'entity' => $variables['view'],
    ));

    // Special case for views function fields.
    if (isset($variables['view']->ds_vd)) {
      foreach ($variables['view']->ds_vd as $key => $value) {
        $variables[$key] = $value;
      }
    }

    // Don't remove the variables so we don't trigger notices.
    $variables['preprocess_keep'] = TRUE;
    ds_entity_variables($variables);
    if (isset($variables['#attached'])) {
      drupal_process_attached($variables);
    }
  }
}

/**
 * Function used for theming the views title, user name etc. Note that
 * this is a function so it can't be overridden by a phptemplate function.
 */
function ds_vd_render_title_field($field) {
  $output = '';
  $formatter = explode('_', $field['formatter']);
  $tag = $formatter[2];
  $output = '<' . $tag . '>' . $field['entity']
    ->get_title() . '</' . $tag . '>';

  // Views is a special case, we stack title on the entity.
  $field['entity']->preprocess_fields[] = 'title';
  $field['entity']->ds_vd['title'] = $output;
}

/**
 * Implements hook_flush_caches().
 */
function ds_extras_flush_caches() {
  return array(
    'cache_ds_panels',
  );
}

/**
 * Implements hook_panels_dashboard_blocks().
 */
function ds_extras_panels_dashboard_blocks(&$vars) {
  $vars['links']['ds_panels'] = array(
    'title' => l(t('Panel view modes'), 'admin/structure/ds/layout'),
    'description' => t('Manage the layout of view modes for every entity.'),
    'weight' => -3,
  );
}

/**
 * Implements hook_ds_panels_default_fields().
 */
function ds_extras_ds_panels_default_fields($entity_type, $bundle, $view_mode) {

  // Get the fields from Field API.
  $fields = field_info_instances($entity_type, $bundle);

  // Add other fields like title, etc.
  switch ($entity_type) {
    case 'node':
      $fields['node_title'] = array(
        'label' => t('Title'),
        'type' => 'node_title',
        'subtype' => 'node_title',
      );
      $fields['node_created'] = array(
        'label' => t('Created date'),
        'type' => 'node_created',
        'subtype' => 'node_created',
      );
      $fields['node_author'] = array(
        'label' => t('Author'),
        'type' => 'node_author',
        'subtype' => 'node_author',
      );
      $fields['node_links'] = array(
        'label' => t('Links'),
        'type' => 'node_links',
        'subtype' => 'node_links',
      );
      if (module_exists('comment') && variable_get("comment_{$bundle}", COMMENT_NODE_OPEN) != COMMENT_NODE_HIDDEN) {
        $fields['node_comments'] = array(
          'label' => t('Comments'),
          'type' => 'node_comments',
          'subtype' => 'node_comments',
        );
        $fields['node_comment_form'] = array(
          'label' => t('Comment form'),
          'type' => 'node_comment_form',
          'subtype' => 'node_comment_form',
        );
      }
      break;
  }
  return $fields;
}

/**
 * Implements hook_entity_view_alter().
 */
function ds_extras_entity_view_alter(&$build, $entity_type) {
  static $loaded = array();

  // If views and core doesn't send information along on the entity,
  // Display suite doesn't have a context to render the layout.
  if (!isset($build['#entity_type']) || !isset($build['#bundle'])) {
    return;
  }
  $bundle = $build['#bundle'];
  $view_mode = $build['#view_mode'];
  if ($overridden_view_mode = ds_extras_get_view_mode()) {
    $view_mode = $overridden_view_mode;
  }
  $layout = ds_get_layout($entity_type, $bundle, $view_mode);

  // Page title options.
  if (variable_get('ds_extras_hide_page_title', FALSE)) {
    $page_title =& drupal_static('ds_page_title');
    if (isset($layout['settings']['hide_page_title']) && $layout['settings']['hide_page_title'] == 1) {
      $page_title['title'] = '';
    }
    elseif (isset($layout['settings']['hide_page_title']) && $layout['settings']['hide_page_title'] == 2 && !empty($layout['settings']['page_option_title'])) {
      $contexts = array();
      $id = arg(0) == 'taxonomy' ? arg(2) : arg(1);
      $entity = entity_load($entity_type, array(
        $id,
      ));
      ds_create_entity_context($entity_type, $entity[$id], $contexts);
      $title = $layout['settings']['page_option_title'];
      $title = filter_xss_admin(ctools_context_keyword_substitute($title, array(), $contexts));
      $page_title['title'] = $title;
      $page_title['head_title'] = $title;
    }
  }

  // Disable blocks.
  if (isset($layout['settings']['hide_sidebars']) && !isset($loaded[$entity_type][$bundle][$view_mode])) {

    // Store the setting.
    $loaded[$entity_type][$bundle][$view_mode] = TRUE;

    // Disable blocks.
    if (isset($layout['settings']['hide_sidebars']) && $layout['settings']['hide_sidebars']) {
      ctools_set_no_blocks();
    }
  }
}

/**
 * Render the entity through the Panels layout.
 */
function ds_extras_render_panel_layout(&$vars) {
  static $displays = array();
  if (isset($vars['elements']) && isset($vars['elements']['#bundle']) && ($layout = ds_get_layout($vars['elements']['#entity_type'], $vars['elements']['#bundle'], $vars['elements']['#view_mode']))) {
    if (empty($layout['settings']['ds_panels'])) {
      return;
    }
    $entity_type = $vars['elements']['#entity_type'];
    $bundle = $vars['elements']['#bundle'];
    $view_mode = $vars['elements']['#view_mode'];
    $element = '#' . $entity_type;
    if ($entity_type == 'user') {
      $element = '#account';
    }
    if ($entity_type == 'taxonomy_term') {
      $element = '#term';
    }

    // Compatibility with #entity elements.
    if (empty($vars['elements'][$element]) && !empty($vars['elements']['#entity'])) {
      $element = '#entity';
    }
    $entity = $vars['elements'][$element];
    ctools_include('plugins', 'panels');
    $contexts = array();

    // Add entity context to begin with.
    ds_create_entity_context($entity_type, $entity, $contexts);

    // Load the display.
    $did = $layout['settings']['did'];
    if (!isset($displays[$did])) {
      $display = panels_load_display($did);
      $display->entity_type = $entity_type;
      $display->bundle = $bundle;
      $display->view_mode = $view_mode;
      $displays[$did] = $display;
    }
    else {
      $display = $displays[$did];
    }
    $display->context = $contexts;
    $info = entity_extract_ids($entity_type, $entity);
    $display->entity_id = $info[0];

    // Add the panels template file as the theme hook suggestion.
    $vars['theme_hook_suggestion'] = $layout['settings']['theme'];

    // Add css ID.
    $vars['css_id'] = $layout['settings']['css_id'];

    // Add classes.
    $class = array();
    $class[] = check_plain($layout['settings']['class']);

    // Add sticky class.
    if ($layout['settings']['sticky'] && $entity->sticky) {
      $class[] = 'sticky';
    }
    $vars['class'] = !empty($class) ? ' ' . implode(' ', $class) : '';

    // Flexible layouts.
    if ($layout['settings']['theme'] == 'panels_flexible') {
      $vars['settings'] = $vars['renderer'] = '';
      $vars['display'] = $display;
      $panels_layout = str_replace('panels-', '', $layout['layout']);
      $vars['layout'] = panels_get_layout($panels_layout);
      $vars['theme_hook_suggestion'] = 'panels_flexible';
    }

    // Responsive layouts.
    if ($layout['settings']['theme'] == 'layout_responsive') {
      $vars['settings'] = $vars['renderer'] = '';
      $vars['display'] = $display;
      $vars['layout'] = panels_get_layout($layout['layout']);
      $vars['theme_hook_suggestion'] = 'layout_responsive';
    }

    // Load renderer.
    $pipeline = $layout['settings']['pipeline'];
    $renderer = panels_get_renderer($pipeline, $display);

    // Attach out-of-band data first.
    $renderer
      ->add_meta();
    $cache = FALSE;
    $cacheable = isset($renderer->display->cache['method']) && !empty($renderer->display->cache['method']);
    if ($cacheable) {
      $cache = panels_get_cached_content($renderer->display, $renderer->display->args, $renderer->display->context);
      if ($cache) {
        $content = $cache->content;
      }
    }

    // If no content is found from cache, call the $renderer
    // methods. In display has a cache setting, store it into cache table.
    if ($cache === FALSE) {
      $renderer
        ->prepare();
      $renderer
        ->render_panes();
      $renderer
        ->render_regions();
      $content = $renderer->rendered['regions'];
      if ($cacheable) {
        $cache = new panels_cache_object();
        $cache
          ->set_content($content);
        panels_set_cached_content($cache, $renderer->display, $renderer->display->args, $renderer->display->context);
      }
    }

    // Overwrite $vars['content'].
    $vars['content'] = $content;
  }
}

/**
 * Implements hook_entity_update().
 */
function ds_extras_entity_update($entity, $type) {
  _ds_extras_cache_clear($entity, $type);
}

/**
 * Implements hook_entity_delete().
 */
function ds_extras_entity_delete($entity, $type) {
  _ds_extras_cache_clear($entity, $type);
}

/**
 * Clears the entity display from cache_ds_panels bin.
 *
 * @param $entity
 *   The full entity object.
 * @param $type
 *   The name of the $entity.
 */
function _ds_extras_cache_clear($entity, $type) {
  $info = entity_extract_ids($type, $entity);
  $cid = $type . ':' . $info[0];
  cache_clear_all($cid, 'cache_ds_panels', TRUE);
}

Functions

Namesort descending Description
ds_extras_admin_paths Implements hook_admin_paths().
ds_extras_block_info Implements hook_block_info().
ds_extras_block_view Implements hook_block_view().
ds_extras_contextual_links_view_alter Implements hook_contextual_links_view_alter().
ds_extras_ctools_plugin_api Implements hook_ctools_plugin_api().
ds_extras_ctools_plugin_directory Implements hook_ctools_plugin_directory().
ds_extras_ctools_plugin_type Implements hook_ctools_plugin_type().
ds_extras_ds_field_theme_functions_info Implements hook_ds_field_theme_functions_info().
ds_extras_ds_layout_info_alter Implements hook_ds_layout_info_alter().
ds_extras_ds_layout_region_alter Implements hook_ds_layout_region_alter().
ds_extras_ds_layout_settings_alter Implements hook_ds_layout_settings_alter().
ds_extras_ds_panels_default_fields Implements hook_ds_panels_default_fields().
ds_extras_entity_delete Implements hook_entity_delete().
ds_extras_entity_info Implements hook_entity_info().
ds_extras_entity_info_alter Implements hook_entity_info_alter().
ds_extras_entity_update Implements hook_entity_update().
ds_extras_entity_view_alter Implements hook_entity_view_alter().
ds_extras_field_attach_view_alter Implements hook_field_attach_view_alter().
ds_extras_field_extra_fields Implements hook_field_extra_fields().
ds_extras_flush_caches Implements hook_flush_caches().
ds_extras_form_ds_styles_form_alter Implements hook_form_FORM_ID_alter().
ds_extras_form_field_ui_display_overview_form_alter Implements hook_form_FORM_ID_alter().
ds_extras_form_field_ui_field_edit_form_alter Implements hook_form_FORM_ID_alter().
ds_extras_form_node_form_alter Implements hook_form_FORM_ID_alter().
ds_extras_get_bundle_view_modes Get view modes for an entity bundle.
ds_extras_get_view_mode Utility funtion to return the view mode for the current entity.
ds_extras_menu Implements hook_menu().
ds_extras_menu_alter Implements hook_menu_alter().
ds_extras_module_implements_alter Implements hook_module_implements_alter().
ds_extras_panels_dashboard_blocks Implements hook_panels_dashboard_blocks().
ds_extras_permission Implements hook_permission().
ds_extras_preprocess_view_layout Implements hook_preprocess_views_view().
ds_extras_process_page_title Page title options for a full entity page view.
ds_extras_render_panel_layout Render the entity through the Panels layout.
ds_extras_switch_view_mode_field Switch view mode field.
ds_extras_theme Implements hook_theme().
ds_extras_theme_registry_alter Implements hook_theme_registry_alter().
ds_preprocess_field Implements hook_preprocess_field().
ds_vd_render_title_field Function used for theming the views title, user name etc. Note that this is a function so it can't be overridden by a phptemplate function.
theme_ds_field_expert Custom output all HTML for the field.
theme_ds_field_minimal Provide minimal HTML for the field.
theme_ds_field_reset Reset all HTML for the field.
_ds_extras_cache_clear Clears the entity display from cache_ds_panels bin.