From 1e2316d76f16e24f9adf415b209695003c778d4f Mon Sep 17 00:00:00 2001 From: Benjamin Renard Date: Tue, 26 Feb 2008 17:40:05 +0000 Subject: [PATCH] =?UTF-8?q?-=20Ajout=20du=20support=20des=20images=20(LSat?= =?UTF-8?q?tr=5Fhtml=20/=20LSformElement=20/=20LSformRule)=20-=20Ajout=20d?= =?UTF-8?q?u=20principe=20de=20relations=20entre=20type=20d'objets=20(LSre?= =?UTF-8?q?lation)=20=20=20Exemple=20:=20Utilisateur=20appartenant=20?= =?UTF-8?q?=C3=A0=20un=20groupe=20-=20Ajout=20du=20LSformElement=5Fselect?= =?UTF-8?q?=5Fobject=20:=20=20=20S=C3=A9lection=20d'un=20objet=20=C3=A0=20?= =?UTF-8?q?travers=20une=20interface=20plus=20conviviale=20qu'une=20liste?= =?UTF-8?q?=20=20=20d=C3=A9roulante.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- svn-commit.tmp | 4 - .../LSobjects/config.LSobjects.LSeegroup.php | 10 +- .../LSobjects/config.LSobjects.LSeepeople.php | 45 +++ trunk/conf/config.error_code.php | 12 + trunk/conf/config.inc.php | 17 +- trunk/includes/class/class.LSattr_html.php | 11 + .../class/class.LSattr_html_image.php | 53 +++ .../class/class.LSattr_html_select_list.php | 48 +-- .../class/class.LSattr_html_select_object.php | 166 +++++++++ trunk/includes/class/class.LSattr_ldap.php | 9 - .../class/class.LSattr_ldap_image.php | 32 ++ trunk/includes/class/class.LSattribute.php | 3 +- trunk/includes/class/class.LSerror.php | 49 ++- trunk/includes/class/class.LSform.php | 43 ++- trunk/includes/class/class.LSformElement.php | 4 +- .../class/class.LSformElement_image.php | 106 ++++++ .../class.LSformElement_select_object.php | 95 +++++ trunk/includes/class/class.LSformRule.php | 21 +- .../class/class.LSformRule_alphanumeric.php | 19 +- .../class/class.LSformRule_compare.php | 29 +- .../includes/class/class.LSformRule_email.php | 27 +- .../class/class.LSformRule_imagefile.php | 68 ++++ .../class/class.LSformRule_imagefilesize.php | 63 ++++ .../class/class.LSformRule_imagesize.php | 74 ++++ .../class/class.LSformRule_lettersonly.php | 19 +- .../class/class.LSformRule_maxlength.php | 27 +- .../class/class.LSformRule_minlength.php | 27 +- .../class/class.LSformRule_nonzero.php | 21 +- .../class/class.LSformRule_nopunctuation.php | 21 +- .../class/class.LSformRule_numeric.php | 21 +- .../class/class.LSformRule_rangelength.php | 29 +- .../includes/class/class.LSformRule_regex.php | 47 +-- .../class/class.LSformRule_required.php | 17 +- trunk/includes/class/class.LSldap.php | 26 +- trunk/includes/class/class.LSldapObject.php | 12 +- .../class/class.LSobjects.LSeegroup.php | 150 +++++++- trunk/includes/class/class.LSsession.php | 171 ++++++++- trunk/includes/js/LSdefault.js | 38 +- trunk/includes/js/LSform.js | 138 ++++++- trunk/includes/js/LSrelation.js | 152 ++++++++ trunk/includes/js/LSselect.js | 92 +++++ trunk/includes/js/LSsession_login.js | 79 ++-- trunk/includes/js/LSsmoothbox.js | 180 +++++++++ trunk/index_ajax.php | 244 ++++++++++++- trunk/modify.php | 8 +- trunk/select.php | 148 ++++++++ trunk/templates/LSrelations.tpl | 13 + trunk/templates/accueil.tpl | 42 +-- trunk/templates/base.tpl | 49 --- trunk/templates/blank.tpl | 20 + trunk/templates/bottom.tpl | 5 + trunk/templates/create.tpl | 37 +- trunk/templates/css/LSform.css | 29 +- trunk/templates/css/LSsmoothbox.css | 28 ++ trunk/templates/css/base.css | 107 +++++- trunk/templates/css/base_print.css | 15 + trunk/templates/empty.tpl | 36 +- trunk/templates/images/imgbroken.png | Bin 0 -> 15374 bytes trunk/templates/images/loading.gif | Bin 0 -> 8238 bytes trunk/templates/images/person.png | Bin 0 -> 22391 bytes trunk/templates/images/zoom.png | Bin 0 -> 935 bytes trunk/templates/modify.tpl | 55 +-- trunk/templates/question.tpl | 36 +- trunk/templates/select.tpl | 17 + trunk/templates/select_table.tpl | 23 ++ trunk/templates/top.tpl | 30 ++ trunk/templates/view.tpl | 50 +-- trunk/templates/viewList.tpl | 54 +-- trunk/view.php | 345 +++++++++++------- 69 files changed, 2917 insertions(+), 749 deletions(-) delete mode 100644 svn-commit.tmp create mode 100644 trunk/includes/class/class.LSattr_html_image.php create mode 100644 trunk/includes/class/class.LSattr_html_select_object.php create mode 100644 trunk/includes/class/class.LSattr_ldap_image.php create mode 100644 trunk/includes/class/class.LSformElement_image.php create mode 100644 trunk/includes/class/class.LSformElement_select_object.php create mode 100644 trunk/includes/class/class.LSformRule_imagefile.php create mode 100644 trunk/includes/class/class.LSformRule_imagefilesize.php create mode 100644 trunk/includes/class/class.LSformRule_imagesize.php create mode 100644 trunk/includes/js/LSrelation.js create mode 100644 trunk/includes/js/LSselect.js create mode 100644 trunk/includes/js/LSsmoothbox.js create mode 100644 trunk/select.php create mode 100644 trunk/templates/LSrelations.tpl delete mode 100644 trunk/templates/base.tpl create mode 100644 trunk/templates/blank.tpl create mode 100644 trunk/templates/bottom.tpl create mode 100644 trunk/templates/css/LSsmoothbox.css create mode 100644 trunk/templates/css/base_print.css create mode 100644 trunk/templates/images/imgbroken.png create mode 100644 trunk/templates/images/loading.gif create mode 100755 trunk/templates/images/person.png create mode 100644 trunk/templates/images/zoom.png create mode 100644 trunk/templates/select.tpl create mode 100644 trunk/templates/select_table.tpl create mode 100644 trunk/templates/top.tpl diff --git a/svn-commit.tmp b/svn-commit.tmp deleted file mode 100644 index e9a71ee3..00000000 --- a/svn-commit.tmp +++ /dev/null @@ -1,4 +0,0 @@ -Start. ---This line, and those below, will be ignored-- - -A . diff --git a/trunk/conf/LSobjects/config.LSobjects.LSeegroup.php b/trunk/conf/LSobjects/config.LSobjects.LSeegroup.php index d49eecf0..a91e9205 100644 --- a/trunk/conf/LSobjects/config.LSobjects.LSeegroup.php +++ b/trunk/conf/LSobjects/config.LSobjects.LSeegroup.php @@ -80,7 +80,7 @@ $GLOBALS['LSobjects']['LSeegroup'] = array ( 'uniqueMember' => array ( 'label' => _('Membres'), 'ldap_type' => 'ascii', - 'html_type' => 'select_list', + 'html_type' => 'select_object', 'required' => 0, 'multiple' => 1, 'validation' => array ( @@ -97,6 +97,14 @@ $GLOBALS['LSobjects']['LSeegroup'] = array ( 'modify' => 1, 'create' => 1 ), + 'selectable_object' => array( + 'object_type' => 'LSeepeople', // Nom de l'objet à lister + 'display_attribute' => '%{cn} (%{uidNumber})', // Spécifie le attributs à lister pour le choix, + // si non définie => utilisation du 'select_display_attrs' + // de la définition de l'objet + + 'value_attribute' => '%{dn}', // Spécifie le attributs dont la valeur sera retournée par + ), 'possible_values' => array( 'OTHER_OBJECT' => array( 'object_type' => 'LSeepeople', // Nom de l'objet à lister diff --git a/trunk/conf/LSobjects/config.LSobjects.LSeepeople.php b/trunk/conf/LSobjects/config.LSobjects.LSeepeople.php index 5d0b329c..af94fb06 100644 --- a/trunk/conf/LSobjects/config.LSobjects.LSeepeople.php +++ b/trunk/conf/LSobjects/config.LSobjects.LSeepeople.php @@ -33,6 +33,19 @@ $GLOBALS['LSobjects']['LSeepeople'] = array ( 'after_save' => 'valid', 'select_display_attrs' => '%{cn}', 'label' => _('Utilisateurs'), + 'relations' => array( + 'groups' => array( + 'label' => _('Appartient aux groupes...'), + 'LSobject' => 'LSeegroup', + 'list_function' => 'listUserGroups', + 'update_function' => 'updateUserGroups', + 'remove_function' => 'removeMember', + 'rights' => array( + 'self' => 'r', + 'admin' => 'w' + ) + ) + ), // Attributes 'attrs' => array ( 'uid' => array ( @@ -426,6 +439,38 @@ $GLOBALS['LSobjects']['LSeepeople'] = array ( 'form' => array ( 'modify' => 0 ) + ), + 'jpegPhoto' => array ( + 'label' => _('Photo'), + 'ldap_type' => 'image', + 'html_type' => 'image', + 'required' => 0, + 'view' => 0, + 'check_data' => array ( + 'imagesize' => array( + 'msg' => _("La taille de l'image n'est pas valide."), + 'param' => array( + 'maxWidth' => 2000 + ) + ), + 'imagefilesize' => array( + 'msg' => _("La taille du fichier image n'est pas valide."), + 'param' => array( + 'maxSize' => 3000000 // taille du fichier en octets + ) + ), + 'imagefile' => array( + 'msg' => _("Le type du fichier n'est pas valide.") + ) + ), + 'form' => array ( + 'modify' => 1 + ), + 'rights' => array( + 'self' => 'w', + 'user' => 'r', + 'admin' => 'w' + ) ) ) ); diff --git a/trunk/conf/config.error_code.php b/trunk/conf/config.error_code.php index d34348ff..cba009f3 100644 --- a/trunk/conf/config.error_code.php +++ b/trunk/conf/config.error_code.php @@ -246,6 +246,18 @@ $GLOBALS['LSerror_code'] = array ( 1012 => array ( 'msg' => _("LSsession : Des informations sont manquantes pour l'affichage de cette page."), 'level' => 'c' + ), + 1013 => array ( + 'msg' => _("LSrelations : La fonction de listage pour la relation %{relation} est inconnu."), + 'level' => 'c' + ), + 1014 => array ( + 'msg' => _("LSrelations : La fonction de mise à jour pour la relation %{relation} est inconnu."), + 'level' => 'c' + ), + 1015 => array ( + 'msg' => _("LSrelations : Une erreur s'est produite durant la mise a jour de la relation %{relation}."), + 'level' => 'c' ) ); diff --git a/trunk/conf/config.inc.php b/trunk/conf/config.inc.php index c866b6b6..31d81fe3 100644 --- a/trunk/conf/config.inc.php +++ b/trunk/conf/config.inc.php @@ -80,6 +80,10 @@ $GLOBALS['LSconfig'] = array( //Debug $GLOBALS['LSdebug']['active'] = true; +define('NB_LSOBJECT_LIST',2); + +define('MAX_SEND_FILE_SIZE',2000000); + // Définitions des locales $textdomain = 'ldapsaisie'; bindtextdomain($textdomain, '/var/www/ldapsaisie/trunk/l10n'); @@ -93,12 +97,21 @@ define('LS_CLASS_DIR', LS_INCLUDE_DIR .'class/'); define('LS_LIB_DIR', LS_INCLUDE_DIR .'libs/'); define('LS_ADDONS_DIR', LS_INCLUDE_DIR .'addons/'); define('LS_JS_DIR', LS_INCLUDE_DIR .'js/'); +define('LS_TMP_DIR', 'tmp/'); // Javascript $GLOBALS['defaultJSscipts']=array( 'mootools.js', - 'LSdefault.js', - 'Debugger.js' + 'LSdefault.js' ); +if ($GLOBALS['LSdebug']['active']) { + $GLOBALS['defaultJSscipts'][]='Debugger.js'; +} + +// PHP values +ini_set( 'magic_quotes_gpc', 'off' ); +ini_set( 'magic_quotes_sybase', 'off' ); +ini_set( 'magic_quotes_runtime', 'off' ); + ?> diff --git a/trunk/includes/class/class.LSattr_html.php b/trunk/includes/class/class.LSattr_html.php index 17cafeb2..832257b4 100644 --- a/trunk/includes/class/class.LSattr_html.php +++ b/trunk/includes/class/class.LSattr_html.php @@ -80,6 +80,17 @@ class LSattr_html { function addToForm (&$form,$idForm,$data=NULL) { $GLOBALS['LSerror'] -> addErrorCode(101,$this -> name); } + + /** + * Effectue les tâches nécéssaires au moment du rafraichissement du formulaire + * + * @param[in] $data mixed La valeur de l'attribut + * + * @retval mixed La valeur formatée de l'attribut + **/ + function refreshForm($data) { + return $data; + } } ?> diff --git a/trunk/includes/class/class.LSattr_html_image.php b/trunk/includes/class/class.LSattr_html_image.php new file mode 100644 index 00000000..018f3770 --- /dev/null +++ b/trunk/includes/class/class.LSattr_html_image.php @@ -0,0 +1,53 @@ + + */ +class LSattr_html_image extends LSattr_html { + + /** + * Ajoute l'attribut au formualaire passer en paramètre + * + * @param[in] &$form LSform Le formulaire + * @param[in] $idForm L'identifiant du formulaire + * @param[in] $data Valeur du champs du formulaire + * + * @retval LSformElement L'element du formulaire ajouté + */ + function addToForm (&$form,$idForm,$data=NULL) { + $element=$form -> addElement('image', $this -> name, $this -> config['label'],$this -> config); + if(!$element) { + $GLOBALS['LSerror'] -> addErrorCode(206,$this -> name); + return; + } + if ($data) { + $element -> setValue($data); + } + return $element; + } + +} + +?> diff --git a/trunk/includes/class/class.LSattr_html_select_list.php b/trunk/includes/class/class.LSattr_html_select_list.php index a06392ba..a4a1f1e2 100644 --- a/trunk/includes/class/class.LSattr_html_select_list.php +++ b/trunk/includes/class/class.LSattr_html_select_list.php @@ -27,38 +27,38 @@ */ class LSattr_html_select_list extends LSattr_html{ - /** - * Ajoute l'attribut au formualaire passer en paramètre - * - * @param[in] &$form LSform Le formulaire - * @param[in] $idForm L'identifiant du formulaire - * @param[in] $data Valeur du champs du formulaire - * - * @retval LSformElement L'element du formulaire ajouté - */ + /** + * Ajoute l'attribut au formualaire passer en paramètre + * + * @param[in] &$form LSform Le formulaire + * @param[in] $idForm L'identifiant du formulaire + * @param[in] $data Valeur du champs du formulaire + * + * @retval LSformElement L'element du formulaire ajouté + */ function addToForm (&$form,$idForm,$data=NULL) { /*if (count($data)>1) { $GLOBALS['LSerror'] -> addErrorCode(103,'select_list'); return; }*/ $possible_values=$this -> getPossibleValues(); - $this -> config['text_possible_values'] = $possible_values; + $this -> config['text_possible_values'] = $possible_values; $element=$form -> addElement('select', $this -> name, $this -> config['label'],$this -> config); - if(!$element) { - $GLOBALS['LSerror'] -> addErrorCode(206,$this -> name); - return; - } - if ($data) { - $element -> setValue($data); - } + if(!$element) { + $GLOBALS['LSerror'] -> addErrorCode(206,$this -> name); + return; + } + if ($data) { + $element -> setValue($data); + } // Mise en place de la regle de verification des donnees $regex_check_data='/'; foreach ($possible_values as $val => $text) { - if($regex_check_data=='/') - $regex_check_data.='^'.preg_quote($val,'/').'$'; - else - $regex_check_data.='|^'.preg_quote($val,'/').'$'; + if($regex_check_data=='/') + $regex_check_data.='^'.preg_quote($val,'/').'$'; + else + $regex_check_data.='|^'.preg_quote($val,'/').'$'; } $regex_check_data.='/'; debug($this -> name.' : < '.$regex_check_data." >
",$GLOBALS['debug_stat']); @@ -74,7 +74,7 @@ class LSattr_html_select_list extends LSattr_html{ * * @retval array Tableau associatif des valeurs possible de la liste avec en clé * la valeur des balises option et en valeur ce qui sera affiché. - */ + */ function getPossibleValues() { $retInfos = array(); if (isset($this -> config['possible_values'])) { @@ -104,8 +104,8 @@ class LSattr_html_select_list extends LSattr_html{ } } else { - $val_name=$this->attribute->ldapObject->getFData($val_name); - $val=$this->attribute->ldapObject->getFData($val); + $val_name=$this->attribute->ldapObject->getFData($val_name); + $val=$this->attribute->ldapObject->getFData($val); $retInfos[$val_name]=$val; } } diff --git a/trunk/includes/class/class.LSattr_html_select_object.php b/trunk/includes/class/class.LSattr_html_select_object.php new file mode 100644 index 00000000..54d0cac9 --- /dev/null +++ b/trunk/includes/class/class.LSattr_html_select_object.php @@ -0,0 +1,166 @@ + + */ +class LSattr_html_select_object extends LSattr_html{ + + /** + * Ajoute l'attribut au formualaire passer en paramètre + * + * @param[in] &$form LSform Le formulaire + * @param[in] $idForm L'identifiant du formulaire + * @param[in] $data Valeur du champs du formulaire + * + * @retval LSformElement L'element du formulaire ajouté + */ + function addToForm (&$form,$idForm,$data=NULL) { + $this -> config['attrObject'] = $this; + $element=$form -> addElement('select_object', $this -> name, $this -> config['label'],$this -> config,$this); + if(!$element) { + $GLOBALS['LSerror'] -> addErrorCode(206,$this -> name); + return; + } + if ($data) { + $values=$this -> getValues($data); + if ($values) { + $element -> setValue($values); + } + } + $element -> setSelectableObject($this -> config['selectable_object']['object_type']); + return $element; + } + + function refreshForm($data) { + return $this -> getValues($data); + } + + /** + * Retourne un tableau des valeurs possibles de la liste + * + * @param[in] mixed Tableau des valeurs de l'attribut + * + * @author Benjamin Renard + * + * @retval array Tableau associatif des valeurs possible de la liste avec en clé + * la valeur des balises option et en valeur ce qui sera affiché. + */ + function getValues($values=NULL) { + $retInfos = array(); + if (isset($this -> config['selectable_object'])) { + $conf=$this -> config['selectable_object']; + if (!isset($conf['object_type'])) { + $GLOBALS['LSerror'] -> addErrorCode(102,$this -> name); + break; + } + + if (is_array($values)) { + if(($conf['value_attribute']=='dn')||($conf['value_attribute']=='%{dn}')) { + $list=array(); + foreach($values as $dn) { + $obj=new $conf['object_type'](); + if ($obj -> loadData($dn)) { + $list[]=$obj; + } + } + } + else { + $filter='(|'; + foreach($values as $val) { + $filter.='('.$conf['value_attribute'].'='.$val.')'; + } + $filter.=')'; + debug($filter); + $obj = new $conf['object_type'](); + $list = $obj -> listObjects($filter); + } + if(($conf['value_attribute']=='dn')||($conf['value_attribute']=='%{dn}')) { + for($i=0;$i dn]=$list[$i] -> getDisplayValue($conf['display_attribute']); + $DNs[]=$list[$i] -> dn; + } + } + else { + for($i=0;$i attrs[$val['value_attribute']] -> getValue()]=$list[$i] -> getDisplayValue($conf['display_attribute']); + $DNs[]=$list[$i] -> dn; + } + } + } + else { + debug($values); + return false; + } + $_SESSION['LSselect'][$conf['object_type']]=$DNs; + return $retInfos; + } + return false; + + } + + + /** + * Retourne un tableau des valeurs de l'attribut à partir de la variable session + * + * @author Benjamin Renard + * + * @retval array Tableau associatif des valeurs possible de la liste avec en clé + * la valeur des balises option et en valeur ce qui sera affiché. + */ + function getValuesFromSession() { + $retInfos = array(); + if (isset($this -> config['selectable_object'])) { + $conf=$this -> config['selectable_object']; + if (!isset($conf['object_type'])) { + $GLOBALS['LSerror'] -> addErrorCode(102,$this -> name); + break; + } + + if(is_array($_SESSION['LSselect'][$conf['object_type']])) { + foreach($_SESSION['LSselect'][$conf['object_type']] as $dn) { + $obj = new $conf['object_type'](); + if ($obj->loadData($dn)) { + if(($conf['value_attribute']=='dn')||($conf['value_attribute']=='%{dn}')) { + $retInfos[$obj -> dn]=$obj -> getDisplayValue($conf['display_attribute']); + } + else { + $retInfos[$obj -> attrs[$val['value_attribute']] -> getValue()]=$obj -> getDisplayValue($conf['display_attribute']); + } + $DNs[]=$dn; + } + } + } + else { + return false; + } + $_SESSION['LSselect'][$conf['object_type']]=$DNs; + return $retInfos; + } + return false; + } + +} + +?> diff --git a/trunk/includes/class/class.LSattr_ldap.php b/trunk/includes/class/class.LSattr_ldap.php index fa19e846..93745220 100644 --- a/trunk/includes/class/class.LSattr_ldap.php +++ b/trunk/includes/class/class.LSattr_ldap.php @@ -68,18 +68,9 @@ class LSattr_ldap { * * @retval mixed La valeur d'affichage de l'attribut */ - function getDisplayValue($data) { return $data; } - - function __sleep() { - return ( array_keys( get_object_vars( &$this ) ) ); - } - - function __wakeup() { - return true; - } } ?> diff --git a/trunk/includes/class/class.LSattr_ldap_image.php b/trunk/includes/class/class.LSattr_ldap_image.php new file mode 100644 index 00000000..297ab3e9 --- /dev/null +++ b/trunk/includes/class/class.LSattr_ldap_image.php @@ -0,0 +1,32 @@ + + */ +class LSattr_ldap_image extends LSattr_ldap { + // \\ +} + +?> diff --git a/trunk/includes/class/class.LSattribute.php b/trunk/includes/class/class.LSattribute.php index 4aaf5785..b7b8aed1 100644 --- a/trunk/includes/class/class.LSattribute.php +++ b/trunk/includes/class/class.LSattribute.php @@ -316,7 +316,8 @@ class LSattribute { function refreshForm(&$form,$idForm) { if(isset($this -> config['form'][$idForm])) { $form_element = &$form -> getElement($this -> name); - return $form_element -> setValue($this -> getFormVal()); + $values = $this -> html -> refreshForm($this -> getFormVal()); + return $form_element -> setValue($values); } return true; } diff --git a/trunk/includes/class/class.LSerror.php b/trunk/includes/class/class.LSerror.php index be5f063b..b8c7dc34 100644 --- a/trunk/includes/class/class.LSerror.php +++ b/trunk/includes/class/class.LSerror.php @@ -36,7 +36,7 @@ class LSerror { * @author Benjamin Renard * * @retval void - */ + */ function LSerror() { $errors = array(); } @@ -53,7 +53,7 @@ class LSerror { * dans le fichier 'error_code.php'. * * @retval void - */ + */ function addErrorCode($code=-1,$msg='') { $this -> errors[]=array($code,$msg); } @@ -64,7 +64,7 @@ class LSerror { * @author Benjamin Renard * * @retval void - */ + */ function stop(){ $this -> display(); exit(1); @@ -78,11 +78,11 @@ class LSerror { * @retval void */ function display() { - $errors = $this -> getErrors(); - if ($errors) { - $GLOBALS['Smarty'] -> assign('LSerrors',$errors); - } - /*if(!empty($this -> errors)) { + $errors = $this -> getErrors(); + if ($errors) { + $GLOBALS['Smarty'] -> assign('LSerrors',$errors); + } + /*if(!empty($this -> errors)) { print "

"._('Erreurs')."

\n"; foreach ($this -> errors as $error) { echo "(Code ".$error[0].") ".getFData($GLOBALS['LSerror_code'][$error[0]]['msg'],$error[1])."
\n"; @@ -92,20 +92,31 @@ class LSerror { /** * Retourne le texte des erreurs - * - * @author Benjamin Renard - * - * @retvat string Le texte des erreurs - */ - function getErrors() { - if(!empty($this -> errors)) { + * + * @author Benjamin Renard + * + * @retvat string Le texte des erreurs + */ + function getErrors() { + if(!empty($this -> errors)) { foreach ($this -> errors as $error) { $txt.="(Code ".$error[0].") ".getFData($GLOBALS['LSerror_code'][$error[0]]['msg'],$error[1])."
\n"; } - return $txt; - } - return; - } + return $txt; + } + return; + } + + /** + * Définir si il y a des erreurs + * + * @author Benjamin Renard + * + * @retvat boolean + */ + function errorsDefined() { + return !empty($this -> errors); + } } ?> diff --git a/trunk/includes/class/class.LSform.php b/trunk/includes/class/class.LSform.php index 5713f781..c7dd1626 100644 --- a/trunk/includes/class/class.LSform.php +++ b/trunk/includes/class/class.LSform.php @@ -42,6 +42,8 @@ class LSform { var $_isValidate = false; var $_notUpdate = array(); + + var $maxFileSize = NULL; /** * Constructeur @@ -81,8 +83,9 @@ class LSform { $LSform_header = "\t\n \t\n \t\n - \t"; - $GLOBALS['Smarty'] -> assign('LSform_header',$LSform_header); + \t\n"; + + $LSform_object = array( 'type' => $this -> ldapObject -> getType(), 'dn' => $this -> ldapObject -> getValue('dn') @@ -97,6 +100,12 @@ class LSform { } $fields[] = $field; } + + if ($this -> maxFileSize) { + $LSform_header.="\t\n"; + } + $GLOBALS['Smarty'] -> assign('LSform_header',$LSform_header); + $GLOBALS['Smarty'] -> assign('LSform_fields',$fields); if($this -> can_validate) { $GLOBALS['Smarty'] -> assign('LSform_submittxt',$this -> submit); @@ -147,6 +156,19 @@ class LSform { $this -> _elementsErrors[$attr->name][]=$msg_error; } + /** + * Savoir si des erreurs son définie pour un élement du formulaire + * + * @author Benjamin Renard + * + * @param[in] $element [required] string Le nom de l'élement + * + * @retval boolean + */ + function definedError($element) { + return isset($this -> _elementsErrors[$element]); + } + /** * Verifie si le formulaire a été validé et que les données sont valides. * @@ -204,7 +226,7 @@ class LSform { foreach($this -> _rules[$element] as $rule) { $ruleType="LSformRule_".$rule['name']; $GLOBALS['LSsession'] -> loadLSclass($ruleType); - if (! call_user_func(array( $ruleType,'validate') , $value, $rule['options'])) { + if (! call_user_func(array( $ruleType,'validate') , $value, $rule['options'], $this -> getElement($element))) { $retval=false; $this -> setElementError($this -> elements[$element],$rule['options']['msg']); } @@ -273,14 +295,14 @@ class LSform { * * @retval LSformElement */ - function addElement($type,$name,$label,$params=array()) { + function addElement($type,$name,$label,$params=array(),&$attr_html=NULL) { $elementType='LSformElement_'.$type; $GLOBALS['LSsession'] -> loadLSclass($elementType); if (!class_exists($elementType)) { $GLOBALS['LSerror'] -> addErrorCode(205,array('type' => $type)); return; } - $element=$this -> elements[$name] = new $elementType($this,$name,$label,$params); + $element=$this -> elements[$name] = new $elementType($this,$name,$label,$params,$attr_html); if ($element) { return $element; } @@ -412,6 +434,17 @@ class LSform { return; } } + + /** + * Défini la taille maximal pour les fichiers envoyés par le formualaire + * + * @param[in] $size La taille maximal en octets + * + * @retval void + **/ + function setMaxFileSize($size) { + $this -> maxFileSize = $size; + } } diff --git a/trunk/includes/class/class.LSformElement.php b/trunk/includes/class/class.LSformElement.php index 6ddcc885..dd6bb968 100644 --- a/trunk/includes/class/class.LSformElement.php +++ b/trunk/includes/class/class.LSformElement.php @@ -37,6 +37,7 @@ class LSformElement { var $values = array(); var $_required = false; var $_freeze = false; + var $attr_html; /** * Constructeur @@ -52,11 +53,12 @@ class LSformElement { * * @retval true */ - function LSformElement (&$form, $name, $label, $params){ + function LSformElement (&$form, $name, $label, $params,&$attr_html){ $this -> name = $name; $this -> label = $label; $this -> params = $params; $this -> form = $form; + $this -> attr_html = $attr_html; return true; } diff --git a/trunk/includes/class/class.LSformElement_image.php b/trunk/includes/class/class.LSformElement_image.php new file mode 100644 index 00000000..1fbe7293 --- /dev/null +++ b/trunk/includes/class/class.LSformElement_image.php @@ -0,0 +1,106 @@ + + */ + +class LSformElement_image extends LSformElement { + + var $postImage = NULL; + var $tmp_file = 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 = true; + if (!$this -> isFreeze()) { + $id=$this -> name.'_'.rand(); + $return = $this -> getLabelInfos(); + $return['html'] = "\n"; + $this -> form -> setMaxFileSize(MAX_SEND_FILE_SIZE); + } + + if (!empty($this -> values[0])) { + $img_path = $GLOBALS['LSsession'] -> getTmpFile($this -> values[0]); + $GLOBALS['Smarty'] -> assign('LSform_image',array( + 'img' => $img_path, + 'id' => $id, + )); + if (!$this -> isFreeze()) { + $GLOBALS['Smarty'] -> assign('LSform_image_actions','delete'); + } + + if ($this -> form -> definedError($this -> name)) { + $GLOBALS['Smarty'] -> assign('LSform_image_errors',true); + } + } + return $return; + } + + /** + * Recupère la valeur de l'élement passée en POST + * + * Cette méthode vérifie la présence en POST de la valeur de l'élément et la récupère + * pour la mettre dans le tableau passer en paramètre avec en clef le nom de l'élément + * + * @param[] array Pointeur sur le tableau qui recupèrera la valeur. + * + * @retval boolean true si la valeur est présente en POST, false sinon + */ + function getPostData(&$return) { + if($this -> isFreeze()) { + return true; + } + + if (is_uploaded_file($_FILES[$this -> name]['tmp_name'])) { + debug($_FILES[$this -> name]['tmp_name']); + $fp = fopen($_FILES[$this -> name]['tmp_name'], "r"); + $buf = fread($fp, filesize($_FILES[$this -> name]['tmp_name'])); + fclose($fp); + $tmp_file = LS_TMP_DIR.$this -> name.'_'.rand().'.tmp'; + if (move_uploaded_file($_FILES[$this -> name]['tmp_name'],$tmp_file)) { + $GLOBALS['LSsession'] -> addTmpFile($buf,$tmp_file); + } + $return[$this -> name][0] = $buf; + } + else { + if (isset($_POST[$this -> name.'_delete'])) { + $return[$this -> name][0]=''; + } + } + return true; + } +} + +?> diff --git a/trunk/includes/class/class.LSformElement_select_object.php b/trunk/includes/class/class.LSformElement_select_object.php new file mode 100644 index 00000000..f4954f9d --- /dev/null +++ b/trunk/includes/class/class.LSformElement_select_object.php @@ -0,0 +1,95 @@ + + */ + +class LSformElement_select_object extends LSformElement { + + /* + * Retourn les infos d'affichage de l'élément + * + * Cette méthode retourne les informations d'affichage de l'élement + * + * @retval array + */ + function getDisplay($refresh=NULL){ + if ($refresh) { + $this -> values = $this -> attr_html -> getValuesFromSession(); + } + $return = $this -> getLabelInfos(); + // value + $id=rand(); + + + if (!$this -> isFreeze()) { + $addBtn="
  • + "._('Modifier')."\n + \n +
  • \n"; + $delete=" "._("; + $class='LSformElement_select_object'; + } + else { + $class=''; + $delete=''; + $addBtn=''; + } + + $return['html']="
      \n"; + $return['html'].=$addBtn; + foreach ($this -> values as $value => $txt) { + $return['html'].="
    • ".$txt."$delete
    • "; + } + $return['html'].="
    \n"; + if (!$this -> isFreeze()) { + $GLOBALS['LSsession'] -> addJSscript('LSform.js'); + $GLOBALS['LSsession'] -> addJSscript('LSselect.js'); + $GLOBALS['LSsession'] -> addJSscript('LSsmoothbox.js'); + $GLOBALS['LSsession'] -> addCssFile('LSsmoothbox.css'); + } + return $return; + } + + /** + * Défini le type d'objet sélectionnable + * + * @param[in] $object string Le type d'object + * + * @retval void + **/ + function setSelectableObject($object) { + $this -> selectableObject = $object; + } + + + +} + +?> diff --git a/trunk/includes/class/class.LSformRule.php b/trunk/includes/class/class.LSformRule.php index dbcaff32..c129740d 100644 --- a/trunk/includes/class/class.LSformRule.php +++ b/trunk/includes/class/class.LSformRule.php @@ -29,22 +29,23 @@ class LSformRule { /** * Constructeur - * - * @author Benjamin Renard * - */ + * + * @author Benjamin Renard * + */ function LSformRule () { return true; } /** * Validation de données - * - * @param mixed $value Données à valider - * @param array $options Options de validation - * - * @return boolean True si les données sont valide, False sinon. - */ - function validate($value,$options=NULL) { + * + * @param mixed $value Données à valider + * @param array $options Options de validation + * @param object $formElement L'objet formElement attaché + * + * @return boolean True si les données sont valide, False sinon. + */ + function validate($value,$options=NULL,$formElement) { return true; } } diff --git a/trunk/includes/class/class.LSformRule_alphanumeric.php b/trunk/includes/class/class.LSformRule_alphanumeric.php index 7ec64f50..cb584fc3 100644 --- a/trunk/includes/class/class.LSformRule_alphanumeric.php +++ b/trunk/includes/class/class.LSformRule_alphanumeric.php @@ -29,16 +29,17 @@ class LSformRule_alphanumeric extends LSformRule { /** * Vérification de la valeur. - * - * @param string $value Value à vérifier - * @param array $options Options de validation (inutile ici) - * - * @return boolean true si la valeur est valide, false sinon - */ - function validate ($value,$options=array()) { + * + * @param string $value Value à vérifier + * @param array $options Options de validation (inutile ici) + * @param object $formElement L'objet formElement attaché + * + * @return boolean true si la valeur est valide, false sinon + */ + function validate ($value,$options=array(),$formElement) { $regex = '/^[a-zA-Z0-9]+$/'; - $GLOBALS['LSsession'] -> loadLSclass('LSformRule_regex'); - return LSformRule_regex :: validate($value,$regex); + $GLOBALS['LSsession'] -> loadLSclass('LSformRule_regex'); + return LSformRule_regex :: validate($value,$regex,$formElement); } } diff --git a/trunk/includes/class/class.LSformRule_compare.php b/trunk/includes/class/class.LSformRule_compare.php index 7b847e33..3037fdbc 100644 --- a/trunk/includes/class/class.LSformRule_compare.php +++ b/trunk/includes/class/class.LSformRule_compare.php @@ -37,7 +37,7 @@ class LSformRule_compare extends LSformRule { */ function _findOperator($operator_name) { - $_operators = array( + $_operators = array( 'eq' => '==', 'neq' => '!=', 'gt' => '>', @@ -57,20 +57,21 @@ class LSformRule_compare extends LSformRule { } } - /** + /** * Vérification des valeurs. - * - * @param string $values Valeurs à vérifier - * @param array $options Options de validation : - * - Operateur : $options['params']['operator'] - * - * @return boolean true si la valeur est valide, false sinon - */ - function validate ($values,$options=array()) { - if (!isset($options['params']['operator'])) { - $GLOBALS['LSerror'] -> addErrorCode(303); - return; - } + * + * @param string $values Valeurs à vérifier + * @param array $options Options de validation : + * - Operateur : $options['params']['operator'] + * @param object $formElement L'objet formElement attaché + * + * @return boolean true si la valeur est valide, false sinon + */ + function validate ($values,$options=array(),$formElement) { + if (!isset($options['params']['operator'])) { + $GLOBALS['LSerror'] -> addErrorCode(303); + return; + } $operator = LSformRule_compare :: _findOperator($options['params']['operator']); if ('==' != $operator && '!=' != $operator) { $compareFn = create_function('$a, $b', 'return floatval($a) ' . $operator . ' floatval($b);'); diff --git a/trunk/includes/class/class.LSformRule_email.php b/trunk/includes/class/class.LSformRule_email.php index 1e581e6c..c8219840 100644 --- a/trunk/includes/class/class.LSformRule_email.php +++ b/trunk/includes/class/class.LSformRule_email.php @@ -29,28 +29,29 @@ class LSformRule_email extends LSformRule { /** * Vérification de la valeur. - * - * @param string $value Valeur à vérifier - * @param array $options Options de validation : - * - Check domain : $option['params']['checkDomain'] - * - * @return boolean true si la valeur est valide, false sinon - */ - function validate($value,$option=array()) { - $regex = '/^((\"[^\"\f\n\r\t\v\b]+\")|([\w\!\#\$\%\&\'\*\+\-\~\/\^\`\|\{\}]+(\.[\w\!\#\$\%\&\'\*\+\-\~\/\^\`\|\{\}]+)*))@((\[(((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9]))\.((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9]))\.((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9]))\.((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9])))\])|(((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9]))\.((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9]))\.((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9]))\.((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9])))|((([A-Za-z0-9\-])+\.)+[A-Za-z\-]+))$/'; + * + * @param string $value Valeur à vérifier + * @param array $options Options de validation : + * - Check domain : $option['params']['checkDomain'] + * @param object $formElement L'objet formElement attaché + * + * @return boolean true si la valeur est valide, false sinon + */ + function validate($value,$option=array(),$formElement) { + $regex = '/^((\"[^\"\f\n\r\t\v\b]+\")|([\w\!\#\$\%\&\'\*\+\-\~\/\^\`\|\{\}]+(\.[\w\!\#\$\%\&\'\*\+\-\~\/\^\`\|\{\}]+)*))@((\[(((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9]))\.((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9]))\.((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9]))\.((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9])))\])|(((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9]))\.((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9]))\.((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9]))\.((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9])))|((([A-Za-z0-9\-])+\.)+[A-Za-z\-]+))$/'; if (!preg_match($regex, $value)) { return false; - } + } if ($option['params']['checkDomain'] && function_exists('checkdnsrr')) { $tokens = explode('@', $email); if (!(checkdnsrr($tokens[1], 'MX') || checkdnsrr($tokens[1], 'A'))) { - return false; - } + return false; + } } - return true; + return true; } } diff --git a/trunk/includes/class/class.LSformRule_imagefile.php b/trunk/includes/class/class.LSformRule_imagefile.php new file mode 100644 index 00000000..8d715f83 --- /dev/null +++ b/trunk/includes/class/class.LSformRule_imagefile.php @@ -0,0 +1,68 @@ + + */ +class LSformRule_imagefile extends LSformRule { + + /** + * Vérification de la valeur. + * + * @param string $values Valeur à vérifier + * @param array $options Options de validation : + * - Type MIME : $options['param']['mimeType'] + * - Type MIME (regex) : $options['param']['mimeTypeRegEx'] + * @param object $formElement L'objet formElement attaché + * + * @return boolean true si la valeur est valide, false sinon + */ + function validate ($value,$options,$formElement) { + $file = $GLOBALS['LSsession'] -> getTmpFile($value); + + $mimetype = mime_content_type($file); + + if (isset($options['param']['mimeType'])) { + if ($mimetype != $options['param']['mimeType']) { + return; + } + } + else { + if (isset($options['param']['mimeTypeRegEx'])) { + $regex = $options['param']['mimeTypeRegEx']; + } + else { + $regex = '/image\/.*/'; + } + if (!preg_match($regex, $mimetype)) { + return false; + } + } + + return true; + } + +} + +?> diff --git a/trunk/includes/class/class.LSformRule_imagefilesize.php b/trunk/includes/class/class.LSformRule_imagefilesize.php new file mode 100644 index 00000000..6b0b0b81 --- /dev/null +++ b/trunk/includes/class/class.LSformRule_imagefilesize.php @@ -0,0 +1,63 @@ + + */ +class LSformRule_imagefilesize extends LSformRule { + + /** + * Vérification de la valeur. + * + * @param string $values Valeur à vérifier + * @param array $options Options de validation : + * - Taille max (en octet) : $options['param']['maxSize'] + * - Taille min (en octet) : $options['param']['minSize'] + * @param object $formElement L'objet formElement attaché + * + * @return boolean true si la valeur est valide, false sinon + */ + function validate ($value,$options,$formElement) { + $file = $GLOBALS['LSsession'] -> getTmpFile($value); + + $size = filesize($file); + + if (is_int($options['param']['maxSize'])) { + if ($size > $options['param']['maxSize']) { + return; + } + } + + if (is_int($options['param']['minSize'])) { + if ($size < $options['param']['minSize']) { + return; + } + } + + return true; + } + +} + +?> diff --git a/trunk/includes/class/class.LSformRule_imagesize.php b/trunk/includes/class/class.LSformRule_imagesize.php new file mode 100644 index 00000000..bf08363d --- /dev/null +++ b/trunk/includes/class/class.LSformRule_imagesize.php @@ -0,0 +1,74 @@ + + */ +class LSformRule_imagesize extends LSformRule { + + /** + * Vérification de la valeur. + * + * @param string $values Valeur à vérifier + * @param array $options Options de validation : + * - Largeur max : $options['param']['maxWidth'] + * - Largeur min : $options['param']['minWidth'] + * - Hauteur max : $options['param']['maxHeight'] + * - Hauteur min : $options['param']['minHeight'] + * @param object $formElement L'objet formElement attaché + * + * @return boolean true si la valeur est valide, false sinon + */ + function validate ($value,$options,$formElement) { + $file = $GLOBALS['LSsession'] -> getTmpFile($value); + debug('Verify : '.$file.' - Options : '.print_r($options,true)); + list($width, $height, $type, $attr) = getimagesize($file); + + if (is_int($options['param']['maxWidth'])) { + if ($width > $options['param']['maxWidth']) { + return; + } + } + if (is_int($options['param']['minWidth'])) { + if ($width < $options['param']['minWidth']) { + return; + } + } + if (is_int($options['param']['maxHeight'])) { + if ($height > $options['param']['maxHeight']) { + return; + } + } + if (is_int($options['param']['minHeight'])) { + if ($height < $options['param']['minHeight']) { + return; + } + } + + return true; + } + +} + +?> diff --git a/trunk/includes/class/class.LSformRule_lettersonly.php b/trunk/includes/class/class.LSformRule_lettersonly.php index 17b3826b..ca5edccd 100644 --- a/trunk/includes/class/class.LSformRule_lettersonly.php +++ b/trunk/includes/class/class.LSformRule_lettersonly.php @@ -29,16 +29,17 @@ class LSformRule_lettersonly extends LSformRule { /** * Vérification de la valeur. - * - * @param string $value Value à vérifier - * @param array $options Options de validation (inutile ici) - * - * @return boolean true si la valeur est valide, false sinon - */ - function validate ($value,$options=array()) { + * + * @param string $value Value à vérifier + * @param array $options Options de validation (inutile ici) + * @param object $formElement L'objet formElement attaché + * + * @return boolean true si la valeur est valide, false sinon + */ + function validate ($value,$options=array(),$formElement) { $regex = '/^[a-zA-Z]+$/'; - $GLOBALS['LSsession'] -> loadLSclass('LSformRule_regex'); - return LSformRule_regex :: validate($value,$regex); + $GLOBALS['LSsession'] -> loadLSclass('LSformRule_regex'); + return LSformRule_regex :: validate($value,$regex,$formElement); } } diff --git a/trunk/includes/class/class.LSformRule_maxlength.php b/trunk/includes/class/class.LSformRule_maxlength.php index ec525938..09e6f057 100644 --- a/trunk/includes/class/class.LSformRule_maxlength.php +++ b/trunk/includes/class/class.LSformRule_maxlength.php @@ -27,20 +27,21 @@ */ class LSformRule_maxlength extends LSformRule { - /** + /** * Vérification de la valeur. - * - * @param string $values Valeur à vérifier - * @param array $options Options de validation : - * - Longueur max : $options['params']['limit'] - * - * @return boolean true si la valeur est valide, false sinon - */ - function validate ($value,$options) { - if(!isset($options['params']['limit'])) { - $GLOBALS['LSerror'] -> addErrorCode(302); - return; - } + * + * @param string $values Valeur à vérifier + * @param array $options Options de validation : + * - Longueur max : $options['params']['limit'] + * @param object $formElement L'objet formElement attaché + * + * @return boolean true si la valeur est valide, false sinon + */ + function validate ($value,$options,$formElement) { + if(!isset($options['params']['limit'])) { + $GLOBALS['LSerror'] -> addErrorCode(302); + return; + } return (strlen($value)<=$options['params']['limit']); } diff --git a/trunk/includes/class/class.LSformRule_minlength.php b/trunk/includes/class/class.LSformRule_minlength.php index a50be3c9..ff665917 100644 --- a/trunk/includes/class/class.LSformRule_minlength.php +++ b/trunk/includes/class/class.LSformRule_minlength.php @@ -27,20 +27,21 @@ */ class LSformRule_minlength extends LSformRule { - /** + /** * Vérification de la valeur. - * - * @param string $values Valeur à vérifier - * @param array $options Options de validation : - * - Longueur min : $options['params']['limit'] - * - * @return boolean true si la valeur est valide, false sinon - */ - function validate ($value,$options) { - if(!isset($options['params']['limit'])) { - $GLOBALS['LSerror'] -> addErrorCode(302); - return; - } + * + * @param string $values Valeur à vérifier + * @param array $options Options de validation : + * - Longueur min : $options['params']['limit'] + * @param object $formElement L'objet formElement attaché + * + * @return boolean true si la valeur est valide, false sinon + */ + function validate ($value,$options,$formElement) { + if(!isset($options['params']['limit'])) { + $GLOBALS['LSerror'] -> addErrorCode(302); + return; + } return (strlen($value)>=$options['params']['limit']); } diff --git a/trunk/includes/class/class.LSformRule_nonzero.php b/trunk/includes/class/class.LSformRule_nonzero.php index 53cb07e3..49525343 100644 --- a/trunk/includes/class/class.LSformRule_nonzero.php +++ b/trunk/includes/class/class.LSformRule_nonzero.php @@ -27,18 +27,19 @@ */ class LSformRule_nonzero extends LSformRule { - /** + /** * Vérification de la valeur. - * - * @param string $values Valeur à vérifier - * @param array $options Options de validation (inutile ici) - * - * @return boolean true si la valeur est valide, false sinon - */ - function validate ($value,$options) { + * + * @param string $values Valeur à vérifier + * @param array $options Options de validation (inutile ici) + * @param object $formElement L'objet formElement attaché + * + * @return boolean true si la valeur est valide, false sinon + */ + function validate ($value,$options,$formElement) { $regex = '/^-?[1-9][0-9]*/'; - $GLOBALS['LSsession'] -> loadLSclass('LSformRule_regex'); - return LSformRule_regex :: validate($value,$regex); + $GLOBALS['LSsession'] -> loadLSclass('LSformRule_regex'); + return LSformRule_regex :: validate($value,$regex,$formElement); } } diff --git a/trunk/includes/class/class.LSformRule_nopunctuation.php b/trunk/includes/class/class.LSformRule_nopunctuation.php index 94d50a5c..7a5e868b 100644 --- a/trunk/includes/class/class.LSformRule_nopunctuation.php +++ b/trunk/includes/class/class.LSformRule_nopunctuation.php @@ -27,18 +27,19 @@ */ class LSformRule_nopunctuation extends LSformRule { - /** + /** * Vérification de la valeur. - * - * @param string $values Valeur à vérifier - * @param array $options Options de validation (inutile ici) - * - * @return boolean true si la valeur est valide, false sinon - */ - function validate ($value,$options=array()) { + * + * @param string $values Valeur à vérifier + * @param array $options Options de validation (inutile ici) + * @param object $formElement L'objet formElement attaché + * + * @return boolean true si la valeur est valide, false sinon + */ + function validate ($value,$options=array(),$formElement) { $regex = '/^[^().\/\*\^\?#!@$%+=,\"\'><~\[\]{}]+$/'; - $GLOBALS['LSsession'] -> loadLSclass('LSformRule_regex'); - return LSformRule_regex :: validate($value,$regex); + $GLOBALS['LSsession'] -> loadLSclass('LSformRule_regex'); + return LSformRule_regex :: validate($value,$regex,$formElement); } } diff --git a/trunk/includes/class/class.LSformRule_numeric.php b/trunk/includes/class/class.LSformRule_numeric.php index 13618c2d..47ae637d 100644 --- a/trunk/includes/class/class.LSformRule_numeric.php +++ b/trunk/includes/class/class.LSformRule_numeric.php @@ -27,18 +27,19 @@ */ class LSformRule_numeric extends LSformRule{ - /** + /** * Vérification de la valeur. - * - * @param string $values Valeur à vérifier - * @param array $options Options de validation (inutile ici) - * - * @return boolean true si la valeur est valide, false sinon - */ - function validate ($value,$options=array()) { + * + * @param string $values Valeur à vérifier + * @param array $options Options de validation (inutile ici) + * @param object $formElement L'objet formElement attaché + * + * @return boolean true si la valeur est valide, false sinon + */ + function validate ($value,$options=array(),$formElement) { $regex = '/(^-?\d\d*\.\d*$)|(^-?\d\d*$)|(^-?\.\d\d*$)/'; - $GLOBALS['LSsession'] -> loadLSclass('LSformRule_regex'); - return LSformRule_regex :: validate($value,$regex); + $GLOBALS['LSsession'] -> loadLSclass('LSformRule_regex'); + return LSformRule_regex :: validate($value,$regex,$formElement); } } diff --git a/trunk/includes/class/class.LSformRule_rangelength.php b/trunk/includes/class/class.LSformRule_rangelength.php index db71f53a..4332a492 100644 --- a/trunk/includes/class/class.LSformRule_rangelength.php +++ b/trunk/includes/class/class.LSformRule_rangelength.php @@ -27,21 +27,22 @@ */ class LSformRule_rangelength extends LSformRule { - /** + /** * Vérification de la valeur. - * - * @param string $values Valeur à vérifier - * @param array $options Options de validation : - * - Longueur min : $options['params']['limits'][0] - * - Longueur max : $options['params']['limits'][1] - * - * @return boolean true si la valeur est valide, false sinon - */ - function validate ($value,$options=array()) { - if(!isset($options['params']['limits'])) { - $GLOBALS['LSerror'] -> addErrorCode(302); - return; - } + * + * @param string $values Valeur à vérifier + * @param array $options Options de validation : + * - Longueur min : $options['params']['limits'][0] + * - Longueur max : $options['params']['limits'][1] + * @param object $formElement L'objet formElement attaché + * + * @return boolean true si la valeur est valide, false sinon + */ + function validate ($value,$options=array(),$formElement) { + if(!isset($options['params']['limits'])) { + $GLOBALS['LSerror'] -> addErrorCode(302); + return; + } $len=strlen($value); return ($len >= $$options['params']['limits'][0] && $len <= $$options['params']['limits'][1]); } diff --git a/trunk/includes/class/class.LSformRule_regex.php b/trunk/includes/class/class.LSformRule_regex.php index cd88466c..b93d18f3 100644 --- a/trunk/includes/class/class.LSformRule_regex.php +++ b/trunk/includes/class/class.LSformRule_regex.php @@ -27,32 +27,33 @@ */ class LSformRule_regex extends LSformRule { - /** + /** * Vérification de la valeur. - * - * @param string $values Valeur à vérifier - * @param array $options Options de validation : - * - Regex : $option['params']['regex'] ou $option - * - * @return boolean true si la valeur est valide, false sinon - */ - function validate($value,$option) { - if (is_array($option)) { - if (isset($option['params']['regex'])) { - $regex=$option['params']['regex']; - } - else { - $GLOBALS['LSerror'] -> addErrorCode(301); - return; - } - } - else { - $regex=$option; - } + * + * @param string $values Valeur à vérifier + * @param array $options Options de validation : + * - Regex : $option['params']['regex'] ou $option + * @param object $formElement L'objet formElement attaché + * + * @return boolean true si la valeur est valide, false sinon + */ + function validate($value,$option,$formElement) { + if (is_array($option)) { + if (isset($option['params']['regex'])) { + $regex=$option['params']['regex']; + } + else { + $GLOBALS['LSerror'] -> addErrorCode(301); + return; + } + } + else { + $regex=$option; + } if (!preg_match($regex, $value)) { return false; - } - return true; + } + return true; } } diff --git a/trunk/includes/class/class.LSformRule_required.php b/trunk/includes/class/class.LSformRule_required.php index 61d5ab39..d5da57db 100644 --- a/trunk/includes/class/class.LSformRule_required.php +++ b/trunk/includes/class/class.LSformRule_required.php @@ -27,15 +27,16 @@ */ class LSformRule_required extends LSformRule { - /** + /** * Vérification de la valeur. - * - * @param string $value Value à vérifier - * @param array $options Options de validation (inutile ici) - * - * @return boolean true si la valeur est valide, false sinon - */ - function validate ($value,$option=NULL) { + * + * @param string $value Value à vérifier + * @param array $options Options de validation (inutile ici) + * @param object $formElement L'objet formElement attaché + * + * @return boolean true si la valeur est valide, false sinon + */ + function validate ($value,$option=NULL,$formElement) { return ((string)$value != ''); } diff --git a/trunk/includes/class/class.LSldap.php b/trunk/includes/class/class.LSldap.php index 767fc05d..5d6b92c9 100644 --- a/trunk/includes/class/class.LSldap.php +++ b/trunk/includes/class/class.LSldap.php @@ -202,6 +202,8 @@ class LSldap { /** * Met à jour une entrée dans l'annuaire + * + * Remarque : Supprime les valeurs vides de attributs et les attributs sans valeur. * * @author Benjamin Renard * @@ -213,8 +215,30 @@ class LSldap { */ function update($object_type,$dn,$change) { debug($change); + $dropAttr=array(); if($entry=$this -> getEntry($object_type,$dn)) { - $entry -> replace($change); + foreach($change as $attrName => $attrVal) { + $drop = true; + if (is_array($attrVal)) { + foreach($attrVal as $val) { + if (!empty($val)) { + $drop = false; + $changeData[$attrName][]=$val; + } + } + } + if($drop) { + $dropAttr[] = $attrName; + } + } + $entry -> replace($changeData); + debug('change : '.print_r($changeData,true)); + debug('drop : '.print_r($dropAttr,true)); + if (!empty($dropAttr)) { + foreach($dropAttr as $attr) { + $entry -> delete($attr); + } + } $ret = $entry -> update(); if (Net_Ldap::isError($ret)) { $GLOBALS['LSerror'] -> addErrorCode(5,$dn); diff --git a/trunk/includes/class/class.LSldapObject.php b/trunk/includes/class/class.LSldapObject.php index 4b8089af..1b8d7a78 100644 --- a/trunk/includes/class/class.LSldapObject.php +++ b/trunk/includes/class/class.LSldapObject.php @@ -268,7 +268,7 @@ class LSldapObject { if(isset($this -> forms[$idForm])) $LSform = $this -> forms[$idForm][0]; else { - $GLOBALS['LSerror'] -> addErrorCode(22,$this -> type_name); + $GLOBALS['LSerror'] -> addErrorCode(22,$this -> getType()); return; } } @@ -281,7 +281,7 @@ class LSldapObject { $LSform = $LSform[0]; } else { - $GLOBALS['LSerror'] -> addErrorCode(23,$this -> type_name); + $GLOBALS['LSerror'] -> addErrorCode(23,$this -> getType()); return; } } @@ -452,12 +452,12 @@ class LSldapObject { } } else { - $GLOBALS['LSerror'] -> addErrorCode(24,array('attr' => $attr->name,'obj' => $this->type_name,'func' => $test['function'])); + $GLOBALS['LSerror'] -> addErrorCode(24,array('attr' => $attr->name,'obj' => $this->getType(),'func' => $test['function'])); return; } } else { - $GLOBALS['LSerror'] -> addErrorCode(25,array('attr' => $attr->name,'obj' => $this->type_name)); + $GLOBALS['LSerror'] -> addErrorCode(25,array('attr' => $attr->name,'obj' => $this->getType())); return; } } @@ -510,7 +510,7 @@ class LSldapObject { if($dn) { $this -> dn=$dn; debug($submitData); - return $GLOBALS['LSldap'] -> update($this -> type_name,$dn, $submitData); + return $GLOBALS['LSldap'] -> update($this -> getType(),$dn, $submitData); } else { $GLOBALS['LSerror'] -> addErrorCode(33); @@ -867,7 +867,7 @@ class LSldapObject { } } else { - $GLOBALS['LSerror'] -> addErrorCode(31,$this -> type_name); + $GLOBALS['LSerror'] -> addErrorCode(31,$this -> getType()); return; } } diff --git a/trunk/includes/class/class.LSobjects.LSeegroup.php b/trunk/includes/class/class.LSobjects.LSeegroup.php index c5beb67c..e9faf4e8 100644 --- a/trunk/includes/class/class.LSobjects.LSeegroup.php +++ b/trunk/includes/class/class.LSobjects.LSeegroup.php @@ -37,12 +37,158 @@ class LSeegroup extends LSldapObject { * @param[in] $config array La configuration de l'objet * * @retval boolean true si l'objet a été construit, false sinon. - * - * @see LSldapObject::LSldapObject() + * + * @see LSldapObject::LSldapObject() */ function LSeegroup ($config='auto') { $this -> LSldapObject('LSeegroup',$config); } + + /** + * Retourne la liste des groupes d'un utilisateur + * + * Retourne un tableau de LSeegroup correspondant aux groupes + * auxquels appartient un utilisateur + * + * @param[in] $userObject Un object LSeepeople + * + * @retval Array of LSeegroup Les groupes de l'utilisateur + **/ + function listUserGroups($userObject) { + $dn = $userObject -> getDn(); + $filter = $this -> getObjectFilter(); + $filter = '(&'.$filter.'(uniqueMember='.$dn.'))'; + return $this -> listObjects($filter); + } + + /** + * Ajoute un utilisateur au groupe + * + * @param[in] $object Un object LSeepeople : l'utilisateur à ajouter + * + * @retval boolean true si l'utilisateur à été ajouté, False sinon + **/ + function addOneMember($object) { + if ($object instanceof LSeepeople) { + if ($this -> attrs['uniqueMember'] instanceof LSattribute) { + $dn = $object -> getDn(); + $values = $this -> attrs['uniqueMember'] -> getValue(); + if (!is_array($values)) { + $updateData = array($dn); + } + else if (!in_array($dn,$values)) { + $values[]=$dn; + $updateData = $values; + } + if (isset($updateData)) { + return $GLOBALS['LSldap'] -> update($this -> getType(),$this -> getDn(), array('uniqueMember' => $updateData)); + } + return true; + } + } + return; + } + + /** + * Supprime un utilisateur du groupe + * + * @param[in] $object Un object LSeepeople : l'utilisateur à supprimer + * + * @retval boolean true si l'utilisateur à été supprimé, False sinon + **/ + function deleteOneMember($object) { + if ($object instanceof LSeepeople) { + if ($this -> attrs['uniqueMember'] instanceof LSattribute) { + $dn = $object -> getDn(); + $values = $this -> attrs['uniqueMember'] -> getValue(); + if ((!is_array($values)) && (!empty($values))) { + $values = array($values); + } + if (is_array($values)) { + $updateData=array(); + foreach($values as $value) { + if ($value!=$dn) { + $updateData[]=$value; + } + } + return $GLOBALS['LSldap'] -> update($this -> getType(),$this -> getDn(), array('uniqueMember' => $updateData)); + } + return; + } + } + return; + } + + /** + * Met à jour les groupes d'un utilisateur + * + * @param[in] $userObject LSeepeople Un object LSeepeople : l'utilisateur + * @param[in] $listDns Array(string) Un tableau des DNs des groupes de l'utilisateur + * + * @retval boolean true si tout c'est bien passé, False sinon + **/ + function updateUserGroups($userObject,$listDns) { + $currentGroups = $this -> listUserGroups($userObject); + $type=$this -> getType(); + if(is_array($currentGroups)) { + if (is_array($listDns)) { + $dontDelete=array(); + $dontAdd=array(); + for ($i=0;$i getDn(); + if (in_array($dn, $listDns)) { + $dontDelete[$i]=true; + $dontAdd[]=$dn; + } + } + + for($i=0;$i deleteOneMember($userObject)) { + return; + } + } + } + + foreach($listDns as $dn) { + if (in_array($dn,$dontAdd)) { + continue; + } + else { + $object = new $type(); + if ($object -> loadData($dn)) { + if (!$object -> addOneMember($userObject)) { + return; + } + } + else { + return; + } + } + } + return true; + } + } + else { + if(!is_array($listDns)) { + return true; + } + foreach($listDns as $dn) { + $object = new $type(); + if ($object -> loadData($dn)) { + if (!$object -> addOneMember($userObject)) { + return; + } + } + else { + return; + } + } + } + } } ?> diff --git a/trunk/includes/class/class.LSsession.php b/trunk/includes/class/class.LSsession.php index cafe86cd..965a4a2c 100644 --- a/trunk/includes/class/class.LSsession.php +++ b/trunk/includes/class/class.LSsession.php @@ -45,6 +45,7 @@ class LSsession { 'topDn_admin' => array () ); var $LSaccess = array(); + var $tmp_file = array(); /** * Constructeur @@ -217,21 +218,27 @@ class LSsession { // Déconnexion if (isset($_GET['LSsession_logout'])) { session_destroy(); + + if (is_array($_SESSION['LSsession']['tmp_file'])) { + $this -> tmp_file = $_SESSION['LSsession']['tmp_file']; + } + $this -> deleteTmpFile(); unset($_SESSION['LSsession']); } + if(isset($_SESSION['LSsession'])) { // Session existante - $this -> confDir = $_SESSION['LSsession'] -> confDir; - $this -> topDn = $_SESSION['LSsession'] -> topDn; - //$this -> LSuserObject = $_SESSION['LSsession'] -> LSuserObject; - $this -> dn = $_SESSION['LSsession'] -> dn; - $this -> rdn = $_SESSION['LSsession'] -> rdn; - $this -> ldapServerId = $_SESSION['LSsession'] -> ldapServerId; + $this -> confDir = $_SESSION['LSsession']['confDir']; + $this -> topDn = $_SESSION['LSsession']['topDn']; + $this -> dn = $_SESSION['LSsession']['dn']; + $this -> rdn = $_SESSION['LSsession']['rdn']; + $this -> ldapServerId = $_SESSION['LSsession']['ldapServerId']; + $this -> tmp_file = $_SESSION['LSsession']['tmp_file']; if ( ($GLOBALS['LSconfig']['cacheLSrights']) || ($this -> ldapServer['cacheLSrights']) ) { - $this -> ldapServer = $_SESSION['LSsession'] -> ldapServer; - $this -> LSrights = $_SESSION['LSsession'] -> LSrights; - $this -> LSaccess = $_SESSION['LSsession'] -> LSaccess; + $this -> ldapServer = $_SESSION['LSsession']['ldapServer']; + $this -> LSrights = $_SESSION['LSsession']['LSrights']; + $this -> LSaccess = $_SESSION['LSsession']['LSaccess']; if (!$this -> LSldapConnect()) return; } @@ -291,7 +298,7 @@ class LSsession { $this -> loadLSrights(); $this -> loadLSaccess(); $GLOBALS['Smarty'] -> assign('LSsession_username',$this -> LSuserObject -> getDisplayValue()); - $_SESSION['LSsession']=$this; + $_SESSION['LSsession']=get_object_vars($this); return true; } else { @@ -357,7 +364,11 @@ class LSsession { } } - + /* + * Retourne les sous-dns du serveur Ldap courant + * + * @retval mixed Tableau des subDn, false si une erreur est survenue. + */ function getSubDnLdapServer() { if ( isset($this ->ldapServer['subdnobject']) ) { if( $this -> loadLSobject($this ->ldapServer['subdnobject']) ) { @@ -485,6 +496,8 @@ class LSsession { * @retval void */ function addJSscript($script) { + if (in_array($script, $this -> JSscripts)) + return; $this -> JSscripts[]=$script; } @@ -514,15 +527,25 @@ class LSsession { foreach ($GLOBALS['defaultJSscipts'] as $script) { $JSscript_txt.="\n"; } + foreach ($this -> JSscripts as $script) { $JSscript_txt.="\n"; } + + if ($GLOBALS['LSdebug']['active']) { + $JSscript_txt.="\n"; + } + else { + $JSscript_txt.="\n"; + } + $GLOBALS['Smarty'] -> assign('LSsession_js',$JSscript_txt); // Css - $Css_txt="\n"; + $Css_txt="\n"; + $Css_txt="\n"; foreach ($this -> CssFiles as $file) { - $Css_txt.="\n"; + $Css_txt.="\n"; } $GLOBALS['Smarty'] -> assign('LSsession_css',$Css_txt); @@ -581,7 +604,6 @@ class LSsession { } } } - debug($this -> LSrights['topDn_admin']); return true; } else { @@ -754,6 +776,127 @@ class LSsession { function canCreate($LSobject) { return $this -> canAccess($LSobject,NULL,'w','rdn'); } + + /** + * Retourne le droit de l'utilisateur à gérer la relation d'objet + * + * @param[in] string $dn Le DN de l'objet (le container_dn du type de l'objet par défaut) + * @param[in] string $relationName Le nom de la relation avec l'objet + * @param[in] string $right Le type de droit a vérifier ('r' ou 'w') + * + * @retval boolean True si l'utilisateur a accès, false sinon + */ + function relationCanAccess($dn,$relationName,$right=NULL) { + $LSobject=$this -> LSuserObject -> getType(); + if (!isset($GLOBALS['LSobjects'][$LSobject]['relations'][$relationName])) + return; + $whoami = $this -> whoami($dn); + + if (($right=='w') || ($right=='r')) { + if ($GLOBALS['LSobjects'][$LSobject]['relations'][$relationName]['rights'][$whoami] == $right) { + return true; + } + } + else { + if (($GLOBALS['LSobjects'][$LSobject]['relations'][$relationName]['rights'][$whoami] == 'w') || ($GLOBALS['LSobjects'][$LSobject]['relations'][$relationName]['rights'][$whoami] == 'r')) { + return true; + } + } + return; + } + + /** + * Retourne le droit de l'utilisateur à modifier la relation d'objet + * + * @param[in] string $dn Le DN de l'objet (le container_dn du type de l'objet par défaut) + * @param[in] string $relationName Le nom de la relation avec l'objet + * + * @retval boolean True si l'utilisateur a accès, false sinon + */ + function relationCanEdit($dn,$relationName) { + return $this -> relationCanAccess($dn,$relationName,'w'); + } + + /* + * Ajoute un fichier temporaire + * + * @author Benjamin Renard + * + * @retval void + **/ + function addTmpFile($value,$filePath) { + $hash = mhash(MHASH_MD5,$value); + $this -> tmp_file[$filePath] = $hash; + $_SESSION['LSsession']['tmp_file'][$filePath] = $hash; + } + + /** + * Retourne le chemin du fichier temporaire si l'existe + * + * @author Benjamin Renard + * + * @param[in] $value La valeur du fichier + * + * @retval mixed + **/ + function tmpFileExist($value) { + $hash = mhash(MHASH_MD5,$value); + foreach($this -> tmp_file as $filePath => $contentHash) { + if ($hash == $contentHash) { + return $filePath; + } + } + return false; + } + + /** + * Retourne le chemin du fichier temporaire + * + * Retourne le chemin du fichier temporaire qu'il créera à partir de la valeur + * s'il n'existe pas déjà. + * + * @author Benjamin Renard + * + * @param[in] $value La valeur du fichier + * + * @retval mixed + **/ + function getTmpFile($value) { + $exist = $this -> tmpFileExist($value); + if (!$exist) { + $img_path = LS_TMP_DIR .rand().'.tmp'; + $fp = fopen($img_path, "w"); + fwrite($fp, $value); + fclose($fp); + $this -> addTmpFile($value,$img_path); + return $img_path; + } + else { + return $exist; + } + } + + /* + * Supprime les fichiers temporaires + * + * @author Benjamin Renard + * + * @retval void + **/ + function deleteTmpFile($filePath=NULL) { + if ($filePath) { + @unlink($filePath); + unset($this -> tmp_file[$filePath]); + unset($_SESSION['LSsession']['tmp_file'][$filePath]); + } + else { + foreach($this -> tmp_file as $file => $content) { + @unlink($file); + } + $this -> tmp_file = array(); + $_SESSION['LSsession']['tmp_file'] = array(); + } + } } diff --git a/trunk/includes/js/LSdefault.js b/trunk/includes/js/LSdefault.js index cb6531ec..96e68aa6 100644 --- a/trunk/includes/js/LSdefault.js +++ b/trunk/includes/js/LSdefault.js @@ -1,6 +1,5 @@ var LSdefault = new Class({ initialize: function(){ - LSdebug('toto'); this.LSdebug = $('LSdebug'); this.LSdebugInfos = $('LSdebug_infos'); this.LSdebug.setOpacity(0); @@ -15,6 +14,10 @@ var LSdefault = new Class({ if (this.LSerror.innerHTML != '') { this.displayLSerror(); } + + this.loading_img=[]; + LSdebug(this.loading_img); + this.loading_img_id=-1; }, onLSdebugHiddenClick: function(event){ @@ -23,6 +26,7 @@ var LSdefault = new Class({ }, displayDebugBox: function() { + this.LSdebug.setStyle('top',getScrollTop()+10); new Fx.Style(this.LSdebug,'opacity',{duration:500}).start(0,0.8); }, @@ -33,18 +37,36 @@ var LSdefault = new Class({ }, displayLSerror: function() { + this.LSerror.setStyle('top',getScrollTop()+10); new Fx.Style(this.LSerror,'opacity',{duration:500}).start(0,0.8); (function(){new Fx.Style(this.LSerror,'opacity',{duration:500}).start(0.8,0);}).delay(5000, this); }, - loadingImgDisplay: function(el) { - this.loading_img = new Element('img'); - this.loading_img.src='templates/images/ajax-loader.gif'; - this.loading_img.injectAfter(el); + loadingImgDisplay: function(el,position) { + this.loading_img_id++; + this.loading_img[this.loading_img_id] = new Element('img'); + this.loading_img[this.loading_img_id].src='templates/images/ajax-loader.gif'; + if (position=='inside') { + this.loading_img[this.loading_img_id].injectInside(el); + } + else { + this.loading_img[this.loading_img_id].injectAfter(el); + } + LSdebug(this.loading_img_id); + return this.loading_img_id; }, - loadingImgHide: function() { - this.loading_img.remove(); + loadingImgHide: function(id) { + if (isNaN(id)) { + this.loading_img.each(function(el) { + if (typeof(el) != 'undefined') + el.remove(); + },this); + this.loading_img_id=-1; + } + else { + this.loading_img[id].remove(); + } } }); @@ -52,7 +74,7 @@ window.addEvent(window.ie ? 'load' : 'domready', function() { varLSdefault = new LSdefault(); }); -LSdebug_active = 1; +LSdebug_active = 0; function LSdebug() { if (LSdebug_active != 1) return; diff --git a/trunk/includes/js/LSform.js b/trunk/includes/js/LSform.js index b6690391..a63ab31c 100644 --- a/trunk/includes/js/LSform.js +++ b/trunk/includes/js/LSform.js @@ -7,6 +7,39 @@ var LSform = new Class({ $$('img.LSform-remove-field-btn').each(function(el) { el.addEvent('click',this.onRemoveFieldBtnClick.bind(this,el)); }, this); + + $$('div.LSform_image').each(function(el) { + el.addEvent('mouseenter',this.onMouseEnterImage.bind(this)); + }, this); + + $$('div.LSform_image').each(function(el) { + el.addEvent('mouseleave',this.onMouseLeaveImage.bind(this)); + }, this); + + $$('img.LSform_image_action_zoom').each(function(el) { + el.addEvent('click',this.zoomImg.bindWithEvent(this,el.getParent().getParent().getNext().src)); + }, this); + + $$('img.LSform_image_action_delete').each(function(el) { + el.addEvent('click',this.onImageDeleteBtnClick.bind(this,el)); + }, this); + + this.initialiseLSformElement_select_object(); + }, + + initialiseLSformElement_select_object: function() { + $$('a.LSformElement_select_object_addBtn').each(function(el) { + el.addEvent('click',this.onLSformElement_select_object_addBtnClick.bindWithEvent(this,el)); + }, this); + + $$('img.LSformElement_select_object_deleteBtn').each(function(el) { + el.addEvent('click',this.LSformElement_select_object_deleteBtn.bind(this,el)); + }, this); + }, + + zoomImg: function(event, src) { + new Event(event).stop(); + varLSsmoothbox.openImg(src); }, onAddFieldBtnClick: function(img){ @@ -20,7 +53,7 @@ var LSform = new Class({ action: 'onAddFieldBtnClick', attribute: attrName, objecttype: $('LSform_objecttype').value, - objectdn: $('LSform_objectdn').value, + objectdn: $('LSform_objectdn').value, idform: $('LSform_idform').value, img: img.id }; @@ -60,6 +93,109 @@ var LSform = new Class({ else { img.getParent().remove(); } + }, + + onMouseEnterImage: function() { + $$('ul.LSform_image_actions').each(function(el) { + el.setStyle('visibility','visible'); + }, this); + }, + + onMouseLeaveImage: function() { + $$('ul.LSform_image_actions').each(function(el) { + el.setStyle('visibility','hidden'); + }, this); + }, + + onImageDeleteBtnClick: function(img) { + $$('form.LSform').each(function(el) { + var input = new Element('input'); + input.type = 'hidden'; + var getInputId = /LSform_image_action_delete_(.*)/ + input.name = $(getInputId.exec(img.id)[1]).name + '_delete'; + input.value='delete'; + input.injectInside(el); + },this); + img.getParent().getParent().getParent().remove(); + }, + + onLSformElement_select_object_addBtnClick: function(event,a) { + new Event(event).stop(); + var getFieldId = /a_(.*)/ + var fieldId = getFieldId.exec(a.id)[1]; + var getId = /a_LSformElement_select_object_.*_([0-9]*)$/ + var Id = getId.exec(a.id)[1]; + + values = new Array(); + $$('input.LSformElement_select_object').each(function(el) { + values.push(el.getProperty('value')); + }, this); + + var data = { + template: 'LSselect', + action: 'refreshSession', + objecttype: $('LSformElement_select_object_objecttype_'+Id).value, + values: Json.toString(values), + href: a.href + }; + + LSdebug(data); + + data.imgload=varLSdefault.loadingImgDisplay(a,'inside'); + this.refreshFields=fieldId; + new Ajax('index_ajax.php', {data: data, onComplete: this.onLSformElement_select_object_addBtnClickComplete.bind(this)}).request(); + }, + + onLSformElement_select_object_addBtnClickComplete: function(responseText, responseXML) { + var data = Json.evaluate(responseText); + LSdebug(data); + if ( data ) { + if ( typeof(data.LSerror) != "undefined" ) { + varLSdefault.displayError(data.LSerror); + return; + } + else { + varLSdefault.loadingImgHide(data.imgload); + varLSsmoothbox.openURL(data.href,this); + } + } + }, + + refresh: function() { + var getAttrName = /LSformElement_select_object_(.*)_[0-9]*/ + var attrName = getAttrName.exec(this.refreshFields)[1]; + var data = { + template: 'LSform', + action: 'refreshField', + attribute: attrName, + objecttype: $('LSform_objecttype').value, + objectdn: $('LSform_objectdn').value, + idform: $('LSform_idform').value, + ul: this.refreshFields + }; + LSdebug(data); + data.imgload=varLSdefault.loadingImgDisplay($('a_' + this.refreshFields)); + new Ajax('index_ajax.php', {data: data, onComplete: this.onRefreshComplete.bind(this)}).request(); + }, + + onRefreshComplete: function(responseText, responseXML) { + var data = Json.evaluate(responseText); + if ( data ) { + if ( typeof(data.LSerror) != "undefined" ) { + varLSdefault.loadingImgHide(); + varLSdefault.displayError(data.LSerror); + return; + } + else { + varLSdefault.loadingImgHide(data.imgload); + $(this.refreshFields).getParent().setHTML(data.html); + this.initialiseLSformElement_select_object(); + } + } + }, + + LSformElement_select_object_deleteBtn: function(img) { + img.getParent().remove(); } }); diff --git a/trunk/includes/js/LSrelation.js b/trunk/includes/js/LSrelation.js new file mode 100644 index 00000000..fcb60419 --- /dev/null +++ b/trunk/includes/js/LSrelation.js @@ -0,0 +1,152 @@ +var LSrelation = new Class({ + initialize: function(){ + this.edit = 0; + this.deleteBtn = []; + this.deleteBtnId = 0; + this.refreshRelation=0; + $$('a.LSrelation_modify').each(function(el) { + this.edit=1; + el.addEvent('click',this.onLSrelationModifyBtnClick.bindWithEvent(this,el)); + }, this); + if (this.edit) { + this.initializeBtn(); + } + }, + + initializeBtn: function() { + $$('img.LSrelation-btn').each(function(el) { + el.remove(); + }, this); + this.deleteBtnId = 0; + $$('li.LSrelation').each(function(li) { + this.deleteBtn[this.deleteBtnId] = new Element('img'); + this.deleteBtn[this.deleteBtnId].src = 'templates/images/delete.png'; + this.deleteBtn[this.deleteBtnId].setStyle('cursor','pointer'); + this.deleteBtn[this.deleteBtnId].addClass('LSrelation-btn'); + this.deleteBtn[this.deleteBtnId].addEvent('click',this.onDeleteBtnClick.bind(this,this.deleteBtn[this.deleteBtnId])); + this.deleteBtn[this.deleteBtnId].injectInside(li); + li.id=this.deleteBtnId; + this.deleteBtnId++; + }, this); + }, + + onDeleteBtnClick: function(img) { + li = img.getParent(); + ul = li.getParent(); + img.remove(); + LSdebug(ul.id); + var getId = /LSrelation_ul_([0-9]*)/ + var id = getId.exec(ul.id)[1]; + + var data = { + template: 'LSrelation', + action: 'deleteByDisplayValue', + id: id, + value: li.innerHTML + }; + this.deleteLi = li; + data.imgload=varLSdefault.loadingImgDisplay(li.id,'inside'); + LSdebug(data); + new Ajax('index_ajax.php', {data: data, onComplete: this.onDeleteBtnClickComplete.bind(this)}).request(); + }, + + onDeleteBtnClickComplete: function(responseText, responseXML) { + var data = Json.evaluate(responseText); + LSdebug(data); + if ( data ) { + if ( typeof(data.LSerror) != "undefined" ) { + if (data.imgload!='') { + varLSdefault.loadingImgHide(data.imgload); + } + else { + varLSdefault.loadingImgHide(); + } + varLSdefault.displayError(data.LSerror); + return; + } + else { + varLSdefault.loadingImgHide(data.imgload); + this.deleteLi.remove(); + } + } + }, + + onLSrelationModifyBtnClick: function(event,a) { + new Event(event).stop(); + + var data = { + template: 'LSrelation', + action: 'refreshSession', + id: a.id, + href: a.href + }; + + LSdebug(data); + this.refreshRelation=a.id; + data.imgload=varLSdefault.loadingImgDisplay('LSrelation_title_'+a.id,'inside'); + new Ajax('index_ajax.php', {data: data, onComplete: this.onLSrelationModifyBtnClickComplete.bind(this)}).request(); + }, + + onLSrelationModifyBtnClickComplete: function(responseText, responseXML) { + var data = Json.evaluate(responseText); + LSdebug(data); + if ( data ) { + if ( typeof(data.LSerror) != "undefined" ) { + if (data.imgload!='') { + varLSdefault.loadingImgHide(data.imgload); + } + else { + varLSdefault.loadingImgHide(); + } + varLSdefault.displayError(data.LSerror); + return; + } + else { + varLSdefault.loadingImgHide(data.imgload); + varLSsmoothbox.openURL(data.href,this); + } + } + }, + + refresh: function() { + var data = { + template: 'LSrelation', + action: 'refreshList', + id: this.refreshRelation + }; + + LSdebug(data); + data.imgload=varLSdefault.loadingImgDisplay('LSrelation_title_'+this.refreshRelation,'inside'); + new Ajax('index_ajax.php', {data: data, onComplete: this.onRrefreshComplete.bind(this)}).request(); + }, + + onRrefreshComplete: function(responseText, responseXML) { + var data = Json.evaluate(responseText); + LSdebug(data); + if ( data ) { + if ( typeof(data.LSerror) != "undefined" ) { + if (data.imgload!='') { + varLSdefault.loadingImgHide(data.imgload); + } + else { + varLSdefault.loadingImgHide(); + } + varLSdefault.displayError(data.LSerror); + return; + } + else { + varLSdefault.loadingImgHide(data.imgload); + $('LSrelation_ul_'+this.refreshRelation).setHTML(data.html); + this.initializeBtn(); + } + } + }, + + +}); + +window.addEvent(window.ie ? 'load' : 'domready', function() { + varLSrelation = new LSrelation(); +}); + +LSdebug('titi'); diff --git a/trunk/includes/js/LSselect.js b/trunk/includes/js/LSselect.js new file mode 100644 index 00000000..e89e571a --- /dev/null +++ b/trunk/includes/js/LSselect.js @@ -0,0 +1,92 @@ +var LSselect = new Class({ + initialize: function(){ + this.initializeContent(); + + $$('form.LSselect_search').each(function(el) { + var input = new Element('input'); + input.setProperty('name','ajax'); + input.setProperty('type','hidden'); + input.injectInside(el); + el.addEvent('submit',this.onSubmitSearchForm.bindWithEvent(this,el)); + }, this); + + }, + + initializeContent: function() { + $$('input.LSobject-select').each(function(el) { + el.addEvent('click',this.oncheckboxChange.bind(this,el)); + }, this); + + $$('a.LSobject-list-page').each(function(el) { + el.addEvent('click',this.onChangePageClick.bindWithEvent(this,el)); + }, this); + }, + + oncheckboxChange: function(checkbox){ + if (checkbox.checked) { + var data = { + template: 'LSselect', + action: 'addLSselectobject-item', + objectdn: checkbox.value, + objecttype: $('LSselect-object').getProperties('caption').caption + }; + LSdebug('plus'); + } + else { + LSdebug('mois'); + var data = { + template: 'LSselect', + action: 'dropLSselectobject-item', + objectdn: checkbox.value, + objecttype: $('LSselect-object').getProperties('caption').caption + }; + } + LSdebug(data); + data.imgload=varLSdefault.loadingImgDisplay(checkbox.getParent().getNext(),'inside'); + new Ajax('index_ajax.php', {data: data, onComplete: this.oncheckboxChangeComplete.bind(this)}).request(); + }, + + oncheckboxChangeComplete: function(responseText, responseXML) { + var data = Json.evaluate(responseText); + varLSdefault.loadingImgHide(data); + }, + + onChangePageClick: function(event, a) { + new Event(event).stop(); + var data = { + ajax: true + }; + this.searchImgload = varLSdefault.loadingImgDisplay($('title'),'inside'); + new Ajax(a.href, {data: data, onComplete: this.onChangePageClickComplete.bind(this)}).request(); + }, + + onChangePageClickComplete: function(responseText, responseXML) { + varLSdefault.loadingImgHide(this.searchImgload); + $('content').setHTML(responseText); + this.initializeContent(); + }, + + onSubmitSearchForm: function(event, form) { + new Event(event).stop(); + var imgload = varLSdefault.loadingImgDisplay($('title'),'inside'); + form.send({ + update: $('content'), + onComplete: this.onSubmitSearchFormComplete.bind(this,imgload) + }); + }, + + onSubmitSearchFormComplete: function(imgload) { + varLSdefault.loadingImgHide(imgload); + this.initializeContent(); + }, + + submit: function() { + var values = new Array(); + $('content').getElements('input[name^=LSobjects_selected]').each(function(el) { + values.push(el.value); + },this); + return values; + } + + +}); diff --git a/trunk/includes/js/LSsession_login.js b/trunk/includes/js/LSsession_login.js index 44d41418..22fe52d9 100644 --- a/trunk/includes/js/LSsession_login.js +++ b/trunk/includes/js/LSsession_login.js @@ -1,47 +1,48 @@ var LSsession_login = new Class({ initialize: function(){ - this.select_ldapserver = $('LSsession_ldapserver'); - if ( ! this.select_ldapserver ) - return; - this.select_ldapserver.addEvent('change',this.onLdapServerChanged.bind(this)); + this.select_ldapserver = $('LSsession_ldapserver'); + if ( ! this.select_ldapserver ) + return; + this.select_ldapserver.addEvent('change',this.onLdapServerChanged.bind(this)); }, - onLdapServerChanged: function(){ - varLSdefault.loadingImgDisplay(this.select_ldapserver); - var server = this.select_ldapserver.value; - var data = { - template: 'login', - action: 'onLdapServerChanged', - server: server - }; - new Ajax('index_ajax.php', {data: data, onComplete: this.onLdapServerChangedComplete.bind(this)}).request(); - }, + onLdapServerChanged: function(){ + var imgload = varLSdefault.loadingImgDisplay(this.select_ldapserver); + var server = this.select_ldapserver.value; + var data = { + template: 'login', + action: 'onLdapServerChanged', + server: server, + imgload: imgload + }; + new Ajax('index_ajax.php', {data: data, onComplete: this.onLdapServerChangedComplete.bind(this)}).request(); + }, - onLdapServerChangedComplete: function(responseText, responseXML){ - varLSdefault.loadingImgHide(); - var data = Json.evaluate(responseText); - LSdebug(data); - if ( data ) { - if (data.LSerror) { - varLSdefault.displayError(data.LSerror); - return; - } - else { - $('LSsession_topDn').getParent().setHTML(data.list_topDn); - LSdebug($('LSsession_topDn').innerHTML); - $$('.loginform-level').each(function(el) { - el.setStyle('display','block'); - }); - } - } - else { - $$('.loginform-level').each(function(el) { - el.setStyle('display','none'); - }); - $('LSsession_topDn').empty(); - } - } + onLdapServerChangedComplete: function(responseText, responseXML){ + varLSdefault.loadingImgHide(); + var data = Json.evaluate(responseText); + LSdebug(data); + if ( data ) { + if (data.LSerror) { + varLSdefault.displayError(data.LSerror); + return; + } + else { + $('LSsession_topDn').getParent().setHTML(data.list_topDn); + LSdebug($('LSsession_topDn').innerHTML); + $$('.loginform-level').each(function(el) { + el.setStyle('display','block'); + }); + } + } + else { + $$('.loginform-level').each(function(el) { + el.setStyle('display','none'); + }); + $('LSsession_topDn').empty(); + } + } }); window.addEvent(window.ie ? 'load' : 'domready', function() { - varLSsession_login = new LSsession_login(); + varLSsession_login = new LSsession_login(); }); diff --git a/trunk/includes/js/LSsmoothbox.js b/trunk/includes/js/LSsmoothbox.js new file mode 100644 index 00000000..2cfdac8b --- /dev/null +++ b/trunk/includes/js/LSsmoothbox.js @@ -0,0 +1,180 @@ +var LSsmoothbox = new Class({ + initialize: function(options) { + this.over = new Element('div'); + this.over.setProperty('id','over-LSsmoothbox'); + this.over.setStyles({ + width: '100%', + height: '100%', + opacity: '0.5', + position: 'absolute', + top: Window.getScrollTop(), + visibility: 'hidden' + }); + this.over.injectInside(document.body); + + this.win = new Element('div'); + this.win.setProperty('id','win-LSsmoothbox'); + this.win.injectInside(document.body); + + this.frame = new Element('div'); + this.frame.setProperty('id','frame-LSsmoothbox'); + + this.pnav = new Element('p'); + this.pnav.setProperty('id','pnav-LSsmoothbox'); + + this.pnav.injectInside(this.win); + this.frame.injectInside(this.win); + + $$('a.LSsmoothbox').each(function(el) { + el.addEvent('click',this.clickA.bindWithEvent(this,el)); + },this); + + $$('img.LSsmoothbox').each(function(el) { + el.addEvent('click',this.clickImg.bindWithEvent(this,el)); + el.setStyle('cursor','pointer'); + },this); + this.fx = { + over: this.over.effect('opacity', {duration: 300}).hide(), + win: this.win.effect('opacity', {duration: 300}).hide() + }; + }, + + clickA: function(event,a) { + new Event(event).stop(); + this.openURL(a.href); + }, + + clickImg: function(event,img) { + new Event(event).stop(); + this.openImg(img.src); + }, + + display: function() { + this.fx.over.start(0.5); + this.fx.win.start(1); + }, + + openURL: function(href,el) { + this.refreshElement = el; + + this.over.setStyle('top',Window.getScrollTop()); + + var winTop = Window.getScrollTop() + ((window.getHeight() - (window.getHeight()*0.8)) /2); + this.win.setStyles({ + width: '80%', + height: '80%', + position: 'absolute', + top: winTop, + left: '10%', + visibility: 'hidden' + }); + + this.frame.setStyles({ + postion: 'absolute', + width: '100%', + height: '95%', + border: 'none' + }); + + this.pnav.setStyles({ + width: '100%', + height: '5%', + cursor: 'pointer' + }); + + this.pnav.empty(); + this.cancelBtn = new Element('span'); + this.cancelBtn.setHTML('Annuler'); + this.cancelBtn.addEvent('click',this.close.bindWithEvent(this,false)); + this.cancelBtn.injectInside(this.pnav); + + this.closeBtn = new Element('span'); + this.closeBtn.setHTML('Valider'); + this.closeBtn.addEvent('click',this.close.bindWithEvent(this,true)); + this.closeBtn.injectInside(this.pnav); + + var options = { + method: 'post', + update: this.frame, + evalScripts: true + }; + + new Ajax(href, options).request(); + this.display(); + }, + + openImg: function(src) { + var margin = 25 + this.img = new Element('img'); + this.img.setProperty('src',src); + if (((this.img.height+margin) > window.getHeight())||(this.img.width>window.getWidth())) { + var rH = window.getHeight() / (this.img.height+margin); + var rW = window.getWidth() / (this.img.width); + if (rH > rW) { + // W + this.img.height = Math.floor(this.img.height*window.getWidth()/this.img.width); + this.img.width = window.getWidth(); + } + else { + // H + this.img.width = Math.floor(this.img.width*(window.getHeight()-margin)/this.img.height); + this.img.height = window.getHeight() - margin; + } + } + + var winTop = Window.getScrollTop() + ((window.getHeight() - (this.img.height+margin)) /2); + var winLeft = (window.getWidth() - this.img.width) /2; + this.win.setStyles({ + width: this.img.width, + height: this.img.height+margin-5, + position: 'absolute', + top: winTop, + left: winLeft, + visibility: 'hidden' + }); + + this.frame.setStyles({ + postion: 'absolute', + width: '100%', + height: this.img.height, + border: 'none' + }); + + this.pnav.setStyles({ + width: '100%', + height: margin-5, + cursor: 'pointer' + }); + + + this.frame.empty(); + this.img.injectInside(this.frame); + + this.pnav.empty(); + this.closeBtn = new Element('span'); + this.closeBtn.setHTML('Fermer'); + this.closeBtn.addEvent('click',this.close.bindWithEvent(this,false)); + this.closeBtn.injectInside(this.pnav); + + this.display(); + }, + + close: function(event,refresh) { + new Event(event).stop(); + this.fx.win.start(0); + this.fx.over.start(0); + if (refresh) { + try { + this.refreshElement.refresh(); + } + catch (e){ + console.log('rater'); + } + } + return true; + } + +}); +window.addEvent(window.ie ? 'load' : 'domready', function() { + varLSsmoothbox = new LSsmoothbox(); +}); diff --git a/trunk/index_ajax.php b/trunk/index_ajax.php index 53f1ea9f..a055adb8 100644 --- a/trunk/index_ajax.php +++ b/trunk/index_ajax.php @@ -11,6 +11,7 @@ if ($_REQUEST['template'] != 'login') { echo json_encode(array('LSerror' => 'LSsession : Impossible d\'initialiser la LSsession.' )); } } +$data=NULL; switch($_REQUEST['template']) { case 'login': switch($_REQUEST['action']) { @@ -21,7 +22,7 @@ switch($_REQUEST['template']) { $list = $GLOBALS['LSsession'] -> getSubDnLdapServerOptions(); if (is_string($list)) { $list=""; - $data = array('list_topDn' => $list); + $data = array('list_topDn' => $list, 'imgload' => $_REQUEST['imgload']); } else if (is_array($list)){ $data = array('LSerror' => $GLOBALS['LSerror']->getErrors()); @@ -34,9 +35,6 @@ switch($_REQUEST['template']) { $data = array('LSerror' => $GLOBALS['LSerror']->getErrors()); } } - else { - $data=NULL; - } break; } break; @@ -58,13 +56,249 @@ switch($_REQUEST['template']) { $data = array('LSerror' => $GLOBALS['LSerror']->getErrors()); } } + break; + case 'refreshField': + if ((isset($_REQUEST['attribute'])) && (isset($_REQUEST['objecttype'])) && (isset($_REQUEST['objectdn'])) && (isset($_REQUEST['idform'])) && (isset($_REQUEST['imgload'])) ) { + $object = new $_REQUEST['objecttype'](); + //$object -> loadData($_REQUEST['objectdn']); + $form = $object -> getForm($_REQUEST['idform']); + $field=$form -> getElement($_REQUEST['attribute']); + $val = $field -> getDisplay(true); + if ( $val ) { + $data = array( + 'html' => $val['html'], + 'imgload' => $_REQUEST['imgload'] + ); + } + else { + $data = array( + 'LSerror' => $GLOBALS['LSerror']->getErrors(), + 'imgload' => $_REQUEST['imgload'] + ); + } + } + break; + } + break; + case 'LSrelation': + switch($_REQUEST['action']) { + case 'refreshSession': + if ((isset($_REQUEST['id'])) && (isset($_REQUEST['href'])) && (isset($_REQUEST['imgload']))) { + if (isset($_SESSION['LSrelation'][$_REQUEST['id']])) { + $conf = $_SESSION['LSrelation'][$_REQUEST['id']]; + if ($GLOBALS['LSsession']->loadLSobject($conf['objectType'])) { + $object = new $conf['objectType'](); + if (($object -> loadData($conf['objectDn'])) && (isset($object->config['relations'][$conf['relationName']]))) { + $relationConf = $object->config['relations'][$conf['relationName']]; + if ($GLOBALS['LSsession'] -> relationCanEdit($object -> getValue('dn'),$conf['relationName'])) { + if (method_exists($relationConf['LSobject'],$relationConf['list_function'])) { + $objRel = new $relationConf['LSobject'](); + $list = $objRel -> $relationConf['list_function']($object); + $_SESSION['LSselect'][$relationConf['LSobject']]=array(); + if (is_array($list)) { + foreach($list as $o) { + $_SESSION['LSselect'][$relationConf['LSobject']][] = $o -> getDn(); + } + } + $data = array( + 'href' => $_REQUEST['href'], + 'id' => $_REQUEST['id'] + ); + } + else { + $GLOBALS['LSerror'] -> addErrorCode(1013,$relationName); + } + } + else { + $GLOBALS['LSerror'] -> addErrorCode(1011); + } + } + else { + $GLOBALS['LSerror'] -> addErrorCode(1012); + } + } + else { + $GLOBALS['LSerror'] -> addErrorCode(1012); + } + $data['imgload'] = $_REQUEST['imgload']; + } + else { + $GLOBALS['LSerror'] -> addErrorCode(1012); + } + } + break; + case 'refreshList': + if ((isset($_REQUEST['id'])) && (isset($_REQUEST['imgload']))) { + if (isset($_SESSION['LSrelation'][$_REQUEST['id']])) { + $conf = $_SESSION['LSrelation'][$_REQUEST['id']]; + if ($GLOBALS['LSsession']->loadLSobject($conf['objectType'])) { + $object = new $conf['objectType'](); + if (($object -> loadData($conf['objectDn'])) && (isset($object->config['relations'][$conf['relationName']]))) { + $relationConf = $object->config['relations'][$conf['relationName']]; + if ($GLOBALS['LSsession'] -> relationCanEdit($object -> getValue('dn'),$conf['relationName'])) { + if (is_array($_SESSION['LSselect'][$relationConf['LSobject']])) { + if (method_exists($relationConf['LSobject'],$relationConf['update_function'])) { + $objRel = new $relationConf['LSobject'](); + if($objRel -> $relationConf['update_function']($object,$_SESSION['LSselect'][$relationConf['LSobject']])) { + if (method_exists($relationConf['LSobject'],$relationConf['list_function'])) { + $list = $objRel -> $relationConf['list_function']($object); + if (is_array($list)) { + foreach($list as $o) { + $data['html'].= "
  • ".$o -> getDisplayValue()."
  • \n"; + } + } + else { + $data['html'] = "
  • "._('Liste vide.')."
  • \n"; + } + $data['id'] = $_REQUEST['id']; + } + else { + $GLOBALS['LSerror'] -> addErrorCode(1013,$relationName); + } + } + else { + $GLOBALS['LSerror'] -> addErrorCode(1015,$relationName); + } + } + else { + $GLOBALS['LSerror'] -> addErrorCode(1014,$relationName); + } + } + } + else { + $GLOBALS['LSerror'] -> addErrorCode(1011); + } + } + else { + $GLOBALS['LSerror'] -> addErrorCode(1012); + } + } + else { + $GLOBALS['LSerror'] -> addErrorCode(1012); + } + $data['imgload'] = $_REQUEST['imgload']; + } + else { + $GLOBALS['LSerror'] -> addErrorCode(1012); + } + } + break; + case 'deleteByDisplayValue': + if ((isset($_REQUEST['id'])) && (isset($_REQUEST['value'])) && (isset($_REQUEST['imgload']))) { + if (isset($_SESSION['LSrelation'][$_REQUEST['id']])) { + $conf = $_SESSION['LSrelation'][$_REQUEST['id']]; + if ($GLOBALS['LSsession']->loadLSobject($conf['objectType'])) { + $object = new $conf['objectType'](); + if (($object -> loadData($conf['objectDn'])) && (isset($object->config['relations'][$conf['relationName']]))) { + $relationConf = $object->config['relations'][$conf['relationName']]; + if ($GLOBALS['LSsession'] -> relationCanEdit($object -> getValue('dn'),$conf['relationName'])) { + if (method_exists($relationConf['LSobject'],$relationConf['list_function'])) { + $objRel = new $relationConf['LSobject'](); + $list = $objRel -> $relationConf['list_function']($object); + if (is_array($list)) { + $ok=false; + foreach($list as $o) { + if($o -> getDisplayValue() == $_REQUEST['value']) { + if (!$o -> deleteOneMember($object)) { + $GLOBALS['LSerror'] -> addErrorCode(1015,$conf['relationName']); + } + else { + $ok = true; + } + } + } + if (!$ok) { + $GLOBALS['LSerror'] -> addErrorCode(1015,$conf['relationName']); + } + } + else { + $GLOBALS['LSerror'] -> addErrorCode(1015,$conf['relationName']); + $GLOBALS['LSerror'] -> addErrorCode(1); + } + } + else { + $GLOBALS['LSerror'] -> addErrorCode(1013,$conf['relationName']); + } + } + else { + $GLOBALS['LSerror'] -> addErrorCode(1011); + } + } + else { + $GLOBALS['LSerror'] -> addErrorCode(1012); + } + } + else { + $GLOBALS['LSerror'] -> addErrorCode(1012); + } + $data['imgload'] = $_REQUEST['imgload']; + } + else { + $GLOBALS['LSerror'] -> addErrorCode(1012); + } + } + break; + } + break; + case 'LSselect': + switch($_REQUEST['action']) { + case 'addLSselectobject-item': + if ((isset($_REQUEST['objecttype'])) && (isset($_REQUEST['objectdn']))) { + if (is_array($_SESSION['LSselect'][$_REQUEST['objecttype']])) { + if (!in_array($_REQUEST['objectdn'],$_SESSION['LSselect'][$_REQUEST['objecttype']])) { + $_SESSION['LSselect'][$_REQUEST['objecttype']][]=$_REQUEST['objectdn']; + } + } + else { + $_SESSION['LSselect'][$_REQUEST['objecttype']][]=$_REQUEST['objectdn']; + } + } + $data=$_REQUEST['imgload']; + break; + case 'dropLSselectobject-item': + if ((isset($_REQUEST['objecttype'])) && (isset($_REQUEST['objectdn']))) { + if (is_array($_SESSION['LSselect'][$_REQUEST['objecttype']])) { + $result=array(); + foreach ($_SESSION['LSselect'][$_REQUEST['objecttype']] as $val) { + if ($val!=$_REQUEST['objectdn']) { + $result[]=$val; + } + } + $_SESSION['LSselect'][$_REQUEST['objecttype']]=$result; + } + } + $data=$_REQUEST['imgload']; + break; + case 'refreshSession': + if ((isset($_REQUEST['objecttype'])) && (isset($_REQUEST['values'])) && (isset($_REQUEST['imgload'])) && (isset($_REQUEST['href'])) ) { + $_SESSION['LSselect'][$_REQUEST['objecttype']]=array(); + $values=json_decode($_REQUEST['values'],false); + if (is_array($values)) { + foreach($values as $val) { + $_SESSION['LSselect'][$_REQUEST['objecttype']][]=$val; + } + } + $data=array( + 'imgload' => $_REQUEST['imgload'], + 'href' => $_REQUEST['href'], + 'values' => $values + ); + } else { - $data=NULL; + $GLOBALS['LSerror'] -> addErrorCode(1012); + $data = array( + 'LSerror' => $GLOBALS['LSerror']->getErrors(), + 'imgload' => $_REQUEST['imgload'] + ); } break; } break; } +if ($GLOBALS['LSerror']->errorsDefined()) { + $data['LSerror'] = $GLOBALS['LSerror']->getErrors(); +} + echo json_encode($data); ?> diff --git a/trunk/modify.php b/trunk/modify.php index ff00e9f7..814d810c 100644 --- a/trunk/modify.php +++ b/trunk/modify.php @@ -68,9 +68,15 @@ if($LSsession -> startLSsession()) { if ($form->validate()) { // MàJ des données de l'objet LDAP if ($object -> updateData('modify')) { - header('Location: view.php?LSobject='.$LSobject.'&dn='.$object -> getDn()); + debug('ok'); + //header('Location: view.php?LSobject='.$LSobject.'&dn='.$object -> getDn()); } } + + + + $GLOBALS['LSsession'] -> addJSscript('LSsmoothbox.js'); + $GLOBALS['LSsession'] -> addCssFile('LSsmoothbox.css'); $GLOBALS['Smarty'] -> assign('LSview_actions',$LSview_actions); $GLOBALS['LSsession'] -> setTemplate('modify.tpl'); $form -> display(); diff --git a/trunk/select.php b/trunk/select.php new file mode 100644 index 00000000..592bd4b5 --- /dev/null +++ b/trunk/select.php @@ -0,0 +1,148 @@ + startLSsession()) { + if (isset($_REQUEST['LSobject'])) { + $LSobject = $_REQUEST['LSobject']; + + if ( $GLOBALS['LSsession'] -> loadLSobject($_REQUEST['LSobject']) ) { + $objectList=array(); + $object = new $_REQUEST['LSobject'](); + + + if ( $_REQUEST['LSview_pattern']!='' ) { + $filter='(|'; + if ( isset($_REQUEST['LSview_approx']) ) { + foreach ($object -> attrs as $attr_name => $attr_val) { + $filter.='('.$attr_name.'~='.$_REQUEST['LSview_pattern'].')'; + } + } + else { + foreach ($object -> attrs as $attr_name => $attr_val) { + $filter.='('.$attr_name.'=*'.$_REQUEST['LSview_pattern'].'*)'; + } + } + $filter.=')'; + $GLOBALS['Smarty']->assign('LSobject_list_filter','filter='.urlencode($filter)); + } + else if ($_REQUEST['filter']) { + $filter=urldecode($_REQUEST['filter']); + $GLOBALS['Smarty']->assign('LSobject_list_filter','filter='.$_REQUEST['filter']); + } + else { + $filter=NULL; + $GLOBALS['Smarty']->assign('LSobject_list_filter',''); + } + + $list=$object -> listObjects($filter); + $nbObjects=count($list); + + if ($nbObjects > NB_LSOBJECT_LIST) { + if (isset($_GET['page'])) { + $list = array_slice($list, ($_GET['page']) * NB_LSOBJECT_LIST, NB_LSOBJECT_LIST); + $GLOBALS['Smarty']->assign('LSobject_list_currentpage',$_GET['page']); + $GLOBALS['Smarty']->assign('LSobject_list_nbpage',ceil($nbObjects / NB_LSOBJECT_LIST)); + } + else { + $list = array_slice($list, 0, NB_LSOBJECT_LIST); + $GLOBALS['Smarty']->assign('LSobject_list_currentpage',0); + $GLOBALS['Smarty']->assign('LSobject_list_nbpage',ceil($nbObjects / NB_LSOBJECT_LIST)); + } + } + $c=0; + foreach($list as $thisObject) { + $c++; + unset($actions); + if ($GLOBALS['LSsession'] -> canAccess($_REQUEST['LSobject'],$thisObject->getValue('dn'))) { + if ($c%2==0) { + $tr='bis'; + } + else { + $tr=''; + } + + if (is_array($_SESSION['LSselect'][$_REQUEST['LSobject']])) { + if(in_array($thisObject -> getValue('dn'),$_SESSION['LSselect'][$_REQUEST['LSobject']])) { + $select = true; + } + else { + $select = false; + } + } + else { + $select = false; + } + + $objectList[]=array( + 'dn' => $thisObject->getValue('dn'), + 'displayValue' => $thisObject->getDisplayValue(), + 'actions' => $actions, + 'tr' => $tr, + 'select' => $select + ); + } + } + + + $GLOBALS['LSsession'] -> addJSscript('LSview.js'); + //$GLOBALS['LSsession'] -> addJSscript('LSselect.js'); + + $GLOBALS['Smarty']->assign('LSview_search',array( + 'action' => $_SERVER['PHP_SELF'], + 'submit' => _('Rechercher'), + 'LSobject' => $_REQUEST['LSobject'] + )); + + $GLOBALS['Smarty']->assign('pagetitle',$object -> getLabel()); + $GLOBALS['Smarty']->assign('LSobject_list_objectname',$object -> getLabel()); + $GLOBALS['Smarty']->assign('LSobject_list_nbresult',$nbObjects); + $GLOBALS['Smarty']->assign('LSobject_list',$objectList); + $GLOBALS['Smarty']->assign('LSobject_list_objecttype',$_REQUEST['LSobject']); + if (isset($_REQUEST['ajax'])) { + $GLOBALS['LSsession'] -> setTemplate('select_table.tpl'); + } + else { + $GLOBALS['LSsession'] -> setTemplate('select.tpl'); + } + } + else { + $GLOBALS['LSerror'] -> addErrorCode(1004,$_REQUEST['LSobject']); + $GLOBALS['LSsession'] -> setTemplate('blank.tpl'); + } + } + else { + $GLOBALS['LSerror'] -> addErrorCode(1012); + $GLOBALS['LSsession'] -> setTemplate('blank.tpl'); + } +} +else { + $GLOBALS['LSsession'] -> setTemplate('login.tpl'); +} + +// Affichage des retours d'erreurs +$GLOBALS['LSsession'] -> displayTemplate(); +?> diff --git a/trunk/templates/LSrelations.tpl b/trunk/templates/LSrelations.tpl new file mode 100644 index 00000000..b494a677 --- /dev/null +++ b/trunk/templates/LSrelations.tpl @@ -0,0 +1,13 @@ +

    {$item.label}

    +{if $item.actions!=''} +

    + {foreach from=$item.actions item=action} + {$action.label} {$action.label} + {/foreach} +

    +{/if} +
      +{foreach from=$item.objectList item=object} +
    • {$object}
    • +{/foreach} +
    diff --git a/trunk/templates/accueil.tpl b/trunk/templates/accueil.tpl index 258cbbc0..069bcac4 100644 --- a/trunk/templates/accueil.tpl +++ b/trunk/templates/accueil.tpl @@ -1,39 +1,3 @@ - - - - LdapSaisie{if $pagetitle != ''} - {$pagetitle}{/if} - - {$LSsession_css} - {$LSsession_js} - - -
    -{$LSerrors} -
    -
    - X -
    {if $LSdebug != ''}{$LSdebug}{/if}
    -
    - -
    - -
    - - -
    - - -
    -
    - - +{include file='top.tpl'} +

    {$pagetitle}

    +{include file='bottom.tpl'} diff --git a/trunk/templates/base.tpl b/trunk/templates/base.tpl deleted file mode 100644 index 8dbeeb0b..00000000 --- a/trunk/templates/base.tpl +++ /dev/null @@ -1,49 +0,0 @@ - - - - LdapSaisie{if $pagetitle != ''} - {$pagetitle}{/if} - - {$LSsession_css} - {$LSsession_js} - - -
    -{$LSerrors} -
    -
    - X -
    {if $LSdebug != ''}{$LSdebug}{/if}
    -
    - -
    -
    - - -
    - -
    -
    - - diff --git a/trunk/templates/blank.tpl b/trunk/templates/blank.tpl new file mode 100644 index 00000000..f12a80f9 --- /dev/null +++ b/trunk/templates/blank.tpl @@ -0,0 +1,20 @@ + + + + LdapSaisie{if $pagetitle != ''} - {$pagetitle}{/if} + + + {$LSsession_css} + {$LSsession_js} + + +
    +{$LSerrors} +
    +
    + X +
    {if $LSdebug != ''}{$LSdebug}{/if}
    +
    + + diff --git a/trunk/templates/bottom.tpl b/trunk/templates/bottom.tpl new file mode 100644 index 00000000..f23e12ff --- /dev/null +++ b/trunk/templates/bottom.tpl @@ -0,0 +1,5 @@ + +
    + + + diff --git a/trunk/templates/create.tpl b/trunk/templates/create.tpl index 32132a6a..2882c6e9 100644 --- a/trunk/templates/create.tpl +++ b/trunk/templates/create.tpl @@ -1,33 +1,4 @@ - - - - LdapSaisie{if $pagetitle != ''} - {$pagetitle}{/if} - - {$LSsession_css} - {$LSsession_js} - - -
    -{$LSerrors} -
    -
    - X -
    {if $LSdebug != ''}{$LSdebug}{/if}
    -
    - -
    -
    - - -
    - -
    -
    - - +{include file='bottom.tpl'} diff --git a/trunk/templates/css/LSform.css b/trunk/templates/css/LSform.css index b766001b..69374d13 100644 --- a/trunk/templates/css/LSform.css +++ b/trunk/templates/css/LSform.css @@ -21,7 +21,7 @@ dd.LSform { .LSform input, .LSform select, .LSform textarea { border: 1px inset #ccc; - width: 20em; + width: 300px; background-color: #b5e4f6; } @@ -46,3 +46,30 @@ ul.LSform { img.LSform-add-field-btn, img.LSform-remove-field-btn { cursor: pointer; } + +a.LSformElement_select_object_addBtn { + text-decoration: none; + color: #000; + font-weight: normal; + +} + +ul.LSformElement_select_object { + border: 1px solid #b5e4f6; + border-bottom: none; + width: 300px; +} + +li.LSformElement_select_object { + padding: 0.1em; + border-bottom: 1px solid #b5e4f6; +} + +li.LSformElement_select_object_addBtn { + background-color: #b5e4f6; + text-align: center; +} + +img.LSformElement_select_object_deleteBtn { + cursor: pointer; +} diff --git a/trunk/templates/css/LSsmoothbox.css b/trunk/templates/css/LSsmoothbox.css new file mode 100644 index 00000000..15487c81 --- /dev/null +++ b/trunk/templates/css/LSsmoothbox.css @@ -0,0 +1,28 @@ +#over-LSsmoothbox { + background-color: #000; + border: 1px solid #000; + margin: 0; + padding: 0; +} + +#win-LSsmoothbox { + background-color: #fff; + border: 3px solid #000; + margin: auto; +} + +#pnav-LSsmoothbox { + text-align: right; + font-family: sans-serif; + font-weight: bold; + background-color: #777; + margin: 0; + margin-bottom: 0; +} + +#pnav-LSsmoothbox span { + color: #fff; + margin: 1em; + margin-bottom: 0; + font-size: 100%; +} diff --git a/trunk/templates/css/base.css b/trunk/templates/css/base.css index 2d34e454..52f9f406 100644 --- a/trunk/templates/css/base.css +++ b/trunk/templates/css/base.css @@ -14,8 +14,10 @@ a:hover { h1 { margin: 0.5em; + margin-bottom: 0em; border-bottom: 1px solid #0072b8; color: #0072b8; + clear: left; } a img { @@ -33,6 +35,7 @@ hr { margin: auto; border: 1px solid #52bce5; background: #fff url(../images/fd_menu.png) repeat-y scroll left top; + height: 100%; } #left { @@ -81,9 +84,11 @@ a.menu { table.LSobject-list { margin-left: 1em; + margin-top: 0.5em; border: 1px solid #52bce5; - width: 30em; + width: 805px; border-collapse: collapse; + clear: both; } td.LSobject-list { @@ -96,6 +101,10 @@ th.LSobject-list { color: #fff; } +tr.LSobject-list-bis { + background-color: #ecf8fd; +} + a.LSobject-list { color: #000; text-decoration: none; @@ -138,11 +147,22 @@ strong.LSobject-list-page { } p.LSview-actions { - text-align: right; - font-size: 0.8em; - margin: 0.2em; - margin-right: 3em; - color: #0072b8; + clear: both; + text-align: right; + font-size: 0.8em; + margin: 0; + margin-top: 0.3em; + margin-right: 3em; + margin-bottom: 0.8em; + color: #0072b8; +} + +a.LSview-actions { + text-decoration: none; + color: #000; + border: 1px solid #0072b8; + border-top: 0; + padding: 0.4em; } p.question { @@ -154,3 +174,78 @@ a.question { margin-top: 3em; color: #0072b8; } + +div.LSform_image { + float: right; + clear: both; + margin: 2em; + background-color: #52bce5; + width: 160px; + padding: 5px; + text-align: center; + -moz-border-radius: 1em; +} + +div.LSform_image_errors { + background-color: #f59a67; +} + +img.LSform_image { + width: 150px; + border: 1px solid #fff; + margin: 5px; +} + +ul.LSform_image_actions { + list-style-type: none; + position: absolute; + margin-top: 8px; + margin-left: 135px; + padding: 0; + visibility: hidden; + cursor: pointer; +} + +form.LSview_search { + float: right; + margin: 0; + margin-top: 0.5em; + margin-right: 2em; +} + +label.LSview_search { + font-size: 0.6em; + display: block; +} + +input[type='text'].LSview_search { + border: 1px solid #0072b8; + width: 12em; +} + +input[type='submit'].LSview_search { + border: 1px solid #0072b8; + width: 8em; + background-color: #52bce5; + color: #fff; +} + +div.LSobject-select { + width: 600px; +} + +#LSselect-object { + width: 570px; +} + +.LSobject-select-check { + width: 10px; +} + +form.LSselect_search { + margin-top: 0.5em; +} + +img.LSrelation-btn { + margin-left: 0.5em; +} diff --git a/trunk/templates/css/base_print.css b/trunk/templates/css/base_print.css new file mode 100644 index 00000000..f5e52374 --- /dev/null +++ b/trunk/templates/css/base_print.css @@ -0,0 +1,15 @@ +#main { + width: 840px; +} + +#left { + display: none; +} + +#status { + display: none; +} + +p.LSview-actions { + display: none; +} diff --git a/trunk/templates/empty.tpl b/trunk/templates/empty.tpl index 5d6e0d7b..70430570 100644 --- a/trunk/templates/empty.tpl +++ b/trunk/templates/empty.tpl @@ -1,34 +1,2 @@ - - - - LdapSaisie{if $pagetitle != ''} - {$pagetitle}{/if} - - {$LSsession_css} - {$LSsession_js} - - -
    -{$LSerrors} -
    -
    - X -
    {if $LSdebug != ''}{$LSdebug}{/if}
    -
    - -
    -
    - - -
    - -
    -
    - - +{include file='top.tpl'} +{include file='bottom.tpl'} diff --git a/trunk/templates/images/imgbroken.png b/trunk/templates/images/imgbroken.png new file mode 100644 index 0000000000000000000000000000000000000000..adeb879e175c128e24c29c7f28f18cb7bf198ba9 GIT binary patch literal 15374 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 literal 0 HcmV?d00001 diff --git a/trunk/templates/images/person.png b/trunk/templates/images/person.png new file mode 100755 index 0000000000000000000000000000000000000000..71038ed775adadd48820de81b684fbafe9c9dc5a GIT binary patch literal 22391 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 JPDHLkV1n1##MS@+ literal 0 HcmV?d00001 diff --git a/trunk/templates/modify.tpl b/trunk/templates/modify.tpl index dcaf0634..b641961b 100644 --- a/trunk/templates/modify.tpl +++ b/trunk/templates/modify.tpl @@ -1,43 +1,28 @@ - - - - LdapSaisie{if $pagetitle != ''} - {$pagetitle}{/if} - - {$LSsession_css} - {$LSsession_js} - - -
    -{$LSerrors} -
    -
    - X -
    {if $LSdebug != ''}{$LSdebug}{/if}
    -
    - -
    -
    - - -
    -
    -
    -
    - - +{include file='bottom.tpl'} diff --git a/trunk/templates/question.tpl b/trunk/templates/question.tpl index 1dddb5ee..1fd13cf7 100644 --- a/trunk/templates/question.tpl +++ b/trunk/templates/question.tpl @@ -1,32 +1,4 @@ - - - - LdapSaisie{if $pagetitle != ''} - {$pagetitle}{/if} - - {$LSsession_css} - {$LSsession_js} - - -
    -{$LSerrors} -
    -
    - X -
    {if $LSdebug != ''}{$LSdebug}{/if}
    -
    - -
    -
    - - -
    - -
    -
    - - +{include file='bottom.tpl'} diff --git a/trunk/templates/select.tpl b/trunk/templates/select.tpl new file mode 100644 index 00000000..c231ddb7 --- /dev/null +++ b/trunk/templates/select.tpl @@ -0,0 +1,17 @@ +
    + +

    + {$pagetitle} +

    +
    + {include file='select_table.tpl'} +
    +
    + diff --git a/trunk/templates/select_table.tpl b/trunk/templates/select_table.tpl new file mode 100644 index 00000000..29b21d9f --- /dev/null +++ b/trunk/templates/select_table.tpl @@ -0,0 +1,23 @@ + + + + + +{foreach from=$LSobject_list item=object} + + + + +{/foreach} +
    {$LSobject_list_objectname}
    {$object.displayValue}
    +{if $LSobject_list_nbpage} +

    + {section name=listpage loop=$LSobject_list_nbpage step=1} + {if $LSobject_list_currentpage == $smarty.section.listpage.index} + {$LSobject_list_currentpage+1} + {else} + {$smarty.section.listpage.index+1} + {/if} + {/section} +

    +{/if} diff --git a/trunk/templates/top.tpl b/trunk/templates/top.tpl new file mode 100644 index 00000000..88eb1c69 --- /dev/null +++ b/trunk/templates/top.tpl @@ -0,0 +1,30 @@ + + + + LdapSaisie{if $pagetitle != ''} - {$pagetitle}{/if} + + + {$LSsession_css} + {$LSsession_js} + + +
    +{$LSerrors} +
    +
    + X +
    {if $LSdebug != ''}{$LSdebug}{/if}
    +
    + +
    +
    + + +
    +