Net_LDAP
[ class tree: Net_LDAP ] [ index: Net_LDAP ] [ all elements ]

Source for file Search.php

Documentation is available at Search.php

  1. <?php
  2. /* vim: set expandtab tabstop=4 shiftwidth=4: */
  3. // +--------------------------------------------------------------------------+
  4. // | Net_LDAP                                                                 |
  5. // +--------------------------------------------------------------------------+
  6. // | Copyright (c) 1997-2003 The PHP Group                                    |
  7. // +--------------------------------------------------------------------------+
  8. // | This library is free software; you can redistribute it and/or            |
  9. // | modify it under the terms of the GNU Lesser General Public               |
  10. // | License as published by the Free Software Foundation; either             |
  11. // | version 2.1 of the License, or (at your option) any later version.       |
  12. // |                                                                          |
  13. // | This library is distributed in the hope that it will be useful,          |
  14. // | but WITHOUT ANY WARRANTY; without even the implied warranty of           |
  15. // | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU        |
  16. // | Lesser General Public License for more details.                          |
  17. // |                                                                          |
  18. // | You should have received a copy of the GNU Lesser General Public         |
  19. // | License along with this library; if not, write to the Free Software      |
  20. // | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA |
  21. // +--------------------------------------------------------------------------+
  22. // | Authors: Tarjej Huse, Benedikt Hallinger                                 |
  23. // +--------------------------------------------------------------------------+
  24. //
  25. // $Id: Search.php,v 1.21 2007/06/13 11:49:21 beni Exp $
  26.  
  27. /**
  28.  * Result set of an LDAP search
  29.  *
  30.  * @author  Tarjei Huse
  31.  * @author  Benedikt Hallinger <beni@php.net>
  32.  * @version $Revision: 1.21 $
  33.  * @package Net_LDAP
  34.  */
  35. class Net_LDAP_Search extends PEAR
  36. {
  37.     /**
  38.      * Search result identifier
  39.      *
  40.      * @access private
  41.      * @var resource 
  42.      */
  43.     var $_search;
  44.  
  45.     /**
  46.      * LDAP resource link
  47.      *
  48.      * @access private
  49.      * @var resource 
  50.      */
  51.     var $_link;
  52.  
  53.     /**
  54.      * Net_LDAP object
  55.      *
  56.      * A reference of the Net_LDAP object for passing to Net_LDAP_Entry
  57.      *
  58.      * @access private
  59.      * @var object Net_LDAP 
  60.      */
  61.     var $_ldap;
  62.  
  63.     /**
  64.      * Result entry identifier
  65.      *
  66.      * @access private
  67.      * @var resource 
  68.      */
  69.     var $_entry = null;
  70.  
  71.     /**
  72.      * The errorcode the search got
  73.      *
  74.      * Some errorcodes might be of interest, but might not be best handled as errors.
  75.      * examples: 4 - LDAP_SIZELIMIT_EXCEEDED - indicates a huge search.
  76.      *               Incomplete results are returned. If you just want to check if there's anything in the search.
  77.      *               than this is a point to handle.
  78.      *           32 - no such object - search here returns a count of 0.
  79.      *
  80.      * @access private
  81.      * @var int 
  82.      */
  83.     var $_errorCode = 0; // if not set - sucess!
  84.  
  85.     /**
  86.     * What attributes we searched for
  87.     *
  88.     * The $attributes array contains the names of the searched attributes and gets
  89.     * passed from $Net_LDAP->search() so the Net_LDAP_Search object can tell
  90.     * what attributes was searched for ({@link _searchedAttrs())}
  91.     *
  92.     * This variable gets set from the constructor and returned
  93.     * from {@link _searchedAttrs()}
  94.     *
  95.     * @access private
  96.     * @var array 
  97.     */
  98.     var $_searchedAttrs = array();
  99.  
  100.     /**
  101.     * Cache variable for storing entries fetched internally
  102.     *
  103.     * This currently is only used by {@link pop_entry()}
  104.     *
  105.     * @access private
  106.     * @var array 
  107.     */
  108.     var $_entry_cache = false;
  109.  
  110.    /**
  111.     * Constructor
  112.     *
  113.     * @access protected
  114.     * @param resource $search         Search result identifier
  115.     * @param Net_LDAP|resource$ldap  Net_LDAP object or just a LDAP-Link resource
  116.     * @param array $attributes        (optional) Array with searched attribute names. (see {@link $_searchedAttrs})
  117.     */
  118.     function Net_LDAP_Search(&$search&$ldap$attributes = array())
  119.     {
  120.         $this->PEAR('Net_LDAP_Error');
  121.  
  122.         $this->setSearch($search);
  123.  
  124.         if (is_a($ldap'Net_LDAP')) {
  125.             $this->_ldap =$ldap;
  126.             $this->setLink($this->_ldap->getLink());
  127.         else {
  128.             $this->setLink($ldap);
  129.         }
  130.  
  131.         $this->_errorCode @ldap_errno($this->_link);
  132.  
  133.         if (is_array($attributes&& !empty($attributes)) {
  134.             $this->_searchedAttrs $attributes;
  135.         }
  136.     }
  137.  
  138.     /**
  139.      * Returns an assosiative array of entry objects
  140.      *
  141.      * @return array Array of entry objects.
  142.      */
  143.     function entries()
  144.     {
  145.         $entries = array();
  146.  
  147.         while ($entry $this->shiftEntry()) {
  148.             $entries[$entry;
  149.         }
  150.  
  151.         return $entries;
  152.     }
  153.  
  154.     /**
  155.      * Get the next entry in the searchresult.
  156.      *
  157.      * This will return a valid Net_LDAP_Entry object or false, so
  158.      * you can use this method to easily iterate over the entries inside
  159.      * a while loop.
  160.      *
  161.      * @return Net_LDAP_Entry|false Reference to Net_LDAP_Entry object or false
  162.      */
  163.     function &shiftEntry()
  164.     {
  165.         if ($this->count(== 0 {
  166.             $false = false;
  167.             return $false;
  168.         }
  169.  
  170.         if (is_null($this->_entry)) {
  171.             $this->_entry @ldap_first_entry($this->_link$this->_search);
  172.             $entry = new Net_LDAP_Entry($this->_ldap$this->_entry);
  173.         else {
  174.             if (!$this->_entry @ldap_next_entry($this->_link$this->_entry)) {
  175.                 $false = false;
  176.                 return $false;
  177.             }
  178.             $entry = new Net_LDAP_Entry($this->_ldap$this->_entry);
  179.         }
  180.         return $entry;
  181.     }
  182.  
  183.     /**
  184.      * Alias function of shiftEntry() for perl-ldap interface
  185.      *
  186.      * @see shiftEntry()
  187.      */
  188.     function shift_entry()
  189.     {
  190.         $args func_get_args();
  191.         return call_user_func_array(array&$this'shiftEntry' )$args);
  192.     }
  193.  
  194.     /**
  195.      * Retrieve the next entry in the searchresult, but starting from last entry
  196.      *
  197.      * This is the opposite to {@link shiftEntry()} and is also very useful
  198.      * to be used inside a while loop.
  199.      *
  200.      * @return Net_LDAP_Entry|false
  201.      */
  202.     function popEntry()
  203.     {
  204.         if (false === $this->_entry_cache{
  205.             // fetch entries into cache if not done so far
  206.             $this->_entry_cache $this->entries();
  207.         }
  208.  
  209.         $return array_pop($this->_entry_cache);
  210.         return (null === $return)? false : $return;
  211.     }
  212.  
  213.     /**
  214.      * Alias function of popEntry() for perl-ldap interface
  215.      *
  216.      * @see popEntry()
  217.      */
  218.     function pop_entry()
  219.     {
  220.         $args func_get_args();
  221.         return call_user_func_array(array&$this'popEntry' )$args);
  222.     }
  223.  
  224.     /**
  225.     * Return entries sorted as array
  226.     *
  227.     * This returns a array with sorted entries and the values.
  228.     * Sorting is done with PHPs {@link array_multisort()}.
  229.     * This method relies on {@link as_struct()} to fetch the raw data of the entries.
  230.     *
  231.     * Please note that attribute names are case sensitive!
  232.     *
  233.     * Usage example:
  234.     * <code>
  235.     *   // to sort entries first by location, then by surename, but descending:
  236.     *   $entries = $search->sorted_as_struct(array('locality','sn'), SORT_DESC);
  237.     * </code>
  238.     *
  239.     * @param array      $attrs Array of attribute names to sort; order from left to right.
  240.     * @param int        $order Ordering direction, either constant SORT_ASC or SORT_DESC
  241.     * @return array|Net_LDAP_Error  Array with sorted entries or error
  242.     */
  243.     function sorted_as_struct($attrs = array('cn')$order = SORT_ASC)
  244.     {
  245.         /*
  246.         * Old Code, suitable and fast for single valued sorting
  247.         * This code should be used if we know that single valued sorting is desired,
  248.         * but we need some method to get that knowledge...
  249.         */
  250.         /*
  251.         $attrs = array_reverse($attrs);
  252.         foreach ($attrs as $attribute) {
  253.             if (!ldap_sort($this->_link, $this->_search, $attribute)){
  254.                 $this->raiseError("Sorting failed for Attribute " . $attribute);
  255.             }
  256.         }
  257.  
  258.         $results = ldap_get_entries($this->_link, $this->_search);
  259.  
  260.         unset($results['count']); //for tidier output
  261.         if ($order) {
  262.             return array_reverse($results);
  263.         } else {
  264.             return $results;
  265.         }*/
  266.  
  267.         /*
  268.         * New code: complete "client side" sorting
  269.         */
  270.         // first some parameterchecks
  271.         if (!is_array($attrs)) {
  272.             return PEAR::raiseError("Sorting failed: Parameterlist must be an array!");
  273.         }
  274.         if ($order != SORT_ASC && $order != SORT_DESC{
  275.             return PEAR::raiseError("Sorting failed: sorting direction not understood! (neither constant SORT_ASC nor SORT_DESC)");
  276.         }
  277.  
  278.         // fetch the entries data
  279.         $entries $this->as_struct();
  280.  
  281.         // now sort each entries attribute values
  282.         // this is neccessary because later we can only sort by one value,
  283.         // so we need the highest or lowest attribute now, depending on the
  284.         // selected ordering for that specific attribute
  285.         foreach ($entries as $dn => $entry{
  286.             foreach ($entry as $attr_name => $attr_values{
  287.                 sort($entries[$dn][$attr_name]);
  288.                 if($order == SORT_DESC{
  289.                     array_reverse($entries[$dn][$attr_name]);
  290.                 }
  291.             }
  292.         }
  293.  
  294.         // reformat entrys array for later use with array_multisort()
  295.         $to_sort = array()// <- will be a numeric array similar to ldap_get_entries
  296.         foreach ($entries as $dn => $entry_attr{
  297.             $row = array();
  298.             $row['dn'$dn;
  299.             foreach ($entry_attr as $attr_name => $attr_values{
  300.                 $row[$attr_name$attr_values;
  301.             }
  302.             $to_sort[$row;
  303.         }
  304.  
  305.         // Build columns for array_multisort()
  306.         // each requested attribute is one row
  307.         $columns = array();
  308.         foreach ($attrs as $attr_name{
  309.             foreach ($to_sort as $key => $row{
  310.                 $columns[$attr_name][$key=$to_sort[$key][$attr_name][0];
  311.             }
  312.         }
  313.  
  314.         // sort the colums with array_multisort
  315.         $sort_params '';
  316.         foreach ($attrs as $attr_name{
  317.             $sort_params .= '$columns[\''.$attr_name.'\'], '.$order.', ';
  318.         }
  319.         eval("array_multisort($sort_params \$to_sort);")// perform sorting
  320.  
  321.         return $to_sort;
  322.     }
  323.  
  324.     /**
  325.     * Return entries sorted as objects
  326.     *
  327.     * This returns a array with sorted Net_LDAP_Entry objects.
  328.     * The sorting is actually done with {@link sorted_as_struct()}.
  329.     *
  330.     * Please note that attribute names are case sensitive!
  331.     *
  332.     * Usage example:
  333.     * <code>
  334.     *   // to sort entries first by location, then by surename, but descending:
  335.     *   $entries = $search->sorted(array('locality','sn'), SORT_DESC);
  336.     * </code>
  337.     *
  338.     * @param array      $attrs Array of sort attributes to sort; order from left to right.
  339.     * @param int        $order Ordering direction, either constant SORT_ASC or SORT_DESC
  340.     * @return array|Net_LDAP_Error  Array with sorted Net_LDAP_Entries or error
  341.     */
  342.     function sorted($attrs = array('cn')$order = SORT_ASC{
  343.         $return = array();
  344.         $sorted $this->sorted_as_struct($attrs$order);
  345.         if (PEAR::isError($sorted)) {
  346.             return $sorted;
  347.         }
  348.         foreach ($sorted as $key => $row{
  349.             $entry $this->_ldap->getEntry($row['dn']$this->_searchedAttrs());
  350.             if (!PEAR::isError($entry)) {
  351.                 array_push($return$entry);
  352.             else {
  353.                 return $entry;
  354.             }
  355.         }
  356.         return $return;
  357.     }
  358.  
  359.    /**
  360.     * Return entries as array
  361.     *
  362.     * This method returns the entries and the selected attributes values as
  363.     * array.
  364.     * The first array level contains all found entries where the keys are the
  365.     * DNs of the entries. The second level arrays contian the entries attributes
  366.     * such that the keys is the lowercased name of the attribute and the values
  367.     * are stored in another indexed array. Note that the attribute values are stored
  368.     * in an array even if there is no or just one value.
  369.     *
  370.     * The array has the following structure:
  371.     * <code>
  372.     * $return = array(
  373.     *           'cn=foo,dc=example,dc=com' => array(
  374.     *                                                'sn'       => array('foo'),
  375.     *                                                'multival' => array('val1', 'val2', 'valN')
  376.     *                                             )
  377.     *           'cn=bar,dc=example,dc=com' => array(
  378.     *                                                'sn'       => array('bar'),
  379.     *                                                'multival' => array('val1', 'valN')
  380.     *                                             )
  381.     *           )
  382.     * </code>
  383.     *
  384.     * @return array      associative result array as described above
  385.     */
  386.     function as_struct()
  387.     {
  388.         $return = array();
  389.         $entries $this->entries();
  390.         foreach ($entries as $entry{
  391.             $attrs = array();
  392.             $entry_attributes $entry->attributes();
  393.             foreach ($entry_attributes as $attr_name{
  394.                 $attr_values $entry->getValue($attr_name'all');
  395.                 if (!is_array($attr_values)) {
  396.                     $attr_values = array($attr_values);
  397.                 }
  398.                 $attrs[$attr_name$attr_values;
  399.             }
  400.             $return[$entry->dn()$attrs;
  401.         }
  402.         return $return;
  403.     }
  404.  
  405.    /**
  406.     * Set the search objects resource link
  407.     *
  408.     * @access public
  409.     * @param resource $search Search result identifier
  410.     * @return void 
  411.     */
  412.     function setSearch(&$search)
  413.     {
  414.         $this->_search $search;
  415.     }
  416.  
  417.    /**
  418.     * Set the ldap ressource link
  419.     *
  420.     * @access public
  421.     * @param resource $link Link identifier
  422.     * @return void 
  423.     */
  424.     function setLink(&$link)
  425.     {
  426.         $this->_link $link;
  427.     }
  428.  
  429.    /**
  430.     * Returns the number of entries in the searchresult
  431.     *
  432.     * @return int Number of entries in search.
  433.     */
  434.     function count()
  435.     {
  436.         /* this catches the situation where OL returned errno 32 = no such object! */
  437.         if (!$this->_search{
  438.             return 0;
  439.         }
  440.         return @ldap_count_entries($this->_link$this->_search);
  441.     }
  442.  
  443.     /**
  444.      * Get the errorcode the object got in its search.
  445.      *
  446.      * @return int The ldap error number.
  447.      */
  448.     function getErrorCode()
  449.     {
  450.         return $this->_errorCode;
  451.     }
  452.  
  453.    /**
  454.     * Destructor
  455.     *
  456.     * @access protected
  457.     */
  458.     function _Net_LDAP_Search()
  459.     {
  460.         @ldap_free_result($this->_search);
  461.     }
  462.  
  463.    /**
  464.     * Closes search result
  465.     */
  466.     function done()
  467.     {
  468.         $this->_Net_LDAP_Search();
  469.     }
  470.  
  471.     /**
  472.     * Return the attribute names this search selected
  473.     *
  474.     * @return array 
  475.     * @see $_searchedAttrs
  476.     * @access private
  477.     */
  478.     function _searchedAttrs()
  479.     {
  480.         return $this->_searchedAttrs;
  481.     }
  482. }
  483.  
  484. ?>

Documentation generated on Mon, 11 Mar 2019 15:09:20 -0400 by phpDocumentor 1.4.4. PEAR Logo Copyright © PHP Group 2004.