diff --git a/build/router/controller/ics.php b/build/router/controller/ics.php
new file mode 100644
index 0000000..757836a
--- /dev/null
+++ b/build/router/controller/ics.php
@@ -0,0 +1,57 @@
+ Calling URI
+ *
+ */
+ public function __construct($url){
+ $this->diplome_id = $url['diplome_id'];
+ }
+
+
+ /* CALL
+ *
+ */
+ public function download(){
+
+ /* [1] Check .ics file
+ =========================================================*/
+ /* (1) Set file name */
+ $file_name = __ROOT__."/tmp/".$this->diplome_id.".ics";
+
+ /* (2) Check if exists */
+ if( !file_exists($file_name) )
+ die("An error occured. Please contact the developers.\n");
+
+
+ /* [2] Display file
+ =========================================================*/
+ /* (1) Headers */
+ header('Content-Type: text/calendar; charset=utf-8');
+ header('Content-Disposition: attachment; filename='.$this->diplome_id);
+
+ /* (2) Body */
+ readfile($file_name);
+
+
+ }
+
+ /* POST-CALL
+ *
+ */
+ public function __destruct(){
+
+ }
+
+
+
+ }
diff --git a/build/router/controller/page.php b/build/router/controller/page.php
new file mode 100644
index 0000000..026c9fc
--- /dev/null
+++ b/build/router/controller/page.php
@@ -0,0 +1,63 @@
+ Calling URI
+ *
+ */
+ public function __construct($url){
+ $this->pagename = $url['page'];
+
+ }
+
+
+ /* CALL
+ *
+ */
+ public function home(){
+
+
+ /* [1] Fetch configuration
+ =========================================================*/
+ /* (1) Get config */
+ try{
+ $config = Config::load("http://sciences.univ-pau.fr/edt/_ressource.js", "http://sciences.univ-pau.fr/edt/_periode.js");
+
+ /* (2) Error management */
+ }catch(\Exception $e){
+ die("An error occured. Please contact the developers.\n");
+ }
+
+ /* (3) Get the diplome list */
+ $diplomes = $config->getDiplomes();
+
+
+
+ /* [2] Display the links
+ =========================================================*/
+ foreach($diplomes as $id=>$name){
+ echo "$name
";
+
+ }
+
+ }
+
+ /* POST-CALL
+ *
+ */
+ public function __destruct(){
+
+ }
+
+
+
+ }
diff --git a/build/router/controller/redirect.php b/build/router/controller/redirect.php
new file mode 100644
index 0000000..31c0d26
--- /dev/null
+++ b/build/router/controller/redirect.php
@@ -0,0 +1,34 @@
+ Calling URI
+ *
+ */
+ public function __construct($url){
+ }
+
+
+ /* CALL
+ *
+ */
+ public function homepage(){
+ header('Location: /');
+ }
+
+ /* POST-CALL
+ *
+ */
+ public function __destruct(){
+
+ }
+
+
+
+ }
diff --git a/build/router/core/ControllerFactory.php b/build/router/core/ControllerFactory.php
new file mode 100644
index 0000000..ad2d642
--- /dev/null
+++ b/build/router/core/ControllerFactory.php
@@ -0,0 +1,51 @@
+ Nom du controller
+ *
+ * @return exists Si oui ou non le controller existe
+ *
+ */
+ public static function checkController($controller){
+ /* (1) Check type + pattern */
+ if( !is_string($controller) || !preg_match('/^[A-Za-z_]\w+$/', $controller) )
+ return false;
+
+ /* (2) On vérifie que la classe existe */
+ if( !file_exists(__BUILD__."/router/controller/$controller.php") )
+ return false;
+
+ /* (3) Sinon il existe */
+ return true;
+ }
+
+
+
+ /* INSTANCIE UN CONTROLLER
+ *
+ * @controller Nom du controller
+ * @arguments [OPTIONNEL] Arguments à passer au constructeur
+ *
+ * @return instance Instance du controller en question
+ *
+ */
+ public static function getController($controller, $arguments=[]){
+ /* (1) On vérifie l'existance du controller */
+ if( !self::checkController($controller) )
+ return false;
+
+ /* (2) On récupère la classe */
+ $class_name = "\\router\\controller\\$controller";
+
+ /* (3) On retourne une instance */
+ return new $class_name($arguments);
+ }
+
+ }
diff --git a/build/router/core/Route.php b/build/router/core/Route.php
new file mode 100644
index 0000000..83bfd95
--- /dev/null
+++ b/build/router/core/Route.php
@@ -0,0 +1,100 @@
+ Pattern correspondant a la route
+ * @controller Controller de la route
+ * @method Methode du controller
+ *
+ * @return instance Retour de l'instance courante
+ *
+ =========================================================*/
+ public function __construct($pattern=null, $controller=null, $method=null){
+ // Note: all arguments must be verified by 'Router->add' method
+
+ /* (1) Pattern -> regex format */
+ $this->pattern = "/^$pattern$/";
+
+ /* (2) Controller */
+ $this->controller = $controller;
+
+ /* (3) Controller's method */
+ $this->method = $method;
+
+ /* (4) Initialize matches */
+ $this->matches = [];
+
+ }
+
+
+
+ /* [3] Checks if route matches URL
+ *
+ * @url URL
+ *
+ * @return matches If matches URL
+ *
+ =========================================================*/
+ public function match($url){
+
+ /* (1) If doesn't matches @url -> false */
+ if( !preg_match($this->pattern, $url, $matches) )
+ return false;
+
+ /* (2) Return only named matches */
+ foreach($matches as $name=>$match)
+ if( !is_numeric($name) )
+ $this->matches[$name] = $match;
+
+ /* (4) Add complete URL */
+ $this->matches['__URL__'] = $url;
+
+ /* (5) Return status */
+ return true;
+ }
+
+
+ /* [4] Method call
+ *
+ * @return response Response
+ *
+ =========================================================*/
+ public function call(){
+ /* (1) Instanciate controller */
+ $instance = ControllerFactory::getController($this->controller, $this->matches);
+
+ /* (2) Launch method & catch response */
+ $response = call_user_func([$instance, $this->method]);
+
+ /* (3) Call controller's destructor */
+ $instance = null;
+
+ /* (4) Return response */
+ return $response;
+ }
+
+ }
diff --git a/build/router/core/Router.php b/build/router/core/Router.php
new file mode 100644
index 0000000..f2200a7
--- /dev/null
+++ b/build/router/core/Router.php
@@ -0,0 +1,333 @@
+run();
+
+ }
+
+
+ /* [3] Constructor
+ *
+ * @url Current URL
+ *
+ * @return instance Instance du routeur
+ *
+ =========================================================*/
+ public function __construct($url=null){
+ /* (1) Checks arguments
+ ---------------------------------------------------------*/
+ /* (1) Default value if incorrect */
+ $this->url = is_string($url) ? $url : '';
+
+ /* (2) Add first '/' if missing */
+ if( !preg_match('/^\//', $url) )
+ $this->url = '/'.$this->url;
+
+
+ /* (2) Loads configuration
+ ---------------------------------------------------------*/
+ /* (1) Tries to load configuration */
+ $this->cnf = self::loadConfig();
+
+ /* (2) If error occurs, throw Exception */
+ if( is_null($this->cnf) )
+ throw new \Exception("[Router] Configuration file error found");
+
+
+ /* (3) Set allowed HTTP methods
+ ---------------------------------------------------------*/
+ /* (1) If not defined */
+ if( !isset($this->cnf['methods']) )
+ throw new \Exception('[Router] Configuration file error, \'methods\' clause missing');
+
+ /* (2) Try to clean methods */
+ $this->http_methods = self::cleanMethods($this->cnf['methods']);
+
+ /* (3) Manage error */
+ if( is_null($this->http_methods) )
+ throw new \Exception('[Router] Configuration file error. \'methods\' must be an array of HTTP methods ["GET", "POST", ...]');
+
+
+ /* (4) Initialize routes
+ ---------------------------------------------------------*/
+ /* (1) Init routes */
+ $this->routes = [];
+
+ foreach($this->http_methods as $method)
+ $this->routes[$method] = [];
+
+ /* (2) Default configuration if missing */
+ if( !isset($this->cnf['routes']) || !is_array($this->cnf['routes']) )
+ $this->cnf['routes'] = [];
+
+
+ /* (5) Loads each route
+ ---------------------------------------------------------*/
+ foreach($this->cnf['routes'] as $pattern=>$route){
+
+ /* (1) If missing (required) parameters */
+ if( !isset($route['controller']) )
+ continue;
+
+ /* (2) Default value for 'methods' */
+ ( !isset($route['methods']) || !is_array($route['methods']) ) && ($route['methods'] = $this->http_methods);
+
+ /* (3) Default value for 'arguments' */
+ ( !isset($route['arguments']) || !is_array($route['arguments']) ) && ($route['arguments'] = []);
+
+ /* (4) Add route */
+ $added = $this->add($pattern, $route['controller'], $route['arguments']);
+
+ // if error -> next
+ if( $added === false )
+ continue;
+
+
+ /* (5) Add route for each method */
+ foreach($route['methods'] as $method)
+ if( in_array($method, $this->http_methods) )
+ $this->routes[$method][] = $added;
+
+ }
+
+
+ }
+
+
+
+
+ /* [4] Adds a route
+ *
+ * @pattern URL pattern with {somevar} variables within
+ * @controller Controller name + method "controllername:methodname"
+ * @arguments List of pattern's arguments and their RegExp composition (default is alphanumeric)
+ *
+ * @return route New instance of Route || false on error
+ *
+ =========================================================*/
+ public function add($pattern=null, $controller=null, $arguments=[]){
+
+ /* (1) Format and check pattern
+ ---------------------------------------------------------*/
+ /* (1) If not a string */
+ if( !is_string($pattern) )
+ return false;
+
+ /* (2) Format pattern and check result */
+ $pattern = self::formatPattern($pattern, $arguments);
+
+ if( $pattern === false )
+ return false;
+
+
+ /* (2) Check controller
+ ---------------------------------------------------------*/
+ /* (1) Check default type */
+ if( !is_string($controller) || !preg_match('/^([A-Za-z_]\w+):([A-Za-z_]\w+)$/', $controller, $c_matches) )
+ return false;
+
+ /* (2) Check existence */
+ if( !ControllerFactory::checkController($c_matches[1]) )
+ return false;
+
+
+ /* (3) Check method
+ ---------------------------------------------------------*/
+ if( !method_exists('\\router\\controller\\'.$c_matches[1], $c_matches[2]) )
+ return false;
+
+
+ /* (4) Return new route
+ ---------------------------------------------------------*/
+ return new Route($pattern, $c_matches[1], $c_matches[2]);
+ }
+
+
+
+
+ /* [5] Router launch
+ *
+ =========================================================*/
+ public function run(){
+ /* (1) Manage HTTP method
+ ---------------------------------------------------------*/
+ /* (1) Fetch HTTP method */
+ $httpMethod = $_SERVER['REQUEST_METHOD'];
+
+ /* (2) If no route for this -> exit */
+ if( !isset($this->routes[$httpMethod]) || count($this->routes[$httpMethod]) <= 0 )
+ return false;
+
+
+ /* (2) Manage routes (matching)
+ ---------------------------------------------------------*/
+ /* (1) Check for each HTTP method's route */
+ foreach($this->routes[$httpMethod] as $route)
+
+ /* (2) First route that matches -> call & return response */
+ if( $route->match($this->url) )
+ return $route->call();
+
+
+ /* (3) If no route found -> return false
+ ---------------------------------------------------------*/
+ return false;
+ }
+
+
+ /* FORMATS A PATTERN
+ *
+ * @pattern Pattern to process on
+ * @arguments List of used arguments, with regex if given
+ * @vars [OPT] If variable replacement have to be done
+ *
+ * @return formatted Formatted pattern || false on error
+ *
+ */
+ public static function formatPattern($pattern, $arguments=[]){
+
+ /* (1) Check arguments
+ ---------------------------------------------------------*/
+ /* (1) Check minimal length */
+ if( strlen($pattern) < 1 )
+ return false;
+
+ /* (2) Arguments formatting */
+ $arguments = !is_array($arguments) ? [] : $arguments;
+
+
+ /* (2) Replace special characters + replace vars
+ ---------------------------------------------------------*/
+ /* (1) Check default URL format */
+ if( !preg_match('/^(\/[\w\{\}-]*)*\/?$/', $pattern) )
+ return false;
+
+ /* (2) Escape special characters */
+ $pattern = str_replace('/', '\\/', $pattern);
+
+ /* (3) Add optional ending '/' */
+ if( !preg_match('/\/$/', $pattern) )
+ $pattern .= '\\/?';
+
+ /* (4) Replace variable by tagged capturing groups */
+ $boundary = self::randBoundary();
+ $pattern = preg_replace('/\{([a-z_][a-z0-9_]*)\}/i', '(?P<$1>'.$boundary.'-$1-'.$boundary.')', $pattern);
+
+
+ /* (3) Variable replacement
+ ---------------------------------------------------------*/
+ /* (1) List variables */
+ $vars = [];
+ $var_pattern = '/'.$boundary.'\-([A-Za-z_][A-Za-z0-9_]*)\-'.$boundary.'/';
+ preg_match_all($var_pattern, $pattern, $matches);
+
+ /* (2) For each matching variable -> replace with associated regex */
+ if( is_array($matches) && isset($matches[1]) ){
+
+ foreach($matches[1] as $m=>$varname){
+
+ // {3.1.1} Not in @arguments -> default regex //
+ if( !isset($arguments[$varname]) || !is_string($arguments[$varname]) ){
+ $pattern = str_replace($matches[0][$m], '[A-Za-z0-9_]+', $pattern);
+ continue;
+ }
+
+ // {3.1.2} If variable in @arguments -> set regex without capturing-groups //
+ // $without_capg = str_replace('(', '(?:', $arguments[$varname]);
+ $pattern = str_replace($matches[0][$m], $arguments[$varname], $pattern);
+
+ }
+
+ }
+
+
+ /* (4) Return formatted pattern
+ ---------------------------------------------------------*/
+ return $pattern;
+ }
+
+
+
+ /* LOADS CONFIGURATION
+ *
+ * @return cnf Configuration content || NULL if error
+ *
+ */
+ private static function loadConfig(){
+ /* (1) Set configuration file's path */
+ $cnfpath = self::config_path();
+
+ /* (2) Checks file */
+ if( !file_exists($cnfpath) )
+ return null; // throw new \Exception("[Router] Configuration file not found");
+
+ /* (3) Checks format -> null if error */
+ return json_decode( file_get_contents($cnfpath), true );
+
+ }
+
+
+ /* CHECKS METHODS AND CLEAN THE LIST IF CORRECT
+ *
+ * @wanted List of wanted methods
+ *
+ * @return cleaned Cleaned methods || null if error
+ *
+ */
+ private static function cleanMethods($wanted=[]){
+ /* (1) Checks @wanted */
+ if( !is_array($wanted) || count($wanted) < 1 )
+ return null; // throw new \Exception('[Router] Configuration file error, \'methods\' must be an array containing managed HTTP methods');
+
+ /* (2) Set methods (uppercase and unique) */
+ $cleaned = [];
+
+ foreach($wanted as $method)
+ if( !in_array(strtoupper($method), $cleaned) )
+ $cleaned[] = strtoupper($method);
+
+ /* (3) Return cleaned method list */
+ return $cleaned;
+ }
+
+ }
diff --git a/build/service/Updater.php b/build/service/Updater.php
index 8101f21..c4367be 100644
--- a/build/service/Updater.php
+++ b/build/service/Updater.php
@@ -43,7 +43,7 @@
=========================================================*/
foreach($this->config->getDiplomes() as $d_id=>$d_name){
- file_put_contents(__ROOT__."/tmp/$d_id.ics", "BEGIN:VCALENDAR", FILE_APPEND);
+ file_put_contents(__ROOT__."/tmp/$d_id.ics", "BEGIN:VCALENDAR\nVERSION:2.0\n", FILE_APPEND);
/* (1) Browse each date
---------------------------------------------------------*/
diff --git a/config/routes.json b/config/routes.json
new file mode 100644
index 0000000..3229c84
--- /dev/null
+++ b/config/routes.json
@@ -0,0 +1,32 @@
+{
+
+ "methods": [ "GET" ],
+
+
+ "routes": {
+
+ "/": {
+ "methods": ["GET"],
+ "controller": "page:home",
+ "arguments": {}
+ },
+
+ "/ics/{diplome_id}": {
+ "methods": ["GET"],
+ "controller": "ics:download",
+ "arguments": {
+ "diplome_id": "T\\d+"
+ }
+ },
+
+ "/{any}": {
+ "methods": ["GET"],
+ "controller": "redirect:homepage",
+ "arguments": {
+ "any": ".+"
+ }
+ }
+
+ }
+
+}
diff --git a/public_html/index.php b/public_html/index.php
index 7a4acf1..86c88fd 100644
--- a/public_html/index.php
+++ b/public_html/index.php
@@ -1,27 +1,8 @@
run();
- /* (2) Error management */
- }catch(\Exception $e){
- die("An error occured. Please contact the developers.\n");
- }
-
- /* (3) Get the diplome list */
- $diplomes = $config->getDiplomes();
-
-
-
- /* [2] Display the links
- =========================================================*/
- foreach($diplomes as $id=>$name){
- echo "$name
";
-
- }