You are here

panopoly_widgets.module in Panopoly Widgets 7

Same filename and directory in other branches
  1. 8.2 panopoly_widgets.module

File

panopoly_widgets.module
View source
<?php

include_once 'panopoly_widgets.features.inc';
include_once 'panopoly_widgets.spotlight.inc';

/**
 * The default list of allowed file extensions in file widgets.
 */
define('PANOPOLY_WIDGETS_FILE_EXTENSIONS_DEFAULT', 'txt doc docx xls xlsx pdf ppt pptx pps ppsx odt ods odp');

/**
 * Implements hook_init()
 */
function panopoly_widgets_init() {

  // Load the seven theme CSS for the media browser. This is done
  // because the seven theme may not be the admin theme, but the
  // media browser assumes that it is....
  if (arg(0) == 'media' && arg(1) == 'browser') {
    if ($GLOBALS['theme'] != 'seven') {
      drupal_add_css(drupal_get_path('theme', 'seven') . '/reset.css', array(
        'basename' => 'seven_reset',
        'group' => CSS_THEME,
      ));
      drupal_add_css(drupal_get_path('theme', 'seven') . '/style.css', array(
        'basename' => 'seven_style',
        'group' => CSS_THEME,
      ));
    }
    drupal_add_css(drupal_get_path('module', 'panopoly_widgets') . '/panopoly-widgets-media-browser.css', array(
      'group' => CSS_THEME,
    ));
  }
}

/**
 * Implements hook_apps_app_info()
 */
function panopoly_widgets_apps_app_info() {
  return array(
    'configure form' => 'panopoly_widgets_configure_form',
  );
}

/**
 * Configuration Form for Panopoly Magic
 */
function panopoly_widgets_configure_form($form, &$form_state) {
  $form = array();
  $file_extensions = variable_get('panopoly_widgets_file_extensions', PANOPOLY_WIDGETS_FILE_EXTENSIONS_DEFAULT);
  $file_extensions = str_replace(' ', ', ', $file_extensions);
  $form['panopoly_widgets_file_extensions'] = array(
    '#title' => t('Allowed file extensions in file widgets.'),
    '#type' => 'textfield',
    '#default_value' => $file_extensions,
    '#element_validate' => array(
      '_file_generic_settings_extensions',
    ),
    '#description' => t('Separate extensions with a space or comma and do not include the leading dot.'),
  );
  $form['panopoly_widgets_spotlight_pause_play_buttons'] = array(
    '#title' => t('Add pause/play button to all spotlight widgets.'),
    '#type' => 'checkbox',
    '#default_value' => variable_get('panopoly_widgets_spotlight_pause_play_buttons', 1),
    '#description' => t('The button will appear under to the slide numbers. Helps with accessibility.'),
  );
  $form = system_settings_form($form);
  $form['#submit'][] = 'panopoly_widgets_configure_form_submit';
  return $form;
}

/**
 * Form submissions callback for panopoly_widgets_configure_form().
 */
function panopoly_widgets_configure_form_submit($form, &$form_state) {
  if ($file_instance = field_info_instance('fieldable_panels_pane', 'field_basic_file_file', 'basic_file')) {
    $file_extensions = $form_state['values']['panopoly_widgets_file_extensions'];
    $file_instance['settings']['file_extensions'] = $file_extensions;
    field_update_instance($file_instance);
  }
}

/** 
 * Implements hook_field_default_field_instances_alter().
 */
function panopoly_widgets_field_default_field_instances_alter(&$instances) {

  // Set the file extensions from our configuration setting.
  if (isset($instances['fieldable_panels_pane-basic_file-field_basic_file_file'])) {
    $file_extensions = variable_get('panopoly_widgets_file_extensions', PANOPOLY_WIDGETS_FILE_EXTENSIONS_DEFAULT);
    $instances['fieldable_panels_pane-basic_file-field_basic_file_file']['settings']['file_extensions'] = $file_extensions;
  }

  // If the linkit module isn't present, then we alter the field settings for
  // the 'Add image' widget to disable linkit on the 'Link' field.
  if (isset($instances['fieldable_panels_pane-image-field_basic_image_link'])) {
    if (!module_exists('linkit')) {
      $instances['fieldable_panels_pane-image-field_basic_image_link']['settings']['linkit']['enable'] = 0;
      $instances['fieldable_panels_pane-image-field_basic_image_link']['settings']['linkit']['profile'] = NULL;
    }
  }
}

/**
 * Implements hook_page_build()
 */
function panopoly_widgets_page_build(&$page) {

  // Add our custom javascript to the footer to override other things.
  drupal_add_js(drupal_get_path('module', 'panopoly_widgets') . '/panopoly-widgets.js', array(
    'scope' => 'footer',
  ));
  drupal_add_js(drupal_get_path('module', 'panopoly_widgets') . '/panopoly-widgets-spotlight.js', array(
    'scope' => 'footer',
  ));
}

/**
 * Implementation of hook_ctools_plugin_directory()
 */
function panopoly_widgets_ctools_plugin_directory($module, $plugin) {
  return 'plugins/' . $plugin;
}

/**
 * Implementation of hook_ctools_content_subtype_alter()
 */
function panopoly_widgets_ctools_content_subtype_alter(&$subtype, &$plugin) {

  // Modify the menu block plugin to better fit into our UI
  if ($plugin['module'] == 'menu_block' && $subtype['menu_title'] == 'Main menu') {
    $subtype['category'][0] = t('Custom');
    $subtype['top level'] = TRUE;
    $subtype['title'] = t('Add submenu');
    $subtype['icon'] = drupal_get_path('module', 'panopoly_widgets') . '/images/icon_submenu.png';
    $subtype['admin css'] = array(
      drupal_get_path('module', 'menu_block') . '/menu-block-admin.css',
    );
    $subtype['admin js'] = array(
      drupal_get_path('module', 'menu_block') . '/menu-block.js',
    );
    $subtype['defaults']['expanded_max_depth'] = 0;
  }

  // Modify the general content item to appear in the generic content sidebar area
  if ($plugin['module'] == 'views_content' && $subtype['title'] == 'Piece of Content') {
    $subtype['category'][0] = t('Custom');
    $subtype['top level'] = TRUE;
    $subtype['title'] = t('Add content item');
    $subtype['icon'] = drupal_get_path('module', 'panopoly_widgets') . '/images/icon_content_item.png';
  }

  // Modify the general content listing to appear in the generic content sidebar area
  if ($plugin['module'] == 'views_content' && $subtype['title'] == 'List of Content') {
    $subtype['category'][0] = t('Custom');
    $subtype['top level'] = TRUE;
    $subtype['title'] = t('Add content list');
    $subtype['icon'] = drupal_get_path('module', 'panopoly_widgets') . '/images/icon_content_list.png';
  }

  // Modify the plugins so we do away with this "node" and "entity" thing
  if ($subtype['category'] == 'Node' || $subtype['category'] == 'Entity') {
    $subtype['category'] = t('Page Content');
  }
  if ($subtype['category'] == 'User') {
    $subtype['category'] = t('User Content');
  }
  if ($subtype['category'] == 'Taxonomy_term' || $subtype['category'] == 'Taxonomy term') {
    $subtype['category'] = t('Category Content');
  }

  // Modify the plugins so we have consistent language around "form" content
  if ($subtype['category'] == 'Form') {
    $subtype['category'] = t('Form Content');
  }
}

/**
 * Implements hook_ctools_plugin_post_alter().
 */
function panopoly_widgets_ctools_plugin_post_alter(&$plugin, &$info) {
  if ($info['module'] == 'ctools' && $info['type'] == 'content_types' && $plugin['module'] == 'fieldable_panels_panes' && $plugin['name'] == 'fieldable_panels_pane') {
    $plugin['original render callback'] = $plugin['render callback'];
    $plugin['render callback'] = 'panopoly_widgets_fieldable_panels_pane_render';
  }
}

/**
 * Gets a list of all the required file fields for the given bundle.
 */
function panopoly_widgets_get_required_file_fields($bundle) {
  $required_file_fields = array();
  $field_instances = field_info_instances('fieldable_panels_pane', $bundle);
  foreach ($field_instances as $field_name => $field_instance) {
    $field_info = field_info_field($field_name);
    if (in_array($field_info['type'], array(
      'file',
      'image',
    )) && !empty($field_instance['required'])) {
      $required_file_fields[] = $field_name;
    }
  }
  return $required_file_fields;
}

/**
 * Render callback for fieldable panels panes.
 */
function panopoly_widgets_fieldable_panels_pane_render($subtype, $conf, $panels_args = array(), $context = array()) {
  ctools_include('content');
  $plugin = ctools_get_content_type('fieldable_panels_pane');

  // Need to first ensure that this is a valid subtype.
  $subtype_info = ctools_content_get_subtype($plugin, $subtype);
  if (!empty($subtype_info)) {
    $entity = fieldable_panels_panes_load_from_subtype($subtype);

    // If the entity has some required file fields, check them.
    $required_file_fields = panopoly_widgets_get_required_file_fields($entity->bundle);
    $missing_required = FALSE;
    if (!empty($required_file_fields)) {
      foreach ($required_file_fields as $required_file_field) {
        $items = field_get_items('fieldable_panels_pane', $entity, $required_file_field);

        // Check if the required file field is empty or the file doesn't exist.
        if (empty($items[0]) || empty($items[0]['fid']) || !file_load($items[0]['fid'])) {
          $missing_required = TRUE;
          break;
        }
      }
    }

    // If a required file field is missing, then we return nothing.
    if ($missing_required) {
      return NULL;
    }

    // Otherwise, hand off to the original render callback.
    $original_render_callback = $plugin['original render callback'];
    return $original_render_callback($subtype, $conf, $panels_args, $context);
  }
}

/**
 * Implementation of hook_form_alter()
 */
function panopoly_widgets_form_alter(&$form, &$form_state, $form_id) {

  // Simplify the menu block edit form
  if ($form_id == 'menu_block_menu_tree_content_type_edit_form') {
    $form['admin_title']['#access'] = FALSE;
    $form['depth']['#access'] = FALSE;
    $form['display_options']['#default_value'] = 'advanced';
    $form['display_options']['#access'] = FALSE;
    $form['title_link']['#access'] = FALSE;
    $form['buttons']['#prefix'] = '<div class="menu-block-ctools-buttons">';

    // Disable some options since they appear busted or confusing in Menu Block
    $form['sort']['#access'] = FALSE;

    // Add configuration for max expanded depth.
    $form['expanded_max_depth'] = array(
      '#type' => 'select',
      '#title' => t('Maximum expanded depth'),
      '#weight' => 9,
      '#options' => array(
        '1' => t('Only 1 level'),
        '2' => t('Only 2 levels'),
        '3' => t('Only 3 levels'),
        '4' => t('Only 4 levels'),
        '5' => t('Only 5 levels'),
        '6' => t('Only 6 levels'),
        '7' => t('Only 7 levels'),
        '8' => t('Only 8 levels'),
        '9' => t('Only 9 levels'),
        '0' => t('Expand all children'),
      ),
      '#default_value' => isset($form_state['conf']['expanded_max_depth']) ? $form_state['conf']['expanded_max_depth'] : 0,
      '#states' => array(
        'visible' => array(
          ':input[name="expanded"]' => array(
            'checked' => TRUE,
          ),
        ),
      ),
    );

    // Modify the 'expanded' checkbox so it appears right above the max depth
    // and makes sense with that option.
    $form['expanded']['#weight'] = 8;
    $form['expanded']['#title'] = t('<strong>Expand children</strong> of this tree.');

    // Hide the 'Always display title' option that only useful in rare edge
    // cases.
    if (!empty($form['display_empty'])) {
      $form['display_empty']['#access'] = FALSE;
    }
  }
  if ($form_id == 'fieldable_panels_panes_fieldable_panels_pane_content_type_edit_form') {

    // Add fields to the FPP object if we are adding a reusable object for the first time
    if ($form_state['entity']->reusable && $form_state['op'] == 'add') {
      if (fieldable_panels_panes_access('update', $form_state['entity'])) {
        $form = fieldable_panels_panes_entity_edit_form($form, $form_state);
        $form_state['no update entity'] = FALSE;
      }
      else {
        $form['message']['#markup'] = '<p>' . t("You don't have permission to edit this widget.") . '</p>';
        return;
      }
    }

    // Add a custom pre-render method to deal with "Content Settings" fieldset.
    $form['#pre_render'][] = 'panopoly_widgets_fieldable_panel_pane_pre_render';

    // Remove the revisioning information
    $form['revision']['revision']['#type'] = 'value';
    $form['revision']['log']['#access'] = FALSE;

    // Add a widget setting
    $form['widget_settings']['#type'] = 'fieldset';
    $form['widget_settings']['#title'] = t('General Settings');
    $form['title']['#attributes']['placeholder'] = $form['title']['#title'];
    $form['title']['#title_display'] = 'invisible';
    $form['widget_settings']['title'] = $form['title'];

    // If the title hasn't been replaced by the title module then it's safe to
    // unset it. Otherwise it's already been hidden by the title module.
    if (!(module_exists('title') && isset($form['title']['#field_replacement']) && $form['title']['#field_replacement'])) {
      unset($form['title']);
    }

    // Move the link field into the general settings tab.
    $form['widget_settings']['link'] = $form['link'];
    unset($form['link']);

    // Improve the reusable interface
    $form['reusable']['#title'] = t('Reusable Settings');
    $form['reusable']['#type'] = 'fieldset';
    $form['reusable']['#process'] = array(
      'ctools_dependent_process',
    );
    $form['reusable']['#id'] = 'reusable-settings';
    $form['reusable']['category']['#value'] = t('Reusable Content');
    $form['reusable']['category']['#type'] = 'value';
    $form['reusable']['admin_description']['#access'] = FALSE;

    // Set the proper dependencies for the reusable markup
    $form['reusable']['warning']['#dependency'] = array(
      'edit-reusable' => array(
        1,
      ),
    );
    $form['reusable']['warning']['#prefix'] = '<div id="reusable-wrapper">';
    $form['reusable']['warning']['#suffix'] = '</div>';
    $form['reusable']['warning']['#type'] = 'item';

    // Update the text for the reusable markup
    $form['reusable']['warning']['#markup'] = '<div class="description">' . t('Note: This item is reusable! Any changes made will be applied globally.') . '</div>';
  }

  // Improve the usability and functionality of the table field widget
  if (!empty($form['field_basic_table_table'])) {
    $form['field_basic_table_table'][LANGUAGE_NONE][0]['tablefield']['import']['#access'] = FALSE;

    // Remove importing from CSV
    $form['field_basic_table_table'][LANGUAGE_NONE][0]['tablefield']['rebuild']['#collapsible'] = FALSE;
    $form['field_basic_table_table'][LANGUAGE_NONE][0]['tablefield']['rebuild']['#collapsed'] = FALSE;
    $form['field_basic_table_table'][LANGUAGE_NONE][0]['tablefield']['rebuild']['count_cols']['#field_prefix'] = $form['field_basic_table_table'][LANGUAGE_NONE][0]['tablefield']['rebuild']['count_cols']['#title'] . '? ';
    $form['field_basic_table_table'][LANGUAGE_NONE][0]['tablefield']['rebuild']['count_cols']['#title'] = '';
    $form['field_basic_table_table'][LANGUAGE_NONE][0]['tablefield']['rebuild']['count_rows']['#field_prefix'] = $form['field_basic_table_table'][LANGUAGE_NONE][0]['tablefield']['rebuild']['count_rows']['#title'] . '? ';
    $form['field_basic_table_table'][LANGUAGE_NONE][0]['tablefield']['rebuild']['count_rows']['#title'] = '';
  }
}

/**
 * Implement the "Content Settings" fieldset in a pre-render. This fixes issues with image caused by initially
 * doing this in a form_alter.
 *
 * @see http://drupal.org/node/1567704
 */
function panopoly_widgets_fieldable_panel_pane_pre_render($element) {

  // Add a content settings fieldset.
  $element['content_settings'] = array(
    '#type' => 'fieldset',
    '#title' => t('Content Settings'),
    '#weight' => 1,
  );

  // Add any remaining fields to the content settings fieldset.
  foreach ($element as $key => $value) {
    if (substr($key, 0, 6) == 'field_' || $key == 'body') {
      $element['content_settings'][$key] = $value;
      unset($element[$key]);
    }
  }
  return $element;
}

/** 
 * Implementation of hook_entity_info_alter()
 */
function panopoly_widgets_entity_info_alter(&$entity_info) {

  // Quick links
  $entity_info['fieldable_panels_pane']['bundles']['quick_links'] = array(
    'label' => t('Add links'),
    'description' => t('Add links'),
    'pane category' => t('Custom'),
    'pane top level' => TRUE,
    'pane icon' => drupal_get_path('module', 'panopoly_widgets') . '/images/icon_link.png',
    'admin' => array(
      'path' => 'admin/structure/fieldable-panels-panes/%fieldable_panels_panes_type',
      'bundle argument' => 3,
      'real path' => 'admin/structure/fieldable-panels-panes/quick-links',
      'access arguments' => array(
        'administer fieldable panels panes',
      ),
    ),
  );

  // Basic file
  $entity_info['fieldable_panels_pane']['bundles']['basic_file'] = array(
    'label' => t('Add file'),
    'description' => t('Add file'),
    'pane category' => t('Custom'),
    'pane top level' => TRUE,
    'pane icon' => drupal_get_path('module', 'panopoly_widgets') . '/images/icon_file.png',
    'admin' => array(
      'path' => 'admin/structure/fieldable-panels-panes/%fieldable_panels_panes_type',
      'bundle argument' => 3,
      'real path' => 'admin/structure/fieldable-panels-panes/basic-file',
      'access arguments' => array(
        'administer fieldable panels panes',
      ),
    ),
  );

  // Basic Image
  $entity_info['fieldable_panels_pane']['bundles']['image'] = array(
    'label' => t('Add image'),
    'description' => t('Add image'),
    'pane category' => t('Custom'),
    'pane top level' => TRUE,
    'pane icon' => drupal_get_path('module', 'panopoly_widgets') . '/images/icon_image.png',
    'admin' => array(
      'path' => 'admin/structure/fieldable-panels-panes/%fieldable_panels_panes_type',
      'bundle argument' => 3,
      'real path' => 'admin/structure/fieldable-panels-panes/image',
      'access arguments' => array(
        'administer fieldable panels panes',
      ),
    ),
  );

  // Basic text
  $entity_info['fieldable_panels_pane']['bundles']['text'] = array(
    'label' => t('Add text'),
    'description' => t('Add text'),
    'pane category' => t('Custom'),
    'pane top level' => TRUE,
    'pane icon' => drupal_get_path('module', 'panopoly_widgets') . '/images/icon_text.png',
    'admin' => array(
      'path' => 'admin/structure/fieldable-panels-panes/%fieldable_panels_panes_type',
      'bundle argument' => 3,
      'real path' => 'admin/structure/fieldable-panels-panes/text',
      'access arguments' => array(
        'administer fieldable panels panes',
      ),
    ),
  );

  // Basic Map
  $entity_info['fieldable_panels_pane']['bundles']['map'] = array(
    'label' => t('Add map'),
    'description' => t('Add map'),
    'pane category' => t('Custom'),
    'pane top level' => TRUE,
    'pane icon' => drupal_get_path('module', 'panopoly_widgets') . '/images/icon_map.png',
    'admin' => array(
      'path' => 'admin/structure/fieldable-panels-panes/%fieldable_panels_panes_type',
      'bundle argument' => 3,
      'real path' => 'admin/structure/fieldable-panels-panes/map',
      'access arguments' => array(
        'administer fieldable panels panes',
      ),
    ),
  );

  // Basic table
  $entity_info['fieldable_panels_pane']['bundles']['table'] = array(
    'label' => t('Add table'),
    'description' => t('Add table'),
    'pane category' => t('Custom'),
    'pane top level' => TRUE,
    'pane icon' => drupal_get_path('module', 'panopoly_widgets') . '/images/icon_table.png',
    'admin' => array(
      'path' => 'admin/structure/fieldable-panels-panes/%fieldable_panels_panes_type',
      'bundle argument' => 3,
      'real path' => 'admin/structure/fieldable-panels-panes/table',
      'access arguments' => array(
        'administer fieldable panels panes',
      ),
    ),
  );

  // Basic video
  $entity_info['fieldable_panels_pane']['bundles']['video'] = array(
    'label' => t('Add video'),
    'description' => t('Add video'),
    'pane category' => t('Custom'),
    'pane top level' => TRUE,
    'pane icon' => drupal_get_path('module', 'panopoly_widgets') . '/images/icon_video.png',
    'admin' => array(
      'path' => 'admin/structure/fieldable-panels-panes/%fieldable_panels_panes_type',
      'bundle argument' => 3,
      'real path' => 'admin/structure/fieldable-panels-panes/video',
      'access arguments' => array(
        'administer fieldable panels panes',
      ),
    ),
  );

  // Spotlight
  $entity_info['fieldable_panels_pane']['bundles']['spotlight'] = array(
    'label' => t('Add spotlight'),
    'description' => t('Add spotlight'),
    'pane category' => t('Custom'),
    'pane top level' => TRUE,
    'pane icon' => drupal_get_path('module', 'panopoly_widgets') . '/images/icon_spotlight.png',
    'admin' => array(
      'path' => 'admin/structure/fieldable-panels-panes/%fieldable_panels_panes_type',
      'bundle argument' => 3,
      'real path' => 'admin/structure/fieldable-panels-panes/spotlight',
      'access arguments' => array(
        'administer fieldable panels panes',
      ),
    ),
  );
}

/**
 * Implements hook_theme().
 */
function panopoly_widgets_theme($existing, $type, $theme, $path) {
  return array(
    'panopoly_spotlight_wrapper' => array(
      'render element' => 'element',
    ),
    'panopoly_spotlight_view' => array(
      'render element' => 'element',
    ),
  );
}

/**
 * Implementation of hook_field_display_ENTITY_TYPE_alter().
 *
 * Update the display settings with the option selected on the entity view mode field.
 */
function panopoly_widgets_field_display_fieldable_panels_pane_alter(&$display, $context) {
  if ($context['field']['field_name'] == 'field_existing_content') {
    $view_mode = $context['entity']->field_view_mode[LANGUAGE_NONE][0]['value'];
    if (!empty($view_mode)) {
      $display['settings']['view_mode'] = $view_mode;
    }
  }
}

/**
 * Implementation of hook_file_default_displays_alter()
 */
function panopoly_widgets_file_default_displays_alter(&$default_displays) {

  // Display the 'Generic file' display on video preview.
  if (!empty($default_displays['video__preview__file_field_file_default'])) {
    $default_displays['video__preview__file_field_file_default']->status = FALSE;
  }

  // Set the default video configuration for videos
  if (!empty($default_displays['video__default__media_vimeo_video'])) {
    $default_displays['video__default__media_vimeo_video']->weight = 0;
    $default_displays['video__default__media_vimeo_video']->settings['protocol_specify'] = FALSE;
  }

  // Set the default image style for videos to be our custom video image style
  if (!empty($default_displays['video__default__media_vimeo_image'])) {
    $default_displays['video__default__media_vimeo_image']->settings['image_style'] = 'panopoly_image_video';
  }

  // Set the teaser image style for videos to be our custom video image style
  if (!empty($default_displays['video__teaser__media_vimeo_image'])) {
    $default_displays['video__teaser__media_vimeo_image']->settings['image_style'] = 'panopoly_image_video';
  }

  // Set the preview image style for videos to be our custom thumbnail image style
  if (!empty($default_displays['video__preview__media_vimeo_image'])) {
    $default_displays['video__preview__media_vimeo_image']->settings['image_style'] = 'panopoly_image_thumbnail';
  }
}

/**
 * Implementation of hook_file_type_alter()
 *
 * Alters list of file types that can be assigned to a file.
 */
function panopoly_widgets_file_type_alter(&$types, $file) {
  if ($file->filemime == 'video/youtube' || $file->filemime == 'video/vimeo') {
    $types[] = 'video';
  }
}

/**
 * Implements hook_menu_block_tree_alter().
 */
function panopoly_widgets_menu_block_tree_alter(&$tree, $config) {

  // Only alter if 'expanded' is enabled and the max isn't 'Expand all children'
  if ($config['expanded'] && isset($config['expanded_max_depth']) && $config['expanded_max_depth'] > 0) {
    _panopoly_widgets_menu_block_tree_expanded_max_depth_alter($tree, $config);
  }

  // Updates menu block settings in case of IPE callback magic. This will only
  // work in limited cases but will be fixed when the page refreshes.
  if (arg(0) == 'panels' && arg(1) == 'ajax') {
    foreach ($tree as $key => $value) {
      $tree[$key]['link']['in_active_trail'] = TRUE;
    }
  }
}

/**
 * Remove items from tree which are below the 'expanded_max_depth'.
 */
function _panopoly_widgets_menu_block_tree_expanded_max_depth_alter(&$tree, $config) {

  // Remove all items above the max depth.
  foreach ($tree as $name => &$item) {
    if (!$item['link']['in_active_trail'] && $item['link']['depth'] > $config['expanded_max_depth']) {
      unset($tree[$name]);
    }
    else {
      _panopoly_widgets_menu_block_tree_expanded_max_depth_alter($item['below'], $config);
    }
  }
}

/**
 * Implements hook_fieldable_panels_pane_view().
 */
function panopoly_widgets_fieldable_panels_pane_view($entity, $view_mode, $langcode) {
  if ($entity->bundle == 'image') {

    // Render the image in a link if one is given.
    if (!empty($entity->field_basic_image_link[LANGUAGE_NONE][0]['url'])) {
      $entity->content['field_basic_image_image'][0]['#path'] = array(
        'path' => $entity->field_basic_image_link[LANGUAGE_NONE][0]['display_url'],
      );
    }
  }
}

/**
 * Implements hook_form_FORM_ID_alter().
 */
function panopoly_widgets_form_fieldable_panels_panes_fieldable_panels_pane_content_type_edit_form_alter(&$form, &$form_state) {
  if (isset($form['widget_settings']['link'])) {

    // For when panopoly_magic is enabled.
    $element =& $form['widget_settings']['link'];
  }
  else {
    $element =& $form['link'];
  }
  $element['path']['#linkit'] = array(
    'enable' => TRUE,
    'profile' => 'content_fields',
    'button_text' => t('Search for existing content'),
  );
}

/**
 * Rewrites the node title by poisening the node_load() static cache.
 *
 * We use this to support overriding the title of 'Content item' widgets.
 * Unfortunately, we can't hook into a spot between when the View loads the
 * entity and Panelizer renders it, so we have to use this hack.
 *
 * @param int $nid
 *   The NID of the node whose title we're going to rewrite.
 * @param string|NULL $title
 *   (optional) If a string is given, the this is the new title for the node.
 *   If NULL is given, return the title to its previous value.
 *
 * @see panopoly_widgets_views_post_execute()
 * @see panopoly_widgets_views_post_render()
 */
function _panopoly_widgets_content_item_title_rewrite($nid, $title = NULL) {
  static $saved_title = array();
  $node = node_load($nid);
  if (!is_null($title)) {
    $saved_title[$nid] = $node->title;
    $node->title = $title;
  }
  elseif (isset($saved_title[$nid])) {
    $node->title = $saved_title[$nid];
  }
}

/**
 * Determines if the given view mode on this node shows the title.
 *
 * @param object $node
 *   The fully loaded node object to check.
 * @param string $view_mode
 *   The view mode.
 *
 * @return boolean
 *   TRUE if the title is shown; FALSE otherwise.
 */
function _panopoly_widgets_is_title_shown($node, $view_mode) {
  if (!empty($node->panelizer) && (!empty($node->panelizer[$view_mode]) || !empty($node->panelizer['default']))) {
    $panelizer_display = isset($node->panelizer[$view_mode]) ? $node->panelizer[$view_mode]->display : $node->panelizer['default']->display;
    if (empty($panelizer_display->hide_title) && empty($panelizer_display->pane_title) && strpos($panelizer_display->title, '%node:title') !== FALSE) {

      // We're showing the title via the Panelizer display title.
      return TRUE;
    }
    else {
      foreach ($panelizer_display->content as $pane) {
        if ($pane->type == 'node_title' && $pane->subtype == 'node_title' || $pane->type == 'token' && $pane->subtype == 'node:title') {

          // We're showing the node title in a Pane inside the view mode.
          return TRUE;
        }
        elseif ($pane->type == 'node_content' && $pane->subtype == 'node_content') {
          $child_view_mode = $pane->configuration['build_mode'];

          // Prevent endless recursion.
          if ($child_view_mode == $view_mode) {
            if ($child_view_mode != 'full') {
              $child_view_mode = 'full';
            }
            else {
              continue;
            }
          }
          if (_panopoly_widgets_is_title_shown($node, $child_view_mode)) {
            return TRUE;
          }
        }
      }
      return FALSE;
    }
  }
  else {

    // If we're not using Panelizer, the theme should always be showing
    // the title when rendering the node.
    return TRUE;
  }
}

/**
 * Implements hook_views_pre_view().
 */
function panopoly_widgets_views_pre_view(&$view, &$display_id, &$args) {
  if ($view->name == 'panopoly_widgets_general_content' && $display_id == 'piece_of_content') {

    // If neither 'nid' or 'title' is set, then don't display anything. This is
    // primarily for the live preview, which would otherwise default to the
    // first node. See issue #2463395.
    if (empty($view->exposed_input) || empty($view->exposed_input['nid']) && empty($view->exposed_input['title'])) {
      $view->executed = TRUE;
    }
  }
}

/**
 * Implements hook_views_default_views_alter().
 */
function panopoly_widgets_views_default_views_alter(&$views) {

  // If the locale module is enabled, ensure the "Add content item" widget's
  // View will respect current language settings for the content.
  if (module_exists('locale') && array_key_exists('panopoly_widgets_general_content', $views)) {

    /** @var views_display $piece_of_content */
    $piece_of_content =& $views['panopoly_widgets_general_content']->display['piece_of_content'];
    $piece_of_content->handler->display->display_options['filters']['language']['id'] = 'language';
    $piece_of_content->handler->display->display_options['filters']['language']['table'] = 'node';
    $piece_of_content->handler->display->display_options['filters']['language']['field'] = 'language';
    $piece_of_content->handler->display->display_options['filters']['language']['value'] = array(
      '***CURRENT_LANGUAGE***' => '***CURRENT_LANGUAGE***',
      'und' => 'und',
    );
  }
}

/**
 * Implements hook_views_post_execute().
 */
function panopoly_widgets_views_post_execute(&$view) {
  if ($view->name == 'panopoly_widgets_general_content' && $view->current_display == 'piece_of_content') {
    $display =& $view->display[$view->current_display];
    $row_plugin = $view->style_plugin->row_plugin;

    // If we are rendering the actual node, rather than showing fields or a
    // table, then we need to move the title override to the node itself.
    if (is_a($row_plugin, 'entity_views_plugin_row_entity_view') && !empty($view->result[0])) {
      $nid = $view->result[0]->nid;
      $overridden_title = $display->handler->options['title'];
      if (!empty($overridden_title)) {
        _panopoly_widgets_content_item_title_rewrite($nid, $overridden_title);
        $hide_pane_title = FALSE;

        // Attempt to determine if the node title is being shown in the view
        // mode, so that we can hide the pane title and avoid showing it twice.
        $node = node_load($nid);
        if (_panopoly_widgets_is_title_shown($node, $row_plugin->options['view_mode'])) {
          unset($display->handler->options['title']);
        }
      }
    }
  }
}

/**
 * Implements hook_views_post_render().
 */
function panopoly_widgets_views_post_render(&$view) {
  if ($view->name == 'panopoly_widgets_general_content' && $view->current_display == 'piece_of_content') {

    // Reset the title to its original value.
    $display = $view->display[$view->current_display];
    if (is_a($view->style_plugin->row_plugin, 'entity_views_plugin_row_entity_view') && !empty($view->result[0])) {
      _panopoly_widgets_content_item_title_rewrite($view->result[0]->nid);
    }
  }
}

/**
 * Implements hook_form_views_exposed_form_alter().
 */
function panopoly_widgets_form_views_exposed_form_alter(&$form, &$form_state) {
  $view = $form_state['view'];

  // We have to do this here, as well as below in the alter hook for the
  // 'views_content_views_panes_content_type_edit_form' because that doesn't
  // always happen early enough.
  if ($view->name == 'panopoly_widgets_general_content' && $view->current_display == 'piece_of_content') {

    // This needs to happen in an #after_build so that it runs after all the
    // other processing that happens on this exposed form.
    $form['#after_build'][] = '_panopoly_widgets_piece_of_content_after_build';
  }
}

/**
 * After build callback for the "Content item" widget's exposed form.
 *
 */
function _panopoly_widgets_piece_of_content_after_build(&$form, &$form_state) {

  // Disable maxlength on autocomplete field because node titles can be long,
  // leading to a validation error, preventing the user from referencing them.
  $form['title']['#maxlength'] = NULL;
  return $form;
}

/**
 * Implements hook_form_FORM_ID_alter().
 */
function panopoly_widgets_form_views_content_views_panes_content_type_edit_form_alter(&$form, &$form_state) {
  $view = $form_state['view'];
  if ($view->name == 'panopoly_widgets_general_content' && $view->current_display == 'piece_of_content') {
    $exposed =& $form['exposed'];

    // Disable maxlength on autocomplete field because node titles can be long,
    // leading to a validation error, preventing the user from referencing them.
    // We need to do this here as well as above in the alter hook for
    // 'views_exposed_form' because there situations where that doesn't run.
    $exposed['filter-title']['title']['#maxlength'] = NULL;

    // Set required on the form rather than the View because we need to allow
    // either 'title' or 'nid' when actually rendering the View.
    $exposed['filter-title']['#required'] = TRUE;
    $exposed['filter-title']['title']['#required'] = TRUE;

    // If the user updated panopoly_widgets, but hasn't run the update function
    // panopoly_wigets_update_7012() yet, then bail out because this code can
    // actually break this widget entirely.
    if (empty($exposed['filter-nid'])) {
      return;
    }

    // If we have a value for NID, then we use that to set the title and then
    // clear out and hide the NID. This allows the user to chose the node using
    // the title autocomplete.
    if (!empty($exposed['filter-nid']['nid']['#default_value'])) {
      if ($node = node_load($exposed['filter-nid']['nid']['#default_value'])) {
        $form_state['original_nid'] = $node->nid;
        $form_state['original_title'] = $node->title;
        $exposed['filter-title']['title']['#default_value'] = $node->title;
      }
    }
    $exposed['filter-nid']['nid']['#default_value'] = '';
    $exposed['filter-nid']['#access'] = FALSE;

    // Add a submit callback that will convert back from the title to the NID.
    array_unshift($form['#submit'], '_panopoly_widgets_content_item_form_submit');
  }
}

/**
 * Submission callback for 'Content Item' widget's exposed form.
 */
function _panopoly_widgets_content_item_form_submit($form, &$form_state) {
  $exposed =& $form_state['values']['exposed'];
  if ($exposed['title'] != $form_state['original_title']) {

    // If the title has changed, we need to load the node with that title, set
    // the NID, and then clear out the title. We use the View itself to query
    // so that the result is consistent with autocomplete.
    $view = views_get_view('panopoly_widgets_general_content');
    $view
      ->set_display('piece_of_content');
    $view
      ->set_exposed_input($exposed);
    $view
      ->pre_execute();
    $view
      ->execute($view->current_display);
    $view
      ->post_execute();
    if (count($view->result) > 0) {
      $exposed['nid'] = $view->result[0]->nid;
      $exposed['title'] = '';
    }
  }
  else {

    // If the title hasn't change, we just revert back to the original NID.
    $exposed['nid'] = $form_state['original_nid'];
    $exposed['title'] = '';
  }
}

Functions

Namesort descending Description
panopoly_widgets_apps_app_info Implements hook_apps_app_info()
panopoly_widgets_configure_form Configuration Form for Panopoly Magic
panopoly_widgets_configure_form_submit Form submissions callback for panopoly_widgets_configure_form().
panopoly_widgets_ctools_content_subtype_alter Implementation of hook_ctools_content_subtype_alter()
panopoly_widgets_ctools_plugin_directory Implementation of hook_ctools_plugin_directory()
panopoly_widgets_ctools_plugin_post_alter Implements hook_ctools_plugin_post_alter().
panopoly_widgets_entity_info_alter Implementation of hook_entity_info_alter()
panopoly_widgets_fieldable_panels_pane_render Render callback for fieldable panels panes.
panopoly_widgets_fieldable_panels_pane_view Implements hook_fieldable_panels_pane_view().
panopoly_widgets_fieldable_panel_pane_pre_render Implement the "Content Settings" fieldset in a pre-render. This fixes issues with image caused by initially doing this in a form_alter.
panopoly_widgets_field_default_field_instances_alter Implements hook_field_default_field_instances_alter().
panopoly_widgets_field_display_fieldable_panels_pane_alter Implementation of hook_field_display_ENTITY_TYPE_alter().
panopoly_widgets_file_default_displays_alter Implementation of hook_file_default_displays_alter()
panopoly_widgets_file_type_alter Implementation of hook_file_type_alter()
panopoly_widgets_form_alter Implementation of hook_form_alter()
panopoly_widgets_form_fieldable_panels_panes_fieldable_panels_pane_content_type_edit_form_alter Implements hook_form_FORM_ID_alter().
panopoly_widgets_form_views_content_views_panes_content_type_edit_form_alter Implements hook_form_FORM_ID_alter().
panopoly_widgets_form_views_exposed_form_alter Implements hook_form_views_exposed_form_alter().
panopoly_widgets_get_required_file_fields Gets a list of all the required file fields for the given bundle.
panopoly_widgets_init Implements hook_init()
panopoly_widgets_menu_block_tree_alter Implements hook_menu_block_tree_alter().
panopoly_widgets_page_build Implements hook_page_build()
panopoly_widgets_theme Implements hook_theme().
panopoly_widgets_views_default_views_alter Implements hook_views_default_views_alter().
panopoly_widgets_views_post_execute Implements hook_views_post_execute().
panopoly_widgets_views_post_render Implements hook_views_post_render().
panopoly_widgets_views_pre_view Implements hook_views_pre_view().
_panopoly_widgets_content_item_form_submit Submission callback for 'Content Item' widget's exposed form.
_panopoly_widgets_content_item_title_rewrite Rewrites the node title by poisening the node_load() static cache.
_panopoly_widgets_is_title_shown Determines if the given view mode on this node shows the title.
_panopoly_widgets_menu_block_tree_expanded_max_depth_alter Remove items from tree which are below the 'expanded_max_depth'.
_panopoly_widgets_piece_of_content_after_build After build callback for the "Content item" widget's exposed form.

Constants

Namesort descending Description
PANOPOLY_WIDGETS_FILE_EXTENSIONS_DEFAULT The default list of allowed file extensions in file widgets.