Merge remote-tracking branch 'origin/master'
This commit is contained in:
commit
17c78d6e87
|
@ -16,14 +16,14 @@
|
|||
|
||||
interface AuthSystem{
|
||||
|
||||
/* VERIFICATION DES ACCES EN FONCTION DE PERMISSIONS ATTENDUES
|
||||
*
|
||||
* @expected<array> Liste des permissions attendues
|
||||
*
|
||||
* @return error<Error> Erreur associée à la permission (Success/PermissionError/TokenError/etc)
|
||||
*
|
||||
*/
|
||||
public static function permission($expected);
|
||||
/** VERIFICATION DES ACCES EN FONCTION DE PERMISSIONS ATTENDUES
|
||||
*
|
||||
* @param array $expected Liste des permissions attendues
|
||||
*
|
||||
* @return Error Erreur associée à la permission (Success/PermissionError/TokenError/etc)
|
||||
*
|
||||
*/
|
||||
public static function permission(array $expected) : Error;
|
||||
}
|
||||
|
||||
?>
|
||||
|
|
|
@ -79,22 +79,19 @@
|
|||
|
||||
|
||||
|
||||
/* VERIFICATION DES ACCES EN FONCTION DE PERMISSIONS ATTENDUES
|
||||
*
|
||||
* @expected<array> Liste des permissions attendues
|
||||
*
|
||||
* @return error<Error> Erreur associée à la permission (Success/PermissionError/TokenError/etc)
|
||||
*
|
||||
*/
|
||||
public static function permission($expected){
|
||||
/** VERIFICATION DES ACCES EN FONCTION DE PERMISSIONS ATTENDUES
|
||||
*
|
||||
* @param array $expected Liste des permissions attendues
|
||||
*
|
||||
* @return Error Erreur associée à la permission (Success/PermissionError/TokenError/etc)
|
||||
*
|
||||
*/
|
||||
public static function permission(array $expected) : Error{
|
||||
|
||||
/* (1) Check format -> if not array of array(s) -> ERROR
|
||||
---------------------------------------------------------*/
|
||||
/* (1) If not array -> ERROR */
|
||||
if( !is_array($expected) )
|
||||
return new Error(Err::FormatError);
|
||||
|
||||
/* (2) If not array of array(s) -> ERROR */
|
||||
/* (1) If not array of array(s) -> ERROR */
|
||||
foreach($expected as $permission_group)
|
||||
if( !is_array($permission_group) )
|
||||
return new Error(Err::FormatError);
|
||||
|
|
|
@ -16,15 +16,15 @@
|
|||
class Checker{
|
||||
|
||||
|
||||
/* VERIFICATIONS DES TYPES UTILES GENERIQUES
|
||||
/** VERIFICATIONS DES TYPES UTILES GENERIQUES
|
||||
*
|
||||
* @type<String> Type que l'on veut verifier
|
||||
* @value<mixed*> Valeur a verifier
|
||||
* @param String $type Type que l'on veut verifier
|
||||
* @param mixed $value Valeur a verifier
|
||||
*
|
||||
* @return match<Boolean> Retourne si oui ou non la valeur @value est du bon type @type
|
||||
* @return Boolean Retourne si oui ou non la valeur @value est du bon type @type
|
||||
*
|
||||
*/
|
||||
public static function run($type, $value){
|
||||
public static function run(String $type, $value) : bool {
|
||||
$checker = true;
|
||||
|
||||
/* [0] On verifie que $value n'est pas nul
|
||||
|
@ -44,6 +44,10 @@
|
|||
// On recupere le sous-type si défini
|
||||
$flags = isset($match[3]) ? explode(',', substr($match[3], 1)) : null;
|
||||
|
||||
// Si numeric -> to String
|
||||
if( is_numeric($value) )
|
||||
$value = (string) $value;
|
||||
|
||||
// On effectue la verification de taille
|
||||
$lenCheck = $checker && is_string($value) && strlen($value) <= $max && strlen($value) >= $min;
|
||||
|
||||
|
@ -91,6 +95,11 @@
|
|||
return $checker && is_numeric($value) && $value <= 2147483647 && $value >= 0;
|
||||
break;
|
||||
|
||||
// Entier relatif (neg ou pos)
|
||||
case 'int':
|
||||
return $checker && is_int($value);
|
||||
break;
|
||||
|
||||
// String quelconque (peut etre vide)
|
||||
case 'text':
|
||||
return $checker && is_string($value);
|
||||
|
@ -143,7 +152,7 @@
|
|||
break;
|
||||
|
||||
case "float":
|
||||
return $checker && is_float($value);
|
||||
return $checker && ( is_int($value) || is_float($value) );
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
|
@ -11,23 +11,34 @@
|
|||
/* (1) Attributes
|
||||
---------------------------------------------------------*/
|
||||
/* (1) Static */
|
||||
|
||||
/** @var Config? */
|
||||
private static $inst = null; // singleton instance
|
||||
private static function config_path(){ return __ROOT__.'/config/modules.json'; }
|
||||
|
||||
private static function config_path() : String { return __ROOT__.'/config/modules.json'; }
|
||||
|
||||
/** @var array[String] */
|
||||
public static $allowed_http_methods = [ "GET", "POST", "PUT", "DELETE" ];
|
||||
|
||||
/* (2) Instance */
|
||||
|
||||
/** @var array */
|
||||
private $raw;
|
||||
|
||||
/** @var array */
|
||||
public $index;
|
||||
|
||||
/** @var Error */
|
||||
public $error;
|
||||
|
||||
|
||||
|
||||
/* (2) Private constructor
|
||||
/** (2) Private constructor
|
||||
*
|
||||
* @path<String> Configuration path
|
||||
* @param String|null $path Configuration path
|
||||
*
|
||||
---------------------------------------------------------*/
|
||||
private function __construct($path=null){
|
||||
private function __construct(?String $path=null){
|
||||
|
||||
// Set default error
|
||||
$this->error = new Error(Err::Success);
|
||||
|
@ -116,9 +127,9 @@
|
|||
|
||||
|
||||
|
||||
/* (3) Static singleton 'get-or-create'
|
||||
/** (3) Static singleton 'get-or-create'
|
||||
*
|
||||
* @return inst<Config> Configuration singleton
|
||||
* @return Config Configuration singleton
|
||||
*
|
||||
---------------------------------------------------------*/
|
||||
public static function get() : Config{
|
||||
|
|
|
@ -15,15 +15,15 @@
|
|||
|
||||
class ModuleFactory{
|
||||
|
||||
/* INSTANCIE UN MODULE
|
||||
/** INSTANCIE UN MODULE
|
||||
*
|
||||
* @module<String> Nom du module
|
||||
* @arguments<Array> [OPTIONNEL] Arguments à passer au constructeur
|
||||
* @param String $module Nom du module
|
||||
* @param array $arguments [OPTIONNEL] Arguments à passer au constructeur
|
||||
*
|
||||
* @return instance<Module> Instance du module en question
|
||||
* @return object|false Instance du module en question
|
||||
*
|
||||
*/
|
||||
public static function getModule($module, $arguments=[]){
|
||||
public static function getModule(String $module, array $arguments=[]){
|
||||
/* (1) On gère les arguments */
|
||||
$arguments = is_array($arguments) ? $arguments : [];
|
||||
|
||||
|
|
|
@ -5,35 +5,50 @@
|
|||
use \api\core\AuthSystem;
|
||||
use \api\core\ModuleFactory;
|
||||
use \api\core\Config;
|
||||
use \error\core\Error;
|
||||
use database\core\Repo;
|
||||
use \error\core\Error;
|
||||
use \error\core\Err;
|
||||
|
||||
|
||||
class Request{
|
||||
|
||||
// Constantes
|
||||
|
||||
/** @var array[bool] */
|
||||
private static $default_options = [ 'download' => false ];
|
||||
|
||||
/** @var AuthSystem|null */
|
||||
private static $authsystem = null;
|
||||
|
||||
|
||||
// Attributs prives utiles (initialisation)
|
||||
|
||||
/** @var array */
|
||||
private $id; // chemin extrait de l'URI
|
||||
|
||||
/** @var array */
|
||||
private $raw_params; // paramètres reçus
|
||||
|
||||
/** @var array */
|
||||
private $params; // paramètres donnés à la fonction
|
||||
|
||||
/** @var array */
|
||||
private $options; // options
|
||||
|
||||
/** @var String */
|
||||
private $http_method; // methode HTTP appelante
|
||||
|
||||
// Contiendra l'etat de la requete
|
||||
/** @var Error */
|
||||
public $error;
|
||||
|
||||
|
||||
/* (0) Constructeur d'une requete de module
|
||||
/** (0) Constructeur d'une requete de module
|
||||
*
|
||||
* @uri<String> URI relative de l'appel
|
||||
* @param<Array> Tableau associatif contenant les parametres utiles au traitement
|
||||
* @forced_method<String> Méthode demandée (optionnel)
|
||||
* @param String|null $uri URI relative de l'appel
|
||||
* @param array|null $params Tableau associatif contenant les parametres utiles au traitement
|
||||
* @param String|null $forced_method Méthode demandée (optionnel)
|
||||
*
|
||||
* @return instance<Request> Instance crée
|
||||
*
|
||||
---------------------------------------------------------*/
|
||||
public function __construct($uri=null, $params=null, $forced_method=null){
|
||||
|
@ -44,38 +59,44 @@
|
|||
|
||||
|
||||
|
||||
/* (1) Constructeur d'une requete de module (delegation)
|
||||
/** (1) Constructeur d'une requete de module (delegation)
|
||||
*
|
||||
* @uri<String> URI relative de l'appel
|
||||
* @param<Array> Tableau associatif contenant les parametres utiles au traitement
|
||||
* @forced_method<String> Méthode demandée (optionnel)
|
||||
* @param String|null $uri URI relative de l'appel
|
||||
* @param array|null $params Tableau associatif contenant les parametres utiles au traitement
|
||||
* @param String|null $forced_method Méthode demandée (optionnel)
|
||||
*
|
||||
* @return status<Boolean> Retourne si oui ou non tout s'est bien passe
|
||||
* @return boolean Retourne si oui ou non tout s'est bien passe
|
||||
*
|
||||
---------------------------------------------------------*/
|
||||
private function buildRequestObject($uri=null, $params=null, $forced_method=null){
|
||||
private function buildRequestObject($uri=null, $params=null, $forced_method=null) :bool{
|
||||
/* (1) Initialisation
|
||||
---------------------------------------------------------*/
|
||||
/* (1) Erreur par défaut */
|
||||
$this->error = new Error(Err::Success);
|
||||
|
||||
/* (2) Si pas parametre manquant, on quitte */
|
||||
if( is_null($uri) )
|
||||
return $this->error->set(Err::MissingPath);
|
||||
if( is_null($uri) ){
|
||||
$this->error->set(Err::MissingPath);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/* (2) On vérifie la configuration
|
||||
---------------------------------------------------------*/
|
||||
/* (1) Dispatch if error */
|
||||
if( Config::get()->error->get() != Err::Success )
|
||||
return ($this->error = Config::get()->error);
|
||||
if( Config::get()->error->get() != Err::Success ){
|
||||
$this->error = Config::get()->error;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/* (3) Verification des types des parametres
|
||||
---------------------------------------------------------*/
|
||||
/* (1) Si path est une <string> */
|
||||
if( !is_string($uri) ) // Si le type est incorrect
|
||||
return $this->error->set(Err::WrongPathModule);
|
||||
if( !is_string($uri) ){
|
||||
$this->error->set(Err::WrongPathModule);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* (2) Add slash at the beginning of URI */
|
||||
if( !preg_match('@^\/@', $uri) )
|
||||
|
@ -85,8 +106,10 @@
|
|||
$this->raw_params = (is_array($params)) ? $params : [];
|
||||
|
||||
/* (4) On définit en constante la méthode HTTP */
|
||||
if( !isset($_SERVER['REQUEST_METHOD']) && !is_string($forced_method) )
|
||||
return $this->error->set(Err::UnknownHttpMethod);
|
||||
if( !isset($_SERVER['REQUEST_METHOD']) && !is_string($forced_method) ){
|
||||
$this->error->set(Err::UnknownHttpMethod);
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->http_method = is_string($forced_method) ? strtoupper($forced_method) : strtoupper($_SERVER['REQUEST_METHOD']);
|
||||
|
||||
|
@ -129,14 +152,14 @@
|
|||
|
||||
|
||||
|
||||
/* (2) Definit le systeme d'authentification
|
||||
/** (2) Definit le systeme d'authentification
|
||||
*
|
||||
* @instance<AuthSystem> Instance de type AuthSystem
|
||||
* @param AuthSystem $instance Instance de type AuthSystem
|
||||
*
|
||||
* @return success<Boolean> Whether the AuthSystem is valid or not
|
||||
* @return boolean Whether the AuthSystem is valid or not
|
||||
*
|
||||
---------------------------------------------------------*/
|
||||
public static function setAuthSystem($instance=null){
|
||||
public static function setAuthSystem( ?AuthSystem $instance=null) : bool{
|
||||
/* (1) Check instance type */
|
||||
if( !($instance instanceof AuthSystem) )
|
||||
return false;
|
||||
|
@ -149,20 +172,22 @@
|
|||
|
||||
|
||||
|
||||
/* (3) Verification du format et de la coherence du chemin specifie
|
||||
/** (3) Verification du format et de la coherence du chemin specifie
|
||||
*
|
||||
* @URI<String> URI d'appel (commence par /)
|
||||
* @param String $uri URI d'appel (commence par /)
|
||||
*
|
||||
* @return validity<Boolean> Retourne si oui ou non l'objet est correct
|
||||
* @return boolean Retourne si oui ou non l'objet est correct
|
||||
*
|
||||
---------------------------------------------------------*/
|
||||
private function checkURI($uri){
|
||||
private function checkURI(String $uri) : bool{
|
||||
|
||||
/* (1) Verification format general
|
||||
---------------------------------------------------------*/
|
||||
/* (1) If wrong format -> exit */
|
||||
if( !preg_match('@^\/[^\/]*(\/[^\/]*)*\/?$@', $uri) )
|
||||
return $this->error->set(Err::WrongPathModule);
|
||||
if( !preg_match('@^\/[^\/]*(\/[^\/]*)*\/?$@', $uri) ){
|
||||
$this->error->set(Err::WrongPathModule);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* (2) Add ending '/' if not there */
|
||||
if( $uri[strlen($uri)-1] != '/' )
|
||||
|
@ -188,8 +213,10 @@
|
|||
}
|
||||
|
||||
/* (2) If @path not found -> exit */
|
||||
if( is_null($path) )
|
||||
return $this->error->set(Err::UnknownModule);
|
||||
if( is_null($path) ){
|
||||
$this->error->set(Err::UnknownModule);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/* (3) Extract URI parameters
|
||||
|
@ -202,8 +229,10 @@
|
|||
$uri_end = "/$uri_end";
|
||||
|
||||
/* (3) If invalid format, return error */
|
||||
if( !preg_match('@^((?:\/[^\/]*)*)\/?$@', $uri_end, $uri_match) )
|
||||
return $this->error->set(Err::InvalidURI);
|
||||
if( !preg_match('@^((?:\/[^\/]*)*)\/?$@', $uri_end, $uri_match) ){
|
||||
$this->error->set(Err::InvalidURI);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* (4) Add each URI parameter to the parameter store */
|
||||
$uri_args = array_slice( explode('/', $uri_match[1]), 1);
|
||||
|
@ -219,12 +248,16 @@
|
|||
$doc_req = $this->http_method == 'OPTIONS';
|
||||
|
||||
/* (2) Check if HTTP method is in allowed methods */
|
||||
if( !in_array($this->http_method, Config::$allowed_http_methods) && !$doc_req )
|
||||
return $this->error->set(Err::UnknownHttpMethod, $this->http_method);
|
||||
if( !in_array($this->http_method, Config::$allowed_http_methods) && !$doc_req ){
|
||||
$this->error->set(Err::UnknownHttpMethod, $this->http_method);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* (3) Check if HTTP method is defined for this @path */
|
||||
if( !isset(Config::get()->index[$path][$this->http_method]) && !$doc_req )
|
||||
return $this->error->set(Err::UnknownMethod, $this->http_method);
|
||||
if( !isset(Config::get()->index[$path][$this->http_method]) && !$doc_req ){
|
||||
$this->error->set(Err::UnknownMethod, $this->http_method);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -241,12 +274,12 @@
|
|||
|
||||
|
||||
|
||||
/* (4) Retourne si on a la permission d'executer cette methode
|
||||
/** (4) Retourne si on a la permission d'executer cette methode
|
||||
*
|
||||
* @return permission<bool> Retourne si on a les droits ou pas pour executer cette methode
|
||||
* @return bool Retourne si on a les droits ou pas pour executer cette methode
|
||||
*
|
||||
---------------------------------------------------------*/
|
||||
private function checkPermission(){
|
||||
private function checkPermission() : bool{
|
||||
|
||||
/* (1) On recupere les informations utiles
|
||||
---------------------------------------------------------*/
|
||||
|
@ -263,8 +296,10 @@
|
|||
if( !is_object(self::$authsystem) || !self::$authsystem instanceof AuthSystem ){
|
||||
|
||||
// try to load default AuthSystem
|
||||
if( !file_exists(__BUILD__.'/api/core/AuthSystemDefault.php') )
|
||||
return $this->error->set(Err::UnreachableResource);
|
||||
if( !file_exists(__BUILD__.'/api/core/AuthSystemDefault.php') ){
|
||||
$this->error->set(Err::UnreachableResource);
|
||||
return false;
|
||||
}
|
||||
|
||||
// load default AuthSystem class
|
||||
$classname = '\\api\\core\\AuthSystemDefault';
|
||||
|
@ -288,25 +323,29 @@
|
|||
|
||||
|
||||
|
||||
/* (5) Verification du type des parametres envoyes
|
||||
/** (5) Verification du type des parametres envoyes
|
||||
*
|
||||
* @return correct<bool> Retourne si oui ou non les parametres ont le bon type
|
||||
* @return bool Retourne si oui ou non les parametres ont le bon type
|
||||
*
|
||||
---------------------------------------------------------*/
|
||||
private function checkParams(){
|
||||
private function checkParams() : bool{
|
||||
|
||||
/* (1) On verifie qu'il ne manque aucun parametre
|
||||
---------------------------------------------------------*/
|
||||
/* (1) Si @params n'est pas un tableau */
|
||||
if( !is_array($this->raw_params) )
|
||||
return $this->error->set(Err::MissingParam);
|
||||
if( !is_array($this->raw_params) ){
|
||||
$this->error->set(Err::MissingParam);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* (2) On récupère les données de la méthode */
|
||||
$method = Config::get()->index[$this->id['path']][$this->id['method']];
|
||||
|
||||
/* (3) Si pas 'parameters' dans la config */
|
||||
if( !isset($method['par']) || !is_array($method['par']) )
|
||||
return $this->error->set(Err::ConfigError);
|
||||
if( !isset($method['par']) || !is_array($method['par']) ){
|
||||
$this->error->set(Err::ConfigError);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/* (2) Si le type est defini, pour chaque param, on teste
|
||||
|
@ -316,16 +355,22 @@
|
|||
/* (2.1) Vérification des données
|
||||
---------------------------------------------------------*/
|
||||
/* (1) Si @name n'est pas une string */
|
||||
if( !is_string($name) )
|
||||
return $this->error->set(Err::ConfigError);
|
||||
if( !is_string($name) ){
|
||||
$this->error->set(Err::ConfigError);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* (2) Si @config n'est pas un tableau */
|
||||
if( !is_array($config) )
|
||||
return $this->error->set(Err::ConfigError);
|
||||
if( !is_array($config) ){
|
||||
$this->error->set(Err::ConfigError);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* (3) So @config['typ] manquant ou incorrect */
|
||||
if( !isset($config['typ']) || !is_string($config['typ']) )
|
||||
return $this->error->set(Err::ConfigError);
|
||||
if( !isset($config['typ']) || !is_string($config['typ']) ) {
|
||||
$this->error->set(Err::ConfigError);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/* (2.2) Gestion des spécifications
|
||||
|
@ -348,10 +393,12 @@
|
|||
$default = $config['def'];
|
||||
|
||||
/* (3.1.2) If FILE and not null -> Check type */
|
||||
if( $config['typ'] != 'FILE' || $default != null )
|
||||
if( !Checker::run($config['typ'], $default) )
|
||||
return $this->error->set(Err::WrongDefaultParam, $rename, $config['typ']);
|
||||
|
||||
if( $config['typ'] != 'FILE' || $default != null ){
|
||||
if( !Checker::run($config['typ'], $default) ) {
|
||||
$this->error->set(Err::WrongDefaultParam, $rename, $config['typ']);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* (4) Si de type 'FILE' + fichier existe => on enregistre la ref. */
|
||||
|
@ -359,8 +406,10 @@
|
|||
$this->params[$rename] = &$_FILES[$name];
|
||||
|
||||
/* (4) Si param obligatoire et manquant -> erreur */
|
||||
if( !isset($this->raw_params[$name]) && !$optional )
|
||||
return $this->error->set(Err::MissingParam, $rename);
|
||||
if( !isset($this->raw_params[$name]) && !$optional ) {
|
||||
$this->error->set(Err::MissingParam, $rename);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/* (2.3) Gestion des valeurs
|
||||
|
@ -382,8 +431,10 @@
|
|||
$this->raw_params[$name] = $json_rep['json'];
|
||||
|
||||
// Si la verification est fausse, on retourne faux
|
||||
if( !Checker::run($config['typ'], $this->raw_params[$name]) )
|
||||
return $this->error->set(Err::WrongParam, $rename, $config['typ']);
|
||||
if( !Checker::run($config['typ'], $this->raw_params[$name]) ){
|
||||
$this->error->set(Err::WrongParam, $rename, $config['typ']);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Sinon, on ajoute aux params qu'on enverra à l'appel
|
||||
else
|
||||
|
@ -402,12 +453,12 @@
|
|||
|
||||
|
||||
|
||||
/* (6) Ajout des options a partir de la configuration
|
||||
/** (6) Ajout des options a partir de la configuration
|
||||
*
|
||||
* @return correct<bool> Retourne FAUS en cas d'erreur
|
||||
* @return bool Retourne FAUS en cas d'erreur
|
||||
*
|
||||
---------------------------------------------------------*/
|
||||
private function buildOptions(){
|
||||
private function buildOptions() : bool{
|
||||
|
||||
/* (1) On récupère les options de la méthode en cours
|
||||
---------------------------------------------------------*/
|
||||
|
@ -447,12 +498,12 @@
|
|||
|
||||
|
||||
|
||||
/* (7) Execute le traitement associe et remplie la reponse
|
||||
/** (7) Execute le traitement associe et remplie la reponse
|
||||
*
|
||||
* @return answer<Response> Retourne une reponse de type <Response> si tout s'est bien passe
|
||||
* @return Response Retourne une reponse de type <Response> si tout s'est bien passe
|
||||
*
|
||||
---------------------------------------------------------*/
|
||||
public function dispatch(){
|
||||
public function dispatch() : Response{
|
||||
|
||||
/* (1) Vérifications de niveau 0
|
||||
---------------------------------------------------------*/
|
||||
|
@ -503,6 +554,11 @@
|
|||
/* (3) On ajoute les données */
|
||||
$response->appendAll($returned);
|
||||
|
||||
/* (4) Si le Debug est actif on ajoute le debug des repo */
|
||||
if(Repo::isDebugEnabled()){
|
||||
$response->append("repoDebug" , Repo::getDebug());
|
||||
}
|
||||
|
||||
/* (4) On retourne la réponse */
|
||||
return $response;
|
||||
|
||||
|
@ -510,10 +566,11 @@
|
|||
|
||||
|
||||
|
||||
/* (8) Gestion d'un téléchargement HTTP
|
||||
*
|
||||
*/
|
||||
public function download($returned){
|
||||
/** (8) Gestion d'un téléchargement HTTP
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function download($returned) : Response{
|
||||
|
||||
/* (1) Vérification des erreurs et paramètres
|
||||
---------------------------------------------------------*/
|
||||
|
@ -550,7 +607,7 @@
|
|||
/* (2) On affiche le contenu */
|
||||
echo $returned['body'];
|
||||
|
||||
return true;
|
||||
return new Response();
|
||||
|
||||
}
|
||||
|
||||
|
@ -599,12 +656,13 @@
|
|||
|
||||
|
||||
|
||||
/* (9) Getter générique
|
||||
/** (9) Getter générique
|
||||
*
|
||||
* @index<String> Index de l'attribut
|
||||
* @param String $index Index de l'attribut
|
||||
*
|
||||
* @return mixed
|
||||
---------------------------------------------------------*/
|
||||
public function get($index=null){
|
||||
public function get(?String $index=null){
|
||||
|
||||
switch($index){
|
||||
|
||||
|
|
|
@ -17,31 +17,36 @@
|
|||
class Response{
|
||||
|
||||
// Attributs prives utiles (initialisation)
|
||||
|
||||
/** @var array */
|
||||
private $data;
|
||||
|
||||
/** @var Error */
|
||||
public $error;
|
||||
|
||||
|
||||
/* CONSTRUCTEUR D'UNE REPONSE DE MODULE
|
||||
/** CONSTRUCTEUR D'UNE REPONSE DE MODULE
|
||||
*
|
||||
* @error<ModuleError> Erreur passee par la requete (si existe)
|
||||
* @param Error $error Erreur passee par la requete (si existe)
|
||||
*
|
||||
*/
|
||||
public function __construct($error=null){
|
||||
public function __construct(?Error $error=null){
|
||||
if( !( $error instanceof Error ) )
|
||||
$error = new Error(Err::Success);
|
||||
|
||||
$this->data = [];
|
||||
$this->error = $error;
|
||||
}
|
||||
/* AJOUTE UNE DONNEE A LA REPONSE
|
||||
|
||||
|
||||
/** AJOUTE UNE DONNEE A LA REPONSE
|
||||
*
|
||||
* @key<String> Le nom de la valeur a ajouter
|
||||
* @value<mixed*> La valeur a ajouter
|
||||
* @param String $key Le nom de la valeur a ajouter
|
||||
* @param mixed $value La valeur a ajouter
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function append($key, $value){
|
||||
public function append(String $key, $value) : Response{
|
||||
// Ajoute une entree pour la cle @key et de valeur @value
|
||||
$this->data[$key] = $value;
|
||||
|
||||
|
@ -49,12 +54,13 @@
|
|||
}
|
||||
|
||||
|
||||
/* AJOUTE TOUTES LES DONNEES A LA REPONSE
|
||||
/** AJOUTE TOUTES LES DONNEES A LA REPONSE
|
||||
*
|
||||
* @dataset<Array> Le tableau associatif correspondant a la reponse
|
||||
* @param array $dataset Le tableau associatif correspondant a la reponse
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function appendAll($dataset){
|
||||
public function appendAll(array $dataset) : Response{
|
||||
// Si ce n'est pas un tableau, on ne fais rien
|
||||
if( !is_array($dataset) )
|
||||
return $this;
|
||||
|
@ -72,17 +78,16 @@
|
|||
|
||||
return $this;
|
||||
}
|
||||
/* RECUPERE UNE DONNEE DE LA REPONSE
|
||||
|
||||
|
||||
/** RECUPERE UNE DONNEE DE LA REPONSE
|
||||
*
|
||||
* @key<String> Le nom de la valeur a recuperer
|
||||
* @param String $key Le nom de la valeur a recuperer
|
||||
*
|
||||
* @return value<mixed*> La valeur a cette cle
|
||||
* @return error<null> Retourne NULL si aucune valeur pour cette cle
|
||||
* @return mixed|null La valeur a cette cle, NULL si aucune valeur pour cette cle
|
||||
*
|
||||
*/
|
||||
public function get($key){
|
||||
public function get(String $key){
|
||||
// Si la valeur de cle @key n'existe pas, on retourne NULL
|
||||
if( !isset($this->data[$key]) )
|
||||
return null;
|
||||
|
@ -92,9 +97,9 @@
|
|||
}
|
||||
|
||||
|
||||
/* RECUPERE TOUTES LES DONNEES DE LA REPONSE
|
||||
/** RECUPERE TOUTES LES DONNEES DE LA REPONSE
|
||||
*
|
||||
* @return data<Array> Les donnees de la reponse
|
||||
* @return array Les donnees de la reponse
|
||||
*
|
||||
*/
|
||||
public function getAll(){
|
||||
|
@ -103,12 +108,12 @@
|
|||
}
|
||||
|
||||
|
||||
/* SERIALISATION A PARTIR DES DONNEES
|
||||
/** SERIALISATION A PARTIR DES DONNEES
|
||||
*
|
||||
* @return json<String> Retourne les donnees serialisees
|
||||
* @return String Retourne les donnees serialisees
|
||||
*
|
||||
*/
|
||||
public function serialize(){
|
||||
public function serialize() : String{
|
||||
|
||||
// Code Http
|
||||
$this->error->setHttpCode();
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: lucas
|
||||
* Date: 08/03/18
|
||||
* Time: 17:36
|
||||
*/
|
||||
|
||||
namespace api\module\departement;
|
||||
|
||||
|
||||
use database\core\Repo;
|
||||
use database\repo\departement;
|
||||
|
||||
class statsController
|
||||
{
|
||||
|
||||
public static function get($args){
|
||||
|
||||
/** @var departement $repo */
|
||||
$repo = Repo::getRepo("departement");
|
||||
|
||||
return ["data" => $repo->getStats()];
|
||||
}
|
||||
}
|
|
@ -63,9 +63,11 @@ class excelController
|
|||
$addEU = function() use (&$UECode,&$allUE,&$UE){
|
||||
//determine if UE is disabled (if cours+td+tp = 0)
|
||||
$totalVH = 0;
|
||||
foreach ($UE["groups"] as $groups){
|
||||
foreach ($groups as $group){
|
||||
$totalVH += $group["VH"];
|
||||
if(is_array($UE["groups"]) && count($UE["groups"]) > 0){
|
||||
foreach ($UE["groups"] as $groups){
|
||||
foreach ($groups as $group){
|
||||
$totalVH += $group["VH"];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -348,6 +350,10 @@ class excelController
|
|||
/** @var tp $tpRepo */
|
||||
$tpRepo = Repo::getRepo("tp");
|
||||
|
||||
$CoursToLink = [];
|
||||
$TDToLink = [];
|
||||
$TPToLink = [];
|
||||
|
||||
foreach ($allUE as $codeUE => $UE){
|
||||
|
||||
if($UE["defaultFormation"]){
|
||||
|
@ -377,22 +383,25 @@ class excelController
|
|||
|
||||
switch ($type){
|
||||
case "Course":
|
||||
$coursRepo->create( $codeUE,
|
||||
$allProf[$group["professor"]]["dbId"],
|
||||
$UE["disabled"] ? $UE["CourseVH"] : $group["VH"],
|
||||
$formations);
|
||||
$CoursToLink[] = ["id" => $coursRepo->create( $codeUE,
|
||||
$allProf[$group["professor"]]["dbId"],
|
||||
$UE["disabled"] ? $UE["CourseVH"] : $group["VH"],
|
||||
[]),
|
||||
"form" => $formations];
|
||||
break;
|
||||
case "TD":
|
||||
$tdRepo->create($codeUE,
|
||||
$allProf[$group["professor"]]["dbId"],
|
||||
$UE["disabled"] ? $UE["TdVH"] : $group["VH"],
|
||||
$formations);
|
||||
$TDToLink[] = ["id" => $tdRepo->create($codeUE,
|
||||
$allProf[$group["professor"]]["dbId"],
|
||||
$UE["disabled"] ? $UE["TdVH"] : $group["VH"],
|
||||
[]),
|
||||
"form" => $formations];
|
||||
break;
|
||||
case "TP":
|
||||
$tpRepo->create($codeUE,
|
||||
$allProf[$group["professor"]]["dbId"],
|
||||
$UE["disabled"] ? $UE["TpVH"] : $group["VH"],
|
||||
$formations);
|
||||
$TPToLink[] = ["id" => $tpRepo->create($codeUE,
|
||||
$allProf[$group["professor"]]["dbId"],
|
||||
$UE["disabled"] ? $UE["TpVH"] : $group["VH"],
|
||||
[]),
|
||||
"form" => $formations];
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -401,7 +410,28 @@ class excelController
|
|||
}
|
||||
}
|
||||
|
||||
return [ 'data' => ["professors" => $allProf, "formations" => $allFormations, "UEs" => $allUE ] ];
|
||||
Repo::enableStacking();
|
||||
|
||||
foreach ($CoursToLink as $cour){
|
||||
foreach ($cour["form"] as $formation){
|
||||
$coursRepo->linkFormation($formation,$cour["id"]);
|
||||
}
|
||||
}
|
||||
foreach ($TDToLink as $cour){
|
||||
foreach ($cour["form"] as $formation){
|
||||
$tdRepo->linkFormation($formation,$cour["id"]);
|
||||
}
|
||||
}
|
||||
foreach ($TPToLink as $cour){
|
||||
foreach ($cour["form"] as $formation){
|
||||
$tpRepo->linkFormation($formation,$cour["id"]);
|
||||
}
|
||||
}
|
||||
|
||||
Repo::flushStack();
|
||||
|
||||
//return [ 'data' => ["professors" => $allProf, "formations" => $allFormations, "UEs" => $allUE ] ];
|
||||
return["data" => true];
|
||||
}catch (Exception $e){
|
||||
return [ 'error' => new Error(Err::UnknownError) ];
|
||||
}
|
||||
|
|
|
@ -42,4 +42,129 @@ class ueController{
|
|||
}
|
||||
|
||||
|
||||
/* (2) Creates a new UE
|
||||
*
|
||||
* @code<String> The code of the UE
|
||||
* @label<String> The UE label (name)
|
||||
* @required<bool> If the UE is required
|
||||
* @volumeCours<float> The UE required volume of COURSES
|
||||
* @volumeTD<float> The UE required volume of TD
|
||||
* @volumeTP<float> The UE required volume of TP
|
||||
* @disabled<bool> [OPT] If it is disabled
|
||||
* @defaultFormation<int> [OPT] If there is a foreign key for a default formation (if only one formation)
|
||||
*
|
||||
* @return created_code<int> The created UE code (if no error)
|
||||
*
|
||||
---------------------------------------------------------*/
|
||||
public static function post($args){
|
||||
$code = "";
|
||||
$label = "";
|
||||
$required = false;
|
||||
$volumeCours = 0;
|
||||
$volumeTD = 0;
|
||||
$volumeTP = 0;
|
||||
$disabled = true;
|
||||
$defaultFormation = -1;
|
||||
extract($args);
|
||||
|
||||
/* Get the ue repo */
|
||||
/** @var ue $ue_repo */
|
||||
$ue_repo = Repo::getRepo('ue');
|
||||
|
||||
/* (1) Check if ue code already exists */
|
||||
$exists = $ue_repo->get($code);
|
||||
|
||||
/* (2) If found -> already exists */
|
||||
if( count($exists) > 0 )
|
||||
return ['error' => new Error(Err::AlreadyExists)];
|
||||
|
||||
/* (3) Else try to create */
|
||||
$repo_rtn = $ue_repo->create(
|
||||
$code,
|
||||
$label,
|
||||
$required,
|
||||
$volumeCours,
|
||||
$volumeTD,
|
||||
$volumeTP,
|
||||
$disabled,
|
||||
is_int($defaultFormation) && $defaultFormation < 0 ? null : $defaultFormation
|
||||
);
|
||||
|
||||
|
||||
/* (4) If repo error -> return it */
|
||||
if( is_null($repo_rtn) )
|
||||
return ['error' => new Error(Err::RepoError)];
|
||||
|
||||
|
||||
/* (5) Else return UID */
|
||||
return ['created_code' => $repo_rtn];
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* (3) Deletes an existing UE
|
||||
*
|
||||
* @code<String> The UE code
|
||||
*
|
||||
* @return deleted<bool> Whether it has been removed
|
||||
*
|
||||
---------------------------------------------------------*/
|
||||
public static function delete($args){
|
||||
$code = '';
|
||||
extract($args);
|
||||
|
||||
/* Get the ue repo */
|
||||
/** @var ue $ue_repo */
|
||||
$ue_repo = Repo::getRepo('ue');
|
||||
|
||||
/* (1) Try to delete */
|
||||
return ['deleted' => $ue_repo->delete($code)];
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* (4) Edits an existing UE
|
||||
*
|
||||
* @code<String> The code of the UE
|
||||
* @label<String> [OPT] The UE label (name)
|
||||
* @required<bool> [OPT] If the UE is required
|
||||
* @volumeCours<float> [OPT] The UE required volume of COURSES
|
||||
* @volumeTD<float> [OPT] The UE required volume of TD
|
||||
* @volumeTP<float> [OPT] The UE required volume of TP
|
||||
* @disabled<bool> [OPT] If it is disabled
|
||||
* @defaultFormation<int> [OPT] default formation for this UE (-1 to unset, NULL to ignore)
|
||||
*
|
||||
* @return updated<bool> Whether it has been updated
|
||||
*
|
||||
---------------------------------------------------------*/
|
||||
public static function put($args){
|
||||
$code = "";
|
||||
$label = "";
|
||||
$required = false;
|
||||
$volumeCours = 0;
|
||||
$volumeTD = 0;
|
||||
$volumeTP = 0;
|
||||
$disabled = true;
|
||||
$defaultFormation = null;
|
||||
extract($args);
|
||||
|
||||
/* Get the ue repo */
|
||||
/** @var ue $ue_repo */
|
||||
$ue_repo = Repo::getRepo('ue');
|
||||
|
||||
/* (1) Try to update */
|
||||
return ['updated' => $ue_repo->update(
|
||||
$code,
|
||||
$label,
|
||||
$required,
|
||||
$volumeCours,
|
||||
$volumeTD,
|
||||
$volumeTP,
|
||||
$disabled,
|
||||
$defaultFormation
|
||||
)];
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -11,6 +11,7 @@
|
|||
**************************/
|
||||
|
||||
namespace database\core;
|
||||
use database\core\PDOWrapper\PDOWrapper;
|
||||
use \error\core\Error;
|
||||
use \error\core\Err;
|
||||
|
||||
|
@ -18,7 +19,7 @@
|
|||
class DatabaseDriver{
|
||||
|
||||
/* STATIC ATTRIBUTES */
|
||||
private static function conf(){
|
||||
private static function conf() : array{
|
||||
// YOUR CONFIGURATION BEHIND
|
||||
$path = __CONFIG__.'/database-driver.json';
|
||||
|
||||
|
@ -36,11 +37,10 @@
|
|||
return $parsed;
|
||||
}
|
||||
|
||||
|
||||
private static $path; // Databases configurations files
|
||||
private static $config; // PDO configurations
|
||||
/** @var DatabaseDriver[] */
|
||||
private static $instance = []; // Database driver instance list
|
||||
|
||||
/** @var Error */
|
||||
public $error;
|
||||
|
||||
/* ATTRIBUTES */
|
||||
|
@ -52,15 +52,16 @@
|
|||
|
||||
|
||||
|
||||
/* CONSTRUCTOR OF A DATABASE DRIVER
|
||||
/** CONSTRUCTOR OF A DATABASE DRIVER
|
||||
*
|
||||
* @host<String> Database Server's host
|
||||
* @dbname<String> Database name
|
||||
* @username<String> Database username
|
||||
* @password<String> Database password
|
||||
* @param String $host Database Server's host
|
||||
* @param String $dbname Database name
|
||||
* @param String $username Database username
|
||||
* @param String $password Database password
|
||||
* @param bool $debug
|
||||
*
|
||||
*/
|
||||
private function __construct($host, $dbname, $username, $password){
|
||||
private function __construct(String $host, String $dbname, String $username, String $password, bool $debug = false){
|
||||
/* (2) Stores configuration */
|
||||
$this->host = $host;
|
||||
$this->dbname = $dbname;
|
||||
|
@ -69,14 +70,19 @@
|
|||
|
||||
try{
|
||||
|
||||
$this->pdo = new \PDO('mysql:host='.$this->host.';dbname='.$this->dbname.';charset=utf8', $this->username, $this->password, [
|
||||
$this->pdo = new PDOWrapper('mysql:host='.$this->host.';dbname='.$this->dbname.';charset=utf8', $this->username, $this->password, [
|
||||
\PDO::ATTR_DEFAULT_FETCH_MODE => \PDO::FETCH_ASSOC,
|
||||
\PDO::ATTR_TIMEOUT => 5
|
||||
\PDO::ATTR_TIMEOUT => 5,
|
||||
\PDO::ERRMODE_EXCEPTION => true
|
||||
]);
|
||||
|
||||
$this->pdo->setAttribute(\PDO::ATTR_STRINGIFY_FETCHES, false);
|
||||
$this->pdo->setAttribute(\PDO::ATTR_EMULATE_PREPARES, false);
|
||||
|
||||
if($debug){
|
||||
$this->pdo->enableDebug();
|
||||
}
|
||||
|
||||
// On signale que tout s'est bien passe
|
||||
$this->error = new Error(Err::Success);
|
||||
|
||||
|
@ -92,22 +98,20 @@
|
|||
**** Multiton Management (static) ****
|
||||
************************************************/
|
||||
|
||||
/* ADDS A NEW CONNECTION
|
||||
/** ADDS A NEW CONNECTION
|
||||
*
|
||||
* @label<String> [optional] Database Label
|
||||
* @param String $label [optional] Database Label
|
||||
*
|
||||
* @return status<Boolean> If added successfully
|
||||
* @return boolean If added successfully
|
||||
*
|
||||
*/
|
||||
private static function add($label=null){
|
||||
private static function add(String $label='default') : bool{
|
||||
$conf = self::conf();
|
||||
|
||||
/* [1] Default values
|
||||
=========================================================*/
|
||||
/* (1) If label isn't given */
|
||||
is_null($label) && ($label = 'default');
|
||||
|
||||
/* (2) If label and no path */
|
||||
/* (1) If label and no path */
|
||||
if( $label !== 'default' && !isset($conf[$label]) )
|
||||
return false;
|
||||
|
||||
|
@ -118,7 +122,11 @@
|
|||
|
||||
/* (1) If local -> instanciates with local configuration */
|
||||
// if( !checkdnsrr($_SERVER['SERVER_NAME'], 'NS') )
|
||||
self::$instance[$label] = new DatabaseDriver($conf[$label]['local']['host'], $conf[$label]['local']['dbname'], $conf[$label]['local']['user'], $conf[$label]['local']['password']);
|
||||
if(!isset($conf[$label]['local']['debug'])){
|
||||
$conf[$label]['local']['debug'] = false;
|
||||
}
|
||||
|
||||
self::$instance[$label] = new DatabaseDriver($conf[$label]['local']['host'], $conf[$label]['local']['dbname'], $conf[$label]['local']['user'], $conf[$label]['local']['password'],$conf[$label]['local']['debug']);
|
||||
/* (2) If Remote -> instanciates with Remote configuration */
|
||||
// else
|
||||
// self::$instance[$label] = new DatabaseDriver($conf[$label]['remote']['host'], $conf[$label]['remote']['dbname'], $conf[$label]['remote']['user'], $conf[$label]['remote']['password']);
|
||||
|
@ -135,22 +143,20 @@
|
|||
}
|
||||
|
||||
|
||||
/* GET A DATABASE DRIVER INSTANCE
|
||||
/** GET A DATABASE DRIVER INSTANCE
|
||||
*
|
||||
* @label<String> [optional] Driver's label
|
||||
*
|
||||
* @return driver<Database> Multiton
|
||||
* @param String $label [optional] Driver's label
|
||||
* @throws \Exception
|
||||
* @return DatabaseDriver Multiton
|
||||
*
|
||||
*/
|
||||
public static function get($label=null){
|
||||
public static function get(String $label='default') : DatabaseDriver{
|
||||
$conf = self::conf();
|
||||
|
||||
/* [1] Checks arguments
|
||||
=========================================================*/
|
||||
/* (1) Label default value */
|
||||
is_null($label) && ($label = 'default');
|
||||
|
||||
/* (2) If no label, or unknown label */
|
||||
/* (1) If no label, or unknown label */
|
||||
if( !isset(self::$instance[$label]) ){
|
||||
|
||||
/* (2.1) Try to add the configuration if exists */
|
||||
|
@ -171,21 +177,31 @@
|
|||
|
||||
|
||||
/** retourne la connection statique
|
||||
* @param null $label
|
||||
* @param String|null $label
|
||||
* @throws \Exception
|
||||
* @return \PDO
|
||||
*/
|
||||
public static function getPDO($label=null){
|
||||
$instance = self::get($label);
|
||||
public static function getPDO(?String $label=null) : \PDO{
|
||||
if(is_string($label)){
|
||||
$instance = self::get($label);
|
||||
}else{
|
||||
$instance = self::get();
|
||||
}
|
||||
|
||||
return $instance->pdo;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return \PDO
|
||||
*/
|
||||
public function pdo(){
|
||||
return $this->pdo;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getConfig(){
|
||||
return [
|
||||
'host' => $this->host,
|
||||
|
@ -194,6 +210,34 @@
|
|||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* enable request stacking
|
||||
*/
|
||||
public function enableStacking(){
|
||||
$this->pdo->enableStacking();
|
||||
}
|
||||
|
||||
/**
|
||||
* send all the stacked request and flush the stack
|
||||
*/
|
||||
public function flushStack(){
|
||||
$this->pdo->executeStack();
|
||||
}
|
||||
|
||||
/** get all debug data
|
||||
* @return array
|
||||
*/
|
||||
public function getDebug() : array{
|
||||
return $this->pdo->getDebug();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function isDebugEnabled() : bool {
|
||||
return $this->pdo->isDebugEnabled();
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,65 @@
|
|||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: lucas
|
||||
* Date: 30/08/16
|
||||
* Time: 17:42
|
||||
*/
|
||||
|
||||
namespace database\core\PDOWrapper;
|
||||
|
||||
|
||||
class PDOStatementWrapper extends \PDOStatement
|
||||
{
|
||||
/** @var String */
|
||||
private $statement;
|
||||
|
||||
/** @var array */
|
||||
private $parameters;
|
||||
|
||||
/** @var PDOWrapper */
|
||||
private $connexion;
|
||||
|
||||
/**
|
||||
* PDOStatementWrapper constructor.
|
||||
* @param String $statement
|
||||
* @param PDOWrapper $connexion
|
||||
*/
|
||||
public function __construct(String $statement, PDOWrapper $connexion)
|
||||
{
|
||||
$this->statement = $statement;
|
||||
$this->connexion = $connexion;
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $input_parameters
|
||||
* @return bool
|
||||
*/
|
||||
public function execute($input_parameters = []) : bool
|
||||
{
|
||||
$this->parameters = $input_parameters;
|
||||
$this->connexion->stackStatement($this);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getStatement() : String
|
||||
{
|
||||
return $this->statement;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getParameters() : array
|
||||
{
|
||||
return $this->parameters;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,197 @@
|
|||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: lucas
|
||||
* Date: 30/08/16
|
||||
* Time: 17:26
|
||||
*/
|
||||
|
||||
namespace database\core\PDOWrapper;
|
||||
|
||||
|
||||
class PDOWrapper extends \PDO
|
||||
{
|
||||
/** @var PDOStatementWrapper[] */
|
||||
private $statements = [];
|
||||
|
||||
/** @var bool */
|
||||
private $stacking = false;
|
||||
|
||||
/** @var array */
|
||||
private $debug = [];
|
||||
|
||||
/** @var bool */
|
||||
private $debugEnabled = false;
|
||||
|
||||
/**
|
||||
* PDOWrapper constructor.
|
||||
* @param String $dsn
|
||||
* @param String $username
|
||||
* @param String $passwd
|
||||
* @param array $options
|
||||
*/
|
||||
public function __construct(String $dsn, String $username, String $passwd, array $options = [])
|
||||
{
|
||||
parent::__construct($dsn, $username, $passwd, $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $statement
|
||||
* @param array $options
|
||||
* @return \PDOStatement
|
||||
*/
|
||||
public function prepare($statement, $options = []) : \PDOStatement
|
||||
{
|
||||
if($this->debugEnabled){
|
||||
$this->storeDebug();
|
||||
}
|
||||
|
||||
if($this->stacking){
|
||||
return new PDOStatementWrapper($statement, $this);
|
||||
}else{
|
||||
return parent::prepare($statement, $options);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws \ReflectionException
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function storeDebug(){
|
||||
//get all the debug info about the repo
|
||||
$prepareStack = debug_backtrace(0,3)[1];
|
||||
$stack = debug_backtrace(0,3)[2];
|
||||
//create the reflection object
|
||||
$f = new \ReflectionMethod($stack["class"],$stack["function"]);
|
||||
//get only the repo name
|
||||
$className = explode("\\",$stack["class"]);
|
||||
$className = $className[count($className)-1];
|
||||
|
||||
$result = [];
|
||||
|
||||
//if we are flushing a stack, just count the number of request stacked
|
||||
if($stack["function"] == "executeStack"){
|
||||
|
||||
$result["StackedRequest"] = true;
|
||||
$result["numberOfStackedRequest"] = substr_count($prepareStack["args"][0],";");
|
||||
//if we are not stacking, log the repo call
|
||||
}else if(!$this->stacking){
|
||||
//store results
|
||||
$result["repoName"] = $className;
|
||||
$result["methodName"] = $stack["function"];
|
||||
$result["args"] = [];
|
||||
|
||||
foreach ($f->getParameters() as $key => $param) {
|
||||
$result["args"][$param->name] = $stack["args"][$key];
|
||||
}
|
||||
//else we are stacking a request, we should not log it
|
||||
}else{
|
||||
return;
|
||||
}
|
||||
|
||||
$this->debug[] = $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getDebug() : array{
|
||||
return $this->debug;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable request stacking
|
||||
*/
|
||||
public function enableStacking(){
|
||||
$this->stacking = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function isDebugEnabled() : bool{
|
||||
return $this->debugEnabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param PDOStatementWrapper $st
|
||||
*/
|
||||
public function stackStatement(PDOStatementWrapper $st){
|
||||
array_push($this->statements,$st);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable repo debug
|
||||
*/
|
||||
public function enableDebug(){
|
||||
$this->debugEnabled = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* disable repo debug
|
||||
*/
|
||||
public function disableDebug(){
|
||||
$this->debugEnabled = false;
|
||||
}
|
||||
|
||||
/** Execute the stored request stack
|
||||
* @return bool
|
||||
*/
|
||||
public function executeStack(){
|
||||
//init the statements and the generator of number
|
||||
$finalStatement = '';
|
||||
$finalExecute = [];
|
||||
$i = 0;
|
||||
|
||||
//for each request stacked
|
||||
foreach ($this->statements as $request){
|
||||
$statement = $request->getStatement();
|
||||
|
||||
// we have to modify the parameters index at the same time that we modify the request, so we use static class attribute
|
||||
$tempParametes = $request->getParameters();
|
||||
|
||||
//find the given pattern in the request, then call our function and replace the matched string by the return value of our function
|
||||
$finalStatement .= rtrim(preg_replace_callback("/(:[a-z_\-0-9]*)/is",function($matches) use (&$i,&$tempParametes){
|
||||
//get next number
|
||||
$i++;
|
||||
|
||||
//delete the ':' at the beginning of the string
|
||||
$tempKey = ltrim($matches[0],':');
|
||||
|
||||
//copy the parameter with the modified index
|
||||
$tempParametes[$tempKey.$i] = $tempParametes[$tempKey];
|
||||
|
||||
//delete the old index
|
||||
unset($tempParametes[$tempKey]);
|
||||
|
||||
//return the modified string for replacement
|
||||
return $matches[0].$i;
|
||||
},$statement),';').';';
|
||||
|
||||
$finalExecute = array_merge($finalExecute,$tempParametes);
|
||||
}
|
||||
|
||||
//disable stacking
|
||||
$this->stacking = false;
|
||||
|
||||
//enable prepare emulation (native prepare do not accept stacked requests
|
||||
parent::setAttribute(\PDO::ATTR_EMULATE_PREPARES, true);
|
||||
|
||||
$this->beginTransaction();
|
||||
|
||||
$req = $this->prepare($finalStatement);
|
||||
|
||||
$success = $req->execute($finalExecute);
|
||||
//as we execute multiple query that we don't fetch, we have to close the cursor if we want to do other requests later
|
||||
$req->closeCursor();
|
||||
$this->commit();
|
||||
|
||||
//using beginTransaction/commit disable the autocommit, we re-activate it
|
||||
$this->setAttribute(\PDO::ATTR_AUTOCOMMIT,1);
|
||||
parent::setAttribute(\PDO::ATTR_EMULATE_PREPARES, false);
|
||||
|
||||
return $success;
|
||||
}
|
||||
}
|
|
@ -12,6 +12,7 @@
|
|||
|
||||
namespace database\core;
|
||||
|
||||
use database\core\PDOWrapper\PDOWrapper;
|
||||
use \error\core\Error;
|
||||
use \error\core\Err;
|
||||
|
||||
|
@ -20,6 +21,9 @@
|
|||
|
||||
/* (1) Driver
|
||||
---------------------------------------------------------*/
|
||||
/**
|
||||
* @var DatabaseDriver
|
||||
*/
|
||||
private static $driver = null;
|
||||
|
||||
public static function setDriver(DatabaseDriver $driver){ self::$driver = $driver; }
|
||||
|
@ -57,6 +61,22 @@
|
|||
return $instance;
|
||||
}
|
||||
|
||||
public static function enableStacking(){
|
||||
static::$driver->enableStacking();
|
||||
}
|
||||
|
||||
public static function flushStack(){
|
||||
static::$driver->flushStack();
|
||||
}
|
||||
|
||||
public static function getDebug() : array{
|
||||
return static::$driver->getDebug();
|
||||
}
|
||||
|
||||
public static function isDebugEnabled() : bool{
|
||||
return static::$driver->isDebugEnabled();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
namespace database\repo;
|
||||
|
||||
|
||||
use database\core\Repo;
|
||||
use database\core\Repo_i;
|
||||
|
||||
class departement extends Repo_i
|
||||
|
@ -88,4 +89,82 @@ class departement extends Repo_i
|
|||
return $results;
|
||||
}
|
||||
|
||||
public function getStats() : array{
|
||||
|
||||
/* (1) Potentiel horaire du département */
|
||||
$Potentiel = $this->pdo->prepare("SELECT SUM(hoursToDo) potentiel
|
||||
FROM Professeur
|
||||
WHERE Categorie_idCategorie IN (1,2,3)
|
||||
GROUP BY Categorie_idCategorie IN (1,2,3);");
|
||||
|
||||
$Potentiel->execute([]);
|
||||
|
||||
$results = $Potentiel->fetch();
|
||||
|
||||
/* (2) Sous-service (professeurs ayant moins d'heure prévu que d'heure du) */
|
||||
/** @var professor $ProfRepo */
|
||||
$ProfRepo = Repo::getRepo("professor");
|
||||
|
||||
$profs = $ProfRepo->getWithVH(null);
|
||||
|
||||
$results["sous_service"] = 0;
|
||||
$results["heures_comp"] = 0;
|
||||
$results["heures_vacataire"] = 0;
|
||||
|
||||
foreach ($profs as $prof){
|
||||
if(in_array($prof["idCat"],[1,2,3,4]) and $prof["equiTD"] < $prof["hoursToDo"]){
|
||||
$results["sous_service"] += $prof["hoursToDo"] - $prof["equiTD"];
|
||||
|
||||
/* (3) Heures effectués par des vacataires */
|
||||
}else if(in_array($prof["idCat"],[5,6])){
|
||||
$results["heures_vacataire"] += $prof["equiTD"];
|
||||
}
|
||||
|
||||
/* (4) Heures complementaires */
|
||||
|
||||
if(is_numeric($prof["VHComp"])){
|
||||
$results["heures_comp"] += $prof["VHComp"];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* (5) Heures effectuées pour des départements exterieurs */
|
||||
//je crois que j'ai créé un montre - Lucas - 2018
|
||||
$HDepExt = $this->pdo->prepare("
|
||||
SELECT U.disabled disabled,
|
||||
count(U.code) nbrUe,
|
||||
SUM((IFNULL(T1.VolumeCours,0)*IFNULL(tauxInfoCours,0) + IFNULL(T2.VolumeTD,0)*IFNULL(tauxInfoTD,0) + IFNULL(T3.VolumeTP,0)*IFNULL(tauxInfoTP,0))) totalInfo,
|
||||
SUM((IFNULL(T1.VolumeCours,0)*(1-IFNULL(tauxInfoCours,0)) + IFNULL(T2.VolumeTD,0)*(1-IFNULL(tauxInfoTD,0)) + IFNULL(T3.VolumeTP,0)*(1-IFNULL(tauxInfoTP,0)))) totalExterieur
|
||||
FROM UE U
|
||||
LEFT JOIN (SELECT SUM(F.isInternal)/count(F.idFormation) tauxInfoCours,SUM(C.volume)*1.5 VolumeCours, C.UE_code code_UE
|
||||
FROM Cours C
|
||||
JOIN GroupeCours C2 ON C.idCours = C2.Cours_idCours
|
||||
JOIN Formation F ON C2.Formation_idFormation = F.idFormation
|
||||
GROUP BY C.UE_code) T1 ON U.code = T1.code_UE
|
||||
LEFT JOIN (SELECT SUM(F.isInternal)/count(F.idFormation) tauxInfoTD,SUM(T1.volume) VolumeTD, T1.UE_code code_UE
|
||||
FROM TD T1
|
||||
JOIN GroupeTD GT ON T1.idTD = GT.TD_idTD
|
||||
JOIN Formation F ON GT.Formation_idFormation = F.idFormation
|
||||
GROUP BY T1.UE_code) T2 ON U.code = T2.code_UE
|
||||
LEFT JOIN (SELECT SUM(F.isInternal)/count(F.idFormation) tauxInfoTP,SUM(T1.volume) VolumeTP, T1.UE_code code_UE
|
||||
FROM TP T1
|
||||
JOIN GroupeTP TP2 ON T1.idTP = TP2.TP_idTP
|
||||
JOIN Formation F ON TP2.Formation_idFormation = F.idFormation
|
||||
GROUP BY T1.UE_code) T3 ON U.code = T3.code_UE
|
||||
GROUP BY U.disabled");
|
||||
|
||||
$HDepExt->execute([]);
|
||||
|
||||
$HDepExtData = $HDepExt->fetchAll();
|
||||
|
||||
$results = array_merge($results,[
|
||||
"heures_exterieur" => $HDepExtData[0]["totalExterieur"],
|
||||
"heures_ue_desactive" => $HDepExtData[1]["totalExterieur"] + $HDepExtData[1]["totalInfo"],
|
||||
"nbr_ue_desactive" => $HDepExtData[1]["nbrUe"]
|
||||
]);
|
||||
|
||||
return $results;
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -64,19 +64,26 @@ class professor extends Repo_i {
|
|||
* @return prof_id<int> The professor's UID (or NULL on error)
|
||||
*
|
||||
---------------------------------------------------------*/
|
||||
public function exists(string $lastName, string $firstName) : ?int{
|
||||
public function exists(string $lastName, string $firstName, ?string $casLogin = null) : ?int{
|
||||
|
||||
/* (1) Prepare Statement */
|
||||
$st = $this->pdo->prepare("SELECT idProfesseur
|
||||
FROM Professeur
|
||||
WHERE firstName = :firstName
|
||||
AND lastName = :lastName");
|
||||
AND lastName = :lastName
|
||||
".(is_string($casLogin) ? "AND casLogin = :casLogin" : ""));
|
||||
|
||||
/* (2) Bind params and execute */
|
||||
$success = $st->execute([
|
||||
$params = [
|
||||
':firstName' => $firstName,
|
||||
':lastName' => $lastName
|
||||
]);
|
||||
];
|
||||
|
||||
if(is_string($casLogin)){
|
||||
$params[":casLogin"] = $casLogin;
|
||||
}
|
||||
|
||||
$success = $st->execute();
|
||||
|
||||
/* (3) Return NULL on error */
|
||||
if( !$success )
|
||||
|
@ -214,21 +221,25 @@ class professor extends Repo_i {
|
|||
/* (1) Prepare Statement */
|
||||
$st = $this->pdo->prepare("SELECT * FROM `Professeur` WHERE `casLogin` = :cas_login");
|
||||
|
||||
/* (2) Bind params and execute statement */
|
||||
/* (2) Check if statement error */
|
||||
if( is_bool($st) )
|
||||
return NULL;
|
||||
|
||||
/* (3) Bind params and execute statement */
|
||||
$success = $st->execute([ ':cas_login' => $cas_login ]);
|
||||
|
||||
/* (3) Manage error */
|
||||
/* (4) Manage error */
|
||||
if( !$success )
|
||||
return NULL;
|
||||
|
||||
/* (4) Get data */
|
||||
/* (5) Get data */
|
||||
$fetched = $st->fetch();
|
||||
|
||||
/* (5) Return NULL on no result */
|
||||
/* (6) Return NULL on no result */
|
||||
if( $fetched === false )
|
||||
return NULL;
|
||||
|
||||
/* (6) Return data */
|
||||
/* (7) Return data */
|
||||
return $fetched;
|
||||
|
||||
}
|
||||
|
@ -319,7 +330,7 @@ class professor extends Repo_i {
|
|||
$prof['VHComp'] = round($prof['equiTD'] - $prof['hoursToDo'], 2);
|
||||
$prof['VHComp'] = ( $prof['VHComp'] < 0 ) ? 0 : $prof['VHComp'];
|
||||
}else{
|
||||
$VH["equiTD"] = $prof["VHTd"] + (2/3)*$prof["VHTp"] + 1.5*$prof["VHCours"];
|
||||
$prof["equiTD"] = $prof["VHTd"] + (2/3)*$prof["VHTp"] + 1.5*$prof["VHCours"];
|
||||
if(is_numeric($prof["hoursToDo"]) and $prof["hoursToDo"] > 0){
|
||||
$prof['VHComp'] = round($prof['equiTD'] - $prof['hoursToDo'], 2);
|
||||
$prof['VHComp'] = ( $prof['VHComp'] < 0 ) ? 0 : $prof['VHComp'];
|
||||
|
|
|
@ -18,16 +18,17 @@ class ue extends Repo_i {
|
|||
*
|
||||
* @code<String> The code of the UE
|
||||
* @label<String> The UE label (name)
|
||||
* @required<bool> If the UE is required
|
||||
* @volumeCours<float> The UE required volume of COURSES
|
||||
* @volumeTD<float> The UE required volume of TD
|
||||
* @volumeTP<float> The UE required volume of TP
|
||||
* @disabled<bool> If it is disabled
|
||||
* @defaultFormation<bool> If there is a foreign key for a default formation (if only one formation)
|
||||
* @disabled<bool> [OPT] If it is disabled
|
||||
* @defaultFormation<int> [OPT] If there is a foreign key for a default formation (if only one formation)
|
||||
*
|
||||
* @return created_code<String> Code of the created UE (NULL on error)
|
||||
*
|
||||
---------------------------------------------------------*/
|
||||
public function create(string $code, string $label, bool $required, float $volumeCours, float $volumeTD, float $volumeTP, bool $disabled = false, ?int $defaultFormation = null) : ?int {
|
||||
public function create(string $code, string $label, bool $required, float $volumeCours, float $volumeTD, float $volumeTP, bool $disabled = false, ?int $defaultFormation = null) : ?string {
|
||||
|
||||
/* (1) Prepare request */
|
||||
$st = $this->pdo->prepare("INSERT INTO UE(`code`, `label`, `required`, `volumeCours`, `volumeTD`, `volumeTP`, `disabled`, `Formation_idFormation`)
|
||||
|
@ -39,14 +40,14 @@ class ue extends Repo_i {
|
|||
|
||||
/* (3) Bind params and execute request */
|
||||
$success = $st->execute([
|
||||
"code" => $code,
|
||||
"label" => $label,
|
||||
"required" => $required ? 1 : 0,
|
||||
"volCours" => $volumeCours,
|
||||
"volTD" => $volumeTD,
|
||||
"volTP" => $volumeTP,
|
||||
"disabled" => $disabled ? 1 : 0,
|
||||
"idFormation" => $defaultFormation
|
||||
':code' => $code,
|
||||
':label' => $label,
|
||||
':required' => $required ? 1 : 0,
|
||||
':volCours' => $volumeCours,
|
||||
':volTD' => $volumeTD,
|
||||
':volTP' => $volumeTP,
|
||||
':disabled' => $disabled ? 1 : 0,
|
||||
':idFormation' => $defaultFormation
|
||||
]);
|
||||
|
||||
/* (4) Manage execution error */
|
||||
|
@ -54,7 +55,7 @@ class ue extends Repo_i {
|
|||
return null;
|
||||
|
||||
/* (5) Return insert id */
|
||||
return $this->pdo->lastInsertId();
|
||||
return $code;
|
||||
|
||||
}
|
||||
|
||||
|
@ -68,7 +69,7 @@ class ue extends Repo_i {
|
|||
* @volumeTD<float> [OPT] The UE's new volume of TD
|
||||
* @volumeTP<float> [OPT] The UE's new volume of TP
|
||||
* @disabled<bool> [OPT] Whether the UE is disabled
|
||||
* @defaultFormation<int> [OPT] The default formation foreign key
|
||||
* @defaultFormation<int> [OPT] The default formation foreign key (-1 to unset)
|
||||
*
|
||||
* @return updated<bool> Whether the update have been successful
|
||||
*
|
||||
|
@ -80,15 +81,25 @@ class ue extends Repo_i {
|
|||
$bind_param = [ ':code' => $code ];
|
||||
|
||||
if( !is_null($label) ){ $build_rq[] = '`label` = :label'; $bind_param[':label'] = $label; }
|
||||
if( !is_null($required) ){ $build_rq[] = '`required` = :required'; $bind_param[':required'] = $required; }
|
||||
if( !is_null($required) ){ $build_rq[] = '`required` = :required'; $bind_param[':required'] = $required?1:0; }
|
||||
if( !is_null($volumeCours) ){ $build_rq[] = '`volumeCours` = :volumeCours'; $bind_param[':volumeCours'] = $volumeCours; }
|
||||
if( !is_null($volumeTD) ){ $build_rq[] = '`volumeTD` = :volumeTD'; $bind_param[':volumeTD'] = $volumeTD; }
|
||||
if( !is_null($volumeTP) ){ $build_rq[] = '`volumeTP` = :volumeTP'; $bind_param[':volumeTP'] = $volumeTP; }
|
||||
if( !is_null($disabled) ){ $build_rq[] = '`disabled` = :disabled'; $bind_param[':disabled'] = $disabled; }
|
||||
if( !is_null($defaultFormation) ){ $build_rq[] = '`Formation_idFormation` = :defaultFormation'; $bind_param[':defaultFormation'] = $defaultFormation; }
|
||||
if( !is_null($disabled) ){ $build_rq[] = '`disabled` = :disabled'; $bind_param[':disabled'] = $disabled?1:0; }
|
||||
|
||||
// not null @defaultFormation -> set it
|
||||
if( !is_null($defaultFormation) ){
|
||||
|
||||
// if @defaultFormation is (-1) -> unset
|
||||
if( $defaultFormation < 0 ){ $build_rq[] = '`Formation_idFormation` = NULL'; }
|
||||
// else -> set to new value
|
||||
else{ $build_rq[] = '`Formation_idFormation` = :defaultFormation'; $bind_param[':defaultFormation'] = $defaultFormation; }
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* (2) ERROR if no updated field */
|
||||
if( count($build_rq) <= 0 || count($bind_param) <= 1 )
|
||||
if( count($build_rq) <= 0 )
|
||||
return FALSE;
|
||||
|
||||
/* (3) Build request */
|
||||
|
@ -160,14 +171,19 @@ class ue extends Repo_i {
|
|||
* @return ues<array> The UEs matching code (NULL on error)
|
||||
*
|
||||
---------------------------------------------------------*/
|
||||
public function get(?String $code=null) : ?array{
|
||||
public function get(?String $code=null) : array{
|
||||
|
||||
/* (1) Manage if no id given */
|
||||
$cond = is_null($code) ? '' : ' WHERE `code` = :code';
|
||||
$cond = is_null($code) ? '' : 'WHERE `code` = :code';
|
||||
$parm = is_null($code) ? [] : [':code' => $code];
|
||||
|
||||
/* (2) Prepare Statement */
|
||||
$st = $this->pdo->prepare("SELECT * FROM `UE`$cond GROUP BY `label` ASC");
|
||||
$this->pdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
|
||||
$st = $this->pdo->prepare("SELECT ue.code, ue.label, ue.disabled, ue.required, ue.volumeCours, ue.volumeTD, ue.volumeTP, IFNULL(ue.Formation_idFormation, -1) idForm, f.labelFormation labelForm
|
||||
FROM `UE` ue
|
||||
LEFT JOIN Formation f ON ue.Formation_idFormation = f.idFormation
|
||||
$cond
|
||||
ORDER BY `ue`.`label` ASC");
|
||||
|
||||
/* (3) Bind params and execute statement */
|
||||
if( is_bool($st) ) return [];
|
||||
|
|
|
@ -4,7 +4,8 @@
|
|||
"host" : "mariadb",
|
||||
"dbname" : "vhost",
|
||||
"user" : "php",
|
||||
"password" : "4JB1dtbrIC8pT935"
|
||||
"password" : "4JB1dtbrIC8pT935",
|
||||
"debug" : true
|
||||
},
|
||||
"remote": {
|
||||
"host" : "db_remote_host",
|
||||
|
|
|
@ -79,6 +79,14 @@
|
|||
"par": {
|
||||
}
|
||||
}
|
||||
},
|
||||
"stats":{
|
||||
"GET": {
|
||||
"des": "Get the statistics about the departement",
|
||||
"per": [],
|
||||
"par": {
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -177,17 +185,17 @@
|
|||
"des": "Creates a new UE",
|
||||
"per": [],
|
||||
"par": {
|
||||
"code": { "des": "UE code.", "typ": "varchar(2,30,alphanumeric)" },
|
||||
"label": { "des": "UE label", "typ": "varchar(2,30,alphanumeric)" },
|
||||
"required": { "des": "If UE is required", "typ": "bool" },
|
||||
"volumeCours": { "des": "Number of course hours for UE", "typ": "float" },
|
||||
"volumeTD": { "des": "Number of TD hours for UE", "typ": "float" },
|
||||
"volumeTP": { "des": "Number of TP hours for UE", "typ": "float" },
|
||||
"disabled": { "des": "Whether UE is disabled", "typ": "boolean" },
|
||||
"defaultFormation": { "des": "UID for optional default formation", "typ": "id", "opt": true }
|
||||
"code": { "des": "UE code.", "typ": "varchar(4,20,alphanumeric)" },
|
||||
"label": { "des": "UE label", "typ": "varchar(4,30,alphanumeric)" },
|
||||
"required": { "des": "If UE is required", "typ": "bool" },
|
||||
"volumeCours": { "des": "Number of course hours for UE", "typ": "float" },
|
||||
"volumeTD": { "des": "Number of TD hours for UE", "typ": "float" },
|
||||
"volumeTP": { "des": "Number of TP hours for UE", "typ": "float" },
|
||||
"disabled": { "des": "Whether UE is disabled", "typ": "boolean" },
|
||||
"defaultFormation": { "des": "UID for optional default formation (-1 if none)", "typ": "int", "opt": true, "def": -1 }
|
||||
},
|
||||
"out": {
|
||||
"created_code": { "des": "Created UE code", "typ": "varchar(2,30,alphanumeric)" }
|
||||
"created_code": { "des": "Created UE code", "typ": "varchar(4,20,alphanumeric)" }
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -195,11 +203,41 @@
|
|||
"des": "Get one or all UE",
|
||||
"per": [],
|
||||
"par": {
|
||||
"URL0": { "des": "Optional UE code.", "typ": "varchar(2,30,alphanumeric)", "ren": "code", "opt": true }
|
||||
"URL0": { "des": "Optional UE code.", "typ": "varchar(4,20,alphanumeric)", "ren": "code", "opt": true }
|
||||
},
|
||||
"out": {
|
||||
"ues": { "des": "UE list", "typ": "array" }
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
"DELETE": {
|
||||
"des": "Deletes an existing UE",
|
||||
"per": [],
|
||||
"par": {
|
||||
"URL0": { "des": "UE code.", "typ": "varchar(4,20,alphanumeric)", "ren": "code" }
|
||||
},
|
||||
"out": {
|
||||
"deleted": { "des": "Whether it has been deleted", "typ": "boolean" }
|
||||
}
|
||||
},
|
||||
|
||||
"PUT": {
|
||||
"des": "Edits an existing UE",
|
||||
"per": [],
|
||||
"par": {
|
||||
"URL0": { "des": "UE code.", "typ": "varchar(4,20,alphanumeric)", "ren": "code" },
|
||||
"label": { "des": "UE label", "typ": "varchar(4,30,alphanumeric)", "opt": true },
|
||||
"required": { "des": "If UE is required", "typ": "bool", "opt": true },
|
||||
"volumeCours": { "des": "Number of course hours for UE", "typ": "float", "opt": true },
|
||||
"volumeTD": { "des": "Number of TD hours for UE", "typ": "float", "opt": true },
|
||||
"volumeTP": { "des": "Number of TP hours for UE", "typ": "float", "opt": true },
|
||||
"disabled": { "des": "Whether UE is disabled", "typ": "boolean", "opt": true },
|
||||
"defaultFormation": { "des": "UID for optional default formation (-1 for none)", "typ": "int", "opt": true }
|
||||
},
|
||||
"out": {
|
||||
"updated": { "des": "Whether the UE has been updated", "typ": "boolean" }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
enable-background="new 0 0 141.732 141.732"
|
||||
height="141.732px"
|
||||
id="Livello_1"
|
||||
version="1.1"
|
||||
viewBox="0 0 141.732 141.732"
|
||||
width="141.732px"
|
||||
xml:space="preserve"
|
||||
sodipodi:docname="bell.svg"
|
||||
inkscape:version="0.92.2 5c3e80d, 2017-08-06"><metadata
|
||||
id="metadata11"><rdf:RDF><cc:Work
|
||||
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
|
||||
id="defs9" /><sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1015"
|
||||
id="namedview7"
|
||||
showgrid="false"
|
||||
inkscape:zoom="1.6651145"
|
||||
inkscape:cx="70.865997"
|
||||
inkscape:cy="70.865997"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="29"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="Livello_1" /><path
|
||||
inkscape:connector-curvature="0"
|
||||
id="fill-edit"
|
||||
d="m 135.055,115.131 c 0,-3.528 -2.861,-6.396 -6.395,-6.396 -8.83,0 -15.988,-7.158 -15.988,-15.99 V 54.367 C 112.672,34.361 98.463,17.658 79.533,13.688 80.121,12.446 80.461,11.06 80.461,9.593 80.462,4.296 76.165,0 70.866,0 c -5.299,0 -9.594,4.296 -9.594,9.598 0,1.467 0.339,2.853 0.927,4.095 -18.928,3.97 -33.137,20.673 -33.137,40.679 v 38.377 c 0,8.832 -7.159,15.99 -15.99,15.99 -3.533,0 -6.396,2.864 -6.396,6.396 0,3.531 2.862,6.396 6.396,6.396 h 15.99 29.011 c 0,9.716 5.729,17.591 12.793,17.591 7.064,0 12.792,-7.875 12.792,-17.591 h 29.014 15.988 v 0 c 3.534,-0.005 6.395,-2.867 6.395,-6.4" /></svg>
|
After Width: | Height: | Size: 2.1 KiB |
|
@ -7,7 +7,7 @@
|
|||
<meta http-equiv="X-UA-Compatible" content="ie=edge">
|
||||
|
||||
|
||||
<title>Gestion des enseignants</title>
|
||||
<title>Gestion des UEs</title>
|
||||
|
||||
<!-- Icon -->
|
||||
<link rel='shortcut icon' href='/favicon.ico'>
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
<div class='card container'>
|
||||
|
||||
<input class='card instant-search neutral' type='text' @keyup='gstore.is_handler($event)' placeholder='Recherche instantannée' id='teacher_view_instant_search'>
|
||||
<button class='card toggle valid' :data-active='gstore.create_card?1:0' @click='gstore.create_card=!gstore.create_card'>+</button>
|
||||
<button class='card toggle valid' :data-active='gstore.create_card?1:0' @click='gstore.create_card=!gstore.create_card' title='Créer un enseignant'>+</button>
|
||||
|
||||
<section class='valid' data-create='' v-show='gstore.create_card'>
|
||||
|
||||
|
@ -58,9 +58,9 @@
|
|||
|
||||
<!-- if VIEW MODE -->
|
||||
<div class='goo-menu' v-show='gstore.edit_i!=pi'>
|
||||
<div class='admin' :data-admin='prof.idProfesseur' :data-active='prof.admin?1:0' @click="gstore.ia_handler(pi)"></div>
|
||||
<div class='remove' :data-remove='prof.idProfesseur' @click="gstore.ir_handler($event.currentTarget.getAttribute('data-remove'))"></div>
|
||||
<div class='edit' :data-edit='prof.idProfesseur' @click="gstore.ie_toggle(pi)"></div>
|
||||
<div class='admin' :data-admin='prof.idProfesseur' :data-active='prof.admin?1:0' title='Admin' @click="gstore.ia_handler(pi)"></div>
|
||||
<div class='remove' :data-remove='prof.idProfesseur' title='Supprimer' @click="gstore.ir_handler(prof.idProfesseur)"></div>
|
||||
<div class='edit' :data-edit='prof.idProfesseur' title='Modifier' @click="gstore.ie_toggle(pi)"></div>
|
||||
</div>
|
||||
|
||||
<!-- if VIEW MODE -->
|
||||
|
@ -73,7 +73,7 @@
|
|||
<!-- endif -->
|
||||
|
||||
<!-- if VIEW MODE -->
|
||||
<h1 v-show='gstore.edit_i!=pi' :class="prof.hoursToDo > prof.equiTD ? 'warning' : ''">{{ prof.firstName }} {{ prof.lastName }} <span :data-visible='prof.casLogin.length'>({{ prof.casLogin }})</span></h1>
|
||||
<h1 v-show='gstore.edit_i!=pi' :class="prof.hoursToDo > prof.equiTD ? 'warning' : ''" :title="prof.hoursToDo > prof.equiTD ? 'Attention: heures manquantes' : ''">{{ prof.firstName }} {{ prof.lastName }} <span :data-visible='prof.casLogin.length'>({{ prof.casLogin }})</span></h1>
|
||||
<!-- if EDIT MODE -->
|
||||
<h1 v-show='gstore.edit_i==pi' :class="prof.hoursToDo > prof.equiTD ? 'warning' : ''">
|
||||
<input type='text' placeholder='Prénom Nom' v-model='gstore.edit_name'>
|
||||
|
@ -91,14 +91,14 @@
|
|||
<!-- endif -->
|
||||
<span>heures à faire</span>
|
||||
</div>
|
||||
<div>
|
||||
<div title='équivalents TD'>
|
||||
<span>{{ prof.equiTD }}</span>
|
||||
<span>heures prévues</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- if VIEW MODE -->
|
||||
<div v-show='gstore.edit_i!=pi' class='sub'><strong>{{ prof.VHCours + prof.VHTd + prof.VHTp }}h</strong> physiques prévues</div>
|
||||
<div v-show='gstore.edit_i!=pi' class='sub' title='total des heures prévues'><strong>{{ prof.VHCours + prof.VHTd + prof.VHTp }}h</strong> réelles prévues</div>
|
||||
<!-- if EDIT MODE -->
|
||||
<div v-show='gstore.edit_i==pi' :class="gstore.edit_err.length > 0 ? 'sub warning' : 'sub'" :data-valid='gstore.edit_err_valid?1:0'>{{ gstore.edit_err }}</div>
|
||||
<!-- endif -->
|
||||
|
@ -107,9 +107,9 @@
|
|||
<!-- if VIEW MODE -->
|
||||
<span v-show='gstore.edit_i!=pi' :class="(prof.VHCours == 0) ? 'course' : 'course active'">{{ prof.VHCours }}h <span>Cours</span></span>
|
||||
<hr v-show='gstore.edit_i!=pi'>
|
||||
<span v-show='gstore.edit_i!=pi' :class="(prof.VHTd == 0) ? 'td' : 'td active'">{{ prof.VHTd }}h <span>TD</span></span>
|
||||
<span v-show='gstore.edit_i!=pi' :class="(prof.VHTd == 0) ? 'td' : 'td active'" >{{ prof.VHTd }}h <span>TD</span></span>
|
||||
<hr v-show='gstore.edit_i!=pi'>
|
||||
<span v-show='gstore.edit_i!=pi' :class="(prof.VHTp == 0) ? 'tp' : 'tp active'">{{ prof.VHTp }}h <span>TP</span></span>
|
||||
<span v-show='gstore.edit_i!=pi' :class="(prof.VHTp == 0) ? 'tp' : 'tp active'" >{{ prof.VHTp }}h <span>TP</span></span>
|
||||
<!-- if EDIT MODE -->
|
||||
<button v-show='gstore.edit_i==pi' class='search' @click='gstore.ie_handler(pi)'>Modifier l'enseignant</button>
|
||||
<button v-show='gstore.edit_i==pi' class='grey' @click='gstore.ie_toggle(-1)'>Annuler</button>
|
||||
|
|
|
@ -1,38 +1,110 @@
|
|||
<template>
|
||||
|
||||
<div id='CONTAINER' class='card' style="top: 0; height: 100%">
|
||||
<div id='CONTAINER' class='card'>
|
||||
|
||||
<div class="card container" style="width: 100%">
|
||||
<section v-if='gstore.ues.length <= 0'>Aucun enseignant trouvé</section>
|
||||
<div class='card container'>
|
||||
|
||||
<section v-for='ue in gstore.ues' :data-id='ue.code'>
|
||||
<span class='category'>{{ ue.code }}</span>
|
||||
<h1>{{ ue.label }}</h1>
|
||||
<input class='card instant-search neutral' type='text' @keyup='gstore.is_handler($event)' placeholder='Recherche instantannée' id='ue_view_instant_search'>
|
||||
<button class='card toggle valid' :data-active='gstore.create_card?1:0' @click='gstore.create_card=!gstore.create_card' title='Créer une UE'>+</button>
|
||||
|
||||
<div class='table'>
|
||||
<div>
|
||||
<span>{{ue.volumeCours}}</span>
|
||||
<span>heures de cours</span>
|
||||
</div>
|
||||
<div>
|
||||
<span>{{ue.volumeTD}}</span>
|
||||
<span>heures de TD</span>
|
||||
</div>
|
||||
<div>
|
||||
<span>{{ue.volumeTP}}</span>
|
||||
<span>heures de TP</span>
|
||||
</div>
|
||||
</div>
|
||||
<section class='valid' data-create='' v-show='gstore.create_card'>
|
||||
|
||||
<div class='sub'><strong>ZOU</strong> équivalents TD</div>
|
||||
<select v-model='gstore.create_form' class='category'>
|
||||
<option selected='selected' disabled='disabled' value='-'>Formation par défaut</option>
|
||||
<option value='-1'>Aucune formation par défaut</option>
|
||||
<option v-for='form in gstore.formations' :value='form.idForm'>{{ form.labelForm }}</option>
|
||||
</select>
|
||||
|
||||
<div class='footer'>
|
||||
<span :class="(ue.volumeCours == 0) ? 'course' : 'course active'">{{ ue.volumeCours }}</span><hr>
|
||||
<span :class="(ue.volumeTD == 0) ? 'td' : 'td active'">{{ ue.volumeTD }}</span><hr>
|
||||
<span :class="(ue.volumeTP == 0) ? 'tp' : 'tp active'">{{ ue.volumeTP }}</span>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
<h1>
|
||||
<input type='text' placeholder='Libellé' v-model='gstore.create_label'>
|
||||
<span data-visible='1'>(<input type='text' placeholder='code' v-model='gstore.create_code'>)</span>
|
||||
</h1>
|
||||
|
||||
<div :class="gstore.create_err.length > 0 ? 'sub warning' : 'sub'" :data-valid='gstore.create_err_valid?1:0'>{{ gstore.create_err }}</div>
|
||||
|
||||
<div class='footer'>
|
||||
<span class='course'><input type='text' placeholder='???' v-model='gstore.create_vol.c'><span>Cours</span></span>
|
||||
<hr>
|
||||
<span class='td'><input type='text' placeholder='???' v-model='gstore.create_vol.td'><span>TD</span></span>
|
||||
<hr>
|
||||
<span class='tp'><input type='text' placeholder='???' v-model='gstore.create_vol.tp'><span>TP</span></span>
|
||||
</div>
|
||||
|
||||
<div class='footer'>
|
||||
<button class='valid' @click='gstore.ic_handler()'>Créer l'UE</button>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section v-if='gstore.ues.length <= 0'>Aucune UE trouvée</section>
|
||||
|
||||
<section v-for='(ue, pi) in gstore.ues'
|
||||
:class="gstore.edit_i==pi ? 'search' : ''"
|
||||
:data-id='ue.code'
|
||||
:data-label='ue.label'>
|
||||
|
||||
|
||||
<!-- if VIEW MODE -->
|
||||
<div class='goo-menu' v-show='gstore.edit_i!=pi'>
|
||||
<div class='enabled' :data-enabled='ue.code' :data-active='ue.disabled?0:1' title='UE activée' @click="gstore.ia_handler(pi)"></div>
|
||||
<div class='remove' :data-remove='ue.code' title='Supprimer' @click="gstore.ir_handler(ue.code)"></div>
|
||||
<div class='edit' :data-edit='ue.code' title='Modifier' @click="gstore.ie_toggle(pi)"></div>
|
||||
</div>
|
||||
|
||||
<!-- if VIEW MODE -->
|
||||
<span v-show='gstore.edit_i!=pi' class='category'>{{ ue.labelForm || 'Aucune formation par défaut' }}</span>
|
||||
<!-- if EDIT MODE -->
|
||||
<select v-show='gstore.edit_i==pi' v-model='gstore.edit_form' class='category'>
|
||||
<option selected='selected' disabled='disabled' value='-'>Formation par défaut</option>
|
||||
<option value='-1'>Aucune formation par défaut</option>
|
||||
<option v-for='form in gstore.formations' :value='form.idForm'>{{ form.labelForm }}</option>
|
||||
</select>
|
||||
<!-- endif -->
|
||||
|
||||
<!-- if VIEW MODE -->
|
||||
<h1 v-show='gstore.edit_i!=pi' :class="ue.required ? 'warning' : ''" :title='ue.required?"UE obligatoire":"UE optionnelle"'>{{ ue.label }}<span :data-visible='1'>({{ ue.code }})</span></h1>
|
||||
<!-- if EDIT MODE -->
|
||||
<h1 v-show='gstore.edit_i==pi' :class="ue.required ? 'warning' : ''">
|
||||
<input type='text' placeholder='Libellé' v-model='gstore.edit_label'>
|
||||
<span :data-visible='1'>({{ ue.code }})</span>
|
||||
<!-- <span data-visible='1'>(<input type='text' placeholder='code' v-model='gstore.edit_code'>)</span> -->
|
||||
</h1>
|
||||
<!-- endif -->
|
||||
|
||||
|
||||
<!-- if VIEW MODE -->
|
||||
<div v-show='gstore.edit_i!=pi' class='sub'><strong>{{ ue.volumeCours + ue.volumeTD + ue.volumeTP }}h</strong> totales</div>
|
||||
<!-- if EDIT MODE -->
|
||||
<div v-show='gstore.edit_i==pi' :class="gstore.edit_err.length > 0 ? 'sub warning' : 'sub'" :data-valid='gstore.edit_err_valid?1:0'>{{ gstore.edit_err }}</div>
|
||||
<!-- endif -->
|
||||
|
||||
<div class='footer'>
|
||||
<!-- if VIEW MODE -->
|
||||
<span v-show='gstore.edit_i!=pi' :class="(ue.volumeCours == 0) ? 'course' : 'course active'">{{ ue.volumeCours }}h <span>Cours</span></span>
|
||||
<hr v-show='gstore.edit_i!=pi'>
|
||||
<span v-show='gstore.edit_i!=pi' :class="(ue.volumeTD == 0) ? 'td' : 'td active'">{{ ue.volumeTD }}h <span>TD</span></span>
|
||||
<hr v-show='gstore.edit_i!=pi'>
|
||||
<span v-show='gstore.edit_i!=pi' :class="(ue.volumeTP == 0) ? 'tp' : 'tp active'">{{ ue.volumeTP }}h <span>TP</span></span>
|
||||
|
||||
<!-- if EDIT MODE -->
|
||||
<span v-show='gstore.edit_i==pi' class='course'><input type='text' placeholder='???' v-model='gstore.edit_vol.c'><span>Cours</span></span>
|
||||
<hr v-show='gstore.edit_i==pi'>
|
||||
<span v-show='gstore.edit_i==pi' class='td'><input type='text' placeholder='???' v-model='gstore.edit_vol.td'><span>TD</span></span>
|
||||
<hr v-show='gstore.edit_i==pi'>
|
||||
<span v-show='gstore.edit_i==pi' class='tp'><input type='text' placeholder='???' v-model='gstore.edit_vol.tp'><span>TP</span></span>
|
||||
|
||||
<!-- endif -->
|
||||
</div>
|
||||
|
||||
|
||||
<!-- if EDIT MODE -->
|
||||
<div class='footer' v-show='gstore.edit_i==pi'>
|
||||
<button v-show='gstore.edit_i==pi' class='search' @click='gstore.ie_handler(pi)'>Modifier l'UE</button>
|
||||
<button v-show='gstore.edit_i==pi' class='grey' @click='gstore.ie_toggle(-1)'>Annuler</button>
|
||||
</div>
|
||||
|
||||
</section>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
|
|
@ -1,16 +1,511 @@
|
|||
/* (1) Load UEs
|
||||
/* (1) Load ues
|
||||
---------------------------------------------------------*/
|
||||
/* (1) Initialize list */
|
||||
gstore.add('ues', []);
|
||||
|
||||
/* (2) Get UEs */
|
||||
api.call('GET ue', { vh: true }, function(rs) {
|
||||
/* (2) Get ues */
|
||||
api.call('GET ue/', { vh: true }, function(rs){
|
||||
|
||||
// {1} If error -> abort //
|
||||
if(rs.error !== 0)
|
||||
return console.log('No UE found, error: ' + rs.error);
|
||||
|
||||
// {2} Store UEs //
|
||||
if( rs.error !== 0 )return console.log('No UE found, error: '+rs.error);
|
||||
console.log(rs);
|
||||
|
||||
// {2} Store ues //
|
||||
gstore.get.ues = rs.ues;
|
||||
|
||||
});
|
||||
|
||||
|
||||
|
||||
/* (2) Load formations
|
||||
---------------------------------------------------------*/
|
||||
/* (1) Initialize list */
|
||||
gstore.add('formations', []);
|
||||
|
||||
/* (2) Get Formations */
|
||||
api.call('GET formation', {}, function(rs){
|
||||
|
||||
// {1} If error -> abort //
|
||||
if( rs.error !== 0 ) return console.log('No formation found, error: '+rs.error);
|
||||
console.log(rs);
|
||||
|
||||
// {2} Format UE filters //
|
||||
for( var i = 0 ; i < rs.formations.length ; i++ )
|
||||
gstore.get.formations.push( rs.formations[i] );
|
||||
|
||||
});
|
||||
|
||||
|
||||
|
||||
/* (2) Manage Instant Search (IS)
|
||||
---------------------------------------------------------*/
|
||||
/* (1) Define global timeout index */
|
||||
gstore.add('is_to', null);
|
||||
|
||||
|
||||
/* (2) Define search value buffer */
|
||||
gstore.add('is_buf', null);
|
||||
|
||||
|
||||
/* (3) Define instant search function */
|
||||
gstore.add('is_handler', function(e){
|
||||
|
||||
/* (1) Remove last timeout */
|
||||
if( gstore.get.is_to != null )
|
||||
clearTimeout(gstore.get.is_to);
|
||||
|
||||
/* (2) Store value in buffer */
|
||||
gstore.get.is_buf = e.target.value.trim().toLowerCase();
|
||||
|
||||
/* (3) Launch timeout (wait 1s) before filtering */
|
||||
gstore.get.is_to = setTimeout(function(){
|
||||
|
||||
// 1. Fetch elements
|
||||
var local_ptr = gstore.get.ues;
|
||||
var l = gstore.get.ues.length;
|
||||
|
||||
// 2. For each element
|
||||
for( var e = 0 ; e < l ; e++ ){
|
||||
|
||||
// 2.1. Show by default
|
||||
var element = document.querySelector('section[data-id=\''+local_ptr[e].code+'\']');
|
||||
if( !element ) continue;
|
||||
|
||||
element.remClass('search-hidden');
|
||||
|
||||
// 2.2. Extract name components
|
||||
var code = local_ptr[e].code.trim().toLowerCase();
|
||||
var label = local_ptr[e].label.trim().toLowerCase();
|
||||
|
||||
// 2.3. Hide if does not match
|
||||
var match_offset = gstore.get.is_buf.length == 0 || code.search(gstore.get.is_buf) + label.search(gstore.get.is_buf);
|
||||
|
||||
if( match_offset <= -2 )
|
||||
element.addClass('search-hidden');
|
||||
|
||||
}
|
||||
|
||||
}, 250);
|
||||
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* (5) Manage instant create
|
||||
---------------------------------------------------------*/
|
||||
/* (1) Initialize toggle show */
|
||||
gstore.add('create_card', false);
|
||||
|
||||
/* (2) Initialize inputs */
|
||||
gstore.add('create_form', '-');
|
||||
gstore.add('create_label', '');
|
||||
gstore.add('create_code', '');
|
||||
gstore.add('create_vol', { c: '', td: '', tp: ''});
|
||||
|
||||
/* (3) Initialize error message */
|
||||
gstore.add('create_err_valid', false);
|
||||
gstore.add('create_err', '');
|
||||
|
||||
/* (4) Define create handler */
|
||||
gstore.add('ic_handler', function(){
|
||||
|
||||
/* (4.1) Trim text input */
|
||||
gstore.get.create_label = gstore.get.create_label.trim();
|
||||
gstore.get.create_code = gstore.get.create_code.trim().toUpperCase();
|
||||
gstore.get.create_form = gstore.get.create_form.toString().trim();
|
||||
gstore.get.create_vol.c = gstore.get.create_vol.c.toString().trim();
|
||||
gstore.get.create_vol.td = gstore.get.create_vol.td.toString().trim();
|
||||
gstore.get.create_vol.tp = gstore.get.create_vol.tp.toString().trim();
|
||||
|
||||
/* (5.4) Store values locally */
|
||||
var form = gstore.get.create_form;
|
||||
var label = gstore.get.create_label;
|
||||
var code = gstore.get.create_code;
|
||||
var vco = gstore.get.create_vol.c;
|
||||
var vtd = gstore.get.create_vol.td;
|
||||
var vtp = gstore.get.create_vol.tp;
|
||||
|
||||
/* (5.5) Init client-side check */
|
||||
var errors = [];
|
||||
|
||||
/* (5.5.1) Check formation */
|
||||
if( isNaN(form) ) errors.push('La formation de l\'UE est manquante');
|
||||
|
||||
/* (5.5.2) Check label */
|
||||
if( typeof label !== 'string' || label.length < 4 )
|
||||
errors.push('Le label doit comprendre faire au moins 4 caractères');
|
||||
|
||||
/* (5.5.3) Check code */
|
||||
if( !/^[A-Z0-9]{4,20}$/.test(code) )
|
||||
errors.push('Le code doit comprendre de 4 à 20 lettres/chiffres');
|
||||
|
||||
/* (5.5.4) Check volumes */
|
||||
if( vco === '' || isNaN(vco) || vco < 0 )
|
||||
errors.push('Le volume horaire de cours doit être un entier positif.');
|
||||
|
||||
/* (5.5.5) Check TD */
|
||||
if( vtd === '' || isNaN(vtd) || vtd < 0 )
|
||||
errors.push('Le volume horaire de TD doit être un entier positif.');
|
||||
|
||||
/* (5.5.6) Check TP */
|
||||
if( vtp === '' || isNaN(vtp) || vtp < 0 )
|
||||
errors.push('Le volume horaire de TP doit être un entier positif.');
|
||||
|
||||
/* (4.4) Show first error only (for 2s) */
|
||||
if( errors.length > 0 ){
|
||||
|
||||
gstore.get.create_err = errors[0];
|
||||
|
||||
return setTimeout(() => gstore.add('create_err', ''), 2000);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* (4.5.1) Création de la requête */
|
||||
var rq = {
|
||||
label: label,
|
||||
code: code,
|
||||
volumeCours: parseInt(vco), /*TODO*/
|
||||
volumeTD: parseInt(vtd), /*TODO*/
|
||||
volumeTP: parseInt(vtp), /*TODO*/
|
||||
required: false, /*TODO*/
|
||||
disabled: false /*TODO*/
|
||||
};
|
||||
|
||||
// optional param
|
||||
if( form != -1 )
|
||||
rq.defaultFormation = form;
|
||||
|
||||
/* (4.5.2) Send request */
|
||||
api.call('POST ue', rq, function(rs){
|
||||
|
||||
console.log(rs);
|
||||
|
||||
/* (4.5.2.1) Manage 'already exist' error */
|
||||
if( rs.error == 29 ){
|
||||
gstore.get.create_err = 'Le code est déja utilisé.';
|
||||
return setTimeout(() => gstore.add('create_err', ''), 2000);
|
||||
}
|
||||
|
||||
/* (4.5.2.2) Manage other errors */
|
||||
if( rs.error !== 0 ){
|
||||
gstore.get.create_err = 'erreur ('+rs.error+') Impossible de créer l\'UE';
|
||||
return setTimeout(() => gstore.add('create_err', ''), 2000);
|
||||
}
|
||||
|
||||
/* (4.5.2.3) Show that user is created */
|
||||
// display all is ok
|
||||
gstore.add('create_err_valid', true);
|
||||
gstore.add('create_err', 'L\'UE a été créé, elle s\'affichera au prochain rechargement');
|
||||
|
||||
// empty fields
|
||||
gstore.get.create_form = '-';
|
||||
gstore.get.create_label = '';
|
||||
gstore.get.create_code = '';
|
||||
// gstore.get.create_h = '';
|
||||
|
||||
return setTimeout(() => {
|
||||
gstore.add('create_err', '');
|
||||
gstore.add('create_err_valid', false);
|
||||
}, 2000);
|
||||
|
||||
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* (6) Manage instant remove
|
||||
---------------------------------------------------------*/
|
||||
/* (1) Define remove handler */
|
||||
gstore.add('ir_handler', function(ue_id){
|
||||
|
||||
/* (1) Abort if wrong ue_id */
|
||||
if( ue_id == null )
|
||||
return;
|
||||
|
||||
/* (2.1) Find index in gstore */
|
||||
var gi = gstore.get.ues.map( (data, i) => { return ( data.code && data.code == ue_id ) ? i : ''; }).join('');
|
||||
|
||||
/* (2.2) Exit if not found */
|
||||
if( isNaN(gi) ) return;
|
||||
var local = gstore.get.ues[gi];
|
||||
|
||||
/* (3) Show popup */
|
||||
(new Promise( (resolve, reject) => {
|
||||
|
||||
popup.ask({
|
||||
title: 'Confirmation de suppression',
|
||||
content: "La suppression de l'UE <b>"+local.label+" ("+local.code+")</b> est irréversible.<br><br>Voulez-vous lea supprimer définitivement ?",
|
||||
action: 'Supprimer',
|
||||
type: 'invalid'
|
||||
}, (popup_rs) => { popup_rs && resolve() });
|
||||
|
||||
/* (4) On pop-up confirmation */
|
||||
})).then(function(){
|
||||
|
||||
|
||||
return new Promise( (resolve, reject) => {
|
||||
|
||||
/* (4.1) Delete UE */
|
||||
api.call('DELETE ue/'+ue_id, {}, function(rs){
|
||||
|
||||
/* (4.1.1) Abort on error */
|
||||
if( rs.error !== 0 || rs.deleted !== true )
|
||||
return reject(rs.error);
|
||||
|
||||
/* (4.1.2) Success */
|
||||
resolve();
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
/* (5) On success */
|
||||
}).then(function(){
|
||||
|
||||
/* remove from visible */
|
||||
gstore.get.ues.splice(gi, 1);
|
||||
|
||||
|
||||
/* (6) On error */
|
||||
}).catch(function(err_code){
|
||||
|
||||
popup.ask({
|
||||
title: 'Error ('+err_code+')',
|
||||
content: 'La suppression a échouée. Veuillez réessayer ultérieurement.',
|
||||
action: 'OK',
|
||||
type: 'neutral'
|
||||
}, () => {});
|
||||
|
||||
});
|
||||
|
||||
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* (7) Manage instant edit
|
||||
---------------------------------------------------------*/
|
||||
/* (1) Init edit_mode */
|
||||
gstore.add('edit_i', -1);
|
||||
|
||||
/* (2) Initialize inputs */
|
||||
gstore.add('edit_form', '-');
|
||||
gstore.add('edit_label', '');
|
||||
// gstore.add('edit_code', '');
|
||||
gstore.add('edit_vol', { c: '', td: '', tp: ''});
|
||||
|
||||
/* (3) Initialize error message */
|
||||
gstore.add('edit_err_valid', false);
|
||||
gstore.add('edit_err', '');
|
||||
|
||||
|
||||
/* (4) Define toggle view */
|
||||
gstore.add('ie_toggle', function(ue_i){
|
||||
|
||||
/* (4.1) Abort if wrong ue_i */
|
||||
if( ue_i == null || isNaN(ue_i) || gstore.get.ues[ue_i] == null)
|
||||
return gstore.add('edit_i', -1);
|
||||
|
||||
/* (4.2) Toggle current value */
|
||||
var ue = gstore.get.ues[ue_i];
|
||||
|
||||
/* (4.3) Pre-fill edit values */
|
||||
gstore.get.edit_form = ue.idForm;
|
||||
gstore.get.edit_label = ue.label;
|
||||
gstore.get.edit_code = ue.code;
|
||||
gstore.get.edit_vol.c = ue.volumeCours;
|
||||
gstore.get.edit_vol.td = ue.volumeTD;
|
||||
gstore.get.edit_vol.tp = ue.volumeTP;
|
||||
|
||||
/* (4.4) Set card to edit mode */
|
||||
gstore.get.edit_i = ue_i;
|
||||
|
||||
});
|
||||
|
||||
/* (5) Confirm update */
|
||||
gstore.add('ie_handler', function(ue_i){
|
||||
|
||||
/* (5.1) Abort if wrong ue_i */
|
||||
if( ue_i == null || isNaN(ue_i) || gstore.get.ues[ue_i] == null)
|
||||
return;
|
||||
|
||||
/* (5.2) Toggle current value */
|
||||
var ue = gstore.get.ues[ue_i];
|
||||
|
||||
/* (5.3) Trim text input */
|
||||
gstore.get.edit_label = gstore.get.edit_label.trim();
|
||||
// gstore.get.edit_code = gstore.get.edit_code.toString().trim().toUpperCase();
|
||||
gstore.get.edit_vol.c = gstore.get.edit_vol.c.toString().trim();
|
||||
gstore.get.edit_vol.td = gstore.get.edit_vol.td.toString().trim();
|
||||
gstore.get.edit_vol.tp = gstore.get.edit_vol.tp.toString().trim();
|
||||
|
||||
/* (5.4) Store values locally */
|
||||
var form = gstore.get.edit_form;
|
||||
var label = gstore.get.edit_label;
|
||||
// var code = gstore.get.edit_code;
|
||||
var vco = gstore.get.edit_vol.c;
|
||||
var vtd = gstore.get.edit_vol.td;
|
||||
var vtp = gstore.get.edit_vol.tp;
|
||||
|
||||
/* (5.5) Init client-side check */
|
||||
var errors = [];
|
||||
|
||||
/* (5.5.1) Check formation */
|
||||
if( isNaN(form) ) errors.push('La formation de l\'UE est manquante');
|
||||
|
||||
/* (5.5.2) Check label */
|
||||
if( typeof label !== 'string' || label.length < 4 )
|
||||
errors.push('Le label doit comprendre faire au moins 4 caractères');
|
||||
|
||||
/* (5.5.3) Check code */
|
||||
// if( !/^[A-Z0-9]{4,20}$/.test(code) )
|
||||
// errors.push('Le code doit comprendre de 4 à 20 lettres/chiffres');
|
||||
|
||||
/* (5.5.4) Check volumes */
|
||||
if( vco === '' || isNaN(vco) || vco < 0 )
|
||||
errors.push('Le volume horaire de cours doit être un entier positif.');
|
||||
|
||||
/* (5.5.5) Check TD */
|
||||
if( vtd === '' || isNaN(vtd) || vtd < 0 )
|
||||
errors.push('Le volume horaire de TD doit être un entier positif.');
|
||||
|
||||
/* (5.5.6) Check TP */
|
||||
if( vtp === '' || isNaN(vtp) || vtp < 0 )
|
||||
errors.push('Le volume horaire de TP doit être un entier positif.');
|
||||
|
||||
/* (5.6) Show first error only (for 2s) */
|
||||
if( errors.length > 0 ){
|
||||
|
||||
gstore.get.edit_err = errors[0];
|
||||
|
||||
return setTimeout(() => gstore.add('edit_err', ''), 2000);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* (5.7) Création de la requête */
|
||||
var rq = {};
|
||||
( label != ue.label ) && ( rq.label = label );
|
||||
// ( code != ue.code ) && ( rq.code = code );
|
||||
( vco != ue.volumeCours ) && ( rq.volumeCours = parseInt(vco) );
|
||||
( vtd != ue.volumeTD ) && ( rq.volumeTD = parseInt(vtd) );
|
||||
( vtp != ue.volumeTP ) && ( rq.volumeTP = parseInt(vtp) );
|
||||
( form != ue.idForm ) && ( rq.defaultFormation = parseInt(form) );
|
||||
|
||||
(new Promise( (resolve, reject) => {
|
||||
|
||||
popup.ask({
|
||||
title: 'Confirmation de modification',
|
||||
content: `La modification de l'UE <b>${ue.label} (${ue.code})</b> est irréversible.<br><br>Voulez-vous la modifier ?`,
|
||||
action: 'Modifier',
|
||||
type: 'search'
|
||||
}, (popup_rs) => { popup_rs && resolve() });
|
||||
|
||||
/* (5.8) On pop-up confirmation */
|
||||
})).then(function(){
|
||||
|
||||
return new Promise( (resolve, reject) => {
|
||||
|
||||
/* (5.8.1) Update UE */
|
||||
api.call(`PUT ue/${ue.code}`, rq, function(rs){
|
||||
|
||||
/* (5.8.1.1) Abort on error */
|
||||
console.log(rq, rs.error != 0, rs.updated != true);
|
||||
if( rs.error != 0 || rs.updated != true )
|
||||
return reject(rs.error);
|
||||
|
||||
/* (5.8.1.2) Success */
|
||||
resolve();
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
/* (5.9) On success */
|
||||
}).then(function(){
|
||||
|
||||
/* (5.9.1) update VueJS element */
|
||||
gstore.get.ues[ue_i].label = label;
|
||||
// gstore.get.ues[ue_i].code = code;
|
||||
gstore.get.ues[ue_i].idForm = parseInt(form);
|
||||
gstore.get.ues[ue_i].volumeCours = parseInt(vco);
|
||||
gstore.get.ues[ue_i].volumeTD = parseInt(vtd);
|
||||
gstore.get.ues[ue_i].volumeTP = parseInt(vtp);
|
||||
|
||||
/* (5.9.2) Try to set the formation label */
|
||||
var fi = gstore.get.formations.map( (data, i) => { return ( data.idForm && data.idForm == form ) ? i : ''; }).join('');
|
||||
|
||||
/* (5.9.3) Exit if not found */
|
||||
if( isNaN(fi) )
|
||||
return gstore.add('edit_i', -1);
|
||||
|
||||
/* (5.9.4) If not found -> set default text */
|
||||
if( !gstore.get.formations.hasOwnProperty(fi) )
|
||||
gstore.get.ues[ue_i].labelForm = '';
|
||||
|
||||
/* (5.9.5) If found -> set formation label */
|
||||
else
|
||||
gstore.get.ues[ue_i].labelForm = gstore.get.formations[fi].labelForm;
|
||||
|
||||
/* (5.9.5) Remove edit mode */
|
||||
gstore.add('edit_i', -1);
|
||||
|
||||
|
||||
/* (5.10) On error */
|
||||
}).catch(function(err_code){
|
||||
|
||||
popup.ask({
|
||||
title: 'Error ('+err_code+')',
|
||||
content: 'La modification a échouée. Veuillez réessayer ultérieurement.',
|
||||
action: 'OK',
|
||||
type: 'neutral'
|
||||
}, () => {});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* (8) Manage instant admin
|
||||
---------------------------------------------------------*/
|
||||
/* (1) Define admin handler */
|
||||
gstore.add('ia_handler', function(ue_i){
|
||||
|
||||
/* (1) Abort if wrong ue_i */
|
||||
if( ue_i == null || isNaN(ue_i) || gstore.get.ues[ue_i] == null)
|
||||
return;
|
||||
|
||||
/* (2) Toggle current value */
|
||||
var local = gstore.get.ues[ue_i];
|
||||
var is_disabled = local.disabled == '1' || local.disabled === true;
|
||||
var new_state = !is_disabled;
|
||||
|
||||
/* (3.1) Update in database */
|
||||
api.call('PUT ue/'+local.code, { disabled: new_state }, function(rs){
|
||||
|
||||
/* (3.1.1) Abort on error */
|
||||
if( rs.error !== 0 || rs.updated !== true )
|
||||
return console.log('Impossible de changer le status \'activée\', erreur '+rs.error);
|
||||
|
||||
/* (3.1.2) Success */
|
||||
gstore.get.ues[ue_i].disabled = new_state ? 1 : 0;
|
||||
|
||||
});
|
||||
|
||||
});
|
|
@ -218,6 +218,7 @@
|
|||
/* (2.1.1) lighter color on hover */
|
||||
& > div.remove[data-remove],
|
||||
& > div.edit[data-edit],
|
||||
& > div.enabled[data-enabled],
|
||||
& > div.admin[data-admin]{
|
||||
background-color: darken(#fff, 12%);
|
||||
|
||||
|
@ -232,6 +233,7 @@
|
|||
/* (2.2) Design elements */
|
||||
& > div.remove[data-remove],
|
||||
& > div.edit[data-edit],
|
||||
& > div.enabled[data-enabled],
|
||||
& > div.admin[data-admin]{
|
||||
display: inline-block;
|
||||
position: absolute;
|
||||
|
@ -275,6 +277,15 @@
|
|||
&[data-active='1']:hover{ background-image: url('/asset/svg/admin.svg@f4a118'); }
|
||||
}
|
||||
|
||||
/* (2.3) DISABLED switch */
|
||||
&.enabled[data-enabled]{
|
||||
background-image: url('/asset/svg/bell.svg@aaaaaa');
|
||||
z-index: 105;
|
||||
|
||||
&:hover{ background-image: url('/asset/svg/bell.svg@555555'); }
|
||||
&[data-active='1']{ background-image: url('/asset/svg/bell.svg@f4bd18'); }
|
||||
&[data-active='1']:hover{ background-image: url('/asset/svg/bell.svg@f4a118'); }
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -351,7 +362,7 @@
|
|||
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
width: 1em;
|
||||
width: 1.2em;
|
||||
height: 1em;
|
||||
|
||||
margin-right: .3em;
|
||||
|
@ -574,6 +585,17 @@
|
|||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
/* (7.1-edit) Card footer input */
|
||||
& > input{
|
||||
width: 2.5em;
|
||||
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
|
||||
border: 0;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/* (7.1-edit) Card button submit */
|
||||
|
|
|
@ -72,7 +72,7 @@ body{
|
|||
}
|
||||
}
|
||||
|
||||
$easter-egg-timeout: 5;
|
||||
$easter-egg-timeout: 10;
|
||||
|
||||
div.icon{
|
||||
display: block;
|
||||
|
|
Loading…
Reference in New Issue