3 * Zend Framework (http://framework.zend.com/)
5 * @link http://github.com/zendframework/zf2 for the canonical source repository
6 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
7 * @license http://framework.zend.com/license/new-bsd New BSD License
10 namespace Zend\Ldap\Node\Schema
;
13 use Zend\Ldap\Converter
;
17 * Zend\Ldap\Node\Schema\OpenLDAP provides a simple data-container for the Schema node of
20 class OpenLdap
extends Node\Schema
27 protected $attributeTypes = null;
34 protected $objectClasses = null;
41 protected $ldapSyntaxes = null;
48 protected $matchingRules = null;
51 * The matching rule use
55 protected $matchingRuleUse = null;
60 * @param \Zend\Ldap\Dn $dn
61 * @param \Zend\Ldap\Ldap $ldap
62 * @return OpenLdap Provides a fluid interface
64 protected function parseSchema(Ldap\Dn
$dn, Ldap\Ldap
$ldap)
66 parent
::parseSchema($dn, $ldap);
67 $this->loadAttributeTypes();
68 $this->loadLdapSyntaxes();
69 $this->loadMatchingRules();
70 $this->loadMatchingRuleUse();
71 $this->loadObjectClasses();
76 * Gets the attribute Types
80 public function getAttributeTypes()
82 return $this->attributeTypes
;
86 * Gets the object classes
90 public function getObjectClasses()
92 return $this->objectClasses
;
96 * Gets the LDAP syntaxes
100 public function getLdapSyntaxes()
102 return $this->ldapSyntaxes
;
106 * Gets the matching rules
110 public function getMatchingRules()
112 return $this->matchingRules
;
116 * Gets the matching rule use
120 public function getMatchingRuleUse()
122 return $this->matchingRuleUse
;
126 * Loads the attribute Types
130 protected function loadAttributeTypes()
132 $this->attributeTypes
= array();
133 foreach ($this->getAttribute('attributeTypes') as $value) {
134 $val = $this->parseAttributeType($value);
135 $val = new AttributeType\
OpenLdap($val);
136 $this->attributeTypes
[$val->getName()] = $val;
139 foreach ($this->attributeTypes
as $val) {
140 if (count($val->sup
) > 0) {
141 $this->resolveInheritance($val, $this->attributeTypes
);
143 foreach ($val->aliases
as $alias) {
144 $this->attributeTypes
[$alias] = $val;
147 ksort($this->attributeTypes
, SORT_STRING
);
151 * Parses an attributeType value
153 * @param string $value
156 protected function parseAttributeType($value)
158 $attributeType = array(
168 'max-length' => null,
169 'single-value' => false,
170 'collective' => false,
171 'no-user-modification' => false,
172 'usage' => 'userApplications',
174 '_parents' => array());
176 $tokens = $this->tokenizeString($value);
177 $attributeType['oid'] = array_shift($tokens); // first token is the oid
178 $this->parseLdapSchemaSyntax($attributeType, $tokens);
180 if (array_key_exists('syntax', $attributeType)) {
181 // get max length from syntax
182 if (preg_match('/^(.+){(\d+)}$/', $attributeType['syntax'], $matches)) {
183 $attributeType['syntax'] = $matches[1];
184 $attributeType['max-length'] = $matches[2];
188 $this->ensureNameAttribute($attributeType);
190 return $attributeType;
194 * Loads the object classes
198 protected function loadObjectClasses()
200 $this->objectClasses
= array();
201 foreach ($this->getAttribute('objectClasses') as $value) {
202 $val = $this->parseObjectClass($value);
203 $val = new ObjectClass\
OpenLdap($val);
204 $this->objectClasses
[$val->getName()] = $val;
206 foreach ($this->objectClasses
as $val) {
207 if (count($val->sup
) > 0) {
208 $this->resolveInheritance($val, $this->objectClasses
);
210 foreach ($val->aliases
as $alias) {
211 $this->objectClasses
[$alias] = $val;
214 ksort($this->objectClasses
, SORT_STRING
);
218 * Parses an objectClasses value
220 * @param string $value
223 protected function parseObjectClass($value)
225 $objectClass = array(
232 'structural' => false,
233 'auxiliary' => false,
237 '_parents' => array());
239 $tokens = $this->tokenizeString($value);
240 $objectClass['oid'] = array_shift($tokens); // first token is the oid
241 $this->parseLdapSchemaSyntax($objectClass, $tokens);
243 $this->ensureNameAttribute($objectClass);
249 * Resolves inheritance in objectClasses and attributes
251 * @param AbstractItem $node
252 * @param array $repository
254 protected function resolveInheritance(AbstractItem
$node, array $repository)
256 $data = $node->getData();
257 $parents = $data['sup'];
258 if ($parents === null ||
!is_array($parents) ||
count($parents) < 1) {
261 foreach ($parents as $parent) {
262 if (!array_key_exists($parent, $repository)) {
265 if (!array_key_exists('_parents', $data) ||
!is_array($data['_parents'])) {
266 $data['_parents'] = array();
268 $data['_parents'][] = $repository[$parent];
270 $node->setData($data);
274 * Loads the LDAP syntaxes
278 protected function loadLdapSyntaxes()
280 $this->ldapSyntaxes
= array();
281 foreach ($this->getAttribute('ldapSyntaxes') as $value) {
282 $val = $this->parseLdapSyntax($value);
283 $this->ldapSyntaxes
[$val['oid']] = $val;
285 ksort($this->ldapSyntaxes
, SORT_STRING
);
289 * Parses an ldapSyntaxes value
291 * @param string $value
294 protected function parseLdapSyntax($value)
299 '_string' => $value);
301 $tokens = $this->tokenizeString($value);
302 $ldapSyntax['oid'] = array_shift($tokens); // first token is the oid
303 $this->parseLdapSchemaSyntax($ldapSyntax, $tokens);
309 * Loads the matching rules
313 protected function loadMatchingRules()
315 $this->matchingRules
= array();
316 foreach ($this->getAttribute('matchingRules') as $value) {
317 $val = $this->parseMatchingRule($value);
318 $this->matchingRules
[$val['name']] = $val;
320 ksort($this->matchingRules
, SORT_STRING
);
324 * Parses an matchingRules value
326 * @param string $value
329 protected function parseMatchingRule($value)
331 $matchingRule = array(
337 '_string' => $value);
339 $tokens = $this->tokenizeString($value);
340 $matchingRule['oid'] = array_shift($tokens); // first token is the oid
341 $this->parseLdapSchemaSyntax($matchingRule, $tokens);
343 $this->ensureNameAttribute($matchingRule);
345 return $matchingRule;
349 * Loads the matching rule use
353 protected function loadMatchingRuleUse()
355 $this->matchingRuleUse
= array();
356 foreach ($this->getAttribute('matchingRuleUse') as $value) {
357 $val = $this->parseMatchingRuleUse($value);
358 $this->matchingRuleUse
[$val['name']] = $val;
360 ksort($this->matchingRuleUse
, SORT_STRING
);
364 * Parses an matchingRuleUse value
366 * @param string $value
369 protected function parseMatchingRuleUse($value)
371 $matchingRuleUse = array(
376 'applies' => array(),
377 '_string' => $value);
379 $tokens = $this->tokenizeString($value);
380 $matchingRuleUse['oid'] = array_shift($tokens); // first token is the oid
381 $this->parseLdapSchemaSyntax($matchingRuleUse, $tokens);
383 $this->ensureNameAttribute($matchingRuleUse);
385 return $matchingRuleUse;
389 * Ensures that a name element is present and that it is single-values.
393 protected function ensureNameAttribute(array &$data)
395 if (!array_key_exists('name', $data) ||
empty($data['name'])) {
397 $data['name'] = $data['oid'];
399 if (is_array($data['name'])) {
400 // make one name the default and put the other ones into aliases
401 $aliases = $data['name'];
402 $data['name'] = array_shift($aliases);
403 $data['aliases'] = $aliases;
405 $data['aliases'] = array();
410 * Parse the given tokens into a data structure
413 * @param array $tokens
416 protected function parseLdapSchemaSyntax(array &$data, array $tokens)
418 // tokens that have no value associated
419 $noValue = array('single-value',
422 'no-user-modification',
426 // tokens that can have multiple values
427 $multiValue = array('must', 'may', 'sup');
429 while (count($tokens) > 0) {
430 $token = strtolower(array_shift($tokens));
431 if (in_array($token, $noValue)) {
432 $data[$token] = true; // single value token
434 $data[$token] = array_shift($tokens);
435 // this one follows a string or a list if it is multivalued
436 if ($data[$token] == '(') {
437 // this creates the list of values and cycles through the tokens
438 // until the end of the list is reached ')'
439 $data[$token] = array();
441 $tmp = array_shift($tokens);
447 $data[$token][] = Converter\Converter
::fromLdap($tmp);
449 $tmp = array_shift($tokens);
452 $data[$token] = Converter\Converter
::fromLdap($data[$token]);
454 // create a array if the value should be multivalued but was not
455 if (in_array($token, $multiValue) && !is_array($data[$token])) {
456 $data[$token] = array($data[$token]);
463 * Tokenizes the given value into an array
465 * @param string $value
466 * @return array tokens
468 protected function tokenizeString($value)
472 // this one is taken from PEAR::Net_LDAP2
473 $pattern = "/\\s* (?:([()]) | ([^'\\s()]+) | '((?:[^']+|'[^\\s)])*)') \\s*/x";
474 preg_match_all($pattern, $value, $matches);
475 $cMatches = count($matches[0]);
476 $cPattern = count($matches);
477 for ($i = 0; $i < $cMatches; $i++
) { // number of tokens (full pattern match)
478 for ($j = 1; $j < $cPattern; $j++
) { // each subpattern
479 $tok = trim($matches[$j][$i]);
480 if (!empty($tok)) { // pattern match in this subpattern
481 $tokens[$i] = $tok; // this is the token
485 if ($tokens[0] == '(') {
486 array_shift($tokens);
488 if ($tokens[count($tokens) - 1] == ')') {