/**
  * @covers \CarnegieLearning\LdapOrmBundle\Ldap\Filter\LdapFilter::format
  */
 public function testFormat()
 {
     // Simple Test
     $filter = new LdapFilter(array('color' => 'green*'));
     $filterString = $filter->format();
     $this->assertEquals('(color=green*)', $filterString);
     // Complex Test
     $attributeName = 'color';
     $attributeValue1 = 'green';
     $attributeValue2 = 'red';
     $attributeValue3 = 'blue';
     $array = array($attributeName => array($attributeValue1, '*' . $attributeValue2 . '*', '* ' . $attributeValue3));
     $filter = new LdapFilter($array);
     $filterString = $filter->format();
     $this->assertEquals('(|(color=green)(color=*red*)(color=* blue))', $filterString);
     // Super Complex Test
     $array = array('&' => array('key3' => 'val3', 'key4' => 'val4', '|' => array('key1' => 'val1', 'key2' => array('val2a', 'val2b'), array('&' => array('key5' => 'val5', 'key6' => 'val6')), array('&' => array('key7' => 'val7', 'key8' => 'val8')), array('&' => array('key9' => 'val9', 'key10' => 'val10')))));
     $filter = new LdapFilter($array);
     $filterString = $filter->format();
     $expected = '(&(key3=val3)(key4=val4)(|(key1=val1)(|(key2=val2a)(key2=val2b))(&(key5=val5)(key6=val6))(&(key7=val7)(key8=val8))(&(key9=val9)(key10=val10))))';
     $this->assertEquals($expected, $filterString);
 }
 /**
  * The core of ORM behavior for this bundle: retrieve data
  * from LDAP and convert results into objects.
  *
  * Options maybe:
  *
  *      attributes (array): array of attribute types (strings)
  *
  *      filter (LdapFilter): a filter array or a correctly formatted filter string
  *
  *      max (integer): the maximum limit of entries to return
  *
  *      searchDn (string): the search DN
  *
  *      subentryNodes (array): parameters for the left hand side of a searchDN, useful for mining subentries.
  *
  *      pageSize (integer): employ pagination and return pages of the given size
  *
  *      pageCookie (opaque): The opaque stucture sent by the LDAP server to maintain pagination state. Default is empty string.
  *
  *      pageCritical (boolean): if pagination employed, force paging and return no results on service which do not provide it. Default is true.
  *
  *      checkOnly (boolean): Only check result existence; don't convert search results to Symfony entities. Default is false.
  *
  * @param string $entityName
  * @param array $options
  * @return array
  * @throws MissingSearchDnException
  */
 public function retrieve($entityName, $options = array())
 {
     $paging = !empty($options['pageSize']);
     $instanceMetadataCollection = $this->getClassMetadata($entityName);
     // Discern max result size
     $max = empty($options['max']) ? self::DEFAULT_MAX_RESULT_COUNT : $options['max'];
     // Employ results paging if requested with pageSize option
     if ($paging) {
         if (!isset($options['pageCritical'])) {
             $options['pageCritical'] = FALSE;
         }
         if (isset($options['pageCookie'])) {
             $this->pageCookie = $options['pageCookie'];
         }
         ldap_control_paged_result($this->client->getLdapResource(), $options['pageSize'], $options['pageCritical'], $this->pageCookie);
     }
     // Discern subentryNodes for substituing into searchDN
     $subentryNodes = empty($options['subentryNodes']) ? array() : $options['subentryNodes'];
     // Discern search DN
     if (isset($options['searchDn'])) {
         $searchDn = $options['searchDn'];
     } else {
         $searchDn = $instanceMetadataCollection->getSearchDn();
     }
     if (empty($searchDn)) {
         throw new MissingSearchDnException('Could not discern search DN while searching for ' . $entityName);
     }
     // Discern LDAP filter
     $objectClass = $instanceMetadataCollection->getObjectClass();
     if (empty($options['filter'])) {
         $filter = '(objectClass=' . $objectClass . ')';
     } else {
         if (is_array($options['filter'])) {
             $options['filter'] = array('&' => array('objectClass' => $objectClass, $options['filter']));
             $ldapFilter = new LdapFilter($options['filter']);
             $filter = $ldapFilter->format();
         } else {
             if (is_a($options['filter'], LdapFilter::class)) {
                 $options['filter']->setFilterArray(array('&' => array('objectClass' => $objectClass, $options['filter']->getFilterArray())));
                 $filter = $options['filter']->format();
             } else {
                 // assume pre-formatted scale/string filter value
                 $filter = '(&(objectClass=' . $objectClass . ')' . $options['filter'] . ')';
             }
         }
     }
     // Discern attributes to retrieve
     if (empty($options['attributes'])) {
         $attributes = array_values($instanceMetadataCollection->getMetadatas());
     } else {
         $attributes = $options['attributes'];
     }
     // Search LDAP
     $searchResult = $this->doRawLdapSearch($filter, $attributes, $max, $searchDn);
     $entries = @ldap_get_entries($this->client->getLdapResource(), $searchResult);
     if (!empty($options['checkOnly']) && $options['checkOnly'] == true) {
         return $entries['count'] > 0;
     }
     $entities = array();
     foreach ($entries as $entry) {
         if (is_array($entry)) {
             $entities[] = $this->entryToEntity($entityName, $entry);
         }
     }
     if ($paging) {
         ldap_control_paged_result_response($this->client->getLdapResource(), $searchResult, $this->pageCookie);
         $this->pageMore = !empty($this->pageCookie);
     }
     if ($entries['count'] == 1) {
         return $entities[0];
     }
     return $entities;
 }