summaryrefslogblamecommitdiffstats
path: root/modules-available/locationinfo/inc/coursebackend/coursebackend_hisinone.inc.php
blob: 82efae8743c98491cee3abf34cc702d2268d3bdd (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11

     
                                                  
 


                                       



                                    
 
 
                                                     
         
                                              
                                                                 
                                     
                 
 
                                                                                     


                                                                
                            
         
 
                                                  


                                                                 




                                                                           
                                                     
         











                                                                                                                                
                 
                              
         
 
                                         
         

                                                                         

                                     





                                                                                                          
                 
                             

         
           

                                                                                                              
           
                                              
         


                                                        
 
                                                                                          
                                 



                                                                                    
                                                       

                                                                                


                                                                 

                  
                                                               
 
                                                    
                                                                                               
                 

                                        
                                                                                                                         


                                       
         
 

                                      
                               

         




                                        





                                        
                                                                 
         

                                               

                              
                                                        


                                                                                              
                                         
                         






                                                                          
                         
                 
                                

         
           

                                                                
           
                                        
         


                                                     
                 

                                           
                 
                                                                                                                     
         
 






                                                      
 
<?php

class CourseBackend_HisInOne extends CourseBackend
{
	private $location;
	private $verifyHostname = true;
	private $verifyCert = true;
	/**
	 * @var bool|resource
	 */
	private $curlHandle = false;


	public function setCredentialsInternal($data)
	{
		if (empty($data['baseUrl'])) {
			$this->addError("No url is given", true);
			return false;
		}

		$this->location = $this->mangleProperty('baseUrl', $data['baseUrl']);
		$this->verifyHostname = $data['verifyHostname'];
		$this->verifyCert = $data['verifyCert'];

		return true;
	}

	public function getCredentialDefinitions()
	{
		return [
			new BackendProperty('baseUrl', 'string'),
			new BackendProperty('verifyCert', 'bool', true),
			new BackendProperty('verifyHostname', 'bool', true)
		];
	}

	public function mangleProperty($prop, $value)
	{
		if ($prop === 'baseUrl') {
			// Update form SOAP to iCal url
			if (preg_match(',^(http.*?)/qisserver,', $value, $out)) {
				$value = $out[1] . '/qisserver/pages/cm/exa/timetable/roomScheduleCalendarExport.faces?roomId=';
			} elseif (preg_match(',(.*[/=])\d*$', $value, $out)) {
				$value = $out[1];
			} elseif (substr_count($value, '/') <= 3) {
				if (substr($value, -1) !== '/') {
					$value .= '/';
				}
				$value .= 'qisserver/pages/cm/exa/timetable/roomScheduleCalendarExport.faces?roomId=';
			}
		}
		return $value;
	}

	public function checkConnection()
	{
		if (empty($this->location)) {
			$this->addError("Credentials are not set", true);
			return false;
		}
		// Unfortunately HisInOne returns an internal server error if you pass an invalid roomId.
		// So we just try a bunch and see if anything works. Even if this fails, using
		// the backend should work, given the URL is actually correct.
		foreach ([60, 100, 5, 10, 50, 110, 200, 210, 250, 300, 333, 500, 1000, 2000] as $roomId) {
			if ($this->downloadIcal($roomId) !== null)
				return true;
		}
		return false;
	}

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

		$ical = new ICalParser(['filterDaysBefore' => 7, 'filterDaysAfter' => 7]);
		$options = array(
			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 => $this->location . $roomId,
			CURLOPT_TIMEOUT => 60,
			CURLOPT_CONNECTTIMEOUT => 4,
		);

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

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

	public function getCacheTime()
	{
		return 30 * 60;
	}

	public function getRefreshTime()
	{
		return 60 * 60;
	}


	public function getDisplayName()
	{
		return "HisInOne";
	}

	public function fetchSchedulesInternal($requestedRoomIds)
	{
		if (empty($requestedRoomIds)) {
			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)
	{
		$title = $event->summary;
		if (empty($title)) {
			$title = $event->description;
		}
		if (empty($title)) {
			$title = 'Unknown';
		}
		return preg_replace([',(\s*<br\s*/?>\s*|\r|\n|\\\r|\\\n)+,', '/\\\\([,;:])/'], ["\n", '$1'], $title);
	}

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

}