1*19378907SAtari911<?php 2*19378907SAtari911/** 3*19378907SAtari911 * DokuWiki Plugin calendar (Action Component) 4*19378907SAtari911 * 5*19378907SAtari911 * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html 6*19378907SAtari911 * @author DokuWiki Community 7*19378907SAtari911 */ 8*19378907SAtari911 9*19378907SAtari911if (!defined('DOKU_INC')) die(); 10*19378907SAtari911 11*19378907SAtari911class action_plugin_calendar extends DokuWiki_Action_Plugin { 12*19378907SAtari911 13*19378907SAtari911 public function register(Doku_Event_Handler $controller) { 14*19378907SAtari911 $controller->register_hook('AJAX_CALL_UNKNOWN', 'BEFORE', $this, 'handleAjax'); 15*19378907SAtari911 $controller->register_hook('TPL_METAHEADER_OUTPUT', 'BEFORE', $this, 'addAssets'); 16*19378907SAtari911 } 17*19378907SAtari911 18*19378907SAtari911 public function handleAjax(Doku_Event $event, $param) { 19*19378907SAtari911 if ($event->data !== 'plugin_calendar') return; 20*19378907SAtari911 $event->preventDefault(); 21*19378907SAtari911 $event->stopPropagation(); 22*19378907SAtari911 23*19378907SAtari911 $action = $_REQUEST['action'] ?? ''; 24*19378907SAtari911 25*19378907SAtari911 switch ($action) { 26*19378907SAtari911 case 'save_event': 27*19378907SAtari911 $this->saveEvent(); 28*19378907SAtari911 break; 29*19378907SAtari911 case 'delete_event': 30*19378907SAtari911 $this->deleteEvent(); 31*19378907SAtari911 break; 32*19378907SAtari911 case 'get_event': 33*19378907SAtari911 $this->getEvent(); 34*19378907SAtari911 break; 35*19378907SAtari911 case 'load_month': 36*19378907SAtari911 $this->loadMonth(); 37*19378907SAtari911 break; 38*19378907SAtari911 case 'toggle_task': 39*19378907SAtari911 $this->toggleTaskComplete(); 40*19378907SAtari911 break; 41*19378907SAtari911 default: 42*19378907SAtari911 echo json_encode(['success' => false, 'error' => 'Unknown action']); 43*19378907SAtari911 } 44*19378907SAtari911 } 45*19378907SAtari911 46*19378907SAtari911 private function saveEvent() { 47*19378907SAtari911 global $INPUT; 48*19378907SAtari911 49*19378907SAtari911 $namespace = $INPUT->str('namespace', ''); 50*19378907SAtari911 $date = $INPUT->str('date'); 51*19378907SAtari911 $eventId = $INPUT->str('eventId', ''); 52*19378907SAtari911 $title = $INPUT->str('title'); 53*19378907SAtari911 $time = $INPUT->str('time', ''); 54*19378907SAtari911 $description = $INPUT->str('description', ''); 55*19378907SAtari911 $color = $INPUT->str('color', '#3498db'); 56*19378907SAtari911 $oldDate = $INPUT->str('oldDate', ''); // Track original date for moves 57*19378907SAtari911 $isTask = $INPUT->bool('isTask', false); 58*19378907SAtari911 $completed = $INPUT->bool('completed', false); 59*19378907SAtari911 $endDate = $INPUT->str('endDate', ''); 60*19378907SAtari911 61*19378907SAtari911 if (!$date || !$title) { 62*19378907SAtari911 echo json_encode(['success' => false, 'error' => 'Missing required fields']); 63*19378907SAtari911 return; 64*19378907SAtari911 } 65*19378907SAtari911 66*19378907SAtari911 list($year, $month, $day) = explode('-', $date); 67*19378907SAtari911 68*19378907SAtari911 $dataDir = DOKU_INC . 'data/meta/'; 69*19378907SAtari911 if ($namespace) { 70*19378907SAtari911 $dataDir .= str_replace(':', '/', $namespace) . '/'; 71*19378907SAtari911 } 72*19378907SAtari911 $dataDir .= 'calendar/'; 73*19378907SAtari911 74*19378907SAtari911 if (!is_dir($dataDir)) { 75*19378907SAtari911 mkdir($dataDir, 0755, true); 76*19378907SAtari911 } 77*19378907SAtari911 78*19378907SAtari911 $eventFile = $dataDir . sprintf('%04d-%02d.json', $year, $month); 79*19378907SAtari911 80*19378907SAtari911 $events = []; 81*19378907SAtari911 if (file_exists($eventFile)) { 82*19378907SAtari911 $events = json_decode(file_get_contents($eventFile), true); 83*19378907SAtari911 } 84*19378907SAtari911 85*19378907SAtari911 // If editing and date changed, remove from old date first 86*19378907SAtari911 if ($eventId && $oldDate && $oldDate !== $date) { 87*19378907SAtari911 list($oldYear, $oldMonth, $oldDay) = explode('-', $oldDate); 88*19378907SAtari911 $oldEventFile = $dataDir . sprintf('%04d-%02d.json', $oldYear, $oldMonth); 89*19378907SAtari911 90*19378907SAtari911 if (file_exists($oldEventFile)) { 91*19378907SAtari911 $oldEvents = json_decode(file_get_contents($oldEventFile), true); 92*19378907SAtari911 if (isset($oldEvents[$oldDate])) { 93*19378907SAtari911 $oldEvents[$oldDate] = array_filter($oldEvents[$oldDate], function($evt) use ($eventId) { 94*19378907SAtari911 return $evt['id'] !== $eventId; 95*19378907SAtari911 }); 96*19378907SAtari911 97*19378907SAtari911 if (empty($oldEvents[$oldDate])) { 98*19378907SAtari911 unset($oldEvents[$oldDate]); 99*19378907SAtari911 } 100*19378907SAtari911 101*19378907SAtari911 file_put_contents($oldEventFile, json_encode($oldEvents, JSON_PRETTY_PRINT)); 102*19378907SAtari911 } 103*19378907SAtari911 } 104*19378907SAtari911 } 105*19378907SAtari911 106*19378907SAtari911 if (!isset($events[$date])) { 107*19378907SAtari911 $events[$date] = []; 108*19378907SAtari911 } 109*19378907SAtari911 110*19378907SAtari911 $eventData = [ 111*19378907SAtari911 'id' => $eventId ?: uniqid(), 112*19378907SAtari911 'title' => $title, 113*19378907SAtari911 'time' => $time, 114*19378907SAtari911 'description' => $description, 115*19378907SAtari911 'color' => $color, 116*19378907SAtari911 'isTask' => $isTask, 117*19378907SAtari911 'completed' => $completed, 118*19378907SAtari911 'endDate' => $endDate, 119*19378907SAtari911 'created' => date('Y-m-d H:i:s') 120*19378907SAtari911 ]; 121*19378907SAtari911 122*19378907SAtari911 // If editing, replace existing event 123*19378907SAtari911 if ($eventId) { 124*19378907SAtari911 $found = false; 125*19378907SAtari911 foreach ($events[$date] as $key => $evt) { 126*19378907SAtari911 if ($evt['id'] === $eventId) { 127*19378907SAtari911 $events[$date][$key] = $eventData; 128*19378907SAtari911 $found = true; 129*19378907SAtari911 break; 130*19378907SAtari911 } 131*19378907SAtari911 } 132*19378907SAtari911 if (!$found) { 133*19378907SAtari911 $events[$date][] = $eventData; 134*19378907SAtari911 } 135*19378907SAtari911 } else { 136*19378907SAtari911 $events[$date][] = $eventData; 137*19378907SAtari911 } 138*19378907SAtari911 139*19378907SAtari911 file_put_contents($eventFile, json_encode($events, JSON_PRETTY_PRINT)); 140*19378907SAtari911 141*19378907SAtari911 echo json_encode(['success' => true, 'events' => $events, 'eventId' => $eventData['id']]); 142*19378907SAtari911 } 143*19378907SAtari911 144*19378907SAtari911 private function deleteEvent() { 145*19378907SAtari911 global $INPUT; 146*19378907SAtari911 147*19378907SAtari911 $namespace = $INPUT->str('namespace', ''); 148*19378907SAtari911 $date = $INPUT->str('date'); 149*19378907SAtari911 $eventId = $INPUT->str('eventId'); 150*19378907SAtari911 151*19378907SAtari911 list($year, $month, $day) = explode('-', $date); 152*19378907SAtari911 153*19378907SAtari911 $dataDir = DOKU_INC . 'data/meta/'; 154*19378907SAtari911 if ($namespace) { 155*19378907SAtari911 $dataDir .= str_replace(':', '/', $namespace) . '/'; 156*19378907SAtari911 } 157*19378907SAtari911 $dataDir .= 'calendar/'; 158*19378907SAtari911 159*19378907SAtari911 $eventFile = $dataDir . sprintf('%04d-%02d.json', $year, $month); 160*19378907SAtari911 161*19378907SAtari911 if (file_exists($eventFile)) { 162*19378907SAtari911 $events = json_decode(file_get_contents($eventFile), true); 163*19378907SAtari911 164*19378907SAtari911 if (isset($events[$date])) { 165*19378907SAtari911 $events[$date] = array_filter($events[$date], function($event) use ($eventId) { 166*19378907SAtari911 return $event['id'] !== $eventId; 167*19378907SAtari911 }); 168*19378907SAtari911 169*19378907SAtari911 if (empty($events[$date])) { 170*19378907SAtari911 unset($events[$date]); 171*19378907SAtari911 } 172*19378907SAtari911 173*19378907SAtari911 file_put_contents($eventFile, json_encode($events, JSON_PRETTY_PRINT)); 174*19378907SAtari911 } 175*19378907SAtari911 } 176*19378907SAtari911 177*19378907SAtari911 echo json_encode(['success' => true]); 178*19378907SAtari911 } 179*19378907SAtari911 180*19378907SAtari911 private function getEvent() { 181*19378907SAtari911 global $INPUT; 182*19378907SAtari911 183*19378907SAtari911 $namespace = $INPUT->str('namespace', ''); 184*19378907SAtari911 $date = $INPUT->str('date'); 185*19378907SAtari911 $eventId = $INPUT->str('eventId'); 186*19378907SAtari911 187*19378907SAtari911 list($year, $month, $day) = explode('-', $date); 188*19378907SAtari911 189*19378907SAtari911 $dataDir = DOKU_INC . 'data/meta/'; 190*19378907SAtari911 if ($namespace) { 191*19378907SAtari911 $dataDir .= str_replace(':', '/', $namespace) . '/'; 192*19378907SAtari911 } 193*19378907SAtari911 $dataDir .= 'calendar/'; 194*19378907SAtari911 195*19378907SAtari911 $eventFile = $dataDir . sprintf('%04d-%02d.json', $year, $month); 196*19378907SAtari911 197*19378907SAtari911 if (file_exists($eventFile)) { 198*19378907SAtari911 $events = json_decode(file_get_contents($eventFile), true); 199*19378907SAtari911 200*19378907SAtari911 if (isset($events[$date])) { 201*19378907SAtari911 foreach ($events[$date] as $event) { 202*19378907SAtari911 if ($event['id'] === $eventId) { 203*19378907SAtari911 echo json_encode(['success' => true, 'event' => $event]); 204*19378907SAtari911 return; 205*19378907SAtari911 } 206*19378907SAtari911 } 207*19378907SAtari911 } 208*19378907SAtari911 } 209*19378907SAtari911 210*19378907SAtari911 echo json_encode(['success' => false, 'error' => 'Event not found']); 211*19378907SAtari911 } 212*19378907SAtari911 213*19378907SAtari911 private function loadMonth() { 214*19378907SAtari911 global $INPUT; 215*19378907SAtari911 216*19378907SAtari911 $namespace = $INPUT->str('namespace', ''); 217*19378907SAtari911 $year = $INPUT->int('year'); 218*19378907SAtari911 $month = $INPUT->int('month'); 219*19378907SAtari911 220*19378907SAtari911 $dataDir = DOKU_INC . 'data/meta/'; 221*19378907SAtari911 if ($namespace) { 222*19378907SAtari911 $dataDir .= str_replace(':', '/', $namespace) . '/'; 223*19378907SAtari911 } 224*19378907SAtari911 $dataDir .= 'calendar/'; 225*19378907SAtari911 226*19378907SAtari911 $eventFile = $dataDir . sprintf('%04d-%02d.json', $year, $month); 227*19378907SAtari911 228*19378907SAtari911 $events = []; 229*19378907SAtari911 if (file_exists($eventFile)) { 230*19378907SAtari911 $events = json_decode(file_get_contents($eventFile), true); 231*19378907SAtari911 } 232*19378907SAtari911 233*19378907SAtari911 echo json_encode(['success' => true, 'events' => $events, 'year' => $year, 'month' => $month]); 234*19378907SAtari911 } 235*19378907SAtari911 236*19378907SAtari911 private function toggleTaskComplete() { 237*19378907SAtari911 global $INPUT; 238*19378907SAtari911 239*19378907SAtari911 $namespace = $INPUT->str('namespace', ''); 240*19378907SAtari911 $date = $INPUT->str('date'); 241*19378907SAtari911 $eventId = $INPUT->str('eventId'); 242*19378907SAtari911 $completed = $INPUT->bool('completed', false); 243*19378907SAtari911 244*19378907SAtari911 list($year, $month, $day) = explode('-', $date); 245*19378907SAtari911 246*19378907SAtari911 $dataDir = DOKU_INC . 'data/meta/'; 247*19378907SAtari911 if ($namespace) { 248*19378907SAtari911 $dataDir .= str_replace(':', '/', $namespace) . '/'; 249*19378907SAtari911 } 250*19378907SAtari911 $dataDir .= 'calendar/'; 251*19378907SAtari911 252*19378907SAtari911 $eventFile = $dataDir . sprintf('%04d-%02d.json', $year, $month); 253*19378907SAtari911 254*19378907SAtari911 if (file_exists($eventFile)) { 255*19378907SAtari911 $events = json_decode(file_get_contents($eventFile), true); 256*19378907SAtari911 257*19378907SAtari911 if (isset($events[$date])) { 258*19378907SAtari911 foreach ($events[$date] as $key => $event) { 259*19378907SAtari911 if ($event['id'] === $eventId) { 260*19378907SAtari911 $events[$date][$key]['completed'] = $completed; 261*19378907SAtari911 break; 262*19378907SAtari911 } 263*19378907SAtari911 } 264*19378907SAtari911 265*19378907SAtari911 file_put_contents($eventFile, json_encode($events, JSON_PRETTY_PRINT)); 266*19378907SAtari911 echo json_encode(['success' => true, 'events' => $events]); 267*19378907SAtari911 return; 268*19378907SAtari911 } 269*19378907SAtari911 } 270*19378907SAtari911 271*19378907SAtari911 echo json_encode(['success' => false, 'error' => 'Event not found']); 272*19378907SAtari911 } 273*19378907SAtari911 274*19378907SAtari911 public function addAssets(Doku_Event $event, $param) { 275*19378907SAtari911 $event->data['link'][] = array( 276*19378907SAtari911 'type' => 'text/css', 277*19378907SAtari911 'rel' => 'stylesheet', 278*19378907SAtari911 'href' => DOKU_BASE . 'lib/plugins/calendar/style.css' 279*19378907SAtari911 ); 280*19378907SAtari911 281*19378907SAtari911 $event->data['script'][] = array( 282*19378907SAtari911 'type' => 'text/javascript', 283*19378907SAtari911 'src' => DOKU_BASE . 'lib/plugins/calendar/script.js' 284*19378907SAtari911 ); 285*19378907SAtari911 } 286*19378907SAtari911} 287