Add LSattr_html :: jsonCompositeAttribute

This commit is contained in:
Benjamin Renard 2017-05-04 17:31:19 +02:00
commit 5227748259
8 changed files with 477 additions and 0 deletions

View file

@ -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;

View file

@ -2,6 +2,7 @@
<!ENTITY conf-LSattr_html_boolean SYSTEM "LSattr_html_boolean.docbook">
<!ENTITY conf-LSattr_html_date SYSTEM "LSattr_html_date.docbook">
<!ENTITY conf-LSattr_html_image SYSTEM "LSattr_html_image.docbook">
<!ENTITY conf-LSattr_html_jsonCompositeAttribute SYSTEM "LSattr_html_jsonCompositeAttribute.docbook">
<!ENTITY conf-LSattr_html_mail SYSTEM "LSattr_html_mail.docbook">
<!ENTITY conf-LSattr_html_maildir SYSTEM "LSattr_html_maildir.docbook">
<!ENTITY conf-LSattr_html_mailQuota SYSTEM "LSattr_html_mailQuota.docbook">
@ -17,3 +18,5 @@
<!ENTITY conf-LSattr_html_url SYSTEM "LSattr_html_url.docbook">
<!ENTITY conf-LSattr_html_valueWithUnit SYSTEM "LSattr_html_valueWithUnit.docbook">
<!ENTITY conf-LSattr_html_xmpp SYSTEM "LSattr_html_xmpp.docbook">
<!ENTITY LSattr_html_select_list "<link linkend='config-LSattr_html_select_list'>LSattr_html_select_list</link>">

View file

@ -0,0 +1,96 @@
<sect4 id="config-LSattr_html_jsonCompositeAttribute">
<title>LSattr_html_jsonCompositeAttribute</title>
<para>Ce type est utilisé pour la gestion des attributs dont les valeurs sont
des dictionnaires de valeurs encodées aux formats <emphasis>JSON</emphasis>.</para>
<programlisting linenumbering="unnumbered">
<citetitle>Exemple de valeur gérée</citetitle>
<![CDATA[{"component1": "value1", "component2": "value2", "component3": "value3"}]]>
</programlisting>
<para>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;.</para>
<programlisting linenumbering="unnumbered">
<citetitle>Structure</citetitle>...
<![CDATA['html_options' => 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]
)
),
[...]
),
),]]>
...
</programlisting>
<variablelist>
<title>Paramètres de configuration</title>
<varlistentry>
<term>components</term>
<listitem>
<para>Tableau associatif obligatoire contenant en valeur clé, l'identifiant des
composants, correspondant à la clé dans le dictionnaire <emphasis>JSON</emphasis>,
et en valeurs associés, la configuration du composant.</para>
<variablelist>
<varlistentry>
<term>label</term>
<listitem>
<simpara>Le label du composant.</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term>type</term>
<listitem>
<simpara>Le type de valeur du composant. Les types possibles sont
<literal>text</literal> ou <literal>select_list</literal> pour respectivement
soit une valeur saisie librement, soit une valeur sélectionnée parmis une liste
déroulante.</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term>options</term>
<listitem>
<simpara>Dans le cadre d'un composant de type <literal>select_list</literal>, 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 <literal>html_options</literal>.</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term>check_data</term>
<listitem>
<simpara>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.
<link linkend='config-LSattribute-check-data'>Voir la section concernée.</link>
</simpara>
</listitem>
</varlistentry>
</variablelist>
</listitem>
</varlistentry>
</variablelist>
</sect4>

View file

@ -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;
}

View file

@ -0,0 +1,32 @@
<?php
/*******************************************************************************
* Copyright (C) 2007 Easter-eggs
* http://ldapsaisie.labs.libre-entreprise.org
*
* Author: See AUTHORS file in top-level directory.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
******************************************************************************/
/**
* Type d'attribut HTML jsonCompositeAttribute
*
* @author Benjamin Renard <brenard@easter-eggs.com>
*/
class LSattr_html_jsonCompositeAttribute extends LSattr_html {
var $LSformElement_type = 'jsonCompositeAttribute';
}

View file

@ -0,0 +1,268 @@
<?php
/*******************************************************************************
* Copyright (C) 2007 Easter-eggs
* http://ldapsaisie.labs.libre-entreprise.org
*
* Author: See AUTHORS file in top-level directory.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
******************************************************************************/
LSsession :: loadLSclass('LSformElement');
/**
* Element jsonCompositeAttribute for LSform
*
* This classe permit to handle compostie attributes encoded with JSON.
*
* @author Benjamin Renard <brenard@easter-eggs.com>
*/
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;
}
}

View file

@ -0,0 +1,7 @@
<ul class='LSform {if $multiple && !$freeze} LSformElement_multiple{/if} LSformElement_jsonCompositeAttribute' id='{$attr_name}' data-fieldType="{$fieldType}">
{foreach from=$parseValues item=parseValue}
<li>{include file="ls:$fieldTemplate"}</li>
{foreachelse}
<li {if $freeze}class='noValue'{/if}>{include file="ls:$fieldTemplate"}</li>
{/foreach}
</ul>

View file

@ -0,0 +1,36 @@
{if $freeze}
{if isset($parseValue)}
{foreach $components as $c => $cconf}
{if !isset($parseValue[$c])}{continue}{/if}
<p>
<label>{tr msg=$cconf.label} : </label>
<span title="{$parseValue[$c].value}">{$parseValue[$c].translated}</span>
</p>
{/foreach}
{else}
{$noValueTxt}
{/if}
{else}
{foreach $components as $c => $cconf}
<p data-component="{$c}">
<label>{tr msg=$cconf.label}{if $cconf.required}*{/if} :</label>
{if $cconf.type=='select_list'}
<select name='{$attr_name}__{$c}[]'>
{foreach from=$cconf.possible_values key=key item=label}
{if is_array($label)}
{if count($label.possible_values)>0}
<optgroup label="{$label.label}">
{html_options options=$label.possible_values selected=$parseValue[$c].value}
</optgroup>
{/if}
{else}
<option value="{$key}" {if $key == $parseValue[$c].value}selected{/if}>{$label}</option>
{/if}
{/foreach}
</select>
{else}
<input type='text' name='{$attr_name}__{$c}[]' value="{if $parseValue and $parseValue[$c]}{$parseValue[$c].value}{/if}"/>
{/if}
</p>
{/foreach}
{/if}