You are here

quicktabs.module in Quick Tabs 6.3

File

quicktabs.module
View source
<?php

/**
 * Implementation of hook_help().
 */
function quicktabs_help($path, $arg) {
  switch ($path) {
    case 'admin/build/quicktabs':
      return t('<p>The Quick Tabs module allows you to create blocks of tabbed content. Clicking on the tabs makes the corresponding content display instantly (it uses jQuery). The content for each tabbed section can be either a node, view, block or another quicktab. It is an ideal way to do something like the Most Popular / Most Emailed stories tabs you see on many news websites.</p>
<p>Once created, the quicktab block show up in your block listing, ready to be configured and enabled like other blocks. Multiple quicktabs can be placed on a single page.</p>
<p>Visit the <a href="@configuration">configuration page</a> to see the available styles and select the default style for your quicktabs.</p>', array(
        '@configuration' => url('admin/settings/quicktabs'),
      ));
    case 'admin/build/quicktabs/add':
      return '<p>' . t('Here you can create a new quicktab block. Once you have created this block you can configure and enable it on the <a href="@overview">blocks</a> page.', array(
        '@overview' => url('admin/build/block'),
      )) . '</p>';
  }
}

/**
 * Implementation of hook_theme().
 */
function quicktabs_theme() {
  return array(
    'quicktabs_settings' => array(
      'arguments' => array(
        'form' => NULL,
      ),
      'file' => 'includes/admin.inc',
    ),
    'quicktabs_admin_form_tabs' => array(
      'arguments' => array(
        'form' => NULL,
      ),
      'file' => 'includes/admin.inc',
    ),
    'quicktabs_views_render' => array(
      'arguments' => array(
        'view' => NULL,
        'tabs' => NULL,
        'machine_name' => NULL,
      ),
      'file' => 'includes/quicktabs.views.inc',
    ),
    'quicktabs_tabs' => array(
      'arguments' => array(
        'quicktabs',
        'active_tab' => 'none',
      ),
    ),
    'quicktabs' => array(
      'arguments' => array(
        'quicktabs',
      ),
    ),
    'quicktabs_tab_access_denied' => array(
      'arguments' => array(
        'tab',
      ),
    ),
  );
}

/**
 * Implementation of hook_menu().
 */
function quicktabs_menu() {
  $items['admin/build/quicktabs'] = array(
    'title' => 'Quicktabs',
    'description' => 'Create blocks of tabbed content.',
    'page callback' => 'quicktabs_list',
    'access callback' => 'user_access',
    'access arguments' => array(
      'administer quicktabs',
    ),
    'type' => MENU_NORMAL_ITEM,
    'file' => 'includes/admin.inc',
  );
  $items['admin/build/quicktabs/list'] = array(
    'title' => 'List',
    'type' => MENU_DEFAULT_LOCAL_TASK,
  );
  $items['admin/build/quicktabs/add'] = array(
    'title' => 'New QT block',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'quicktabs_form',
      'add',
    ),
    'access arguments' => array(
      'administer quicktabs',
    ),
    'type' => MENU_LOCAL_TASK,
    'file' => 'includes/admin.inc',
  );
  $items['admin/build/quicktabs/%quicktabs'] = array(
    'title' => 'Edit',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'quicktabs_form',
      'edit',
      3,
    ),
    'access arguments' => array(
      'administer quicktabs',
    ),
    'load arguments' => array(
      'edit',
    ),
    'type' => MENU_CALLBACK,
    'file' => 'includes/admin.inc',
  );
  $items['admin/build/quicktabs/%quicktabs/edit'] = array(
    'title' => 'Edit',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'quicktabs_form',
      'edit',
      3,
    ),
    'access arguments' => array(
      'administer quicktabs',
    ),
    'type' => MENU_DEFAULT_LOCAL_TASK,
    'file' => 'includes/admin.inc',
  );
  $items['admin/build/quicktabs/%quicktabs/delete'] = array(
    'title' => 'Delete',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'quicktabs_block_delete',
      3,
    ),
    'access arguments' => array(
      'administer quicktabs',
    ),
    'load arguments' => array(
      'delete',
    ),
    'type' => MENU_LOCAL_TASK,
    'file' => 'includes/admin.inc',
  );
  $items['admin/build/quicktabs/%quicktabs/clone'] = array(
    'title' => 'Clone',
    'page callback' => 'quicktabs_clone',
    'page arguments' => array(
      3,
    ),
    'access arguments' => array(
      'administer quicktabs',
    ),
    'load arguments' => array(
      'clone',
    ),
    'type' => MENU_LOCAL_TASK,
    'file' => 'includes/admin.inc',
  );
  if (module_exists('ctools')) {
    $items['admin/build/quicktabs/%quicktabs/export'] = array(
      'title' => 'Export',
      'page callback' => 'drupal_get_form',
      'page arguments' => array(
        'quicktabs_export_form',
        3,
      ),
      'access arguments' => array(
        'administer quicktabs',
      ),
      'type' => MENU_LOCAL_TASK,
      'file' => 'includes/admin.inc',
    );
  }
  $items['admin/settings/quicktabs'] = array(
    'title' => 'Quicktabs',
    'description' => 'Select the default style for quicktabs.',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'quicktabs_settings',
    ),
    'access callback' => 'user_access',
    'access arguments' => array(
      'administer site configuration',
    ),
    'type' => MENU_NORMAL_ITEM,
    'file' => 'includes/admin.inc',
  );
  $items['quicktabs/ahah'] = array(
    'page callback' => 'quicktabs_ahah',
    'access callback' => 'user_access',
    'access arguments' => array(
      'administer quicktabs',
    ),
    'type' => MENU_CALLBACK,
    'file' => 'includes/admin.inc',
  );
  $items['quicktabs/ajax'] = array(
    'page callback' => 'quicktabs_ajax',
    'access callback' => 'user_access',
    'access arguments' => array(
      'access content',
    ),
    'type' => MENU_CALLBACK,
  );
  return $items;
}

/**
 * Implementation of hook_perm().
 */
function quicktabs_perm() {
  return array(
    'administer quicktabs',
  );
}

/**
 * Implementation of hook_block().
 */
function quicktabs_block($op = 'list', $delta = 0, $edit = array()) {
  switch ($op) {
    case 'list':
      $blocks = array();
      foreach (quicktabs_get_all_quicktabs() as $qt_name => $quicktabs) {
        $blocks[$qt_name]['info'] = $quicktabs['title'];
        $blocks[$qt_name]['cache'] = BLOCK_NO_CACHE;
      }
      return $blocks;
      break;
    case 'view':
      $mainblock = array();
      if ($quicktabs = quicktabs_load($delta)) {
        $mainblock['subject'] = $quicktabs['title'];
        $mainblock['content'] = theme('quicktabs', $quicktabs);
      }
      return $mainblock;
      break;
  }
}

/**
 * Render quicktabs.
 */
function quicktabs_render($quicktabs) {

  // Allow other modules to alter the Quicktabs instance before it gets output.
  drupal_alter('quicktabs', $quicktabs);

  // convert views arguments to an array, retrieving %-style args from url
  $quicktabs['tabs'] = _quicktabs_prepare_views_args($quicktabs['tabs']);
  if ($quicktabs['hide_empty_tabs'] && !$quicktabs['ajax']) {

    // Remove empty tabpgages.
    foreach ($quicktabs['tabs'] as $key => $tab) {
      $contents = quicktabs_render_tabpage($tab, TRUE);
      if (empty($contents)) {
        $quicktabs['tabs'][$key] = NULL;
      }
      else {
        $quicktabs['tabs'][$key]['rendered'] = $contents;
      }
    }
  }
  $tabs_count = count($quicktabs['tabs']);
  if ($tabs_count <= 0) {
    return '';
  }
  if ($quicktabs['style'] == 'default') {
    $quicktabs['style'] = variable_get('quicktabs_tabstyle', 'nostyle');
  }
  quicktabs_add_css($quicktabs['style']);
  $javascript = drupal_add_js('misc/progress.js', 'core');
  if (!isset($javascript['setting'][1]['quicktabs']) || !array_key_exists('qt_' . $quicktabs['machine_name'], $javascript['setting'][1]['quicktabs'])) {

    // Only the tabs are used in quicktabs.js
    $settings = array(
      'tabs' => $quicktabs['ajax'] ? $quicktabs['tabs'] : quicktabs_array_fill_keys(array_keys(array_filter($quicktabs['tabs'])), 0),
    );
    drupal_add_js(array(
      'quicktabs' => array(
        'qt_' . $quicktabs['machine_name'] => $settings,
      ),
    ), 'setting');
  }
  drupal_add_js(drupal_get_path('module', 'quicktabs') . '/js/quicktabs.js');
  $attributes = drupal_attributes(array(
    'id' => 'quicktabs-' . $quicktabs['machine_name'],
    'class' => 'quicktabs_wrapper quicktabs-style-' . drupal_strtolower($quicktabs['style']),
  ));
  $output = '<div' . $attributes . '>';
  $active_tab = _quicktabs_get_active_tab($quicktabs);
  $output .= theme('quicktabs_tabs', $quicktabs, $active_tab);

  // The main content area, each quicktab container needs a unique id.
  $attributes = drupal_attributes(array(
    'id' => 'quicktabs_container_' . $quicktabs['machine_name'],
    'class' => 'quicktabs_main quicktabs-style-' . drupal_strtolower($quicktabs['style']),
  ));
  $output .= '<div' . $attributes . '>';
  if ($quicktabs['ajax']) {

    // Prepare ajax views.
    _quicktabs_prepare_views($quicktabs['tabs']);

    // Render only the active tabpage.
    if (isset($active_tab)) {
      $attributes = drupal_attributes(array(
        'id' => 'quicktabs_tabpage_' . $quicktabs['machine_name'] . '_' . $active_tab,
        'class' => 'quicktabs_tabpage',
      ));
      $output .= '<div' . $attributes . '>' . quicktabs_render_tabpage($quicktabs['tabs'][$active_tab]) . '</div>';
    }

    // We need page preprocessing to populate Drupal.quicktabs.scripts when js aggregation is on.
    quicktabs_has_rendered_ajax_tab(TRUE);
  }
  else {

    // Render all tabpgages.
    foreach ($quicktabs['tabs'] as $key => $tab) {
      $attributes = drupal_attributes(array(
        'id' => 'quicktabs_tabpage_' . $quicktabs['machine_name'] . '_' . $key,
        'class' => 'quicktabs_tabpage' . ($active_tab == $key ? '' : ' quicktabs-hide'),
      ));
      $tab_content = isset($tab['rendered']) ? $tab['rendered'] : quicktabs_render_tabpage($tab);
      $output .= '<div' . $attributes . '>' . $tab_content . '</div>';
    }
  }
  $output .= '</div></div>';
  return $output;
}

/**
 * Ajax callback for tab content.
 */
function quicktabs_ajax($type) {
  $args = func_get_args();
  $type = array_shift($args);
  $func = 'quicktabs_ajax_' . $type;
  $response = array(
    'content' => '',
    'js_css' => array(),
  );
  if (function_exists($func)) {
    $output = call_user_func_array($func, $args);
    $js_css = quicktabs_ajax_js_css();
    $response['content'] = $output;
    $response['js_css'] = $js_css;
  }
  drupal_json(array(
    'status' => 0,
    'data' => $response,
  ));
}

/**
 * Ajax callback for node tabpage.
 */
function quicktabs_ajax_node($nid, $teaser, $hide_title) {
  $tabpage = array(
    'type' => 'node',
    'nid' => $nid,
    'teaser' => $teaser,
    'hide_title' => $hide_title,
  );
  $output = quicktabs_render_tabpage($tabpage);
  return $output;
}

/**
 * Ajax callback for block tabpage.
 */
function quicktabs_ajax_block($qt_name, $bid, $hide_title) {
  $tabpage = array(
    'type' => 'block',
    'qt_name' => $qt_name,
    'bid' => $bid,
    'hide_title' => $hide_title,
  );
  $output = quicktabs_render_tabpage($tabpage);
  return $output;
}

/**
 * Ajax callback for qtabs tabpage.
 */
function quicktabs_ajax_qtabs($qt_name) {
  $tabpage = array(
    'type' => 'qtabs',
    'machine_name' => $qt_name,
  );
  $output = quicktabs_render_tabpage($tabpage);
  return $output;
}

/**
 * Ajax callback for callback tabpage.
 */
function quicktabs_ajax_callback($args) {
  $args = func_get_args();
  $path = implode('/', $args);
  $_GET['q'] = $path;

  // pretend we're in this path
  return menu_execute_active_handler($path);
}

/**
 * Theme function to display the access denied tab.
 *
 * @ingroup themeable
 */
function theme_quicktabs_tab_access_denied($tab) {
  return t('You are not authorized to access this content.');
}

/**
 * Theme function to output quicktabs.
 *
 * @ingroup themeable
 */
function theme_quicktabs($quicktabs) {
  return quicktabs_render($quicktabs);
}

/**
 * Theme function for output of the tabs. Use this to ADD extra classes.
 * The general structure 'ul.quicktabs_tabs li a' needs to be maintained
 * for the jQuery to work.
 *
 * @ingroup themeable
 */
function theme_quicktabs_tabs($quicktabs, $active_tab = 'none') {
  $output = '';
  $tabs_count = count($quicktabs['tabs']);
  if ($tabs_count <= 0) {
    return $output;
  }
  $index = 1;
  $output .= '<ul class="quicktabs_tabs quicktabs-style-' . drupal_strtolower($quicktabs['style']) . '">';
  foreach ($quicktabs['tabs'] as $tabkey => $tab) {
    if (!empty($tab)) {
      $class = 'qtab-' . $tabkey;

      // Add first, last and active classes to the list of tabs to help out themers.
      $class .= $tabkey == $active_tab ? ' active' : '';
      $class .= $index == 1 ? ' first' : '';
      $class .= $index == $tabs_count ? ' last' : '';
      $attributes_li = drupal_attributes(array(
        'class' => $class,
      ));
      $options = _quicktabs_construct_link_options($quicktabs, $tabkey);

      // Support for translatable tab titles with i18nstrings.module.
      if (module_exists('i18nstrings')) {
        $tab['title'] = i18nstrings('quicktabs:tab:' . $quicktabs['machine_name'] . '--' . $tabkey . ':title', $tab['title']);
      }
      $output .= '<li' . $attributes_li . '>' . l($tab['title'], $_GET['q'], $options) . '</li>';
      $index++;
    }
  }
  $output .= '</ul>';
  return $output;
}

/**
 * Helper function to construct link options for tab links.
 */
function _quicktabs_construct_link_options($quicktabs, $tabkey) {
  $qt_name = $quicktabs['machine_name'];
  $ajax = $quicktabs['ajax'];
  $tab = $quicktabs['tabs'][$tabkey];
  $id = 'quicktabs-tab-' . implode('-', array(
    $qt_name,
    $tabkey,
  ));

  // Need to construct the correct query for the tab links.
  $query = $_GET;
  unset($query['quicktabs_' . $qt_name]);
  unset($query['q']);
  unset($query['page']);
  $query['quicktabs_' . $qt_name] = $tabkey;
  if ($ajax) {
    $class = 'qt_ajax_tab';
  }
  else {
    $class = 'qt_tab';
  }
  $link_options = array(
    'attributes' => array(
      'id' => $id,
      'class' => $class,
    ),
    'query' => $query,
    'fragment' => 'quicktabs-' . $qt_name,
  );
  return $link_options;
}

/**
 * Fetch the necessary CSS files for the tab styles.
 */
function quicktabs_add_css($style) {

  // Add quicktabs CSS.
  drupal_add_css(drupal_get_path('module', 'quicktabs') . '/css/quicktabs.css');
  if ($style == 'default') {

    // Get the default style.
    $style = variable_get('quicktabs_tabstyle', 'nostyle');
  }
  $style_css = _quicktabs_get_style_css($style);
  if ($style_css != 'nostyle') {
    drupal_add_css($style_css, 'module');
  }
}

/**
 * Helper function to get the css file for given style.
 */
function _quicktabs_get_style_css($style = 'nostyle') {
  static $tabstyles;
  if ($style != 'nostyle') {
    if (!isset($tabstyles)) {
      $tabstyles = module_invoke_all('quicktabs_tabstyles');
    }
    foreach ($tabstyles as $css_file => $tabstyle) {
      if ($style == $tabstyle) {
        return $css_file;
      }
    }
  }
  return 'nostyle';
}

/**
 * Implementation of hook_quicktabs_tabstyles().
 *
 * This hook allows other modules to create additional tab styles for
 * the quicktabs module.
 *
 * @return array
 *   An array of key => value pairs suitable for inclusion as the #options in a
 *   select or radios form element. Each key must be the location of a css
 *   file for a quick tabs style. Each value should be the name of the style.
 */
function quicktabs_quicktabs_tabstyles() {
  $tabstyles_directory = drupal_get_path('module', 'quicktabs') . '/tabstyles';
  $files = file_scan_directory($tabstyles_directory, '\\.css$');
  $tabstyles = array();
  foreach ($files as $file) {

    // Skip RTL files.
    if (!strpos($file->name, '-rtl')) {
      $tabstyles[$file->filename] = drupal_ucfirst($file->name);
    }
  }
  return $tabstyles;
}

/**
 * Get a list of all available tab styles, suitable for use as an options array.
 */
function quicktabs_style_options($include_defaults = TRUE) {
  $styles = module_invoke_all('quicktabs_tabstyles');

  // The keys used for options must be valid html id-s.
  foreach ($styles as $style) {
    $style_options[$style] = $style;
  }
  ksort($style_options);
  if ($include_defaults) {
    $style_options = array(
      'nostyle' => t('No style'),
      'default' => t('Default style'),
    ) + $style_options;
  }
  return $style_options;
}

/**
 * Load all from defaults and database quicktabs.
 */
function quicktabs_get_all_quicktabs() {
  $quicktabs = array();

  // Load quicktabs via ctools if present.
  if (module_exists('ctools')) {
    ctools_include('export');
    $loaded = ctools_export_load_object('quicktabs', 'all');
    foreach ($loaded as $qt_name => $quicktab) {
      $quicktabs[$qt_name] = (array) $quicktab;
    }
    return $quicktabs;
  }

  // Otherwise, load from DB
  $result = db_query('SELECT machine_name, title, tabs, ajax, hide_empty_tabs, default_tab, style FROM {quicktabs} ORDER BY title');
  while ($quicktab = db_fetch_array($result)) {
    $quicktabs[$quicktab['machine_name']] = _quicktabs_unpack($quicktab);
  }
  return $quicktabs;
}

/**
 * Load the quicktabs data.
 */
function quicktabs_load($qt_name, $op = 'view') {

  // Load quicktabs via ctools is present.
  if (module_exists('ctools')) {
    ctools_include('export');
    $defaults = ctools_export_load_object('quicktabs', 'names', array(
      $qt_name,
    ));
    return isset($defaults[$qt_name]) ? (array) $defaults[$qt_name] : FALSE;
  }

  // Load quicktabs from the database.
  $quicktabs = db_fetch_array(db_query("SELECT machine_name, title, tabs, ajax, hide_empty_tabs, default_tab, style FROM {quicktabs} WHERE machine_name = '%s'", $qt_name));
  if ($quicktabs) {
    return _quicktabs_unpack($quicktabs);
  }
  return FALSE;
}

/**
 * Unpack a quicktabs row array from the database.
 */
function _quicktabs_unpack($quicktabs) {
  $tabs = unserialize($quicktabs['tabs']);
  $weight = array();
  foreach ($tabs as $key => $tab) {
    $weight[$key] = $tab['weight'];
    if ($tab['type'] == 'qtabs' && $tab['machine_name'] == $qt_name) {
      unset($tabs[$key]);
      unset($weight[$key]);
    }
  }
  array_multisort($weight, SORT_ASC, $tabs);
  $quicktabs['tabs'] = $tabs;
  return $quicktabs;
}

/**
 * Render quicktabs tabpage.
 */
function quicktabs_render_tabpage($tab, $hide_empty = FALSE) {
  static $cache;
  $cachekey = md5(serialize($tab));
  if (isset($cache[$cachekey])) {
    return $cache[$cachekey];
  }
  $output = '';
  switch ($tab['type']) {
    case 'qtabs':
      if (isset($tab['machine_name'])) {
        if ($quicktabs = quicktabs_load($tab['machine_name'])) {
          $output = theme('quicktabs', $quicktabs);
        }
      }
      break;
    case 'view':
      if (isset($tab['vid'])) {
        if (module_exists('views')) {
          if ($view = views_get_view($tab['vid'])) {
            if ($view
              ->access($tab['display'])) {
              $view
                ->set_display($tab['display']);
              $view
                ->set_arguments($tab['args']);
              $view_output = $view
                ->preview();
              if (!empty($view->result) || $view->display_handler
                ->get_option('empty') || !empty($view->style_plugin->definition['even empty'])) {
                $output = $view_output;
              }
              else {
                $output = '';
              }
            }
            elseif (!$hide_empty) {
              $output = theme('quicktabs_tab_access_denied', $tab);
            }
            $view
              ->destroy();
          }
        }
        elseif (!$hide_empty) {
          $output = t('Views module not enabled, cannot display tab content.');
        }
      }
      break;
    case 'block':
      if (isset($tab['bid'])) {

        // Ensure the block is assigned to the requested quicktabs block. This test prevents
        // AJAX access to blocks that have not been added to an AJAX-enabled quicktabs block.
        // The qt_name key is set only for AJAX requests.
        if (isset($tab['qt_name'])) {
          $break = TRUE;
          $quicktabs = quicktabs_load($tab['qt_name']);

          // Ensure AJAX is enabled for the quicktabs block.
          if (!empty($quicktabs) && $quicktabs['ajax'] == 1) {

            // Ensure the requested tab has been added to the quicktabs block.
            foreach ($quicktabs['tabs'] as $quicktab) {
              if (isset($quicktab['bid']) && $quicktab['bid'] == $tab['bid']) {
                $break = FALSE;
                break;
              }
            }
          }
          if ($break == TRUE) {
            if (!$hide_empty) {
              $output = theme('quicktabs_tab_access_denied', $tab);
            }
            break;
          }
        }
        $pos = strpos($tab['bid'], '_delta_');
        $blockmodule = substr($tab['bid'], 0, $pos);
        $blockdelta = substr($tab['bid'], $pos + 7);
        $access = _quictabs_access_block($blockmodule, $blockdelta);
        if ($access) {
          $block = (object) module_invoke($blockmodule, 'block', 'view', $blockdelta);
          if (isset($block->content)) {
            $block->module = $blockmodule;
            $block->delta = $blockdelta;
            $block->region = 'quicktabs_tabpage';
            if ($tab['hide_title'] || !isset($block->subject)) {
              $block->subject = FALSE;
            }
            $output = theme('block', $block);
          }
        }
        else {
          $output = theme('quicktabs_tab_access_denied', $tab);
        }
      }
      break;
    case 'node':
      if (isset($tab['nid'])) {
        $node = node_load($tab['nid']);
        if (!empty($node)) {
          if (node_access('view', $node)) {
            $output = node_view($node, $tab['teaser'], $tab['hide_title'], TRUE);
          }
          elseif (!$hide_empty) {
            $output = theme('quicktabs_tab_access_denied', $tab);
          }
        }
      }
      break;
    case 'freetext':
      $output = $tab['text'];
      break;
    case 'callback':
      $output = menu_execute_active_handler($tab['path']);
      break;
  }
  $cache[$cachekey] = $output;
  return $output;
}

/**
 * Helper function to determine if user has access to a specific block delta.
 */
function _quictabs_access_block($module = '', $delta = '') {
  global $user;
  $rids = array_keys($user->roles);
  $result = db_query("SELECT rid from {blocks_roles} br WHERE module = '%s' and delta = '%s'", $module, $delta);
  $authorized_rids = array();
  while ($rid = db_result($result)) {
    $authorized_rids[] = $rid;
  }

  // Return whether the user can access the block:
  // - Either all roles have access - no record in {blocks_roles}
  // - Or only specific roles have access - in which case rids should match.
  return count($authorized_rids) == 0 || count(array_intersect($authorized_rids, $rids)) != 0;
}

/**
 * Helper function to determine active tab from the url.
 */
function _quicktabs_get_active_tab($quicktabs) {
  $active_tab = isset($quicktabs['default_tab']) && $quicktabs['default_tab'] !== false ? $quicktabs['default_tab'] : key($quicktabs['tabs']);
  $active_tab = isset($_GET['quicktabs_' . $quicktabs['machine_name']]) ? $_GET['quicktabs_' . $quicktabs['machine_name']] : $active_tab;
  if (isset($active_tab) && isset($quicktabs['tabs'][$active_tab])) {
    return $active_tab;
  }
  return NULL;
}

/**
 * Helper function to add views settings to ajax tabs.
 */
function _quicktabs_prepare_views($tabs) {
  if (module_exists('views')) {
    views_add_js('ajax_view');
    views_add_css('views');
    foreach ($tabs as $key => $tab) {
      if ($tab['type'] == 'view') {

        // We need to pass view details to js in case there is ajax paging.
        $settings = array(
          'views' => array(
            'ajax_path' => url('views/ajax'),
            'ajaxViews' => array(
              array(
                'view_name' => $tab['vid'],
                'view_display_id' => $tab['display'],
                'view_args' => implode('/', $tab['args']),
                'view_path' => $_GET['q'],
              ),
            ),
          ),
        );
        drupal_add_js($settings, 'setting');
      }
    }
  }
}

/**
 * Helper function to use view arguments from the URL.
 */
function _quicktabs_prepare_views_args($tabs) {
  foreach ($tabs as $key => $tab) {
    if ($tab['type'] == 'view') {
      $url_args = arg();
      $args = $tab['args'];
      foreach ($url_args as $id => $arg) {
        $args = str_replace("%{$id}", $arg, $args);
      }
      $args = preg_replace(',/?(%\\d),', '', $args);
      $args = $args ? explode('/', $args) : array();
      $tab['args'] = $args;
      $tabs[$key] = $tab;
    }
  }
  return $tabs;
}

/**
 * Implementation of hook_locale().
 */
function quicktabs_locale($op = 'groups', $group = NULL) {
  switch ($op) {
    case 'groups':
      return array(
        'quicktabs' => t('Quick Tabs'),
      );
    case 'info':
      $info['quicktabs']['refresh callback'] = 'quicktabs_locale_refresh';
      $info['quicktabs']['format'] = FALSE;
      return $info;
  }
}

/**
 * Refresh locale strings.
 */
function quicktabs_locale_refresh() {
  foreach (quicktabs_get_all_quicktabs() as $qt_name => $quicktabs) {
    foreach ($quicktabs['tabs'] as $tabkey => $tab) {
      i18nstrings_update('quicktabs:tab:' . $qt_name . '--' . $tabkey . ':title', $tab['title']);
    }
  }
  return TRUE;
}

/**
 * This function is based on the ctools_ajax_render() function in the CTools
 * AJAX framework. It allows us to pull js/css files and js settings for content
 * that will be loaded via ajax.
 */
function quicktabs_ajax_js_css() {
  $query_string = '?' . substr(variable_get('css_js_query_string', '0'), 0, 1);
  $scripts = drupal_add_js(NULL, NULL);
  foreach ($scripts as $type => $data) {
    switch ($type) {
      case 'setting':
        $settings = $data;
        break;
      case 'inline':

        // currently we ignore inline javascript.
        break;
      default:

        // If JS preprocessing is off, we still need to output the scripts.
        // Additionally, go through any remaining scripts if JS preprocessing is on and output the non-cached ones.
        foreach ($data as $path => $info) {
          $js_files[] = base_path() . $path . ($info['cache'] ? $query_string : '?' . time());
        }
    }
  }
  $css = drupal_add_css();
  foreach ($css as $media => $types) {

    // If CSS preprocessing is off, we still need to output the styles.
    // Additionally, go through any remaining styles if CSS preprocessing is on and output the non-cached ones.
    foreach ($types as $type => $files) {
      if ($type == 'module') {

        // Setup theme overrides for module styles.
        $theme_styles = array();
        foreach (array_keys($css[$media]['theme']) as $theme_style) {
          $theme_styles[] = basename($theme_style);
        }
      }
      foreach ($types[$type] as $file => $preprocess) {

        // If the theme supplies its own style using the name of the module style, skip its inclusion.
        // This includes any RTL styles associated with its main LTR counterpart.
        if ($type == 'module' && in_array(str_replace('-rtl.css', '.css', basename($file)), $theme_styles)) {

          // Unset the file to prevent its inclusion when CSS aggregation is enabled.
          unset($types[$type][$file]);
          continue;
        }

        // Only include the stylesheet if it exists.
        if (file_exists($file)) {
          $css_files[] = array(
            'file' => base_path() . $file . $query_string,
            'media' => $media,
          );
        }
      }
    }
  }
  $js_css = array();
  if (!empty($settings)) {
    $js_css['js_settings'] = call_user_func_array('array_merge_recursive', $settings);
  }
  if (!empty($js_files)) {
    $js_css['js_files'] = $js_files;
  }
  if (!empty($css_files)) {
    $js_css['css_files'] = $css_files;
  }
  return $js_css;
}

/**
 * Implementation of hook_views_api().
 */
function quicktabs_views_api() {
  return array(
    'api' => 2,
    'path' => drupal_get_path('module', 'quicktabs') . '/includes',
  );
}

/**
 * PHP4 version of array_fill_keys().
 */
function quicktabs_array_fill_keys($keys, $value) {
  $return = array();
  foreach ($keys as $key) {
    $return[$key] = $value;
  }
  return $return;
}

/**
 * Tracks if an ajax tab has been rendered for the current request.
 */
function quicktabs_has_rendered_ajax_tab($value = NULL) {
  static $ajax = FALSE;
  if (isset($value)) {
    $ajax = $value;
  }
  return $ajax;
}

/**
 * Implementation of hook_preprocess_page().
 */
function quicktabs_preprocess_page(&$variables) {

  // Check if any ajax tab has been rendered.
  if (quicktabs_has_rendered_ajax_tab()) {

    // Check if js or css preprocessing is on.
    $ppjs = variable_get('preprocess_js', FALSE);
    $ppcss = variable_get('preprocess_css', FALSE);
    if ($ppjs || $ppcss) {
      $files = quicktabs_ajax_js_css();
      $js = '<script type="text/javascript">';
      $js .= "\n<!--//--><![CDATA[//><!--";
      $js .= "\nif (Drupal && Drupal.quicktabs) {";

      // Populate scripts
      if ($ppjs && !empty($files['js_files'])) {
        $js .= "\n  Drupal.quicktabs.scripts = " . drupal_to_js(drupal_map_assoc($files['js_files'])) . ';';
      }

      // Populate css
      if ($ppcss && !empty($files['css_files'])) {
        $css_paths = array();
        foreach ($files['css_files'] as $entry) {
          $css_paths[$entry['file']] = $entry['file'];
        }
        $js .= "\n  Drupal.quicktabs.css = " . drupal_to_js($css_paths) . ';';
      }
      $js .= "\n}";
      $js .= "\n//--><!]]>";
      $js .= "\n</script>";
      $variables['closure'] .= $js;
    }
  }
}

Functions

Namesort descending Description
quicktabs_add_css Fetch the necessary CSS files for the tab styles.
quicktabs_ajax Ajax callback for tab content.
quicktabs_ajax_block Ajax callback for block tabpage.
quicktabs_ajax_callback Ajax callback for callback tabpage.
quicktabs_ajax_js_css This function is based on the ctools_ajax_render() function in the CTools AJAX framework. It allows us to pull js/css files and js settings for content that will be loaded via ajax.
quicktabs_ajax_node Ajax callback for node tabpage.
quicktabs_ajax_qtabs Ajax callback for qtabs tabpage.
quicktabs_array_fill_keys PHP4 version of array_fill_keys().
quicktabs_block Implementation of hook_block().
quicktabs_get_all_quicktabs Load all from defaults and database quicktabs.
quicktabs_has_rendered_ajax_tab Tracks if an ajax tab has been rendered for the current request.
quicktabs_help Implementation of hook_help().
quicktabs_load Load the quicktabs data.
quicktabs_locale Implementation of hook_locale().
quicktabs_locale_refresh Refresh locale strings.
quicktabs_menu Implementation of hook_menu().
quicktabs_perm Implementation of hook_perm().
quicktabs_preprocess_page Implementation of hook_preprocess_page().
quicktabs_quicktabs_tabstyles Implementation of hook_quicktabs_tabstyles().
quicktabs_render Render quicktabs.
quicktabs_render_tabpage Render quicktabs tabpage.
quicktabs_style_options Get a list of all available tab styles, suitable for use as an options array.
quicktabs_theme Implementation of hook_theme().
quicktabs_views_api Implementation of hook_views_api().
theme_quicktabs Theme function to output quicktabs.
theme_quicktabs_tabs Theme function for output of the tabs. Use this to ADD extra classes. The general structure 'ul.quicktabs_tabs li a' needs to be maintained for the jQuery to work.
theme_quicktabs_tab_access_denied Theme function to display the access denied tab.
_quicktabs_construct_link_options Helper function to construct link options for tab links.
_quicktabs_get_active_tab Helper function to determine active tab from the url.
_quicktabs_get_style_css Helper function to get the css file for given style.
_quicktabs_prepare_views Helper function to add views settings to ajax tabs.
_quicktabs_prepare_views_args Helper function to use view arguments from the URL.
_quicktabs_unpack Unpack a quicktabs row array from the database.
_quictabs_access_block Helper function to determine if user has access to a specific block delta.