/libraries/Zend/Ldap/Collection/DefaultIterator.php

https://github.com/kiranatama/sagalaya · PHP · 307 lines · 164 code · 25 blank · 118 comment · 25 complexity · 5ac76a96c3accb12595106bcd6d41d81 MD5 · raw file

  1. <?php
  2. /**
  3. * Zend Framework (http://framework.zend.com/)
  4. *
  5. * @link http://github.com/zendframework/zf2 for the canonical source repository
  6. * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
  7. * @license http://framework.zend.com/license/new-bsd New BSD License
  8. * @package Zend_Ldap
  9. */
  10. namespace Zend\Ldap\Collection;
  11. use Zend\Ldap;
  12. use Zend\Ldap\Exception;
  13. /**
  14. * Zend\Ldap\Collection\DefaultIterator is the default collection iterator implementation
  15. * using ext/ldap
  16. *
  17. * @category Zend
  18. * @package Zend_Ldap
  19. */
  20. class DefaultIterator implements \Iterator, \Countable
  21. {
  22. const ATTRIBUTE_TO_LOWER = 1;
  23. const ATTRIBUTE_TO_UPPER = 2;
  24. const ATTRIBUTE_NATIVE = 3;
  25. /**
  26. * LDAP Connection
  27. *
  28. * @var \Zend\Ldap\Ldap
  29. */
  30. protected $ldap = null;
  31. /**
  32. * Result identifier resource
  33. *
  34. * @var resource
  35. */
  36. protected $resultId = null;
  37. /**
  38. * Current result entry identifier
  39. *
  40. * @var resource
  41. */
  42. protected $current = null;
  43. /**
  44. * Number of items in query result
  45. *
  46. * @var integer
  47. */
  48. protected $itemCount = -1;
  49. /**
  50. * The method that will be applied to the attribute's names.
  51. *
  52. * @var integer|callback
  53. */
  54. protected $attributeNameTreatment = self::ATTRIBUTE_TO_LOWER;
  55. /**
  56. * Constructor.
  57. *
  58. * @param \Zend\Ldap\Ldap $ldap
  59. * @param resource $resultId
  60. * @throws \Zend\Ldap\Exception\LdapException if no entries was found.
  61. * @return DefaultIterator
  62. */
  63. public function __construct(Ldap\Ldap $ldap, $resultId)
  64. {
  65. $this->ldap = $ldap;
  66. $this->resultId = $resultId;
  67. $this->itemCount = @ldap_count_entries($ldap->getResource(), $resultId);
  68. if ($this->itemCount === false) {
  69. throw new Exception\LdapException($this->ldap, 'counting entries');
  70. }
  71. }
  72. public function __destruct()
  73. {
  74. $this->close();
  75. }
  76. /**
  77. * Closes the current result set
  78. *
  79. * @return bool
  80. */
  81. public function close()
  82. {
  83. $isClosed = false;
  84. if (is_resource($this->resultId)) {
  85. $isClosed = @ldap_free_result($this->resultId);
  86. $this->resultId = null;
  87. $this->current = null;
  88. }
  89. return $isClosed;
  90. }
  91. /**
  92. * Gets the current LDAP connection.
  93. *
  94. * @return \Zend\Ldap\Ldap
  95. */
  96. public function getLDAP()
  97. {
  98. return $this->ldap;
  99. }
  100. /**
  101. * Sets the attribute name treatment.
  102. *
  103. * Can either be one of the following constants
  104. * - Zend\Ldap\Collection\DefaultIterator::ATTRIBUTE_TO_LOWER
  105. * - Zend\Ldap\Collection\DefaultIterator::ATTRIBUTE_TO_UPPER
  106. * - Zend\Ldap\Collection\DefaultIterator::ATTRIBUTE_NATIVE
  107. * or a valid callback accepting the attribute's name as it's only
  108. * argument and returning the new attribute's name.
  109. *
  110. * @param integer|callback $attributeNameTreatment
  111. * @return DefaultIterator Provides a fluent interface
  112. */
  113. public function setAttributeNameTreatment($attributeNameTreatment)
  114. {
  115. if (is_callable($attributeNameTreatment)) {
  116. if (is_string($attributeNameTreatment) && !function_exists($attributeNameTreatment)) {
  117. $this->attributeNameTreatment = self::ATTRIBUTE_TO_LOWER;
  118. } elseif (is_array($attributeNameTreatment)
  119. && !method_exists($attributeNameTreatment[0], $attributeNameTreatment[1])
  120. ) {
  121. $this->attributeNameTreatment = self::ATTRIBUTE_TO_LOWER;
  122. } else {
  123. $this->attributeNameTreatment = $attributeNameTreatment;
  124. }
  125. } else {
  126. $attributeNameTreatment = (int)$attributeNameTreatment;
  127. switch ($attributeNameTreatment) {
  128. case self::ATTRIBUTE_TO_LOWER:
  129. case self::ATTRIBUTE_TO_UPPER:
  130. case self::ATTRIBUTE_NATIVE:
  131. $this->attributeNameTreatment = $attributeNameTreatment;
  132. break;
  133. default:
  134. $this->attributeNameTreatment = self::ATTRIBUTE_TO_LOWER;
  135. break;
  136. }
  137. }
  138. return $this;
  139. }
  140. /**
  141. * Returns the currently set attribute name treatment
  142. *
  143. * @return integer|callback
  144. */
  145. public function getAttributeNameTreatment()
  146. {
  147. return $this->attributeNameTreatment;
  148. }
  149. /**
  150. * Returns the number of items in current result
  151. * Implements Countable
  152. *
  153. * @return int
  154. */
  155. public function count()
  156. {
  157. return $this->itemCount;
  158. }
  159. /**
  160. * Return the current result item
  161. * Implements Iterator
  162. *
  163. * @return array|null
  164. * @throws \Zend\Ldap\Exception\LdapException
  165. */
  166. public function current()
  167. {
  168. if (!is_resource($this->current)) {
  169. $this->rewind();
  170. }
  171. if (!is_resource($this->current)) {
  172. return null;
  173. }
  174. $entry = array('dn' => $this->key());
  175. $ber_identifier = null;
  176. $name = @ldap_first_attribute(
  177. $this->ldap->getResource(), $this->current,
  178. $ber_identifier
  179. );
  180. while ($name) {
  181. $data = @ldap_get_values_len($this->ldap->getResource(), $this->current, $name);
  182. unset($data['count']);
  183. switch ($this->attributeNameTreatment) {
  184. case self::ATTRIBUTE_TO_LOWER:
  185. $attrName = strtolower($name);
  186. break;
  187. case self::ATTRIBUTE_TO_UPPER:
  188. $attrName = strtoupper($name);
  189. break;
  190. case self::ATTRIBUTE_NATIVE:
  191. $attrName = $name;
  192. break;
  193. default:
  194. $attrName = call_user_func($this->attributeNameTreatment, $name);
  195. break;
  196. }
  197. $entry[$attrName] = $data;
  198. $name = @ldap_next_attribute(
  199. $this->ldap->getResource(), $this->current,
  200. $ber_identifier
  201. );
  202. }
  203. ksort($entry, SORT_LOCALE_STRING);
  204. return $entry;
  205. }
  206. /**
  207. * Return the result item key
  208. * Implements Iterator
  209. *
  210. * @throws \Zend\Ldap\Exception\LdapException
  211. * @return string|null
  212. */
  213. public function key()
  214. {
  215. if (!is_resource($this->current)) {
  216. $this->rewind();
  217. }
  218. if (is_resource($this->current)) {
  219. $currentDn = @ldap_get_dn($this->ldap->getResource(), $this->current);
  220. if ($currentDn === false) {
  221. throw new Exception\LdapException($this->ldap, 'getting dn');
  222. }
  223. return $currentDn;
  224. } else {
  225. return null;
  226. }
  227. }
  228. /**
  229. * Move forward to next result item
  230. * Implements Iterator
  231. *
  232. * @throws \Zend\Ldap\Exception\LdapException
  233. * @return
  234. */
  235. public function next()
  236. {
  237. $code = 0;
  238. if (is_resource($this->current) && $this->itemCount > 0) {
  239. $this->current = @ldap_next_entry($this->ldap->getResource(), $this->current);
  240. if ($this->current === false) {
  241. $msg = $this->ldap->getLastError($code);
  242. if ($code === Exception\LdapException::LDAP_SIZELIMIT_EXCEEDED) {
  243. // we have reached the size limit enforced by the server
  244. return;
  245. } elseif ($code > Exception\LdapException::LDAP_SUCCESS) {
  246. throw new Exception\LdapException($this->ldap, 'getting next entry (' . $msg . ')');
  247. }
  248. }
  249. } else {
  250. $this->current = false;
  251. }
  252. }
  253. /**
  254. * Rewind the Iterator to the first result item
  255. * Implements Iterator
  256. *
  257. *
  258. * @throws \Zend\Ldap\Exception\LdapException
  259. */
  260. public function rewind()
  261. {
  262. if (is_resource($this->resultId)) {
  263. $this->current = @ldap_first_entry($this->ldap->getResource(), $this->resultId);
  264. if ($this->current === false
  265. && $this->ldap->getLastErrorCode() > Exception\LdapException::LDAP_SUCCESS
  266. ) {
  267. throw new Exception\LdapException($this->ldap, 'getting first entry');
  268. }
  269. }
  270. }
  271. /**
  272. * Check if there is a current result item
  273. * after calls to rewind() or next()
  274. * Implements Iterator
  275. *
  276. * @return boolean
  277. */
  278. public function valid()
  279. {
  280. return (is_resource($this->current));
  281. }
  282. }