Zugriffssteuerung über Sonderrechte (Gruppen-Verwaltung)
+ Achtung: Wenn eines der drei vom Raumbelegungsplan benutzten Sonderrechte keiner Gruppe
+ zugewiesen wird, besitzen alle Benutzer dieses Portalservers das entsprechende Sonderrecht!
+
Räume werden in der Rechnerverwaltung angelegt
+
Komplette Neuentwicklung des Quellcodes auf Basis von PHP 5
+
+
Alle Formulare werden innerhalb der Tabelle angezeigt, ebenso die
+ dazugehörigen Meldungen
+
Neu eingefügte Buchungen werden farblich markiert
+
Administrations-Seite zum Anlegen von periodischen Buchungen entfällt
+
+
+
Algorithmus zum Zeichnen der Buchungstabelle schlanker gemacht
Fehler bei Neuinstallation als RPM und anschlieÃender Konfiguration lieferte Warning: implode(): Bad arguments. in /opt/iserv/idesk/rooms/admin/config.php on line 168
Das Modul gibt sich bei einer Neukonfiguration im Log als Fehlermeldungmodul aus, bei Buchungen wurden falsche Räume angezeigt
+
Lizenztext auf Deutsch
+
Kosmetik
+
+
+
iserv-rooms-2.0-2
+Release: 28. August 2006
+
+
RPM repariert, die SQL-Tabellen wurden bei einem Update erst angelegt und dann wieder gelöscht
+
Admin-Bereich: Wochentage werden wieder angezeigt
+
+
+
iserv-rooms-2.0-1
+Release: 28. August 2006
+
+
Statistik hinzugefügt und damit Option „Abgelaufene Buchungen löschen“ repariert
+
SQL-Tabelle wird bei der Installation erstellt, nicht vom Konfigurations-Skript, dadurch Zugriffsprobleme beseitigt.
+
Modul ist nur von bestimmten Gruppen nutzbar, in Konfiguration einstellbar
+
Stundenplanansicht im Benutzerbereich
+
Lizenz: Donationware
+
Konfiguration wird bei Update nicht mehr überschrieben
+
Wochenende optional anschaltbar
+
+
+
+
diff --git a/img/16/mod_room-reservation_config.png b/img/16/mod_room-reservation_config.png
new file mode 100644
index 0000000..5b5261b
Binary files /dev/null and b/img/16/mod_room-reservation_config.png differ
diff --git a/img/16/mod_room-reservation_index.png b/img/16/mod_room-reservation_index.png
new file mode 100644
index 0000000..8d5b17b
Binary files /dev/null and b/img/16/mod_room-reservation_index.png differ
diff --git a/img/24/mod_room-reservation_timeslice.png b/img/24/mod_room-reservation_timeslice.png
new file mode 100755
index 0000000..ee35861
Binary files /dev/null and b/img/24/mod_room-reservation_timeslice.png differ
diff --git a/img/32/mod_room-reservation_config.png b/img/32/mod_room-reservation_config.png
new file mode 100644
index 0000000..ddaaeb0
Binary files /dev/null and b/img/32/mod_room-reservation_config.png differ
diff --git a/img/32/mod_room-reservation_index.png b/img/32/mod_room-reservation_index.png
new file mode 100644
index 0000000..ccb3211
Binary files /dev/null and b/img/32/mod_room-reservation_index.png differ
diff --git a/includes/config.inc b/includes/config.inc
new file mode 100755
index 0000000..8ae6f37
--- /dev/null
+++ b/includes/config.inc
@@ -0,0 +1,15 @@
+flushTimeslices();
+$this->addTimeslice(new mod_roomReservationTimeslice(25200, 30600));
+$this->addTimeslice(new mod_roomReservationTimeslice(32400, 37800));
+$this->addTimeslice(new mod_roomReservationTimeslice(39600, 45000));
+$this->addTimeslice(new mod_roomReservationTimeslice(50400, 55800));
+$this->addTimeslice(new mod_roomReservationTimeslice(57600, 63000));
+$this->addTimeslice(new mod_roomReservationTimeslice(64800, 70200));
+$this->setShowWeekend(true);
+$this->setShowLessons(false);
+?>
\ No newline at end of file
diff --git a/includes/exceptions.inc b/includes/exceptions.inc
new file mode 100755
index 0000000..8d7c688
--- /dev/null
+++ b/includes/exceptions.inc
@@ -0,0 +1,44 @@
+
\ No newline at end of file
diff --git a/includes/functions.inc b/includes/functions.inc
new file mode 100755
index 0000000..1704bc5
--- /dev/null
+++ b/includes/functions.inc
@@ -0,0 +1,276 @@
+ 0);
+}
+
+/**
+ * Get the real user name for an account name
+ * @param $strAct (string) Account name of the user to look up
+ * @return (string) The real name of the user. If the function fails, it returns null.
+ * Call getLastError() to get more information about the error.
+ */
+function getRealUserName($strAct) {
+ $hQuery = db_query("SELECT firstname, lastname FROM users WHERE act = $1;", $strAct);
+ if(!is_resource($hQuery)) {
+ // TODO throw exception
+ setLastError(RS_ERROR_SQL);
+ return null;
+ }
+ if(pg_num_rows($hQuery) == 0) {
+ return $strAct; // User not found in database, return account name
+ }
+ $arResult = pg_fetch_array($hQuery);
+ return user_join_name($arResult);
+}
+
+/**
+ * Determine if a specified group exists
+ * @param $strAct (string) Account name of the group
+ * @return (bool / null) If the function fails, it returns null. Call getLastError() to
+ * get more information about the error.
+ */
+function isGroup($strAct) {
+ $hQuery = db_query("SELECT * FROM groups WHERE act = $1;", $strAct);
+ if(!is_resource($hQuery)) {
+ // TODO throw exception
+ setLastError(RS_ERROR_SQL);
+ return null;
+ }
+ return (pg_num_rows($hQuery) > 0);
+}
+
+/**
+ * Look up the name of a group
+ * @param $strAct (string) Account name of the group
+ * @return (string) The name of the group. If the function fails, it returns null.
+ * Call getLastError() to get more information about the error.
+ */
+function getGroupName($strAct) {
+ $hQuery = db_query("SELECT * FROM groups WHERE act = $1;", $strAct);
+ if(!is_resource($hQuery)) {
+ // TODO throw exception
+ setLastError(RS_ERROR_SQL);
+ return null;
+ }
+ if(pg_num_rows($hQuery) == 0) {
+ return $strAct; // Group not found in database, return account name
+ }
+ $arResult = pg_fetch_array($hQuery);
+ return $arResult["name"];
+}
+
+/**
+ * Create a link to write a mail to the specified account name.
+ * This function returns a link if the specified account exists, otherwise it returns the
+ * account name.
+ * @param $strAct (string) Account name
+ * @param $strColor (string) Background color for icon()
+ * @param $strParams (string) additional URL parameters
+ * @return string
+ */
+function mailToUserLink($strAct, $strColor = "bl", $strParams = "") {
+ if(!isAct($strAct)) {
+ return $strAct;
+ }
+ return popup(relroot("msg/write/?to=".user_mail_addr($strAct).$strParams),
+ 600, 400, nobr(icon("mail-reply-usr", array("size" => 16, "bg" =>
+ $strColor)) . getRealUserName($strAct)));
+}
+
+/**
+ * Determine if a specified string is a valid mail address
+ * @param $strAddr string
+ * @return string
+ */
+function isMailAddress($strAddr) {
+ return ((preg_match("/([a-zA-Z0-9_\-\.]*(@[a-zA-Z0-9\-\.]*)?(\s*,\s*)?)+/", $strAddr) > 0)
+ and (preg_match("/(\s*,\s*)$/", $strAddr) == 0));
+}
+
+/**
+ * Module-specific logging function.
+ * Prefixes the log message with a module-specific string and writes it to the logs.
+ * @param $strLog (string) Log message
+ * @return void
+ */
+function rrInsertLog($strLog) {
+ log_insert("Raumbelegungsplan: " . $strLog);
+}
+
+/**
+ * Get the SQL day number from a given timestamp.
+ * @param $ts (timestamp)
+ * @return (int) 0-6 for Sunday to Monday
+ */
+function rrDateToSQLDayNumber($ts) {
+ $aDays = array("Sun" => 0, "Mon" => 1, "Tue" => 2,
+ "Wed" => 3, "Thu" => 4, "Fri" => 5, "Sat" => 6);
+ return $aDays[date("D", $ts)];
+}
+
+/**
+ * Convert a UNIX timestamp to an SQL date string
+ * @param $ts (timestamp)
+ * @return string
+ */
+function dateToSql($ts) { return date("Y\-m\-d", intval($ts)); }
+
+/**
+ * Calculate the timestamp of the monday in the current week
+ * @param $ts (timestamp) Calculate the value relative to this date
+ * @return timestamp
+ */
+function rrGetMonday($ts = null) {
+ if($ts === null) {
+ $ts = time();
+ }
+ if(date("D", $ts) == "Mon") {
+ // Today is monday
+ return strtotime("00:00", $ts);
+ } else {
+ return strtotime("last monday", $ts);
+ }
+}
+
+/** (array of strings) Additional CSS rules */
+$rsLocalCss = array();
+
+/**
+ * Add CSS rules to the page
+ * @param $s (string)
+ * @return void
+ */
+function rrAddCss($s) {
+ rrDebug("rsAddCss: add \"$s\"");
+ $GLOBALS["rsLocalCss"][] = $s;
+}
+
+/**
+ * Get CSS rules that have been added with rmAddCss()
+ * @return string
+ */
+function rrGetCSS() {
+ rrDebug("rsGetCss: Local CSS is ".var_export($GLOBALS["rsLocalCss"], true));
+ return implode("\n", $GLOBALS["rsLocalCss"]);
+}
+
+function rrDebug($s, $bReturn = false) {
+ if(isset($_GET["debug"])) {
+ if(!$bReturn) {
+ echo "\n";
+ } else {
+ return $s;
+ }
+ }
+}
+
+/**
+ * sprintf with support for ordinal numbers.
+ * This version of sprintf replaces all substrings of the type /\\d+#/
+ * (i.e. a decimal number with a hash sign appended) in the input string with
+ * the corresponding english ordinal number prefices (st, nd, rd, th).
+ * @param $str (string) Input string
+ * @param $args (mixed) Additional parameters to be passed to sprintf()
+ * @return (string)
+ */
+function _sprintf_ord($str, $args /*leave this parameters for doxygen*/) {
+ $args = func_get_args();
+ if(preg_match_all("/%[bcdufosxX]/", $args[0], $temp) != func_num_args()-1) {
+ trigger_error("Too few arguments", E_USER_ERROR);
+ return false;
+ }
+ $str = call_user_func_array("sprintf", $args);
+ while(preg_match("/(.*)(\d+)#(.*)/", $str, $m))
+ $str = $m[1]._(append_ord_suffix($m[2])).$m[3];
+ return $str;
+}
+?>
diff --git a/includes/globals.inc b/includes/globals.inc
new file mode 100755
index 0000000..067ab4c
--- /dev/null
+++ b/includes/globals.inc
@@ -0,0 +1,47 @@
+
diff --git a/includes/mod_roomReservationBooking.inc b/includes/mod_roomReservationBooking.inc
new file mode 100755
index 0000000..a6a1c8a
--- /dev/null
+++ b/includes/mod_roomReservationBooking.inc
@@ -0,0 +1,201 @@
+setUid(null);
+ $this->setRoom($strRoom);
+ $this->setDate($tsDate);
+ $this->setTsFirst($nTsFirst);
+ $this->setTsLast($nTsLast);
+ $this->setAct($strAct);
+ $this->setReason($strReason);
+ $this->setInterval($nInterval);
+ }
+
+ /***************************************************************************/
+ /**
+ * @}
+ * @name Access to attributes
+ * @{
+ */
+
+ /**
+ * Set the unique ID in database
+ * @param $n (int) Unique ID in database
+ * @return void
+ */
+ public function setUid($n) {
+ if(is_null($n)) {
+ $this->nUid = null;
+ } else {
+ $this->nUid = intval($n);
+ }
+ }
+
+ /**
+ * Set the name of the room
+ * @param $str (string) Name of the room
+ * @return void
+ */
+ public function setRoom($str) { $this->strRoom = $str; }
+
+ /**
+ * Set the date when the booking takes place
+ * @param $ts (timestamp) Date, only the date part is taken care of
+ * @return void
+ */
+ public function setDate($ts) {
+ // Only take the date part
+ $this->tsDate = intval(strtotime(date("Y\-m\-d", intval($ts)))); }
+
+ /**
+ * Set the first timeslice
+ * @param $n (int) Number of the first timeslice
+ * @return void
+ */
+ public function setTsFirst($n) { $this->nTsFirst = intval($n); }
+
+ /**
+ * Set the end timeslice
+ * @param $n (int) Number of the last timeslice (may be the start timeslice)
+ * @return void
+ */
+ public function setTsLast($n) { $this->nTsLast = intval($n); }
+
+ /**
+ * Set the account name of the owner
+ * @param $str (string) Account name
+ * @return void
+ */
+ public function setAct($str) { $this->strAct = $str; }
+
+ /**
+ * Set the reason for the booking
+ * @param $str (string) Reason
+ * @return void
+ */
+ public function setReason($str) { $this->strReason = $str; }
+
+ /**
+ * Set the flag whether the booking repeates every week
+ * @param $n (int) interval in weeks, 0 for no recurrence
+ * @return void
+ */
+ public function setInterval($n) { $this->nInterval = intval(abs($n)); }
+
+ /**
+ * Get the unique ID in database
+ * @return int / null
+ */
+ public function getUid() { return intval($this->nUid); }
+
+ /**
+ * Get the name of the room
+ * @return string
+ */
+ public function getRoom() { return $this->strRoom; }
+
+ /**
+ * Get the date when the booking takes place
+ * @return timestamp
+ */
+ public function getDate() { return intval($this->tsDate); }
+
+ /**
+ * Get the the number of the first timeslice
+ * @return int
+ */
+ public function getTsFirst() { return intval($this->nTsFirst); }
+
+ /**
+ * Get the number of the last timeslice (may be the start timeslice)
+ * @return int
+ */
+ public function getTsLast() { return intval($this->nTsLast); }
+
+ /**
+ * Get the account name of the owner
+ * @return string
+ */
+ public function getAct() { return $this->strAct; }
+
+ /**
+ * Get the reason for the booking
+ * @return string
+ */
+ public function getReason() { return $this->strReason; }
+
+ /**
+ * Get the recurrence interval
+ * @return int
+ */
+ public function getInterval() { return $this->nInterval; }
+
+ /**@}*/
+}
+?>
diff --git a/includes/mod_roomReservationBookingPage.inc b/includes/mod_roomReservationBookingPage.inc
new file mode 100755
index 0000000..f01423c
--- /dev/null
+++ b/includes/mod_roomReservationBookingPage.inc
@@ -0,0 +1,212 @@
+oCfg = $oCfg;
+ $this->oRm = $oRm;
+ $this->oBm = $oBm;
+
+ // create the booking table here, so the CSS is already added
+ /** @todo maybe move it into beforeAddCSS()... ? */
+ $this->oBt = new mod_roomReservationBookingsTable($this->oCfg, $this->oRm,
+ $this->oBm, "?bookingpage[action]=edit", "?bookingpage[action]=delete");
+
+ parent::__construct($oCfg);
+ $this->setTitle(_c("Room Reservation Schedule"));
+ $this->setIcon("mod_room-reservation_index");
+ }
+
+ /***************************************************************************/
+ /**
+ * @}
+ * @name Initialization
+ * @{
+ */
+
+ /**
+ * Process the REQUEST variables and preset the some variables
+ * @return void
+ */
+ protected function processRequestVariables() {
+ // take all settings from the booking table
+ $this->setRoom($this->oBt->getRoom());
+ $this->setStart($this->oBt->getDate());
+ }
+
+ /***************************************************************************/
+ /**
+ * @}
+ * @name Access to attributes
+ * @{
+ */
+
+ /**
+ * Set the starting date
+ * @param $ts (timestamp)
+ */
+ public function setStart($ts) { $this->tsStart = intval($ts); }
+
+ /**
+ * Set the room to show in the booking table
+ * @param $str (string) Name of the room
+ */
+ public function setRoom($str) { $this->strRoom = $str; }
+
+ /**
+ * Get the starting date
+ * @return int
+ */
+ public function getStart() { return intval($this->tsStart); }
+
+ /**
+ * Get the name of the room to show in the booking table
+ * @return string
+ */
+ public function getRoom() { return $this->strRoom; }
+
+ /***************************************************************************/
+ /**
+ * @}
+ * @name Output
+ * @{
+ */
+
+ /**
+ * Show the page.
+ * @return void
+ */
+ public function doShow() {
+ // Protect access
+ if(!$this->oCfg->userCanView()) {
+ echo sprintf("
\n";
+
+ $this->oBt->show();
+
+ parent::endShow();
+ }
+}
+?>
diff --git a/includes/mod_roomReservationBookingTable.inc b/includes/mod_roomReservationBookingTable.inc
new file mode 100755
index 0000000..c325d88
--- /dev/null
+++ b/includes/mod_roomReservationBookingTable.inc
@@ -0,0 +1,766 @@
+oCfg = $oCfg;
+ $this->oRm = $oRm;
+ $this->oBm = $oBm;
+
+ $this->processRequestVariables();
+ $this->addCSS();
+ }
+
+ /***************************************************************************/
+ /**
+ * @}
+ * @name Initialization
+ * @{
+ */
+
+ /**
+ * Process the REQUEST variables and preset the some variables
+ * @return void
+ */
+ protected function processRequestVariables() {
+
+ ########################
+ # FIXME remove this
+ var_export($_GET); echo "";
+ var_export($_POST); echo "";
+ ########################
+
+ // default values
+ $aoRooms = $this->oRm->getRooms();
+ if($aoRooms != array()) {
+ $or = $aoRooms[0];
+ $this->setRoom($or->getName());
+ }
+ $this->setDate(time());
+ $this->setAction(MOD_ROOM_RESERVATION_BT_ACTION_SHOW);
+ $this->nPostInterval = 0;
+
+ // handle GET parameters
+ if(isset($_GET["mod_roomReservationBookingTable"])) {
+ $ga = isset($_GET["mod_roomReservationBookingTable"]["action"]) ?
+ $_GET["mod_roomReservationBookingTable"]["action"] : "";
+ $this->setAction(($ga == "book") ?
+ MOD_ROOM_RESERVATION_BT_ACTION_BOOK : (($ga == "edit") ?
+ MOD_ROOM_RESERVATION_BT_ACTION_EDIT : (($ga == "delete") ?
+ MOD_ROOM_RESERVATION_BT_ACTION_DELETE : (($ga == "submit") ?
+ MOD_ROOM_RESERVATION_BT_ACTION_SUBMIT : (($ga == "submitdelete") ?
+ MOD_ROOM_RESERVATION_BT_ACTION_SUBMITDELETE :
+ MOD_ROOM_RESERVATION_BT_ACTION_SHOW)))));
+ $this->setDate(isset($_GET["mod_roomReservationBookingTable"]["date"]) ?
+ intval($_GET["mod_roomReservationBookingTable"]["date"]) : time());
+ $this->setRoom(isset($_GET["mod_roomReservationBookingTable"]["room"]) ?
+ $_GET["mod_roomReservationBookingTable"]["room"] : "");
+ $this->setTsFirst(
+ isset($_GET["mod_roomReservationBookingTable"]["tsfirst"]) ?
+ intval($_GET["mod_roomReservationBookingTable"]["tsfirst"]) : 0);
+ $this->setTsLast($this->getTsFirst());
+
+ // if deletion form is requested, set the right date, room etc.
+ if($this->getAction() == MOD_ROOM_RESERVATION_BT_ACTION_DELETE) {
+ if(isset($_GET["mod_roomReservationBookingTable"]["uid"]) &&
+ $_GET["mod_roomReservationBookingTable"]["uid"] >= 0) {
+ $this->setUid(intval(
+ $_GET["mod_roomReservationBookingTable"]["uid"]));
+ } else {
+ trigger_error("The UID is invalid.", E_USER_ERROR);
+ }
+ $ob = mod_roomReservationBookingsManager::getBookingByUid(
+ $this->getUid());
+ $this->setRoom($ob->getRoom());
+ if($ob->getInterval() > 0) {
+ // don't show the first date when the booking was created, but the
+ // date of the page where the user clicked the delete button
+ $this->setDate(
+ isset($_GET["mod_roomReservationBookingTable"]["date"]) ?
+ intval($_GET["mod_roomReservationBookingTable"]["date"]) : time());
+ } else {
+ $this->setDate($ob->getDate());
+ }
+ $this->setTsFirst($ob->getTsFirst());
+ }
+ }
+
+ if(isset($_POST["mod_roomReservationBookingTable"])) {
+ if(isset($_POST["mod_roomReservationBookingTable"]["submitbooking"])) {
+ // submission of the booking form
+ // let POST variables overwrite the variables
+ $this->setDate(
+ isset($_POST["mod_roomReservationBookingTable"]["date"]) ?
+ intval($_POST["mod_roomReservationBookingTable"]["date"]) : time());
+ $this->setRoom(
+ isset($_POST["mod_roomReservationBookingTable"]["room"]) ?
+ $_POST["mod_roomReservationBookingTable"]["room"] : "");
+ $this->setTsFirst(
+ isset($_POST["mod_roomReservationBookingTable"]["tsfirst"]) ?
+ intval($_POST["mod_roomReservationBookingTable"]["tsfirst"]) : 0);
+ $this->setTsLast(
+ isset($_POST["mod_roomReservationBookingTable"]["tslast"]) ?
+ intval($_POST["mod_roomReservationBookingTable"]["tslast"]) :
+ $this->getTsFirst());
+ $this->setReason(
+ isset($_POST["mod_roomReservationBookingTable"]["reason"]) ?
+ $_POST["mod_roomReservationBookingTable"]["reason"] : "");
+ $this->nPostInterval =
+ isset($_POST["mod_roomReservationBookingTable"]["interval"]) ?
+ intval($_POST["mod_roomReservationBookingTable"]["interval"]) : 0;
+ $this->strPostAccount =
+ isset($_POST["mod_roomReservationBookingTable"]["account"]) ?
+ $_POST["mod_roomReservationBookingTable"]["account"] : "";
+ }
+
+ if(isset($_POST["mod_roomReservationBookingTable"]["submitdelete"])) {
+ // submission of the deletion form
+ if(isset($_POST["mod_roomReservationBookingTable"]["uid"]) &&
+ $_POST["mod_roomReservationBookingTable"]["uid"] >= 0) {
+ $this->setUid(
+ intval($_POST["mod_roomReservationBookingTable"]["uid"]));
+ } else {
+ trigger_error("The UID is invalid.", E_USER_ERROR);
+ }
+ // set the right date, room etc.
+ $ob = mod_roomReservationBookingsManager::getBookingByUid(
+ $this->getUid());
+ $this->setRoom($ob->getRoom());
+ $this->setDate($ob->getDate());
+ $this->setTsFirst($ob->getTsFirst());
+ $this->setSubmitButtonValue(isset(
+ $_POST["mod_roomReservationBookingTable"]["submitdelete"]) ?
+ $_POST["mod_roomReservationBookingTable"]["submitdelete"] : "");
+ }
+ }
+
+ ################
+ /** FIXME remove this */
+ echo sprintf("date: %s ", $this->getDate());
+ echo sprintf("room: %s ", $this->getRoom());
+ echo sprintf("reason: %s ", $this->getReason());
+ echo sprintf("tsfirst: %s ", $this->getTsFirst());
+ echo sprintf("tslast: %s ", $this->getTsLast());
+ echo sprintf("action: %s ", $this->getAction());
+ ################
+ }
+
+ /***************************************************************************/
+ /**
+ * @}
+ * @name Access to attributes
+ * @{
+ */
+
+ /**
+ * Set the action that should be done
+ * @param $c (constant) See @ref bookingtable_actions for possible values
+ */
+ protected function setAction($c) { $this->cAction = intval($c); }
+
+ /**
+ * Set the starting timeslice of the requested booking
+ * @param $n (int)
+ */
+ protected function setTsFirst($n) { $this->nTsFirst = intval($n); }
+
+ /**
+ * Set the ending timeslice of the requested booking
+ * @param $n (int)
+ */
+ protected function setTsLast($n) { $this->nTsLast = intval($n); }
+
+ /**
+ * Set the date of the requested booking or the date to be shown in the
+ * booking table
+ * @param $ts (timestamp)
+ */
+ public function setDate($ts) { $this->tsDate = intval($ts); }
+
+ /**
+ * Set the room of the requested booking or the room to be shown in the
+ * booking table
+ * @param $str (string)
+ */
+ protected function setRoom($str) { $this->strRoom = $str; }
+
+ /**
+ * Set the reason of the requested booking
+ * @param $str (string)
+ */
+ protected function setReason($str) { $this->strReason = $str; }
+
+ /**
+ * Set the UID of the booking to be deleted / edited
+ * @param $n (int)
+ */
+ protected function setUid($n) { $this->nUid = intval($n); }
+
+ /**
+ * Set the value of the submit button that the user clicked
+ * @param $str (string)
+ */
+ protected function setSubmitButtonValue($str) {
+ $this->strSubmitButtonValue = $str;
+ }
+
+ /**
+ * Get the name of the room of the requested booking or the room to show in
+ * the booking table
+ * @return string
+ */
+ public function getRoom() { return $this->strRoom; }
+
+ /**
+ * Get the action that should be done
+ * @return constant See @ref bookingtable_actions for possible values
+ */
+ public function getAction() { return $this->cAction; }
+
+ /**
+ * Get the the starting timeslice of the requested booking
+ * @return int
+ */
+ public function getTsFirst() { return $this->nTsFirst; }
+
+ /**
+ * Get the the ending timeslice of the requested booking
+ * @return int
+ */
+ public function getTsLast() { return $this->nTsLast; }
+
+ /**
+ * Get the the date of the requested booking or the date to be shown in the
+ * booking table
+ * @return timestamp
+ */
+ public function getDate() { return $this->tsDate; }
+
+ /**
+ * Get the the reason of the requested booking
+ * @return string
+ */
+ public function getReason() { return $this->strReason; }
+
+ /**
+ * Get the UID of the booking to be deleted / edited
+ * @return int
+ */
+ public function getUid() { return $this->nUid; }
+
+ /**
+ * Get the value of the submit button that the user clicked
+ * @return string
+ */
+ public function getSubmitButtonValue() {
+ return $this->strSubmitButtonValue;
+ }
+
+ /***************************************************************************/
+ /**
+ * @}
+ * @name Output
+ * @{
+ */
+
+ /**
+ * Add the CSS rules needed for this page
+ * @return void
+ */
+ protected function addCSS() {
+ $strCss = <<oCfg->isShowWeekend()) {
+ $strCss .= "#mod_roomReservationBookingTable td.cell { width:13%; }";
+ } else {
+ $strCss .= "#mod_roomReservationBookingTable td.cell { width:18.2%; }";
+ }
+ rrAddCss($strCss);
+ }
+
+ /**
+ * Show the timetable
+ * @return void
+ * @throws AccessException
+ * @todo increase the height of the cells a little
+ */
+ public function show() {
+ // Protect access
+ if(!$this->oCfg->userCanView()) {
+ throw new AccessException(MOD_ROOM_RESERVATION_ERROR_ACCESS_DENIED);
+ return;
+ }
+
+ // Print the header with the days
+ $ncTs = sizeof($this->oCfg->getTimeslices());
+ $nDays = ($this->oCfg->isShowWeekend()) ? 7 : 5;
+
+ echo "
";
+
+ // Print header with day names
+ echo "
";
+ for($ts = rrGetMonday($this->getDate()), $i=0; $i < $nDays;
+ $ts = strtotime("1 day", $ts), $i++) {
+ // Use a different color for the current day
+ $strClass = "heading";
+ $strTitle = strftime("%A %x", $ts);
+ if(date("Ymd") === date("Ymd", $ts)) {
+ $strClass .= " today";
+ $strTitle .= " "._c("room-reservation:(today)");
+ }
+ echo sprintf("
%s
", $strClass, $strTitle);
+ }
+ echo "
\n";
+
+ // Print timetable
+ // To take care of bookings with more than one timeslice, we use an array
+ // that tells us which cell in the current column is the next to fill
+ $anNextRow = array_fill(0, $nDays, 0);
+ // Iterate over the timeslices
+ for($nTs = 0; $nTs < $ncTs; $nTs++) {
+ $strLessons = $this->oCfg->isShowLessons() ?_sprintf_ord(
+ _c("room-reservation:%s# lesson"), $nTs + 1) . " " : "";
+ $oTs = $this->oCfg->getTimeslice($nTs);
+ $strTs = sprintf("%s - %s", strftime(_("%#I:%M %p"), $oTs->getBegin()),
+ strftime(_("%#I:%M %p"), $oTs->getEnd()));
+ // First column: Lesson
+ echo sprintf("
%s
", $strLessons . $strTs);
+
+ // Iterate over the days
+ for($ts = rrGetMonday($this->getDate()), $i = 0; $i <= $nDays;
+ $ts = strtotime("1 day", $ts), $i++) {
+ // Don't print if there is a spanning booking on the current cell
+ if(isset($anNextRow[$i]) && $anNextRow[$i] == $nTs) {
+ if(($ob = $this->oBm->getBookingByTimeslice($this->getRoom(), $ts,
+ $nTs)) !== null) {
+ // a booking exists here
+ // print booking or deletion form or handle the deletion form
+
+ // deletion form is requested:
+ if(($this->getAction() == MOD_ROOM_RESERVATION_BT_ACTION_DELETE) &&
+ (date("Ymd", $this->getDate()) == date("Ymd", $ts)) &&
+ ($this->getTsFirst() == $nTs) &&
+ ($this->getRoom() == $this->getRoom())) {
+ $anNextRow[$i] += $this->printBooking($nTs, $ts, $ob,
+ MOD_ROOM_RESERVATION_BTPB_DELETE);
+
+ // deletion form is submitted:
+ } else if(($this->getAction() ==
+ MOD_ROOM_RESERVATION_BT_ACTION_SUBMITDELETE) &&
+ (date("Ymd", $this->getDate()) == date("Ymd", $ts)) &&
+ ($this->getTsFirst() == $nTs) &&
+ ($this->getRoom() == $this->getRoom())) {
+ if($this->getSubmitButtonValue() == _("Delete")) {
+ // the user clicked the "delete" button
+ $bSuccess = false;
+ try {
+ $bSuccess = $this->oBm->delete($this->getUid());
+ } catch(Exception $e) {
+ $anNextRow[$i] += $this->printBooking($nTs, $ts, $ob, 0,
+ array($e->getMessage()));
+ }
+ // print booking link and a success message
+ if($bSuccess) {
+ $anNextRow[$i] += $this->printBookingLink($nTs, $ts,
+ array(_c("room-reservation:The booking was deleted.")));
+ }
+ } else {
+ // the user cancelled the request
+ $anNextRow[$i] += $this->printBooking($nTs, $ts, $ob);
+ }
+
+ // Something else -- print booking
+ } else {
+ $anNextRow[$i] += $this->printBooking($nTs, $ts, $ob);
+ }
+ } else {
+ // no booking is here
+ // print booking link, booking form or handle booking form
+ $asErrors = array();
+
+ // booking form is requested:
+ if(($this->getAction() == MOD_ROOM_RESERVATION_BT_ACTION_BOOK) &&
+ (date("Ymd", $this->getDate()) == date("Ymd", $ts)) &&
+ ($this->getTsFirst() == $nTs) &&
+ ($this->getRoom() == $this->getRoom())) {
+ $anNextRow[$i] += $this->printBookingForm($nTs, $ts, $asErrors);
+
+ // booking form is submitted:
+ } else if(($this->getAction() ==
+ MOD_ROOM_RESERVATION_BT_ACTION_SUBMIT) &&
+ // only handle the request if the form was in the current cell
+ (date("Ymd", $this->getDate()) == date("Ymd", $ts)) &&
+ ($this->getTsFirst() == $nTs) &&
+ ($this->getRoom() == $this->getRoom())) {
+
+ // try writing the booking to the database
+ $nNewUid = -1;
+ $oNewBooking = new mod_roomReservationBooking($this->getRoom(),
+ $this->getDate(), $this->getTsFirst(), $this->getTsLast(),
+ (trim($this->strPostAccount) == "") ? $_SESSION["act"] :
+ $this->strPostAccount, $this->getReason(),
+ $this->nPostInterval);
+ try {
+ $nNewUid = $this->oBm->write($oNewBooking);
+ } catch(Exception $s) {
+ // print the booking form again with the user's input
+ // @todo check for overlapping bookings and print them
+ $asErrors[] = $s->getMessage();
+ $anNextRow[$i] += $this->printBookingForm($nTs, $ts,
+ $asErrors);
+ }
+ if($nNewUid > 0) {
+ // print new booking and increment the "next row" variable by
+ // the current span
+ $anNextRow[$i] += $this->printBooking($nTs, $ts, $oNewBooking,
+ MOD_ROOM_RESERVATION_BTPB_NEW);
+ }
+
+ // Something else -- print booking link:
+ } else {
+ $anNextRow[$i] += $this->printBookingLink($nTs, $ts);
+ }
+ }
+ }
+ }
+ echo "
\n";
+ }
+ echo "
";
+ }
+
+ /**
+ * Print a single booking in the booking table.
+ * @param $nTs (int) current timeslice
+ * @param $ts (timestamp) current date
+ * @param $ob (mod_roomReservationBooking) the booking
+ * @param $cFlags (constant) Flags,
+ * See @ref bookingtable_printbooking_flags for more information.
+ * @param $asMsgs (array of strings) Additional messages to be printed
+ * inside the cell, one array element per message
+ * @return (int) the span of the booking
+ */
+ protected function printBooking($nTs, $ts, mod_roomReservationBooking $ob,
+ $cFlags = 0, $asMsgs = array()) {
+ $strAfter = "";
+ $strBefore = "";
+
+ // messages
+ if(count($asMsgs) > 0) {
+ $strBefore .= "
".nl2br(q(join("\n", $asMsgs)))."
\n";
+ }
+
+ // calculate the timespan of the current booking
+ $nSpan = $ob->getTsLast() - $ob->getTsFirst() + 1;
+
+ if(($cFlags & MOD_ROOM_RESERVATION_BTPB_DELETE) ==
+ MOD_ROOM_RESERVATION_BTPB_DELETE) {
+
+ // Restrict access
+ if(!($this->oBm->userIsOwner($ob->getUid()) or
+ $this->oCfg->userIsAdmin())) {
+ $strBefore .= "
", icon("dlg-warn",
+ array("bg" =>"gb")), _c("room-reservation:Attention: This ".
+ "booking is a recurring booking. If you delete it, the period will ".
+ "be deallocated for every week, not just this single week!"));
+ $strAfter .= sprintf("
", $_SERVER["PHP_SELF"],
+ _c("room-reservation:Delete this booking?"),
+ ($ob->getInterval() > 0 ? $strWarning : ""), $GLOBALS["smlbtn"],
+ _("Delete"), $GLOBALS["smlbtn"], _("Cancel"), $ob->getUid(),
+ $this->getRoom(), $this->getDate());
+ }
+ } else {
+ // delete and edit links, show only if user is allowed to
+ if($this->oBm->userIsOwner($ob->getUid()) ||
+ $this->oCfg->userIsAdmin()) {
+ /** @todo edit form */
+ $strAfter .= sprintf(" (".
+ "%s)",
+ $_SERVER["PHP_SELF"], $ob->getUid(), $ts,
+ _c("room-reservation:Edit this booking"),
+ _c("room-reservation:edit"), $_SERVER["PHP_SELF"], $ob->getUid(),
+ $ts, _c("room-reservation:Delete this booking"),
+ _c("room-reservation:delete"));
+ }
+ }
+
+ // test if booking is new and should be highlighted
+ $strClass = "cell booking".($ob->getInterval() > 0 ? " recurring" : "");
+ if(($cFlags & MOD_ROOM_RESERVATION_BTPB_NEW) ==
+ MOD_ROOM_RESERVATION_BTPB_NEW) {
+ $strClass .= " new";
+ }
+ // Use a different style for the current day
+ $strClass .= (date("Ymd", $ob->getDate()) == date("Ymd") ? " today" : "");
+ /** @todo: add ?subject=... to mailto link */
+ echo sprintf("
\n",
+ $strBefore, $strURL, _c("room-reservation:Book this room from here"),
+ _c("room-reservation:(Book from here)"));
+ } else {
+ // only print the messages
+ echo sprintf("
%s
\n",
+ $strBefore);
+ }
+ return 1;
+ }
+ /** @} */
+}
+?>
diff --git a/includes/mod_roomReservationBookingsManager.inc b/includes/mod_roomReservationBookingsManager.inc
new file mode 100755
index 0000000..573f340
--- /dev/null
+++ b/includes/mod_roomReservationBookingsManager.inc
@@ -0,0 +1,263 @@
+oCfg = $oCfg;
+ }
+
+ /***************************************************************************/
+ /**
+ * @}
+ * @name Retrieving bookings
+ * @{
+ */
+
+ /**
+ * Fetch a booking with the given unique ID from the SQL table
+ * @param $nUid (int) Unique ID of the booking
+ * @return mod_roomReservationBooking
+ */
+ public static function getBookingByUid($nUid) {
+ $h = db_query("SELECT * FROM mod_roomreservation_bookings WHERE rrb_uid = $1;", $nUid);
+ $a = pg_fetch_array($h);
+ $o = new mod_roomReservationBooking($a["rrb_room"], strtotime($a["rrb_date"]),
+ intval($a["rrb_tsfirst"]), intval($a["rrb_tslast"]), $a["rrb_act"],
+ $a["rrb_reason"], intval($a["rrb_interval"]));
+ $o->setUid(intval($a["rrb_uid"]));
+ return $o;
+ }
+
+ /**
+ * Test if there is a booking which takes place on the specified position at
+ * the specified date.
+ * @param $strRoom (string) Name of the room
+ * @param $tsDate (timestamp) The date
+ * @param $nTimeslice (int) The number of the timeslice
+ * @return mod_roomReservationBooking The booking which takes place on the
+ * specified time or null if no booking could be found.
+ */
+ public static function getBookingByTimeslice($strRoom, $tsDate,
+ $nTimeslice) {
+ $a = mod_roomReservationBookingsManager::getOverlappingBookings(
+ new mod_roomReservationBooking($strRoom, $tsDate, $nTimeslice,
+ $nTimeslice, null, null));
+ return isset($a[0]) ? $a[0] : null;
+ }
+
+ /**
+ * Get all bookings in database which overlap with the given booking.
+ * @param $ob (mod_roomReservationBooking) New booking that should be tested
+ * if it overlaps
+ * @return array with elements of type mod_roomReservationBooking
+ */
+ public static function getOverlappingBookings(
+ mod_roomReservationBooking $ob) {
+ // TODO: Test for bookings that only take place every n.th week (modulo n)
+
+ // Two bookings overlap, when they are on the same day and if
+ // old beginning < new ending AND old ending > new beginning
+ $hQuery = db_query("SELECT * FROM mod_roomreservation_bookings WHERE ".
+ "rrb_room = $1 AND ((rrb_interval > 0 AND EXTRACT(DOW FROM rrb_date) ".
+ "= $2) OR (rrb_interval = 0 AND rrb_date = $3)) AND rrb_tsfirst <= ".
+ "$4 AND rrb_tslast >= $5 ORDER BY rrb_tsfirst;", $ob->getRoom(),
+ date("w", $ob->getDate()), date("Y-m-d", $ob->getDate()),
+ intval($ob->getTsLast()), intval($ob->getTsFirst()));
+ $aoReturn = array();
+ while($aResult = pg_fetch_array($hQuery)) {
+ $aoReturn[] = mod_roomReservationBookingsManager::getBookingByUid(
+ $aResult["rrb_uid"]);
+ }
+ return $aoReturn;
+ }
+
+ /***************************************************************************/
+ /**
+ * @}
+ * @name Management of bookings
+ * @{
+ */
+
+ /**
+ * Insert or update a booking in the database.
+ * The function throws an AccessException if the user was not allowed to
+ * write the booking, or an SQLException if there was an error while trying
+ * to insert or update the booking into the database.
+ * @param $ob (mod_roomReservationBooking) Booking to write to the database
+ * @return (int) The UID of the written booking
+ * @throws SQLException, AccessException
+ * @todo document
+ */
+ function write(mod_roomReservationBooking $ob) {
+ // protect access
+ if(($ob->getUid() != null and !$this->oCfg->userIsAdmin() and
+ !$this->userIsOwner($ob->nUid)) or
+ ($ob->getUid() == null and !$this->oCfg->userCanBook())) {
+ throw new AccessException(MOD_ROOM_RESERVATION_ERROR_ACCESS_DENIED);
+ }
+
+ $strWhere = null;
+ $strLog = "";
+
+ // check if everything is right and throw exceptions
+ if(trim($ob->getAct()) == "") {
+ $ob->setAct($SESSION["act"]);
+ } elseif(!isAct($ob->getAct())) {
+ throw new Exception(MOD_ROOM_RESERVATION_ERROR_NO_SUCH_ACCOUNT);
+ return false;
+ }
+ if($ob->getTsFirst() > $ob->getTsLast()) {
+ throw new SQLException(MOD_ROOM_RESERVATION_ERROR_END_BEFORE_BEGIN);
+ return false;
+ }
+ if(trim($ob->getReason()) == "") {
+ throw new SQLException(MOD_ROOM_RESERVATION_ERROR_NO_REASON);
+ return false;
+ }
+
+ // Test for overlapping bookings
+ if($this->getOverlappingBookings($ob) != array()) {
+ throw new SQLException(MOD_ROOM_RESERVATION_ERROR_BOOKING_OVERLAPS);
+ return false;
+ }
+
+ // @todo Show real times in log, take it from config
+
+ // Update or insert?
+ if($ob->getUid() == null) {
+ // No UID yet, insert new booking
+ $strLog = sprintf("Raum â%sâ am %s von %s bis %s gebucht",
+ $ob->getRoom(), date("d\.m\.Y", $ob->getDate()),
+ intval($ob->getTsFirst()), intval($ob->getTsLast()));
+ } else {
+ // Update an existing booking
+ // @todo write old and new times into log
+ $strWhere = "rs_uid = ".qdb(intval($ob->getUid()));
+ $strLog = sprintf("Buchung im Raum â%sâ auf %s von %s bis %s ".
+ "geändert (Begründung: â%sâ)", $ob->getRoom(), date("d\.m\.Y",
+ $ob->getDate()), intval($ob->getTsFirst()),
+ intval($ob->getTsLast()), $ob->getReason());
+ }
+ $aPut["rrb_room"] = $ob->getRoom();
+ $aPut["rrb_date"] = date("Y\-m\-d", $ob->getDate());
+ $aPut["rrb_tsfirst"] = intval($ob->getTsFirst());
+ $aPut["rrb_tslast"] = intval($ob->getTsLast());
+ $aPut["rrb_act"] = $ob->getAct();
+ $aPut["rrb_reason"] = $ob->getReason();
+ $aPut["rrb_interval"] = intval($ob->getInterval());
+
+ // @todo test if the foreign keys are being violated and throw an error
+ // message if neccessary
+ db_store("mod_roomreservation_bookings", $aPut, $strWhere);
+
+ $hQuery = db_query("SELECT currval('mod_roomreservation_bookings_rrb_uid_seq') ".
+ "FROM mod_roomreservation_bookings;");
+ $nNewUid = pg_fetch_result($hQuery, 0, "currval");
+
+ rrInsertLog($strLog);
+
+ // Return new UID
+ return $nNewUid;
+ }
+
+ /**
+ * Delete a booking from the database
+ * @param $nUid (int) Unique ID of the booking
+ * @return (bool) true on success, otherwise false.
+ * @todo test
+ */
+ public function delete($nUid) {
+ // Only administrators and owners are allowed to delete bookings
+ if(!($this->oCfg->userIsAdmin() or $this->userIsOwner($nUid))) {
+ throw new AccessException(MOD_ROOM_RESERVATION_ERROR_ACCESS_DENIED);
+ return false;
+ }
+
+ // @todo: Show real times in log, take it from config
+ $ob = $this->getBookingByUid($nUid);
+ $strLog = sprintf("Buchung in Raum â%sâ am %s von %s bis %s ".
+ "gelöscht", $ob->getRoom(), date("d\.m\.Y", $ob->getDate()),
+ $ob->getTsFirst(), $ob->getTsLast());
+ // Delete it from the database
+ if(!db_query("DELETE FROM mod_roomreservation_bookings WHERE ".
+ "rrb_uid = $1;", $nUid)) {
+ throw new SQLException(MOD_ROOM_RESERVATION_ERROR_SQL);
+ return false;
+ } else {
+ rrInsertLog($strLog);
+ return true;
+ }
+ }
+
+ /**
+ * Determine if the current user is the owner of a specified error report.
+ * If this function fails, call getLastError() to get more information.
+ * @param $nID (int) Unique ID of the error report
+ * @throws SQLException
+ * @return bool
+ */
+ public static function userIsOwner($nID) {
+ if(!isset($_SESSION["act"])) {
+ return false; // user is not logged in
+ } else {
+ $hQuery = db_query("SELECT rrb_act FROM mod_roomreservation_bookings WHERE ".
+ "rrb_uid = $1;", intval($nID));
+ if(!is_resource($hQuery)) {
+ throw new SQLException(MOD_ROOM_RESERVATION_ERROR_SQL);
+ return false;
+ }
+ $arResult = pg_fetch_array($hQuery);
+ return ($arResult["rrb_act"] == $_SESSION["act"]);
+ }
+ }
+}
+?>
diff --git a/includes/mod_roomReservationConfig.inc b/includes/mod_roomReservationConfig.inc
new file mode 100755
index 0000000..9c02e3e
--- /dev/null
+++ b/includes/mod_roomReservationConfig.inc
@@ -0,0 +1,385 @@
+ 0;
+}
+
+/**
+ * Retrieve all groups that have a privilege assigned
+ * @param $strPriv (string) Privilege to test
+ * @return array
+ */
+function rrPrivilegedGroups($strPriv) {
+ $aReturn = array();
+ $h = db_query("SELECT act FROM privileges_assign WHERE privilege = $1 ".
+ "ORDER BY act;", $strPriv);
+ if(pg_num_rows($h) > 0) {
+ while($a = pg_fetch_array($h)) {
+ $aReturn[] = $a["act"];
+ }
+ }
+ return $aReturn;
+}
+
+/**
+ * User-defined compare function to compare timeslices
+ * @param $oTs1 (mod_roomReservationTimeslice)
+ * @param $oTs2 (mod_roomReservationTimeslice)
+ * @return (int) -1 if $oTs1 begins before $oTs2,
+ * 0 if the $oTs1 and $oTs2 have the same beginning,
+ * 1 if $oTs1 begins after $oTs2.
+ */
+function rrConfigSortTimeslices(mod_roomReservationTimeslice $oTs1,
+ mod_roomReservationTimeslice $oTs2) {
+ if($oTs1->getBegin() == $oTs2->getBegin()) {
+ return 0;
+ } else {
+ return ($oTs1->getBegin() > $oTs2->getBegin()) ? 1 : -1;
+ }
+}
+
+define("MOD_ROOM_RESERVATION_CONFIGFILE_HEADER", "flushTimeslices();
+ $this->setShowWeekend(false);
+ $this->setShowLessons(true);
+ $this->asMessages = array();
+
+ $this->readConfig();
+ }
+
+ /**
+ * **************************************************************************
+ * @}
+ * @name Access to attributes
+ * @{
+ */
+
+ /**
+ * Add a timeslice. A check is done that the timeslices do not overlap, and
+ * in this case, an Exception is thrown.
+ * @param $oTs (mod_roomReservationTimeslice)
+ * @throws Exception
+ * @return void
+ */
+ public function addTimeslice(mod_roomReservationTimeslice $oTs) {
+ // Check for overlapping timeslices
+ foreach($this->aoTimeslices as $oOldTs) {
+ if(($oOldTs->getBegin() < $oTs->getEnd() and
+ $oOldTs->getEnd() > $oTs->getBegin())) {
+ throw new Exception(
+ MOD_ROOM_RESERVATION_ERROR_CONFIG_OVERLAPPING_TIMESLICE);
+ }
+ }
+ $this->aoTimeslices[] = $oTs;
+ usort($this->aoTimeslices, "rrConfigSortTimeslices");
+ return;
+ }
+
+ /**
+ * Delete a timeslice
+ * @param $oTs (mod_roomReservationTimeslice) the timeslice to delete. If
+ * the timeslice is not found, an Exception is thrown.
+ * @throws Exception
+ * @return void
+ */
+ public function deleteTimeslice(mod_roomReservationTimeslice $oTs) {
+ for($i = 0; $i < count($this->aoTimeslices); $i++) {
+ if($this->aoTimeslices[$i]->getBegin() == $oTs->getBegin() and
+ $this->aoTimeslices[$i]->getEnd() == $oTs->getEnd()) {
+ // use array_splice because it renumbers the keys
+ array_splice($this->aoTimeslices, $i, 1);
+ return;
+ }
+ }
+ throw new Exception(MOD_ROOM_RESERVATION_ERROR_CONFIG_NO_SUCH_TIMESLICE);
+ }
+
+ /**
+ * Delete all timeslices.
+ * @return void
+ */
+ public function flushTimeslices() { $this->aoTimeslices = array(); }
+
+ /**
+ * Show or hide the weekend
+ * @param $b (bool)
+ */
+ public function setShowWeekend($b) { $this->bShowWeekend = ($b == true); }
+
+ /**
+ * Show or hide the lesson strings in the booking table
+ * @param $b (bool)
+ */
+ public function setShowLessons($b) { $this->bShowLessons = ($b == true); }
+
+ /**
+ * Add a message to the internal array of (error) messages
+ * @param $sMessage (string)
+ */
+ public function addMessage($sMessage) {
+ array_merge($this->asMessages, array($sMessage));
+ }
+
+ /**
+ * Get all timeslices in chronological order
+ * @return array of rmTimeslice
+ */
+ public function getTimeslices() { return $this->aoTimeslices; }
+
+ /**
+ * Return the starting times of every timeslice
+ * @param $bFormat (bool) true: Format the times according to the
+ * current locale
+ * false: return just the timestamps
+ * @return array
+ */
+ public function getTimesliceBeginnings($bFormat = false) {
+ $aot = $this->getTimeslices();
+ $aRet = array();
+ foreach($aot as $ao) {
+ $aRet[] = $bFormat ? _date("%#I:%M %p", $ao->getBegin()) :
+ $ao->getBegin();
+ }
+ return $aRet;
+ }
+
+ /**
+ * Return the ending times of every timeslice
+ * @param $bFormat (bool) true: Format the times according to the
+ * current locale
+ * false: return just the timestamps
+ * @return array
+ */
+ public function getTimesliceEndings($bFormat = false) {
+ $aot = $this->getTimeslices();
+ $aRet = array();
+ foreach($aot as $ao) {
+ $aRet[] = $bFormat ? _date("%#I:%M %p", $ao->getEnd()) : $ao->getEnd();
+ }
+ return $aRet;
+ }
+
+ /**
+ * Get a timeslice
+ * @param $n (int) index of the timeslice in the array
+ * @return rmTimeslice
+ */
+ public function getTimeslice($n) { return $this->aoTimeslices[$n]; }
+
+ /**
+ * Determine if the weekend is shown
+ * @return bool
+ */
+ public function isShowWeekend() { return ($this->bShowWeekend == true); }
+
+ /**
+ * Determine if the lesson strings in the booking table are shown
+ * @return bool
+ * FIXME needed?
+ */
+ public function isShowLessons() { return ($this->bShowLessons == true); }
+
+ /**
+ * Determine if the current user has admin rights. This function tests
+ * if the user is in a group which has the privilege of admin rights.
+ * @todo test
+ * @return bool
+ */
+ public function userIsAdmin() {
+ return secure_privilege("mod_roomreservation_admin");
+ }
+
+ /**
+ * Determine if the current user can book rooms. This function tests
+ * if the user is in a group which has the privilege to book rooms.
+ * If no group has this privilege, all users can book.
+ * @todo test
+ * @return bool
+ */
+ public function userCanBook() {
+ if(!rrPrivilegeAssigned("mod_roomreservation_book")) {
+ // If the privilege is not assigned to any group, all users can book
+ return true;
+ } else {
+ // If user is admin, it makes sense that he can book rooms ;-)
+ return secure_privilege("mod_roomreservation_book") ||
+ secure_privilege("mod_roomreservation_admin");
+ }
+ }
+
+ /**
+ * Determine if the current user can view bookings. This function tests
+ * if the user is in a group which has been configured as a group who
+ * can view bookings. If no groups are configured, any user can view the
+ * bookings table.
+ * @todo test
+ * @return bool
+ */
+ public function userCanView() {
+ if(!rrPrivilegeAssigned("mod_roomreservation_view")) {
+ // If the privilege is not assigned to any group, all users can view
+ return true;
+ } else {
+ // If user is admin or can book, it makes sense that he can view bookings
+ return secure_privilege("mod_roomreservation_admin") ||
+ secure_privilege("mod_roomreservation_book") ||
+ secure_privilege("mod_roomreservation_view");
+ }
+ }
+
+ /**
+ * Get the messages that have been produced
+ * @return string
+ */
+ public function getMessages() {
+ return join("\n", $this->asMessages);
+ }
+
+ /***************************************************************************/
+ /**
+ * @}
+ * @name Operations
+ * @{
+ */
+
+ /**
+ * Write the current state of this instance to the config file.
+ * @throws IOException
+ * @return bool
+ */
+ public function writeConfig() {
+ // Open config file
+ $hFile = fopen("mod_room-reservation/config.inc", "w", true);
+ if(!is_resource($hFile)) {
+ throw new IOException(MOD_ROOM_RESERVATION_ERROR_OPEN_FILE);
+ return false;
+ }
+ // Try to lock file repeatedly
+ for($n = 0; !flock($hFile, LOCK_EX); $n++) {
+ if($n > 10) {
+ throw new IOException(MOD_ROOM_RESERVATION_ERROR_OPEN_FILE);
+ return false; // Give up
+ } else {
+ sleep(0.2); // Retry after 100 ms
+ }
+ }
+
+ // Create text for config file
+ $strFile = MOD_ROOM_RESERVATION_CONFIGFILE_HEADER;
+
+ // Timeslices
+ $strFile .= "\$this->flushTimeslices();\n";
+ foreach($this->getTimeslices() as $oTs) {
+ $strFile .= sprintf("\$this->addTimeslice(new ".
+ "mod_roomReservationTimeslice(%d, %d));\n", $oTs->getBegin(),
+ $oTs->getEnd());
+ }
+
+ // Show weekend
+ $strFile .= sprintf("\$this->setShowWeekend(%s);\n",
+ $this->isShowWeekend() ? "true" : "false");
+
+ // Show lessons
+ $strFile .= sprintf("\$this->setShowLessons(%s);\n",
+ $this->isShowLessons() ? "true" : "false");
+
+ $strFile .= "?>";
+
+ // Write to config file and unlock it
+ if(fwrite($hFile, $strFile) == false) {
+ throw new IOException(MOD_ROOM_RESERVATION_ERROR_WRITE_FILE);
+ return false;
+ }
+ if(!flock($hFile, LOCK_UN)) {
+ throw new IOException(MOD_ROOM_RESERVATION_ERROR_UNLOCK_FILE);
+ return false;
+ }
+
+ rrInsertLog("Konfiguration verändert");
+ return true;
+ }
+
+ /**
+ * Read configuration from file. Returns false if an error occured,
+ * in this case getMessages() contains error messages.
+ * @return bool
+ */
+ public function readConfig() {
+ global $g_rmCfg;
+ try {
+ require("mod_room-reservation/config.inc");
+ } catch(Exception $e) {
+ $this->addMessage($e->getMessage());
+ }
+ }
+
+ /** @} */
+}
+?>
diff --git a/includes/mod_roomReservationConfigPage.inc b/includes/mod_roomReservationConfigPage.inc
new file mode 100755
index 0000000..4c74132
--- /dev/null
+++ b/includes/mod_roomReservationConfigPage.inc
@@ -0,0 +1,173 @@
+setTitle(_c("room-reservation:Configuration"));
+ $this->setIcon("mod_room-reservation_config");
+ }
+
+ public function processRequestVariables() {
+ // default values
+ $this->bPostShowWeekend = $this->oCfg->isShowWeekend();
+ $this->bPostShowLessons = $this->oCfg->isShowLessons();
+
+ if(isset($_POST["mod_roomReservationConfigPage"])) {
+ if(isset($_POST["mod_roomReservationConfigPage"]["showweekend"])) {
+ $this->bPostShowWeekend =
+ ($_POST["mod_roomReservationConfigPage"]["showweekend"] == true);
+ }
+ ###########
+ echo "bPostShowWeekend is ".($this->bPostShowWeekend?"true ":"false ");
+ ###########
+
+ if(isset($_POST["mod_roomReservationConfigPage"]["showlessons"])) {
+ $this->bPostShowLessons =
+ ($_POST["mod_roomReservationConfigPage"]["showlessons"] == true);
+ }
+ ###########
+ echo "bPostShowLessons is ".($this->bPostShowLessons?"true ":"false ");
+ ###########
+
+ // process the request
+ if(isset($_POST["mod_roomReservationConfigPage"]["submit"])) {
+ $this->oCfg->setShowWeekend($this->bPostShowWeekend);
+ $this->oCfg->setShowLessons($this->bPostShowLessons);
+ try {
+ $this->oCfg->writeConfig();
+ } catch(Exception $e) {
+ $this->asMessages[] = $e->getMessage();
+ }
+ }
+ }
+ }
+
+ public function doShow() {
+ // error messages
+ if(count($this->asMessages) > 0) {
+ printf("
", _c("room-reservation:This is ".
+ "a short summary of the privileges related to the room reservation ".
+ "schedulde and the groups which have them assigned."),
+ sprintf(_c("room-reservation:If one of these privileges is not assigned to ".
+ "any group, all users on this server are allowed to perform the specified ".
+ "action. Please use the %sgroup administration%s to assign and revoke ".
+ "privileges."), "", ""),
+ _c("room-reservation:Please note that every group with the booking ".
+ "privilege can also implicitly view the booking table and every group with ".
+ "the administration privilege can also implicitly book and view the ".
+ "booking table."));
+ echo "
", _c("room-reservation:Here you can fill in the ".
+ "periods where bookings can be undertaken. A booking period can ".
+ "e. g. correspond to a lesson."));
+ echo "
Um eine Buchung vorzunehmen dort auf „Ab hier buchen“ klicken, wo die Buchung beginnen soll.
+
Neu: Eigene Buchungen (außer den wiederkehrenden Buchungen in dunkelblau) können gelöscht werden, indem auf den Link „Buchung löschen“ geklickt wird.
+
Mit Klick auf den Benutzernamen kann eine E-Mail an den Benutzer geschrieben werden.
+
\n";
+
+ $bookings->PrintTimeTable($start, $room);
+
+ echo " ";
+}
+
+_PageBlue();
+*/
+?>
diff --git a/update-iserv1-iserv2.pl b/update-iserv1-iserv2.pl
new file mode 100755
index 0000000..3105f77
--- /dev/null
+++ b/update-iserv1-iserv2.pl
@@ -0,0 +1,254 @@
+#!/usr/bin/perl -w
+
+use strict;
+use warnings;
+use IServ::DB;
+use Time::Local;
+
+my $OLDCFG = "/old/opt/iserv/idesk/rooms/admin/config.inc.rpmsave";
+# FIXME insert real path
+my $NEWCFG = "test.inc";
+
+my @tsbegin;
+my @tsend;
+my @tsbeginold;
+my @tsendold;
+my @allowedgroups;
+my @admingroups;
+my $restrictaccess = 0;
+my $showweekend = 0;
+my $showlessons = 1;
+
+# convert the config file
+open IN, "<", $OLDCFG or die "ERROR: old config file could not be opened: $!";
+while() {
+ # skip unused variables
+ if(/\$cfgRooms\[(\"LogOnInsert\"|\'LogOnInsert\')\]/) {
+ #print "NOTICE: config variable \"LogOnInsert\" is no longer used.\n";
+ } elsif(/\$cfgRooms\[(\"OldBookings\"|\'OldBookings\')\]/) {
+ #print "NOTICE: config variable \"OldBookings\" is no longer used.\n";
+ } elsif(/\$cfgRooms\[(\"ShowClassEdit\"|\'ShowClassEdit\')\]/) {
+ #print "NOTICE: config variable \"ShowClassEdit\" is no longer used.\n";
+ } elsif(/\$cfgRooms\[(\"ClassEditText\"|\'ClassEditText\')\]/) {
+ #print "NOTICE: config variable \"ClassEditText\" is no longer used.\n";
+
+ # AbsTime is now named ShowLessons
+ } elsif(/\$cfgRooms\[(\"AbsTime\"|\'AbsTime\')\]\s*=\s*(true|false|0|1)\s*/) {
+ print "AbsTime is $2\n";
+ $showlessons = ($2 eq "true" or $2 eq "1") ? 1 : 0;
+
+ # ShowWeekend
+ } elsif(/\$cfgRooms\[(\"ShowWeekend\"|\'ShowWeekend\')\]\s*=\s*(true|false|0|1)/) {
+ print "ShowWeekend is $2\n";
+ $showweekend = ($2 eq "true" or $2 eq "1") ? 1 : 0;
+
+ # timeslice beginnings
+ } elsif(/\$cfgRooms\[(\"TimeslicesBegin\"|\'TimeslicesBegin\')\]\s*=\s*array\s*\(/) {
+ print "processing timeslice beginnings...\n";
+ while() {
+ if(/\);/) {
+ last;
+ } else {
+ /\s*(\d)\s*=>\s*[\'\"](\d\d?):(\d\d)[\'\"]\s*/;
+ my $hr = $2;
+ $hr = "0$hr" if length $hr < 2;
+ push @tsbeginold, "$hr:$3:00";
+ push @tsbegin, Time::Local::timelocal 0, $3, $hr, 1, 0, 1970;
+ print " found beginning: $hr:$3\n";
+ }
+ }
+
+ # timeslice endings
+ } elsif(/\$cfgRooms\[(\"TimeslicesEnd\"|\'TimeslicesEnd\')\]\s*=\s*array\s*\(/) {
+ print "processing timeslice endings...\n";
+ while() {
+ if(/\);/) {
+ last;
+ } else {
+ /\s*(\d)\s*=>\s*[\'\"](\d\d?):(\d\d)[\'\"]\s*/;
+ my $hr = $2;
+ $hr = "0$hr" if length $hr < 2;
+ push @tsendold, "$hr:$3:00";
+ push @tsend, Time::Local::timelocal 0, $3, $hr, 1, 0, 1970;
+ print " found ending: $hr:$3\n";
+ }
+ }
+
+ # add rooms to the database, if they do not exist yet
+ } elsif(/\$cfgRooms\[(\"Rooms\"|\'Rooms\')\]\s*=\s*array\s*\(/) {
+ print "processing rooms...\n";
+ while() {
+ if(/\);/) {
+ last;
+ } else {
+ /\s*\d\s*=>\s*((\'([^\']*)\')|(\"([^\"]*)\"))\s*/;
+ my $sqlval = IServ::DB::Val $3;
+ if(IServ::DB::Rows "SELECT * FROM rooms WHERE name = $sqlval;") {
+ print " room '$3' found in database.\n";
+ } else {
+ print "NOTICE: room '$3' not found in database, adding it.\n";
+ IServ::DB::Put "rooms", { "name" => $3 } or die $!;
+ }
+ }
+ }
+
+ # convert old user rights to privileges
+ } elsif(/\$cfgRooms\[(\"RestrictAccess\"|\'RestrictAccess\')\]\s*=\s*(false|true|0|1)/) {
+ #print "config variable \"RestrictAccess\" is no longer used.\n";
+ $restrictaccess = ($2 eq "true" or $2 eq "1") ? 1 : 0;
+
+ } elsif(/\$cfgRooms\[(\"AllowedGroups\"|\'AllowedGroups\')\]\s*=\s*array\s*\(/) {
+ print "processing allowed groups...\n";
+ while() {
+ if(/\);/) {
+ last;
+ } else {
+ /\s*\d\s*=>\s*((\'([^\']*)\')|(\"([^\"]*)\"))\s*/;
+ my $name = IServ::DB::Val $3;
+ my @act = IServ::DB::GetArr "SELECT act FROM groups WHERE name=$name;";
+ if(@act) {
+ print " found group $name.\n";
+ push @allowedgroups, $act[0]{"act"};
+ } else {
+ print "NOTICE: group $name not found in database, ignoring it.\n";
+ }
+ }
+ }
+
+ } elsif(/\$cfgRooms\[(\"GroupsAdmin\"|\'GroupsAdmin\')\]\s*=\s*array\s*\(/) {
+ #print "config variable AdminGroups is not longer used\n"
+ print "processing admin groups...\n";
+ while() {
+ if(/\);/) {
+ last;
+ } else {
+ /\s*\d\s*=>\s*((\'([^\']*)\')|(\"([^\"]*)\"))\s*/;
+ my $name = IServ::DB::Val $3;
+ my @act = IServ::DB::GetArr "SELECT act FROM groups WHERE name=$name;";
+ if(@act) {
+ print " found group $name.\n";
+ push @admingroups, $act[0]{"act"};
+ } else {
+ print "NOTICE: group $name not found in database, ignoring it.\n";
+ }
+ }
+ }
+ }
+}
+
+print "converting old user rights to privileges...\n";
+# change the privilege names to the right ones
+if($restrictaccess) {
+ foreach(@allowedgroups) {
+ my $priv = "mod_roomreservation_view";
+ my $act = "$_";
+ my @act = IServ::DB::GetArr "SELECT act FROM privileges_assign ".
+ "WHERE privilege='$priv' AND act='$act';";
+ if(@act) {
+ print " group $_ is already allowed to see the bookings, ignoring it.\n";
+ } else {
+ IServ::DB::Put "privileges_assign", { "act" => $_,
+ "privilege" => $priv } or die $!;
+ print " allowed viewing for group '$_'\n";
+ }
+
+ $priv = "mod_roomreservation_book";
+ @act = "SELECT act FROM privileges_assign ".
+ "WHERE privilege='$priv' AND act='$act';";
+ if(@act) {
+ print " group $_ is already allowed to book, ignoring it.\n";
+ } else {
+ IServ::DB::Put "privileges_assign", { "act" => $_,
+ "privilege" => $priv } or die $!;
+ print " allowed booking for group '$_'\n";
+ }
+ }
+}
+foreach(@admingroups) {
+ my $priv = "mod_roomreservation_admin";
+ my $act = "$_";
+ my @act = IServ::DB::GetArr "SELECT act FROM privileges_assign ".
+ "WHERE privilege='$priv' AND act='$act';";
+ if(@act) {
+ print " group $_ has already adminship, ignoring it.\n";
+ } else {
+ IServ::DB::Put "privileges_assign", { "act" => $_,
+ "privilege" => $priv } or die $!;
+ print " allowed administration for group '$_'\n";
+ }
+}
+
+print "writing config file...\n";
+system "touch $NEWCFG";
+open OUT, ">", $NEWCFG or die "ERROR: new config file could not be opened: $!";
+print OUT "flushTimeslices();\n";
+for(my $i = 0; $i <= $#tsbegin; $i++) {
+ print OUT "\$this->addTimeslice(new rsTimeslice($tsbegin[$i],$tsend[$i]));\n";
+}
+print OUT "\$this->setShowWeekend($showweekend);\n";
+print OUT "\$this->setShowLessons($showlessons);\n";
+print OUT "?>";
+close OUT;
+close IN;
+
+print "\nconverting the database. Have a lot of fun...\n";
+open IN, "cat /old/rooms.sql | iconv -f utf8 -t utf8 |" or die
+#open IN, " "timeslice" ("15:00:00" => "3")
+my $i = 0;
+my %tsbeginoldkeys;
+my %tsendoldkeys;
+foreach (@tsbeginold) {
+ $tsbeginoldkeys{$_} = $i;
+ $i++;
+}
+$i = 0;
+foreach (@tsendold) {
+ $tsendoldkeys{$_} = $i;
+ $i++;
+}
+
+#my ($key, $val);
+#while(($key, $val) = each(%tsbeginoldkeys)) {
+# print "$key => $val\n";
+#}
+#while(($key, $val) = each(%tsendoldkeys)) {
+# print "$ke:y => $val\n";
+#}
+
+# FIXME database conversion
+print "Importing old bookings...\n";
+IServ::DB::Exec "CREATE TABLE mod_roomreservation_bookings_old (id INT NOT NULL PRIMARY KEY, room TEXT NOT NULL, date DATE NOT NULL, timebegin TIME NOT NULL, timeend TIME NOT NULL, act TEXT REFERENCES users(Act) ON DELETE CASCADE ON UPDATE CASCADE NOT NULL, class TEXT, reason TEXT NOT NULL, fixed BOOL);";
+while() {
+ $_ =~ s/INSERT INTO rooms/INSERT INTO mod_roomreservation_bookings_old/;
+ #print "$_";
+ IServ::DB::Exec($_);
+}
+#IServ::DB::Exec "INSERT INTO mod_roomreservation_bookings";
+IServ::DB::Exec "DROP TABLE mod_roomreservation_bookings_old;";
+
+die 333;
+$i = 0;
+
+my $maxid = 0;
+while() {
+ if(/COPY \"rooms\" FROM stdin;/) {
+ while() {
+ if(/\\\./) {
+ last;
+ } elsif(/(\d+)\t([^\t]*)\t(\d{4}-\d\d-\d\d)\t(\d\d:\d\d:\d\d)\t(\d\d:\d\d:\d\d)\t([a-zA-Z0-9\.-]+)\t([^\t]*)\t([^\t]*)\t(t|f)/) {
+ $i++;
+ # FIXME convert the timeslices!!!
+ # FIXME insert the right table name and rs_weekly
+ # ignore uid, it is serial, also class is not used anymore
+ # print $tsbeginoldkeys{$4}; print "\n";
+ IServ::DB::Put "roomschedule", { "rs_room" => $2, "rs_date" => $3,
+ "rs_tsfirst" => $tsbeginoldkeys{$4}, "rs_tslast" => $tsendoldkeys{$5},
+ "rs_act" => $6, "rs_reason" => $8, "rs_weekly" => $9 };
+ }
+ }
+ }
+}
+print "$i datasets converted.\ndone!\n";