You are here

colorbox_node.module in Colorbox Node 7.3

Same filename and directory in other branches
  1. 7 colorbox_node.module
  2. 7.2 colorbox_node.module

Creates a menu callback with support for displaying a node inside of a colorbox.

File

colorbox_node.module
View source
<?php

/**
 * @file
 * Creates a menu callback with support for displaying a node inside of
 * a colorbox.
 */

/**
 * Implments hook_preprocess_html().
 */
function colorbox_node_preprocess_html() {

  // check to see if colorbox should be active.
  if (!_colorbox_active()) {
    return;

    // Don't add the JavaScript and CSS on specified paths.
  }

  // We need to include our misc/ajax.js function all the time in case
  // since we are using the built in AJAX Framework
  drupal_add_library('system', 'drupal.ajax');
  drupal_add_js(drupal_get_path('module', 'colorbox_node') . '/colorbox_node.js', array(
    'type' => 'file',
    'weight' => 10,
  ));
  $js_settings = array(
    'width' => variable_get('colorbox_node_width', '600px'),
    'height' => variable_get('colorbox_node_height', '600px'),
  );

  // Allow other modules to add or change the default settings.
  drupal_alter('colorbox_node_settings', $js_settings);
  drupal_add_js(array(
    'colorbox_node' => $js_settings,
  ), array(
    'type' => 'setting',
    'scope' => JS_DEFAULT,
  ));
}

/**
 * Implements hook_menu().
 */
function colorbox_node_menu() {
  $items['colorbox/%colorbox_node_url'] = array(
    'page callback' => 'colorbox_node_output',
    'page arguments' => array(
      1,
    ),
    'access callback' => 'colorbox_node_check_access',
    'access arguments' => array(
      1,
    ),
    'load arguments' => array(
      '%map',
    ),
    'delivery callback' => 'ajax_deliver',
    'theme callback' => 'ajax_base_page_theme',
    'type' => MENU_CALLBACK,
  );
  return $items;
}

/**
 * Checks the access of the path for the current user
 * based on the menu system access
 * @param $path
 * @return bool
 */
function colorbox_node_check_access($path) {
  $menu_item = menu_get_item($path);
  return isset($menu_item['access']) && $menu_item['access'];
}

/**
 * Implements hook_form_alter().
 */
function colorbox_node_form_alter(&$form, &$form_state, $form_id) {
  switch ($form_id) {
    case 'colorbox_admin_settings':
      $form['colorbox_node'] = array(
        '#type' => 'fieldset',
        '#title' => t('Colorbox Node Integration'),
      );
      $form['colorbox_node']['colorbox_node_regions'] = array(
        '#type' => 'checkbox',
        '#title' => module_exists('context') ? t('Enable Regions') : t('Enable Regions <span class="error">Missing Context Module</span>'),
        '#description' => t('This enables regions to be rendered inside the colorbox modal.  The context module can further target a colorbox modal. <em><b>Experimental</b></em>'),
        '#default_value' => variable_get('colorbox_node_regions', FALSE),
        '#disabled' => !module_exists('context') ? TRUE : FALSE,
      );
      $form['colorbox_node']['colorbox_node_width'] = array(
        '#type' => 'textfield',
        '#title' => t('Default Width'),
        '#description' => t('Default width of the colorbox loaded window.  You must include the \'px\' or \'%\' suffix with your numeric value.'),
        '#default_value' => variable_get('colorbox_node_width', '600px'),
      );
      $form['colorbox_node']['colorbox_node_height'] = array(
        '#type' => 'textfield',
        '#title' => t('Default Height'),
        '#description' => t('Default height of the colorbox loaded window.  You must include the \'px\' or \'%\' suffix with your numeric value.'),
        '#default_value' => variable_get('colorbox_node_height', '600px'),
      );
      break;
  }
}

/**
 * Adds AJAX support to the registration form inside a colorbox modal.
 */
function colorbox_node_form_user_register_form_alter(&$form, &$form_state) {
  colorbox_node_form_ajax_support($form, $form_state, 'register');
}

/**
 * Adds AJAX support to the login form inside a colorbox modal.
 */
function colorbox_node_form_user_login_alter(&$form, &$form_state) {
  colorbox_node_form_ajax_support($form, $form_state, 'login');
}

/**
 * Adds AJAX support to the user pass reset form inside a colorbox modal.
 */
function colorbox_node_form_user_pass_alter(&$form, &$form_state) {
  colorbox_node_form_ajax_support($form, $form_state, 'pass');
}

/**
 * Adds AJAX support to the node edit form inside a colorbox modal.
 */
function colorbox_node_form_node_form_alter(&$form, &$form_state) {
  colorbox_node_form_ajax_support($form, $form_state, 'node');
}

/**
 * Adds AJAX support to the user edit form inside a colorbox modal.
 */
function colorbox_node_form_user_profile_form_alter(&$form, &$form_state) {
  colorbox_node_form_ajax_support($form, $form_state, 'user', 'redirect', 'user');
}

/**
 * @param $form
 * @param $form_state
 * @param $form_id
 * @param string $action
 * The action to take when the form is completed.
 *   close    = Closes the colorbox modal.
 *   redirect = Closes the colorbox modal and redirects the user to the $destination url
 *   reload   = Reloads the current page.  This is good for the login form.
 *   replace  = Replaces the form/ajax data with the provided $destination.
 * @param string $destination
 */
function colorbox_node_form_ajax_support(&$form, &$form_state, $form_id, $action = 'close', $destination = '') {

  // Check to see if we are inside an active colorbox
  if (colorbox_node_is_active() || isset($form_state['#colorboxNode'])) {

    // Set our form to be active as AJAX upload fields will be in a
    // different context and this code will never be called again and will fail out.
    $form_state['#colorboxNode'] = TRUE;
    $form['#prefix'] = '<div id="colorboxNode-' . $form_id . '-Wrapper">';
    $form['#suffix'] = '</div>';
    $form['actions']['submit']['#id'] = 'colorboxNode-' . $form_id . '-Submit';
    $form['actions']['submit']['#ajax'] = array(
      'callback' => 'colorbox_node_ajax_submit',
      'wrapper' => 'colorboxNode-' . $form_id . '-Wrapper',
      'method' => 'replace',
      'effect' => 'fade',
    );
    if ($action == 'reload') {
      $form['#cbox_reload'] = TRUE;
    }
    elseif ($action == 'redirect') {
      $form['#cbox_redirect'] = $destination;
    }
    elseif ($action == 'replace') {
      $form['#cbox_replace'] = $destination;
    }
  }
}

/**
 * Handles all the ajax forms and runs them through this
 * central function to either return the form with error
 * messages, or to close the colorbox and populate our
 * messages div container.
 *
 * @param $form
 * @param $form_state
 * @return array
 * @throws Exception
 */
function colorbox_node_ajax_submit($form, &$form_state) {
  if (!form_get_errors()) {

    // Set our commands for the return to just display status messages.
    $commands = array();

    // Replace the content area with the provided destination
    if (isset($form['#cbox_replace'])) {
      return colorbox_node_output($form['#cbox_replace']);
    }

    // Close the colorbox modal.
    // This is the default behavior.
    $commands[] = ajax_command_invoke('#cboxClose', 'click');

    // Reload the main window if required.
    if (isset($form['#cbox_reload'])) {

      // @TODO: What happens to our messages if the page is reloaded?
      $commands[] = array(
        'command' => 'colorboxNodeReload',
      );
    }
    else {

      // Redirect the user to the passed in destination.
      // @TODO: Add support for dynamic redirects based on newly created content
      if (isset($form['#cbox_redirect'])) {
        $url = url($form['#cbox_redirect']);
        $commands[] = array(
          'command' => 'colorboxNodeRedirect',
          'data' => $url,
        );
      }
      else {
        if (isset($form_state['redirect']) && !empty($form_state['redirect'])) {

          // Lets see if we can find the natural redirect from the form.
          // @TODO: I think the redirect key can also be an array.  Add checks for that.
          if (is_array($form_state['redirect']) && isset($form_state['redirect'][0])) {
            $path = $form_state['redirect'][0];
            $options = array();
            if (isset($form_state['redirect'][1])) {
              foreach ($form_state['redirect'][1] as $key => $value) {
                $options[$key] = $value;
              }
            }
            $data = url($path, $options);
          }
          else {
            $data = url($form_state['redirect']);
          }
          $commands[] = array(
            'command' => 'colorboxNodeRedirect',
            'data' => $data,
          );
        }
        else {

          // Set message.
          // @TODO: How not to make this theme specific?
          // @TODO: Maybe a variable on the admin settings page?
          $commands[] = ajax_command_before('#main-content', theme('status_messages'));
        }
      }
    }
    return array(
      '#type' => 'ajax',
      '#commands' => $commands,
    );
  }
  return $form;
}

/**
 * Displays a node view without the page template.
 * Takes the path as our argument and from that we
 * will determine the internal path and node id.
 */
function colorbox_node_output($path) {

  // Tell others our modal window is active
  drupal_static('colorbox_node_is_active', TRUE);

  // Setup our return destination.
  if (!isset($_GET['destination'])) {
    $_GET['destination'] = $path;
  }

  // Change our super global for the rest of the
  // bootstrap process.
  $_GET['q'] = $path;

  // Fetch our callback based on our path.
  $page_callback_result = menu_execute_active_handler($path, FALSE);

  // Lets include our context execution.
  if (module_exists('context')) {
    if ($plugin = context_get_plugin('condition', 'colorbox_node')) {
      $plugin
        ->execute('view');
    }
  }
  $commands = array();

  // Is we have an array, lets assume we need to render it out.
  if (is_array($page_callback_result)) {
    if (isset($page_callback_result['nodes'])) {
      foreach ($page_callback_result['nodes'] as $nid => $tmp_node) {
        if (isset($tmp_node['#view_mode'])) {
          $node_view = $tmp_node['#node'];
          $node_view_array = node_view($node_view, 'colorbox');
          if (module_exists('comment')) {
            $node_view_array['comments'] = comment_node_page_additions($node_view);
          }
          $rendered_node = drupal_render($node_view_array);
          $page_callback_result['nodes'][$nid] = array(
            '#markup' => $rendered_node,
          );
        }
      }
    }
  }

  // Load up our regions if enabled.
  if (variable_get('colorbox_node_regions', FALSE) == TRUE) {
    drupal_set_page_content($page_callback_result);
    $page_callback_result = element_info('ajax');

    // Modules can add elements to $page as needed in hook_page_build().
    foreach (module_implements('page_build') as $module) {
      $function = $module . '_page_build';
      $function($page_callback_result);
    }

    // Modules alter the $page as needed. Blocks are populated into regions like
    // 'sidebar_first', 'footer', etc.
    drupal_alter('page', $page_callback_result);
  }

  // Allow other modules to alter the colorbox node callback
  drupal_alter('colorbox_node_page_callback_result', $page_callback_result);
  $html = is_string($page_callback_result) ? $page_callback_result : drupal_render($page_callback_result);
  $commands[] = ajax_command_html('#cboxLoadedContent', $html);

  // Add the status messages inside the new content's wrapper element, so that
  // on subsequent Ajax requests, it is treated as old content.
  $commands[] = ajax_command_prepend('#cboxLoadedContent', theme('status_messages'));

  // Render our commands out to the browser.
  return array(
    '#type' => 'ajax',
    '#commands' => $commands,
  );
}

/**
 * Takes a path as an array of all our arguments from the
 * url structure.  We then put that structure back together,
 * find our system path and then return it.
 */
function colorbox_node_url_load($arg, $path = array()) {

  // First lets remove 'colorbox'
  array_shift($path);

  // Lets determine if we have a prefix from our languages.
  if (module_exists('locale') && function_exists('language_url_split_prefix')) {

    // Get our language list to pass into our url splitter.
    $languages = language_list();

    // Turn the path into a string so we can then remove our prefix.
    $path_string = implode('/', $path);
    $language_path = language_url_split_prefix($path_string, $languages);

    // Separate out the returned path and language.  We should always
    // have two indexes, the first is the language, second is the path.
    $language = $language_path[0] ? $language_path[0]->language : '';
    $final_path = $language_path[1];

    // Lets find our path based on the current translation.
    return drupal_get_normal_path($final_path, $language);
  }

  // Now lets buld our path to return our system path,
  return drupal_get_normal_path(implode('/', $path));
}

/**
 * Determines if the current page request is inside a modal window.
 */
function colorbox_node_is_active() {
  return drupal_static('colorbox_node_is_active', FALSE);
}

/**
 * Implements hook_entity_info_alter().
 */
function colorbox_node_entity_info_alter(&$entity_info) {
  $entity_info['node']['view modes']['colorbox'] = array(
    'label' => t('Colorbox'),
    'custom settings' => FALSE,
  );
}

/**
 * Implements hook_views_api().
 */
function colorbox_node_views_api() {
  return array(
    'api' => 2,
    'path' => drupal_get_path('module', 'colorbox_node') . '/views',
  );
}

/**
 * Implements hook_context_plugins().
 */
function colorbox_node_context_plugins() {
  $plugins = array();
  $plugins['colorbox_node_context_condition'] = array(
    'handler' => array(
      'path' => drupal_get_path('module', 'colorbox_node'),
      'file' => 'colorbox_node.context.inc',
      'class' => 'colorbox_node_context_condition',
      'parent' => 'context_condition',
    ),
  );
  return $plugins;
}

/**
 * Implements hook_context_registry().
 */
function colorbox_node_context_registry() {
  return array(
    'conditions' => array(
      'colorbox_node' => array(
        'title' => t('Colorbox Modal'),
        'description' => t('Set this context based on if you are viewing your content inside a colorbox modal.'),
        'plugin' => 'colorbox_node_context_condition',
      ),
    ),
  );
}

/**
 * Implement hook_ctools_plugin_api().
 */
function colorbox_node_ctools_plugin_api($module, $api) {
  if ($module == 'page_manager') {
    return array(
      'version' => 2,
    );
  }
}

/**
 * Implement hook_ctools_plugin_directory().
 */
function colorbox_node_ctools_plugin_directory($module, $plugin) {
  if ($module == 'page_manager' || $module == 'ctools') {
    return 'ctools/plugins/' . $plugin;
  }
}

/**
 * Implements hook_menu_attribute_info().
 */
function colorbox_node_menu_attribute_info() {

  // Add a data-inner-width attribute.
  $attributes['data-inner-width'] = array(
    'label' => t('Data-Inner-Width (px)'),
    'description' => t('Specifies the inner width used by colorbox.'),
    'form' => array(
      '#size' => 5,
    ),
  );

  // Add a data-inner-width attribute.
  $attributes['data-inner-height'] = array(
    'label' => t('Data-Inner-Height (px)'),
    'description' => t('Specifies the inner height used by colorbox.'),
    'form' => array(
      '#size' => 5,
    ),
  );
  return $attributes;
}

/**
 * Implements hook_field_formatter_info_alter().
 */
function colorbox_node_field_formatter_info_alter(&$info) {
  if (isset($info['entityreference_label']) && module_exists('field_formatter_settings')) {
    $info['entityreference_label']['settings'] += array(
      'colorbox_node_link' => FALSE,
      'colorbox_node_classes' => '',
      'colorbox_node_width' => '600',
      'colorbox_node_height' => '600',
    );
  }
}

/**
 * Implements hook_field_formatter_settings_form_alter().
 */
function colorbox_node_field_formatter_settings_form_alter(&$settings_form, $context) {

  // Integration with the entityreference module
  if (isset($context['instance']['display'][$context['view_mode']]['type']) && $context['instance']['display'][$context['view_mode']]['type'] == 'entityreference_label') {
    $display = $context['instance']['display'][$context['view_mode']];
    $settings = $display['settings'];
    switch ($context['form']['#form_id']) {
      case 'field_ui_display_overview_form':
        $class = 'fields-field-entity-settings-edit-form-settings';
        break;
      case 'views_ui_config_item_form':
      default:
        $class = 'options-settings';
        break;
    }
    $settings_form['colorbox_node_link'] = array(
      '#title' => t('Open in a Colorbox'),
      '#type' => 'checkbox',
      '#default_value' => $settings['colorbox_node_link'],
      '#dependency' => array(
        'edit-' . $class . '-link' => array(
          1,
        ),
      ),
    );
    $settings_form['colorbox_node_width'] = array(
      '#type' => 'textfield',
      '#title' => t('Colorbox Width'),
      '#default_value' => !empty($settings['colorbox_node_width']) ? $settings['colorbox_node_width'] : '600',
      '#dependency' => array(
        'edit-' . $class . '-colorbox-node-link' => array(
          1,
        ),
      ),
      '#dependency_count' => 1,
      '#weight' => 1,
    );
    $settings_form['colorbox_node_height'] = array(
      '#type' => 'textfield',
      '#title' => t('Colorbox Height'),
      '#default_value' => !empty($settings['colorbox_node_height']) ? $settings['colorbox_node_height'] : '600',
      '#dependency' => array(
        'edit-' . $class . '-colorbox-node-link' => array(
          1,
        ),
      ),
      '#dependency_count' => 1,
      '#weight' => 2,
    );
    $settings_form['colorbox_node_classes'] = array(
      '#title' => t('Classes to add to the anchor tag (in addition to "colorbox-node")'),
      '#type' => 'textfield',
      '#default_value' => $settings['colorbox_node_classes'],
      '#dependency' => array(
        'edit-' . $class . '-colorbox-node-link' => array(
          1,
        ),
      ),
      '#weight' => 3,
    );
  }
}

/**
 * Implements hook_field_formatter_settings_summary_alter().
 */
function colorbox_node_field_formatter_settings_summary_alter(&$summary, $context) {
  if ($context['instance']['display'][$context['view_mode']]['type'] == 'entityreference_label') {
    $display = $context['instance']['display'][$context['view_mode']];
    $settings = $display['settings'];
    if (!empty($summary)) {
      $summary .= '<br />';
    }
    if (isset($settings['colorbox_node_link']) && $settings['colorbox_node_link']) {
      $summary .= t('Open in Colorbox');
    }
  }
}

/**
 * Implements hook_field_attach_view_alter().
 */
function colorbox_node_field_attach_view_alter(&$output, $context) {
  foreach (element_children($output) as $field_name) {
    $element =& $output[$field_name];
    $field = field_info_field($field_name);
    if (!isset($field['settings']['target_type'])) {
      continue;
    }

    // Load up the rest of our data since we have a target type.
    $instance = field_info_instance($element['#entity_type'], $field_name, $element['#bundle']);
    $entity = entity_get_info($field['settings']['target_type']);
    $display = $instance['display']['default'];
    $settings = $display['settings'];

    // In views, we will have a localized context for our settings.
    // Set them here to override the defaults.
    if (isset($context['display']) && isset($context['display']['settings'])) {
      $settings = $context['display']['settings'];
    }

    // If we are not linking as a colorbox, then just continue on.
    if (!isset($settings['colorbox_node_link']) || !$settings['colorbox_node_link']) {
      continue;
    }
    $handler = entityreference_get_selection_handler($field, $instance, $element['#entity_type'], $entity);
    foreach (element_children($element) as $delta) {
      $label = $handler
        ->getLabel($element['#items'][$delta]['entity']);
      if ($uri = entity_uri($field['settings']['target_type'], $element['#items'][$delta]['entity'])) {
        $class = array();
        if (!empty($settings['colorbox_node_classes'])) {
          $class = array_unique(explode(' ', trim($settings['colorbox_node_classes'])));
        }
        $class[] = 'colorbox-node';
        $uri['options']['attributes'] = array(
          'class' => $class,
          'data-inner-width' => $settings['colorbox_node_width'],
          'data-inner-height' => $settings['colorbox_node_height'],
        );
        $element[$delta]['#markup'] = l($label, $uri['path'], $uri['options']);
      }
    }
  }
}

Functions

Namesort descending Description
colorbox_node_ajax_submit Handles all the ajax forms and runs them through this central function to either return the form with error messages, or to close the colorbox and populate our messages div container.
colorbox_node_check_access Checks the access of the path for the current user based on the menu system access
colorbox_node_context_plugins Implements hook_context_plugins().
colorbox_node_context_registry Implements hook_context_registry().
colorbox_node_ctools_plugin_api Implement hook_ctools_plugin_api().
colorbox_node_ctools_plugin_directory Implement hook_ctools_plugin_directory().
colorbox_node_entity_info_alter Implements hook_entity_info_alter().
colorbox_node_field_attach_view_alter Implements hook_field_attach_view_alter().
colorbox_node_field_formatter_info_alter Implements hook_field_formatter_info_alter().
colorbox_node_field_formatter_settings_form_alter Implements hook_field_formatter_settings_form_alter().
colorbox_node_field_formatter_settings_summary_alter Implements hook_field_formatter_settings_summary_alter().
colorbox_node_form_ajax_support _state _id
colorbox_node_form_alter Implements hook_form_alter().
colorbox_node_form_node_form_alter Adds AJAX support to the node edit form inside a colorbox modal.
colorbox_node_form_user_login_alter Adds AJAX support to the login form inside a colorbox modal.
colorbox_node_form_user_pass_alter Adds AJAX support to the user pass reset form inside a colorbox modal.
colorbox_node_form_user_profile_form_alter Adds AJAX support to the user edit form inside a colorbox modal.
colorbox_node_form_user_register_form_alter Adds AJAX support to the registration form inside a colorbox modal.
colorbox_node_is_active Determines if the current page request is inside a modal window.
colorbox_node_menu Implements hook_menu().
colorbox_node_menu_attribute_info Implements hook_menu_attribute_info().
colorbox_node_output Displays a node view without the page template. Takes the path as our argument and from that we will determine the internal path and node id.
colorbox_node_preprocess_html Implments hook_preprocess_html().
colorbox_node_url_load Takes a path as an array of all our arguments from the url structure. We then put that structure back together, find our system path and then return it.
colorbox_node_views_api Implements hook_views_api().