FieldType.class.php 45 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486
  1. <?php
  2. /**
  3. * Type de champs possibles dans l'application
  4. * @author valentin carruesco
  5. * @category Core
  6. * @license MIT
  7. */
  8. class FieldType{
  9. public $label,$slug,$sqlType,$description,$icon,$default,$input;
  10. public function toArray(){
  11. return json_decode(json_encode($this), true);
  12. }
  13. public function __toString() {
  14. return json_encode($this->toArray());
  15. }
  16. //traduit une valeur en champ/label/légende HTML en fonction de son type
  17. public static function toHtml($field,$types=null,$options = array('allowCustomLabel'=>true)){
  18. if(!isset($types)) $types = self::available();
  19. if(!isset($field['id'])) $field['id'] = '';
  20. $type = isset($field['type']) && isset($types[$field['type']]) ? $types[$field['type']] : $types['text'];
  21. $label = '';
  22. if(!empty($field['label'])){
  23. $label = '<label class="mb-0"';
  24. if(!empty($field['id'])) $label .= 'for="'.$field['id'].'"';
  25. $label .= '>'.$field['label'].'</label>';
  26. }
  27. if(!isset($field['attributes'])) $field['attributes'] = array();
  28. $field['attributes'] = array_merge($type->default_attributes,$field['attributes']);
  29. if(empty($field['value']) && !empty($field['default'])) $field['value'] = $field['default'];
  30. if(!empty($field['placeholder'])) $field['attributes']['placeholder'] = $field['placeholder'];
  31. if(!empty($field['required'])) $field['attributes']['required'] = $field['required'];
  32. $func = $type->onInput;
  33. $inputOptions = array_merge(array('type'=>$type,'label'=>$label), $options);
  34. $input = $func($field,$inputOptions);
  35. return array(
  36. 'label' => isset($type->customLabel) && $type->customLabel && $options['allowCustomLabel'] ? '' : $label,
  37. 'legend' => isset($field['legend']) ? $field['legend'] : '',
  38. 'input' => $input,
  39. 'data' => $field
  40. );
  41. }
  42. public static function toForm($fields,$types=null){
  43. $htmlFields = array();
  44. if(!isset($types)) $types = self::available();
  45. uasort ($fields,function($a,$b){
  46. if(!isset($a['sort'])) $a['sort'] = 100;
  47. if(!isset($b['sort'])) $b['sort'] = 100;
  48. return $a['sort'] - $b['sort'];
  49. });
  50. foreach ($fields as $key => $field) {
  51. if(!isset($field['id'])) $field['id'] = $key;
  52. $htmlFields[] = self::toHtml($field,$types);
  53. }
  54. return $htmlFields;
  55. }
  56. //liste des types de champs disponibles
  57. public static function available($key=null){
  58. $types = array();
  59. //Texte
  60. $type_text = new self();
  61. $type_text->slug = 'text';
  62. $type_text->label = 'Texte';
  63. $type_text->sqlType = 'string';
  64. $type_text->label = 'Texte';
  65. $type_text->icon = 'fas fa-font';
  66. $type_text->description = 'Texte court mono ligne';
  67. $type_text->default = '';
  68. $type_text->default_attributes = array(
  69. 'class'=>'"form-control"',
  70. 'type'=>'"text"'
  71. );
  72. $type_text->filter = array(
  73. 'operators' => array(
  74. 'like' =>array("view" =>'text'),
  75. 'not like' =>array("view" =>'text'),
  76. '=' =>array("view" =>'text'),
  77. '!=' =>array("view" =>'text'),
  78. 'null' =>array(),
  79. 'not null' =>array()
  80. )
  81. );
  82. /* Exemples d'utilisation des méthodes de convertion de types
  83. Type | BDD | onLoad | onRawDisplay | onHtmlDisplay | onInput | fromRawDisplay
  84. ====================================================================================================================================================================
  85. Date | 12345 | d/m/y | d/m/y | d/m/y | <input data-type="date" ... value="{{onLoad}}"> | 12345
  86. User | theo.lecoq | theo.lecoq | Théo Lecoq | Théo Lecoq | <input data-type="user" ... value="{{onLoad}}"> | theo.lecoq
  87. Dictionary | 6 | 6 | Véhicules > bateau | Véhicules > bateau | <input data-type="dictionary" ... value="{{onLoad}}"> | 6
  88. password | ==x$yh.. | toto | toto | toto | <input data-type="password" ... value="{{onLoad}}"> | ==x$yh..
  89. url | http://... | http://... | http://... | <a href="http://..."></a> | <input data-type="url" ... value="{{onLoad}}"> | http://..
  90. onLoad : Utilisé pour converti une valeur de la base en une valeur comprehensible par l'erp et
  91. ses composants (pas forcement human readable)
  92. onRawDisplay : Valeur human readable brute sans mise en forme ou html, utilisé par exemple dans les export text/ excel
  93. fromRawDisplay : utilisé pour convertir la valeur affichée brute en valeur technique BDD (inverse de onRawDisplay) utilisé apr exemple pour les import depuis excel
  94. onHtmlDisplay : Valeur human readable avec mise en forme ou html, utilisé pour affichage sur les pages, un parametre decoration peut être mise a true pour avoir des décoration contextuelles (ex : une icone de calendrier devant la date)
  95. onInput : utilisé pour afficher l'input approprié, cette méthode doit s'appuyer sur le onLoad
  96. onSave : utilisé pour une transformation de la valeur avant enregistrement en base
  97. */
  98. $type_text->onLoad = function($value,$options = array()){
  99. return $value;
  100. };
  101. $type_text->onRawDisplay = function($value,$options = array()){
  102. return $value;
  103. };
  104. $type_text->onHtmlDisplay = function($value,$options = array()){
  105. $raw = $options['type']->onRawDisplay;
  106. $html = $raw($value,$options);
  107. return $html;
  108. };
  109. $type_text->onInput = function($field=array(),$options=array()){
  110. $attributes = array_merge($options['type']->default_attributes,$field['attributes']);
  111. if(isset($field['id'])) $field['attributes']['id'] ='"'.$field['id'].'"';
  112. $html = '';
  113. $html.= '<input value="'.(isset($field['value']) ? str_replace('"','&quot;',$field['value']) : '').'"';
  114. foreach ($field['attributes'] as $key => $value) {
  115. $html.= ' ';
  116. $html.= $key;
  117. if(!empty($value) && is_string($value)) $html.= '='.$value;
  118. $html.= ' ';
  119. }
  120. $html.= '>';
  121. return $html;
  122. };
  123. $types[$type_text->slug] = $type_text;
  124. //File
  125. $type_file = new self();
  126. $type_file->slug = 'file';
  127. $type_file->label = 'Fichier';
  128. $type_file->sqlType = '';
  129. $type_file->default_attributes = array_merge($type_text->default_attributes,array(
  130. 'class'=>'"component-file-default bg-white shadow-sm rounded-sm"',
  131. 'data-type'=>'"file"',
  132. 'data-extension'=>'"jpg,png,bmp,jpeg,gif,svg,webp,docx,xlsx,pptx,msg,eml,pdf,zip,doc,xls,ppt,txt,csv,mp3,wav,mp4,avi,flv"',
  133. 'data-action'=>'{{action}}',
  134. 'data-id'=>'"'.uniqid(rand(0,100)).'"',
  135. 'data-data'=> "'{}'",
  136. ));
  137. $type_file->settings = array(
  138. 'action'=>array('type'=>'text','default'=>"dynamicform_handle_file",'attributes'=> array('class'=>'"form-control hidden"','disabled'=>true)),
  139. 'extension'=> array('type'=>'text','label'=>'Extensions permises','placeholder'=>'"Séparation par \',\'"','attributes'=> array('class'=>'"form-control"')),
  140. 'size'=> array('type'=>'integer','label'=>'Taille max (octets)','attributes'=> array('class'=>'"form-control"')),
  141. 'limit'=> array('type'=>'integer','label'=>'Nombre max de fichiers','attributes'=> array('class'=>'"form-control"')),
  142. 'storage'=> array('type'=>'filepicker','label'=>'Dossier d\'enregistrement','attributes'=> array('class'=>'"form-control"','data-editable'=>true)),
  143. 'access'=> array(
  144. 'type'=>'list',
  145. 'label'=>'Contrôle des droits et accès à faire sur la section',
  146. 'values'=>function(){
  147. $scopes = array();
  148. foreach(Right::availables() as $slug=>$scope)
  149. $scopes[$slug] = $scope['label'];
  150. return $scopes;
  151. },
  152. 'attributes'=> array('class'=>'"form-control"')
  153. ),
  154. /*'label'=> array('type'=>'text','label'=>'Libellé visible dans la dropzone du composant','placeholder'=>'"Faites glisser vos fichiers ici"','attributes'=> array('class'=>'"form-control"')),
  155. 'readonly'=> array('type'=>'boolean','label'=>'Lecture seule','attributes'=> array('class'=>'"form-control"')),*/
  156. );
  157. $type_file->onInput = function($field=array(),$options=array()){
  158. $attributes = array_merge($options['type']->default_attributes,$field['attributes']);
  159. if(isset($field['id'])) $field['attributes']['id'] ='"'.$field['id'].'"';
  160. //gestion des scopes, uid et slug si dynamics
  161. $data = array();
  162. //id entité si présente
  163. $data['id'] = isset($field['options']['uid']) ? $field['options']['uid'] : '';
  164. //id scope de l'entité si présente
  165. $data['scope'] = isset($field['options']['scope']) ? $field['options']['scope'] : '';
  166. //slug du composant
  167. $data['slug'] = isset($field['slug']) ? $field['slug'] : '';
  168. //Gestion des data-data depuis le champ (ex: type image en settings globaux)
  169. if(!empty($field['attributes']) && !empty($field['attributes']['data-data'])){
  170. $fieldData = json_decode($field['attributes']['data-data'], true);
  171. $data = !empty($fieldData) ? json_encode(array_merge($data, $fieldData)) : json_encode($data);
  172. }
  173. $field['attributes']['data-data'] = $data;
  174. $html = '';
  175. $html.= '<input ';
  176. foreach ($field['attributes'] as $key => $value) {
  177. $html.= ' ';
  178. $html.= $key;
  179. if(!empty($value)) $html.= '='.$value;
  180. $html.= ' ';
  181. }
  182. $html.= '>';
  183. return $html;
  184. };
  185. $type_file->onSave = function($value,$options=array()){
  186. $path = $options['options']['scope'].SLASH.$options['options']['uid'];
  187. $limit = 1;
  188. if(!empty($options['field']->meta)){
  189. $meta = json_decode($options['field']->meta,true);
  190. if(!empty($meta['limit']) && $meta['limit']>1) $limit =$meta['limit'] ;
  191. if(!empty($meta['storage'])) $path = template($meta['storage'],$options['options'],true);
  192. }
  193. File::save_component($options['field']->slug,$path.($limit==1?'':SLASH.$options['field']->slug).SLASH.'{{label}}');
  194. return null;
  195. };
  196. $type_file->onRawDisplay = function($value,$options = array()){
  197. $value = '';
  198. $meta = json_decode($options['meta'],true);
  199. $templateData = array();
  200. foreach($options as $key=>$option){
  201. if(!is_string($option)) continue;
  202. $templateData[$key] = $option;
  203. }
  204. $path = File::dir().template($meta['storage'],$templateData,true).'/*';
  205. foreach (glob($path) as $file) {
  206. $filePath = str_replace(File::dir(),'',$file);
  207. $value .= PHP_EOL.basename($file).' ('.ROOT_URL.'action.php?action='.$meta['action'].'&type=download&path='.base64_encode($filePath).')';
  208. }
  209. return $value;
  210. };
  211. $type_file->onHtmlDisplay = function($value,$options = array()){
  212. $html = '';
  213. $meta = json_decode($options['meta'],true);
  214. $templateData = array();
  215. foreach($options as $key=>$option){
  216. if(!is_string($option)) continue;
  217. $templateData[$key] = $option;
  218. }
  219. $path = File::dir().template($meta['storage'],$templateData,true).'/*';
  220. $html .= '<ul class="list-group list-group-flush shadow-sm">';
  221. foreach (glob($path) as $file) {
  222. $filePath = str_replace(File::dir(),'',$file);
  223. $html .= '<li class="list-group-item p-1"><a href="';
  224. $html .= 'action.php?action='.$meta['action'].'&type=download&path='.base64_encode($filePath);
  225. $html.= '">'.basename($file).'<a></li>';
  226. }
  227. $html.='</ul>';
  228. return $html;
  229. };
  230. $type_file->icon = 'fas fa-file-upload';
  231. $type_file->description = 'Envoi de fichier';
  232. $type_file->default = '';
  233. $types[$type_file->slug] = $type_file;
  234. //Image
  235. $type = new self();
  236. $type->slug = 'image';
  237. $type->label = 'Image';
  238. $type->sqlType = '';
  239. $type->default_attributes = array_merge($type_text->default_attributes,array(
  240. 'class'=>'"component-file-cover bg-white shadow-sm rounded-sm"',
  241. 'data-type'=>'"file"',
  242. 'data-limit'=>'"1"',
  243. 'data-extension'=>'"jpg,png,bmp,jpeg,gif,svg,webp"',
  244. 'data-action'=>'{{action}}',
  245. 'data-id'=>'"'.uniqid(rand(0,100)).'"',
  246. 'data-data'=> "'{}'" ,
  247. ));
  248. $type->settings = array(
  249. 'action'=>array('type'=>'text','default'=>"dynamicform_handle_file",'attributes'=> array('class'=>'"form-control hidden"','disabled'=>true)),
  250. 'extension'=> array('type'=>'text','label'=>'Extensions permises','placeholder'=>'"Séparation par \',\'"','attributes'=> array('class'=>'"form-control"')),
  251. 'size'=> array('type'=>'integer','label'=>'Taille max (octets)','attributes'=> array('class'=>'"form-control"')),
  252. 'storage'=> array('type'=>'filepicker','label'=>'Dossier d\'enregistrement','attributes'=> array('class'=>'"form-control"','data-editable'=>true)),
  253. 'access'=> array(
  254. 'type'=>'list',
  255. 'label'=>'Contrôle des droits et accès à faire sur la section',
  256. 'values'=>function(){
  257. $scopes = array();
  258. foreach(Right::availables() as $slug=>$scope)
  259. $scopes[$slug] = $scope['label'];
  260. return $scopes;
  261. },
  262. 'attributes'=> array('class'=>'"form-control"')
  263. ),
  264. /*'label'=> array('type'=>'text','label'=>'Libellé visible dans la dropzone du composant','placeholder'=>'"Faites glisser vos fichiers ici"','attributes'=> array('class'=>'"form-control"')),
  265. 'readonly'=> array('type'=>'boolean','label'=>'Lecture seule','attributes'=> array('class'=>'"form-control"')),*/
  266. );
  267. $type->onInput = $type_file->onInput;
  268. $type->onSave = $type_file->onSave;
  269. $type->onHtmlDisplay = function($value,$options = array()){
  270. $html = '<div class="fieldtype-image-cover">';
  271. $meta = json_decode($options['meta'],true);
  272. $templateData = array();
  273. foreach($options as $key=>$option){
  274. if(!is_string($option)) continue;
  275. $templateData[$key] = $option;
  276. }
  277. $path = File::dir().template($meta['storage'],$templateData,true).'/*';
  278. $files = glob($path);
  279. $file = $files[0];
  280. $filePath = str_replace(File::dir(),'',$file);
  281. $action = 'action.php?action='.$meta['action'].'&type=download&path='.base64_encode($filePath);
  282. $html .= '<img class="shadow-sm rounded-sm" style="max-width: 100px;height: auto;" src="'.$action.'">';
  283. if(count($files)>1) $html .= '<span><i class="far fa-file-image"></i> +'.count($files).' </span>';
  284. $html .= '</div>';
  285. return $html;
  286. };
  287. $type->onRawDisplay = $type_file->onRawDisplay;
  288. $type->icon = 'far fa-image';
  289. $type->description = "Envoi d'image";
  290. $type->default = '';
  291. $types[$type->slug] = $type;
  292. //User
  293. $type = new self();
  294. $type->slug = 'user';
  295. $type->label = 'Utilisateur';
  296. $type->sqlType = 'string';
  297. $type->default_attributes = array_merge($type_text->default_attributes,array(
  298. 'data-type'=>'"user"',
  299. ));
  300. $type->filter = array(
  301. 'operators' => array(
  302. '=' =>array("view" =>'user'),
  303. '!=' =>array("view" =>'user'),
  304. 'like' =>array("view" =>'user'),
  305. 'not like' =>array("view" =>'user'),
  306. 'null' =>array(),
  307. 'not null' =>array()
  308. )
  309. );
  310. $type->onInput = $type_text->onInput;
  311. $type->onRawDisplay = function($value,$options = array()){
  312. if(empty($value)) return '';
  313. $user = User::byLogin($value);
  314. return !$user? '':$user->fullName();
  315. };
  316. $type->onHtmlDisplay = function($value,$options = array()){
  317. $raw = $options['type']->onRawDisplay;
  318. $html = $raw($value,$options);
  319. if(isset($options['decoration']) && $options['decoration']) $html = '<img src="action.php?action=core_account_avatar_download&amp;user='.$value.'&amp;extension=jpg" class="avatar-mini avatar-rounded avatar-login" title="'.$html.'"> '.$html;
  320. return $html;
  321. };
  322. $type->icon = 'fas fa-user';
  323. $type->description = 'Autocompletion sur les comptes utilisateurs';
  324. $type->default = '';
  325. $types[$type->slug] = $type;
  326. //Firm
  327. $type = new self();
  328. $type->slug = 'firm';
  329. $type->label = 'Etablissement';
  330. $type->sqlType = 'string';
  331. $type->default_attributes = array_merge($type_text->default_attributes,array(
  332. 'data-type'=>'"firm"',
  333. ));
  334. $type->onInput = $type_text->onInput;
  335. $type->icon = 'fas fa-building';
  336. $type->description = 'Autocompletion sur les établissements';
  337. $type->default = '';
  338. $type->onRawDisplay = function($value,$options = array()){
  339. if(empty($value) || !is_numeric($value)) return '';
  340. $firm = Firm::getById($value);
  341. return !$firm? '':$firm->label;
  342. };
  343. $type->filter = array(
  344. 'operators' => array(
  345. '=' =>array("view" =>'firm'),
  346. '!=' =>array("view" =>'firm'),
  347. 'null' =>array(),
  348. 'not null' =>array()
  349. )
  350. );
  351. $types[$type->slug] = $type;
  352. //Rank
  353. $type = new self();
  354. $type->slug = 'rank';
  355. $type->label = 'Rang';
  356. $type->sqlType = 'int';
  357. $type->default_attributes = array_merge($type_text->default_attributes,array(
  358. 'data-type'=>'"user"',
  359. 'data-types'=>'"rank"',
  360. ));
  361. $type->onInput = $type_text->onInput;
  362. $type->icon = 'fas fa-user-lock';
  363. $type->description = 'Autocompletion sur les rangs';
  364. $type->default = '';
  365. $type->onRawDisplay = function($value,$options = array()){
  366. if(empty($value) || !is_numeric($value)) return '';
  367. $rank = Rank::getById($value);
  368. return !$rank? '':$rank->label;
  369. };
  370. $type->filter = array(
  371. 'operators' => array(
  372. '=' =>array("view" =>'rank'),
  373. '!=' =>array("view" =>'rank'),
  374. 'null' =>array(),
  375. 'not null' =>array()
  376. )
  377. );
  378. $types[$type->slug] = $type;
  379. //Textarea
  380. $type_longstring = new self();
  381. $type_longstring->slug = 'textarea';
  382. $type_longstring->label = 'Texte Long';
  383. $type_longstring->sqlType = 'longstring';
  384. $type_longstring->default_attributes = $type_text->default_attributes;
  385. $type_longstring->onInput = function($field=array(),$options=array()){
  386. $html = '';
  387. $html .= '<textarea ';
  388. if(isset($field['id'])) $field['attributes']['id'] ='"'.$field['id'].'"';
  389. foreach ($field['attributes'] as $key=>$attribute) {
  390. if( $key=='value' ) continue;
  391. $html .= ' '.$key;
  392. if(!empty($attribute))
  393. $html .= '='.$attribute;
  394. }
  395. if(isset($field['value']) && is_array($field['value']))
  396. $field['value'] = json_encode($field['value']);
  397. $html .='>'.(isset($field['value']) && !empty($field['value']) ? (is_callable($field['value']) ? $field['value']() : $field['value']) : '').'</textarea>';
  398. return $html ;
  399. };
  400. $type_longstring->filter = array(
  401. 'operators' => array(
  402. 'like' =>array("view" =>'text'),
  403. 'not like' =>array("view" =>'text'),
  404. '=' =>array("view" =>'text'),
  405. '!=' =>array("view" =>'text'),
  406. 'null' =>array(),
  407. 'not null' =>array()
  408. )
  409. );
  410. $type_longstring->icon = 'fas fa-text-width';
  411. $type_longstring->description = 'Texte long multi ligne';
  412. $type_longstring->default = '';
  413. $types[$type_longstring->slug] = $type_longstring;
  414. //Wysiwyg
  415. $type = new self();
  416. $type->slug = 'wysiwyg';
  417. $type->label = 'Texte enrichi';
  418. $type->sqlType = 'longstring';
  419. $type->default_attributes = array_merge($type_longstring->default_attributes,array(
  420. 'data-type'=>'"wysiwyg"',
  421. 'class'=>'""',
  422. ));
  423. $type->onInput = $type_longstring->onInput;
  424. $type->onRawDisplay = function($value,$options = array()){
  425. if(empty($value)) return '';
  426. return strip_tags($value);
  427. };
  428. $type->onHtmlDisplay = function($value,$options = array()){
  429. $html = html_entity_decode($value);
  430. return $html;
  431. };
  432. $type->filter = $type_longstring->filter;
  433. $type->icon = 'fas fa-spell-check';
  434. $type->description = 'Texte riche multi ligne';
  435. $type->default = '';
  436. $types[$type->slug] = $type;
  437. //Date
  438. $type = new self();
  439. $type->slug = 'date';
  440. $type->label = 'Date';
  441. $type->sqlType = 'date';
  442. $type->default_attributes = array_merge($type_text->default_attributes,array(
  443. 'data-type'=>'"date"',
  444. 'title'=>'"format jj/mm/aaaa"',
  445. 'placeholder'=>'"JJ/MM/AAAA"',
  446. ));
  447. $type->onLoad = function($value){
  448. return !is_null($value) || is_numeric($value) ? date('d/m/Y',$value) : '';
  449. };
  450. $type->onSave = function($value,$options=array()){
  451. return !empty($value) ? timestamp_date($value) : null;
  452. };
  453. $type->onRawDisplay = function($value,$options = array()){
  454. $html = !is_null($value) && is_numeric($value) ? date('d/m/Y',$value) : '';
  455. return $html;
  456. };
  457. $type->fromRawDisplay = function($value,$options = array()){
  458. return timestamp_date($value);
  459. };
  460. $type->filter = array(
  461. 'operators' => array(
  462. 'between' =>array("view" =>'date'),
  463. '=' =>array("view" =>'date'),
  464. '!=' =>array("view" =>'date'),
  465. 'null' =>array(),
  466. 'not null' =>array()
  467. )
  468. );
  469. $type->onInput = $type_text->onInput;
  470. $type->icon = 'far fa-calendar';
  471. $type->description = 'Date au format jj/mm/aaaa';
  472. $type->default = '';
  473. $types[$type->slug] = $type;
  474. //Tags
  475. $type = new self();
  476. $type->slug = 'tag';
  477. $type->label = 'Etiquettes';
  478. $type->sqlType = 'string';
  479. $type->default_attributes = array_merge($type_text->default_attributes,array(
  480. 'data-type'=>'"tag"',
  481. 'data-multiple'=>'true'
  482. ));
  483. $type->onInput = $type_text->onInput;
  484. $type->icon = 'fas fa-tags';
  485. $type->description = 'Etiquettes (tags) séparés par virgules, espace ou tabulation';
  486. $type->default = '';
  487. $type->onHtmlDisplay = function($value,$options = array()){
  488. $html = '';
  489. $tags = explode(',',$value);
  490. $html = '<span class="badge">'.implode('</span><span class="badge">',$tags).'</span>';
  491. return $html;
  492. };
  493. $type->filter = array(
  494. 'operators' => array(
  495. 'in' =>array("view" =>'tag'),
  496. 'not in' =>array("view" =>'tag'),
  497. 'inline-and' =>array("view" =>'tag'),
  498. 'inline-or' =>array("view" =>'tag'),
  499. 'null' =>array(),
  500. 'not null' =>array()
  501. )
  502. );
  503. $type->onSave = function($value,$options=array()){
  504. $value = explode(',',$value);
  505. $value = array_filter($value);
  506. $value = ','.implode(',',$value).',';
  507. if($value==',,') $value = '';
  508. return $value;
  509. };
  510. $types[$type->slug] = $type;
  511. //File picker
  512. $type = new self();
  513. $type->slug = 'filepicker';
  514. $type->label = 'Parcourir';
  515. $type->sqlType = 'longstring';
  516. $type->default_attributes = array_merge($type_text->default_attributes,array(
  517. 'data-type'=>'"filepicker"',
  518. ));
  519. $type->onInput = $type_text->onInput;
  520. $type->icon = 'far fa-folder-open';
  521. $type->description = 'Rechercher dans un dossier';
  522. $type->default = '';
  523. $type->settings = array(
  524. 'root'=> array(
  525. 'type'=>'filepicker',
  526. 'label'=>'Racine ciblée',
  527. 'attributes'=> array('class'=>'"form-control"', 'data-root'=>"")
  528. )
  529. );
  530. $type->filter = array(
  531. 'operators' => array(
  532. '=' =>array("view" =>'filepicker'),
  533. '!=' =>array("view" =>'filepicker'),
  534. 'null' =>array(),
  535. 'not null' =>array()
  536. )
  537. );
  538. $types[$type->slug] = $type;
  539. //Heure
  540. $type = new self();
  541. $type->slug = 'hour';
  542. $type->label = 'Heure';
  543. $type->sqlType = 'string';
  544. $type->default_attributes = array_merge($type_text->default_attributes,array(
  545. 'data-type'=>'"hour"',
  546. 'title'=>'"format hh:mm"',
  547. 'placeholder'=>'"13:37"',
  548. ));
  549. $type->onInput = $type_text->onInput;
  550. $type->icon = 'far fa-clock';
  551. $type->description = 'Combo Heures/minutes';
  552. $type->default = '';
  553. $type->filter = array(
  554. 'operators' => array(
  555. '<' =>array("view" =>'hour'),
  556. '>' =>array("view" =>'hour'),
  557. '=' =>array("view" =>'hour'),
  558. 'null' =>array(),
  559. 'not null' =>array()
  560. )
  561. );
  562. $types[$type->slug] = $type;
  563. //Dictionnaire
  564. $type_dictionary = new self();
  565. $type_dictionary->slug = 'dictionary';
  566. $type_dictionary->label = 'Liste configurable';
  567. $type_dictionary->sqlType = 'int';
  568. $type_dictionary->default_attributes = array_merge($type_text->default_attributes,array(
  569. 'data-type'=>'"dictionary"',
  570. 'data-slug'=>'"{{key}}"',
  571. 'data-depth'=>'"1"',
  572. 'key'=>'data-disable-label',
  573. 'data-value'=>'',
  574. 'class'=>'"form-control select-control"'
  575. ));
  576. $type_dictionary->settings = array(
  577. 'slug'=> array(
  578. 'type'=>'dictionary',
  579. 'label'=>'Liste ciblée',
  580. 'attributes'=> array(
  581. 'class'=>'"form-control"',
  582. 'data-slug'=>"",
  583. 'data-output'=>"slug"
  584. )
  585. )
  586. );
  587. $type_dictionary->onRawDisplay = function($value,$options = array()){
  588. if(empty($value) || !is_numeric($value)) return '';
  589. $dictionary = Dictionary::getById($value);
  590. return !$dictionary? '':$dictionary->label;
  591. };
  592. $type_dictionary->fromRawDisplay = function($value,$options = array()){
  593. $filters = array('label'=>$value);
  594. if(isset($options['parent'])) $filters['parent'] = $options['parent'];
  595. $dictionary = Dictionary::load($filters);
  596. return !$dictionary ? 0 : $dictionary->id;
  597. };
  598. $type_dictionary->onInput = function($field = array(),$options = array()){
  599. if(isset($field['id'])) $field['attributes']['id'] ='"'.$field['id'].'"';
  600. if(isset($field['value'])) $field['attributes']['data-value'] = $field['value'];
  601. //gestion des metas de dynamiques fields pour listes simples
  602. if(isset($field['attributes']['data-values'])){
  603. $field['values'] = $field['attributes']['data-values'];
  604. unset($field['attributes']['data-values']);
  605. }
  606. $html = '';
  607. $html .= '<select ';
  608. foreach ($field['attributes'] as $key=>$attribute) {
  609. $html .= $key;
  610. if(!empty($attribute))
  611. $html .= '='.$attribute;
  612. $html .= ' ';
  613. }
  614. $html .='>';
  615. if(isset($field['values'])){
  616. $values = is_callable($field['values']) ? $field['values']() : $field['values'];
  617. if(!empty($values) && is_array($values)){
  618. foreach($values as $key=>$value){
  619. $html .='<option '.(isset($field['value']) && $field['value']==$key?' selected="selected" ':'').' value="'.$key.'">'.$value.'</option>';
  620. }
  621. }
  622. }
  623. $html .='</select>';
  624. return $html ;
  625. };
  626. $type_dictionary->icon = 'fas fa-list-ol';
  627. $type_dictionary->description = 'Liste de sélection configurable récursive';
  628. $type_dictionary->default = '';
  629. $type_dictionary->filter = array(
  630. 'attributes' => array(
  631. 'data-display'=>'"dropdown"',
  632. 'data-slug'=>'"{{slug}}"',
  633. 'data-depth'=>'"{{depth}}"',
  634. 'data-value-selector'=>'".filter-value:last-child"'
  635. ),
  636. 'operators' => array(
  637. 'in' =>array(
  638. "view" => "checkbox-list",
  639. "value-separator" => ","
  640. ),
  641. 'not in' =>array(
  642. "view" => "checkbox-list",
  643. "value-separator" => ","
  644. ),
  645. '=' =>array("view" =>'dictionary'),
  646. '!=' =>array("view" =>'dictionary'),
  647. 'null' =>array(),
  648. 'not null' =>array()
  649. )
  650. );
  651. $types[$type_dictionary->slug] = $type_dictionary;
  652. //Table JSON clé / valeur
  653. $type = new self();
  654. $type->slug = 'jsontable';
  655. $type->label = 'Table clé/valeur';
  656. $type->sqlType = 'longstring';
  657. $type->default_attributes = array(
  658. 'type'=>'"text"',
  659. 'data-type'=>'"jsontable"',
  660. 'data-format'=>'"key-value"',
  661. );
  662. $type->onInput = $type_text->onInput;
  663. $type->icon = 'fas fa-table';
  664. $type->description = 'Table clé/valeur enregistré en JSON';
  665. $type->default = '';
  666. $type->onRawDisplay = function($value){
  667. $stream = '';
  668. $table = json_decode($value,true);
  669. if(!is_array($table)) return '';
  670. foreach($table as $key=>$value){
  671. $stream .= ''.$key.' : '.$value.',';
  672. }
  673. return $stream;
  674. };
  675. $type->onHtmlDisplay = function($value){
  676. $html = '<ul class="list-group">';
  677. $table = json_decode($value,true);
  678. if(!is_array($table)) return '';
  679. foreach($table as $key=>$value){
  680. $html .= '<li class="list-group-item p-1"><strong>'.$key.'</strong> : '.$value.'</li>';
  681. }
  682. $html .= '</ul>';
  683. return $html;
  684. };
  685. $types[$type->slug] = $type;
  686. //Liste
  687. $type_list = new self();
  688. $type_list->slug = 'list';
  689. $type_list->label = 'Liste classique';
  690. $type_list->sqlType = 'string';
  691. $type_list->default_attributes = array_merge($type_text->default_attributes,array(
  692. 'class'=>'"form-control select-control"'
  693. ));
  694. $type_list->filter = array(
  695. 'attributes' => array(
  696. 'data-values'=>'"{{filterTypeValue}}"',
  697. ),
  698. 'operators' => array(
  699. 'in' =>array(
  700. "view" => "checkbox-list",
  701. "value-separator" => ",",
  702. ),
  703. 'not in' =>array(
  704. "view" => "checkbox-list",
  705. "value-separator" => ",",
  706. ),
  707. 'inline-and' =>array(
  708. "view" => "checkbox-list",
  709. "value-separator" => ",",
  710. ),
  711. 'inline-or' =>array(
  712. "view" => "checkbox-list",
  713. "value-separator" => ",",
  714. ),
  715. '=' =>array("view" =>'list'),
  716. '!=' =>array("view" =>'list'),
  717. 'null' =>array(),
  718. 'not null' =>array()
  719. )
  720. );
  721. $type_list->onInput = $type_dictionary->onInput;
  722. $type_list->onRawDisplay = function($value,$options = array()){
  723. if(!isset($options['meta'])) return '';
  724. $list = json_decode($options['meta'],true);
  725. return isset($list['values']) && isset($list['values'][$value]) ? $list['values'][$value] : '';
  726. };
  727. $type_list->icon = 'fas fa-list-ol';
  728. $type_list->description = 'Liste de sélection classique';
  729. $type_list->default = '';
  730. $type_list->settings = array(
  731. 'values'=> array(
  732. 'type'=>'jsontable',
  733. 'label'=>'Valeurs possibles',
  734. 'attributes'=> array(
  735. 'data-columns' => '\'{"key":"Clé","value":"Valeur"}\'',
  736. 'data-format' => '"key-value"'
  737. ))
  738. );
  739. $types[$type_list->slug] = $type_list;
  740. //Checkbox list
  741. $type_checkbox = new self();
  742. $type_checkbox->slug = 'checkbox-list';
  743. $type_checkbox->label = 'Liste de cases à cocher';
  744. $type_checkbox->sqlType = 'longtext';
  745. $type_checkbox->default_attributes = array_merge($type_text->default_attributes,array(
  746. 'data-type'=>'"checkbox-list"',
  747. 'data-slug'=>'"{{key}}"',
  748. 'data-display'=>'"dropdown"',
  749. 'value'=>'"{{value}}"',
  750. 'class'=>'"form-control"'
  751. ));
  752. $type_checkbox->settings = array(
  753. 'slug'=> array(
  754. 'type'=>'dictionary',
  755. 'label'=>'Liste ciblée',
  756. 'attributes'=> array(
  757. 'class'=>'"form-control"',
  758. 'data-slug'=>"",
  759. 'data-output'=>"slug",
  760. 'data-format'=>"slug"
  761. )
  762. ),
  763. 'values'=> array(
  764. 'type'=>'jsontable',
  765. 'label'=>'Valeurs possibles',
  766. 'attributes'=> array(
  767. 'data-columns' => '\'{"key":"Clé","value":"Valeur"}\'',
  768. 'data-format' => '"key-value"'
  769. )),
  770. 'operator-delete'=> array(
  771. 'type'=>'text',
  772. 'value'=>'["in","not in"]',
  773. 'attributes'=> array(
  774. 'class' => '"hidden"',
  775. ))
  776. );
  777. $type_checkbox->filter = array(
  778. 'attributes' => array(
  779. 'data-display'=>'"dropdown"',
  780. 'data-slug'=>'"{{slug}}"',
  781. 'data-depth'=>'"{{depth}}"',
  782. //'data-display'=>'"{{display}}"',
  783. 'data-values'=>'"{{filterTypeValue}}"',
  784. 'data-multi-level-select'=>'"{{multiLevelSelect}}"',
  785. ),
  786. 'operators' => array(
  787. 'in' =>array(
  788. "view" => "checkbox-list",
  789. "value-separator" => ","
  790. ),
  791. 'not in' =>array(
  792. "view" => "checkbox-list",
  793. "value-separator" => ","
  794. ),
  795. 'inline-and' =>array(
  796. "view" => "checkbox-list"
  797. ),
  798. 'inline-or' =>array(
  799. "view" => "checkbox-list"
  800. ),
  801. '=' =>array("view" =>'dictionary'),
  802. '!=' =>array("view" =>'dictionary'),
  803. 'null' =>array(),
  804. 'not null' =>array()
  805. )
  806. );
  807. $type_checkbox->onInput = function($field=array(),$options=array()){
  808. $attributes = array_merge($options['type']->default_attributes,$field['attributes']);
  809. if(isset($field['id'])) $field['attributes']['id'] ='"'.$field['id'].'"';
  810. $html = '';
  811. $html.= '<input value="'.(isset($field['value']) ? str_replace('"','&quot;',$field['value']) : '').'"';
  812. foreach ($field['attributes'] as $key => $value) {
  813. $html.= ' ';
  814. $html.= $key;
  815. if(!empty($value)) $html.= '='.(is_string($value)?$value:"'".json_encode($value)."'");
  816. $html.= ' ';
  817. }
  818. $html.= '>';
  819. return $html;
  820. };
  821. $type_checkbox->onSave = function($value,$options=array()){
  822. $value = explode(',',$value);
  823. $value = array_filter($value);
  824. $value = ','.implode(',',$value).',';
  825. if($value==',,') $value = '';
  826. return $value;
  827. };
  828. $type_checkbox->onLoad = function($value){
  829. $value = explode(',',$value);
  830. $value = array_filter($value);
  831. $value = implode(',',$value);
  832. return $value;
  833. };
  834. $type_checkbox->onRawDisplay = function($value,$field) use($type_checkbox){
  835. $onLoad = $type_checkbox->onLoad;
  836. $value = $onLoad($value);
  837. $values = explode(',',$value);
  838. if(count($values)==0) return '';
  839. $results = array();
  840. //dictionary
  841. $ids = array();
  842. foreach($values as $i=>$id){
  843. if(empty($id) || !is_numeric($id)) continue;
  844. unset($values[$i]);
  845. $ids[] = $id ;
  846. }
  847. if(count($ids)!=0){
  848. $dictionnaries = Dictionary::loadAll(array('id:IN'=>$ids));
  849. foreach($dictionnaries as $dictionary){
  850. $results[] = $dictionary->label;
  851. }
  852. }
  853. //valeur en dur
  854. if(!empty($field['meta'])){
  855. $meta = json_decode($field['meta'],true);
  856. if(!empty($meta['values'])){
  857. $availableValues = $meta['values'];
  858. foreach($values as $id){
  859. if(isset($availableValues[$id])) $results[] = $availableValues[$id];
  860. }
  861. }
  862. };
  863. $value = implode(',',$results);
  864. return $value;
  865. };
  866. $type_checkbox->onHtmlDisplay = function($value,$field) use($type_checkbox){
  867. $onRawDisplay = $type_checkbox->onRawDisplay;
  868. $value = explode(',',$onRawDisplay($value,$field));
  869. $value = array_filter($value);
  870. $value = '<span class="badge badge-secondary">'.implode('</span> <span class="badge badge-secondary">',$value).'</span>';
  871. return $value;
  872. };
  873. $type_checkbox->fromRawDisplay = function($value,$options = array()){
  874. $filters = array('label'=>$value);
  875. if(isset($options['parent'])) $filters['parent'] = $options['parent'];
  876. $dictionary = Dictionary::load($filters);
  877. return !$dictionary ? 0 : $dictionary->id;
  878. };
  879. $type_checkbox->icon = 'fas fa-list';
  880. $type_checkbox->description = 'Liste de cases à cocher configurable';
  881. $type_checkbox->default = '';
  882. $types[$type_checkbox->slug] = $type_checkbox;
  883. //Entier
  884. $type = new self();
  885. $type->slug = 'integer';
  886. $type->label = 'Nombre Entier';
  887. $type->sqlType = 'int';
  888. $type->default_attributes = array_merge($type_text->default_attributes,array(
  889. 'type'=>'"number"',
  890. ));
  891. $type->onInput = $type_text->onInput;
  892. $type->icon = 'fas fa-sort-numeric-down';
  893. $type->description = 'Nombre entier';
  894. $type->onSave = function($value,$options=array()){
  895. $value = trim($value);
  896. if(!empty($value) && !is_numeric($value)) throw new Exception("Ce champ ne doit contenir que des chiffres et être entier");
  897. return $value;
  898. };
  899. $type->filter = array(
  900. 'operators' => array(
  901. 'in' => array(
  902. "view" =>'tag',
  903. "value-separator" => ","
  904. ),
  905. 'not in' => array(
  906. "view" =>'tag',
  907. "value-separator" => ","
  908. ),
  909. '<' => array("view" =>'decimal'),
  910. '>' => array("view" =>'decimal'),
  911. '=' => array("view" =>'decimal'),
  912. '!=' => array("view" =>'decimal'),
  913. 'between' => array("view" =>'decimal'),
  914. 'null' => array(),
  915. 'not null' => array()
  916. )
  917. );
  918. $type->default = '';
  919. $types[$type->slug] = $type;
  920. //Flottant
  921. $type = new self();
  922. $type->slug = 'decimal';
  923. $type->label = 'Décimal';
  924. $type->sqlType = 'decimal';
  925. $type->default_attributes = array_merge($type_text->default_attributes,array(
  926. 'data-type'=>'"decimal"'
  927. ));
  928. $type->onInput = $type_text->onInput;
  929. $type->icon = 'fas fa-sort-numeric-down';
  930. $type->description = 'Nombre décimal';
  931. $type->onSave = function($value,$options=array()){
  932. $value = trim(str_replace(',', '.', $value));
  933. if(!empty($value) && !is_numeric($value)) throw new Exception("Ce champ ne doit contenir que des chiffres");
  934. return $value;
  935. };
  936. $type->filter = array(
  937. 'operators' => array(
  938. 'in' => array(
  939. "view" =>'tag',
  940. "value-separator" => ","
  941. ),
  942. 'not in' => array(
  943. "view" =>'tag',
  944. "value-separator" => ","
  945. ),
  946. '<' => array("view" =>'decimal'),
  947. '>' => array("view" =>'decimal'),
  948. '=' => array("view" =>'decimal'),
  949. '!=' => array("view" =>'decimal'),
  950. 'between' => array("view" =>'decimal'),
  951. 'null' => array(),
  952. 'not null' => array()
  953. )
  954. );
  955. $type->default = '';
  956. $types[$type->slug] = $type;
  957. //Adresse
  958. $type = new self();
  959. $type->slug = 'address';
  960. $type->label = 'Adresse';
  961. $type->sqlType = 'longstring';
  962. $type->default_attributes = array_merge($type_text->default_attributes,array(
  963. 'data-type'=>'"location"',
  964. ));
  965. $type->onInput = $type_text->onInput;
  966. $type->icon = 'fas fa-street-view';
  967. $type->description = 'Adresse postale';
  968. $type->default = '';
  969. $type->filter = array(
  970. 'operators' => array(
  971. 'like' => array("view" =>'text'),
  972. '=' => array("view" =>'text'),
  973. '!=' => array("view" =>'text'),
  974. 'null' => array(),
  975. 'not null' => array()
  976. )
  977. );
  978. $types[$type->slug] = $type;
  979. //Password
  980. $type = new self();
  981. $type->slug = 'password';
  982. $type->label = 'Mot de passe';
  983. $type->sqlType = 'string';
  984. $type->default_attributes = array_merge($type_text->default_attributes,array(
  985. 'data-type'=>'"password"',
  986. 'autocomplete'=>'"new-password"',
  987. ));
  988. $type->onInput = $type_text->onInput;
  989. $type->onSave = function($value,$options=array()){
  990. return encrypt($value);
  991. };
  992. $type->onLoad = function($value){
  993. $value = decrypt($value);
  994. return $value === false ? '' : $value;
  995. };
  996. $type->onRawDisplay = function($value,$options = array()){
  997. $value = decrypt($value);
  998. return $value === false ? '' : $value;
  999. };
  1000. $type->icon = 'fas fa-unlock-alt';
  1001. $type->description = 'Mot de passe caché';
  1002. $type->default = '';
  1003. $types[$type->slug] = $type;
  1004. //Couleur
  1005. $type = new self();
  1006. $type->slug = 'color';
  1007. $type->label = 'Couleur';
  1008. $type->sqlType = 'string';
  1009. $type->default_attributes = array_merge($type_text->default_attributes,array(
  1010. 'data-type'=>'"color"',
  1011. ));
  1012. $type->onHtmlDisplay = function($value,$options = array()){
  1013. if(empty($value)){
  1014. $html = '<span class="fa-stack">
  1015. <i class="far fa-circle fa-stack-1x"></i>
  1016. <i class="fas fa-slash text-danger fa-stack-1x"></i>
  1017. </span>';
  1018. }else{
  1019. $html = '<i class="fas fa-circle" style="color:'.$value.'"></i>';
  1020. }
  1021. return $html;
  1022. };
  1023. $type->filter = array(
  1024. 'operators' => array(
  1025. '=' => array("view" =>'text'),
  1026. '!=' => array("view" =>'text'),
  1027. 'null' => array(),
  1028. 'not null' => array()
  1029. )
  1030. );
  1031. $type->onInput = $type_text->onInput;
  1032. $type->icon = 'fas fa-palette';
  1033. $type->description = 'Couleur';
  1034. $type->default = '';
  1035. $types[$type->slug] = $type;
  1036. //Icône
  1037. $type = new self();
  1038. $type->slug = 'icon';
  1039. $type->label = 'Icône';
  1040. $type->sqlType = 'string';
  1041. $type->default_attributes = array_merge($type_text->default_attributes,array(
  1042. 'data-type'=>'"icon"',
  1043. ));
  1044. $type->onInput = $type_text->onInput;
  1045. $type->onHtmlDisplay = function($value,$options = array()){
  1046. $html = '<i class="'.$value.'"></i>';
  1047. return $html;
  1048. };
  1049. $type->filter = array(
  1050. 'operators' => array(
  1051. '=' => array("view" =>'icon'),
  1052. '!=' => array("view" =>'icon'),
  1053. 'null' => array(),
  1054. 'not null' => array()
  1055. )
  1056. );
  1057. $type->icon = 'fas fa-icons';
  1058. $type->description = 'Icône d\'illustration';
  1059. $type->default = '';
  1060. $types[$type->slug] = $type;
  1061. //Prix
  1062. $type = new self();
  1063. $type->slug = 'price';
  1064. $type->label = 'Prix';
  1065. $type->sqlType = 'decimal';
  1066. $type->onInput = $type_text->onInput;
  1067. $type->icon = 'fas fa-euro-sign';
  1068. $type->description = 'Devis monetaire';
  1069. $type->default = '';
  1070. $type->default_attributes = array_merge($type_text->default_attributes,array(
  1071. 'data-type'=>'"price"',
  1072. 'step'=>'"0.01"',
  1073. 'type'=>'number'
  1074. ));
  1075. $type->filter = array(
  1076. 'operators' => array(
  1077. '=' => array("view" =>'price'),
  1078. '!=' => array("view" =>'price'),
  1079. '<' => array("view" =>'price'),
  1080. '>' => array("view" =>'price'),
  1081. 'between' =>array("view" =>'price'),
  1082. 'in' => array(
  1083. "view" =>'tag',
  1084. "value-separator" => ","
  1085. ),
  1086. 'not in' => array(
  1087. "view" =>'tag',
  1088. "value-separator" => ","
  1089. ),
  1090. 'null' => array(),
  1091. 'not null' => array()
  1092. )
  1093. );
  1094. $type->onSave = function($value,$options=array()){
  1095. $value = trim(str_replace(',', '.', $value));
  1096. if(!empty($value) && !is_numeric($value)) throw new Exception("Le prix ne doit contenir que des chiffres");
  1097. return $value;
  1098. };
  1099. $types[$type->slug] = $type;
  1100. //Choix
  1101. $type = new self();
  1102. $type->slug = 'choice';
  1103. $type->label = 'Choix';
  1104. $type->customLabel = false;
  1105. $type->sqlType = 'longstring';
  1106. $type->default_attributes = array_merge($type_text->default_attributes,array(
  1107. 'data-type'=>'"choice"',
  1108. 'class'=>''
  1109. ));
  1110. $type->filter = array(
  1111. 'attributes' => array('data-values'=>'"{{filterTypeValue}}"'),
  1112. 'operators' => array(
  1113. '=' => array("view" =>'choice'),
  1114. '!=' => array("view" =>'choice'),
  1115. 'null' => array(),
  1116. 'not null' => array()
  1117. )
  1118. );
  1119. $type->settings = array(
  1120. 'values'=> array(
  1121. 'type'=>'jsontable',
  1122. 'label'=>'Options possibles',
  1123. 'attributes'=> array(
  1124. 'data-columns' => '\'{"key":"Clé","value":"Valeur"}\'',
  1125. 'data-format' => '"key-value"'
  1126. )
  1127. )
  1128. );
  1129. $type->onInput = function($field=array(),$options=array()){
  1130. $attributes = array_merge($options['type']->default_attributes,$field['attributes']);
  1131. if(isset($field['id'])) $field['attributes']['id'] ='"'.$field['id'].'"';
  1132. $html = '';
  1133. $html.= '<input value="'.(isset($field['value']) ? str_replace('"','&quot;',$field['value']) : '').'" data-values="'.(isset($field['values']) ? htmlspecialchars(json_encode($field['values']), ENT_QUOTES, 'UTF-8') : '').'"';
  1134. foreach ($field['attributes'] as $key => $value) {
  1135. $html.= ' ';
  1136. $html.= $key;
  1137. if(!empty($value)) $html.= '='.(is_string($value)?$value:"'".json_encode($value)."'");
  1138. $html.= ' ';
  1139. }
  1140. $html.= '>';
  1141. return $html;
  1142. };
  1143. $type->onRawDisplay = function($value,$options = array()){
  1144. if(isset($options['meta'])){
  1145. $meta = is_string($options['meta']) ? json_decode($options['meta'],true) : $options['meta'];
  1146. if(isset($meta['values']) && isset($meta['values'][$value])){
  1147. $value = $meta['values'][$value];
  1148. }
  1149. }
  1150. return $value;
  1151. };
  1152. $type->onHtmlDisplay = $type->onRawDisplay;
  1153. $type->icon = 'far fa-dot-circle';
  1154. $type->description = 'Choix unique';
  1155. $type->default = '';
  1156. $types[$type->slug] = $type;
  1157. //Booléen
  1158. $type = new self();
  1159. $type->slug = 'boolean';
  1160. $type->label = 'Vrai ou Faux';
  1161. $type->customLabel = true;
  1162. $type->sqlType = 'boolean';
  1163. $type->default_attributes = array_merge($type_text->default_attributes,array(
  1164. 'data-type'=>'"checkbox"',
  1165. 'class'=>'',
  1166. 'type'=>'"checkbox"'
  1167. ));
  1168. $type->filter = array(
  1169. 'operators' => array(
  1170. '=' => array("view" =>'boolean'),
  1171. 'null' => array(),
  1172. 'not null' => array()
  1173. )
  1174. );
  1175. $type->onRawDisplay = function($value,$options = array()){
  1176. return $value ? 'VRAI' : 'FAUX';
  1177. };
  1178. $type->onHtmlDisplay = function($value,$options = array()){
  1179. $html = $value ? '<i class="fas fa-check text-success"></i>' : '<i class="fas fa-times text-danger"></i>' ;
  1180. return $html;
  1181. };
  1182. $type->onInput = function($field=array(),$option=array()){
  1183. $html = '';
  1184. $html.= '<div><label><input id="'.(isset($field['id'])?$field['id']:'').'" ';
  1185. if(isset($field['value']) && $field['value'] == 1){
  1186. $field['attributes']['checked'] = '"checked"';
  1187. }
  1188. foreach ($field['attributes'] as $key => $value) {
  1189. $html.= ' ';
  1190. $html.= $key;
  1191. if(!empty($value)) $html.= '='.$value;
  1192. $html.= ' ';
  1193. }
  1194. $html.= '>';
  1195. if(!empty($field['label']) && $option['allowCustomLabel']) $html.= ' '.$field['label'];
  1196. $html.= '</label></div>';
  1197. return $html;
  1198. };
  1199. $type->icon = 'far fa-check-square';
  1200. $type->description = 'Vrai ou Faux';
  1201. $type->default = '';
  1202. $types[$type->slug] = $type;
  1203. //Url
  1204. $type = new self();
  1205. $type->slug = 'url';
  1206. $type->label = 'Adresse web';
  1207. $type->sqlType = 'string';
  1208. $type->default_attributes = array_merge($type_text->default_attributes,array(
  1209. 'data-type'=>'"url"',
  1210. ));
  1211. $type->onSave = function($value,$options=array()){
  1212. if(!empty($value) && !filter_var($value, FILTER_VALIDATE_URL) ) throw new Exception("Mauvais format d'adresse web");
  1213. return $value;
  1214. };
  1215. $type->onInput = $type_text->onInput;
  1216. $type->onHtmlDisplay = function($value,$options = array()){
  1217. if(empty($value)) return $value;
  1218. $html = '<a href="'.$value.'">';
  1219. $html .= $value;
  1220. $html.= '</a>';
  1221. return $html;
  1222. };
  1223. $type->filter = array(
  1224. 'operators' => array(
  1225. '=' => array("view" =>'url'),
  1226. '!=' => array("view" =>'url'),
  1227. 'like' => array("view" =>'text'),
  1228. 'not like' => array("view" =>'text'),
  1229. 'null' => array(),
  1230. 'not null' => array()
  1231. )
  1232. );
  1233. $type->icon = 'fas fa-globe';
  1234. $type->description = 'Adresse Url (web)';
  1235. $type->default = '';
  1236. $types[$type->slug] = $type;
  1237. //Mail
  1238. $type = new self();
  1239. $type->slug = 'mail';
  1240. $type->label = 'E-mail';
  1241. $type->sqlType = 'string';
  1242. $type->default_attributes = array_merge($type_text->default_attributes,array(
  1243. 'data-type'=>'"mail"',
  1244. 'type'=>'"mail"',
  1245. 'pattern'=>'".+@.+"'
  1246. ));
  1247. $type->onSave = function($value,$options=array()){
  1248. if(!empty($value) && !check_mail($value)) throw new Exception("Mauvais format d'e-mail");
  1249. return $value;
  1250. };
  1251. $type->onHtmlDisplay = function($value,$options = array()){
  1252. $html = '<a href="mailto:'.$value.'">';
  1253. $html .= $value;
  1254. $html.= '</a>';
  1255. return $html;
  1256. };
  1257. $type->filter = array(
  1258. 'operators' => array(
  1259. '=' => array("view" =>'mail'),
  1260. '!=' => array("view" =>'mail'),
  1261. 'like' => array("view" =>'text'),
  1262. 'not like' => array("view" =>'text'),
  1263. 'null' => array(),
  1264. 'not null' => array()
  1265. )
  1266. );
  1267. $type->onInput = $type_text->onInput;
  1268. $type->icon = 'far fa-envelope-open';
  1269. $type->description = 'E-mail';
  1270. $type->default = '';
  1271. $types[$type->slug] = $type;
  1272. //Téléphone
  1273. $type = new self();
  1274. $type->slug = 'phone';
  1275. $type->label = 'Téléphone';
  1276. $type->sqlType = 'string';
  1277. $type->default_attributes = array_merge($type_text->default_attributes,array(
  1278. 'data-type'=>'"phone"'
  1279. ));
  1280. $type->onSave = function($value,$options=array()){
  1281. if(!empty($value) && !check_phone_number($value)) throw new Exception("Mauvais format de téléphone");
  1282. $value = normalize_phone_number($value);
  1283. return $value;
  1284. };
  1285. $type->onInput = $type_text->onInput;
  1286. $type->icon = 'fas fa-mobile-alt';
  1287. $type->description = 'N° Téléphone';
  1288. $type->default = '';
  1289. $type->filter = array(
  1290. 'operators' => array(
  1291. 'like' =>array("view" =>'text'),
  1292. 'not like' =>array("view" =>'text'),
  1293. '=' =>array("view" =>'phone'),
  1294. '!=' =>array("view" =>'phone'),
  1295. 'null' =>array(),
  1296. 'not null' =>array()
  1297. )
  1298. );
  1299. $types[$type->slug] = $type;
  1300. Plugin::callHook('field_types',array(&$types));
  1301. if(isset($key)) return isset($types[$key])? $types[$key] : $types['text'];
  1302. return $types;
  1303. }
  1304. }