opening_hours.module in Opening hours 6
Same filename and directory in other branches
Opening hours module.
File
opening_hours.moduleView source
<?php
/**
* @file
* Opening hours module.
*/
/**
* Implements hook_menu().
*/
function opening_hours_menu() {
$include_path = drupal_get_path('module', 'opening_hours') . '/includes';
$items = array();
$items['node/%node/opening_hours'] = array(
'title' => 'Opening hours',
'page callback' => 'opening_hours_node_edit_page',
'page arguments' => array(
1,
),
'access callback' => 'opening_hours_node_edit_access',
'access arguments' => array(
1,
),
'weight' => 3,
'file' => 'opening_hours.pages.inc',
'file path' => $include_path,
'type' => MENU_LOCAL_TASK,
);
$items['opening_hours/instances'] = array(
'page callback' => 'opening_hours_crud_api_page',
'access callback' => TRUE,
'file' => 'opening_hours.pages.inc',
'file path' => $include_path,
'type' => MENU_CALLBACK,
);
$items['opening_hours/instances/%opening_hours_instance'] = array(
'page callback' => 'opening_hours_instance_id_api_page',
'page arguments' => array(
2,
),
'access callback' => 'user_access',
'access arguments' => array(
'edit opening hours for content',
),
'file' => 'opening_hours.pages.inc',
'file path' => $include_path,
'type' => MENU_CALLBACK,
);
$items['admin/content/opening_hours'] = array(
'title' => 'Opening hours',
'page callback' => 'opening_hours_admin_settings_page',
'access arguments' => array(
'administer opening hours configuration',
),
'file' => 'opening_hours.admin.inc',
'file path' => $include_path,
);
$items['admin/content/opening_hours/blocked_day/add'] = array(
'title' => 'Add blocked day',
'page callback' => 'drupal_get_form',
'page arguments' => array(
'opening_hours_admin_blocked_day_add_form',
),
'access arguments' => array(
'administer opening hours configuration',
),
'file' => 'opening_hours.admin.inc',
'file path' => $include_path,
);
$items['admin/content/opening_hours/blocked_day/%/delete'] = array(
'title' => 'Delete blocked day',
'page callback' => 'drupal_get_form',
'page arguments' => array(
'opening_hours_admin_blocked_day_delete_form',
4,
),
'access arguments' => array(
'administer opening hours configuration',
),
'file' => 'opening_hours.admin.inc',
'file path' => $include_path,
);
return $items;
}
/**
* Implements hook_block().
*/
function opening_hours_block($op = 'list', $delta = 0, $edit = array()) {
switch ($op) {
case 'list':
return array(
'week' => array(
'info' => t('Opening hours for node by week'),
'cache' => BLOCK_NO_CACHE,
),
);
break;
case 'view':
$block = new stdClass();
if ($node = menu_get_object()) {
$block->title = t('Opening hours');
$block->content = theme('opening_hours_' . $delta, $node);
}
return $block;
}
}
/**
* Implements hook_form_FORM_ID_alter().
*
* We add our own fieldset to the node settings form, so the user can
* enable opening hours for a node type there.
*/
function opening_hours_form_node_type_form_alter(&$form, &$form_state) {
$form['opening_hours'] = array(
'#type' => 'fieldset',
'#title' => t('Opening hours'),
'#collapsible' => TRUE,
'#collapsed' => TRUE,
);
$form['opening_hours']['opening_hours_enabled'] = array(
'#type' => 'checkbox',
'#title' => t('Enable opening hours for this content type'),
'#default_value' => variable_get('opening_hours_enabled_' . $form['#node_type']->type, FALSE),
);
}
/**
* Implements hook_perm().
*/
function opening_hours_perm() {
return array(
'edit opening hours for content',
'administer opening hours configuration',
);
}
/**
* Implements hook_cron().
*/
function opening_hours_cron() {
$last_monthly = variable_get('opening_hours_last_monthly_cron', 0);
// If more than 30 days has passed since last cron, run it again.
if ($last_monthly < $_SERVER['REQUEST_TIME'] - 30 * 86400) {
// Delete repeating instance copies more than a week in the past.
db_query("\n DELETE FROM {opening_hours}\n WHERE original_instance_id IS NOT NULL\n AND customised = 0\n AND date < '%s'\n ", array(
':date' => date('Y-m-d', $_SERVER['REQUEST_TIME'] - 7 * 86400),
));
// Propagate instances that are still repeating.
$propagate_query = db_query("\n SELECT * FROM {opening_hours}\n WHERE repeat_end_date > '%s'\n AND repeat_rule IS NOT NULL AND repeat_rule != ''\n ", array(
':date' => date('Y-m-d', $_SERVER['REQUEST_TIME']),
));
while ($instance = db_fetch_object($propagate_query)) {
opening_hours_repeat_instance_propagate($instance);
}
}
variable_set('opening_hours_last_monthly_cron', $_SERVER['REQUEST_TIME']);
}
/**
* Implements hook_theme().
*/
function opening_hours_theme($existing, $type, $theme, $path) {
return array(
'opening_hours_admin' => array(
'arguments' => array(),
'path' => $path . '/templates',
'template' => 'opening_hours_admin',
),
'opening_hours_presentation' => array(
'arguments' => array(),
'path' => $path . '/templates',
'template' => 'opening_hours_presentation',
),
'opening_hours_week' => array(
'arguments' => array(
'node' => NULL,
),
'path' => $path . '/templates',
'template' => 'opening_hours_week',
),
);
}
/**
* Implements of hook_admin_theme().
*/
function opening_hours_admin_theme_options($op = 'info', $option = NULL) {
switch ($op) {
case 'info':
return array(
'opening_hours' => array(
'title' => t('Opening hours'),
'description' => t('Use the administration theme when administering the opening hours calender.'),
),
);
case 'check':
return $option == 'opening_hours' && arg(0) == 'node' && arg(2) == 'opening_hours';
}
}
/**
* Implements hook_ctools_plugin_directory().
*/
function opening_hours_ctools_plugin_directory($module, $plugin) {
if ($module == 'ctools' && !empty($plugin)) {
return "plugins/{$plugin}";
}
}
/**
* Access callback for the opening hours node edit page.
*/
function opening_hours_node_edit_access($node) {
return user_access('edit opening hours for content') && variable_get('opening_hours_enabled_' . $node->type);
}
/**
* Check if any opening hours has been input on a node.
*
* Used for hiding the opening_hours block on pages where it will never
* display any data.
*
* @param integer $nid
* Node ID to check.
*
* @return boolean
* TRUE if opening hours are present, FALSE if not.
*/
function opening_hours_present_on_node($nid, $reset = FALSE) {
static $presence = array();
$verdict = FALSE;
// Load Drupal’s cache if $presence array is empty.
if (!$reset && empty($presence) && ($cache = cache_get('opening_hours_present_on_node'))) {
if (is_array($cache->data)) {
$presence = $cache->data;
}
}
// Check the static cache.
if (!isset($presence[$nid]) || $reset) {
$presence[$nid] = (bool) db_result(db_query("\n SELECT instance_id FROM {opening_hours} WHERE nid = %d LIMIT 1\n ", array(
':nid' => $nid,
)));
cache_set('opening_hours_present_on_node', $presence);
}
return $presence[$nid];
}
/**
* Load opening hours instance by id.
*/
function opening_hours_instance_load($instance_id) {
$query = db_query("SELECT * FROM {opening_hours} WHERE instance_id = %d LIMIT 1", array(
':id' => $instance_id,
));
if ($row = db_fetch_object($query)) {
return opening_hours_instance_prepare($row);
}
return FALSE;
}
/**
* Load opening hours instances by nid and date.
*/
function opening_hours_instance_load_multiple($nids, $from_date, $to_date) {
// Make sure nids is an array.
if (!is_array($nids)) {
$nids = array(
$nids,
);
}
// Filter nids, so we don't pass nasty things to the database.
array_filter($nids, 'is_numeric');
array_filter($nids);
$query = db_query("\n SELECT * FROM {opening_hours} WHERE nid IN (" . implode(',', $nids) . ")\n AND date BETWEEN '%s' AND '%s'\n ORDER BY start_time\n ", array(
':from_date' => $from_date,
':to_date' => $to_date,
));
$results = array();
while ($row = db_fetch_object($query)) {
$results[] = opening_hours_instance_prepare($row);
}
return $results;
}
/**
* Prepare an instance object loaded from the database for use with Backbone.
*/
function opening_hours_instance_prepare($instance) {
// Cast integers to the correct type.
$instance->instance_id = (int) $instance->instance_id;
$instance->nid = (int) $instance->nid;
$instance->original_instance_id = !empty($instance->original_instance_id) ? (int) $instance->original_instance_id : NULL;
// Backbone expects the primary key to be named `id`. Let's not disappoint.
$instance->id = $instance->instance_id;
$instance->start_time = opening_hours_format_time($instance->start_time);
$instance->end_time = opening_hours_format_time($instance->end_time);
return $instance;
}
/**
* Format a time value from the database, stripping the seconds.
*/
function opening_hours_format_time($time) {
$matches = array();
preg_match('/^([0-2]?\\d):([0-5]?\\d)/', $time, $matches);
if (!empty($matches[1]) && !empty($matches[2])) {
return $matches[1] . ':' . $matches[2];
}
return NULL;
}
/**
* Propagates a repeating instance.
*
* Makes copies of the event each time it repeats until either the
* repeat rule ends or two years have passed.
*/
function opening_hours_repeat_instance_propagate(&$instance) {
// Maximum limit is about two years in the future.
$limit = $_SERVER['REQUEST_TIME'] + 365 * 86400;
// Set up the increment for the repeat rule.
if ($instance->repeat_rule == 'weekly') {
$increment = 7 * 86400;
}
if (!empty($instance->repeat_end_date)) {
// Use noon on the date when converting to timestamp to dodge
// daylight savings issues.
$end_date = strtotime($instance->repeat_end_date . 'T12:00:00');
// If the end date is before the limit, it becomes the new limit.
if ($end_date && $end_date < $limit) {
$limit = $end_date;
}
}
// Bail if we don't have an increment.
if (empty($increment) || $increment < 2) {
return;
}
$current_date = strtotime($instance->date . 'T12:00:00');
// Figure out how far the instance has already been propagated, and
// start there.
$start_point_date = db_result(db_query('
SELECT MAX(date) FROM {opening_hours} WHERE original_instance_id = %d
', array(
':id' => $instance->instance_id,
)));
if ($start_point_date) {
$start_point_date = strtotime($start_point_date . 'T12:00:00');
// If our start point is later than the current date, use that when
// iterating, so we don't generate duplicate entries.
if ($start_point_date > $current_date) {
$current_date = $start_point_date;
}
}
while ($current_date < $limit) {
$current_date += $increment;
// Generate the new propagated instance.
$propagated = (object) array(
'nid' => $instance->nid,
'date' => date('Y-m-d', $current_date),
'start_time' => $instance->start_time,
'end_time' => $instance->end_time,
'original_instance_id' => $instance->instance_id,
'customised' => 0,
);
// Propagate the notice, if set.
if (!empty($instance->notice)) {
$propagated->notice = $instance->notice;
}
drupal_write_record('opening_hours', $propagated);
}
}
/**
* Prevent additional propagation of instance.
*
* Sets the repeat end date of an instance to the date of the latest
* existing instance to prevent additional propagation.
*/
function opening_hours_repeat_stop_propagation($instance_id) {
// Get the date of the last non-deleted instance.
$max_date = db_result(db_query('
SELECT MAX(date) FROM {opening_hours} WHERE original_instance_id = %d
', array(
':id' => $instance_id,
)));
db_query("\n UPDATE {opening_hours}\n SET repeat_end_date = '%s'\n WHERE instance_id = %d\n ", array(
':date' => $max_date,
':id' => $instance_id,
));
}
/**
* Helper function to load our JavaScript dependencies.
*/
function opening_hours_add_js($type = 'presentation', $nid = FALSE) {
$files = array(
'opening_hours.prototype.js',
'opening_hours.core.js',
);
// If jQuery Update is configured to use development versions of
// jQuery, it's probably safe to assume that we want development
// versions of Backbone and Underscore.
$uncompressed = variable_get('jquery_update_compression_type', '') == 'none';
$files[] = $uncompressed ? 'underscore.js' : 'underscore-min.js';
$settings = array(
'blockedDays' => variable_get('opening_hours_blocked_days', array()),
'firstDayOfWeek' => (int) variable_get('date_first_day', 1),
// Options for the jQuery UI datepicker date formatter.
'formatDate' => array(
'monthNames' => array(
t('January'),
t('February'),
t('March'),
t('April'),
t('May'),
t('June'),
t('July'),
t('August'),
t('September'),
t('October'),
t('November'),
t('December'),
),
'dayNames' => array(
t('Sunday'),
t('Monday'),
t('Tuesday'),
t('Wednesday'),
t('Thursday'),
t('Friday'),
t('Saturday'),
),
),
);
// We need the datepicker plugin for formatting and selecting dates.
date_popup_load();
if ($type == 'admin') {
// We use jQuery UI dialogs for editing opening hours.
jquery_ui_add('ui.dialog');
$files[] = $uncompressed ? 'backbone.js' : 'backbone-min.js';
$files[] = 'opening_hours.models.js';
$files[] = 'opening_hours.collections.js';
$files[] = 'opening_hours.views.js';
$files[] = 'opening_hours.routers.js';
$files[] = 'opening_hours.admin.js';
// For the admin page, we need the node ID, passed from the page callback.
$settings['nid'] = $nid;
$settings['path'] = base_path() . drupal_get_path('module', 'opening_hours');
}
elseif ($type == 'presentation') {
$files[] = 'opening_hours.presentation.js';
}
$path = drupal_get_path('module', 'opening_hours');
foreach ($files as $filename) {
drupal_add_js($path . '/js/' . $filename);
}
drupal_add_js(array(
'OpeningHours' => $settings,
), 'setting');
}
/**
* Preprocess variables for the week template.
*/
function template_preprocess_opening_hours_week(&$vars) {
static $once;
// Only add JavaScript and templates the first time this is run on a page.
if (!$once) {
drupal_add_css(drupal_get_path('module', 'opening_hours') . '/css/opening_hours.theme.css');
opening_hours_add_js();
// Add our client-side templates to the page.
$vars['preface'] = theme('opening_hours_presentation');
$once = TRUE;
}
}
Functions
Name![]() |
Description |
---|---|
opening_hours_add_js | Helper function to load our JavaScript dependencies. |
opening_hours_admin_theme_options | Implements of hook_admin_theme(). |
opening_hours_block | Implements hook_block(). |
opening_hours_cron | Implements hook_cron(). |
opening_hours_ctools_plugin_directory | Implements hook_ctools_plugin_directory(). |
opening_hours_format_time | Format a time value from the database, stripping the seconds. |
opening_hours_form_node_type_form_alter | Implements hook_form_FORM_ID_alter(). |
opening_hours_instance_load | Load opening hours instance by id. |
opening_hours_instance_load_multiple | Load opening hours instances by nid and date. |
opening_hours_instance_prepare | Prepare an instance object loaded from the database for use with Backbone. |
opening_hours_menu | Implements hook_menu(). |
opening_hours_node_edit_access | Access callback for the opening hours node edit page. |
opening_hours_perm | Implements hook_perm(). |
opening_hours_present_on_node | Check if any opening hours has been input on a node. |
opening_hours_repeat_instance_propagate | Propagates a repeating instance. |
opening_hours_repeat_stop_propagation | Prevent additional propagation of instance. |
opening_hours_theme | Implements hook_theme(). |
template_preprocess_opening_hours_week | Preprocess variables for the week template. |