Last active
December 23, 2015 03:29
-
-
Save GuillaumeDerval/6574088 to your computer and use it in GitHub Desktop.
Script permettant de créer des fichiers aux format ICS à partir du module ADE de l'UCL.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/* | |
UCL2ICS v2.3 | |
Guillaume Derval, basé sur le travail de ploki (forum-epl) | |
- Fix general | |
- Remise en forme du code (meme si Nicolas dit que ce n'est pas suffisant ;-) ) | |
- Ajout de la possibilite d'enlever des cours | |
- On ne sauvegarde plus rien sur le disque | |
- UTF-8 inside | |
- Lien d'abonnement | |
- Colle les cours dédoublés (voir plus bas) | |
- Emails des formateurs et respect du format iCalendar pour ceux-ci | |
- Nouveau login ADE | |
(NB: merci de ne pas porter attention à la qualité du code, tout ceci à été fait itérativement et de manière presque irréfléchie :D) | |
*/ | |
ini_set('display_errors', false); | |
error_reporting(E_NONE); | |
function CutDate($date) | |
{ | |
$ar = explode("/",$date); | |
return $ar[2].$ar[1].$ar[0]; | |
} | |
function CatHeure($heure) | |
{ | |
$heures = explode('h',$heure); //0=h,1=min | |
return $heures; | |
} | |
function HFin($debut,$duree) | |
{ | |
$duree = str_replace('min','',$duree); | |
$duree_ar = explode('h',$duree); | |
$dureeh = $duree_ar[0]; // comme il y a des cours de la forme 15min, on pourrait donc avoir des minutes dans duree_ar[0] | |
$dureem = (isset($duree_ar[1]))?$duree_ar[1]:$duree_ar[0]; // si on a une duree de la forme 2h , dureem est vide (0 pour une addition) | |
$finm = $debut[1]+$dureem; | |
if(($finm)>=60) { | |
$debut[0]=$debut[0]+1; | |
$finm = $finm-60; | |
} | |
$finm = (strlen($finm)<2)?'0'.$finm:$finm;// on rajoute le 0 si l'heure de fin est 8h09 par exemple | |
$finh = $debut[0]+$dureeh; // on suppose qu'on aura jamais cours après minuit, et qu'on inclu pas les s*n* dans l'edt ADE... | |
$finh = (strlen($finh)<2)?'0'.$finh:$finh; // la meme que pour les minutes | |
$final = $finh.$finm.'00'; // la forme ics est hhmmss, donc on met ss à 00 | |
return $final; | |
} | |
/* | |
codes and weeks must be strings (array glued with ,) | |
*/ | |
function getCoursesFromCodes($codes,$weeks,$projectID,$dh) | |
{ | |
$url = 'http://horaire.sgsi.ucl.ac.be:8080'; | |
// CREATION DU COOKIE | |
$id= time().rand(0,100000000); | |
$fh = fopen("cookie_".$id.".txt","w"); | |
fclose($fh); | |
// OUVERTURE DE SESSION | |
$ch1 = curl_init(); | |
curl_setopt($ch1, CURLOPT_HEADER, 0); | |
//curl_setopt($ch1, CURLOPT_COOKIEFILE, realpath("basecookie.txt")); | |
curl_setopt($ch1, CURLOPT_POST, true); | |
curl_setopt($ch1, CURLOPT_POSTFIELDS, "showTab=true&showTabInstructors=true&showImage=true&iE=true&displayConfId=46&display=true&x=&y=&isClickable=true&changeOptions=true&displayType=0&showLoad=false&showTreeCategory2=true&showTabActivity=true&showTabWeek=false&showTabDay=false&showTabStage=false&showTabDate=true&showTabHour=true&showTabDuration=true&aC=true&aTy=true&aUrl=false&aSize=false&aMx=false&aSl=false&aCx=false&aCy=false&aCz=false&aTz=false&aN=false&aNe=false&showTabTrainees=false&sC=false&sTy=false&sUrl=false&sE=false&sM=false&sJ=false&sA1=false&sA2=false&sZp=false&sCi=false&sSt=false&sCt=false&sT=false&sF=false&sCx=false&sCy=false&sCz=false&sTz=false&showTabRooms=true&roC=false&roTy=false&roUrl=false&roE=false&roM=false&roJ=false&roA1=false&roA2=false&roZp=false&roCi=false&roSt=false&roCt=false&roT=false&roF=false&roCx=false&roCy=false&roCz=false&roTz=false&showTabResources=false&reC=false&reTy=false&reUrl=false&reE=false&reM=false&reJ=false&reA1=false&reA2=false&reZp=false&reCi=false&reSt=false&reCt=false&reT=false&reF=false&reCx=false&reCy=false&reCz=false&reTz=false&showTabCategory5=false&c5C=false&c5Ty=false&c5Url=false&c5E=false&c5M=false&c5J=false&c5A1=false&c5A2=false&c5Zp=false&c5Ci=false&c5St=false&c5Ct=false&c5T=false&c5F=false&c5Cx=false&c5Cy=false&c5Cz=false&c5Tz=false&showTabCategory6=false&c6C=false&c6Ty=false&c6Url=false&c6E=false&c6M=false&c6J=false&c6A1=false&c6A2=false&c6Zp=false&c6Ci=false&c6St=false&c6Ct=false&c6T=false&c6F=false&c6Cx=false&c6Cy=false&c6Cz=false&c6Tz=false&showTabCategory7=false&c7C=false&c7Ty=false&c7Url=false&c7E=false&c7M=false&c7J=false&c7A1=false&c7A2=false&c7Zp=false&c7Ci=false&c7St=false&c7Ct=false&c7T=false&c7F=false&c7Cx=false&c7Cy=false&c7Cz=false&c7Tz=false&showTabCategory8=false&c8C=false&c8Ty=false&c8Url=false&c8E=false&c8M=false&c8J=false&c8A1=false&c8A2=false&c8Zp=false&c8Ci=false&c8St=false&c8Ct=false&c8T=false&c8F=false&c8Cx=false&c8Cy=false&c8Cz=false&c8Tz=false"); | |
curl_setopt($ch1, CURLOPT_COOKIEJAR, realpath("cookie_".$id.".txt")); | |
curl_setopt($ch1, CURLOPT_RETURNTRANSFER, true); | |
curl_setopt($ch1, CURLOPT_USERAGENT, 'Mozilla 5/0'); // utf-8 | |
curl_setopt($ch1, CURLOPT_URL, $url.'/ade/custom/modules/plannings/direct_planning.jsp?weeks='.$weeks.'&code='.$codes.'&login=etudiantbv&password=studentbv&projectId='.$projectID); | |
curl_exec($ch1); | |
curl_close($ch1); | |
// CHARGEMENT DE LA SESSION ET AFFICHAGE EN TABLEAU | |
$ch2 = curl_init(); | |
curl_setopt($ch2, CURLOPT_HEADER, 0); | |
curl_setopt($ch2, CURLOPT_COOKIEFILE, realpath("cookie_".$id.".txt")); | |
curl_setopt($ch2, CURLOPT_RETURNTRANSFER, true); | |
curl_setopt($ch2, CURLOPT_USERAGENT, 'Mozilla 5/0'); // utf-8 | |
curl_setopt($ch2, CURLOPT_URL, $url.'/ade/custom/modules/plannings/info.jsp?order=slot'); | |
$horaire = curl_exec($ch2); | |
curl_close($ch2); | |
// SUPRESSION DU COOKIE | |
unlink("cookie_".$id.".txt"); | |
//echo $horaire; | |
// TRAITEMENT DE L'HORAIRE | |
$horaire = str_replace('<BODY>','',$horaire); | |
$horaire = str_replace('&','&',$horaire); | |
$horaire = str_replace('&','&',$horaire); | |
$dom = new DOMDocument(); // creation d'un objet DOM pour lire le html | |
$dom->loadHTML($horaire) or die('erreur'); | |
$lignes = $dom->getElementsByTagName('tr'); // on recupere toute les lignes | |
$result = array(); | |
$cours = array(); | |
$i=0; | |
foreach ($lignes as $ligne) | |
{ | |
if($i>1) | |
{ | |
// les deux premiers tr sont des titres, osef | |
$content = $ligne->childNodes; | |
$noms = array('date','mat','heure','duree','nom','type','prof','profmail','salle'); | |
$entree = array(); | |
foreach($noms as $nomid => $nom) | |
$entree[$nom] = $content->item($nomid)->nodeValue; // attribution des valeurs aux variables | |
if($dh) | |
$entree['nom'] = ucfirst(mb_strtolower($entree['nom'], 'UTF-8')); | |
$entree['nom'] = preg_replace("# i #", ' I ', $entree['nom']); | |
$result[] = $entree; | |
$cours[$entree['mat']] = $entree['nom']; | |
} | |
$i++; | |
} | |
// Colle les cours dedoubles (Ex: cours d'anglais le lundi 23/09 de 08h30 à 9h30 et de 9h30 à 10h30, dans le meme local, avec le meme formateur) | |
for($i = 0; $i < count($result); $i++) | |
{ | |
for($j = $i+1; $j < count($result); $j++) | |
{ | |
if($result[$i]['date'] == $result[$j]['date'] && | |
$result[$i]['mat'] == $result[$j]['mat'] && | |
$result[$i]['salle'] == $result[$j]['salle'] && | |
$result[$i]['prof'] == $result[$j]['prof'] && | |
$result[$i]['nom'] == $result[$j]['nom']) | |
{ | |
$heuressI = CatHeure($result[$i]['heure']); | |
$heureDebutI = $heuressI[0].$heuressI[1]."00"; | |
$heureFinI = HFin($heuressI,$result[$i]['duree']); //hhmmss | |
$heuressJ = CatHeure($result[$j]['heure']); | |
$heureDebutJ = $heuressJ[0].$heuressJ[1]."00"; | |
$heureFinJ = HFin($heuressJ,$result[$j]['duree']); //hhmmss | |
$dureeI = explode('h',str_replace('min','',$result[$i]['duree'])); | |
$dureeJ = explode('h',str_replace('min','',$result[$j]['duree'])); | |
$nduree = $dureeI[0]*60+$dureeJ[0]*60; | |
if(isset($dureeI[1])) $nduree+=$dureeI[1]; | |
if(isset($dureeJ[1])) $nduree+=$dureeJ[1]; | |
$nduree = "".floor($nduree/60)."h".($nduree%60)."min"; | |
if($heureDebutI == $heureFinJ) | |
{ | |
$result[$i]['heure'] = $result[$j]['heure']; | |
$result[$i]['duree'] = $nduree; | |
unset($result[$j]); | |
$result = array_values($result); | |
} | |
else if($heureDebutJ == $heureFinI) | |
{ | |
$result[$i]['duree'] = $nduree; | |
unset($result[$j]); | |
$result = array_values($result); | |
} | |
} | |
} | |
} | |
return array($cours, $result); | |
} | |
function makeICS($horaire, $cours) | |
{ | |
$buf_ics = "BEGIN:VCALENDAR | |
VERSION:2.0 | |
PRODID:-//ETSIL 3//iCal 1.0//EN | |
CALSCALE:GREGORIAN | |
METHOD:PUBLISH | |
BEGIN:VTIMEZONE | |
TZID:Bruxelles\, Copenhague\, Madrid\, Paris | |
BEGIN:STANDARD | |
DTSTART:20001029T030000 | |
RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10 | |
TZNAME:Paris\, Madrid | |
TZOFFSETFROM:+0200 | |
TZOFFSETTO:+0100 | |
END:STANDARD | |
BEGIN:DAYLIGHT | |
DTSTART:20000326T020000 | |
RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=3 | |
TZNAME:Paris\, Madrid (heure d'été) | |
TZOFFSETFROM:+0100 | |
TZOFFSETTO:+0200 | |
END:DAYLIGHT | |
END:VTIMEZONE\n"; | |
// EXTRACTION DES DONNEES DU DOMDOCUMENT | |
$stamp_id = rand(10,59); | |
foreach ($horaire as $entree) | |
{ | |
if(!in_array($entree['mat'], $cours)) | |
continue; | |
$heuress = CatHeure($entree['heure']); // tableau avec heure en 0 et minute en 1 | |
$hfin = HFin($heuress,$entree['duree']); // hhmmss | |
$date = CutDate($entree['date']); // aaaammjj | |
$salle = $entree['salle']; | |
$coursN=$entree['nom']; | |
$buf_ics .= "BEGIN:VEVENT\n"; | |
$description = "Sigle: ".$entree['mat']; | |
$description .= "\\nType: ".$entree['type']; | |
$description .= "\n"; | |
$buf_ics .= "DESCRIPTION:".$description; | |
if($entree['prof'] != "") | |
{ | |
$buf_ics .= "ORGANIZER;CN=".$entree['prof'].":MAILTO:"; | |
if($entree['profmail'] != "") | |
$buf_ics .= str_replace(' ', ',', trim($entree['profmail'])); | |
else | |
$buf_ics .= "no@email.be"; | |
$buf_ics .= "\n"; | |
} | |
$buf_ics .= "DTSTAMP:20100130T1200".$stamp_id."Z\n"; | |
$buf_ics .= 'DTSTART;TZID="Bruxelles, Copenhague, Madrid, Paris":'.$date.'T'.$heuress[0].$heuress[1]."00\n"; | |
$buf_ics .= 'DTEND;TZID="Bruxelles, Copenhague, Madrid, Paris":'.$date.'T'.$hfin."\n"; | |
$buf_ics .= 'LOCATION:'.$salle."\n"; | |
$buf_ics .= "SUMMARY:".$coursN."\nEND:VEVENT\n"; | |
}; | |
$buf_ics .= "END:VCALENDAR"; | |
return $buf_ics; | |
} | |
if(!isset($_POST['horaire']) && !(isset($_GET['codes']) && isset($_GET['courses']) && isset($_GET['weeks']) && isset($_GET['project']))) | |
{ | |
//Nicolas, c'est rien que pour toi. | |
?> | |
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta charset="utf-8"> | |
<title>ADE to ICS</title> | |
<link rel="stylesheet" href="ade.css"> | |
</head> | |
<body> | |
<h1>UCL ADE to ICS<span id="version">v2.2</span></h1> | |
<form class="top" id="formulaire" method="post" action="ade.php"> | |
<?php | |
$semaines=''; | |
if(isset($_POST['semaines'])) | |
$semaines = htmlentities($_POST['semaines']); | |
else | |
{ | |
for ($i = 0; $i < 35; $i++) | |
$semaines .= ','.$i; | |
$semaines = ltrim($semaines,','); //supprime la premiere virgule | |
} | |
$codes = 'FSA13BA,minmap13,Majinfo13,LANGL1873,LFSAB1105'; | |
if(isset($_POST['codes'])) | |
$codes = htmlentities($_POST['codes']); | |
$projet = 16; | |
if(isset($_POST['projet'])) | |
$projet = (int)$_POST['projet']; | |
?> | |
<label for="codes">Codes cours (séparés par virgules) ou lien ADE donné par <a href="https://www.uclouvain.be/horaires-epl.html">l'outil horaire de l'EPL</a>: </label><br/><input type="text" name="codes" id="codes" size="120" value="<?php echo $codes;?>"/><br/> | |
<label for="semaines">Semaines désirées (séparées par virgules): </label><br/><input type="text" name="semaines" id="semaines" value="<?php echo $semaines; ?>" size="60"/><br/> | |
Nous sommes en S<?php echo (date("W")+14)%51; ?>. La premiere semaine du premier quadrimestre est la semaine 0, et celle du second quadrimestre est la semaine 19<br/> | |
<label for="projet">ID du projet (pour 2013-2014, c'est 16): </label><input type="text" name="projet" id="projet" value="<?php echo $projet; ?>"/><br/> | |
<input type="checkbox" name="deshurler" id="deshurler" checked="checked"/> <label for="deshurler">dé-HURLER le nom des cours</label><br/> | |
<input type="submit" value="Lancer" /> | |
</form> | |
<?php | |
if (isset($_POST['codes']) && $_POST['codes']!='') | |
{ | |
// PARAMETRES ------------------------------------------------------------------------------------------------------------- | |
$codes = $_POST['codes']; | |
if(strpos($codes, 'http') !== false) | |
{ | |
$t = explode('&', $codes); | |
foreach($t as $v) | |
{ | |
$t2 = explode('=', $v); | |
if(count($t2) == 2 && $t2[0] == 'code') | |
{ | |
$codes = $t2[1]; | |
break; | |
} | |
} | |
} | |
$semaines = $_POST['semaines']; | |
$projectID = isset($_POST['projet']) ? (int)$_POST['projet'] : 16; | |
$dh = isset($_POST['deshurler']); | |
// ----------------------------------------------------------------------------------------------------------------------------- | |
$t = getCoursesFromCodes($codes,$semaines,$projectID,$dh); | |
$cours = $t[0]; | |
$result = $t[1]; | |
//exclure les cours inutiles | |
?> | |
<h2>Choisissez les cours à inclure</h2> | |
<form class="top" id="formulaire" method="post" action="ade.php"> | |
<input type="hidden" name="horaire" value="<?php echo htmlspecialchars(json_encode($result), ENT_COMPAT, "UTF-8");?>"/> | |
<input type="hidden" name="codes" value="<?php echo htmlspecialchars($codes, ENT_COMPAT, "UTF-8"); ?>"/> | |
<input type="hidden" name="semaines" value="<?php echo htmlspecialchars($semaines, ENT_COMPAT, "UTF-8"); ?>"/> | |
<input type="hidden" name="projet" value="<?php echo htmlspecialchars($projet, ENT_COMPAT, "UTF-8"); ?>"/> | |
<input type="hidden" name="dh" value="<?php echo (isset($_POST['deshurler']) ? '1':'0'); ?>"/> | |
<table> | |
<?php | |
asort($cours); | |
foreach($cours as $mat => $nom) | |
{ | |
$mat = htmlspecialchars($mat, ENT_COMPAT, "UTF-8"); | |
$nom = htmlspecialchars($nom, ENT_COMPAT, "UTF-8"); | |
echo "<tr><td><input type='checkbox' name='cours[]' value='$mat' id='cours$mat' checked='checked'/></td><td><label for='cours$mat'>$mat</label></td><td><label for='cours$mat'>$nom</label></td></tr>"; | |
} | |
?> | |
</table> | |
<input type="submit" value="Go!"/> <input type="checkbox" name="getlink" id="getlink" checked="checked"/> <label for="getlink">Recevoir le lien d'abonnement</label> | |
</form> | |
<?php | |
} | |
?> | |
<div id="footer">Par <a href="http://www.guillaumederval.be">Guillaume Derval</a>, basé sur le code de Ploki<br/><a href="https://gist.github.com/GuillaumeDerval/6574088">Code source!</a></div> | |
</body> | |
</html> | |
<?php | |
} | |
else if(isset($_POST['horaire']) && !isset($_POST['getlink'])) | |
{ | |
$horaire = json_decode(stripslashes($_POST['horaire']), true); | |
header('Content-type: text/calendar; charset=utf-8'); | |
header('Content-Disposition: inline; filename=calendar.ics'); | |
echo makeICS($horaire, $_POST['cours']); | |
} | |
else if(isset($_POST['horaire']) && isset($_POST['getlink'])) | |
{ | |
$cours = $_POST['cours']; | |
foreach($cours as $key => $val) | |
$cours[$key] = urlencode(preg_replace('#[^A-Za-z0-9_\-=]#isU', '', $val)); | |
$cours = array_unique($cours); | |
$cours = implode(',', $cours); | |
$codes = explode(',', $_POST['codes']); | |
foreach($codes as $key => $val) | |
$codes[$key] = preg_replace('#[^A-Za-z0-9_\-]#isU', '', $val); | |
$codes = implode(',', $codes); | |
$weeks = explode(',', $_POST['semaines']); | |
foreach($weeks as $key => $val) | |
$weeks[$key] = preg_replace('#[^0-9]#isU', '', $val); | |
$weeks = implode(',', $weeks); | |
$link = "http://www.guillaumederval.be/ade.php?codes=".$codes."&courses=".$cours."&weeks=".$weeks."&project=".(int)$_POST['projet']."&dh=".(isset($_POST['dh']) ? '1':'0'); | |
?> | |
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta charset="utf-8"> | |
<title>ADE to ICS</title> | |
<link rel="stylesheet" href="ade.css"> | |
</head> | |
<body> | |
<h1>UCL ADE to ICS<span id="version">v2.2</span></h1> | |
<div class="likeform"> | |
Le lien d'abonnement est <br/> | |
<div class="monospace"> | |
<a href="<?php echo htmlspecialchars($link, ENT_COMPAT, "UTF-8");?>"><?php echo htmlspecialchars($link, ENT_COMPAT, "UTF-8");?></a> | |
</div> | |
Vous pouvez l'utiliser pour une mise à jour automatique de vos calendriers!<br/> | |
<br/> | |
Sous Apple iCal, faites Fichier->Nouvel Abonnement Calendar.<br/> | |
<br/> | |
Sur Google Agenda, faites Autres agenda->appuyez sur la petite flèche->Ajouter par URL.<br/> | |
Le lien ne fonctionne pas? Google Agenda ne supporte pas les liens trop longs; passer le lien dans un url-shortener comme <a href="http://www.bit.ly">Bit.ly</a> résoudra le problème.<br/> | |
<br/> | |
De cette manière, si un cours apparait ou disparait de ADE, la même action se déroulera sur votre calendrier ;-)<br/> | |
Vous pouvez également directement cliquer sur le lien pour télécharger le fichier ICS. | |
</div> | |
<div id="footer">Par <a href="http://www.guillaumederval.be">Guillaume Derval</a>, basé sur le code de Ploki<br/><a href="https://gist.github.com/GuillaumeDerval/6574088">Code source!</a></div> | |
</body> | |
</html> | |
<?php | |
} | |
else if(isset($_GET['codes']) && isset($_GET['courses']) && isset($_GET['weeks']) && isset($_GET['project'])) | |
{ | |
$courses = explode(',',$_GET['courses']); | |
foreach($cours as $key => $val) | |
$courses[$key] = preg_replace('#[^A-Za-z0-9_\-]#isU', '', $val); | |
$codes = explode(',',$_GET['codes']); | |
foreach($codes as $key => $val) | |
$codes[$key] = preg_replace('#[^A-Za-z0-9_\-]#isU', '', $val); | |
$codes = implode(',', $codes); | |
$weeks = explode(',',$_GET['weeks']); | |
foreach($codes as $key => $val) | |
$weeks[$key] = preg_replace('#[^0-9]#isU', '', $val); | |
$weeks = implode(',', $weeks); | |
$project = (int)$_GET['project']; | |
$t = getCoursesFromCodes($codes,$weeks,$project,isset($_GET['dh']) && $_GET['dh'] == 1); | |
$horaire = $t[1]; | |
header('Content-type: text/calendar; charset=utf-8'); | |
header('Content-Disposition: inline; filename=calendar.ics'); | |
echo makeICS($horaire, $courses); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment