Improved caching of schema
This commit is contained in:
parent
8ec1d2b1fe
commit
92e5afd614
@ -4,7 +4,6 @@ namespace App\Classes\LDAP\Schema;
|
|||||||
|
|
||||||
use Illuminate\Support\Collection;
|
use Illuminate\Support\Collection;
|
||||||
use Illuminate\Support\Facades\Log;
|
use Illuminate\Support\Facades\Log;
|
||||||
use LdapRecord\Connection;
|
|
||||||
|
|
||||||
use App\Classes\LDAP\Server;
|
use App\Classes\LDAP\Server;
|
||||||
use App\Exceptions\InvalidUsage;
|
use App\Exceptions\InvalidUsage;
|
||||||
@ -19,7 +18,6 @@ use App\Ldap\Entry;
|
|||||||
class ObjectClass extends Base {
|
class ObjectClass extends Base {
|
||||||
// The server ID that this objectclass belongs to.
|
// The server ID that this objectclass belongs to.
|
||||||
private Server $server;
|
private Server $server;
|
||||||
private Connection $connection;
|
|
||||||
|
|
||||||
// Array of objectClass names from which this objectClass inherits
|
// Array of objectClass names from which this objectClass inherits
|
||||||
private Collection $sup_classes;
|
private Collection $sup_classes;
|
||||||
@ -51,7 +49,7 @@ class ObjectClass extends Base {
|
|||||||
*
|
*
|
||||||
* eg: ( 2.5.6.0 NAME 'top' DESC 'top of the superclass chain' ABSTRACT MUST objectClass )
|
* eg: ( 2.5.6.0 NAME 'top' DESC 'top of the superclass chain' ABSTRACT MUST objectClass )
|
||||||
*/
|
*/
|
||||||
public function __construct(string $line,Entry $entry,Server $server)
|
public function __construct(string $line,Server $server)
|
||||||
{
|
{
|
||||||
parent::__construct($line);
|
parent::__construct($line);
|
||||||
|
|
||||||
@ -60,7 +58,6 @@ class ObjectClass extends Base {
|
|||||||
$strings = preg_split('/[\s,]+/',$line,-1,PREG_SPLIT_DELIM_CAPTURE);
|
$strings = preg_split('/[\s,]+/',$line,-1,PREG_SPLIT_DELIM_CAPTURE);
|
||||||
|
|
||||||
// Init
|
// Init
|
||||||
$this->connection = $entry->getConnection();
|
|
||||||
$this->server = $server;
|
$this->server = $server;
|
||||||
$this->may_attrs = collect();
|
$this->may_attrs = collect();
|
||||||
$this->may_force = collect();
|
$this->may_force = collect();
|
||||||
|
@ -32,6 +32,19 @@ class Server
|
|||||||
'matchingrules',
|
'matchingrules',
|
||||||
];
|
];
|
||||||
|
|
||||||
|
public function __get(string $key): mixed
|
||||||
|
{
|
||||||
|
switch ($key) {
|
||||||
|
case 'attributetypes': return $this->attributetypes;
|
||||||
|
case 'ldapsyntaxes': return $this->ldapsyntaxes;
|
||||||
|
case 'matchingrules': return $this->matchingrules;
|
||||||
|
case 'objectclasses': return $this->objectclasses;
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw new Exception('Unknown key:'.$key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Query the server for a DN and return its children and if those children have children.
|
* Query the server for a DN and return its children and if those children have children.
|
||||||
*
|
*
|
||||||
@ -151,230 +164,232 @@ class Server
|
|||||||
if (! in_array($item,self::schema_types))
|
if (! in_array($item,self::schema_types))
|
||||||
throw new InvalidUsage('Invalid request to fetch schema: '.$item);
|
throw new InvalidUsage('Invalid request to fetch schema: '.$item);
|
||||||
|
|
||||||
// First pass if we have already retrieved the schema item
|
$result = Cache::remember('schema'.$item,config('ldap.cache.time'),function() use ($item) {
|
||||||
switch ($item) {
|
// First pass if we have already retrieved the schema item
|
||||||
case 'attributetypes':
|
switch ($item) {
|
||||||
if (isset($this->attributetypes))
|
case 'attributetypes':
|
||||||
return is_null($key) ? $this->attributetypes : $this->attributetypes->get($key);
|
if (isset($this->attributetypes))
|
||||||
else
|
return $this->attributetypes;
|
||||||
$this->attributetypes = collect();
|
else
|
||||||
|
$this->attributetypes = collect();
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'ldapsyntaxes':
|
case 'ldapsyntaxes':
|
||||||
if (isset($this->ldapsyntaxes))
|
if (isset($this->ldapsyntaxes))
|
||||||
return is_null($key) ? $this->ldapsyntaxes : $this->ldapsyntaxes->get($key);
|
return $this->ldapsyntaxes;
|
||||||
else
|
else
|
||||||
$this->ldapsyntaxes = collect();
|
$this->ldapsyntaxes = collect();
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'matchingrules':
|
case 'matchingrules':
|
||||||
if (isset($this->matchingrules))
|
if (isset($this->matchingrules))
|
||||||
return is_null($key) ? $this->matchingrules : $this->matchingrules->get($key);
|
return $this->matchingrules;
|
||||||
else
|
else
|
||||||
$this->matchingrules = collect();
|
$this->matchingrules = collect();
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/*
|
|
||||||
case 'matchingruleuse':
|
|
||||||
if (isset($this->matchingruleuse))
|
|
||||||
return is_null($key) ? $this->matchingruleuse : $this->matchingruleuse->get($key);
|
|
||||||
else
|
|
||||||
$this->matchingruleuse = collect();
|
|
||||||
|
|
||||||
break;
|
|
||||||
*/
|
|
||||||
|
|
||||||
case 'objectclasses':
|
|
||||||
if (isset($this->objectclasses))
|
|
||||||
return is_null($key) ? $this->objectclasses : $this->objectclasses->get($key);
|
|
||||||
else
|
|
||||||
$this->objectclasses = collect();
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
// Shouldnt get here
|
|
||||||
default:
|
|
||||||
throw new InvalidUsage('Invalid request to fetch schema: '.$item);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Try to get the schema DN from the specified entry.
|
|
||||||
$schema_dn = Entry::schemaDN();
|
|
||||||
$schema = (new Server)->fetch($schema_dn);
|
|
||||||
|
|
||||||
switch ($item) {
|
|
||||||
case 'attributetypes':
|
|
||||||
Log::debug('Attribute Types');
|
|
||||||
// build the array of attribueTypes
|
|
||||||
//$syntaxes = $this->SchemaSyntaxes($dn);
|
|
||||||
|
|
||||||
foreach ($schema->{$item} as $line) {
|
|
||||||
if (is_null($line) || ! strlen($line))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
$o = new AttributeType($line);
|
|
||||||
$this->attributetypes->put($o->name_lc,$o);
|
|
||||||
|
|
||||||
/*
|
|
||||||
if (isset($syntaxes[$attr->getSyntaxOID()])) {
|
|
||||||
$syntax = $syntaxes[$attr->getSyntaxOID()];
|
|
||||||
$attr->setType($syntax->getDescription());
|
|
||||||
}
|
|
||||||
$this->attributetypes[$attr->getName()] = $attr;
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* bug 856832: create an entry in the $attrs_oid array too. This
|
|
||||||
* will be a ref to the $attrs entry for maintenance and performance
|
|
||||||
* reasons
|
|
||||||
*/
|
|
||||||
//$attrs_oid[$attr->getOID()] = &$attrs[$attr->getName()];
|
|
||||||
}
|
|
||||||
|
|
||||||
// go back and add data from aliased attributeTypes
|
|
||||||
foreach ($this->attributetypes as $o) {
|
|
||||||
/* foreach of the attribute's aliases, create a new entry in the attrs array
|
|
||||||
* with its name set to the alias name, and all other data copied.*/
|
|
||||||
|
|
||||||
if ($o->aliases->count()) {
|
|
||||||
Log::debug(sprintf('\ Attribute [%s] has the following aliases [%s]',$o->name,$o->aliases->join(',')));
|
|
||||||
|
|
||||||
foreach ($o->aliases as $alias) {
|
|
||||||
$new_attr = clone $o;
|
|
||||||
$new_attr->setName($alias);
|
|
||||||
$new_attr->addAlias($o->name);
|
|
||||||
$new_attr->removeAlias($alias);
|
|
||||||
|
|
||||||
$this->attributetypes->put(strtolower($alias),$new_attr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Now go through and reference the parent/child relationships
|
|
||||||
foreach ($this->attributetypes as $o)
|
|
||||||
if ($o->sup_attribute) {
|
|
||||||
$parent = strtolower($o->sup_attribute);
|
|
||||||
|
|
||||||
if ($this->attributetypes->has($parent) !== FALSE)
|
|
||||||
$this->attributetypes[$parent]->addChild($o->name);
|
|
||||||
}
|
|
||||||
|
|
||||||
// go through any children and add details if the child doesnt have them (ie, cn inherits name)
|
|
||||||
// @todo This doesnt traverse children properly, so children of children may not get the settings they should
|
|
||||||
foreach ($this->attributetypes as $parent) {
|
|
||||||
foreach ($parent->children as $child) {
|
|
||||||
$child = strtolower($child);
|
|
||||||
|
|
||||||
/* only overwrite the child's SINGLE-VALUE property if the parent has it set, and the child doesnt
|
|
||||||
* (note: All LDAP attributes default to multi-value if not explicitly set SINGLE-VALUE) */
|
|
||||||
if (! is_null($parent->is_single_value) && is_null($this->attributetypes[$child]->is_single_value))
|
|
||||||
$this->attributetypes[$child]->setIsSingleValue($parent->is_single_value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add the used in and required_by values.
|
|
||||||
foreach ($this->schema('objectclasses') as $object_class) {
|
|
||||||
$must_attrs = $object_class->getMustAttrNames();
|
|
||||||
$may_attrs = $object_class->getMayAttrNames();
|
|
||||||
$oclass_attrs = $must_attrs->merge($may_attrs)->unique();
|
|
||||||
|
|
||||||
// Add Used In.
|
|
||||||
foreach ($oclass_attrs as $attr_name)
|
|
||||||
if ($this->attributetypes->has(strtolower($attr_name)))
|
|
||||||
$this->attributetypes[strtolower($attr_name)]->addUsedInObjectClass($object_class->name);
|
|
||||||
|
|
||||||
// Add Required By.
|
|
||||||
foreach ($must_attrs as $attr_name)
|
|
||||||
if ($this->attributetypes->has(strtolower($attr_name)))
|
|
||||||
$this->attributetypes[strtolower($attr_name)]->addRequiredByObjectClass($object_class->name);
|
|
||||||
|
|
||||||
// Force May
|
|
||||||
foreach ($object_class->getForceMayAttrs() as $attr_name)
|
|
||||||
if ($this->attributetypes->has(strtolower($attr_name->name)))
|
|
||||||
$this->attributetypes[strtolower($attr_name->name)]->setForceMay();
|
|
||||||
}
|
|
||||||
|
|
||||||
return is_null($key) ? $this->attributetypes : $this->attributetypes->get($key);
|
|
||||||
|
|
||||||
case 'objectclasses':
|
|
||||||
Log::debug('Object Classes');
|
|
||||||
|
|
||||||
foreach ($schema->{$item} as $line) {
|
|
||||||
if (is_null($line) || ! strlen($line))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
$o = new ObjectClass($line,$schema,$this);
|
|
||||||
$this->objectclasses->put($o->name_lc,$o);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Now go through and reference the parent/child relationships
|
|
||||||
foreach ($this->objectclasses as $o)
|
|
||||||
foreach ($o->getSupClasses() as $parent) {
|
|
||||||
$parent = strtolower($parent);
|
|
||||||
if ($this->objectclasses->has($parent) !== FALSE)
|
|
||||||
$this->objectclasses[$parent]->addChildObjectClass($o->name);
|
|
||||||
}
|
|
||||||
|
|
||||||
return is_null($key) ? $this->objectclasses : $this->objectclasses->get($key);
|
|
||||||
|
|
||||||
case 'ldapsyntaxes':
|
|
||||||
Log::debug('LDAP Syntaxes');
|
|
||||||
|
|
||||||
foreach ($schema->{$item} as $line) {
|
|
||||||
if (is_null($line) || ! strlen($line))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
$o = new LDAPSyntax($line);
|
|
||||||
$this->ldapsyntaxes->put(strtolower($o->oid),$o);
|
|
||||||
}
|
|
||||||
|
|
||||||
return is_null($key) ? $this->ldapsyntaxes : $this->ldapsyntaxes->get($key);
|
|
||||||
|
|
||||||
case 'matchingrules':
|
|
||||||
Log::debug('Matching Rules');
|
|
||||||
$this->matchingruleuse = collect();
|
|
||||||
|
|
||||||
foreach ($schema->{$item} as $line) {
|
|
||||||
if (is_null($line) || ! strlen($line))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
$o = new MatchingRule($line);
|
|
||||||
$this->matchingrules->put($o->name_lc,$o);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* For each MatchingRuleUse entry, add the attributes who use it to the
|
case 'matchingruleuse':
|
||||||
* MatchingRule in the $rules array.
|
if (isset($this->matchingruleuse))
|
||||||
*/
|
return is_null($key) ? $this->matchingruleuse : $this->matchingruleuse->get($key);
|
||||||
if ($schema->matchingruleuse) {
|
else
|
||||||
foreach ($schema->matchingruleuse as $line) {
|
$this->matchingruleuse = collect();
|
||||||
|
|
||||||
|
break;
|
||||||
|
*/
|
||||||
|
|
||||||
|
case 'objectclasses':
|
||||||
|
if (isset($this->objectclasses))
|
||||||
|
return $this->objectclasses;
|
||||||
|
else
|
||||||
|
$this->objectclasses = collect();
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Shouldnt get here
|
||||||
|
default:
|
||||||
|
throw new InvalidUsage('Invalid request to fetch schema: '.$item);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try to get the schema DN from the specified entry.
|
||||||
|
$schema_dn = Entry::schemaDN();
|
||||||
|
$schema = (new Server)->fetch($schema_dn);
|
||||||
|
|
||||||
|
switch ($item) {
|
||||||
|
case 'attributetypes':
|
||||||
|
Log::debug('Attribute Types');
|
||||||
|
// build the array of attribueTypes
|
||||||
|
//$syntaxes = $this->SchemaSyntaxes($dn);
|
||||||
|
|
||||||
|
foreach ($schema->{$item} as $line) {
|
||||||
if (is_null($line) || ! strlen($line))
|
if (is_null($line) || ! strlen($line))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
$o = new MatchingRuleUse($line);
|
$o = new AttributeType($line);
|
||||||
$this->matchingruleuse->put($o->name_lc,$o);
|
$this->attributetypes->put($o->name_lc,$o);
|
||||||
|
|
||||||
if ($this->matchingrules->has($o->name_lc) !== FALSE)
|
/*
|
||||||
$this->matchingrules[$o->name_lc]->setUsedByAttrs($o->getUsedByAttrs());
|
if (isset($syntaxes[$attr->getSyntaxOID()])) {
|
||||||
|
$syntax = $syntaxes[$attr->getSyntaxOID()];
|
||||||
|
$attr->setType($syntax->getDescription());
|
||||||
|
}
|
||||||
|
$this->attributetypes[$attr->getName()] = $attr;
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* bug 856832: create an entry in the $attrs_oid array too. This
|
||||||
|
* will be a ref to the $attrs entry for maintenance and performance
|
||||||
|
* reasons
|
||||||
|
*/
|
||||||
|
//$attrs_oid[$attr->getOID()] = &$attrs[$attr->getName()];
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
// go back and add data from aliased attributeTypes
|
||||||
/* No MatchingRuleUse entry in the subschema, so brute-forcing
|
foreach ($this->attributetypes as $o) {
|
||||||
* the reverse-map for the "$rule->getUsedByAttrs()" data.*/
|
/* foreach of the attribute's aliases, create a new entry in the attrs array
|
||||||
foreach ($this->schema('attributetypes') as $attr) {
|
* with its name set to the alias name, and all other data copied.*/
|
||||||
$rule_key = strtolower($attr->getEquality());
|
|
||||||
|
|
||||||
if ($this->matchingrules->has($rule_key) !== FALSE)
|
if ($o->aliases->count()) {
|
||||||
$this->matchingrules[$rule_key]->addUsedByAttr($attr->name);
|
Log::debug(sprintf('\ Attribute [%s] has the following aliases [%s]',$o->name,$o->aliases->join(',')));
|
||||||
|
|
||||||
|
foreach ($o->aliases as $alias) {
|
||||||
|
$new_attr = clone $o;
|
||||||
|
$new_attr->setName($alias);
|
||||||
|
$new_attr->addAlias($o->name);
|
||||||
|
$new_attr->removeAlias($alias);
|
||||||
|
|
||||||
|
$this->attributetypes->put(strtolower($alias),$new_attr);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return is_null($key) ? $this->matchingrules : $this->matchingrules->get($key);
|
// Now go through and reference the parent/child relationships
|
||||||
}
|
foreach ($this->attributetypes as $o)
|
||||||
|
if ($o->sup_attribute) {
|
||||||
|
$parent = strtolower($o->sup_attribute);
|
||||||
|
|
||||||
return NULL;
|
if ($this->attributetypes->has($parent) !== FALSE)
|
||||||
|
$this->attributetypes[$parent]->addChild($o->name);
|
||||||
|
}
|
||||||
|
|
||||||
|
// go through any children and add details if the child doesnt have them (ie, cn inherits name)
|
||||||
|
// @todo This doesnt traverse children properly, so children of children may not get the settings they should
|
||||||
|
foreach ($this->attributetypes as $parent) {
|
||||||
|
foreach ($parent->children as $child) {
|
||||||
|
$child = strtolower($child);
|
||||||
|
|
||||||
|
/* only overwrite the child's SINGLE-VALUE property if the parent has it set, and the child doesnt
|
||||||
|
* (note: All LDAP attributes default to multi-value if not explicitly set SINGLE-VALUE) */
|
||||||
|
if (! is_null($parent->is_single_value) && is_null($this->attributetypes[$child]->is_single_value))
|
||||||
|
$this->attributetypes[$child]->setIsSingleValue($parent->is_single_value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add the used in and required_by values.
|
||||||
|
foreach ($this->schema('objectclasses') as $object_class) {
|
||||||
|
$must_attrs = $object_class->getMustAttrNames();
|
||||||
|
$may_attrs = $object_class->getMayAttrNames();
|
||||||
|
$oclass_attrs = $must_attrs->merge($may_attrs)->unique();
|
||||||
|
|
||||||
|
// Add Used In.
|
||||||
|
foreach ($oclass_attrs as $attr_name)
|
||||||
|
if ($this->attributetypes->has(strtolower($attr_name)))
|
||||||
|
$this->attributetypes[strtolower($attr_name)]->addUsedInObjectClass($object_class->name);
|
||||||
|
|
||||||
|
// Add Required By.
|
||||||
|
foreach ($must_attrs as $attr_name)
|
||||||
|
if ($this->attributetypes->has(strtolower($attr_name)))
|
||||||
|
$this->attributetypes[strtolower($attr_name)]->addRequiredByObjectClass($object_class->name);
|
||||||
|
|
||||||
|
// Force May
|
||||||
|
foreach ($object_class->getForceMayAttrs() as $attr_name)
|
||||||
|
if ($this->attributetypes->has(strtolower($attr_name->name)))
|
||||||
|
$this->attributetypes[strtolower($attr_name->name)]->setForceMay();
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->attributetypes;
|
||||||
|
|
||||||
|
case 'ldapsyntaxes':
|
||||||
|
Log::debug('LDAP Syntaxes');
|
||||||
|
|
||||||
|
foreach ($schema->{$item} as $line) {
|
||||||
|
if (is_null($line) || ! strlen($line))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
$o = new LDAPSyntax($line);
|
||||||
|
$this->ldapsyntaxes->put(strtolower($o->oid),$o);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->ldapsyntaxes;
|
||||||
|
|
||||||
|
case 'matchingrules':
|
||||||
|
Log::debug('Matching Rules');
|
||||||
|
$this->matchingruleuse = collect();
|
||||||
|
|
||||||
|
foreach ($schema->{$item} as $line) {
|
||||||
|
if (is_null($line) || ! strlen($line))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
$o = new MatchingRule($line);
|
||||||
|
$this->matchingrules->put($o->name_lc,$o);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* For each MatchingRuleUse entry, add the attributes who use it to the
|
||||||
|
* MatchingRule in the $rules array.
|
||||||
|
*/
|
||||||
|
if ($schema->matchingruleuse) {
|
||||||
|
foreach ($schema->matchingruleuse as $line) {
|
||||||
|
if (is_null($line) || ! strlen($line))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
$o = new MatchingRuleUse($line);
|
||||||
|
$this->matchingruleuse->put($o->name_lc,$o);
|
||||||
|
|
||||||
|
if ($this->matchingrules->has($o->name_lc) !== FALSE)
|
||||||
|
$this->matchingrules[$o->name_lc]->setUsedByAttrs($o->getUsedByAttrs());
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
/* No MatchingRuleUse entry in the subschema, so brute-forcing
|
||||||
|
* the reverse-map for the "$rule->getUsedByAttrs()" data.*/
|
||||||
|
foreach ($this->schema('attributetypes') as $attr) {
|
||||||
|
$rule_key = strtolower($attr->getEquality());
|
||||||
|
|
||||||
|
if ($this->matchingrules->has($rule_key) !== FALSE)
|
||||||
|
$this->matchingrules[$rule_key]->addUsedByAttr($attr->name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->matchingrules;
|
||||||
|
|
||||||
|
case 'objectclasses':
|
||||||
|
Log::debug('Object Classes');
|
||||||
|
|
||||||
|
foreach ($schema->{$item} as $line) {
|
||||||
|
if (is_null($line) || ! strlen($line))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
$o = new ObjectClass($line,$this);
|
||||||
|
$this->objectclasses->put($o->name_lc,$o);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now go through and reference the parent/child relationships
|
||||||
|
foreach ($this->objectclasses as $o)
|
||||||
|
foreach ($o->getSupClasses() as $parent) {
|
||||||
|
$parent = strtolower($parent);
|
||||||
|
if ($this->objectclasses->has($parent) !== FALSE)
|
||||||
|
$this->objectclasses[$parent]->addChildObjectClass($o->name);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->objectclasses;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return is_null($key) ? $result : $result->get($key);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function schemaSyntaxName(string $oid): ?LDAPSyntax
|
public function schemaSyntaxName(string $oid): ?LDAPSyntax
|
||||||
|
Loading…
Reference in New Issue
Block a user