| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498 | 
							- <?php
 
- require_once(__DIR__.DIRECTORY_SEPARATOR.'DynamicField.class.php');
 
- /**
 
-  * Define a dynamicform.
 
-  * @author Charles DUBOIS
 
-  * @category Plugin
 
-  * @license MIT
 
-  */
 
- class DynamicForm extends Entity{
 
- 	public $id;
 
- 	public $slug; //Slug (Texte)
 
- 	public $color; //Couleur (Couleur)
 
- 	public $icon; //Icônes (Icône)
 
- 	public $label; //Libellé (Texte)
 
- 	public $state; //State (Texte)
 
- 	public $firm; //Etablissement (Number)
 
- 	protected $TABLE_NAME = 'dynamicform_form';
 
- 	public $entityLabel = 'Formulaire';
 
- 	public $fields = array(
 
- 		'id' => 'key',
 
- 		'slug' => array('type'=>'string', 'label' => 'Slug'),
 
- 		'color' => array('type'=>'string', 'label' => 'Couleur'),
 
- 		'icon' => array('type'=>'string', 'label' => 'Icônes'),
 
- 		'state' => array('type'=>'string', 'label' => 'Etat'),
 
- 		'firm' => array('type'=>'int', 'label' => 'Etablissement','link'=>'class/Firm.class.php'),
 
- 		'label' => array('type'=>'string', 'label' => 'Libellé')
 
- 	);
 
- 	//Colonnes indexées
 
- 	public $indexes = array('slug','firm');
 
- 	public static function remove($slug,$options = array()){
 
- 		Plugin::need('dynamicform/DynamicField,dynamicform/DynamicValue');
 
- 		$form = self::load(array('slug'=>$slug));
 
- 		if(!$form) return;
 
- 		$query = 'DELETE FROM {{table}} WHERE field IN(SELECT id FROM '.DynamicField::tableName().' fi WHERE fi.form=?) ';
 
- 		$data = array($form->id);
 
- 		if(empty($options['scope'])){
 
- 			$query .= ' AND scope=? ';
 
- 			$data[] = $options['scope'];
 
- 		}
 
- 		if(empty($options['uid'])){
 
- 			$query .= ' AND uid=? ';
 
- 			$data[] = $options['uid'];
 
- 		}
 
- 		DynamicValue::staticQuery($query,$data);
 
- 	}
 
- 	public static function check_required($slug,$options = array(),$newValues){
 
- 		Plugin::need('dynamicform/DynamicField');
 
- 		$types = FieldType::available();
 
- 		$query = "SELECT fi.id,fi.type,fi.label,fi.meta,fi.slug,fi.mandatory,fi.readonly
 
- 			FROM {{table}} fi
 
- 			LEFT JOIN ".self::tableName()." fo ON fi.form = fo.id
 
- 			WHERE fo.slug = ? ";
 
- 		$data = array($slug);
 
- 		$fields = DynamicField::staticQuery($query,$data,true,1);
 
- 		foreach($fields as $field)
 
- 			if(empty($newValues[$field->slug]) && $field->mandatory) throw new Exception('Le champ '.$field->label.' est obligatoire');
 
- 		//pour réutilisation de performance par la méthode record, souvant appellée juste après
 
- 		return $fields;
 
- 	}
 
- 	public static function record($slug,$options = array(),$newValues){
 
- 		Plugin::need('dynamicform/DynamicField');
 
- 		$types = FieldType::available();
 
- 		//si on a pas récupéré les fields dans un opération précédente (ex check_required), on les récupere ici
 
- 		if(!isset($options['fields'])){
 
- 			$query = "SELECT fi.id,fi.type,fi.label,fi.meta,fi.slug,fi.mandatory,fi.readonly
 
- 				FROM {{table}} fi
 
- 				LEFT JOIN ".self::tableName()." fo ON fi.form = fo.id
 
- 				WHERE fo.slug = ? ";
 
- 			$data = array($slug);
 
- 			$fields = DynamicField::staticQuery($query,$data,true,1);
 
- 		}else{
 
- 			$fields = $options['fields'];
 
- 			//gain de perf
 
- 			unset($options['fields']);
 
- 		}
 
- 		//on affiche chaque champ dynamique du formulaire
 
- 		foreach($fields as $field){
 
- 			if(empty($newValues[$field->slug]) && $field->mandatory) throw new Exception('Le champ '.$field->label.' est obligatoire');
 
- 			//on verifie qu'une valeur a été donnée
 
- 			if(!isset($newValues[$field->slug])) continue;
 
- 			//si le champ est en lecture seule on n'enregistre pas de valeur
 
- 			if($field->readonly) continue;
 
- 			DynamicField::record(array('field'=>$field,'value'=>$newValues[$field->slug],'options'=>$options,'types'=>$types));
 
- 		}
 
- 	}
 
- 	/**
 
- 	 * Affiche un formulaire en fonction de son slug et de ses options de contexte
 
- 	 * @param <String> slug du formulaire ciblé
 
- 	 * @param <Array> options des filtres de sélection des champs
 
- 	 * @return <Array> tableau des options de ciblage des champs à récupérer
 
- 	 */
 
- 	public static function show($slug,$options = array()){
 
- 		global $myFirm;
 
- 		Plugin::need('dynamicform/DynamicField,dynamicform/DynamicValue');
 
- 		$options = array_merge(array(
 
- 			'label' => 'block', // inline (input group) / block (label classique) / none (pas de label)
 
- 			'legend' => 'block', // block (span text muted) / none (pas de label)
 
- 			'input-class' => '', // classes additionnelles a placer sur les inputs
 
-             'input-group-class' => '', // classes additionnelles a placer sur les groupes d'inputs
 
- 			'scope' => '', // ex : client
 
- 			'uid' => '', // ex : 12
 
- 			'firm' => $myFirm->id // ex : 1
 
- 		),$options);
 
- 		$options['format'] = 'table';
 
- 		$types = FieldType::available();
 
- 		//Initialisation des options de sélection des champs scope / firm etc
 
- 		$listOptions = self::list_options($slug, $options);
 
- 		//Si pas de slug on affiche rien
 
- 		if(empty($listOptions))return;
 
- 		//Récupération du tableau d'objets champs
 
- 		$fieldsObjects = self::get_fields($listOptions);
 
- 		//Mise au format table (mise en page ligne colonne) de la liste des champs
 
- 		$fieldsTable = self::fields_layout($fieldsObjects, $types, $options);
 
- 		//Mise au format liste (à plat) de la liste des champs
 
- 		$options['format'] = 'list';
 
- 		$fieldsList = self::fields_layout($fieldsObjects, $types, $options);
 
- 		$stream = '';
 
- 		$values = self::get_values($fieldsList,$options);
 
- 		if(isset($options['arrayOutput']) && $options['arrayOutput']){
 
- 			return self::get_values_as_array($fieldsList,$values);
 
- 		}
 
- 		//mise en page
 
- 		foreach($fieldsTable as $i => $columns) {
 
- 			$stream .= '<div class="row">';
 
- 			foreach ($columns as $u => $fields) {
 
- 				$stream .= '<div class="col-md column">';
 
- 				foreach($fields as $field){
 
- 					$value = isset($values[$field['id']]) ? $values[$field['id']] : '';
 
- 					$stream .= DynamicField::show(array('field'=>$field,'value'=>$value,'types'=>$types,'options'=>$options));
 
- 				}
 
- 				$stream .= '</div>';
 
- 			}
 
- 			$stream .= '</div>';
 
- 		}
 
- 		return $stream;
 
- 	}
 
- 	/**
 
- 	 * Retourne un tableau de champs disponibles pour ce slug et cette firm
 
- 	 * @param <String> slug du formulaire ciblé
 
- 	 * @param <Array> options des filtres de sélection des champs
 
- 	 * @return <Array> tableau des options de ciblage des champs à récupérer
 
- 	 */
 
- 	public static function list($slug,$options = array()){
 
- 		$types = FieldType::available();
 
- 		$options = self::list_options($slug,$options);
 
- 		if(empty($options)) return array();
 
- 		$fields = self::get_fields($options);
 
- 		$rows = self::fields_layout($fields,$types,$options);
 
- 		return $rows;
 
- 	}
 
- 	/**
 
- 	 * Initialise les options de filtrage pour récupération des champs
 
- 	 * @param <String> slug du formulaire ciblé
 
- 	 * @param <Array> options des filtres de sélection des champs
 
- 	 * @return <Array> tableau des options de ciblage des champs à récupérer
 
- 	 */
 
- 	public static function list_options($slug,$options = array()){
 
- 		global $myFirm;
 
- 		$options = array_merge(array(
 
- 			'firm' => $myFirm->id, // ex : 1
 
- 			'format' => 'list' // table (mise en page ligne colonne) ou liste (a plat)
 
- 		),$options);
 
- 		$forms = self::loadAll(array('slug'=>$slug,'firm:IN'=>array($options['firm'],'0')));
 
- 		if(!$forms || count($forms)==0) return array();
 
- 		$formIds = array();
 
- 		foreach ($forms as $form)
 
- 			$formIds[] = $form->id;
 
- 		$options['slug'] = $slug;
 
- 		$options['form'] = $formIds;
 
- 		$options['firm'] = array($options['firm'],'0');
 
- 		return $options;
 
- 	}
 
- 	/**
 
- 	 * Retourne un tableau de champs (de type array) formaté en liste ou table selon l'option 'format'
 
- 	 * @param <Array> tableau d'options/ filtres de sélection
 
- 	 * @return <Array> tableau brut de champs (de type object) selon les options settées
 
- 	 */
 
- 	public static function get_fields_layout($options = array()){
 
- 		$types = FieldType::available();
 
- 		$fields = self::get_fields($options);
 
- 		return self::fields_layout($fields,$types,$options);
 
- 	}
 
- 	/**
 
- 	 * Retourne un tableau brut de champs (de type object) selon les options settées
 
- 	 * @param <Array> tableau d'options/ filtres de sélection
 
- 	 * @return <Array> tableau brut de champs (de type object) selon les options settées
 
- 	 */
 
- 	public static function get_fields($options = array()){
 
- 		Plugin::need('dynamicform/DynamicField');
 
- 		$data = array();
 
- 		if(empty($options['format'])) $options['format'] = 'table';
 
- 		$query = 'SELECT fi.* FROM {{table}} fi LEFT JOIN '.self::tableName().' fo ON fi.form = fo.id WHERE 1 ';
 
- 		$query .= ' AND fo.state=? ';
 
- 		$data[] = self::ACTIVE;
 
- 		if(isset($options['slug'])){
 
- 			$query .= ' AND fo.slug=? ';
 
- 			$data[] = $options['slug'];
 
- 		}else if(isset($options['id'])){
 
- 			$query .= ' AND fo.id=? ';
 
- 			$data[] = $options['id'];
 
- 		}
 
- 		if(isset($options['form'])){
 
- 			$query .= ' AND fo.id IN ('.implode(',',array_fill(0,count($options['form']),'?')).')';
 
- 			foreach ($options['form'] as $form)
 
- 				$data[] = $form;
 
- 		}
 
- 		if(isset($options['firm'])){
 
- 			$query .= ' AND fo.firm IN ('.implode(',',array_fill(0,count($options['firm']),'?')).')';
 
- 			foreach ($options['firm'] as $firm)
 
- 				$data[] = $firm;
 
- 		}
 
- 		$query .= ' ORDER BY fi.row,fi.column,fi.sort';
 
- 		$dynamicfields = array();
 
-         foreach(DynamicField::staticQuery($query,$data,true) as $dynamicField){
 
-             if(!is_null($dynamicField->meta) && !empty($dynamicField->meta))
 
-                 $dynamicField->meta = base64_encode($dynamicField->meta);
 
-             $dynamicfields[] = $dynamicField;
 
-         }
 
- 		return $dynamicfields;
 
- 	}
 
- 	/**
 
- 	 * Retourne un tableau de champs (de type array) formaté en liste ou table selon l'option 'format'
 
- 	 * @param <Array> tableau brut d'objets champs dynamiques
 
- 	 * @param <Array> tableau des fieldtypes disponibles
 
- 	 * @param <Array> tableau des options de sélection et de format
 
- 	 * @return <Array> tableau formaté (table ou liste) des champs dynamiques ciblés
 
- 	 */
 
- 	public static function fields_layout($fields,$types,$options = array()){
 
- 		if(is_null($types)) $types = FieldType::available();
 
- 		if(empty($options['format'])) $options['format'] = 'table';
 
- 		$rows = array();
 
- 		foreach($fields as $field){
 
- 			$row = $field->toArray();
 
- 			$row['type'] = $types[$row['type']];
 
- 			if($options['format'] == 'table'){
 
- 				if(!isset($rows[$field->row])) $rows[$field->row] = array();
 
- 				if(!isset($rows[$field->row][$field->column])) $rows[$field->row][$field->column] = array();
 
- 				$rows[$field->row][$field->column][] = $row;
 
- 			}else{
 
- 				$rows[] = $row;
 
- 			}
 
- 		}
 
- 		return $rows;
 
- 	}
 
- 	/**
 
- 	 * Retourne un tableau brut de valeurs pour un set de champs en fonction du scope / firm
 
- 	 * @param <Array> tableau brut de champs dynamiques (sous forme d'arrays)
 
- 	 * @param <Array> tableau des options de sélection et de format
 
- 	 * @return <Array> tableau brut des valeurs des champs dynamiques ciblés avec comme clé l'identifiant du champ dynamique
 
- 	 */
 
- 	public static function get_values($fields,$options){
 
- 		Plugin::need('dynamicform/DynamicValue');
 
- 		$values = array();
 
- 		$fieldIds = array();
 
- 		//Récuperation des id de fields
 
- 		foreach($fields as $field)
 
- 			$fieldIds[] = $field['id'];
 
- 		if(empty($fieldIds)) return $values;
 
- 		$valueFilters = array('field:IN'=>$fieldIds);
 
- 		if(!empty($options['firm'])) $valueFilters['firm:IN'] = array($options['firm'],0);
 
- 		if(!empty($options['scope'])) $valueFilters['scope'] = $options['scope'];
 
- 		$valueFilters['uid'] = $options['uid'];
 
- 		//récuperation des valeurs déja enregistrées pour ces fields
 
- 		foreach (DynamicValue::loadAll($valueFilters) as $key => $value)
 
- 			$values[$value->field] = $value->value;
 
- 		return $values;
 
- 	}
 
- 	/**
 
- 	 * Retourne le tableau formaté des valeurs de champs pour export
 
- 	 * @category manipulation de tableaux
 
- 	 * @param <Array> tableau brut des valeurs des champs dynamiques
 
- 	 * @return <Array> tableau des valeurs des champs dynamiques utilisables pour l'export
 
- 	 */
 
- 	public static function get_values_as_array($fields,$values){
 
- 		$arrayOutput = array();
 
- 		foreach($fields as $field){
 
- 			$field['value']= isset($values[$field['id']]) ? $values[$field['id']] : '';
 
- 			$arrayOutput[] = $field;
 
- 		}
 
- 		return $arrayOutput;
 
- 	}
 
- 	/**
 
- 	 * Ajoute à la requete originelle les valeurs des champs dynamiques aliasisés par le slug du champ dynamique
 
- 	 * @category manipulation de chaine pour création dynamiqe de requête de sélection en base
 
- 	 * @param <Array> tableau des champs dynamiques potentiellement affichables
 
- 	 * @param <String> requête originelle de sélection en base à modifier
 
- 	 * @param <String> alias de la table mère présente dans le FROM de la requête originelle de sélection
 
- 	 * @return <String> requête de sélection modifiée avec les valeurs des champs dynamiques
 
- 	 */
 
- 	public static function query_column_add($fields,&$query,$alias = ''){
 
- 		global $_;
 
- 		Plugin::need('dynamicform/DynamicValue');
 
- 		$columns = array();
 
- 		//Tableau des champs dynamiques disponibles
 
-  		foreach($fields as $field)
 
-  			$columns[$field['id']] = $field['slug'];
 
-  		//Tableau des champs dynamiques sélectionnés
 
- 		$selected = isset($_['columns']) && isset($_['columns']['added']) ? $_['columns']['added'] : array();
 
- 		//On ne garde que les champs sélectionés et présents dans les champs disponibles ET les champs requetés en filtres
 
- 		if(isset($_['filters']['advanced'])){
 
- 			foreach($_['filters']['advanced'] as $field){
 
- 				$parts = explode('dynamicField_',$field['column']);
 
- 				//on ne traite que les field dynamiques
 
- 				if(count($parts)<=1) continue;
 
- 				//pour retrouver le slug du custom field (slug-fitlre) depuis le slug du filtre (dynamicField_{{id}})
 
- 				$dynamicSlug = $columns[str_replace('.value','',$parts[1])];
 
- 				$selected[] = $dynamicSlug;
 
- 			}
 
- 		}
 
- 		$columns = array_intersect($columns,$selected);
 
- 		//On crée la chaine de sélection des valeurs
 
- 		$selectFields = array();
 
-  		foreach($columns as $id=>$slug)
 
-  			$selectFields[] = 'dynamicField_'.$id.'.value AS "'.$slug.'"';
 
-  		//On récupère ce qu'il y a entre select et from et on le concatène à la chaine de sélection des valeurs créé
 
- 		$selectFields = empty($selectFields) ? ' ' : ','.implode(',',$selectFields);
 
- 		$query = preg_replace("/(?<=SELECT)(.*)(?=FROM)/i","$0".$selectFields.' ',$query);
 
- 		//on récupère ce qu'il y a entre select et where et on le concat avec les left joins pour chaque champs dynamiques à afficher
 
- 		$joinFields = array();
 
- 		foreach($columns as $id=>$slug)
 
- 			$joinFields[] = ' LEFT JOIN '.DynamicValue::tableName().' dynamicField_'.$id.' ON dynamicField_'.$id.'.uid = '.(empty($alias) ? 'id' : '`'.$alias.'`.id').' AND dynamicField_'.$id.'.field = '.$id;
 
- 		$joinFields = implode(' ',$joinFields);
 
- 		$query = preg_replace("/(?<=SELECT)(.*)(?=WHERE)/is","$0".$joinFields.' ',$query);
 
- 	}
 
- 	//Retourne un set de filtres de colonnes dynamiques en fonction de la liste des
 
- 	//champs custom fournie
 
- 	public static function get_dynamic_columns($fields){
 
- 		$columns = array();
 
- 		foreach ($fields as $field) {
 
-             $columns[$field['slug']] =
 
-                 array(
 
-                     'head' => '<th data-sortable="dynamicField_'.$field['id'].'.value" data-available="'.$field['slug'].'">'.$field['label'].'</th>',
 
-                     'body' => '<td class="align-middle text-center">{{{'.$field['slug'].'}}}</td>',
 
-                 );
 
-         }
 
-         return  $columns;
 
- 	}
 
- 	//Convertion des valeurs retours d'une db pour des colonnes dynamiques en fonction de leurs types
 
- 	public static function search_values(&$row,$options){
 
- 		if(!isset($options['force-raw'])) $options['force-raw'] = false;
 
- 		//Récupération des champs afin d'avoir les metas pour affichaqge fieldtypes exotique list, dictionary...
 
- 		$meta = array();
 
- 		foreach(DynamicField::loadAll(array('slug:IN'=>array_keys($options['slugs']))) as $field)
 
- 			$meta[$field->slug] = $field->meta;
 
- 		//pour chaque champ, s'il fait partie des types qui possèdent une propriété onHtmlDisplay, on l'applique à la valeur du champ
 
- 		foreach($options['slugs'] as $slug=>$value){
 
- 			if(!isset($options['types'][$slug])) continue;
 
- 			$type = $options['types'][$slug];
 
- 			$displayOptions = array('meta'=>$meta[$slug],'type'=>$type);
 
- 			//tansmission des parametres de contexte
 
- 			foreach($options as $key=>$option){
 
- 				if(!is_string($option)) continue;
 
- 				$displayOptions[$key] = $option;
 
- 			}
 
- 			if(isset($row['id'])) $displayOptions['uid'] = $row['id'];
 
- 			if(property_exists($type,"onHtmlDisplay") && !$options['force-raw']){
 
- 				$method = $type->onHtmlDisplay;
 
- 				$displayOptions['decoration']  = 'true';
 
- 				$value = $method($value,$displayOptions);
 
- 			}elseif(property_exists($type,"onRawDisplay")){
 
- 				$method = $type->onRawDisplay;
 
- 				$value = $method($value,$displayOptions);
 
- 			}
 
- 			$row[$slug] = $value;
 
- 		}
 
- 	}
 
- 	//Récuperation des valeurs de champs dynamic pour un formulaire, un scope et un item donné sous la forme slug field => valeur
 
- 	public static function values($formSlug,$options){
 
- 		require_once(__DIR__.SLASH.'DynamicForm.class.php');
 
- 		require_once(__DIR__.SLASH.'DynamicField.class.php');
 
- 		require_once(__DIR__.SLASH.'DynamicValue.class.php');
 
- 		$query  = 'SELECT dfi.slug,dva.value FROM {{table}} dva
 
- 		LEFT JOIN '.DynamicField::tableName().' dfi ON dfi.id = dva.field
 
- 		LEFT JOIN '.DynamicForm::tableName().' dfo ON  dfo.id = dfi.form
 
- 		WHERE dfo.slug = ? AND dva.scope = ? AND dva.uid = ?';
 
- 		$data = array($formSlug,$options['scope'],$options['uid']);
 
- 		$values = array();
 
- 		foreach (DynamicValue::staticQuery($query,$data,true) as $key => $value)
 
- 			$values[$value->foreign('slug')] = $value->value;
 
- 		return $values;
 
- 	}
 
- 	//Retourne un set de filtres de recherche avancée en fonction de la liste des
 
- 	//champs custom fournie
 
- 	public static function get_filters($fields){
 
- 		$filters = array();
 
- 		foreach($fields as $field){
 
-         	$filterOptions = '';
 
- 			$filterType = $field['type']->slug;
 
- 			$meta = isset($field['meta']) ? json_decode(base64_decode($field['meta']),true) : (object) array();
 
- 			//le field doit comprendre le meta show-filter pour afficher le filtre (case a cocher dans la construction du formulaire)
 
- 			if(!is_array($meta) || empty($meta['show-filter'])) continue;
 
- 			$filterOptions = ' data-filter-type="'.$filterType.'" ';
 
- 			if(is_array($meta)){
 
- 				foreach($meta as $key=>$value)
 
- 					$filterOptions .= 'data-'.$key.'=\''.(is_string($value) ? $value : str_replace("'","\'",json_encode($value))).'\' ';
 
- 			}
 
-             //si le type de champ ne propose pas de filtre on l'ignore
 
-             if(!property_exists($field['type'],'filter')) continue;
 
-             $filters[$field['slug']] = '<option value="dynamicField_'.$field['id'].'.value"'.$filterOptions.'>'.$field['label'].'</option>';
 
-         }
 
-         return $filters;
 
- 	}
 
- }
 
- ?>
 
 
  |