diff options
Diffstat (limited to 'modules-available/locationinfo/inc/coursebackend.inc.php')
-rw-r--r-- | modules-available/locationinfo/inc/coursebackend.inc.php | 98 |
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) { |