Add the Chronological
This commit is contained in:
143
src/ChronologicalCalendarWidget.php
Normal file
143
src/ChronologicalCalendarWidget.php
Normal file
@@ -0,0 +1,143 @@
|
||||
<?php
|
||||
|
||||
namespace dokuwiki\plugin\luxtools;
|
||||
|
||||
/**
|
||||
* Render the chronological calendar widget markup.
|
||||
*/
|
||||
class ChronologicalCalendarWidget
|
||||
{
|
||||
/**
|
||||
* Render full calendar widget HTML for one month.
|
||||
*
|
||||
* @param int $year
|
||||
* @param int $month
|
||||
* @param string $baseNs
|
||||
* @return string
|
||||
*/
|
||||
public static function render(int $year, int $month, string $baseNs = 'chronological'): string
|
||||
{
|
||||
if (!self::isValidMonth($year, $month)) return '';
|
||||
|
||||
$firstDayTs = mktime(0, 0, 0, $month, 1, $year);
|
||||
$daysInMonth = (int)date('t', $firstDayTs);
|
||||
$firstWeekday = (int)date('N', $firstDayTs); // 1..7 (Mon..Sun)
|
||||
|
||||
$monthCursor = \DateTimeImmutable::createFromFormat('!Y-n-j', sprintf('%04d-%d-1', $year, $month));
|
||||
if (!($monthCursor instanceof \DateTimeImmutable)) return '';
|
||||
|
||||
$prevMonth = $monthCursor->sub(new \DateInterval('P1M'));
|
||||
$nextMonth = $monthCursor->add(new \DateInterval('P1M'));
|
||||
|
||||
$monthStartDate = sprintf('%04d-%02d-01', $year, $month);
|
||||
$monthDayId = ChronoID::dateToDayId($monthStartDate, $baseNs);
|
||||
$monthId = $monthDayId !== null ? ChronoID::dayIdToMonthId($monthDayId, $baseNs) : null;
|
||||
$yearId = $monthId !== null ? ChronoID::monthIdToYearId($monthId, $baseNs) : null;
|
||||
|
||||
$prevStartDate = $prevMonth->format('Y-m-d');
|
||||
$prevDayId = ChronoID::dateToDayId($prevStartDate, $baseNs);
|
||||
$prevMonthId = $prevDayId !== null ? ChronoID::dayIdToMonthId($prevDayId, $baseNs) : null;
|
||||
|
||||
$nextStartDate = $nextMonth->format('Y-m-d');
|
||||
$nextDayId = ChronoID::dateToDayId($nextStartDate, $baseNs);
|
||||
$nextMonthId = $nextDayId !== null ? ChronoID::dayIdToMonthId($nextDayId, $baseNs) : null;
|
||||
|
||||
$leadingEmpty = $firstWeekday - 1;
|
||||
$totalCells = (int)ceil(($leadingEmpty + $daysInMonth) / 7) * 7;
|
||||
|
||||
$todayY = (int)date('Y');
|
||||
$todayM = (int)date('m');
|
||||
$todayD = (int)date('d');
|
||||
|
||||
$dayUrlTemplate = function_exists('wl') ? (string)wl('__LUXTOOLS_ID_RAW__') : '';
|
||||
$monthUrlTemplate = $dayUrlTemplate;
|
||||
$yearUrlTemplate = $dayUrlTemplate;
|
||||
$ajaxUrl = defined('DOKU_BASE') ? (string)DOKU_BASE . 'lib/exe/ajax.php' : 'lib/exe/ajax.php';
|
||||
|
||||
$html = '<div class="luxtools-plugin luxtools-calendar" data-luxtools-calendar="1"'
|
||||
. ' data-base-ns="' . hsc($baseNs) . '"'
|
||||
. ' data-current-year="' . hsc((string)$year) . '"'
|
||||
. ' data-current-month="' . hsc(sprintf('%02d', $month)) . '"'
|
||||
. ' data-day-url-template="' . hsc($dayUrlTemplate) . '"'
|
||||
. ' data-month-url-template="' . hsc($monthUrlTemplate) . '"'
|
||||
. ' data-year-url-template="' . hsc($yearUrlTemplate) . '"'
|
||||
. ' data-luxtools-ajax-url="' . hsc($ajaxUrl) . '"'
|
||||
. ' data-prev-month-id="' . hsc((string)$prevMonthId) . '"'
|
||||
. ' data-next-month-id="' . hsc((string)$nextMonthId) . '"'
|
||||
. '>';
|
||||
|
||||
$html .= '<div class="luxtools-calendar-nav">';
|
||||
$html .= '<div class="luxtools-calendar-nav-prev">';
|
||||
$html .= '<button type="button" class="luxtools-calendar-nav-button" data-luxtools-dir="-1" aria-label="Previous month">◀</button>';
|
||||
$html .= '</div>';
|
||||
|
||||
$html .= '<div class="luxtools-calendar-title">';
|
||||
$monthLabel = date('F', $firstDayTs);
|
||||
if ($monthId !== null && function_exists('wl')) {
|
||||
$html .= '<a class="luxtools-calendar-month-link" href="' . hsc((string)wl($monthId)) . '">' . hsc($monthLabel) . '</a>';
|
||||
} else {
|
||||
$html .= hsc($monthLabel);
|
||||
}
|
||||
$html .= ' ';
|
||||
if ($yearId !== null && function_exists('wl')) {
|
||||
$html .= '<a class="luxtools-calendar-year-link" href="' . hsc((string)wl($yearId)) . '">' . hsc((string)$year) . '</a>';
|
||||
} else {
|
||||
$html .= hsc((string)$year);
|
||||
}
|
||||
$html .= '</div>';
|
||||
|
||||
$html .= '<div class="luxtools-calendar-nav-next">';
|
||||
$html .= '<button type="button" class="luxtools-calendar-nav-button" data-luxtools-dir="1" aria-label="Next month">▶</button>';
|
||||
$html .= '</div>';
|
||||
$html .= '</div>';
|
||||
|
||||
$html .= '<table class="luxtools-calendar-table">';
|
||||
$html .= '<thead><tr>';
|
||||
foreach (['Mo', 'Di', 'Mi', 'Do', 'Fr', 'Sa', 'So'] as $weekday) {
|
||||
$html .= '<th scope="col">' . hsc($weekday) . '</th>';
|
||||
}
|
||||
$html .= '</tr></thead><tbody>';
|
||||
|
||||
for ($cell = 0; $cell < $totalCells; $cell++) {
|
||||
if ($cell % 7 === 0) $html .= '<tr>';
|
||||
|
||||
$dayNumber = $cell - $leadingEmpty + 1;
|
||||
if ($dayNumber < 1 || $dayNumber > $daysInMonth) {
|
||||
$html .= '<td class="luxtools-calendar-day luxtools-calendar-day-empty"></td>';
|
||||
} else {
|
||||
$date = sprintf('%04d-%02d-%02d', $year, $month, $dayNumber);
|
||||
$dayId = ChronoID::dateToDayId($date, $baseNs);
|
||||
|
||||
$classes = 'luxtools-calendar-day';
|
||||
if ($year === $todayY && $month === $todayM && $dayNumber === $todayD) {
|
||||
$classes .= ' luxtools-calendar-day-today';
|
||||
}
|
||||
|
||||
$html .= '<td class="' . hsc($classes) . '">';
|
||||
if ($dayId !== null && function_exists('html_wikilink')) {
|
||||
$html .= (string)html_wikilink($dayId, (string)$dayNumber);
|
||||
} else {
|
||||
$html .= hsc((string)$dayNumber);
|
||||
}
|
||||
$html .= '</td>';
|
||||
}
|
||||
|
||||
if ($cell % 7 === 6) $html .= '</tr>';
|
||||
}
|
||||
|
||||
$html .= '</tbody></table></div>';
|
||||
return $html;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $year
|
||||
* @param int $month
|
||||
* @return bool
|
||||
*/
|
||||
public static function isValidMonth(int $year, int $month): bool
|
||||
{
|
||||
if ($year < 1) return false;
|
||||
if ($month < 1 || $month > 12) return false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user