| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950 | 
							- <?php
 
- function secondToTime($seconds) {
 
- 	$t = round($seconds);
 
- 	return sprintf('%02d:%02d:%02d', ($t/3600),($t/60%60), $t%60);
 
- }
 
- function app_autoloader($class_name) {
 
- 	$roots = array(__ROOT__.'class');
 
- 	require_once(__ROOT__.'class'.SLASH.'Plugin.class.php');
 
- 	Plugin::callHook('class_root',array(&$roots));
 
- 	foreach ($roots as $root) {
 
- 		if(file_exists($root.SLASH.$class_name.'.class.php')){
 
- 	    	require_once($root.SLASH.$class_name.'.class.php');
 
- 	    	break;
 
- 		}
 
- 	}
 
- }
 
- function errorToException( $errno, $errstr, $errfile, $errline, $errcontext) {
 
- 	throw new ErrorException($errstr, 0, $errno, $errfile, $errline);   
 
- }
 
- function unhandledException($ex){
 
- 	global $myUser,$_;
 
- 	$source = 'ui';
 
- 	if(isset($_SERVER['SCRIPT_NAME']) && $_SERVER['SCRIPT_NAME'] == '/action.php') $source = 'action';
 
- 	if(php_sapi_name()=='cli') $source = 'shell';
 
- 	
 
- 	$error = array();
 
- 	$error['code'] = $ex->getCode();
 
- 	$error['message'] = $ex->getMessage();
 
- 	$error['file'] = $ex->getFile();
 
- 	$error['line'] = $ex->getLine();
 
- 	$error['trace'] = $ex->getTraceAsString();
 
- 	$debugLink ='';
 
- 	if(isset($_SERVER['SERVER_NAME']) && $_SERVER['SERVER_NAME']=='127.0.0.1') $debugLink = exception_link($ex);
 
- 	$advanced = (isset($myUser) && $myUser->superadmin) || (isset($_SERVER['HTTP_HOST']) && $_SERVER['HTTP_HOST']== '127.0.0.1');
 
- 	switch($source){
 
- 		case 'ui':
 
- 			$response = '';
 
- 			//Récuperation de la requete échouée si l'utilisateur n'est pas authentifié
 
- 			switch($ex->getCode()){
 
- 				 case 401:
 
- 			        $_SESSION['last_request'] = $_SERVER['REQUEST_URI'];
 
- 			        if(isset($_SESSION['logout_redirect'])){
 
- 			        	echo '<script type="text/javascript">window.location="'.$_SESSION['logout_redirect'].'";</script>';
 
- 			        }
 
- 			        echo '<div id="message" class="alert alert-info"><strong>Connexion requise : </strong><span>'.$error['message'];
 
- 			        echo '<br> Pour vous connecter, cliquez sur le menu "Connexion" en haut à droite de cet écran';
 
- 			        echo '</span></div>';
 
- 			    break;
 
- 			    default: 
 
- 			    	 $response = '<div "id="message" class="d-block alert alert-danger m-3">';
 
- 					$response .= '<a style="color:inherit;text-decoration:none;" class="d-block" href="'.$debugLink.'">';
 
- 					
 
- 					
 
- 					if($advanced && isset($_['action']))  $response .= '<strong>Action : </strong><span>'.$_['action'].'</span><br>';
 
- 			       
 
- 			        $response .= '<strong>Erreur : </strong><span>'.$error['message'].'</span>';
 
- 			        $response .= '</a>';
 
- 			        if($advanced){
 
- 			        	$response .= '<small style="opacity:0.8;">'.$error['file'].' <strong>L'.$error['line'].'</strong><pre class="mb-0">';
 
- 			 			$response .= exception_trace($ex);
 
- 			        	$response .= '</pre></small>';
 
- 			        }
 
- 			        $response .= '</div>';
 
- 			    break;
 
- 			}
 
- 			echo $response;
 
- 			require_once(__DIR__.SLASH.'footer.php');
 
- 		break;
 
- 		case 'shell':
 
- 			$response = PHP_EOL.str_repeat('-',100).PHP_EOL." \033[31m ERREUR : \033[0m ".$ex->getFile()." L\033[33m".$ex->getLine()."\033[0m".PHP_EOL.'  '."\033[94m".$ex->getMessage()."\033[0m".PHP_EOL.str_repeat('-',100).PHP_EOL;
 
- 			echo $response;
 
- 		break;
 
- 		case 'action':
 
- 			$error['error'] = $error['message'];
 
- 			$response = json_encode($error);
 
- 			echo $response;
 
- 		break;
 
- 		default:
 
- 			$response = '[Erreur '.$error['code'].'] '.$error['file'].' L'.$error['line'].PHP_EOL.$error['message'].PHP_EOL.$error['trace'];
 
- 			echo $response;
 
- 		break;
 
- 	}
 
- 	exit();
 
- }
 
- function get_OS(){
 
- 	return strtoupper(substr(PHP_OS, 0, 3));
 
- }
 
- function OS_path_max_length(){
 
- 	switch(get_OS()){
 
- 		case 'WIN':
 
- 			return 259;
 
- 		break;
 
- 		default:
 
- 			return 4096;
 
- 		break;
 
- 	}
 
- }
 
- function OS_element_max_length(){
 
- 	switch(get_OS()){
 
- 		case 'WIN':
 
- 			return 255;
 
- 		break;
 
- 		default:
 
- 			return 255;
 
- 		break;
 
- 	}
 
- }
 
- function exception_link($ex,$type = 'exception'){
 
- 	if($type=='exception'){
 
- 		$filePath = $ex->getFile();
 
- 		$line = $ex->getLine();
 
- 	}else if($type=='trace'){
 
- 		$filePath = isset($ex['file']) ? $ex['file'] :  '';
 
- 		$line = isset($ex['line'])  ? $ex['line']:  '';
 
- 	}
 
- 	$filePath = explode('/',$filePath);
 
- 	$filePath = implode('\\',$filePath);
 
- 	return 'w2d://'.base64_encode(
 
- 		json_encode(
 
- 			array(
 
- 		'action'=>'alias',
 
- 		'alias'=>'sublime',
 
- 		'arguments'=>$filePath.'":'.$line
 
- 			)
 
- 		)
 
- 	); 
 
- }
 
- function exception_trace($ex){
 
- 	$error = '';
 
- 	foreach($ex->getTrace() as $trace){
 
- 		$error .= '<hr class="my-1" /><a style="color:inherit;text-decoration:none;" href="'.exception_link($trace,'trace').'">'.str_replace(__ROOT__,'',(isset($trace['file']) ? $trace['file'] : 0 )).' <strong>L'.(isset($trace['line']) ? $trace['line'] : 0 ).'</strong>  - ';
 
- 		if(!empty($trace['class'])) $error .= $trace['class'];
 
- 		if(!empty($trace['type'])) $error .= $trace['type'];
 
- 		if(!empty($trace['function'])) $error .= $trace['function'];
 
- 		if(!empty($trace['args'])){
 
- 			$error .= '(';
 
- 			$stringArgs = array();
 
- 			foreach($trace['args'] as $arg){
 
- 				$stringArgs[]=gettype($arg).( in_array(gettype($arg),array('string','integer','double','boolean','null')) ? ' <strong>'.$arg.'</strong>': '');
 
- 			}
 
- 			$error .= implode(', ',$stringArgs);
 
- 			$error .= ')';
 
- 		}
 
- 		$error .= '</a>';
 
- 	}
 
- 	return $error;
 
- }
 
- function ip(){
 
- 	if(isset($_SERVER['HTTP_X_FORWARDED_FOR']))
 
- 		$ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
 
- 	elseif(isset($_SERVER['HTTP_CLIENT_IP']))
 
- 		$ip = $_SERVER['HTTP_CLIENT_IP'];
 
- 	else 
 
- 		$ip = isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] :'';
 
- 	return $ip;
 
- }
 
- //Check si l'url serveur est en HTTPS
 
- function is_url_securised(){
 
- 	//La verification de HTTP_X_FORWARDED_PROTO permet de gerer les reverse proxy qui font du https -> http
 
-     return (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO']=='https') || (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off');
 
- }
 
- //Définit le schéma d'URL à utiliser
 
- function define_url_scheme(){
 
-     return is_url_securised() ? 'https' : 'http';
 
- }
 
- function encode_uri($uri){
 
-     return preg_replace_callback("{[^0-9a-z_.!~*'();,/?:@&=+$#-]}i", function ($m) {
 
-         return sprintf('%%%02X', ord($m[0]));
 
-     }, $uri);
 
- }
 
- //Définit la racine des médias en
 
- //fonction du schéma d'URL (http ou https)
 
- function define_media_root(){
 
-     return is_url_securised() ? preg_replace('|http(s)?://|i',define_url_scheme().'://',ROOT_URL) : ROOT_URL;
 
- }
 
- function encrypt($data){
 
- 	$keyHash = md5(CRYPTKEY);
 
- 	$data = openssl_encrypt ($data,'aes256',$keyHash,true,'1234567812345678');
 
- 	return base64_encode($data);
 
- }
 
- function decrypt($data){
 
- 	$keyHash = md5(CRYPTKEY);
 
- 	$data = base64_decode($data);
 
- 	return openssl_decrypt ($data,'aes256',$keyHash,true,'1234567812345678');
 
- }
 
- //Génère un slug unique pour l'element de liste utilisable dans le code
 
- // $label  => string du label à slugifier
 
- // $column => la colonne en base où checker les slugs existants
 
- function generateSlug($label, $class, $column, $allowChars = '', $separator = '-'){
 
-     $slug = slugify($label,$allowChars,$separator);
 
-     $item = new $class();
 
-     if(!array_key_exists($column, $item->fieldMapping)) return;
 
-     $params = array_key_exists('state', $item->fieldMapping) ? array('state'=>$class::ACTIVE) : array();
 
-     $i='';
 
-     while($class::rowCount(array_merge(array($column=>($i==''?$slug:$slug.$separator.$i)), $params)) > 0) $i++;
 
-     return $i==''?$slug:$slug.$separator.$i;
 
- }
 
- function slugify($text,$allowChars = '', $separator='-') {
 
- 	setlocale(LC_CTYPE, 'fr_FR.UTF-8');
 
- 	try{
 
- 		$encoding = mb_detect_encoding($text, mb_detect_order(), false);
 
- 	    if($encoding == "UTF-8") $text = mb_convert_encoding($text, 'UTF-8', 'UTF-8'); 
 
- 	   
 
-     	$clean = iconv(mb_detect_encoding($text, mb_detect_order(), false), 'ASCII//TRANSLIT', $text);
 
- 	}catch(Exception $e){
 
- 		$clean =  $text;
 
- 	}
 
- 	$clean = normalize_chars($clean);
 
-    $clean = preg_replace("/[^a-zA-Z0-9\/_|+ -".preg_quote($allowChars)."]/", '', $clean);
 
-    $clean = strtolower(trim($clean, $separator));
 
-    $clean = preg_replace("/[\\".preg_quote(str_replace(str_split($allowChars),'','/_|+ -'))."]+/", $separator, $clean);
 
-    return $clean;
 
- }
 
- if(!function_exists('glob_recursive')) {
 
- 	// Does not support flag GLOB_BRACE        
 
- 	function glob_recursive($pattern, $flags = 0,$forbiddenPathes = array(),$root = null){
 
- 		$files = glob($pattern, $flags);
 
- 		foreach (glob(dirname($pattern).SLASH.'*', GLOB_ONLYDIR|GLOB_NOSORT) as $dir) {
 
- 			if(isset($root))
 
- 				if(in_array(str_replace($root,'',$dir), $forbiddenPathes)) continue;
 
- 			$files = array_merge($files, glob_recursive($dir.SLASH.basename($pattern), $flags,$forbiddenPathes,$root));
 
- 		}
 
- 		return $files;
 
- 	}
 
- }
 
- //Récupère la dernière clé d'un tableau
 
- //avec fallback pour versions de PHP < 7
 
- if (!function_exists("array_key_last")) {
 
-     function array_key_last($array) {
 
-         if (!is_array($array) || empty($array)) return NULL;
 
-         return array_keys($array)[count($array)-1];
 
-     }
 
- }
 
- //Récupère la première clé d'un tableau
 
- //avec fallback pour versions de PHP < 7
 
- if(!function_exists('array_key_first')) {
 
-     function array_key_first($array) {
 
-         $array = array_keys($array);
 
-         return isset($array[0]) ? $array[0] : NULL;
 
-     }
 
- }
 
- //Aplatit un tableau multidimensionnel
 
- //en un tableau à 1 seul niveau
 
- function array_flatten($array) {
 
- 	$return = array();
 
- 	foreach($array as $key => $value) {
 
- 		if(is_array($value)){ 
 
- 			$return = array_merge($return, array_flatten($value));
 
- 		} else {
 
- 			$return[$key] = $value;
 
- 		} 
 
- 	}
 
- 	return $return;
 
- }
 
- function array_map_recursive($callback, $array) {
 
- 	$func = function ($item) use (&$func, &$callback) {
 
- 		return is_array($item) ? array_map($func, $item) : call_user_func($callback, $item);
 
- 	};
 
- 	return array_map($func, $array);
 
- }
 
- //Même principe que le ORDER BY de MySQL
 
- //mais sur différentes clés d'un tableau
 
- //Auteur: jimpoz -> https://www.php.net/manual/fr/function.array-multisort.php#100534
 
- function array_orderby() {
 
- 	//Permet de récupérer les paramètres passés dynamiquement
 
- 	//Car on ne sait pas combien de paramètres on peut avoir
 
-     $args = func_get_args();
 
-     $data = array_shift($args);
 
-     foreach ($args as $n => $field) {
 
-         if (is_string($field)) {
 
-             $tmp = array();
 
-             foreach ($data as $key => $row)
 
-                 $tmp[$key] = $row[$field];
 
-             $args[$n] = $tmp;
 
-         }
 
-     }
 
-     $args[] = &$data;
 
-     call_user_func_array('array_multisort', $args);
 
-     return array_pop($args);
 
- }
 
- function secure_user_vars($var){
 
- 	if(is_array($var)){
 
- 		$array = array();
 
- 		foreach($var as $key=>$value):
 
- 			$array[secure_user_vars($key)] = secure_user_vars($value);
 
- 		endforeach;
 
- 		return $array;
 
- 	} else {
 
- 		return str_replace('&','&',htmlspecialchars($var, ENT_NOQUOTES, "UTF-8"));
 
- 	}
 
- }
 
- function base64_to_image($base64_string, $output_file) {
 
- 	$ifp = fopen($output_file, "wb"); 
 
- 	$data = explode(',', $base64_string);
 
- 	fwrite($ifp, base64_decode($data[1])); 
 
- 	fclose($ifp); 
 
- 	return $output_file; 
 
- }
 
- function getExt($file){
 
- 	$ext = explode('.',$file);
 
- 	return strtolower(array_pop($ext));
 
- }
 
- function get_gravatar($mail,$size = 100){
 
- 	return file_get_contents("http://www.gravatar.com/avatar/" . md5( strtolower( trim( $mail ) ) ) . "?&s=".$size);
 
- }
 
- function getExtIcon($ext){
 
- 	$icon = '';
 
- 	switch($ext){
 
- 		case '7z':
 
- 		case 'rar':
 
- 		case 'gz':
 
- 		case 'zip':
 
- 			$icon = 'far fa-file-archive text-warning';
 
- 		break;
 
- 		
 
- 		case 'php':
 
- 		case 'js':
 
- 		case 'py':
 
- 		case 'c':
 
- 		case 'cpp':
 
- 		case 'css':
 
- 		case 'h':
 
- 		case 'hpp':
 
- 		case 'html':
 
- 		case 'htm':
 
- 		case 'asp':
 
- 		case 'jsp':
 
- 			$icon = 'fas fa-file-code text-secondary text-warning';
 
- 		break;
 
- 		
 
- 		case 'xls':
 
- 		case 'xlsx':
 
- 		case 'xlsb':
 
- 		case 'csv':
 
- 			$icon = 'far fa-file-excel text-success';
 
- 		break;
 
- 		
 
- 		case 'bmp':
 
- 		case 'jpg':
 
- 		case 'jfif':
 
- 		case 'jpeg':
 
- 		case 'ico':
 
- 		case 'gif':
 
- 		case 'png':
 
- 		case 'svg':
 
- 			$icon = 'far fa-file-image text-info';
 
- 		break;
 
- 		
 
- 		case 'pdf':
 
- 			$icon = 'far fa-file-pdf text-danger';
 
- 		break;
 
- 		case 'ppt':
 
- 		case 'pptx':
 
- 			$icon = 'fa-file-powerpoint-o text-warning' ;
 
- 		break;
 
- 		
 
- 		case 'txt':
 
- 		case 'htaccess':
 
- 		case 'md':
 
- 			$icon = 'far fa-file-alt';
 
- 		break;
 
- 		
 
- 		case 'doc':
 
- 		case 'docx':
 
- 		case 'word':
 
- 			$icon = 'far fa-file-word text-primary';
 
- 		break;
 
- 		
 
- 		case 'avi':
 
- 		case 'wmv':
 
- 		case 'mov':
 
- 		case 'divx':
 
- 		case 'xvid':
 
- 		case 'mkv':
 
- 		case 'flv':
 
- 		case 'mpeg':
 
- 		case 'h264':
 
- 		case 'rmvb':
 
- 		case 'mp4':
 
- 			$icon = 'far fa-file-video text-secondary';
 
- 		break;
 
- 		
 
- 		case 'wav':
 
- 		case 'ogg':
 
- 		case 'ogv':
 
- 		case 'ogx':
 
- 		case 'oga':
 
- 		case 'riff':
 
- 		case 'bwf':
 
- 		case 'wma':
 
- 		case 'flac':
 
- 		case 'aac':
 
- 		case 'mp3':
 
- 			$icon = 'far fa-file-audio text-secondary';
 
- 		break;
 
- 		default:
 
- 			$icon = 'far fa-file';
 
- 		break;
 
- 	}
 
- 	return $icon;
 
- }
 
- function getExtContentType($ext){
 
- 	$cType = '';
 
- 	switch($ext){
 
- 		case '7z':
 
- 			$cType = 'application/x-7z-compressed';
 
- 		break;
 
- 		case 'rar':
 
- 			$cType = 'application/x-rar-compressed';
 
- 		break;
 
- 		case 'gz':
 
- 			$cType = 'application/x-gzip';
 
- 		break;
 
- 		case 'zip':
 
- 			$cType = 'application/zip';
 
- 		break;
 
- 		case 'xls':
 
- 			$cType = 'application/vnd.ms-excel';
 
- 		break;
 
- 		case 'xlsx':
 
- 			$cType = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet';
 
- 		break;
 
- 		case 'csv':
 
- 			$cType = 'text/csv';
 
- 		break;
 
- 		case 'jpg':
 
- 		case 'jpeg':
 
- 			$cType = 'image/jpeg';
 
- 		break;
 
- 		case 'bmp':
 
- 		case 'gif':
 
- 		case 'png':
 
- 			$cType = 'image/'.$ext;
 
- 		break;
 
- 		case 'ppt':
 
- 			$cType = 'application/vnd.ms-powerpoint';
 
- 		break;
 
- 		case 'pptx':
 
- 			$cType = 'application/vnd.openxmlformats-officedocument.presentationml.presentation';
 
- 		break;
 
- 		case 'pdf':
 
- 			$cType = 'application/pdf';
 
- 		break;
 
- 		case 'txt':
 
- 			$cType = 'text/plain';
 
- 		break;
 
- 		
 
- 		case 'doc':
 
- 		case 'word':
 
- 			$cType = 'application/msword';
 
- 		break;
 
- 		case 'docx':
 
- 			$cType = 'application/vnd.openxmlformats-officedocument.wordprocessingml.document';
 
- 		break;
 
- 		
 
- 		case 'aac':
 
- 		case 'wav':
 
- 			$cType = 'audio/'.$ext;
 
- 		break;
 
- 			$cType = 'audio/aac';
 
- 		break;
 
- 		case 'mp3':
 
- 			$cType = 'audio/mpeg3';
 
- 		break;
 
- 		case 'otf':
 
- 		case 'ttf':
 
- 		case 'woff':
 
- 		case 'woff2':
 
- 			$cType = 'font/'.$ext;
 
- 		break;
 
- 		default:
 
- 			$cType = 'application/octet-stream';
 
- 		break;
 
- 	}
 
- 	return $cType;
 
- }
 
- function max_upload_size($limits = array()){
 
- 	$limits[] = str_replace('M','',ini_get('post_max_size')) *1048576;
 
- 	$limits[] = str_replace('M','',ini_get('upload_max_filesize')) *1048576;
 
- 	return readable_size(min($limits));
 
- }
 
- function readable_size($bytes)
 
- {
 
- 	if(empty($bytes) || !is_numeric($bytes)) return '0 o';
 
- 	if($bytes<1024){
 
- 		return round(($bytes / 1024), 2).' o';
 
- 	}elseif(1024<$bytes && $bytes<1048576){
 
- 		return round(($bytes / 1024), 2).' ko';
 
- 	}elseif(1048576<=$bytes && $bytes<1073741824){
 
- 		return round(($bytes / 1024)/1024, 2).' Mo';
 
- 	}elseif(1073741824<=$bytes){
 
- 		return round(($bytes / 1024)/1024/1024, 2).' Go';
 
- 	}
 
- }
 
- function relative_time($date, $date2=null, $relativeLimit=null, $detailled=false){
 
- 	$from = new DateTime();
 
-     $from->setTimestamp($date);
 
-     $to = new DateTime("now");
 
-     if(isset($date2)) $to->setTimestamp($date2);
 
-     $intervalle = $from->diff($to);
 
-     if(isset($relativeLimit) && $intervalle->days > $relativeLimit){
 
-     	$limitFormat = $detailled ? 'd/m/Y - H:i' : 'd/m/Y';
 
-     	return date($limitFormat, $date);
 
-     }
 
-     $prefixe = $from > $to ? 'Dans ' :'Il y a ' ;
 
-     if(isset($date2)) $prefixe = '';
 
-     $years = $intervalle->format('%y');
 
-     $month = $intervalle->format('%m');
 
-     $days = $intervalle->format('%d');
 
-     $hours = $intervalle->format('%h');
 
-     $minutes = $intervalle->format('%i');
 
-     if ($years != 0) {
 
-         $relative_date = $prefixe . $years . ' an' . (($years > 1) ? 's' : '');
 
-         if ($month >= 6) $relative_date .= ' et demi';
 
-     } elseif ($month != 0) {
 
-         $relative_date = $prefixe . $month . ' mois';
 
-         if ($days >= 15) $relative_date .= ' et demi';
 
-     } elseif ($days != 0) {
 
-         $relative_date = $prefixe . $days . ' jour' . (($days > 1) ? 's' : '');
 
-     } elseif ($hours != 0) {
 
-         $relative_date = $prefixe . $hours . ' heure' . (($hours > 1) ? 's' : '');
 
-     } elseif ($minutes != 0) {
 
-         $relative_date = $prefixe . $minutes . ' minute' . (($minutes > 1) ? 's' : '');
 
-     } else {
 
-         $relative_date = $prefixe . ' quelques secondes';
 
-     }
 
-     return $relative_date;
 
- }
 
- function image_resize($image,$w,$h){
 
- 	$resource = imagecreatefromstring(file_get_contents($image));
 
- 	$size = getimagesize($image);
 
- 	$h = (($size[1] * (($w)/$size[0])));
 
- 	$thumbnail = imagecreatetruecolor($w , $h);
 
- 	imagecopyresampled($thumbnail ,$resource, 0,0, 0,0, $w, $h, $size[0],$size[1]);
 
- 	imagedestroy($resource);
 
- 	imagejpeg($thumbnail , $image, 100);
 
- }
 
- function arand($array){
 
- 	return $array[array_rand($array)];
 
- }
 
- //Convertis une date en timestamp 
 
- //(format possible dd-mm-yyyy ou dd/mm/yyyy)
 
- function timestamp_date($date){
 
- 	$date = explode('/',str_replace('-', '/', $date));
 
- 	if(count($date)!=3) return 0;
 
- 	$year = $date[2];
 
- 	$m = 0;
 
- 	$h = 0;
 
- 	if(strpos($year, ':')){
 
- 	    $yinfos = explode(' ',$year);
 
- 	    $year = $yinfos[0];
 
- 	    list($h,$m) = explode(':',$yinfos[1]);
 
- 	}
 
- 	return mktime($h,$m,0,$date[1],$date[0],$year);
 
- }
 
- //Convertis une heur en timestamp à partir du 01/01/1970
 
- //(format possible hh:mm)
 
- function timestamp_hour($hour){
 
- 	$hour = explode(':',$hour);
 
- 	if(count($hour)!=2) return 0;
 
- 	return mktime($hour[0],$hour[1],0,1,1,1970);
 
- }
 
- // Récupère la différence entre 2 dates
 
- // avec le format spécifique fourni en paramètres
 
- // On compare Date1 à Date2
 
- // (format possible)
 
- function format_date_diff($date1, $date2, $format='%a'){
 
- 	$datetime1 = date_create($date1);
 
- 	$datetime2 = date_create($date2);
 
- 	
 
- 	$interval = $datetime1->diff($datetime2);
 
- 	
 
- 	return $interval->format($format);
 
- }
 
- /**
 
-  * Normalise un tableau de filtres pour le composant Filter
 
-  * 
 
-  * $filters : Array => tableau des paramètres avancés au format
 
-  * array(
 
-  *   "jean",	//Mot clé de la recherche simple
 
-  * 	 array(
 
-  *    	'nom_de_votre_colonne:operateur' 	=> 'valeur_attendue',
 
-  *    	'join' 	=> 'and|or', //Facultatif
 
-  *   ),
 
-  *   etc... (à répéter pour les N critères)
 
-  * )
 
-  * Eg. :
 
-  *  filters_default(array(
 
-  *     "jean",
 
-  *     array(
 
-  *         'birth' => "17/09/1998",
 
-  *         'join' => 'or'
 
-  *     ),
 
-  *     array(
 
-  *         'phone:like' => "9754"
 
-  *     )
 
-  *  ));
 
-  */
 
- function filters_default($filters){
 
- 	$finalFilters = array();
 
- 	foreach ($filters as $filter) {
 
- 		//Gestion du keyword
 
- 		if(!is_array($filter) && !is_object($filter)){
 
- 			array_unshift($finalFilters, $filter);
 
- 			continue;
 
- 		}
 
- 		$tempFilter = array();
 
- 		foreach ($filter as $column => $value) {
 
- 			//Gestion du join
 
- 			if ($column == 'join') {
 
- 				$tempFilter['join'] = $value;
 
- 				continue;
 
- 			}
 
- 			//Gestion de la colonne ciblée avec opérator
 
- 			$column = explode(':', $column);
 
- 			$tempFilter['column'] = $column[0];
 
- 			if(isset($column[1])) $tempFilter['operator'] = $column[1];
 
- 			//Gestion de la value
 
- 			$tempFilter['value'] = $value;
 
- 		}
 
- 		if(!empty($tempFilter)) $finalFilters[] = $tempFilter;
 
- 	}
 
- 	return filters_set($finalFilters);
 
- }
 
- /**
 
-  * Normalise et contrôles sur un tableau
 
-  * de filtres pour le composant Filter.
 
-  * 
 
-  * $filters : Array => tableau des paramètres avancés au format
 
-  * array(
 
-  *   "jean",	//Mot clé de la recherche simple, peut aussi être nommée 'keyword' => "jean"
 
-  * 	 array(
 
-  *    	'column' 	=> 'nom_de_votre_colonne]',
 
-  *     	'operator' 	=> '=|!=|LIKE:<:>', 					//Facultatif => "=" par défaut
 
-  *      'value' 	=> 'valeur_attendue',					//Peut être du type array si plusieurs valeurs attendues
 
-  *      'join' 		=> 'and|or'								//Facultatif => "and" par défaut
 
-  *   ),
 
-  *   etc... (à répéter pour les N critères)
 
-  * )
 
-  * Eg. :
 
-  * filters_set(array(
 
-  * 	 'test',
 
-  *   array(
 
-  *   	'column' => 'login',
 
-  *   	'value'	 => 'admin'
 
-  *   )
 
-  * ));
 
-  */
 
- function filters_set($filters){
 
- 	if(!is_array($filters)) return array();
 
- 	$finalFilters = array(
 
- 		'k' => '',
 
- 		'a' => array()
 
- 	);
 
- 	foreach ($filters as $key => $filter) {
 
- 		if($key==="keyword" || (!is_array($filter)) ) {
 
- 			$finalFilters['k'] = $filter;
 
- 			continue;
 
- 		}
 
- 		if(isset($filter['group'])){
 
- 			$subfilters = filters_set($filter['group']);
 
- 			if(isset($subfilters['a'])) $finalFilters['a'][] = array('g'=>$subfilters['a']);
 
- 			continue;
 
- 		}
 
- 		if(!isset($filter['column']) || !isset($filter['value'])) continue;
 
- 		
 
- 		$filter['operator'] = isset($filter['operator']) ? $filter['operator'] : '=';
 
- 		$filter['operator'] = html_entity_decode($filter['operator']);
 
- 		if(!in_array(strtolower($filter['operator']), array('<','>','=','!=','like','not like','between','is null','is not null'))) continue;
 
- 		$tempFilter = array(
 
- 			"c" => $filter['column'], 
 
- 			"o" => $filter['operator'], 
 
- 			"v" => is_array($filter['value']) ? $filter['value'] : array($filter['value']), 
 
- 		);
 
- 		if(isset($filter['subcolumn'])) $tempFilter['s'] = $filter['subcolumn'];
 
- 		if(isset($filter['join'])){
 
- 			if(!in_array(strtolower($filter['join']), array('and','or'))) continue;
 
- 			$tempFilter['j'] = $filter['join'];
 
- 		}
 
- 		if(isset($filter['type'])) $tempFilter['t'] = $filter['type'];
 
- 		$finalFilters['a'][] = $tempFilter;
 
- 	}
 
- 	return $finalFilters;
 
- }
 
- //altère un fitlre de recherche avancée de façon personnalisée et récursive
 
- function filter_alteration($filters,$index,$mutator){
 
- 	foreach ($filters as $key => $value) {
 
- 		if(isset($value['group'])){
 
- 			$filters[$key]['group'] = filter_alteration($filters[$key]['group'],$index,$mutator);
 
- 		}else{
 
- 			if($value['column'] != $index) continue;
 
- 			$initialFilter = $filters[$key];
 
- 			$filters[$key] = $mutator($value);
 
- 			//Si la fonction d'alteration retourne null on supprime le filtre initial
 
- 			if($filters[$key] == null){
 
- 				//Gestion des joins, si le filtre supprimé avait un prédécesseur
 
- 				if(isset($filters[$key-1])){
 
- 					//si le filtre supprimé avait un join, on le transfere au prédécesseur
 
- 					if(isset($filters[$key+1]) && !empty($initialFilter['join']) ){
 
- 						$filters[$key-1]['join'] = $initialFilter['join'];
 
- 					//sinon on se content de supprimer le join du prédecesseur
 
- 					}else{
 
- 						unset($filters[$key-1]['join']);
 
- 					}
 
- 				}
 
- 				//suppression du filtre
 
- 				unset($filters[$key]);
 
- 			}
 
- 		}
 
- 	}
 
- 	return $filters;
 
- }
 
- // Construit une requete sécurisée pour le composant filtre
 
- function filter_secure_query($filters,$allowedColumns,&$query,&$data,$iteration = 0,$columnEscape="`"){
 
- 	if($iteration==0 && !empty($filters)) $query .= ' AND (';
 
- 	
 
- 	global $databases_credentials;
 
- 	$connector = $databases_credentials['local']['connector'];
 
- 	$operators = $connector::operators();
 
- 	$allowedOperators = array_keys($operators);
 
- 	foreach ($filters as $filter) {
 
- 		if(isset($filter['group'])){
 
- 			$query .= ' ( ';
 
- 			 filter_secure_query($filter['group'],$allowedColumns,$query,$data,$iteration+1);
 
- 			$query .= ' ) ';
 
- 		}else{
 
- 			$filter['operator'] = html_entity_decode($filter['operator']);
 
- 			if(!in_array($filter['column'], $allowedColumns)) throw new Exception("Colonne '".$filter['column']."' interdite", 400);
 
- 			if(!in_array(strtolower($filter['operator']), $allowedOperators)) return;
 
- 			if(isset($filter['join']) && !in_array(strtolower($filter['join']), array('and','or'))) return;
 
- 			if(!preg_match("/.*\..*/i", $filter['column']))
 
- 				$filter['column'] = $columnEscape.$filter['column'].$columnEscape;
 
- 			
 
- 			if(strtolower($filter['type']) == 'date' && isset($filter['value'])){
 
- 				$filter['column'] = 'UNIX_TIMESTAMP(STR_TO_DATE(DATE_FORMAT(FROM_UNIXTIME('.$filter['column'].'),"%d/%m/%Y"), "%d/%m/%Y"))';
 
- 				if(is_array($filter['value'])){
 
- 					foreach($filter['value'] as $j=>$value){
 
- 						$filter['value'][$j] = timestamp_date($value);
 
- 					}
 
- 				} else {
 
- 					$filter['value'] = timestamp_date($filter['value']);
 
- 				}
 
- 			}
 
- 			$operator = $operators[strtolower($filter['operator'])];
 
- 			if(is_string($operator['sql'])){
 
- 				$method = function($column,$value = null,&$query,&$data) use($operator){
 
- 					$query .= str_replace(array('{{column}}','{{value}}'),array($column,'?'),$operator['sql']);
 
- 					if(isset($value) && isset($value[0])) $data[] = $value[0];
 
- 				};
 
- 			}else{
 
- 				$method = $operator['sql'];
 
- 			}
 
- 			$query.=' ( ';
 
- 			$method($filter['column'],isset($filter['value'])?$filter['value']:null,$query,$data);
 
- 			$query.=' ) ';
 
- 			
 
- 		}
 
- 		if(isset($filter['join'])) $query .= ' '.$filter['join'].' ';
 
- 	}
 
- 	if($iteration==0 && !empty($filters)) $query .= ')';
 
- }
 
- //remplace {{column}} par les colonnes dans $available - les colonnes dans $_['columns']['unselected']
 
- function column_secure_query($columns,$_,&$query){
 
- 	$unselected = isset($_['columns']) && isset($_['columns']['unselected']) ? $_['columns']['unselected'] : array();
 
- 	$columns = array_diff($columns, $unselected);
 
- 	$query = str_replace('{{columns}}',implode(',',$columns),$query);
 
- }
 
- function sort_secure_query($sort,$allowedColumns,&$query){
 
- 	if(!in_array($sort['sortable'], $allowedColumns)) return;
 
- 	if(!in_array(strtolower($sort['sort']), array('asc','desc',''))) return;
 
- 	$query .= ' ORDER BY '.$sort['sortable'].' '.$sort['sort'];
 
- }
 
- function check_mail($mail){
 
- 	return ($mail && !empty($mail) && filter_var($mail, FILTER_VALIDATE_EMAIL));
 
- }
 
- function truncate($text, $length = 100, $options = array()) {
 
-     $default = array(
 
-         'ending' => '...',
 
-         'exact' => true,
 
-         'html' => false,
 
-         'keepTags' => true,
 
-     );
 
-     $options = array_merge($default, $options);
 
-     extract($options);
 
-     if ($html) {
 
-         if (mb_strlen(preg_replace('/<.*?>/', '', $text)) <= $length) {
 
-             return $text;
 
-         }
 
-         $totalLength = mb_strlen(strip_tags($ending));
 
-         $openTags = array();
 
-         $truncate = '';
 
-         preg_match_all('/(<\/?([\w+]+)[^>]*>)?([^<>]*)/', $text, $tags, PREG_SET_ORDER);
 
-         foreach ($tags as $tag) {
 
-             if (!preg_match('/img|br|input|hr|area|base|basefont|col|frame|isindex|link|meta|param/s', $tag[2])) {
 
-                 if (preg_match('/<[\w]+[^>]*>/s', $tag[0])) {
 
-                     array_unshift($openTags, $tag[2]);
 
-                 } else if (preg_match('/<\/([\w]+)[^>]*>/s', $tag[0], $closeTag)) {
 
-                     $pos = array_search($closeTag[1], $openTags);
 
-                     if ($pos !== false) {
 
-                         array_splice($openTags, $pos, 1);
 
-                     }
 
-                 }
 
-             }
 
-             $truncate .= $tag[1];
 
-             $contentLength = mb_strlen(preg_replace('/&[0-9a-z]{2,8};|&#[0-9]{1,7};|&#x[0-9a-f]{1,6};/i', ' ', $tag[3]));
 
-             if ($contentLength + $totalLength > $length) {
 
-                 $left = $length - $totalLength;
 
-                 $entitiesLength = 0;
 
-                 if (preg_match_all('/&[0-9a-z]{2,8};|&#[0-9]{1,7};|&#x[0-9a-f]{1,6};/i', $tag[3], $entities, PREG_OFFSET_CAPTURE)) {
 
-                     foreach ($entities[0] as $entity) {
 
-                         if ($entity[1] + 1 - $entitiesLength <= $left) {
 
-                             $left--;
 
-                             $entitiesLength += mb_strlen($entity[0]);
 
-                         } else {
 
-                             break;
 
-                         }
 
-                     }
 
-                 }
 
-                 $truncate .= mb_substr($tag[3], 0 , $left + $entitiesLength);
 
-                 break;
 
-             } else {
 
-                 $truncate .= $tag[3];
 
-                 $totalLength += $contentLength;
 
-             }
 
-             if ($totalLength >= $length) {
 
-                 break;
 
-             }
 
-         }
 
-     } else {
 
-         if (mb_strlen($text) <= $length) {
 
-             return $text;
 
-         } else {
 
-             $truncate = mb_substr($text, 0, $length - mb_strlen($ending));
 
-         }
 
-     }
 
-     if (!$exact) {
 
-         $spacepos = mb_strrpos($truncate, ' ');
 
-         if (isset($spacepos)) {
 
-             if ($html) {
 
-                 $bits = mb_substr($truncate, $spacepos);
 
-                 preg_match_all('/<\/([a-z]+)>/', $bits, $droppedTags, PREG_SET_ORDER);
 
-                 if (!empty($droppedTags)) {
 
-                     foreach ($droppedTags as $closingTag) {
 
-                         if (!in_array($closingTag[1], $openTags)) {
 
-                             array_unshift($openTags, $closingTag[1]);
 
-                         }
 
-                     }
 
-                 }
 
-             }
 
-             $truncate = mb_substr($truncate, 0, $spacepos);
 
-         }
 
-     }
 
-     $truncate .= $ending;
 
-     if ($html) {
 
-         foreach ($openTags as $tag) {
 
-             $truncate .= '</'.$tag.'>';
 
-         }
 
-     }
 
-     return (!$keepTags ? strip_tags($truncate) : $truncate);
 
- }
 
- /**
 
-  * Permet de tronquer un texte en fonction d'un
 
-  * nombre de caractères donné
 
-  * @param  string $content    le texte à tronquer
 
-  * @param  int $limit le nombre de caractères qu'on garde
 
-  * @param  string $limiter le caractère de remplacement de fin de chaine
 
-  * @return string            le texte final, tronqué
 
-  */
 
- function truncate_content($content,$limit,$limiter){
 
- 	if(strlen($content)>$limit) $content = mb_substr($content, 0,$limit).$limiter;
 
- 	return $content;
 
- }
 
- //Permet de décoder la chaîne d'entrée $string
 
- //en UTF-8 et de décoder les caractères spéciaux
 
- //pour l'affichage HTML
 
- function html_decode_utf8($string){
 
- 	return htmlspecialchars(html_entity_decode($string), ENT_QUOTES, 'UTF-8');
 
- }
 
- //Convertit la première lettre de la chaine $string
 
- //en majuscule et le reste de la chaine en minuscule UTF-8
 
- //pour l'affichage HTML
 
- function mb_ucfirst($string,$encoding = 'UTF-8'){
 
- 	$length = mb_strlen($string, $encoding);
 
-     $firstChar = mb_substr($string, 0, 1, $encoding);
 
-     $rest = mb_substr($string, 1, $length - 1, $encoding);
 
-     return mb_strtoupper($firstChar, $encoding).$rest;
 
- }
 
- // Permet de mettre au bon format le n° de 
 
- // téléphone fourni dans le formulaire
 
- function normalize_phone_number($number){
 
- 	$nb = str_replace(array(' ', '.', ',', '-'), '', $number);
 
- 	$nb = chunk_split($nb, 2, ' ');
 
- 	$nb = rtrim($nb);
 
- 	preg_match("/^[0-9]{2} [0-9]{2} [0-9]{2} [0-9]{2} [0-9]{2}/", $nb, $matches);
 
- 	return isset($matches[0]) ? $matches[0] : $nb;
 
- }
 
- // Permet de voir si le format du n° de téléphone
 
- // fourni correspond à un format correct
 
- function check_phone_number($number, $international=false){
 
- 	if(!$international && preg_match("/\+/i", $number)) return false;
 
- 	$nb = str_replace(array(' ', '.', ',', '-'), '', $number);
 
- 	if (!is_numeric($nb)) return false;
 
- 	return true;
 
- }
 
- //Retourne la valeur la plus proche d'un
 
- //nombre donné par rapport à un tableau de
 
- //nombres
 
- function get_closest_number($search, $arr){
 
- 	$closest = null;
 
- 	foreach ($arr as $item) {
 
- 		if ($closest === null || abs($search - $closest) > abs($item - $search)) {
 
- 			$closest = $item;
 
- 		}
 
- 	}
 
- 	return $closest;
 
- }
 
- //  Permet de convertir string encodée en UTF-8
 
- //  en ASCII pour ensuite appliquer une méthode
 
- //  de Levenshtein sans avoir de divergences
 
- //  trop importantes dues aux accents présents.
 
- function utf8_to_extended_ascii($str, &$map) {
 
-     // find all multibyte characters (cf. utf-8 encoding specs)
 
- 	$matches = array();
 
- 	if (!preg_match_all('/[\xC0-\xF7][\x80-\xBF]+/', $str, $matches))
 
-         return $str; // plain ascii string
 
-     
 
-     // update the encoding map with the characters not already met
 
-     foreach ($matches[0] as $mbc)
 
-     	if (!isset($map[$mbc]))
 
-     		$map[$mbc] = chr(128 + count($map));
 
-     // finally remap non-ascii characters
 
-     return strtr($str, $map);
 
- }
 
- // Override de la méthode de Levenshtein pour
 
- // compérer 2 strings encondées en UTF-8
 
- function levenshtein_utf8($s1, $s2) {
 
- 	$charMap = array();
 
- 	$s1 = utf8_to_extended_ascii($s1, $charMap);
 
- 	$s2 = utf8_to_extended_ascii($s2, $charMap);
 
- 	return levenshtein($s1, $s2);
 
- }
 
- // Méthode qui retourne sous forme de tableau 
 
- // les metaphones // des différents mots d'une 
 
- // phrase.
 
- function get_metaphones($sentence) {
 
- 	$metaphones = array();
 
- 	$words = explode(' ',$sentence);
 
- 	foreach ($words as $word) {
 
- 		$metaphones[] = metaphone($word);
 
- 	}
 
- 	return $metaphones;
 
- }
 
- // Permet de trouver une chaîne de caractère s'approchant
 
- // le plus de l'entrée fournie en paramètres
 
- function find_best_match($words = array(), $input = '') {
 
- 	$closest = '';
 
- 	$foundBestMatch = -1;
 
- 	$tmpInput = implode(' ', get_metaphones($input));
 
- 	foreach($words as $word) {
 
- 		$tmpGauge = implode(' ', get_metaphones($word));
 
- 		$similarity = levenshtein_utf8($tmpInput, $tmpGauge);
 
- 		if ($similarity == 0) {
 
- 			$closest = $word;
 
- 			$foundBestMatch = 0;
 
- 			break;
 
- 		}
 
- 		if ($similarity <= $foundBestMatch || $foundBestMatch < 0) {
 
- 			$closest  = $word;
 
- 			$foundBestMatch = $similarity;
 
- 		}
 
- 	}
 
- 	return $closest;
 
- }
 
- // Convertit nombres en lettres (utile pour Excel)
 
- function numbers_to_letters($num){
 
- 	$num = intval($num);
 
- 	$letter = '';
 
- 	if ($num <= 0) return $letter;
 
- 	while($num != 0){
 
- 		$p = ($num - 1) % 26;
 
- 		$num = intval(($num - $p) / 26);
 
- 		$letter = chr(65 + $p) . $letter;
 
- 	}
 
- 	return $letter;     
 
- }
 
- //Convertit lettres en nombres (utile pour Excel)
 
- function letters_to_numbers($col){
 
- 	$col = str_pad($col,3,'0', STR_PAD_LEFT);
 
- 	$i = 0;
 
- 	if ($col[0] != '0') {
 
- 		$i = ((ord($col[0]) - 64) * 676) + 26;
 
- 		$i += ($col[1] == '0') ? 0 : (ord($col[1]) - 65) * 26;
 
- 	} else {
 
- 		$i += ($col[1] == '0') ? 0 : (ord($col[1]) - 64) * 26;
 
- 	}
 
- 	$i += ord($col[2]) - 64;
 
- 	return $i;
 
- }
 
- //Check si c'est un date bien formattée
 
- function is_date($date){
 
- 	$date = str_replace(array('-',' ','\\'),'/',trim($date));
 
- 	if(trim($date)=='') return false;
 
- 	if (count(explode('/',$date)) < 3) return false;
 
- 	list($d,$m,$y) = explode('/',$date);		
 
- 	if( !is_numeric($d) || !is_numeric($m) || !is_numeric($y) ) return false;
 
- 	return checkdate (  $m ,  $d ,  $y );
 
- }
 
- //Cherche la position de $needles dans
 
- //$haystack, où $needles est un array
 
- //de string et $haystack est le string à
 
- //comparer
 
- function strpos_array($haystack, $needles=array(), $offset=0) {
 
- 	$chr = array();
 
- 	foreach($needles as $needle) {
 
- 		$res = strpos($haystack, $needle, $offset);
 
- 		if ($res !== false) $chr[$needle] = $res;
 
- 	}
 
- 	if(empty($chr)) return false;
 
- 	return min($chr);
 
- }
 
- //Supprime un dossier et son contenu
 
- //de manière récursive 
 
- function delete_folder_tree($dir, $selfDestroy=false) { 
 
- 	if(!file_exists($dir)) return;
 
- 	$files = array_diff(scandir($dir), array('.','..')); 
 
- 	foreach ($files as $file) 
 
- 		(is_dir("$dir/$file")) ? delete_folder_tree("$dir/$file") : unlink("$dir/$file"); 
 
- 	if($selfDestroy) return rmdir($dir); 
 
- }
 
- //Normalise les caractères un peu spéciaux
 
- //d'une chaîne de caractère
 
- function normalize_chars($string, $mask=array()) {
 
- 	$normalizeChars = array(
 
- 		'Š'=>'S', 'š'=>'s', 'Ð'=>'Dj','Ž'=>'Z', 'ž'=>'z', 'À'=>'A', 'Á'=>'A', 'Â'=>'A', 'Ã'=>'A', 'Ä'=>'A',
 
- 		'Å'=>'A', 'Æ'=>'A', 'Ç'=>'C', 'È'=>'E', 'É'=>'E', 'Ê'=>'E', 'Ë'=>'E', 'Ì'=>'I', 'Í'=>'I', 'Î'=>'I',
 
- 		'Ï'=>'I', 'Ñ'=>'N', 'Ń'=>'N', 'Ò'=>'O', 'Ó'=>'O', 'Ô'=>'O', 'Õ'=>'O', 'Ö'=>'O', 'Ø'=>'O', 'Ù'=>'U',
 
- 		'Ú'=>'U', 'Û'=>'U', 'Ü'=>'U', 'Ý'=>'Y', 'Þ'=>'B', 'ß'=>'Ss','à'=>'a', 'á'=>'a', 'â'=>'a', 'ã'=>'a', 
 
- 		'ä'=>'a', 'å'=>'a', 'æ'=>'a', 'ç'=>'c', 'è'=>'e', 'é'=>'e', 'ê'=>'e', 'ë'=>'e', 'ì'=>'i', 'í'=>'i', 
 
- 		'î'=>'i', 'ï'=>'i', 'ð'=>'o', 'ñ'=>'n', 'ń'=>'n', 'ò'=>'o', 'ó'=>'o', 'ô'=>'o', 'õ'=>'o', 'ö'=>'o',
 
- 		'ø'=>'o', 'ù'=>'u', 'ú'=>'u', 'û'=>'u', 'ü'=>'u', 'ý'=>'y', 'ý'=>'y', 'þ'=>'b', 'ÿ'=>'y', 'ƒ'=>'f',
 
- 		'ă'=>'a', 'î'=>'i', 'â'=>'a', 'ș'=>'s', 'ț'=>'t', 'Ă'=>'A', 'Î'=>'I', 'Â'=>'A', 'Ș'=>'S', 'Ț'=>'T',
 
- 		'’'=>'\'', '–'=>'-', '€'=>'€', '&'=>'&','œ'=>'oe', '•'=>'-'
 
- 	);
 
- 	return strtr($string, array_diff_key($normalizeChars, array_flip($mask)));
 
- }
 
- //Convertit un nombre en son équivalent écrit
 
- //e.g: 23 --> VINGT-TROIS
 
- function number_to_words($number, $feminine=false) {
 
- 	$hyphen      = '-';
 
- 	$conjunction = ' et ';
 
- 	$negative    = 'moins ';
 
- 	$decimal     = ' virgule ';
 
- 	$dictionary  = array(
 
- 		0                   => 'zero',
 
- 		1                   => !$feminine?'un':'une',
 
- 		2                   => 'deux',
 
- 		3                   => 'trois',
 
- 		4                   => 'quatre',
 
- 		5                   => 'cinq',
 
- 		6                   => 'six',
 
- 		7                   => 'sept',
 
- 		8                   => 'huit',
 
- 		9                   => 'neuf',
 
- 		10                  => 'dix',
 
- 		11                  => 'onze',
 
- 		12                  => 'douze',
 
- 		13                  => 'treize',
 
- 		14                  => 'quatorze',
 
- 		15                  => 'quinze',
 
- 		16                  => 'seize',
 
- 		17                  => 'dix-sept',
 
- 		18                  => 'dix-huit',
 
- 		19                  => 'dix-neuf',
 
- 		20                  => 'vingt',
 
- 		30                  => 'trente',
 
- 		40                  => 'quarante',
 
- 		50                  => 'cinquante',
 
- 		60                  => 'soixante',
 
- 		70                  => 'soixante-dix',
 
- 		80                  => 'quatre-vingt',
 
- 		90                  => 'quatre-vingt dix',
 
- 		100                 => 'cent',
 
- 		1000                => 'mille',
 
- 		1000000             => 'million',
 
- 		1000000000          => 'milliard',
 
- 		1000000000000       => 'trillion',
 
- 		1000000000000000    => 'quadrillion',
 
- 		1000000000000000000 => 'quintillion'
 
- 	);
 
- 	if (!is_numeric($number)) return false;
 
- 	if (($number >= 0 && (int) $number < 0) || (int) $number < 0 - PHP_INT_MAX) throw new Exception('number_to_words accepte uniquement des nombres compris entre -'.PHP_INT_MAX.' et '.PHP_INT_MAX);
 
- 	
 
- 	if ($number < 0) return $negative.number_to_words(abs($number));
 
- 	$string = $fraction = null;
 
- 	if (strpos($number, '.') !== false)
 
- 		list($number, $fraction) = explode('.', $number);
 
- 	switch (true) {
 
- 		case $number < 21:
 
- 			$string = $dictionary[$number];
 
- 		break;
 
- 		case $number == 21:
 
- 			$string = $dictionary[20].$conjunction.$dictionary[1];
 
- 		break; 
 
- 		case $number == 31:
 
- 			$string = $dictionary[30].$conjunction.$dictionary[1];
 
- 		break; 
 
- 		case $number == 41:
 
- 			$string = $dictionary[40].$conjunction.$dictionary[1];
 
- 		break; 
 
- 		case $number == 51:
 
- 			$string = $dictionary[50].$conjunction.$dictionary[1];
 
- 		break; 
 
- 		case $number == 61:
 
- 			$string = $dictionary[60].$conjunction.$dictionary[1];
 
- 		break; 
 
- 		case $number == 71:
 
- 			$string = $dictionary[60].$conjunction.$dictionary[11];
 
- 		break; 
 
- 		case $number == 81:
 
- 			$string = $dictionary[80].$hyphen.$dictionary[1];
 
- 		break; 
 
- 		case $number == 91:
 
- 			$string = $dictionary[80].$hyphen.$dictionary[11];
 
- 		break; 
 
- 		case $number < 100:
 
- 			$tens   = ((int) ($number / 10)) * 10;
 
- 			$units  = $number % 10;
 
- 			$string = $dictionary[$tens];
 
- 			if ($units) {
 
- 				$string .= $hyphen . $dictionary[$units];
 
- 			}
 
- 		break;
 
- 		case $number < 1000:
 
- 			$hundreds  = $number / 100;
 
- 			$remainder = $number % 100;
 
- 			$string = ((int)$hundreds==1 ? '' : $dictionary[$hundreds].' ') . $dictionary[100];
 
- 			if ($remainder) {
 
- 				$string .= ' ' . number_to_words($remainder);
 
- 			}
 
- 		break;
 
- 		default:
 
- 			$baseUnit = pow(1000, floor(log($number, 1000)));
 
- 			$numBaseUnits = (int) ($number / $baseUnit);
 
- 			$remainder = $number % $baseUnit;
 
- 			$string = number_to_words($numBaseUnits) . ' ' . $dictionary[$baseUnit];
 
- 			if ($remainder) {
 
- 				$string .= $remainder < 100 ? $conjunction : ' ';
 
- 				$string .= number_to_words($remainder);
 
- 			}
 
- 		break;
 
- 	}
 
- 	if (null !== $fraction && is_numeric($fraction)) {
 
- 		$string .= $decimal;
 
- 		if(strlen($fraction) <= 3) {
 
- 			$string .= number_to_words($fraction);
 
- 		} else {
 
- 			$words = array();
 
- 			foreach (str_split((string) $fraction) as $number)
 
- 				$words[] = $dictionary[$number];
 
- 			$string .= implode(' ', $words);
 
- 		}
 
- 	}
 
- 	return mb_strtoupper($string);
 
- }
 
- /**
 
-  * Retrourne le numéral ordinal compact
 
-  * d'un nombre passé en paramètre.
 
-  * eg: 
 
-  * 	1 --> 1er, 
 
-  *  2 --> 2ème, etc..
 
-  * Les nombres ordinaux sont définis par un
 
-  * l'ensemble des entiers naturels non nuls
 
-  * représenté N*={1,2,3,...}
 
-  */
 
- function number_to_ordinal($number, $feminine=false){
 
- 	$number = (int) $number;
 
- 	//Aucun ordinal pour le rang 0
 
- 	if($number == 0) return;
 
- 	if($number == 1) 
 
- 		return $number.($feminine?'ère':'er');
 
- 	return $number.'ème';
 
- }
 
- /**
 
-  * Vérifie si un nombre est entre 2 bornes
 
-  * Possibilité d'inclure ou d'exclure les bornes avec $strict
 
-  */
 
- function number_between($number, $low, $high, $strict=false) {
 
- 	if(!$strict && ($number<$low || $number>$high)) return false;
 
- 	if($strict && ($number<=$low || $number>=$high)) return false;
 
- 	return true;
 
- }
 
- /*
 
-  * Fonction pour vérifier si un nombre
 
-  * est un nombre décimal
 
-  *
 
-  * Eg: 	- 95.00 --> false
 
-  * 		- 95.5  --> true
 
-  * Les nombres avec décimales à 0 sont donc exclus
 
-  */
 
- function is_decimal($val) {
 
-     return is_numeric($val) && floor($val)!=$val;
 
- }
 
- /**
 
-  * Retourne les fonction interdites
 
-  * utilisées dans une fonction eval()
 
-  * @param  string $source [le string qui va $etre eval()]
 
-  * @return Array          [Tableau des méthodes utilisées interdites]
 
-  */
 
- function forbidden_macro($source){
 
- 	$tokens = token_get_all('<?php '.$source.' ?>');
 
- 	$forbiddens = array();
 
- 	$allowed_functions = array(
 
- 		'ucfirst',
 
- 		'strto.*',
 
- 		'str_.*',
 
- 		'substr',
 
- 		'password_encrypt',
 
- 		'strpos',
 
- 		'date',
 
- 		'[im|ex]plode',
 
- 		'preg_*',
 
- 		'count',
 
- 		'time',
 
- 		'array_.*',
 
- 		'.sort',
 
- 	);
 
- 	foreach($tokens as $token){
 
- 		if(is_string($token)) continue;   
 
- 		list($id, $text,$line) = $token;
 
- 		if(in_array($id, array(T_FUNCTION,T_FUNC_C,T_EVAL,T_STRING))){
 
- 			$allowed = false;
 
- 			foreach ($allowed_functions as $function) {
 
- 				preg_match('/'.$function.'/i', $text, $matches);
 
- 				if(count($matches)!=0){
 
- 					$allowed = true;
 
- 					break;
 
- 				}
 
- 			}
 
- 			if(!$allowed) $forbiddens[] = $text.' L'.$line;
 
- 		}
 
- 		if(in_array($id, array(
 
- 			T_INCLUDE,
 
- 			T_EXTENDS,
 
- 			T_CLONE,
 
- 			T_EXIT,
 
- 			T_GLOBAL,
 
- 			T_HALT_COMPILER,
 
- 			T_IMPLEMENTS,
 
- 			T_INCLUDE_ONCE,
 
- 			T_REQUIRE,
 
- 			T_REQUIRE_ONCE,
 
- 			T_IMPLEMENTS
 
- 		))){
 
- 			$forbiddens[] = $text.' L'.$line;
 
- 		}
 
- 	}
 
- 	return $forbiddens;
 
- }
 
- //Fonction respectant la syntaxe mustache (prototype a roder)
 
- function mustache_template($stream,$data){
 
-    //blocks (loop, if, else)
 
- 	
 
-     $stream = preg_replace_callback('/\{\{(#|\^)?([^\}]*)\}\}(.*?)\{\{\/\2\}\}/is',function($matches) use ($data) {
 
-         $stream = '';
 
-         $expression = $matches[0];
 
-         $key = $matches[2];
 
-         $template = $matches[3];
 
-         if(!isset($data[$key])){
 
-         	$stream = '';$expression;
 
-         	return $stream;
 
-         }
 
-         $value = $data[$key];
 
-         //if ou loop
 
-         if($matches[1] == '#'){
 
-         	//loop
 
-         	if(is_array($value)) {
 
-         		$length = count($value);
 
-         		$i = 0;
 
-         		foreach ($value as $key=>$value2) {
 
-         			//gère les exception de derniere occurence de boucle (ex,toutes les occurences finissent par , sauf la derniere)
 
-         			// syntaxe : {{;}}mon texte partout sauf derniere occurence{{/;}}
 
-         			$lastOccurenceReplace =  $i!=$length-1 ? '$1'  : '';
 
-         			$lineTemplate = preg_replace('/\{\{;\}\}(.*)\{\{\/;\}\}/isU', $lastOccurenceReplace, $template);
 
-         			
 
-         			$localData = is_array($value2) ? array_merge($data,$value2) : $data;
 
-         			$stream.= mustache_template($lineTemplate,$localData);
 
-         			$i++;
 
-         		}
 
-         		return $stream;
 
-         	//if
 
-         	}else{
 
-         		if(!empty($value) && $value!=false){
 
-         			return mustache_template($template,$data);
 
-         		}
 
-         		return '';
 
-         	}
 
-         //else
 
-         }else if($matches[1] == '^'){
 
-         	if(!$value) return mustache_template($template,$data);
 
-     		return '';
 
-     	
 
-         //cas de block non gérés car sans char operateur # ou ^ ex : {{expression}}{{/expression}}
 
-         }else{
 
-         	$stream = $expression;
 
-         	return $stream;
 
-         }
 
-     },$stream);
 
-     //simple vars
 
-      $stream = preg_replace_callback('/\{\{([^\}]*)\}\}/isU',function($matches) use ($data) {
 
-         $key = $matches[1];
 
-         if(isset($data[$key]) && (is_string($data[$key]) || is_numeric($data[$key])) ) return $data[$key];
 
-         $value = '';
 
-         $attributes = explode('.',$key);
 
-         $current = $data;
 
-         foreach ($attributes as $attribute) {
 
-         	if ( !isset($current[$attribute]) ) return;
 
-         	$current = $current[$attribute];
 
-         	$value = $current;
 
-         }
 
-         return $value;
 
- 	 },$stream);
 
-     return $stream;
 
- }
 
- function template($stream,$data,$mustacheTemplate = false){
 
- 	if($mustacheTemplate) return mustache_template($stream,$data);
 
-    //loop
 
-     $stream = preg_replace_callback('/{{\:([^\/\:\?}]*)}}(.*?){{\/\:[^\/\:\?}]*}}/is',function($matches) use ($data) {
 
-         $tag = $matches[1];
 
-         $streamTpl = $matches[2];
 
-         $stream = '';
 
-         if(!isset($data[$tag])) return $stream;
 
-         $values = $data[$tag];
 
-         foreach($values as $join){
 
-             $occurence = $streamTpl;
 
-             foreach($join as $key=>$value){
 
-             	if(is_array($value) || is_object($value)) continue;
 
-                 $occurence = str_replace(array('{{'.$key.'}}'),array($value),$occurence);
 
-             }
 
-             $stream .= $occurence;
 
-         }
 
-         return $stream;
 
-     },$stream);
 
-     //conditions
 
-     $stream = preg_replace_callback('/{{\?([^\/\:\?}]*)}}(.*?){{\/\?[^\/\:\?}]*}}/is',function($matches) use ($data) {
 
-         $key = $matches[1];
 
-         $stream = $matches[2];
 
-         return !isset($data[$key]) || (is_array($data[$key]) && count($data[$key])==0) ?'':$stream;
 
-     },$stream);
 
-     //simple vars
 
-     $stream = preg_replace_callback('/{{([^\/\:\;\?}]*)}}/',function($matches) use ($data) {
 
-         $key = $matches[1];
 
-         if(isset($data[$key]) && (is_string($data[$key]) || is_numeric($data[$key])) ) return $data[$key];
 
-         $value = '';
 
-         $attributes = explode('.',$key);
 
-         $current = $data;
 
-         foreach ($attributes as $attribute) {
 
-         	if ( !isset($current[$attribute]) ) return;
 
-         	$current = $current[$attribute];
 
-         	$value = $current;
 
-         }
 
-         return $value;
 
-     },$stream); 
 
-   
 
-     return $stream;
 
- }
 
- /**
 
-  * Auteur: Anonymous
 
-  * Lien: https://www.php.net/manual/en/features.file-upload.post-method.php#120686
 
-  * 
 
-  * Normalise le tableau de fichier récupérés
 
-  * pour une utilisation plus efficace et intuitive
 
-  * 
 
-  * Exemple de format initial pour 2 fichiers dans $_FILES :
 
-  * Array (
 
-     [name] => Array (
 
-         [0] => foo.txt
 
-         [1] => bar.txt
 
-     ),
 
-     [type] => Array(
 
-         [0] => text/plain
 
-         [1] => text/plain
 
-     ),
 
-     [tmp_name] => Array(
 
-         [0] => /tmp/phpYzdqkD
 
-         [1] => /tmp/phpeEwEWG
 
-     ),
 
-     [error] => Array(
 
-         [0] => 0
 
-         [1] => 0
 
-     ),
 
-     [size] => Array(
 
-         [0] => 123
 
-         [1] => 456
 
-     )
 
-  * )
 
-  * 
 
-  * Exemple de format de retour pour 2 fichiers :
 
-  * Array(
 
-     [0] => Array(
 
-         [name] => foo.txt
 
-         [type] => text/plain
 
-         [tmp_name] => /tmp/phpYzdqkD
 
-         [error] => 0
 
-         [size] => 123
 
-     ),
 
-     [1] => Array(
 
-         [name] => bar.txt
 
-         [type] => text/plain
 
-         [tmp_name] => /tmp/phpeEwEWG
 
-         [error] => 0
 
-         [size] => 456
 
-     )
 
- )
 
-  * @param  Array &$file_post [tableau de fichiers $_FILES]
 
-  * @return Array             [le tableau ré-arrangé]
 
-  */
 
- function normalize_php_files() {
 
-     $function = function($files, $fixedFiles=array(), $path=array()) use (&$function) {
 
-         foreach ($files as $key => $value) {
 
-             $temp = $path;
 
-             $temp[] = $key;
 
-        
 
-             if(is_array($value)) {
 
-                 $fixedFiles = $function($value, $fixedFiles, $temp);
 
-             } else {
 
-                 $next = array_splice($temp, 1, 1);
 
-                 $temp = array_merge($temp, $next);
 
-                 $new = &$fixedFiles;
 
-                
 
-                 foreach ($temp as $key)
 
-                     $new = &$new[$key];
 
-                 $new = $value;
 
-             }
 
-         }
 
-         return $fixedFiles;
 
-     };
 
-     return $function($_FILES);
 
- }
 
- /**
 
-  * Incrémente automatiquement le nom d'un
 
-  * fichier si celui-ci existe déjà
 
-  * Fonction récursive.
 
-  * @param  String $extension [extension du fichier]
 
-  * @param  String $folder    [dossier où localiser le fichier]
 
-  * @param  String $filename  [nom du fichier]
 
-  * @return String            [nom de fichier final]
 
-  */
 
- function autoincrement_filename($extension, $folder, $filename){
 
- 	static $counter = 0;
 
- 	$fileNb = count(glob(FILE_PATH.$folder.$filename));
 
- 	$filenameProps = explode('.', $filename);
 
- 	
 
- 	unset($filenameProps[count($filenameProps)-1]);
 
- 	$finalFilename = implode('.', $filenameProps);
 
- 	if($fileNb>0) {
 
- 		$counter+=1;
 
- 		$filename = preg_match("/(^.*?\()(\d+)([^\\d]*\)\..*$)/", $filename, $matches) ? $matches[1].$counter.$matches[3] : $finalFilename.'('.$counter.')'.'.'.$extension;
 
- 		$filename = autoincrement_filename($extension, $folder, $filename);
 
- 	}
 
- 	return $filename;
 
- }
 
- function relative_path($absolutePath,$reference = __ROOT__){
 
- 	$absolutePath = str_replace(array('\\','/'),SLASH,$absolutePath);
 
- 	$reference = str_replace(array('\\','/'),SLASH,$reference);
 
- 	return str_replace($reference,'',$absolutePath);
 
- }
 
- //Définit si une couleur hexadecimale est claire
 
- //ou sombre en fonction d'un seuil de luminosité
 
- function get_light($hexcode,$treshold = 510.0) {
 
- 	$rgb = to_rgb($hexcode);
 
- 	return (max($rgb[0], $rgb[1], $rgb[2]) + min($rgb[0], $rgb[1], $rgb[2])) / $treshold; 
 
- }
 
- //Génère une couleur hexadécimale aléatoire
 
- function random_hex_color() {
 
-     return '#'.str_pad(dechex(mt_rand(0, 0xFFFFFF)), 6, '0', STR_PAD_LEFT);
 
- }
 
- //Génère une couleur pastel basé sur 
 
- //le hash md5 du mot passé en paramètre
 
- function random_hex_pastel_color($name) {
 
-     $hash = md5($name);
 
-     $red = hexdec(substr($hash, 8, 2));
 
-     $green = hexdec(substr($hash, 4, 2));
 
-     $blue = hexdec(substr($hash, 0, 2));
 
-     if($red < 128) $red += 128;
 
-     if($green < 128) $green += 128;
 
-     if($blue < 128) $blue += 128;
 
-     return "#" . dechex($red) . dechex($green) . dechex($blue);
 
- }
 
- //Convertit un code hexadecimal en code RGB
 
- function to_rgb($hexcode) {
 
- 	$hexcode = substr($hexcode, 1);	    
 
- 	return array(hexdec($hexcode[0] . $hexcode[1]),
 
- 		hexdec($hexcode[2] . $hexcode[3]),
 
- 		hexdec($hexcode[4] . $hexcode[5]));    
 
- }
 
- //Retourne le nom complet d'un mois en fonction de son numéro
 
- function month_name($month){
 
- 	$translates = array('Janvier','Fevrier','Mars','Avril','Mai','Juin','Juillet','Aout','Septembre','Octobre','Novembre','Décembre');
 
- 	return $translates[$month-1];
 
- }
 
- //Retourne le nom complet d'un jour en fonction de son numéro (1 : lundi,..., 7 :dimanche)
 
- function day_name($day){
 
-     $translates = array('Lundi','Mardi','Mercredi','Jeudi','Vendredi','Samedi','Dimanche');
 
-     return isset($translates[$day-1])? $translates[$day-1]:$day;
 
- }
 
- //Convertit un timestamp dans un format 
 
- //agréable et complet : ex Mardi 18 Avril 2019
 
- function complete_date($time=null){
 
- 	if(!isset($time)) $time = time();
 
- 	return day_name(date('N',$time)).' '.date('d',$time).' '.month_name(date('m',$time)).' '.date('Y',$time);
 
- }
 
- //Récuperation des jours féries
 
- function get_not_workable($date=null){
 
- 	if ($date === null)
 
- 		$date = time();
 
- 	$date = strtotime(date('m/d/Y',$date));
 
- 	$year = date('Y',$date);
 
- 	if($year < 1970 || $year > 2037) throw new exception("Date non valide inférieure à 1970 ou supérieure à 2037", 400);
 
- 	$easterDate  = easter_date($year);
 
- 	$easterDay   = date('j', $easterDate);
 
- 	$easterMonth = date('n', $easterDate);
 
- 	$easterYear  = date('Y', $easterDate);
 
- 	$holidays = array(
 
- 	    // Dates fixes
 
- 	    mktime(0, 0, 0, 1,  1,  $year),  // 1er janvier
 
- 	    mktime(0, 0, 0, 5,  1,  $year),  // Fête du travail
 
- 	    mktime(0, 0, 0, 5,  8,  $year),  // Victoire des alliés
 
- 	    mktime(0, 0, 0, 7,  14, $year),  // Fête nationale
 
- 	    mktime(0, 0, 0, 8,  15, $year),  // Assomption
 
- 	    mktime(0, 0, 0, 11, 1,  $year),  // Toussaint
 
- 	    mktime(0, 0, 0, 11, 11, $year),  // Armistice
 
- 	    mktime(0, 0, 0, 12, 25, $year),  // Noel
 
- 	    // Dates variables
 
- 	    mktime(0, 0, 0, $easterMonth, $easterDay + 1,  $easterYear),
 
- 	    mktime(0, 0, 0, $easterMonth, $easterDay + 39, $easterYear),
 
- 	    mktime(0, 0, 0, $easterMonth, $easterDay + 50, $easterYear),
 
- 	);
 
- 	return $holidays;
 
- }
 
- //Retourne le chemin web d'un fichier en fonction de son chemin 
 
- //physique (ex : /img/logo.png pour /var/www/erp-core/img/logo.png)
 
- function webpath($path){
 
-     $url = ROOT_URL.str_replace(array(__DIR__.SLASH,"\\","/"),array('','/','/'),$path);
 
-     $url = preg_replace('/([^\:])(\/{2,})/i', '$1/', $url);
 
-     return $url;
 
- }
 
- //Retourne un tableau clé/valeur des valeurs
 
- //existantes en doublons du tableau passé en paramètre
 
- function array_not_unique($array=array()){
 
- 	return array_diff_key($array, array_unique($array));
 
- }
 
- //Retourne true si aucune valeur du tableau passé
 
- //en paramètre a un doublon, false sinon. 
 
- function is_array_unique($array=array()){
 
- 	return empty(array_not_unique($array));
 
- }
 
- function make_cookie($name, $value, $expire='', $ns ='/') {
 
- 	if($expire == ''){
 
- 		setcookie($name, $value, mktime(0,0,0, date("d"), date("m"), (date("Y")+1)), $ns);
 
- 	} else {
 
- 		setcookie($name, '', mktime(0,0,0, date("d"), date("m"), (date("Y")-1)), $ns);
 
- 	}
 
- }
 
- //Permet de formatter les prix à afficher
 
- //de la même manière partout sur l'ERP.
 
- //Si jamais on veut changer de normalisation
 
- //pour l'affichage des prix, il suffit de changer
 
- //le fonctionnement ici uniquement.
 
- function display_price($price){
 
- 	return number_format($price, 2, ',', ' ');
 
- }
 
- //Permet de formatter les prix à enregistrer
 
- //de la même manière partout sur l'ERP.
 
- //Si jamais on veut changer de normalisation
 
- //pour l'enregistrement des prix, il suffit de changer
 
- //le fonctionnement ici uniquement.
 
- function format_price($price){
 
- 	return str_replace(',','.',$price);
 
- }
 
- //Permet de calculer un age en fonction de la date du jour
 
- //Paramètre : la date de départ(format timestamp), l'unité de retour souhaitée(format 'd', 'm', 'Y'... voir fonction diff de php)
 
- //Renvoie : l'age en entier
 
- function age($from,$unit = 'y'){
 
- 	if(!isset($from) || !is_numeric($from)) return 'N/A';
 
- 	$from = new \DateTime(date('Y-m-d',$from));
 
- 	$to = new \DateTime('today');
 
- 	$age = $from->diff($to);
 
- 	if(!$age || !array_key_exists($unit, $age))
 
- 		return 'N/A';
 
- 	return $age = $age->$unit;
 
- }
 
- //Permet d'échapper tous les caractères interdits dans une chaine json
 
- function escape_json_string($value) { # list from www.json.org: (\b backspace, \f formfeed)
 
-     $escapers = array("\\", "/", "\"", "\n", "\r", "\t", "\x08", "\x0c");
 
-     $replacements = array("\\\\", "\\/", "\\\"", "\\n", "\\r", "\\t", "\\f", "\\b");
 
-     $result = str_replace($escapers, $replacements, $value);
 
-     return $result;
 
- }
 
- if( !function_exists('apache_request_headers') ) {
 
- 	///
 
- 	function apache_request_headers() {
 
- 	  $arh = array();
 
- 	  $rx_http = '/\AHTTP_/';
 
- 	  foreach($_SERVER as $key => $val) {
 
- 	    if( preg_match($rx_http, $key) ) {
 
- 	      $arh_key = preg_replace($rx_http, '', $key);
 
- 	      $rx_matches = array();
 
- 	      // do some nasty string manipulations to restore the original letter case
 
- 	      // this should work in most cases
 
- 	      $rx_matches = explode('_', $arh_key);
 
- 	      if( count($rx_matches) > 0 and strlen($arh_key) > 2 ) {
 
- 	        foreach($rx_matches as $ak_key => $ak_val) $rx_matches[$ak_key] = ucfirst($ak_val);
 
- 	        $arh_key = implode('-', $rx_matches);
 
- 	      }
 
- 	      $arh[$arh_key] = $val;
 
- 	    }
 
- 	  }
 
- 	  return( $arh );
 
- 	}
 
- }
 
- if(!function_exists('apache_get_version')){
 
-     function apache_get_version(){
 
-         if(!isset($_SERVER['SERVER_SOFTWARE']) || strlen($_SERVER['SERVER_SOFTWARE']) == 0){
 
-             return false;
 
-         }
 
-         return $_SERVER["SERVER_SOFTWARE"];
 
-     }
 
- }
 
- //Effectue un basename en tenant compte des caractères
 
- //utf8( non pris en compte par basename PHP sous linux)
 
- function mt_basename($path){
 
- 	$path = str_replace(array("\\","/"),SLASH, $path);
 
- 	$nameSplit = explode(SLASH,$path);
 
- 	return end($nameSplit);
 
- }
 
- //filtre les balises dangeureuses (script,link..) dans les contenus wysiwyg 
 
- function wysiwyg_filter($html){
 
- 	
 
- 	$html = preg_replace('#<(script|link)(.*?)>(.*?)</(script|link)>#is', '', $html);
 
- 	$html = preg_replace('#<(script|link)([^>]*?)>#is', '', $html);
 
- 	return $html;
 
- }
 
- function display_format_price($price) {
 
- 	return display_price(format_price($price));
 
- }
 
- function unzip($zipPath,$destination,$options = array()){
 
- 	$zip = new ZipArchive();
 
- 	if(!$zip->open($zipPath)) throw new Exception("Impossible d'ouvrir l'archive");
 
- 	for( $u = 0; $u < $zip->numFiles; $u++ ){ 
 
- 		$infos = $zip->statIndex( $u );
 
- 		
 
- 		//dossier
 
- 		if(substr($infos['name'],-1,1)=='/'){
 
- 			$infos['name'] = str_replace('..','.',$infos['name']);
 
- 			mkdir($destination.SLASH.$infos['name'],0755,true);
 
- 		//fichier
 
- 		}else{
 
- 			$parentDir = dirname($infos['name']);
 
- 			if(!empty($parentDir) && !file_exists($parentDir)) mkdir($parentDir,0755,true);
 
- 			if(!empty($options['allowedExtensions'])){
 
- 				if(!in_array(getExt($infos['name']),$options['allowedExtensions']))  continue;
 
- 			}
 
- 			file_put_contents($destination.SLASH.$infos['name'], $zip->getFromName($infos['name']));
 
- 		}
 
- 		
 
- 	}
 
- }
 
- //retourne le tableaux des mentions depuis un texte libre ité de notre composant wysiwyg
 
- //#mention #wysiwyg
 
- function get_mention($text){
 
- 	$mentionned = array(
 
- 		'user'=> array(),
 
- 		'rank'=> array(),
 
- 		'object'=> array(),
 
- 	);
 
- 	preg_match_all('|class="data-mention-user".*data-mention-value="([^"]*)"|isU', $text, $matches,PREG_SET_ORDER);
 
- 	$users = User::getAll();
 
- 	$ranks = Rank::loadAll();
 
- 	foreach($matches as $match){
 
- 		foreach($users as $user){
 
- 			if($match[1] == $user->login)
 
- 				$mentionned['user'][] = $user;
 
- 		}
 
- 		foreach($ranks as $rank){
 
- 			if($match[1] == $rank->id)
 
- 				$mentionned['rank'][] = $rank;
 
- 		}
 
- 	}
 
- 	preg_match_all('|class="data-mention-object".*data-mention-value="([^"]*)"|isU', $text, $matches,PREG_SET_ORDER);
 
- 	foreach ($matches as $match){
 
- 		$mentionned['object'][] = $match[1];
 
- 	}
 
- 	return $mentionned;
 
- }
 
- function value_encapsulate($value, $char = ',') {
 
- 	$value = trim($value, $char);
 
- 	$value = $char.$value.$char;
 
- 	return $value;
 
- }
 
- /*
 
- Donne le differentiel en heures/jours entre deux dates en prenant en compte les horaires ouvrés et de la pause déjeuner
 
- 	$start : timestamp de début
 
- 	$end : timestamp de fin 
 
- 	$openStartHour : heure ouvrée de début de journée
 
- 	$openEndHour : heure ouvrée de fin de journée
 
- 	$lunchHour : temps de pause déjeuner (en heure)
 
- */
 
- /*
 
- Donne le differentiel en heures/jours entre deux dates en prenant en compte les horaires ouvrés et de la pause déjeuner
 
- $start : timestamp de début
 
- $end : timestamp de fin 
 
- $openStartHour : heure ouvrée de début de journée
 
- $openEndHour : heure ouvrée de fin de journée
 
- $lunchHour : temps de pause déjeuner (en heure)
 
- */
 
- function date_workable_diff($start,$end,$openStartHour = 9,$openEndHour = 18,$lunchHour = 1){
 
- 	$startTime = (new DateTime())->setTimestamp($start)->setTime(0,0,0);
 
- 	$endTime = (new DateTime())->setTimestamp($end)->setTime(0,0,0);
 
- 	
 
- 	$maxHours = $openEndHour - $openStartHour  - $lunchHour;
 
- 	$days = array();
 
- 	//Si la fin n'est pas le même jour que le début
 
- 	if($startTime->format('d-m-Y') != $endTime->format('d-m-Y')){
 
- 		for($i=0;$i<$endTime->diff($startTime)->format("%a")+1;$i++){
 
- 			$current = clone $startTime;
 
- 			$current->add(new DateInterval('P'.$i.'D'));
 
- 			$intervalStart = clone $current;
 
- 			$intervalEnd = clone $current;
 
- 			if($startTime->format('d-m-Y') != $intervalStart->format('d-m-Y')){
 
- 				$intervalStart->setTime($openStartHour,0,0);
 
- 			}else{
 
- 				$intervalStart = (new DateTime())->setTimestamp($start);
 
- 			}
 
- 			if($endTime->format('d-m-Y') != $intervalEnd->format('d-m-Y')){
 
- 				$intervalEnd->setTime($openEndHour,0,0);
 
- 			}else{
 
- 				$intervalEnd = (new DateTime())->setTimestamp($end);
 
- 			}
 
- 			$days[] = array('start'=>$intervalStart,'end'=>$intervalEnd);
 
- 		}
 
- 	}else{
 
- 		$days[]= array('start'=>(new DateTime())->setTimestamp($start),'end'=> (new DateTime())->setTimestamp($end));
 
- 	}
 
- 	
 
- 	$deltaHours = 0;
 
- 	foreach($days as $day){
 
- 		$hours = $day['end']->format('H') - $day['start']->format("H");
 
- 		//On enleve $lunchHour de pause déjeuner (12h-13h) dans les cas ou le temps pietine sur la pause
 
- 		if( ($day['end']->format('H') < 13 && $day['end']->format('H') > 12) || 
 
- 			($day['start']->format('H') < 13 && $day['start']->format('H') > 12) || 
 
- 			($day['start']->format('H') <12 && $day['end']->format('H') > 13)
 
- 		) $hours-= $lunchHour;
 
- 		$deltaHours += $hours;
 
- 	}
 
- 	
 
- 	$deltaDays = round($deltaHours / $maxHours,2);
 
- 	return array(
 
- 		'hours' => $deltaHours,
 
- 		'days' => $deltaDays
 
- 	);
 
- }
 
- if (!function_exists('getallheaders')) {
 
-     function getallheaders() {
 
-     $headers = [];
 
-     foreach ($_SERVER as $name => $value) {
 
-         if (substr($name, 0, 5) == 'HTTP_') {
 
-             $headers[str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', substr($name, 5)))))] = $value;
 
-         }
 
-     }
 
-     return $headers;
 
-     }
 
- }
 
- ?>
 
 
  |