Skip to content
This repository was archived by the owner on Jan 30, 2020. It is now read-only.
This repository was archived by the owner on Jan 30, 2020. It is now read-only.

Support LDAP paging control #41

@bishopb

Description

@bishopb

Originally requested at zendframework/zendframework#2780. Now that ZF requires PHP 5.5, we can rely on ldap_control_paged_result to send the paging control option and consume all entries. It's simply a matter of implementing it within the API.

A straightforward way that returns a complete array after pulling all pages follows. This solution improves on a similar one posted on SO, by reusing the base methods as much as possible. However, I feel that:

  • This is hackish. It jumps through hoops to access the result ID and it conflates the idea of "desired maximum number of entries" (sizelimit) with "number of entries to request per page".
  • A final solution should include an Iterator for pages, with an InnerIterator for entries.

Unfortunately, I've not had luck with a design that addresses these concerns. Ideas welcome.

    public function searchAllEntries(
        $filter, $basedn = null, $scope = self::SEARCH_SCOPE_SUB,
        array $attributes = [], $sort = null, $collectionClass = null,
        $sizelimit = 0, $timelimit = 0
    )
    {
        // calculate page size, then remove it from the filter as we need
        // ldap_search to grab as many as it can, per page
        $pagesz = ($filter['sizelimit'] ?: ($sizelimit ?: 500));
        unset($filter['sizelimit']);

        // run the loop, grabbing pages
        $ldap   = $this->getResource();
        $result = [];
        $cookie = '';
        ErrorHandler::start(E_WARNING);
        ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, 3);
        do {
            ldap_control_paged_result($ldap, $pagesz, true, $cookie);

            // run the search and add in the results
            $collection = $this->search(
                $filter, $basedn, $scope, $attributes, $sort, $collectionClass,
                null, // no size limit: we need maximum per page
                $timelimit
            );
            $result = array_merge($result, $collection->toArray());

            // get that pesky search result resource handle, which is a
            // private member of the collection's inner iterator
            $inner = $collection->getInnerIterator();
            $steal = function (DefaultIterator $it) { return $it->resultId; };
            $steal = \Closure::bind($steal, null, $inner);
            $entry = $steal($inner);

            // get the next page cookie
            ldap_control_paged_result_response($ldap, $entry, $cookie);
        } while (! empty($cookie));

        // ensure that subsequent reads don't attempt to use paging
        ldap_control_paged_result($ldap, 0);
        ErrorHandler::stop();

        return $result;
    }

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions