Reprise projet été 2016

This commit is contained in:
xdrm-brackets 2016-07-02 17:10:41 +02:00
parent 8b26204bd2
commit 23dc72a64c
27 changed files with 1279 additions and 275 deletions

View File

@ -3,4 +3,4 @@
"dbname" : "stefproject", "dbname" : "stefproject",
"user" : "php", "user" : "php",
"password" : "QbzjZACndQM6NmuD" "password" : "QbzjZACndQM6NmuD"
} }

View File

@ -1,10 +1,13 @@
<?php define('__ROOT__', dirname(__FILE__) ); <?php define('__ROOT__', dirname(__FILE__) );
require_once __ROOT__.'/manager/autoloader.php'; require_once __ROOT__.'/manager/autoloader.php';
use \router\Router; use \router\Router;
use \manager\ResourceDispatcher; use \manager\ResourceDispatcher;
use \manager\ModuleRequest; use \manager\ModuleRequest;
use \manager\ModuleResponse;
use \manager\ManagerError;
/*******************************************/ /*******************************************/
/* DEBUGGER */ /* DEBUGGER */
@ -41,27 +44,24 @@
$R->get('f(?:/([\w-]+))*/?', function(){ new ResourceDispatcher($_GET['url'], true); }); $R->get('f(?:/([\w-]+))*/?', function(){ new ResourceDispatcher($_GET['url'], true); });
// Api // Api
$R->post('api/?', function(){ $R->post('api(?:/(.*))?', function($url){
$request = ModuleRequest::fromPost($_POST); $request = ModuleRequest::fromPost($url, $_POST);
$answer = $request->dispatch(); $answer = $request->dispatch();
echo $answer->serialize(); // Si c'est une réponse (et non un download)
if( $answer instanceof ModuleResponse )
echo $answer->serialize();
}); });
// N'importe -> page d'accueil // N'importe -> page d'accueil
$R->get('.+', function(){ header('Location: /dashboard/'); }); $R->get('.+', function(){ header('Location: /dashboard/'); });
$R->post('.+', function(){ header('Location: /dashboard/'); });
// $R->post('.*', function(){
// var_dump( 'Acces POST : '.$_GET['url'] );
// var_dump( $_POST );
// });
/* [2] On lance le routeur /* [2] On lance le routeur
===================================================*/ ===================================================*/
$R->run(); $R->run();
?> ?>

6
js/action-script-min.js vendored Normal file
View File

@ -0,0 +1,6 @@
DOM={WRAPPER:$("WRAPPER"),HEADER:$("HEADER"),MENUSIDE:$("MENU-SIDE"),CONTAINER:$("CONTAINER")};var pageManager=new pageManagerClass;pageManager.setPage(null,"/view",DOM.CONTAINER,"profile dashboard machines users groups analytics settings".split(" "));var api=new APIClass("/api/");
function navSubMenu(a){var c=document.querySelector('#CONTAINER > .sub-menu-side > span[data-sublink="'+pageManager.vars[0]+'"]'),b=null,b=a instanceof Element?a:null,b="string"==typeof a?document.querySelector('#CONTAINER > .sub-menu-side > span[data-sublink="'+a+'"]'):b,b=null==b?document.querySelector("#CONTAINER > .sub-menu-side > span[data-sublink]"):b;if(null==b)return!1;null!=c&&c.remClass("active");a=document.querySelectorAll("#CONTAINER > section[data-sublink].active");for(c=0;c<a.length;c++)a[c].remClass("active");
null!=b&&(b.addClass("active"),a=document.querySelector('#CONTAINER > section[data-sublink="'+b.getData("sublink")+'"]'),null!=a&&a.addClass("active"));if(!b.getData("sublink"))return!1;a=pageManager.vars[0]!=b.getData("sublink");pageManager.vars[0]=b.getData("sublink");a&&pageManager.updateURL()}
function navMenu(a){var c=document.querySelector('#WRAPPER > #MENU-SIDE > span[data-link="'+pageManager.page+'"]'),b=null,b=a instanceof Element?a:null,b="string"==typeof a?document.querySelector('#WRAPPER > #MENU-SIDE > span[data-link="'+a+'"]'):b,b=null==b?document.querySelector('#WRAPPER > #MENU-SIDE > span[data-link="'+pageManager.pagelist[0]+'"]'):b;if(null==b)return!1;null!=c&&c.remClass("active");null!=b&&b.addClass("active");b.getData("link")&&(DOM.HEADER.addClass("loading"),pageManager.setPage(b.getData("link")),
pageManager.activeXHR.addEventListener("loadend",function(){DOM.HEADER.remClass("loading");1<=pageManager.vars.length&&null!=document.querySelector('#CONTAINER > .sub-menu-side > [data-sublink="'+pageManager.vars[0]+'"]')?navSubMenu(pageManager.vars[0]):navSubMenu(null);document.querySelector("#CONTAINER > .sub-menu-side").addEventListener("click",function(a){for(a=a.target;a!=document.body&&!a.getData("sublink");)a=a.parentNode;a.getData("sublink")&&navSubMenu(a)},!1)},!1))}navMenu(pageManager.page);
DOM.MENUSIDE.addEventListener("click",function(a){for(a=a.target;a!=document.body&&!a.getData("link");)a=a.parentNode;a.getData("link")&&navMenu(a.getData("link"))},!1);

View File

@ -26,7 +26,7 @@ function navSubMenu(subsection){
var target = null; var target = null;
// si @subsection est un element, on le prends // si @subsection est un element, on le prends
target = (subsection instanceof Element) ? subsection : null; target = (subsection instanceof Element) ? subsection : null;
// Si string, on trouve l'element correspondant // Si string, on trouve l'element correspondant
target = (typeof subsection == 'string') ? document.querySelector('#CONTAINER > .sub-menu-side > span[data-sublink="'+subsection+'"]') : target; target = (typeof subsection == 'string') ? document.querySelector('#CONTAINER > .sub-menu-side > span[data-sublink="'+subsection+'"]') : target;
@ -42,7 +42,7 @@ function navSubMenu(subsection){
// On desactive l'element courant // On desactive l'element courant
if( current != null ) if( current != null )
current.remClass('active'); current.remClass('active');
// On cache les sections visibles // On cache les sections visibles
var visibleSections = document.querySelectorAll('#CONTAINER > section[data-sublink].active'); var visibleSections = document.querySelectorAll('#CONTAINER > section[data-sublink].active');
for( var i = 0 ; i < visibleSections.length ; i++ ) for( var i = 0 ; i < visibleSections.length ; i++ )
@ -86,7 +86,7 @@ function navSubMenu(subsection){
/* [2] Toggle du side-menu <-> navigation /* [2] Toggle du side-menu <-> navigation
===========================================*/ ===========================================*/
function navMenu(section){ function navMenu(section){
/* [1] Format du param /* [1] Format du param
------------------------------------------------*/ ------------------------------------------------*/
// Contient l'element courant // Contient l'element courant
@ -96,7 +96,7 @@ function navMenu(section){
var target = null; var target = null;
// si @section est un element, on le prends // si @section est un element, on le prends
target = (section instanceof Element) ? section : null; target = (section instanceof Element) ? section : null;
// Si string, on trouve l'element correspondant // Si string, on trouve l'element correspondant
target = (typeof section == 'string') ? document.querySelector('#WRAPPER > #MENU-SIDE > span[data-link="'+section+'"]') : target; target = (typeof section == 'string') ? document.querySelector('#WRAPPER > #MENU-SIDE > span[data-link="'+section+'"]') : target;
@ -188,6 +188,3 @@ DOM.MENUSIDE.addEventListener('click', function(e){
if( target.getData('link') ) if( target.getData('link') )
navMenu(target.getData('link')); navMenu(target.getData('link'));
}, false); }, false);

4
js/lib/api-min.js vendored Normal file
View File

@ -0,0 +1,4 @@
function APIClass(c){this.target=c}
APIClass.prototype={xhr:[],buffer:null,optionalParams:[],send:function(c,f,g){c.hasOwnProperty("path")||f({ModuleError:4});for(var a=0;a<this.xhr.length;a++)4==this.xhr[a].readyState&&this.xhr.splice(a,1);this.xhr.push(null);a=this.xhr.length-1;this.optionalParams[a]=[];if(3<arguments.length)for(var d=3;d<arguments.length;d++)this.optionalParams[a].push(arguments[d]);this.xhr[a]=window.XMLHttpRequest?new XMLHttpRequest:new ActiveXObject("Microsoft.XMLHttpRequest");var e=this;this.xhr[a].onreadystatechange=
function(){if(4==e.xhr[a].readyState)if(e.buffer=e.xhr[a].responseText,console.log("api request",c),-1<[0,200].indexOf(e.xhr[a].status))try{f(JSON.parse(e.xhr[a].responseText),e.optionalParams[a])}catch(b){f({ModuleError:-1,ErrorDescription:"Erreur au niveau de api.js"},e.optionalParams[a]),console.warn(b)}else f({ModuleError:3})};var d=new FormData,b;for(b in c)"path"==b?d.append(b,c[b]):c[b]instanceof File?d.append(b,c[b]):d.append(b,JSON.stringify(c[b]));this.xhr[a].open("POST",this.target,!0);
null!=g&&this.xhr[a].setRequestHeader("Authorization","Digest "+g);this.xhr[a].setRequestHeader("X-Requested-With","XMLHttpRequest");this.xhr[a].send(d)}};

View File

@ -1,83 +1,111 @@
/* classe API */ /* classe API */
function APIClass(target){ this.target = target; }; function APIClass(target){ this.target = target; }
APIClass.prototype = { APIClass.prototype = {
xhr: [], // tableau d'objets pour les requêtes ajax xhr: [], // tableau d'objets pour les requêtes ajax
buffer: null, // Contiendra le buffer pour debugger si erreur de parsage
optionalParams: [], // Contiendra les paramètres que l'on veut passer au scope de @pHandler
/* transaction avec le serveur (http://host/api/) /* transaction avec le serveur (http://host/api/)
* *
* @param pRequest<Object> l'objet passé en JSON à http://host/api/ * @param pRequest<Object> l'objet passé en POST (attribut->postfield) à http://host/api/
* @param pHandler<Function> fonction qui s'éxécutera lors de la réponse (1 argument -> réponse<Object>) * @param pHandler<Function> fonction qui s'éxécutera lors de la réponse (1 argument -> réponse<Object>)
* @param pToken<String> Optionnel, token d'auth pour l'api
* @param pParams<Mixed> Optionnels, liste d'arguments à passer au scope de @pHandler
* *
* @return answer<Object> l'objet retourné par http://host/api/ via pHandler (1er argument) * @return answer<Object> l'objet retourné par http://host/api/ via pHandler (1er argument)
* *
*************************************************************************************************** ***************************************************************************************************
* *
* @usecase * @usecase
* 1. var answerObject = sendRequest( * 1. var answerObject = sendRequest(
* 2. { var1: "exemple", var2: 198294 }, * 2. { var1: "exemple", var2: 198294 },
* 3. function(rep){ alert(rep); } * 3. function(rep){ alert(rep); }
* 4. ); * 4. );
* @explain * @explain
* 1. on appelle la fonction <=> on créé la requête * 1. on appelle la fonction <=> on créé la requête
* 2. on passe l'objet qui sera envoyé * 2. on passe l'objet qui sera envoyé
* 3. on passe une fonction qui utilise un argument (sera la réponse de http://host/api/) (sous forme d'objet) * 3. on passe une fonction qui utilise un argument (sera la réponse de http://host/api/) (sous forme d'objet)
* *
*/ */
send: function(pRequest, pHandler){ send: function(pRequest, pHandler, pToken){
// Si le chemin de delegation n'est pas renseigne, on renvoie une erreur // Si le chemin de delegation n'est pas renseigne, on renvoie une erreur
if( !pRequest.hasOwnProperty('path') ) if( !pRequest.hasOwnProperty('path') )
pHandler({ModuleError:4}); pHandler({ModuleError:4});
// on efface les requêtes qui sont terminées (toutes celles de this.xhr) // on efface les requêtes qui sont terminées (toutes celles de this.xhr)
for( var i = 0 ; i < this.xhr.length ; i++ ){ for( var i = 0 ; i < this.xhr.length ; i++ )
if( this.xhr[i].readyState == 4 ) // si terminée if( this.xhr[i].readyState == 4 ) // si terminée
this.xhr = this.xhr.slice(0,i-1).concat(this.xhr.slice(i,this.xhr.length-1)); // suppression entrée this.xhr.splice(i, 1);
}
// on créé une nouvelle entrée // on créé une nouvelle entrée
this.xhr.push(null); this.xhr.push(null);
i = this.xhr.length-1; i = this.xhr.length-1;
// Gestion des paramètres optionnels à passer au scope de @pHandler
this.optionalParams[i] = [];
if( arguments.length > 3 )
for( var arg = 3 ; arg < arguments.length ; arg++ )
this.optionalParams[i].push( arguments[arg] );
// création de l'objet AJAX // création de l'objet AJAX
if(window.XMLHttpRequest) // IE7+, Firefox, Chrome, Opera, Safari if(window.XMLHttpRequest) // IE7+, Firefox, Chrome, Opera, Safari
this.xhr[i] = new XMLHttpRequest(); this.xhr[i] = new XMLHttpRequest();
else // IE5, IE6 else // IE5, IE6
this.xhr[i] = new ActiveXObject('Microsoft.XMLHttpRequest'); this.xhr[i] = new ActiveXObject('Microsoft.XMLHttpRequest');
console.log(pRequest);
var ptrAPI = this; var ptrAPI = this;
this.xhr[i].onreadystatechange = function(){ this.xhr[i].onreadystatechange = function(){
if( ptrAPI.xhr[i].readyState == 4 ){ // si la requête est terminée if( ptrAPI.xhr[i].readyState == 4 ){ // si la requête est terminée
ptrAPI.buffer = ptrAPI.xhr[i].responseText;
/* DEBUG : affiche la réponse BRUTE de http://host/api/ */ /* DEBUG : affiche la réponse BRUTE de http://host/api/ */
// console.log('http://host/api/ => '+ptrAPI.xhr[i].responseText); // console.log('http://host/api/ => '+ptrAPI.xhr[i].responseText);
// console.log( JSON.parse(ptrAPI.xhr[i].responseText) ); // console.log( JSON.parse(ptrAPI.xhr[i].responseText) );
console.log('api request', pRequest);
/* si success de requête */ /* si success de requête */
if( [0,200].indexOf(ptrAPI.xhr[i].status) > -1 ){ // si fichier existe et reçu if( [0,200].indexOf(ptrAPI.xhr[i].status) > -1 ){ // si fichier existe et reçu
try{ pHandler( JSON.parse(ptrAPI.xhr[i].responseText) ); } // si on peut parser, on envoie try{ pHandler( JSON.parse(ptrAPI.xhr[i].responseText), ptrAPI.optionalParams[i]); } // si on peut parser, on envoie
catch(e){ pHandler({ModuleError:1}); } // sinon on envoie obj.request = 'corrupted' catch(e){ pHandler({ModuleError:-1, ErrorDescription:'Erreur au niveau de api.js'}, ptrAPI.optionalParams[i]); console.warn(e); } // sinon on envoie obj.request = 'corrupted'
} }
/* sinon retourne obj.request = 'unreachable' */ /* sinon retourne obj.request = 'unreachable' */
else else
pHandler({ModuleError:3}); pHandler({ModuleError:3});
} }
} };
// on créé un formulaire POST (virtuel) // on créé un formulaire POST (virtuel)
var form = new FormData(); var form = new FormData();
form.append('path', pRequest.path ); // on créé la variable $_POST['json']=>request
if( pRequest.hasOwnProperty('data') ) // On ajoute tous les attributs en POST
form.append('data', JSON.stringify(pRequest.data) ); for( var key in pRequest )
// On envoie le 'path' tel quel <String>
if( key == 'path' ) form.append(key, pRequest[key]);
// On envoie un fichier tel quel <File>
else if( pRequest[key] instanceof File ) form.append(key, pRequest[key]);
// On envoie le reste en JSON
else form.append(key, JSON.stringify(pRequest[key]));
this.xhr[i].open('POST', this.target, true); this.xhr[i].open('POST', this.target, true);
// Gestion du token optionnel
if( pToken != null ) this.xhr[i].setRequestHeader('Authorization', 'Digest '+pToken);
// Header pour dire que c'est AJAX
this.xhr[i].setRequestHeader('X-Requested-With', 'XMLHttpRequest');
this.xhr[i].send( form ); this.xhr[i].send( form );
} }

5
js/lib/form-deflater-min.js vendored Normal file
View File

@ -0,0 +1,5 @@
function FormDeflater(b,c,a){for(var d=0;d<c.length;d++)c[d]=c[d].toLowerCase();for(d=0;d<a.length;d++)a[d]=a[d].toLowerCase();this.container=b;this.tags=c;this.attr=a}FormDeflater.prototype={container:this.container,tags:this.tags,attr:this.attr};
FormDeflater.prototype.deflate=function(){for(var b=this.getChildren(this.container),b=this.filterElements(b),c={},a=0;a<b.length;a++)for(var d=0;d<this.attr.length;d++){var e=b[a].getAttribute(this.attr[d]);if(null!==e&&0<e.length){c.hasOwnProperty(e)?c[e]instanceof Array?c[e].push({target:b[a],attr:this.attr[d],value:b[a].value,checked:b[a].checked}):c[e]=[c[e],{target:b[a],attr:this.attr[d],value:b[a].value,checked:b[a].checked}]:c[e]={target:b[a],attr:this.attr[d],value:b[a].value,checked:b[a].checked};
break}}return c=this.cleanOutput(c)};FormDeflater.prototype.checkable=function(b){return"INPUT"!=b.tagName||-1==["radio","checkbox"].indexOf(b.getAttribute("type").toLowerCase())?!1:!0};
FormDeflater.prototype.cleanOutput=function(b){var c={},a;for(a in b)if(b[a]instanceof Array){var d=!0,e=[],f;for(f in b[a])if(this.checkable(b[a][f].target))!0===b[a][f].checked&&e.push(f);else{d=!1;break}if(d)if(1==e.length)c[a]=b[a][e[0]].value;else for(f in c[a]=[],e)c[a].push(b[a][e[f]].value);else for(f in c[a]=[],b[a])c[a].push(b[a][f].value)}else this.checkable(b[a].target)?c[a]=b[a].checked?b[a].value:null:c[a]=b[a].value;return c};
FormDeflater.prototype.getChildren=function(b){if(!(b instanceof Element))return[];for(var c=b=[].slice.call(b.children),a=0;a<b.length;a++)c=c.concat([].slice.call(this.getChildren(b[a])));return c};FormDeflater.prototype.filterElements=function(b){for(var c=[],a=0;a<b.length;a++)-1<this.tags.indexOf(b[a].tagName.toLowerCase())&&c.push(b[a]);return c};

285
js/lib/form-deflater.js Normal file
View File

@ -0,0 +1,285 @@
/* CONSTRUCTEUR D'UN DEFLATER DE formulaire
*
* @container<Element> Formulaire ou autre élément contenant les champs
* @tags<Array> Tableau contenant les éléments à prendre en compte
* @attr<Array> Tableau contenant les attributs à prendre pour le nom (par ordre de priorité)
*
*/
function FormDeflater(container, tags, attr){
/* [0] Vérification des INPUT
=========================================================*/
var correctParams = container instanceof Element;
correctParams = correctParams && tags instanceof Array;
correctParams = correctParams && attr instanceof Array;
/* [1] On formatte les données
=========================================================*/
// On met les tags en minuscule
for( var i = 0 ; i < tags.length ; i++ )
tags[i] = tags[i].toLowerCase();
// On met les attributs en minuscule
for( var i = 0 ; i < attr.length ; i++ )
attr[i] = attr[i].toLowerCase();
/* [2] On enregistre les attributs
=========================================================*/
this.container = container;
this.tags = tags;
this.attr = attr;
}
FormDeflater.prototype = {
container: this.container, // Contiendra le 'formulaire' (<form> ou autre)
tags: this.tags, // Contiendra les balises HTML à ne pas prendre en compte
attr: this.attr // Contiendra la liste des attributs à prendre pour nom (par ordre de priorité)
};
/* RETOURNE UN OBJET CONTENANT LES DONNÉES DU FORMULAIRE
*
* @return form<Object> Objet correspondant aux données du formulaire
*
*/
FormDeflater.prototype.deflate = function(){
/* [1] On récupère tous les enfants
=========================================================*/
var children = this.getChildren( this.container );
/* [2] On filtre les éléments qui ont pas le bon tag
=========================================================*/
children = this.filterElements( children );
/* [3] On essaie de trouver les attributs primants (non vides et en premier dans la liste @this.attr)
=========================================================*/
/* (0) On initialise l'objet de retour */
var object = {};
/* (1) Pour chacun des éléments */
for( var c = 0 ; c < children.length ; c++ ){
/* (2) Pour chacun des attributs par ordre de priorité */
for( var a = 0 ; a < this.attr.length ; a++ ){
// On récupère l'attribut
var attr = children[c].getAttribute(this.attr[a]);
/* (3) Si l'attribut est défini (pas null ni vide) */
if( attr !== null && attr.length > 0 ){
/* (4) Si on a pas déja un champ de même nom */
if( object.hasOwnProperty(attr) ){
var existing = object[attr];
// {1} Si l'existant est un tableau, on ajoute notre valeur //
if( existing instanceof Array )
object[attr].push( { target: children[c], attr: this.attr[a], value: children[c].value, checked: children[c].checked } );
// {2} Sinon, si c'est une valeur seule, on crée un tableau //
else
object[attr] = [ object[attr], { target: children[c], attr: this.attr[a], value: children[c].value, checked: children[c].checked } ];
/* (5) Si c'est le premier champ avec ce nom, on le crée */
}else
object[attr] = { target: children[c], attr: this.attr[a], value: children[c].value, checked: children[c].checked };
// On en a fini pour cet élément
break;
}
}
}
/* [4] On met en forme les données
=========================================================*/
object = this.cleanOutput(object);
return object;
};
/* RETOURNE SI UN ELEMENT EST UN BOUTON DE TYPE RADIO/CHECKBOX OU NON
*
* @element<Element> Element en question
*
* @return result<Boolean> Renvoie si TRUE or FALSE il en est un
*
*/
FormDeflater.prototype.checkable = function(element){
if( element.tagName != 'INPUT' )
return false;
if( ['radio', 'checkbox'].indexOf( element.getAttribute('type').toLowerCase() ) == -1 )
return false;
return true;
};
/* NETTOIE LES DONNÉES EN SORTIE POUR QU'ELLES SOIENT UTILISABLES ET OPTIMISÉES
*
* @input<Object> Données "brutes"
*
* @return output<Object> Données sans les valeurs inutiles et explicitées
*
*/
FormDeflater.prototype.cleanOutput = function(input){
var output = {};
/* [1] On parcourt toutes les valeurs récupérées
=========================================================*/
for( var key in input ){
/* [2] Si c'est un tableau
=========================================================*/
if( input[key] instanceof Array ){
// VRAI si tous les éléments sont radio/checkbox
var areCheckable = true;
// Contiendra les indices des valeurs ou 'checked=TRUE'
var checkedIndexes = [];
/* (1) On vérifie si tous les champs sont checkables */
for( var i in input[key])
// si pas checkable, on arrête de vérifier
if( !this.checkable(input[key][i].target) ){
areCheckable = false;
break;
// Sinon si checkable et checked=TRUE, on incrémente @nbChecked
}else if( input[key][i].checked === true )
checkedIndexes.push(i);
/* (2) Si c'est que des radio ou des checkbox avec une seule valeur à TRUE */
if( areCheckable )
if( checkedIndexes.length == 1 )
output[key] = input[key][checkedIndexes[0]].value;
/* (3) Si c'est que des radio ou des checkbox avec plusieurs valeurs à TRUE */
else{
output[key] = [];
for( var i in checkedIndexes )
output[key].push( input[key][checkedIndexes[i]].value );
}
/* (4) Si c'est pas que des radio ou des checkbox, on met les valeurs */
else{
output[key] = [];
for( var i in input[key] )
output[key].push( input[key][i].value );
}
/* [3] S'il n'y a qu'une donnée (pas un tableau)
=========================================================*/
}else{
/* (1) Si de type 'radio' ou 'checkbox', on met la valeur de 'checked' */
if( this.checkable(input[key].target) )
output[key] = input[key].checked ? input[key].value : null;
/* (2) Sinon, on met la valeur de 'value' */
else
output[key] = input[key].value;
}
}
return output;
};
/* RETOURNE LA LISTE DE TOUS LES ÉLÉMENTS QUEL QUE SOIT LE NIVEAU HIÉRARCHIQUE
*
* @parent<Element> Parent duquel on veut les enfants
*
* @return children<Array> Tableau contenant tous les enfants
*
*/
FormDeflater.prototype.getChildren = function(parent){
// Si le parent n'est pas un élément, on retourne aucun enfant
if( !(parent instanceof Element) ) return [];
/* [1] Initialisation des variables
=========================================================*/
// Contient la liste des enfants directs
var children = [].slice.call(parent.children);
// Contiendra la liste des enfants directs et indirects
var allChildren = children;
/* [2] On parcourt tous les enfants
=========================================================*/
for( var i = 0 ; i < children.length ; i++ ){
// On relance la fonction récursivement sur tous les enfants
allChildren = allChildren.concat( [].slice.call(this.getChildren(children[i])) );
}
/* [3] On retourne le résultat
=========================================================*/
return allChildren;
};
/* FILTRE LES éléments en fonction de @this.tags et @this.attr
*
* @elements<Array> Le tableau contenant les éléments à trier
*
* @return filtered<Array> Retourne le tableau des éléments filtrés
*
*/
FormDeflater.prototype.filterElements = function(elements){
// Contiendra les éléments correspondants aux critères
var filtered = [];
/* [1] On parcourt tous les éléments
=========================================================*/
for( var i = 0 ; i < elements.length ; i++ )
// Si l'élément a le bon tag, on le garde
if( this.tags.indexOf( elements[i].tagName.toLowerCase() ) > -1 )
filtered.push(elements[i]);
/* [2] On retourne les éléments filtržés
=========================================================*/
return filtered;
};
/************/
/* USE CASE */
/************/
/* (1) Instanciation */
/*HIDDEN*/// var instance = new FormDeflater(
/*HIDDEN*/// document.getElementById('myform'),
/*HIDDEN*/// ['input', 'select'], // éléments à prendre en compte (tagName)
/*HIDDEN*/// ['id', 'name', 'data-elementname'] // Attributs par ordre de priorité
/*HIDDEN*/// );
/*HIDDEN*///
/* (2) On récupère l'objet */
/*HIDDEN*///
/*HIDDEN*/// var object = instance.deflate();
/*HIDDEN*///

7
js/lib/input-checker-min.js vendored Normal file
View File

@ -0,0 +1,7 @@
function formatChecker(a,c,b){this.value=a;this.pattern=c;this.rules=2<arguments.length?b:[]}
formatChecker.prototype={value:this.value,pattern:this.pattern,rules:this.rules,regexp:null,default_rules:{i:"[0-9]",a:"[a-z]",A:"[A-Z]",x:"[a-zA-Z]"},compile:function(){for(var a="^",c=[],b=0;b<this.pattern.length;b++)this.rules.hasOwnProperty(this.pattern[b])?(a+=this.rules[this.pattern[b]],c.push(this.rules[this.pattern[b]])):this.default_rules.hasOwnProperty(this.pattern[b])?(a+=this.default_rules[this.pattern[b]],c.push(this.default_rules[this.pattern[b]])):(a+=this.pattern[b],c.push(this.pattern[b]));
this.regexp=new RegExp(a+"$");this.regexp.patternDecomposition=c},check:function(a){null==this.regexp&&this.compile();if(0<arguments.length&&a instanceof Array)for(var c=0;c<this.pattern.length;c++){var b="^",b=this.rules.hasOwnProperty(this.pattern[c])?b+this.rules[this.pattern[c]]:this.default_rules.hasOwnProperty(this.pattern[c])?b+this.default_rules[this.pattern[c]]:b+this.pattern[c],b=b+"$";a.push(null!=this.value[c].match(new RegExp(b)))}return null!=this.value.match(this.regexp)}};
function inputChecker(){}
inputChecker.prototype={input:[],defval:[],checker:[],append:function(a,c,b){if(!(a instanceof HTMLInputElement&&c instanceof formatChecker))return!1;var d=this.input.push(a);if(d!=this.checker.push(c)||d!=this.defval.push(2<arguments.length?b:null))return!1},check:function(a){a=this.input.indexOf(a);if(0>a)return!1;this.checker[a].value=this.input[a].value;return this.checker[a].check()},checkAll:function(){for(var a=!0,c=0;c<this.input.length;c++)a=a&&this.check(this.input[c]);return a},correct:function(a,
c){if(0>(index=this.input.indexOf(a)))return null;c=1<arguments.length?c:!0;this.checker[index].value=this.input[index].value;this.checker[index].compile();var b=this.checker[index].regexp.patternDecomposition,d=this.input[index].value;if(!this.check(a)){for(var e=0;e<b.length&&(c||!(e>=this.input[index].value.length));e++){var f=new RegExp("^"+b[e]+"$");0==d.length||null==d[e]?d=d.slice(0,e).concat(this.defval[index][e]).concat(d.slice(e)):null==d[e].match(f)&&(d=null!=d[e].match(new RegExp("^"+
b[e+1]+"$"))?d.slice(0,e).concat(this.defval[index][e]).concat(d.slice(e)):d.slice(0,e).concat(this.defval[index][e]).concat(d.slice(e+1)))}d=d.slice(0,b.length);this.input[index].value=d}}};

View File

@ -1,8 +1,8 @@
// __ _ _ _ // __ _ _ _
// / _| ___ _ __ _ __ ___ __ _| |_ ___| |__ ___ ___| | _____ _ __ // / _| ___ _ __ _ __ ___ __ _| |_ ___| |__ ___ ___| | _____ _ __
// | |_ / _ \| '__| '_ ` _ \ / _` | __|____ / __| '_ \ / _ \/ __| |/ / _ \ '__| // | |_ / _ \| '__| '_ ` _ \ / _` | __|____ / __| '_ \ / _ \/ __| |/ / _ \ '__|
// | _| (_) | | | | | | | | (_| | ||_____| (__| | | | __/ (__| < __/ | // | _| (_) | | | | | | | | (_| | ||_____| (__| | | | __/ (__| < __/ |
// |_| \___/|_| |_| |_| |_|\__,_|\__| \___|_| |_|\___|\___|_|\_\___|_| // |_| \___/|_| |_| |_| |_|\__,_|\__| \___|_| |_|\___|\___|_|\_\___|_|
// //
function formatChecker(pValue, pPattern, pRules){ function formatChecker(pValue, pPattern, pRules){
this.value = pValue; this.value = pValue;
@ -64,7 +64,7 @@ formatChecker.prototype = {
/* [1] On génère la RegExp si ce n'est pas déjà fait /* [1] On génère la RegExp si ce n'est pas déjà fait
====================================================*/ ====================================================*/
if( this.regexp == null ) this.compile(); if( this.regexp == null ) this.compile();
/* [2] Gestion de la plaque à trous /* [2] Gestion de la plaque à trous
====================================================*/ ====================================================*/
@ -96,7 +96,7 @@ formatChecker.prototype = {
} }
} }
// on retourne TRUE si c'est bon, FALSE sinon // on retourne TRUE si c'est bon, FALSE sinon
return this.value.match( this.regexp ) != null; return this.value.match( this.regexp ) != null;
@ -131,11 +131,11 @@ formatChecker.prototype = {
// _ _ _ _ // _ _ _ _
// (_)_ __ _ __ _ _| |_ ___| |__ ___ ___| | _____ _ __ // (_)_ __ _ __ _ _| |_ ___| |__ ___ ___| | _____ _ __
// | | '_ \| '_ \| | | | __|____ / __| '_ \ / _ \/ __| |/ / _ \ '__| // | | '_ \| '_ \| | | | __|____ / __| '_ \ / _ \/ __| |/ / _ \ '__|
// | | | | | |_) | |_| | ||_____| (__| | | | __/ (__| < __/ | // | | | | | |_) | |_| | ||_____| (__| | | | __/ (__| < __/ |
// |_|_| |_| .__/ \__,_|\__| \___|_| |_|\___|\___|_|\_\___|_| // |_|_| |_| .__/ \__,_|\__| \___|_| |_|\___|\___|_|\_\___|_|
// //
function inputChecker(){}; function inputChecker(){};
@ -220,7 +220,7 @@ inputChecker.prototype = {
* @pInputElement<HTMLInputElement> l'élément <input> concerné * @pInputElement<HTMLInputElement> l'élément <input> concerné
* @pToEnd<Boolean> si on doit corriger jusqu'à la fin ou uniquement jusqu'à l'avancéé actuelle * @pToEnd<Boolean> si on doit corriger jusqu'à la fin ou uniquement jusqu'à l'avancéé actuelle
* *
* *
* @return correctValue<String> retourne la valeur corrigée * @return correctValue<String> retourne la valeur corrigée
* retourne NULL si erreur * retourne NULL si erreur
*/ */
@ -265,12 +265,12 @@ inputChecker.prototype = {
-----------------------------------------------------------*/ -----------------------------------------------------------*/
if( tmpValue.length == 0 || tmpValue[i] == null ) if( tmpValue.length == 0 || tmpValue[i] == null )
tmpValue = tmpValue.slice(0, i).concat( this.defval[index][i] ).concat( tmpValue.slice(i) ); tmpValue = tmpValue.slice(0, i).concat( this.defval[index][i] ).concat( tmpValue.slice(i) );
/* (2) Valeur ne correspond pas au schéma du caractère /* (2) Valeur ne correspond pas au schéma du caractère
-----------------------------------------------------------*/ -----------------------------------------------------------*/
else if( tmpValue[i].match(tmpRegExp) == null ){ else if( tmpValue[i].match(tmpRegExp) == null ){
// si le caractère suivant match, on décale d'une position // si le caractère suivant match, on décale d'une position
if( tmpValue[i].match(new RegExp( '^'+RegExpByChar[i+1]+'$' )) != null ) if( tmpValue[i].match(new RegExp( '^'+RegExpByChar[i+1]+'$' )) != null )
tmpValue = tmpValue.slice(0, i).concat( this.defval[index][i] ).concat( tmpValue.slice(i) ); tmpValue = tmpValue.slice(0, i).concat( this.defval[index][i] ).concat( tmpValue.slice(i) );
// sinon on remplace // sinon on remplace
else else
@ -283,11 +283,11 @@ inputChecker.prototype = {
tmpValue = tmpValue.slice(0, RegExpByChar.length); tmpValue = tmpValue.slice(0, RegExpByChar.length);
// on met à jour la valeur de l'élément input // on met à jour la valeur de l'élément input
this.input[index].value = tmpValue; this.input[index].value = tmpValue;
} }
} }
}; };

9
js/lib/page-manager-min.js vendored Normal file
View File

@ -0,0 +1,9 @@
function pageManagerClass(){}var ptrPageManagerClass;
pageManagerClass.prototype={depJS:null,depCSS:null,xhr:[],activeXHR:null,page:null,vars:[],path:"",jsPath:"js",cssPath:"css",pagelist:null,container:null,ajax:function(b,c,f,a){for(var d=0;d<this.xhr.length;d++)this.xhr=this.xhr.slice(0,d-1).concat(this.xhr.slice(d,this.xhr.length-1));var e;e=window.XMLHttpRequest?this.xhr.push(new XMLHttpRequest)-1:this.xhr.push(new ActiveXObject("Microsoft.XMLHttpRequest"))-1;this.activeXHR=this.xhr[e];var g=this;this.xhr[e].onreadystatechange=function(){4==g.xhr[e].readyState&&
(-1<[0,200].indexOf(g.xhr[e].status)?c(g.xhr[e].responseText):c())};f="string"==typeof f&&/^POST|GET$/i.test(f)?f.toUpperCase():"POST";a="POST"==f&&"object"==typeof a&&a instanceof FormData?a:null;this.xhr[e].open(f,b,!0);this.xhr[e].send(a);return this},explodeURL:function(b){b=1<=arguments.length?b:document.URL;if(null!=this.pagelist&&/^(?:(?:https?:\/\/)?[^\/]+)\/([a-z0-9_]+)\/?(?:\/((?:.+\/)+)\/?)?$/i.test(b)){for(var c=RegExp.$2.split("/");""==c[c.length-1];)c.pop();return-1<this.pagelist.indexOf(RegExp.$1)?
{page:RegExp.$1,"var":c}:null}return null},loadDependencies:function(){"object"==typeof this.depCSS&&this.depCSS instanceof Element&&this.depCSS.parentNode==document.head&&document.head.removeChild(this.depCSS);"object"==typeof this.depJS&&this.depJS instanceof Element&&this.depJS.parentNode==document.head&&document.head.removeChild(this.depJS);ptrPageManagerClass=this;this.ajax(this.path+"/"+this.cssPath+"/"+this.page+".css",function(b){null!=b?(ptrPageManagerClass.depCSS=document.createElement("link"),
ptrPageManagerClass.depCSS.rel="stylesheet",ptrPageManagerClass.depCSS.type="text/css",ptrPageManagerClass.depCSS.href=ptrPageManagerClass.path+"/"+ptrPageManagerClass.cssPath+"/"+ptrPageManagerClass.page+".css",document.head.appendChild(ptrPageManagerClass.depCSS)):console.warn("[loadDependencies_Error] - ("+ptrPageManagerClass.path+"/"+ptrPageManagerClass.cssPath+"/"+ptrPageManagerClass.page+".css)")});this.ajax(this.path+"/"+this.jsPath+"/"+this.page+".js",function(b){null!=b?(ptrPageManagerClass.depJS=
document.createElement("script"),ptrPageManagerClass.depJS.type="text/javascript",ptrPageManagerClass.depJS.src=ptrPageManagerClass.path+"/"+ptrPageManagerClass.jsPath+"/"+ptrPageManagerClass.page+".js",document.head.appendChild(ptrPageManagerClass.depJS)):console.warn("[loadDependencies_Error] - ("+ptrPageManagerClass.path+"/"+ptrPageManagerClass.jsPath+"/"+ptrPageManagerClass.page+".js)")})},updateURL:function(){0<this.vars.length?window.history.pushState(this.page,this.page,"/"+this.page+"/"+this.vars.join("/")+
"/"):window.history.pushState(this.page,this.page,"/"+this.page+"/")},setPage:function(b,c,f,a){var d="object"==typeof a&&a instanceof Array?a:null;if(null!=d)for(a=0;a<d.length&&(d="string"==typeof d[a]&&/^[a-z0-9_]+$/i.test(d[a])?d:null,null!=d);a++);this.pagelist=null!=d?d:this.pagelist;this.page=this.pagelist[0];this.path="string"==typeof c?c:this.path;this.container="object"==typeof f&&f instanceof Element?f:this.container;if(null!=this.pagelist&&null!=this.container)if("string"==typeof b&&-1<
this.pagelist.indexOf(b)){this.page=b;var e=this;b=new FormData;for(a=0;a<this.vars.length;a++)b.append(this.vars[a],null);this.ajax(this.path+"/"+this.page+".php",function(a){e.container.innerHTML=a;e.loadDependencies()},"POST",b);this.updateURL()}else if(c=this.explodeURL(),null!=c){this.page=c.page;var g=this;b=new FormData;for(a=this.vars.length=0;a<c["var"].length;a++)this.vars[a]=c["var"][a],b.append(this.vars[a],null);this.ajax(this.path+"/"+this.page+".php",function(a){g.container.innerHTML=
a;g.loadDependencies()},"POST",b);this.updateURL()}else this.setPage(this.pagelist[0]);else console.warn("pagelist et container manquant");return this},refresh:function(){this.setPage(this.page);return this}};

View File

@ -45,7 +45,7 @@ pageManagerClass.prototype = {
if(window.XMLHttpRequest) // IE7+, Firefox, Chrome, Opera, Safari if(window.XMLHttpRequest) // IE7+, Firefox, Chrome, Opera, Safari
index = this.xhr.push( new XMLHttpRequest() ) -1; index = this.xhr.push( new XMLHttpRequest() ) -1;
else // IE5, IE6 else // IE5, IE6
index = this.xhr.push( new ActiveXObject('Microsoft.XMLHttpRequest') ) -1; index = this.xhr.push( new ActiveXObject('Microsoft.XMLHttpRequest') ) -1;
// On definit un pointeur sur l'instance XHR active (ajax) // On definit un pointeur sur l'instance XHR active (ajax)
@ -83,7 +83,7 @@ pageManagerClass.prototype = {
// var fd = new FormData(); // création d'un formulaire // var fd = new FormData(); // création d'un formulaire
// fd.append('var', 100); // ajout de la variable VAR qui vaut 100 // fd.append('var', 100); // ajout de la variable VAR qui vaut 100
// ajax( 'index.php', alert, null, fd ); // saut de paramètre avec null + envoi formulaire // ajax( 'index.php', alert, null, fd ); // saut de paramètre avec null + envoi formulaire
// ajax( 'index.php?var=10', alert, 'GET' ); // envoi formulaire en GET (dans l'url) // ajax( 'index.php?var=10', alert, 'GET' ); // envoi formulaire en GET (dans l'url)
// ajax( 'index.php?var=10', alert, 'POST', fd ); // envoi formulaire en GET (dans l'url) + en POST via le formulaire FD // ajax( 'index.php?var=10', alert, 'POST', fd ); // envoi formulaire en GET (dans l'url) + en POST via le formulaire FD
@ -101,7 +101,7 @@ pageManagerClass.prototype = {
explodeURL: function(url_data){ explodeURL: function(url_data){
url_data = (arguments.length >= 1) ? url_data : document.URL; url_data = (arguments.length >= 1) ? url_data : document.URL;
// si pageList est correct et que l'URL correspond à un schéma de page => continue [sinon] return null // si pageList est correct et que l'URL correspond à un schéma de page => continue [sinon] return null
if( this.pagelist != null && /^(?:(?:http:\/\/)?[^\/]+)\/([a-z0-9_]+)\/?(?:\/((?:.+\/)+)\/?)?$/i.test(url_data) ){ if( this.pagelist != null && /^(?:(?:https?:\/\/)?[^\/]+)\/([a-z0-9_]+)\/?(?:\/((?:.+\/)+)\/?)?$/i.test(url_data) ){
// si la page récupérée dans l'url est dans la liste => renvoi de l'objet [sinon] null // si la page récupérée dans l'url est dans la liste => renvoi de l'objet [sinon] null
var vars = RegExp.$2.split('/'); var vars = RegExp.$2.split('/');
while( vars[vars.length-1] == '' ) // on supprime les dernières entrées vides while( vars[vars.length-1] == '' ) // on supprime les dernières entrées vides
@ -156,7 +156,7 @@ pageManagerClass.prototype = {
}, },
/* ======================================================================= /* =======================================================================
Met à jour l'URL de la page en fonction de la page chargée et des Met à jour l'URL de la page en fonction de la page chargée et des
variables associées (ne recharge aucune ressource) variables associées (ne recharge aucune ressource)
======================================================================= */ ======================================================================= */
updateURL: function(){ updateURL: function(){
@ -177,13 +177,13 @@ pageManagerClass.prototype = {
- pContainer<Element> l'élément du DOM qui contiendra la page chargée (**) - pContainer<Element> l'élément du DOM qui contiendra la page chargée (**)
- pPageList<Array<string>> tableau contenant la liste des pages sous forme de chaînes de caractères (**) (***) - pPageList<Array<string>> tableau contenant la liste des pages sous forme de chaînes de caractères (**) (***)
* Le chemin du dossier sans le '/' final si c'est le dossier actuel le chemin est une chaîne vide * Le chemin du dossier sans le '/' final si c'est le dossier actuel le chemin est une chaîne vide
Si le dossier est 'page' et que l'on cherche la page 'accUe1l', la requête sera vers 'page/accUe1l.php' Si le dossier est 'page' et que l'on cherche la page 'accUe1l', la requête sera vers 'page/accUe1l.php'
le nom de la page est sensible à la casse le nom de la page est sensible à la casse
** 1. pPageList et pContainer doivent être mis en paramètres uniquement à la première utilisation ** 1. pPageList et pContainer doivent être mis en paramètres uniquement à la première utilisation
et la première utilisation doit se faire au chargement de la page car elle permetra et la première utilisation doit se faire au chargement de la page car elle permetra
de mettre l'URL à jour et/ou charger la page de l'URL de mettre l'URL à jour et/ou charger la page de l'URL
*** la première page du tableau est la page par défaut (qui est chargée si l'URL ne contient *** la première page du tableau est la page par défaut (qui est chargée si l'URL ne contient
pas la page ou si la page de l'URL ne correspond à aucune page de la liste) pas la page ou si la page de l'URL ne correspond à aucune page de la liste)
========================================================================== */ ========================================================================== */
setPage: function(pName, pPath, pContainer, pPageList){ setPage: function(pName, pPath, pContainer, pPageList){
@ -205,7 +205,7 @@ pageManagerClass.prototype = {
/* on attribue le paramètre pContainer à l'attribut si il est spécifié */ /* on attribue le paramètre pContainer à l'attribut si il est spécifié */
this.container = ( typeof pContainer == 'object' && pContainer instanceof Element ) ? pContainer : this.container; this.container = ( typeof pContainer == 'object' && pContainer instanceof Element ) ? pContainer : this.container;
// si this.pagelist && this.container ne sont pas null && // si this.pagelist && this.container ne sont pas null &&
if( this.pagelist != null && this.container != null ){ if( this.pagelist != null && this.container != null ){
// si le pName est renseigné et qu'il est dans pagelist // si le pName est renseigné et qu'il est dans pagelist
if( typeof pName == 'string' && this.pagelist.indexOf(pName) > -1 ){ if( typeof pName == 'string' && this.pagelist.indexOf(pName) > -1 ){
@ -219,15 +219,15 @@ pageManagerClass.prototype = {
var fd = new FormData(); var fd = new FormData();
for( var i = 0 ; i < this.vars.length ; i++ ) for( var i = 0 ; i < this.vars.length ; i++ )
fd.append(this.vars[i], null); fd.append(this.vars[i], null);
this.ajax(this.path+'/'+this.page+'.php', function(e){ this.ajax(this.path+'/'+this.page+'.php', function(e){
ptrPageManagerClass.container.innerHTML = e; ptrPageManagerClass.container.innerHTML = e;
ptrPageManagerClass.loadDependencies(); ptrPageManagerClass.loadDependencies();
}, 'POST', fd); }, 'POST', fd);
// change l'URL en conséquences(stateObj, titre, url) // change l'URL en conséquences(stateObj, titre, url)
this.updateURL(); this.updateURL();
}else{ // si la page n'est pas spécifiée ou qu'elle n'est pas dans la liste des pages }else{ // si la page n'est pas spécifiée ou qu'elle n'est pas dans la liste des pages
var urlGet = this.explodeURL(); var urlGet = this.explodeURL();
@ -248,12 +248,12 @@ pageManagerClass.prototype = {
this.ajax(this.path+'/'+this.page+'.php', function(e){ this.ajax(this.path+'/'+this.page+'.php', function(e){
ptrThis.container.innerHTML = e; ptrThis.container.innerHTML = e;
ptrThis.loadDependencies(); ptrThis.loadDependencies();
}, 'POST', fd); }, 'POST', fd);
// change l'URL en conséquences(stateObj, titre, url) // change l'URL en conséquences(stateObj, titre, url)
this.updateURL(); this.updateURL();
}else // si l'url ne contient rien, on charge la page par défaut }else // si l'url ne contient rien, on charge la page par défaut
this.setPage(this.pagelist[0]); this.setPage(this.pagelist[0]);
} }
@ -276,4 +276,4 @@ pageManagerClass.prototype = {
return this; return this;
} }
} }

2
js/lib/reset-min.js vendored Normal file
View File

@ -0,0 +1,2 @@
function $(a){var b=document.querySelectorAll("#"+a);a=document.querySelectorAll("."+a);return 0<b.length?b[0]:a[0]}Element.prototype.getData=function(a){return"undefined"==typeof this.dataset?!1:this.dataset.hasOwnProperty(a)?this.dataset[a]:!1};Element.prototype.addClass=function(a){var b=this.className.split(" ");-1<b.indexOf(a)||(b.push(a),this.className=b.join(" ").trim())};
Element.prototype.remClass=function(a){var b=this.className.split(" ");a=b.indexOf(a);-1!=a&&(b=b.slice(0,a).concat(b.slice(a+1)),this.className=b.join(" ").trim())};NodeList.prototype.indexOf=HTMLCollection.prototype.indexOf=function(a){for(var b=0;b<this.length;b++)if(this[b]==a)return b;return-1};Element.prototype.anim=function(a,b){var c=this;c.addClass(a);setTimeout(function(){c.remClass(a)},b)};var format_code=new formatChecker(null,"HH-HH-HH-HH",{H:"[0-9A-F]"});

View File

@ -110,4 +110,4 @@ Element.prototype.anim = function(className, timeout){
/* DEFINITION DES FORMATS UTILES POUR INPUT-CHECKER /* DEFINITION DES FORMATS UTILES POUR INPUT-CHECKER
* *
*/ */
var format_code = new formatChecker(null, 'HH-HH-HH-HH', { 'H' : '[0-9A-F]'} ) var format_code = new formatChecker(null, 'HH-HH-HH-HH', { 'H' : '[0-9A-F]'} )

View File

@ -1,10 +1,10 @@
<?php <?php
namespace manager; namespace manager;
class DataBase{ class DataBase{
/* ATTRIBUTS STATIQUES */ /* ATTRIBUTS STATIQUES */
public static $config_path = array( public static $config_path = array(
'local' => 'f/json/database-local/conf', 'local' => 'f/json/database-local/conf',
@ -29,8 +29,8 @@
$this->dbname = $dbname; $this->dbname = $dbname;
$this->username = $username; $this->username = $username;
$this->password = $password; $this->password = $password;
try{ try{
self::$pdo = new \PDO('mysql:host='.$this->host.';dbname='.$this->dbname, $this->username, $this->password); self::$pdo = new \PDO('mysql:host='.$this->host.';dbname='.$this->dbname, $this->username, $this->password);
// On signale que tout s'est bien passe // On signale que tout s'est bien passe
@ -48,7 +48,7 @@
if( self::$instance == null || self::$error != ManagerError::Success ){ // Si aucune instance existante OU erreur de connection if( self::$instance == null || self::$error != ManagerError::Success ){ // Si aucune instance existante OU erreur de connection
// chargement de la configuration du server SQL // chargement de la configuration du server SQL
if( !isset($_SERVER['HTTP_HOST']) || isset($_SERVER['HTTP_HOST']) && $_SERVER['HTTP_HOST'] == 'stefproject' ) if( !checkdnsrr($_SERVER['SERVER_NAME'], 'NS') )
$conf = json_decode( ResourceDispatcher::getResource(self::$config_path['local']), true ); $conf = json_decode( ResourceDispatcher::getResource(self::$config_path['local']), true );
else else
$conf = json_decode( ResourceDispatcher::getResource(self::$config_path['remote']), true ); $conf = json_decode( ResourceDispatcher::getResource(self::$config_path['remote']), true );
@ -57,7 +57,7 @@
self::$instance = new DataBase($conf['host'], $conf['dbname'], $conf['user'], $conf['password']); self::$instance = new DataBase($conf['host'], $conf['dbname'], $conf['user'], $conf['password']);
} }
return self::$instance; return self::$instance;
} }
@ -104,7 +104,7 @@
* @fetchData<Array> le résultat d'une $requeteSQL->fetchAll() * @fetchData<Array> le résultat d'une $requeteSQL->fetchAll()
* @oneDimension<Boolean> FAUX <=> fetchAll ; VRAI <=> fetch * @oneDimension<Boolean> FAUX <=> fetchAll ; VRAI <=> fetch
* *
* @return newFetchData<Array> retourne le tableau donné en paramètre mais sans les valeurs à clés numériques * @return newFetchData<Array> retourne le tableau donné en paramètre mais sans les valeurs à clés numériques
* *
*/ */
public static function delNumeric($fetchData, $oneDimension=false){ public static function delNumeric($fetchData, $oneDimension=false){
@ -121,19 +121,19 @@
// on supprime les doublons des entrées (indice numérique) // on supprime les doublons des entrées (indice numérique)
for( $i = 0 ; $i < count($fetchData) ; $i++ ) // pour tout les utilisateurs for( $i = 0 ; $i < count($fetchData) ; $i++ ) // pour tout les utilisateurs
foreach($fetchData[$i] as $col => $val){ // pour toutes les entrées foreach($fetchData[$i] as $col => $val){ // pour toutes les entrées
if( !mb_detect_encoding($val, 'UTF-8') ) if( !\mb_detect_encoding($val, 'UTF-8') )
$fetchData[$i][$col] = utf8_encode($val); $fetchData[$i][$col] = utf8_encode($val);
if( is_int($col) ){ // Si indice numerique if( is_int($col) ){ // Si indice numerique
if( $nextEquivalent ) // Si suit un indice textuel if( $nextEquivalent ) // Si suit un indice textuel
unset( $fetchData[$i][$col] ); // on supprime l'indice unset( $fetchData[$i][$col] ); // on supprime l'indice
$nextEquivalent = false; // Dans tous les cas, on dit que le prochain ne pourra pas etre supprime si numerique $nextEquivalent = false; // Dans tous les cas, on dit que le prochain ne pourra pas etre supprime si numerique
}else // Si l'indice n'est pas un entier }else // Si l'indice n'est pas un entier
$nextEquivalent = true; // On signale qu'il y aura peut etre un indice numerique suivant $nextEquivalent = true; // On signale qu'il y aura peut etre un indice numerique suivant
} }
/* [2] 1 dimensions /* [2] 1 dimensions
@ -142,14 +142,14 @@
// on supprime les doublons des entrées (indice numérique) // on supprime les doublons des entrées (indice numérique)
foreach($fetchData as $i=>$val){ // pour toutes les entrées foreach($fetchData as $i=>$val){ // pour toutes les entrées
if( !mb_detect_encoding($val, 'UTF-8') ) if( !\mb_detect_encoding($val, 'UTF-8') )
$fetchData[$i] = utf8_encode($val); $fetchData[$i] = utf8_encode($val);
if( is_int($i) ){ // Si indice numerique if( is_int($i) ){ // Si indice numerique
if( $nextEquivalent ) // Si suit un indice textuel if( $nextEquivalent ) // Si suit un indice textuel
unset( $fetchData[$i] ); // on supprime l'indice unset( $fetchData[$i] ); // on supprime l'indice
$nextEquivalent = false; // Dans tous les cas, on dit que le prochain ne pourra pas etre supprime si numerique $nextEquivalent = false; // Dans tous les cas, on dit que le prochain ne pourra pas etre supprime si numerique
}else // Si l'indice n'est pas un entier }else // Si l'indice n'est pas un entier
@ -165,12 +165,12 @@
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
// _ __ _ _ _ // _ __ _ _ _
// __ _____ _ __(_)/ _(_) ___ __ _| |_(_) ___ _ __ ___ // __ _____ _ __(_)/ _(_) ___ __ _| |_(_) ___ _ __ ___
// \ \ / / _ \ '__| | |_| |/ __/ _` | __| |/ _ \| '_ \/ __| // \ \ / / _ \ '__| | |_| |/ __/ _` | __| |/ _ \| '_ \/ __|
// \ V / __/ | | | _| | (_| (_| | |_| | (_) | | | \__ \ // \ V / __/ | | | _| | (_| (_| | |_| | (_) | | | \__ \
// \_/ \___|_| |_|_| |_|\___\__,_|\__|_|\___/|_| |_|___/ // \_/ \___|_| |_|_| |_|\___\__,_|\__|_|\___/|_| |_|___/
// //
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
@ -183,43 +183,104 @@
* *
*/ */
public static function check($type, $value){ public static function check($type, $value){
$checker = !is_null($value); $checker = true;
/* [0] On verifie que $value n'est pas nul
=========================================================*/
if( is_null($value) ) return false;
/* [1] Si de type VARCHAR(min, max)
=========================================================*/
if( preg_match('/^varchar\((\d+), ?(\d+)\)$/', $type, $match) ){
// On recupere la taille min
$min = (int) $match[1];
// On recupere la taille max
$max = (int) $match[2];
// On effectue la verification
return $checker && is_string($value) && strlen($value) <= $max && strlen($value) >= $min;
}
/* [2] Si de type ARRAY(type_elements)
=========================================================*/
if( preg_match('/^array<(.+)>$/', $type, $match) ){
// Si c'est pas un tableau on retourne une erreur
if( !is_array($value) )
return false;
$elements_type = $match[1];
// On verifie le type pour chaque element
foreach($value as $element)
// Si erreur dans au moins 1 element, on retourne que c'est incorrect
if( !self::check($elements_type, $element) )
return false;
// Si aucune erreur, on retourne que tout est bon
return true;
}
/* [n] Sinon, tous les autres types definis
=========================================================*/
switch($type){ switch($type){
/* (1) Global */ // Quoi que ce soit
case 'auto_increment_id': case 'mixed':
return $checker && is_numeric($value) && $value <= 2147483647 && $value >= -2147483647; return $checker && !is_null($value);
break; break;
/* (2) Utilisateur */ // Entier positif (id dans BDD)
case 'user.code': case 'id':
case 'machine.code': return $checker && is_numeric($value) && $value <= 2147483647 && $value >= 0;
return $checker && is_string($value) && preg_match('/^[\dA-F]{2}(\-[\dA-F]{2}){3,5}$/i', $value);
break; break;
case 'user.username': // String quelconque (peut etre vide)
case 'machine.name': case 'text':
case 'group.name': return $checker && is_string($value);
return $checker && is_string($value) && preg_match('/^[\w-]{1,30}$/i', $value);
break; // Adresse mail (255 caracteres max)
case 'mail':
case 'user.firstname':
case 'user.lastname':
return $checker && is_string($value) && preg_match('/^[a-z -]{3,30}$/i', $value);
break;
case 'user.mail':
return $checker && is_string($value) && strlen($value) <= 50 && preg_match('/^[\w\.-]+@[\w\.-]+\.[a-z]{2,4}$/i', $value); return $checker && is_string($value) && strlen($value) <= 50 && preg_match('/^[\w\.-]+@[\w\.-]+\.[a-z]{2,4}$/i', $value);
break; break;
case 'user.password': // Hash sha1
case 'sha1':
return $checker && is_string($value) && preg_match('/^[\da-f]{40}$/i', $value); return $checker && is_string($value) && preg_match('/^[\da-f]{40}$/i', $value);
break; break;
case 'user.status': // Numéro de téléphone
return $checker && is_numeric($value) && floor($value) == $value && $value >= 0 && $value <= 100; case 'number':
return $checker && is_string($value) && preg_match('/^(?:0|\+33 ?|0?0?33 ?|)([1-9] ?(?:[0-9] ?){8})$/i', $value);
break; break;
// Tableau non vide
case 'array':
return $checker && is_array($value) && count($value) > 0;
break;
// Boolean
case 'boolean':
return $checker && is_bool($value);
break;
// Objet non vide
case 'object':
return $checker && is_object($value) && count((array) $value) > 0;
break;
// Chaine JSON (on vérifie via le parser)
case 'json':
return $checker && is_string($value) && json_decode($value, true) !== NULL;
break;
default:
return false;
break;
} }
return $checker; return $checker;
@ -227,5 +288,80 @@
} }
/* FONCTION QUI FORMATTE UN NUMÉRO DE TÉLÉPHONE
*
* @number<String> Numéro de téléphone en +336/336/06/0336/00336
*
* @return formatted<String> Numéro formatté (06), on FALSE si erreur
*
*/
public static function formatNumber($number){
// On met en <string> quel que soit le type
$number = (string) $number;
// On supprime tous les espaces
$number = str_replace(' ', '', $number);
// On formatte le numéro
if( preg_match("/^(?:\+33|0?0?33|0)(.+)/", $number, $m) )
$number = '0'.$m[1];
// On retourne le numéro formatté
return $number;
}
public static function readableNumber($number){
/* (1) On formatte le numéro si c'est pas fait */
$formatted = self::formatNumber($number);
for( $i = 1 ; $i < strlen($formatted) ; $i++ )
if( ($i-2) % 3 == 0 )
$formatted = substr($formatted, 0, $i).' '.substr($formatted, $i);
return $formatted;
}
////////////////////////////////////
// _ _
// __| | __ _| |_ ___ ___
// / _` |/ _` | __/ _ \/ __|
// | (_| | (_| | || __/\__ \
// \__,_|\__,_|\__\___||___/
//
////////////////////////////////////
// 1) Convertis une date en en francais explicite
public static function frDate($date){
/* [1] On definit les traductions
=========================================================*/
// Jours de la semaine
$days = array("Lundi", "Mardi", "Mercredi", "Jeudi", "Vendredi", "Samedi", "Dimanche");
// Mois de l'annee
$months = array("Janvier", "Février", "Mars", "Avril", "Mai", "Juin", "Juillet", "Août", "Septembre", "Octobre", "Novembre", "Décembre");
/* [2] On recupere le timestamp et les indices
=========================================================*/
$time = strtotime($date); // timestamp
$daynum = intval( date('N', $time)-1 ); // jour dans la semaine
$monthnum = intval( date('n', $time)-1 ); // numero du mois dans l'annee
/* [3] On recupere les infos independemment
=========================================================*/
$result = array(
$days[$daynum], // nom de jour
date('j', $time), // jour du mois
$months[$monthnum], // nom du mois
date('Y', $time), // annee
);
return implode(" ", $result);
}
} }
?> ?>

View File

@ -1,6 +1,6 @@
<?php <?php
namespace manager; namespace manager;
@ -60,6 +60,21 @@
// Erreur lors de la creation d'un objet PDO (connection) // Erreur lors de la creation d'un objet PDO (connection)
const PDOConnection = 14; const PDOConnection = 14;
/* API token */
// Token inexistant ou faux
const TokenError = 15;
const PermissionError = 16;
/* Erreur d'UPLOAD */
const UploadError = 17;
// Mauvais format de fichier
const FormatError = 18;
/* Erreur au niveau javascript */
//const JavascriptError = 19; // -> géré en js
/* EXPLICITE UN CODE D'ERREUR /* EXPLICITE UN CODE D'ERREUR
* *
@ -70,33 +85,43 @@
*/ */
public static function explicit($error){ public static function explicit($error){
switch($error){ switch($error){
case self::Success: return "Tout s'est bien deroule"; break; case self::Success: return "Tout s'est bien deroulé."; break;
case self::ParsingFailed: return "La lecture du fichier JSON a echoue"; break; case self::ParsingFailed: return "La lecture du fichier JSON ou XML a echouée."; break;
case self::InvalidFlags: return "Les specifications (drapeaux) sont incorrects"; break;
case self::UnreachableResource: return "La ressource n'existe pas (404)"; break;
case self::MissingPath: return "Le chemin de delegation n'a pas ete renseigne"; break;
case self::WrongPathModule: return "Le chemin de delegation est incorrect ('nomModule/nomMethode')"; break;
case self::WrongPathRepo: return "Le chemin de delegation est incorrect ('nomRepo/nomMethode')"; break;
case self::UnknownModule: return "Le module n'existe pas"; break;
case self::UnknownRepo: return "Le repo n'existe pas"; break;
case self::UnknownMethod: return "Le methode n'existe pas"; break;
case self::UncallableMethod: return "Le methode n'est pas amorcable"; break;
case self::ParamError: return "Un ou plusieurs parametres sont manquants ou incorrects"; break; case self::InvalidFlags: return "Les spécifications (drapeaux) sont incorrects."; break;
case self::ModuleError: return "Erreur lors du traitement du module"; break; case self::UnreachableResource: return "La ressource n'existe pas (404)."; break;
case self::RepoError: return "Erreur lors du traitement du repo"; break; case self::MissingPath: return "Le chemin de délégation n'a pas été renseigné."; break;
case self::WrongPathModule: return "Le chemin de délégation est incorrect ('nomModule/nomMethode')."; break;
case self::WrongPathRepo: return "Le chemin de délégation est incorrect ('nomRepo/nomMethode')."; break;
case self::UnknownModule: return "Le module n'existe pas."; break;
case self::UnknownRepo: return "Le repo n'existe pas."; break;
case self::UnknownMethod: return "Le methode n'existe pas."; break;
case self::UncallableMethod: return "Le methode n'est pas amorçable."; break;
case self::PDOConnection: return "La connexion avec la base de donnees a echoue"; break; case self::ParamError: return "Un ou plusieurs paramètres sont manquants ou incorrects."; break;
case self::ModuleError: return "Erreur lors du traitement du module."; break;
case self::RepoError: return "Erreur lors du traitement du repo."; break;
// default: return "Erreur inconnue..."; break; case self::PDOConnection: return "La connexion avec la base de données a echouée."; break;
case self::TokenError: return "Le token de connection est absent, érroné ou expiré."; break;
case self::PermissionError: return "Vous n'avez pas la permission d'effectuer cette action."; break;
case self::UploadError: return "Une erreur d'upload est survenue."; break;
case self::FormatError: return "Le fichier n'est pas au bon format."; break;
default: return "Description d'erreur inconnue..."; break;
} }
// Erreur inconnue // Erreur inconnue
return null; return null;
} }
public static function setHttpCode($error){
http_response_code( $error == self::Success ? 200 : 417 );
}
} }
?> ?>

View File

@ -1,28 +1,22 @@
<?php <?php
namespace manager; namespace manager;
use \manager\Database;
// FORMAT:
//
// path: "nomModule/nomMethode"
// data1: {donnee1}
// data2: {donnee2}
// ...
//
//
//
//
class ModuleRequest{ class ModuleRequest{
// Constantes // Constantes
public static $config_path = 'f/json/modules/conf'; public static $config_path = 'f/json/modules/conf';
public static $default_options = array(
'download' => false
);
// Attributs prives utiles (initialisation) // Attributs prives utiles (initialisation)
private $path; private $path;
private $data; private $params;
private $modules; private $modules;
private $options;
// Contiendra la reponse a la requete // Contiendra la reponse a la requete
public $answer; public $answer;
@ -37,12 +31,13 @@
/* CONSTRUCTEUR D'UNE REQUETE DE MODULE /* CONSTRUCTEUR D'UNE REQUETE DE MODULE
* *
* @path<String> Chemin de delegation ("module/methode") * @path<String> Chemin de delegation ("module/methode")
* @data<Array> Tableau contenant les parametres utiles au traitement * @param<Array> Tableau associatif contenant les parametres utiles au traitement
* @token<String> Token d'acces a l'api (OPTIONNEL)
* *
* @return status<Boolean> Retourne si oui ou non tout s'est bien passe * @return status<Boolean> Retourne si oui ou non tout s'est bien passe
* *
*/ */
public function __construct($path=null, $data=null){ public function __construct($path=null, $params=null, $token=null){
// Si pas parametre manquant, on quitte // Si pas parametre manquant, on quitte
if( $path == null ){ if( $path == null ){
$this->error = ManagerError::MissingPath; $this->error = ManagerError::MissingPath;
@ -53,7 +48,7 @@
=========================================================*/ =========================================================*/
// Modules specifies // Modules specifies
$this->modules = json_decode( ResourceDispatcher::getResource(self::$config_path), true ); $this->modules = json_decode( ResourceDispatcher::getResource(self::$config_path), true );
// Gestion de l'erreur de parsage // Gestion de l'erreur de parsage
if( $this->modules == null ){ if( $this->modules == null ){
$this->error = ManagerError::ParsingFailed; $this->error = ManagerError::ParsingFailed;
@ -71,19 +66,37 @@
} }
// Type de @data (optionnel) // Type de @data (optionnel)
$data = (is_array($data)) ? $data : array(); $params = (is_array($params)) ? $params : array();
/* [2] Verification du chemin (existence module+methode) /* [2] Verification du chemin (existence module+methode)
=========================================================*/ =========================================================*/
if( !$this->checkPath($path) ) // Verification de la coherence du chemin + attribution if( !$this->checkPath($path) ) // Verification de la coherence du chemin + attribution
return false; return false;
// Gestion d'erreur interne
/* [3] Construction de l'objet
/* [3] Verification des droits
=========================================================*/ =========================================================*/
$this->data = $data; if( !$this->checkPermission($token) ) // Si on a pas les droits
return false;
/* [4] Verification des parametres (si @type est defini)
=========================================================*/
if( !$this->checkParams($params) ){ // Verification de tous les types
$this->error = ManagerError::ParamError;
return false;
}
/* [5] Récupèration des options
=========================================================*/
$this->buildOptions();
/* [6] Construction de l'objet
=========================================================*/
$this->params = $params;
$this->error = ManagerError::Success; $this->error = ManagerError::Success;
return true; // On retourne que tout s'est bien passe return true; // On retourne que tout s'est bien passe
@ -94,35 +107,40 @@
/* EXECUTE LE TRAITEMENT ASSOCIE ET REMPLIE LA REPONSE /* EXECUTE LE TRAITEMENT ASSOCIE ET REMPLIE LA REPONSE
* *
* @return answer<ModuleAnswer> Retourne une reponse de type <ModuleAnswer> si tout s'est bien passe * @return answer<ModuleResponse> Retourne une reponse de type <ModuleResponse> si tout s'est bien passe
* *
*/ */
public function dispatch(){ public function dispatch(){
/* [0] Si c'est un download, on lance la methode `download()`
=========================================================*/
if( $this->options['download'] === true )
return $this->download();
/* [1] On verifie qu'aucune erreur n'a ete signalee /* [1] On verifie qu'aucune erreur n'a ete signalee
=========================================================*/ =========================================================*/
if( $this->error != ManagerError::Success ) // si il y a une erreur if( $this->error != ManagerError::Success ) // si il y a une erreur
return new ModuleAnswer($this->error); // on la passe a la reponse return new ModuleResponse($this->error); // on la passe a la reponse
/* [2] On verifie que la methode est amorcable /* [2] On verifie que la methode est amorcable
=========================================================*/ =========================================================*/
if( !is_callable($this->getFunctionCaller()) ){ if( !is_callable($this->getFunctionCaller()) ){
$this->error = ManagerError::UncallableMethod; $this->error = ManagerError::UncallableMethod;
return new ModuleAnswer($this->error); return new ModuleResponse($this->error);
} }
/* [3] On amorce la methode /* [3] On amorce la methode
=========================================================*/ =========================================================*/
$returned = call_user_func_array( $this->getFunctionCaller(), $this->data ); $returned = call_user_func( $this->getFunctionCaller(), $this->params );
/* [4] Gestion de la reponse /* [4] Gestion de la reponse
=========================================================*/ =========================================================*/
$answer = new ModuleAnswer($this->error); $response = new ModuleResponse($this->error);
$answer->appendAll($returned); $response->appendAll($returned);
return $answer; return $response;
} }
@ -130,71 +148,168 @@
/* DESERIALISATION ET CREATION D'UN OBJET
*
* @jsonString<String> Json au format string contenant les donnees
* /* EXECUTE LE TRAITEMENT ASSOCIE ET RENVOIE UN FICHIER AVEC LE HEADER ET LE BODY SPECIFIE
* @return instance<ModuleRequest> Retourne un objet de type <ModuleRequest>
* *
*/ */
public static function fromString($jsonString){ public function download(){
$json = json_decode( $jsonString, true ); /* [1] On verifie qu'aucune erreur n'a ete signalee
=========================================================*/
if( $this->error != ManagerError::Success ) // si il y a une erreur
return new ModuleResponse($this->error); // on la passe a la reponse
// Verification du parsage
if( $json == null )
return new ModuleRequest();
// Verification des parametres /* [2] On verifie que la methode est amorcable
if( !isset($json['path']) ) =========================================================*/
return new ModuleRequest(); if( !is_callable($this->getFunctionCaller()) ){
$this->error = ManagerError::UncallableMethod;
return new ModuleResponse($this->error);
}
// On definit $data au cas ou il soit vide
$data = (isset($json['data'])) ? $json['data'] : array();
return new ModuleRequest($json['path'], $data); /* [3] On amorce la methode
=========================================================*/
$returned = call_user_func( $this->getFunctionCaller(), $this->params );
/* [4] Vérification des erreurs et paramètres
=========================================================*/
/* (1) Vérification de l'erreur retournée, si pas Success, on retourne l'erreur */
if( isset($returned['ModuleError']) && $returned['ModuleError'] != ManagerError::Success ){
$this->error = $returned['ModuleError'];
return new ModuleResponse($this->error);
}
/* (2) Vérification du contenu, si pas défini */
if( !isset($returned['body']) ){
$this->error = ManagerError::ParamError;
return new ModuleResponse($this->error);
}
/* (3) Si @headers n'est pas défini on met par défaut */
if( !isset($returned['headers']) || !is_array($returned['headers']) )
$returned['headers'] = array();
$fromAjax = isset($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest';
/* [5] Si la requête vient d'ajax on crée un fichier temporaire et on renvoie son URL
=========================================================*/
if( $fromAjax ){
$tmpfname = '/tmp/download_'.uniqid().'.php';
$bodyfname = __ROOT__.'/tmp/content_'.uniqid().'.php';
/* (1) On crée le fichier temporaire */
$tmpfnameroot = __ROOT__.$tmpfname;
$tmpfile = fopen($tmpfnameroot, 'w');
fwrite($tmpfile, '<?php'.PHP_EOL);
/* (2) Script qui écrira les headers */
foreach($returned['headers'] as $header=>$value)
fwrite($tmpfile, "header(\"$header: $value\");".PHP_EOL);
/* (3) Script qui écrira le contenu */
// 1) On écrit le contenu dans un fichier temporaire (et oui encore)
$bodyfile = fopen($bodyfname, 'w');
fwrite($bodyfile, $returned['body']);
fclose($bodyfile);
chmod($bodyfname, 0775);
fwrite($tmpfile, "readfile('$bodyfname');".PHP_EOL);
/* (4) Script qui supprimera les fichiers temporaires */
fwrite($tmpfile, "unlink('$bodyfname');".PHP_EOL);
fwrite($tmpfile, "unlink(__FILE__);".PHP_EOL);
fwrite($tmpfile, '?>'.PHP_EOL);
/* (5) On ferme le fichier */
fclose($tmpfile);
chmod($tmpfnameroot, 0775);
$response = new ModuleResponse(ManagerError::Success);
$response->append('link', $tmpfname);
return $response;
/* [6] Gestion du download direct si pas AJAX
=========================================================*/
}else{
/* (1) On définit les headers */
foreach($returned['headers'] as $header=>$value)
header($header.': '.$value);
/* (2) On affiche le contenu */
echo $returned['body'];
return true;
}
} }
/* DESERIALISATION A PARTIR DES DONNEES POST /* DESERIALISATION A PARTIR DES DONNEES POST
* *
* @url<String> Contenu de l'url après api/ (si existe)
* @post<Array> Tableau des donnes $_POST => @path + @data (opt) * @post<Array> Tableau des donnes $_POST => @path + @data (opt)
* *
* @return instance<ModuleRequest> Retourne un objet de type <ModuleRequest> * @return instance<ModuleRequest> Retourne un objet de type <ModuleRequest>
* *
*/ */
public static function fromPost($post){ public static function fromPost($url, $post){
/* [0] Verification de l'authentification
=========================================================*/
// On definit le token
$token = isset($_SERVER['PHP_AUTH_DIGEST']) ? $_SERVER['PHP_AUTH_DIGEST'] : null;
/* [1] On verifie que le @path est renseigne /* [1] On verifie que le @path est renseigne
=========================================================*/ =========================================================*/
/* (1) Si le path est dans @url */
$pathInUrl = is_string($url[0]) && strlen($url[0]) > 0 && preg_match('#^([\w_-]+)/([\w_-]+)/?$#', $url[0], $urlMatches);
// On l'utilise pour le chemin
if( $pathInUrl )
$post['path'] = $urlMatches[1].'/'.$urlMatches[2];
/* (2) On vérifie dans tous les cas si le path existe */
if( !isset($post['path']) ) if( !isset($post['path']) )
return new ModuleRequest(); return new ModuleRequest();
/* [2] On verifie que @data est renseigne /* [2] On verifie que @data est renseigne
=========================================================*/ =========================================================*/
// Si variable n'existe pas, on cree un tableau vide // Si variable n'existe pas, on cree un tableau vide
$data = (isset($post['data'])) ? $post['data'] : array(); $params = $post;
// Si c'est toujours pas un tableau, on essaie de voir si c'est un json // On retire le @path de @params
$data = (!is_array($data)) ? json_decode($data, true) : $data; unset($params['path']);
// Si toujours pas de tableau, on cree un tableau vide
$data = (!is_array($data)) ? array() : $data;
/* [3] On retourne une instance de <ModuleRequest>
/* [3] On met les paramètres JSON en JSON (si ils décodent sans erreur)
=========================================================*/ =========================================================*/
return new ModuleRequest($post['path'], $data); foreach($params as $name=>$value){
$json = json_decode( $value, true );
// Si aucune erreur, on affecte la valeur
if( !is_null($json) )
$params[$name] = $json;
}
/* [4] On retourne une instance de <ModuleRequest>
=========================================================*/
// On cree notre requete avec le token
return new ModuleRequest($post['path'], $params, $token);
} }
/* VERIFICATION DU FORMAT ET DE LA COHERENCE DU CHEMIN SPECIFIE /* VERIFICATION DU FORMAT ET DE LA COHERENCE DU CHEMIN SPECIFIE
* *
* @path<String> String correspondant au chemin de delegation ("module/methode") * @path<String> String correspondant au chemin de delegation ("module/methode")
@ -214,6 +329,7 @@
$module = $matches[1]; $module = $matches[1];
$method = $matches[2]; $method = $matches[2];
/* [2] Verification de l'existence du module (conf) /* [2] Verification de l'existence du module (conf)
=========================================================*/ =========================================================*/
if( !array_key_exists($module, $this->modules) ){ // Si le module n'est pas specifie dans la conf if( !array_key_exists($module, $this->modules) ){ // Si le module n'est pas specifie dans la conf
@ -223,11 +339,11 @@
/* [3] Verification de l'existence de la methode (conf) /* [3] Verification de l'existence de la methode (conf)
=========================================================*/ =========================================================*/
if( array_search($method, $this->modules[$module]) === false ){ // Si la methode n'est pas specifie dans la conf if( array_key_exists($method, $this->modules[$module]) === false ){ // Si la methode n'est pas specifie dans la conf
$this->error = ManagerError::UnknownMethod; $this->error = ManagerError::UnknownMethod;
return false; // On retourne FALSE, si erreur return false; // On retourne FALSE, si erreur
} }
/* [4] Enregistrement du chemin et renvoi de SUCCESS /* [4] Enregistrement du chemin et renvoi de SUCCESS
@ -244,6 +360,180 @@
/* RETOURNE SI ON A LA PERMISSION D'EXECUTER CETTE METHODE
*
* @token<String> Token d'acces a l'API (OPTIONNEL)
*
* @return permission<bool> Retourne si on a les droits ou pas pour executer cette methode
*
*/
private function checkPermission($token=null){
/* [1] On recupere les informations utiles
=========================================================*/
// On recupere le nom de la methode
$method = $this->modules[$this->path['module']][$this->path['method']];
// Si aucune permission n'est definie
if( !isset($method['permissions']) ) return true;
/* [2] Gestion si un @token est defini
=========================================================*/
if( Database::check('sha1', $token) ){
/* (1) On verifie que le token est valide */
$checkToken = new Repo('token/check', array($token) );
$token_permissions = $checkToken->answer();
// Si le token est invalide, on retourne une erreur -> FAUX
if( $token_permissions === false ){
$this->error = ManagerError::TokenError;
return false;
}
$local_permissions = $token_permissions;
/* [3] Gestion si aucun token, avec utilisateur connecté
=========================================================*/
}else if( isset($_SESSION['permission']) )
$local_permissions = $_SESSION['permission'];
// Si ni token, ni SESSION, erreur
else{
$this->error = ManagerError::PermissionError;
return false;
}
/* [4] Verification des droits parmi les permissions donnees
=========================================================*/
/* (1) On recupere la liste des permissions possibles */
$permissions = $method['permissions'];
/* (2) Si aucune permission n'est definie, on laisse l'acces */
if( count($permissions) == 0 ) return true;
/* (3) On verifie qu'il y a au moins une permission ok */
foreach($permissions as $permission)
if( in_array($permission, $local_permissions) ) return true;
/* [5] On retourne FAUX si aucun droit n'a ete trouve
=========================================================*/
$this->error = ManagerError::PermissionError;
return false;
}
/* VERIFICATION DU TYPE DES PARAMETRES ENVOYES
*
* @params<Array> Tableau associatif contenant les parametres
* @params peut se voir rajouter les paramètres optionnels s'ils ne sont pas renseignés (initialisés à NULL)
*
* @return correct<bool> Retourne si oui ou non les parametres ont le bon type
*
*/
private function checkParams(&$params){
/* [1] On verifie qu'il ne manque aucun parametre
=========================================================*/
// Si @params n'est pas un tableau
if( !is_array($params) ) return false;
$method = $this->modules[$this->path['module']][$this->path['method']];
/* [2] Si le type est defini, pour chaque param, on teste
=========================================================*/
foreach($method['parameters'] as $name=>$paramsdata){
/* (1) On récupère si le paramètre est optionnel ou pas */
$optional = isset($paramsdata['optional']) && $paramsdata['optional'] === true;
/* (2) Récupère si le paramètre est un fichier et définit comme de type 'FILE' */
$isFile = isset($paramsdata['type']) && $paramsdata['type'] == 'FILE' && isset($_FILES[$name]);
/* (3) Si le paramètre est obligatoire et qu'il n'est pas donné -> erreur */
if( !isset($params[$name]) && !$optional && !$isFile )
return false;
/* (4) Si le type n'est pas defini, on a pas besoin de le vérifier */
if( !isset($paramsdata['type']) )
continue;
/* (5) Si le paramètre est optionnel et n'est pas donné */
if( $isFile || $optional && (!isset($params[$name]) || is_null($params[$name])) ){
// On le crée le param optionnel avec la valeur NULL
$params[$name] = null;
// On donne une référence vers le fichier, si c'en est un
if( $isFile )
$params[$name] = &$_FILES[$name];
continue; // On passe au paramètre suivant
/* (6) Si le paramètre est renseigné */
}else
// Si la verification est fausse, on retourne faux
if( !Database::check($paramsdata['type'], $params[$name]) )
return false;
}
/* [3] Gestion du retour, si tout s'est bien passe
=========================================================*/
return true;
}
/* AJOUT DES OPTIONS A PARTIR DE LA CONFIGURATION
*
*/
private function buildOptions(){
/* [0] On récupère les options de la méthode en cours
=========================================================*/
$method = $this->modules[$this->path['module']][$this->path['method']];
/* (1) Si 'option' n'est pas défini (ou incorrect), on met les valeurs par défaut */
if( !isset($method['options']) || !is_array($method['options']) )
return true;
/* (2) Par défaut on définit les options par défaut */
$this->options = self::$default_options;
/* (3) On récupère les options données */
$options = $method['options'];
/* [1] Gestion des différentes options
=========================================================*/
foreach($options as $option=>$value){
/* (1) On ne prend en compte l'option que si elle est dans les options par défaut */
if( !isset(self::$default_options[$option]) )
continue;
/* (2) Le type de la valeur doit être le même que celui de la valeur par défaut */
if( gettype($value) != gettype(self::$default_options[$option]) )
continue;
/* (3) Si tout est bon, on définit la valeur */
$this->options[$option] = $value;
}
return true;
}
/* RENVOI LE CHEMIN D'AMORCAGE DE LA METHODE /* RENVOI LE CHEMIN D'AMORCAGE DE LA METHODE
* *
* @return path<Array> Retourne le chemin d'amorcage de la requete * @return path<Array> Retourne le chemin d'amorcage de la requete
@ -256,4 +546,4 @@
} }
?> ?>

View File

@ -1,20 +1,20 @@
<?php <?php
namespace manager; namespace manager;
// FORMAT:
// // FORMAT:
//
// path: "nomModule/nomMethode" // path: "nomModule/nomMethode"
// data1: {donnee1} // data1: {donnee1}
// data2: {donnee2} // data2: {donnee2}
// ... // ...
// //
// //
// //
// //
class ModuleAnswer{ class ModuleResponse{
// Attributs prives utiles (initialisation) // Attributs prives utiles (initialisation)
private $data; private $data;
@ -136,8 +136,20 @@
*/ */
public function serialize(){ public function serialize(){
// Code Http
ManagerError::setHttpCode($this->error);
// Type de contenu
// header('Content-Type: application/json');
// On rajoute l'erreur au message // On rajoute l'erreur au message
$returnData = array_merge( array('ModuleError' => $this->error), $this->data ); $returnData = array_merge(
array(
'ModuleError' => $this->error,
'ErrorDescription' => ManagerError::explicit($this->error)
),
$this->data
);
return json_encode($returnData); return json_encode($returnData);
@ -147,4 +159,4 @@
} }
?> ?>

View File

@ -1,18 +1,18 @@
<?php <?php
namespace manager; namespace manager;
// FORMAT:
// // FORMAT:
//
// path: "nomModule/nomMethode" // path: "nomModule/nomMethode"
// data1: {donnee1} // data1: {donnee1}
// data2: {donnee2} // data2: {donnee2}
// ... // ...
// //
// //
// //
// //
class Repo{ class Repo{
@ -54,7 +54,7 @@
=========================================================*/ =========================================================*/
// Modules specifies // Modules specifies
$this->repositories = json_decode( ResourceDispatcher::getResource(self::$config_path), true ); $this->repositories = json_decode( ResourceDispatcher::getResource(self::$config_path), true );
// Gestion de l'erreur de parsage // Gestion de l'erreur de parsage
if( $this->repositories == null ){ if( $this->repositories == null ){
$this->error = ManagerError::ParsingFailed; $this->error = ManagerError::ParsingFailed;
@ -72,7 +72,7 @@
} }
// Type de @data (optionnel) // Type de @data (optionnel)
$data = (is_array($data)) ? $data : array(); $data = (is_array($data)) ? $data : array();
/* [2] Verification du chemin (existence repo+methode) /* [2] Verification du chemin (existence repo+methode)
@ -165,7 +165,7 @@
$this->error = ManagerError::UnknownMethod; $this->error = ManagerError::UnknownMethod;
return false; // On retourne FALSE, si erreur return false; // On retourne FALSE, si erreur
} }
/* [4] Enregistrement du chemin et renvoi de SUCCESS /* [4] Enregistrement du chemin et renvoi de SUCCESS
@ -194,4 +194,4 @@
} }
?> ?>

View File

@ -1,11 +1,33 @@
<?php <?php
// On definit la racine __ROOT__ si c'est pas deja fait /* [0] On definit la racine __ROOT__ si c'est pas deja fait
=========================================================*/
if( !defined('__ROOT__') ) define('__ROOT__', dirname(dirname(__FILE__)) ); if( !defined('__ROOT__') ) define('__ROOT__', dirname(dirname(__FILE__)) );
/* [1] On définit __SERVER_HOST__ et __SERVER_ROOT__ si c'est pas déja fait
=========================================================*/
if( !defined('__SERVER_HOST__') || !defined('__SERVER_ROOT') ){
/* (1) On charge le fichier de configuration */
$json = json_decode( file_get_contents(__ROOT__.'/config/server.json'), true );
// Si pas d'erreur, on définit
if( !is_null($json) ){
/* (2) Gestion de la config si server local ou remote */
if( !isset($_SERVER['SERVER_NAME']) || !checkdnsrr($_SERVER['SERVER_NAME'], 'NS') )
$config = $json['local'];
else
$config = $json['remote'];
/* (3) Création des constantes */
define('__SERVER_HOST__', $config['host']);
define('__SERVER_ROOT__', $config['root']);
}
}
@ -22,28 +44,6 @@
/* APPEL DYNAMIQUE DES CLASSES PASSEES EN PARAMETRE
*
* @classes<Array> Tableau contenant le nom des classes
*
*/
function autoload($classes){
foreach($classes as $class){
$name_only = substr(strrchr($class, '\\'), 1);
var_dump('use '.$class.' as '.$name_only.';');
eval('use '.$class.' as '.$name_only.';');
}
}
/* AUTOLOADER /* AUTOLOADER
* *
* @className<String> Nom de la classe appelee * @className<String> Nom de la classe appelee
@ -63,7 +63,7 @@
require_once $path; // on inclue le fichier require_once $path; // on inclue le fichier
} }
// On definit l'autoloader comme autoloader (obvious) // On definit l'autoloader comme autoloader (obvious)
spl_autoload_register('autoloader', false, true); spl_autoload_register('autoloader', false, true);
@ -73,4 +73,15 @@
/* On demarre la session securisee PHP /* On demarre la session securisee PHP
=========================================================*/ =========================================================*/
\manager\sessionManager::session_start(); \manager\sessionManager::session_start();
?>
/* [3] Gestion des droits des utilisateurs
=========================================================*/
/* (1) Retourne si l'utilisateur est connecte ou non */
function connected(){ return isset($_SESSION['permission']) && count($_SESSION['permission']) > 0; }
/* (2) Retourne si l'utilisateur a le status en question */
function permission($type){ return connected() && in_array($type, $_SESSION['permission']); }
?>

116
manager/repo/parentRepo.php Normal file
View File

@ -0,0 +1,116 @@
<?php
namespace manager\repo;
use \manager\Database;
class parentRepo{
// mise à jour du nom de la table (pour les enfants)
protected static function table_name(){ static $table_name = null; return $table_name; }
/* GESTION DES GETTERS dynamiques
*
* @method<String> Nom du getter du type 'getAll' ou 'getX' avec 'X' une colonne de la table en question
* @args<Array> Liste des arguments, $args[0] est la valeur du getter (sauf pour 'getAll')
*
* @return lines<Array> Retourne le résultat du fetchAll()
*
*/
public static function __callStatic($method, $args){
// Si static::table_name() NULL
if( is_null(static::table_name()) ) return false;
/* [1] On vérifie que la méthode est 'getX', avec X une chaine
=========================================================*/
// Si c'est pas le bon format, on retourne une erreur
if( !preg_match('/^get(?:By(\w+)|(All))$/', $method, $matches) ) return false;
/* [2] On charge la liste des colonnes de la table
=========================================================*/
$getColumns = Database::getPDO()->query('SHOW COLUMNS FROM '.static::table_name());
$cols = Database::delNumeric( $getColumns->fetchAll() );
$table_columns = array(
'_PRIMARY_' => array() // Contiendra les champs de la clé primaire
);
// On ajoute la liste des colonnes
foreach($cols as $column){
// On enregistre la clé primaire (si elle l'est)
if( $column['Key'] == 'PRI' ) array_push($table_columns['_PRIMARY_'], $column['Field']);
array_push($table_columns, $column['Field']);
}
/* [3] On vérifie que la valeur après 'get' est dans $table_columns
=========================================================*/
$columnName = strtolower($matches[1]);
$getAll = count($matches) > 2; // Si 'getAll'
$getById = $columnName == 'id';
$getSomething = count($args) > 0 && in_array($columnName, $table_columns); // Si 'getX', et 'X' dans la liste des colonnes
// Si ni 'getAll' ni 'getSomething' -> erreur
if( !$getById && !$getAll && !$getSomething ) return false;
/* [4] On rédige la requête
=========================================================*/
$getRequestString = 'SELECT * FROM '.static::table_name();
// Si c'est 'getById', on ajoute une condition (clé primaire)
if( $getById ){
// S'il manque un paramètre, on retourne une erreur
if( count($args) < count($table_columns['_PRIMARY_']) )
return false;
// Pour chaque clé primaire (si elle est composée)
foreach($table_columns['_PRIMARY_'] as $i=>$primary_column)
// Première ligne
if( $i == 0 ) $getRequestString .= ' WHERE '.$table_columns['_PRIMARY_'][$i].' = :primary'.$i;
// Lignes suivantes
else $getRequestString .= ' AND '.$table_columns['_PRIMARY_'][$i].' = :primary'.$i;
// Si c'est 'getSomething', on ajoute une condition
}else if( $getSomething )
$getRequestString .= ' WHERE '.$columnName.' = :value';
$getRequestString .= ' ORDER BY 1 ASC';
// On prépare la requête
$getRequest = Database::getPDO()->prepare($getRequestString);
/* [5] On exécute la requête
=========================================================*/
// Si 'getById', on compose la clé primaire
if( $getById ){
$pdo_vars = array();
foreach($table_columns['_PRIMARY_'] as $i=>$primary_column)
$pdo_vars[':primary'.$i] = $args[$i];
$getRequest->execute( $pdo_vars );
// Si 'getSomething', on ajoute le champ
}else
$getRequest->execute(array(
':value' => ($getSomething||$getById) ? $args[0] : null
));
/* [6] On récupère le résultat
=========================================================*/
return Database::delNumeric( $getRequest->fetchAll() );
}
}
?>

View File

@ -26,7 +26,7 @@
// On definit l'id session si donne en argument // On definit l'id session si donne en argument
if( $session_id != null ) if( $session_id != null )
session_id( $session_id ); session_id( $session_id );
// Precaution: on met a jour le cookie // Precaution: on met a jour le cookie
setcookie('PHPSESSID', session_id(), time()+60*30 ); setcookie('PHPSESSID', session_id(), time()+60*30 );
@ -45,7 +45,7 @@
/*******************/ /*******************/
private static function update_token(){ private static function update_token(){
$token = self::$prefix.self::secure_sha1(uniqid()); $token = self::$prefix.self::secure_sha1(uniqid());
// On definit le token en session // On definit le token en session
$_SESSION['session_token'] = $token; $_SESSION['session_token'] = $token;
@ -53,11 +53,17 @@
$_COOKIE['session_token'] = $_SESSION['session_token']; $_COOKIE['session_token'] = $_SESSION['session_token'];
setcookie('session_token', $_COOKIE['session_token'], time()+60*30 ); setcookie('session_token', $_COOKIE['session_token'], time()+60*30 );
} }
/************/ /************/
/* AMORCEUR */ /* AMORCEUR */
/************/ /************/
public static function session_start(){ public static function session_start(){
// \session_start();
// return;
/* [1] Génération et Gestion des donnees a utiliser /* [1] Génération et Gestion des donnees a utiliser
==============================================================*/ ==============================================================*/
// On genere le hash a partir des donnees personnelles // On genere le hash a partir des donnees personnelles
@ -79,16 +85,16 @@
\session_start(); \session_start();
// On verifie l'id session (5 premiers chars du hash des donnees perso) // On verifie l'id session (5 premiers chars du hash des donnees perso)
$valid_sessid = strpos( session_id(), substr(self::$prefix,0,5) ) === 0; $valid_sessid = strpos( session_id(), substr(self::$prefix,0,5) ) === 0;
// Si id session incorrect ou pas de token // Si id session incorrect ou pas de token
if( !$valid_sessid ) if( !$valid_sessid )
self::reset_session( $sessid ); // On initialise la session (bon id session) self::reset_session( $sessid ); // On initialise la session (bon id session)
// si id session invalide // si id session invalide
/* [3] Verification du token /* [3] Verification du token
==============================================================*/ ==============================================================*/
// On verifie que le token est valide // On verifie que le token est valide

12
test/ajaxTest.php Normal file
View File

@ -0,0 +1,12 @@
<?php define('__ROOT__', dirname(dirname(__FILE__)) );
require_once __ROOT__.'/manager/autoloader.php';
debug();
// DEFAULT SESSION CREDENTIALS
echo '{"data1": "'.session_id().'",';
echo '"data2": "'. ( $_SESSION['session_token']==$_COOKIE['session_token'] ? 'YES' : 'NO' ). '"}';
?>

View File

@ -1,4 +1,4 @@
<?php define('__ROOT__', dirname(__FILE__) ); <?php define('__ROOT__', dirname(dirname(__FILE__)) );
require_once __ROOT__.'/manager/autoloader.php'; require_once __ROOT__.'/manager/autoloader.php';
use \manager\ModuleRequest; use \manager\ModuleRequest;
@ -167,7 +167,7 @@
/* TEST DU DISPATCHER DES MANAGERS /* TEST DU DISPATCHER DES MANAGERS
* *
* @return nomRetour<typeRetour> Description du retour * @return nomRetour<typeRetour> Description du retour
*/ */
function testModuleDispatcher(){ function testModuleDispatcher(){
@ -189,7 +189,7 @@
/* TEST DU DISPATCHER DES REPO /* TEST DU DISPATCHER DES REPO
* *
* @return nomRetour<typeRetour> Description du retour * @return nomRetour<typeRetour> Description du retour
*/ */
function testRepoDispatcher(){ function testRepoDispatcher(){
@ -305,4 +305,4 @@
// new ResourceDispatcher('f/svg/search/st/sub-menu-side/ff0000', true); // new ResourceDispatcher('f/svg/search/st/sub-menu-side/ff0000', true);
?> ?>

53
test/sessionTest.php Normal file
View File

@ -0,0 +1,53 @@
<?php define('__ROOT__', dirname(dirname(__FILE__)) );
require_once __ROOT__.'/manager/autoloader.php';
debug();
// DEFAULT SESSION CREDENTIALS
var_dump( 'SESSID---'.session_id() );
var_dump( 'TOKEN----'.( $_SESSION['session_token']==$_COOKIE['session_token'] ? 'YES' : 'NO' ) );
?>
<div id=ajax1>NO VALUE</div><br>
<div id=ajax2>NO VALUE</div>
<br><br><br><br>
<button id=testAjax>LOAD AJAX</button>
<script type='text/javascript'>
function pHandler(data){
var parsedData = JSON.parse(data);
document.getElementById('ajax1').innerHTML = parsedData.data1;
document.getElementById('ajax2').innerHTML = parsedData.data2;
}
function testAjax(){
var xhr; // object ajax
if(window.XMLHttpRequest) // IE7+, Firefox, Chrome, Opera, Safari
xhr = new XMLHttpRequest();
else // IE5, IE6
xhr = new ActiveXObject('Microsoft.XMLHttpRequest');
xhr.onreadystatechange = function(){
if( xhr.readyState == 4 ) // si la requête est terminée
if( [0,200].indexOf(xhr.status) > -1 ) // si fichier existe et reçu
pHandler(xhr.responseText);
else // si code d'erreur retourne null
pHandler();
}
xhr.open( 'POST', '/test/ajaxTest.php', true );
xhr.send();
}
document.getElementById('testAjax').onclick = testAjax;
</script>

10
todo.md
View File

@ -135,7 +135,7 @@
- [x] [view/][view] Ajout de "use CLASS;" - [x] [view/][view] Ajout de "use CLASS;"
- [x] Ajout de "use CLASS;" dans les fichiers pour simplifier la lisibilite - [x] Ajout de "use CLASS;" dans les fichiers pour simplifier la lisibilite
- [x] [phpunit/sessionManager] test unitaires du manager de session php - [x] [phpunit/sessionManager] test unitaires du manager de session php
- [x] [ModuleAnswer] Gestion des erreurs au niveau interne des Modules - [x] [ModuleResponse] Gestion des erreurs au niveau interne des Modules
- [x] [autoloader][phpunit/bootstrap.php] Correction des bugs de $_SERVER avec PHPUnit -> autoloader + bootstrap personnalise - [x] [autoloader][phpunit/bootstrap.php] Correction des bugs de $_SERVER avec PHPUnit -> autoloader + bootstrap personnalise
- [x] [sessionManager] Import de sessionManager - [x] [sessionManager] Import de sessionManager
- [x] [phpunit/tests/Database_*] Tests unitaire de delNumeric() - [x] [phpunit/tests/Database_*] Tests unitaire de delNumeric()
@ -156,8 +156,8 @@
- [x] [view/*.php] Modification des views - [x] [view/*.php] Modification des views
- [x] Mise a jour / Modification / Correction des images du menu-side - [x] Mise a jour / Modification / Correction des images du menu-side
- [x] [ModuleRequest->dispatch] Passage de l'erreur a la reponse - [x] [ModuleRequest->dispatch] Passage de l'erreur a la reponse
- [x] [ModuleAnswer->serialize] Integration de l'erreur dans la serialisation - [x] [ModuleResponse->serialize] Integration de l'erreur dans la serialisation
- [x] [ModuleAnswer->get+getAll] Accesseurs aux donnees de la reponse - [x] [ModuleResponse->get+getAll] Accesseurs aux donnees de la reponse
- [x] Gestion des erreurs - [x] Gestion des erreurs
- [x] [ModuleError::explicit] Explicitation - [x] [ModuleError::explicit] Explicitation
- [x] Conception du systeme de delegation des managers - [x] Conception du systeme de delegation des managers
@ -165,8 +165,8 @@
- [x] [ModuleRequest->__construct] Inline (en php) - [x] [ModuleRequest->__construct] Inline (en php)
- [x] [ModuleRequest::fromString] Serialise (en json <String>) - [x] [ModuleRequest::fromString] Serialise (en json <String>)
- [x] [ModuleRequest::FromURL] Par url (POST) - [x] [ModuleRequest::FromURL] Par url (POST)
- [x] [ModuleAnswer] Module Answer - [x] [ModuleResponse] Module Answer
- [x] [ModuleAnswer->serialize] Serialisation pour renvoi - [x] [ModuleResponse->serialize] Serialisation pour renvoi
- [x] [index.php] Gestion de url/api avec donnees POST - [x] [index.php] Gestion de url/api avec donnees POST
- [x] [ModuleRequest->getFunctionCaller] Correction semantique du chemin d'amorcage, utilisation de tableau - [x] [ModuleRequest->getFunctionCaller] Correction semantique du chemin d'amorcage, utilisation de tableau
- [x] Gestion des erreurs - [x] Gestion des erreurs

View File

@ -54,7 +54,7 @@
echo "<section data-sublink='view' class='list'>"; echo "<section data-sublink='view' class='list'>";
// echo 'Liste des utilisateurs: <br>'; // echo 'Liste des utilisateurs: <br>';
// si erreur, on affiche l'explicitation // si erreur, on affiche l'explicitation
if( $answer->error != ManagerError::Success ){ if( $answer->error != ManagerError::Success ){
// var_dump( ManagerError::explicit($answer->error) ); // var_dump( ManagerError::explicit($answer->error) );
@ -72,14 +72,14 @@
foreach( $answer->get('machines') as $machine){ foreach( $answer->get('machines') as $machine){
$clusters = new Repo('machine/getClusters', array($machine['id_machine'])); $clusters = new Repo('machine/getClusters', array($machine['id_machine']));
$clusters = $clusters->answer(); $clusters = $clusters->answer();
echo "<article class='inline-box' id='".$machine['id_machine']."'>"; echo "<article class='inline-box' id='".$machine['id_machine']."'>";
// Nom de la machine // Nom de la machine
echo "<span class='title'>#".$machine['name']."</span>"; echo "<span class='title'>#".$machine['name']."</span>";
// Icone vers la suppression // Icone vers la suppression
echo "<span class='link_remove' data-machine='".$machine['id_machine']."'>"; echo "<span class='link_remove' data-machine='".$machine['id_machine']."'>";
echo ResourceDispatcher::getResource('f/svg/remove/st/sub-menu-side'); echo ResourceDispatcher::getResource('f/svg/remove/st/sub-menu-side');
echo "</span>"; echo "</span>";
@ -91,12 +91,12 @@
// Code RFID // Code RFID
echo "<span class='code'>"; echo "<span class='code'>";
echo ResourceDispatcher::getResource('f/svg/card/st/container'); echo ResourceDispatcher::getResource('f/svg/card/st/container');
echo "<span>"; echo "<span>";
echo $machine['code']; echo $machine['code'];
echo "</span>"; echo "</span>";
@ -105,7 +105,7 @@
// Groupes de la machine // Groupes de la machine
echo "<span class='groups'>"; echo "<span class='groups'>";
echo ResourceDispatcher::getResource('f/svg/group/st/container'); echo ResourceDispatcher::getResource('f/svg/group/st/container');
if( $clusters != false ) if( $clusters != false )
foreach($clusters as $cluster) foreach($clusters as $cluster)
echo "<span>".$cluster['name']."</span>"; echo "<span>".$cluster['name']."</span>";
@ -163,7 +163,7 @@
// Indice du resultat // Indice du resultat
echo "<span class='remove_search_view'>machine <span class='remove_search_num'>0</span> sur <span class='remove_search_sum'>0</span></span><br><br>"; echo "<span class='remove_search_view'>machine <span class='remove_search_num'>0</span> sur <span class='remove_search_sum'>0</span></span><br><br>";
echo "<button id='remove_search_submit' class='search'>Trouver</button><br>"; echo "<button id='remove_search_submit' class='search'>Trouver</button><br>";
echo "<br><br><hr class='OR' data-label='PUIS' /><br><br>"; echo "<br><br><hr class='OR' data-label='PUIS' /><br><br>";
echo "<input id='remove_code' type='text' placeholder='CO-DE-RF-ID'><br>"; echo "<input id='remove_code' type='text' placeholder='CO-DE-RF-ID'><br>";
@ -194,9 +194,9 @@
// Indice du resultat // Indice du resultat
echo "<span class='edit_search_view'>machine <span class='edit_search_num'>0</span> sur <span class='edit_search_sum'>0</span></span><br><br>"; echo "<span class='edit_search_view'>machine <span class='edit_search_num'>0</span> sur <span class='edit_search_sum'>0</span></span><br><br>";
echo "<button id='edit_search_submit' class='search'>Trouver</button><br>"; echo "<button id='edit_search_submit' class='search'>Trouver</button><br>";
echo "<br><br><hr class='OR' data-label='PUIS' /><br><br>"; echo "<br><br><hr class='OR' data-label='PUIS' /><br><br>";
echo "<input id='edit_code' type='text' placeholder='Code'><br>"; echo "<input id='edit_code' type='text' placeholder='Code'><br>";
echo "<input id='edit_name' type='text' placeholder='Name'><br>"; echo "<input id='edit_name' type='text' placeholder='Name'><br>";
echo "<button id='edit_submit' disabled>Modifier</button>"; echo "<button id='edit_submit' disabled>Modifier</button>";