Pārlūkot izejas kodu

-Core: Clean des traling space

necron.s550 2 gadi atpakaļ
vecāks
revīzija
47b844e902
100 mainītis faili ar 1581 papildinājumiem un 1833 dzēšanām
  1. 1 1
      404.php
  2. 1 1
      account.api.php
  3. 5 5
      account.global.php
  4. 4 4
      account.lost.php
  5. 1 1
      account.php
  6. 8 8
      action.php
  7. 6 10
      class/Action.class.php
  8. 12 12
      class/Address.class.php
  9. 22 34
      class/Api.class.php
  10. 9 13
      class/Configuration.class.php
  11. 1 1
      class/Contact.class.php
  12. 9 11
      class/ContactPerson.class.php
  13. 2 4
      class/Database.class.php
  14. 7 16
      class/Dictionary.class.php
  15. 70 91
      class/Entity.class.php
  16. 16 21
      class/Excel.class.php
  17. 24 70
      class/FieldType.class.php
  18. 38 59
      class/File.class.php
  19. 1 4
      class/Firm.class.php
  20. 4 7
      class/History.class.php
  21. 17 18
      class/Image.class.php
  22. 13 17
      class/JWToken.class.php
  23. 9 22
      class/Log.class.php
  24. 7 8
      class/Mail.class.php
  25. 14 14
      class/Pdf.class.php
  26. 23 39
      class/Plugin.class.php
  27. 0 24
      class/Rank.class.php
  28. 2 4
      class/Right.class.php
  29. 1 35
      class/User.class.php
  30. 1 1
      class/UserFirmRank.class.php
  31. 2 3
      class/UserPreference.class.php
  32. 11 11
      common.php
  33. 6 6
      connector/Mysql.class.php
  34. 9 9
      connector/Oracle.class.php
  35. 7 7
      connector/SqlServer.class.php
  36. 9 9
      connector/Sqlite.class.php
  37. 4 4
      firm.php
  38. 24 24
      footer.php
  39. 95 97
      function.php
  40. 22 22
      header.php
  41. 1 1
      index.php
  42. 27 49
      install.php
  43. 21 21
      js/main.js
  44. 41 41
      js/plugins.js
  45. 3 3
      login.php
  46. 1 1
      migration/migration.php
  47. 2 2
      plugin/activedirectory/AdFirmRank.class.php
  48. 33 33
      plugin/activedirectory/AdServer.class.php
  49. 40 40
      plugin/activedirectory/action.php
  50. 13 13
      plugin/activedirectory/activedirectory.plugin.php
  51. 4 4
      plugin/activedirectory/js/main.js
  52. 14 14
      plugin/activedirectory/setting.list.ad.firm.rank.php
  53. 16 16
      plugin/activedirectory/setting.list.adserver.php
  54. 10 10
      plugin/activedirectory/setting.sheet.adserver.php
  55. 10 10
      plugin/client/Client.class.php
  56. 159 159
      plugin/client/action.php
  57. 8 8
      plugin/client/card.client.php
  58. 61 61
      plugin/client/client.plugin.php
  59. 2 2
      plugin/client/client.widget.configure.php
  60. 2 2
      plugin/client/client.widget.php
  61. 24 24
      plugin/client/css/main.css
  62. 3 3
      plugin/client/css/widget.css
  63. 10 10
      plugin/client/export.html
  64. 5 5
      plugin/client/js/component.js
  65. 37 37
      plugin/client/js/main.js
  66. 15 15
      plugin/client/page.list.client.php
  67. 16 16
      plugin/client/page.sheet.client.php
  68. 6 6
      plugin/client/setting.global.client.php
  69. 10 10
      plugin/client/tab.home.php
  70. 4 4
      plugin/clientmap/action.php
  71. 13 13
      plugin/clientmap/clientmap.plugin.php
  72. 5 5
      plugin/clientmap/css/main.css
  73. 13 13
      plugin/clientmap/js/main.js
  74. 25 25
      plugin/clientmap/page.list.client.php
  75. 2 2
      plugin/clientmap/setting.global.clientmap.php
  76. 28 28
      plugin/contact/action.php
  77. 9 9
      plugin/contact/contact.plugin.php
  78. 6 6
      plugin/contact/js/main.js
  79. 15 15
      plugin/contact/page.list.contact.person.php
  80. 11 11
      plugin/contact/page.sheet.contact.person.php
  81. 1 1
      plugin/contact/setting.global.contact.php
  82. 2 2
      plugin/customiser/Theme.class.php
  83. 4 4
      plugin/customiser/action.php
  84. 8 8
      plugin/customiser/customiser.plugin.php
  85. 4 4
      plugin/customiser/js/main.js
  86. 3 3
      plugin/customiser/setting.global.customiser.php
  87. 6 6
      plugin/directory/action.php
  88. 7 7
      plugin/directory/directory.plugin.php
  89. 5 5
      plugin/directory/js/main.js
  90. 57 57
      plugin/document/Element.class.php
  91. 39 39
      plugin/document/WebDav.class.php
  92. 69 69
      plugin/document/action.php
  93. 10 10
      plugin/document/css/document.api.css
  94. 28 28
      plugin/document/document.plugin.php
  95. 82 82
      plugin/document/js/document.api.js
  96. 5 5
      plugin/document/js/main.js
  97. 1 1
      plugin/document/js/widget.js
  98. 1 1
      plugin/document/new.action.php
  99. 1 1
      plugin/document/setting.document.php
  100. 6 6
      plugin/document/tab.client.php

+ 1 - 1
404.php

@@ -1,4 +1,4 @@
-<?php 
+<?php
 
 ?>
 

+ 1 - 1
account.api.php

@@ -1,4 +1,4 @@
-<?php 
+<?php
 global $myUser, $myFirm, $conf;
 if (!$myUser->connected()) throw new Exception("Vous devez être connecté pour accéder à la page",401);
 

+ 5 - 5
account.global.php

@@ -1,4 +1,4 @@
-<?php 
+<?php
 global $myUser, $myFirm, $conf;
 if (!$myUser->connected()) throw new Exception("Vous devez être connecté pour accéder à la page",401);
 ?>
@@ -17,13 +17,13 @@ if (!$myUser->connected()) throw new Exception("Vous devez être connecté pour
 			<div class="user-ranks">
 				<label for="rank">Rangs :</label><br>
 				<small class="text-muted">
-					<?php 
+					<?php
 					$ranks = array();
 					if($myUser->superadmin == 1) {
 						$ranks = array('Super Admin');
 					} else {
-						foreach($myUser->ranks[$myFirm->id] as $rank) 
-							$ranks[] = $rank->label; 
+						foreach($myUser->ranks[$myFirm->id] as $rank)
+							$ranks[] = $rank->label;
 					}
 
 					foreach ($ranks as $i=>$rank): ?>
@@ -75,7 +75,7 @@ if (!$myUser->connected()) throw new Exception("Vous devez être connecté pour
 			<label for="mobile">Téléphone mobile professionnel :</label>
 			<input id="mobile" name="mobile" class="form-control" placeholder="N° Téléphone mobile professionnel" type="text" value="<?php echo $myUser->mobile; ?>">
 		</div>
-		
+
 	</div><br>
 	<div class="row mb-2">
 		<div class="col-md-6">

+ 4 - 4
account.lost.php

@@ -1,4 +1,4 @@
-<?php 
+<?php
 require_once (__DIR__.DIRECTORY_SEPARATOR.'header.php');
 global $conf,$myUser,$myFirm,$_;
 if($myUser->connected()) throw new Exception("Vous devez être déconnecté pour accéder à cette fonctionnalité");
@@ -15,7 +15,7 @@ if(isset($_['token'])){
 	$baseToken = UserPreference::load(array('user'=>$login,'key'=>'lost_password'));
 	if(!$baseToken || $baseToken->value!=$token) throw new Exception("expiré ou inexistant");
 	if(!empty($conf->get('password_lost_mail_expire')) && (time()-$baseToken->created) > strtotime(intval($conf->get('password_lost_mail_expire')).' days', 0)) throw new Exception("Lien de récupération expiré");
-	
+
 	if(!$user = User::load(array('login'=>$login))) throw new Exception("Token expiré ou inexistant");
 }
 ?>
@@ -51,12 +51,12 @@ if(isset($_['token'])){
 				        <li><strong>Mot de passe : </strong><code class="font-weight-bold bg-light p-2 pointer" onclick="select_text(this, event);copy_string($(this).text(), this);"><?php echo $newPassword; ?></code></li>
 				    </ul>
 				    <a href="index.php" class="btn btn-success mt-2 w-100" ><i class="fas fa-home"></i> Retour à l'accueil</a>
-				    <?php 
+				    <?php
 				break;
 				default:
 					throw new Exception("Token expiré ou inexistant");
 				break;
-			} 
+			}
 		else: ?>
 			<h5 class="text-muted text-uppercase col-xl-12"><i class="fas fa-unlock mr-1"></i>Mot de passe oublié</h5>
 			<p class="col-xl-12 my-4">

+ 1 - 1
account.php

@@ -1,4 +1,4 @@
-<?php require_once __DIR__.DIRECTORY_SEPARATOR.'header.php';  
+<?php require_once __DIR__.DIRECTORY_SEPARATOR.'header.php';
 
 User::check_access('account','read');
 

+ 8 - 8
action.php

@@ -120,7 +120,7 @@ Action::register('initialize_activity',function(&$response){
 
 /** Tables de recherches **/
 
-//Save des colonnes dynamiques 
+//Save des colonnes dynamiques
 Action::register('core_table_colum_save',function(&$response){
 	global $myUser,$_;
 	if(!$myUser->connected()) return;
@@ -133,7 +133,7 @@ Action::register('core_table_colum_save',function(&$response){
 	$_SESSION['currentUser'] = serialize($myUser);
 });
 
-//Load des colonnes dynamiques 
+//Load des colonnes dynamiques
 Action::register('core_table_colum_search',function(&$response){
 	global $myUser,$_;
 	if(!isset($myUser)) throw new Exception("Utilisateur non définis");
@@ -142,7 +142,7 @@ Action::register('core_table_colum_search',function(&$response){
 	return $response;
 });
 
-//Save des fitlres de recherches en preference 
+//Save des fitlres de recherches en preference
 Action::register('core_filter_save',function(&$response){
 	global $myUser,$_;
 	if(!$myUser->connected()) throw new Exception("Permission non accordée");
@@ -180,11 +180,11 @@ Action::register('core_filter_save',function(&$response){
 	$_SESSION['currentUser'] = serialize($myUser);
 });
 
-/** 
+/**
  * Suppression d'une recherche enregistrée
  *  @param boolean global Définit si la recherche est globale ou non
  *  @param string slug Représente le slug de la table de résultats associée
- *  @param 
+ *  @param
  * */
 Action::register('core_filter_delete',function(&$response){
 	global $myUser,$_;
@@ -309,7 +309,7 @@ Action::register('core_search_log',function(&$response){
 });
 
 
-/* Gestion des entitées */ 
+/* Gestion des entitées */
 //Récuperation d'une liste d'entitées en fonction du plugin ciblé
 Action::register('core_entity_search',function(&$response){
 	global $myUser,$_;
@@ -404,10 +404,10 @@ Action::register('core_plugin_search',function(&$response){
 
 	foreach(Firm::loadAll() as $firm)
 		$firms[] =  $firm->toArray();
-	
+
 	foreach(Plugin::getAll(true) as $plugin)
 		$firmPluginMapping[$plugin->id] = $plugin->firms;
-	
+
 	foreach(Plugin::getAll(false,$includeCore) as $plugin){
 
 		$plugin->folder = array('name'=>$plugin->folder,'path'=>$plugin->path());

+ 6 - 10
class/Action.class.php

@@ -12,11 +12,11 @@
  */
 class Action {
     /**
-     * Execute an action 
+     * Execute an action
      * #### Example
      * ```php
-     * Action::write(function(&$response){ 
-     *  $response['custom'] = 'hello world!'; 
+     * Action::write(function(&$response){
+     *  $response['custom'] = 'hello world!';
      * },array('user'=>'u','plugin'=>'d')); //User must have user update right and delete plugin right to perform this action
      * ```.
      *
@@ -32,12 +32,9 @@ class Action {
         set_error_handler(function ($level, $error, $file, $line) { throw new Exception($error." \r\n\r\n  ".$file.' - L '.$line.'');});
         try {
             foreach ($p as $scope => $right) {
-                if (!$myUser->can($scope, $right)) 
-                    throw new Exception('Vous ne disposez pas des droits suffisants pour effectuer cette action');
-                
+                if (!$myUser->can($scope, $right)) throw new Exception('Vous ne disposez pas des droits suffisants pour effectuer cette action');
             }
             $f($response);
-            
         } catch (Exception $e) {
             $response['error'] = $e->getMessage();
             $response['errorCode'] = $e->getCode();
@@ -49,14 +46,14 @@ class Action {
 
                 //Si c'est une erreur de bound sql / data  ou une erreur de syntaxe sql
                 if($e->getCode() == 'HY093' || $e->getCode() == '42000'){
-                    
+
                     //On recupere la premiere trace qui n'est pas Entity ou Action (trace significative)
                     foreach($traces as $i => $currentTrace){
                         if(isset($currentTrace['file']) && in_array(basename($currentTrace['file']), array('Entity.class.php','Action.class.php'))) continue;
                         $traceIndex = $i;
                         break;
                     }
-            
+
                     //On affiche la requete et les datas
                     if(isset($traces[1]) && $traces[1]['function']=='customQuery'){
 
@@ -74,7 +71,6 @@ class Action {
                 $response['trace'] = '<pre class="text-light" style="overflow:initial;">'.exception_trace($e).'</pre>';
             }
         }
-
         echo json_encode($response);
         restore_error_handler();
     }

+ 12 - 12
class/Address.class.php

@@ -37,21 +37,21 @@ class Address extends Entity{
     public function toArray($decoded=false) {
         $fields = parent::toArray($decoded);
         $fields['fullName'] = $this->fullName();
- 
+
         if($decoded){
             $fields['fullName'] = html_entity_decode($fields['fullName']);
-        } 
+        }
         return $fields;
     }
 
 	/**
 	 * Permet de récupérer un tableau de
 	 * données liées à l'adresse via l'API Here
-	 * 
-	 * Détail des paramètres possibles : https://developer.here.com/documentation/geocoder/dev_guide/topics/resource-geocode.html 
+	 *
+	 * Détail des paramètres possibles : https://developer.here.com/documentation/geocoder/dev_guide/topics/resource-geocode.html
 	 * Types de réponses : https://developer.here.com/documentation/geocoder/dev_guide/topics/resource-type-response-geocode.html
 	 * Voir utilisation live ici : https://developer.here.com/documentation/examples/rest/geocoder/latitude-longitude-no-attributes
-	 * 
+	 *
 	 * @param $responseAttributes : Définit les attributs de réponse à récupérer, séparés par virgule (ps,mq,mt,mc,pr par défaut)
 	 * Listes des possibilités:
 	 *    - ps = performedSearch
@@ -60,7 +60,7 @@ class Address extends Entity{
 	 *    - mc = matchCode
 	 *    - pr = parsedRequest
 	 *    - none = aucun attribut
-	 * 
+	 *
 	 * @param $locationAttributes : Définit les attributs de réponse à récupérer, séparés par virgule
 	 * Listes des possibilités:
 	 *    - ar = address
@@ -77,7 +77,7 @@ class Address extends Entity{
 	public function infos($responseAttributes='ps,mq,mt,mc,pr', $locationAttributes='ar,mr,mv,dt,sd,ad,ai,li,in', $maxResults=null){
 		global $myUser, $conf;
 		if(!$myUser->connected()) throw new Exception("Vous devez être connecté",401);
-		
+
 		$results = array();
 		$appUrl = $conf->get('maps_api_geocode_url');
 		$appId = $conf->get('maps_api_id');
@@ -137,7 +137,7 @@ class Address extends Entity{
 		if($response === false){
 			Log::put("Erreur de récupération cURL : ".curl_error($ch),'Location API');
 			return $results;
-		} 
+		}
 
 		$results = json_decode($response);
 
@@ -189,13 +189,13 @@ class Address extends Entity{
 	}
 
 
-	//Retourne l'adresse sur une seule ligne 
+	//Retourne l'adresse sur une seule ligne
 	//au format : street, complement, zip city country
 	public function fullName(){
 		$fullname = '';
 		if(!empty($this->street)) $fullname .= $this->street;
 		if(!empty($this->complement)) $fullname .= ', '.$this->complement;
-		
+
 		if($fullname!='') $fullname .= ', ';
 		if(!empty($this->zip)) $fullname .= $this->zip;
 		if(!empty($this->city)) $fullname .= ' '.$this->city;
@@ -215,7 +215,7 @@ class Address extends Entity{
 		return !$plainText ? $array : $plain;
 	}
 
-	
+
 	public function getCoordinates(){
 		return self::coordinates($this->fullName());
 	}
@@ -246,7 +246,7 @@ class Address extends Entity{
 				'icon' => "fas fa-shipping-fast",
 				'color' => "#4dabf7",
 			)
-			
+
 		);
 		Plugin::callHook('address_types', array(&$types));
 		if(!isset($key)) return $types;

+ 22 - 34
class/Api.class.php

@@ -24,14 +24,14 @@ class Api{
 	function register(){
 		Plugin::addHook('api',function(&$apis){
 			$apis[$this->slug] = $this;
-			
 		});
 	}
 
 	//retourne la liste des headers de la requete courante (clé normalisées)
 	public static function headers(){
 		$headers = array();
-		foreach(getallheaders() as $key=>$value) $headers[mb_strtolower($key)] = $value;
+		foreach(getallheaders() as $key=>$value)
+			$headers[mb_strtolower($key)] = $value;
 		return $headers;
 	}
 
@@ -45,18 +45,18 @@ class Api{
 	public static function token_session(){
 		if(php_sapi_name() == 'cli') return;
 		if(!self::requested()) return;
-		
+
 		$headers = self::headers();
 		if(!isset($headers['authorization'])) return;
-		
+
 		try{
 			$authorization = explode(' ',$headers['authorization']);
 			if(count($authorization)!=2 || strtolower($authorization[0])!='bearer') throw new Exception("Bad Authorization header (required Authorization: Bearer <JWToken>)",403);
 			global $conf,$myUser;
-		
+
 			$token = JWToken::parse(trim($authorization[1]),$conf->get('jwtauth_secret'));
-			//si une session est en cours 
-			if(session_status() == PHP_SESSION_ACTIVE){ 
+			//si une session est en cours
+			if(session_status() == PHP_SESSION_ACTIVE){
 				//si la session courant a le mauvais id (ex une session anonyme ou expirée) on la détruit et on la recréé avec le bon id
 				if( session_id() !=$token['attributes']['session_id']){
 					session_destroy();
@@ -68,12 +68,12 @@ class Api{
 				session_id($token['attributes']['session_id']);
 				session_start();
 			}
-			
+
 
 			if(!isset($_SESSION['currentUser'])) throw new Exception('Token session has expired',498);
 		}catch(Exception $e){
-			$response['error'] = $e->getMessage(); 
-			$response['errorCode'] = $e->getCode(); 
+			$response['error'] = $e->getMessage();
+			$response['errorCode'] = $e->getCode();
 			echo json_encode($response);
 			exit;
 		}
@@ -82,7 +82,7 @@ class Api{
 	public static function run(){
 		global $_,$myUser;
 		$response = array();
-		
+
 		try{
 			set_error_handler(function( $errno ,  $errstr , $errfile ,  $errline){
 				throw new Exception("Error ".$errno." Processing Request : ".$errfile." => ".$errstr.' L'.$errline, 500);
@@ -96,14 +96,14 @@ class Api{
 			if(count($command)<1) throw new Exception("Unspecified API");
 
 			$headers = self::headers();
-			
+
 			//basic auth (deprecated, utiliser plutot JWToken et Authorization Bearer)
 			if(isset($_SERVER['PHP_AUTH_USER']) && isset($_SERVER['PHP_AUTH_PW'])){
 				$user = User::check($_SERVER['PHP_AUTH_USER'],$_SERVER['PHP_AUTH_PW']);
 				if(!$user) throw new Exception('Le compte spécifié est inexistant');
 				$myUser = $user;
 			}
-			
+
 			$request = array(
 				'version' =>array_shift($command),
 				'module' =>array_shift($command),
@@ -128,7 +128,7 @@ class Api{
 				foreach ($apis as $api) {
 					$routes= array();
 					foreach($api->route as $route){
-						
+
 						foreach($route as $method=>$infos){
 							if(!isset($routes[$infos->slug])) $routes[$infos->slug] = array() ;
 							$routes[$infos->slug][] = $infos->method.' '.$api->slug .'/'.$infos->pattern .': '. $infos->description ;
@@ -139,10 +139,10 @@ class Api{
 			}else{
 				if(!isset($apis[$request['module']])) throw new Exception("Api '".$request['module']."' is missing, see ".ROOT_URL."/api/{version}/schema for available calls", 404);
 				$api = $apis[$request['module']];
-				
+
 				if(!isset($api->route[$request['route']]))  throw new Exception("Route '".$api->slug.'/'.$request['route']."' is missing, see ".ROOT_URL."/api/schema?pretty for available calls", 404);
 				$route = $api->route[$request['route']];
-				
+
 
 				if(!isset($route[$request['method']]))  throw new Exception("Method ".$request['method']." '".$api->slug.'/'.$route->slug."' is not allowed", 405);
 				$method = $route[$request['method']];
@@ -156,17 +156,12 @@ class Api{
 				unset($response['code']);
 				unset($response['headers']);
 			}
-
-			
-
-		}catch(Exception $e){
+		} catch(Exception $e) {
 			$response['error'] = $e->getMessage();
-			$code = $e->getCode();					
+			$code = $e->getCode();
 			if(empty($code)) $code = 0;
-			$response['errorCode'] = $code;	
+			$response['errorCode'] = $code;
 		}
-
-
 		$codes = array(
 			200 => 'HTTP/1.1 200 Ok',
 			201 => 'HTTP/1.1 201 Created',
@@ -189,15 +184,10 @@ class Api{
 		if (ob_get_length()) ob_end_clean();
 		header(isset($codes[$code]) ? $codes[$code] : $codes[0]);
 
-		foreach ($headers as $header) {
+		foreach ($headers as $header)
 			header($header);
-		}
-		
-		if(isset($_['pretty'])){
-			echo json_encode($response,JSON_PRETTY_PRINT);
-		}else{
-			echo json_encode($response);
-		}
+
+		echo (isset($_['pretty'])) ? json_encode($response,JSON_PRETTY_PRINT) : json_encode($response);
 		exit();
 	}
 }
@@ -218,5 +208,3 @@ class ApiRoute{
 		$this->callback = $callback;
 	}
 }
-
-?>

+ 9 - 13
class/Configuration.class.php

@@ -28,7 +28,7 @@ class Configuration extends Entity {
      */
     public function getAll() {
         if (!isset($_SESSION['configuration'])) {
-           
+
             $configurationManager = new self();
             $configs = $configurationManager->loadAll();
             $this->confTab = array();
@@ -42,10 +42,10 @@ class Configuration extends Entity {
         }
     }
 
-    //Définit / récupere un set de configurations générique
+    //Défini / récupère un set de configurations générique
     public static function setting($name,$settings=null){
         if(!isset($settings)) return isset($GLOBALS['setting'][$name]) ? $GLOBALS['setting'][$name] : array();
-        $GLOBALS['setting'][$name] = $settings; 
+        $GLOBALS['setting'][$name] = $settings;
     }
 
     //Met en page (tableau html) un set de configuration générique
@@ -58,9 +58,9 @@ class Configuration extends Entity {
             <?php foreach($options as $key=>$infos):
                 if(!is_array($infos)): ?>
                 <tr><th colspan="2" class="bg-secondary text-light py-2 align-middle"><h4 class="m-0"><i class="fas fa-angle-right"></i> <?php echo $infos;?></h4></th></tr>
-                <?php continue; endif; 
+                <?php continue; endif;
                 $confValue = $conf->get($key);
-                
+
 
                 $infos['attributes'] = empty($infos['attributes']) ? array() : $infos['attributes'];
                 if(isset($confValue)) $infos['value'] = htmlentities($confValue);
@@ -72,18 +72,13 @@ class Configuration extends Entity {
                         $infos['attributes'][$attribute] = $attribute.'="'.$parameter.'"';
                    }
                 }
-
                 $infos['id'] = $key;
 
                 if(!empty( $infos['placeholder'])) $infos['placeholder'] = '"'. $infos['placeholder'].'"';
                 if(!empty( $infos['placeholder'])) $infos['attributes']['placeholder'] = $infos['placeholder'] ;
 
-                
-                $field = FieldType::toHtml($infos,null,array('allowCustomLabel'=>false)); 
-            
-
+                $field = FieldType::toHtml($infos,null,array('allowCustomLabel'=>false));
                 ?>
-
                 <tr class="<?php echo $key; ?>">
                     <th class="align-middle position-relative"><?php echo $field['label']; ?>
                     <?php if (!empty($field['legend'])): ?>
@@ -138,7 +133,7 @@ class Configuration extends Entity {
     public function put($key, $value) {
         $secured_value = encrypt($value);
         $configurationManager = new self();
-        if (isset($this->confTab[$key])) {
+        if(isset($this->confTab[$key])) {
             $configurationManager->change(array('value' => $secured_value), array('key' => $key));
         } else {
             $configurationManager->add($key, $secured_value);
@@ -152,7 +147,7 @@ class Configuration extends Entity {
      * #### Example
      * ```php
      * global $conf; // global var, contain configurations
-     * echo $conf->remove('myNewConfigKey'); //delete myNewConfigKey from 'conf' default namespace 
+     * echo $conf->remove('myNewConfigKey'); //delete myNewConfigKey from 'conf' default namespace
      * echo $conf->remove('myNewConfigKey','myCustomPluginConfig'); //delete myNewConfigKey from 'myCustomPluginConfig' namespace
      * ```.
      *
@@ -164,6 +159,7 @@ class Configuration extends Entity {
         $config->key = $key;
         $config->value = $value;
         $config->save();
+
         $this->confTab[$key] = $value;
         unset($_SESSION['configuration']);
     }

+ 1 - 1
class/Contact.class.php

@@ -51,7 +51,7 @@ class Contact extends Entity{
 			),
 		);
 		Plugin::callHook('contact_types', array(&$types));
-		
+
 		return isset($key) && isset($types[$key]) ? $types[$key] : $types;
 	}
 }

+ 9 - 11
class/ContactPerson.class.php

@@ -21,7 +21,7 @@ class ContactPerson extends Entity{
 	public $scope; //Scope (Texte)
 	public $comment; //Commentaire (Texte long)
 	public $uid; //UID (Entier)
-	public $meta = array(); 
+	public $meta = array();
 	public $tag; //Etiquettes (Etiquettes)
 
 	const TYPE_EXTERNAL = "external";
@@ -47,8 +47,6 @@ class ContactPerson extends Entity{
 		'tag' => array('type'=>'tag', 'label' => 'Etiquettes')
 	);
 
-	
-
 	//Colonnes indexées
 	public $indexes = array('uid','scope');
 
@@ -57,12 +55,12 @@ class ContactPerson extends Entity{
 		$filters = array('scope'=>'contact_person','uid'=>$this->id);
 		if(!empty($types)) $filters['type:IN'] = implode(',',$types);
 		if($defaultOnly) $filters['label'] = '';
-		
+
 		foreach(Contact::loadAll($filters) as $contact){
 			if($contact->type==Contact::PHONE && $contact->label=='') $this->phone = $contact->value;
 			if($contact->type==Contact::MOBILE && $contact->label=='') $this->mobile = $contact->value;
 			if($contact->type=="mail" && $contact->label=='') $this->mail = $contact->value;
-		
+
 			if(!isset($this->meta[$contact->type])) $this->meta[$contact->type] = array();
 			$this->meta[$contact->type][] = $contact;
 		}
@@ -100,7 +98,7 @@ class ContactPerson extends Entity{
 		$query .= ',(SELECT value FROM '.Contact::tableName().' c WHERE c.type=? AND c.scope=? AND c.uid={{table}}.id AND (c.label=? OR c.label IS NULL) LIMIT 1) as mobile';
 		$query .= ',(SELECT value FROM '.Contact::tableName().' c WHERE c.type=? AND c.scope=? AND c.uid={{table}}.id AND (c.label=? OR c.label IS NULL) LIMIT 1) as mail';
 		$query .= ' FROM {{table}}';
-		
+
 		$data[] = Contact::PHONE;
 		$data[] = 'contact_person';
 		$data[] = '';
@@ -135,7 +133,7 @@ class ContactPerson extends Entity{
 	//liste des Civilité possibles
 	public static function civilities($key=null){
 		$items = array(
-			'm' => array('label'=>'M.'), 
+			'm' => array('label'=>'M.'),
 			'mme' => array('label'=>'Mme.')
 		);
 		if(!isset($key)) return $items;
@@ -152,22 +150,22 @@ class ContactPerson extends Entity{
 	//Sauvegarde l'entité et ses entitées de contact liées (téléphones, mail...)
 	public function save_all(){
 		parent::save();
-		
+
 		$currentMeta = array('phone'=>$this->phone,'mobile'=>$this->mobile,'mail'=>$this->mail);
 		//Enregistrement des mails et téléphones princpaux dans la table de contacts (si renseignés)
 		if(!isset($this->phone) && !isset($this->mobile) && !isset($this->mail)) return;
-		
+
 
 		$metaContacts = array('phone','mail','mobile');
 		//récuperation des contacts par defaut existants pour cette personne
 		$this->meta($metaContacts,true);
-		
+
 		foreach ($metaContacts as $metaContact) {
 			//si le champ est renseigné
 			if(isset($currentMeta[$metaContact])){
 				//on récupere le champ existant ou on en créé un nouveau
 				$contact = !empty($this->meta[$metaContact]) ? $this->meta[$metaContact][0] : new Contact();
-				
+
 
 				//on ne save que si la valeur a changée
 				if($contact->value != $currentMeta[$metaContact]){

+ 2 - 4
class/Database.class.php

@@ -52,14 +52,12 @@ class Database {
 
             $connectionString = $connector::connection;
 
-            foreach ($database as $key => $value) {
+            foreach ($database as $key => $value)
                 $connectionString = str_replace('{{'.$key.'}}',$value,$connectionString);
-            }
 
             $connectionString = str_replace('{{ROOT}}',__ROOT__,$connectionString);
-        
             $this->connections[$baseUid] = new PDO($connectionString, $database['login'], $database['password'],$connector::pdo_attributes());
-     
+
             if(method_exists ( $connector , 'beforeTransaction' ))
             $connector::beforeTransaction($this->connections[$baseUid]);
         } catch (Exception $e) {

+ 7 - 16
class/Dictionary.class.php

@@ -1,7 +1,7 @@
 <?php
 /**
 * Manage application and plugins lists with key/value pair.
-* 
+*
 * @author valentin carruesco
 *
 * @category Core
@@ -50,16 +50,15 @@ class Dictionary extends Entity {
 
 	public static function childs($param = array(),$options = array('depth'=>1,'format'=>'object'),$level=1) {
 		$childs = array();
-		
+
 		if(isset($param['id']) && $param['id']==0){
 			$parent = new Dictionary();
 			$parent->id = 0;
 			$parent->label = 'Racine';
-
 		}else{
 			$parent = self::load($param);
 		}
-		
+
 		if(!$parent) return $childs;
 		$state = isset($param['state:IN']) ? $param['state:IN'] : self::ACTIVE;
 		foreach (self::loadAll(array('parent'=>$parent->id, 'state:IN'=>$state), array(' label ASC ')) as $child) {
@@ -73,12 +72,7 @@ class Dictionary extends Entity {
 	}
 
 	public static function hierarchy($idOrSlug, $slug, &$elements=array()) {
-	   if(is_numeric($idOrSlug)){
-	   		$current = self::getById($idOrSlug);
-	   }else{
-	   		$current = self::bySlug($idOrSlug);
-	   }
-	  
+   		$current = (is_numeric($idOrSlug)) ? self::getById($idOrSlug) : self::bySlug($idOrSlug);
 	   if(!$current) return array();
 
 	   if(($current->parent == 0 && $slug != '') || ($current->parent == -1 && $slug == '')) return $elements;
@@ -91,14 +85,10 @@ class Dictionary extends Entity {
 	   }else{
 			$parent = self::load(array('id' => $current->parent));
 	   }
-
-
 	   $children = self::childs(array('id'=>$parent->id));
 
 	   $parent->childs = array();
-
 	   foreach($children as $child){
-
 	    	if($child->id == $current->id) {
 	    		$child = !empty($elements) ? $elements : $child;
 	    		$child->selected = true;
@@ -108,8 +98,8 @@ class Dictionary extends Entity {
 	    	}
     		$parent->childs[] = $child;
 	   }
-
 	   $elements = $parent;
+
 	   return self::hierarchy($parent->id, $slug, $elements);
 	}
 
@@ -118,7 +108,8 @@ class Dictionary extends Entity {
 		$childs = self::bySlug($slug,true);
 		self::delete(array('slug'=>$slug));
 		if(!is_array($childs)) return;
-		foreach ($childs as $item) 
+
+		foreach ($childs as $item)
 			self::remove($item->slug);
 	}
 }

+ 70 - 91
class/Entity.class.php

@@ -48,15 +48,13 @@ class Entity {
             if(!is_array($type)) $type = array('type'=>$type,'column'=>$field);
             if(!isset($type['column'])) $type['column'] = $field;
             if(isset($type['link'])) $this->links[$type['column']] = $type['link'];
-            
+
             $type['fieldtype'] = $type['type'];
             //conversion des field type en sql type
-            if(isset($fieldTypes[$type['type']]))
-                $type['type'] = $fieldTypes[$type['type']]->sqlType;
-            
-            $fieldMapping[$field] = $type;
-        } 
+            if(isset($fieldTypes[$type['type']])) $type['type'] = $fieldTypes[$type['type']]->sqlType;
 
+            $fieldMapping[$field] = $type;
+        }
         return $fieldMapping;
     }
 
@@ -68,12 +66,10 @@ class Entity {
     }
 
     public function __toString() {
-        foreach ($this->toArray() as $key => $value) {
+        foreach ($this->toArray() as $key => $value)
             echo $key.' : '.$value.','.PHP_EOL;
-        }
     }
 
-  
     public function __sleep() {
         return array_keys($this->toArray());
     }
@@ -85,11 +81,11 @@ class Entity {
     //Comparaison de deux instances d'une même entité, retourne les champs ayant changés uniquement
     public static function compare($obj1,$obj2,$ignore=array()){
         $class = get_called_class();
-      
+
         $compare = array();
         foreach ($obj1->fields as $field => $type) {
             if($field == 'updated' || $field == 'updater' || in_array($field, $ignore)) continue;
-  
+
             if($obj1->$field != $obj2->$field){
                 if($type=='int' && (($obj1->$field==0 && $obj2->$field =='') || ($obj2->$field=='' && $obj1->$field ==0)) ) continue;
                 $compare[] = array('field'=>$field,'value1'=>$obj1->$field,'value2'=>$obj2->$field);
@@ -132,7 +128,6 @@ class Entity {
         // $this->close();
     }
 
-    
     //Libellé human readable de l'entité
     public static function entityLabel() {
         $class = get_called_class();
@@ -164,9 +159,7 @@ class Entity {
 
         if ($statement != false) {
             $statement = $statement->fetchArray();
-            if ($statement['numRows'] == 1) {
-                $return = true;
-            }
+            if ($statement['numRows'] == 1) $return = true;
         }
         if ($autocreate && !$return) self::create();
         return $return;
@@ -178,14 +171,12 @@ class Entity {
             $class = array_shift($infos);
             require_once($classDirectory.SLASH.$class.'.class.php');
             $reflection = new ReflectionClass($class);
-            if (!class_exists($class) || !method_exists($class, 'create') || $class == get_class() || $reflection->isAbstract()) {
-                continue;
-            }
-            
+            if (!class_exists($class) || !method_exists($class, 'create') || $class == get_class() || $reflection->isAbstract()) continue;
+
             $class::create();
         }
     }
-    
+
     public static function uninstall($classDirectory) {
         foreach (glob($classDirectory.SLASH.'*.class.php') as $file) {
             $infos = explode('.', basename($file));
@@ -210,8 +201,8 @@ class Entity {
         $query = Entity::render($sql,array(
            'table' => $class::tableName(false,$instance),
            'fieldMapping' => $instance->fieldMapping
-           ));
-        
+        ));
+
         $instance->customQuery($query);
     }
 
@@ -231,17 +222,15 @@ class Entity {
 
         $fieldMapping = $instance->field_mapping($instance->fields);
 
-        foreach ($instance->fields(false) as $slug => $field) {
+        foreach ($instance->fields(false) as $slug => $field)
             $fields[$slug] =  isset($types[$field['type']]) ? $types[$field['type']] : $types['default'];
-        }
-        
-        
+
         $sql = $connector::create();
         $query = Entity::render($sql,array(
            'table' => $class::tableName(false,$instance),
            'fields' => $fields,
            'fieldMapping' => $instance->fieldMapping
-           ));
+        ));
 
         $instance->customQuery($query);
         if(isset($instance->indexes)) $instance->index($instance->indexes);
@@ -255,8 +244,8 @@ class Entity {
         $query = Entity::render($sql,array(
            'table' => $class::tableName(false,$instance),
            'fieldMapping' => $instance->fieldMapping
-           ));
-        
+        ));
+
         $instance->customQuery($query);
         if(isset($instance->indexes)) $instance->index($instance->indexes,false);
     }
@@ -270,12 +259,12 @@ class Entity {
     public function save() {
         global $myUser;
         $this->updated = time();
-        
+
         if(is_object($myUser) && $myUser->login!='') $this->updater = $myUser->login;
         //update
         if (isset($this->id) && $this->id > 0) {
             $fields = array();
-            foreach ($this->fields as $field => $type) 
+            foreach ($this->fields as $field => $type)
                 $fields[$field] = $this->{$field};
             self::change($fields,array('id'=>$this->id));
         //insert
@@ -302,7 +291,7 @@ class Entity {
         $this->id = !isset($this->id) || !is_numeric($this->id) ? $this->pdo->lastInsertId() : $this->id;
     }
 
-    
+
      /**
      * Methode d'insertion massive de l'entité.
      * @category manipulation SQL
@@ -328,12 +317,11 @@ class Entity {
         foreach ($entities_groups as $entities_group) {
             $end = count($entities_group)-1;
             $data = array();
-            
 
             foreach($entities_group as $u=>$entity){
                 $entity->updated = $time;
                 $entity->updater = $login;
-               
+
                 $fields = array();
                 $i = 0;
                 foreach ($entity->fields as $field => $type) {
@@ -350,7 +338,7 @@ class Entity {
                        'fieldMapping' => $reference->fieldMapping
                     ));
                 }
-                
+
                 $query .= self::render($sql_body,array(
                    'table' => $entity->tableName(false,$entity),
                    'fields' => $fields,
@@ -371,7 +359,7 @@ class Entity {
      */
     public static function change($columns, $columns2 = array()) {
         $class = get_called_class();
-       
+
         $instance = new $class();
         $connector = $instance->connector;
 
@@ -383,7 +371,7 @@ class Entity {
             $fields[$field] = ':'.$i;
             $i++;
         }
-     
+
         $filters = array();
         foreach($columns2 as $key=>$value){
             $filter = array(
@@ -435,7 +423,7 @@ class Entity {
      * @param <String> $operation="=" definis le type d'operateur pour la requete select
      * @return <Array<Entity>> $Entity
      */
-   
+
     public static function loadAll($columns = array(), $order = null, $limit = null, $selColumn = array('*'), $joins = 0) {
         $class = get_called_class();
         $instance = new $class();
@@ -463,7 +451,7 @@ class Entity {
             $connector::processField($filter,$value,$values,$i);
             $filters[] = $filter;
          }
-         
+
          if(!empty($order)){
              foreach ($order as $key=>$clause) {
                 foreach ($instance->fieldMapping as $attribute => $infos) {
@@ -482,13 +470,11 @@ class Entity {
         );
         $data['joins']  = array();
         if($joins!=0){
-            foreach ($data['selected'] as $k=>$column) {
+            foreach ($data['selected'] as $k=>$column)
                $data['selected'][$k] = $tableName.'.'.$column;
-            }
+
             $data = self::recursiveJoining($instance,$data,$joins);
         }
-        
-            
         $sql = $connector::select();
         $sql = Entity::render($sql,$data);
 
@@ -520,16 +506,14 @@ class Entity {
                     list($className,$field2) = $classField;
 
                 $alias = substr($linkTable,0,3).'_'.$field;
-                
+
                 $joinInstance = new $className();
-                foreach ($joinInstance->fields as $key=>$type) {
+                foreach ($joinInstance->fields as $key=>$type)
                     $data['selected'][] = $alias.'.'.$key.' as '.$linkTable.'_join_'.$key;
-                }
-             
-                $joinTable1 = $instanceTable;
 
+                $joinTable1 = $instanceTable;
                 if(!empty($joinInstanceAlias)) $joinTable1 = $joinInstanceAlias;
-                
+
                 $data['joins'][] = array(
                     'jointable1' => $joinTable1,
                     'jointable2' => $linkTable,
@@ -584,7 +568,7 @@ class Entity {
             'filter' =>  count($filters) == 0 ? null: $filters,
             'fieldMapping' => $instance->fieldMapping
         );
-        
+
         $sql = $connector::count();
         $execQuery = $instance->customQuery(Entity::render($sql,$data), $values);
         $row = $execQuery->fetch();
@@ -592,16 +576,14 @@ class Entity {
         return $row['number'];
     }
 
-    public static function loadAllOnlyColumn($selColumn, $columns, $order = null, $limit = null) {  
-        $objects = self::loadAll($columns, $order, $limit, $selColumn); 
+    public static function loadAllOnlyColumn($selColumn, $columns, $order = null, $limit = null) {
+        $objects = self::loadAll($columns, $order, $limit, $selColumn);
         if (count($objects) == 0) $objects = array();
         return $objects;
     }
 
     /**
      * Méthode de selection unique d'élements de l'entité.
-     *
-
      *
      * @category manipulation SQL
      *
@@ -645,7 +627,7 @@ class Entity {
                     foreach($values as $join){
                         $occurence = $sqlTpl;
                         foreach($join as $key=>$value){
-                            $occurence = str_replace(array('{{'.$key.'}}'),array($value),$occurence); 
+                            $occurence = str_replace(array('{{'.$key.'}}'),array($value),$occurence);
                         }
                         $sql.= $occurence;
                     }
@@ -663,7 +645,7 @@ class Entity {
                             $value['tag'],
                             $operator,
                             $postoperator),
-                        $sqlTpl); 
+                        $sqlTpl);
                         $occurence = preg_replace_callback('/{{\;}}(.*?){{\/\;}}/',function($matches) use ($last){
                             return $last? '': $matches[1];
                         },$occurence);
@@ -681,13 +663,13 @@ class Entity {
                             $infos = explode(':',$key);
                             $key = $infos[0];
                             $operator = $infos[1];
-                            
+
                             if($operator=='IN' || $operator=='NOT IN'){
                                 $operator = $operator.'(';
                                 $postoperator = ')';
                             }
-                        } 
-                        $occurence = str_replace(array('{{key}}','{{value}}','{{operator}}','{{postoperator}}'),array($key,$value,$operator,$postoperator),$sqlTpl); 
+                        }
+                        $occurence = str_replace(array('{{key}}','{{value}}','{{operator}}','{{postoperator}}'),array($key,$value,$operator,$postoperator),$sqlTpl);
                         $occurence = preg_replace_callback('/{{\;}}(.*?){{\/\;}}/',function($matches) use ($last){
                             return $last? '': $matches[1];
                         },$occurence);
@@ -705,14 +687,14 @@ class Entity {
             $key = $matches[1];
             $sql = $matches[2];
             return !isset($data[$key]) || (is_array($data[$key]) && count($data[$key])==0) ?'':$sql;
-        },$sql); 
+        },$sql);
 
         //simple vars
         $sql = preg_replace_callback('/{{([^\/\:\;\?}]*)}}/',function($matches) use ($data) {
             $key = $matches[1];
             return isset($data[$key])?$data[$key]:'';
-        },$sql); 
-      
+        },$sql);
+
         return $sql;
     }
 
@@ -732,7 +714,7 @@ class Entity {
     public static function deleteById($id) {
         self::delete(array('id' => $id));
     }
-    
+
     /**
      * Méthode de Suppression d'elements de l'entité.
 
@@ -747,7 +729,7 @@ class Entity {
         $class = get_called_class();
         $instance = new $class();
         $connector = $instance->connector;
-        
+
         $i=0;
         $values = array();
         $filters = array();
@@ -770,14 +752,14 @@ class Entity {
             $connector::processField($filter,$value,$values,$i);
             $filters[] = $filter;
         }
-        
+
         $data = array(
-           'table' => $class::tableName(false,$instance),
-           'limit' =>  count($limit) == 0 ? null: $limit,
-           'filter' =>  count($filters) == 0 ? null: $filters,
-           'fieldMapping' => $instance->fieldMapping
-           );
-        
+            'table' => $class::tableName(false,$instance),
+            'limit' =>  count($limit) == 0 ? null: $limit,
+            'filter' =>  count($filters) == 0 ? null: $filters,
+            'fieldMapping' => $instance->fieldMapping
+        );
+
         $sql = $connector::delete();
         return $instance->customQuery(Entity::render($sql,$data), $values);
     }
@@ -788,7 +770,7 @@ class Entity {
      * si la classe contient l'attribut $this->indexes = array(...);
 
      * @category manipulation SQL
-     * @param <Array> | <String>  $colonne(s)  
+     * @param <Array> | <String>  $colonne(s)
      * @param <Boolean>  Mode (true : ajout, false : suppression)
      * @return Aucun retour
      */
@@ -812,7 +794,7 @@ class Entity {
 
             $results = $class::staticQuery(Entity::render($connector::count_index(),$data));
             $exists = $results->fetch();
-            
+
             if($mode){
                 if($exists['exists'] != 1) $class::staticQuery(Entity::render($connector::create_index(),$data));
             }else{
@@ -820,10 +802,10 @@ class Entity {
             }
         }
     }
-    
+
     //Génération d'une pagination
     public static function paginate($itemPerPage,$currentPage,&$query,$data,$alias=''){
-        
+
         $class = get_called_class();
         $instance = new $class();
         $keys = array_keys($instance->fields, 'key');
@@ -838,7 +820,7 @@ class Entity {
         $number = $queryNumber[0];
         $pageNumber = $number / $itemPerPage;
         if($currentPage >= $pageNumber) $currentPage = 0;
-        
+
         $limit = ' LIMIT '.($currentPage*$itemPerPage).','.$itemPerPage;
         $query .= $limit;
         return array(
@@ -868,14 +850,14 @@ class Entity {
         $query = preg_replace_callback('/{{([^}]*)}}/si', function($match) use ($mapping){
             return isset($mapping[$match[1]]) && isset($mapping[$match[1]]['column']) ? $mapping[$match[1]]['column'] : $match[0];
         }, $query);
-      
+
         try{
             if(BASE_DEBUG) self::logFile($query.' :: '.json_encode($data, JSON_UNESCAPED_UNICODE),debug_backtrace());
             $results = $this->pdo->prepare($query);
             $results->execute($data);
             if (!$results) throw new Exception(json_encode($this->pdo->errorInfo()));
         }catch(Exception $e){
-            
+
             Log::put("[SQL ERROR] - Erreur : ".$e->getMessage().' - Requete : '.$query.' - Données : '.json_encode($data, JSON_UNESCAPED_UNICODE));
             if(BASE_DEBUG) self::logFile( "Erreur : ".$e->getMessage());
             throw $e;
@@ -899,11 +881,11 @@ class Entity {
                     $object->{$field} = $queryReturn[$dbField];
                     unset($queryReturn[$dbField]);
                 }
-            }   
+            }
             if($joins>0) $object = self::recursiveJoiningFill($object,$queryReturn,$joins);
             foreach ($queryReturn as $key => $value) {
                 if(!is_numeric($key)) $object->foreignColumns[$key] = $value;
-            }  
+            }
             $objects[] = $object;
             unset($object);
         }
@@ -916,7 +898,7 @@ class Entity {
         return isset($this->foreignColumns[$key]) ? $this->foreignColumns[$key]  : '';
     }
 
-    //Renvois une chaine de selecteur sql devant être join 
+    //Renvois une chaine de selecteur sql devant être join
     //ex : Client::joinString('cli') --> cli.id client_join_id,cli.label client_join_label ...
     public static function joinString($prefix = ''){
         $class = get_called_class();
@@ -940,10 +922,9 @@ class Entity {
 
                 $instanceLink = new $classLink();
                 $tableName =  $classLink::tableName(false,$instanceLink);
-                foreach ($instanceLink->fields as $field => $type) {
-                    if (isset($queryReturn[$tableName.'_join_'.$field]))
-                         $instanceLink->{$field} = $queryReturn[$tableName.'_join_'.$field];
-                }
+                foreach ($instanceLink->fields as $field => $type)
+                    if(isset($queryReturn[$tableName.'_join_'.$field])) $instanceLink->{$field} = $queryReturn[$tableName.'_join_'.$field];
+
                 $instanceLink = self::recursiveJoiningFill($instanceLink,$queryReturn,$iterations);
                 $object->joins[$link] =  $instanceLink;
             }
@@ -955,12 +936,10 @@ class Entity {
      * Récupere l'objet join ex : $contact->join("adress")->street; --> récupere l'attribut street de la class Adress dont l'id est spécifié dans la colonne adress de la class Contact
      * Nb : cette méthode ne fonctionne que si vous avez placé le parametre joins > 0 dans la méthode LoadALl
      * Nb : cette méthode ne fonctionne que si vous avez précisé le lien entre Contact et Adress dans la classe Contact via :
-        
-         protected $links = array(
-        'address' => 'Address'
+        protected $links = array(
+            'address' => 'Address'
         );
      *
-
      * @category manipulation SQL
      *
      * @param <Array>  $colonnes      (WHERE)
@@ -978,11 +957,11 @@ class Entity {
         file_put_contents(__DIR__.SLASH.'..'.SLASH.'sql.debug.sql', date('H:i:s').' | '.$msg.PHP_EOL,FILE_APPEND);
         //A décommenter pour obtenir la stacktrace d'un appel sql dans le fichier sql.debug.sql
         //if(isset($backtrace)) file_put_contents(__DIR__.SLASH.'..'.SLASH.'sql.debug.sql', json_encode($backtrace,JSON_PRETTY_PRINT).PHP_EOL,FILE_APPEND);
-        
+
     }
 
     public static function log_executed_query($string, $data) {
-        $indexed=$data==array_values($data);
+        $indexed = $data==array_values($data);
         foreach($data as $k=>$v) {
             if(is_string($v)) $v="'$v'";
             if($indexed) $string=preg_replace('/\?/',$v,$string,1);

+ 16 - 21
class/Excel.class.php

@@ -1,4 +1,4 @@
-<?php 
+<?php
 
 require_once (__DIR__.SLASH.'..'.SLASH.'constant.php');
 //Exemple d'utilisation de XLSXWriter : https://github.com/mk-j/PHP_XLSXWriter/tree/master/examples
@@ -7,26 +7,22 @@ require_once (LIB_PATH.'SimpleXLSX'.SLASH.'SimpleXLSX.class.php');
 
 class Excel
 {
-	/** 
+	/**
 	 * Parse un fichier xlsx et retourne le contenu lignes / colonnes
 	 *  @param  string $xlsxFile : chemin vers le fichier a parser OU flux si $isStream = true
 	 *  @param  bool $isStream : définit si l'entrée est un fichier ou un flux
 	 * 	@param  int $sheetIndex : numero de l'onglet excel a parser (commence a 0)
 	 * 	@param  bool $cellInfos : si passé a true, ajoute des infos de cellule (type etc...) plus lent.
 	 */
-	
+
 	public static function parse($xlsxFile,$isStream = false,$sheetIndex=1,$cellInfos = false) {
 		$xlsx = SimpleXLSX::parse($xlsxFile,$isStream);
-		if(!$xlsx)  throw new Exception(SimpleXLSX::parseError());
-		if($cellInfos){
-			$rows = $xlsx->rowsEx($sheetIndex);
-		}else{
-			$rows = $xlsx->rows($sheetIndex);
-		}
+		if(!$xlsx) throw new Exception(SimpleXLSX::parseError());
+		$rows = ($cellInfos) ? $xlsx->rowsEx($sheetIndex) : $xlsx->rows($sheetIndex);
 		return $rows;
 	}
-	
-	/** 
+
+	/**
 	 * Retourne le contenu d'un tableau convertit au format XLSX
 	 * @param  array $rows      le tableau avec les lignes à exporter dans le fichier
 	 * @param  array $mapping   le mapping qui permet d'ajouter des libellé en fct des clés de colonne
@@ -38,7 +34,7 @@ class Excel
 	 * @param  string $sheetname le nom à donner à la feuille de calcul courante
 	 * @return string            le stream du fichier généré
 	 */
-	public static function exportArray($rows, $mapping, $sheetname='Classeur 1'){ 
+	public static function exportArray($rows, $mapping, $sheetname='Classeur 1'){
 		$data = $header = array();
 		$style = array(
 			'border'	=> 'top,left,bottom,right',
@@ -46,9 +42,8 @@ class Excel
 		);
 
 		if(empty($mapping) && isset($rows[0])){
-			foreach($rows[0] as $key=>$value){
+			foreach($rows[0] as $key=>$value)
 				$mapping[$key] = $key;
-			}
 		}
 
 		foreach ($rows as $key => $item) {
@@ -60,12 +55,11 @@ class Excel
 					isset($item[$slug]) ? array_push($itemContent, $item[$slug]) : array_push($itemContent, '');
 				}
 			} else {
-				foreach ($item as $field => $value) {
+				foreach ($item as $field => $value)
 					array_push($itemContent, $item[$field]);
-				}
 			}
 			array_push($data, $itemContent);
-		}	
+		}
 
 		ob_start();
 		$excel = new XLSXWriter();
@@ -75,9 +69,10 @@ class Excel
 
 		$excel->writeToStdOut();
 		$output = ob_get_clean();
+
 		return $output;
 	}
-	
+
 	/**
 	 * Export de données sur plusieurs feuilles Excel
 	 * @param array $content 	[Contenu à exporter]
@@ -109,12 +104,12 @@ class Excel
 	 *     	), etc...
 	 * );
 	 * On place généralement $response['rows'] dans l'index 'rows' d'une feuille Excel
-	 * 
+	 *
 	 * @param string $filename 	[Nom du fichier à exporter]
-	 * 
+	 *
 	 * @return string 			[Fichier XSLX]
 	 */
-	public static function exportMultipleSheets($content){ 
+	public static function exportMultipleSheets($content){
 		$commonStyle = array('border'=> 'top,left,bottom,right', 'border-style'=> 'thin');
 		$headerStyle = array_merge($commonStyle, array('font-style'=> 'bold','border-color'=> '#2a2a28'));
 		$contentStyle = array_merge($commonStyle, array('border-color'=> '#cecece'));

+ 24 - 70
class/FieldType.class.php

@@ -85,7 +85,7 @@ class FieldType{
 		);
 
 		$type_text->filter = array(
-			'operators' => array (
+			'operators' => array(
 				'like' =>array("view" =>'text'),
 				'not like' =>array("view" =>'text'),
 				'=' =>array("view" =>'text'),
@@ -126,13 +126,11 @@ class FieldType{
 		};
 
 		$type_text->onInput = function($field=array(),$options=array()){
-
 			$attributes = array_merge($options['type']->default_attributes,$field['attributes']);
 
 			if(isset($field['id'])) $field['attributes']['id'] ='"'.$field['id'].'"';
 
 			$html = '';
-
 			$html.= '<input  value="'.(isset($field['value']) ? str_replace('"','&quot;',$field['value']) : '').'"';
 			foreach ($field['attributes'] as $key => $value) {
 				$html.= ' ';
@@ -140,8 +138,8 @@ class FieldType{
 				if(!empty($value) && is_string($value)) $html.= '='.$value;
 				$html.= ' ';
 			}
-
 			$html.= '>';
+
 			return $html;
 		};
 		$types[$type_text->slug] = $type_text;
@@ -204,7 +202,6 @@ class FieldType{
 			$field['attributes']['data-data'] = $data;
 
 			$html = '';
-
 			$html.= '<input ';
 			foreach ($field['attributes'] as $key => $value) {
 				$html.= ' ';
@@ -225,10 +222,8 @@ class FieldType{
 				$meta = json_decode($options['field']->meta,true);
 
 				if(!empty($meta['limit']) && $meta['limit']>1) $limit =$meta['limit'] ;
-				if(!empty($meta['storage']))
-					$path = template($meta['storage'],$options['options'],true);
+				if(!empty($meta['storage'])) $path = template($meta['storage'],$options['options'],true);
 			}
-
 			File::save_component($options['field']->slug,$path.($limit==1?'':SLASH.$options['field']->slug).SLASH.'{{label}}');
 
 			return null;
@@ -236,7 +231,6 @@ class FieldType{
 
 		$type_file->onRawDisplay = function($value,$options = array()){
 			$value = '';
-
 			$meta = json_decode($options['meta'],true);
 
 			$templateData = array();
@@ -256,7 +250,6 @@ class FieldType{
 
 		$type_file->onHtmlDisplay = function($value,$options = array()){
 			$html = '';
-
 			$meta = json_decode($options['meta'],true);
 
 			$templateData = array();
@@ -264,7 +257,6 @@ class FieldType{
 				if(!is_string($option)) continue;
 				$templateData[$key] = $option;
 			}
-
 			$path = File::dir().template($meta['storage'],$templateData,true).'/*';
 			$html .=  '<ul class="list-group list-group-flush shadow-sm">';
 
@@ -284,7 +276,6 @@ class FieldType{
 		$type_file->default = '';
 		$types[$type_file->slug] = $type_file;
 
-
 		//Image
 		$type = new self();
 		$type->slug = 'image';
@@ -320,9 +311,7 @@ class FieldType{
 		);
 
 		$type->onInput = $type_file->onInput;
-
 		$type->onSave = $type_file->onSave;
-
 		$type->onHtmlDisplay = function($value,$options = array()){
 			$html = '<div class="fieldtype-image-cover">';
 			$meta = json_decode($options['meta'],true);
@@ -334,7 +323,6 @@ class FieldType{
 			}
 
 			$path = File::dir().template($meta['storage'],$templateData,true).'/*';
-
 			$files = glob($path);
 
 			$file = $files[0];
@@ -346,19 +334,16 @@ class FieldType{
 			if(count($files)>1) $html .= '<span><i class="far fa-file-image"></i> +'.count($files).' </span>';
 			$html .= '</div>';
 
-
 			return $html;
 		};
 
-		$type->onRawDisplay  = $type_file->onRawDisplay;
-
+		$type->onRawDisplay = $type_file->onRawDisplay;
 		$type->icon = 'far fa-image';
 		$type->description = "Envoi d'image";
 		$type->default = '';
 		$types[$type->slug] = $type;
 
 
-
 		//User
 		$type = new self();
 		$type->slug = 'user';
@@ -368,9 +353,8 @@ class FieldType{
 			'data-type'=>'"user"',
 		));
 
-
 		$type->filter = array(
-			'operators' => array (
+			'operators' => array(
 				'=' =>array("view" =>'user'),
 				'!='  =>array("view" =>'user'),
 				'like' =>array("view" =>'user'),
@@ -380,9 +364,7 @@ class FieldType{
 			)
 		);
 
-
 		$type->onInput  = $type_text->onInput;
-
 		$type->onRawDisplay = function($value,$options = array()){
 			if(empty($value)) return '';
 			$user = User::byLogin($value);
@@ -418,7 +400,7 @@ class FieldType{
 			return !$firm? '':$firm->label;
 		};
 		$type->filter = array(
-			'operators' => array (
+			'operators' => array(
 				'=' =>array("view" =>'firm'),
 				'!='  =>array("view" =>'firm'),
 				'null' =>array(),
@@ -449,14 +431,13 @@ class FieldType{
 			return !$rank? '':$rank->label;
 		};
 		$type->filter = array(
-			'operators' => array (
+			'operators' => array(
 				'=' =>array("view" =>'rank'),
 				'!='  =>array("view" =>'rank'),
 				'null' =>array(),
 				'not null' =>array()
 			)
 		);
-
 		$types[$type->slug] = $type;
 
 
@@ -485,7 +466,7 @@ class FieldType{
 			return $html ;
 		};
 		$type_longstring->filter = array(
-			'operators' => array (
+			'operators' => array(
 				'like' =>array("view" =>'text'),
 				'not like' =>array("view" =>'text'),
 				'=' =>array("view" =>'text'),
@@ -494,7 +475,6 @@ class FieldType{
 				'not null' =>array()
 			)
 		);
-
 		$type_longstring->icon = 'fas fa-text-width';
 		$type_longstring->description = 'Texte long multi ligne';
 		$type_longstring->default = '';
@@ -557,9 +537,8 @@ class FieldType{
 			return timestamp_date($value);
 		};
 
-
 		$type->filter = array(
-			'operators' => array (
+			'operators' => array(
 				'between' =>array("view" =>'date'),
 				'=' =>array("view" =>'date'),
 				'!='  =>array("view" =>'date'),
@@ -568,7 +547,6 @@ class FieldType{
 			)
 		);
 
-
 		$type->onInput  = $type_text->onInput;
 		$type->icon = 'far fa-calendar';
 		$type->description = 'Date au format jj/mm/aaaa';
@@ -598,7 +576,7 @@ class FieldType{
 			return $html;
 		};
 		$type->filter = array(
-			'operators' => array (
+			'operators' => array(
 				'in' =>array("view" =>'tag'),
 				'not in' =>array("view" =>'tag'),
 				'inline-and' =>array("view" =>'tag'),
@@ -615,9 +593,6 @@ class FieldType{
 			if($value==',,') $value = '';
 			return $value;
 		};
-
-
-
 		$types[$type->slug] = $type;
 
 
@@ -643,14 +618,13 @@ class FieldType{
 		);
 
 		$type->filter = array(
-			'operators' => array (
+			'operators' => array(
 				'=' =>array("view" =>'filepicker'),
 				'!='  =>array("view" =>'filepicker'),
 				'null' =>array(),
 				'not null' =>array()
 			)
 		);
-
 		$types[$type->slug] = $type;
 
 		//Heure
@@ -669,7 +643,7 @@ class FieldType{
 		$type->default = '';
 
 		$type->filter = array(
-			'operators' => array (
+			'operators' => array(
 				'<' =>array("view" =>'hour'),
 				'>' =>array("view" =>'hour'),
 				'=' =>array("view" =>'hour'),
@@ -677,7 +651,6 @@ class FieldType{
 				'not null' =>array()
 			)
 		);
-
 		$types[$type->slug] = $type;
 
 
@@ -749,7 +722,6 @@ class FieldType{
 					}
 				}
 			}
-
 			$html .='</select>';
 			return $html ;
 		};
@@ -805,8 +777,6 @@ class FieldType{
 			foreach($table as $key=>$value){
 				$stream .= ''.$key.' : '.$value.',';
 			}
-
-
 			return $stream;
 		};
 
@@ -821,7 +791,6 @@ class FieldType{
 			$html .= '</ul>';
 			return $html;
 		};
-
 		$types[$type->slug] = $type;
 
 		//Liste
@@ -882,8 +851,6 @@ class FieldType{
 					'data-format' => '"key-value"'
 				))
 		);
-
-
 		$types[$type_list->slug] = $type_list;
 
 
@@ -997,10 +964,7 @@ class FieldType{
 			$values = explode(',',$value);
 			if(count($values)==0) return '';
 
-
-
 			$results = array();
-
 			//dictionary
 			$ids = array();
 			foreach($values as $i=>$id){
@@ -1071,7 +1035,7 @@ class FieldType{
 		};
 
 		$type->filter = array(
-			'operators' => array (
+			'operators' => array(
 				'in' => array(
 					"view" =>'tag',
 					"value-separator" => ","
@@ -1145,7 +1109,7 @@ class FieldType{
 		$type->default = '';
 
 		$type->filter = array(
-			'operators' => array (
+			'operators' => array(
 				'like' => array("view" =>'text'),
 				'=' => array("view" =>'text'),
 				'!=' => array("view" =>'text'),
@@ -1207,7 +1171,7 @@ class FieldType{
 		};
 
 		$type->filter = array(
-			'operators' => array (
+			'operators' => array(
 				'=' => array("view" =>'text'),
 				'!=' => array("view" =>'text'),
 				'null' => array(),
@@ -1236,7 +1200,7 @@ class FieldType{
 		};
 
 		$type->filter = array(
-			'operators' => array (
+			'operators' => array(
 				'=' => array("view" =>'icon'),
 				'!=' => array("view" =>'icon'),
 				'null' => array(),
@@ -1267,7 +1231,7 @@ class FieldType{
 		));
 
 		$type->filter = array(
-			'operators' => array (
+			'operators' => array(
 				'=' => array("view" =>'price'),
 				'!=' => array("view" =>'price'),
 				'<' => array("view" =>'price'),
@@ -1307,7 +1271,7 @@ class FieldType{
 
 		$type->filter = array(
 			'attributes' => array('data-values'=>'"{{filterTypeValue}}"'),
-			'operators' => array (
+			'operators' => array(
 				'=' => array("view" =>'choice'),
 				'!=' => array("view" =>'choice'),
 				'null' => array(),
@@ -1322,7 +1286,8 @@ class FieldType{
 				'attributes'=> array(
 					'data-columns' => '\'{"key":"Clé","value":"Valeur"}\'',
 					'data-format' => '"key-value"'
-				))
+				)
+			)
 		);
 
 		$type->onInput  = function($field=array(),$options=array()){
@@ -1354,7 +1319,6 @@ class FieldType{
 		};
 
 		$type->onHtmlDisplay  = $type->onRawDisplay;
-
 		$type->icon = 'far fa-dot-circle';
 		$type->description = 'Choix unique';
 		$type->default = '';
@@ -1371,25 +1335,20 @@ class FieldType{
 			'class'=>'',
 			'type'=>'"checkbox"'
 		));
-
 		$type->filter = array(
-			'operators' => array (
+			'operators' => array(
 				'=' => array("view" =>'boolean'),
 				'null' => array(),
 				'not null' => array()
 			)
 		);
-
-
 		$type->onRawDisplay = function($value,$options = array()){
 			return $value ? 'VRAI' : 'FAUX';
 		};
-
 		$type->onHtmlDisplay  = function($value,$options = array()){
 			$html = $value ? '<i class="fas fa-check text-success"></i>' : '<i class="fas fa-times text-danger"></i>' ;
 			return $html;
 		};
-
 		$type->onInput = function($field=array(),$option=array()){
 			$html = '';
 
@@ -1412,9 +1371,6 @@ class FieldType{
 		$type->icon = 'far fa-check-square';
 		$type->description = 'Vrai ou Faux';
 		$type->default = '';
-
-
-
 		$types[$type->slug] = $type;
 
 		//Url
@@ -1439,7 +1395,7 @@ class FieldType{
 		};
 
 		$type->filter = array(
-			'operators' => array (
+			'operators' => array(
 				'=' => array("view" =>'url'),
 				'!=' => array("view" =>'url'),
 				'like' => array("view" =>'text'),
@@ -1476,7 +1432,7 @@ class FieldType{
 		};
 
 		$type->filter = array(
-			'operators' => array (
+			'operators' => array(
 				'=' => array("view" =>'mail'),
 				'!='  => array("view" =>'mail'),
 				'like'  => array("view" =>'text'),
@@ -1511,7 +1467,7 @@ class FieldType{
 		$type->default = '';
 
 		$type->filter = array(
-			'operators' => array (
+			'operators' => array(
 				'like' =>array("view" =>'text'),
 				'not like' =>array("view" =>'text'),
 				'=' =>array("view" =>'phone'),
@@ -1528,5 +1484,3 @@ class FieldType{
 		return $types;
 	}
 }
-
-?>

+ 38 - 59
class/File.class.php

@@ -1,7 +1,7 @@
 <?php
 
 class File{
-	
+
 	//Gère l'upload d'un fichier des vérifications au stockage dans le dossier file
 	public static function upload($index, $path, $maxSize=1048576, $extensions=array('jpg','png','jpeg','gif','bmp'), $trimParentDir=true){
 		if($trimParentDir) $path = str_replace('..','',$path);
@@ -10,15 +10,16 @@ class File{
 		$extension = getExt($_FILES[$index]['name']);
 		if($_FILES[$index]['size'] > $maxSize) throw new Exception("Taille du fichier trop grande, taille maximum :".readable_size($maxSize).' ('.$maxSize.' octets)');
 		if(is_array($extensions) && !in_array($extension , $extensions)) throw new Exception("Extension '".$extension."' du fichier non permise, autorisé :".implode(', ',$extensions));
+
 		$filePath = str_replace(array('/','\\','{{ext}}'),array(SLASH,SLASH,$extension),$path);
 		$fileName = basename($filePath);
 		$folderPath = dirname($filePath);
 		$folderAbsolutePath = self::dir().$folderPath;
 		$fileAbsolutePath = $folderAbsolutePath.SLASH.$fileName;
-		
+
 		if(!file_exists($folderAbsolutePath)) mkdir($folderAbsolutePath,0755,true);
 		if(!move_uploaded_file($_FILES[$index]['tmp_name'], $fileAbsolutePath)) throw new Exception("Impossible de déplacer le fichier envoyé");
-		
+
 		return array(
 			'absolute' => $fileAbsolutePath,
 			'relative' => $filePath,
@@ -49,7 +50,7 @@ class File{
 		if(!file_exists($folderAbsolutePath)) mkdir($folderAbsolutePath,0755,true);
 		if(!file_exists($file)) throw new Exception("Le fichier ".$file." n'existe pas",404);
 		if(!rename($file, $fileAbsolutePath)) throw new Exception("Impossible de déplacer le fichier envoyé");
-		
+
 		return array(
 			'absolute' => (get_OS() === 'WIN' ? iconv('UTF-8', 'UTF-8//IGNORE', utf8_encode($fileAbsolutePath)) : $fileAbsolutePath),
 			'relative' => (get_OS() === 'WIN' ? iconv('UTF-8', 'UTF-8//IGNORE', utf8_encode($filePath)) : $filePath),
@@ -60,15 +61,15 @@ class File{
 	public static function delete($namespace,$file,$trimParentDir = true,$ignoreExistence = false){
 		if($trimParentDir) $file = str_replace('..','',$file);
 		$namespace = trim($namespace, SLASH);
-		
+
 		$file =  $namespace.SLASH.substr($file, strlen($namespace)+1);
 		$file =  File::dir().$file;
 		$file =  str_replace(array('\\','/'),array(SLASH,SLASH),$file);
-		
+
 		if(!file_exists($file)){
 			if($ignoreExistence){
 				return;
-			}else{
+			} else {
 				throw new Exception("Le fichier '".$file."'  n'existe pas");
 			}
 		}
@@ -83,18 +84,13 @@ class File{
 		if($trimParentDir) $path = str_replace('..','',$path);
 		$hasFile = glob($path);
 		if(count($hasFile)==0) throw new Exception("Fichier inexistant :".$path);
-		$path = $hasFile[0];		
+		$path = $hasFile[0];
 
 		$stream = file_get_contents($path);
-		
-
 		$mime = !isset($mime) ? self::mime($path) : $mime;
-		
-		if(!isset($name)){
-			$name = (get_OS() === 'WIN') ? utf8_encode(basename($path)) : basename($path);
-		}
-	
-		if (ob_get_contents()) ob_end_clean();
+
+		if(!isset($name)) $name = (get_OS() === 'WIN') ? utf8_encode(basename($path)) : basename($path);
+		if(ob_get_contents()) ob_end_clean();
 		header("Content-Type: ".$mime);
 		header("Content-Length: " . strlen($stream));
 		header("Content-Disposition: ".($forceDownload?"attachment":"inline")."; filename=\"".utf8_decode($name)."\"");
@@ -106,13 +102,12 @@ class File{
 			header('Pragma: no-cache');
 			header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
 		}
-
-		echo $stream; 
+		echo $stream;
 	}
 
 	public static function downloadStream($stream, $name='Sans titre', $mime='application/octet-stream'){
-
 		if (ob_get_contents()) ob_end_clean();
+
 		header("Content-Type: ".$mime);
 		header("Content-Length: " . strlen($stream));
 		header('Expires: Sun, 01 Jan 2014 00:00:00 GMT');
@@ -121,10 +116,9 @@ class File{
 		header('Cache-Control: post-check=0, pre-check=0', FALSE);
 		header('Pragma: no-cache');
 		header("Content-Disposition: attachment; filename=\"".$name."\"");
-		echo $stream; 
-		
-	}
 
+		echo $stream;
+	}
 
 	public static function dir(){
 		return __ROOT__.FILE_PATH;
@@ -134,13 +128,13 @@ class File{
 	public static function core(){
 		return self::dir().'core';
 	}
-	
+
 	public static function temp(){
 		$path = self::dir().SLASH.'tmp'.SLASH;
 		if(!file_exists($path)) mkdir($path,0755,true);
 		return $path;
 	}
-	
+
 	public static function clear_temp(){
 		$time = time();
 		foreach(glob(self::temp().'*.*') as $file){
@@ -149,26 +143,24 @@ class File{
 		}
 	}
 
-
 	public static function copy($source,$destination,$trimParentDir = true){
 		if($trimParentDir) $source = str_replace('..','',$source);
 		if($trimParentDir) $destination = str_replace('..','',$destination);
 		$result = true;
 		if(is_file($source)) return copy($source,$destination);
-		$dir = opendir($source); 
-	    if(!file_exists($destination)) mkdir($destination,0755,true); 
-	    while(false !== ( $file = readdir($dir)) ) { 
-	        if (( $file != '.' ) && ( $file != '..' )) { 
-	            if ( is_dir($source . SLASH . $file) ) { 
-	               $result = self::copy($source.SLASH.$file,$destination.SLASH.$file); 
-	            } 
-	            else { 
-	               $copyResult = copy($source.SLASH.$file,$destination.SLASH.$file); 
+		$dir = opendir($source);
+	    if(!file_exists($destination)) mkdir($destination,0755,true);
+	    while(false !== ( $file = readdir($dir)) ) {
+	        if (( $file != '.' ) && ( $file != '..' )) {
+	            if ( is_dir($source . SLASH . $file) ) {
+	               $result = self::copy($source.SLASH.$file,$destination.SLASH.$file);
+	            } else {
+	               $copyResult = copy($source.SLASH.$file,$destination.SLASH.$file);
 	               if(!$copyResult) $result = false;
-	            } 
-	        } 
-	    } 
-	    closedir($dir); 
+	            }
+	        }
+	    }
+	    closedir($dir);
 	    return $result;
 	}
 
@@ -190,7 +182,7 @@ class File{
 					$destination = $originalDirectory.SLASH.$name.'('.$increment.').'.$ext;
 				}
 				copy($element, $destination);
-			}else{
+			} else {
 				$name = basename($element);
 				$destination = $originalDirectory.SLASH.$name;
 				if(!file_exists($destination)) mkdir($destination,0755,true);
@@ -213,7 +205,6 @@ class File{
 			'size' => $size,
 			'icon' => getExtIcon($extension)
 		);
-	
 	}
 
 
@@ -221,15 +212,13 @@ class File{
 		global $_;
 		if(!isset($_[$index])) return;
 		$destinationTpl = str_replace('/',SLASH,$destination);
-		
 		$saveds = array();
 
-
 		foreach($_[$index] as $file){
 			$destination = template($destinationTpl,$file,true);
 			$file = self::dir().$file['path'];
-			if(file_exists($file))
-				self::move($file,$destination);
+			if(file_exists($file)) self::move($file,$destination);
+
 			$saveds[] = array(
 				'absolute' => self::dir().$destination,
 				'relative' => $destination,
@@ -260,12 +249,10 @@ class File{
 
 				$storage = str_replace('/',SLASH,$options['storage']);
 				$storage = self::dir().template($storage,$_,true);
-				
-				
+
 				//si l'url contient // on considere qu'il lui manque des élements de masque et on annule le browse
 				//utile quand l'action est appellée alors qu'un parametre manque (ex: id de l'entité liée au fichier)
 				if(strpos($storage, '//') === false){
-
 					foreach(glob($storage, GLOB_BRACE) as $i=>$file){
 						if(!is_file($file)) continue;
 						$fileArray = self::toArray($file);
@@ -279,7 +266,7 @@ class File{
 				User::check_access($options['access'],'read');
 				$name = isset($_['name']) ? $_['name'] : null;
 				$path = self::dir().base64_decode($_['path']);
-				
+
 				try{
 					self::downloadFile($path,$name);
 				}catch(Exception $e){
@@ -301,15 +288,12 @@ class File{
 					$file = $_FILES[$_['index']];
 					$tempPath = self::temp().basename($file['tmp_name']);
 					move_uploaded_file($file['tmp_name'], $tempPath);
-				
+
 					$response = self::toArray($tempPath,$file['name']);
-			
 					$response['url'] = 'action.php?action='.$options['action'].'&type=download&name='.urlencode($response['label']).'&path='.base64_encode($response['path']);
 					$response['sort'] = $_['sort'];
 
-					if( in_array($response['extension'], array('png','gif','jpg','jpeg','bmp')) ) $response['preview'] = $response['url'];
-
-
+					if(in_array($response['extension'], array('png','gif','jpg','jpeg','bmp'))) $response['preview'] = $response['url'];
 				}catch(Exception $e){
 					$response['error'] = $e->getMessage();
 				}
@@ -318,16 +302,11 @@ class File{
 		return $response;
 	}
 
-
 	public static function convert_encoding($path){
 		return get_OS() === 'WIN' ? utf8_encode($path) : $path;
 	}
-	
+
 	public static function convert_decoding($path){
 		return get_OS() === 'WIN' ? utf8_decode($path) : $path;
 	}
-
-
 }
-
-?>

+ 1 - 4
class/Firm.class.php

@@ -7,11 +7,8 @@
  */
 class Firm extends Entity{
 	public $id,$label,$description,$mail,$phone,$fax,$street,$street2,$city,$zipcode,$siret,$iban;
-
 	public $entityLabel = 'Etablissement';
-
-	public $fields =
-	array(
+	public $fields = array(
 		'id' => array('label'=>'Identifiant', 'type'=>'key'),
 		'label' => array('label'=>'Libellé', 'type'=>'text'),
 		'description' => array('label'=>'Description', 'type'=>'textarea'),

+ 4 - 7
class/History.class.php

@@ -15,7 +15,7 @@ class History extends Entity{
 	public $importance; //Importance de message (Texte)
 	public $meta; //Meta données (Texte Long)
 	public $sort; //Ordre (int)
-	
+
 	const TYPE_READ = 'read';
 	const TYPE_COMMENT = 'comment';
 	const TYPE_EDIT = 'edit';
@@ -38,7 +38,6 @@ class History extends Entity{
 		'meta' => array('label'=> 'Meta informations' , 'type'=>'textarea')
 	);
 
-
 	function __construct(){
 		parent::__construct();
 		$this->importance = 'normal';
@@ -90,7 +89,7 @@ class History extends Entity{
 			$fieldKey = $difference['field'];
 			if(!isset($fields[$fieldKey])) continue;
 			$field =  $fields[$fieldKey];
-			
+
 			$value1 = $difference['value1'];
 			$value2 = $difference['value2'];
 
@@ -112,9 +111,9 @@ class History extends Entity{
 				//si le champs est une foreign key on affiche l'eventuel libellé de cette foreign key
 				if(isset($field['link'])){
 					require_once $field['link'];
-					$class =  str_replace('.class.php','',basename($field['link'])); 
+					$class =  str_replace('.class.php','',basename($field['link']));
 					if(property_exists($class,'label')){
-						
+
 						$instance1 = $class::getById($difference['value1']);
 						if($instance1) $value1 =  $instance1->label;
 
@@ -132,7 +131,6 @@ class History extends Entity{
 			}else{
 				$detail.=' modifié de <span class="font-weight-bold">'.truncate($value1,100).'</span> en <span class="font-weight-bold">'.truncate($value2,100).'</span>';
 			}
-			
 		}
 
 		$history = new History();
@@ -143,4 +141,3 @@ class History extends Entity{
 		$history->save();
 	}
 }
-?>

+ 17 - 18
class/Image.class.php

@@ -5,7 +5,7 @@ class Image {
 	public static function toJpg($path){
 		$infos = pathinfo($path);
 		if($infos['extension']=='jpg' || $infos['extension']=='jpeg') return $path;
-	
+
 		//Make image with white background instead of black when converting png to jpg
 		$input = self::resource($path);
 		list($width, $height) = getimagesize($path);
@@ -24,7 +24,7 @@ class Image {
 	public static function toPng($path){
 		$infos = pathinfo($path);
 		if($infos['extension']=='png') return;
-	
+
 		$input = self::resource($path);
 		list($width, $height) = getimagesize($path);
 		$output = imagecreatetruecolor($width, $height);
@@ -69,28 +69,28 @@ class Image {
 	    }
 
 	    $dst_resource = ImageCreateTrueColor($thumb_w,$thumb_h);
-    	
+
     	switch (mb_strtolower($infos['extension'])) {
     	    case 'png':
     	        $resource = ImageCreateFromPNG($path);
     	        imagealphablending($dst_resource, false);
-    	        imagecopyresampled($dst_resource,$resource,0,0,0,0,$thumb_w,$thumb_h,$oldX,$oldY); 
+    	        imagecopyresampled($dst_resource,$resource,0,0,0,0,$thumb_w,$thumb_h,$oldX,$oldY);
     	        imagesavealpha($dst_resource, true);
     	        $result = imagepng($dst_resource, $path, 4);
     	    break;
 
     	    case 'jpg':
     	    case 'jpeg':
-    	        imagecopyresampled($dst_resource,$resource,0,0,0,0,$thumb_w,$thumb_h,$oldX,$oldY); 
+    	        imagecopyresampled($dst_resource,$resource,0,0,0,0,$thumb_w,$thumb_h,$oldX,$oldY);
     	        $result = imagejpeg($dst_resource,$path,80);
     	    break;
-    	    
+
     	    default:
 	    	    //On ne peut pas resize les GIF (sans faire une usine à gaz)
 	    	    //On ne peut resize les BMP que depuis la v7.0 de PHP
     	    break;
     	}
-	    imagedestroy($dst_resource); 
+	    imagedestroy($dst_resource);
     	imagedestroy($resource);
 	}
 
@@ -120,9 +120,9 @@ class Image {
 
 	/*
 	Retourne une image selon l'angle définit
-	Prérequis systeme : 
-	- Installer le paquet imagemagick (apt-get install imagemagick) 
-	
+	Prérequis systeme :
+	- Installer le paquet imagemagick (apt-get install imagemagick)
+
 	nb: Si le pb "convert-im6.q16: not authorized `outfile.pdf' @ error/constitute.c/WriteImage/1037" apparait
 	editer /etc/ImageMagick-6/policy.xml et changer sur la ligne  PDFle droit  none à read|write .*/
 	public static function rotate($image,$destination,$degree){
@@ -133,11 +133,10 @@ class Image {
 		return $result;
 	}
 
-
 	/*
 	Concatene les images fournies en une seule
-	Prérequis systeme : 
-	- Installer le paquet imagemagick (apt-get install imagemagick) 
+	Prérequis systeme :
+	- Installer le paquet imagemagick (apt-get install imagemagick)
 	*/
 	public static function concatenate($images,$destinationPath){
 		$command = 'convert -limit width 100KP ';
@@ -150,16 +149,16 @@ class Image {
 
 	/*
 	Convertis le tableau de chemin d'images fournis en un PDF
-	Prérequis systeme : 
-	- Installer le paquet imagemagick (apt-get install imagemagick) 
-	
+	Prérequis systeme :
+	- Installer le paquet imagemagick (apt-get install imagemagick)
+
 	nb: Si le pb "convert-im6.q16: not authorized `outfile.pdf' @ error/constitute.c/WriteImage/1037" apparait
 	editer /etc/ImageMagick-6/policy.xml et changer sur la ligne  PDFle droit  none à read|write .*/
 	public static function toPDF($images,$pdfPath){
 		$command = 'convert ';
-		foreach ($images as $image) {
+		foreach($images as $image)
 			$command .= ' "'.$image.'" ';
-		}
+
 		$command .= ' -quality 100 "'.$pdfPath.'"';
 		$result = shell_exec ($command);
 	}

+ 13 - 17
class/JWToken.class.php

@@ -6,20 +6,17 @@
  * @license MIT
  */
 class JWToken {
-	
-	/* Décrypte une JWT Token avec la clé secrete fournie 
-	*/
+
+	/* Décrypte une JWT Token avec la clé secrete fournie */
 	public static function parse($encodedString,$key){
-		
 		$infos = explode('.', $encodedString);
-
-
 	    if(count($infos)!=3) throw new Exception("JWT error : incorrect format", 401);
 
 	    list($header64, $payloadb64, $signatureb64) = $infos;
 	    $header = $header64;
 	    $payload = $payloadb64;
-	    //header
+
+		//header
 	    $remainder = strlen($header) % 4;
 	    if ($remainder) {
 	        $padlen = 4 - $remainder;
@@ -27,7 +24,8 @@ class JWToken {
 	    }
 	    $header = base64_decode(strtr($header, '-_', '+/'));
 	    $header = json_decode($header,true);
-	    //payload
+
+		//payload
 	    $remainder = strlen($payload) % 4;
 	    if ($remainder) {
 	        $padlen = 4 - $remainder;
@@ -35,7 +33,8 @@ class JWToken {
 	    }
 	    $payload = base64_decode(strtr($payload, '-_', '+/'));
 	    $payload = json_decode($payload,true);
-	    //signature
+
+		//signature
 	    $remainder = strlen($signatureb64) % 4;
 	    if ($remainder) {
 	        $padlen = 4 - $remainder;
@@ -51,26 +50,23 @@ class JWToken {
 	    $status |= (mb_strlen($signature, '8bit') ^ mb_strlen($hash, '8bit'));
 	    $verify = ($status === 0);
 	    if(!$verify) throw new Exception("JWT error : bad signature or encryption key", 401);
-	  
+
 	    if($payload['exp']<time()) throw new Exception("JWT error : token is expired since ".date('d/m/Y H:i:s',$payload['exp']), 498);
-	    
 	    return $payload;
 	}
 
 	//Créé un token crypté en HS256 à partir du payload / clé privée fournis
-	public static function createFromJson($payload, $key)
-	{
-
+	public static function createFromJson($payload, $key) {
 	    $header = json_encode(array('typ' => 'JWT', 'alg' => 'HS256'));
 	    $payload = json_encode($payload);
+
 	   	$segments = array();
 	 	$segments[] = str_replace('=', '', strtr(base64_encode($header), '+/', '-_'));
 	 	$segments[] = str_replace('=', '', strtr(base64_encode($payload), '+/', '-_'));
 	    $signing_input = implode('.', $segments);
 	    $signature =  hash_hmac('SHA256', $signing_input, $key, true);
 	    $segments[] = str_replace('=', '', strtr(base64_encode($signature), '+/', '-_'));
+
 	    return implode('.', $segments);
 	}
-		
-}
-?>
+}

+ 9 - 22
class/Log.class.php

@@ -25,7 +25,7 @@ class Log extends Entity {
     }
 
     public static function put($label,$category = 'Général') {
-    
+
         $log = new self();
         $log->label = $label;
         $log->category = $category;
@@ -36,9 +36,6 @@ class Log extends Entity {
     //Compare deux instances d'une même entité et log
     //les differences entre les deux dans un format JSON
     public static function compare($old,$new = null,$metafunction=null){
-      
-
-       
         $log = new self();
         $log->label = array();
 
@@ -52,20 +49,15 @@ class Log extends Entity {
             $log->label['action'] = 'update';
             $log->label['fields'] = Entity::compare($old,$new);
         }
-    
+
         $log->label['entity'] = $old->tableName();
-        
-        
         $log->category = $log->label['entity'].'::compare';
         $log->ip = ip();
 
-        if(isset($metafunction))
-            $metafunction($log);
-        
+        if(isset($metafunction)) $metafunction($log);
 
         $log->label = json_encode($log->label);
         $log->save();
-
     }
 
     public static function clear($delay = 1){
@@ -73,7 +65,6 @@ class Log extends Entity {
        self::delete(array('created:<'=>$treshold));
     }
 
-    
     //Fonction permettant un benchmark simple et précis.
     public static function benchmark($title = ""){
         global $lastBench;
@@ -82,17 +73,16 @@ class Log extends Entity {
         $bt =  debug_backtrace();
 
         $newBench = array(
-                'time' =>  microtime(true),
-                'file' =>  str_replace(__ROOT__,'',$bt[0]['file']),
-                'line' =>  $bt[0]['line'],
-         );
+            'time' =>  microtime(true),
+            'file' =>  str_replace(__ROOT__,'',$bt[0]['file']),
+            'line' =>  $bt[0]['line'],
+        );
 
         $label = '';
         if(!isset($lastBench)){
             $label .= PHP_EOL.PHP_EOL.'['.($title=="" ? "BENCHMARK" : $title ).'] - Début requete > benchmark : '. number_format(microtime(true)-$_SERVER["REQUEST_TIME_FLOAT"],4).' ms'.PHP_EOL;
             $label .= PHP_EOL."\t".'=> '.$newBench['file'].PHP_EOL.PHP_EOL;
-           
-        }else{
+        } else {
             if($lastBench['file']!= $newBench['file'])  $label .= PHP_EOL."\t".'=> '.$newBench['file'].PHP_EOL;
             $time = $newBench['time'] - $lastBench['time'];
             $title.= ' L.'.$lastBench['line'].' > L.'.$newBench['line'].' '.$title;
@@ -105,7 +95,4 @@ class Log extends Entity {
         $newBench['time'] = $newBench['time'] - ( microtime(true) - $start);
         $lastBench = $newBench;
     }
-
-    
-    
-}
+}

+ 7 - 8
class/Mail.class.php

@@ -32,13 +32,12 @@ class Mail{
 
 		// clé aléatoire de limite
 		$boundary = md5(uniqid(microtime(), TRUE));
-		 
+
 		// Headers
 		$headers = 'From: '.$this->expeditor."\r\n";
 		$headers .= "Reply-to: ".$this->reply."\r\n";
 		$headers .= 'X-Mailer: PHP/' . phpversion(). "\r\n" ;
 
-
 		if(isset($this->recipients['cc']) &&  count($this->recipients['cc'])>0) $headers .= 'Cc: '.implode(',',$this->recipients['cc']) . "\r\n";
      	if(isset($this->recipients['cci']) && count($this->recipients['cci'])>0) $headers .= 'Bcc: '.implode(',',$this->recipients['cci']) . "\r\n";
 
@@ -46,8 +45,8 @@ class Mail{
 		$headers .= 'Mime-Version: 1.0'."\r\n";
 		$headers .= 'Content-Type: multipart/mixed;boundary='.$boundary."\r\n";
 		$headers .= "\r\n";
-		 
-	
+
+
 		// Message
 		$stream = '--'.$boundary."\r\n";
 		$stream .= 'Content-Type: multipart/alternative; boundary="alt-'.$boundary."\"\r\n\r\n";
@@ -71,7 +70,7 @@ class Mail{
 		$stream .= $this->message.'</body></html>'."\r\n\r\n";
 		$stream .= '--alt-'.$boundary."--\r\n\r\n";
 
-		foreach($this->attachments as $attachment):
+		foreach($this->attachments as $attachment) {
 			$stream .= '--'.$boundary."\r\n";
 			if(isset($attachment['cid'])) {
 				$stream .= 'Content-Disposition: inline; filename="'.utf8_decode($attachment['name']).'"'."\r\n";
@@ -85,14 +84,14 @@ class Mail{
 				$stream .= 'Content-Disposition:attachment; filename="'.utf8_decode($attachment['name']).'"'."\n\n";
 				$stream .= chunk_split(base64_encode($attachment['stream']))."\r\n";
 			}
-		endforeach;
+		}
 
 		// Fin
 		$stream .= '--'.$boundary.'--';
-		
+
 		$title = mb_encode_mimeheader($this->title,'UTF-8');
 		try{
-			set_error_handler(function($errno, $errstr, $errfile, $errline, array $errcontext) { 
+			set_error_handler(function($errno, $errstr, $errfile, $errline, array $errcontext) {
 				throw new Exception("Erreur d'envoi de mail n°".$errno." :".$errstr);
 			});
 			mail(implode(',',array_unique($this->recipients['to'])), $title, $stream, $headers);

+ 14 - 14
class/Pdf.class.php

@@ -1,9 +1,9 @@
-<?php 
+<?php
 /**
 	Classe de génération des PDF à partir d'un flux html.
 	Fonctionne sous linux et windows, necessite les binaires wkhtml placés dans "erp\lib\wkhtmltopdf"
-	
-	Sous linux : 
+
+	Sous linux :
 	sudo wget https://github.com/wkhtmltopdf/wkhtmltopdf/releases/download/0.12.4/wkhtmltox-0.12.4_linux-generic-amd64.tar.xz
 	sudo tar xvf wkhtmltox-0.12.4_linux-generic-amd64.tar.xz
 	sudo mv wkhtmltox/bin/wkhtmlto* /usr/bin/
@@ -14,7 +14,7 @@
 	echo xvfb-run -a -s "-screen 0 640x480x16" wkhtmltopdf "$@" > /usr/local/bin/wkhtmltopdf.sh
 	sudo chmod a+x /usr/local/bin/wkhtmltopdf.sh
 
-	ex utilisation : 
+	ex utilisation :
 
 	$pdf = new Pdf('<h1>Hello World</h1>');
 	$pdf->orientation = 'Landscape';
@@ -27,16 +27,16 @@
 	Pour ajouter un header, il faut ajouter les éléments suivants :
 	<!-- #header --> avant le contenu du header
 	<!-- /header --> après le contenu du header
-	
+
 	De même avec le footer (remplacer header par footer)
-	
+
 	@author v.carruesco, v.morreel
 	@version 2.0
 **/
 class Pdf{
 	public $html,$orientation,$margin,$css;
 
-	function __construct($html = null, $margin = array(), $format = 'A4', $orientation = 'Portrait'){
+	function __construct($html=null, $margin=array(), $format='A4', $orientation='Portrait'){
 		$this->html = $html;
 		$this->margin = (object) array(
 			'top' => isset($margin['top']) ? $margin['top'] : '10',
@@ -53,7 +53,7 @@ class Pdf{
 	// le format fdf brut (utile uniquement pour du débug ou pour de l'interne)
 	// NB : Penser a installer ``apt-get install pdftk`` (ou pdftk pour windows) sur le système avant de lancer ce script
 	public static function extractData($file,$onlyfdf = false){
-		
+
 		$command = 'pdftk '.$file.' generate_fdf output -';
 		$datastream = shell_exec($command);
 		if($onlyfdf) return $datastream;
@@ -92,7 +92,7 @@ class Pdf{
 		file_put_contents($fdfPath, $fdf);
 		$command = 'pdftk '.$file.' fill_form '.$fdfPath.' output "'.$pdfPath.'"';
 		if($flat) $command.=' flatten';
-		
+
 		shell_exec($command);
 		$datastream = file_get_contents($pdfPath);
 		unlink($pdfPath);
@@ -103,9 +103,9 @@ class Pdf{
 
 	/*
 	Convertis le tableau de chemin d'images fournis en un PDF
-	Prérequis systeme : 
-	- Installer le paquet imagemagick (apt-get install imagemagick) 
-	
+	Prérequis systeme :
+	- Installer le paquet imagemagick (apt-get install imagemagick)
+
 	nb: Si le pb "convert-im6.q16: not authorized `outfile.pdf' @ error/constitute.c/WriteImage/1037" apparait
 	editer /etc/ImageMagick-6/policy.xml et changer sur la ligne "<policy domain="coder" rights="none" pattern="PDF" />" PDF le droit none à read|write .*/
 	public static function fromImage($images,$pdfPath){
@@ -128,7 +128,7 @@ class Pdf{
 	        	$urls = $match[2];
 	        	foreach ($urls as $key => $url) {
 	        		if (preg_match("/asset=(.*.woff(2?))/i", $url, $asset)) {
-						$path = get_asset_absolute_path($asset[1]);        		
+						$path = get_asset_absolute_path($asset[1]);
 	        			$body = str_replace($url, $path, $body);
 	        		}
 	        	}
@@ -147,7 +147,7 @@ class Pdf{
         if(preg_match("/<!--[\s\t\r\n]*#header[\s\t\r\n]*-->(.*)<!--[\s\t\r\n]*\/header[\s\t\r\n]*-->/isU", $body, $match))
         	$header = $match[0];
 
-        //Récupération du footer pdf 
+        //Récupération du footer pdf
         if(preg_match("/<!--[\s\t\r\n]*#footer[\s\t\r\n]*-->(.*)<!--[\s\t\r\n]*\/footer[\s\t\r\n]*-->/isU", $body, $match))
         	$footer = $match[0];
 

+ 23 - 39
class/Plugin.class.php

@@ -39,29 +39,28 @@ class Plugin{
 	}
 
 	public static function addHook($hookName, $functionName){
-		$GLOBALS['hooks'][$hookName][] = $functionName;  
+		$GLOBALS['hooks'][$hookName][] = $functionName;
 	}
 
 	public static function callHook($hookName, $hookArguments = array()) {
 		if(!isset($GLOBALS['hooks'][$hookName])) return;
 		foreach($GLOBALS['hooks'][$hookName] as $functionName)
-			call_user_func_array($functionName, $hookArguments);  
+			call_user_func_array($functionName, $hookArguments);
 	}
-	
+
 	public static function includeAll(){
 		global $myFirm;
 		$validFirm = is_object($myFirm) && is_numeric($myFirm->id) && $myFirm->id!=-1;
 		foreach(self::getAll() as $plugin) {
 			if(!$plugin->state) continue;
 			if($validFirm && !in_array($myFirm->id, $plugin->firms)) continue;
-			
+
 			$main = $plugin->path().SLASH.$plugin->folder.'.plugin.php';
 			if(file_exists($main)) require_once($main);
 		}
 	}
-	
+
 	public static function getAll($enableOnly = false,$includeCore = false){
-		
 		$plugins = array();
 		foreach(glob(__ROOT__.PLUGIN_PATH.'*'.SLASH.'app.json') as $file){
 			$plugin = self::parseManifest($file);
@@ -70,32 +69,23 @@ class Plugin{
 		}
 
 		if($includeCore) $plugins[] = self::parseManifest('.');
-		
 
 		usort($plugins, function($a, $b){
-			if ($a->name == $b->name) 
-				$result = 0;
-
-			if($a->name < $b->name){
-				$result = -1;
-			} else{
-				$result = 1;
-			}
-			return  $result;
+			return strcmp($a->name, $b->name);
 		});
 		return $plugins;
 	}
-	
+
 	public static function getById($id){
 		$plugin = false;
 		foreach(self::getAll() as $onePlugin)
 			if($onePlugin->id==$id) $plugin = $onePlugin;
 		return $plugin;
 	}
-	
+
 	public static function parseManifest($file){
 
-		//si on cible le coeur
+		//Si on cible le coeur
 		if($file=='.' || basename(dirname($file)) == 'class'){
 			$plugin = new Plugin();
 			$plugin->name = 'Coeur logiciel';
@@ -112,7 +102,7 @@ class Plugin{
 			$plugin->core = true;
 			$plugin->color ='#222222';
 			$plugin->icon = 'fas fa-bullseye';
-		//si c'est un plugin classique
+		//Si c'est un plugin classique
 		}else{
 			$enabled = self::states();
 			$plugin = new self();
@@ -134,31 +124,28 @@ class Plugin{
 			if(isset($manifest['core'])) $plugin->core = $manifest['core'];
 			if(isset($manifest['color'])) $plugin->color = $manifest['color'];
 			if(isset($manifest['icon'])) $plugin->icon = $manifest['icon'];
-			if(isset($manifest['require'])) $plugin->require = isset($manifest['require'])? $manifest['require']: array();
+			if(isset($manifest['require'])) $plugin->require = isset($manifest['require']) ? $manifest['require'] : array();
 		}
 		return $plugin;
 	}
-	
+
 	public static function state($id,$state){
 		$enabled = self::states();
 		$plugin = self::getById($id);
-		
+
 		$main = $plugin->path().SLASH.$plugin->folder.'.plugin.php';
-		if(file_exists($main))
-			require_once($main);
-		
+		if(file_exists($main)) require_once($main);
+
 		if($state==0){
 			unset($enabled[$plugin->id]);
 			Plugin::callHook('uninstall',array($plugin->id));
 		} else {
-			if(!isset($enabled[$plugin->id]))
-				$enabled[$plugin->id] = array();
+			if(!isset($enabled[$plugin->id])) $enabled[$plugin->id] = array();
 			Plugin::callHook('install',array($plugin->id));
 		}
-		
 		self::states($enabled);
 	}
-	
+
 	public static  function states($states = false){
 		$enabledFile = File::core().SLASH.'plugin.json';
 		if(!file_exists($enabledFile)) touch($enabledFile);
@@ -174,7 +161,6 @@ class Plugin{
 		return isset($enabled[$id]);
 	}
 
-	
 	public function path(){
 		if($this->folder=='.') return __ROOT__.SLASH.'class';
 		return __ROOT__.PLUGIN_PATH.$this->folder;
@@ -189,14 +175,12 @@ class Plugin{
 		return ROOT_URL.'/'.str_replace(SLASH, '/', PLUGIN_PATH).basename(dirname($bt[0]['file']));
 	}
 
-
-	public static function addCss($css,$options = array('forcePath'=>false)) { 
+	public static function addCss($css,$options = array('forcePath'=>false)) {
 		if(!$options['forcePath']){
 			$bt =  debug_backtrace();
 			if(substr($css, 0,4) != 'http') $css = str_replace(array(__ROOT__,'\\'),array('','/'),dirname($bt[0]['file'])).$css;
 		}
-		
-		$GLOBALS['hooks']['css_files'][] = $css;  
+		$GLOBALS['hooks']['css_files'][] = $css;
 	}
 
 	public static function callCss($root = null,$cacheVersion = ''){
@@ -209,12 +193,12 @@ class Plugin{
 		}
 		return $stream;
 	}
-	
-	public static function addJs($js){  
+
+	public static function addJs($js){
 		global $_;
 		$bt =  debug_backtrace();
 		if(substr($js, 0,4) != 'http') $js = str_replace(array(__ROOT__,'\\'),array('','/'),dirname($bt[0]['file'])).$js;
-		$GLOBALS['hooks']['js_files'][] = $js;  
+		$GLOBALS['hooks']['js_files'][] = $js;
 	}
 
 	public static function callJs($root = null,$cacheVersion = ''){
@@ -232,7 +216,7 @@ class Plugin{
 	/*
 	 * Aide à l'inclusion de classes de plugin, ex:
 	 * require_once('..'.SLASH.'plugin'.SLASH.'issue'.SLASH.'Event.class.php');
-	 * 	devient : 
+	 * 	devient :
 	 * Plugin::need('issue/Event');
 	 * Il est possible de faires des inclusions mulitples, ex :
 	 * Plugin::need('issue/Event, client/Client, client/ClientContact');

+ 0 - 24
class/Rank.class.php

@@ -14,28 +14,4 @@ class Rank extends Entity {
 		'description' => array('label'=> 'Description' , 'type'=>'textarea'),
 		'superadmin' => array('label'=> 'Rang super administrateur' , 'type'=>'boolean')
 	);
-
-	function setId($id){
-		$this->id = $id;
-	}
-	
-	function getId(){
-		return $this->id;
-	}
-
-	function getLabel(){
-		return $this->label;
-	}
-
-	function setLabel($label){
-		$this->label = $label;
-	}
-
-	function getDescription(){
-		return $this->description;
-	}
-
-	function setDescription($description){
-		$this->description = $description;
-	}
 }

+ 2 - 4
class/Right.class.php

@@ -23,11 +23,9 @@ class Right extends Entity {
         'targetUid' => array('label'=>'Identifiant de l\'entité cible', 'type'=>'integer')
     );
 
-   
-
     //Colonnes indexées
     public $indexes = array('firm', 'targetScope', 'targetUid', 'scope', 'uid');
-    
+
     //enregistrement d'un droit possible sur un module, une entité ...
     public static function register($scope,$options){
         //options par defaut
@@ -41,7 +39,7 @@ class Right extends Entity {
             }
         ),$options);
 
-        $GLOBALS['rights'][$scope] = $options;  
+        $GLOBALS['rights'][$scope] = $options;
     }
 
     //récuperation des meta information d'un droit

+ 1 - 35
class/User.class.php

@@ -544,7 +544,6 @@ class User extends Entity {
 
     public function disconnect($redirect=null){
         global $conf;
-
         if(isset($this->login)) $this->preference('cookie','');
 
         $url = 'index.php';
@@ -561,38 +560,6 @@ class User extends Entity {
         return $url;
     }
 
-    public function setLogin($login){
-        $this->login = $login;
-    }
-
-    public function setName($name){
-        $this->name = $name;
-    }
-
-    public function setFirstName($firstname){
-        $this->firstname = $firstname;
-    }
-
-    public function setMail($mail){
-        $this->mail = $mail;
-    }
-
-    public function setPhone($phone){
-        $this->phone = $phone;
-    }
-
-    public function setMobile($mobile){
-        $this->mobile = $mobile;
-    }
-
-    public function setFunction($function){
-        $this->function = $function;
-    }
-
-    public function setGroups($groups){
-        $this->groups = $groups;
-    }
-
     public static function generateToken(){
         return substr(md5(uniqid(rand(), true)),0,10);
     }
@@ -620,8 +587,7 @@ class User extends Entity {
         return $ranks;
     }
 
-
-        //Retourne un objet manager (User vide si pas de manager) quel que soit le provider d'entré (ad : objet, db: login)
+    //Retourne un objet manager (User vide si pas de manager) quel que soit le provider d'entré (ad : objet, db: login)
     public function manager(){
         $manager = new User();
         if(!isset($this->manager)) return $manager;

+ 1 - 1
class/UserFirmRank.class.php

@@ -8,7 +8,7 @@
 class UserFirmRank extends Entity{
 	public $id,$firm,$user,$rank;
 	protected $TABLE_NAME = 'user_firm_rank';
-	
+
 	public $entityLabel = 'Rang d\'utilisateur pour un établissement';
 	protected $fields = array(
 		'id' => array('label'=>'Identifiant', 'type'=>'key'),

+ 2 - 3
class/UserPreference.class.php

@@ -9,11 +9,10 @@ class UserPreference extends Entity{
 	public $id,$user,$key,$value;
 	public $TABLE_NAME = 'user_preference';
 	public $entityLabel = 'Préférence utilisateur';
-	public $links = array( 
+	public $links = array(
 		'user' => 'User.login'
 	);
-	public $fields =
-	array(
+	public $fields = array(
 		'id' => array('label'=>'Identtifiant', 'type'=>'key'),
 		'user' => array('label'=>'Utilisateur', 'type'=>'user'),
 		'key' => array('label'=>'Clé', 'type'=>'text'),

+ 11 - 11
common.php

@@ -1,4 +1,4 @@
-<?php 
+<?php
 $start_time = microtime(TRUE);
 $now = intval($start_time);
 
@@ -59,7 +59,7 @@ Configuration::setting('configuration-global',array(
 		"data-action"=>"core_general_logo",
 		"data-id"=>"logo-light",
 		"data-data"=>"{\"variant\":\"light\"}",
-		
+
 	)),
 	"logo-dark" => array("label"=>"Logo application (sombre)", "legend"=>"S'appliquera sur les fonds clairs de l'ensemble des établissements", "type"=>"image"/*, "default"=>"img/logo/default-logo.dark.png"*/, "attributes"=>array(
 		"data-action"=>"core_general_logo",
@@ -137,7 +137,7 @@ if($myUser->login==null && isset($_COOKIE[COOKIE_NAME])){
 		Log::put("Cookie trouvé, connexion via le cookie", 'Utilisateur');
 	    if(Plugin::is_active('fr.core.activedirectory'))
 	        require_once(PLUGIN_PATH.'activedirectory'.SLASH.'activedirectory.plugin.php');
-	    
+
 	    $myUser = User::byLogin($cookie->user);
         if($myUser!=false){
         	Log::put("Utilisateur trouvé lors de la connexion via le cookie", 'Utilisateur');
@@ -180,7 +180,7 @@ Plugin::addHook("menu_setting", function(&$settingMenu){
 		'icon' => 'fas fa-angle-right',
 		'label' => 'Général',
 	);
-	
+
 	if($myUser->can('plugin','configure'))
 		$settingMenu[]= array(
 			'sort' =>18,
@@ -241,7 +241,7 @@ Plugin::addHook("menu_setting", function(&$settingMenu){
 			'label' => 'Logs',
 			'category' => 'administration'
 		);
-	
+
 	if($myUser->login!='')
 		$settingMenu[]= array(
 			'sort' =>16,
@@ -254,7 +254,7 @@ Plugin::addHook("menu_setting", function(&$settingMenu){
 
 Plugin::addHook("menu_main", function(&$mainMenu) {
 	global $myUser;
-	
+
 	if(!$myUser->connected()) return;
 	$mainMenu[] = array(
 		'sort' =>0,
@@ -291,7 +291,7 @@ Plugin::addHook("menu_user", function(&$userMenu){
 
 		foreach ($myUser->firms as $firm)
 			$options .= '<option '.($myFirm->id == $firm->id ? "selected='selected'":"").' value="'.$firm->id.'">'.$firm->label.'</option>';
-		
+
 		$userMenu[]= array(
 			'sort' => 1,
 			'custom' => "<div class='firm-item mt-2' onclick='event.stopPropagation();'><small class='mb-1'>Établissement : </small><select class=\"form-control form-control-sm\" onchange=\"window.location='action.php?action=core_firm_select&firm='+$(this).val();\">".$options."</select></div><div class='dropdown-divider mb-1'></div>",
@@ -363,7 +363,7 @@ Plugin::addHook("rewrite", function ($requested){
 	$file = File::dir().$requested;
 	$file = preg_replace('/\?v=[a-z0-9]*/i','',$file);
 	$files = glob($file);
-	
+
 	if(count($files) ==0){
 		$file = __ROOT__.'/img/image-not-found.jpg';
 	}else{
@@ -398,7 +398,7 @@ Plugin::addHook("page", function(){
 
     if(!file_exists($file)) throw new Exception("Page ".$page." inexistante");
     require_once($file);
-}); 
+});
 
 
 Plugin::addHook("content_setting", function(){
@@ -433,12 +433,12 @@ Plugin::addHook("cron",function($time){
 	if(date('H:i', $time)!='01:00') return;
 	//Clear automatique des logs
 	global $conf;
-	foreach(Log::staticQuery('SELECT DISTINCT category FROM {{table}}',array(),true) as $log): 
+	foreach(Log::staticQuery('SELECT DISTINCT category FROM {{table}}',array(),true) as $log):
 		$slug = slugify($log->category);
 		$key = 'log_retention_time_'.$slug;
 		if($conf->get($key)=='') continue;
 		Log::clear($conf->get($key));
-	endforeach; 
+	endforeach;
 });
 
 Plugin::includeAll();

+ 6 - 6
connector/Mysql.class.php

@@ -23,7 +23,7 @@ class Mysql
 	}
 
 	public static function operators($key=null){
-		$operators =  
+		$operators =
 		array(
 
 				'in'=> array(
@@ -62,7 +62,7 @@ class Mysql
 						'slug'=> 'like',
 						'label'=>'Contient',
 						'sql'=>function($column,$values,&$query,&$data){
-				
+
 							$data[] = '%'.$values[0].'%';
 							$query .= ' '.$column.' LIKE ?' ;
 						}
@@ -71,7 +71,7 @@ class Mysql
 						'slug'=> 'not like',
 						'label'=>'Ne contient pas',
 						'sql'=>function($column,$values,&$query,&$data){
-				
+
 							$data[] = '%'.$values[0].'%';
 							$query .= ' '.$column.' NOT LIKE ?' ;
 						}
@@ -130,7 +130,7 @@ class Mysql
 							}
 					$query .= ' ) ';
 				})
-			
+
 		);
 		if(!isset($key)) return $operators;
 		return isset($operators[$key]) ?$operators[$key] : array('label'=>'Non définit','sql'=>'');
@@ -155,7 +155,7 @@ class Mysql
             }
             $field['tag'] = implode(' AND ',$field['tag']);
 		}else if($field['operator'] == 'IN' || $field['operator'] == 'NOT IN'){
-            $field['tag'] = array(); 
+            $field['tag'] = array();
 
             $valueArray = !is_array($value)?explode(',',$value) : $value;
             foreach ($valueArray as $v2) {
@@ -196,7 +196,7 @@ class Mysql
 		$pdo->exec("set names utf8");
 		$pdo->exec("SET time_zone='".TIME_ZONE."'");
 	}
-	
+
 	public static function select(){
 		$sql = 'SELECT {{:selected}}{{value}}{{;}},{{/;}}{{/:selected}} FROM `{{table}}` {{?joins}}{{:joins}}LEFT JOIN `{{jointable2}}` {{jointableAlias}} ON `{{jointable1}}`.{{field1}}= `{{jointableAlias}}`.{{field2}} {{/:joins}}{{/?joins}} {{?filter}} WHERE {{:filter}} `{{table}}`.`{{key}}` {{operator}} {{value}} {{postoperator}} {{;}} AND {{/;}} {{/:filter}} {{/?filter}} {{?orderby}}ORDER BY {{:orderby}}{{value}}{{;}},{{/;}}{{/:orderby}} {{/?orderby}} {{?limit}}LIMIT {{:limit}}{{value}}{{;}},{{/;}}{{/:limit}}{{/?limit}}';
 		return $sql;

+ 9 - 9
connector/Oracle.class.php

@@ -31,7 +31,7 @@ class Oracle
 	}
 
 	public static function operators($key=null){
-		$operators =  
+		$operators =
 		array(
 
 				'in'=> array(
@@ -70,7 +70,7 @@ class Oracle
 						'slug'=> 'like',
 						'label'=>'Contient',
 						'sql'=>function($column,$values,&$query,&$data){
-				
+
 							$data[] = '%'.$values[0].'%';
 							$query .= ' '.$column.' LIKE ?' ;
 						}
@@ -79,7 +79,7 @@ class Oracle
 						'slug'=> 'not like',
 						'label'=>'Ne contient pas',
 						'sql'=>function($column,$values,&$query,&$data){
-				
+
 							$data[] = '%'.$values[0].'%';
 							$query .= ' '.$column.' NOT LIKE ?' ;
 						}
@@ -138,23 +138,23 @@ class Oracle
 							}
 					$query .= ' ) ';
 				})
-			
+
 		);
 		if(!isset($key)) return $operators;
 		return isset($operators[$key]) ?$operators[$key] : array('label'=>'Non définit','sql'=>'');
 	}
 
 	public static function processField(&$field,&$value,&$values,&$i){
-		
+
 		if($field['type'] == 'date'){
-			
+
 			$field['operator'].= ' to_date( ';
 			$field['postoperator'].= ',\'YYYY-MM-DD\')';
 		}
 		switch($field['operator']){
 			case 'IN':
 			case 'NOT IN':
-	            $field['tag'] = array(); 
+	            $field['tag'] = array();
 	            $valueArray = !is_array($value)?explode(',',$value) : $value;
             	foreach ($valueArray as $v2) {
 	                $tag = ':'.$i;
@@ -196,7 +196,7 @@ class Oracle
 	}
 
 
-	
+
 	public static function select(){
 		$sql = 'SELECT {{:selected}}{{value}}{{;}},{{/;}}{{/:selected}} FROM "{{table}}" {{?joins}}{{:joins}}LEFT JOIN "{{jointable2}}" {{jointableAlias}} ON "{{jointable1}}".{{field1}}= "{{jointableAlias}}".{{field2}} {{/:joins}}{{/?joins}} {{?filter}} WHERE {{:filter}} "{{table}}"."{{key}}" {{operator}} {{value}} {{postoperator}} {{;}} AND {{/;}} {{/:filter}} {{/?filter}} {{?orderby}}ORDER BY {{:orderby}}{{value}}{{;}},{{/;}}{{/:orderby}} {{/?orderby}}{{?limit}}FETCH NEXT {{:limit}}{{value}}{{;}}{{/;}} ROWS ONLY{{/:limit}}{{/?limit}}';
 		return $sql;
@@ -264,7 +264,7 @@ class Oracle
 		return $sql;
 	}
 	public static function show_columns(){
-	  $sql = "SELECT COLUMN_NAME \"column\",DATA_TYPE \"type\" 
+	  $sql = "SELECT COLUMN_NAME \"column\",DATA_TYPE \"type\"
 		FROM user_tab_cols
 		WHERE table_name = '{{table}}' AND USER_GENERATED = 'YES'";
 	  return $sql;

+ 7 - 7
connector/SqlServer.class.php

@@ -32,7 +32,7 @@ class SqlServer
 	}
 
 	public static function operators($key=null){
-		$operators =  
+		$operators =
 		array(
 
 				'in'=> array(
@@ -71,7 +71,7 @@ class SqlServer
 						'slug'=> 'like',
 						'label'=>'Contient',
 						'sql'=>function($column,$values,&$query,&$data){
-				
+
 							$data[] = '%'.$values[0].'%';
 							$query .= ' '.$column.' LIKE ?' ;
 						}
@@ -80,7 +80,7 @@ class SqlServer
 						'slug'=> 'not like',
 						'label'=>'Ne contient pas',
 						'sql'=>function($column,$values,&$query,&$data){
-				
+
 							$data[] = '%'.$values[0].'%';
 							$query .= ' '.$column.' NOT LIKE ?' ;
 						}
@@ -139,7 +139,7 @@ class SqlServer
 							}
 					$query .= ' ) ';
 				})
-			
+
 		);
 		if(!isset($key)) return $operators;
 		return isset($operators[$key]) ?$operators[$key] : array('label'=>'Non définit','sql'=>'');
@@ -155,7 +155,7 @@ class SqlServer
             }
             $field['tag'] = implode(' AND ',$field['tag']);
 		}else if($field['operator'] == 'IN' || $field['operator'] == 'NOT IN'){
-            $field['tag'] = array(); 
+            $field['tag'] = array();
             $valueArray = !is_array($value)?explode(',',$value) : $value;
             foreach ($valueArray as $v2) {
                 $tag = ':'.$i;
@@ -194,7 +194,7 @@ class SqlServer
 	public static function beforeTransaction($pdo){
 		$pdo->exec("set names utf8");
 	}
-	
+
 	public static function select(){
 		$sql = 'SELECT {{:selected}}{{value}}{{;}},{{/;}}{{/:selected}} FROM "{{table}}" {{?joins}}{{:joins}}LEFT JOIN "{{jointable2}}" {{jointableAlias}} ON "{{jointable1}}".{{field1}}= {{jointableAlias}}.{{field2}} {{/:joins}}{{/?joins}} {{?filter}} WHERE {{:filter}} "{{table}}"."{{key}}" {{operator}} {{value}} {{postoperator}} {{;}} AND {{/;}} {{/:filter}} {{/?filter}} {{?orderby}}ORDER BY {{:orderby}}{{value}}{{;}},{{/;}}{{/:orderby}} {{/?orderby}} {{?limit}}LIMIT {{:limit}}{{value}}{{;}},{{/;}}{{/:limit}}{{/?limit}}';
 		return $sql;
@@ -266,7 +266,7 @@ class SqlServer
 	  $sql = "select * from information_schema.columns where table_name = '{{table}}'";
 	  return $sql;
 	}
-	
+
 
 }
 

+ 9 - 9
connector/Sqlite.class.php

@@ -29,7 +29,7 @@ class Sqlite
 	}
 
 	public static function operators($key=null){
-		$operators =  
+		$operators =
 		array(
 
 				'in'=> array(
@@ -68,7 +68,7 @@ class Sqlite
 						'slug'=> 'like',
 						'label'=>'Contient',
 						'sql'=>function($column,$values,&$query,&$data){
-				
+
 							$data[] = '%'.$values[0].'%';
 							$query .= ' '.$column.' LIKE ?' ;
 						}
@@ -77,7 +77,7 @@ class Sqlite
 						'slug'=> 'not like',
 						'label'=>'Ne contient pas',
 						'sql'=>function($column,$values,&$query,&$data){
-				
+
 							$data[] = '%'.$values[0].'%';
 							$query .= ' '.$column.' NOT LIKE ?' ;
 						}
@@ -136,7 +136,7 @@ class Sqlite
 							}
 					$query .= ' ) ';
 				})
-			
+
 		);
 		if(!isset($key)) return $operators;
 		return isset($operators[$key]) ?$operators[$key] : array('label'=>'Non définit','sql'=>'');
@@ -152,7 +152,7 @@ class Sqlite
             }
             $field['tag'] = implode(' AND ',$field['tag']);
 		}else if($field['operator'] == 'IN' || $field['operator'] == 'NOT IN'){
-            $field['tag'] = array(); 
+            $field['tag'] = array();
             $valueArray = !is_array($value)?explode(',',$value) : $value;
             foreach ($valueArray as $v2) {
                 $tag = ':'.$i;
@@ -173,7 +173,7 @@ class Sqlite
             $i++;
         }
 	}
-	
+
 	public static function types(){
 		$types = array();
         $types['string'] = $types['timestamp'] = $types['datetime'] = $types['date'] = 'VARCHAR(255)';
@@ -188,8 +188,8 @@ class Sqlite
         $types['default'] = 'TEXT';
 		return $types;
 	}
-	
-	
+
+
 	public static function select(){
 		$sql = 'SELECT {{:selected}}{{value}}{{;}},{{/;}}{{/:selected}} FROM "{{table}}" {{?joins}}{{:joins}}LEFT JOIN {{jointable2}} {{jointableAlias}} ON {{jointable1}}.{{field1}}= {{jointableAlias}}.{{field2}} {{/:joins}}{{/?joins}} {{?filter}}WHERE {{:filter}}"{{table}}"."{{key}}"{{operator}}{{value}}{{postoperator}} {{;}} AND {{/;}} {{/:filter}} {{/?filter}}  {{?orderby}}ORDER BY {{:orderby}}{{value}}{{;}},{{/;}}{{/:orderby}} {{/?orderby}} {{?limit}}LIMIT {{:limit}}{{value}}{{;}},{{/;}}{{/:limit}}{{/?limit}}';
 		return $sql;
@@ -206,7 +206,7 @@ class Sqlite
 		$sql = 'UPDATE {{table}} SET {{?fields}} {{:fields}}"{{key}}"={{value}} {{;}}, {{/;}}{{/:fields}} {{/?fields}} {{?filter}}WHERE {{:filter}}"{{table}}"."{{key}}"{{operator}}{{value}}{{postoperator}} {{;}} AND {{/;}} {{/:filter}} {{/?filter}}';
 		return $sql;
 	}
-	
+
 
 	public static function insert_head(){
 		$sql = 'INSERT INTO  {{table}} ({{?fields}} {{:fields}}"{{key}}" {{;}} , {{/;}} {{/:fields}} {{/?fields}})VALUES';

+ 4 - 4
firm.php

@@ -1,4 +1,4 @@
-<?php 
+<?php
 require_once('header.php');
 User::check_access('firm','read');
 
@@ -7,7 +7,7 @@ $firm = Firm::provide();
 <div class="plugin-core">
 	<div id="firm-form" class="row justify-content-md-center firm-form" data-action="core_firm_save" data-id="<?php echo $firm->id; ?>">
 		<div class="col-md-6 shadow-sm bg-white p-3">
-			<h3>Etablissement 
+			<h3>Etablissement
 			<div onclick="core_firm_save();" class="btn btn-small btn-success right"><i class="fas fa-check"></i> Enregistrer</div>
 			<a href="setting.php?section=firm" class="btn btn-small btn-dark right  mr-2">Retour</a></h3>
 			<label for="label">Raison sociale</label>
@@ -35,10 +35,10 @@ $firm = Firm::provide();
 			<label for="iban">N° IBAN</label>
 			<input  value="<?php echo $firm->iban; ?>" class="form-control"  type="text"  id="iban" >
 			<br/>
-			
+
 		</div>
 	</div>
 </div>
-<?php 
+<?php
 require_once('footer.php');
 ?>

+ 24 - 24
footer.php

@@ -1,7 +1,7 @@
 
 </div>
 
-<?php 
+<?php
 global $myUser,$conf,$myFirm;
 $scheme = isset($scheme) ? $scheme : define_url_scheme();
 $mediaRoot = isset($mediaRoot) ? $mediaRoot : define_media_root();
@@ -18,14 +18,14 @@ uasort ($footerMenu , function($a,$b){return $a['sort']>$b['sort']?1:-1;});
 	<footer class="footer noPrint">
 		<div class="container-fluid py-0 text-center">
 			<span class="text-muted">
-			<?php 
+			<?php
 				echo $conf->get('show_application_name_footer') ? PROGRAM_NAME.' V'.SOURCE_VERSION.' ' : '';
 				if($conf->get('show_application_author_footer')){
 					if(!empty($conf->get('application_author_website_footer')))
 						echo 'by <a href="'.$conf->get('application_author_website_footer').'" target="_blank">@'.PROGRAM_AUTHOR.'</a>';
 					else
 						echo 'by @'.PROGRAM_AUTHOR;
-				}				
+				}
 				echo !empty($conf->get('show_application_documentation_footer')) && file_exists('file/guide/'.$conf->get('show_application_documentation_footer')) && $myUser->connected() ? ' | <a href="file/guide/'.$conf->get('show_application_documentation_footer').'" target="_blank"><i class="far fa-file-pdf"></i> Documentation</a>' : '';
 				echo $conf->get('show_process_time_footer') ? ' - '.$loadingTime : '';
 			?>
@@ -52,7 +52,7 @@ uasort ($footerMenu , function($a,$b){return $a['sort']>$b['sort']?1:-1;});
 
 	<!-- Composant filtre -->
 	<div class="advanced-search-box hidden">
-		
+
 			<div class="input-group simple-search">
 				<div class="input-group-prepend d-none d-md-flex">
 					<div class="input-group-text data-search-label">Recherche</div>
@@ -63,7 +63,7 @@ uasort ($footerMenu , function($a,$b){return $a['sort']>$b['sort']?1:-1;});
 					<div class="btn btn-info btn-search" title="Rechercher"><i class="fas fa-search mr-1"></i><span class="d-none d-md-inline">Rechercher</span></div>
 				</div>
 			</div>
-	
+
 		<div class="advanced-search">
 		    <ul class="criterias group">
 	            <li class="condition hidden">
@@ -73,14 +73,14 @@ uasort ($footerMenu , function($a,$b){return $a['sort']>$b['sort']?1:-1;});
 	                		<option value="{{value}}" data-filter-type="{{type}}">{{label}}</option>
 	                	{{/columns}}
 	                </select>
-	                </span> 
-	                <span class="filter-subcolumn"></span> 
-	                <span class="filter-operator"></span> 
-	                <span class="filter-value"></span> 
+	                </span>
+	                <span class="filter-subcolumn"></span>
+	                <span class="filter-operator"></span>
+	                <span class="filter-value"></span>
 	                <span class="filter-option">
 	                	<i title="Déplacer la ligne" class="fas fa-arrows-alt btn-move d-none d-md-inline-block"></i>
 	                    <i title="Déplacer dans le groupe supérieur" class="btn-unindent fas fa-angle-left"></i>
-	                    <i title="Déplacer dans un sous-groupe" class="btn-indent fas fa-angle-right"></i> 
+	                    <i title="Déplacer dans un sous-groupe" class="btn-indent fas fa-angle-right"></i>
 	                    <i title="Supprimer la ligne" class="btn-delete far fa-trash-alt"></i>
 	                    <i title="Ajouter une ligne après" class="btn-add fas fa-plus"></i>
 	                </span>
@@ -126,10 +126,10 @@ uasort ($footerMenu , function($a,$b){return $a['sort']>$b['sort']?1:-1;});
 
 	<div class="hidden">
 
-		<?php 
+		<?php
 		$fieldTypes = FieldType::available();
 		foreach($fieldTypes as $fieldType): ?>
-			<div class="available-field-type" data-field-type="<?php echo $fieldType->slug; ?>"><?php 
+			<div class="available-field-type" data-field-type="<?php echo $fieldType->slug; ?>"><?php
 			$m = $fieldType->onInput;
 			$type = isset($field['type']) && isset($fieldTypes[$field['type']]) ? $fieldTypes[$field['type']] : $fieldTypes['text'];
 
@@ -146,14 +146,14 @@ uasort ($footerMenu , function($a,$b){return $a['sort']>$b['sort']?1:-1;});
 			if(isset($fieldType->filter['attributes']))
 				$attributes = array_merge($attributes,$fieldType->filter['attributes']);
 
-			echo $m(array('attributes'=>$attributes),array('type'=>$type,'label'=>'')); 
+			echo $m(array('attributes'=>$attributes),array('type'=>$type,'label'=>''));
 		?></div>
 		<?php endforeach; ?>
 		?>
-	
 
 
-		<?php foreach($fieldTypes as $fieldType): 
+
+		<?php foreach($fieldTypes as $fieldType):
 			if(!property_exists($fieldType,'filter')) continue;
 			global $databases_credentials;
        		$connector = $databases_credentials['local']['connector'];
@@ -168,15 +168,15 @@ uasort ($footerMenu , function($a,$b){return $a['sort']>$b['sort']?1:-1;});
 		?>
 		<div class="filter-value-block" data-value-type="<?php echo $fieldType->slug; ?>"  <?php echo $selector ?> >
 			<select class="form-control filter-operator border-0 text-primary">
-				<?php foreach($fieldType->filter['operators'] as $operator=>$view): 
+				<?php foreach($fieldType->filter['operators'] as $operator=>$view):
 					$operator = $operators[$operator];
 					$valuesNumber = isset($operator['values']) ? $operator['values'] : 1;
 					if(count($view)==0) $valuesNumber = 0;
 
-					
+
 				?>
-				<option 
-					data-default-view="<?php echo base64_encode(json_encode($view)); ?>" <?php echo isset($operator['values'])?' data-values="'.$valuesNumber.'" ':''; ?> 
+				<option
+					data-default-view="<?php echo base64_encode(json_encode($view)); ?>" <?php echo isset($operator['values'])?' data-values="'.$valuesNumber.'" ':''; ?>
 					value="<?php echo $operator['slug']; ?>"><?php echo $operator['label']; ?></option>
 				<?php endforeach; ?>
 			</select>
@@ -248,7 +248,7 @@ uasort ($footerMenu , function($a,$b){return $a['sort']>$b['sort']?1:-1;});
 					{{#url}}</a>{{/url}}
 					<span class="btn-bar">
 						<span class="file-button"></span>
-						<span class="btn-delete pointer"><i class="far fa-trash-alt"></i></span> 
+						<span class="btn-delete pointer"><i class="far fa-trash-alt"></i></span>
 					</span>
 				</div>
 				<div class="progress-bar"></div>
@@ -276,7 +276,7 @@ uasort ($footerMenu , function($a,$b){return $a['sort']>$b['sort']?1:-1;});
 	    <div class="history-add mb-2" data-tooltip   title="Ajouter un commentaire ici..." onclick="history_add()"><i class="far fa-comment-dots"></i></div>
 
 	    <div class="comments-loader text-center p-3"><small class="text-muted"><i class="fas fa-circle-notch fa-spin-fast"></i> Chargement en cours....</small></div>
-	    
+
 	    <ul class="comments">
 	        <li class="hidden comment" data-id="{{id}}" data-type="{{type.slug}}" data-importance="{{importance}}" data-sort="{{sort}}">
 	            <div>
@@ -348,8 +348,8 @@ uasort ($footerMenu , function($a,$b){return $a['sort']>$b['sort']?1:-1;});
 					                    <th colspan="6" class="col-read">
 					                    	<select id="permission-firm" class="form-control form-control-sm w-100" onchange="core_permission_right_search()"></select>
 					                    </th>
-										
-					                  
+
+
 					                </tr>
 					            </thead>
 					            <thead>
@@ -414,8 +414,8 @@ uasort ($footerMenu , function($a,$b){return $a['sort']>$b['sort']?1:-1;});
 	<script> window.FontAwesomeConfig = {searchPseudoElements: true}</script>
 	<!-- lib js -->
 	<script src="<?php echo $mediaRoot ?>/js/vendor/popper.min.js"></script>
-	
 	<script src="<?php echo $mediaRoot ?>/js/vendor/mustache.min.js"></script>
+	<!-- jQuery / jQuery UI -->
 	<script src="<?php echo $mediaRoot ?>/js/vendor/jquery-ui.min.js"></script>
 	<script src="<?php echo $mediaRoot ?>/js/vendor/jquery.timepicker.js"></script>
 	<!-- prevent jquery ui / boostrap conflit on $.tooltip() -->

+ 95 - 97
function.php

@@ -15,7 +15,7 @@ function app_autoloader($class_name) {
 	}
 }
 function errorToException( $errno, $errstr, $errfile, $errline, $errcontext) {
-	throw new ErrorException($errstr, 0, $errno, $errfile, $errline);   
+	throw new ErrorException($errstr, 0, $errno, $errfile, $errline);
 }
 
 function unhandledException($ex){
@@ -23,7 +23,7 @@ function unhandledException($ex){
 	$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();
@@ -49,13 +49,11 @@ function unhandledException($ex){
 			        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">';
+			    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){
@@ -132,7 +130,7 @@ function exception_link($ex,$type = 'exception'){
 		'arguments'=>$filePath.'":'.$line
 			)
 		)
-	); 
+	);
 }
 
 function exception_trace($ex){
@@ -162,7 +160,7 @@ function ip(){
 		$ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
 	elseif(isset($_SERVER['HTTP_CLIENT_IP']))
 		$ip = $_SERVER['HTTP_CLIENT_IP'];
-	else 
+	else
 		$ip = isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] :'';
 	return $ip;
 }
@@ -222,8 +220,8 @@ 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'); 
-	   
+	    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;
@@ -238,7 +236,7 @@ function slugify($text,$allowChars = '', $separator='-') {
 }
 
 if(!function_exists('glob_recursive')) {
-	// Does not support flag GLOB_BRACE        
+	// 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) {
@@ -273,11 +271,11 @@ if(!function_exists('array_key_first')) {
 function array_flatten($array) {
 	$return = array();
 	foreach($array as $key => $value) {
-		if(is_array($value)){ 
+		if(is_array($value)){
 			$return = array_merge($return, array_flatten($value));
 		} else {
 			$return[$key] = $value;
-		} 
+		}
 	}
 	return $return;
 }
@@ -325,11 +323,11 @@ function secure_user_vars($var){
 }
 
 function base64_to_image($base64_string, $output_file) {
-	$ifp = fopen($output_file, "wb"); 
+	$ifp = fopen($output_file, "wb");
 	$data = explode(',', $base64_string);
-	fwrite($ifp, base64_decode($data[1])); 
-	fclose($ifp); 
-	return $output_file; 
+	fwrite($ifp, base64_decode($data[1]));
+	fclose($ifp);
+	return $output_file;
 }
 
 function getExt($file){
@@ -350,7 +348,7 @@ function getExtIcon($ext){
 		case 'zip':
 			$icon = 'far fa-file-archive text-warning';
 		break;
-		
+
 		case 'php':
 		case 'js':
 		case 'py':
@@ -365,14 +363,14 @@ function getExtIcon($ext){
 		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':
@@ -383,7 +381,7 @@ function getExtIcon($ext){
 		case 'svg':
 			$icon = 'far fa-file-image text-info';
 		break;
-		
+
 		case 'pdf':
 			$icon = 'far fa-file-pdf text-danger';
 		break;
@@ -391,19 +389,19 @@ function getExtIcon($ext){
 		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':
@@ -417,7 +415,7 @@ function getExtIcon($ext){
 		case 'mp4':
 			$icon = 'far fa-file-video text-secondary';
 		break;
-		
+
 		case 'wav':
 		case 'ogg':
 		case 'ogv':
@@ -485,7 +483,7 @@ function getExtContentType($ext){
 		case 'txt':
 			$cType = 'text/plain';
 		break;
-		
+
 		case 'doc':
 		case 'word':
 			$cType = 'application/msword';
@@ -493,7 +491,7 @@ function getExtContentType($ext){
 		case 'docx':
 			$cType = 'application/vnd.openxmlformats-officedocument.wordprocessingml.document';
 		break;
-		
+
 		case 'aac':
 		case 'wav':
 			$cType = 'audio/'.$ext;
@@ -590,7 +588,7 @@ function arand($array){
 	return $array[array_rand($array)];
 }
 
-//Convertis une date en timestamp 
+//Convertis une date en timestamp
 //(format possible dd-mm-yyyy ou dd/mm/yyyy)
 function timestamp_date($date){
 	$date = explode('/',str_replace('-', '/', $date));
@@ -621,16 +619,16 @@ function timestamp_hour($hour){
 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
@@ -685,7 +683,7 @@ function filters_default($filters){
 /**
  * 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"
@@ -727,15 +725,15 @@ function filters_set($filters){
 		}
 
 		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']), 
+			"c" => $filter['column'],
+			"o" => $filter['operator'],
+			"v" => is_array($filter['value']) ? $filter['value'] : array($filter['value']),
 		);
 		if(isset($filter['subcolumn'])) $tempFilter['s'] = $filter['subcolumn'];
 
@@ -782,7 +780,7 @@ function filter_alteration($filters,$index,$mutator){
 // 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'];
@@ -801,7 +799,7 @@ function filter_secure_query($filters,$allowedColumns,&$query,&$data,$iteration
 			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'])){
@@ -825,7 +823,7 @@ function filter_secure_query($filters,$allowedColumns,&$query,&$data,$iteration
 			$query.=' ( ';
 			$method($filter['column'],isset($filter['value'])?$filter['value']:null,$query,$data);
 			$query.=' ) ';
-			
+
 		}
 		if(isset($filter['join'])) $query .= ' '.$filter['join'].' ';
 	}
@@ -972,7 +970,7 @@ function mb_ucfirst($string,$encoding = 'UTF-8'){
     return mb_strtoupper($firstChar, $encoding).$rest;
 }
 
-// Permet de mettre au bon format le n° de 
+// 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);
@@ -1014,7 +1012,7 @@ function utf8_to_extended_ascii($str, &$map) {
 	$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]))
@@ -1034,8 +1032,8 @@ function levenshtein_utf8($s1, $s2) {
 	return levenshtein($s1, $s2);
 }
 
-// Méthode qui retourne sous forme de tableau 
-// les metaphones // des différents mots d'une 
+// Méthode qui retourne sous forme de tableau
+// les metaphones // des différents mots d'une
 // phrase.
 function get_metaphones($sentence) {
 	$metaphones = array();
@@ -1082,7 +1080,7 @@ function numbers_to_letters($num){
 		$num = intval(($num - $p) / 26);
 		$letter = chr(65 + $p) . $letter;
 	}
-	return $letter;     
+	return $letter;
 }
 //Convertit lettres en nombres (utile pour Excel)
 function letters_to_numbers($col){
@@ -1102,7 +1100,7 @@ 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);		
+	list($d,$m,$y) = explode('/',$date);
 	if( !is_numeric($d) || !is_numeric($m) || !is_numeric($y) ) return false;
 	return checkdate (  $m ,  $d ,  $y );
 }
@@ -1121,13 +1119,13 @@ function strpos_array($haystack, $needles=array(), $offset=0) {
 }
 
 //Supprime un dossier et son contenu
-//de manière récursive 
-function delete_folder_tree($dir, $selfDestroy=false) { 
+//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); 
+	$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
@@ -1137,8 +1135,8 @@ function normalize_chars($string, $mask=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', 
+		'Ú'=>'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',
@@ -1194,7 +1192,7 @@ function number_to_words($number, $feminine=false) {
 
 	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;
@@ -1208,28 +1206,28 @@ function number_to_words($number, $feminine=false) {
 		break;
 		case $number == 21:
 			$string = $dictionary[20].$conjunction.$dictionary[1];
-		break; 
+		break;
 		case $number == 31:
 			$string = $dictionary[30].$conjunction.$dictionary[1];
-		break; 
+		break;
 		case $number == 41:
 			$string = $dictionary[40].$conjunction.$dictionary[1];
-		break; 
+		break;
 		case $number == 51:
 			$string = $dictionary[50].$conjunction.$dictionary[1];
-		break; 
+		break;
 		case $number == 61:
 			$string = $dictionary[60].$conjunction.$dictionary[1];
-		break; 
+		break;
 		case $number == 71:
 			$string = $dictionary[60].$conjunction.$dictionary[11];
-		break; 
+		break;
 		case $number == 81:
 			$string = $dictionary[80].$hyphen.$dictionary[1];
-		break; 
+		break;
 		case $number == 91:
 			$string = $dictionary[80].$hyphen.$dictionary[11];
-		break; 
+		break;
 		case $number < 100:
 			$tens   = ((int) ($number / 10)) * 10;
 			$units  = $number % 10;
@@ -1275,8 +1273,8 @@ function number_to_words($number, $feminine=false) {
 /**
  * Retrourne le numéral ordinal compact
  * d'un nombre passé en paramètre.
- * eg: 
- * 	1 --> 1er, 
+ * eg:
+ * 	1 --> 1er,
  *  2 --> 2ème, etc..
  * Les nombres ordinaux sont définis par un
  * l'ensemble des entiers naturels non nuls
@@ -1287,7 +1285,7 @@ function number_to_ordinal($number, $feminine=false){
 	//Aucun ordinal pour le rang 0
 	if($number == 0) return;
 
-	if($number == 1) 
+	if($number == 1)
 		return $number.($feminine?'ère':'er');
 	return $number.'ème';
 }
@@ -1340,7 +1338,7 @@ function forbidden_macro($source){
 	);
 
 	foreach($tokens as $token){
-		if(is_string($token)) continue;   
+		if(is_string($token)) continue;
 		list($id, $text,$line) = $token;
 
 		if(in_array($id, array(T_FUNCTION,T_FUNC_C,T_EVAL,T_STRING))){
@@ -1377,7 +1375,7 @@ function forbidden_macro($source){
 //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];
@@ -1400,7 +1398,7 @@ function mustache_template($stream,$data){
         			// 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++;
@@ -1418,7 +1416,7 @@ function mustache_template($stream,$data){
         }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;
@@ -1489,18 +1487,18 @@ function template($stream,$data,$mustacheTemplate = false){
         	$value = $current;
         }
         return $value;
-    },$stream); 
-  
+    },$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 (
@@ -1524,7 +1522,7 @@ function template($stream,$data,$mustacheTemplate = false){
         [1] => 456
     )
  * )
- * 
+ *
  * Exemple de format de retour pour 2 fichiers :
  * Array(
     [0] => Array(
@@ -1550,14 +1548,14 @@ function normalize_php_files() {
         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];
 
@@ -1583,7 +1581,7 @@ function autoincrement_filename($extension, $folder, $filename){
 
 	$fileNb = count(glob(FILE_PATH.$folder.$filename));
 	$filenameProps = explode('.', $filename);
-	
+
 	unset($filenameProps[count($filenameProps)-1]);
 	$finalFilename = implode('.', $filenameProps);
 
@@ -1605,7 +1603,7 @@ function relative_path($absolutePath,$reference = __ROOT__){
 //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; 
+	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
@@ -1613,7 +1611,7 @@ 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 
+//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);
@@ -1630,10 +1628,10 @@ function random_hex_pastel_color($name) {
 
 //Convertit un code hexadecimal en code RGB
 function to_rgb($hexcode) {
-	$hexcode = substr($hexcode, 1);	    
+	$hexcode = substr($hexcode, 1);
 	return array(hexdec($hexcode[0] . $hexcode[1]),
 		hexdec($hexcode[2] . $hexcode[3]),
-		hexdec($hexcode[4] . $hexcode[5]));    
+		hexdec($hexcode[4] . $hexcode[5]));
 }
 
 //Retourne le nom complet d'un mois en fonction de son numéro
@@ -1648,7 +1646,7 @@ function day_name($day){
     return isset($translates[$day-1])? $translates[$day-1]:$day;
 }
 
-//Convertit un timestamp dans un format 
+//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();
@@ -1687,7 +1685,7 @@ function get_not_workable($date=null){
 	return $holidays;
 }
 
-//Retourne le chemin web d'un fichier en fonction de son chemin 
+//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);
@@ -1702,7 +1700,7 @@ function array_not_unique($array=array()){
 }
 
 //Retourne true si aucune valeur du tableau passé
-//en paramètre a un doublon, false sinon. 
+//en paramètre a un doublon, false sinon.
 function is_array_unique($array=array()){
 	return empty(array_not_unique($array));
 }
@@ -1794,9 +1792,9 @@ function mt_basename($path){
 	return end($nameSplit);
 }
 
-//filtre les balises dangeureuses (script,link..) dans les contenus wysiwyg 
+//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;
@@ -1809,9 +1807,9 @@ function display_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++ ){ 
+	for( $u = 0; $u < $zip->numFiles; $u++ ){
 		$infos = $zip->statIndex( $u );
-		
+
 		//dossier
 		if(substr($infos['name'],-1,1)=='/'){
 			$infos['name'] = str_replace('..','.',$infos['name']);
@@ -1826,7 +1824,7 @@ function unzip($zipPath,$destination,$options = array()){
 			file_put_contents($destination.SLASH.$infos['name'], $zip->getFromName($infos['name']));
 		}
 
-		
+
 	}
 }
 
@@ -1870,7 +1868,7 @@ function value_encapsulate($value, $char = ',') {
 /*
 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 
+	$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)
@@ -1878,7 +1876,7 @@ Donne le differentiel en heures/jours entre deux dates en prenant en compte les
 /*
 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 
+$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)
@@ -1886,7 +1884,7 @@ $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();
@@ -1915,20 +1913,20 @@ function date_workable_diff($start,$end,$openStartHour = 9,$openEndHour = 18,$lu
 	}
 
 
-	
+
 	$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) || 
+		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,

+ 22 - 22
header.php

@@ -1,4 +1,4 @@
-<?php require_once __DIR__.DIRECTORY_SEPARATOR.'common.php'; 
+<?php require_once __DIR__.DIRECTORY_SEPARATOR.'common.php';
 
 $scheme = define_url_scheme();
 $mediaRoot = define_media_root();
@@ -6,7 +6,7 @@ $mediaRoot = define_media_root();
 if(!empty($myUser->preference('passwordTime')) && !$myUser->superadmin){
     $basepage = explode('?',$page);
     $basepage = $basepage[0];
-    if(is_numeric($conf->get('password_delay')) && $basepage!="account.php" && ((time() - ($conf->get('password_delay') * 86400) > $myUser->preference('passwordTime')))) 
+    if(is_numeric($conf->get('password_delay')) && $basepage!="account.php" && ((time() - ($conf->get('password_delay') * 86400) > $myUser->preference('passwordTime'))))
     	header('location: account.php?error=Votre mot de passe est trop vieux, veuillez le renouveller ci dessous.');
 }
 
@@ -29,7 +29,7 @@ if(!isset($_['admin_login']) && file_exists(File::dir().SLASH.'enabled.maintenan
 	$mainMenu = array();
 	Plugin::callHook("menu_main", array(&$mainMenu));
 	uasort($mainMenu , function($a,$b){return $a['sort']-$b['sort'];});
-	
+
 	$userMenu = array();
 	if($myUser->connected()){
 		Plugin::callHook("menu_user", array(&$userMenu));
@@ -49,7 +49,7 @@ if(!isset($_['admin_login']) && file_exists(File::dir().SLASH.'enabled.maintenan
 
 		<!-- Favicon -->
     	<link rel="shortcut icon" type="image/png" href="media/core/public/favicon.png" />
-	
+
 		<?php $title = $myUser->connected() ? 'Accueil':'Connexion';
 		foreach($mainMenu as $item)
 			$title = (!empty($item['url']) && strpos($page, $item['url']) !== false) ? $item['label'] : $title;
@@ -57,9 +57,9 @@ if(!isset($_['admin_login']) && file_exists(File::dir().SLASH.'enabled.maintenan
 		foreach($userMenu as $item)
 			$title = (isset($item['url']) && strpos($page, $item['url']) !== false) ? $item['label'] : $title;
 		?>
-	
+
 		<title><?php echo PROGRAM_NAME.' - '.$title ?></title>
-	
+
 		<!-- Bootstrap core CSS -->
 		<link href="<?php echo $mediaRoot ?>/css/bootstrap.min.css" rel="stylesheet">
 		<!-- jQuery UI -->
@@ -86,7 +86,7 @@ if(!isset($_['admin_login']) && file_exists(File::dir().SLASH.'enabled.maintenan
 		<!-- Plugin css files -->
 		<?php echo Plugin::callCss($mediaRoot,$cacheVersion); ?>
 	</head>
-	
+
 	<body>
 
 		<!-- Fixed navbar -->
@@ -103,12 +103,12 @@ if(!isset($_['admin_login']) && file_exists(File::dir().SLASH.'enabled.maintenan
 					</div>
 				</div>
 			</button>
-			<?php endif; 
+			<?php endif;
 
 			$logo = 'media/core/public/logo.png';
 			if($myFirm->id!=0  ){
 				$firmLogo = $myFirm->logo('publicPath');
-			
+
 				if(!empty($firmLogo)) $logo = $firmLogo;
 			}
 			?>
@@ -116,22 +116,22 @@ if(!isset($_['admin_login']) && file_exists(File::dir().SLASH.'enabled.maintenan
 			<div class="collapse navbar-collapse" id="navbarCollapse">
 				<ul class="navbar-nav navbar-main">
 				<?php foreach($mainMenu as $item): ?>
-					<?php if (isset($item['label']) && $item['label'] == 'Réglages') $page = basename($_SERVER['PHP_SELF']); 
+					<?php if (isset($item['label']) && $item['label'] == 'Réglages') $page = basename($_SERVER['PHP_SELF']);
 					$classes = isset($item['classes'])? $item['classes']: '';
-					if(isset($item['url']) 
-						&& ((!empty($item['url']) 
-						&& strpos($page, $item['url']) !== false 
+					if(isset($item['url'])
+						&& ((!empty($item['url'])
+						&& strpos($page, $item['url']) !== false
 						&& $item['url'] != 'index.php') || $page == $item['url'])
 						|| (isset($item['active']) && $item['active'] ==true)
 					){
 						$classes .= ' active';
-					} 
+					}
 					?>
 					<li data-id="<?php echo isset($item['id'])?$item['id']:''; ?>" class="nav-item <?php echo $classes; ?> ">
-						<a class="nav-link" 
-							title="<?php echo isset($item['title'])?$item['title']:''; ?>" 
-							target="<?php echo isset($item['target'])?$item['target']:''; ?>" 
-							onclick="<?php echo isset($item['onclick'])?$item['onclick']:''; ?>" 
+						<a class="nav-link"
+							title="<?php echo isset($item['title'])?$item['title']:''; ?>"
+							target="<?php echo isset($item['target'])?$item['target']:''; ?>"
+							onclick="<?php echo isset($item['onclick'])?$item['onclick']:''; ?>"
 							<?php echo isset($item['url'])? 'href="'.$item['url'].'"':''; ?>>
 							<?php echo (isset($item['icon'])?'<i class="'.$item['icon'].'"></i> ':'').'<span>'.(isset($item['label'])?$item['label']:'').'</span>'; ?>
 							<?php echo isset($item['html'])? $item['html']:''; ?>
@@ -142,7 +142,7 @@ if(!isset($_['admin_login']) && file_exists(File::dir().SLASH.'enabled.maintenan
 				<?php Plugin::callHook("header", array()); ?>
 
 				<div id="loginHeader" class="ml-auto d-flex text-right" data-firm="<?php echo $myFirm->id; ?>" data-connected="<?php echo $myUser->login; ?>">
-				<?php Plugin::callHook("login_header", array());		
+				<?php Plugin::callHook("login_header", array());
 				if(empty($conf->get('hide_header_login')) || $myUser->connected() || (!empty($conf->get('hide_header_login')) && ($page!='index.php' || ($page!='' && $page!='index.php')))): ?>
 					<!-- User connecté -->
 					<?php if($myUser->connected()): ?>
@@ -168,7 +168,7 @@ if(!isset($_['admin_login']) && file_exists(File::dir().SLASH.'enabled.maintenan
 					<div class="dropdown user-dropdown-menu ml-1" id="login-dropdown">
 						<button class="btn btn-dark dropdown-toggle" type="button" id="dropdownMenuButton" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">Connexion</button>
 						<div class="dropdown-menu dropdown-menu-right pb-1" aria-labelledby="dropdownMenuButton">
-							<div class="dropdown-item login-item"> 
+							<div class="dropdown-item login-item">
 								<?php require_once(__DIR__.SLASH.'login.php'); ?>
 							</div>
 						</div>
@@ -178,7 +178,7 @@ if(!isset($_['admin_login']) && file_exists(File::dir().SLASH.'enabled.maintenan
 				</div>
 			</div>
 		</nav>
-	
+
 		<!-- Begin page content -->
 		<div class="container-fluid">
-<?php } 
+<?php }

+ 1 - 1
index.php

@@ -1,5 +1,5 @@
 <?php
 require_once __DIR__.DIRECTORY_SEPARATOR.'header.php';
 Plugin::callHook('page');
-require_once __DIR__.DIRECTORY_SEPARATOR.'footer.php'; 
+require_once __DIR__.DIRECTORY_SEPARATOR.'footer.php';
 ?>

+ 27 - 49
install.php

@@ -23,7 +23,7 @@ if(isset($_GET['action']) && $_GET['action'] =='check_connection'){
 try {
 
 	/*
-	Page customizable depuis n'importe quel app.json de plugin via la mention : 
+	Page customizable depuis n'importe quel app.json de plugin via la mention :
 
 	"install":  "Install.class.php",
 
@@ -45,7 +45,7 @@ try {
 	$_ = array_map('secure_user_vars', array_merge($_POST, $_GET));
 	require_once('class/Plugin.class.php');
 	$entityFolder = __DIR__.'/class/';
-	
+
 
 	if(file_exists(__DIR__.DIRECTORY_SEPARATOR.'.git') && !file_exists(__DIR__.DIRECTORY_SEPARATOR.'.git'.DIRECTORY_SEPARATOR.'.htaccess')){
 		file_put_contents(__DIR__.DIRECTORY_SEPARATOR.'.git'.DIRECTORY_SEPARATOR.'.htaccess', 'Require all denied');
@@ -67,10 +67,10 @@ try {
 
 
 
-		
-	
+
+
 	/*
-	Installation en mode cli, exemple : 
+	Installation en mode cli, exemple :
 	php install.php "{\"connector\":\"Mysql\",\"host\":\"mysql-host\",\"login\":\"root\",\"password\":\"root\",\"name\":\"hackpoint\",\"root\":\"http:\/\/127.0.0.1\/hackpoint\"}"
 	*/
 	if(php_sapi_name() == 'cli'){
@@ -103,11 +103,11 @@ try {
 		<link rel="stylesheet" href="css/fontawesome-all.min.css">
 		<!-- Custom styles for this template -->
 		<link href="css/main.css" rel="stylesheet">
-		<?php 
+		<?php
 
-		
 
-		if(method_exists($custom['class'], 'css')): ?>
+
+		if(!empty($custom['class']) && method_exists($custom['class'], 'css')): ?>
 			<link href="<?php echo $custom['plugin'].$custom['class']::css(); ?>" rel="stylesheet">
 		<?php endif; ?>
 		<style>
@@ -125,12 +125,12 @@ try {
 			<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarCollapse" aria-controls="navbarCollapse" aria-expanded="false" aria-label="Toggle navigation">
 				<span class="navbar-toggler-icon"></span>
 			</button>
-			
+
 		</nav>
 
 		<!-- Begin page content -->
 		<div class="container">
-		<?php 
+		<?php
 		$entities = array();
 
 		foreach(glob(__DIR__.'/connector/*.class.php') as $classFile){
@@ -149,11 +149,7 @@ try {
 		//if(!in_array('sqlite',PDO::getAvailableDrivers())) throw new Exception('Le driver SQLITE est requis, veuillez installer sqlite3 (sous linux : <code>sudo apt-get install php5-sqlite && service apache2 restart</code>)');
 
 		if(isset($_['connector'])){
-			
 			install_core($_,$custom);
-
-			
-
 			?>
 
 			<div class="alert alert-success alert-dismissable">
@@ -161,7 +157,7 @@ try {
 				<strong>Succès!</strong> La base est bien installée, l'utilisateur par défaut est <code>admin:admin</code>, pensez à changer le mot de passe rapidemment. <br>
 			</div>
 			<a class="btn btn-primary" href="index.php">Revenir à l'index</a>
-			<?php 
+			<?php
 		} else {
 
 			$root = 'http'.((!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off')|| $_SERVER['SERVER_PORT'] == 443?'s':'').'://'.$_SERVER['HTTP_HOST'].($_SERVER['SERVER_PORT']==80?'':':'.$_SERVER['SERVER_PORT']).$_SERVER['REQUEST_URI'];
@@ -169,14 +165,14 @@ try {
 			$parts = explode('?',$root);
 			$root = array_shift($parts);
 
-			if( method_exists($custom['class'], 'pre_form') ) $custom['class']::pre_form();
+			if(!empty($custom['class']) && method_exists($custom['class'], 'pre_form') ) $custom['class']::pre_form();
 			?>
 
 			<div class="row justify-content-md-center">
 				<form class="col-md-6 mt-3" action="install.php" method="POST">
 					<h3>Installation</h3>
 					<p class="text-muted">Merci de bien vouloir remplir les champs ci-dessous</p>
-					
+
 
 					<div class="input-group mb-3">
 						<div class="input-group-prepend">
@@ -190,7 +186,7 @@ try {
 						</select>
 					</div>
 
-					<?php if(isset($_['sgbd']) && $_['sgbd']!=''): 
+					<?php if(isset($_['sgbd']) && $_['sgbd']!=''):
 						require_once(__DIR__.'/connector/'.$_['sgbd'].'.class.php');
 						foreach($_['sgbd']::fields() as $field): ?>
 
@@ -199,7 +195,7 @@ try {
 							    	<label class="input-group-text"  for="<?php echo $field['id']; ?>"><?php echo $field['label']; ?></label>
 							    </div>
 
-							
+
 							<?php if(!isset($field['comment'])): ?><small><?php echo $field['comment']; ?></small><br/><?php endif; ?>
 							<input type="text" class="form-control" value="<?php echo $field['default']; ?>" name="<?php echo $field['id']; ?>" id="<?php echo $field['id']; ?>"/></div>
 						<?php endforeach;  ?>
@@ -214,7 +210,7 @@ try {
 
 						<div class="btn btn-primary right" onclick="$(this).addClass('btn-preloader');$(this).parent().get(0).submit()"><i class="far fa-check-circle"></i> Installer</div>
 						<div class="btn btn-dark right mr-2 btn-test" onclick="check_connection()"><i class="far fa-check-circle"></i> Tester la connexion</div>
-						
+
 						</div>
 
 					<?php endif; ?>
@@ -222,20 +218,18 @@ try {
 			</div>
 			<?php
 
-			if( method_exists($custom['class'], 'post_form') ) $custom['class']::post_form();
+			if(!empty($custom['class']) && method_exists($custom['class'], 'post_form') ) $custom['class']::post_form();
 		}
 	} catch (Exception $e) { ?>
 			<div class="alert alert-danger">
 				<button aria-hidden="true" data-dismiss="alert" class="close" type="button">×</button>
 				<strong>Oops!</strong> <?php echo $e->getMessage().' - '.$e->getFile().' L'.$e->getLine().'<hr/><pre>'.$e->getTraceAsString().'</pre>';
-				?> 
+				?>
 			</div>
 		<?php
 	} ?>
 	</div>
 
-
-
 	<!-- Bootstrap core JavaScript -->
 	<!-- Placed at the end of the document so the pages load faster -->
 	<script src="https://code.jquery.com/jquery-3.3.1.min.js" integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=" crossorigin="anonymous"></script>
@@ -245,7 +239,7 @@ try {
 	<script src="js/vendor/mustache.min.js"></script>
 	<script src="js/plugins.js"></script>
 	<script src="js/main.js"></script>
-	<?php if( method_exists($custom['class'], 'js') ): ?>
+	<?php if(!empty($custom['class']) && method_exists($custom['class'], 'js') ): ?>
 		<link href="<?php echo $custom['plugin'].$custom['class']::js(); ?>" rel="stylesheet">
 	<?php endif; ?>
 	<script type="text/javascript">
@@ -269,11 +263,10 @@ try {
 				});
 			}
 	</script>
-
 </body>
 </html>
 
-<?php 
+<?php
 
 function install_core($parameters,$custom){
 	$constantStream = file_get_contents(__DIR__.'/constant-sample.php');
@@ -292,15 +285,12 @@ function install_core($parameters,$custom){
 		$constantStream = str_replace("{{".$key."}}",$value,$constantStream);
 	}
 	file_put_contents(__DIR__.DIRECTORY_SEPARATOR.'constant.php',$constantStream);
-
 	require_once(__DIR__.DIRECTORY_SEPARATOR.'constant.php');
 
 	if(!file_exists(File::core())) mkdir(File::core(),0755,true);
-
 	require_once(__ROOT__.'class'.SLASH.'Entity.class.php');
 
-
-	if( method_exists($custom['class'], 'pre_install') ) $custom['class']::pre_install();
+	if(!empty($custom['class']) && method_exists($custom['class'], 'pre_install') ) $custom['class']::pre_install();
 
 	//install entities
 	Entity::install(__ROOT__.'class');
@@ -309,13 +299,12 @@ function install_core($parameters,$custom){
 	$conf = new Configuration();
 	$conf->getAll();
 
-	//create firm 
+	//create firm
 	$firm = new Firm();
 	$firm->label = 'Établissement';
 	$firm->description = 'Établissement par défaut';
 	$firm->save();
 
-
 	/* RANKS */
 	//create admin rank
 	$superAdmin = new Rank();
@@ -338,14 +327,13 @@ function install_core($parameters,$custom){
 	$connected->superadmin = false;
 	$connected->save();
 
-
 	//create default user
 	$admin = new User();
 	$admin->login = 'admin';
 	$admin->password = User::password_encrypt('admin');
 	$admin->firstname = 'Administrateur';
-	$admin->name = 'Principal'; 
-	$admin->superadmin = 1; 
+	$admin->name = 'Principal';
+	$admin->superadmin = 1;
 	$admin->state = User::ACTIVE;
 	$admin->meta = json_encode($admin->meta);
 	$admin->save();
@@ -357,8 +345,6 @@ function install_core($parameters,$custom){
 	$userfirmrank->rank = $superAdmin->id;
 	$userfirmrank->save();
 
-	
-
 	$admin->loadRanks();
 	$_SESSION['currentUser'] = serialize($admin);
 	$myUser = $admin;
@@ -392,31 +378,23 @@ function install_core($parameters,$custom){
 		$right->save();
 	}
 
-
-	
-	
 	//Activation des plugins par défaut
 	foreach ($enablePlugins as  $plugin) {
 		if(!Plugin::exist($plugin)) continue;
 		Plugin::state($plugin,true);
-	} 
-
+	}
 	$states = Plugin::states();
 
 	//Activation des plugins pour les établissements
 	foreach(Firm::loadAll() as $firm){
 		foreach ($enablePlugins as  $plugin) {
 			if(!Plugin::exist($plugin)) continue;
-			$firms = $states[$plugin];	
+			$firms = $states[$plugin];
 			$key = array_search($firm->id, $firms);
 			$firms[] = $firm->id;
 			$states[$plugin] = array_values($firms);
 			Plugin::states($states);
 		}
 	}
-
-	if( method_exists($custom['class'], 'post_install') ) $custom['class']::post_install();
-			
+	if(!empty($custom['class']) && method_exists($custom['class'], 'post_install') ) $custom['class']::post_install();
 }
-
-?>

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 21 - 21
js/main.js


+ 41 - 41
js/plugins.js

@@ -21,7 +21,7 @@
 	}
 }());
 
-//Affiche un message 'message' de type 'type' pendant 'timeout' secondes and 
+//Affiche un message 'message' de type 'type' pendant 'timeout' secondes and
 $.message = function (type,message,timeout,addClass){
 	message = message.replace(/<\/?script|iframe|object[^>]*>/gim,'');
 	var types = {
@@ -69,8 +69,8 @@ $.toast = function (options) {
 
 	var toastFunctions = {
 		hideToast: function(toast, timeout){
-			setTimeout(function(){ 
-				toast.addClass('hidden'); 
+			setTimeout(function(){
+				toast.addClass('hidden');
 				setTimeout(function(){
 					toast.remove();
 				},100);
@@ -95,7 +95,7 @@ $.toast = function (options) {
 
 	if(o.title) $('.toastTitle > span', popup).html(o.title);
 	$('.toastMessage', popup).html(o.content);
-	
+
 	//Apparition du toast
 	setTimeout(function(){ popup.removeClass('hidden'); }, 50);
 
@@ -110,7 +110,7 @@ $.toast = function (options) {
 			progress.hideEta = new Date().getTime() + progress.maxHideTime;
 			popup.append(progressBar);
 			progress.toastInterval = setInterval(toastFunctions.updateProgress, 10);
-		} 
+		}
 
 		//Au terme du timeout, on cache le toast
 		toastFunctions.hideToast(popup, o.timeout);
@@ -154,7 +154,7 @@ $.setForm = function(element,data){
 		} else {
 			input.val(data[id]);
 		}
-		
+
 	});
 	return o;
 }
@@ -200,9 +200,9 @@ $.action = function(data,success,error,progress) {
 				    if (m.index === debugRegex.lastIndex) debugRegex.lastIndex++;
 				    var path = m[2].split('/');
 				    path = path.slice(-3).join('/');
-				    
+
 				    var filePath = m[2].replace(/\//ig,'\\');
-				    var link = 'w2d://'+btoa(JSON.stringify({action:'alias',alias:'sublime',arguments:filePath+'":'+m[3]})); 
+				    var link = 'w2d://'+btoa(JSON.stringify({action:'alias',alias:'sublime',arguments:filePath+'":'+m[3]}));
 				    var html = '<a style="color:inherit;text-decoration:none;" href="'+link+'">'+path+'<br><strong>L'+m[3]+'</strong><br>'+m[1]+'<br/><small>('+data.action+')</small></a>';
 					$.message('warning',html,0);
 				}
@@ -213,13 +213,13 @@ $.action = function(data,success,error,progress) {
 			} else {
 				if(response.errorCode && response.errorCode=='401') core_logout();
 				var errorMessage = '';
-				
+
 				if(response.file){
 					var filePath = response.file.replace(/\//ig,'\\');
-				    var link = 'w2d://'+btoa(JSON.stringify({action:'alias',alias:'sublime',arguments:filePath+'":'+response.line})); 
+				    var link = 'w2d://'+btoa(JSON.stringify({action:'alias',alias:'sublime',arguments:filePath+'":'+response.line}));
 				    errorMessage += '<a style="color:inherit;text-decoration:none;" href="'+link+'">'+response.file.replace('/var/www/html/','')+'<br><strong>L'+response.line+'</strong></a>';
 				}
-				
+
 				errorMessage += "<br>"+response.error;
 
 				if(response.trace) errorMessage += "<i class='fab fa-stack-overflow d-block pointer m-1' title=\"Voir la trace complête\" onclick=\"$(this).next('div').toggleClass('hidden')\"></i><div class='hidden' style='font-size:10px;max-height:200px;overflow:auto;text-align:left;'>"+response.trace+"</div>";
@@ -386,7 +386,7 @@ $.fn.extend({
 			if(!id) id = element.attr('data-id');
 			if(!id && element.attr("type")=='radio') id = element.attr('name');
 			if(!id) return;
-			
+
 			if(element.attr("type")=='checkbox'){
 				o[id] = (element.is(':checked')?1:0);
 
@@ -418,7 +418,7 @@ $.fn.extend({
 					o[id] = element.val();
 				}
 			}
-			
+
 		});
 		return o;
 	},
@@ -609,7 +609,7 @@ $.fn.extend({
     		if(enableReadOnly){
 	    		obj.find('input,textarea,select').attr('readonly','readonly');
 	    		obj.find('textarea[data-type="wysiwyg"]').trumbowyg('disable');
-	    		
+
 	    		obj.find('input[data-type],select[data-type],textarea[data-type]').each(function(){
 	    			var input = $(this);
 	    			var component = input.data("data-component");
@@ -619,8 +619,8 @@ $.fn.extend({
 	    			}
 	    			if(component) component.attr('readonly','readonly');
 	    		});
-	    		
-	    		
+
+
 	    	}else{
 	    		obj.find('input,textarea,select').removeAttr('readonly');
 	    		obj.find('textarea[data-type="wysiwyg"]').trumbowyg('enable');
@@ -794,7 +794,7 @@ $.fn.extend({
 
 			var paginationPreferenceUid = ($.urlParam('module')?$.urlParam('module'):'main')+'-'+($.urlParam('page')?$.urlParam('page') :'main')+'-'+obj.attr('id');
 			var paginationPreference = $.storage('pagination');
-			
+
 			if(paginationPreference[paginationPreferenceUid]){
 				//si une valeur est présente dans le localstorage on la prend
 				option.itemPerPage = paginationPreference[paginationPreferenceUid];
@@ -815,7 +815,7 @@ $.fn.extend({
 				container = $('>tbody',obj);
 				model = container.find('tr:first-child');
 				if(!option.export && !option.differential) container.children('tr:not(.hidden)').remove();
-			
+
 				/** début colonnes dynamiques **/
 				var slug = obj.attr('data-slug');
 				if(slug){
@@ -876,7 +876,7 @@ $.fn.extend({
 
 						$('thead tr:eq(0) th:last-child',obj).append(plusButton);
 						$('thead tr:eq(0) th[data-available]',obj).append('<i class="fas fa-times text-danger dynamic-table-delete ml-2" title="Supprimer la colonne" data-tooltip></i>');
-						
+
 						//Gestion events
 						$('.dynamic-table-delete',obj).click(function(){
 							element = $(this).closest('th');
@@ -884,7 +884,7 @@ $.fn.extend({
 							th.addClass('hidden');
 							$('> tbody > tr',obj).each(function(){
 								$('> td:eq('+th.index()+')',this).addClass('hidden');
-							});	
+							});
 							dynamic_table_refresh_menu(obj);
 							dynamic_table_save(obj);
 						});
@@ -953,11 +953,11 @@ $.fn.extend({
 			//fix images url not found on template
 			tpl = tpl.replace(/(<img\s[^>]*\s?)(data-src)/g,'$1src');
 
-			var pagination = 
+			var pagination =
 				obj.attr('data-pagination')!=null && $(obj.attr('data-pagination')).length ?
 					$(obj.attr('data-pagination')) :
-					(obj.nextAll('.pagination').length ? 
-						obj.nextAll('.pagination') : 
+					(obj.nextAll('.pagination').length ?
+						obj.nextAll('.pagination') :
 						obj.parent().nextAll('.pagination')
 					);
 
@@ -1174,7 +1174,7 @@ $.fn.extend({
 			var response = {};
 			obj.find('thead th[data-sortable]').each(function(i,th){
 				var th = $(th);
-				
+
 				if(th.attr('data-sort') && th.attr('data-sort')!=""){
 					response = {
 						sort : th.attr('data-sort'),
@@ -1202,7 +1202,7 @@ $.fn.extend({
 				th.attr('data-sort',data.sort);
 				if(option.onSort) option.onSort();
 			});
-			
+
 		});
 	},
 	autocomplete: function(o){
@@ -1349,10 +1349,10 @@ $.fn.extend({
 							zip: selected.address.postalCode ? selected.address.postalCode : '',
 						};
 						infos.address = (infos.street && infos.street.length && infos.number && infos.number.length) ? infos.number+' '+infos.street : (infos.street ? infos.street : '');
-						
+
 						obj.removeData();
 						obj.data(infos);
-						
+
 						if(o.select) o.select(infos);
 						if(o.geocode) o.geocode(selected);
 					}
@@ -1420,7 +1420,7 @@ $.fn.extend({
 
 				picker.removeClass('active');
 				setTimeout(function(){
-					
+
 					picker.removeClass('hidden');
 					setTimeout(function(){picker.addClass('active')},50);
 				},150);
@@ -1436,10 +1436,10 @@ $.fn.extend({
 				picker.removeClass('active');
 				setTimeout(function(){picker.addClass('hidden')},200);
 			});
-			
+
 			if(input.hasAttr('required')) component.attr('required','');
 			if(input.hasAttr('readonly')) component.attr('readonly','');
-		
+
 
 		});
 	},
@@ -1500,7 +1500,7 @@ $.fn.extend({
 	phone: function (options){
 		return this.each(function(){
 			var obj = $(this);
-			
+
 			options = $.extend({
 				regex: '^[0-9]{10}$',
 				emptyField: false,
@@ -1512,7 +1512,7 @@ $.fn.extend({
 			if(options.typeOnly){
 				obj.keydown(function(event){
 					if((event.ctrlKey && ['v','a','c','x'].indexOf(event.key) !== -1) || ['Backspace','ArrowLeft','ArrowRight',' '].indexOf(event.key) !== -1) return true;
-					
+
 					var regexType = RegExp(options.typeOnly, 'g');
 					return regexType.test(event.key);
 				});
@@ -1672,7 +1672,7 @@ $.fn.extend({
 					component.container.val(item.label);
 				}
 			}
-			
+
 			//Gestion des champs déja remplis au chargement de la page
 			if(input.val() !='' && options.nullChars.indexOf(input.val())==-1){
 				var uid = input.val();
@@ -1690,7 +1690,7 @@ $.fn.extend({
 				});
 
 				container.val('Chargement...');
-			
+
 				window.componentQueue[slug].timeout = setTimeout(function(){
 					$.action({
 						action : options.edit,
@@ -1715,7 +1715,7 @@ $.fn.extend({
 			}
 
 			container.keyup(function(e){
-				if (e.ctrlKey || 
+				if (e.ctrlKey ||
 					e.key == "Control" ||
 					e.key == "ArrowUp" ||
 					e.key == "ArrowDown" ||
@@ -1726,13 +1726,13 @@ $.fn.extend({
 					e.key == "Tab" ||
 					e.key == "Alt" ||
 					e.key == "Home" ||
-					e.key == "End") 
+					e.key == "End")
 						return;
-				 
+
 				input.val('');
 			});
 
-			//autocompletion 
+			//autocompletion
 			container.autocomplete({
 				action : options.autocomplete,
 				suggest : function(){ return  !input.is('[readonly]') && !input.is('[disabled]')},
@@ -1769,7 +1769,7 @@ $.fn.extend({
 			elem.filter(':not([data-lazy=""])').each(function() {
 				var element = $(this);
 	        	var elemOffsetTop = element.offset().top;
-				//Si parent est $(window) on récupère la valeur du scrollTop, sinon on prend la valeur du offsetTop du parent 
+				//Si parent est $(window) on récupère la valeur du scrollTop, sinon on prend la valeur du offsetTop du parent
 				var viewportOffset = viewportHeight + ((parent.get(0)===parent.get(0).window) ? parent.scrollTop() : parent.offset().top);
 
 				//Check si l'image se situe (en px) à 1/3 de sa taille ou moins du bas du viewport du parent pour le requêter
@@ -1779,7 +1779,7 @@ $.fn.extend({
 
 					//Check pour ajouter attribut src (tag IMG) ou mettre en background-image (tag autre)
 					element.is('img') ? element.attr({src: srcImg}) : element.css({"background-image": 'url('+srcImg+')'});
-					
+
 					if(callback!=null) {
 						elementEvent = !element.is('img') ? $('<img/>').attr('src', srcImg) : element;
 
@@ -1799,7 +1799,7 @@ $.fn.extend({
 		//Appel qd parent scroll
 	    parent.off('scroll').on('scroll', function(){
 	    	if(window.scrollTimer) clearTimeout(window.scrollTimer);
-	    	//Ajout timeout pour éviter de trigger à 
+	    	//Ajout timeout pour éviter de trigger à
 	    	//chaque scroll, on attend que le user stabilise
 	    	window.scrollTimer = setTimeout(function(){
 	    		obj.lazyload(obj,parent,callback);

+ 3 - 3
login.php

@@ -2,20 +2,20 @@
 global $conf,$myUser;
 $loginMenu = array();
 Plugin::callHook("menu_login", array(&$loginMenu));
-uasort ($loginMenu , function($a,$b){return $a['sort']>$b['sort']?1:-1;}); 
+uasort ($loginMenu , function($a,$b){return $a['sort']>$b['sort']?1:-1;});
 
 ?>
 <div id="loginForm" class="form-inline mt-mb-0 login-form">
 	<label for="login">Identifiant</label>
 	<input name="login" id="login" maxlength="260" class="form-control form-control-sm mb-2" type="text" required autofocus="true" autocomplete="username">
-	<label for="password">Mot de passe</label> 
+	<label for="password">Mot de passe</label>
 	<input data-type="password" name="password" id="password" class="form-control form-control-sm " type="password" required autocomplete="current-password">
 	<div class="form-check connexion-remember mb-1" title="Cocher la case pour enregistrer la session de connexion">
 	    <label class="form-check-label pointer" onclick="event.stopPropagation();"><input data-type="checkbox" class="" type="checkbox" id="rememberMe" name="rememberMe"> Rester connecté</label>
 	</div>
 	<div class="btn btn-primary btn-sm btn-login w-100" title="Connexion" id="login-button" onclick="core_login(this)" tabindex="0">
 		<i class="fas fa-fw fa-sign-in-alt"></i> Se connecter</div>
-	
+
 	<?php foreach($loginMenu as $item): ?>
 		<?php if(isset($item['custom'])):
 			echo $item['custom'];

+ 1 - 1
migration/migration.php

@@ -392,7 +392,7 @@ addStep('Dictionary : Correctif de la faute historique', function($mode){
 
 addStep('Host : input client en dynamicForm', function($mode){
 	Plugin::need('dynamicform/DynamicForm, dynamicform/DynamicField, dynamicform/DynamicValue, host/Machine, client/Client');
-	
+
 	$form = DynamicForm::load(array('slug'=>'host-sheet'));
 	if($form)return;
 	$form = new DynamicForm();

+ 2 - 2
plugin/activedirectory/AdFirmRank.class.php

@@ -12,7 +12,7 @@ class AdFirmRank extends Entity{
 	public $rank; //Rang ERP (Rang)
 	public $group; //Groupe AD (Liste classique)
 	public $server; //Serveur (Nombre Entier)
-	
+
 	protected $TABLE_NAME = 'activedirectory_ad_firm_rank';
 	public $entityLabel = 'Liaison groupe rang';
 	public $fields = array(
@@ -25,6 +25,6 @@ class AdFirmRank extends Entity{
 
 	//Colonnes indexées
 	public $indexes = array();
-	
+
 }
 ?>

+ 33 - 33
plugin/activedirectory/AdServer.class.php

@@ -21,9 +21,9 @@ class AdServer extends Entity{
 	public $adminPassword; //Mot de passe compte administrateur (Mot de passe)
 	public $mapping; //Plan de liaisons des champs (Texte Long)
 	public $authenticationMode = 'samaccountname'; //Authentication mode (Texte)
-	
+
 	private $datasource; //Ressource AD
-	
+
 	protected $TABLE_NAME = 'activedirectory_ad_server';
 	public $entityLabel = 'Serveur active directory';
 	public $fields = array(
@@ -41,10 +41,10 @@ class AdServer extends Entity{
 		'adminPassword' => array('type'=>'password','label' => 'Mot de passe compte administrateur'),
 		'mapping' => array('type'=>'textarea','label' => 'Plan de liaisons des champs'),
 		'authenticationMode' => array('type'=>'text','label' => 'Authentication mode'),
-	
+
 	);
 
-	//retourne le mapping champ ad -> champ ustilisateur de base 
+	//retourne le mapping champ ad -> champ ustilisateur de base
 	function default_mapping(){
 		$mapping = array(
 			'sn'=>array('label'=>'Nom','field'=>'name','source'=>'active_directory'),
@@ -54,18 +54,18 @@ class AdServer extends Entity{
 			'mobile'=>array('label'=>'Téléphone mobile','field'=>'mobile','source'=>'active_directory'),
 			'title'=>array('label'=>'Fonction','field'=>'function','source'=>'active_directory'),
 			//prend le samaccountname ou le userprincipalname en fct de la conf
-			'samaccountname'=>array('label'=>'samaccountname','field'=>function(&$user,$infos){ 
+			'samaccountname'=>array('label'=>'samaccountname','field'=>function(&$user,$infos){
 				$user->login = str_replace($this->domain,'',mb_strtolower($infos[$this->authenticationMode][0]));
 			},'source'=>'active_directory'),
 			'origin'=>array('label'=>'samaccountname','field'=>'origin','value'=>'active_directory','source'=>'hardcoded'),
 			'department'=>array('label'=>'Nom','field'=>'service','source'=>'active_directory'),
-			'thumbnailphoto'=>array('label'=>'Photo 1','field'=>function(&$user,$infos){ 
+			'thumbnailphoto'=>array('label'=>'Photo 1','field'=>function(&$user,$infos){
 				$user->meta['ldap_avatar'] = base64_encode($infos['thumbnailphoto'][0]);
 			},'source'=>'active_directory'),
-			'jpegphoto'=>array('label'=>'Photo 2','field'=>function(&$user,$infos){ 
+			'jpegphoto'=>array('label'=>'Photo 2','field'=>function(&$user,$infos){
 				$user->meta['ldap_avatar'] = base64_encode($infos['jpegphoto'][0]);
 			},'source'=>'active_directory'),
-			'accountexpires'=>array('label'=>'Expiration','field'=>function(&$user,$infos){ 
+			'accountexpires'=>array('label'=>'Expiration','field'=>function(&$user,$infos){
 				$seconds = (float)($infos['accountexpires'][0] / 10000000);
 				//Convertion d'un timestamp AD en timestamp UNIX
 				$timestamp = round($seconds - (((1970-1601) * 365.242190) * 86400));
@@ -75,12 +75,12 @@ class AdServer extends Entity{
 			'memberof'=>array('label'=>'Membre de','field'=>'','source'=>'active_directory'),
 			'manager'=>array('label'=>'Manager','field'=>'manager','source'=>'active_directory'),
 			'userprincipalname'=>array('label'=>'userprincipalname','field'=>'','source'=>'active_directory'),
-			'whencreated'=>array('label'=>'Date création','field'=>function(&$user,$infos){ 
+			'whencreated'=>array('label'=>'Date création','field'=>function(&$user,$infos){
 				if(!isset($infos['whencreated'][0]) || strlen($infos['whencreated'][0])<12 ) return;
 				$created = substr($infos['whencreated'][0],0,8).' '.substr($infos['whencreated'][0],8,2).':'.substr($infos['whencreated'][0],10,2);
 				$user->created = strtotime($created);
 			},'source'=>'active_directory')
-				
+
 		);
 
 		return $mapping;
@@ -89,7 +89,7 @@ class AdServer extends Entity{
 	//retourn les mapping champ ad->champ user par défaut + customs
 	function getMapping(){
 		$mapping = array();
-		
+
 		$jsonmapping = json_decode($this->mapping,true) ;
 		if(is_array($jsonmapping)){
 			foreach(json_decode($this->mapping,true) as $json){
@@ -98,7 +98,7 @@ class AdServer extends Entity{
 				$mapping[$json['slug']]= $json;
 			}
 		}
-	
+
 		$mapping = array_merge(self::default_mapping(),$mapping);
 
 		return $mapping;
@@ -136,11 +136,11 @@ class AdServer extends Entity{
 
 		if($ip==null || $port==null || $this->userRoot==null) throw new Exception('Paramètres de connexion manquants',400);
 		$this->datasource = ldap_connect($ip);
-		if(!$this->datasource) throw new Exception('Connexion échouée', 404);	
+		if(!$this->datasource) throw new Exception('Connexion échouée', 404);
 
 		ldap_set_option($this->datasource,LDAP_OPT_PROTOCOL_VERSION,$this->protocolVersion);
 		ldap_set_option($this->datasource, LDAP_OPT_REFERRALS, 0);
-		
+
 		switch($options['mode']){
 			case 'admin':
 				$login = $this->adminLogin;
@@ -155,18 +155,18 @@ class AdServer extends Entity{
 				$password = $options['password'];
 			break;
 		}
-	
+
 		try{
 			if(@ldap_bind($this->datasource,$login,$password) == false)
 				throw new Exception(ldap_error($this->datasource), 403);
-			
+
 		}catch(Exception $e){
 			if(ldap_errno($this->datasource)==49){
 				throw new Exception('Identifiant ou mot de passe incorrect', 403);
 			}else{
 				throw new Exception('Connexion échouée :'.ldap_error($this->datasource), 404);
 			}
-			
+
 		}
 	}
 
@@ -222,17 +222,17 @@ class AdServer extends Entity{
 
 		$default_filters = array();
 		$filterChain = '';
-		
+
 		$default_filters['objectClass'] = 'user';
 		$default_filters['objectCategory'] = 'person';
 
 		$filters = array_merge($default_filters,$filters);
 
 		if(count($filters)>1) $filterChain ='(&';
-	
+
 		foreach($filters as $key=>$value)
 			$filterChain .= '('.$key.'='.$value.')';
-		
+
 		if(count($filters)>1) $filterChain .= ')';
 
 		$entries = $this->search(explode(PHP_EOL,$this->userRoot),$filterChain,$options['select'],$options['limit']);
@@ -287,7 +287,7 @@ class AdServer extends Entity{
 				$users[$key] = $user;
 			}
 		}
-		
+
 		return $users;
 	}
 
@@ -304,18 +304,18 @@ class AdServer extends Entity{
 			if($attribute['source']=='hardcoded' && !empty($attribute['value'])){
 				$user->$field = $attribute['value'];
 				continue;
-			} 
+			}
 
 			//si aucune correspondance trouvée dans l'entrée ldap on passe au suivant
 			if(empty($entry[$ldap]) || empty($entry[$ldap][0])) continue;
-			
+
 
 			//si le field définit est une méthode anonyme
 			if(!is_string($field)){
 				$field($user,$entry);
 			//si le field définit est un simple attribut
 			}else{
-				
+
 				if(property_exists($user,$field)){
 					$user->$field = $entry[$ldap][0];
 				}else{
@@ -324,7 +324,7 @@ class AdServer extends Entity{
 			}
 		}
 
-		
+
 
 		//Récuperation des groupes direct et indirects
 		$user->groups = array();
@@ -344,12 +344,12 @@ class AdServer extends Entity{
 		$user->groups[] = $groupItem['label'];
 
 		if(isset($ranks[$groupItem['label']])){
-			
+
 			foreach($ranks[$groupItem['label']] as $firmrank){
 				$user->ranks[$firmrank->firm][$firmrank->rank] = $firmrank->join('rank');
 				$user->firms[$firmrank->firm] = $firmrank->join('firm');
 			}
-			
+
 		}
 
 		foreach($groupItem['memberof'] as $parentDn){
@@ -411,26 +411,26 @@ class AdServer extends Entity{
 
 		$default_filters = array();
 		$filterChain = '';
-		
+
 		$default_filters['objectClass'] = 'group';
 
 		$filters = array_merge($default_filters,$filters);
 
 		if(count($filters)>1) $filterChain ='(&';
-	
+
 		foreach($filters as $key=>$value)
 			$filterChain .= '('.$key.'='.$value.')';
-		
+
 		if(count($filters)>1) $filterChain .= ')';
 
-		
+
 		$entries = $this->search(explode(PHP_EOL,$this->groupRoot),$filterChain,array('name','memberOf'));
-		
+
 
 
 		for($i=0; $i<$entries['count']; $i++){
 			$info = $entries[$i];
-		
+
 			$group = array(
 				'label' => $info['name'][0],
 				'dn' => $info['dn'],

+ 40 - 40
plugin/activedirectory/action.php

@@ -5,7 +5,7 @@
 		global $_;
 		User::check_access('activedirectory','read');
 		require_once(__DIR__.SLASH.'AdServer.class.php');
-		
+
 		// OPTIONS DE RECHERCHE, A ACTIVER POUR UNE RECHERCHE AVANCEE
 		$query = 'SELECT main.* FROM '.AdServer::tableName().' main  WHERE 1';
 		$data = array();
@@ -30,9 +30,9 @@
 		$response['pagination'] = AdServer::paginate($itemPerPage,(!empty($_['page'])?$_['page']:0),$query,$data,'main');
 
 		$adservers = AdServer::staticQuery($query,$data,true,0);
-		
 
-		
+
+
 
 		$response['rows'] = array();
 		foreach($adservers as $adserver){
@@ -42,24 +42,24 @@
 				$row['created'] = date('d-m-Y',$row['created']);
 				$row['updated'] = date('d-m-Y',$row['updated']);
 			}
-			
+
 			$response['rows'][] = $row;
 		}
-		
+
 		/* Mode export */
 		if($_['export'] == 'true'){
 			if(empty($response['rows'])) $response['rows'][] = array('Vide'=>'Aucune données');
 			$fieldsMapping = array();
-			foreach (AdServer::fields(false) as $key => $value) 
+			foreach (AdServer::fields(false) as $key => $value)
 				$fieldsMapping[$value['label']] = $key;
 			$stream = Excel::exportArray($response['rows'],$fieldsMapping ,'Export');
 			File::downloadStream($stream,'export-adserver-'.date('d-m-Y').'.xlsx');
 			exit();
 		}
-		
+
 	});
-	
-	
+
+
 	//Ajout ou modification d'élément serveur active directory
 	Action::register('activedirectory_adserver_save',function(&$response){
 		global $_;
@@ -84,10 +84,10 @@
 
 		$response = $item->toArray();
 	});
-	
 
 
-	
+
+
 	//Suppression d'élement serveur active directory
 	Action::register('activedirectory_fields_search',function(&$response){
 		global $_;
@@ -96,17 +96,17 @@
 		if(empty($_['id']) || !is_numeric($_['id'])) throw new Exception("Identifiant incorrect");
 		$server = AdServer::getById($_['id']);
 		$server->login();
-	
+
 
 		$response['groups'] = array();
 		foreach($server->groups() as $group){
 			$response['groups'][] = $group['label'];
 		}
-		
+
 		$server->logout();
 
 	});
-	
+
 	//Suppression d'élement serveur active directory
 	Action::register('activedirectory_adserver_delete',function(&$response){
 		global $_;
@@ -115,7 +115,7 @@
 		if(empty($_['id']) || !is_numeric($_['id'])) throw new Exception("Identifiant incorrect");
 		AdServer::deleteById($_['id']);
 	});
-	
+
 	//Test de connexion au serveur / OUs
 	Action::register('activedirectory_adserver_test',function(&$response){
 		global $_;
@@ -149,14 +149,14 @@
 			}catch(Exception $e){
 
 				switch($e->getCode()){
-					case 400 : 
-						$response['data_validity'] = false;  
-						$response['server_reachable'] = false; 
+					case 400 :
+						$response['data_validity'] = false;
+						$response['server_reachable'] = false;
 						$response['authentication_admin'] = false;
 						$response['authentication_readonly'] = false;
 					break;
-					case 404 :  
-						$response['server_reachable'] = false; 
+					case 404 :
+						$response['server_reachable'] = false;
 						$response['authentication_admin'] = false;
 						$response['authentication_readonly'] = false;
 					break;
@@ -167,14 +167,14 @@
 
 		}catch(Exception $e){
 			switch($e->getCode()){
-				case 400 : 
-					$response['data_validity'] = false;  
-					$response['server_reachable'] = false; 
+				case 400 :
+					$response['data_validity'] = false;
+					$response['server_reachable'] = false;
 					$response['authentication_admin'] = false;
 					$response['authentication_readonly'] = false;
 				break;
-				case 404 :  
-					$response['server_reachable'] = false; 
+				case 404 :
+					$response['server_reachable'] = false;
 					$response['authentication_admin'] = false;
 					$response['authentication_readonly'] = false;
 				break;
@@ -183,7 +183,7 @@
 			$response['error_detail'] = $e->getMessage();
 		}
 	});
-	
+
 
 	//Sauvegarde des configurations de Active directory
 	Action::register('activedirectory_setting_save',function(&$response){
@@ -200,7 +200,7 @@
 				$conf->put($key,$value);
 		}
 	});
-	
+
 
 	/** AdFirmRank / LIAISON GROUPE RANG **/
 	//Récuperation d'une liste de liaison groupe rang
@@ -209,9 +209,9 @@
 		User::check_access('activedirectory','read');
 		require_once(__DIR__.SLASH.'AdFirmRank.class.php');
 		require_once(__ROOT__.SLASH.'plugin/activedirectory/AdServer.class.php');
-		
+
 		// OPTIONS DE RECHERCHE, A ACTIVER POUR UNE RECHERCHE AVANCEE
-		$query = 'SELECT main.*,main.id as id, '.Firm::joinString('f').', '.Rank::joinString('r').' FROM '.AdFirmRank::tableName().' main  
+		$query = 'SELECT main.*,main.id as id, '.Firm::joinString('f').', '.Rank::joinString('r').' FROM '.AdFirmRank::tableName().' main
 			LEFT JOIN '.Firm::tableName().' f ON f.id=main.firm
 			LEFT JOIN '.Rank::tableName().' r ON r.id=main.rank
 		  WHERE 1';
@@ -237,9 +237,9 @@
 		$response['pagination'] = AdFirmRank::paginate($itemPerPage,(!empty($_['page'])?$_['page']:0),$query,$data,'main');
 
 		$adFirmRanks = AdFirmRank::staticQuery($query,$data,true,1);
-		
 
-		
+
+
 
 		$response['rows'] = array();
 		foreach($adFirmRanks as $adFirmRank){
@@ -252,24 +252,24 @@
 				$row['created'] = date('d-m-Y',$row['created']);
 				$row['updated'] = date('d-m-Y',$row['updated']);
 			}
-			
+
 			$response['rows'][] = $row;
 		}
-		
+
 		/* Mode export */
 		if($_['export'] == 'true'){
 			if(empty($response['rows'])) $response['rows'][] = array('Vide'=>'Aucune données');
 			$fieldsMapping = array();
-			foreach (AdFirmRank::fields(false) as $key => $value) 
+			foreach (AdFirmRank::fields(false) as $key => $value)
 				$fieldsMapping[$value['label']] = $key;
 			$stream = Excel::exportArray($response['rows'],$fieldsMapping ,'Export');
 			File::downloadStream($stream,'export-AdFirmRank-'.date('d-m-Y').'.xlsx');
 			exit();
 		}
-		
+
 	});
-	
-	
+
+
 	//Ajout ou modification d'élément liaison groupe rang
 	Action::register('activedirectory_ad_firm_rank_save',function(&$response){
 		global $_;
@@ -284,7 +284,7 @@
 
 		$response = $item->toArray();
 	});
-	
+
 	//Récuperation ou edition d'élément liaison groupe rang
 	Action::register('activedirectory_ad_firm_rank_edit',function(&$response){
 		global $_;
@@ -293,7 +293,7 @@
 		require_once(__DIR__.SLASH.'AdFirmRank.class.php');
 		$response = AdFirmRank::getById($_['id'],1)->toArray();
 	});
-	
+
 
 	//Suppression d'élement liaison groupe rang
 	Action::register('activedirectory_ad_firm_rank_delete',function(&$response){
@@ -304,7 +304,7 @@
 		AdFirmRank::deleteById($_['id']);
 	});
 
-	
+
 
 
 ?>

+ 13 - 13
plugin/activedirectory/activedirectory.plugin.php

@@ -23,7 +23,7 @@ function activedirectory_action(){
 //Déclaration du menu de réglages
 function activedirectory_menu_setting(&$settingMenu){
 	global $myUser;
-	
+
 	if(!$myUser->can('activedirectory','configure')) return;
 	$settingMenu[]= array(
 		'sort' =>1,
@@ -54,7 +54,7 @@ function activedirectory_directory_list(&$usermapping){
 }
 
 function activedirectory_account_global(){
-	global $myUser; 
+	global $myUser;
 	require_once(__DIR__.SLASH.'AdServer.class.php');
 	$metas = array();
 	//todo récuperer les meta pour tous les serveurs ad
@@ -86,8 +86,8 @@ function activedirectory_login(&$user,$login,$password,$loadRight,$loadManager=t
 
 	foreach(AdServer::loadAll() as $server){
 
-		try{			
-			
+		try{
+
 			$options = array();
 			if(!$noPassword) $options = array('mode'=>'login','login'=>$login.$server->domain,'password'=> $password);
 
@@ -115,14 +115,14 @@ function activedirectory_login(&$user,$login,$password,$loadRight,$loadManager=t
 			if(!isset($users[$login])) return;
 
 			$user = $users[$login];
-			
+
 			$avatarPath = __ROOT__.FILE_PATH.AVATAR_PATH.$user->login.'.jpg';
 			if(isset($user->meta['ldap_avatar']) && !file_exists(__ROOT__.FILE_PATH.AVATAR_PATH.$user->login.'.gif')){
 				if(!file_exists(__ROOT__.FILE_PATH.AVATAR_PATH)) mkdir(__ROOT__.FILE_PATH.AVATAR_PATH,0755,true);
 				file_put_contents($avatarPath,base64_decode($user->meta['ldap_avatar']));
 			}
-			
-			
+
+
 			$server->logout();
 			break;
 		}catch(Exception $e){
@@ -135,7 +135,7 @@ function activedirectory_login(&$user,$login,$password,$loadRight,$loadManager=t
 function activedirectory_user_get_all(&$users,$options){
 
 	require_once(__DIR__.SLASH.'AdServer.class.php');
-	
+
 	global $conf;
 
 	foreach (AdServer::loadAll() as $server) {
@@ -174,7 +174,7 @@ function activedirectory_user_save(&$user,$userForm,&$response){
 	}
 
 	$server = AdServer::getById($meta['activedirectory_server']);
-   
+
     if($server->adminLogin=='') throw new Exception("Le compte AD admin n'est pas configuré, veuillez contacter un administrateur");
 	$server->login(array('mode'=>'admin'));
 
@@ -195,7 +195,7 @@ function activedirectory_user_save(&$user,$userForm,&$response){
 		$temp = explode('.', $temp);
 		array_pop($temp);
 		$temp = implode('.',$temp).'.jpg';
-		
+
 		if(file_exists($temp)){
 			$changes['jpegphoto'] = file_get_contents($temp);
 			unlink($temp);
@@ -225,12 +225,12 @@ Configuration::setting('activedirectory',array(
 ));
 
 //Déclation des assets
-Plugin::addCss("/css/main.css"); 
-Plugin::addJs("/js/main.js"); 
+Plugin::addCss("/css/main.css");
+Plugin::addJs("/js/main.js");
 
 //Mapping hook / fonctions
 Plugin::addHook("install", "activedirectory_install");
-Plugin::addHook("uninstall", "activedirectory_uninstall"); 
+Plugin::addHook("uninstall", "activedirectory_uninstall");
 Plugin::addHook("menu_setting", "activedirectory_menu_setting");
 Plugin::addHook("content_setting", "activedirectory_content_setting");
 

+ 4 - 4
plugin/activedirectory/js/main.js

@@ -1,6 +1,6 @@
 //CHARGEMENT DE LA PAGE
 function init_setting_activedirectory(){
-	
+
 
 	$('#adservers').sortable_table({
 		onSort : activedirectory_adserver_search
@@ -17,9 +17,9 @@ function init_setting_sheet_adserver(){
 
 //Enregistrement des configurations
 function activedirectory_setting_save(){
-	$.action({ 
-		action: 'activedirectory_setting_save', 
-		fields:  $('#activedirectory-setting-form').toJson() 
+	$.action({
+		action: 'activedirectory_setting_save',
+		fields:  $('#activedirectory-setting-form').toJson()
 	},function(){
 		$.message('success','Enregistré');
 	});

+ 14 - 14
plugin/activedirectory/setting.list.ad.firm.rank.php

@@ -10,8 +10,8 @@ require_once(__DIR__.SLASH.'AdFirmRank.class.php');
 ?>
 <div class="plugin-activedirectory">
     <div class="row">
-   
-        
+
+
         <div class="col-md-12">
             <select id="activedirectory_ad_firm_rank-filters" data-type="filter" data-label="Recherche" data-function="activedirectory_ad_firm_rank_search">
                 <option value="main.label" data-filter-type="text">Libellé</option>
@@ -20,7 +20,7 @@ require_once(__DIR__.SLASH.'AdFirmRank.class.php');
                 <option value="main.group" data-filter-type="list" data-values='<?php echo json_encode($groups); ?>' >Groupe AD</option>
             </select>
         </div>
-        
+
     </div>
     <h5 class="results-count my-2"><span></span> Résultat(s)
         <!-- bloc de preference de pagination -->
@@ -30,9 +30,9 @@ require_once(__DIR__.SLASH.'AdFirmRank.class.php');
     	<!-- search results -->
     	<div class="col-xl-12">
 
-            
 
-    		
+
+
             <!-- présentation tableau -->
             <table id="ad-firm-ranks" class="table table-striped mb-0" data-entity-search="activedirectory_ad_firm_rank_search">
                 <thead>
@@ -44,10 +44,10 @@ require_once(__DIR__.SLASH.'AdFirmRank.class.php');
                         <th></th>
                     </tr>
                 </thead>
-                
+
                 <thead>
                     <tr id="ad-firm-rank-form" data-action="activedirectory_ad_firm_rank_save" data-id="">
-                    
+
                         <th>
                             <select class="form-control select-control" type="text" value id="group" ></select>
                         </th>
@@ -56,18 +56,18 @@ require_once(__DIR__.SLASH.'AdFirmRank.class.php');
                         <th class="text-right"><div onclick="activedirectory_ad_firm_rank_save();" class="btn btn-success" title="Enregistrer" data-tooltip><i class="fas fa-check"></i></div></th>
                     </tr>
                 </thead>
-                
+
                 <tbody>
                     <tr data-id="{{id}}" class="hidden item-line">
     	                <!--<td class="align-middle">{{id}}</td>-->
     	                <td class="align-middle">{{group}}</td>
                         <td class="align-middle"><a href="setting.php?section=right&rank={{rank.id}}">{{rank.label}}</a></td>
                         <td class="align-middle"><a href="firm.php?id={{firm.id}}">{{firm.label}}</a></td>
-    	                
-    	                
+
+
     	                <td class="align-middle text-right">
                             <div class="btn-group btn-group-sm" role="group">
-                                
+
                                 <div class="btn text-info" title="Éditer ad_firm_rank" onclick="activedirectory_ad_firm_rank_edit(this);"><i class="fas fa-pencil-alt"></i></div>
                                 <div class="btn text-danger" title="Supprimer ad_firm_rank" onclick="activedirectory_ad_firm_rank_delete(this);"><i class="far fa-trash-alt"></i></div>
                             </div>
@@ -75,16 +75,16 @@ require_once(__DIR__.SLASH.'AdFirmRank.class.php');
                     </tr>
                </tbody>
             </table>
-            
 
-            
+
+
              <!-- Pagination (data-range définit le nombre de pages max affichées avant et après la page courante) -->
             <ul class="pagination justify-content-center"  data-range="5">
                 <li class="page-item hidden" data-value="{{value}}" title="Voir la page {{label}}" onclick="$(this).parent().find('li').removeClass('active');$(this).addClass('active');activedirectory_ad_firm_rank_search();">
                     <span class="page-link">{{label}}</span>
                 </li>
             </ul>
-          
+
     	</div>
     </div>
 </div>

+ 16 - 16
plugin/activedirectory/setting.list.adserver.php

@@ -32,18 +32,18 @@ require_once(__DIR__.SLASH.'AdServer.class.php');
                     <div onclick="window.print();" class="btn btn-info rounded-0 btn-squarred" title="Imprimer la page"><i class="fas fa-print"></i></div>
                     <div onclick="activedirectory_adserver_search(null,true);" id="export-activedirectorys-btn" class="btn btn-info rounded-0 btn-squarred ml-1 btn-export" title="Exporter les résultats"><i class="fas fa-file-export"></i></div>
                 </div>
-                
-                
+
+
                 <div class="my-auto ml-auto mr-0 noPrint">
                     <?php if($myUser->can('activedirectory', 'edit')) : ?>
                     <a href="setting.php?section=sheet.adserver" class="btn btn-success right"><i class="fas fa-plus"></i> Ajouter</a>
                     <?php endif; ?>
                 </div>
-                
+
             </div>
             <div class="clear noPrint"></div>
         </div>
-        
+
         <div class="col-md-12">
             <select id="activedirectory_adserver-filters" data-type="filter" data-label="Recherche" data-function="activedirectory_adserver_search">
                 <option value="main.label" data-filter-type="text">Libellé</option>
@@ -60,7 +60,7 @@ require_once(__DIR__.SLASH.'AdServer.class.php');
                 <option value="main.defaultRank" data-filter-type="rank">Rang par défaut</option>
             </select>
         </div>
-        
+
     </div>
     <h5 class="results-count my-2"><span></span> Résultat(s)
         <!-- bloc de preference de pagination -->
@@ -70,9 +70,9 @@ require_once(__DIR__.SLASH.'AdServer.class.php');
     	<!-- search results -->
     	<div class="col-xl-12">
 
-            
 
-    		
+
+
             <!-- présentation tableau -->
             <table id="adservers" class="table table-striped " data-entity-search="activedirectory_adserver_search">
                 <thead>
@@ -80,28 +80,28 @@ require_once(__DIR__.SLASH.'AdServer.class.php');
                         <!--<th>#</th>-->
                         <th data-sortable="ip">IP</th>
                         <th data-sortable="port">Port</th>
-                       
+
                         <th data-sortable="domain">Domaine</th>
                         <th data-available="userRoot" data-sortable="protocolVersion">Version</th>
-                        
+
                         <th data-available="userRoot" data-sortable="userRoot">Racines</th>
-  
+
                         <th></th>
                     </tr>
                 </thead>
-                
+
                 <tbody>
                     <tr data-id="{{id}}" class="hidden item-line">
     	                <!--<td class="align-middle">{{id}}</td>-->
     	                <td class="align-middle">{{ip}}</td>
     	                <td class="align-middle">{{port}} / {{sslPort}}</td>
-    	             
+
                         <td class="align-middle">{{domain}}</td>
     	                <td class="align-middle">{{protocolVersion}}</td>
     	                <td class="align-middle"><small class="text-muted">{{userRoot}}<br>{{groupRoot}}</small></td>
 
-    	              
-    
+
+
     	                <td class="align-middle text-right">
                             <div class="btn-group btn-group-sm" role="group">
                                 <a class="btn text-info" title="Éditer adserver" href="setting.php?section=sheet.adserver&id={{id}}"><i class="fas fa-pencil-alt"></i></a>
@@ -111,7 +111,7 @@ require_once(__DIR__.SLASH.'AdServer.class.php');
                     </tr>
                </tbody>
             </table>
-            
+
 
             <br>
              <!-- Pagination (data-range définit le nombre de pages max affichées avant et après la page courante) -->
@@ -120,7 +120,7 @@ require_once(__DIR__.SLASH.'AdServer.class.php');
                     <span class="page-link">{{label}}</span>
                 </li>
             </ul>
-          
+
     	</div>
     </div>
 </div>

+ 10 - 10
plugin/activedirectory/setting.sheet.adserver.php

@@ -1,4 +1,4 @@
-<?php 
+<?php
 User::check_access('activedirectory','read');
 require_once(__DIR__.SLASH.'AdServer.class.php');
 $adserver = AdServer::provide();
@@ -8,17 +8,17 @@ $adserver = AdServer::provide();
 <div class="plugin-activedirectory">
 	<div id="adserver-form" class="row justify-content-md-center adserver-form" data-action="activedirectory_adserver_save" data-id="<?php echo $adserver->id; ?>">
 		<div class="col-md-12">
-			<h3>SERVEUR 
+			<h3>SERVEUR
 			<div onclick="activedirectory_adserver_save();" class="btn btn-small btn-success right"><i class="fas fa-check"></i> Enregistrer</div>
 			<div onclick="activedirectory_adserver_test();" class="btn btn-small btn-test btn-primary right  mr-2"><i class="fas fa-vial"></i> Tester</div>
 			<a href="setting.php?section=list.adserver" class="btn btn-small btn-dark right  mr-2">Retour</a></h3>
-			
+
 
 			<div id="activedirectory-test" class="activedirectory-test">
 				<template>
 					<div class="shadow-sm bg-white p-3 mb-3">
 						<h7 class="text-muted font-weight-bold">TESTS DE CONNEXION</h7>
-						
+
 						<div class="row">
 							<div class="col-md-4 activedirectory-test-block">
 								<div class="mb-3">
@@ -74,7 +74,7 @@ $adserver = AdServer::provide();
 					  <div class="input-group-prepend">
 					    <label class="input-group-text" for="ip">IP</label>
 					  </div>
-			
+
 					<input  value="<?php echo $adserver->ip; ?>" class="form-control"  type="text"  id="ip" >
 					<div class="input-group-prepend">
 					    <label class="input-group-text" for="port">Port</label>
@@ -90,7 +90,7 @@ $adserver = AdServer::provide();
 					<input  value="<?php echo $adserver->protocolVersion; ?>" class="form-control"  type="number"  id="protocolVersion" >
 				</div>
 
-				
+
 				<div class="input-group mb-3">
 					  <div class="input-group-prepend">
 					    <label class="input-group-text" for="ip">Domaine</label>
@@ -123,8 +123,8 @@ $adserver = AdServer::provide();
 
 
 				<label for="authenticationMode" class="d-block">Mode d'authentification</label>
-				
-				<?php 
+
+				<?php
 					$modes = array();
 					foreach(AdServer::authenticationModes() as $key=>$mode){
 						$modes[$key] = $mode['label'];
@@ -152,7 +152,7 @@ $adserver = AdServer::provide();
 			<div class="shadow-sm bg-white p-3 mt-3">
 				<h7 class="text-muted font-weight-bold">GROUPES & RANGS</h7>
 				<?php require_once(__DIR__.SLASH.'setting.list.ad.firm.rank.php'); ?>
-		
+
 			</div>
 
 			<div class="shadow-sm bg-white p-3 mt-3">
@@ -162,7 +162,7 @@ $adserver = AdServer::provide();
 				<input  data-format="multiple-values" data-columns='{"slug":"Champ AD","label":"Libellé","field":"Attribut Utilisateur"}' value='<?php echo $adserver->mapping; ?>'  data-type="jsontable" id="mapping">
 				<div class="clear"></div>
 			</div>
-			
+
 		</div>
 	</div>
 </div>

+ 10 - 10
plugin/client/Client.class.php

@@ -23,7 +23,7 @@ class Client extends Entity{
 	public $job; //Métier (Texte)
 	public $meta; //Meta (JSON)
 	public $firm; //Etablissement (Entier)
-	
+
 	protected $TABLE_NAME = 'client';
 	public $entityLabel = 'Client';
 	public $fields = array(
@@ -46,7 +46,7 @@ class Client extends Entity{
 		'firm' => array('type'=>'int', 'label' => 'Etablissement','link'=>'class/Firm.class.php')
 	);
 
-	
+
 
 	//Colonnes indexées
 	public $indexes = array('parent','category','type','firm');
@@ -93,7 +93,7 @@ class Client extends Entity{
 		return self::types($this->type);
 	}
 
-	
+
 	public function dir(){
 		return File::dir().'client'.SLASH.$this->id.SLASH;
 	}
@@ -154,7 +154,7 @@ class Client extends Entity{
 					$rows[] = $row;
 				}
 			break;
-			
+
 			case 'siret':
 				foreach(Client::loadAll(array(
 					'siret' => trim($label),
@@ -169,7 +169,7 @@ class Client extends Entity{
 				return;
 			break;
 		}
-		
+
 
 		return $rows;
 	}
@@ -249,17 +249,17 @@ class Client extends Entity{
 
 	public static function code($client){
 		global $conf;
-		
+
 		$mask = empty($conf->get('client_code_mask')) ? '{{label[2]}}-{{Y}}{{M}}-{{id}}' : $conf->get('client_code_mask');
 		$data = $client->toArray();
-	
+
 		$data['label'] = $client->label();
 
 		$data['M'] = date('m');
 		$data['m'] = date('m');
 		$data['Y'] = date('Y');
 		$data['y'] = date('y');
-		
+
 		$mask = preg_replace_callback('/{{label\[([0-9]*)\]}}/is', function($matches) use ($client){
 			if(count($matches)>=1){
 				return strlen($client->label>=$matches[1]) ? substr($client->label, 0,$matches[1]) : $client->label;
@@ -326,7 +326,7 @@ class Client extends Entity{
 		$contacts = array();
 		$filters = array('uid'=>$this->id,'scope'=>'client') ;
 		if(isset($key)) $filters['type'] = $key;
-		
+
 		foreach(Contact::loadAll($filters) as $contact){
 			$contacts[$contact->type] = $contact;
 		}
@@ -353,7 +353,7 @@ class Client extends Entity{
 		if($recursive){
 			foreach(Client::loadAll(array('parent'=>$this->id,'state:!='=>Client::INACTIVE)) as $subclient){
 				$subclient->remove();
-			} 
+			}
 		}
 		global $myFirm;
 		//Gestion des champs dynamiques

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 159 - 159
plugin/client/action.php


+ 8 - 8
plugin/client/card.client.php

@@ -8,7 +8,7 @@
 				<h3 class="label"><a title="Plus de détails" href="index.php?module=client&page=client.detail&id=<?php echo $client->id; ?>" target="_blank">
 					<?php echo $client->label; ?></a>
 				</h3>
-				
+
 				<small class="mail text-muted">Créé par <?php echo $client->creator; ?> le <?php echo date('d-m-Y',$client->created); ?></small>
 				<?php if($client->siret!=''): ?>
 					<br><small class="text-box"> N° SIRET <a href="https://www.societe.com/cgi-bin/search?champs=<?php echo $client->label; ?>"><?php echo $client->siret; ?></a></small>
@@ -16,20 +16,20 @@
 			</div>
 		</div>
 		<div class="content-block">
-			<?php 
+			<?php
 			$addresses = $client->addresses();
-			if(count($addresses)!=0): 
-				foreach ($addresses as $address) : 
+			if(count($addresses)!=0):
+				foreach ($addresses as $address) :
 			?>
 				<div class="mt-2">
 				<div class="font-weight-bold">Adresse [<?php echo Address::types($address->type)['label']; ?>]: </div>
 				<div class="text-box"><?php echo $address->fullName(); ?></div>
 			</div>
 			<?php	endforeach; ?>
-			
+
 			<?php endif; ?>
-			
-		 
+
+
 			<div class="clear"></div>
 		</div>
 	</div>
@@ -41,7 +41,7 @@
 
 			<small class="font-weight-bold text-uppercase text-muted">Contacts : </small>
 			<ul class="client-card-contacts">
-			<?php 
+			<?php
 			foreach($contacts as $contact): ?>
 				<li>
 				 <?php  echo $contact->fullName(); ?><br>

+ 61 - 61
plugin/client/client.plugin.php

@@ -21,7 +21,7 @@ function client_page(){
 	$page = str_replace('..','',$page);
 	$file = __DIR__.SLASH.'page.'.$page.'.php';
 	if(!file_exists($file)) throw new Exception("Page ".$page." inexistante");
-	
+
 	require_once($file);
 }
 
@@ -34,7 +34,7 @@ function client_install($id){
 
     $conf->put('client_enable_map', 1);
     $conf->put('client_sheet_max_field', 8);
-    $conf->put('client_type', "both"); 
+    $conf->put('client_type', "both");
     //Doc sur : https://entreprise.data.gouv.fr/api_doc/sirene
     $conf->put('client_api_url','https://entreprise.data.gouv.fr/api/sirene/v1/full_text/{{label}}');
     $conf->put('client_api_sheet_url','https://entreprise.data.gouv.fr/api/sirene/v3/etablissements/?siren={{siret}}');
@@ -65,7 +65,7 @@ function client_install($id){
 		$model->privacy = 'public';
 		$model->dataset = 'client-sheet';
 		$model->slug = 'client-sheet';
-		$model->description= "Modèle d'export PDF utilisé depuis la fiche d'un client"; 
+		$model->description= "Modèle d'export PDF utilisé depuis la fiche d'un client";
 		$model->document_temporary = '';
 		$model->export_format =  'pdf';
 		$model->plugin = 'client';
@@ -93,8 +93,8 @@ Right::register('client_sheet',array(
 	'check' => function($action,$right){
 		global $myUser;
 		if($right->uid <= 0) throw new Exception('Id non spécifié');
-		
-		
+
+
 		if(!$myUser->can('client','edit')) throw new Exception('Seul le un edtieur de  client peut définir des droits pour cette fiche');
 	}
 ));
@@ -104,7 +104,7 @@ require_once(__DIR__.SLASH.'action.php');
 //Déclaration du menu de réglages
 function client_menu_setting(&$settingMenu){
 	global  $myUser;
-	
+
 	if(!$myUser->can('client','configure')) return;
 	$settingMenu[]= array(
 		'sort' =>1,
@@ -135,7 +135,7 @@ Configuration::setting('client',array(
     	{{rand(x,y)}} : Chiffre aléatoire entre x et y<br>
     	",
     	"placeholder"=>"ex: {{label[2]}}-{{Y}}{{M}}-{{id}}","type"=>"text"),
-   
+
     'client_enable_map' => array("label"=>"Afficher la mini-map","type"=>"boolean"),
     'client_sheet_max_field' => array("label"=>"Nombre de champs avant résumé","type"=>"number"),
     'client_type' => array("label"=>"Type de client","type"=>"list",'values' => array('individual'=>'Particulier','firm'=>'Entreprise','both'=>'Les deux'), 'default'=>'both'),
@@ -148,7 +148,7 @@ Configuration::setting('client',array(
     'client_holding_singular' => array("label"=>"Libellé des holdings (singulier)",'placeholder'=>'holding',"type"=>"text"),
     'client_label_plural' => array("label"=>"Libellé des clients (pluriel)",'placeholder'=>'clients',"type"=>"text"),
     'client_label_singular' => array("label"=>"Libellé des clients (singulier)",'placeholder'=>'client',"type"=>"text"),
-    
+
 ));
 
 
@@ -168,7 +168,7 @@ function client_widget(&$widgets){
 	$modelWidget->description = "Module de gestion des clients et prospects";
 	$widgets[] = $modelWidget;
 }
-  
+
 
 function client_tab_menu(&$clientMenu,$client){
 	$menu = new MenuItem();
@@ -211,32 +211,32 @@ if( $myFirm->has_plugin('fr.core.export')){
 
 	ExportModel::add('client','client-sheet', 'Fiche client', function($parameters){
 		global $myUser,$myFirm;
-		
+
 		require_once(__DIR__.SLASH.'Client.class.php');
 
 		$client = new Client();
 
 		if(isset($parameters['description']) && $parameters['description']!=true && !empty($parameters['id']))
 			$client =  Client::getById($parameters['id']);
-		
+
 		$data['client'] = ExportModel::fromEntity($client);
-		
+
 
 
 		unset($data['client']['value']['parent']);
 
-		
+
 
 		if(empty($client->comment)) unset($data['client']['value']['comment']['value']);
 
 
 
-		$data['client']['value']['category']['value'] = 
+		$data['client']['value']['category']['value'] =
 		isset($data['client']['value']['category']) && $data['client']['value']['category']['value']!=0 ? Dictionary::getById($data['client']['value']['category']['value'])->label: 'Aucune';
-		
-		if(!empty($data['client']['value']['type']['value'])) 
+
+		if(!empty($data['client']['value']['type']['value']))
 			$data['client']['value']['type']['value'] = Client::types($data['client']['value']['type']['value'])['label'];
-		
+
 
 		if(!empty($data['client']['value']['condition']['value']))
 			$data['client']['value']['condition']['value'] = Client::conditions($data['client']['value']['condition']['value'])['label'];
@@ -258,7 +258,7 @@ if( $myFirm->has_plugin('fr.core.export')){
 			$contactRow['mail']['value'] = $contact->mail;
 
 			$data['client']['value']['contacts']['value'][] = $contactRow;
-			
+
 		}
 
 		//export des adresses liées
@@ -267,8 +267,8 @@ if( $myFirm->has_plugin('fr.core.export')){
 		foreach($addresses as $address){
 			$data['client']['value']['addresses']['value'][] = ExportModel::fromEntity($address)['value'];
 		}
-		
-		//export des champs custom 
+
+		//export des champs custom
 		if($myFirm->has_plugin('fr.core.dynamicform')){
 			Plugin::need('dynamicform/DynamicForm');
 			$data['client']['value']['dynamicFields'] = array('label'=>'Champs personnalisés liés', 'type'=>'list','value' => array());
@@ -285,7 +285,7 @@ if( $myFirm->has_plugin('fr.core.export')){
 						$value = $dynamicField['value'];
 						if(!isset(  $fieldTypes[$dynamicField['type']->slug])   ) continue;
 						$type = $fieldTypes[$dynamicField['type']->slug];
-						
+
 						if(!empty($value) && property_exists($type,"onRawDisplay")){
 							$method = $type->onRawDisplay;
 							$value = $method($value,array('type'=>$type));
@@ -298,7 +298,7 @@ if( $myFirm->has_plugin('fr.core.export')){
 		}
 
 
-		
+
 
 		$data['client']['value']['logo'] = array(
 			'label'=>'Logo du client',
@@ -307,12 +307,12 @@ if( $myFirm->has_plugin('fr.core.export')){
 		);
 
 		if(empty($client->comment)) $data['client']['value']['comment']['value'] = false;
-		
+
 		$parent = new Client();
 		$parent->label = 'Aucun';
 
 		if(!empty($client->parent)) $parent = Client::getById($client->parent);
-			
+
 		$data['client']['value']['parent'] = ExportModel::fromEntity($parent);
 		// print_r($data['client']['value']['parent']);
 		// print_r($client->parent);
@@ -335,11 +335,11 @@ function client_filter(&$filters){
 	global $conf;
 	require_once(__DIR__.SLASH.'Client.class.php');
 	$types = array();
-	foreach (Client::types() as $key => $value) 
+	foreach (Client::types() as $key => $value)
 	   $types[$key] = $value['label'];
-	
+
 	$conditions = array();
-	foreach (Client::conditions() as $key => $value) 
+	foreach (Client::conditions() as $key => $value)
    		$conditions[$key] = $value['label'];
 
 
@@ -376,12 +376,12 @@ function client_search_view(&$columns){
 	global $conf;
 	$hideFields = explode("\n",$conf->get('client_hide_fields'));
 	$mycolumns = array(
-            'logo' => 
+            'logo' =>
                 array(
                     'head' => '<th></th>',
                     'body' => '<td class="align-middle text-center"><img class="client-logo-mini avatar-rounded" data-src="{{logo}}"></td>',
                 ),
-             'label' => 
+             'label' =>
                 array(
                     'head' => '<th data-sortable="main.label">Libellé</th>',
                     'body' => '<td class="align-middle">
@@ -391,55 +391,55 @@ function client_search_view(&$columns){
                         {{#job}}<br/><small class="text-muted">{{{job}}}</small>{{/job}}
                     </td>',
                 ),
-            'code' => 
+            'code' =>
                 array(
                     'head' => '<th data-sortable="code" data-available="created">Code '.($conf->get('client_label_singular')).'</th>',
                     'body' => '<td class="align-middle">{{code}}</td>',
                 ),
-            'city' => 
+            'city' =>
                 array(
                     'head' => '<th data-sortable="address.city">Ville</th>',
                     'body' => '<td class="align-middle text-warning" title="{{address.street}} {{address.complement}} {{address.zip}} {{address.city}}">
                         {{address.city}} {{#address.zip}}
                         <small class="text-muted">
-                            ({{address.zip}}) 
+                            ({{address.zip}})
                             <a title="Afficher sur Google Map" target="_blank" href="{{address.mapurl}}"><i class="fas fa-map-marked-alt text-muted ml-2 pointer"></i></a>
                         </small>
                         {{/address.zip}}
                     </td>',
                 ),
-            'type' => 
+            'type' =>
                 array(
                     'head' => '<th data-sortable="main.type" data-available="main.type">Type</th>',
                     'body' => '<td class="align-middle">{{type.label}}</td>',
                 ),
-            'category' => 
+            'category' =>
                 array(
                     'head' => '<th data-sortable="category.label" data-available="main.category">Categorie</th>',
                     'body' => '<td class="align-middle">{{category.label}}</td>',
                 ),
 
-            'mail' => 
+            'mail' =>
                 array(
                     'head' => '<th data-sortable="mail.value" data-available="mail">E-mail</th>',
                     'body' => '<td class="align-middle"><a href="mailto:{{mail}}">{{mail}}</a></td>',
                 ),
-            'phone' => 
+            'phone' =>
                 array(
                     'head' => '<th data-sortable="phone.value" data-available="main.phone">Téléphone</th>',
                     'body' => '<td class="align-middle">{{phone}}</td>',
                 ),
-            'comment' => 
+            'comment' =>
                 array(
                     'head' => '<th data-sortable="main.comment" data-available="main.comment">Commentaire</th>',
                     'body' => '<td class="align-middle" ><small style="display:block;max-width:300px;max-height:40px;overflow:auto;">{{comment}}</small></td>',
                 ),
-            'condition' => 
+            'condition' =>
                 array(
                     'head' => '<th data-sortable="main.condition" data-available="main.created">Statut</th>',
                     'body' => '<td class="align-middle">{{condition.label}}</td>',
                 ),
-            'firm' => 
+            'firm' =>
                 array(
                     'head' => '<th data-sortable="fi.label" data-available="fi.label">Etablissement</th>',
                     'body' => '<td class="align-middle">{{firm.label}}</td>',
@@ -504,7 +504,7 @@ $sheet = array();
 		'value' => html_entity_decode($client->job)
 	);
 
-	
+
 	$sheet['firstname'] = array(
 		'client-type' => 'individual',
 		'label' => 'Prénom',
@@ -605,7 +605,7 @@ function client_field_type(&$types){
 	$type->slug = 'client';
 	$type->label = 'Client';
 	$type->sqlType = 'integer';
-	$type->default_attributes = 
+	$type->default_attributes =
 	array(
 		'class'=>'"form-control"',
 		'data-type'=>'"client"',
@@ -639,11 +639,11 @@ function client_field_type(&$types){
 		return '<a href="index.php?module=client&page=sheet.client&id='.$value.'">'.$client->label.'</a>';
 	};
 
-	
+
 	$type->icon = 'fab fa-black-tie';
 	$type->description = 'Autocompletion sur les clients';
 	$type->default = '';
-	$types[$type->slug] = $type; 
+	$types[$type->slug] = $type;
 }
 
 
@@ -651,48 +651,48 @@ function client_field_type(&$types){
 
 function client_sheet_option(&$options){
 		global $myUser,$_,$myFirm;
-		if($myUser->can('client','configure')): 
+		if($myUser->can('client','configure')):
 			$options[] = '<div class="dropdown-item pointer user-select-none px-3" title="Fusionner ce client" onclick="client_client_merge_edit()"><i class="fas fa-object-group text-warning"></i> Fusionner</div>';
-		endif; 
-		if($myUser->can('export', 'read') && $myFirm->has_plugin('fr.core.export')) : 
+		endif;
+		if($myUser->can('export', 'read') && $myFirm->has_plugin('fr.core.export')) :
 			$options[] = '<div class="d-inline-block" data-type="export-model" data-parameters=\''.stripslashes(json_encode(array("plugin"=>"client","dataset"=>"client-sheet","id"=>$_['id']))).'\'>
 					<div class="dropdown-item pointer user-select-none px-3" title="Exporter ce client"><i class="fas fa-download"></i> Exporter</div>
 				</div>';
-	    endif; 
-	    if($myUser->can('client','edit') || ($_['id']!=0 && $myUser->can('client_sheet','edit',$_['id']))): 
-	       	$options[] = '<div class="dropdown-item pointer user-select-none px-3" data-type="right" 
+	    endif;
+	    if($myUser->can('client','edit') || ($_['id']!=0 && $myUser->can('client_sheet','edit',$_['id']))):
+	       	$options[] = '<div class="dropdown-item pointer user-select-none px-3" data-type="right"
        				data-scope = "client_sheet" data-uid = "'.$_['id'].'"><i class="fas fa-user-lock"></i>  Permissions sur la fiche</div>';
-       	endif; 
-       	if($myUser->can('client','delete') || ($_['id']!=0 && $myUser->can('client_sheet','delete',$_['id']))): 
+       	endif;
+       	if($myUser->can('client','delete') || ($_['id']!=0 && $myUser->can('client_sheet','delete',$_['id']))):
 				$options[] = '<div class="dropdown-item text-danger pointer user-select-none px-3" title="Supprimer ce client" onclick="client_client_delete()"><i class="fa fa-trash-alt"></i> Supprimer</div>';
 		endif;
 }
 
 //Déclation des assets
-Plugin::addCss("/css/main.css"); 
-Plugin::addJs("/js/main.js"); 
+Plugin::addCss("/css/main.css");
+Plugin::addJs("/js/main.js");
 Plugin::addCss('/css/component.css');
 Plugin::addJs('/js/component.js');
 
 //Mapping hook / fonctions
 Plugin::addHook("install", "client_install");
-Plugin::addHook("uninstall", "client_uninstall"); 
+Plugin::addHook("uninstall", "client_uninstall");
 
 
-Plugin::addHook("menu_main", "client_menu"); 
-Plugin::addHook("page", "client_page");  
+Plugin::addHook("menu_main", "client_menu");
+Plugin::addHook("page", "client_page");
 
-Plugin::addHook("menu_setting", "client_menu_setting");    
-Plugin::addHook("content_setting", "client_content_setting");   
-Plugin::addHook("widget", "client_widget"); 
+Plugin::addHook("menu_setting", "client_menu_setting");
+Plugin::addHook("content_setting", "client_content_setting");
+Plugin::addHook("widget", "client_widget");
 Plugin::addHook("client_merge", "client_merge");
 
 Plugin::addHook("field_types", "client_field_type");
 Plugin::addHook("client_sheet_option", "client_sheet_option");
 
 Plugin::addHook("client_list_action","client_list_action");
-Plugin::addHook("client_menu", "client_tab_menu");    
-Plugin::addHook("client_page", "client_tab_page");    
+Plugin::addHook("client_menu", "client_tab_menu");
+Plugin::addHook("client_page", "client_tab_page");
 Plugin::addHook("client_filter", "client_filter");
 Plugin::addHook("client_sheet", "client_sheet");
 Plugin::addHook("client_search_view","client_search_view");

+ 2 - 2
plugin/client/client.widget.configure.php

@@ -1,4 +1,4 @@
-<?php 
+<?php
 
 $max = $widget->data('client_number');
 $max = $max == "" ? 5 : $max;
@@ -6,4 +6,4 @@ $max = $max == "" ? 5 : $max;
 <div id="client-widget-form">
 	<label for="client-max">Nombre de nouveaux clients à afficher :</label>
 	<input type="number" class="form-control mb-2" value="<?php echo $max; ?>" name="client-max" id="client-max">
-</div> 
+</div>

+ 2 - 2
plugin/client/client.widget.php

@@ -1,4 +1,4 @@
-<?php 
+<?php
 	require_once(__DIR__.SLASH.'Client.class.php');
 	$max = $widget->data('client_number');
 	$max = $max =="" ? 5 : $max ;
@@ -14,7 +14,7 @@
 	<h5 class="ml-2 mb-3 mt-3"><?php echo $max>0 ? $max.' dernier'.($max>1?'s':'').' client'.($max>1?'s':'') : 'Aucun nouveau client'; ?></h5>
 
 	<div class="last-clients">
-		
+
 		<ul class="list-unstyled clients text-center mb-0 pb-4">
 		<?php foreach($last5 as $client): ?>
 			<!-- @TODO: Mettre le logo client en background de chaque li -->

+ 24 - 24
plugin/client/css/main.css

@@ -62,7 +62,7 @@
 	order:1;
 	width: 20%;
 	max-width: 305px;
-	min-height: 100%;		
+	min-height: 100%;
 }
 .client-content-panel{
     flex: 1;
@@ -134,7 +134,7 @@
 	padding: 0;
 	margin: 0;
 	box-shadow: inset 0 0px 0px 4px #f0f1f6;
-} 
+}
 .client-history{
 	padding:20px;
 }
@@ -213,7 +213,7 @@
 	background-color: #ffffff;
 	position: relative;
 }
-.client-content-panel .client-form .client-map{ 
+.client-content-panel .client-form .client-map{
 	float: left;
 	width:50%;
 	background-color: #333333;
@@ -228,11 +228,11 @@
 	transition:all 0.2s ease-in-out;
 }
 
-.client-content-panel .client-form.client-form-map .client-map{ 
+.client-content-panel .client-form.client-form-map .client-map{
 	display: block;
 }
 
-.client-content-panel .client-form .client-map:hover{ 
+.client-content-panel .client-form .client-map:hover{
 	filter: grayscale(0);
 }
 
@@ -252,7 +252,7 @@
 	display: none;
 }
 
-.client-content-panel .client-form .client-thumbnail{ 
+.client-content-panel .client-form .client-thumbnail{
 	position: absolute;
     top: -45px;
     left: calc(50% - 59px);
@@ -267,7 +267,7 @@
     border-radius: 100%;
     cursor: pointer;
 }
-.client-content-panel .client-form.client-form-map .client-thumbnail{ 
+.client-content-panel .client-form.client-form-map .client-thumbnail{
 	top:calc(50% - 59px);
 	left:-60px;
 }
@@ -317,7 +317,7 @@
 }
 .client-content-panel .client-form .client-info .btn-dark:hover,.client-contact-panel .btn-dark:hover {
 	background-color: #414143;
-	
+
 }
 .client-content-panel .client-form .client-info .btn-info,.client-contact-panel .btn-info {
 	background-color: #67bff1;
@@ -327,25 +327,25 @@
 	background-color: #1fa2ec;
 }
 
-.client-content-panel .client-form .client-info{ 
+.client-content-panel .client-form .client-info{
 	float: left;
-	
+
 	padding: 25px;
 	width:100%;
 	box-sizing: border-box;
 }
-.client-content-panel .client-form.client-form-map .client-info{ 
+.client-content-panel .client-form.client-form-map .client-info{
 	width: 50%;
 	padding: 15px 15px 15px 50px;
 	min-height: 425px;
 }
-.client-content-panel .client-form .client-info label{ 
+.client-content-panel .client-form .client-info label{
 	text-transform: uppercase;
 	color:#b3b4ca;
 	font-size: 12px;
 	margin-bottom: 0;
 }
-.client-content-panel .client-form .client-info .form-control{ 
+.client-content-panel .client-form .client-info .form-control{
 	font-weight: bold;
 	border:0;
 	border-radius: 0;
@@ -353,7 +353,7 @@
 	color:#565a7c;
 	font-size:12px;
 }
-.client-content-panel .client-form .client-info textarea.form-control{ 
+.client-content-panel .client-form .client-info textarea.form-control{
 	background-color: #f3f3f3;
 }
 .client-content-panel .client-form .client-info .btn-more-fields:hover {
@@ -361,7 +361,7 @@
 }
 .client-content-panel .client-form .field-block {
 	margin-bottom: 0.5rem;
-} 
+}
 .client-content-panel .client-form .client-info{
 	position: relative;
 }
@@ -373,7 +373,7 @@
 }
 .client-contact-panel .contact-template{
 	position: relative;
-	
+
 }
 .client-contact-panel .contact-template .btn-options,
 .client-contact-panel .address .btn-options
@@ -402,7 +402,7 @@
 	text-align: center;
 	text-transform: uppercase;
 	transition: all 0.2s ease-in-out;
-} 
+}
 .client-content-panel .client-menu-bar > ul >li a{
 	color: inherit;
 	padding:15px;
@@ -424,7 +424,7 @@
 .client-content-panel .client-menu-bar > ul >li.active{
 	border-bottom: 4px solid #64bcfa;
 	color:#6cb9ec;
-} 
+}
 .client-contact-panel h4{
 	font-size: 11px;
 	font-weight: bold;
@@ -438,8 +438,8 @@
 	width: calc(100% - 30px);
 }
 
-.client-contact-panel .internals-list, 
-.client-contact-panel .contacts-list, 
+.client-contact-panel .internals-list,
+.client-contact-panel .contacts-list,
 .client-contact-panel .addresses-list {
 	list-style-type: none;
 	margin:0;
@@ -672,8 +672,8 @@
 }
 
 .client-logo-mini{
-	height: 50px; 
-	width: 50px; 
+	height: 50px;
+	width: 50px;
 }
 
 .client-content-page .table,.client-content-page .table tr > th:first-of-type,.client-content-page .table tr > td:first-of-type{
@@ -728,7 +728,7 @@
 }
 
 @media only screen and  (max-device-width : 480px) {
-	
+
 	.page-sheet-client .client-container{
 		display: block;
 	}
@@ -754,7 +754,7 @@
 		min-width: 50%;
 	}
 
-	
+
 	.client-content-panel .client-form .client-map {
 	    float: none;
 	    width: 100%;

+ 3 - 3
plugin/client/css/widget.css

@@ -16,14 +16,14 @@
 	overflow-x: auto;
 	overflow-y: hidden;
     background: #6b5b95;
-} 
+}
 
 .widget .client-container > h5 {
 	text-transform: uppercase;
 	font-size: 14px;
-	
+
 	color: rgba(255,255,255,0.5);
-} 
+}
 
 .widget .client-container  .last-clients a {
 	text-decoration: none;

+ 10 - 10
plugin/client/export.html

@@ -16,33 +16,33 @@
 
 <div class="  ">
 	<div class="bg-white shadow-sm ">
-		<div class=""> 
-			<div class="p-3 bg-light mb-3"> 
+		<div class="">
+			<div class="p-3 bg-light mb-3">
 				<h3>Fiche structure</h3>
-					<img src="{{client.logo::image}}" style="width: 100px;height:100px;" class="left mr-3"> 
+					<img src="{{client.logo::image}}" style="width: 100px;height:100px;" class="left mr-3">
 					<div class="left">
 						<h4 class="text-primary mb-0">{{client.label}} {{client.firstname}} {{client.name}}</h4>
 							Métier : <strong>{{client.job}}</strong><br>
 							Code : <strong>{{client.code}}</strong><br>
 							Catégorie: <strong>{{client.category}}</strong><br>
 							N° SIRET : <strong>{{client.siret}}</strong><br>
-							
+
 							Type : <strong>{{client.type}}</strong>
 							Condition : <strong>{{client.condition}}</strong><br/>
 							Structure parente : <strong>{{client.parent.label}}</strong><br/>
-							
+
 							Date de création : <strong>{{client.created}}</strong><br/>
 							Date de modification : <strong>{{client.updated}}</strong><br/>
 							Modificateur : <strong>{{client.updater}}</strong><br/>
 							Créateur : <strong>{{client.creator}}</strong><br/>
 					</div>
 					<div class="clear"></div>
-					
-					
-				
+
+
+
 
 		</div>
-		<div class="bg-light p-2"> 
+		<div class="bg-light p-2">
 				<div  class="">
 
 					<h3>Autres informations</h3>
@@ -60,7 +60,7 @@
 					<h5> CONTACTS </h5>
 					<ul class="list-group">
 					{{#client.contacts}}
-						<li class="list-group-item"><i class="fas fa-user"></i> {{civility}} {{firstname}} {{name}} <span class="text-muted">{{job}}</span> 
+						<li class="list-group-item"><i class="fas fa-user"></i> {{civility}} {{firstname}} {{name}} <span class="text-muted">{{job}}</span>
 							{{#mobile}}<span class="text-muted d-block" data-type="phone-text">{{mobile}}</span>{{/mobile}}
 						    {{^mobile}}{{#phone}}<span class="text-muted d-block" data-type="phone-text">{{phone}}</span>{{/phone}}{{/mobile}}
 						    {{#mail}}<span class="text-muted  d-block"><a href="mailto:{{mail}}">{{mail}}</a></span>{{/mail}}

+ 5 - 5
plugin/client/js/component.js

@@ -1,6 +1,6 @@
 
 /*
-Pour un client : 
+Pour un client :
 <input type="text" data-type="client" class="form-control" id="my_client">
 Pour un contact lié au client #7
 <input type="text" data-type="contact" data-scope="client" data-uid="7" class="form-control" id="my_contact">
@@ -19,7 +19,7 @@ function init_components_client(input){
 			}
 		}
 	};
-	
+
 	input.component_autocomplete('client',$.extend(data,{
 		skin: function(item){
 			var html = '';
@@ -35,7 +35,7 @@ function init_components_client(input){
 			if(item.parentLabel) html+='<small class="text-muted">'+item.parentLabel+'</small>' ;
 			html+='<span>'+label ;
 			if(input.attr('data-extra') && input.attr('data-extra').split(',').indexOf('id')!=-1) html += '<small> #' + item.id+'</small>';
-			html +='</span>'; 
+			html +='</span>';
 			html += '</small></div>'
 			html += '</div>'
 			return html;
@@ -50,10 +50,10 @@ function init_components_client(input){
 		},
 		onLoad: function(component,item){
 			var label = item.label;
-		
+
 			if(item.parent) label+=' ('+item.parent.label+')';
 			component.container.val(label);
 		}
 	}));
-	
+
 }

+ 37 - 37
plugin/client/js/main.js

@@ -20,8 +20,8 @@ function init_plugin_client(){
 
 		break;
 	}
-	
-	
+
+
 
 	$(document).click(function(){
 		$('#client-api .dropdown-menu').hide();
@@ -69,7 +69,7 @@ function client_tab_init_home(){
 	client_live_update();
 	client_image_edit('.client-form .client-thumbnail','logo-thumbnail');
 	client_address_change();
-} 
+}
 
 function client_image_edit(element,fileId){
 	var element = $(element);
@@ -112,7 +112,7 @@ function client_type_change(){
 
 function client_address_change(element){
 	client_update_map_size();
-	
+
 	if(!$('.client-form').hasClass('client-form-map') || !$('#addresses li:not(.hidden)').length) return;
 
 	var element = element!=null ? $(element) : $('#addresses li[data-type="global"]');
@@ -155,7 +155,7 @@ function client_internet_modal(){
 function client_api_search(){
 	var label = $('#label').val();
 	if(!label) return $.message('warning','Vous devez remplir le libellé pour lancer une recherche');
-	
+
 	var choices = $('#client-internet-modal .choices');
 
 	var city = $('.client-city').attr('data-city');
@@ -164,8 +164,8 @@ function client_api_search(){
 	$('#client-internet-modal .modal-preloader').addClass('btn-preloader');
 
 	$('#client-internet-modal .choices').fill({
-		action: 'client_api_search', 
-		label:  label 
+		action: 'client_api_search',
+		label:  label
 	},function(r){
 		for(var k in r.rows){
 			var row = r.rows[k];
@@ -175,7 +175,7 @@ function client_api_search(){
 		}
 		$('#client-internet-modal .modal-preloader').removeClass('btn-preloader');
 	});
-	
+
 }
 
 function client_api_load(li){
@@ -188,9 +188,9 @@ function client_api_load(li){
 	var comment = $('#comment').val();
 	if(comment) comment+'\n';
 	$('#comment').val(comment+"Taille : "+infos.size+' - (environ '+infos.employees+' employés'+"\n"+infos.status+" - SIREN : "+infos.siren+"\n"+" Société fondée le : "+infos.created);
-	
+
 	$('#client-internet-modal').modal('hide');
-	
+
 	client_client_save(function(client){
 		client_address_save({
 			"type": "global",
@@ -204,14 +204,14 @@ function client_api_load(li){
 		},true);
 	},true);
 
-	
+
 }
 
 //Enregistrement des configurations
 function client_setting_save(){
-	$.action({ 
-		action: 'client_setting_save', 
-		fields:  $('#client-setting-form').toJson() 
+	$.action({
+		action: 'client_setting_save',
+		fields:  $('#client-setting-form').toJson()
 	},function(){
 		$.message('success','Enregistré');
 	});
@@ -228,7 +228,7 @@ function client_client_search(options){
 	if(options && options.exportMode) $('.btn-export').addClass('btn-preloader');
 
 	var searchTable = $('#clients').data('searchTable');
-	searchTable.resetGlobalCheckbox(); 
+	searchTable.resetGlobalCheckbox();
 	if(!options.keepChecked) searchTable.resetCheckbox();
 
 	$('#clients').fill({
@@ -250,7 +250,7 @@ function client_client_search(options){
 
 
 function client_client_mail_copy(){
-	
+
 	$.action({
 		action : 'client_client_mail_copy',
 		ids : $('#clients').data('searchTable').checkboxes()
@@ -267,13 +267,13 @@ function client_relation_search(callback){
 		action:'client_relation_search',
 		client: $.urlParam('id'),
 		showing:function(line,key,data){
-			
+
 			if(data.level == 'holding'){
 				$('#holding').append(line.detach());
 			}else if(data.level =='memberof'){
 				$('#memberof').append(line.detach());
 			}
-			
+
 
 			line.removeClass('hidden');
 		}
@@ -315,7 +315,7 @@ function client_relation_delete(element){
 		line.remove();
 	});
 	$('#client-holding-modal').modal('hide');
-	
+
 }
 
 //Ajout ou modification d'élément client
@@ -323,7 +323,7 @@ function client_client_save(callback,noMessage){
 	var data = $('#client-form').toJson();
 
 	data.type = $('input[name="type"]:checked').val();
-	
+
 	$('#client-form input[type="radio"]:checked').each(function(i,element){
 		data[$(element).attr('name')] = $(element).attr('value');
 	});
@@ -337,14 +337,14 @@ function client_client_save(callback,noMessage){
 	data.cover = $('#cover-thumbnail').get(0).files[0];
 
 	data.parent = $.urlParam('parent');
-	
+
 	$.action(data,function(r){
 		$.urlParam('id',r.id)
 		$('.client-container').attr('data-id',r.id);
 		if(callback) callback(r);
 		if(!noMessage) $.message('success','Enregistré');
 	});
-	
+
 }
 
 
@@ -383,7 +383,7 @@ function client_client_check_duplicate(element){
 		label : element.val(),
 		id : $('#client-form').attr('data-id')
 	},function(r){
-		
+
 		var clientWarning = $('.client-warning',element.parent());
 		if(clientWarning.length==0){
 			clientWarning = $('<a class="input-group-append hidden client-warning" data-tooltip> \
@@ -418,7 +418,7 @@ function client_client_delete(element){
 	var recursive = confirm('Voulez vous supprimer également les sous entreprises de ce client ?');
 	var line = element ? $(element).closest('tr') : null;
 	var id = line ? line.attr('data-id') : $.urlParam('id');
-	
+
 	$.action({
 		action: 'client_client_delete',
 		id: id,
@@ -460,7 +460,7 @@ function client_contact_search(callback,exportMode){
 		$('.internals-title span').text(stats.internals);
 		$('.contacts-title span').text(stats.contacts);
 	});
-	
+
 }
 
 function client_contact_mobile_toggle(){
@@ -474,7 +474,7 @@ function client_contact_save(){
 	data.action = 'client_contact_save';
 	data.client = $.urlParam('id');
 	data.id = $('#contactModal').attr('data-id');
-	
+
 	data.account = $('#contactModal .contact-type-block:not(.hidden) [data-id="account"]').val();
 	data.job = data['contact-job'];
 	data.comment = data['contact-comment'];
@@ -511,8 +511,8 @@ function client_contact_edit(element){
 		modal.attr('data-id',r.id);
 
 		if(!r.type) r.type = 'external';
-		$('[name="contact-type"][data-value="'+r.type+'"]').click(); 
-	
+		$('[name="contact-type"][data-value="'+r.type+'"]').click();
+
 		client_contact_type();
 		init_components('#contactModal');
 	});
@@ -522,7 +522,7 @@ function client_contact_edit(element){
 function client_contact_delete(element){
 	if(!confirm('Êtes vous sûr de vouloir supprimer ce contact ?')) return;
 	var line = $(element).closest('li');
-	
+
 	$.action({
 		action: 'client_contact_delete',
 		id: line.attr('data-id')
@@ -535,7 +535,7 @@ function client_contact_delete(element){
 function client_contact_type(){
 
 	$('.contact-type-block').addClass('hidden');
-	
+
 	switch($('[name="contact-type"]:checked').attr('data-value')){
 		case 'external':
 			$('.external-type-block').removeClass('hidden');
@@ -575,7 +575,7 @@ function client_address_save(fromCode,callback,noMessage){
 	var data = $('#addressModal').toJson();
 	data.action = 'client_address_save';
 	data.client = $.urlParam('id');
-	
+
 	data.id = $('#addressModal').attr('data-id');
 	data.job = data['contact-job'];
 	data.mail = data['contact-mail'];
@@ -601,7 +601,7 @@ function client_address_edit(element){
 	var id = element ? $(element).closest('li').attr('data-id'): null;
 	$('#addressModal').modal('show');
 	$('#addressModal').clear();
-	
+
 	if(id){
 		$.action({
 			action: 'client_address_edit',
@@ -631,7 +631,7 @@ function client_address_fill(data){
 function client_address_delete(element){
 	if(!confirm('Êtes-vous sûr de vouloir supprimer cette adresse ?')) return;
 	var line = $(element).closest('li');
-	
+
 	$.action({
 		action: 'client_address_delete',
 		id: line.attr('data-id')
@@ -661,9 +661,9 @@ function client_address_copy(element){
 //Récuperation d'une liste de history dans le tableau #historys
 function client_core_history_search(callback,exportMode){
 	if($('.client-container').attr('data-id')=='') return;
-	
+
 	var box = new FilterBox('#client-history-filters');
-	
+
 	$('#historys').fill({
 		action:'client_core_history_search',
 		filters: box.filters(),
@@ -686,7 +686,7 @@ function client_core_history_save(callback){
 	$.action(data,function(r){
 		$('#history-comment').attr('data-id','')
 		$('#history-comment').val('');
-		
+
 		$('#history-comment').data('trumbowyg').empty()
 		client_core_history_search();
 		if(callback) callback();
@@ -710,7 +710,7 @@ function client_history_edit(element){
 function client_core_history_delete(element){
 	if(!confirm('Êtes-vous sûr de vouloir supprimer cet historique client ?')) return;
 	var line = $(element).closest('.item-line');
-	
+
 	$.action({
 		action: 'client_core_history_delete',
 		id: line.attr('data-id')

+ 15 - 15
plugin/client/page.list.client.php

@@ -3,7 +3,7 @@ global $myUser,$myFirm,$conf;
 
 
 
-if(!$myUser->can('client','read') && !$myUser->can('client_sheet','read',0,array('contains'=>true))) 
+if(!$myUser->can('client','read') && !$myUser->can('client_sheet','read',0,array('contains'=>true)))
     throw new Exception("Permission non accordée");
 
 require_once(__DIR__.SLASH.'Client.class.php');
@@ -21,7 +21,7 @@ if($myFirm->has_plugin('fr.core.dynamicform') || ($myFirm->id==-1 && Plugin::is_
     Plugin::need('dynamicform/DynamicForm');
     $options = array();
     if(!empty($_['firm']) && is_numeric($_['firm'])) $options['firm'] = $_['firm'];
-   
+
     //Récuperation des champs custom
     $fields = Dynamicform::list('client-sheet-custom',$options);
     //Ajout des champs custom en filtres
@@ -50,7 +50,7 @@ if($myFirm->has_plugin('fr.core.dynamicform') || ($myFirm->id==-1 && Plugin::is_
         </div>
         <div class="clear noPrint"></div>
     </div>
-    
+
     <div class="col-md-8 noPrint search-container">
         <select id="filters" <?php echo $myUser->connected()?'data-slug="client-search"':''; ?> data-global-shortcut="#clients-shortcuts" data-user-shortcut="#clients-shortcuts" data-type="filter" data-label="Recherche" data-autosearch="false" data-function="client_client_search">
             <?php foreach ($filters as $filter): echo $filter; endforeach; ?>
@@ -67,18 +67,18 @@ if($myFirm->has_plugin('fr.core.dynamicform') || ($myFirm->id==-1 && Plugin::is_
 
     </div>
     <div class="col-md-4">
-        
+
     </div>
 </div>
-<h5 class="results-count"><span></span> Résultat(s) 
+<h5 class="results-count"><span></span> Résultat(s)
     <!-- selection mutliples lignes par checkbox -->
     <div class="btn-group btn-checkbox-action" data-count="0">
       <button type="button" class="btn btn-small btn-light dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
         <span class="count font-weight-bold"></span> Selectionnés
       </button>
       <div class="dropdown-menu">
-       
-        <?php echo Plugin::callHook('client_list_action',array()); 
+
+        <?php echo Plugin::callHook('client_list_action',array());
 
        ?>
       </div>
@@ -87,13 +87,13 @@ if($myFirm->has_plugin('fr.core.dynamicform') || ($myFirm->id==-1 && Plugin::is_
 <div class="row">
 	<!-- search results -->
 	<div class="col-xl-12">
-    
-		<table id="clients" 
-            data-type="search-table" 
-            data-slug="client-search-table"  
+
+		<table id="clients"
+            data-type="search-table"
+            data-slug="client-search-table"
             data-entity-search="client_client_search"
             data-checkbox-action=".btn-checkbox-action"
-            class="table table-striped table-clients" 
+            class="table table-striped table-clients"
             >
             <thead>
                 <tr>
@@ -103,17 +103,17 @@ if($myFirm->has_plugin('fr.core.dynamicform') || ($myFirm->id==-1 && Plugin::is_
             </thead>
             <tbody>
                 <tr data-id="{{id}}" class="hidden client-state-{{state}}">
-                   
+
                     <?php foreach($columns as $row): echo $row['body']; endforeach;  ?>
 	                <td class="align-middle text-right">
                         <div class="btn-group btn-group-sm" role="group">
                             <a class="btn text-info noPrint" title="Consulter le client" href="index.php?module=client&page=sheet.client&id={{id}}<?php echo isset($_['embedded'])?'&embedded':'' ?>"><i class="<?php echo $myUser->can('client','edit')?'fas fa-pencil-alt':'fas fa-eye'; ?>"></i></a>
-                               
+
                             {{#deletable}}
                             <div class="btn text-danger noPrint" title="Supprimer le client" onclick="client_client_delete(this);">
                                 <i class="far fa-trash-alt"></i>
                             </div>
-                            {{/deletable}} 
+                            {{/deletable}}
                         </div>
                     </td>
                 </tr>

+ 16 - 16
plugin/client/page.sheet.client.php

@@ -1,4 +1,4 @@
-<?php 
+<?php
 global $conf,$myUser,$myFirm;
 
 require_once(__DIR__.SLASH.'Client.class.php');
@@ -12,7 +12,7 @@ if(!$myUser->can('client','read') && $client->id!=0 && !$myUser->can('client_she
 if(isset($_['id']) && !$client) throw new Exception("Aucun client existant avec cet identifiant");
 
 $addresses = $client->addresses('global');
-$mainAddress = !empty($addresses) ? $addresses[0]: new Address(); 
+$mainAddress = !empty($addresses) ? $addresses[0]: new Address();
 
 $contacts = $client->contacts();
 
@@ -71,7 +71,7 @@ $editable = $myUser->can('client','edit') && ($client->id==0 || $client->firm==$
 				<i class="far fa-calendar-alt"></i> Créé le <span><?php echo complete_date($client->created); ?></span><br>
 				<i class="fas fa-user-tie"></i> Créé par <span><?php echo $creator->fullName(); ?></span>
 			</div>
-			<?php 
+			<?php
 				//hook panel de gauche après créé par...
 				Plugin::callHook('client_panel',array($client));
 			?>
@@ -79,11 +79,11 @@ $editable = $myUser->can('client','edit') && ($client->id==0 || $client->firm==$
 
 		<div class="client-summary-sites type-firm">
 			<div >
-				<h3 class="text-uppercase mb-0"><?php echo mb_strtoupper($conf->get('client_holding_singular')); ?> 
+				<h3 class="text-uppercase mb-0"><?php echo mb_strtoupper($conf->get('client_holding_singular')); ?>
 					<a class="right pointer client-edition editable-only" data-tooltip title="Lier cette entreprise à un client existant" onclick="client_relation_add(true);"><i class="fas fa-link" ></i></a>
 				</h3>
 				<ul id="holding" class="p-0 m-0"></ul>
-				
+
 			</div>
 
 				<h3 class="text-uppercase"><span class="client-subsite-count"></span>Sous-établissements <a class="right pointer client-edition editable-only" data-tooltip title="Ajouter un sous-établissement" onclick="window.location = 'index.php?module=client&page=sheet.client&parent='+$.urlParam('id');"><i class="far fa-plus-square"  ></i></a></h3>
@@ -183,8 +183,8 @@ $editable = $myUser->can('client','edit') && ($client->id==0 || $client->firm==$
 						<div class="adress-content d-inline-block ml-3">
 							<h2>{{type.label}}</h2>
 							<p class="text-muted mb-0">
-								{{street}} {{complement}}, 
-								<br>{{#zip}}{{zip}}{{/zip}}{{^zip}}-{{/zip}} {{#city}}{{city}}{{/city}}{{^city}}-{{/city}} 
+								{{street}} {{complement}},
+								<br>{{#zip}}{{zip}}{{/zip}}{{^zip}}-{{/zip}} {{#city}}{{city}}{{/city}}{{^city}}-{{/city}}
 								<br>{{#country}}{{country}}{{/country}}
 							</p>
 						</div>
@@ -257,7 +257,7 @@ $editable = $myUser->can('client','edit') && ($client->id==0 || $client->firm==$
 					</div>
 					<label for="tag">Etiquettes</label>
 					<input  value="" class="form-control" placeholder="facturation, livraison..." type="text"  data-type="tag"  data-multiple=true  id="tag" >
-					
+
 					<label class="mb-1" for="contact-job">Fonction :</label>
 					<input id="contact-job" class="form-control form-control-sm" placeholder="PDG, Directeur commercial..." value="" type="text">
 					<label class="mb-1" for="contact-comment">Commentaire :</label>
@@ -265,7 +265,7 @@ $editable = $myUser->can('client','edit') && ($client->id==0 || $client->firm==$
 				</div>
 				<div class="modal-footer">
 					<button type="button" class="btn btn-light" data-dismiss="modal" title="Fermer sans enregistrer">Fermer</button>
-					
+
 					<button type="button" onclick="client_contact_save();" class="btn btn-primary" title="Enregistrer la fiche contact"><i class="fas fa-check"></i> Enregistrer</button>
 				</div>
 			</div>
@@ -377,12 +377,12 @@ $editable = $myUser->can('client','edit') && ($client->id==0 || $client->firm==$
 						</div>
 					</div>
 					<hr class="my-2">
-					
-					
+
+
 						<div class="row">
 							<div class="col-md-12">
 								<p>Dans le cas ou les deux clients comportent des informations, choisissez qui l'emporte</p>
-								
+
 								<table class="table">
 									<thead>
 									<tr>
@@ -392,7 +392,7 @@ $editable = $myUser->can('client','edit') && ($client->id==0 || $client->firm==$
 									</tr>
 									</thead>
 									<tbody>
-								<?php foreach(Client::fields(false) as $field): 
+								<?php foreach(Client::fields(false) as $field):
 									if($field['column']=='id' || $field['column']=='parent') continue;
 									?>
 									<tr>
@@ -407,10 +407,10 @@ $editable = $myUser->can('client','edit') && ($client->id==0 || $client->firm==$
 								<div class="merge-logs"></div>
 
 							</div>
-							
+
 						</div>
-						
-					
+
+
 				</div>
 				<div class="modal-footer">
 					<button type="button" class="btn btn-light" data-dismiss="modal" title="Fermer sans enregistrer">Fermer</button>

+ 6 - 6
plugin/client/setting.global.client.php

@@ -16,20 +16,20 @@ User::check_access('client','configure');
 
         <h3>Import excel</h3>
         <p>Pour importer des clients, téléchargez la trame <a href="action.php?action=client_import_model">d'export ici</a> puis envoyez la trame renseignée dans le champs ci dessous</p>
-        <input 
+        <input
             type="text"
             data-type="file"
-            data-extension="csv" 
+            data-extension="csv"
             data-action="client_import_component"
-            data-id="attachments" 
+            data-id="attachments"
             class="component-file-default bg-white shadow-sm">
 
         <div class="btn" onclick="client_import();">Importer</div>
         <hr/>
-        
+
         <p>Pour ajouter des champs personnalisés à la fiche client, créez une formulaire dynamique ayant pour slug <code>client-sheet-custom</code></p>
         <p>Pour intégrer la base client à une autre application, vous pouvez utiliser le code suivant :</p>
-        
+
 
         <code>
              &lt;iframe frameborder="0" width="100%" align="center" height="600px" src="<?php echo ROOT_URL ?>/index.php?module=client&firm=<?php echo $myFirm->id ?>&embedded=1"&gt;&lt;/iframe&gt;
@@ -40,5 +40,5 @@ User::check_access('client','configure');
     </div>
 
 
-    
+
 </div>

+ 10 - 10
plugin/client/tab.home.php

@@ -1,4 +1,4 @@
-<?php 
+<?php
 global $myUser,$_,$conf,$myFirm;
 
 
@@ -30,8 +30,8 @@ Plugin::callHook('client_sheet_option',array(&$sheetOptions));
 		</div>
 
 	</div>
-	
-	
+
+
 	<div class="client-info">
 		<div class="client-thumbnail" title="Editer le logo" style="background-image:url(action.php?action=client_assets_load&type=logo&client=<?php echo $client->id; ?>)"></div>
 		<?php if(count($sheetOptions) > 0): ?>
@@ -40,7 +40,7 @@ Plugin::callHook('client_sheet_option',array(&$sheetOptions));
 				<i class="fas fa-ellipsis-v text-muted"></i>
 			</div>
 			<div class="dropdown-menu py-1" aria-labelledby="dropdownMenuButton">
-				<?php 
+				<?php
 				foreach($sheetOptions as $sheetOption) echo $sheetOption;
 				?>
 			</div>
@@ -56,13 +56,13 @@ Plugin::callHook('client_sheet_option',array(&$sheetOptions));
 			</label>
 			<?php endforeach; ?>
 		</div>
-	<?php 
+	<?php
 
 		$types = FieldType::available();
 		$fields = FieldType::toForm($sheet);
 
 		foreach($fields as $key=>$field): ?>
-			<span class="<?php echo isset($field['data']['block-class'])?$field['data']['block-class']:'';?>"> 
+			<span class="<?php echo isset($field['data']['block-class'])?$field['data']['block-class']:'';?>">
 			<?php echo $field['label']; ?>
 			<?php echo isset($field['data']['before'])?$field['data']['before']:''; ?>
 			<?php echo $field['input']; ?>
@@ -96,7 +96,7 @@ Plugin::callHook('client_sheet_option',array(&$sheetOptions));
 		<div onclick="client_client_save();" class="btn btn-info w-100 text-uppercase editable-only">
 			<i class="fas fa-check"></i> Enregistrer
 		</div>
-	
+
 	</div>
 	<div class="clear"></div>
 </div>
@@ -123,7 +123,7 @@ Plugin::callHook('client_sheet_option',array(&$sheetOptions));
 	        </select>
 	    </div>
 	</div>
-	
+
 	<div class="row">
 		<!-- search results -->
 		<div class="col-xl-12 client-history">
@@ -136,7 +136,7 @@ Plugin::callHook('client_sheet_option',array(&$sheetOptions));
 					</div>
 					<div class="d-inline-block client-history-content">
 						<div class="w-100 text-right client-history-author">
-							 <img src="action.php?action=core_account_avatar_download&amp;user={{creator.login}}&amp;extension=jpg" class="avatar-mini avatar-rounded avatar-login" title="{{creator.fullName}}"> 
+							 <img src="action.php?action=core_account_avatar_download&amp;user={{creator.login}}&amp;extension=jpg" class="avatar-mini avatar-rounded avatar-login" title="{{creator.fullName}}">
 							<small>{{created.time}}</small>
 						</div>
 						{{{comment}}}
@@ -182,7 +182,7 @@ Plugin::callHook('client_sheet_option',array(&$sheetOptions));
 			</li>
         </ul>
 
-    
+
 
       </div>
       <div class="modal-footer">

+ 4 - 4
plugin/clientmap/action.php

@@ -1,5 +1,5 @@
 <?php
-	
+
 	//Sauvegarde des configurations de client
 Action::register('client_map_setting_save',function(&$response){
 			global $myUser,$_,$conf;
@@ -7,16 +7,16 @@ Action::register('client_map_setting_save',function(&$response){
 
 			//Si input file "multiple", possibilité de normlaiser le
 			//tableau $_FILES récupéré avec la fonction => normalize_php_files();
-			
+
 			foreach(Configuration::setting('clientmap') as $key=>$value){
 				if(!is_array($value)) continue;
 				$allowed[] = $key;
 			}
 			foreach ($_['fields'] as $key => $value) {
-				
+
 				if(in_array($key, $allowed))
 					$conf->put($key,$value);
 			}
 		});
-	
+
 ?>

+ 13 - 13
plugin/clientmap/clientmap.plugin.php

@@ -23,7 +23,7 @@ function clientmap_page(){
 	$page = str_replace('..','',$page);
 	$file = __DIR__.SLASH.'page.'.$page.'.php';
 	if(!file_exists($file)) throw new Exception("Page ".$page." inexistante");
-	
+
 	require_once($file);
 }
 
@@ -32,14 +32,14 @@ function clientmap_install($id){
 	if($id != 'fr.core.clientmap') return;
 	Entity::install(__DIR__);
 
-	
+
 }
 
 //Fonction executée lors de la désactivation du plugin
 function clientmap_uninstall($id){
 	if($id != 'fr.core.clientmap') return;
 	Entity::uninstall(__DIR__);
-	
+
 }
 
 //Déclaration des sections de droits du plugin
@@ -56,7 +56,7 @@ require_once(__DIR__.SLASH.'action.php');
 //Déclaration du menu de réglages
 function clientmap_menu_setting(&$settingMenu){
 	global  $myUser;
-	
+
 	if(!$myUser->can('client','configure')) return;
 	$settingMenu[]= array(
 		'sort' =>1,
@@ -75,24 +75,24 @@ function clientmap_content_setting(){
 
 Configuration::setting('clientmap',array(
     "Général",
-    
+
     'clientmap_custom_fields' => array("label"=>"Ajouter champs custom suivants","legend"=>"slug des champs séparés par saut de ligne (ex: mon-champ-1 <saut de ligne> mon-champ-2","type"=>"textarea"),
-    
+
 ));
 
 
 //Déclation des assets
-Plugin::addCss("/css/main.css"); 
-Plugin::addJs("/js/main.js"); 
+Plugin::addCss("/css/main.css");
+Plugin::addJs("/js/main.js");
 
 //Mapping hook / fonctions
 Plugin::addHook("install", "clientmap_install");
-Plugin::addHook("uninstall", "clientmap_uninstall"); 
+Plugin::addHook("uninstall", "clientmap_uninstall");
 
 
-Plugin::addHook("menu_main", "clientmap_menu"); 
-Plugin::addHook("page", "clientmap_page"); 
-Plugin::addHook("menu_setting", "clientmap_menu_setting");    
-Plugin::addHook("content_setting", "clientmap_content_setting");   
+Plugin::addHook("menu_main", "clientmap_menu");
+Plugin::addHook("page", "clientmap_page");
+Plugin::addHook("menu_setting", "clientmap_menu_setting");
+Plugin::addHook("content_setting", "clientmap_content_setting");
 
 ?>

+ 5 - 5
plugin/clientmap/css/main.css

@@ -90,7 +90,7 @@
 	background-color: #ffffff;
 }
 
-.plugin-clientmap .map-container{ 
+.plugin-clientmap .map-container{
 	margin-left: 22%;
 	height:100%;
 }
@@ -102,8 +102,8 @@
 .plugin-clientmap .map-panel .advanced-search-box li.condition > .filter-option{
 	font-size: 11px;
 }
- 
-.plugin-clientmap .map-panel .advanced-search-box .filter-operator, 
+
+.plugin-clientmap .map-panel .advanced-search-box .filter-operator,
 .plugin-clientmap .map-panel .advanced-search-box .filter-value {
     width: 100%;
     font-size: 11px;
@@ -153,7 +153,7 @@
     bottom: 10px;
     right: 10px;
 }
-.plugin-clientmap .map-panel #clients li{ 
+.plugin-clientmap .map-panel #clients li{
 	position: relative;
 	padding:15px;
 	border-bottom:1px solid #eeeded;
@@ -187,7 +187,7 @@
 	text-align: center;
 }
 
-.plugin-clientmap .map-panel #clients li:hover{ 
+.plugin-clientmap .map-panel #clients li:hover{
 	background-color: #f8f8f8;
 }
 

+ 13 - 13
plugin/clientmap/js/main.js

@@ -14,9 +14,9 @@ function init_plugin_clientmap(){
 
 //Enregistrement des configurations
 function client_map_setting_save(){
-	$.action({ 
-		action: 'client_map_setting_save', 
-		fields:  $('#client-map-setting-form').toJson() 
+	$.action({
+		action: 'client_map_setting_save',
+		fields:  $('#client-map-setting-form').toJson()
 	},function(){
 		$.message('success','Enregistré');
 	});
@@ -31,7 +31,7 @@ function client_map_search(options){
 	if(options && options.exportMode) $('.btn-export').addClass('btn-preloader');
 
 	var searchTable = $('#clients').data('searchTable');
-	searchTable.resetGlobalCheckbox(); 
+	searchTable.resetGlobalCheckbox();
 	if(!options.keepChecked) searchTable.resetCheckbox();
 
 	var data = {
@@ -46,8 +46,8 @@ function client_map_search(options){
 	var customFields = $('#customFields').text().split("\n").filter(n => n);
 	console.log(customFields);
 	if(customFields.length!=0){
-		data.columns = { 
-			added : customFields, 
+		data.columns = {
+			added : customFields,
 			deleted : []
 		}
 	}
@@ -63,23 +63,23 @@ function client_map_search(options){
 
 		for (var k in response.rows) {
 			var client = response.rows[k];
-			
+
 			if(!client.meta) continue;
-			
-			
+
+
 			if(!client.meta.longitude || !client.meta.latitude) continue;
 			var clientPoint = {};
 			clientPoint.latitude = client.meta.latitude;
 			clientPoint.longitude = client.meta.longitude;
 			clientPoint.id = client.id;
-			clientPoint.label = Mustache.render(tooltipTpl,{client:client}); 
+			clientPoint.label = Mustache.render(tooltipTpl,{client:client});
 			jsonPoints.push(clientPoint);
 		}
-     
-		
+
+
 
 		$('.map-container').html('<div data-type="map" data-zoom-position="topright" id="client-map" style="height:100%;width:80%;"></div>');
-		
+
 		$('#client-map').get(0).innerHtml = JSON.stringify(jsonPoints);
 		if(jsonPoints.length==0){
 			$('#client-map-no-points').removeClass('hidden');

+ 25 - 25
plugin/clientmap/page.list.client.php

@@ -11,18 +11,18 @@ Plugin::need('client/Client');
 
 $filters = array();
 Plugin::callHook('client_filter',array(&$filters));
-        
 
 
 
-Plugin::callHook('client_search_view',array(&$columns)); 
+
+Plugin::callHook('client_search_view',array(&$columns));
 
 //Filtres && colonne tableau en fonction des champs dynamiques
 if($myFirm->has_plugin('fr.core.dynamicform') || ($myFirm->id==-1 && Plugin::is_active('fr.core.dynamicform')) ){
     Plugin::need('dynamicform/DynamicForm');
     $options = array();
     if(!empty($_['firm']) && is_numeric($_['firm'])) $options['firm'] = $_['firm'];
-   
+
     //Récuperation des champs custom
     $fields = Dynamicform::list('client-sheet-custom',$options);
     //Ajout des champs custom en filtres
@@ -34,34 +34,34 @@ if($myFirm->has_plugin('fr.core.dynamicform') || ($myFirm->id==-1 && Plugin::is_
 ?>
 <div class="plugin-clientmap">
     <div class="map-panel shadow-sm">
-       
-        
+
+
         <div class="col-md-12 map-panel-box noPrint pt-3" style="height: inherit;">
             <select id="filters" data-type="filter" data-label="Recherche" data-autosearch="false" data-function="client_map_search">
-               
+
                 <?php foreach ($filters as $filter): echo $filter; endforeach; ?>
             </select>
 
-           
+
             <div class="btn btn-link btn-return hidden w-100 my-3" onclick="client_map_edit_cancel()">RETOUR RECHERCHE</div>
             <div class="client-list-container">
             <ul id="clients"
 
-            data-type="search-table" 
-            data-slug="client-search-table"  
+            data-type="search-table"
+            data-slug="client-search-table"
             data-entity-search="client_map_search"
             data-checkbox-action=".btn-checkbox-action"
             class="" >
-            
-               
+
+
                     <li data-id="{{id}}" class="hidden client-state-{{state}} client-item" onclick="client_map_edit(this)">
-                       
+
                         <div>
                             <img class="client-logo-mini avatar-rounded left mr-2 mt-2 map-client-avatar" data-src="{{logo}}">
                             <div class="map-client-label"  title="{{{label}}} ({{type.label}})">
                                 {{{label}}} ({{type.label}}) {{#pseudonym}}<small class="text-muted">({{{pseudonym}}})</small>{{/pseudonym}}
-                               
-                                
+
+
                                 {{#job}}<br/><div class="text-muted client-job" title="{{{job}}}">{{{job}}}</div>{{/job}}
                             </div>
                             <div class="clear"></div>
@@ -72,7 +72,7 @@ if($myFirm->has_plugin('fr.core.dynamicform') || ($myFirm->id==-1 && Plugin::is_
                         <div class="my-2">
                             <i class="fas fa-map-marker-alt text-icon"></i> {{address.street}} {{address.complement}}  {{#address.zip}}
                             <small class="text-muted d-block">
-                                {{address.city}} ({{address.zip}}) 
+                                {{address.city}} ({{address.zip}})
                             </small>
                             {{/address.zip}}
                         </div>
@@ -85,7 +85,7 @@ if($myFirm->has_plugin('fr.core.dynamicform') || ($myFirm->id==-1 && Plugin::is_
                             {{#phone}}<div class="my-2"><i class="fas fa-mobile-alt text-icon"></i> {{phone}}</div>{{/phone}}
 
                             {{#client-sheet-custom_site-internet}}<div class="my-2"><a href="{{meta.website}}" target="_blank"><i class="fas fa-globe-europe text-icon"></i> {{{client-sheet-custom_site-internet}}}</a></div>{{/client-sheet-custom_site-internet}}
-                            
+
                              <a class="btn btn-primary w-100 text-white my-3" title="Afficher sur Google Map" target="_blank" href="{{address.mapurl}}"><i class="fas fa-map-marked-alt ml-2 pointer"></i> VOIR SUR GOOGLE</a>
                         </div>
 
@@ -93,10 +93,10 @@ if($myFirm->has_plugin('fr.core.dynamicform') || ($myFirm->id==-1 && Plugin::is_
                             <i class="fas fa-external-link-alt"></i>
                         </a>
                     </li>
-              
+
             </ul>
             </div><br>
-           
+
              <ul class="pagination justify-content-center noPrint"  data-range="5">
                 <li class="page-item hidden" data-value="{{value}}" title="Voir la page {{label}}" onclick="$(this).parent().find('li').removeClass('active');$(this).addClass('active');client_map_search();">
                     <span class="page-link">{{label}}</span>
@@ -108,21 +108,21 @@ if($myFirm->has_plugin('fr.core.dynamicform') || ($myFirm->id==-1 && Plugin::is_
     <div id="map-panel-button" class="d-sm-flex d-md-none rounded-right"  onclick="collapseMapPanel()">
         <i class="fas fa-caret-right"></i>
     </div>
-    
-    
+
+
     <!-- search results -->
     <div class="map-container"></div>
-    
+
     <div id="client-map-no-points" class="client-map-no-points p-3 bg-white shadow-sm">Aucun résultat(s) pour ce(s) critère(s)</div>
 
-    <!-- marker tooltip template -->        
-    <template id="map-tooltip"><img class="client-logo-mini avatar-rounded left mr-2" src="{{client.logo}}"> 
+    <!-- marker tooltip template -->
+    <template id="map-tooltip"><img class="client-logo-mini avatar-rounded left mr-2" src="{{client.logo}}">
         <a href="index.php?module=client&page=sheet.client&id={{client.id}}" data-id="{{client.id}}"  class="pointer text-info font-weight-bold mb-1 d-block">{{client.label}}</a><small class="text-muted">{{client.job}}</small>
         <div class="text-center mt-2">{{client.address.street}} {{client.address.zip}} {{client.address.city}}</div>
     </template>
      <!-- Pagination (data-range définit le nombre de pages max affichées avant et après la page courante) -->
-        
-    <div class="hidden" id="customFields"><?php 
+
+    <div class="hidden" id="customFields"><?php
     global $conf;
     echo $conf->get('clientmap_custom_fields'); ?></div>
 </div>

+ 2 - 2
plugin/clientmap/setting.global.clientmap.php

@@ -11,10 +11,10 @@ User::check_access('client','configure');
         <div class="clear"></div>
 		<hr>
     </div>
-    
+
     <p>Pour ajouter des champs personnalisés à la fiche client, créez une formulaire dynamique ayant pour slug <code>client-sheet-custom</code></p>
     <p>Pour intégrer la base client à une autre application, vous pouvez utiliser le code suivant :</p>
-    
+
 
     <code>
          &lt;iframe frameborder="0" width="100%" align="center" height="600px" src="<?php echo ROOT_URL ?>/index.php?module=clientmap&p=1&embedded=1"&gt;&lt;/iframe&gt;

+ 28 - 28
plugin/contact/action.php

@@ -4,8 +4,8 @@
 	Action::register('contact_contact_person_search',function(&$response){
 		global $_;
 		User::check_access('contact','read');
-		
-		
+
+
 		// OPTIONS DE RECHERCHE, A ACTIVER POUR UNE RECHERCHE AVANCEE
 		$query = 'SELECT * FROM '.ContactPerson::tableName().' WHERE 1';
 		$data = array();
@@ -28,11 +28,11 @@
 		$response['pagination'] = ContactPerson::paginate($pageNumber,(!empty($_['page'])?$_['page']:0),$query,$data);
 
 		$contactpersons = ContactPerson::staticQuery($query,$data,true,0);
-		
+
 		$ids = array();
 		foreach($contactpersons as $contactperson)
 			$ids[] = $contactperson->id;
-		
+
 		$contactInfos = array();
 
 		if(!empty($ids)){
@@ -45,7 +45,7 @@
 		$response['rows'] = array();
 		foreach($contactpersons as $contactperson){
 			$row = $contactperson->toArray();
-			$row['civility'] = ContactPerson::civilities($row['civility']); 
+			$row['civility'] = ContactPerson::civilities($row['civility']);
 			$row['fullname'] = $contactperson->fullName();
 			$row['phones'] = array();
 			$row['mails'] = array();
@@ -63,7 +63,7 @@
 						$row['rawmails'][] = $contact->value;
 					}
 				}
-				
+
 			}
 
 			if($_['export'] == 'true'){
@@ -81,14 +81,14 @@
 			$row['avatar'] = $row['avatar'] = 'action.php?action=contact_avatar_load&path='.base64_encode($contactperson->avatar());
 			$response['rows'][] = $row;
 		}
-		
+
 		/* Mode export */
 		if($_['export'] == 'true'){
-			
+
 			$fieldsMapping = array();
-			foreach (ContactPerson::fields(false) as $key => $value) 
+			foreach (ContactPerson::fields(false) as $key => $value)
 				$fieldsMapping[$value['label']] = $key;
-			
+
 			$fieldsMapping['Téléphones'] = 'rawphones';
 			$fieldsMapping['E-mails'] = 'rawmails';
 
@@ -96,25 +96,25 @@
 			File::downloadStream($stream,'export-contacts-'.date('d-m-Y').'.xlsx');
 			exit();
 		}
-		
+
 	});
 
 	Action::register('contact_contact_search',function(&$response){
 		global $_;
 		User::check_access('contact','read');
-		
+
 		$response['rows'] = array();
 		foreach (Contact::loadAll(array('scope'=>$_['scope'],'uid'=>$_['uid'])) as $key => $contact) {
 			$response['rows'][] = $contact->toArray();
 		}
 	});
-	
-	
+
+
 	//Ajout ou modification d'élément contact
 	Action::register('contact_contact_person_save',function(&$response){
 		global $_,$myFirm;
 		User::check_access('contact','edit');
-		
+
 		$item = ContactPerson::provide();
 		$oldItem = clone $item;
 		$item->name = $_['name'];
@@ -131,7 +131,7 @@
 		$item->save();
 
 		History::entityChange('contactperson',$oldItem,$item);
-		
+
 		if(empty($item->uid)){
 			$item->uid = $item->id;
 			$item->save();
@@ -155,39 +155,39 @@
 
 				$contact->type = $line["type"];
 				$contact->value = $line["value"];
-			
+
 				$contact->save();
 			}
-	
+
 		}
 
 
 		$response = $item->toArray();
 	});
-	
+
 
 	Action::register('contact_avatar_load',function(&$response){
 			global $myUser,$_;
 			User::check_access('contact','read');
-			
+
 			$_['path'] = str_replace("..", "", base64_decode($_['path']));
 
-			
+
 			File::downloadFile($_['path']);
 	});
-	
-	
+
+
 
 	//Suppression d'élement contact
 	Action::register('contact_contact_person_delete',function(&$response){
 		global $_;
 		User::check_access('contact','delete');
-		
+
 		if(empty($_['id']) || !is_numeric($_['id'])) throw new Exception("Identifiant incorrect");
 		ContactPerson::deleteById($_['id']);
 	});
-	
-	
+
+
 
 	//Sauvegarde des configurations de Annuaire de contacts
 	Action::register('contact_setting_save',function(&$response){
@@ -204,9 +204,9 @@
 				$conf->put($key,$value);
 		}
 	});
-	
 
-	
+
+
 
 
 ?>

+ 9 - 9
plugin/contact/contact.plugin.php

@@ -23,7 +23,7 @@ function contact_page(){
 	$page = str_replace('..','',$page);
 	$file = __DIR__.SLASH.'page.'.$page.'.php';
 	if(!file_exists($file)) throw new Exception("Page ".$page." inexistante");
-	
+
 	require_once($file);
 }
 
@@ -35,7 +35,7 @@ function contact_install($id){
 	global $myFirm;
 		if($myFirm->has_plugin('fr.core.dynamicform')){
 		Plugin::need('dynamicform/DynamicForm');
-		
+
 		$form = new DynamicForm();
 		$form->slug = 'contact-form';
 		$form->color = '#cecece';
@@ -85,7 +85,7 @@ function contact_action(){
 //Déclaration du menu de réglages
 function contact_menu_setting(&$settingMenu){
 	global $myUser;
-	
+
 	if(!$myUser->can('contact','configure')) return;
 	$settingMenu[]= array(
 		'sort' =>1,
@@ -112,21 +112,21 @@ Configuration::setting('contact',array(
     "Général",
     //'contact_enable' => array("label"=>"Activer","type"=>"boolean"),
 ));
-  
+
 
 
 
 //Déclation des assets
-Plugin::addCss("/css/main.css"); 
-Plugin::addJs("/js/main.js"); 
+Plugin::addCss("/css/main.css");
+Plugin::addJs("/js/main.js");
 
 //Mapping hook / fonctions
 Plugin::addHook("install", "contact_install");
-Plugin::addHook("uninstall", "contact_uninstall"); 
+Plugin::addHook("uninstall", "contact_uninstall");
 
 
-Plugin::addHook("menu_main", "contact_menu"); 
-Plugin::addHook("page", "contact_page"); 
+Plugin::addHook("menu_main", "contact_menu");
+Plugin::addHook("page", "contact_page");
 Plugin::addHook("menu_setting", "contact_menu_setting");
 Plugin::addHook("content_setting", "contact_content_setting");
 ?>

+ 6 - 6
plugin/contact/js/main.js

@@ -14,9 +14,9 @@ function init_plugin_contact(){
 
 //Enregistrement des configurations
 function contact_setting_save(){
-	$.action({ 
-		action: 'contact_setting_save', 
-		fields:  $('#contact-setting-form').toJson() 
+	$.action({
+		action: 'contact_setting_save',
+		fields:  $('#contact-setting-form').toJson()
 	},function(){
 		$.message('success','Enregistré');
 	});
@@ -72,7 +72,7 @@ function contact_contact_add(element,data){
 	}else{
 		var line = $('#contact-list li:eq(0)');
 	}
-	
+
 	var newline = line.clone().clear();
 	line.after(newline);
 
@@ -82,7 +82,7 @@ function contact_contact_add(element,data){
 		newline.find('.type').val(data.type);
 		newline.find('.value').val(data.value);
 	}
-	
+
 	contact_contact_save();
 }
 
@@ -93,7 +93,7 @@ function contact_contact_remove(element){
 	}else{
 		line.remove();
 	}
-	
+
 	contact_contact_save();
 }
 function contact_contact_search(){

+ 15 - 15
plugin/contact/page.list.contact.person.php

@@ -22,19 +22,19 @@ foreach (ContactPerson::civilities() as $key => $civility) {
                     <div onclick="window.print();" class="btn btn-info rounded-0 btn-squarred" title="Imprimer la page"><i class="fas fa-print"></i></div>
                     <div onclick="contact_contact_person_search(null,true);" id="export-contacts-btn" class="btn btn-info rounded-0 btn-squarred ml-1" title="Exporter les résultats"><i class="fas fa-file-export"></i></div>
                 </div>
-                
+
                 <div class="my-auto ml-auto mr-0 noPrint">
                     <?php if($myUser->can('contact', 'edit')) : ?>
                     <a href="index.php?module=contact&page=sheet.contact.person" class="btn btn-success right"><i class="fas fa-plus"></i> Ajouter</a>
                     <?php endif; ?>
                 </div>
-                
+
             </div>
             <div class="clear noPrint"></div>
         </div>
-        
+
         <div class="col-md-12">
-           
+
             <select id="filters" data-type="filter" data-label="Recherche" data-function="contact_contact_person_search">
                 <option value="label" data-filter-type="text">Libellé</option>
                 <option value="name" data-filter-type="text">Nom</option>
@@ -42,10 +42,10 @@ foreach (ContactPerson::civilities() as $key => $civility) {
                 <option value="job" data-filter-type="text">Métier</option>
                 <option value="civility" data-operator-delete='["in","not in"]' data-filter-type="list" data-values='<?php echo json_encode($civilities); ?>' >Civilité</option>
                 <option value="state" data-operator-delete='["in","not in"]' data-filter-type="list" data-values='{"<?php echo ContactPerson::ACTIVE; ?>":"Actif","<?php echo ContactPerson::INACTIVE; ?>":"Inactif"}' >Etat</option>
-                
+
                 <option value="scope" data-filter-type="text">Module</option>
                 <option value="tag" data-operator-delete='["in","not in"]' data-filter-type="tag">Etiquettes</option>
-        
+
                 <option value="comment" data-filter-type="text">Commentaire</option>
                 <?php
                     //Champs dynamiques
@@ -55,27 +55,27 @@ foreach (ContactPerson::civilities() as $key => $civility) {
                             $fields = Dynamicform::get_fields(array('slug'=>'contact-form'));
                             foreach ($fields as $k => $field): ?>
                                 <option value="<?php echo $field['slug'] ?>" data-filter-type="text"><?php echo $field['label'] ?></option>
-                           <?php 
+                           <?php
                           endforeach;
                     endif; */
                     //todo a décommenter et implémenter avec la feature de JN pour les recherches sur dynamic field
-                    //lorsqu'elle sera terminée.          
+                    //lorsqu'elle sera terminée.
                 ?>
             </select>
         </div>
-        
+
     </div>
     <h5 class="results-count"><span></span> Résultat(s)</h5>
     <div class="row">
     	<!-- search results -->
     	<div class="col-xl-12">
-    		
+
             <table id="contact-persons" class="table table-striped " data-entity-search="contact_contact_person_search">
                 <thead>
                     <tr>
-               
+
                         <th >Contact</th>
- 
+
                         <th data-sortable="job">Métier</th>
                         <th data-sortable="civility">Civilité</th>
                         <th data-sortable="phone">Téléphone</th>
@@ -84,9 +84,9 @@ foreach (ContactPerson::civilities() as $key => $civility) {
                         <th></th>
                     </tr>
                 </thead>
-                
+
                 <tbody>
-                    
+
 
                     <tr data-id="{{id}}" class="hidden item-line">
     	                <td class="align-middle"><div class="contact-avatar left mr-2"><img class="avatar-rounded" src="{{avatar}}"></div> {{{fullname}}}</td>
@@ -124,7 +124,7 @@ foreach (ContactPerson::civilities() as $key => $civility) {
                     <span class="page-link">{{label}}</span>
                 </li>
             </ul>
-          
+
     	</div>
     </div>
 </div>

+ 11 - 11
plugin/contact/page.sheet.contact.person.php

@@ -1,4 +1,4 @@
-<?php 
+<?php
 User::check_access('contact','read');
 
 $contacts = array();
@@ -20,12 +20,12 @@ if($contactperson->id==''){
 <div class="plugin-contact">
 	<div id="contact-person-form" class="row justify-content-md-center contact-person-form" data-action="contact_contact_person_save" data-id="<?php echo $contactperson->id; ?>">
 		<div class="col-md-4 shadow-sm bg-white p-3">
-			<h3>Contact 
+			<h3>Contact
 			<div onclick="contact_contact_person_save();" class="btn btn-small btn-success right"><i class="fas fa-check"></i> Enregistrer</div>
 			<div class="btn btn-small btn-info mb-2 btn-dark mr-2 right" data-scope="contactperson" data-uid="<?php echo $contactperson->id; ?>" data-show-important="true" data-type="history" data-tooltip title="Ouvrir l'historique"> <i class="far fa-comment-dots"></i></div>
 			<a href="index.php?module=contact&page=list.contact.person" class="btn btn-small btn-dark right  mr-2">Retour</a>
 		</h3>
-			
+
 
 			<label for="name">Nom</label>
 			<input  value="<?php echo $contactperson->name; ?>" class="form-control"  type="text"  id="name" >
@@ -42,7 +42,7 @@ if($contactperson->id==''){
 
 			<label for="tag">Etiquettes</label>
 			<input  value="<?php echo $contactperson->tag; ?>" class="form-control"  type="text"  data-type="tag"  data-multiple=true  id="tag" >
-			
+
 			<hr/>
 			<label for="phones" class="text-muted font-weight-bold">TELEPHONES(S) & EMAILS(S)</label>
 			<ul id="contact-list" class="contact-list">
@@ -65,17 +65,17 @@ if($contactperson->id==''){
 					</div>
 				</li>
 			</ul>
-			
 
-			
+
+
 			<input  value="<?php echo base64_encode(json_encode($contacts)); ?>" class="form-control"  type="hidden"  id="contacts" >
 			<input  value="<?php echo $contactperson->scope; ?>" class="form-control"  type="hidden"  id="scope" >
 			<input  value="<?php echo $contactperson->uid; ?>" class="form-control"  type="hidden"  id="uid" >
 
-		
-	
+
+
 			<br/>
-			
+
 		</div>
 
 		<?php
@@ -88,12 +88,12 @@ if($contactperson->id==''){
 					'uid'=>$contactperson->id
 				));
 				if(!empty($form)):
-				
+
 		?>
 
 		<div class="col-md-4 shadow-sm bg-white p-3 ml-3">
 			<h3>Informations complémentaires</h3>
-			<?php 
+			<?php
 			echo $form;
 			?>
 		</div>

+ 1 - 1
plugin/contact/setting.global.contact.php

@@ -5,7 +5,7 @@ User::check_access('contact','configure');
 
 <div class="row">
     <div class="col-xl-12"><br>
-    	
+
         <h3 class="mb-0"><i class="far fa-address-card"></i> Réglages Annuaire de contacts <div onclick="contact_setting_save();" class="btn btn-sm btn-success float-right"><i class="fas fa-check"></i> Enregistrer</div></h3>
         <div class="clear"></div>
 		<hr>

+ 2 - 2
plugin/customiser/Theme.class.php

@@ -26,8 +26,8 @@ class Theme{
 
 		$dir = self::dir();
 		if(!file_exists($dir)) mkdir($dir,0755,true);
-			
-		
+
+
 
 		foreach(glob($dir.SLASH.'*'.SLASH.'app.json') as $themeFile){
 			$path = dirname($themeFile);

+ 4 - 4
plugin/customiser/action.php

@@ -13,7 +13,7 @@ Action::register('customiser_theme_zipTheme',function(&$response){
 		'namespace' => 'customiser', //stockés dans file/customiser/*.*
 		'access' => 'customiser', // crud sur customiser,
 		'size' => '1000000000', // taille max
-		'extension' => 'zip', 
+		'extension' => 'zip',
 		'storage' => 'theme/upload.zip'
 	),$response);
 });
@@ -21,7 +21,7 @@ Action::register('customiser_theme_zipTheme',function(&$response){
 Action::register('customiser_theme_install',function(&$response){
 	global $_,$myUser ;
 	require_once(__DIR__.SLASH.'Theme.class.php');
-	
+
 	User::check_access('customiser','configure');
 	if(empty($_['file'])) return;
 
@@ -31,10 +31,10 @@ Action::register('customiser_theme_install',function(&$response){
 
 		$zip = new ZipArchive();
 		if(!$zip->open($zipFile)) throw new Exception("Impossible d'ouvrir l'import");
-		
+
 		$app = $zip->getFromName('app.json');
 		if(!$app) throw new Exception('Fichier app.json manquant à la racine de l\'archive');
-		
+
 		$app = json_decode($app,true);
 		$folderId = str_replace(array('..','/','\\'),array('.',''),$app['id']);
 		$templateDir = Theme::dir().$folderId;

+ 8 - 8
plugin/customiser/customiser.plugin.php

@@ -17,14 +17,14 @@ function customiser_uninstall($id){
 Right::register('customiser',array('label'=>'Gestion des droits sur le plugin customiser'));
 
 
-//Cette fonction comprends toutes les actions 
+//Cette fonction comprends toutes les actions
 //du plugin qui ne nécessitent pas de vue html
 require_once(__DIR__.SLASH.'action.php');
 
 //Déclaration du menu de réglages
 function customiser_menu_setting(&$settingMenu){
 	global  $myUser;
-	
+
 	if(!$myUser->can('customiser','configure')) return;
 	$settingMenu[]= array(
 		'sort' => 1,
@@ -49,15 +49,15 @@ if(!empty($conf->get('core_theme'))){
 	if(file_exists(__ROOT__.SLASH.$jsFile)) Plugin::addJs($jsFile,array('forcePath'=>true));
 }
 //Déclation des assets
-Plugin::addCss("/css/main.css"); 
-Plugin::addJs("/js/main.js"); 
+Plugin::addCss("/css/main.css");
+Plugin::addJs("/js/main.js");
 
 //Mapping hook / fonctions
 Plugin::addHook("install", "customiser_install");
-Plugin::addHook("uninstall", "customiser_uninstall"); 
+Plugin::addHook("uninstall", "customiser_uninstall");
+
+Plugin::addHook("menu_setting", "customiser_menu_setting");
+Plugin::addHook("content_setting", "customiser_content_setting");
 
-Plugin::addHook("menu_setting", "customiser_menu_setting");    
-Plugin::addHook("content_setting", "customiser_content_setting");   
- 
 
 ?>

+ 4 - 4
plugin/customiser/js/main.js

@@ -41,7 +41,7 @@ function customiser_theme_install(){
 		}],
 		action : 'customiser_theme_install'
 	};
-	
+
 	$.action(data,function(){
 		$.message('success','Installé');
 		$('#zipTheme').val('');
@@ -53,9 +53,9 @@ function customiser_theme_install(){
 }
 
 function customiser_theme_save(){
-	$.action({ 
-		action : 'customiser_theme_save', 
-		theme :  $('[name="selected-theme"]:checked').val() 
+	$.action({
+		action : 'customiser_theme_save',
+		theme :  $('[name="selected-theme"]:checked').val()
 	},function(){
 		$.message('success','Enregistré');
 	});

+ 3 - 3
plugin/customiser/setting.global.customiser.php

@@ -18,7 +18,7 @@ require_once(__DIR__.SLASH.'Theme.class.php');
 			}else{
 				$cover = 'plugin/customiser/img/default-cover.jpg';
 			}
-		
+
 			?>
 			<div class="col mb-4">
 				<label class="card pointer h-100" data-css="<?php echo ROOT_URL.$theme['css-relative-url']; ?>" onclick="customiser_preview(this);">
@@ -31,7 +31,7 @@ require_once(__DIR__.SLASH.'Theme.class.php');
 				    </div>
 					<div class="card-footer h-100 position-relative p-2">
 						<small class="text-muted d-block mb-1"><i class="far fa-meh-blank"></i> <?php echo isset($theme['author']) ? $theme['author']['name'] : 'Auteur inconnu'; ?></small>
-						
+
 						<?php if($theme['last-update']==0): ?>
 						<small class="text-muted d-block">Aucun thème</small>
 					    <?php else: ?>
@@ -49,7 +49,7 @@ require_once(__DIR__.SLASH.'Theme.class.php');
 					<h5 class="bg-dark text-light text-center p-3 mb-0">INSTALLER UN THEME</h5>
 					<p class="bg-dark text-light text-center mb-2">Fichier <span class="font-weight-bold">.zip</span> accepté</p>
 					<input  class="component-file-default bg-white shadow-sm rounded-sm"  type="text" onchange="customiser_theme_install();"  data-type="file"  data-extension="zip"  data-action="customiser_theme_zipTheme"  data-id="zipTheme" id="zipTheme" >
-			
+
 				</label>
 			</div>
 		</div>

+ 6 - 6
plugin/directory/action.php

@@ -33,7 +33,7 @@
 			Log::put('Envois à '.$sms->phone.' ERREUR : '.$e->getMessage(),'Sms');
 		}
 	});
-	
+
 
 	Action::register('directory_get_qr',function(&$response){
 		global $myUser,$_,$conf;
@@ -60,7 +60,7 @@
 		if(empty($user)) throw new Exception("Utilisateur introuvable");
 
 		header('Content-Type: text/x-vCard');
-		header('Content-Disposition: attachment; filename= "'.$user->login.'.vcf"');  
+		header('Content-Disposition: attachment; filename= "'.$user->login.'.vcf"');
 
 		$vCard =  'BEGIN:VCARD'.PHP_EOL;
 		$vCard .= 'VERSION:3.0'.PHP_EOL;
@@ -72,7 +72,7 @@
 		$vCard .= 'URL:'.PHP_EOL;
 		$vCard .= 'EMAIL:'.utf8_decode($user->mail).PHP_EOL;
 		$vCard .= 'END:VCARD';
-		header('Content-Length: '.strlen($vCard)); 
+		header('Content-Length: '.strlen($vCard));
 		echo $vCard;
 		exit();
 	});
@@ -80,12 +80,12 @@
 	Action::register('directory_get_excel',function(&$response){
 		global $myUser,$_,$conf;
 		if(!$myUser->connected()) throw new Exception("Permission denied");
-		
+
 		list($columns,$userMapping) = directory_get_contacts();
 
 		$excel = implode(';',$columns)."\n";
-		foreach($userMapping as $user=>$infos){ 
-			foreach ($infos['values'] as $key => $value): 
+		foreach($userMapping as $user=>$infos){
+			foreach ($infos['values'] as $key => $value):
 				$excel .= strip_tags(utf8_decode($value)).';';
 			endforeach;
 			$excel .= "\n";

+ 7 - 7
plugin/directory/directory.plugin.php

@@ -13,9 +13,9 @@ function directory_plugin_menu(&$accountMenu){
 }
 
 function directory_get_contacts(){
-	
+
 	$users = User::getAll();
-	
+
 	$userMapping = array();
 	foreach ($users as $user) {
 		$userMapping[$user->login] = array(
@@ -60,7 +60,7 @@ function directory_plugin_page(){
 		<div class="tab-pane fade show active">
 		<h3>Annuaire</h3>
 		<p>Annuaire de la société</p>
-		<hr> 
+		<hr>
 
 		<a type="btn" href="action.php?action=directory_get_excel" class="btn btn-primary" title="Excel"><i class="far fa-file-excel"></i> Exporter l'annuaire (.csv)</a>
 	   	<br/><br/>
@@ -73,7 +73,7 @@ function directory_plugin_page(){
 				    <th>Action</th>
 			    </tr>
 		    </thead>
-		    <?php foreach($userMapping as $infos){ 
+		    <?php foreach($userMapping as $infos){
 		    	$user = $infos['object'];
 		    	if($user->origin != ''){
 		    	?>
@@ -89,7 +89,7 @@ function directory_plugin_page(){
 		    		<?php endif; ?>
 		    	</td>
 		    </tr>
-		    <?php 
+		    <?php
 				}
 			} ?>
 		    </table>
@@ -107,8 +107,8 @@ function directory_plugin_page(){
 
 Plugin::addJs("/js/main.js");
 
-Plugin::addHook("menu_account", "directory_plugin_menu");  
-Plugin::addHook("content_account", "directory_plugin_page"); 
+Plugin::addHook("menu_account", "directory_plugin_menu");
+Plugin::addHook("content_account", "directory_plugin_page");
 
 
 ?>

+ 5 - 5
plugin/directory/js/main.js

@@ -1,15 +1,15 @@
 $(document).ready(function(){
 
 
-});	
+});
 
 function directory_send_sms(button){
 	var user = $(button).closest('tr').attr('data-user');
 	$(button).addClass('btn-preloader');
-	$.action({ 
-		action : 'directory_send_sms', 
+	$.action({
+		action : 'directory_send_sms',
 		user :  user
-	},function(r){ 
-		$.message('info','SMS envoyé à '+r.phone); 
+	},function(r){
+		$.message('info','SMS envoyé à '+r.phone);
 	});
 }

+ 57 - 57
plugin/document/Element.class.php

@@ -33,17 +33,17 @@ class Element extends Entity{
 	public function thumbnail(){
 		if(!in_array($this->extension, array('jpg','png','jpeg','gif','bmp','jfif'))) return $this->icon();
 		if(!file_exists(self::root().'.thumbnails')) mkdir(self::root().'.thumbnails',755,true);
-		
+
 		$thumbname = str_replace(array('\\','./'),array('/',''),$this->path);
 		$thumbnail = self::root().'.thumbnails'.SLASH.base64_encode($thumbname).'.'.$this->extension;
-		
+
 		if(!file_exists($thumbnail)){
 			$osPath = File::convert_decoding($this->path);
 			copy(self::root().$osPath,$thumbnail);
 			Image::resize($thumbnail,200,200);
 		}
 		$path ='data:image/'.$this->extension.';base64,'.base64_encode(file_get_contents($thumbnail));
-		
+
 		return $path;
 	}
 
@@ -51,7 +51,7 @@ class Element extends Entity{
 	public function icon(){
 		$path = 'plugin/document/img/file-types/';
 		$icon = $this->type == 'directory' ? 'folder.svg' : 'document.svg';
-		
+
 		switch($this->extension){
 			case 'docx':
 			case 'doc':
@@ -120,22 +120,22 @@ class Element extends Entity{
 		}
 
 		$path .= $icon;
-	
+
 		return $path;
 	}
 
 	//Récuperation d'un element base depuis un chemin physique, ou d'un objet element rensiegné a partir du path si non existant en base (prend du utf8 en entré)
 	public static function fromPath($path){
-		
+
 		$element = new self();
 
 		//convertion utf8 ISO-8859-1
 		$osPath = File::convert_decoding($path);
 		$infos = pathinfo($path);
 		//Gestion label
-		
+
 		$element->label = mt_basename($path);
-		
+
 		$element->path = str_replace(array(self::root(),'\\'),array('','/'),$path);
 		$element->type = is_dir($osPath) ? 'directory' : 'file';
 		$element->link = is_link($osPath);
@@ -146,29 +146,29 @@ class Element extends Entity{
 			$fi = new FilesystemIterator($osPath, FilesystemIterator::SKIP_DOTS);
 			$element->childNumber = iterator_count($fi);
 			$element->size =  0;
-		} else { 
+		} else {
 			if(isset($infos['extension'])) $element->extension = $infos['extension'];
 			$element->size = !$exists ? 0 : filesize($osPath);
 		}
 
 		$element->updated =  !$exists ? 0 : filemtime($osPath);
 		$element->created =  !$exists ? 0 : filectime($osPath);
-		
+
 		$relativePath = trim(str_replace(Element::root(),'',$path),SLASH);
 		if ($baseElement = Element::load(array('path'=>str_replace('\\','/',$relativePath)   ))) {
 			$element->creator = $baseElement->creator;
 			$element->id = $baseElement->id;
 		}
 		$element->path = trim($element->path,'/');
-		
+
 		return $element;
 	}
-	
+
 	//Récuperation de la liste des élements d'un repertoire (tiens compte des droits utilisateur) (attends de l'utf8)
 	public static function browse($scanned,$folderOnly = false){
 		global $myUser,$myFirm;
 		require_once(__DIR__.SLASH.'ElementRight.class.php');
-	
+
 		$osScanned = File::convert_decoding($scanned);
 		$elements = array();
 		User::check_access('document','read');
@@ -177,16 +177,16 @@ class Element extends Entity{
 		//Récuperation du tableau des rang utilisateur sous forme d'id.
 		$ranks = array();
 		if(!$myUser->superadmin){
-			foreach($myUser->ranks[$myFirm->id] as $rank)	
+			foreach($myUser->ranks[$myFirm->id] as $rank)
 				$ranks[] = $rank->id;
 		}
 
 		$existingPathes = array();
-		
+
 		//Fix glob et utilisation d'un dossier avec des [] (glob utilise ce char pour de la regex, on doit escape)
 		$osScanned = str_replace(array('[',']'),array('\[','\]'), $osScanned);
 		$osScanned = str_replace(array('\[','\]'), array('[[]','[]]'), $osScanned);
-	
+
 
 		//Pour chaque fichier physique existant
 		foreach(glob($osScanned) as $osPath){
@@ -195,7 +195,7 @@ class Element extends Entity{
 			$basePath = File::convert_encoding($osPath);
 			if((substr(mt_basename($osPath), 0,1)=='.') || ($folderOnly && !is_dir($osPath))) continue;
 
-			
+
 			//Récuperation/création de l'element objet correspondant (frompath n'accepte que l'utf8, on lui donne le basepath)
 			$line = Element::fromPath($basePath);
 
@@ -222,15 +222,15 @@ class Element extends Entity{
 				}
 
 				//On récupere les droits pour chaques chemin
-				foreach(ElementRight::staticQuery('SELECT er.*,el.path as '.Element::tableName().'_join_path  
-					FROM {{table}} er 
-					LEFT JOIN '.Element::tableName().' el ON el.id=er.element 
-					WHERE (er.entity=? OR (er.entity=? AND er.uid=?) OR (er.entity=? AND er.uid IN ('.str_repeat('?,',count($ranks)-1).'?))) 
+				foreach(ElementRight::staticQuery('SELECT er.*,el.path as '.Element::tableName().'_join_path
+					FROM {{table}} er
+					LEFT JOIN '.Element::tableName().' el ON el.id=er.element
+					WHERE (er.entity=? OR (er.entity=? AND er.uid=?) OR (er.entity=? AND er.uid IN ('.str_repeat('?,',count($ranks)-1).'?)))
 					AND element IN(SELECT id from '.Element::tableName().' WHERE path IN ('.str_repeat('?,',count($pathes)-1).'?)) ',array_merge(array("all","user",$myUser->login,"rank"),$ranks,$pathes),true,1) as $right){
 
 					$element = $right->join('element');
-				
-					
+
+
 					//Si les droits sont sur un dossier parent et sont recursifs OU si les droits sont sur le fichier concerné on continue la verification
 					if($right->element == $line->id || ($right->recursive && strpos($line->path, $element->path)!==false ) )
 						$can = true;
@@ -270,7 +270,7 @@ class Element extends Entity{
 					$filename = File::convert_encoding($filename);
 					$filename =  str_replace($path,mt_basename($path),$filename);
 					$filename=iconv("UTF-8", "IBM850", $filename);
-					if(!$zip->addFromString($filename, file_get_contents($resource))) throw new Exception("Impossible de compresser le fichier ".$path);	
+					if(!$zip->addFromString($filename, file_get_contents($resource))) throw new Exception("Impossible de compresser le fichier ".$path);
 				}
 
 				if(count($ressources)==0)
@@ -279,7 +279,7 @@ class Element extends Entity{
 				$zip->close();
 			}
 			$stream = file_get_contents($filepath);
-			unlink($filepath); 
+			unlink($filepath);
 		}else{
 			$stream = file_get_contents($osPath);
 		}
@@ -288,7 +288,7 @@ class Element extends Entity{
 
 	//Creation d'un raccourcis (prends de l'utf 8 en entrée)
 	public static function shortcut($path,$destination,$readonly = false){
-	
+
 		$osDestination = File::convert_decoding($destination);
 		if(file_exists($osDestination)) return false;
 		$element = Element::fromPath($destination);
@@ -307,14 +307,14 @@ class Element extends Entity{
 
 	//Supression d'un répértoire ou d'un fichier en base et en physique (prends de l'utf 8 en entrée)
 	public static function remove($path){
-		
+
 		require_once(__DIR__.SLASH.'ElementRight.class.php');
 		$osPath = File::convert_decoding($path);
 		if(!file_exists($osPath)) return;
 		$element = Element::fromPath($path);
 		$dbPath = str_replace('\\','/',$element->path);
 		if(!self::hasRight($element,'edit')) throw new Exception("Permissions insuffisantes",403);
-	
+
 		if(is_dir($osPath) && !is_link($osPath)) {
 
 
@@ -354,7 +354,7 @@ class Element extends Entity{
 			$baseElement = Element::load(array('path'=>$dbPath));
 			if(is_object($baseElement) && $baseElement->id != 0) $element->id = $baseElement->id;
 		}
-		
+
 		if(!File::copy($osPath,$osTo)) throw new Exception('Erreur lors de la copie...');
 		$newelement = Element::fromPath($to);
 
@@ -380,15 +380,15 @@ class Element extends Entity{
 		$osTo = File::convert_decoding($to);
 
 		if(!file_exists($osPath)) return;
-		
+
 		$element = Element::fromPath($path);
-		
-		
+
+
 		//Si le dossier se termine par un ., on supprime ce . (non pris en charge par l'os)
 		if($element->type=="directory" && substr($to, -1,1) =='.')
 			$to = substr($to, 0,strlen($to)-1);
-		
-		
+
+
 		if($to == $path) return $element;
 
 		if(!self::hasRight($element,'edit')) throw new Exception("Permissions insuffisantes",403);
@@ -398,16 +398,16 @@ class Element extends Entity{
 		if(!file_exists($parentPathOsTo))  throw new Exception("Dossier de destination inexistant",404);
 		$parentTo = Element::fromPath($parentPathTo);
 		if(!self::hasRight($parentTo,'edit')) throw new Exception("Permissions insuffisantes",403);
-	
+
 
 		$dbPath = str_replace('\\','/',$element->path);
-			
+
 			if(file_exists($osTo)) return false;
 
 			if($element->type == 'directory'){
-				
+
 				$element->path = $oldPath = $element->path;
-				
+
 				//Si c'est un dossier, on récupere tous les élements commencant par ce nom afin de modifier leurs chemins
 				$baseElement = Element::staticQuery('SELECT * FROM {{table}} WHERE `path` = ? OR `path` LIKE ?',array($dbPath,$dbPath.'/%'), true);
 			} else {
@@ -438,7 +438,7 @@ class Element extends Entity{
 				$baseElement->label = $toElement->label;
 				$baseElement->save();
 			}
-		
+
 
 		return $toElement;
 	}
@@ -466,7 +466,7 @@ class Element extends Entity{
 		file_put_contents($osPath, $stream);
 
 		$element = Element::fromPath($path, array('preview'=>false));
-		
+
 		if(!self::hasRight($element,'edit')) throw new Exception("Permissions insuffisantes",403);
 
 		$element->save();
@@ -478,7 +478,7 @@ class Element extends Entity{
 
 		//on filtre les noms non utf8 ou interdits
 		$path = dirname($path).SLASH.self::convertName(basename($path));
-		
+
 		$osPath = File::convert_decoding($path);
 		$parentPath = dirname($path);
 		$osParentPath = dirname($osPath);
@@ -526,17 +526,17 @@ class Element extends Entity{
 		}
 
 		$userRanks = array();
-		foreach ($myUser->ranks[$myFirm->id] as $rank) 
+		foreach ($myUser->ranks[$myFirm->id] as $rank)
 			$userRanks[] = $rank->id;
-		
+
 
 		$data = array();
-		$query = 'SELECT dr.recursive,dr.edit,dr.read,de.path 
-		FROM {{table}} dr 
-		LEFT JOIN '.Element::tableName().' de ON de.id = dr.element 
+		$query = 'SELECT dr.recursive,dr.edit,dr.read,de.path
+		FROM {{table}} dr
+		LEFT JOIN '.Element::tableName().' de ON de.id = dr.element
 		WHERE dr.element IN(
-			SELECT id 
-			FROM '.Element::tableName().' 
+			SELECT id
+			FROM '.Element::tableName().'
 			WHERE path IN ('.str_repeat('?,',count($allPathes)-1).'?)
 		)  AND (dr.entity=? OR (dr.entity=? AND dr.uid=?) ';
 		$data = array_merge($allPathes, array("all","user",$myUser->login));
@@ -544,10 +544,10 @@ class Element extends Entity{
 		if(count($userRanks)!=0){
 			$query .= ' OR (dr.entity=? AND dr.uid IN ('.str_repeat('?,',count($userRanks)-1).'?)) ';
 			$data = array_merge($data,array("rank"),$userRanks);
-		} 
-		
+		}
+
 		$query .= ') ORDER BY CHAR_LENGTH(de.path)';
-		
+
 		$result = ElementRight::staticQuery($query,$data);
 
 		$rights = array(
@@ -555,22 +555,22 @@ class Element extends Entity{
 			'read'=> false
 		);
 		foreach($result->fetchAll() as $line){
-	
+
 			//si le droit n'est pas récursif et que le chemin associé n'est pas exactement cleui ciblé on ignore ce droit
 			if($line['recursive'] != 1  && $line['path']!=$element->path) continue;
-			
+
 			if($line['edit'] == 1) $rights['edit'] = true;
 			if($line['read'] == 1) $rights['read'] = true;
-			
+
 		}
-		
+
 		if(!$rights[$type]) return false;
 
 		return true;
 	}
 
 	public static function remove_dir_recursive($path) {
-		
+
 		//Fix glob et utilisation d'un dossier avec des [] (glob utilise ce char pour de la regex, on doit escape)
 		$globPath = $path.SLASH.'{,.}*';
 		$globPath = str_replace(array('[',']'),array('\[','\]'), $globPath);
@@ -587,7 +587,7 @@ class Element extends Entity{
 		rmdir($path);
 	}
 
-	
+
 
 }
 ?>

+ 39 - 39
plugin/document/WebDav.class.php

@@ -45,8 +45,8 @@ class WebDav{
 
 		$this->logit($log);
 
-	
-		
+
+
 
 		if(!file_exists(self::logPath()))
 			mkdir(self::logPath(),0755,true);
@@ -58,8 +58,8 @@ class WebDav{
 				$user = isset($server['PHP_AUTH_USER']) ? $server['PHP_AUTH_USER']: '';
 				$password = isset($server['PHP_AUTH_PW']) ? $server['PHP_AUTH_PW']: '';
 
-				$header = apache_request_headers(); 
-			
+				$header = apache_request_headers();
+
 				if(isset($header['Authorization']) && $header['Authorization']!=''){
 					$authorization = explode(' ',$header['Authorization']);
 					if(count($authorization)==2){
@@ -73,29 +73,29 @@ class WebDav{
 				$password = $password =='' ? 'anonymous': $password;
 
 				$this->user = $function($user,$password);
-				
-			}catch(Exception $e){		    
+
+			}catch(Exception $e){
 		    	$this->logit('REQUEST URI : '.$requestUri.PHP_EOL.'REQUEST HEADERS : '.json_encode($headers));
 				$this->logit('Error '.self::headerFromCode(401).'  for -'. $user.' :'.$e->getCode().' '.$e->getMessage() );
 				$this->logit(json_encode($_SERVER,JSON_PRETTY_PRINT));
-				$header = apache_request_headers(); 
+				$header = apache_request_headers();
 				$header = $this->logit(json_encode($header,JSON_PRETTY_PRINT));
 				$header = $this->logit(json_encode($_REQUEST,JSON_PRETTY_PRINT));
-					
+
 				self::emit_header($e->getCode());
 	    		if($e->getCode()==401)
 					header('WWW-Authenticate: Basic realm="Software Webdav gate"');
-			    
+
 		    	echo $e->getMessage();
 		    	exit();
 		    }
 		}
 
-		
+
 
 		try{
 
-	        
+
 			switch($method) {
 
 				//Returns a list of properties of a file, a directory of a directory and its files.
@@ -112,15 +112,15 @@ class WebDav{
 						$scanned = $this->folder.$this->get_path($server);
 
 						$files = array();
-						
+
 						if(isset($this->do['list']) ){
 							$function = $this->do['list'];
 							$files = $function($scanned,$depth);
 						}
-						
+
 						$locks = $this->lock();
 						$xml = '';
-						
+
 						foreach ($files as $i=>$file) {
 							$url = $requestUri.'/';
 							//Si on est pas sur le premier dossier/fichier d'origine, c'est qu'on est sur un enfant du dossier, on concatene son url au dossier
@@ -157,7 +157,7 @@ class WebDav{
 
 				      	$this->logit('Download '.$file);
 						if(!isset($this->do['download']) ) throw new Exception("Not implemented", 501);
-						
+
 						$function = $this->do['download'];
 						$stream = $function($file);
 						self::emit_header(200);
@@ -181,21 +181,21 @@ class WebDav{
 			    	$log= "\t === ".'Réponse : '.PHP_EOL;
 			      	try{
 				        $target = $this->folder.$this->get_path($server);
-				        
+
 
 						$this->logit('PUT '.$target);
 						if(!isset($this->do['edit']) ) throw new Exception("Not implemented", 501);
-						
+
 						$function = $this->do['edit'];
 						$function($target, $body,'file');
 						self::emit_header(201);
-						
+
 
 						$log.= "\t".'- 201 Created'.PHP_EOL;
 						$this->logit($log);
 
 				    }catch(Exception $e){
-				   
+
 				    	$log.= "\t".'- '.$e->getCode().' '.$e->getMessage().PHP_EOL;
 						$this->logit($log);
 				    	self::emit_header($e->getCode());
@@ -224,7 +224,7 @@ class WebDav{
 			    case 'MOVE':
 			    	$log= "\t === ".'Réponse : '.PHP_EOL;
 			      	try{
-				      	
+
 
 				        $target = $this->folder.$this->get_path($server);
 
@@ -237,13 +237,13 @@ class WebDav{
 				        $to = substr($to, -1,1) == SLASH ? substr($to, 0,strlen($to)-1): $to;
 
 				        $this->logit('Move '.$target.' to '.$to.' (url :'.$toUrl.')');
-				        
+
 				        if(!isset($this->do['move']) ) throw new Exception("Not implemented", 501);
-				        
+
 						$function = $this->do['move'];
 						$function($target,$to);
 						self::emit_header(200);
-		
+
 			        }catch(Exception $e){
 				    	$log.= "\t".'- '.$e->getCode().' '.$e->getMessage().PHP_EOL;
 						$this->logit($log);
@@ -255,7 +255,7 @@ class WebDav{
 		        case 'MKCOL':
 		        	$log= "\t === ".'Réponse : '.PHP_EOL;
 			      	try{
-				      	
+
 				        $path = $this->folder.$this->get_path($server);
 				        $this->logit('Create folder '.$path);
 
@@ -292,14 +292,14 @@ class WebDav{
 		      	break;
 
 		      	case 'POST':
-		      		$log= "\t === ".'Réponse : '.PHP_EOL;		      	
+		      		$log= "\t === ".'Réponse : '.PHP_EOL;
 		        	self::emit_header(501);
 		        	$log.= "\t".'- 501 Not implemented'.PHP_EOL;
 					$this->logit($log);
 		      	break;
 
 		      	case 'TRACE':
-		      		$log= "\t === ".'Réponse : '.PHP_EOL;		      	
+		      		$log= "\t === ".'Réponse : '.PHP_EOL;
 		        	self::emit_header(501);
 		        	$log.= "\t".'- 501 Not implemented'.PHP_EOL;
 					$this->logit($log);
@@ -333,7 +333,7 @@ class WebDav{
 						self::emit_header(200);
 						$function = $this->do['properties'];
 						$function($properties,$namespaces);
-						
+
 						break;
 					}
 
@@ -349,7 +349,7 @@ class WebDav{
 					        	$response .= '<'.$value['ns'].':'.$value['key'].' />';
 					        }
 					$response .= '
-					       
+
 					      </d:prop>
 					    </d:propstat>
 					  </d:response>
@@ -375,16 +375,16 @@ class WebDav{
 				        $toUrl = parse_url($toUrl, PHP_URL_PATH);
 				        $to = $this->folder.str_replace('/',SLASH,utf8_decode(str_replace($this->root,'',$toUrl)));
 				        $this->logit('Copy '.$target.' to '.$to.' (url :'.$toUrl.')');
-				        
+
 				        if(!isset($this->do['copy'])) throw new Exception("Not implemented", 501);
-				        
+
 						$function = $this->do['copy'];
 						$function($target,$to);
 						self::emit_header(200);
 
 						$log.= "\t".'- 200 OK'.PHP_EOL;
 						$this->logit($log);
-					
+
 			        }catch(Exception $e){
 				    	$log.= "\t".'- '.$e->getCode().' '.$e->getMessage().PHP_EOL;
 						$this->logit($log);
@@ -521,7 +521,7 @@ class WebDav{
 		}
 		//Si aucun parametre n'est spécifié, on retourne la liste des verrous
 		if($file==null) return $locks;
-		
+
 		//Si les properties sont a false, on supprime le verrou
 		if($properties===false){
 			unset($locks[base64_encode($file)]);
@@ -545,13 +545,13 @@ class WebDav{
 
 	*/
 	public static function xml_file($url,$fileInfos,$locks){
-		
+
 
 		if(!isset($fileInfos['create_time'])) $fileInfos['create_time'] =  time();
 		if(!isset($fileInfos['update_time'])) $fileInfos['update_time']  =  time();
 		if(!isset($fileInfos['length'])) $fileInfos['length'] = 0;
-	
-		
+
+
 		$fileInfos['create_time'] = $fileInfos['create_time'] - (3600*2);
 		$fileInfos['update_time'] = $fileInfos['update_time'] - (3600*2);
 
@@ -596,7 +596,7 @@ class WebDav{
                         	</D:activelock>
 	                    </D:lockdiscovery>';
 	            }
-	             
+
 
               	if(isset($fileInfos['length']))
 	              	 $xml.= '<D:getcontentlength>'.$fileInfos['length'].'</D:getcontentlength>';
@@ -607,7 +607,7 @@ class WebDav{
 	              </D:prop>
 	              <D:status>HTTP/1.1 200 OK</D:status>
 	           </D:propstat>';
-	           
+
 	           if(!isset($fileInfos['length'])){
 	           		$xml .=  '<D:propstat>
 	              <D:prop>
@@ -616,7 +616,7 @@ class WebDav{
 	              <D:status>HTTP/1.1 404 Not Found</D:status>
 	           		</D:propstat>';
 	           }
-	 		
+
 	    $xml .= '</D:response>';
 	    return $xml;
 	}
@@ -632,7 +632,7 @@ class WebDav{
 		$path = str_replace('\\', '/', $path);
 		$path = str_replace('//', '/', $path);
 		$path = substr($path,strlen($this->root));
-		
+
 		if(substr($path, -1)=='/') $path = substr($path, 0,-1);
 		return $path;
 	}

+ 69 - 69
plugin/document/action.php

@@ -4,33 +4,33 @@ global $_,$conf;
 	//Récuperation d'une liste de element
 	Action::register('document_element_search',function(&$response){
 			global $myUser,$_,$conf;
-		
+
 			User::check_access('document','read');
 			require_once(__DIR__.SLASH.'Element.class.php');
 
 
-			
+
 
 			//recherche par libellé
 			if(!empty($_['keyword'])){
 				$query = 'SELECT * FROM {{table}} WHERE 1';
 				$data = $elements = array();
-				
+
 				$query .= ' AND label LIKE ?';
-				$data[] = '%'.$_['keyword'].'%';				
+				$data[] = '%'.$_['keyword'].'%';
 
 				$folder = isset($_['folder']) && !empty($_['folder']) ? $_['folder'] : '.';
 				if(isset($_['folder']) && !empty($_['folder']))
 					$query .= ' AND `path` LIKE "'.$_['folder'].'%'.'"';
 
-				
+
 				//Tri des colonnes
 				if(isset($_['sort']))
 					sort_secure_query($_['sort'],array('label','creator','size'),$query,$data);
-				
-				
 
-			           
+
+
+
 
 				foreach (Element::staticQuery($query,$data,true) as $element){
 					// Check des partages sur l'élément
@@ -45,16 +45,16 @@ global $_,$conf;
 
 					$line->path = rtrim($line->path, SLASH);
 
-					
-				
-					
+
+
+
 					$osPath = Element::root().str_replace('/',SLASH,$line->path);
 					if(!file_exists($osPath)){
 						Element::deleteById($line->id);
 						continue;
 					}
 					$row = $line->toArray();
-					
+
 					$row['updatedRelative'] = relative_time($line->updated);
 					$row['sizeReadable'] = $row['type'] == 'directory' ? $line->childNumber.' élements' : readable_size($line->size);
 					$row['updatedReadable'] = day_name(date('N',$line->updated)).' '. date('d ',$line->updated).month_name(date('m',$line->updated)).date(' Y à H:i',$line->updated);
@@ -62,7 +62,7 @@ global $_,$conf;
 					$row['link'] = $line->link;
 					$row['icon'] = $line->icon();
 					$row['childNumber'] = $line->childNumber;
-					
+
 
 					$elements[] = $row;
 				}
@@ -71,7 +71,7 @@ global $_,$conf;
 			//recherche par arborescence
 			}else{
 
-				
+
 
 				if(isset($_['folder']) && !empty($_['folder'])){
 					$folder = str_replace('/',SLASH,$_['folder']);
@@ -80,7 +80,7 @@ global $_,$conf;
 					if(isset($_['root'])) $folder = str_replace('/',SLASH,$_['root']);
 				}
 
-				
+
 				$response['rows'] = array();
 				$scanned = Element::root().$folder.SLASH.'*';
 
@@ -98,7 +98,7 @@ global $_,$conf;
 					$row['icon'] = $line->icon();
 					$row['link'] = $line->link;
 					$row['childNumber'] = $line->childNumber;
-			
+
 					$response['rows'][] = $row;
 				}
 
@@ -137,7 +137,7 @@ global $_,$conf;
 
 		$level = count(explode('/',$folder));
 		$parentLevel = $level-1 < 0 ? 0 : $level-1;
-	
+
 		$parts = explode('/',$folder);
 		$path = '';
 		$level = 0;
@@ -169,7 +169,7 @@ global $_,$conf;
 				Element::deleteById($directory->id);
 				continue;
 			}
-			
+
 			$response['tree'][] =$directory->path;
 		}
 
@@ -187,7 +187,7 @@ global $_,$conf;
 		User::check_access('document','read');
 		require_once(PLUGIN_PATH.'dashboard'.SLASH.'DashboardWidget.class.php');
 		$widget = DashboardWidget::current();
-		
+
 		$root = $widget->data('widget-document-root');
 		$root = !empty($root) ? ': <strong>'.$root.'</strong>':'';
 
@@ -200,26 +200,26 @@ global $_,$conf;
 	});
 
 	Action::register('document_widget_configure_save',function(&$response){
-	
+
 			global $myUser,$_;
 			require_once(PLUGIN_PATH.'dashboard'.SLASH.'DashboardWidget.class.php');
 
 			User::check_access('document','configure');
 
 			$widget = DashboardWidget::getById($_['id']);
-			
+
 			$widget->data('widget-document-tree',$_['widget-document-tree']);
 			$widget->data('widget-document-detail',$_['widget-document-detail']);
 			$widget->data('widget-document-search',$_['widget-document-search']);
 
 			$root = str_replace(array('./','../'),'',$_['widget-document-root']);
 			$widget->data('widget-document-root',$root);
-			
+
 			$widget->save();
-		
+
 	});
 
-	
+
 	Action::register('document_widget_configure',function(&$response){
 		global $myUser;
 		require_once(PLUGIN_PATH.'dashboard'.SLASH.'DashboardWidget.class.php');
@@ -234,8 +234,8 @@ global $_,$conf;
 
 	Action::register('document_embedded',function(&$response){
 			User::check_access('document','read');
-			Plugin::addCss("/css/main.css"); 
-			Plugin::addJs("/js/main.js"); 
+			Plugin::addCss("/css/main.css");
+			Plugin::addJs("/js/main.js");
 
 			ob_start();
 			global $myUser,$_;
@@ -244,11 +244,11 @@ global $_,$conf;
 			if(isset($_['data']['root'])) $_['data']['root'] = str_replace('\\', '/', $_['data']['root']);
 			require_once(__DIR__.SLASH.'page.list.php');
 			$response['html'] = ob_get_clean();
-		
+
 	});
 
 	Action::register('document_folder_create',function(&$response){
-	
+
 			global $myUser,$_,$conf;
 			User::check_access('document','edit');
 			require_once(__DIR__.SLASH.'Element.class.php');
@@ -264,16 +264,16 @@ global $_,$conf;
 
 
 	Action::register('document_element_preview',function(&$response){
-	
+
 			global $myUser,$_;
 			User::check_access('document','read');
 			require_once(__DIR__.SLASH.'Element.class.php');
-			
+
 			//l'ui ne renvois que les /, on les convertis par le separateur de l'os
 			$_['path'] = str_replace('/', SLASH, $_['path']);
 
 			$path = str_replace(SLASH.'.'.SLASH,SLASH,Element::root().$_['path']);
-			
+
 			$osPath = File::convert_decoding($path);
 			if(!file_exists($osPath)) throw new Exception('Cet élément a peut-être été modifié ou déplacé par quelqu\'un d\'autre. Rafraîchissez la page et réessayez.');
 			$element = Element::fromPath($path);
@@ -293,7 +293,7 @@ global $_,$conf;
 	});
 
 	Action::register('document_properties_show',function(&$response){
-	
+
 			global $myUser,$_;
 			User::check_access('document','read');
 			require_once(__DIR__.SLASH.'Element.class.php');
@@ -301,30 +301,30 @@ global $_,$conf;
 			$element = Element::provide();
 			$element->path = str_replace('\\', '/', $element->path);
 			$row = $element->toArray();
-			
+
 			$filePath = Element::root().$element->path;
 			$row['updatedLabel'] = date('d/m/Y H:i',filemtime($filePath));
-		
+
 			$bundle = base64_encode(json_encode(array(
 				'root' => $element->path,
 				'folder' => '',
 			)));
 			$row['rootUrl'] = ROOT_URL.'/index.php?module=document&data='.$bundle;
-			$response['row'] = $row;	
+			$response['row'] = $row;
 	});
 
 	Action::register('document_element_execute',function(&$response){
 		global $myUser,$_,$conf;
 		User::check_access('document','read');
 		require_once(__DIR__.SLASH.'Element.class.php');
-		
+
 		$isopath =  Element::root().base64_decode(rawurldecode($_['path']));
 		$utf8Path = utf8_encode($isopath);
 		$osPath = get_OS() === 'WIN' ? $isopath : $utf8Path;
-		
+
 		$stream = Element::download($utf8Path);
 		$name = mt_basename($utf8Path);
-		
+
 		$mime = 'application/octet-stream';
 		if(is_dir($osPath)){
 			$mime = 'application/zip';
@@ -336,7 +336,7 @@ global $_,$conf;
 	});
 
 	Action::register('document_element_move',function(&$response){
-	
+
 			global $myUser,$_,$conf;
 			User::check_access('document','edit');
 			require_once(__DIR__.SLASH.'Element.class.php');
@@ -354,7 +354,7 @@ global $_,$conf;
 				une nouvelle ligne, ce qui rend le proprietaire du fichier anonymous
 			*/
 			if($_['to']=='.') $_['to'] = '';
-			
+
 			$to = Element::root().$_['to'];
 			$osTo = File::convert_decoding($to);
 			if(!is_dir($osTo)) return;
@@ -364,10 +364,10 @@ global $_,$conf;
 
 			$element = Element::move($from,$to);
 			$response['element'] = $element;
-			if($conf->get('document_enable_logs')) Log::put('Déplacement de '.$from.' dans '.$to,'document');	
+			if($conf->get('document_enable_logs')) Log::put('Déplacement de '.$from.' dans '.$to,'document');
 	});
 
-	Action::register('document_element_rename',function(&$response){	
+	Action::register('document_element_rename',function(&$response){
 			global $myUser,$_,$conf;
 			User::check_access('document','edit');
 			require_once(__DIR__.SLASH.'Element.class.php');
@@ -376,7 +376,7 @@ global $_,$conf;
 			if(!isset($_['label']) || empty($_['label'])) throw new Exception("Le nom ne doit pas être vide");
 
 			if(strlen($_['label']) > 80) throw new Exception("Taille maximale autorisée de 80 caractères.");
-			
+
 			//l'ui ne renvois que les /, on les convertis par le separateur de l'os
 			$_['path'] = str_replace('/', SLASH, $_['path']);
 			$from =  Element::root().$_['path'];
@@ -389,21 +389,21 @@ global $_,$conf;
 			if(file_exists($to)) throw new Exception('Action impossible, un élément existe déjà avec ce nom.');
 			$char = document_check_element_name(htmlspecialchars_decode(html_entity_decode($_['label']), ENT_QUOTES));
 			if(!empty($char)) throw new Exception("Caractères interdits : ".$char);
-			
+
 			$element = Element::move($from,$to);
-			
+
 			if(!$element) throw new Exception("Erreur lors de la récupération de l'élément renommé", 500);
-			
+
 			$element->path = str_replace('\\', '/', $element->path);
 			$response['element'] = $element;
-			if($conf->get('document_enable_logs') ) Log::put('Renommage de l\'élément : '.$from.' en '.$to,'document');	
+			if($conf->get('document_enable_logs') ) Log::put('Renommage de l\'élément : '.$from.' en '.$to,'document');
 	});
 
 	Action::register('document_element_delete',function(&$response){
 			global $myUser,$_,$conf;
 			User::check_access('document','delete');
 			require_once(__DIR__.SLASH.'Element.class.php');
-			
+
 			//l'ui ne renvois que les /, on les convertis par le separateur de l'os
 			$path =  Element::root().str_replace('/', SLASH,$_['path']);
 			$osPath =  File::convert_decoding($path);
@@ -416,7 +416,7 @@ global $_,$conf;
 				$thumbpath = Element::root().'.thumbnails'.SLASH.base64_encode($thumbname).'.'.$extension;
 				if(file_exists($thumbpath)) unlink($thumbpath);
 			}
-			if($conf->get('document_enable_logs')) Log::put("Suppression d'un élément : ".$path,'document');	
+			if($conf->get('document_enable_logs')) Log::put("Suppression d'un élément : ".$path,'document');
 	});
 
 	//edition d'un fichier (chargement)
@@ -431,7 +431,7 @@ global $_,$conf;
 			$osPath = File::convert_decoding($path);
 
 			if(!file_exists($osPath)) throw new Exception("Impossible de trouver le fichier, peut-être a t-il été supprimé entre temps, veuillez recharger la page.");
-			
+
 			$response['path'] = $path;
 			$response['label'] = mt_basename($path);
 			$response['content'] = Element::download($path);
@@ -440,7 +440,7 @@ global $_,$conf;
 
 	//edition d'un fichier (sauvegarde)
 	Action::register('document_element_save',function(&$response){
-	
+
 			global $myUser,$_,$conf;
 			User::check_access('document','edit');
 			require_once(__DIR__.SLASH.'Element.class.php');
@@ -464,11 +464,11 @@ global $_,$conf;
 
 	//upload d'un fichier
 	Action::register('document_element_upload',function(&$response){
-	
+
 			global $myUser,$_,$conf;
 			User::check_access('document','edit');
 			require_once(__DIR__.SLASH.'Element.class.php');
-			
+
 			$response['sort'] = $_['sort'];
 
 			if(empty($_FILES)) throw new Exception("Aucun document à importer");
@@ -476,10 +476,10 @@ global $_,$conf;
 			$osPath = File::convert_decoding($path);
 
 			if(!file_exists($osPath)) throw new Exception("Dossier ".$osPath." introuvable");
-			
+
 			$maxSize = $conf->get('document_allowed_size');
 			$extensions = explode(',',str_replace(' ', '', $conf->get('document_allowed_extensions')));
-			
+
 			$extension = getExt($_FILES['file']['name'][0]);
 			if($_FILES['file']['size'][0] > $maxSize) throw new Exception("Taille du fichier ".$_FILES['file']['name'][0]." trop grande, taille maximum :".readable_size($maxSize).' ('.$maxSize.' octets)');
 			if(!in_array($extension , $extensions)) throw new Exception("Extension '".$extension."' du fichier ".$_FILES['file']['name'][0]." non permise, autorisé :".implode(', ',$extensions));
@@ -488,14 +488,14 @@ global $_,$conf;
 			$filePath =  $path.$_FILES['file']['name'][0];
 			if(!file_exists($_FILES['file']['tmp_name'][0]))  throw new Exception("Fichier temporaire n°".$_['sort']." inexistant, verifiez la clause upload_max_size de PHP.");
 			Element::addFile($filePath,file_get_contents($_FILES['file']['tmp_name'][0]));
-			
-			if($conf->get('document_enable_logs')) Log::put("Upload d'un élément : ".$filePath,'document');			
-		
+
+			if($conf->get('document_enable_logs')) Log::put("Upload d'un élément : ".$filePath,'document');
+
 	});
 
 	//Sauvegarde des configurations de document
 	Action::register('document_setting_save',function(&$response){
-	
+
 			global $myUser,$_,$conf;
 			User::check_access('document','configure');
 
@@ -505,17 +505,17 @@ global $_,$conf;
 			}
 			foreach ($_['fields'] as $key => $value)
 				if(in_array($key, $allowed)) $conf->put($key,$value);
-		
+
 	});
 
 	/** ELEMENTRIGHT **/
 	//Récuperation d'une liste de elementright
 	Action::register('document_right_search',function(&$response){
-	
+
 			global $myUser,$_;
 			User::check_access('document','read');
 			require_once(__DIR__.SLASH.'ElementRight.class.php');
-			
+
 			$rights = ElementRight::loadAll(array('element'=>$_['id']));
 			foreach($rights as $right){
 				if($right->entity =='rank'){
@@ -529,13 +529,13 @@ global $_,$conf;
 				if($row['recursive'] == 0) unset($row['recursive']);
 				$response['rows'][] = $row;
 			}
-			
-		
+
+
 	});
 
 	//Ajout ou modification d'élément elementright
 	Action::register('document_right_save',function(&$response){
-	
+
 			global $myUser,$_;
 			User::check_access('document','edit');
 			require_once(__DIR__.SLASH.'ElementRight.class.php');
@@ -558,12 +558,12 @@ global $_,$conf;
 			ElementRight::delete(array('element'=>$item->element,'entity'=>$item->entity,'uid'=>$item->uid));
 
 			$item->save();
-		
+
 	});
-	
+
 	//Suppression d'élement elementright
 	Action::register('document_right_delete',function(&$response){
-	
+
 			global $myUser,$_;
 			User::check_access('document','delete');
 			require_once(__DIR__.SLASH.'ElementRight.class.php');
@@ -574,7 +574,7 @@ global $_,$conf;
 			if($element->creator != $myUser->login && !$myUser->can('document','configure') && !$myUser->superadmin) throw new Exception("Vous n'etes pas propriétaire de cet élement",403);
 
 			ElementRight::deleteById($right->id);
-		
+
 	});
 
 

+ 10 - 10
plugin/document/css/document.api.css

@@ -181,7 +181,7 @@
 	transition: background 0.1s ease-in-out;
 	padding:15px;
 	text-align: center;
-	
+
 	overflow: hidden;
 }
 .document-container ul.file-elements-grid{
@@ -470,7 +470,7 @@
 	position: fixed; /* Sit on top of the page content */
 	width: 100%; /* Full width (cover the whole page) */
 	height: 100%; /* Full height (cover the whole page) */
-	top: 0; 
+	top: 0;
 	left: 0;
 	right: 0;
 	bottom: 0;
@@ -526,7 +526,7 @@
 @keyframes floating {
 	from { transform: translate(0,  0px); }
 	50%  { transform: translate(0, 15px); }
-	to   { transform: translate(0, -0px); }    
+	to   { transform: translate(0, -0px); }
 }
 
 .document-container .file-panel.drag-over {
@@ -700,7 +700,7 @@
 	width: 350px;
 	max-width: 350px;
 	text-overflow: ellipsis;
-	overflow: hidden; 
+	overflow: hidden;
 	white-space: nowrap;
 }
 
@@ -725,9 +725,9 @@
 .detail-panel .detail-thumbnail{
 	background: url(../img/default-image.svg) no-repeat center center #f5f4f4;
 	height:250px;
-	
+
 	text-align: center;
-	background-size: auto 140px; 
+	background-size: auto 140px;
 }
 .detail-panel .detail-thumbnail .thumbnail-preloader{
 	font-size: 40px;
@@ -738,7 +738,7 @@
 	box-sizing: border-box;
 	color:#cecece;
 	transition: opacity 0.2s ease-in-out;
-	
+
 }
 .detail-panel .detail-thumbnail .thumbnail-preloader.show{
  	opacity:1;
@@ -848,8 +848,8 @@
 	}
 	75% { transform: translateY(9px) rotate(67.5deg); }
 	100% { transform: translateY(0) rotate(90deg); }
-} 
-.preloader-upload-shadow { 
+}
+.preloader-upload-shadow {
 	width: 50px;
 	height: 5px;
 	background: #000;
@@ -879,7 +879,7 @@
 	    width: 100%;
 	}
 	.document-container .detail-thumbnail {
-	
+
 	   height:200px;
 	}
 	.module-document .footer{

+ 28 - 28
plugin/document/document.plugin.php

@@ -55,7 +55,7 @@ Right::register('document',array('label'=>'Gestion des droits sur le plugin docu
 //Déclaration du menu de réglages
 function document_menu_setting(&$settingMenu){
 	global  $myUser;
-	
+
 	if($myUser->can('document','configure')) {
 		$settingMenu[]= array(
 			'sort' =>4,
@@ -85,7 +85,7 @@ function document_dav_document($requested){
 
 	if(substr($requested, 0,13)!='dav/documents') return;
 	if(empty($requested)) throw new Exception("Unspecified DAV path");
-    
+
 	if($conf->get('document_enable_dav') != "1"){
 		header('HTTP/1.1 501 Method not implemented');
 	    header('Content-Type: text/html; charset=utf-8');
@@ -119,19 +119,19 @@ function document_dav_document($requested){
 		global $myUser;
 
 		if($myUser->login !=''){
-		
+
 			return $myUser;
 		}
-		
+
 
 		$myUser = User::check($login,$password);
 
 		if(!$myUser)
 			throw new Exception("Problème lors de la connexion, veuillez contacter l'administrateur",401);
-		
+
 		if(file_exists('enabled.maintenance') && $myUser->superadmin != 1)
 			throw new Exception('Seul un compte Super Admin peut se connecter en mode maintenance',401);
-		
+
 		if(!$myUser->connected())
 			throw new Exception('Identifiant ou mot de passe incorrect',401);
 
@@ -139,15 +139,15 @@ function document_dav_document($requested){
 			$_SESSION['firm'] = serialize(Firm::getById($myUser->preference('default_firm')));
 			if(!$_SESSION['firm'])
 				throw new Exception("Problème lors de la connexion, veuillez contacter l'administrateur",401);
-			
+
 		}else if(count($myUser->firms)!=0){
 			$_SESSION['firm'] = serialize(reset($myUser->firms));
 			if(!$_SESSION['firm'])
 				throw new Exception(" Problème lors de la connexion, veuillez contacter l'administrateur",401);
 		}else{
 			throw new Exception('Ce compte n\'est actif sur aucune firm',401);
-		}			
-		
+		}
+
 		$myFirm = isset($_SESSION['firm']) ? unserialize($_SESSION['firm']) : new Firm();
 		if(!$myFirm)
 			throw new Exception("Problème lors de la connexion, veuillez contacter l'administrateur",401);
@@ -169,7 +169,7 @@ function document_dav_document($requested){
 		$utf8Path = utf8_encode($isoPath);
 
 		//pour verfiier si le fichier existe, on récupere son chemin système avec le bon encodage
-		$osPath = get_OS() === 'WIN' ? $isoPath: $utf8Path; 
+		$osPath = get_OS() === 'WIN' ? $isoPath: $utf8Path;
 
 		if(!file_exists($osPath))  throw new Exception("Fichier inexistant",404);
 	    if(!is_file($osPath)) throw new Exception("Méthode non autorisée sur autre chose qu'un fichier",501);
@@ -235,7 +235,7 @@ function document_dav_document($requested){
 		User::check_access('document','read');
 
 		//pour verfier si le fichier existe, on récupere son chemin système avec le bon encodage
-		$osPath = get_OS() === 'WIN' ? $isoPath: $utf8Path; 
+		$osPath = get_OS() === 'WIN' ? $isoPath: $utf8Path;
 		if(!file_exists($osPath)) throw new Exception("Not found", 404);
 
 		$files = array();
@@ -256,7 +256,7 @@ function document_dav_document($requested){
 		//Si le dav demande un scan en profondeur du dossier, on scan les enfants du dossier ciblé
 		if($depth>0)
 			$toScan = array_merge($toScan,Element::browse($utf8Path.SLASH.'*'));
-		
+
 		foreach($toScan as $element){
 			//on convertis l'utf8 de l'element pour passer en iso webdav windows si le serveur est sous windows
 			$path = Element::root().(get_OS() === 'WIN' ? utf8_decode( $element->path) : $element->path );
@@ -314,7 +314,7 @@ function document_widget(&$widgets){
 	$modelWidget = new DashboardWidget();
 	$modelWidget->model = 'document';
 	$modelWidget->title = 'Documents';
-	
+
 	$modelWidget->icon = 'fas fa-file';
 	$modelWidget->background = '#A3CB38';
 	$modelWidget->callback = 'init_components';
@@ -354,10 +354,10 @@ function document_client_merge($clientBase,$clientToMerge,&$logs){
 	Plugin::need('client/Client');
 	require_once(__DIR__.SLASH.'Element.class.php');
 	$logs[] = ' Migration des documents attaches ';
-	
-	
 
-	$clientDirectoryTemplate = empty($conf->get('document_client_directory')) ? 'Clients'.SLASH.'{{slug}}' : $conf->get('document_client_directory'); 
+
+
+	$clientDirectoryTemplate = empty($conf->get('document_client_directory')) ? 'Clients'.SLASH.'{{slug}}' : $conf->get('document_client_directory');
 
 	$toMergeRelativeDirectory = str_replace('{{slug}}',$clientToMerge->slug,$clientDirectoryTemplate);
 	$toMergeDirectory = Element::root().$toMergeRelativeDirectory;
@@ -392,7 +392,7 @@ $api->route('element/upload','Upload un fichier dans la racine spécifiée','POS
 	   	$contents = array();
 	   	foreach ($parts as $part) {
 	   		if(empty(trim($part))) continue;
-	
+
 	   		list($header,$body) = explode("\n\n",$part,2);
 	   		$content = array(
 	   			'header' => array(),
@@ -404,7 +404,7 @@ $api->route('element/upload','Upload un fichier dans la racine spécifiée','POS
 	   		}
 	   		$contents[] = $content;
 	   	}
-	  	
+
 	  }
 	}
 
@@ -420,12 +420,12 @@ $api->route('element/upload','Upload un fichier dans la racine spécifiée','POS
 			$_FILES['file']['tmp_name'][$i] = $tmpfname;
 			$i++;
 		}
-		
+
 		if(strpos($content['header']['Content-Type'], 'application/json')!==false){
 			$_ = json_decode($content['body'],true);
 		}
 	}
-	
+
 	if(!isset($contents)){
 		$_ = json_decode($request['body'],true);
 	}
@@ -447,7 +447,7 @@ function document_cron($time){
 
 	require_once(__DIR__.SLASH.'Element.class.php');
 	require_once(__DIR__.SLASH.'ElementRight.class.php');
-	
+
 	$toDelete = array();
 	$i = 0;
 	$ids = array();
@@ -469,11 +469,11 @@ function document_cron($time){
 
 
 //Déclation des assets
-Plugin::addCss("/css/main.css"); 
-Plugin::addCss("/css/document.api.css"); 
-Plugin::addJs("/js/component.js",true); 
-Plugin::addJs("/js/document.api.js"); 
-Plugin::addJs("/js/main.js"); 
+Plugin::addCss("/css/main.css");
+Plugin::addCss("/css/document.api.css");
+Plugin::addJs("/js/component.js",true);
+Plugin::addJs("/js/document.api.js");
+Plugin::addJs("/js/main.js");
 
 //Mapping hook / fonctions
 Plugin::addHook("widget", "document_widget");
@@ -482,9 +482,9 @@ Plugin::addHook("uninstall", "document_uninstall");
 
 
 Plugin::addHook("menu_main", "document_menu");
-Plugin::addHook("page", "document_page");  
+Plugin::addHook("page", "document_page");
 
-Plugin::addHook("menu_setting", "document_menu_setting");    
+Plugin::addHook("menu_setting", "document_menu_setting");
 Plugin::addHook("content_setting", "document_content_setting");
 Plugin::addHook("rewrite", "document_dav_document");
 Plugin::addHook("cron", "document_cron");

+ 82 - 82
plugin/document/js/document.api.js

@@ -2,7 +2,7 @@
 
 
 var DocumentApi = function(element,options) {
-			
+
 			this.onEvents = {};
 			this.currentView = 'list';
 			this.currentFolder = '.';
@@ -52,28 +52,28 @@ var DocumentApi = function(element,options) {
 				rightDelete : true,
 				rightPermission : true,
 				panels : {
-					detail : { 
+					detail : {
 						visible : true,
 						buttons : []
 					},
-					view : { 
+					view : {
 						visible : true,
 						buttons : []
 					},
-					tree : { 
+					tree : {
 						visible : true
 					},
-					files : { 
+					files : {
 						visible : true
 					},
-					workspace : { 
+					workspace : {
 						visible : true
 					},
-					search : { 
+					search : {
 						visible : true,
 						buttons : []
 					},
-					breadcrumb : { 
+					breadcrumb : {
 						visible : true
 					}
 				},
@@ -96,17 +96,17 @@ var DocumentApi = function(element,options) {
 					right_save : 'document_right_save',
 					right_delete : 'document_right_delete',
 				}
-			};		
+			};
 			if(options) this.options = $.extend(this.options,options);
 
 	}
 	DocumentApi.prototype.load = function(callbacks){
-			
+
 		this.dom.container.html('Chargement...');
 		var element = this.element;
 		var object = this;
 
-		
+
 		object.options.panels.detail.buttons.push({
 			buttonClass : 'btn-primary btn-download',
 			icon : 'fas fa-arrow-alt-circle-down',
@@ -202,7 +202,7 @@ var DocumentApi = function(element,options) {
 				visibility : {
 					'type': ['file','directory']
 				}
-			});			
+			});
 		}
 
 		object.dom.container.load('action.php?action='+object.options.actions.template,function(){
@@ -223,9 +223,9 @@ var DocumentApi = function(element,options) {
 			if(object.options.panels['files'].visible  === false) object.hidePanel('files');
 			if(object.options.panels['workspace'].visible  === false) object.hidePanel('workspace');
 			if(object.options.panels['breadcrumb'].visible  === false) object.hidePanel('breadcrumb');
-			
+
 			$('.root-folder span',object.dom.panels.tree).text(object.options.rootLabel);
-			
+
 			object.views.push({
 				uid : 'list',
 				icon : 'fas fa-align-justify',
@@ -242,11 +242,11 @@ var DocumentApi = function(element,options) {
 
 			//Chargement des vues disponibles
 			object.loadViews();
-			
+
 			//Rendu de la vue courante & Chargement des fichiers
 			object.renderView(object.options.path);
 
-			
+
 
 			//Chargement des boutons ajouter (dossier, fichier..)
 			$('.document-create-dropdown .dropdown-item:not(.hidden)').remove();
@@ -290,7 +290,7 @@ var DocumentApi = function(element,options) {
 					$('.doc-search-container').removeClass('typing');
 				}
 			});
-			
+
 			$(".search-clear").click(function(){
 				$('.doc-search-container').removeClass('typing');
 
@@ -330,7 +330,7 @@ var DocumentApi = function(element,options) {
 			$('.detail-buttons',object.dom.panels.detail).on('click','.btn-element-delete',function(){object.element_delete();});
 
 			$('.tree-folders',object.dom.panels.tree).on('click','li',function(event){object.folder_toggle(this,event);});
-			
+
 			//editeur
 			$('.dropdown-menu-button',object.dom.panels.search).click(function(){$('.file-element').removeClass('element-focused');});
 			$('.create-txt-button',object.dom.panels.search).click(function(){object.element_edit();});
@@ -356,7 +356,7 @@ var DocumentApi = function(element,options) {
 	DocumentApi.prototype.hidePanel = function (panel){
 		var object = this;
 		object.options.panels[panel].visible = false;
-		
+
 		if(object.dom.panels[panel]!=null) object.dom.panels[panel].addClass('hidden');
 	}
 	DocumentApi.prototype.showPanel = function (panel){
@@ -368,9 +368,9 @@ var DocumentApi = function(element,options) {
 
 	//Récuperation d'une liste de element dans le tableau elements
 	DocumentApi.prototype.element_search = function (folderPath){
-		
+
 		var object = this;
-	
+
 		if(object.isProcessing) return;
 
 		$('.file-preloader',object.dom.panels.files).removeClass('hidden');
@@ -394,11 +394,11 @@ var DocumentApi = function(element,options) {
 			root :object.options.root,
 			folder : folderPath ? folderPath : object.currentFolder
 		}
-		
+
 		data.folder = data.folder == '.' ? '': data.folder;
 
 
-		
+
 		//gestion de l'arborescence de gauche (tree)
 		$.action(data,function(r){
 			var tree = $('ul.tree-folders',object.dom.panels.tree);
@@ -422,8 +422,8 @@ var DocumentApi = function(element,options) {
 		  					if(selected && (selected.indexOf(path+'/')!==-1 || selected==path) ) classes+= ' folder-open ';
 		  					var row = {
 		  						path : path,
-		  						label : part, 
-		  						className : classes 
+		  						label : part,
+		  						className : classes
 		  					};
 		  					var element = $(Mustache.render(tpl,row));
 		  					element.removeClass('hidden');
@@ -433,9 +433,9 @@ var DocumentApi = function(element,options) {
 		  			}
 		  		}
 	  		}
-			
+
 		});
-		
+
 
 		data.action = object.options.actions.element_search;
 
@@ -458,7 +458,7 @@ var DocumentApi = function(element,options) {
 
 			//reset panel detail
 			object.reset_preview();
-		
+
 
 			//EVENTS
 
@@ -466,10 +466,10 @@ var DocumentApi = function(element,options) {
 			$('.file-view:visible .file-element',object.dom.panels.files).off('click').click(function(event){ object.element_preview(this, event);  });
 			//Ouverture fichier / dossier
 			$('.file-view:visible .file-element',object.dom.panels.files).off('dblclick').dblclick(function(event){ object.element_execute(this);  });
-			
+
 
 			//Renommage
-			$('.file-view:visible .file-element .element-rename',object.dom.panels.files).click(function(event){ 
+			$('.file-view:visible .file-element .element-rename',object.dom.panels.files).click(function(event){
 				event.stopPropagation();
 	 			event.preventDefault();
 				object.element_rename_edit(this);
@@ -486,12 +486,12 @@ var DocumentApi = function(element,options) {
 				}
 
 				if (e.type !== 'blur' && e.keyCode !== 13) return;
-				
+
 				var tr = input.closest('.file-element');
 				var button = tr.find('.element-rename');
 
 				var newLabel = input.val().replace(/\s+$/, '');
-			
+
 				//Les dossiers ne peuvent finir par un .
 				if(newLabel.slice(-1) == '.' && tr.attr('data-type') =='directory') newLabel = newLabel.slice(0,-1);
 
@@ -506,13 +506,13 @@ var DocumentApi = function(element,options) {
 				//Attribution nouveau label
 				text.text(newLabel).removeClass('hidden');
 				input.addClass('hidden');
-		 		
+
 				$.action({
 					action : object.options.actions.element_rename,
 					path : tr.attr('data-path'),
 					label : newLabel
 				}, function(r){
-					
+
 					button.removeClass('hidden');
 					$('.tree-folders li[data-path="'+ tr.attr('data-path')+'"]').attr('data-path',r.element.path).find('span').text(newLabel);
 					tr.attr('data-path', r.element.path);
@@ -526,9 +526,9 @@ var DocumentApi = function(element,options) {
 					text.text(label);
 					button.removeClass('hidden');
 				});
-				
+
 			});
-			
+
 			//Maj du placeholder de la recherche
 	 		$('.label-search').attr('placeholder','Rechercher'+(breadcrumb ? ' dans '+breadcrumb[breadcrumb.length-1]:''));
 
@@ -551,7 +551,7 @@ var DocumentApi = function(element,options) {
 					stop: function(e, ui){
 						$('.original-placeholder').remove();
 						$(e.originalEvent.target).one('click', function(e){
-							e.stopImmediatePropagation(); 
+							e.stopImmediatePropagation();
 						});
 					}
 				}).disableSelection();
@@ -592,9 +592,9 @@ var DocumentApi = function(element,options) {
 					},
 					out: function(e, ui){
 						var to = $(this);
-						if( to.hasClass('root-folder') && to.hasClass('folder-focused')) 
+						if( to.hasClass('root-folder') && to.hasClass('folder-focused'))
 							to.removeClass('folder-focused');
-						if(to.hasClass('folder-hover')) 
+						if(to.hasClass('folder-hover'))
 							to.removeClass('folder-hover');
 					},
 					drop: function(event, ui) {
@@ -657,9 +657,9 @@ var DocumentApi = function(element,options) {
 		if(!object.dom.panels.breadcrumb) return;
 
 		if(breadcrumb === null) breadcrumb = ['.'];
-		
+
 		if(breadcrumb[0]!='.') breadcrumb.unshift('.');
-		
+
 		$('ul li:visible',object.dom.panels.breadcrumb).remove();
 
 		var tpl = $('li:not(:visible)',object.dom.panels.breadcrumb).get(0).outerHTML;
@@ -680,7 +680,7 @@ var DocumentApi = function(element,options) {
 		});
 	}
 
-	
+
 
 	/** DOSSIER */
 	DocumentApi.prototype.folder_toggle = function (element, event, force){
@@ -709,7 +709,7 @@ var DocumentApi = function(element,options) {
 	}
 
 
-	
+
 
 	// Preloader affiché durant l'upload
 	DocumentApi.prototype.toggle_preloader_upload = function(){
@@ -741,7 +741,7 @@ var DocumentApi = function(element,options) {
 		//Upload des images dans le presse papier
 		window.addEventListener("paste", function(event){
 			var clipboardData = event.clipboardData || window.clipboardData;
-			
+
 		   if(clipboardData.getData('Text').length) return;
 
 			if(event.clipboardData == false || event.clipboardData.items == undefined) return;
@@ -759,7 +759,7 @@ var DocumentApi = function(element,options) {
 					file : file
 				});
 			}
-			form.trigger('submit');		   
+			form.trigger('submit');
 		}, false);
 
 
@@ -806,7 +806,7 @@ var DocumentApi = function(element,options) {
 		   fileQueue = [];
 			if(!e.originalEvent.dataTransfer) return;
 			droppedFiles = e.originalEvent.dataTransfer.files;
-		
+
 			for (var i=0, f; f=droppedFiles[i]; ++i) {
 
 				if(f.name.indexOf(".")==-1 && f.size%4096 == 0) {
@@ -818,21 +818,21 @@ var DocumentApi = function(element,options) {
 					file : droppedFiles[i]
 				});
 			}
-			form.trigger('submit');			
+			form.trigger('submit');
 		});
 
 		form.on('submit', function (e) {
 			$('.drag-overlay').addClass('hidden');
-			e.preventDefault();  
+			e.preventDefault();
 			var tpl = $('.upload-files li.hidden').get(0).outerHTML;
 			$('.upload-files li:not(.hidden)').remove();
-		
+
 			var fileProcessed = [];
 
 			object.toggle_preloader_upload();
 			for( var k in fileQueue){
 				var file = fileQueue[k].file;
-				
+
 				var line = $(Mustache.render(tpl,{
 					label : file.name,
 					sort : k,
@@ -841,7 +841,7 @@ var DocumentApi = function(element,options) {
 				line.removeClass('hidden');
 				$('.upload-files').append(line);
 
-				
+
 				var ajaxData = new FormData();
 
 				ajaxData.append(input.attr('name'), file);
@@ -868,7 +868,7 @@ var DocumentApi = function(element,options) {
 							$('.upload-files li[data-sort="'+response.sort+'"] .upload-file-state').addClass('success').html('<i class="far fa-check-circle"></i> Succès');
 						else
 							$('.upload-files li[data-sort="'+response.sort+'"] .upload-file-state').addClass('error').html('<i class="fas fa-exclamation-circle"></i> Erreur :'+response.error);
-						
+
 						fileProcessed.push(response);
 
 						$('.preloader-upload-container .upload-state span').text(fileProcessed.length+'/'+fileQueue.length+' fichiers envoyés');
@@ -894,9 +894,9 @@ var DocumentApi = function(element,options) {
 					xhr: function() {
 						var xhr = new window.XMLHttpRequest();
 						xhr.sort = k;
-						
+
 						xhr.upload.addEventListener("progress", function(evt){
-							
+
 							if (evt.lengthComputable) {
 							var percentComplete = (evt.loaded / evt.total) * 100;
 							percentComplete = Math.round(percentComplete * 100) / 100;
@@ -905,8 +905,8 @@ var DocumentApi = function(element,options) {
 								.css('width',percentComplete+'%')
 								.text(percentComplete+'%')
 								.attr('aria-valuenow',percentComplete);
-					
-					
+
+
 							}
 						}, false);
 						return xhr;
@@ -956,7 +956,7 @@ var DocumentApi = function(element,options) {
 
 	 	//adapte la largeur de l'input à  la largeur du texte avec un max de 320 px et un min de 45px
 	 	var width = Math.min(Math.max(text.width(),45),320);
-	 	
+
 		button.addClass('hidden');
 		text.addClass('hidden');
 
@@ -976,7 +976,7 @@ var DocumentApi = function(element,options) {
 	DocumentApi.prototype.remove_treeline = function(from){
 		var parent = $('.folder-focused ul');
 		if(parent.length == 0) parent = $('.tree-panel > ul');
-		$('li',parent).each(function(i,li){ 
+		$('li',parent).each(function(i,li){
 			var li = $(li);
 			if(li.attr('data-path') == from.attr('data-path')) {
 				li.remove();
@@ -1006,7 +1006,7 @@ var DocumentApi = function(element,options) {
 		console.log(object.selected);
 
 		$('.file-view:visible .file-element',object.dom.panels.files).removeClass('element-focused');
-			
+
 		for(var k in object.selected){
 			object.selected[k].element.addClass('element-focused');
 		}
@@ -1016,7 +1016,7 @@ var DocumentApi = function(element,options) {
 		if(object.selected.length==1){
 			$('.right-panel',object.dom.panels.detail).addClass('hidden');
 			$('.detail-buttons',object.dom.panels.detail).removeClass('hidden');
-			
+
 
 			if(object.selected.type =='directory') {
 				$('.detail-buttons > .directory-button',object.dom.panels.detail).removeClass('hidden');
@@ -1031,7 +1031,7 @@ var DocumentApi = function(element,options) {
 					var data = object.options.panels.detail.buttons[i];
 					if(data.visibility && data.visibility.type && data.visibility.type.indexOf(object.selected.type) == -1 ) continue;
 					if(data.visibility && data.visibility.extension && data.visibility.extension.indexOf(object.selected.extension) == -1 ) continue;
-					
+
 					var button = $(Mustache.render(buttonTemplate,data));
 					button.removeClass('hidden');
 					$('.detail-buttons').append(button);
@@ -1041,8 +1041,8 @@ var DocumentApi = function(element,options) {
 			//autoblur sur le rename d'un fichier en cours si existant
 			var currentRename = $('.file-view:visible .file-element .rename-input:visible');
 			if(currentRename.length>0) currentRename.trigger('blur');
-			
-	
+
+
 
 			$('.detail-thumbnail .thumbnail-preloader',object.dom.panels.detail).addClass('show');
 
@@ -1112,7 +1112,7 @@ var DocumentApi = function(element,options) {
 		var selected = object.selected[0];
 
 		if($('span .rename-input:visible',selected.element).length) return;
-		
+
 		$.action({
 			action : object.options.actions.element_share_edit,
 			path : selected.path,
@@ -1130,7 +1130,7 @@ var DocumentApi = function(element,options) {
 		$('.file-editor-input',object.dom.panels.file).removeClass('hidden');
 
 		$('.file-editor-input',object.dom.panels.file).val('');
-		
+
 		var saveShortcut = function(event){
 			if(event.ctrlKey && event.key == 's'){
 				object.element_edit_save(true);
@@ -1157,19 +1157,19 @@ var DocumentApi = function(element,options) {
 				$('.file-editor-input',object.dom.panels.file).unbind('keydown').keydown(saveShortcut);
 
 				if(r.wysiwyg){
-					
+
 					$('.file-editor-input').addClass('hidden');
 					var iframe = $('<iframe width="100%" height="100%" frameBorder="0">');
 
 
 					iframe.on('load',function(){
-						
+
 						object.dom.editor =  $('<div id="editor">').html($('.file-editor-input').val());
 
 						object.dom.editor.unbind('keydown').keydown(saveShortcut);
 
 						var contextIframe = $(this).contents()[0];
-				
+
 		                // Set the style on the head of the iframe.
 		                $('head', contextIframe).append('<link href="css/trumbowyg.min.css" rel="stylesheet"> \
 		                	<style>html,body{padding:0!important;margin:0!important;}.trumbowyg-box{margin-top: 0;}.trumbowyg-button-pane{position:fixed;margin-top: -1px;}.trumbowyg-box .trumbowyg-editor{margin-top:20px;border:0px;}.trumbowyg-box{border:0px;}.trumbowyg-dropdown{position:fixed!important;width:300px!important;}</style>');
@@ -1177,8 +1177,8 @@ var DocumentApi = function(element,options) {
 		                // Set the content to be editable.
 		                $('body', contextIframe).append(object.dom.editor);
 
-		               
-						
+
+
 		                object.dom.editor.trumbowyg(object.editorOptions);
 					});
 
@@ -1195,7 +1195,7 @@ var DocumentApi = function(element,options) {
 	DocumentApi.prototype.element_edit_save = function(dontCloseEditor){
 		var object = this;
 
-		
+
 		var content = $('.file-editor-input',object.dom.panels.file).val();
 
 		if($('.file-editor-content iframe').length > 0){
@@ -1257,7 +1257,7 @@ var DocumentApi = function(element,options) {
 			});
 			return;
 		}
-	
+
 		object.triggerEvent('executed',{
 				element : line,
 				path : line.attr('data-path')
@@ -1277,7 +1277,7 @@ var DocumentApi = function(element,options) {
 			break;
 		}
 
-		
+
 	}
 
 	// Téléchargement d'un élément de la GED
@@ -1285,7 +1285,7 @@ var DocumentApi = function(element,options) {
 		var object = this;
 		var line = line ? line : object.selected[0].element;
 		if(line.length == 0) return $.message('info', 'Sélectionnez d\'abord un élément à télécharger');
-			
+
 		object.triggerEvent('downloaded',{
 				element : line,
 				path : line.attr('data-path')
@@ -1300,15 +1300,15 @@ var DocumentApi = function(element,options) {
 	/** PROPERTIES **/
 
 	DocumentApi.prototype.properties_show = function(){
-		
+
 		var object = this;
 		var modal = $('.document-properties-modal');
 		var tpl = $('.modal-body-template',modal).html();
 		modal.modal('show');
 
 		$('.modal-body',modal).html('Chargement...');
-		
-		
+
+
 		$.action({
 			action : object.options.actions.properties_show,
 			id : object.selected[0].id
@@ -1333,7 +1333,7 @@ var DocumentApi = function(element,options) {
 	//Récuperation d'une liste de elementright dans le tableau elementrights
 	DocumentApi.prototype.right_search = function(callback){
 		var object = this;
-	
+
 		if(object.selected.length == 0) return;
 
 		$('.element-rights').fill({
@@ -1347,7 +1347,7 @@ var DocumentApi = function(element,options) {
 	//Ajout ou modification d'élément elementright
 	DocumentApi.prototype.right_save = function(){
 		var object = this;
-	
+
 		var data = {
 			uid : $('.element-right-form input.uid').val(),
 			read : $('.element-right-form input.read').prop('checked') ? 1 :0,
@@ -1406,10 +1406,10 @@ var DocumentApi = function(element,options) {
 	DocumentApi.prototype.addView = function(data){
 		var object = this;
 		data.html = $(data.html);
-		
+
 		data.html.attr('data-view',data.uid);
 		if(!data.html.hasClass('file-view')) data.html.addClass('file-view');
-		
+
 		object.views.push(data);
 	}
 
@@ -1446,7 +1446,7 @@ var DocumentApi = function(element,options) {
 				object.view($(this).attr('data-view'));
 			});
 
-			
+
 			if($('.file-view[data-view="'+view.uid+'"]',object.dom.panels.files).length==0)
 		 		object.dom.panels.files.append(view.html);
 

+ 5 - 5
plugin/document/js/main.js

@@ -7,10 +7,10 @@ function init_plugin_document(){
 	}
 
 	var urlOptions = $.urlParam('data');
-	
+
 	if(urlOptions && urlOptions!='')
 		urlOptions = JSON.parse(atob(urlOptions));
-	
+
 	var doc = new DocumentApi('#document-container',urlOptions);
 
 	var data = $('#document-container').data();
@@ -25,9 +25,9 @@ function init_plugin_document(){
 /** SETTINGS */
 //Enregistrement des configurations
 function document_setting_save(){
-	$.action({ 
-		action : 'document_setting_save', 
-		fields :  $('#document-setting-form').toJson() 
+	$.action({
+		action : 'document_setting_save',
+		fields :  $('#document-setting-form').toJson()
 	}, function(r){
 		$.message('success','Enregistré');
 	});

+ 1 - 1
plugin/document/js/widget.js

@@ -6,7 +6,7 @@ function widget_document_init(){
 function document_widget_configure_save(widget,modal){
 
 	var data = $('#document-widget-form').toJson();
-	
+
 	data.action = 'document_widget_configure_save';
 	data.id = modal.attr('data-widget');
 

+ 1 - 1
plugin/document/new.action.php

@@ -1,4 +1,4 @@
 <?php
-/** ELEMENT **/	
+/** ELEMENT **/
 
 ?>

+ 1 - 1
plugin/document/setting.document.php

@@ -1,4 +1,4 @@
-<?php 
+<?php
 global $myUser,$conf;
 User::check_access('document','configure');
 ?>

+ 6 - 6
plugin/document/tab.client.php

@@ -6,7 +6,7 @@ require_once(__DIR__.SLASH.'Element.class.php');
 $client = Client::getById($_['id']);
 
 
-$relativeDirectory = empty($conf->get('document_client_directory')) ? 'Clients'.SLASH.'{{slug}}' : $conf->get('document_client_directory'); 
+$relativeDirectory = empty($conf->get('document_client_directory')) ? 'Clients'.SLASH.'{{slug}}' : $conf->get('document_client_directory');
 $relativeDirectory = str_replace('{{slug}}',$client->slug,$relativeDirectory);
 
 $clientDirectory = Element::root().$relativeDirectory;
@@ -18,11 +18,11 @@ $element->save();
 ?>
 
 <div class="p-2">
-	<div style="background-color: #ffffff;"  data-type="library" 
+	<div style="background-color: #ffffff;"  data-type="library"
 	data-root-label="C:"
-	data-root="<?php echo $relativeDirectory;?>"  
-	data-tree-panel="false"  
-	data-search-panel="true"  
-	data-detail-panel="true" 
+	data-root="<?php echo $relativeDirectory;?>"
+	data-tree-panel="false"
+	data-search-panel="true"
+	data-detail-panel="true"
 	></div>
 </div>

Daži faili netika attēloti, jo izmaiņu fails ir pārāk liels