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