diff --git a/doc/conf/LSattribute/LSattr_html.docbook b/doc/conf/LSattribute/LSattr_html.docbook index 2c2bdd1b..59fdd074 100644 --- a/doc/conf/LSattribute/LSattr_html.docbook +++ b/doc/conf/LSattribute/LSattr_html.docbook @@ -6,6 +6,7 @@ &conf-LSattr_html_boolean; &conf-LSattr_html_date; &conf-LSattr_html_image; + &conf-LSattr_html_jsonCompositeAttribute; &conf-LSattr_html_mail; &conf-LSattr_html_maildir; &conf-LSattr_html_mailQuota; diff --git a/doc/conf/LSattribute/LSattr_html/LSattr_html.entities.xml b/doc/conf/LSattribute/LSattr_html/LSattr_html.entities.xml index 3be2d267..3e342b14 100644 --- a/doc/conf/LSattribute/LSattr_html/LSattr_html.entities.xml +++ b/doc/conf/LSattribute/LSattr_html/LSattr_html.entities.xml @@ -2,6 +2,7 @@ + @@ -17,3 +18,5 @@ + +LSattr_html_select_list"> diff --git a/doc/conf/LSattribute/LSattr_html/LSattr_html_jsonCompositeAttribute.docbook b/doc/conf/LSattribute/LSattr_html/LSattr_html_jsonCompositeAttribute.docbook new file mode 100644 index 00000000..09fe1097 --- /dev/null +++ b/doc/conf/LSattribute/LSattr_html/LSattr_html_jsonCompositeAttribute.docbook @@ -0,0 +1,96 @@ + + LSattr_html_jsonCompositeAttribute + Ce type est utilisé pour la gestion des attributs dont les valeurs sont + des dictionnaires de valeurs encodées aux formats JSON. + + +Exemple de valeur gérée + + + + Le principe est que ces dictionnaires contienent plusieurs composants référencés + par leur clé et stockant une valeur dont le type peut être un texte libre ou + bien être issue d'une liste déroulante configurable selon le même principe que + le type d'attribut &LSattr_html_select_list;. + + +Structure... + array ( + 'components' => array ( + '[clé composant 1]' => array ( + 'label' => '[Label du composant]', + 'type' => '[Type de la valeur stocké]', + 'required' => [Booléen], + 'check_data' => => array ( + // Régle de vérification syntaxique des données saisies + ), + ), + '[clé composant 2]' => array ( + 'label' => '[Label du composant 2]', + 'type' => 'select_list', + 'required' => [Booléen], + 'options' => array ( + [Configuration équivalente à un attribut LSattr_html_select_list] + ) + ), + [...] + ), +),]]> +... + + + +Paramètres de configuration + + + components + + Tableau associatif obligatoire contenant en valeur clé, l'identifiant des + composants, correspondant à la clé dans le dictionnaire JSON, + et en valeurs associés, la configuration du composant. + + + + label + + Le label du composant. + + + + + type + + Le type de valeur du composant. Les types possibles sont + text ou select_list pour respectivement + soit une valeur saisie librement, soit une valeur sélectionnée parmis une liste + déroulante. + + + + + options + + Dans le cadre d'un composant de type select_list, cela + correspond à la configuration de la liste déroulante. Cette configuration utilise la + même syntaxe de configuration que celle du type d'attribut &LSattr_html_select_list; + et son paramètre html_options. + + + + + check_data + + Tableau associatif contenant les règles de vérification syntaxique + des données du composant. Ces règles sont configurables de la même manière + que les celles des valeurs attributs. + Voir la section concernée. + + + + + + + + + + diff --git a/public_html/css/default/LSformElement_jsonCompositeAttribute.css b/public_html/css/default/LSformElement_jsonCompositeAttribute.css new file mode 100644 index 00000000..28b641f3 --- /dev/null +++ b/public_html/css/default/LSformElement_jsonCompositeAttribute.css @@ -0,0 +1,34 @@ +ul.LSformElement_jsonCompositeAttribute li { + border: 1px dotted #CCC; + padding: 2px; +} + +ul.LSformElement_jsonCompositeAttribute li.noValue { + border: none; +} + +ul.LSformElement_jsonCompositeAttribute p { + margin: 0; +} + +ul.LSformElement_jsonCompositeAttribute p label { + font-weight: bold; +} + +div.jsonCompositeAttribute_possibleValues ul { + list-style-type: none; + padding: 0; + margin: 0; + border: 1px solid #CCC; + border-collapse: collapse; +} + +div.jsonCompositeAttribute_possibleValues li { + border-bottom: 1px solid #CCC; + margin-bottom: 2px; +} + +div.jsonCompositeAttribute_possibleValues li:hover { + background-color: #CCC; + cursor: pointer; +} diff --git a/public_html/includes/class/class.LSattr_html_jsonCompositeAttribute.php b/public_html/includes/class/class.LSattr_html_jsonCompositeAttribute.php new file mode 100644 index 00000000..82e26ebb --- /dev/null +++ b/public_html/includes/class/class.LSattr_html_jsonCompositeAttribute.php @@ -0,0 +1,32 @@ + + */ +class LSattr_html_jsonCompositeAttribute extends LSattr_html { + + var $LSformElement_type = 'jsonCompositeAttribute'; + +} diff --git a/public_html/includes/class/class.LSformElement_jsonCompositeAttribute.php b/public_html/includes/class/class.LSformElement_jsonCompositeAttribute.php new file mode 100644 index 00000000..ee061617 --- /dev/null +++ b/public_html/includes/class/class.LSformElement_jsonCompositeAttribute.php @@ -0,0 +1,268 @@ + + */ + +class LSformElement_jsonCompositeAttribute extends LSformElement { + + var $template = 'LSformElement_jsonCompositeAttribute.tpl'; + var $fieldTemplate = 'LSformElement_jsonCompositeAttribute_field.tpl'; + + function LSformElement_jsonCompositeAttribute (&$form, $name, $label, $params,&$attr_html){ + parent :: LSformElement($form, $name, $label, $params,$attr_html); + if (is_array($this -> params['html_options']['components'])) { + $this -> components = $this -> params['html_options']['components']; + } + } + + /* + * Value components : + * + * Format : + * array ( + * '[component1_key]' => array ( + * 'label' => '[component label]', + * 'type' => '[component type]', + * 'required' => '[booléen]', + * 'check_data' => array([config LSform_rule]) + * ), + * '[component2_key]' => array ( + * 'label' => 'label2', + * 'type' => 'select_list', + * 'options' => array([config as LSattr_html_select_list html_options]), + * ), + * [...] + * ) + * Types : + * - 'select_list' => Component feed by a list of valeur configured like an + * atribute LSattr_html :: select_list. + * - 'text' => manual entry + * + */ + var $components = array(); + + /** + * Retourne les infos d'affichage de l'élément + * + * Cette méthode retourne les informations d'affichage de l'élement + * + * @retval array + */ + function getDisplay(){ + $return = $this -> getLabelInfos(); + + $parseValues=array(); + $invalidValues=array(); + foreach($this -> values as $val) { + $decodedValue=json_decode($val, true); + if (is_array($decodedValue)) { + $parseValue=array('value' => $val); + foreach($decodedValue as $c => $cvalue) { + $parseValue[$c]=$this -> translateComponentValue($c,$cvalue); + } + $parseValues[]=$parseValue; + } + else { + $invalidValues[]=$val; + } + } + + $components = $this -> components; + foreach($components as $c => $cconf) { + if ($cconf['type']=='select_list') { + $components[$c]['possible_values']=$this -> getSelectListComponentPossibleValues($c); + } + } + + $return['html'] = $this -> fetchTemplate(NULL, + array( + 'parseValues' => $parseValues, + 'components' => $components + ) + ); + LSsession :: addCssFile('LSformElement_jsonCompositeAttribute.css'); + return $return; + } + + + /** + * Return HTML code of an empty field + * + * @retval string HTML code of an empty field. + */ + function getEmptyField() { + return $this -> fetchTemplate($this -> fieldTemplate,array('components' => $this -> components)); + } + + /** + * Translate componant value + * + * Return an array containing : + * - value : untranslated value + * - translated : translated value + * + * @param[in] $c string The component name + * @param[in] $value string The value + * + * @retval array + **/ + function translateComponentValue($c,$value) { + $retval = array ( + 'translated' => $value, + 'value' => $value, + ); + if (isset($this -> components[$c])) { + if ($this -> components[$c]['type']=='select_list') { + $retval['translated'] = $this -> getSelectListComponentValueLabel($c,$value); + } + //elseif type == 'text' => no transformation + } + return $retval; + } + + /** + * Retreive possible values of an select_list component + * + * @param[in] $c string The component name + * + * @retval array + **/ + protected $_cache_getSelectListComponentPossibleValues=array(); + protected function getSelectListComponentPossibleValues($c) { + if (!isset($this -> _cache_getSelectListComponentPossibleValues[$c])) { + if (!LSsession :: loadLSclass('LSattr_html_select_list')) return; + $this -> _cache_getSelectListComponentPossibleValues[$c]=LSattr_html_select_list :: getPossibleValues($this -> components[$c]['options'], $this -> name, $this->attr_html->attribute->ldapObject); + } + return $this -> _cache_getSelectListComponentPossibleValues[$c]; + } + + /** + * Retreive value's label of an select_list component + * + * @param[in] $c string The component name + * @param[in] $value string The value + * + * @retval array + **/ + protected function getSelectListComponentValueLabel($c,$value) { + if ($this -> getSelectListComponentPossibleValues($c)) { + foreach ($this -> _cache_getSelectListComponentPossibleValues[$c] as $v => $label) { + if (is_array($label)) { + if (!isset($label['possible_values'])) continue; + foreach ($label['possible_values'] as $vk => $vl) + if ($vk == $$value) return $vl; + } + if ($v == $value) return $label; + } + } + return; + } + + /** + * Retreive LSformElement value from POST data + * + * This method check present of this element's value in POST data and retreive + * it to feed the array passed in paramater. + * + * @param[] array Reference of the array for retreived values + * + * @retval boolean true if value is in POST data, false instead + */ + function getPostData(&$return) { + if($this -> isFreeze()) { + return true; + } + + $count=0; + $end=false; + $return[$this -> name]=array(); + while ($end==false) { + $value=array(); + $parseValue=array(); + $errors=array(); + $unemptyComponents=array(); + foreach ($this -> components as $c => $cconf) { + if (isset($_POST[$this -> name.'__'.$c][$count])) { + $parseValue[$c]=$_POST[$this -> name.'__'.$c][$count]; + if ($cconf['required'] && empty($parseValue[$c])) { + $errors[]=getFData(__('Component %{c} must be defined'),__($cconf['label'])); + continue; + } + if (empty($parseValue[$c])) { + continue; + } + $unemptyComponents[]=$c; + if ($cconf['type']=='select_list') { + if (!$this -> getSelectListComponentValueLabel($c, $parseValue[$c])) { + $errors[]=getFData(__('Invalid value for component %{c}.'),__($cconf['label'])); + } + } + if (is_array($cconf['check_data'])) { + foreach($cconf['check_data'] as $ruleType => $rconf) { + $className='LSformRule_'.$ruleType; + if (LSsession::loadLSclass($className)) { + $r=new $className(); + if (!$r -> validate($parseValue[$c],$rconf,$this)) { + if (isset($rconf['msg'])) { + $errors[]=getFData(__($rconf['msg']),__($cconf['label'])); + } + else { + $errors[]=getFData(__('Invalid value for component %{c}.'),__($cconf['label'])); + } + } + } + else { + $errors[]=getFData(__("Can't validate value of component %{c}."),__($cconf['label'])); + } + } + } + $value[$c]=$parseValue[$c]; + } + else { + // end of value break + $end=true; + break; + } + + } + if (!$end) { + if (!empty($unemptyComponents)) { + foreach($errors as $e) { + $this -> form -> setElementError($this -> attr_html,$e); + } + $return[$this -> name][]=json_encode($value); + } + $count++; + } + } + return true; + } + +} diff --git a/public_html/templates/default/LSformElement_jsonCompositeAttribute.tpl b/public_html/templates/default/LSformElement_jsonCompositeAttribute.tpl new file mode 100644 index 00000000..7c1cccd9 --- /dev/null +++ b/public_html/templates/default/LSformElement_jsonCompositeAttribute.tpl @@ -0,0 +1,7 @@ + diff --git a/public_html/templates/default/LSformElement_jsonCompositeAttribute_field.tpl b/public_html/templates/default/LSformElement_jsonCompositeAttribute_field.tpl new file mode 100644 index 00000000..31030e13 --- /dev/null +++ b/public_html/templates/default/LSformElement_jsonCompositeAttribute_field.tpl @@ -0,0 +1,36 @@ +{if $freeze} + {if isset($parseValue)} + {foreach $components as $c => $cconf} + {if !isset($parseValue[$c])}{continue}{/if} +

+ + {$parseValue[$c].translated} +

+ {/foreach} + {else} + {$noValueTxt} + {/if} +{else} + {foreach $components as $c => $cconf} +

+ + {if $cconf.type=='select_list'} + + {else} + + {/if} +

+ {/foreach} +{/if}