summaryrefslogblamecommitdiffstats
path: root/modules-available/locationinfo/inc/icalcoursebackend.inc.php
blob: fba0866c9af1673ea0ebded736150bec4c0fadfc (plain) (tree)






















































































































































                                                                                                                             
<?php

abstract class ICalCourseBackend extends CourseBackend
{

	/** @var string */
	private $location;
	/** @var string */
	private $authMethod;
	/** @var string */
	private $user;
	/** @var string */
	private $pass;
	/** @var bool */
	private $verifyHostname;
	/** @var bool */
	private $verifyCert;
	/** @var bool|resource */
	private $curlHandle = false;

	/**
	 * Initialize values
	 *
	 * @param string $location
	 * @param bool $verifyCert
	 * @param bool $verifyHostname
	 * @param string $authMethod
	 * @param string $user
	 * @param string $pass
	 */
	protected function init($location, $verifyCert, $verifyHostname,
		$authMethod = 'NONE', $user = '', $pass = '')
	{
		$this->verifyCert = $verifyCert;
		$this->verifyHostname = $verifyHostname;
		if (strpos($location, '%ID%') === false) {
			$location .= '%ID%';
		}
		$this->location = $location;
		$this->authMethod = $authMethod;
		$this->user = $user;
		$this->pass = $pass;
	}

	/**
	 * @param int $roomId room id
	 * @param callable $errorFunc
	 * @return ICalEvent[]|null all events for this room in the range -7 days to +7 days, or NULL on error
	 */
	protected function downloadIcal($roomId)
	{
		if (!$this->isOK())
			return null;
		if ($this->curlHandle === false) {
			$this->curlHandle = curl_init();
		}

		$ical = new ICalParser(['filterDaysBefore' => 7, 'filterDaysAfter' => 7]);
		$options = [
			CURLOPT_WRITEFUNCTION => function ($ch, $data) use ($ical) {
				$ical->feedData($data);
				return strlen($data);
			},
			CURLOPT_FOLLOWLOCATION => true,
			CURLOPT_SSL_VERIFYHOST => $this->verifyHostname ? 2 : 0,
			CURLOPT_SSL_VERIFYPEER => $this->verifyCert ? 1 : 0,
			CURLOPT_URL => str_replace('%ID%', $roomId, $this->location),
			CURLOPT_TIMEOUT => 60,
			CURLOPT_CONNECTTIMEOUT => 4,
		];
		if ($this->authMethod !== 'NONE' && defined('CURLAUTH_' . $this->authMethod)) {
			$options[CURLOPT_HTTPAUTH] = constant('CURLAUTH_' . $this->authMethod);
			$options[CURLOPT_USERPWD] = $this->user;
			if (!empty($this->pass)) {
				$options[CURLOPT_USERPWD] .= ':' . $this->pass;
			}
		}

		curl_setopt_array($this->curlHandle, $options);

		$curlRet = curl_exec($this->curlHandle);
		if (!$curlRet) {
			$this->addError('Curl error: ' . curl_error($this->curlHandle) . ' for ' . $roomId, false);
		}
		$ical->finish();
		if (!$ical->isValid()) {
			if ($curlRet) {
				$this->addError("Did not find a VCALENDAR in returned data for $roomId", false);
			}
			return null;
		}
		return $ical->events();
	}

	public function fetchSchedulesInternal($requestedRoomIds): array
	{
		if (empty($requestedRoomIds) || !$this->isOK()) {
			return array();
		}
		$tTables = [];
		foreach ($requestedRoomIds as $roomId) {
			$data = $this->downloadIcal($roomId);
			if ($data === null) {
				$this->addError("Downloading ical for $roomId failed", false);
				continue;
			}
			foreach ($data as $event) {
				$tTables[$roomId][] = array(
					'title' => $this->toTitle($event),
					'start' => $event->dtstart,
					'end' => $event->dtend,
					'cancelled' => false, // ??? How
				);
			}
		}
		return $tTables;
	}

	/**
	 * Get a usable title from either SUMMARY or DESCRIPTION
	 * @param ICalEvent $event
	 */
	private function toTitle($event): string
	{
		$title = $event->summary;
		if (empty($title)) {
			$title = $event->description;
		}
		if (empty($title)) {
			$title = 'Unknown';
		}
		return (string)preg_replace([',(\s*<br\s*/?>\s*|\r|\n|\\\r|\\\n)+,', '/\\\\([,;:])/'], ["\n", '$1'], $title);
	}

	protected function isOK(): bool
	{
		if (empty($this->location)) {
			$this->addError("Credentials are not set", true);
			return false;
		}
		return true;
	}

	public function __destruct()
	{
		if ($this->curlHandle !== false) {
			curl_close($this->curlHandle);
		}
	}

}