summaryrefslogtreecommitdiffstats
path: root/modules-available/locationinfo/inc/coursebackend.inc.php
diff options
context:
space:
mode:
Diffstat (limited to 'modules-available/locationinfo/inc/coursebackend.inc.php')
-rw-r--r--modules-available/locationinfo/inc/coursebackend.inc.php98
1 files changed, 44 insertions, 54 deletions
diff --git a/modules-available/locationinfo/inc/coursebackend.inc.php b/modules-available/locationinfo/inc/coursebackend.inc.php
index bc5b059e..ea1bebac 100644
--- a/modules-available/locationinfo/inc/coursebackend.inc.php
+++ b/modules-available/locationinfo/inc/coursebackend.inc.php
@@ -19,7 +19,7 @@ abstract class CourseBackend
*/
protected $error = false;
/**
- * @var array list of errors that occured, fill using addError()
+ * @var array list of errors that occurred, fill using addError()
*/
private $errors;
/**
@@ -39,7 +39,7 @@ abstract class CourseBackend
$this->errors = [];
}
- protected final function addError($message, $fatal)
+ protected final function addError(string $message, bool $fatal)
{
$this->errors[] = ['time' => time(), 'message' => $message, 'fatal' => $fatal];
}
@@ -55,7 +55,7 @@ abstract class CourseBackend
self::$backendTypes = array();
foreach (glob(dirname(__FILE__) . '/coursebackend/coursebackend_*.inc.php', GLOB_NOSORT) as $file) {
require_once $file;
- preg_match('#coursebackend_([^/\.]+)\.inc\.php$#i', $file, $out);
+ preg_match('#coursebackend_([^/.]+)\.inc\.php$#i', $file, $out);
$className = 'CourseBackend_' . $out[1];
if (!class_exists($className)) {
trigger_error("Backend type source unit $file doesn't seem to define class $className", E_USER_ERROR);
@@ -71,13 +71,13 @@ abstract class CourseBackend
*
* @return array list of backends
*/
- public static function getList()
+ public static function getList(): array
{
self::loadDb();
return array_keys(self::$backendTypes);
}
- public static function exists($backendType)
+ public static function exists($backendType): bool
{
self::loadDb();
return isset(self::$backendTypes[$backendType]);
@@ -89,7 +89,7 @@ abstract class CourseBackend
* @param string $backendType name of module type
* @return \CourseBackend|false module instance
*/
- public static function getInstance($backendType)
+ public static function getInstance(string $backendType)
{
self::loadDb();
if (!isset(self::$backendTypes[$backendType])) {
@@ -106,18 +106,18 @@ abstract class CourseBackend
/**
* @return string return display name of backend
*/
- public abstract function getDisplayName();
+ public abstract function getDisplayName(): string;
/**
* @returns \BackendProperty[] list of properties that need to be set
*/
- public abstract function getCredentialDefinitions();
+ public abstract function getCredentialDefinitions(): array;
/**
* @return boolean true if the connection works, false otherwise
*/
- public abstract function checkConnection();
+ public abstract function checkConnection(): bool;
/**
* uses json to setCredentials, the json must follow the form given in
@@ -126,36 +126,45 @@ abstract class CourseBackend
* @param array $data assoc array with data required by backend
* @returns bool if the credentials were in the correct format
*/
- public abstract function setCredentialsInternal($data);
+ public abstract function setCredentialsInternal(array $data): bool;
/**
* @return int desired caching time of results, in seconds. 0 = no caching
*/
- public abstract function getCacheTime();
+ public abstract function getCacheTime(): int;
/**
* @return int age after which timetables are no longer refreshed should be
* greater then CacheTime
*/
- public abstract function getRefreshTime();
+ public abstract function getRefreshTime(): int;
/**
* Internal version of fetch, to be overridden by subclasses.
*
- * @param $roomIds array with remote IDs for wanted rooms
+ * @param $requestedRoomIds array with remote IDs for wanted rooms
* @return array a recursive array that uses the roomID as key
* and has the schedule array as value. A schedule array contains an array in this format:
* ["start"=>'JJJJ-MM-DD"T"HH:MM:SS',"end"=>'JJJJ-MM-DD"T"HH:MM:SS',"title"=>string]
*/
- protected abstract function fetchSchedulesInternal($roomId);
+ protected abstract function fetchSchedulesInternal(array $requestedRoomIds): array;
- private static function fixTime(&$start, &$end)
+ /**
+ * In case you want to sanitize or otherwise mangle a property for your backend,
+ * override this.
+ */
+ public function mangleProperty(string $prop, $value)
+ {
+ return $value;
+ }
+
+ private static function fixTime(string &$start, string &$end): bool
{
- if (!preg_match('/^\d+-\d+-\d+T\d+:\d+:\d+$/', $start) || !preg_match('/^\d+-\d+-\d+T\d+:\d+:\d+$/', $end))
+ if (!preg_match('/^(\d{2}|\d{4})-?\d{2}-?\d{2}-?T\d{1,2}:?\d{2}:?(\d{2})?$/', $start))
return false;
$start = strtotime($start);
$end = strtotime($end);
- if ($start >= $end)
+ if ($start === false || $end === false || $start >= $end)
return false;
$start = date('Y-m-d\TH:i:s', $start);
$end = date('Y-m-d\TH:i:s', $end);
@@ -166,14 +175,10 @@ abstract class CourseBackend
* Method for fetching the schedule of the given rooms on a server.
*
* @param array $requestedLocationIds array of room ID to fetch
- * @return array|bool array containing the timetables as value and roomid as key as result, or false on error
+ * @return array array containing the timetables as value and roomid as key as result, or false on error
*/
- public final function fetchSchedule($requestedLocationIds)
+ public final function fetchSchedule(array $requestedLocationIds): array
{
- if (!is_array($requestedLocationIds)) {
- $this->addError('No array of roomids was given to fetchSchedule', false);
- return false;
- }
if (empty($requestedLocationIds))
return array();
$requestedLocationIds = array_values($requestedLocationIds);
@@ -183,14 +188,13 @@ abstract class CourseBackend
array('locations' => $requestedLocationIds));
$returnValue = [];
$remoteIds = [];
- while ($row = $dbquery1->fetch(PDO::FETCH_ASSOC)) {
- //Check if in cache if lastUpdate is null then it is interpreted as 1970
- if ($row['lastcalendarupdate'] + $this->getCacheTime() > $NOW) {
- $returnValue[$row['locationid']] = json_decode($row['calendar']);
- } else {
+ foreach ($dbquery1 as $row) {
+ // Check if in cache - if lastUpdate is null then it is interpreted as 1970
+ if ($row['lastcalendarupdate'] + $this->getCacheTime() < $NOW) {
$remoteIds[$row['locationid']] = $row['serverlocationid'];
}
-
+ // Always add to return value - if updating fails, we better use the stale data than nothing
+ $returnValue[$row['locationid']] = json_decode($row['calendar'], true);
}
// No need for additional round trips to backend
if (empty($remoteIds)) {
@@ -211,7 +215,7 @@ abstract class CourseBackend
'lastuse' => $NOW - $this->getRefreshTime(),
'minage' => $NOW - $this->getCacheTime(),
));
- while ($row = $dbquery4->fetch(PDO::FETCH_ASSOC)) {
+ foreach ($dbquery4 as $row) {
$remoteIds[$row['locationid']] = $row['serverlocationid'];
}
}
@@ -222,15 +226,12 @@ abstract class CourseBackend
// if, nothing bad will happen...
Database::exec("UPDATE locationinfo_locationconfig SET lastcalendarupdate = :time
WHERE lastcalendarupdate < :time AND serverid = :serverid AND serverlocationid IN (:slocs)", [
- 'time' => $NOW - $this->getCacheTime() / 2,
+ 'time' => $NOW - ($this->getCacheTime() - 60), // Protect for one minute max.
'serverid' => $this->serverId,
'slocs' => array_values($remoteIds),
]);
}
$backendResponse = $this->fetchSchedulesInternal(array_unique($remoteIds));
- if ($backendResponse === false) {
- return false;
- }
// Fetching might have taken a while, get current time again
$NOW = time();
@@ -254,15 +255,15 @@ abstract class CourseBackend
'serverid' => $this->serverId,
'serverlocationid' => $serverRoomId,
'ttable' => $value,
- 'now' => $NOW
+ 'now' => $NOW, // Set real "lastupdate" here
));
}
-
- unset($calendar);
}
+ unset($calendar);
// Add rooms that were requested to the final return value
foreach ($remoteIds as $location => $serverRoomId) {
- if (isset($backendResponse[$serverRoomId]) && in_array($location, $requestedLocationIds)) {
+ if (isset($backendResponse[$serverRoomId]) && is_array($backendResponse[$serverRoomId])
+ && in_array($location, $requestedLocationIds)) {
// Only add if we can map it back to our location id AND it was not an unsolicited coalesced refresh
$returnValue[$location] = $backendResponse[$serverRoomId];
}
@@ -271,7 +272,7 @@ abstract class CourseBackend
return $returnValue;
}
- public final function setCredentials($serverId, $data)
+ public final function setCredentials(int $serverId, array $data): bool
{
foreach ($this->getCredentialDefinitions() as $prop) {
if (!isset($data[$prop->property])) {
@@ -291,18 +292,9 @@ abstract class CourseBackend
}
/**
- * @return false if there was no error string with error message if there was one
- */
- public final function getError()
- {
- trigger_error('getError() is legacy; use getErrors()');
- return $this->error;
- }
-
- /**
- * @return array list of errors that occured during processing.
+ * @return array list of errors that occurred during processing.
*/
- public final function getErrors()
+ public final function getErrors(): array
{
return $this->errors;
}
@@ -367,7 +359,7 @@ abstract class CourseBackend
* @param string $response xml document to convert
* @return bool|array array representation of the xml if possible, false otherwise
*/
- protected function xmlStringToArray($response, &$error)
+ protected function xmlStringToArray(string $response, &$error)
{
$cleanresponse = preg_replace('/(<\/?)(\w+):([^>]*>)/', '$1$2$3', $response);
try {
@@ -379,8 +371,7 @@ abstract class CourseBackend
}
return false;
}
- $array = json_decode(json_encode((array)$xml), true);
- return $array;
+ return json_decode(json_encode((array)$xml), true);
}
}
@@ -403,7 +394,6 @@ class BackendProperty {
* Initialize additional fields of this class that are only required
* for rendering the server configuration dialog.
*
- * @param string $backendId target backend id
* @param mixed $current current value of this property.
*/
public function initForRender($current = null) {