You are here

jquery_calendar.module in jQuery World Calendars API 7

Same filename and directory in other branches
  1. 3.x jquery_calendar.module

Implements necessary hooks, API and helpers for jQuery World Calendars.

@todo

File

jquery_calendar.module
View source
<?php

/**
 * @file
 * Implements necessary hooks, API and helpers for jQuery World Calendars.
 *
 * @todo
 *   - Implement hook_library().
 */

/**
 * Implements hook_permission().
 */
function jquery_calendar_permission() {
  return array(
    'administer jquery calendar' => array(
      'title' => 'Administer jQuery Calendar API',
      'description' => 'Administer jQuery Calendar API configuration options.',
    ),
  );
}

/**
 * Implements hook_menu().
 */
function jquery_calendar_menu() {
  $items = array();

  // Administration form:
  $items['admin/config/user-interface/jquery-calendar'] = array(
    'title' => 'jQuery Calendar API',
    'description' => 'Configuration options for jQuery World Calendars.',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'jquery_calendar_form_settings',
    ),
    'access arguments' => array(
      'administer jquery calendar',
    ),
    'file' => 'jquery_calendar.admin.inc',
  );

  // Settings default tab:
  $items['admin/config/user-interface/jquery-calendar/settings'] = array(
    'title' => 'Settings',
    'type' => MENU_DEFAULT_LOCAL_TASK,
    'weight' => 0,
  );

  // Demonstration tab:
  $items['admin/config/user-interface/jquery-calendar/demo'] = array(
    'title' => 'Demonstration',
    'description' => 'jQuery World Calendar demonstration.',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'jquery_calendar_form_demo',
    ),
    'access arguments' => array(
      'administer jquery calendar',
    ),
    'file' => 'jquery_calendar.admin.inc',
    'type' => MENU_LOCAL_TASK,
    'weight' => 10,
  );
  return $items;
}

/**
 * API function to include specified jQuery Calendar
 * library components while trying to take care of dups n' deps.
 *
 * @param $components
 *   Library components that should be loaded on the page.
 *   Either a string with a single filename or comma-separated
 *   filenames. Also it accepts an array of filenames.
 *   Allowed values are:
 *   - all: contains base, plus and datepicker components together.
 *   - base
 *   - plus
 *   - picker
 *   - picker.ext
 *   - validation
 *   - taiwan
 *   - thai
 *   - julian
 *   - persian
 *   - islamic
 *   - hebrew
 *   - ethiopian
 *   - coptic
 *   - mayan
 * @param $locales
 *   Library localization files that should be loaded on the page.
 *   This can be an array, a single string or a comma-separated one.
 *   Note that compressions for these components are not available.
 *   If passed empty automatically adds the languages that are enabled in site
 *   Allowed values are:
 *   - lang: contains all Gregorian calendar locales.
 *   - picker.lang: contains all datepicker locales.
 *   - taiwan-zh-TW
 *   - thai-th
 *   - persian-fa
 *   - islamic-ar
 *   - hebrew-he
 *   - ethiopian-am
 *   - gregorian-af
 *   - gregorian-sq
 *   - gregorian-ar
 *   - gregorian-hy
 *   - gregorian-az
 *   - gregorian-eu
 *   - gregorian-bs
 *   - gregorian-bg
 *   - gregorian-ca
 *   - gregorian-zh-HK
 *   - gregorian-zh-CN
 *   - gregorian-zh-TW
 *   - gregorian-hr
 *   - gregorian-cs
 *   - gregorian-da
 *   - gregorian-nl
 *   - gregorian-nl-BE
 *   - gregorian-en-GB
 *   - gregorian-eo
 *   - gregorian-et
 *   - gregorian-fo
 *   - gregorian-fa
 *   - gregorian-fi
 *   - gregorian-fr
 *   - gregorian-fr-CH
 *   - gregorian-gl
 *   - gregorian-de
 *   - gregorian-de-CH
 *   - gregorian-el
 *   - gregorian-gu
 *   - gregorian-he
 *   - gregorian-hu
 *   - gregorian-is
 *   - gregorian-id
 *   - gregorian-it
 *   - gregorian-ja
 *   - gregorian-ko
 *   - gregorian-lv
 *   - gregorian-lt
 *   - gregorian-mk
 *   - gregorian-ms
 *   - gregorian-no
 *   - gregorian-pl
 *   - gregorian-pt-BR
 *   - gregorian-ro
 *   - gregorian-ru
 *   - gregorian-sr
 *   - gregorian-sr-SR
 *   - gregorian-sk
 *   - gregorian-sl
 *   - gregorian-es
 *   - gregorian-es-AR
 *   - gregorian-sv
 *   - gregorian-ta
 *   - gregorian-th
 *   - gregorian-ar
 *   - gregorian-uk
 *   - gregorian-ur
 *   - gregorian-vi
 *   - picker-af
 *   - picker-sq
 *   - picker-ar
 *   - picker-hy
 *   - picker-az
 *   - picker-eu
 *   - picker-bs
 *   - picker-bg
 *   - picker-ca
 *   - picker-zh-HK
 *   - picker-zh-CN
 *   - picker-zh-TW
 *   - picker-hr
 *   - picker-cs
 *   - picker-da
 *   - picker-nl
 *   - picker-nl-BE
 *   - picker-en-GB
 *   - picker-eo
 *   - picker-et
 *   - picker-fo
 *   - picker-fa
 *   - picker-fi
 *   - picker-fr
 *   - picker-fr-CH
 *   - picker-gl
 *   - picker-de
 *   - picker-de-CH
 *   - picker-el
 *   - picker-gu
 *   - picker-he
 *   - picker-hu
 *   - picker-is
 *   - picker-id
 *   - picker-it
 *   - picker-ja
 *   - picker-ko
 *   - picker-lv
 *   - picker-lt
 *   - picker-mk
 *   - picker-ms
 *   - picker-no
 *   - picker-pl
 *   - picker-pt-BR
 *   - picker-ro
 *   - picker-ru
 *   - picker-sr
 *   - picker-sr-SR
 *   - picker-sk
 *   - picker-sl
 *   - picker-es
 *   - picker-es-AR
 *   - picker-sv
 *   - picker-ta
 *   - picker-th
 *   - picker-ar
 *   - picker-uk
 *   - picker-ur
 *   - picker-vi
 * @param $theme
 *   Datepicker theme.
 * @param $compression
 *   Compression level:
 *   - normal
 *   - min
 *   - pack
 *
 * @see http://keith-wood.name/calendars.html
 * @see http://keith-wood.name/calendarsPicker.html
 *
 * @todo: Add validation API for component availability.
 */
function jquery_calendar_add($components = array(), $locales = array(), $theme = '', $compression = '') {
  static $loaded = array(
    'files' => array(),
  );

  // Add current lang to drupal js settings to be used by data pickers on runtime when nessesary
  global $language;
  $thelang = $language->language;
  $js_variables = array(
    'lang' => $thelang,
  );
  drupal_add_js(array(
    'jquery_calendar' => $js_variables,
  ), "setting");
  $compression = !empty($compression) ? $compression : variable_get('jquery_calendar_compression_level');

  // Convert input parameters to array.
  list($components, $locales) = _jquery_calendar_input_to_array($components, $locales);

  // Check if there's any additional locale available:
  $site_locales = function_exists('locale_language_list') ? locale_language_list('name', TRUE) : NULL;
  if ($site_locales && empty($locales)) {
    foreach ($site_locales as $name => $title) {
      if ($name == 'en') {
        continue;
      }
      $locales[] = 'gregorian-' . $name;
      if (in_array('picker', $components)) {
        $locales[] = 'picker-' . $name;
      }
      if (in_array('persian', $components) && $name == 'fa') {
        $locales[] = 'persian-' . $name;
      }
      if (in_array('thai', $components) && $name == 'th') {
        $locales[] = 'thai-' . $name;
      }
      if (in_array('taiwan', $components) && $name == 'zh-TW') {
        $locales[] = 'taiwan-' . $name;
      }
      if (in_array('islamic', $components) && $name == 'ar') {
        $locales[] = 'islamic-' . $name;
      }
      if (in_array('hebrew', $components) && $name == 'he') {
        $locales[] = 'hebrew-' . $name;
      }
      if (in_array('ethiopian', $components) && $name == 'am') {
        $locales[] = 'ethiopian-' . $name;
      }
    }
  }

  // Clean locales and append 'em to components.
  $length = count($locales);
  for ($i = 0; $i < $length; ++$i) {

    // Remove the gregorian prefix from locale packages.
    if (strpos($locales[$i], 'gregorian') !== FALSE) {
      $locales[$i] = str_replace('gregorian', '', $locales[$i]);
    }
  }

  // Merge components and locales.
  $components = array_merge($components, $locales);

  // See if we should add all of the library components.
  if (!isset($loaded['all']) && in_array('all', $components)) {
    $loaded['all'] = $loaded['base'] = $loaded['plus'] = $loaded['picker'] = $loaded['files']['base'] = $loaded['files']['plus'] = $loaded['files']['picker'] = TRUE;
    jquery_calendar_add(array(
      'all',
    ));
  }
  elseif (!isset($loaded['base'])) {
    $loaded['base'] = TRUE;
    jquery_calendar_add(array(
      'base',
    ));
  }

  // Fulfill dependencies & load library components.
  foreach ($components as $component) {
    if ($component == 'picker' && !isset($loaded['plus'])) {
      $loaded['plus'] = TRUE;
      jquery_calendar_add(array(
        'plus',
      ));
    }
    elseif (($component == 'picker.ext' || $component == 'validation') && !isset($loaded['picker'])) {
      $loaded['picker'] = TRUE;
      jquery_calendar_add(array(
        'picker',
      ));
    }

    // Load the component itself.
    if (!isset($loaded['files'][$component])) {
      $path = _jquery_calendar_component_path($component, $compression);

      // If the component file exists,
      // include and set appropriate flags.
      if (file_exists($path)) {
        drupal_add_js($path);
        $loaded[$component] = TRUE;
        $loaded['files'][$component] = $path;
      }
    }
  }

  // Add datepicker themes, if required.
  // TODO: Add themeroller and jQuery.UI support.
  if (isset($loaded['picker'])) {

    // Override the default theme, if necessary.
    $theme = !empty($theme) ? $theme : variable_get('jquery_calendar_datepicker_theme');

    // Add datepicker theme style.
    $path = _jquery_calendar_component_path('picker', '', 'css', "{$theme}.calendars");
    drupal_add_css($path);
  }
}

/**
 * Helper function to build a library component path.
 *
 * @param $component
 *   Library component name.
 * @param $compression
 *   Compression level.
 * @param $extension
 *   Component file extension.
 * @param $prefix
 *   Component filename prefix.
 *
 * @return
 *   Library component path.
 */
function _jquery_calendar_component_path($component, $compression, $extension = 'js', $prefix = 'jquery.calendars') {
  $path = _jquery_calendar_path() . '/' . $prefix;

  // Fix compression level if required.
  $compression = $compression == 'normal' || empty($compression) || strpos($component, '-') !== FALSE ? '' : '.' . $compression;

  // Fix component name if required.
  if ($component[0] != '-') {
    $component = empty($component) || $component == 'base' ? '' : '.' . $component;
  }
  return $path . $component . $compression . '.' . $extension;
}

/**
 * Helper function to get the library path using Libraries module API.
 *
 * @param $library
 *   Library name to return its path.
 * @param $filename
 *   A library filename to check its existence as an additional condition.
 *
 * @return
 *   Either the library path or FALSE on fail.
 *
 * @see libraries_get_path()
 * @see http://drupal.org/project/libraries
 */
function _jquery_calendar_path($library = 'jquery.calendars', $filename = '') {

  // Get library path via Libraries API.
  $path = libraries_get_path($library);

  // Scan the given path to see if it's that proper one.
  $directory = file_scan_directory($path, '/.*/', array(
    'recurse' => FALSE,
  ));

  // Check that the specified file exists in the given directory.
  $exists = !empty($filename) ? file_exists($path . '/' . $filename) : TRUE;

  // If all is set, return the path.
  if (is_dir($path) && $exists && !empty($directory)) {
    return $path;
  }

  // Or #fail.
  return FALSE;
}

/**
 * Helper function that checks module requirements.
 *
 * @return
 *   An array as per required by hook_requirements().
 */
function _jquery_calendar_requirements_check() {
  if (!defined('REQUIREMENT_OK')) {
    define('REQUIREMENT_OK', 0);
  }
  if (!defined('REQUIREMENT_ERROR')) {
    define('REQUIREMENT_ERROR', 2);
  }
  $t = get_t();
  $requirements = array(
    'jquery_calendar' => array(
      'title' => $t('jQuery Calendar API'),
      'value' => $t('Not installed correctly.'),
    ),
  );

  // Check jQuery Calendars.
  if (!_jquery_calendar_path('jquery.calendars')) {
    $requirements['jquery_calendar']['severity'] = REQUIREMENT_ERROR;
    $requirements['jquery_calendar']['description'] = $t('The <a href="!library">jQuery World Calendars</a> plugin is missing. <a href="!download">Download</a> the library and extract it to <code>sites/all/libraries/</code> directory. Also you need to rename the extracted directory to <strong>jquery.calendars</strong>.', array(
      '!library' => 'http://keith-wood.name/calendars.html',
      '!download' => 'http://keith-wood.name/zip/jquery.calendars.package-1.1.2.zip',
    ));
  }
  else {
    $requirements['jquery_calendar']['severity'] = REQUIREMENT_OK;
    $requirements['jquery_calendar']['value'] = $t('Installed correctly.');
  }
  return $requirements;
}

/**
 * Internal helper to collect all datepicker themes.
 *
 * @return
 *   An array of datepicker theme component names.
 */
function _jquery_calendar_datepicker_themes() {
  $themes = array();
  $files = file_scan_directory(_jquery_calendar_path(), '/.css/', array(
    'key' => 'name',
    'recurse' => FALSE,
  ));
  foreach ($files as $key => $file) {

    // Exluclude jQuery UI themes, for now.
    if (drupal_substr($key, 0, 2) == 'ui') {
      continue;
    }

    // Loadup the array.
    $name = str_replace('.calendars.picker', '', $key);
    $themes[$name] = ucwords($name) . ' - ' . $file->name;
  }
  return $themes;
}

/**
 * Internal helper to convert a mixed-formatted input to an array.
 *
 * @param
 *   Unlimited input parameters.
 *
 * @return
 *   An array of input arrays.
 */
function _jquery_calendar_input_to_array() {
  $arrays = array();
  $args = func_get_args();
  foreach ($args as $arg) {
    if (is_array($arg)) {
      $arg = array_map('trim', $arg);
    }
    else {
      $arg = strpos($arg, ',') !== FALSE ? array_map('trim', explode(',', $arg)) : array(
        trim($arg),
      );
    }
    $arrays[] = array_filter($arg);
  }
  return $arrays;
}

Functions

Namesort descending Description
jquery_calendar_add API function to include specified jQuery Calendar library components while trying to take care of dups n' deps.
jquery_calendar_menu Implements hook_menu().
jquery_calendar_permission Implements hook_permission().
_jquery_calendar_component_path Helper function to build a library component path.
_jquery_calendar_datepicker_themes Internal helper to collect all datepicker themes.
_jquery_calendar_input_to_array Internal helper to convert a mixed-formatted input to an array.
_jquery_calendar_path Helper function to get the library path using Libraries module API.
_jquery_calendar_requirements_check Helper function that checks module requirements.