function office_hours_field_formatter_view in Office Hours 7
Implements hook_field_formatter_view().
Be careful: date_api uses PHP: 0=Sunday, and DateObject uses ISO: 1=Sunday.
File
- includes/
office_hours.formatter.inc, line 240 - Implements the office_hours formatter.
Code
function office_hours_field_formatter_view($entity_type, $entity, $field, $instance, $langcode, $items, $display) {
$element = array();
if (!$items) {
return $element;
}
// Allow other modules to alter the items before the calculations are done.
// @see office_hours.api.php for an example.
$context = array(
'entity_type' => $entity_type,
'entity' => $entity,
'field' => $field,
'instance' => $instance,
'langcode' => $langcode,
'display' => $display,
);
drupal_alter('office_hours_field_formatter_view', $items, $context);
// Initialize formatter settings.
$settings = _office_hours_field_formatter_defaults($display['settings']);
// Initialize daynames, using date_api as key: 0=Sun - 6=Sat.
switch ($settings['daysformat']) {
case 'number':
// ISO-8601 numerical representation.
$daynames = range(1, 7);
break;
case 'none':
$daynames = array_fill(0, 7, '');
break;
case 'long':
$daynames = date_week_days(TRUE);
break;
case 'short':
default:
$daynames = date_week_days_abbr(TRUE, TRUE, 3);
break;
}
// Initialize days and times, using date_api as key (0=Sun, 6-Sat)
// Empty days are not yet present in $items, and are now added in $days.
$days = array();
for ($day = 0; $day < 7; $day++) {
$days[$day] = array(
'startday' => $day,
'endday' => NULL,
'times' => NULL,
'current' => FALSE,
'next' => FALSE,
);
}
// @TODO: support timezones.
$timezone = NULL;
// Avoid repetitive calculations, use static.
// See http://drupal.org/node/1969956.
// And even better, avoid the expensive DateObject.
$today = (int) idate('w', $_SERVER['REQUEST_TIME']);
// Get daynumber sun=0 - sat=6.
$now = date('Gi', $_SERVER['REQUEST_TIME']);
// 'Gi' format.
$next = NULL;
// Loop through all lines. Detect the current line and the open/closed status.
// Convert the daynumber to (int) to get '0' for Sundays, not 'false'.
foreach (element_children($items) as $key => $arraykey) {
$el = $items[$arraykey];
// Calculate start and end times.
$day = $el['day'];
$start = _office_hours_time_to_mil($el['starthours']);
// 'Gi' format.
$end = _office_hours_time_to_mil($el['endhours']);
// 'Gi' format.
$comment = $el['comment'];
$times = array(
'start' => $start,
'end' => $end,
'comment' => $comment,
);
$days[$day]['times'][] = $times;
// Are we currently open? If not, when is the next time?
// Remember: empty days are not in $items; they are present in $days.
// Note: the 'open' determination is moved to file office_hours.formatter.inc.
if ($day < $today) {
// Initialize to first day of (next) week, in case we're closed
// the rest of the week.
if ($next === NULL) {
$next = (int) $day;
}
}
if ($day - $today == -1 || $day - $today == 6) {
// We were open yesterday evening, check if we are still open.
if ($start >= $end && $end >= $now) {
$days[$day]['current'] = TRUE;
$next = (int) $day;
}
}
elseif ($day == $today) {
if ($start <= $now) {
// We were open today, check if we are still open.
if ($start > $end || $start == $end || $start < $end && $end > $now) {
// We have closed already.
$days[$day]['current'] = TRUE;
$next = (int) $day;
}
else {
// We have already closed.
}
}
else {
// We will open later today.
$next = (int) $day;
}
}
elseif ($day > $today) {
if ($next === NULL || $next < $today) {
$next = (int) $day;
}
}
}
if ($next !== NULL) {
$days[(int) $next]['next'] = TRUE;
}
// We have to separate display from JS 'Open' calculation here.
// So we copy the days array before it get modified for display:
// See https://www.drupal.org/project/office_hours/issues/2919519
$days2calc = $days;
// Reorder weekdays to match the first day of the week, using formatter settings;
// $days = date_week_days_ordered($days); //using variable_get('date_first_day');
if ($settings['date_first_day'] > 0) {
for ($i = 1; $i <= $settings['date_first_day']; $i++) {
$last = array_shift($days);
array_push($days, $last);
}
}
// Check if we're compressing times. If so, combine lines of the same day into one.
if ($settings['compress']) {
foreach ($days as $day => &$info) {
if (is_array($info['times'])) {
// Initialize first block of the day.
$day_times = $info['times'][0];
// Compress other block in first block.
foreach ($info['times'] as $index => $block_times) {
$day_times['start'] = min($day_times['start'], $block_times['start']);
$day_times['end'] = max($day_times['end'], $block_times['end']);
}
$info['times'] = array(
0 => $day_times,
);
}
}
}
// Check if we're grouping days.
if ($settings['grouped']) {
for ($i = 0; $i < 7; $i++) {
if ($i == 0) {
$times = $days[$i]['times'];
}
elseif ($times != $days[$i]['times']) {
$times = $days[$i]['times'];
}
else {
// N.B. for 0=Sundays, we need to (int) the indices.
$days[$i]['endday'] = $days[(int) $i]['startday'];
$days[$i]['startday'] = $days[(int) $i - 1]['startday'];
$days[$i]['current'] = $days[(int) $i]['current'] || $days[(int) $i - 1]['current'];
$days[$i]['next'] = $days[(int) $i]['next'] || $days[(int) $i - 1]['next'];
unset($days[(int) $i - 1]);
}
}
}
// Theme the result.
$element[] = array(
'#markup' => theme('office_hours_field_formatter_default', array(
'element' => $items,
'display' => $display,
'days' => $days,
'days2calc' => $days2calc,
'settings' => $settings,
'daynames' => $daynames,
'timezone' => $timezone,
'context' => array(
'entity_type' => $entity_type,
'entity' => $entity,
'field' => $field,
'instance' => $instance,
'langcode' => $langcode,
'items' => $items,
'display' => $display,
),
)),
'#attached' => array(
'js' => array(
drupal_get_path('module', 'office_hours') . '/js/office_hours.formatter.js',
),
),
);
return $element;
}