}} current month * - {{calendar>YYYY-MM}} specific month * - {{calendar>YYYY-MM&base=chronological}} custom base namespace (optional) */ class syntax_plugin_luxtools_calendar extends SyntaxPlugin { /** @inheritdoc */ public function getType() { return 'substition'; } /** @inheritdoc */ public function getPType() { return 'block'; } /** @inheritdoc */ public function getSort() { return 224; } /** @inheritdoc */ public function connectTo($mode) { $this->Lexer->addSpecialPattern('\{\{calendar>.*?\}\}', $mode, 'plugin_luxtools_calendar'); } /** @inheritdoc */ public function handle($match, $state, $pos, Doku_Handler $handler) { $match = substr($match, strlen('{{calendar>'), -2); [$target, $flags] = array_pad(explode('&', $match, 2), 2, ''); $target = trim((string)$target); $params = $this->parseFlags($flags); $baseNs = $params['base'] ?? 'chronological'; $resolved = $this->resolveTargetMonth($target); if ($resolved === null) { return [ 'ok' => false, 'error' => 'calendar_err_badmonth', ]; } return [ 'ok' => true, 'year' => $resolved['year'], 'month' => $resolved['month'], 'base' => $baseNs, ]; } /** @inheritdoc */ public function render($format, Doku_Renderer $renderer, $data) { if ($data === false || !is_array($data)) return false; if ($format !== 'xhtml') return false; if (!($renderer instanceof Doku_Renderer_xhtml)) return false; if (!($data['ok'] ?? false)) { $message = (string)$this->getLang((string)($data['error'] ?? 'calendar_err_badmonth')); if ($message === '') $message = 'Invalid calendar month. Use YYYY-MM.'; $renderer->doc .= '
' . hsc($message) . '
'; return true; } $year = (int)$data['year']; $month = (int)$data['month']; $baseNs = (string)$data['base']; $renderer->doc .= ChronologicalCalendarWidget::render($year, $month, $baseNs); return true; } /** * @param string $flags * @return array */ protected function parseFlags(string $flags): array { $params = []; foreach (explode('&', $flags) as $flag) { if (trim($flag) === '') continue; [$name, $value] = array_pad(explode('=', $flag, 2), 2, ''); $name = strtolower(trim($name)); $value = trim($value); if ($name === '') continue; $params[$name] = $value; } if (!isset($params['base']) || trim($params['base']) === '') { $params['base'] = 'chronological'; } return $params; } /** * Resolve target string to year/month. * * Accepted formats: * - '' (current month) * - YYYY-MM * * @param string $target * @return array{year:int,month:int}|null */ protected function resolveTargetMonth(string $target): ?array { if ($target === '') { return [ 'year' => (int)date('Y'), 'month' => (int)date('m'), ]; } if (!preg_match('/^(\d{4})-(\d{2})$/', $target, $matches)) { return null; } $year = (int)$matches[1]; $month = (int)$matches[2]; if ($year < 1) return null; if ($month < 1 || $month > 12) return null; return [ 'year' => $year, 'month' => $month, ]; } }