summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian Klinger2016-06-10 17:19:50 +0200
committerChristian Klinger2016-06-10 17:19:50 +0200
commitcab4355fec9928639e688d096d9ad5e77cb28493 (patch)
tree79aa7dc308c4c877bef87f89cf2b88fbe917ef74
parentuse Module:: instead of require (diff)
downloadslx-admin-cab4355fec9928639e688d096d9ad5e77cb28493.tar.gz
slx-admin-cab4355fec9928639e688d096d9ad5e77cb28493.tar.xz
slx-admin-cab4355fec9928639e688d096d9ad5e77cb28493.zip
first rough version of exams-module.
-rw-r--r--inc/request.inc.php15
-rw-r--r--install/content.sql2
-rw-r--r--install/schema.sql3
-rw-r--r--modules-available/dozmod/api.inc.php128
-rw-r--r--modules-available/exams/config.json5
-rw-r--r--modules-available/exams/inc/exams.inc.php17
-rw-r--r--modules-available/exams/page.inc.php76
-rw-r--r--modules-available/exams/templates/page-add-exam.html25
-rw-r--r--modules-available/exams/templates/page-exams.html32
9 files changed, 242 insertions, 61 deletions
diff --git a/inc/request.inc.php b/inc/request.inc.php
index f46210af..0052fb24 100644
--- a/inc/request.inc.php
+++ b/inc/request.inc.php
@@ -45,5 +45,18 @@ class Request
if ($type !== false) settype($_REQUEST[$key], $type);
return $_REQUEST[$key];
}
-
+
+ /**
+ * @return true iff the request is a GET request
+ */
+ public static function isPost() {
+ return $_SERVER['REQUEST_METHOD'] == 'POST';
+ }
+
+ /**
+ * @return true iff the request is a POST request
+ */
+ public static function isGet() {
+ return $_SERVER['REQUEST_METHOD'] == 'GET';
+ }
}
diff --git a/install/content.sql b/install/content.sql
index bf54a711..ca730611 100644
--- a/install/content.sql
+++ b/install/content.sql
@@ -1,2 +1,4 @@
+USE openslx;
+
INSERT INTO property (name, dateline, value) VALUES ('webif-version', 0, 11);
diff --git a/install/schema.sql b/install/schema.sql
index c4ca99c5..b8ea768b 100644
--- a/install/schema.sql
+++ b/install/schema.sql
@@ -1,6 +1,9 @@
SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
SET time_zone = "+00:00";
+CREATE DATABASE openslx;
+USE openslx;
+
CREATE TABLE `callback` (
`taskid` varchar(40) CHARACTER SET ascii COLLATE ascii_bin NOT NULL,
`dateline` int(10) unsigned NOT NULL,
diff --git a/modules-available/dozmod/api.inc.php b/modules-available/dozmod/api.inc.php
index 52c8dcfb..b37c668c 100644
--- a/modules-available/dozmod/api.inc.php
+++ b/modules-available/dozmod/api.inc.php
@@ -11,7 +11,7 @@
if (!Module::isAvailable('locations')) {
- die('require locations module');
+ die('require locations module');
}
@@ -23,52 +23,52 @@ $availableRessources = ['vmx', 'test', 'netrules'];
function cache_hash($obj)
{
- return md5(serialize($obj));
+ return md5(serialize($obj));
}
function cache_key_to_filename($key)
{
- return "/tmp/bwlp-slxadmin-cache-$key"; // TODO: hash
+ return "/tmp/bwlp-slxadmin-cache-$key"; // TODO: hash
}
function cache_put($key, $value)
{
- $filename = cache_key_to_filename($key);
- file_put_contents($filename, $value);
+ $filename = cache_key_to_filename($key);
+ file_put_contents($filename, $value);
}
function cache_has($key)
{
- $filename = cache_key_to_filename($key);
- $mtime = filemtime($filename);
+ $filename = cache_key_to_filename($key);
+ $mtime = filemtime($filename);
- if (!$mtime) {
- return false; // cache miss
- }
- if (time() - $mtime > CONFIG_DOZMOD_EXPIRE) {
- return false;
- } else {
- return true;
- }
+ if (!$mtime) {
+ return false; // cache miss
+ }
+ if (time() - $mtime > CONFIG_DOZMOD_EXPIRE) {
+ return false;
+ } else {
+ return true;
+ }
}
function cache_get($key)
{
- $filename = cache_key_to_filename($key);
- return file_get_contents($filename);
+ $filename = cache_key_to_filename($key);
+ return file_get_contents($filename);
}
/* good for large binary files */
function cache_get_passthru($key)
{
- $filename = cache_key_to_filename($key);
- $fp = fopen($filename, "r");
- if ($fp) {
- fpassthru($fp);
- } else {
- Util::traceError("cannot open file");
- }
+ $filename = cache_key_to_filename($key);
+ $fp = fopen($filename, "r");
+ if ($fp) {
+ fpassthru($fp);
+ } else {
+ Util::traceError("cannot open file");
+ }
}
/* END: Cache ---------------------------------------------------- */
@@ -88,56 +88,64 @@ function println($str) { echo "$str\n"; }
* */
function _getLecturesForLocations($locationIds)
{
- $ids = implode('%20', $locationIds);
- $url = LIST_URL . "?locations=$ids";
- $responseXML = Download::asString($url, 60, $code);
- $xml = new SimpleXMLElement($responseXML);
- $uuids = [];
- foreach ($xml->eintrag as $e) {
- $uuids[] = strval($e->uuid['param'][0]);
- }
- return $uuids;
+ /* if in any of the locations there is an exam active, consider the client
+ to be in "exam-mode" and only offer him exams (no lectures) */
+ $examMode = false;
+
+ if (Module::isAvailable('exams')) {
+ $examMode = Exams::isInExamMode($locationIds);
+ }
+ $ids = implode('%20', $locationIds);
+ $url = LIST_URL . "?locations=$ids" . ($examMode ? '&exams' : '');
+ $responseXML = Download::asString($url, 60, $code);
+ $xml = new SimpleXMLElement($responseXML);
+
+ $uuids = [];
+ foreach ($xml->eintrag as $e) {
+ $uuids[] = strval($e->uuid['param'][0]);
+ }
+ return $uuids;
}
/** Caching wrapper around _getLecturesForLocations() */
function getLecturesForLocations($locationIds)
{
- $key = 'lectures_' . cache_hash($locationIds);
- if (cache_has($key)) {
- return unserialize(cache_get($key));
- } else {
- $value = _getLecturesForLocations($locationIds);
- cache_put($key, serialize($value));
- return $value;
- }
+ $key = 'lectures_' . cache_hash($locationIds);
+ if (cache_has($key)) {
+ return unserialize(cache_get($key));
+ } else {
+ $value = _getLecturesForLocations($locationIds);
+ cache_put($key, serialize($value));
+ return $value;
+ }
}
function _getVMX($lecture_uuid)
{
- $url = VMX_URL . '/' . $lecture_uuid;
- $response = Download::asString($url, 60, $code);
- return $response;
+ $url = VMX_URL . '/' . $lecture_uuid;
+ $response = Download::asString($url, 60, $code);
+ return $response;
}
/** Caching wrapper around _getVMX() **/
function getVMX($lecture_uuid)
{
- $key = 'vmx_' . $lecture_uuid;
- if (cache_has($key)) {
- cache_get_passthru($key);
- } else {
- $value = _getVMX($lecture_uuid);
- cache_put($key, $value);
- return $value;
- }
+ $key = 'vmx_' . $lecture_uuid;
+ if (cache_has($key)) {
+ cache_get_passthru($key);
+ } else {
+ $value = _getVMX($lecture_uuid);
+ cache_put($key, $value);
+ return $value;
+ }
}
// -----------------------------------------------------------------------------//
$ip = $_SERVER['REMOTE_ADDR'];
if (substr($ip, 0, 7) === '::ffff:') {
- $ip = substr($ip, 7);
+ $ip = substr($ip, 7);
}
/* request data, don't trust */
@@ -145,10 +153,10 @@ $resource = Request::get('resource', false, 'string');
$lecture = Request::get('lecture', false, 'string');
if ($resource === false) {
- Util::traceError("you have to specify the 'resource' parameter");
+ Util::traceError("you have to specify the 'resource' parameter");
}
if ($lecture === false) {
- Util::traceError("you have to specify the 'lecture' parameter");
+ Util::traceError("you have to specify the 'lecture' parameter");
}
/* lookup location id(s) */
@@ -161,18 +169,18 @@ $lectures = getLecturesForLocations($location_ids);
/* validate request -------------------------------------------- */
/* check resources */
if (!in_array($resource, $availableRessources)) {
- Util::traceError("unknown resource: $resource");
+ Util::traceError("unknown resource: $resource");
}
/* check that the user requests a lecture that he is allowed to have */
if (!in_array($lecture, $lectures)) {
- Util::traceError("client is not allowed to access this lecture: $lecture");
+ Util::traceError("client is not allowed to access this lecture: $lecture");
}
if ($resource === 'vmx') {
- echo getVMX($lecture);
+ echo getVMX($lecture);
} else if ($resource === 'test') {
- echo "Here's your special test data!";
+ echo "Here's your special test data!";
} else {
- echo "I don't know how to give you that resource";
+ echo "I don't know how to give you that resource";
}
diff --git a/modules-available/exams/config.json b/modules-available/exams/config.json
new file mode 100644
index 00000000..e109b27b
--- /dev/null
+++ b/modules-available/exams/config.json
@@ -0,0 +1,5 @@
+{
+ "category":"main.status",
+ "dependencies": [ "locations" ],
+ "permission": "0"
+}
diff --git a/modules-available/exams/inc/exams.inc.php b/modules-available/exams/inc/exams.inc.php
new file mode 100644
index 00000000..9e5833ba
--- /dev/null
+++ b/modules-available/exams/inc/exams.inc.php
@@ -0,0 +1,17 @@
+<?php
+
+class Exams {
+
+
+ /**
+ * @param: array of location ids
+ * @return: true iff for any of the given location ids an exam is scheduled
+ **/
+ public static function isInExamMode($locationIds) {
+ // TODO: Better use prepared statement
+ $l = '(' . implode(', ', $locationIds) . ')';
+ $res = Database::queryFirst("SELECT (COUNT(examid) > 0) as examMode FROM exams WHERE starttime < NOW() AND endtime > NOW() AND locationid IN $l", []);
+
+ return $res['examMode'];
+ }
+}
diff --git a/modules-available/exams/page.inc.php b/modules-available/exams/page.inc.php
new file mode 100644
index 00000000..e5129d38
--- /dev/null
+++ b/modules-available/exams/page.inc.php
@@ -0,0 +1,76 @@
+<?php
+
+class Page_Exams extends Page
+{
+ var $action;
+ var $exams;
+ var $locations;
+
+ protected function doPreprocess()
+ {
+ User::load();
+
+ $req_action = Request::get('action', 'show');
+ if (in_array($req_action, ['show', 'add', 'delete'])) {
+ $this->action = $req_action;
+ }
+
+ if ($this->action === 'show') {
+ $tmp = Database::simpleQuery("select * from exams NATURAL LEFT OUTER JOIN location;", []);
+ while ($exam = $tmp->fetch(PDO::FETCH_ASSOC)) {
+ $this->exams[] = $exam;
+ }
+ } elseif ($this->action === 'add') {
+ $tmp = Database::simpleQuery("select * from location;", []);
+ while ($loc = $tmp->fetch(PDO::FETCH_ASSOC)) {
+ $this->locations[] = $loc;
+ }
+
+ if (Request::isPost()) {
+ /* process form-data */
+ $locationid = Request::post('location');
+ $starttime = Request::post('starttime');
+ $endtime = Request::post('endtime');
+
+ $res = Database::exec("INSERT INTO exams(locationid, starttime, endtime) VALUES(:locationid, :starttime, :endtime);",
+ compact('locationid', 'starttime', 'endtime'));
+
+ if ($res === false) {
+ Message::addError('exam-not-added');
+ } else {
+ Message::addInfo('exam-added-success');
+ }
+ Util::redirect('?do=exams');
+ }
+
+ } elseif ($this->action === 'delete') {
+ if (!Request::isPost()) { die('delete only works with a post request'); }
+ $examid = Request::post('examid');
+ $res = Database::exec("DELETE FROM exams WHERE examid = :examid;", compact('examid'));
+ if ($res === false) {
+ Message::addError('exam-not-deleted-error');
+ } else {
+ Message::addInfo('exam-deleted-success');
+ }
+ Util::redirect('?do=exams');
+ } else {
+ Util::traceError("unknown action");
+ }
+ }
+
+ protected function doRender()
+ {
+ // Render::setTitle(Dictionary::translate('lang_exams'));
+ //Render::addTemplate('page-exams', $_POST);
+
+ if ($this->action === "show") {
+ Render::setTitle("All Exams");
+ Render::addTemplate('page-exams', ['exams' => $this->exams]);
+ } elseif ($this->action === "add") {
+ Render::setTitle("Add Exam");
+ Render::addTemplate('page-add-exam', ['locations' => $this->locations]);
+ }
+ // Render::output('hi');
+ }
+
+}
diff --git a/modules-available/exams/templates/page-add-exam.html b/modules-available/exams/templates/page-add-exam.html
new file mode 100644
index 00000000..b610fcd8
--- /dev/null
+++ b/modules-available/exams/templates/page-add-exam.html
@@ -0,0 +1,25 @@
+<h1>Add Exam</h1>
+
+<form class="form" method="POST" action="?do=exams&action=add">
+ <div class="form-group">
+ <label for="location">Location</label>
+ <select name="location" class="form-control">
+ {{#locations}}
+ <option value="{{locationid}}"> {{locationname}} </option>
+ {{/locations}}
+ </select>
+ </div>
+
+ <div class="form-group">
+ <label for="starttime">Start Time</label>
+ <input class="form-control" type="datetime" name="starttime" />
+ </div>
+
+ <div class="form-group">
+ <label for="endtime">Start Time</label>
+ <input class="form-control" type="datetime" name="endtime" />
+ </div>
+
+ <input type="hidden" name="token" value="{{token}}" />
+ <input type="submit" class="btn btn-success" value="Add Exam"></input>
+</form>
diff --git a/modules-available/exams/templates/page-exams.html b/modules-available/exams/templates/page-exams.html
new file mode 100644
index 00000000..6c67fa2c
--- /dev/null
+++ b/modules-available/exams/templates/page-exams.html
@@ -0,0 +1,32 @@
+
+<h1>All Exams</h1>
+
+<table class="table">
+ <tr>
+ <th>ID</th>
+ <th>Location</th>
+ <th>Begin</th>
+ <th>End</th>
+ <th>Actions</th>
+ </tr>
+ {{#exams}}
+ <tr>
+ <td>{{examid}}</td>
+ <td>
+ <a href="?do=baseconfig&module=locations&locationid={{locationid}}"> {{locationname}} </a>
+ </td>
+ <td>{{starttime}}</td>
+ <td>{{endtime}}</td>
+ <td>
+ <form method="POST" action="?do=exams&action=delete"
+ onsubmit="return confirm('delete really?');">
+ <input type="hidden" name="token" value="{{token}}"/>
+ <input type="hidden" name="examid" value="{{examid}}"/>
+ <input type="submit" value="Delete" class="btn btn-sm" />
+ </form>
+ </td>
+ </tr>
+ {{/exams}}
+
+</table>
+<a href="?do=exams&action=add" class="btn btn-success">Add Exam </a>