office_hours.module in Office Hours 5
Same filename and directory in other branches
Creates a field and widget for inserting working or office hours per day
implementation of hook_menu.
File
office_hours.moduleView source
<?php
/**
* @file
* Creates a field and widget for inserting working or office hours per day
*
*
*
/**
* implementation of hook_menu.
*/
function office_hours_menu($may_cache) {
if (!$may_cache) {
drupal_add_css(drupal_get_path('module', 'office_hours') . '/office_hours.css');
}
}
/**
* Implementation of hook_field_info
*
* @return
* An array keyed by field type name. Each element of the array is an associative
* array with these keys and values:
* - "label": The human-readable label for the field type.
*/
function office_hours_field_info() {
return array(
'office_hours' => array(
'label' => 'Office Hours',
),
);
}
/**
* implementation of hook_field
* Handle the parameters for a field.
*
* @param $op
* @param $field
* The field on which the operation is to be performed.
* @return
* This varies depending on the operation.
* - "form": an array of form elements to add to
* the settings page.
* - "validate": no return value. Use form_set_error().
* - "save": an array of names of form elements to
* be saved in the database.
* - "database columns": an array keyed by column name, with arrays of column
* information as values.
* - "callbacks": an array describing the field's behaviour regarding hook_field
* operations. The array is keyed by hook_field operations ('view', 'validate'...)
* and has the following possible values :
* CONTENT_CALLBACK_NONE : do nothing for this operation
* CONTENT_CALLBACK_CUSTOM : use the behaviour in hook_field(operation)
* CONTENT_CALLBACK_DEFAULT : use content.module's default bahaviour
* Note : currently only the 'view' operation implements this feature.
* - "tables": an array of 'tables' definitions as expected by views.module
* (see Views Documentation).
* - "arguments": an array of 'arguments' definitions as expected by views.module
* (see Views Documentation).
* - "filters": an array of 'filters' definitions as expected by views.module
* (see Views Documentation).
* When providing several filters, it is recommended to use the 'name'
* attribute in order to let the user distinguish between them. If no 'name'
* is specified for a filter, the key of the filter will be used instead.
*/
function office_hours_field_settings($op, $field) {
switch ($op) {
case 'form':
$options = _create_hours_arr($field, FALSE);
$optlim = _create_hours_arr($field);
$form = array();
$form['hoursformat'] = array(
'#type' => 'select',
'#title' => t('Hours format'),
'#options' => array(
t('24 hrs.'),
t('12 hrs'),
),
'#default_value' => $field['hoursformat'] ? $field['hoursformat'] : 0,
'#required' => FALSE,
'#description' => t('Format of the clock. IMPORTANT NOTE: if you do not select "Multiple values", you can enter only one day.'),
);
$form['granularity'] = array(
'#type' => 'select',
'#title' => t('granularity of time'),
'#options' => array(
0 => t('Hours'),
30 => t('Half hours'),
15 => t('Quarter hours'),
),
'#default_value' => $field['granularity'] ? $field['granularity'] : 0,
'#required' => FALSE,
'#description' => t('Allow inserting quarter hours, half hours, or only hours of the day'),
);
$form['limitstart'] = array(
'#type' => 'select',
'#title' => t('Limit widget start hours'),
'#options' => $options,
'#default_value' => $field['limitstart'] ? $field['limitstart'] : FALSE,
'#required' => FALSE,
'#description' => t('Set the allowed start hours. Note: if you just changed the clock format, please submit before changing this.'),
);
$form['limitend'] = array(
'#type' => 'select',
'#title' => t('Limit widget end hours'),
'#options' => $options,
'#default_value' => $field['limitend'] ? $field['limitend'] : FALSE,
'#required' => FALSE,
'#description' => t('Set the allowed end hours. Note: if you just changed the clock format, please submit before changing this'),
);
$form['defaultstart'] = array(
'#type' => 'select',
'#title' => t('Start hours default'),
'#options' => $optlim,
'#default_value' => $field['defaultstart'] ? $field['defaultstart'] : FALSE,
'#required' => FALSE,
'#description' => t('Use this field if you want for specific hours to show by default.'),
);
$form['defaultend'] = array(
'#type' => 'select',
'#title' => t('End hours default'),
'#options' => $optlim,
'#default_value' => $field['defaultend'] ? $field['defaultend'] : FALSE,
'#required' => FALSE,
'#description' => t('Use this field if you want for specific hours to show by default.'),
);
$form['valhrs'] = array(
'#type' => 'checkbox',
'#title' => t('Validate hours'),
//'#options' => array('validatehrs'=> t('Check that closing hours are not earlier than opening hours')),
'#required' => FALSE,
'#default_value' => isset($field['valhrs']) ? $field['valhrs'] : 0,
'#description' => t('Check that closing hours are not earlier than opening hours. Please note that this will work as long as the opening hours are not through midnight.'),
);
return $form;
case 'validate':
if ($field['defaultend'] != 'none' && $field['defaultstart'] != 'none') {
if (tf_to_mil($field['defaultend']) <= tf_to_mil($field['defaultstart'])) {
form_set_error('defaultend', 'Default ending hours are earlier than start hours');
}
}
if ($field['limitend'] != 'none' && $field['limitstart'] != 'none') {
if (tf_to_mil($field['limitend']) <= tf_to_mil($field['limitstart'])) {
form_set_error('limitend', 'Limit ending hours are earlier than start hours');
}
}
break;
case 'save':
return array(
'hoursformat',
'granularity',
'limitstart',
'limitend',
'defaultstart',
'defaultend',
'valhrs',
);
case 'database columns':
$columns = array(
'day' => array(
'type' => 'int',
'length' => 1,
'unsigned' => TRUE,
),
'starthours' => array(
'type' => 'varchar',
'length' => 10,
'not null' => FALSE,
'sortable' => TRUE,
),
'endhours' => array(
'type' => 'varchar',
'length' => 10,
'not null' => FALSE,
'sortable' => TRUE,
),
);
return $columns;
case 'callbacks':
return array(
'view' => CONTENT_CALLBACK_CUSTOM,
);
case 'tables':
$tables = content_views_field_tables($field);
return $tables;
case 'arguments':
$arguments = content_views_field_arguments($field);
return $arguments;
case 'filters':
return array(
'substring' => array(
'operator' => 'views_handler_operator_like',
'handler' => 'views_handler_filter_like',
),
'alpha_order' => array(
'name' => 'alphabetical order',
'operator' => 'views_handler_operator_gtlt',
),
);
}
}
/**
* implementation of hook_field
* Define the behavior of a field type.
*
* @param $op
* What kind of action is being performed. Possible values.
* @param &$node
* The node the action is being performed on. This argument is passed by
* reference for performance only; do not modify it.
* @param $field
* The field the action is being performed on.
* @param &$node_field
* The contents of the field in this node. Changes to this variable will
* be saved back to the node object.
* @return
* This varies depending on the operation.
* - The "load" operation should return an object containing extra values
* to be merged into the node object.
* - The "view" operation should return a string containing an HTML
* representation of the field data.
* - The "insert", "update", "delete", "validate", and "submit" operations
* have no return value.
*
* In most cases, only "validate" operations is relevant ; the rest
* have default implementations in content_field() that usually suffice.
*/
function office_hours_field($op, &$node, $field, &$node_field, $teaser, $page) {
switch ($op) {
case 'view':
$context = $teaser ? 'teaser' : 'full';
$formatter = isset($field['display_settings'][$context]['format']) ? $field['display_settings'][$context]['format'] : 'default';
$items = array();
foreach ($node_field as $delta => $item) {
$items[$delta]['view'] = content_format($field, $item, $formatter, $node);
}
return theme('field', $node, $field, $items, $teaser, $page);
case 'validate':
if ($field['valhrs'] == 1) {
if (is_array($node_field)) {
foreach ($node_field as $delta => $item) {
$error_field = $field['field_name'] . '][' . $delta . '][endhours';
$starthours = tf_to_mil($item['starthours']);
$endhours = tf_to_mil($item['endhours']);
if ($starthours >= $endhours) {
form_set_error($error_field, t('Closing hours are earlier than opening hours'));
}
}
}
}
break;
}
}
/**
* Declare information about a formatter.
*
* @return
* An array keyed by formatter name. Each element of the array is an associative
* array with these keys and values:
* - "label": The human-readable label for the formatter.
* - "field types": An array of field type names that can be displayed using
* this formatter.
*/
function office_hours_field_formatter_info() {
return array(
'default' => array(
'label' => 'default',
'field types' => array(
'office_hours',
),
),
);
}
/**
* implementation of hook_field_formatter
* Prepare an individual item for viewing in a browser.
*
* @param $field
* The field the action is being performed on.
* @param $item
* An array, keyed by column, of the data stored for this item in this field.
* @param $formatter
* The name of the formatter being used to display the field.
* @param $node
* The node object, for context. Will be NULL in some cases.
* Warning : when displaying field retrieved by Views, $node will not
* be a "full-fledged" node object, but an object containg the data returned
* by the Views query (at least nid, vid, changed)
* @return
* An HTML string containing the formatted item.
*
* It is important that this function at the minimum perform security
* transformations such as running check_plain() or check_markup().
*/
function office_hours_field_formatter($field, $item, $formatter, $node) {
static $count = 0;
static $lastday = 7;
if ($count > 0) {
//this is not the first iteration.
if ($lastday == $item['day']) {
$display = 'hide';
}
else {
$display = 'show';
}
}
$count++;
$lastday = $item['day'];
if (isset($item['day'])) {
$daykey = check_plain($item['day']);
$days = array(
0 => t('Sunday'),
1 => t('Monday'),
2 => t('Tuesday'),
3 => t('Wednesday'),
4 => t('Thursday'),
5 => t('Friday'),
6 => t('Saturday'),
);
$day = $days[$daykey];
}
else {
$day = '';
}
$endhrs = check_plain($item['endhours']);
$strhrs = check_plain($item['starthours']);
if ($field['hoursformat'] == 1) {
$endhrs = convert_to_ampm($endhrs);
$strhrs = convert_to_ampm($strhrs);
}
switch ($formatter) {
default:
return theme('oh_formatter_display', $day, $strhrs, $endhrs, $display);
}
}
/**
* Declare information about a widget.
*
* @return
* An array keyed by widget name. Each element of the array is an associative
* array with these keys and values:
* - "label": The human-readable label for the widget.
* - "field types": An array of field type names that can be edited using
* this widget.
*/
function office_hours_widget_info() {
return array(
'default' => array(
'label' => t('Office Hours'),
'field types' => array(
'office_hours',
),
),
);
}
/**
* * Implementation of hook_widget().
*
* @param $op
* What kind of action is being performed. Possible values:
* @param &$node
* The node the action is being performed on. This argument is passed by
* reference for performance only; do not modify it.
* @param $field
* The field the action is being performed on.
* @param &$node_field
* The contents of the field in this node. Changes to this variable will
* be saved back to the node object.
* @return
* This varies depending on the operation.
* - The "form" operation should return an array of form elements to display.
* - Other operations have no return value.
*/
function office_hours_widget($op, &$node, $field, &$node_field) {
switch ($op) {
case 'prepare form values':
$items = array();
foreach ($node_field as $key => $item) {
$day = $item['day'];
$delta = $day * 2;
//0,2,4,6,8,10,12
$deltaplus = $delta + 1;
//1,3,5,7,9,11,13
if (!isset($items[$delta])) {
$items[$delta] = $item;
}
else {
$items[$deltaplus] = $item;
}
}
$node_field = $items;
break;
case 'form':
$ophours = _create_hours_arr($field, TRUE);
$opdays = array(
t('Sunday'),
t('Monday'),
t('Tuesday'),
t('Wednesday'),
t('Thursday'),
t('Friday'),
t('Saturday'),
);
$form = array();
$form[$field['field_name']] = array(
'#tree' => TRUE,
);
$form[$field['field_name']]['#type'] = 'fieldset';
$form[$field['field_name']]['#title'] = t($field['widget']['label']);
$form[$field['field_name']]['#description'] = t('Mark the days you want to show and set the hours accordingly');
$form[$field['field_name']]['#attributes'] = array(
'class' => 'office-container-inline',
);
foreach (range(0, 6) as $day) {
//day is 0,1,2,3,4,5,6
if ($field['multiple']) {
$delta = $day * 2;
//0,2,4,6,8,10,12
$deltaplus = $delta + 1;
//1,3,5,7,9,11,13
}
else {
$delta = $day;
}
$form[$field['field_name']][$delta]['day'] = array(
'#type' => 'value',
'#value' => $day,
);
$form[$field['field_name']][$delta]['daycheck'] = array(
'#type' => 'checkbox',
'#title' => $opdays[$day],
'#description' => $field['widget']['description'],
'#default_value' => isset($node_field[$delta]['day']) ? 1 : 0,
'#prefix' => '<div class="office-hours-block">',
);
$form[$field['field_name']][$delta]['starthours'] = array(
'#type' => 'select',
'#title' => '',
'#options' => $ophours,
'#required' => $field['required'],
'#description' => $field['widget']['description'],
'#prefix' => '<div class ="oh-toggle">',
'#default_value' => isset($node_field[$delta]['starthours']) ? $node_field[$delta]['starthours'] : $field['defaultstart'],
);
$form[$field['field_name']][$delta]['endhours'] = array(
'#type' => 'select',
'#title' => '',
'#options' => $ophours,
'#required' => $field['required'],
'#description' => $field['widget']['description'],
'#default_value' => isset($node_field[$delta]['endhours']) ? $node_field[$delta]['endhours'] : $node_field['defaultend'],
);
if ($field['multiple']) {
$form[$field['field_name']][$delta]['morelink'] = array(
'#value' => t('Additional hours block:'),
'#prefix' => '<span class ="morelink">',
'#suffix' => '</span>',
);
$form[$field['field_name']][$deltaplus]['day'] = array(
'#type' => 'value',
'#value' => $day,
);
$form[$field['field_name']][$deltaplus]['starthours'] = array(
// from more link
'#type' => 'select',
'#title' => '',
'#options' => $ophours,
'#description' => $field['widget']['description'],
'#prefix' => '<div class ="oh-toggle-more">',
'#default_value' => isset($node_field[$deltaplus]['starthours']) ? $node_field[$deltaplus]['starthours'] : '',
);
$form[$field['field_name']][$deltaplus]['endhours'] = array(
//from more link
'#type' => 'select',
'#title' => '',
'#options' => $ophours,
'#description' => $field['widget']['description'],
'#default_value' => isset($node_field[$deltaplus]['endhours']) ? $node_field[$deltaplus]['endhours'] : '',
'#suffix' => '</div></div></div>',
);
}
}
return $form;
case 'process form values':
foreach ($node_field as $delta => $item) {
if ($item['day'] == NULL && ($delta == 0 || $delta == 1)) {
//adjust for sunday.
$node_field[$delta]['day'] = '0';
}
if ($item['daycheck'] == 0 && $delta % 2 == 0) {
unset($node_field[$delta]);
}
if ($item['starthours'] == 'none' || $item['endhours'] == 'none') {
unset($node_field[$delta]);
}
}
break;
}
}
/**
* helper function to create hours array.
* items are saved in 24 hours string format (i.e '18:00').
*/
function _create_hours_arr($field, $limit = TRUE) {
$fl1 = $field['limitstart'];
$fl2 = $field['limitend'];
$gran = $field['granularity'] == 0 ? 60 : $field['granularity'];
$limst = 0;
$limend = 23;
$mins = '00';
$mine = 60;
if ($limit === TRUE) {
if ($fl1 != 'none') {
list($limst, $mins) = explode(":", $fl1);
}
if ($fl2 != 'none') {
list($limend, $mine) = explode(":", $fl2);
}
}
$ophours['none'] = t('None');
if ($field['hoursformat'] == 1) {
//12-hour clock
foreach (range($limst, $limend) as $i) {
$mincounter = $i == $limst ? $mins : 0;
//in the first iteration, start the count according to limst. if not, begin from 0
for (; $mincounter <= 45; $mincounter = $mincounter + $gran) {
if (!($i == $limend && $mincounter > $mine)) {
//last iteration
$mincounter = $mincounter == 0 ? '00' : $mincounter;
//preparing the mincounter for use in a string
$hr = $i . ':' . $mincounter;
$ophours[$hr] = convert_to_ampm($hr);
}
}
}
}
else {
//24-hour clock
foreach (range($limst, $limend) as $i) {
$mincounter = $i == $limst ? $mins : 0;
for (; $mincounter <= 45; $mincounter = $mincounter + $gran) {
if (!($i == $limend && $mincounter > $mine)) {
$mincounter = $mincounter == 0 ? '00' : $mincounter;
$hr = $i . ':' . $mincounter;
$ophours[$hr] = $hr;
}
}
}
}
return $ophours;
}
/**
* Helper function for conversion of clock format.
*/
function convert_to_ampm($hour) {
list($hr, $min) = explode(":", $hour);
if ($hr == '0') {
// midnight
$hr = 12;
$ampm = ' AM';
}
elseif ($hr == 12) {
// noon
$hr = 12;
$ampm = ' PM';
}
elseif ($hr > 12 && $hr < 24) {
// a pm time
$hr = $hr - 12;
$ampm = ' PM';
}
else {
$ampm = ' AM';
}
return $hr . ':' . $min . $ampm;
}
function tf_to_mil($hour) {
list($hr, $min) = explode(":", $hour);
$hr = $hr * 60 + $min;
return $hr;
}
/**
* Theme function for date node display
*/
function theme_oh_formatter_display($day, $strhrs, $endhrs, $display) {
$display = !isset($display) ? 'show' : $display;
return '<div class="oh-display"><span class="oh-display-day-' . $display . '">' . $day . '</span>
<span class="oh-display-start">' . $strhrs . '</span>
<span class="oh-display-separator"> - </span>
<span class="oh-display-end">' . $endhrs . '</span></div>';
}
Functions
Name | Description |
---|---|
convert_to_ampm | Helper function for conversion of clock format. |
office_hours_field | implementation of hook_field Define the behavior of a field type. |
office_hours_field_formatter | implementation of hook_field_formatter Prepare an individual item for viewing in a browser. |
office_hours_field_formatter_info | Declare information about a formatter. |
office_hours_field_info | Implementation of hook_field_info |
office_hours_field_settings | implementation of hook_field Handle the parameters for a field. |
office_hours_menu | @file Creates a field and widget for inserting working or office hours per day |
office_hours_widget | Implementation of hook_widget(). |
office_hours_widget_info | Declare information about a widget. |
tf_to_mil | |
theme_oh_formatter_display | Theme function for date node display |
_create_hours_arr | helper function to create hours array. items are saved in 24 hours string format (i.e '18:00'). |