LSattribute :: generateValue() : Fixed bug when generated value is an array.
[ldapsaisie.git] / public_html / includes / class / class.LSform.php
1 <?php
2 /*******************************************************************************
3  * Copyright (C) 2007 Easter-eggs
4  * http://ldapsaisie.labs.libre-entreprise.org
5  *
6  * Author: See AUTHORS file in top-level directory.
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License version 2
10  * as published by the Free Software Foundation.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
20
21 ******************************************************************************/
22
23
24 /**
25  * Formulaire pour LdapSaisie
26  *
27  * Cette classe gère les formulaires
28  *
29  * @author Benjamin Renard <brenard@easter-eggs.com>
30  */
31
32 class LSform {
33   var $ldapObject;
34   var $idForm;
35   var $can_validate = true;
36   var $elements = array();
37   var $_rules = array();
38
39   var $_postData = array();
40  
41   var $_elementsErrors = array();
42   var $_isValidate = false;
43
44   var $_notUpdate = array();
45   
46   var $maxFileSize = NULL;
47
48   /**
49    * Constructeur
50    *
51    * Cette methode construit l'objet et définis la configuration.
52    *
53    * @author Benjamin Renard <brenard@easter-eggs.com>
54    *
55    * @param[in] $idForm [<b>required</b>] string L'identifiant du formulaire
56    * @param[in] $submit string La valeur du bouton submit
57    *
58    * @retval void
59    */ 
60   function LSform (&$ldapObject,$idForm,$submit=NULL){
61     $this -> idForm = $idForm;
62     if (!$submit) {
63       $this -> submit = _("Validate");
64     }
65     else {
66       $this -> submit = $submit;
67     }
68     $this -> ldapObject = $ldapObject;
69     LSsession :: loadLSclass('LSformElement');
70   }
71   
72   /**
73    * Affiche le formualaire
74    *
75    * @author Benjamin Renard <brenard@easter-eggs.com>
76    *
77    * @retval void
78    */ 
79   function display(){
80     if ($this -> idForm == 'view') {
81       self :: loadDependenciesDisplayView();
82     }
83     else {
84       LSsession :: addJSscript('LSformElement_field.js');
85       LSsession :: addJSscript('LSformElement.js');
86       LSsession :: addJSscript('LSform.js');
87       LSsession :: addCssFile('LSform.css');
88     }
89     
90     LSsession :: addHelpInfos(
91       'LSform',
92       array(
93         'addFieldBtn' => _('Add a field to add another values.'),
94         'removeFieldBtn' => _('Delete this field.')
95       )
96     );
97     
98     $GLOBALS['Smarty'] -> assign('LSform_action',$_SERVER['PHP_SELF']);
99     $LSform_header = "\t<input type='hidden' name='validate' value='LSform'/>\n
100     \t<input type='hidden' name='idForm' id='LSform_idform' value='".$this -> idForm."'/>\n
101     \t<input type='hidden' name='LSform_objecttype' id='LSform_objecttype'  value='".$this -> ldapObject -> getType()."'/>\n
102     \t<input type='hidden' name='LSform_objectdn' id='LSform_objectdn'  value='".$this -> ldapObject -> getValue('dn')."'/>\n";
103
104     
105     $LSform_object = array(
106       'type' => $this -> ldapObject -> getType(),
107       'dn' => $this -> ldapObject -> getValue('dn')
108     );
109     $GLOBALS['Smarty'] -> assign('LSform_object',$LSform_object);
110     
111     $layout_config=LSconfig :: get("LSobjects.".$LSform_object['type'].".LSform.layout");
112     if (is_array($layout_config)) {
113       $GLOBALS['Smarty'] -> assign('LSform_layout',$layout_config);
114       $GLOBALS['Smarty'] -> assign('LSform_layout_nofield_label',_('No field.'));
115     }
116     
117     $fields = array();
118     foreach($this -> elements as $element) {
119       $field = array();
120       $field = $element -> getDisplay();
121       if (isset($this -> _elementsErrors[$element -> name])) {
122         $field['errors']= $this -> _elementsErrors[$element -> name];
123       }
124       $fields[$element -> name] = $field;
125     }
126     
127     if ($this -> maxFileSize) {
128       $LSform_header.="\t<input type='hidden' name='MAX_FILE_SIZE' value='".$this -> maxFileSize."'/>\n";
129     }
130     $GLOBALS['Smarty'] -> assign('LSform_header',$LSform_header);
131     
132     $GLOBALS['Smarty'] -> assign('LSform_fields',$fields);
133     if($this -> can_validate) {
134       $GLOBALS['Smarty'] -> assign('LSform_submittxt',$this -> submit);
135     }
136   }
137   
138  /*
139   * Méthode chargeant les dépendances d'affichage d'une LSview
140   * 
141   * @retval void
142   */
143   public static function loadDependenciesDisplayView() {
144     LSsession :: addCssFile('LSform.css');
145     LSsession :: addJSscript('LSform.js');
146     LSsession :: addJSconfigParam('LSview_labels', array(
147       'delete_confirm_text'     => _("Do you really want to delete"),
148       'delete_confirm_title'    => _("Caution"),
149       'delete_confirm_validate'  => _("Delete")
150     ));
151     if (LSsession :: loadLSclass('LSconfirmBox')) {
152       LSconfirmBox :: loadDependenciesDisplay();
153     }
154     LSsession :: addJSscript('LSview.js');
155   }
156   
157   /**
158    * Affiche la vue
159    *
160    * @author Benjamin Renard <brenard@easter-eggs.com>
161    *
162    * @retval void
163    */ 
164   function displayView(){
165     self :: loadDependenciesDisplayView();
166     
167     $LSform_object = array(
168       'type' => $this -> ldapObject -> getType(),
169       'dn' => $this -> ldapObject -> getDn()
170     );
171     $GLOBALS['Smarty'] -> assign('LSform_object',$LSform_object);
172     $fields = array();
173     foreach($this -> elements as $element) {
174       $field = $element -> getDisplay();
175       $fields[$element -> name] = $field;
176     }
177     $GLOBALS['Smarty'] -> assign('LSform_fields',$fields);
178     
179     $layout_config=LSconfig :: get("LSobjects.".$LSform_object['type'].".LSform.layout");
180     if (is_array($layout_config)) {
181       $GLOBALS['Smarty'] -> assign('LSform_layout',$layout_config);
182       $GLOBALS['Smarty'] -> assign('LSform_layout_nofield_label',_('No field.'));
183     }
184   }  
185   
186   /**
187    * Défini l'erreur sur un champ
188    *
189    * @author Benjamin Renard <brenard@easter-eggs.com>
190    *
191    * @param[in] $attr [<b>required</b>] string Le nom du champ
192    * @param[in] $msg Le format du message d'erreur à afficher (pouvant comporter
193    *                 des valeurs %{[n'importe quoi]} qui seront remplacé par le label
194    *                 du champs concerné.
195    *
196    * @retval void
197    */ 
198   function setElementError($attr,$msg=NULL) {
199     if($msg!='') {
200       $msg_error=getFData($msg,$attr->getLabel());
201     }
202     else {
203       $msg_error=getFData(_("%{label} attribute data is not valid."),$attr->getLabel());
204     }
205     $this -> _elementsErrors[$attr->name][]=$msg_error;
206   }
207   
208   /**
209    * Savoir si des erreurs son définie pour un élement du formulaire
210    *
211    * @author Benjamin Renard <brenard@easter-eggs.com>
212    *
213    * @param[in] $element [<b>required</b>] string Le nom de l'élement
214    * 
215    * @retval boolean
216    */ 
217   function definedError($element=NULL) {
218     if ($element) {
219       return isset($this -> _elementsErrors[$element]);
220     }
221     else {
222       return !empty($this -> _elementsErrors);
223     }
224   }
225   
226   /**
227    * Retourne le tableau des erreurs
228    * 
229    * @retval Array array(element => array(errors))
230    */
231   function getErrors() {
232     return $this -> _elementsErrors;
233   }
234   
235   /**
236    * Verifie si le formulaire a été validé et que les données sont valides.
237    *
238    * @author Benjamin Renard <brenard@easter-eggs.com>
239    *
240    * @retval boolean true si le formulaire a été validé et que les données ont été validées, false sinon
241    */ 
242   function validate(){
243     if(!$this -> can_validate)
244       return;
245     if ($this -> isSubmit()) {
246       if (!$this -> getPostData()) {
247         LSerror :: addErrorCode('LSform_01');
248         return;
249       }
250       $this -> setValuesFromPostData();
251       //Validation des données ici !!! ///
252       if (!$this -> checkData()) {
253         return;
254       }
255       LSdebug("Data are checked up");
256       $this -> _isValidate = true;
257       return true;
258     }
259     return false;
260   }
261
262   /**
263    * Vérifier les données du formulaire à partir des régles définis sur les champs
264    *
265    * @author Benjamin Renard <brenard@easter-eggs.com>
266    *
267    * @retval boolean true si toutes la saisie est OK, false sinon
268    */
269   function checkData() {
270     $retval=true;
271     foreach ($this -> _postData as $element => $values) {
272       if(!is_array($values)) {
273         $values=array($values);
274       }
275       if ($this -> elements[$element] -> isRequired()) {
276         if (!$this -> checkRequired($values)) {
277           $this -> setElementError($this -> elements[$element],_("Mandatory field"));
278           $retval=false;
279         }
280       }
281
282       foreach($values as $value) {
283         if (empty($value)) {
284           continue;
285         }
286         if (!is_array($this -> _rules[$element]))
287           continue;
288         LSsession :: loadLSclass('LSformRule');
289         foreach($this -> _rules[$element] as $rule) {
290           $ruleType="LSformRule_".$rule['name'];
291           LSsession :: loadLSclass($ruleType);
292           if (! call_user_func(array( $ruleType,'validate') , $value, $rule['options'], $this -> getElement($element))) {
293             $retval=false;
294             $this -> setElementError($this -> elements[$element],$rule['options']['msg']);
295           }
296         }
297       }
298     }
299     return $retval;
300   }
301
302   /**
303    * Vérifie si au moins une valeur est présente dans le tableau
304    *
305    * @author Benjamin Renard <brenard@easter-eggs.com>
306    *
307    * @param[in] $data array tableau de valeurs
308    *
309    * @retval boolean true si au moins une valeur est présente, false sinon
310    */
311   function checkRequired($data) {
312     foreach($data as $val) {
313       if (!empty($val)||(is_string($val)&&($val=="0")))
314         return true;
315     }
316     return;
317   }
318
319   /**
320    * Verifie si la saisie du formulaire est présente en POST
321    *
322    * @author Benjamin Renard <brenard@easter-eggs.com>
323    *
324    * @retval boolean true si la saisie du formulaire est présente en POST, false sinon
325    */
326   function isSubmit() {
327     if( (isset($_POST['validate']) && ($_POST['validate']=='LSform')) && (isset($_POST['idForm']) && ($_POST['idForm'] == $this -> idForm)) )
328       return true;
329     return;
330   }
331
332   /**
333    * Défini arbitrairement des données en POST
334    * 
335    * @author Benjamin Renard <brenard@easter-eggs.com>
336    * 
337    * @param[in] $data array('attr' => array(values)) Tableau des données du formulaire
338    * @param[in] $consideredAsSubmit Définie si on force le formualaire comme envoyer
339    * 
340    * @retval boolean true si les données ont été définies, false sinon
341    */
342   function setPostData($data,$consideredAsSubmit=false) {
343     if (is_array($data)) {
344       foreach($data as $key => $values) {
345         if (!is_array($values)) {
346           $values = array($values);
347         }
348         $_POST[$key] = $values;
349       }
350       
351       if ($consideredAsSubmit) {
352         $_POST['validate']='LSform';
353         $_POST['idForm']=$this -> idForm;
354       }
355       
356       return true;
357     }
358     return;
359   }
360
361   /**
362    * Récupère les valeurs postées dans le formulaire
363    *
364    * @author Benjamin Renard <brenard@easter-eggs.com>
365    *
366    * @retval boolean true si les valeurs ont bien été récupérées, false sinon.
367    */
368   function getPostData() {
369     foreach($this -> elements as $element_name => $element) {
370       if( !($element -> getPostData($this -> _postData)) ) {
371         LSerror :: addErrorCode('LSform_02',$element_name);
372         return;
373       }
374     }
375     return true;
376   }
377
378   /**
379    * Ajoute un élément au formulaire
380    * 
381    * Ajoute un élément au formulaire et définis les informations le concernant.
382    *
383    * @param[in] $type string Le type de l'élément
384    * @param[in] $name string Le nom de l'élément
385    * @param[in] $label string Le label de l'élément
386    * @param[in] $param mixed Paramètres supplémentaires
387    *
388    * @retval LSformElement
389    */
390   function addElement($type,$name,$label,$params=array(),&$attr_html) {
391     $elementType='LSformElement_'.$type;
392     LSsession :: loadLSclass($elementType);
393     if (!class_exists($elementType)) {
394       LSerror :: addErrorCode('LSform_05',array('type' => $type));  
395       return;
396     }
397     $element=$this -> elements[$name] = new $elementType($this,$name,$label,$params,$attr_html);
398     if ($element) {
399       return $element;
400     }
401     else {
402       unset ($this -> elements[$name]);
403       LSerror :: addErrorCode('LSform_06',array('element' => $name));
404       return;
405     }
406   }
407
408   /**
409    * Ajoute une règle sur un élément du formulaire
410    *
411    * @author Benjamin Renard <brenard@easter-eggs.com>
412    *
413    * @param[in] $element string Le nom de l'élément conserné
414    * @param[in] $rule string Le nom de la règle à ajouter
415    * @param[in] $options array Options (facultative)
416    *
417    * @retval boolean
418    */
419   function addRule($element, $rule, $options=array()) {
420     if ( isset($this ->elements[$element]) ) {
421       if ($this -> isRuleRegistered($rule)) {
422         $this -> _rules[$element][]=array(
423                   'name' => $rule,
424                   'options' => $options
425                   );
426         return true;
427       }
428       else {
429         LSerror :: addErrorCode('LSattribute_03',array('attr' => $element,'rule'=>$rule));      
430         return;
431       }
432     }
433     else {  
434       LSerror :: addErrorCode('LSform_04',array('element' => $element));
435       return;
436     }
437   }
438
439
440
441
442   /**
443    * Définis comme requis un élément
444    *
445    * @author Benjamin Renard <brenard@easter-eggs.com>
446    *
447    * @param[in] $element string Le nom de l'élément conserné
448    *
449    * @retval boolean
450    */
451   function setRequired($element) {
452     if (isset( $this -> elements[$element] ) )
453       return $this -> elements[$element] -> setRequired();
454     else
455       return;
456   }
457
458   /**
459    * Détermine la valider de la règle
460    *
461    * Devra déterminer si la règle passez en paramètre est correcte
462    *
463    * @author Benjamin Renard <brenard@easter-eggs.com>
464    *
465    * @param[in] $element string Le nom de l'élément conserné
466    */
467   function isRuleRegistered($rule) {
468     LSsession :: loadLSclass('LSformRule');
469     LSsession :: loadLSclass('LSformRule_'.$rule);
470     return class_exists('LSformRule_'.$rule);
471   }
472
473   /**
474    * Retourne les valeurs validés du formulaire
475    *
476    * @retval mixed Les valeurs validés du formulaire, ou false si elles ne le sont pas
477    */
478   function exportValues() {
479     if ($this -> _isValidate) {
480       $retval=array();
481       foreach($this -> _postData as $element => $values) {
482         $retval[$element] = $this -> elements[$element] -> exportValues();
483       }
484       return $retval;
485     }
486     else {
487       return;
488     }
489   }
490
491   /**
492    * Retourn un élement du formulaire
493    *
494    * @param[in] string $element Nom de l'élement voulu
495    *
496    * @retval LSformElement L'élement du formulaire voulu
497    */
498   function getElement($element) {
499     return $this -> elements[$element];
500   }
501
502   /**
503    * Défini les valeurs des élements à partir des valeurs postées
504    *
505    * @retval boolean True si les valeurs ont été définies, false sinon.
506    */
507   function setValuesFromPostData() {
508     if (empty($this -> _postData)) {
509       return;
510     }
511     foreach($this -> _postData as $element => $values) {
512       $this -> elements[$element] -> setValueFromPostData($values);
513     }
514     return true;
515   }
516
517   /**
518    * Retourne le code HTML d'un champ vide.
519    * 
520    * @param[in] string Le nom du champ du formulaire
521    *
522    * @retval string Le code HTML du champ vide.
523    */
524   function getEmptyField($element) {
525     $element = $this -> getElement($element);
526     if ($element) {      
527       return $element -> getEmptyField();     
528     }
529     else {
530       return;
531     }
532   }
533   
534   /**
535    * Défini la taille maximal pour les fichiers envoyés par le formualaire
536    * 
537    * @param[in] $size La taille maximal en octets
538    * 
539    * @retval  void
540    **/
541   function setMaxFileSize($size) {
542     $this -> maxFileSize = $size;
543   }
544
545
546   public static function ajax_onAddFieldBtnClick(&$data) {
547     if ((isset($_REQUEST['attribute'])) && (isset($_REQUEST['objecttype'])) && (isset($_REQUEST['objectdn'])) && (isset($_REQUEST['idform'])) && (isset($_REQUEST['fieldId'])) ) {
548       if (LSsession ::loadLSobject($_REQUEST['objecttype'])) {
549         $object = new $_REQUEST['objecttype']();
550         $object -> loadData($_REQUEST['objectdn']);
551         $form = $object -> getForm($_REQUEST['idform']);
552         $emptyField=$form -> getEmptyField($_REQUEST['attribute']);
553         if ( $emptyField ) {
554           $data = array(
555             'html' => $form -> getEmptyField($_REQUEST['attribute']),
556             'fieldId' => $_REQUEST['fieldId'],
557             'fieldtype' => get_class($form -> getElement($_REQUEST['attribute']))
558           );
559         }
560       }
561     }
562   }
563 }
564
565 /**
566  * Error Codes
567  */
568 LSerror :: defineError('LSform_01',
569 _("LSform : Error during the recovery of the values of the form.")
570 );
571 LSerror :: defineError('LSform_02',
572 _("LSform : Error durring the recovery of the value of the field '%{element}'.")
573 );
574 // No longer used
575 /*LSerror :: defineError(203,
576 _("LSform : Data of the field %{element} are not validate.")
577 );*/
578 LSerror :: defineError('LSform_04',
579 _("LSform : The field %{element} doesn't exist.")
580 );
581 LSerror :: defineError('LSform_05',
582 _("LSfom : Field type unknow (%{type}).")
583 );
584 LSerror :: defineError('LSform_06',
585 _("LSform : Error during the creation of the element '%{element}'.")
586 );
587 // No longer used
588 /*LSerror :: defineError(207,
589 _("LSform : No value has been entered into the field '%{element}'.")
590 );*/
591
592 ?>