12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949 |
- <?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':
- //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;
- }
- }
- ?>
|