Files
thetool/application/Calendar/CalendarController.php
Daniel Spitzer cb67e821ec Kalender Update
* Feature Implementation Excel Export
2025-03-03 09:21:24 +01:00

704 lines
28 KiB
PHP

<?php
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
use PhpOffice\PhpSpreadsheet\Style\Alignment;
use PhpOffice\PhpSpreadsheet\Style\Border;
use PhpOffice\PhpSpreadsheet\Style\Color;
use PhpOffice\PhpSpreadsheet\Helper\Html;
class CalendarController extends mfBaseController
{
protected function init()
{
$this->needlogin = true;
$me = new User();
$me->loadMe();
$this->me = $me;
$this->layout()->set("me", $me);
if (!$me->is(["Admin"])) {
$this->redirect("Dashboard");
}
}
protected function detailAction()
{
$this->layout()->setTemplate("Calendar/Detail");
}
protected function apiAction()
{
if (!$this->me->is(["Admin"])) {
$return = false;
}
$do = $this->request->do;
switch ($do) {
case "getCalendarEvents":
$r = $this->request;
$calendarEvents = CalendarModel::getCalendarEvents($this->me->id, 0, $r);
return $calendarEvents;
die();
case "getCalendarEvent":
$r = $this->request;
$id = ($r->id);
$calendarEvents = CalendarModel::getCalendarEvent($id);
return $calendarEvents;
die();
case "searchCalendarEvents" :
$r = $this->request;
$calendarEvents = CalendarModel::searchCalendarEvents($r);
return $calendarEvents;
die();
case "generateCalendarEventsXlsx" :
$r = $this->request;
$this->generateXlsx($r);
return $calendarEvents;
die();
case "getCalendarEventAttachment" :
$r = $this->request;
$id = ($r->id);
$this->getCalendarAttachment($id);
die();
case "getCalendarEventAttachmentTmp" :
$r = $this->request;
$id = ($r->id);
$name = ($r->name);
$this->getCalendarAttachmentTmp($id, $name);
die();
case "updateCalendarEvent":
$r = $this->request;
$calendarEvents = CalendarModel::updateCalendarEvent($r, $this->me);
if ($r->customer_info_check) {
if ($r->customer_info_type == 1) {
$body = $r->customer_info_text;
$email = new Emailnotification();
$email->setSubject('Inbetriebnahme');
$email->setBody($body);
$email->setFrom('termin@xinon.at', 'Terminbestätigung');
$email->setTo($r->customer_info_type_text);
$email->send();
} else if ($r->customer_info_type == 2) {
$sms = new SmsNotification();
$customerText = trim($r->customer_info_text);
$body = "Xinon Terminbestätigung:" . PHP_EOL . $customerText;
$sms->setBody($body);
$customerNumber = trim($r->customer_info_type_text);
$customerNumber = str_replace(" ", "", $customerNumber);
$customerNumber = str_replace("(", "", $customerNumber);
$customerNumber = str_replace(")", "", $customerNumber);
$customerNumber = str_replace("-", "", $customerNumber);
$customerNumber = str_replace("/", "", $customerNumber);
$customerNumber = str_replace(".", "", $customerNumber);
$customerNumber = str_replace(",", "", $customerNumber);
$customerNumber = str_replace(";", "", $customerNumber);
$customerNumber = str_replace(":", "", $customerNumber);
if (preg_match('/^0/', $customerNumber)) {
$customerNumber = "+43" . substr($customerNumber, 1);
}
$sms->setRecipient($customerNumber);
if (!empty($customerNumber) && !empty($customerText)) {
$sms->send();
}
}
}
die();
case "updateCalendarEventState" :
$r = $this->request;
$calendarEvents = CalendarModel::updateCalendarEventState($r, $this->me);
die();
case "getAddress":
$r = $this->request;
$this->getAddress($r);
die();
case "getTicket";
$r = $this->request;
$this->getTicket($r);
die();
case "insertCalendarEvent":
$r = $this->request;
if ($r->rruleData) {
$rrules = json_encode($this->generateGraphRecurrence($r->rruleData, $r->start));
}
$calendarEvents = CalendarModel::insertCalendarEvent($r, $this->me, $rrules);
if ($r->customer_info_check) {
if ($r->customer_info_type == 1) {
$body = $r->customer_info_text;
$email = new Emailnotification();
$email->setSubject('Technikertermin Xinon');
$email->setBody($body);
$email->setFrom('termin@xinon.at', 'Terminbestätigung');
$email->setTo($r->customer_info_type_text);
$email->send();
} else if ($r->customer_info_type == 2) {
$sms = new SmsNotification();
$customerText = trim($r->customer_info_text);
$body = "Xinon Terminbestätigung:" . PHP_EOL . $customerText;
$sms->setBody($body);
$customerNumber = trim($r->customer_info_type_text);
$customerNumber = str_replace(" ", "", $customerNumber);
$customerNumber = str_replace("(", "", $customerNumber);
$customerNumber = str_replace(")", "", $customerNumber);
$customerNumber = str_replace("-", "", $customerNumber);
$customerNumber = str_replace("/", "", $customerNumber);
$customerNumber = str_replace(".", "", $customerNumber);
$customerNumber = str_replace(",", "", $customerNumber);
$customerNumber = str_replace(";", "", $customerNumber);
$customerNumber = str_replace(":", "", $customerNumber);
if (preg_match('/^0/', $customerNumber)) {
$customerNumber = "+43" . substr($customerNumber, 1);
}
$sms->setRecipient($customerNumber);
if (!empty($customerNumber) && !empty($customerText)) {
$sms->send();
}
}
}
die();
case "deleteCalendarEvent":
$r = $this->request;
$id = ($r->id);
CalendarModel::deleteCalendarEvent($r);
die();
case "updateCalendarColor":
$r = $this->request;
$calendar_id = ($r->calendar_id);
$bgcolors = ($r->bgcolors);
$txtcolors = ($r->txtcolors);
$id = ($r->id);
$this->updateCalendarColor($id, $calendar_id, $bgcolors, $txtcolors);
die();
case "uploadCalendarEventAttachment":
$r = $this->request;
$filename = $_FILES['upload_file']['name'];
$filesize = $_FILES['upload_file']['size'];
$file_content = file_get_contents($_FILES['upload_file']['tmp_name']);
$filetype = $_FILES['upload_file']['type'];
$file_content = base64_encode($file_content);
$newkey = $r->newkey;
$id = CalendarModel::insertCalendarEventAttachmentTemp($filename, $filetype, $file_content, $filesize, $newkey);
if ($id) {
$json['success'] = true;
$json['id'] = $id;
}
$json = json_encode($json);
echo $json;
die();
case "deleteCalendarEventAttachmentTmp":
$r = $this->request;
$newkey = ($r->newkey);
$name = ($r->name);
CalendarModel::deleteCalendarEventAttachmentTemp($newkey, $name);
die();
default:
$return = false;
}
}
protected function encryptString($plainText, $password, $salt)
{
// Definiere den Algorithmus und die Länge des Initialisierungsvektors
$cipher = "aes-256-cbc";
$ivlen = openssl_cipher_iv_length($cipher);
// Generiere einen Initialisierungsvektor
$iv = openssl_random_pseudo_bytes($ivlen);
// Erzeuge einen Schlüssel aus dem Passwort und dem Salt
$key = hash_pbkdf2("sha256", $password, $salt, 1000, 32, true);
// Verschlüssele den String
$cipherText = openssl_encrypt($plainText, $cipher, $key, 0, $iv);
// Füge den IV an den verschlüsselten Text an, da dieser für die Entschlüsselung benötigt wird
$cipherText = base64_encode($iv . $cipherText);
return $cipherText;
}
protected function updateCalendarColor($id, $calendar_id, $bgcolors, $txtcolors)
{
$r = $this->request;
$groups = $r->groups;
$redis = new Redis();
//Connecting to Redis
$redis->connect('172.16.5.5', '6379');
//$redis->auth('password');
$Calendar = new Calendar($id);
foreach ($bgcolors as $key => $value) {
$colordata[$calendar_id[$key]]['bgcolor'] = $value;
$colordata[$calendar_id[$key]]['txtcolor'] = $txtcolors[$key];
}
$Calendar->colors = json_encode($colordata);
if ($groups) {
$Calendar->groups = $groups;
}
$redis->set('thetool_calendar_usercolors_' . $this->me->id, json_encode($colordata));
$Calendar->save();
die();
}
protected function viewAction()
{
$Calendar = CalendarModel::search(array("user_id" => $this->me->id));
$CalendarAll = CalendarModel::getAll();
$encryptedUser = $this->encryptString($this->me->id, "testpw", "testsalt");
$this->layout()->set("Calendar", $Calendar);
$this->layout()->set("CalendarAll", $CalendarAll);
$this->layout()->set("encryptedUser", $encryptedUser);
$timerecordingholidays = TimerecordingHolidayModel::getAll();
$this->layout()->set("timerecordingholidays", $timerecordingholidays);
$timerecordingemployees = TimerecordingEmployeeModel::getAll();
$standardCalendarColors = CalendarModel::$standardCalendarColors;
$specialCalendarColors = CalendarModel::$specialCalendarColors;
$this->layout()->set("timerecordingemployees", $timerecordingemployees);
$this->layout()->set("standardCalendarColors", $standardCalendarColors);
$this->layout()->set("specialCalendarColors", $specialCalendarColors);
$this->layout()->setTemplate("Calendar/View");
}
private function getCalendarAttachment($id)
{
$content = CalendarModel::getCalendarEventAttachment($id);
//
// header('Content-Type: application/octet-stream');
header('Content-Type: ' . $content['contentType']);
header('Content-disposition: attachment; filename="' . $content['name'] . '"');
echo base64_decode($content['content']);
exit;
}
private function getCalendarAttachmentTmp($id, $name)
{
$content = CalendarModel::getCalendarEventAttachmentTmp($id, $name);
//
// header('Content-Type: application/octet-stream');
header('Content-Type: ' . $content['contentType']);
header('Content-disposition: attachment; filename="' . $content['name'] . '"');
echo base64_decode($content['content']);
exit;
}
private function getAddress($r)
{
$xinon = $r->xinon;
$address = AddressModel::search(array("Controller!" => 'Calendar', "search_term!" => $r->term, "xinon" => $xinon), array('count' => '20'));
$mobiles = CalendarModel::$austrian_mobile_prefixes;
$prefixes = array('0043', '43 ', '43', '0');
foreach ($address as $key => $value) {
unset($mobilenumber);
$id = $value->id;
if ($value->company) {
$text = "(F) " . $value->company;
} else {
$text = "(P) " . $value->firstname . " " . $value->lastname;
}
if ($value->mobile) {
foreach ($mobiles as $mobile) {
foreach ($prefixes as $prefix) {
if (strpos($value->mobile, $prefix . $mobile) !== false) {
$mobilenumber = str_replace($prefix . $mobile, '+43' . $mobile, $value->mobile);
$found = 1;
break;
}
}
if ($found) {
break;
}
}
}
if ($value->phone) {
foreach ($mobiles as $mobile) {
foreach ($prefixes as $prefix) {
if (strpos($value->phone, $prefix . $mobile) !== false) {
$mobilenumber = str_replace($prefix . $mobile, '+43' . $mobile, $value->phone);
$found = 1;
break;
}
}
if ($found) {
break;
}
}
}
if ($mobilenumber) {
if (strlen($mobilenumber) > 0 && strlen($mobilenumber) < 22) {
$mobilenumber = str_replace(" ", "", $mobilenumber);
$mobilenumber = str_replace("(", "", $mobilenumber);
$mobilenumber = str_replace(")", "", $mobilenumber);
$mobilenumber = str_replace("-", "", $mobilenumber);
$mobilenumber = str_replace("/", "", $mobilenumber);
$mobilenumber = str_replace(".", "", $mobilenumber);
$mobilenumber = str_replace(",", "", $mobilenumber);
$mobilenumber = str_replace(";", "", $mobilenumber);
$mobilenumber = str_replace(":", "", $mobilenumber);
}
} else if ($value->mobile) {
$mobilenumber = $value->mobile;
} else if ($value->phone) {
$mobilenumber = $value->phone;
} else {
$mobilenumber = "";
}
$rows[] = array(
'id' => $id,
'text' => $value->customer_number . " " . $text . " - " . $value->street . ", " . $value->zip . " " . $value->city,
'mail' => $value->email,
'mobilenumber' => $mobilenumber,
'spin' => $value->spin,
'location' => $value->street . ", " . $value->zip . " " . $value->city,
'name' => $value->customer_number . " " . $text
);
}
$json['incomplete_results'] = false;
$json['total_count'] = count($rows);
$json['items'] = $rows;
$json = json_encode($json);
echo trim($json);
die();
}
private function getTicket($r)
{
$project = new XinonProject();
$data = $project->searchSupportTickets($r->term);
foreach ($data as $key => $value) {
$rows[] = array(
'id' => $value['id'],
'text' => 'Ticket: ' . $value['id'] . " " . $value['subject'],
'subject' => $value['subject'],
'mail' => $value['customField5'],
'mobilenumber' => $value['customField4'],
'location' => $value['customField3'],
'name' => $value['customField2']
);
}
$json['incomplete_results'] = false;
$json['total_count'] = count($rows);
$json['items'] = $rows;
$json = json_encode($json);
echo trim($json);
die();
}
private function generateGraphRecurrence($data, $startDate)
{
$graph = [
'pattern' => [],
'range' => []
];
$freq = strtoupper($data['rrule_frequency']);
switch ($freq) {
case 'DAILY':
$graph['pattern']['type'] = 'daily';
break;
case 'WEEKLY':
$graph['pattern']['type'] = 'weekly';
break;
case 'MONTHLY':
if (!empty($data['monthly_type']) && $data['monthly_type'] === 'BYMONTHDAY') {
$graph['pattern']['type'] = 'absoluteMonthly';
$graph['pattern']['dayOfMonth'] = intval($data['rrule_bymonthday']);
} elseif (!empty($data['monthly_type']) && $data['monthly_type'] === 'BYSETPOS') {
$graph['pattern']['type'] = 'relativeMonthly';
// Mapping: 1 => first, 2 => second, 3 => third, 4 => fourth, -1 => last
$setpos = intval($data['rrule_setpos']);
$indexMapping = [
1 => 'first',
2 => 'second',
3 => 'third',
4 => 'fourth',
-1 => 'last'
];
$graph['pattern']['index'] = isset($indexMapping[$setpos]) ? $indexMapping[$setpos] : 'first';
if (!empty($data['rrule_bynweekday'])) {
$graph['pattern']['daysOfWeek'] = [$this->convertDayToGraph(strtoupper($data['rrule_bynweekday']))];
}
}
break;
case 'YEARLY':
$graph['pattern']['type'] = 'absoluteYearly';
break;
default:
$graph['pattern']['type'] = 'daily';
}
$graph['pattern']['interval'] = 1;
if ($freq === 'WEEKLY' && !empty($data['rrule-byweekday'])) {
$days = is_array($data['rrule-byweekday']) ? $data['rrule-byweekday'] : [$data['rrule-byweekday']];
$graphDays = [];
foreach ($days as $day) {
$graphDays[] = $this->convertDayToGraph(strtoupper($day));
}
$graph['pattern']['daysOfWeek'] = $graphDays;
}
$graph['range']['startDate'] = $startDate;
if (!empty($data['rrule_until'])) {
$graph['range']['endDate'] = $data['rrule_until'];
$graph['range']['type'] = 'endDate';
} elseif (!empty($data['rrule_count'])) {
$graph['range']['numberOfOccurrences'] = intval($data['rrule_count']);
$graph['range']['type'] = 'numbered';
} else {
$graph['range']['type'] = 'noEnd';
}
return $graph;
}
private function convertDayToGraph($dayAbbrev)
{
$mapping = [
'MO' => 'monday',
'TU' => 'tuesday',
'WE' => 'wednesday',
'TH' => 'thursday',
'FR' => 'friday',
'SA' => 'saturday',
'SU' => 'sunday'
];
return isset($mapping[$dayAbbrev]) ? $mapping[$dayAbbrev] : $dayAbbrev;
}
private function generateXlsx($r)
{
$calendarEvents = json_decode(CalendarModel::getCalendarEvents($this->me->id, 0, $r, true), true);
$eventTypes = CalendarModel::$eventTypes;
$xls = new Spreadsheet();
$sheet = $xls->getActiveSheet();
$writer = new Xlsx($xls);
$sheet->getStyle('A1:AN1')->getFont()->setBold(true);
$sheet->getStyle('A:E')->getAlignment()->setHorizontal(\PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER);
$sheet->getStyle('I:L')->getAlignment()->setHorizontal(\PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER);
$sheet->getColumnDimension('A')->setWidth(25);
$sheet->getColumnDimension('B')->setWidth(15);
$sheet->getColumnDimension('C')->setWidth(10);
$sheet->getColumnDimension('D')->setWidth(15);
$sheet->getColumnDimension('E')->setWidth(10);
$sheet->getColumnDimension('F')->setWidth(40);
$sheet->getColumnDimension('G')->setWidth(40);
$sheet->getColumnDimension('H')->setWidth(20);
$sheet->getColumnDimension('I')->setWidth(10);
$sheet->getColumnDimension('J')->setWidth(10);
$sheet->getColumnDimension('K')->setWidth(15);
$sheet->getColumnDimension('L')->setWidth(15);
$sheet->setCellValue([1, 1], 'Kalender')
->setCellValue([2, 1], 'Startdatum')
->setCellValue([3, 1], 'Startzeit')
->setCellValue([4, 1], 'Enddatum')
->setCellValue([5, 1], 'Endzeit')
->setCellValue([6, 1], 'Betreff')
->setCellValue([7, 1], 'Ort')
->setCellValue([8, 1], 'Beschreibung')
->setCellValue([9, 1], 'Termintyp')
->setCellValue([10, 1], 'Privat')
->setCellValue([11, 1], 'Sichtbarkeit')
->setCellValue([12, 1], 'Organisator')
;
$counter = 2;
foreach ($calendarEvents['data'] as $event) {
if ($event['privateflag']['privateflag']) {
$event['privateflag']['privateflag'] = "Ja";
} else {
$event['privateflag']['privateflag'] = "Nein";
}
if ($event['isorganizer']['isorganizer']) {
$event['isorganizer']['isorganizer'] = "Ja";
} else {
$event['isorganizer']['isorganizer'] = "Nein";
}
if ($event['busy']['busy'] == 1) {
$event['busy']['busy'] = "gebucht";
} else if ($event['busy']['busy'] == 2) {
$event['busy']['busy'] = "mit Vorbehalt";
} else {
$event['busy']['busy'] = "frei";
}
if ($event['allDay']['allDay'] == 0) {
$starttime = date("H:i", strtotime($event['cstart']['cstart']));
$endtime = date("H:i", strtotime($event['cend']['cend']));
$startdate = date("d.m.Y", strtotime($event['cstart']['cstart']));
$enddate = date("d.m.Y", strtotime($event['cend']['cend']));
} else {
$starttime = "";
$startdate = date("d.m.Y", strtotime($event['cstart']['cstart']));
$endtime = "";
$enddate = date("d.m.Y", strtotime($event['cend']['cend']) - 7500);
}
if ($event['event_type']['event_type'] != "") {
$helper = new Html();
$richText = $helper->toRichTextObject($event['description']['description']);
$calendarType = $eventTypes[$event['event_type']['event_type']];
$sheet->setCellValue([1, $counter], $event['calendar_name']['calendar_name'])
->setCellValue([2, $counter], $startdate)
->setCellValue([3, $counter], $starttime)
->setCellValue([4, $counter], $enddate)
->setCellValue([5, $counter], $endtime)
->setCellValue([6, $counter], $event['ccategory']['ccategory'])
->setCellValue([7, $counter], $event['location']['location'])
->setCellValue([8, $counter], $richText)
->setCellValue([9, $counter], $calendarType)
->setCellValue([10, $counter], $event['privateflag']['privateflag'])
->setCellValue([11, $counter], $event['busy']['busy'])
->setCellValue([12, $counter], $event['isorganizer']['isorganizer'])
;
$counter++;
}
}
header("Content-type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
header('Content-disposition: attachment; filename="Kalender-' . date('Y-m-d_H-i-s') . '-' . uniqid() . '.xlsx"');
$writer->save('php://output');
exit;
}
protected function indexAction()
{
$this->layout()->setTemplate("Calendar/Index");
$calendars = CalendarModel::getAll();
$calendarTemplateEventTypes = CalendarTemplateModel::$calendarTemplateEventTypes;
$this->layout()->set("calendarTemplateEventTypes", $calendarTemplateEventTypes);
$calendartemplates = CalendarTemplateModel::getAll();
$this->layout()->set("calendartemplates", $calendartemplates);
$this->layout()->set("calendars", $calendars);
}
protected function addAction()
{
$users = UserModel::getAll();
$this->layout()->set("users", $users);
$this->layout()->setTemplate("Calendar/Form");
}
protected function editAction()
{
$id = $this->request->id;
if (!is_numeric($id) || !$id) {
$this->layout()->setFlash("Kalender Verwaltung nicht gefunden", "error");
$this->redirect("Calendar");
}
$calendars = new Calendar($id);
if ($calendars->id != $id) {
$this->layout()->setFlash("Kalender Verwaltung nicht gefunden", "error");
$this->redirect("Calendar");
}
$this->layout()->set("calendars", $calendars);
return $this->addAction();
}
protected function saveAction()
{
$r = $this->request;
$id = $r->id;
//var_dump($r->get());exit;
if (is_numeric($id) && $id > 0) {
$mode = "edit";
$calendars = new Calendar($id);
if (!$calendars->id) {
$this->layout()->setFlash("Kalender Verwaltung nicht gefunden", "error");
$this->redirect("Calendar");
}
} else {
$mode = "add";
}
$data = [];
if ($mode == "add") {
$data['user_id'] = trim($r->user_id);
if (!$data['user_id']) {
$this->layout()->setFlash("Name darf nicht leer sein", "error");
$this->redirect("Calendar");
}
}
$data['go_calendar_id'] = trim($r->go_calendar_id);
$data['microsoft_id'] = trim($r->microsoft_id);
// $data['rights'] = trim($r->rights);
// $data['colors'] = trim($r->colors);
// $data['subscription_id'] = trim($r->subscription_id);
// $data['expirationDateTime'] = trim($r->expirationDateTime);
$data['active'] = trim($r->active);
if (!$data['go_calendar_id']) {
$data['go_calendar_id'] = NULL;
}
if (!$data['microsoft_id']) {
$data['microsoft_id'] = NULL;
}
if (!$data['active']) {
$data['active'] = '0';
}
if ($mode == "edit") {
$calendars->update($data);
} else {
$calendars = CalendarModel::create($data);
}
$id = $calendars->save();
if (!$id) {
$this->layout()->setFlash("Kalender Verwaltung konnte nicht angelegt werden", "error");
$this->redirect("Calendar");
}
if ($mode == "edit") {
$this->layout()->setFlash("Kalender Verwaltung erfolgreich geändert", "success");
} else if ($mode = "add") {
$this->layout()->setFlash("Kalender Verwaltung erfolgreich angelegt", "success");
}
$this->redirect("Calendar");
}
protected function deleteAction()
{
$id = $this->request->id;
$calendars = new Calendar($id);
if (!$calendars->id || $calendars->id != $id) {
$this->layout()->setFlash("Kalender Verwaltung nicht gefunden.", "error");
$this->redirect("Calendar");
}
$calendars->delete();
$this->redirect("Calendar");
}
}