View complete documentation at !link.
", array('!link' => 'http://drupal.org/node/120710'));
}
}
function calendar_init() {
drupal_add_css(drupal_get_path('module', 'calendar') .'/calendar.css');
include_once(drupal_get_path('module', 'calendar') .'/theme/theme.inc');
drupal_add_js(drupal_get_path('module', 'calendar') .'/calendarblock.js');
drupal_add_js('misc/progress.js');
}
function calendar_theme() {
$path = drupal_get_path('module', 'calendar');
require_once "./$path/theme/theme.inc";
$base = array(
'file' => 'theme.inc',
'path' => "$path/theme",
);
return array(
'calendar_nav' => $base + array(
'template' => 'calendar-nav',
'arguments' => array('view' => NULL, 'with_weeknos' => NULL)
),
'calendar_day_node' => $base + array(
'template' => 'calendar-day-node',
'arguments' => array('node' => NULL, 'view' => NULL),
),
'calendar_month_node' => $base + array(
'template' => 'calendar-month-node',
'arguments' => array('node' => NULL, 'view' => NULL),
),
'calendar_week_node' => $base + array(
'template' => 'calendar-week-node',
'arguments' => array('node' => NULL, 'view' => NULL),
),
'calendar_datebox' => $base + array(
'template' => 'calendar-datebox',
'arguments' => array(
'date' => NULL, 'view' => NULL, 'items' => NULL, 'params' => NULL, 'selected' => NULL),
),
'calendar_title' => $base + array(
'arguments' => array('calendar_type' => NULL, 'view' => NULL),
),
'calendar_date_combo' => $base + array(
'arguments' => array('node', 'lable', 'view'),
),
'calendar_empty_day' => $base + array(
'arguments' => array(),
),
'calendar_stripe_legend' => $base + array(
'arguments' => array('stripe_labels'),
),
'calendar_stripe_stripe' => $base + array(
'arguments' => array('node'),
),
);
}
/**
* Find the number of calendar weeks for a year.
*
* @param int $year
* @return int number of calendar weeks in selected year.
*/
function calendar_max_weeks($year) {
$date = date_make_date(($year+1) . '-01-01 12:00:00', 'UTC');
date_modify($date, '-1 day');
return calendar_date_week(date_format($date, 'Y-m-d'));
}
/**
* Find the calendar week number for a date.
*
* @param string $date, in the format Y-m-d
* @return int calendar week number.
*/
function calendar_date_week($date) {
$parts = explode('-', $date);
$date = date_make_date($date . ' 12:00:00', 'UTC');
$year_date = date_make_date($parts[0] . '-01-01 12:00:00', 'UTC');
$week = intval(date_format($date, 'W'));
$year_week = intval(date_format($year_date, 'W'));
$date_year = intval(date_format($date, 'o'));
// remove the leap week if it's present
if ($date_year > intval($parts[0])) {
$last_date = drupal_clone($date);
date_modify($last_date, '-7 days');
$week = date_format($last_date, 'W') + 1;
} else if ($date_year < intval($parts[0])) {
$week = 0;
}
if ($year_week != 1) $week++;
// convert to ISO-8601 day number, to match weeks calculated above
$iso_first_day = 1 + (variable_get('date_first_day', 0) + 6) % 7;
// if it's before the starting day, it's the previous week
if (intval(date_format($date, 'N')) < $iso_first_day) $week--;
// if the year starts before, it's an extra week at the beginning
if (intval(date_format($year_date, 'N')) < $iso_first_day) $week++;
return $week;
}
/**
* Implementation of hook_form_alter().
* Make sure calendar_fields() gets updated.
*/
function calendar_form_alter($form_id, &$form) {
if ($form_id == 'views_edit_view') {
$form['#submit'] = array_merge($form['#submit'], array('calendar_clear_all' => array()));
}
}
/**
* TODO need to identify type of timezone handling needed for each date field
*/
function calendar_offset($field_name) {
$default_offset = variable_get('date_default_timezone', 0);
$configurable_zones = variable_get('configurable_timezones', 1);
}
/**
* Implementation of hook_views_query()
*
* Handle the date_popup calendar goto date.
*/
function calendar_views_query_alter(&$query, &$view) {
// Check if a new date has been selected and if so redirect.
if (isset($_POST['calendar_goto'])) {
$parts = explode('/', $_POST['calendar_goto']['date']);
$type = $_POST['calendar_type'];
if ($type == 'year') {
unset($parts[1], $parts[2]);
}
elseif ($type == 'month') {
unset($parts[2]);
}
elseif ($type == 'week') {
$date = implode('-', $parts);
$parts[1] = 'W'. calendar_date_week($date);
unset($parts[2]);
}
drupal_goto($view->url .'/'. implode('/', $parts));
drupal_exit();
}
}
/**
* A function to test the validity of various date parts
*/
function calendar_part_is_valid($value, $type) {
if ( !preg_match('/^[0-9]*$/', $value) ) {
return false;
}
$value = intval($value);
if ($value <= 0) return false;
switch ($type) {
case 'year':
if ($value < DATE_MIN_YEAR) return false;
break;
case 'month':
if ($value < 0 || $value > 12) return false;
break;
case 'day':
if ($value < 0 || $value > 31) return false;
break;
case 'week':
if ($value < 0 || $value > 53) return false;
}
return true;
}
/**
* implementation of hook_block()
*/
function calendar_block($op = 'list', $delta = 0) {
switch ($op) {
case 'list' :
$blocks[0]['info'] = t('Calendar Legend.');
$blocks[1]['info'] = t('Switch Calendar.');
return $blocks;
break;
case 'view' :
switch ($delta) {
case 0:
$block['subject'] = t('Calendar Legend');
$block['content'] = $GLOBALS['calendar_stripe_labels'] ? ''. theme('calendar_stripe_legend', $GLOBALS['calendar_stripe_labels']) .'
' : '';
return $block;
case 1:
$block['subject'] = t('Switch Calendar');
$block['content'] = $GLOBALS['calendar_is_calendar'] ? drupal_get_form('calendar_switch_view') : '';
return $block;
}
}
}
/**
* A block with a drop-down list that allows the user to switch between
* views of the current period
*/
function calendar_switch_view() {
$options[''] = t('Calendar');
$options['list'] = t('List');
$options['teasers'] = t('Teasers');
$options['nodes'] = t('Nodes');
$options['table'] = t('Table');
$form = array(
'#method' => 'GET',
'view' => array(
'#type' => 'select',
'#default_value' => $_GET['view'],
'#options' => $options,
),
'q' => array(
'#type' => 'hidden',
'#value' => $_GET['q'],
),
'submit' => array('#type' => 'submit', '#value' => t('Switch')),
);
return $form;
}
/**
* Calendar display types
*/
function calendar_display_types() {
return array('year' => t('Year'), 'month' => t('Month'), 'day' => t('Day'), 'week' => t('Week'));
}
/**
* Figure out which type of display to use,
* based on the current argument.
*
* @return year, month, day, or week.
*/
function calendar_current_type($view) {
if (!is_object($view) || !is_array($view->argument)) {
if (!empty($view->default_display)) {
return $view->default_display;
}
return FALSE;
}
$i = 0;
foreach ($view->argument as $argument) {
if ($argument['id'] == 'calendar_date') {
$parts = array_keys(calendar_arg_parts($view->args[$i]));
break;
}
$i++;
}
return array_pop($parts);
}
/**
* Parse calendar parts from the argument.
*
* Should handle the following patterns:
* YYYY, YYYY-MM, YYYY-M, YYYY-MM-DD, YYYY-M-D, YYYY-W99, YYYY-W9,
* YYYYMM, YYYYMMDD, YYYYW99, YYYYW9
*/
function calendar_arg_parts($argument) {
$parts = array();
preg_match('/(\d{4})?-?(W)?(\d{1,2})?-?(\d{1,2})?/', $argument, $matches);
if (!empty($matches[1])) {
$parts['year'] = $matches[1];
}
if (!empty($matches[3])) {
if (empty($matches[2])) {
$parts['month'] = $matches[3];
}
else {
$parts['week'] = $matches[3];
}
}
if (!empty($matches[4])) {
$parts['day'] = $matches[4];
}
return $parts;
}
/**
* Imput a valid format string for the current argument.
*
* Will always return a format string that uses the dash
* as a separator even if the current argument omits it,
* but that's OK for the way the Calendar module uses it.
*/
function calendar_arg_format($argument) {
$format = array();
$parts = calendar_arg_parts($argument);
foreach ($parts as $key => $part) {
switch ($key) {
case 'year':
$format[] = strlen($part) < 4 ? 'y' : 'Y';
break;
case 'month':
$format[] = strlen($part) < 2 ? 'n' : 'm';
break;
case 'day':
$format[] = strlen($part) < 2 ? 'j' : 'd';
break;
case 'week':
$format[] = '\Ww';
break;
}
}
return implode('-', $format);
}
/**
* Pick up filter and sort info from url.
*/
function calendar_url_append($view) {
//if ($view->build_type == 'page') {
foreach ($_GET as $key => $val) {
if ($key != 'q' && $key != 'view') {
if (!is_array($val)) {
$url .= '&'. $key .'='. $val;
}
else {
foreach ($val as $v) {
$url .= '&'. $key .'[]='. $v;
}
}
}
}
//}
return $url;
}
/**
* create a stripe id from a combination of the field and content types
* and store value for legend
* formula tries to create a unique id for each possible combination
*
* @param $node - the node object
* @param $query_name - the views queryname for this date field
* @param $delta - the delta for this field, used to distinguish fields that appear more than once in the calendar
* @param $label - the label to give this stripe.
*/
function calendar_node_stripe($view, $node, $query_name, $delta, $stripe = NULL, $label = '') {
$type_names = node_get_types('names');
if (!$label) {
$label = $type_names[$node->type] .' '. $view->field[$delta]['label'];
}
if (!$stripe) {
$i = 1;
foreach ($type_names as $k => $v) {
if ($k == $node->type) {
break;
}
$i++;
}
$stripe = intval((20 * $delta) + $i);
}
$GLOBALS['calendar_stripe_labels'][$stripe] = $label;
return $stripe;
}
/**
* Moved the following infrequently-used functions to separate file
* so the code is not parsed on every page.
*/
/**
* Identify all potential date/timestamp fields
*/
function calendar_fields($type = 'name', $reset = FALSE) {
static $fields;
if (empty($fields) || $reset) {
$cid = 'calendar_fields';
if (!$reset && $cached = cache_get($cid, 'cache_views')) {
$fields = $cached->data;
}
else {
include_once('./'. drupal_get_path('module', 'calendar') .'/calendar.inc');
$fields = _calendar_fields();
}
}
return $fields[$type];
}
/**
* Empty or reset cached values.
*
* @param $remove
* whether or not to completely remove the caches.
*/
function calendar_clear_all($remove = FALSE) {
if ($remove) {
cache_clear_all('calendar_views', 'cache_views');
cache_clear_all('calendar_fields', 'cache_views');
}
else {
calendar_fields('name', TRUE);
calendar_info(TRUE);
}
}
/**
* Helper function to figure out a group gid to use in blocks.
*
* @return an array of group nodes that are relevant.
* @todo this may need more work.
*/
function calendar_og_groups($view) {
if (!$groupnode = og_get_group_context()) {
global $user;
$groupnodes = array_keys($user->og_groups);
}
else {
$groupnodes = array($groupnode->nid);
}
return $groupnodes;
}
/**
* A selector to jump to a new date in the calendar.
*
* @param unknown_type $view
* @return unknown
*/
function calendar_date_select($view) {
return ''. drupal_get_form('calendar_date_select_form', $view) .'
';
}
/**
* The date selector form.
*
* @param object $view
* @return the form element
*
* @TODO is the title desired here or does it take up too much space??
*/
function calendar_date_select_form($view) {
$format = 'Y/m/d';
$form['calendar_goto'] = array(
//'#title' => t('Calendar date'),
'#type' => 'date_popup',
'#default_value' => date_format($view->min_date, 'Y-m-d'),
'#date_timezone' => date_default_timezone_name(),
'#date_format' => $format,
);
$form['calendar_type'] = array(
'#type' => 'hidden',
'#value' => $view->calendar_type,
);
$form['submit'] = array(
'#type' => 'submit',
'#value' => t('Change date'),
);
return $form;
}