View source
<?php
namespace Drupal\smart_date;
use Drupal\Core\Field\FieldItemListInterface;
use Drupal\smart_date\Entity\SmartDateFormatInterface;
trait SmartDateTrait {
public function viewElements(FieldItemListInterface $items, $langcode) {
$elements = [];
$format_label = $this
->getSetting('format');
if ($format_label) {
$entity_storage_manager = \Drupal::entityTypeManager()
->getStorage('smart_date_format');
$format = $entity_storage_manager
->load($format_label);
$settings = $format
->getOptions();
}
else {
$settings = [
'separator' => $this
->getSetting('separator'),
'join' => $this
->getSetting('join'),
'time_format' => $this
->getSetting('time_format'),
'time_hour_format' => $this
->getSetting('time_hour_format'),
'date_format' => $this
->getSetting('date_format'),
'date_first' => $this
->getSetting('date_first'),
'ampm_reduce' => $this
->getSetting('ampm_reduce'),
'allday_label' => $this
->getSetting('allday_label'),
];
}
foreach ($items as $delta => $item) {
if (!empty($item->value) && !empty($item->end_value)) {
$elements[$delta] = static::formatSmartDate($item->value, $item->end_value, $settings);
if (!empty($item->_attributes)) {
$elements[$delta]['#attributes'] += $item->_attributes;
unset($item->_attributes);
}
}
}
return $elements;
}
public static function formatSmartDate($start_ts, $end_ts, $settings, $timezone = NULL, $return_type = '') {
$date_reduce = FALSE;
if ($settings['date_format']) {
$range['start']['date'] = \Drupal::service('date.formatter')
->format($start_ts, '', $settings['date_format'], $timezone);
$range['end']['date'] = \Drupal::service('date.formatter')
->format($end_ts, '', $settings['date_format'], $timezone);
if ($range['start']['date'] == $range['end']['date']) {
if ($settings['date_first']) {
unset($range['end']['date']);
}
else {
unset($range['start']['date']);
}
}
else {
$date_reduce = $settings['ampm_reduce'];
$settings['ampm_reduce'] = FALSE;
}
}
if (!$settings['time_format']) {
return static::rangeFormat($range, $settings, $return_type);
}
$temp_start = date('H:i', $start_ts);
$temp_end = date('H:i', $end_ts);
if (!isset($range['start']['date']) || !isset($range['end']['date'])) {
if ($temp_start == $temp_end) {
if ($settings['date_first']) {
$range['start']['time'] = static::timeFormat($end_ts, $settings, $timezone);
}
else {
$range['end']['time'] = static::timeFormat($end_ts, $settings, $timezone);
}
return static::rangeFormat($range, $settings, $return_type);
}
if (!$settings['ampm_reduce'] || date('a', $start_ts) != date('a', $end_ts)) {
$settings['ampm_reduce'] = FALSE;
}
}
if ($temp_start == '00:00' && $temp_end == '23:59') {
if ($settings['allday_label']) {
if ($settings['date_first'] && isset($range['end']['date']) || empty($range['start']['date'])) {
$range['end']['time'] = $settings['allday_label'];
}
else {
$range['start']['time'] = $settings['allday_label'];
}
}
if ($date_reduce) {
$start = getdate($start_ts);
$end = getdate($end_ts);
if ($start['year'] == $end['year']) {
$valid_days = [];
$invalid_days = [];
preg_match_all('/[dj]/', $settings['date_format'], $valid_days, PREG_OFFSET_CAPTURE);
preg_match_all('/[DNlwz]/', $settings['date_format'], $invalid_days, PREG_OFFSET_CAPTURE);
if ($start['month'] == $end['month'] && count($valid_days[0]) == 1 && count($invalid_days[0]) == 0) {
$day_loc = $valid_days[0][0][1];
if ($s_loc = strpos($settings['date_format'], 'S', $day_loc)) {
$offset = 1 + $s_loc - $day_loc;
}
else {
$offset = 1;
}
$start_format = substr($settings['date_format'], 0, $day_loc + $offset);
$end_format = substr($settings['date_format'], $day_loc);
$range['start']['date'] = \Drupal::service('date.formatter')
->format($start_ts, '', $start_format, $timezone);
$range['end']['date'] = \Drupal::service('date.formatter')
->format($end_ts, '', $end_format, $timezone);
}
else {
if (strpos($settings['date_format'], 'Y') === 0) {
$year_pos = 0;
}
elseif (strpos($settings['date_format'], 'Y') == strlen($settings['date_format']) - 1) {
$year_pos = -1;
}
else {
$year_pos = FALSE;
}
if ($year_pos !== FALSE) {
$valid_tokens = [];
preg_match_all('/[djDNlwzSFmMn]/', $settings['date_format'], $valid_tokens, PREG_OFFSET_CAPTURE);
if ($valid_tokens) {
if ($year_pos == 0) {
$first_token = $valid_tokens[0][0];
$end_format = substr($settings['date_format'], $first_token[1]);
$range['end']['date'] = \Drupal::service('date.formatter')
->format($end_ts, '', $end_format, $timezone);
}
else {
$last_token = array_pop($valid_tokens[0]);
$start_format = substr($settings['date_format'], 0, $last_token[1] + 1);
$range['start']['date'] = \Drupal::service('date.formatter')
->format($start_ts, '', $start_format, $timezone);
}
}
}
}
}
}
return static::rangeFormat($range, $settings, $return_type);
}
$range['start']['time'] = static::timeFormat($start_ts, $settings, $timezone, TRUE);
$range['end']['time'] = static::timeFormat($end_ts, $settings, $timezone);
return static::rangeFormat($range, $settings, $return_type);
}
private static function loadSmartDateFormat($formatName) {
$format = NULL;
$loadedFormat = \Drupal::getContainer()
->get('entity_type.manager')
->getStorage('smart_date_format')
->load($formatName);
if ($format instanceof SmartDateFormatInterface) {
$format = $loadedFormat;
}
return $format;
}
private static function rangeFormat($range, $settings, $return_type = '') {
if ($return_type == 'string') {
$pieces = [];
foreach ($range as $key => $parts) {
if ($parts) {
if (!$settings['date_first']) {
krsort($parts);
}
$pieces[] = implode($settings['join'], $parts);
}
}
return implode($settings['separator'], $pieces);
}
foreach ($range as $key => &$parts) {
if ($parts && is_array($parts) && count($parts) > 1) {
$parts['join'] = $settings['join'];
if ($settings['date_first']) {
ksort($parts);
}
else {
krsort($parts);
}
}
elseif (!$parts) {
unset($range[$key]);
}
}
if (count($range) > 1) {
$range['separator'] = $settings['separator'];
krsort($range);
}
$output = static::array_to_render($range);
$output['#attributes']['class'] = [
'smart_date_range',
];
return $output;
}
private static function array_to_render($array) {
if (!is_array($array)) {
return false;
}
$output = [];
foreach ($array as $key => $child) {
$child == array_pop($array);
if (is_array($child)) {
$output[$key] = static::array_to_render($child);
}
else {
$output[$key] = [
'#markup' => $child,
];
}
}
return $output;
}
private static function timeFormat($time, $settings, $timezone = NULL, $is_start = FALSE) {
$format = $settings['time_format'];
if (!empty($settings['time_hour_format']) && date('i', $time) == '00') {
$format = $settings['time_hour_format'];
}
if ($is_start) {
if ($settings['ampm_reduce']) {
$format = preg_replace('/\\s*(?<![\\\\])a/i', '', $format);
}
$format = preg_replace('/\\s*(?<![\\\\])[eOPTZ]/i', '', $format);
}
return \Drupal::service('date.formatter')
->format($time, '', $format, $timezone);
}
}