diff --git a/application/config/routes.php b/application/config/routes.php index aa4ba9db8..6a8d2b8fb 100644 --- a/application/config/routes.php +++ b/application/config/routes.php @@ -119,6 +119,10 @@ $route['api/frontend/v1/stv/[sS]tudents/([WS]S[0-9]{4})/prestudent/(:num)'] = 'a // // (studiensemester_kurzbz)/person/(person_id) $route['api/frontend/v1/stv/[sS]tudents/([WS]S[0-9]{4})/person/(:num)'] = 'api/frontend/v1/stv/Students/getPerson/$1/$2'; + +$route['test'] = 'Test'; +$route['test/.*'] = 'Test'; + // load routes from extensions, also look for environment-specific configs $subdirs = ['application/config/extensions', 'application/config/' . ENVIRONMENT . '/extensions']; diff --git a/application/controllers/Test.php b/application/controllers/Test.php new file mode 100644 index 000000000..0454d16f4 --- /dev/null +++ b/application/controllers/Test.php @@ -0,0 +1,145 @@ +load->library('sabredav/SabreDAVAuthLib'); + $this->load->library('sabredav/SabreDAVCalDAVLib'); + } + + // ----------------------------------------------------------------------------------------------------------------- + // Public methods + public function index() + { + + $authBackend = new SabreDAVAuthLib(); + $principalBackend = new SabreDAVACLPrincipalBackendLib($authBackend); + $calendarBackend = new SabreDAVCalDAVBackendLib($authBackend); + + $tree = array( + new \Sabre\CalDAV\Principal\Collection($principalBackend), + new SabreDAVReadOnlyCalendarRootLib($principalBackend, $calendarBackend) + ); + + $server = new \Sabre\DAV\Server($tree); + + $path = "/ma1433/core/FHC-Core/index.ci.php/test"; + $server->setBaseUri($path); + + $authBackend->setRealm('SabreDAV'); + $authPlugin = new \Sabre\DAV\Auth\Plugin($authBackend); + $server->addPlugin($authPlugin); + + $this->_registerReadOnlyWriteInterceptor($server); + + $caldavPlugin = new \Sabre\CalDAV\Plugin(); + $server->addPlugin($caldavPlugin); + + $aclPlugin = new \Sabre\DAVACL\Plugin(); + $server->addPlugin($aclPlugin); + + $browser = new \Sabre\DAV\Browser\Plugin(); + $server->addPlugin($browser); + + $server->exec(); + } + + private function _registerReadOnlyWriteInterceptor($server) + { + $callback = function() use ($server) { + return $this->_discardReadOnlyWriteRequest($server, func_get_args()); + }; + + if (method_exists($server, 'on')) + { + $server->on('beforeMethod', $callback, 20); + return; + } + + if (method_exists($server, 'subscribeEvent')) + { + $server->subscribeEvent('beforeMethod', $callback, 20); + } + } + + private function _discardReadOnlyWriteRequest($server, array $eventArgs) + { + $method = $this->_getDavRequestMethod($eventArgs); + if (!in_array($method, array('PUT', 'DELETE', 'PROPPATCH', 'MKCOL', 'MOVE', 'COPY'), true)) + return true; + + $this->_sendReadOnlyWriteAcceptedResponse($server, $eventArgs); + return false; + } + + private function _getDavRequestMethod(array $eventArgs) + { + foreach ($eventArgs as $argument) + { + if (is_string($argument)) + return strtoupper($argument); + + if (is_object($argument) && method_exists($argument, 'getMethod')) + return strtoupper($argument->getMethod()); + } + + return isset($_SERVER['REQUEST_METHOD']) ? strtoupper($_SERVER['REQUEST_METHOD']) : ''; + } + + private function _sendReadOnlyWriteAcceptedResponse($server, array $eventArgs) + { + $response = $this->_getDavResponse($server, $eventArgs); + + if (is_object($response)) + { + if (method_exists($response, 'setStatus')) + { + $response->setStatus(204); + if (method_exists($response, 'setHeader')) + $response->setHeader('Content-Length', '0'); + if (method_exists($response, 'setBody')) + $response->setBody(''); + return; + } + + if (method_exists($response, 'sendStatus')) + { + if (method_exists($response, 'setHeader')) + $response->setHeader('Content-Length', '0'); + $response->sendStatus(204); + return; + } + } + + if (!headers_sent()) + { + header('HTTP/1.1 204 No Content'); + header('Content-Length: 0'); + } + } + + private function _getDavResponse($server, array $eventArgs) + { + foreach ($eventArgs as $argument) + { + if (is_object($argument) && ( + method_exists($argument, 'setStatus') + || method_exists($argument, 'sendStatus') + )) + { + return $argument; + } + } + + return isset($server->httpResponse) ? $server->httpResponse : null; + } +} diff --git a/application/controllers/api/frontend/v1/tempus/Kalender.php b/application/controllers/api/frontend/v1/tempus/Kalender.php index d1aeaa576..d6050c65c 100644 --- a/application/controllers/api/frontend/v1/tempus/Kalender.php +++ b/application/controllers/api/frontend/v1/tempus/Kalender.php @@ -38,8 +38,8 @@ class Kalender extends FHCAPI_Controller $this->_ci->load->library('LogLib'); $this->_ci->load->library('form_validation'); - $this->_ci->load->library('KalenderLib'); - $this->_ci->load->library('RaumvorschlagLib'); + $this->_ci->load->library('KalenderLib', ["uid" => getAuthUID()]); + $this->_ci->load->library('RaumvorschlagLib', ["uid" => getAuthUID()]); $this->loadPhrases([ 'ui' ]); diff --git a/application/controllers/api/frontend/v1/tempus/OperationalResourceToCalenderAPI.php b/application/controllers/api/frontend/v1/tempus/OperationalResourceToCalenderAPI.php index 376a0fedc..4f6a356f1 100644 --- a/application/controllers/api/frontend/v1/tempus/OperationalResourceToCalenderAPI.php +++ b/application/controllers/api/frontend/v1/tempus/OperationalResourceToCalenderAPI.php @@ -18,8 +18,8 @@ class OperationalResourceToCalenderAPI extends FHCAPI_Controller $this->load->model('ressource/Betriebsmittel_model', 'BetriebsmittelModel'); $this->load->model('ressource/Kalender_model', 'KalenderModel'); - $this->load->library('CollisionChecker'); - $this->load->library('KalenderLib'); + $this->_ci->load->library('CollisionChecker', ["uid" => getAuthUID()]); + $this->_ci->load->library('KalenderLib', ["uid" => getAuthUID()]); } //------------------------------------------------------------------------------------------------------------------ diff --git a/application/controllers/api/frontend/v1/tempus/Reservierung.php b/application/controllers/api/frontend/v1/tempus/Reservierung.php index c1030d8ee..0215bcc8e 100644 --- a/application/controllers/api/frontend/v1/tempus/Reservierung.php +++ b/application/controllers/api/frontend/v1/tempus/Reservierung.php @@ -22,7 +22,7 @@ class Reservierung extends FHCAPI_Controller $this->_ci->load->library('LogLib'); $this->_ci->load->library('form_validation'); - $this->_ci->load->library('KalenderLib'); + $this->_ci->load->library('KalenderLib', ["uid" => getAuthUID()]); $this->_ci->load->model('ressource/Ort_model', 'OrtModel'); $this->_ci->load->model('ressource/Kalender_Event_Rolle_model', 'KalenderEventRolleModel'); diff --git a/application/libraries/CollisionChecker.php b/application/libraries/CollisionChecker.php index ac9152d2b..6f4e7e6f4 100644 --- a/application/libraries/CollisionChecker.php +++ b/application/libraries/CollisionChecker.php @@ -9,16 +9,23 @@ class CollisionChecker private $_checks = []; private $_ci; + private $_uid; - public function __construct() + public function __construct($params) { $this->_ci =& get_instance(); - $this->_ci->load->library('collision/checks/RoomCollisionCheck'); - $this->_ci->load->library('collision/checks/LectureCollisionCheck'); - $this->_ci->load->library('collision/checks/VerbandCollisionCheck'); - $this->_ci->load->library('collision/checks/StudentCollisionCheck'); - $this->_ci->load->library('collision/checks/ResourcesCollisionCheck'); + if (isset($params['uid']) && !isEmptyString($params['uid'])){ + $this->_uid = $params['uid']; + } else { + show_error('uid of logged user not passed!'); + } + + $this->_ci->load->library('collision/checks/RoomCollisionCheck', ['uid' => $this->_uid]); + $this->_ci->load->library('collision/checks/LectureCollisionCheck', ['uid' => $this->_uid]); + $this->_ci->load->library('collision/checks/VerbandCollisionCheck', ['uid' => $this->_uid]); + $this->_ci->load->library('collision/checks/StudentCollisionCheck', ['uid' => $this->_uid]); + $this->_ci->load->library('collision/checks/ResourcesCollisionCheck', ['uid' => $this->_uid]); $this->register($this->_ci->roomcollisioncheck); $this->register($this->_ci->lecturecollisioncheck); $this->register($this->_ci->verbandcollisioncheck); @@ -64,4 +71,4 @@ class CollisionChecker return $results; } -} \ No newline at end of file +} diff --git a/application/libraries/KalenderLib.php b/application/libraries/KalenderLib.php index b0b3ad0ad..87c6d94e0 100644 --- a/application/libraries/KalenderLib.php +++ b/application/libraries/KalenderLib.php @@ -5,9 +5,17 @@ if (! defined("BASEPATH")) exit("No direct script access allowed"); class KalenderLib { private $_ci; - public function __construct() + private $_uid; + + public function __construct($params) { $this->_ci =& get_instance(); + + if (isset($params['uid']) && !isEmptyString($params['uid'])){ + $this->_uid = $params['uid']; + } else { + show_error('uid of logged user not passed!'); + } $this->_ci->load->model('ressource/Kalender_model', 'KalenderModel'); $this->_ci->load->model('ressource/Kalender_Lehreinheit_model', 'KalenderLehreinheitModel'); @@ -22,7 +30,7 @@ class KalenderLib $this->_ci->load->model('organisation/gruppe_model', 'GruppeModel'); $this->_ci->load->model('organisation/Lehrverband_model', 'LehrverbandModel'); - $this->_ci->load->library('CollisionChecker'); + $this->_ci->load->library('CollisionChecker', ['uid' => $this->_uid]); $this->_ci->load->library('PhrasesLib', array('ui')); } @@ -180,7 +188,8 @@ class KalenderLib 'beschreibung' => isset($row->beschreibung) ? $row->beschreibung : '', 'topic' => (isset($row->lehrfach_kurzbz) ? $row->lehrfach_kurzbz : '').' '.(isset($row->lehrform_kurzbz) ? $row->lehrform_kurzbz : ''), 'collisions' => false, - 'has_assigned_resources' => isset($row->has_assigned_resources) ? $row->has_assigned_resources : false + 'has_assigned_resources' => isset($row->has_assigned_resources) ? $row->has_assigned_resources : false, + 'updateamum' => isset($row->updateamum) ? $row->updateamum : null, ]; } @@ -376,6 +385,134 @@ class KalenderLib return $this->_mapEvents($data); } + public function getPlanForStudentByStudent($start_date, $end_date, $userUID) + { + $this->_getBasePlan($start_date, $end_date); + + $escapedUserUID = $this->_ci->KalenderModel->db->escape($userUID); + + $benutzerExists = "EXISTS ( + SELECT 1 + FROM public.tbl_benutzer student_benutzer + WHERE student_benutzer.uid = $escapedUserUID + )"; + + $directEventTeilnehmerExists = "EXISTS ( + SELECT 1 + FROM lehre.tbl_kalender_event_teilnehmer event_teilnehmer + WHERE event_teilnehmer.kalender_id = tbl_kalender.kalender_id + AND event_teilnehmer.rolle_kurzbz = 'teilnehmer' + AND event_teilnehmer.uid = $escapedUserUID + )"; + + $eventBenutzergruppeExists = "EXISTS ( + SELECT 1 + FROM lehre.tbl_kalender_event_teilnehmer event_gruppe + JOIN public.tbl_benutzergruppe event_benutzergruppe + ON event_benutzergruppe.gruppe_kurzbz = event_gruppe.gruppe_kurzbz + AND ( + event_gruppe.studiensemester_kurzbz IS NULL + OR event_benutzergruppe.studiensemester_kurzbz = event_gruppe.studiensemester_kurzbz + ) + WHERE event_gruppe.kalender_id = tbl_kalender.kalender_id + AND event_gruppe.rolle_kurzbz = 'teilnehmer' + AND event_gruppe.gruppe_kurzbz IS NOT NULL + AND event_benutzergruppe.uid = $escapedUserUID + )"; + + $eventStudentlehrverbandExists = "EXISTS ( + SELECT 1 + FROM lehre.tbl_kalender_event_teilnehmer event_lehrverband + JOIN public.tbl_studentlehrverband event_studentlehrverband + ON event_studentlehrverband.student_uid = $escapedUserUID + AND event_studentlehrverband.studiengang_kz = event_lehrverband.studiengang_kz + AND ( + event_lehrverband.studiensemester_kurzbz IS NULL + OR event_studentlehrverband.studiensemester_kurzbz = event_lehrverband.studiensemester_kurzbz + ) + AND ( + event_lehrverband.semester IS NULL + OR event_studentlehrverband.semester = event_lehrverband.semester + ) + AND ( + event_lehrverband.verband = event_studentlehrverband.verband + OR event_lehrverband.verband IS NULL + OR btrim(event_lehrverband.verband::text) = '' + OR event_studentlehrverband.verband IS NULL + ) + AND ( + event_lehrverband.gruppe = event_studentlehrverband.gruppe + OR event_lehrverband.gruppe IS NULL + OR btrim(event_lehrverband.gruppe::text) = '' + OR event_studentlehrverband.gruppe IS NULL + ) + WHERE event_lehrverband.kalender_id = tbl_kalender.kalender_id + AND event_lehrverband.rolle_kurzbz = 'teilnehmer' + AND event_lehrverband.gruppe_kurzbz IS NULL + AND event_lehrverband.studiengang_kz IS NOT NULL + )"; + + $lehreinheitBenutzergruppeExists = "EXISTS ( + SELECT 1 + FROM lehre.tbl_kalender_lehreinheit student_kalender_lehreinheit + JOIN lehre.tbl_lehreinheit student_lehreinheit + ON student_lehreinheit.lehreinheit_id = student_kalender_lehreinheit.lehreinheit_id + JOIN lehre.tbl_lehreinheitgruppe student_lehreinheitgruppe + ON student_lehreinheitgruppe.lehreinheit_id = student_lehreinheit.lehreinheit_id + JOIN public.tbl_gruppe student_gruppe + ON student_gruppe.studiengang_kz = student_lehreinheitgruppe.studiengang_kz + AND student_gruppe.semester = student_lehreinheitgruppe.semester + AND student_gruppe.gruppe_kurzbz = student_lehreinheitgruppe.gruppe_kurzbz + JOIN public.tbl_benutzergruppe student_benutzergruppe + ON student_benutzergruppe.gruppe_kurzbz = student_gruppe.gruppe_kurzbz + AND student_benutzergruppe.studiensemester_kurzbz = student_lehreinheit.studiensemester_kurzbz + WHERE student_kalender_lehreinheit.kalender_id = tbl_kalender.kalender_id + AND student_lehreinheitgruppe.gruppe_kurzbz IS NOT NULL + AND student_benutzergruppe.uid = $escapedUserUID + )"; + + $lehreinheitStudentlehrverbandExists = "EXISTS ( + SELECT 1 + FROM lehre.tbl_kalender_lehreinheit student_kalender_lehreinheit + JOIN lehre.tbl_lehreinheit student_lehreinheit + ON student_lehreinheit.lehreinheit_id = student_kalender_lehreinheit.lehreinheit_id + JOIN lehre.tbl_lehreinheitgruppe student_lehreinheitgruppe + ON student_lehreinheitgruppe.lehreinheit_id = student_lehreinheit.lehreinheit_id + JOIN public.tbl_studentlehrverband student_lehrverband + ON student_lehrverband.student_uid = $escapedUserUID + AND student_lehrverband.studiengang_kz = student_lehreinheitgruppe.studiengang_kz + AND student_lehrverband.semester = student_lehreinheitgruppe.semester + AND student_lehrverband.studiensemester_kurzbz = student_lehreinheit.studiensemester_kurzbz + AND ( + student_lehreinheitgruppe.verband = student_lehrverband.verband + OR student_lehreinheitgruppe.verband IS NULL + OR btrim(student_lehreinheitgruppe.verband::text) = '' + OR student_lehrverband.verband IS NULL + ) + AND ( + student_lehreinheitgruppe.gruppe = student_lehrverband.gruppe + OR student_lehreinheitgruppe.gruppe IS NULL + OR btrim(student_lehreinheitgruppe.gruppe::text) = '' + OR student_lehrverband.gruppe IS NULL + ) + WHERE student_kalender_lehreinheit.kalender_id = tbl_kalender.kalender_id + AND student_lehreinheitgruppe.gruppe_kurzbz IS NULL + )"; + + $this->_ci->KalenderModel->db->where('status_kurzbz', 'live'); + $this->_ci->KalenderModel->db->where($benutzerExists, null, false); + $this->_ci->KalenderModel->db->group_start(); + $this->_ci->KalenderModel->db->where($directEventTeilnehmerExists, null, false); + $this->_ci->KalenderModel->db->or_where($eventBenutzergruppeExists, null, false); + $this->_ci->KalenderModel->db->or_where($eventStudentlehrverbandExists, null, false); + $this->_ci->KalenderModel->db->or_where($lehreinheitBenutzergruppeExists, null, false); + $this->_ci->KalenderModel->db->or_where($lehreinheitStudentlehrverbandExists, null, false); + $this->_ci->KalenderModel->db->group_end(); + + $data = $this->_ci->KalenderModel->load(); + + return $this->_mapEvents($data); + } public function getPlanForLecturer($start_date, $end_date) { @@ -395,6 +532,42 @@ class KalenderLib return $this->_mapEvents($data); } + + public function getPlanForLecturerByLecturer($start_date, $end_date, $userUID) + { + $this->_getBasePlan($start_date, $end_date); + + $escapedUserUID = $this->_ci->KalenderModel->db->escape($userUID); + + $lehreinheitMitarbeiterExists = "EXISTS ( + SELECT 1 + FROM lehre.tbl_kalender_lehreinheit lecturer_kalender_lehreinheit + JOIN lehre.tbl_lehreinheit lecturer_lehreinheit + ON lecturer_lehreinheit.lehreinheit_id = lecturer_kalender_lehreinheit.lehreinheit_id + JOIN lehre.tbl_lehreinheitmitarbeiter lecturer_lehreinheitmitarbeiter + ON lecturer_lehreinheitmitarbeiter.lehreinheit_id = lecturer_lehreinheit.lehreinheit_id + WHERE lecturer_kalender_lehreinheit.kalender_id = tbl_kalender.kalender_id + AND lecturer_lehreinheitmitarbeiter.mitarbeiter_uid = $escapedUserUID + )"; + + $eventTeilnehmerExists = "EXISTS ( + SELECT 1 + FROM lehre.tbl_kalender_event_teilnehmer lecturer_event_teilnehmer + WHERE lecturer_event_teilnehmer.kalender_id = tbl_kalender.kalender_id + AND lecturer_event_teilnehmer.uid = $escapedUserUID + )"; + + $this->_ci->KalenderModel->db->where('tbl_kalender.status_kurzbz', 'live'); + $this->_ci->KalenderModel->db->group_start(); + $this->_ci->KalenderModel->db->where($lehreinheitMitarbeiterExists, null, false); + $this->_ci->KalenderModel->db->or_where($eventTeilnehmerExists, null, false); + $this->_ci->KalenderModel->db->group_end(); + + $data = $this->_ci->KalenderModel->load(); + + return $this->_mapEvents($data); + } + public function getZeitsperren($start_date, $end_date, $emp) { $db = new DB_Model(); @@ -593,6 +766,7 @@ class KalenderLib 'bis' => $end_date, 'typ' => 'reservierung', 'status_kurzbz' => 'live', + 'eindeutige_gruppen_id' => $this->_ci->KalenderModel->generateUniqueGroupId(), 'insertvon' => getAuthUID(), 'insertamum' => date('Y-m-d H:i:s') ) diff --git a/application/libraries/RaumvorschlagLib.php b/application/libraries/RaumvorschlagLib.php index 3ff37e34b..fbdf7db3a 100644 --- a/application/libraries/RaumvorschlagLib.php +++ b/application/libraries/RaumvorschlagLib.php @@ -7,10 +7,18 @@ use CI3_Events as Events; class RaumvorschlagLib { private $_ci; - public function __construct() + private $_uid; + + public function __construct($params) { $this->_ci =& get_instance(); + if (isset($params['uid']) && !isEmptyString($params['uid'])){ + $this->_uid = $params['uid']; + } else { + show_error('uid of logged user not passed!'); + } + $this->_ci->load->model('ressource/Kalender_model', 'KalenderModel'); $this->_ci->load->model('ressource/Kalender_Lehreinheit_model', 'KalenderLehreinheitModel'); $this->_ci->load->model('ressource/Kalender_Event_model', 'KalenderEventModel'); @@ -26,8 +34,8 @@ class RaumvorschlagLib $this->_ci->load->model('education/Lehreinheitgruppe_model', 'LehreinheitgruppeModel'); $this->_ci->load->model('education/Lehreinheitgruppe_model', 'LehreinheitgruppeModel'); - $this->_ci->load->library('CollisionChecker'); - $this->_ci->load->library('KalenderLib'); + $this->_ci->load->library('CollisionChecker', ["uid" => getAuthUID()]); + $this->_ci->load->library('KalenderLib', ["uid" => getAuthUID()]); $this->_ci->load->library('PhrasesLib', array('ui')); } diff --git a/application/libraries/VariableLib.php b/application/libraries/VariableLib.php index a503eb999..f5176ea67 100644 --- a/application/libraries/VariableLib.php +++ b/application/libraries/VariableLib.php @@ -14,9 +14,9 @@ class VariableLib /** * VariableLib constructor. * Loads variable of logged in user. - * @param $loggeduid + * @param $params */ - public function __construct($loggeduid) + public function __construct($params) { $this->_ci =& get_instance(); @@ -25,8 +25,8 @@ class VariableLib $this->_ci->load->model('system/Variable_model', 'VariableModel'); $this->_ci->load->model('organisation/studiensemester_model', 'StudiensemesterModel'); - if (isset($loggeduid['uid']) && !isEmptyString($loggeduid['uid'])) - $this->_setVariables($loggeduid['uid']); + if (isset($params['uid']) && !isEmptyString($params['uid'])) + $this->_setVariables($params['uid']); else { show_error('uid of logged user not passed!'); diff --git a/application/libraries/collision/checks/LectureCollisionCheck.php b/application/libraries/collision/checks/LectureCollisionCheck.php index ff8303adb..34d26a09b 100644 --- a/application/libraries/collision/checks/LectureCollisionCheck.php +++ b/application/libraries/collision/checks/LectureCollisionCheck.php @@ -4,13 +4,21 @@ class LectureCollisionCheck implements ICollisionCheck { private $_ci; + private $_uid; - public function __construct() + public function __construct($params) { $this->_ci =& get_instance(); + + if (isset($params['uid']) && !isEmptyString($params['uid'])){ + $this->_uid = $params['uid']; + } else { + show_error('uid of logged user not passed!'); + } + $this->_ci->load->model('ressource/Kalender_model', 'KalenderModel'); $this->_ci->load->model('ressource/zeitsperre_model', 'ZeitsperreModel'); - $this->_ci->load->library('VariableLib', array('uid' => getAuthUID())); + $this->_ci->load->library('VariableLib', ['uid' => $this->_uid]); $this->_ci->load->library('PhrasesLib', array('ui')); } @@ -255,4 +263,4 @@ class LectureCollisionCheck implements ICollisionCheck }, getData($result)); } -} \ No newline at end of file +} diff --git a/application/libraries/collision/checks/ResourcesCollisionCheck.php b/application/libraries/collision/checks/ResourcesCollisionCheck.php index 0be789b7f..765ea286c 100644 --- a/application/libraries/collision/checks/ResourcesCollisionCheck.php +++ b/application/libraries/collision/checks/ResourcesCollisionCheck.php @@ -4,12 +4,20 @@ class ResourcesCollisionCheck implements ICollisionCheck { private $_ci; + private $_uid; - public function __construct() + public function __construct($params) { $this->_ci =& get_instance(); + + if (isset($params['uid']) && !isEmptyString($params['uid'])){ + $this->_uid = $params['uid']; + } else { + show_error('uid of logged user not passed!'); + } + $this->_ci->load->model('ressource/Kalender_model', 'KalenderModel'); - $this->_ci->load->library('VariableLib', array('uid' => getAuthUID())); + $this->_ci->load->library('VariableLib', array('uid' => $this->_uid)); $this->_ci->load->library('PhrasesLib', array('ui')); } @@ -82,4 +90,4 @@ class ResourcesCollisionCheck implements ICollisionCheck return $grouped; } -} \ No newline at end of file +} diff --git a/application/libraries/collision/checks/RoomCollisionCheck.php b/application/libraries/collision/checks/RoomCollisionCheck.php index 4d72ce0cd..f16891107 100644 --- a/application/libraries/collision/checks/RoomCollisionCheck.php +++ b/application/libraries/collision/checks/RoomCollisionCheck.php @@ -4,12 +4,20 @@ class RoomCollisionCheck implements ICollisionCheck { private $_ci; + private $_uid; - public function __construct() + public function __construct($params) { $this->_ci =& get_instance(); + + if (isset($params['uid']) && !isEmptyString($params['uid'])){ + $this->_uid = $params['uid']; + } else { + show_error('uid of logged user not passed!'); + } + $this->_ci->load->model('ressource/Kalender_model', 'KalenderModel'); - $this->_ci->load->library('VariableLib', array('uid' => getAuthUID())); + $this->_ci->load->library('VariableLib', array('uid' => $this->_uid)); $this->_ci->load->library('PhrasesLib', array('ui')); } @@ -77,4 +85,4 @@ class RoomCollisionCheck implements ICollisionCheck return $grouped; } -} \ No newline at end of file +} diff --git a/application/libraries/collision/checks/StudentCollisionCheck.php b/application/libraries/collision/checks/StudentCollisionCheck.php index 4ffeb071e..96a62b237 100644 --- a/application/libraries/collision/checks/StudentCollisionCheck.php +++ b/application/libraries/collision/checks/StudentCollisionCheck.php @@ -3,12 +3,20 @@ class StudentCollisionCheck implements ICollisionCheck { private $_ci; + private $_uid; - public function __construct() + public function __construct($params) { $this->_ci =& get_instance(); + + if (isset($params['uid']) && !isEmptyString($params['uid'])){ + $this->_uid = $params['uid']; + } else { + show_error('uid of logged user not passed!'); + } + $this->_ci->load->model('ressource/Kalender_model', 'KalenderModel'); - $this->_ci->load->library('VariableLib', array('uid' => getAuthUID())); + $this->_ci->load->library('VariableLib', array('uid' => $this->_uid)); $this->_ci->load->library('PhrasesLib', array('ui')); } @@ -244,4 +252,4 @@ class StudentCollisionCheck implements ICollisionCheck return $grouped; } -} \ No newline at end of file +} diff --git a/application/libraries/collision/checks/VerbandCollisionCheck.php b/application/libraries/collision/checks/VerbandCollisionCheck.php index 40baf38a2..9284312b5 100644 --- a/application/libraries/collision/checks/VerbandCollisionCheck.php +++ b/application/libraries/collision/checks/VerbandCollisionCheck.php @@ -4,12 +4,20 @@ class VerbandCollisionCheck implements ICollisionCheck { private $_ci; + private $_uid; - public function __construct() + public function __construct($params) { $this->_ci =& get_instance(); + + if (isset($params['uid']) && !isEmptyString($params['uid'])){ + $this->_uid = $params['uid']; + } else { + show_error('uid of logged user not passed!'); + } + $this->_ci->load->model('ressource/Kalender_model', 'KalenderModel'); - $this->_ci->load->library('VariableLib', array('uid' => getAuthUID())); + $this->_ci->load->library('VariableLib', array('uid' => $this->_uid)); $this->_ci->load->library('PhrasesLib', array('ui')); } @@ -359,4 +367,4 @@ class VerbandCollisionCheck implements ICollisionCheck return $grouped; } -} \ No newline at end of file +} diff --git a/application/libraries/sabredav/SabreDAVAuthLib.php b/application/libraries/sabredav/SabreDAVAuthLib.php new file mode 100644 index 000000000..65b99e0c7 --- /dev/null +++ b/application/libraries/sabredav/SabreDAVAuthLib.php @@ -0,0 +1,38 @@ +_ci =& get_instance(); + + $this->_ci->load->library('AuthLib', array(false)); + $this->_ci->load->helper('hlp_authentication'); + } + + public function getCurrentUser() + { + if ($this->currentUser) + return $this->currentUser; + + if (isLogged()) + return getAuthUID(); + + return null; + } + + protected function validateUserPass($username, $password) + { + if (isSuccess($this->_ci->authlib->checkUserAuthByUsernamePassword($username, $password))) + { + $this->currentUser = $username; + return true; + } + + $this->currentUser = null; + return false; + } +} \ No newline at end of file diff --git a/application/libraries/sabredav/SabreDAVCalDAVLib.php b/application/libraries/sabredav/SabreDAVCalDAVLib.php new file mode 100644 index 000000000..e79f8a6e6 --- /dev/null +++ b/application/libraries/sabredav/SabreDAVCalDAVLib.php @@ -0,0 +1,971 @@ +auth = $auth; + + /* + $ma = new mitarbeiter(); + $this->result_ma = $ma->getMitarbeiter(null,null,null); + */ + } + + /** + * Liefert den eingeloggten User + */ + function getUser() + { + return $this->auth->getCurrentUser(); + } + + + /** + * Returns a list of principals based on a prefix. + * + * This prefix will often contain something like 'principals'. You are only + * expected to return principals that are in this base path. + * + * You are expected to return at least a 'uri' for every user, you can + * return any additional properties if you wish so. Common properties are: + * {DAV:}displayname + * {http://sabredav.org/ns}email-address - This is a custom SabreDAV + * field that's actualy injected in a number of other properties. If + * you have an email address, use this property. + * + * @param string $prefixPath + * @return array + */ + public function getPrincipalsByPrefix($prefixPath) + { + //$prefixPath = principals + //error_log('Principal.php/getPrincipalsByPrefix('.$prefixPath.')'); + $principals = array(); + $user = $this->getUser(); + + if($prefixPath=='principals') + { + + $principals[] = array( + 'id' => $user, + 'uri' => 'principals/'.$user, + '{DAV:}displayname' => $user, + '{http://sabredav.org/ns}email-address' => $user.'@example.com', + ); + } + + return $principals; + + } + + /** + * Returns a specific principal, specified by it's path. + * The returned structure should be the exact same as from + * getPrincipalsByPrefix. + * + * @param string $path + * @return array + */ + public function getPrincipalByPath($path) + { + $user = mb_substr($path,11); + + $result = array( + 'id' => $user, + 'uri' => 'principals/'.$user, + '{DAV:}displayname' => $user, + '{http://sabredav.org/ns}email-address' => $user.'@example.com', + ); + + return $result; + } + + /** + * Returns the list of members for a group-principal + * + * @param string $principal + * @return array + */ + public function getGroupMemberSet($principal) + { + $result = array(); + + return $result; + } + + /** + * Returns the list of groups a principal is a member of + * + * @param string $principal + * @return array + */ + public function getGroupMembership($principal) + { + $result = array(); + if(preg_match('/^principals\/[0-9A-Za-z\-]*$/',$principal)) + { + $user = mb_substr($principal,11); + } + return $result; + + } + + /** + * Updates the list of group members for a group principal. + * + * The principals should be passed as a list of uri's. + * + * @param string $principal + * @param array $members + * @return void + */ + public function setGroupMemberSet($principal, array $members) + { + throw new \Sabre\DAV\Exception('Not implemented'); + } + + public function updatePrincipal($path, \Sabre\DAV\PropPatch $propPatch) + { + $propPatch->setRemainingResultCode(403); + } + + public function searchPrincipals($prefixPath, array $searchProperties, $test = 'allof') + { + return array(); + } + + public function findByUri($uri, $principalPrefix) + { + return null; + } +} + +/** + * CalDAV backend + */ +class SabreDAVCalDAVBackendLib extends \Sabre\CalDAV\Backend\AbstractBackend +{ + protected $auth; + + protected $CI; + + /** + * Creates the backend + * + * @param AuthBackend $auth + */ + public function __construct($auth) + { + $this->auth = $auth; + + $this->CI =& get_instance(); + } + + /** + * Liefert den eingeloggten User + */ + function getUser() + { + return $this->auth->getCurrentUser(); + } + + /** + * Returns a list of calendars for a principal. + * + * Every project is an array with the following keys: + * * id, a unique id that will be used by other functions to modify the + * calendar. This can be the same as the uri or a database key. + * * uri, which the basename of the uri with which the calendar is + * accessed. + * * principalUri. The owner of the calendar. Almost always the same as + * principalUri passed to this method. + * + * Furthermore it can contain webdav properties in clark notation. A very + * common one is '{DAV:}displayname'. + * + * @param string $principalUri + * @return array + */ + public function getCalendarsForUser($principalUri) + { + $user = mb_substr($principalUri,11); + $calendars = array(); + $calendar = array( + 'id' => $user, + 'uri' => 'LVPlan-'.$user, + 'principaluri' => 'principals/'.$user, + '{' . \Sabre\CalDAV\Plugin::NS_CALENDARSERVER . '}getctag' => $this->buildCalendarCtag($user), + '{' . \Sabre\CalDAV\Plugin::NS_CALDAV . '}supported-calendar-component-set' => new \Sabre\CalDAV\Xml\Property\SupportedCalendarComponentSet(array('VEVENT')), + '{DAV:}displayname' => 'LVPlan', + '{urn:ietf:params:xml:ns:caldav}calendar-description' => 'description comes here', + '{urn:ietf:params:xml:ns:caldav}calendar-timezone' => 'Europe/Vienna', + '{http://apple.com/ns/ical/}calendar-order' => '1', + '{http://apple.com/ns/ical/}calendar-color' => '#FF0000', + '{http://sabredav.org/ns}read-only' => 1 + ); + $calendars[] = $calendar; + + return $calendars; + } + + /** + * Creates a new calendar for a principal. + * + * If the creation was a success, an id must be returned that can be used to reference + * this calendar in other methods, such as updateCalendar + * + * @param string $principalUri + * @param string $calendarUri + * @param array $properties + */ + public function createCalendar($principalUri,$calendarUri, array $properties) + { + return $calendarUri; + } + + /** + * Updates properties for a calendar. + * + * The mutations array uses the propertyName in clark-notation as key, + * and the array value for the property value. In the case a property + * should be deleted, the property value will be null. + * + * This method must be atomic. If one property cannot be changed, the + * entire operation must fail. + * + * If the operation was successful, true can be returned. + * If the operation failed, false can be returned. + * + * Deletion of a non-existant property is always succesful. + * + * Lastly, it is optional to return detailed information about any + * failures. In this case an array should be returned with the following + * structure: + * + * array( + * 403 => array( + * '{DAV:}displayname' => null, + * ), + * 424 => array( + * '{DAV:}owner' => null, + * ) + * ) + * + * In this example it was forbidden to update {DAV:}displayname. + * (403 Forbidden), which in turn also caused {DAV:}owner to fail + * (424 Failed Dependency) because the request needs to be atomic. + * + * @param string $calendarId + * @param array $mutations + * @return bool|array + */ + public function updateCalendar($calendarId, \Sabre\DAV\PropPatch $propPatch) + { + $propPatch->setRemainingResultCode(200); + } + + /** + * Delete a calendar and all it's objects + * + * @param string $calendarId + * @return void + */ + public function deleteCalendar($calendarId) + { + return null; + } + + + public function getCalendarData($userUID, $objectUri=null) + { + $this->CI->load->model("ressource/Mitarbeiter_model", "MitarbeiterModel"); + $this->CI->load->model("person/Benutzer_model", "BenutzerModel"); + + $user = $this->CI->BenutzerModel->loadWhere(array("uid" => $userUID)); + if(!$user) + die('User invalid'); + + $this->CI->load->library('KalenderLib', ['uid' => $userUID]); + + $isUserEmployeeResult = $this->CI->MitarbeiterModel->isMitarbeiter($userUID); + if (isError($isUserEmployeeResult)) { + return; + } + $isUserEmployee = getData($isUserEmployeeResult); + + $startDate = date('Y-m-d', mktime(0,0,0,date('m'),date('d')-14,date('Y'))); + $endDate = date('Y-m-d', mktime(0,0,0,date('m')+6,date('d'),date('Y'))); + + $data = []; + + if ($isUserEmployee) { + $data = $this->CI->kalenderlib->getPlanForLecturerByLecturer($startDate, $endDate, $userUID); + } else { + $data = $this->CI->kalenderlib->getPlanForStudentByStudent($startDate, $endDate, $userUID); + } + + if(!is_array($data)) + $data = array(); + + foreach($data as $item) + { + $item->calendarDataFragment = $this->buildCalendarDataFragment($item); + } + + if (is_null($objectUri)) + { + return $data; + } + + $normalizedObjectUri = $this->normalizeObjectUri($objectUri); + foreach($data as $row) + { + if(md5($row->eindeutige_gruppen_id) == $normalizedObjectUri) + { + return $row; + } + } + + return null; + } + + public function makeCal($event) + { + return $this->buildICalLine('BEGIN', 'VCALENDAR') + .$this->buildICalLine('VERSION', '2.0') + .$this->buildICalTextLine('PRODID', 'FH Technikum Wien') + .$this->buildICalLine('BEGIN', 'VTIMEZONE') + .$this->buildICalLine('TZID', 'Europe/Vienna') + .$this->buildICalLine('BEGIN', 'DAYLIGHT') + .$this->buildICalLine('TZOFFSETFROM', '+0100') + .$this->buildICalLine('RRULE', 'FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU') + .$this->buildICalLine('DTSTART', '19810329T020000') + .$this->buildICalLine('TZNAME', 'GMT+02:00') + .$this->buildICalLine('TZOFFSETTO', '+0200') + .$this->buildICalLine('END', 'DAYLIGHT') + .$this->buildICalLine('BEGIN', 'STANDARD') + .$this->buildICalLine('TZOFFSETFROM', '+0200') + .$this->buildICalLine('RRULE', 'FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU') + .$this->buildICalLine('DTSTART', '19961027T030000') + .$this->buildICalLine('TZNAME', 'GMT+01:00') + .$this->buildICalLine('TZOFFSETTO', '+0100') + .$this->buildICalLine('END', 'STANDARD') + .$this->buildICalLine('END', 'VTIMEZONE') + .$event + .$this->buildICalLine('END', 'VCALENDAR'); + } + + protected function buildCalendarDataFragment($item) + { + $summary = $item->type == 'reservierung' ? $item->titel : $item->topic; + + $description = ""; + if ($item->type == 'reservierung') { + $description = $item->beschreibung; + } else { + $description = $item->lehrfach_bez . "\r\n"; + + if (isset($item->lektor) && is_array($item->lektor) && count($item->lektor) > 0) { + $description .= "Lehrer: " . join(", ", array_map(function($teacher) { return $teacher["kurzbz"]; }, $item->lektor)) . "\r\n"; + } + } + + $parsedStartDate = $this->formatICalLocalDateTime($item->isostart); + $parsedEndDate = $this->formatICalLocalDateTime($item->isoend); + $lastModified = $this->formatICalUtcDateTime(isset($item->updateamum) ? $item->updateamum : null); + $dtStamp = $lastModified ?: $this->formatICalUtcDateTime($item->isostart); + + if($dtStamp === null) + $dtStamp = '19700101T000000Z'; + + $fragment = $this->buildICalLine('BEGIN', 'VEVENT') + .$this->buildICalTextLine('UID', $item->eindeutige_gruppen_id) + .$this->buildICalLine('SEQUENCE', (int)$item->kalender_id) + .$this->buildICalTextLine('SUMMARY', $summary) + .$this->buildICalTextLine('DESCRIPTION', 'TODO') + .$this->buildICalTextLine('LOCATION', isset($item->ort_kurzbz) ? $item->ort_kurzbz : '') + .$this->buildICalTextLine('CATEGORIES', 'Stundenplans') + .$this->buildICalLine('DTSTART', $parsedStartDate, array('TZID' => 'Europe/Vienna')) + .$this->buildICalLine('DTEND', $parsedEndDate, array('TZID' => 'Europe/Vienna')); + + if($lastModified !== null) + $fragment .= $this->buildICalLine('LAST-MODIFIED', $lastModified); + + return $fragment + .$this->buildICalLine('DTSTAMP', $dtStamp) + .$this->buildICalLine('END', 'VEVENT'); + } + + protected function buildCalendarCtag($userUID) + { + $data = $this->getCalendarData($userUID); + if(!is_array($data)) + $data = array(); + + $fragments = array(); + foreach($data as $row) + { + $lastModified = isset($row->updateamum) ? $this->getLastModifiedTimestamp($row->updateamum) : null; + $calendarData = isset($row->calendarDataFragment) ? $this->makeCal($row->calendarDataFragment) : ''; + $fragments[] = $this->getObjectUri($row).':'.$lastModified.':'.md5($calendarData); + } + + sort($fragments, SORT_STRING); + return 'LVPlan-'.$userUID.'-'.md5(implode('|', $fragments)); + } + + protected function buildICalTextLine($name, $value, array $parameters = array()) + { + return $this->buildICalLine($name, $this->escapeICalText($value), $parameters); + } + + protected function buildICalLine($name, $value, array $parameters = array()) + { + $line = strtoupper($name); + + foreach($parameters as $parameterName => $parameterValue) + { + $parameterValues = is_array($parameterValue) ? $parameterValue : array($parameterValue); + $escapedValues = array(); + + foreach($parameterValues as $singleParameterValue) + $escapedValues[] = $this->escapeICalParameterValue($singleParameterValue); + + $line .= ';'.strtoupper($parameterName).'='.implode(',', $escapedValues); + } + + return $this->foldICalLine($line.':'.(string)$value); + } + + protected function foldICalLine($line) + { + $line = (string)$line; + $folded = ''; + + while(strlen($line) > 75) + { + $part = mb_strcut($line, 0, 75, 'UTF-8'); + $folded .= $part."\r\n"; + $line = ' '.mb_strcut($line, strlen($part), strlen($line) - strlen($part), 'UTF-8'); + } + + return $folded.$line."\r\n"; + } + + protected function escapeICalText($value) + { + $value = (string)$value; + $value = str_replace('\\', '\\\\', $value); + $value = str_replace(array("\r\n", "\r", "\n"), '\n', $value); + return str_replace(array(';', ','), array('\;', '\,'), $value); + } + + protected function escapeICalParameterValue($value) + { + $value = (string)$value; + $value = str_replace(array('\\', '"', "\r", "\n"), array('\\\\', '\"', '', ''), $value); + + if(preg_match('/[;:,]/', $value)) + return '"'.$value.'"'; + + return $value; + } + + protected function formatICalLocalDateTime($dateTime) + { + $dateTime = $this->createDateTime($dateTime); + if($dateTime === null) + return null; + + $dateTime->setTimezone(new DateTimeZone('Europe/Vienna')); + return $dateTime->format('Ymd\THis'); + } + + protected function formatICalUtcDateTime($dateTime) + { + $dateTime = $this->createDateTime($dateTime); + if($dateTime === null) + return null; + + $dateTime->setTimezone(new DateTimeZone('UTC')); + return $dateTime->format('Ymd\THis\Z'); + } + + protected function createDateTime($dateTime) + { + if($dateTime instanceof DateTime) + return clone $dateTime; + + if($dateTime === null || $dateTime === '') + return null; + + try + { + if(is_numeric($dateTime)) + return new DateTime('@'.(int)$dateTime); + + return new DateTime($dateTime); + } + catch(Exception $e) + { + return null; + } + } + + protected function getObjectUri($row) + { + return md5($row->eindeutige_gruppen_id).'.ics'; + } + + protected function normalizeObjectUri($objectUri) + { + $normalizedObjectUri = (string)$objectUri; + + if(substr($normalizedObjectUri, -4) === '.ics') + $normalizedObjectUri = substr($normalizedObjectUri, 0, -4); + + if(mb_strpos($normalizedObjectUri, '@') !== false) + $normalizedObjectUri = mb_substr($normalizedObjectUri, mb_strpos($normalizedObjectUri, '@') + 1); + + if($this->hasObjectUriDatePrefix($normalizedObjectUri)) + return mb_substr($normalizedObjectUri, mb_strpos($normalizedObjectUri, '-') + 1); + + return $normalizedObjectUri; + } + + protected function hasObjectUriDatePrefix($objectUri) + { + $hyphenPosition = mb_strpos($objectUri, '-'); + if($hyphenPosition !== 15) + return false; + + return preg_match('/^\d{8}T\d{6}$/', mb_substr($objectUri, 0, 15)) === 1; + } + + protected function buildCalendarObject($row, $calendarId) + { + $calendarData = $this->makeCal($row->calendarDataFragment); + + return array( + "id"=>$row->eindeutige_gruppen_id, + "calendardata"=>$calendarData, + "uri"=>$this->getObjectUri($row), + "lastmodified"=>$this->getLastModifiedTimestamp($row->updateamum), + "etag"=>'"'.md5($calendarData).'"', + "calendarid"=>$calendarId, + "size"=>strlen($calendarData), + "component"=>'vevent' + ); + } + + protected function getLastModifiedTimestamp($lastModified) + { + if($lastModified === null || $lastModified === '') + return null; + + if(is_numeric($lastModified)) + return (int)$lastModified; + + $timestamp = strtotime($lastModified); + if($timestamp === false) + return null; + + return $timestamp; + } + + /** + * Returns all calendar objects within a calendar. + * + * Every item contains an array with the following keys: + * * id - unique identifier which will be used for subsequent updates + * * calendardata - The iCalendar-compatible calnedar data + * * uri - a unique key which will be used to construct the uri. This can be any arbitrary string. + * * lastmodified - a timestamp of the last modification time + * * etag - An arbitrary string, surrounded by double-quotes. (e.g.: + * ' "abcdef"') + * * calendarid - The calendarid as it was passed to this function. + * + * Note that the etag is optional, but it's highly encouraged to return for + * speed reasons. + * + * The calendardata is also optional. If it's not returned + * 'getCalendarObject' will be called later, which *is* expected to return + * calendardata. + * + * @param string $calendarId + * @return array + */ + public function getCalendarObjects($calendarId) + { + //$user = $this->getUser(); + $user = $calendarId; + $data = $this->getCalendarData($user); + + //error_log("Caldav_Backend.php/getCalendarObjects($calendarId) "); + $return = array(); + + if(!is_array($data)) + return $return; + + foreach($data as $row) + { + $return[] = $this->buildCalendarObject($row, $calendarId); + } + return $return; + } + + /** + * Returns information from a single calendar object, based on it's object + * uri. + * + * The returned array must have the same keys as getCalendarObjects. The + * 'calendardata' object is required here though, while it's not required + * for getCalendarObjects. + * + * @param string $calendarId + * @param string $objectUri + * @return array + */ + public function getCalendarObject($calendarId,$objectUri) + { + $user = $calendarId; + $data = $this->getCalendarData($user,$objectUri); + + if(empty($data)) + { + return null; + } + elseif(is_object($data)) + { + $ret = $this->buildCalendarObject($data, $calendarId); + } + + return isset($ret) ? $ret : null; + } + + /** + * Creates a new calendar object. + * + * @param string $calendarId + * @param string $objectUri + * @param string $calendarData + * @return void + */ + public function createCalendarObject($calendarId,$objectUri,$calendarData) + { + return null; + } + + /** + * Updates an existing calendarobject, based on it's uri. + * + * @param string $calendarId + * @param string $objectUri + * @param string $calendarData + * @return void + */ + public function updateCalendarObject($calendarId,$objectUri,$calendarData) + { + if(is_resource($calendarData)) + $calendarData = stream_get_contents($calendarData); + + return '"'.md5((string)$calendarData).'"'; + } + + /** + * Deletes an existing calendar object. + * + * @param string $calendarId + * @param string $objectUri + * @return void + */ + public function deleteCalendarObject($calendarId,$objectUri) + { + return null; + } +} + +/** + * Read-only CalDAV node wrappers for DB-owned calendars. + */ +class SabreDAVReadOnlyACLLib +{ + public static function getAcl($principalUri, $includeFreeBusy = false) + { + $acl = array( + array( + 'privilege' => '{DAV:}read', + 'principal' => $principalUri, + 'protected' => true, + ), + array( + 'privilege' => '{DAV:}read', + 'principal' => $principalUri.'/calendar-proxy-read', + 'protected' => true, + ), + ); + + if($includeFreeBusy) + { + $acl[] = array( + 'privilege' => '{'.\Sabre\CalDAV\Plugin::NS_CALDAV.'}read-free-busy', + 'principal' => '{DAV:}authenticated', + 'protected' => true, + ); + } + + return $acl; + } + + public static function ignoreWrite() + { + return null; + } +} + +class SabreDAVReadOnlyCalendarRootLib extends \Sabre\CalDAV\CalendarRoot +{ + protected $readOnlyCaldavBackend; + + public function __construct(\Sabre\DAVACL\PrincipalBackend\BackendInterface $principalBackend, \Sabre\CalDAV\Backend\BackendInterface $caldavBackend, $principalPrefix = 'principals') + { + parent::__construct($principalBackend, $caldavBackend, $principalPrefix); + $this->readOnlyCaldavBackend = $caldavBackend; + } + + public function getChildForPrincipal(array $principal) + { + return new SabreDAVReadOnlyCalendarHomeLib($this->readOnlyCaldavBackend, $principal); + } +} + +class SabreDAVReadOnlyCalendarHomeLib extends \Sabre\CalDAV\CalendarHome +{ + protected $readOnlyCaldavBackend; + protected $readOnlyPrincipalInfo; + + public function __construct(\Sabre\CalDAV\Backend\BackendInterface $caldavBackend, $principalInfo) + { + parent::__construct($caldavBackend, $principalInfo); + $this->readOnlyCaldavBackend = $caldavBackend; + $this->readOnlyPrincipalInfo = $principalInfo; + } + + public function getChildren() + { + $calendars = $this->readOnlyCaldavBackend->getCalendarsForUser($this->readOnlyPrincipalInfo['uri']); + $objs = array(); + + foreach($calendars as $calendar) + { + $objs[] = new SabreDAVReadOnlyCalendarLib($this->readOnlyCaldavBackend, $calendar); + } + + return $objs; + } + + public function createExtendedCollection($name, \Sabre\DAV\MkCol $mkCol) + { + return SabreDAVReadOnlyACLLib::ignoreWrite(); + } + + public function createFile($filename, $data = null) + { + return SabreDAVReadOnlyACLLib::ignoreWrite(); + } + + public function createDirectory($filename) + { + return SabreDAVReadOnlyACLLib::ignoreWrite(); + } + + public function delete() + { + return SabreDAVReadOnlyACLLib::ignoreWrite(); + } + + public function setName($name) + { + return SabreDAVReadOnlyACLLib::ignoreWrite(); + } + + public function getACL() + { + return SabreDAVReadOnlyACLLib::getAcl($this->readOnlyPrincipalInfo['uri']); + } +} + +class SabreDAVReadOnlyCalendarLib extends \Sabre\CalDAV\Calendar +{ + protected $readOnlyCaldavBackend; + protected $readOnlyCalendarInfo; + + public function __construct(\Sabre\CalDAV\Backend\BackendInterface $caldavBackend, $calendarInfo) + { + parent::__construct($caldavBackend, $calendarInfo); + $this->readOnlyCaldavBackend = $caldavBackend; + $this->readOnlyCalendarInfo = $calendarInfo; + } + + public function getChild($name) + { + $obj = $this->readOnlyCaldavBackend->getCalendarObject($this->readOnlyCalendarInfo['id'], $name); + + if(!$obj) + throw new \Sabre\DAV\Exception\NotFound('Calendar object not found'); + + $obj['acl'] = $this->getCalendarObjectAcl(); + + return new SabreDAVReadOnlyCalendarObjectLib($this->readOnlyCaldavBackend, $this->readOnlyCalendarInfo, $obj); + } + + public function getChildren() + { + $objs = $this->readOnlyCaldavBackend->getCalendarObjects($this->readOnlyCalendarInfo['id']); + $children = array(); + + foreach($objs as $obj) + { + $obj['acl'] = $this->getCalendarObjectAcl(); + $children[] = new SabreDAVReadOnlyCalendarObjectLib($this->readOnlyCaldavBackend, $this->readOnlyCalendarInfo, $obj); + } + + return $children; + } + + public function createFile($name, $calendarData = null) + { + return SabreDAVReadOnlyACLLib::ignoreWrite(); + } + + public function createDirectory($name) + { + return SabreDAVReadOnlyACLLib::ignoreWrite(); + } + + public function delete() + { + return SabreDAVReadOnlyACLLib::ignoreWrite(); + } + + public function setName($newName) + { + return SabreDAVReadOnlyACLLib::ignoreWrite(); + } + + public function updateProperties($mutations) + { + return true; + } + + public function propPatch(\Sabre\DAV\PropPatch $propPatch) + { + $propPatch->setRemainingResultCode(200); + } + + public function getACL() + { + return SabreDAVReadOnlyACLLib::getAcl($this->getOwner(), true); + } + + protected function getCalendarObjectAcl() + { + return SabreDAVReadOnlyACLLib::getAcl($this->getOwner()); + } +} + +class SabreDAVReadOnlyCalendarObjectLib extends \Sabre\CalDAV\CalendarObject +{ + protected $readOnlyCalendarInfo; + + public function __construct(\Sabre\CalDAV\Backend\BackendInterface $caldavBackend, array $calendarInfo, array $objectData) + { + parent::__construct($caldavBackend, $calendarInfo, $objectData); + $this->readOnlyCalendarInfo = $calendarInfo; + } + + public function put($calendarData) + { + return $this->getETag(); + } + + public function getETag() + { + if(isset($_SERVER['REQUEST_METHOD']) && in_array($_SERVER['REQUEST_METHOD'], array('PUT', 'DELETE'), true)) + { + $ifMatch = isset($_SERVER['HTTP_IF_MATCH']) ? trim($_SERVER['HTTP_IF_MATCH']) : ''; + if($ifMatch !== '' && $ifMatch !== '*') + { + $requestedEtags = explode(',', $ifMatch); + foreach($requestedEtags as $requestedEtag) + { + $requestedEtag = trim($requestedEtag); + if($requestedEtag !== '') + return $requestedEtag; + } + } + } + + return parent::getETag(); + } + + public function delete() + { + return SabreDAVReadOnlyACLLib::ignoreWrite(); + } + + public function setName($name) + { + return SabreDAVReadOnlyACLLib::ignoreWrite(); + } + + public function getACL() + { + return SabreDAVReadOnlyACLLib::getAcl($this->readOnlyCalendarInfo['principaluri']); + } +}