source: trunk/library/Zend/Ldap/Node.php @ 5146

Revision 5146, 29.0 KB checked in by wmerlotto, 12 years ago (diff)

Ticket #2305 - Enviando alteracoes, desenvolvidas internamente na Prognus. Library: adicionando arquivos.

Line 
1<?php
2/**
3 * Zend Framework
4 *
5 * LICENSE
6 *
7 * This source file is subject to the new BSD license that is bundled
8 * with this package in the file LICENSE.txt.
9 * It is also available through the world-wide-web at this URL:
10 * http://framework.zend.com/license/new-bsd
11 * If you did not receive a copy of the license and are unable to
12 * obtain it through the world-wide-web, please send an email
13 * to license@zend.com so we can send you a copy immediately.
14 *
15 * @category   Zend
16 * @package    Zend_Ldap
17 * @subpackage Node
18 * @copyright  Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
19 * @license    http://framework.zend.com/license/new-bsd     New BSD License
20 * @version    $Id: Node.php 22662 2010-07-24 17:37:36Z mabe $
21 */
22
23/**
24 * @see Zend_Ldap
25 */
26require_once 'Zend/Ldap.php';
27/**
28 * @see Zend_Ldap_Node_Abstract
29 */
30require_once 'Zend/Ldap/Node/Abstract.php';
31
32/**
33 * Zend_Ldap_Node provides an object oriented view into a LDAP node.
34 *
35 * @category   Zend
36 * @package    Zend_Ldap
37 * @subpackage Node
38 * @copyright  Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
39 * @license    http://framework.zend.com/license/new-bsd     New BSD License
40 */
41class Zend_Ldap_Node extends Zend_Ldap_Node_Abstract implements Iterator, RecursiveIterator
42{
43    /**
44     * Holds the node's new DN if node is renamed.
45     *
46     * @var Zend_Ldap_Dn
47     */
48    protected $_newDn;
49    /**
50     * Holds the node's orginal attributes (as loaded).
51     *
52     * @var array
53     */
54    protected $_originalData;
55    /**
56     * This node will be added
57     *
58     * @var boolean
59     */
60    protected $_new;
61    /**
62     * This node will be deleted
63     *
64     * @var boolean
65     */
66    protected $_delete;
67    /**
68     * Holds the connection to the LDAP server if in connected mode.
69     *
70     * @var Zend_Ldap
71     */
72    protected $_ldap;
73
74    /**
75     * Holds an array of the current node's children.
76     *
77     * @var array
78     */
79    protected $_children;
80
81    /**
82     * Controls iteration status
83     *
84     * @var boolean
85     */
86    private $_iteratorRewind = false;
87
88    /**
89     * Constructor.
90     *
91     * Constructor is protected to enforce the use of factory methods.
92     *
93     * @param  Zend_Ldap_Dn $dn
94     * @param  array        $data
95     * @param  boolean      $fromDataSource
96     * @param  Zend_Ldap    $ldap
97     * @throws Zend_Ldap_Exception
98     */
99    protected function __construct(Zend_Ldap_Dn $dn, array $data, $fromDataSource, Zend_Ldap $ldap = null)
100    {
101        parent::__construct($dn, $data, $fromDataSource);
102        if ($ldap !== null) $this->attachLdap($ldap);
103        else $this->detachLdap();
104    }
105
106    /**
107     * Serialization callback
108     *
109     * Only DN and attributes will be serialized.
110     *
111     * @return array
112     */
113    public function __sleep()
114    {
115        return array('_dn', '_currentData', '_newDn', '_originalData',
116            '_new', '_delete', '_children');
117    }
118
119    /**
120     * Deserialization callback
121     *
122     * Enforces a detached node.
123     *
124     * @return null
125     */
126    public function __wakeup()
127    {
128        $this->detachLdap();
129    }
130
131    /**
132     * Gets the current LDAP connection.
133     *
134     * @return Zend_Ldap
135     * @throws Zend_Ldap_Exception
136     */
137    public function getLdap()
138    {
139        if ($this->_ldap === null) {
140            /**
141             * @see Zend_Ldap_Exception
142             */
143            require_once 'Zend/Ldap/Exception.php';
144            throw new Zend_Ldap_Exception(null, 'No LDAP connection specified.', Zend_Ldap_Exception::LDAP_OTHER);
145        }
146        else return $this->_ldap;
147    }
148
149    /**
150     * Attach node to an LDAP connection
151     *
152     * This is an offline method.
153     *
154     * @uses   Zend_Ldap_Dn::isChildOf()
155     * @param  Zend_Ldap $ldap
156     * @return Zend_Ldap_Node Provides a fluid interface
157     * @throws Zend_Ldap_Exception
158     */
159    public function attachLdap(Zend_Ldap $ldap)
160    {
161        if (!Zend_Ldap_Dn::isChildOf($this->_getDn(), $ldap->getBaseDn())) {
162            /**
163             * @see Zend_Ldap_Exception
164             */
165            require_once 'Zend/Ldap/Exception.php';
166            throw new Zend_Ldap_Exception(null, 'LDAP connection is not responsible for given node.',
167                Zend_Ldap_Exception::LDAP_OTHER);
168        }
169
170        if ($ldap !== $this->_ldap) {
171            $this->_ldap = $ldap;
172            if (is_array($this->_children)) {
173                foreach ($this->_children as $child) {
174                    $child->attachLdap($ldap);
175                }
176            }
177        }
178        return $this;
179    }
180
181    /**
182     * Detach node from LDAP connection
183     *
184     * This is an offline method.
185     *
186     * @return Zend_Ldap_Node Provides a fluid interface
187     */
188    public function detachLdap()
189    {
190        $this->_ldap = null;
191        if (is_array($this->_children)) {
192            foreach ($this->_children as $child) {
193                $child->detachLdap();
194            }
195        }
196        return $this;
197    }
198
199    /**
200     * Checks if the current node is attached to a LDAP server.
201     *
202     * This is an offline method.
203     *
204     * @return boolean
205     */
206    public function isAttached()
207    {
208        return ($this->_ldap !== null);
209    }
210
211    /**
212     * @param  array   $data
213     * @param  boolean $fromDataSource
214     * @throws Zend_Ldap_Exception
215     */
216    protected function _loadData(array $data, $fromDataSource)
217    {
218        parent::_loadData($data, $fromDataSource);
219        if ($fromDataSource === true) {
220            $this->_originalData = $data;
221        } else {
222            $this->_originalData = array();
223        }
224        $this->_children = null;
225        $this->_markAsNew(($fromDataSource === true) ? false : true);
226        $this->_markAsToBeDeleted(false);
227    }
228
229    /**
230     * Factory method to create a new detached Zend_Ldap_Node for a given DN.
231     *
232     * @param  string|array|Zend_Ldap_Dn $dn
233     * @param  array                     $objectClass
234     * @return Zend_Ldap_Node
235     * @throws Zend_Ldap_Exception
236     */
237    public static function create($dn, array $objectClass = array())
238    {
239        if (is_string($dn) || is_array($dn)) {
240            $dn = Zend_Ldap_Dn::factory($dn);
241        } else if ($dn instanceof Zend_Ldap_Dn) {
242            $dn = clone $dn;
243        } else {
244            /**
245             * @see Zend_Ldap_Exception
246             */
247            require_once 'Zend/Ldap/Exception.php';
248            throw new Zend_Ldap_Exception(null, '$dn is of a wrong data type.');
249        }
250        $new = new self($dn, array(), false, null);
251        $new->_ensureRdnAttributeValues();
252        $new->setAttribute('objectClass', $objectClass);
253        return $new;
254    }
255
256    /**
257     * Factory method to create an attached Zend_Ldap_Node for a given DN.
258     *
259     * @param  string|array|Zend_Ldap_Dn $dn
260     * @param  Zend_Ldap                 $ldap
261     * @return Zend_Ldap_Node|null
262     * @throws Zend_Ldap_Exception
263     */
264    public static function fromLdap($dn, Zend_Ldap $ldap)
265    {
266        if (is_string($dn) || is_array($dn)) {
267            $dn = Zend_Ldap_Dn::factory($dn);
268        } else if ($dn instanceof Zend_Ldap_Dn) {
269            $dn = clone $dn;
270        } else {
271            /**
272             * @see Zend_Ldap_Exception
273             */
274            require_once 'Zend/Ldap/Exception.php';
275            throw new Zend_Ldap_Exception(null, '$dn is of a wrong data type.');
276        }
277        $data = $ldap->getEntry($dn, array('*', '+'), true);
278        if ($data === null) {
279            return null;
280        }
281        $entry = new self($dn, $data, true, $ldap);
282        return $entry;
283    }
284
285    /**
286     * Factory method to create a detached Zend_Ldap_Node from array data.
287     *
288     * @param  array   $data
289     * @param  boolean $fromDataSource
290     * @return Zend_Ldap_Node
291     * @throws Zend_Ldap_Exception
292     */
293    public static function fromArray(array $data, $fromDataSource = false)
294    {
295        if (!array_key_exists('dn', $data)) {
296            /**
297             * @see Zend_Ldap_Exception
298             */
299            require_once 'Zend/Ldap/Exception.php';
300            throw new Zend_Ldap_Exception(null, '\'dn\' key is missing in array.');
301        }
302        if (is_string($data['dn']) || is_array($data['dn'])) {
303            $dn = Zend_Ldap_Dn::factory($data['dn']);
304        } else if ($data['dn'] instanceof Zend_Ldap_Dn) {
305            $dn = clone $data['dn'];
306        } else {
307            /**
308             * @see Zend_Ldap_Exception
309             */
310            require_once 'Zend/Ldap/Exception.php';
311            throw new Zend_Ldap_Exception(null, '\'dn\' key is of a wrong data type.');
312        }
313        $fromDataSource = ($fromDataSource === true) ? true : false;
314        $new = new self($dn, $data, $fromDataSource, null);
315        $new->_ensureRdnAttributeValues();
316        return $new;
317    }
318
319    /**
320     * Ensures that teh RDN attributes are correctly set.
321     *
322     * @return void
323     */
324    protected function _ensureRdnAttributeValues()
325    {
326        foreach ($this->getRdnArray() as $key => $value) {
327            Zend_Ldap_Attribute::setAttribute($this->_currentData, $key, $value, false);
328        }
329    }
330
331    /**
332     * Marks this node as new.
333     *
334     * Node will be added (instead of updated) on calling update() if $new is true.
335     *
336     * @param boolean $new
337     */
338    protected function _markAsNew($new)
339    {
340        $this->_new = ($new === false) ? false : true;
341    }
342
343    /**
344     * Tells if the node is consiedered as new (not present on the server)
345     *
346     * Please note, that this doesn't tell you if the node is present on the server.
347     * Use {@link exits()} to see if a node is already there.
348     *
349     * @return boolean
350     */
351    public function isNew()
352    {
353        return $this->_new;
354    }
355
356    /**
357     * Marks this node as to be deleted.
358     *
359     * Node will be deleted on calling update() if $delete is true.
360     *
361     * @param boolean $delete
362     */
363    protected function _markAsToBeDeleted($delete)
364    {
365        $this->_delete = ($delete === true) ? true : false;
366    }
367
368
369    /**
370    * Is this node going to be deleted once update() is called?
371    *
372    * @return boolean
373    */
374    public function willBeDeleted()
375    {
376        return $this->_delete;
377    }
378
379    /**
380     * Marks this node as to be deleted
381     *
382     * Node will be deleted on calling update() if $delete is true.
383     *
384     * @return Zend_Ldap_Node Provides a fluid interface
385     */
386    public function delete()
387    {
388        $this->_markAsToBeDeleted(true);
389        return $this;
390    }
391
392    /**
393    * Is this node going to be moved once update() is called?
394    *
395    * @return boolean
396    */
397    public function willBeMoved()
398    {
399        if ($this->isNew() || $this->willBeDeleted()) {
400            return false;
401        } else if ($this->_newDn !== null) {
402            return ($this->_dn != $this->_newDn);
403        } else {
404            return false;
405        }
406    }
407
408    /**
409     * Sends all pending changes to the LDAP server
410     *
411     * @param  Zend_Ldap $ldap
412     * @return Zend_Ldap_Node Provides a fluid interface
413     * @throws Zend_Ldap_Exception
414     */
415    public function update(Zend_Ldap $ldap = null)
416    {
417        if ($ldap !== null) {
418            $this->attachLdap($ldap);
419        }
420        $ldap = $this->getLdap();
421        if (!($ldap instanceof Zend_Ldap)) {
422            /**
423             * @see Zend_Ldap_Exception
424             */
425            require_once 'Zend/Ldap/Exception.php';
426            throw new Zend_Ldap_Exception(null, 'No LDAP connection available');
427        }
428
429        if ($this->willBeDeleted()) {
430            if ($ldap->exists($this->_dn)) {
431                $ldap->delete($this->_dn);
432            }
433            return $this;
434        }
435
436        if ($this->isNew()) {
437            $data = $this->getData();
438            $ldap->add($this->_getDn(), $data);
439            $this->_loadData($data, true);
440            return $this;
441        }
442
443        $changedData = $this->getChangedData();
444        if ($this->willBeMoved()) {
445            $recursive = $this->hasChildren();
446            $ldap->rename($this->_dn, $this->_newDn, $recursive, false);
447            foreach ($this->_newDn->getRdn() as $key => $value) {
448                if (array_key_exists($key, $changedData)) {
449                    unset($changedData[$key]);
450                }
451            }
452            $this->_dn = $this->_newDn;
453            $this->_newDn = null;
454        }
455        if (count($changedData) > 0) {
456            $ldap->update($this->_getDn(), $changedData);
457        }
458        $this->_originalData = $this->_currentData;
459        return $this;
460    }
461
462    /**
463     * Gets the DN of the current node as a Zend_Ldap_Dn.
464     *
465     * This is an offline method.
466     *
467     * @return Zend_Ldap_Dn
468     */
469    protected function _getDn()
470    {
471        return ($this->_newDn === null) ? parent::_getDn() : $this->_newDn;
472    }
473
474    /**
475     * Gets the current DN of the current node as a Zend_Ldap_Dn.
476     * The method returns a clone of the node's DN to prohibit modification.
477     *
478     * This is an offline method.
479     *
480     * @return Zend_Ldap_Dn
481     */
482    public function getCurrentDn()
483    {
484        $dn = clone parent::_getDn();
485        return $dn;
486    }
487
488    /**
489     * Sets the new DN for this node
490     *
491     * This is an offline method.
492     *
493     * @param  Zend_Ldap_Dn|string|array $newDn
494     * @throws Zend_Ldap_Exception
495     * @return Zend_Ldap_Node Provides a fluid interface
496     */
497    public function setDn($newDn)
498    {
499        if ($newDn instanceof Zend_Ldap_Dn) {
500            $this->_newDn = clone $newDn;
501        } else {
502            $this->_newDn = Zend_Ldap_Dn::factory($newDn);
503        }
504        $this->_ensureRdnAttributeValues();
505        return $this;
506    }
507
508    /**
509     * {@see setDn()}
510     *
511     * This is an offline method.
512     *
513     * @param  Zend_Ldap_Dn|string|array $newDn
514     * @throws Zend_Ldap_Exception
515     * @return Zend_Ldap_Node Provides a fluid interface
516     */
517    public function move($newDn)
518    {
519        return $this->setDn($newDn);
520    }
521
522    /**
523     * {@see setDn()}
524     *
525     * This is an offline method.
526     *
527     * @param  Zend_Ldap_Dn|string|array $newDn
528     * @throws Zend_Ldap_Exception
529     * @return Zend_Ldap_Node Provides a fluid interface
530     */
531    public function rename($newDn)
532    {
533        return $this->setDn($newDn);
534    }
535
536    /**
537     * Sets the objectClass.
538     *
539     * This is an offline method.
540     *
541     * @param  array|string $value
542     * @return Zend_Ldap_Node Provides a fluid interface
543     * @throws Zend_Ldap_Exception
544     */
545    public function setObjectClass($value)
546    {
547        $this->setAttribute('objectClass', $value);
548        return $this;
549    }
550
551    /**
552     * Appends to the objectClass.
553     *
554     * This is an offline method.
555     *
556     * @param  array|string $value
557     * @return Zend_Ldap_Node Provides a fluid interface
558     * @throws Zend_Ldap_Exception
559     */
560    public function appendObjectClass($value)
561    {
562        $this->appendToAttribute('objectClass', $value);
563        return $this;
564    }
565
566    /**
567     * Returns a LDIF representation of the current node
568     *
569     * @param  array $options Additional options used during encoding
570     * @return string
571     */
572    public function toLdif(array $options = array())
573    {
574        $attributes = array_merge(array('dn' => $this->getDnString()), $this->getData(false));
575        /**
576         * Zend_Ldap_Ldif_Encoder
577         */
578        require_once 'Zend/Ldap/Ldif/Encoder.php';
579        return Zend_Ldap_Ldif_Encoder::encode($attributes, $options);
580    }
581
582    /**
583     * Gets changed node data.
584     *
585     * The array contains all changed attributes.
586     * This format can be used in {@link Zend_Ldap::add()} and {@link Zend_Ldap::update()}.
587     *
588     * This is an offline method.
589     *
590     * @return array
591     */
592    public function getChangedData()
593    {
594        $changed = array();
595        foreach ($this->_currentData as $key => $value) {
596            if (!array_key_exists($key, $this->_originalData) && !empty($value)) {
597                $changed[$key] = $value;
598            } else if ($this->_originalData[$key] !== $this->_currentData[$key]) {
599                $changed[$key] = $value;
600            }
601        }
602        return $changed;
603    }
604
605    /**
606     * Returns all changes made.
607     *
608     * This is an offline method.
609     *
610     * @return array
611     */
612    public function getChanges()
613    {
614        $changes = array(
615            'add'     => array(),
616            'delete'  => array(),
617            'replace' => array());
618        foreach ($this->_currentData as $key => $value) {
619            if (!array_key_exists($key, $this->_originalData) && !empty($value)) {
620                $changes['add'][$key] = $value;
621            } else if (count($this->_originalData[$key]) === 0 && !empty($value)) {
622                $changes['add'][$key] = $value;
623            } else if ($this->_originalData[$key] !== $this->_currentData[$key]) {
624                if (empty($value)) {
625                    $changes['delete'][$key] = $value;
626                } else {
627                    $changes['replace'][$key] = $value;
628                }
629            }
630        }
631        return $changes;
632    }
633
634    /**
635     * Sets a LDAP attribute.
636     *
637     * This is an offline method.
638     *
639     * @param  string $name
640     * @param  mixed  $value
641     * @return Zend_Ldap_Node Provides a fluid interface
642     * @throws Zend_Ldap_Exception
643     */
644    public function setAttribute($name, $value)
645    {
646        $this->_setAttribute($name, $value, false);
647        return $this;
648    }
649
650    /**
651     * Appends to a LDAP attribute.
652     *
653     * This is an offline method.
654     *
655     * @param  string $name
656     * @param  mixed  $value
657     * @return Zend_Ldap_Node Provides a fluid interface
658     * @throws Zend_Ldap_Exception
659     */
660    public function appendToAttribute($name, $value)
661    {
662        $this->_setAttribute($name, $value, true);
663        return $this;
664    }
665
666    /**
667     * Checks if the attribute can be set and sets it accordingly.
668     *
669     * @param  string  $name
670     * @param  mixed   $value
671     * @param  boolean $append
672     * @throws Zend_Ldap_Exception
673     */
674    protected function _setAttribute($name, $value, $append)
675    {
676        $this->_assertChangeableAttribute($name);
677        Zend_Ldap_Attribute::setAttribute($this->_currentData, $name, $value, $append);
678    }
679
680    /**
681     * Sets a LDAP date/time attribute.
682     *
683     * This is an offline method.
684     *
685     * @param  string        $name
686     * @param  integer|array $value
687     * @param  boolean       $utc
688     * @return Zend_Ldap_Node Provides a fluid interface
689     * @throws Zend_Ldap_Exception
690     */
691    public function setDateTimeAttribute($name, $value, $utc = false)
692    {
693        $this->_setDateTimeAttribute($name, $value, $utc, false);
694        return $this;
695    }
696
697    /**
698     * Appends to a LDAP date/time attribute.
699     *
700     * This is an offline method.
701     *
702     * @param  string        $name
703     * @param  integer|array $value
704     * @param  boolean       $utc
705     * @return Zend_Ldap_Node Provides a fluid interface
706     * @throws Zend_Ldap_Exception
707     */
708    public function appendToDateTimeAttribute($name, $value, $utc = false)
709    {
710        $this->_setDateTimeAttribute($name, $value, $utc, true);
711        return $this;
712    }
713
714    /**
715     * Checks if the attribute can be set and sets it accordingly.
716     *
717     * @param  string        $name
718     * @param  integer|array $value
719     * @param  boolean       $utc
720     * @param  boolean       $append
721     * @throws Zend_Ldap_Exception
722     */
723    protected function _setDateTimeAttribute($name, $value, $utc, $append)
724    {
725        $this->_assertChangeableAttribute($name);
726        Zend_Ldap_Attribute::setDateTimeAttribute($this->_currentData, $name, $value, $utc, $append);
727    }
728
729    /**
730     * Sets a LDAP password.
731     *
732     * @param  string $password
733     * @param  string $hashType
734     * @param  string $attribName
735     * @return Zend_Ldap_Node Provides a fluid interface
736     * @throws Zend_Ldap_Exception
737     */
738    public function setPasswordAttribute($password, $hashType = Zend_Ldap_Attribute::PASSWORD_HASH_MD5,
739        $attribName = 'userPassword')
740    {
741        $this->_assertChangeableAttribute($attribName);
742        Zend_Ldap_Attribute::setPassword($this->_currentData, $password, $hashType, $attribName);
743        return $this;
744    }
745
746    /**
747     * Deletes a LDAP attribute.
748     *
749     * This method deletes the attribute.
750     *
751     * This is an offline method.
752     *
753     * @param  string $name
754     * @return Zend_Ldap_Node Provides a fluid interface
755     * @throws Zend_Ldap_Exception
756     */
757    public function deleteAttribute($name)
758    {
759        if ($this->existsAttribute($name, true)) {
760            $this->_setAttribute($name, null, false);
761        }
762        return $this;
763    }
764
765    /**
766     * Removes duplicate values from a LDAP attribute
767     *
768     * @param  string $attribName
769     * @return void
770     */
771    public function removeDuplicatesFromAttribute($attribName)
772    {
773        Zend_Ldap_Attribute::removeDuplicatesFromAttribute($this->_currentData, $attribName);
774    }
775
776    /**
777     * Remove given values from a LDAP attribute
778     *
779     * @param  string      $attribName
780     * @param  mixed|array $value
781     * @return void
782     */
783    public function removeFromAttribute($attribName, $value)
784    {
785        Zend_Ldap_Attribute::removeFromAttribute($this->_currentData, $attribName, $value);
786    }
787
788    /**
789     * @param  string $name
790     * @return boolean
791     * @throws Zend_Ldap_Exception
792     */
793    protected function _assertChangeableAttribute($name)
794    {
795        $name = strtolower($name);
796        $rdn = $this->getRdnArray(Zend_Ldap_Dn::ATTR_CASEFOLD_LOWER);
797        if ($name == 'dn') {
798            /**
799             * @see Zend_Ldap_Exception
800             */
801            require_once 'Zend/Ldap/Exception.php';
802            throw new Zend_Ldap_Exception(null, 'DN cannot be changed.');
803        }
804        else if (array_key_exists($name, $rdn)) {
805            /**
806             * @see Zend_Ldap_Exception
807             */
808            require_once 'Zend/Ldap/Exception.php';
809            throw new Zend_Ldap_Exception(null, 'Cannot change attribute because it\'s part of the RDN');
810        } else if (in_array($name, self::$_systemAttributes)) {
811            /**
812             * @see Zend_Ldap_Exception
813             */
814            require_once 'Zend/Ldap/Exception.php';
815            throw new Zend_Ldap_Exception(null, 'Cannot change attribute because it\'s read-only');
816        }
817        else return true;
818    }
819
820    /**
821     * Sets a LDAP attribute.
822     *
823     * This is an offline method.
824     *
825     * @param  string $name
826     * @param  mixed  $value
827     * @return null
828     * @throws Zend_Ldap_Exception
829     */
830    public function __set($name, $value)
831    {
832        $this->setAttribute($name, $value);
833    }
834
835    /**
836     * Deletes a LDAP attribute.
837     *
838     * This method deletes the attribute.
839     *
840     * This is an offline method.
841     *
842     * @param  string $name
843     * @return null
844     * @throws Zend_Ldap_Exception
845     */
846    public function __unset($name)
847    {
848        $this->deleteAttribute($name);
849    }
850
851    /**
852     * Sets a LDAP attribute.
853     * Implements ArrayAccess.
854     *
855     * This is an offline method.
856     *
857     * @param  string $name
858     * @param  mixed  $value
859     * @return null
860     * @throws Zend_Ldap_Exception
861     */
862    public function offsetSet($name, $value)
863    {
864        $this->setAttribute($name, $value);
865    }
866
867    /**
868     * Deletes a LDAP attribute.
869     * Implements ArrayAccess.
870     *
871     * This method deletes the attribute.
872     *
873     * This is an offline method.
874     *
875     * @param  string $name
876     * @return null
877     * @throws Zend_Ldap_Exception
878     */
879    public function offsetUnset($name)
880    {
881        $this->deleteAttribute($name);
882    }
883
884    /**
885     * Check if node exists on LDAP.
886     *
887     * This is an online method.
888     *
889     * @param  Zend_Ldap $ldap
890     * @return boolean
891     * @throws Zend_Ldap_Exception
892     */
893    public function exists(Zend_Ldap $ldap = null)
894    {
895        if ($ldap !== null) {
896            $this->attachLdap($ldap);
897        }
898        $ldap = $this->getLdap();
899        return $ldap->exists($this->_getDn());
900    }
901
902    /**
903     * Reload node attributes from LDAP.
904     *
905     * This is an online method.
906     *
907     * @param  Zend_Ldap $ldap
908     * @return Zend_Ldap_Node Provides a fluid interface
909     * @throws Zend_Ldap_Exception
910     */
911    public function reload(Zend_Ldap $ldap = null)
912    {
913        if ($ldap !== null) {
914            $this->attachLdap($ldap);
915        }
916        $ldap = $this->getLdap();
917        parent::reload($ldap);
918        return $this;
919    }
920
921    /**
922     * Search current subtree with given options.
923     *
924     * This is an online method.
925     *
926     * @param  string|Zend_Ldap_Filter_Abstract $filter
927     * @param  integer                          $scope
928     * @param  string                           $sort
929     * @return Zend_Ldap_Node_Collection
930     * @throws Zend_Ldap_Exception
931     */
932    public function searchSubtree($filter, $scope = Zend_Ldap::SEARCH_SCOPE_SUB, $sort = null)
933    {
934        /**
935         * @see Zend_Ldap_Node_Collection
936         */
937        require_once 'Zend/Ldap/Node/Collection.php';
938        return $this->getLdap()->search($filter, $this->_getDn(), $scope, array('*', '+'), $sort,
939            'Zend_Ldap_Node_Collection');
940    }
941
942    /**
943     * Count items in current subtree found by given filter.
944     *
945     * This is an online method.
946     *
947     * @param  string|Zend_Ldap_Filter_Abstract $filter
948     * @param  integer                          $scope
949     * @return integer
950     * @throws Zend_Ldap_Exception
951     */
952    public function countSubtree($filter, $scope = Zend_Ldap::SEARCH_SCOPE_SUB)
953    {
954        return $this->getLdap()->count($filter, $this->_getDn(), $scope);
955    }
956
957    /**
958     * Count children of current node.
959     *
960     * This is an online method.
961     *
962     * @return integer
963     * @throws Zend_Ldap_Exception
964     */
965    public function countChildren()
966    {
967        return $this->countSubtree('(objectClass=*)', Zend_Ldap::SEARCH_SCOPE_ONE);
968    }
969
970    /**
971     * Gets children of current node.
972     *
973     * This is an online method.
974     *
975     * @param  string|Zend_Ldap_Filter_Abstract $filter
976     * @param  string                           $sort
977     * @return Zend_Ldap_Node_Collection
978     * @throws Zend_Ldap_Exception
979     */
980    public function searchChildren($filter, $sort = null)
981    {
982        return $this->searchSubtree($filter, Zend_Ldap::SEARCH_SCOPE_ONE, $sort);
983    }
984
985    /**
986     * Checks if current node has children.
987     * Returns whether the current element has children.
988     *
989     * Can be used offline but returns false if children have not been retrieved yet.
990     *
991     * @return boolean
992     * @throws Zend_Ldap_Exception
993     */
994    public function hasChildren()
995    {
996        if (!is_array($this->_children)) {
997            if ($this->isAttached()) {
998                return ($this->countChildren() > 0);
999            } else {
1000                return false;
1001            }
1002        } else {
1003            return (count($this->_children) > 0);
1004        }
1005    }
1006
1007    /**
1008     * Returns the children for the current node.
1009     *
1010     * Can be used offline but returns an empty array if children have not been retrieved yet.
1011     *
1012     * @return Zend_Ldap_Node_ChildrenIterator
1013     * @throws Zend_Ldap_Exception
1014     */
1015    public function getChildren()
1016    {
1017        if (!is_array($this->_children)) {
1018            $this->_children = array();
1019            if ($this->isAttached()) {
1020                $children = $this->searchChildren('(objectClass=*)', null);
1021                foreach ($children as $child) {
1022                    $this->_children[$child->getRdnString(Zend_Ldap_Dn::ATTR_CASEFOLD_LOWER)] = $child;
1023                }
1024            }
1025        }
1026        /**
1027         * @see Zend_Ldap_Node_ChildrenIterator
1028         */
1029        require_once 'Zend/Ldap/Node/ChildrenIterator.php';
1030        return new Zend_Ldap_Node_ChildrenIterator($this->_children);
1031    }
1032
1033    /**
1034     * Returns the parent of the current node.
1035     *
1036     * @param  Zend_Ldap $ldap
1037     * @return Zend_Ldap_Node
1038     * @throws Zend_Ldap_Exception
1039     */
1040    public function getParent(Zend_Ldap $ldap = null)
1041    {
1042        if ($ldap !== null) {
1043            $this->attachLdap($ldap);
1044        }
1045        $ldap = $this->getLdap();
1046        $parentDn = $this->_getDn()->getParentDn(1);
1047        return self::fromLdap($parentDn, $ldap);
1048    }
1049
1050    /**
1051     * Return the current attribute.
1052     * Implements Iterator
1053     *
1054     * @return array
1055     */
1056    public function current()
1057    {
1058        return $this;
1059    }
1060
1061    /**
1062     * Return the attribute name.
1063     * Implements Iterator
1064     *
1065     * @return string
1066     */
1067    public function key()
1068    {
1069        return $this->getRdnString();
1070    }
1071
1072    /**
1073     * Move forward to next attribute.
1074     * Implements Iterator
1075     */
1076    public function next()
1077    {
1078        $this->_iteratorRewind = false;
1079    }
1080
1081    /**
1082     * Rewind the Iterator to the first attribute.
1083     * Implements Iterator
1084     */
1085    public function rewind()
1086    {
1087        $this->_iteratorRewind = true;
1088    }
1089
1090    /**
1091     * Check if there is a current attribute
1092     * after calls to rewind() or next().
1093     * Implements Iterator
1094     *
1095     * @return boolean
1096     */
1097    public function valid()
1098    {
1099        return $this->_iteratorRewind;
1100    }
1101}
Note: See TracBrowser for help on using the repository browser.