Skip to content

Instantly share code, notes, and snippets.

@MarZab
Last active October 11, 2015 23:47
Show Gist options
  • Save MarZab/3937963 to your computer and use it in GitHub Desktop.
Save MarZab/3937963 to your computer and use it in GitHub Desktop.
Wise Timetable to iCalendar Converter
<?php
/*
* Wise Timetable to vCalendar Converter
* @Author Marko Zabreznik
* @copyright Marko Zabreznik
* @license http://www.gnu.org/licenses/gpl-3.0.html GNU/GPL
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
* PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Usage: urnik.php?c=[id][,id]...
* id is number of the course
*
*/
define('LOCALE', 'Slovenian');
define('URL', 'http://feri.um.si/urniki5/courses.php');
/* */
date_default_timezone_set('UTC');
setlocale(LC_ALL, LOCALE);
// do a post request with APC caching
function do_cached_post_request($url, $data, $optional_headers = null){
$params = array('http' => array(
'method' => 'POST',
'content' => $data
));
if ($optional_headers !== null)
$params['http']['header'] = $optional_headers;
// maybe get from APC
$hash = md5(serialize($params));
if (function_exists('apc_fetch') && $response = apc_fetch($hash))
return $response;
$fp = @fopen($url, 'rb', false, stream_context_create($params));
if (!$fp)
throw new Exception("Problem with $url, $php_errormsg");
$response = @stream_get_contents($fp);
if ($response === false) {
throw new Exception("Problem reading data from $url, $php_errormsg");
}
//$response = iconv('Windows-1250', 'UTF-8', $response); // očitno so popravli to
// store to APC
if (function_exists('apc_add'))
apc_add($hash, $response, 360 );
return $response;
}
/* */
// get courses from url
$courses='';
foreach(explode(',',$_GET['c']) as $course)
if(is_numeric($course)) $courses[]=$course;
if(empty($courses))
die('not enought data');
// get courses from Wise Timetable server
$data = do_cached_post_request(URL,'show_week=0&courses_values='.implode('%2C',$courses));
// get data from HTML
preg_match_all('/span class="caption">(.*?)<\/span/is', $data, $titles);
preg_match_all('/\/thead>(.*?)<\/table/is', $data, $tables);
if (!isset($_GET['debug'])) {
header("Content-Type: text/calendar; charset=utf-8");
header('Content-Disposition: attachment; filename="feri-' . implode('-',$courses). '.ical"');
} else {
header("Content-Type: text/plain; charset=utf-8");
}
// VCalendar Header
$out = <<<EOT
BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//hxcal//NONSGML Version 1//EN
EOT;
function escapeString($string) {
return preg_replace('/([\,;])/','\\\$1', $string);
}
// parse courses
$it = 0;
foreach($tables[1] as $table) {
$table = explode('class="data"',$table);
$title = escapeString(mb_convert_case(trim($titles[1][$it]), MB_CASE_TITLE, 'UTF-8'));
// parse events
foreach($table as $trow){
if (!preg_match_all('/td class="wholeCell">(.*?)<\/td/is', $trow, $cells))
continue;
$cells = $cells[1];
$time = explode(' - ',$cells[2]);
$start = strtotime($cells[1].' '.$time[0]. ' Europe/Ljubljana');
$dtstart = date('Ymd\THis', $start);
$end = strtotime($cells[1].' '.$time[1]. ' Europe/Ljubljana');
$dtend = date('Ymd\THis',$end);
$cells[6] = escapeString (mb_convert_case($cells[6], MB_CASE_TITLE, 'UTF-8'));
$cells[3] = escapeString( $cells[3] );
$cells[4] = escapeString( $cells[4] );
$cells[5] = escapeString( $cells[5] );
$cells[6] = escapeString( $cells[6] );
$out.= <<<EOT
BEGIN:VEVENT
DTSTART:{$dtstart}Z
DTEND:{$dtend}Z
LOCATION:{$cells[3]}
DESCRIPTION:{$cells[4]}: {$cells[6]} za {$cells[5]} ob {$time[0]}
SUMMARY:$title
END:VEVENT
EOT;
}
$it++;
}
$out.= "END:VCALENDAR".PHP_EOL;
echo str_replace("\n","\r\n",$out);
// end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment