- LSldapObject : Ajout des méthodes suivantes :
[ldapsaisie.git] / trunk / includes / class / class.LSldapObject.php
1 <?php
2 /*******************************************************************************
3  * Copyright (C) 2007 Easter-eggs
4  * http://ldapsaisie.labs.libre-entreprise.org
5  *
6  * Author: See AUTHORS file in top-level directory.
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License version 2
10  * as published by the Free Software Foundation.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
20
21 ******************************************************************************/
22
23 $GLOBALS['LSsession'] -> loadLSclass('LSattribute');
24
25 /**
26  * Base d'un objet ldap
27  *
28  * Cette classe définis la base de tout objet ldap géré par LdapSaisie
29  *
30  * @author Benjamin Renard <brenard@easter-eggs.com>
31  */
32 class LSldapObject { 
33   
34   var $config = array();
35   var $type_name;
36   var $attrs = array();
37   var $forms;
38   var $view;
39   var $dn=false;
40   var $other_values=array();
41   var $submitError=true;
42   var $_whoami=NULL;
43   var $_subDn_value=NULL;
44   
45   /**
46    * Constructeur
47    *
48    * Cette methode construit l'objet et définis la configuration.
49    * Elle lance la construction du tableau d'attributs représentés par un objet LSattribute.
50    *
51    * @author Benjamin Renard <brenard@easter-eggs.com>
52    *
53    * @param[in] $type_name [<b>required</b>] string Le nom du type de l'objet
54    * @param[in] $config array La configuration de l'objet
55    *
56    * @retval boolean true si l'objet a été construit, false sinon.
57    */ 
58   function LSldapObject($type_name,$config='auto') {
59     $this -> type_name = $type_name;
60     $this -> config = $config;
61     if($config=='auto') {
62       if(isset($GLOBALS['LSobjects'][$type_name])) {
63         $this -> config = $GLOBALS['LSobjects'][$type_name];
64       }
65       else {
66         $GLOBALS['LSerror'] -> addErrorCode(21);
67         return;
68       }
69     }
70     foreach($this -> config['attrs'] as $attr_name => $attr_config) {
71       if(!$this -> attrs[$attr_name]=new LSattribute($attr_name,$attr_config,$this)) {
72         return;
73       }
74     }
75     return true;
76   }
77   
78   /**
79    * Charge les données de l'objet
80    *
81    * Cette methode définis le DN de l'objet et charge les valeurs de attributs de l'objet
82    * à partir de l'annuaire.
83    *
84    * @author Benjamin Renard <brenard@easter-eggs.com>
85    *
86    * @param[in] $dn string Le DN de l'objet.
87    *
88    * @retval boolean true si la chargement a réussi, false sinon.
89    */ 
90   function loadData($dn) {
91     $this -> dn = $dn;
92     $data = $GLOBALS['LSldap'] -> getAttrs($dn);
93     if(!empty($data)) {
94       foreach($this -> attrs as $attr_name => $attr) {
95         if(!$this -> attrs[$attr_name] -> loadData($data[$attr_name]))
96           return;
97       }
98       return true;
99     }
100     return;
101   }
102   
103   /**
104    * Recharge les données de l'objet
105    *
106    * @author Benjamin Renard <brenard@easter-eggs.com>
107    *
108    * @retval boolean true si la rechargement a réussi, false sinon.
109    */ 
110   function reloadData() {
111     $data = $GLOBALS['LSldap'] -> getAttrs($this -> dn);
112     foreach($this -> attrs as $attr_name => $attr) {
113       if(!$this -> attrs[$attr_name] -> reloadData($data[$attr_name]))
114         return;
115     }
116     return true;
117   }
118   
119   /**
120    * Retourne le format d'affichage de l'objet
121    *
122    * @author Benjamin Renard <brenard@easter-eggs.com>
123    *
124    * @retval string Format d'affichage de l'objet.
125    */ 
126   function getDisplayAttributes() {
127     return $this -> config['select_display_attrs'];
128   }
129   
130   /**
131    * Retourne la valeur descriptive d'affichage de l'objet
132    * 
133    * Cette fonction retourne la valeur descriptive d'affichage de l'objet en fonction
134    * du format défini dans la configuration de l'objet ou spécifié en paramètre.
135    *
136    * @author Benjamin Renard <brenard@easter-eggs.com>
137    *
138    * @param[in] $spe [<i>optionnel</i>] string Format d'affichage de l'objet
139    *
140    * @retval string Valeur descriptive d'affichage de l'objet
141    */ 
142   function getDisplayValue($spe='') {
143     if ($spe=='') {
144       $spe = $this -> getDisplayAttributes();
145     }
146     return $this -> getFData($spe,&$this -> attrs,'getDisplayValue');
147   }
148   
149   /**
150    * Chaine formatée
151    * 
152    * Cette fonction retourne la valeur d'une chaine formatée en prennant les valeurs
153    * de l'objet.
154    *
155    * @author Benjamin Renard <brenard@easter-eggs.com>
156    *
157    * @param[in] $format string Format de la chaine
158    *
159    * @retval string Valeur d'une chaine formatée
160    */ 
161   function getFData($format) {
162     $format=getFData($format,$this,'getValue');
163     return $format;
164   }
165   
166   /**
167    * Construit un formulaire de l'objet
168    * 
169    * Cette méthode construit un formulaire LSform à partir de la configuration de l'objet
170    * et de chaque attribut.
171    *
172    * @param[in] $idForm [<b>required</b>] Identifiant du formulaire a créer
173    * @param[in] $load DN d'un objet similaire dont la valeur des attribut doit être chargé dans le formulaire.
174    *
175    * @author Benjamin Renard <brenard@easter-eggs.com>
176    *
177    * @retval LSform Le formulaire crée
178    */ 
179   function getForm($idForm,$load=NULL) {
180     $GLOBALS['LSsession'] -> loadLSclass('LSform');
181     $LSform = new LSform($this,$idForm);
182     $this -> forms[$idForm] = array($LSform,$load);
183     
184     if ($load) {
185       $type = $this -> getType();
186       $loadObject = new $type();
187       if (!$loadObject -> loadData($load)) {
188         $load=false;
189       }
190     }
191     
192     if ($load) {
193       foreach($this -> attrs as $attr_name => $attr) {
194         if(!$this -> attrs[$attr_name] -> addToForm($LSform,$idForm,$this,$loadObject -> getValue($attr_name))) {
195           $LSform -> can_validate = false;
196         }
197       }
198     }
199     else {
200       foreach($this -> attrs as $attr_name => $attr) {
201         if(!$this -> attrs[$attr_name] -> addToForm($LSform,$idForm,$this)) {
202           $LSform -> can_validate = false;
203         }
204       }      
205     }
206     return $LSform;
207   }
208   
209   /**
210    * Construit un formulaire de l'objet
211    * 
212    * Cette méthode construit un formulaire LSform à partir de la configuration de l'objet
213    * et de chaque attribut.
214    *
215    * @param[in] $idForm [<b>required</b>] Identifiant du formulaire a créer
216    * @param[in] $config Configuration spécifique pour le formulaire
217    *
218    * @author Benjamin Renard <brenard@easter-eggs.com>
219    *
220    * @retval LSform Le formulaire crée
221    */ 
222   function getView() {
223     $GLOBALS['LSsession'] -> loadLSclass('LSform');
224     $this -> view = new LSform($this,'view');
225     foreach($this -> attrs as $attr_name => $attr) {
226       $this -> attrs[$attr_name] -> addToView($this -> view);
227     }
228     $this -> view -> can_validate = false;
229     return $this -> view;
230   }  
231   
232   /**
233    * Rafraichis le formulaire de l'objet
234    * 
235    * Cette méthode recharge les données d'un formulaire LSform.
236    *
237    * @param[in] $idForm [<b>required</b>] Identifiant du formulaire a créer
238    *
239    * @author Benjamin Renard <brenard@easter-eggs.com>
240    *
241    * @retval boolean true sile formulaire a été rafraichis, false sinon
242    */ 
243   function refreshForm($idForm) {
244     $LSform = $this -> forms[$idForm][0];
245     foreach($this -> attrs as $attr_name => $attr) {
246       if(!$this -> attrs[$attr_name] -> refreshForm($LSform,$idForm)) {
247         return;
248       }
249     }
250     return true;
251   }
252   
253   /**
254    * Met à jour les données de l'objet et de l'entré de l'annuaire
255    * 
256    * Met à jour les données de l'objet à partir d'un retour d'un formulaire.
257    *
258    * @param[in] $idForm Identifiant du formulaire d'origine
259    *
260    * @author Benjamin Renard <brenard@easter-eggs.com>
261    *
262    * @retval boolean true si la mise à jour a réussi, false sinon
263    *
264    * @see validateAttrsData()
265    * @see submitChange()
266    */ 
267   function updateData($idForm=NULL) {
268     if($idForm!=NULL) {
269       if(isset($this -> forms[$idForm]))
270         $LSform = $this -> forms[$idForm][0];
271       else {
272         $GLOBALS['LSerror'] -> addErrorCode(22,$this -> getType());
273         return;
274       }
275     }
276     else {
277       if(count($this -> forms) > 0) {
278         reset($this -> forms);
279         $idForm = key($this -> forms);
280         $LSform = current($this -> forms);
281         $config = $LSform[1];
282         $LSform = $LSform[0];
283       }
284       else {
285         $GLOBALS['LSerror'] -> addErrorCode(23,$this -> getType());
286         return;
287       }
288     }
289     $new_data = $LSform -> exportValues();
290     foreach($new_data as $attr_name => $attr_val) {
291       if(isset($this -> attrs[$attr_name])) {
292         $this -> attrs[$attr_name] -> setUpdateData($attr_val);
293       }
294     }
295     if($this -> validateAttrsData($idForm)) {
296       debug("les données sont validées");
297       if(isset($this -> config['before_save'])) {
298         if(function_exists($this -> config['before_save'])) {
299           if(!$this -> config['before_save']($this)) {
300             $GLOBALS['LSerror'] -> addErrorCode(28,$this -> config['before_save']);
301             return;
302           }
303         }
304         else {
305           $GLOBALS['LSerror'] -> addErrorCode(27,$this -> config['before_save']);
306           return;
307         }
308       }
309       if ($this -> submitChange($idForm)) {
310         debug('Les modifications sont submitées');
311         $this -> submitError = false;
312         $this -> reloadData();
313         $this -> refreshForm($idForm);
314       }
315       else {
316         return;
317       }
318       if((isset($this -> config['after_save']))&&(!$this -> submitError)) {
319         if(function_exists($this -> config['after_save'])) {
320           if(!$this -> config['after_save']($this)) {
321             $GLOBALS['LSerror'] -> addErrorCode(30,$this -> config['after_save']);
322             return;
323           }
324         }
325         else {
326           $GLOBALS['LSerror'] -> addErrorCode(29,$this -> config['after_save']);
327           return;
328         }
329       }
330       return true;
331     }
332     else {
333       return;
334     }
335   }
336   
337   /**
338    * Valide les données retournées par un formulaire
339    *
340    * @param[in] $idForm Identifiant du formulaire d'origine
341    *
342    * @author Benjamin Renard <brenard@easter-eggs.com>
343    *
344    * @retval boolean true si les données sont valides, false sinon
345    */ 
346   function validateAttrsData($idForm) {
347     $LSform=$this -> forms[$idForm][0];
348     foreach($this -> attrs as $attr) {
349       if (!$attr -> isValidate()) {
350         if($attr -> isUpdate()) {
351           if (!$this -> validateAttrData($LSform, $attr)) {
352             return;
353           }
354         }
355         else if( ($attr -> getValue() == '') && ($attr -> isRequired()) ) { 
356           if ( $attr -> canBeGenerated()) {
357             if ($attr -> generateValue()) {
358               if (!$this -> validateAttrData($LSform, $attr)) {
359                 $GLOBALS['LSerror'] -> addErrorCode(48,$attr -> getLabel());
360                 return;
361               }
362             }
363             else {
364               $GLOBALS['LSerror'] -> addErrorCode(47,$attr -> getLabel());
365               return;
366             }
367           }
368           else {
369             $GLOBALS['LSerror'] -> addErrorCode(46,$attr -> getLabel());
370             return;
371           }
372
373         }
374       }
375     }
376     return true;
377   }
378
379    /**
380    * Valide les données d'un attribut
381    *
382    * @param[in] $LSForm Formulaire d'origine
383    * @param[in] &$attr Attribut à valider
384    *
385    * @author Benjamin Renard <brenard@easter-eggs.com>
386    *
387    * @retval boolean true si les données sont valides, false sinon
388    */
389   function validateAttrData(&$LSform,&$attr) {
390     $vconfig=$attr -> getValidateConfig();
391
392     $data=$attr -> getUpdateData();
393     if(!is_array($data)) {
394       $data=array($data);
395     }
396
397     // Validation des valeurs de l'attribut
398     if(is_array($vconfig)) {
399       foreach($vconfig as $test) {
400         // Définition du basedn par défaut
401         if (!isset($test['basedn'])) {
402           $test['basedn']=$GLOBALS['LSsession']->topDn;
403         }
404
405         // Définition du message d'erreur
406         if (!empty($test['msg'])) {
407           $msg_error=getFData($test['msg'],$this,'getValue');
408         }
409         else {
410           $msg_error=getFData(_("L'attribut %{attr} n'est pas valide."),$attr -> getLabel());
411         }
412         foreach($data as $val) {
413           // validation par check LDAP
414           if((isset($test['filter'])||isset($test['basedn']))&&(isset($test['result']))) {
415             $sparams=(isset($test['scope']))?array('scope' => $test['scope']):array();
416             $this -> other_values['val']=$val;
417             $sfilter_user=(isset($test['basedn']))?getFData($test['filter'],$this,'getValue'):NULL;
418             if(isset($test['object_type'])) {
419               $test_obj = new $test['object_type']();
420               $sfilter=$test_obj->getObjectFilter();
421               $sfilter='(&'.$sfilter;
422               if($sfilter_user[0]=='(') {
423                 $sfilter=$sfilter.$sfilter_user.')';
424               }
425               else {
426                 $sfilter=$sfilter.'('.$sfilter_user.'))';
427               }
428             }
429             else {
430               $sfilter=$sfilter_user;
431             }
432             $sbasedn=(isset($test['basedn']))?getFData($test['basedn'],$this,'getValue'):NULL;
433             $ret=$GLOBALS['LSldap'] -> getNumberResult ($sfilter,$sbasedn,$sparams);
434             if($test['result']==0) {
435               if($ret!=0) {
436                 $LSform -> setElementError($attr,$msg_error);
437                 return;
438               }
439             }
440             else {
441               if($ret<=0) {
442                 $LSform -> setElementError($attr,$msg_error);
443                 return;
444               }
445             }
446           }
447           // Validation par fonction externe
448           else if(isset($test['function'])) {
449             if (function_exists($test['function'])) {
450               if(!$test['function']($this)) {
451                 $LSform -> setElementError($attr,$msg_error);
452               return;
453               }
454             }
455             else {
456               $GLOBALS['LSerror'] -> addErrorCode(24,array('attr' => $attr->name,'obj' => $this->getType(),'func' => $test['function']));
457               return;
458             }
459           }
460           else {
461             $GLOBALS['LSerror'] -> addErrorCode(25,array('attr' => $attr->name,'obj' => $this->getType()));
462             return;
463           }
464         }
465       }
466     }
467     // Génération des valeurs des attributs dépendants
468     $dependsAttrs=$attr->getDependsAttrs();
469     if (!empty($dependsAttrs)) {
470       foreach($dependsAttrs as $dependAttr) {
471         if(!isset($this -> attrs[$dependAttr])){
472           $GLOBALS['LSerror'] -> addErrorCode(34,array('attr_depend' => $dependAttr, 'attr' => $attr -> getLabel()));
473           continue;
474         }
475         if($this -> attrs[$dependAttr] -> canBeGenerated()) {
476           if (!$this -> attrs[$dependAttr] -> generateValue()) {
477             $GLOBALS['LSerror'] -> addErrorCode(47,$this -> attrs[$dependAttr] -> getLabel());
478             return;
479           }
480         }
481         else {
482           $GLOBALS['LSerror'] -> addErrorCode(46,$this -> attrs[$dependAttr] -> getLabel());
483           return;
484         }
485       }
486     }
487
488     $attr -> validate();
489     unset($this -> other_values['val']);
490     return true;
491   }
492
493   /**
494    * Met à jour les données modifiés dans l'annuaire
495    *
496    * @param[in] $idForm Identifiant du formulaire d'origine
497    *
498    * @author Benjamin Renard <brenard@easter-eggs.com>
499    *
500    * @retval boolean true si la mise à jour a réussi, false sinon
501    */ 
502   function submitChange($idForm) {
503     $submitData=array();
504     foreach($this -> attrs as $attr) {
505       if(($attr -> isUpdate())&&($attr -> isValidate())) {
506         $submitData[$attr -> name] = $attr -> getUpdateData();
507       }
508     }
509     if(!empty($submitData)) {
510       $dn=$this -> getDn();
511       if($dn) {
512         $this -> dn=$dn;
513         debug($submitData);
514         return $GLOBALS['LSldap'] -> update($this -> getType(),$dn, $submitData);
515       }
516       else {
517         $GLOBALS['LSerror'] -> addErrorCode(33);
518         return;
519       }
520     }
521     else {
522       return true;
523     }
524   }
525   
526   /**
527    * Retourne les informations issus d'un DN
528    *
529    * @param[in] $dn Un DN.
530    *
531    * @author Benjamin Renard <brenard@easter-eggs.com>
532    *
533    * @retval array Tableau : 
534    *                  - [0] : le premier paramètre
535    *                  - [1] : les paramètres suivants
536    */ 
537   function getDnInfos($dn) {
538     $infos=ldap_explode_dn($dn,0);
539     if(!$infos)
540       return;
541     $first=true;
542     for($i=1;$i<$infos['count'];$i++)
543       if($first) {
544         $basedn.=$infos[$i];
545         $first=false;
546       }
547       else
548         $basedn.=','.$infos[$i];
549     return array($infos[0],$basedn);
550   }
551   
552   /**
553    * Retourne le filtre correpondants aux objetcClass de l'objet
554    *
555    * @author Benjamin Renard <brenard@easter-eggs.com>
556    *
557    * @retval string le filtre ldap correspondant au type de l'objet
558    */ 
559   function getObjectFilter() {
560     if(!isset($this -> config['objectclass'])) return;
561     foreach ($this -> config['objectclass'] as $class)
562       $filter.='(objectClass='.$class.')';
563     return $filter;
564   }
565   
566   /**
567    * Retourne une liste d'objet du même type.
568    *
569    * Effectue une recherche en fonction des paramètres passé et retourne un
570    * tableau d'objet correspond au resultat de la recherche.
571    *
572    * @author Benjamin Renard <brenard@easter-eggs.com>
573    *
574    * @param[in] $filter array (ou string) Filtre de recherche Ldap / Tableau de filtres de recherche
575    * @param[in] $basedn string DN de base pour la recherche
576    * @param[in] $params array Paramètres de recherche au format Net_LDAP2::search()
577    *
578    * @retval array Tableau d'objets correspondant au resultat de la recherche
579    */ 
580   function listObjects($filter='',$basedn=NULL,$params=array()) {
581     $retInfos=array();
582     $attrs=false;
583     $check_final_dn=false;
584
585     if(!is_array($filter))
586       $filter=array(array('filter' => $filter));
587     
588     $nbFilter=count($filter);
589
590     for($i=0;$i<$nbFilter;$i++) {
591       $new_attrs=array();
592       // Défintion des paramètres de base pour la recherche
593       $sbasedn=$basedn;
594       $sparams=$params;
595       $ret=array();
596       if (isset($filter[$i]['scope']))
597         $sparams["scope"]=$filter[$i]['scope'];
598       
599       // Definition des critères de recherche correspondant au type d'objet à lister
600       if(($nbFilter==1)||(!isset($filter[$i]['attr']))) {
601         // Filtre sur l'objet souhaité
602         $sfilter='(&';
603         $sfilter.=$this -> getObjectFilter();
604         $sfilter_end=')';
605         $check_final_dn=true;
606       }
607       // Initialisation des critères d'une recherche intermédiaire
608       else {
609         if(isset($filter[$i]['object_type'])) {
610           $obj_tmp=new $filter[$i]['object_type']();
611           $obj_filter=$obj_tmp->getObjectFilter();
612           $sfilter='(&'.$obj_filter;
613           $sfilter_end=')';
614         }
615         else {
616           $sfilter='';
617           $sfilter_end='';
618         }
619         if(isset($filter[$i]['scope'])) {
620           $sparams['scope']=$filter[$i]['scope'];
621         }
622         if(isset($filter[$i]['basedn'])) {
623           $sbasedn=$filter[$i]['basedn'];
624         }
625       }
626       // Dans le cas d'une recherche intermédiaire ou finale
627       if($attrs!=false) {
628         // Initialisation des variables
629         $ret_gen=array();
630         $new_attrs=array();
631         
632         // Pour tout les attributs retournés
633         for($ii=0;$ii<count($attrs);$ii++) {
634           $sfilter_for='';
635           // Définition du filtre de recherche à partir des paramètres utilisateurs et
636           // des paramètres de recherche de l'objet à listé (dans le cas d'une recherche finale
637           if((isset($filter[$i]['filter']))&&(!empty($filter[$i]['filter']))) {
638             $sfilter_user=getFData($filter[$i]['filter'],$attrs[$ii]);
639             if($sfilter_user[0]=='(')
640               $sfilter_for=$sfilter.$sfilter_user;
641             else
642               $sfilter_for=$sfilter.'('.$sfilter_user.')';
643           }
644           else {
645             $sfilter_for=$sfilter;
646           }
647           
648           if(isset($filter[$i]['basedn'])) {
649             $sbasedn=getFData($filter[$i]['basedn'],$attrs[$ii]);
650             if ((!$this -> isCompatibleDNs($sbasedn,$basedn))&&($check_final_dn)) continue;
651           }
652         
653           // Vérification de la compatibilité du basedn de la recherche et du basedn générale
654           // Finalisation du filtre
655           $sfilter_for.=$sfilter_end;
656         
657         
658           // Execution de la recherche
659           $ret=$GLOBALS['LSldap'] -> search ($sfilter_for,$sbasedn,$sparams);
660           
661           // Si il y un retour
662           if(isset($ret[0])) {
663             // si il ya une suite (recherche intermédiaire)
664             if($filter[$i]['attr']){
665               for($iii=0;$iii<count($ret);$iii++) {
666                 if(isset($ret[$iii]['attrs'][$filter[$i]['attr']])) {
667                   // cas de valeur multiple
668                   if(is_array($ret[$iii]['attrs'][$filter[$i]['attr']])) {
669                     foreach($ret[$iii]['attrs'][$filter[$i]['attr']] as $val_attr) {
670                       $new_attrs[]=$val_attr;
671                     }
672                   }
673                   // cas de valeur unique
674                   else {
675                     $new_attrs[]=$ret[$iii]['attrs'][$filter[$i]['attr']];
676                   }
677                 }
678               }
679             }
680             else {
681               // vérification de la compatibilité de la compatibilité du DN resultant
682               // et du basedn de recherche 
683               if (!$this -> isCompatibleDNs($ret[0]['dn'],$basedn))
684                 continue;
685               // ajout du DN au resultat finale
686               $ret_gen[]=$ret[0]['dn'];
687             }
688           }
689         }
690         // cas du dernier filtre
691         if(!empty($ret_gen)) {
692           // on quitte la boucle des filtres de la conf
693           $ret=$ret_gen;
694           break;
695         }
696         // dans le cas d'une suite prévu mais d'un retour nul de la précédente recherche
697         else if(empty($new_attrs)) {
698             // retour vide et arrêt de la recherche
699             $ret=array();
700             break;
701         }
702         else {
703           $attrs=$new_attrs;
704         }
705       }
706       // Dans le cas de la recherche initiale
707       else {
708         // Déclaration du filtre de recherche
709         if((isset($filter[$i]['filter']))&&(!empty($filter[$i]['filter']))) {
710           if($filter[$i]['filter'][0]=='(') {
711             $sfilter.=$filter[$i]['filter'];
712           }
713           else {
714             $sfilter.='('.$filter[$i]['filter'].')';
715           }
716         }
717         // fermeture du filtre
718         $sfilter.=$sfilter_end;
719         
720         // Lancement de la recherche
721         $ret=$GLOBALS['LSldap'] -> search ($sfilter,$sbasedn,$sparams);
722         
723         //Si filtre multiple => on recupère une liste d'attributs
724         if(isset($filter[$i]['attr'])) {
725           for($ii=0;$ii<count($ret);$ii++) {
726             if(isset($ret[$ii]['attrs'][$filter[$i]['attr']])) {
727               // cas de valeur multiple
728               if(is_array($ret[$ii]['attrs'][$filter[$i]['attr']])) {
729                 foreach($ret[$ii]['attrs'][$filter[$i]['attr']] as $val_attr) {
730                   $attrs[]=$val_attr;
731                 }
732               }
733               // cas de valeur unique
734               else {
735                 $attrs[]=$ret[$ii]['attrs'][$filter[$i]['attr']];
736               }
737             }
738           }
739           
740           // Si aucunne valeur n'est retournées
741           if(empty($attrs)){
742             // arrêt et retour à zéro
743             $ret=array();
744             break;
745           }
746         }
747         // Si recherche unique
748         else {
749           // préparation du retour finale
750           if (is_array($ret)) {
751             $ret_final=array();
752             foreach($ret as $obj)
753               $ret_final[]=$obj['dn'];
754             $ret=$ret_final;
755           }
756           else {
757             $ret=array();
758           }
759           break;
760         }
761       }
762     }
763     
764     // Création d'un tableau d'objet correspondant au valeur retourné
765     for($i=0;$i<count($ret);$i++) {
766       $retInfos[$i] = new $this -> type_name($this -> config);
767       $retInfos[$i] -> loadData($ret[$i]);
768     }
769     
770     return $retInfos;
771   }
772  
773  
774   /**
775    * Recherche un objet à partir de la valeur exact de son RDN
776    * 
777    * @author Benjamin Renard <brenard@easter-eggs.com>
778    * 
779    * @param[in] $name string Valeur de son RDN
780    * @param[in] $basedn string Le DN de base de la recherche
781    * 
782    * @retval array Tableau d'objets correspondant au resultat de la recherche
783    */
784   function searchObject($name,$basedn=NULL) {
785     $filter = $this -> config['rdn'].'='.$name; 
786     return $this -> listObjects($filter,$basedn); 
787   }
788
789   /**
790    * Retourne une valeur de l'objet
791    *
792    * Retourne une valeur en fonction du paramètre. Si la valeur est inconnue, la valeur retourné est ' '.
793    * tableau d'objet correspond au resultat de la recherche.
794    *
795    * Valeurs possibles :
796    * - 'dn' ou '%{dn} : DN de l'objet
797    * - [nom d'un attribut] : valeur de l'attribut
798    * - [clef de $this -> other_values] : valeur de $this -> other_values
799    *
800    * @author Benjamin Renard <brenard@easter-eggs.com>
801    *
802    * @param[in] $val string Le nom de la valeur demandée
803    *
804    * @retval mixed la valeur demandé ou ' ' si celle-ci est inconnue.
805    */ 
806   function getValue($val) {
807     if(($val=='dn')||($val=='%{dn}')) {
808       return $this -> dn;
809     }
810     else if(($val=='rdn')||($val=='%{rdn}')) {
811       return $this -> attrs[ $this -> config['rdn'] ] -> getValue();
812     }
813     else if(isset($this ->  attrs[$val])){
814       if (method_exists($this ->  attrs[$val],'getValue'))
815         return $this -> attrs[$val] -> getValue();
816       else
817         return ' ';
818     }
819     else if(isset($this -> other_values[$val])){
820       return $this -> other_values[$val];
821     }
822     else {
823       return ' ';
824     }
825   }
826
827   /**
828    * Retourn un tableau pour un select d'un objet du même type
829    * 
830    * @author Benjamin Renard <brenard@easter-eggs.com>
831    *
832    * @retval array('dn' => 'display')
833    */
834   function getSelectArray($topDn=NULL) {
835     $list = $this -> listObjects(NULL,$topDn);
836     $return=array();
837     foreach($list as $object) {
838       $return[$object -> getDn()] = $object -> getDisplayValue(); 
839     }
840     return $return;
841   }
842
843   /**
844    * Retourne le DN de l'objet
845    *
846    * Cette methode retourne le DN de l'objet. Si celui-ci n'existe pas, il le construit à partir de la 
847    * configuration de l'objet et la valeur de son attribut rdn.
848    *
849    * @author Benjamin Renard <brenard@easter-eggs.com>
850    *
851    * @retval string Le DN de l'objet
852    */   
853   function getDn() {
854     if($this -> dn) {
855       return $this -> dn;
856     }
857     else {
858       $rdn_attr=$this -> config['rdn'];
859       if( (isset($this -> config['rdn'])) && (isset($this -> attrs[$rdn_attr])) && (isset($this -> config['container_dn'])) && (isset($GLOBALS['LSsession']->topDn)) ) {
860         $rdn_val=$this -> attrs[$rdn_attr] -> getUpdateData();
861         if (!empty($rdn_val)) {
862           return $rdn_attr.'='.$rdn_val[0].','.$this -> config['container_dn'].','.$GLOBALS['LSsession']->topDn;
863         }
864         else {
865           $GLOBALS['LSerror'] -> addErrorCode(32,$this -> config['rdn']);
866           return;
867         }
868       }
869       else {
870         $GLOBALS['LSerror'] -> addErrorCode(31,$this -> getType());
871         return;
872       }
873     }
874   }
875
876   /**
877    * Retourne le type de l'objet
878    *
879    * @author Benjamin Renard <brenard@easter-eggs.com>
880    * 
881    * @retval string Le type de l'objet ($this -> type_name)
882    */
883   function getType() {
884     return $this -> type_name;
885   }
886   
887   /**
888    * Retourne qui est l'utilisateur par rapport à cet object
889    *
890    * @author Benjamin Renard <brenard@easter-eggs.com>
891    * 
892    * @retval string 'admin'/'self'/'user' pour Admin , l'utilisateur lui même ou un simple utilisateur
893    */
894   function whoami() {
895     if (!$this -> _whoami)
896       $this -> _whoami = $GLOBALS['LSsession'] -> whoami($this -> dn);
897     return $this -> _whoami;
898   }
899   
900   /**
901    * Retourne le label de l'objet
902    *
903    * @author Benjamin Renard <brenard@easter-eggs.com>
904    * 
905    * @retval string Le label de l'objet ($this -> config['label'])
906    */
907   function getLabel() {
908     return $this -> config['label'];
909   }
910   
911   
912   /**
913    * Supprime l'objet dans l'annuaire
914    *
915    * @author Benjamin Renard <brenard@easter-eggs.com>
916    * 
917    * @retval boolean True si l'objet à été supprimé, false sinon
918    */
919   function remove() {
920     return $GLOBALS['LSldap'] -> remove($this -> getDn());
921   }
922   
923   /**
924    * L'objet est-il nouveau
925    * 
926    * @author Benjamin Renard <brenard@easter-eggs.com>
927    * 
928    * @retval boolean True si l'objet est nouveau, false sinon
929    */
930   function isNew() {
931     return (!$this -> dn);
932   }
933
934   /**
935    * Retourne la valeur (DN) du subDn de l'objet  
936    * 
937    * @return string La valeur du subDn de l'object
938    */
939   function getSubDnValue() {
940     if ($this -> _subDn_value) {
941       return $this -> _subDn_value;
942     }
943     $dn = $this -> getValue('dn');
944     $subDn_value='';
945     $subDnLdapServer = $GLOBALS['LSsession'] -> getSortSubDnLdapServer();
946     foreach ($subDnLdapServer as $subDn => $subDn_name) {
947       if (isCompatibleDNs($subDn,$dn)&&($subDn!=$dn)) {
948         $subDn_value=$subDn;
949         break;
950       }
951     }
952     $this -> _subDn_value = $subDn_value;
953     return $subDn_value;
954   }
955
956   /**
957    * Retourne la nom du subDn de l'objet  
958    * 
959    * @return string Le nom du subDn de l'object
960    */
961   function getSubDnName() {
962     $subDnLdapServer = $GLOBALS['LSsession'] -> getSortSubDnLdapServer();
963     return $subDnLdapServer[$this -> getSubDnValue()];
964   }
965 }
966
967 ?>