Optimize schema objectclass processing, changing debugging output, remove redundant functions
This commit is contained in:
parent
56fcd729e7
commit
acf19cdc5b
@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
namespace App\Classes\LDAP\Schema;
|
namespace App\Classes\LDAP\Schema;
|
||||||
|
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
|
||||||
use App\Exceptions\InvalidUsage;
|
use App\Exceptions\InvalidUsage;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -10,38 +12,38 @@ use App\Exceptions\InvalidUsage;
|
|||||||
* A schema item is an ObjectClass, an AttributeBype, a MatchingRule, or a Syntax.
|
* A schema item is an ObjectClass, an AttributeBype, a MatchingRule, or a Syntax.
|
||||||
* All schema items have at least two things in common: An OID and a Description.
|
* All schema items have at least two things in common: An OID and a Description.
|
||||||
*/
|
*/
|
||||||
abstract class Base {
|
abstract class Base
|
||||||
|
{
|
||||||
|
private const LOGKEY = 'Sb-';
|
||||||
|
|
||||||
protected const DEBUG_VERBOSE = FALSE;
|
protected const DEBUG_VERBOSE = FALSE;
|
||||||
|
|
||||||
// Record the LDAP String
|
// Record the LDAP String
|
||||||
private string $line;
|
private(set) string $line;
|
||||||
|
|
||||||
// The schema item's name.
|
// The schema item's name.
|
||||||
protected string $name = '';
|
protected(set) string $name = '';
|
||||||
|
|
||||||
// The OID of this schema item.
|
// The OID of this schema item.
|
||||||
protected string $oid = '';
|
protected(set) string $oid = '';
|
||||||
|
|
||||||
# The description of this schema item.
|
# The description of this schema item.
|
||||||
protected string $description = '';
|
protected(set) string $description = '';
|
||||||
|
|
||||||
// Boolean value indicating whether this objectClass is obsolete
|
// Boolean value indicating whether this objectClass is obsolete
|
||||||
private bool $is_obsolete = FALSE;
|
private(set) bool $is_obsolete = FALSE;
|
||||||
|
|
||||||
public function __construct(string $line)
|
public function __construct(string $line)
|
||||||
{
|
{
|
||||||
$this->line = $line;
|
$this->line = $line;
|
||||||
|
|
||||||
|
$this->parse($line);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function __get(string $key): mixed
|
public function __get(string $key): mixed
|
||||||
{
|
{
|
||||||
switch ($key) {
|
switch ($key) {
|
||||||
case 'description': return $this->description;
|
|
||||||
case 'is_obsolete': return $this->is_obsolete;
|
|
||||||
case 'line': return $this->line;
|
|
||||||
case 'name': return $this->name;
|
|
||||||
case 'name_lc': return strtolower($this->name);
|
case 'name_lc': return strtolower($this->name);
|
||||||
case 'oid': return $this->oid;
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw new InvalidUsage('Unknown key:'.$key);
|
throw new InvalidUsage('Unknown key:'.$key);
|
||||||
@ -58,65 +60,91 @@ abstract class Base {
|
|||||||
return $this->name;
|
return $this->name;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
protected function parse(string $line): void
|
||||||
* @return string
|
|
||||||
* @deprecated replace with $class->description
|
|
||||||
*/
|
|
||||||
public function getDescription(): string
|
|
||||||
{
|
{
|
||||||
return $this->description;
|
$strings = preg_split('/[\s,]+/',$line,-1,PREG_SPLIT_DELIM_CAPTURE);
|
||||||
|
|
||||||
|
for ($i=0; $i < count($strings); $i++) {
|
||||||
|
$this->parse_chunk($strings,$i);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
protected function parse_chunk(array $strings,int &$i): void
|
||||||
* Gets whether this item is flagged as obsolete by the LDAP server.
|
|
||||||
*
|
|
||||||
* @deprecated replace with $this->is_obsolete
|
|
||||||
*/
|
|
||||||
public function getIsObsolete(): bool
|
|
||||||
{
|
{
|
||||||
return $this->is_obsolete;
|
switch ($strings[$i]) {
|
||||||
}
|
case '(':
|
||||||
|
case ')':
|
||||||
|
break;
|
||||||
|
|
||||||
/**
|
case 'NAME':
|
||||||
* Return the objects name.
|
if ($strings[$i+1] !== '(') {
|
||||||
*
|
do {
|
||||||
* @param boolean $lower Return the name in lower case (default)
|
$this->name .= (strlen($this->name) ? ' ' : '').$strings[++$i];
|
||||||
* @return string The name
|
} while (! preg_match('/\'$/s',$strings[$i]));
|
||||||
* @deprecated use object->name
|
|
||||||
*/
|
|
||||||
public function getName(bool $lower=TRUE): string
|
|
||||||
{
|
|
||||||
return $lower ? strtolower($this->name) : $this->name;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
} else {
|
||||||
* Return the objects name.
|
$i++;
|
||||||
*
|
|
||||||
* @return string The name
|
|
||||||
* @deprecated use object->oid
|
|
||||||
*/
|
|
||||||
public function getOID(): string
|
|
||||||
{
|
|
||||||
return $this->oid;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setDescription(string $desc): void
|
do {
|
||||||
{
|
$this->name .= (strlen($this->name) ? ' ' : '').$strings[++$i];
|
||||||
$this->description = $desc;
|
} while (! preg_match('/\'$/s',$strings[$i]));
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
do {
|
||||||
* Sets this attribute's name.
|
$i++;
|
||||||
*
|
} while (! preg_match('/\)+\)?/',$strings[$i]));
|
||||||
* @param string $name The new name to give this attribute.
|
}
|
||||||
*/
|
|
||||||
public function setName($name): void
|
|
||||||
{
|
|
||||||
$this->name = $name;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setOID(string $oid): void
|
$this->name = preg_replace("/^\'(.*)\'$/",'$1',$this->name);
|
||||||
{
|
|
||||||
$this->oid = $oid;
|
if (static::DEBUG_VERBOSE)
|
||||||
|
Log::debug(sprintf('%s:- Case NAME returned (%s)',self::LOGKEY,$this->name));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'DESC':
|
||||||
|
do {
|
||||||
|
$this->description .= (strlen($this->description) ? ' ' : '').$strings[++$i];
|
||||||
|
|
||||||
|
} while (! preg_match('/\'$/s',$strings[$i]));
|
||||||
|
|
||||||
|
$this->description = preg_replace("/^\'(.*)\'$/",'$1',$this->description);
|
||||||
|
|
||||||
|
if (static::DEBUG_VERBOSE)
|
||||||
|
Log::debug(sprintf('%s:- Case DESC returned (%s)',self::LOGKEY,$this->description));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'OBSOLETE':
|
||||||
|
$this->is_obsolete = TRUE;
|
||||||
|
|
||||||
|
if (static::DEBUG_VERBOSE)
|
||||||
|
Log::debug(sprintf('%s:- Case OBSOLETE returned (%s)',self::LOGKEY,$this->is_obsolete));
|
||||||
|
break;
|
||||||
|
|
||||||
|
// @note currently not captured
|
||||||
|
case 'X-SUBST':
|
||||||
|
case 'X-ORDERED':
|
||||||
|
case 'X-EQUALITY':
|
||||||
|
case 'X-ORIGIN':
|
||||||
|
$value = '';
|
||||||
|
|
||||||
|
do {
|
||||||
|
$value .= ($value ? ' ' : '').preg_replace('/^\'(.+)\'$/','$1',$strings[++$i]);
|
||||||
|
|
||||||
|
} while (! preg_match("/\'$/s",$strings[$i]));
|
||||||
|
|
||||||
|
if (static::DEBUG_VERBOSE)
|
||||||
|
Log::debug(sprintf('%s:- Case [%s] returned (%s) - IGNORED',self::LOGKEY,$strings[$i],$value));
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
if (preg_match('/[\d\.]+/i',$strings[$i]) && ($i === 1)) {
|
||||||
|
$this->oid = $strings[$i];
|
||||||
|
|
||||||
|
if (static::DEBUG_VERBOSE)
|
||||||
|
Log::debug(sprintf('%s:- Case default returned OID (%s)',self::LOGKEY,$this->oid));
|
||||||
|
|
||||||
|
} elseif ($strings[$i])
|
||||||
|
Log::alert(sprintf('%s:! Case default discovered a value NOT parsed (%s)',self::LOGKEY,$strings[$i]));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -16,8 +16,13 @@ use App\Exceptions\InvalidUsage;
|
|||||||
*/
|
*/
|
||||||
final class ObjectClass extends Base
|
final class ObjectClass extends Base
|
||||||
{
|
{
|
||||||
|
private const LOGKEY = 'SOC';
|
||||||
|
|
||||||
|
// Array of objectClasses which inherit from this one
|
||||||
|
private(set) Collection $child_classes;
|
||||||
|
|
||||||
// Array of objectClass names from which this objectClass inherits
|
// Array of objectClass names from which this objectClass inherits
|
||||||
private Collection $sup_classes;
|
private(set) Collection $sup_classes;
|
||||||
|
|
||||||
// One of STRUCTURAL, ABSTRACT, or AUXILIARY
|
// One of STRUCTURAL, ABSTRACT, or AUXILIARY
|
||||||
private int $type;
|
private int $type;
|
||||||
@ -29,187 +34,14 @@ final class ObjectClass extends Base
|
|||||||
private Collection $may_attrs;
|
private Collection $may_attrs;
|
||||||
|
|
||||||
// Arrays of attribute names that this objectClass has been forced to MAY attrs, due to configuration
|
// Arrays of attribute names that this objectClass has been forced to MAY attrs, due to configuration
|
||||||
private Collection $may_force;
|
private(set) Collection $may_force;
|
||||||
|
|
||||||
// Array of objectClasses which inherit from this one
|
|
||||||
private Collection $child_objectclasses;
|
|
||||||
|
|
||||||
private bool $is_obsolete;
|
private bool $is_obsolete;
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new ObjectClass object given a raw LDAP objectClass string.
|
|
||||||
*
|
|
||||||
* eg: ( 2.5.6.0 NAME 'top' DESC 'top of the superclass chain' ABSTRACT MUST objectClass )
|
|
||||||
*
|
|
||||||
* @param string $line Schema Line
|
|
||||||
* @param Server $server
|
|
||||||
* @todo Deprecate this $server variable? It is only used for isForceMay() determination, and that might be better done elsewhere?
|
|
||||||
*/
|
|
||||||
public function __construct(string $line,Server $server)
|
|
||||||
{
|
|
||||||
parent::__construct($line);
|
|
||||||
|
|
||||||
if (static::DEBUG_VERBOSE)
|
|
||||||
Log::debug(sprintf('Parsing ObjectClass [%s]',$line));
|
|
||||||
|
|
||||||
$strings = preg_split('/[\s,]+/',$line,-1,PREG_SPLIT_DELIM_CAPTURE);
|
|
||||||
|
|
||||||
// Init
|
|
||||||
$this->may_attrs = collect();
|
|
||||||
$this->may_force = collect();
|
|
||||||
$this->must_attrs = collect();
|
|
||||||
$this->sup_classes = collect();
|
|
||||||
$this->child_objectclasses = collect();
|
|
||||||
|
|
||||||
for ($i=0; $i < count($strings); $i++) {
|
|
||||||
switch ($strings[$i]) {
|
|
||||||
case '(':
|
|
||||||
case ')':
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'NAME':
|
|
||||||
if ($strings[$i+1] != '(') {
|
|
||||||
do {
|
|
||||||
$this->name .= (strlen($this->name) ? ' ' : '').$strings[++$i];
|
|
||||||
|
|
||||||
} while (! preg_match('/\'$/s',$strings[$i]));
|
|
||||||
|
|
||||||
} else {
|
|
||||||
$i++;
|
|
||||||
|
|
||||||
do {
|
|
||||||
$this->name .= (strlen($this->name) ? ' ' : '').$strings[++$i];
|
|
||||||
|
|
||||||
} while (! preg_match('/\'$/s',$strings[$i]));
|
|
||||||
|
|
||||||
do {
|
|
||||||
$i++;
|
|
||||||
} while (! preg_match('/\)+\)?/',$strings[$i]));
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->name = preg_replace("/^\'(.*)\'$/",'$1',$this->name);
|
|
||||||
|
|
||||||
if (static::DEBUG_VERBOSE)
|
|
||||||
Log::debug(sprintf(sprintf('- Case NAME returned (%s)',$this->name)));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'DESC':
|
|
||||||
do {
|
|
||||||
$this->description .= (strlen($this->description) ? ' ' : '').$strings[++$i];
|
|
||||||
|
|
||||||
} while (! preg_match('/\'$/s',$strings[$i]));
|
|
||||||
|
|
||||||
$this->description = preg_replace("/^\'(.*)\'$/",'$1',$this->description);
|
|
||||||
|
|
||||||
if (static::DEBUG_VERBOSE)
|
|
||||||
Log::debug(sprintf('- Case DESC returned (%s)',$this->description));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'OBSOLETE':
|
|
||||||
$this->is_obsolete = TRUE;
|
|
||||||
|
|
||||||
if (static::DEBUG_VERBOSE)
|
|
||||||
Log::debug(sprintf('- Case OBSOLETE returned (%s)',$this->is_obsolete));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'SUP':
|
|
||||||
if ($strings[$i+1] != '(') {
|
|
||||||
$this->sup_classes->push(preg_replace("/'/",'',$strings[++$i]));
|
|
||||||
|
|
||||||
} else {
|
|
||||||
$i++;
|
|
||||||
|
|
||||||
do {
|
|
||||||
$i++;
|
|
||||||
|
|
||||||
if ($strings[$i] != '$')
|
|
||||||
$this->sup_classes->push(preg_replace("/'/",'',$strings[$i]));
|
|
||||||
|
|
||||||
} while (! preg_match('/\)+\)?/',$strings[$i+1]));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (static::DEBUG_VERBOSE)
|
|
||||||
Log::debug(sprintf('- Case SUP returned (%s)',$this->sup_classes->join(',')));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'ABSTRACT':
|
|
||||||
$this->type = Server::OC_ABSTRACT;
|
|
||||||
|
|
||||||
if (static::DEBUG_VERBOSE)
|
|
||||||
Log::debug(sprintf('- Case ABSTRACT returned (%s)',$this->type));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'STRUCTURAL':
|
|
||||||
$this->type = Server::OC_STRUCTURAL;
|
|
||||||
|
|
||||||
if (static::DEBUG_VERBOSE)
|
|
||||||
Log::debug(sprintf('- Case STRUCTURAL returned (%s)',$this->type));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'AUXILIARY':
|
|
||||||
$this->type = Server::OC_AUXILIARY;
|
|
||||||
|
|
||||||
if (static::DEBUG_VERBOSE)
|
|
||||||
Log::debug(sprintf('- Case AUXILIARY returned (%s)',$this->type));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'MUST':
|
|
||||||
$attrs = collect();
|
|
||||||
|
|
||||||
$i = $this->parseList(++$i,$strings,$attrs);
|
|
||||||
|
|
||||||
if (static::DEBUG_VERBOSE)
|
|
||||||
Log::debug(sprintf('= parseList returned %d (%s)',$i,$attrs->join(',')));
|
|
||||||
|
|
||||||
foreach ($attrs as $string) {
|
|
||||||
$attr = new ObjectClassAttribute($string,$this->name);
|
|
||||||
|
|
||||||
if ($server->isForceMay($attr->getName())) {
|
|
||||||
$this->may_force->push($attr);
|
|
||||||
$this->may_attrs->push($attr);
|
|
||||||
|
|
||||||
} else
|
|
||||||
$this->must_attrs->push($attr);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (static::DEBUG_VERBOSE)
|
|
||||||
Log::debug(sprintf('- Case MUST returned (%s) (%s)',$this->must_attrs->join(','),$this->may_force->join(',')));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'MAY':
|
|
||||||
$attrs = collect();
|
|
||||||
|
|
||||||
$i = $this->parseList(++$i,$strings,$attrs);
|
|
||||||
|
|
||||||
if (static::DEBUG_VERBOSE)
|
|
||||||
Log::debug(sprintf('parseList returned %d (%s)',$i,$attrs->join(',')));
|
|
||||||
|
|
||||||
foreach ($attrs as $string) {
|
|
||||||
$attr = new ObjectClassAttribute($string,$this->name);
|
|
||||||
$this->may_attrs->push($attr);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (static::DEBUG_VERBOSE)
|
|
||||||
Log::debug(sprintf('- Case MAY returned (%s)',$this->may_attrs->join(',')));
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
if (preg_match('/[\d\.]+/i',$strings[$i]) && ($i === 1)) {
|
|
||||||
$this->oid = $strings[$i];
|
|
||||||
if (static::DEBUG_VERBOSE)
|
|
||||||
Log::debug(sprintf('- Case default returned (%s)',$this->oid));
|
|
||||||
|
|
||||||
} elseif ($strings[$i])
|
|
||||||
Log::alert(sprintf('! Case default discovered a value NOT parsed (%s)',$strings[$i]),['line'=>$line]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public function __get(string $key): mixed
|
public function __get(string $key): mixed
|
||||||
{
|
{
|
||||||
return match ($key) {
|
return match ($key) {
|
||||||
'attributes' => $this->getAllAttrs(TRUE),
|
'attributes' => $this->getAllAttrs(TRUE),
|
||||||
'sup' => $this->sup_classes,
|
|
||||||
'type_name' => match ($this->type) {
|
'type_name' => match ($this->type) {
|
||||||
Server::OC_STRUCTURAL => 'Structural',
|
Server::OC_STRUCTURAL => 'Structural',
|
||||||
Server::OC_ABSTRACT => 'Abstract',
|
Server::OC_ABSTRACT => 'Abstract',
|
||||||
@ -229,11 +61,8 @@ final class ObjectClass extends Base
|
|||||||
*/
|
*/
|
||||||
public function getAllAttrs(bool $parents=FALSE): Collection
|
public function getAllAttrs(bool $parents=FALSE): Collection
|
||||||
{
|
{
|
||||||
return $this->getMustAttrs($parents)
|
return $this
|
||||||
->transform(function($item) {
|
->getMustAttrs($parents)
|
||||||
$item->required = true;
|
|
||||||
return $item;
|
|
||||||
})
|
|
||||||
->merge($this->getMayAttrs($parents));
|
->merge($this->getMayAttrs($parents));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -245,57 +74,8 @@ final class ObjectClass extends Base
|
|||||||
*/
|
*/
|
||||||
public function addChildObjectClass(string $name): void
|
public function addChildObjectClass(string $name): void
|
||||||
{
|
{
|
||||||
if (! $this->child_objectclasses->contains($name))
|
if (! $this->child_classes->contains($name))
|
||||||
$this->child_objectclasses->push($name);
|
$this->child_classes->push($name);
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the array of objectClass names which inherit from this objectClass.
|
|
||||||
*
|
|
||||||
* @return Collection Names of objectClasses which inherit from this objectClass.
|
|
||||||
* @deprecated use $this->child_objectclasses
|
|
||||||
*/
|
|
||||||
public function getChildObjectClasses(): Collection
|
|
||||||
{
|
|
||||||
return $this->child_objectclasses;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Behaves identically to addMustAttrs, but it operates on the MAY
|
|
||||||
* attributes of this objectClass.
|
|
||||||
*
|
|
||||||
* @param array $attr An array of attribute names (strings) to add.
|
|
||||||
*/
|
|
||||||
private function addMayAttrs(array $attr): void
|
|
||||||
{
|
|
||||||
if (! is_array($attr) || ! count($attr))
|
|
||||||
return;
|
|
||||||
|
|
||||||
$this->may_attrs = $this->may_attrs->merge($attr)->unique();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds the specified array of attributes to this objectClass' list of
|
|
||||||
* MUST attributes. The resulting array of must attributes will contain
|
|
||||||
* unique members.
|
|
||||||
*
|
|
||||||
* @param array $attr An array of attribute names (strings) to add.
|
|
||||||
*/
|
|
||||||
private function addMustAttrs(array $attr): void
|
|
||||||
{
|
|
||||||
if (! is_array($attr) || ! count($attr))
|
|
||||||
return;
|
|
||||||
|
|
||||||
$this->must_attrs = $this->must_attrs->merge($attr)->unique();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return Collection
|
|
||||||
* @deprecated use $this->may_force
|
|
||||||
*/
|
|
||||||
public function getForceMayAttrs(): Collection
|
|
||||||
{
|
|
||||||
return $this->may_force;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -313,42 +93,16 @@ final class ObjectClass extends Base
|
|||||||
*/
|
*/
|
||||||
public function getMayAttrs(bool $parents=FALSE): Collection
|
public function getMayAttrs(bool $parents=FALSE): Collection
|
||||||
{
|
{
|
||||||
// If we dont need our parents, then we'll just return ours.
|
|
||||||
if (! $parents)
|
|
||||||
return $this->may_attrs
|
|
||||||
->sortBy(fn($item)=>strtolower($item->name.$item->source));
|
|
||||||
|
|
||||||
$attrs = $this->may_attrs;
|
$attrs = $this->may_attrs;
|
||||||
|
|
||||||
foreach ($this->getParents() as $object_class)
|
if ($parents)
|
||||||
$attrs = $attrs->merge($object_class->getMayAttrs($parents));
|
foreach ($this->getParents() as $object_class)
|
||||||
|
$attrs = $attrs->merge($object_class->getMayAttrs($parents));
|
||||||
// Remove any duplicates
|
|
||||||
$attrs = $attrs->unique(function($item) { return $item->name; });
|
|
||||||
|
|
||||||
// Return a sorted list
|
// Return a sorted list
|
||||||
return $attrs->sortBy(function($item) { return strtolower($item->name.$item->source); });
|
return $attrs
|
||||||
}
|
->unique(fn($item)=>$item->name)
|
||||||
|
->sortBy(fn($item)=>strtolower($item->name.$item->source));
|
||||||
/**
|
|
||||||
* Gets an array of attribute names (strings) that entries of this ObjectClass must define.
|
|
||||||
* This differs from getMayAttrs in that it returns an array of strings rather than
|
|
||||||
* array of AttributeType objects
|
|
||||||
*
|
|
||||||
* @param bool $parents An array of ObjectClass objects to use when traversing
|
|
||||||
* the inheritance tree. This presents some what of a bootstrapping problem
|
|
||||||
* as we must fetch all objectClasses to determine through inheritance which
|
|
||||||
* attributes this objectClass provides.
|
|
||||||
* @return Collection The array of allowed attribute names (strings).
|
|
||||||
*
|
|
||||||
* @throws InvalidUsage
|
|
||||||
* @see getMustAttrs
|
|
||||||
* @see getMayAttrs
|
|
||||||
* @see getMustAttrNames
|
|
||||||
*/
|
|
||||||
public function getMayAttrNames(bool $parents=FALSE): Collection
|
|
||||||
{
|
|
||||||
return $this->getMayAttrs($parents)->ppluck('name');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -365,41 +119,16 @@ final class ObjectClass extends Base
|
|||||||
*/
|
*/
|
||||||
public function getMustAttrs(bool $parents=FALSE): Collection
|
public function getMustAttrs(bool $parents=FALSE): Collection
|
||||||
{
|
{
|
||||||
// If we dont need our parents, then we'll just return ours.
|
|
||||||
if (! $parents)
|
|
||||||
return $this->must_attrs->sortBy(function($item) { return strtolower($item->name.$item->source); });
|
|
||||||
|
|
||||||
$attrs = $this->must_attrs;
|
$attrs = $this->must_attrs;
|
||||||
|
|
||||||
foreach ($this->getParents() as $object_class)
|
if ($parents)
|
||||||
$attrs = $attrs->merge($object_class->getMustAttrs($parents));
|
foreach ($this->getParents() as $object_class)
|
||||||
|
$attrs = $attrs->merge($object_class->getMustAttrs($parents));
|
||||||
// Remove any duplicates
|
|
||||||
$attrs = $attrs->unique(function($item) { return $item->name; });
|
|
||||||
|
|
||||||
// Return a sorted list
|
// Return a sorted list
|
||||||
return $attrs->sortBy(function($item) { return strtolower($item->name.$item->source); });
|
return $attrs
|
||||||
}
|
->unique(fn($item)=>$item->name)
|
||||||
|
->sortBy(fn($item)=>strtolower($item->name.$item->source));
|
||||||
/**
|
|
||||||
* Gets an array of attribute names (strings) that entries of this ObjectClass must define.
|
|
||||||
* This differs from getMustAttrs in that it returns an array of strings rather than
|
|
||||||
* array of AttributeType objects
|
|
||||||
*
|
|
||||||
* @param bool $parents An array of ObjectClass objects to use when traversing
|
|
||||||
* the inheritance tree. This presents some what of a bootstrapping problem
|
|
||||||
* as we must fetch all objectClasses to determine through inheritance which
|
|
||||||
* attributes this objectClass provides.
|
|
||||||
* @return Collection The array of allowed attribute names (strings).
|
|
||||||
*
|
|
||||||
* @throws InvalidUsage
|
|
||||||
* @see getMustAttrs
|
|
||||||
* @see getMayAttrs
|
|
||||||
* @see getMayAttrNames
|
|
||||||
*/
|
|
||||||
public function getMustAttrNames(bool $parents=FALSE): Collection
|
|
||||||
{
|
|
||||||
return $this->getMustAttrs($parents)->ppluck('name');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -426,27 +155,6 @@ final class ObjectClass extends Base
|
|||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the objectClass names from which this objectClass inherits.
|
|
||||||
*
|
|
||||||
* @return Collection An array of objectClass names (strings)
|
|
||||||
* @deprecated use $this->sup_classes;
|
|
||||||
*/
|
|
||||||
public function getSupClasses(): Collection
|
|
||||||
{
|
|
||||||
return $this->sup_classes;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the type of this objectClass: STRUCTURAL, ABSTRACT, or AUXILIARY.
|
|
||||||
*
|
|
||||||
* @deprecated use $this->type_name
|
|
||||||
*/
|
|
||||||
public function getType()
|
|
||||||
{
|
|
||||||
return $this->type;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return if this objectclass is auxiliary
|
* Return if this objectclass is auxiliary
|
||||||
*
|
*
|
||||||
@ -462,27 +170,9 @@ final class ObjectClass extends Base
|
|||||||
*/
|
*/
|
||||||
public function isForceMay(string $attr): bool
|
public function isForceMay(string $attr): bool
|
||||||
{
|
{
|
||||||
return $this->may_force->ppluck('name')->contains($attr);
|
return $this->may_force
|
||||||
}
|
->pluck('name')
|
||||||
|
->contains($attr);
|
||||||
/**
|
|
||||||
* Return if this objectClass is related to $oclass
|
|
||||||
*
|
|
||||||
* @param array $oclass ObjectClasses that this attribute may be related to
|
|
||||||
* @return bool
|
|
||||||
* @throws InvalidUsage
|
|
||||||
*/
|
|
||||||
public function isRelated(array $oclass): bool
|
|
||||||
{
|
|
||||||
// If I am in the array, we'll just return false
|
|
||||||
if (in_array_ignore_case($this->name,$oclass))
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
foreach ($oclass as $object_class)
|
|
||||||
if ($object_class->isStructural() && in_array_ignore_case($this->name,$object_class->getParents()->pluck('name')))
|
|
||||||
return TRUE;
|
|
||||||
|
|
||||||
return FALSE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function isStructural(): bool
|
public function isStructural(): bool
|
||||||
@ -490,6 +180,143 @@ final class ObjectClass extends Base
|
|||||||
return $this->type === Server::OC_STRUCTURAL;
|
return $this->type === Server::OC_STRUCTURAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new ObjectClass object given a raw LDAP objectClass string.
|
||||||
|
*
|
||||||
|
* eg: ( 2.5.6.0 NAME 'top' DESC 'top of the superclass chain' ABSTRACT MUST objectClass )
|
||||||
|
*
|
||||||
|
* @param string $line Schema Line
|
||||||
|
*/
|
||||||
|
protected function parse(string $line): void
|
||||||
|
{
|
||||||
|
Log::debug(sprintf('%s:Parsing ObjectClass [%s]',self::LOGKEY,$line));
|
||||||
|
|
||||||
|
// Init
|
||||||
|
$this->may_attrs = collect();
|
||||||
|
$this->may_force = collect();
|
||||||
|
$this->must_attrs = collect();
|
||||||
|
$this->sup_classes = collect();
|
||||||
|
$this->child_classes = collect();
|
||||||
|
|
||||||
|
parent::parse($line);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function parse_chunk(array $strings,int &$i): void
|
||||||
|
{
|
||||||
|
switch ($strings[$i]) {
|
||||||
|
case 'NAME':
|
||||||
|
if ($strings[$i+1] != '(') {
|
||||||
|
do {
|
||||||
|
$this->name .= (strlen($this->name) ? ' ' : '').$strings[++$i];
|
||||||
|
|
||||||
|
} while (! preg_match('/\'$/s',$strings[$i]));
|
||||||
|
|
||||||
|
} else {
|
||||||
|
$i++;
|
||||||
|
|
||||||
|
do {
|
||||||
|
$this->name .= (strlen($this->name) ? ' ' : '').$strings[++$i];
|
||||||
|
|
||||||
|
} while (! preg_match('/\'$/s',$strings[$i]));
|
||||||
|
|
||||||
|
do {
|
||||||
|
$i++;
|
||||||
|
} while (! preg_match('/\)+\)?/',$strings[$i]));
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->name = preg_replace("/^\'(.*)\'$/",'$1',$this->name);
|
||||||
|
|
||||||
|
if (static::DEBUG_VERBOSE)
|
||||||
|
Log::debug(sprintf('%s:- Case NAME returned (%s)',self::LOGKEY,$this->name));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'SUP':
|
||||||
|
if ($strings[$i+1] != '(') {
|
||||||
|
$this->sup_classes->push(preg_replace("/'/",'',$strings[++$i]));
|
||||||
|
|
||||||
|
} else {
|
||||||
|
$i++;
|
||||||
|
|
||||||
|
do {
|
||||||
|
$i++;
|
||||||
|
|
||||||
|
if ($strings[$i] != '$')
|
||||||
|
$this->sup_classes->push(preg_replace("/'/",'',$strings[$i]));
|
||||||
|
|
||||||
|
} while (! preg_match('/\)+\)?/',$strings[$i+1]));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (static::DEBUG_VERBOSE)
|
||||||
|
Log::debug(sprintf('%s:- Case SUP returned (%s)',self::LOGKEY,$this->sup_classes->join(',')));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'ABSTRACT':
|
||||||
|
$this->type = Server::OC_ABSTRACT;
|
||||||
|
|
||||||
|
if (static::DEBUG_VERBOSE)
|
||||||
|
Log::debug(sprintf('%s:- Case ABSTRACT returned (%s)',self::LOGKEY,$this->type));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'STRUCTURAL':
|
||||||
|
$this->type = Server::OC_STRUCTURAL;
|
||||||
|
|
||||||
|
if (static::DEBUG_VERBOSE)
|
||||||
|
Log::debug(sprintf('%s:- Case STRUCTURAL returned (%s)',self::LOGKEY,$this->type));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'AUXILIARY':
|
||||||
|
$this->type = Server::OC_AUXILIARY;
|
||||||
|
|
||||||
|
if (static::DEBUG_VERBOSE)
|
||||||
|
Log::debug(sprintf('%s:- Case AUXILIARY returned (%s)',self::LOGKEY,$this->type));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'MUST':
|
||||||
|
$attrs = collect();
|
||||||
|
|
||||||
|
$i = $this->parseList(++$i,$strings,$attrs);
|
||||||
|
|
||||||
|
if (static::DEBUG_VERBOSE)
|
||||||
|
Log::debug(sprintf('%s:= parseList returned %d (%s)',self::LOGKEY,$i,$attrs->join(',')));
|
||||||
|
|
||||||
|
foreach ($attrs as $string) {
|
||||||
|
$attr = new ObjectClassAttribute($string,$this->name);
|
||||||
|
|
||||||
|
if (config('server')->isForceMay($attr->getName())) {
|
||||||
|
$this->may_force->push($attr);
|
||||||
|
$this->may_attrs->push($attr);
|
||||||
|
|
||||||
|
} else
|
||||||
|
$attr->required = TRUE;
|
||||||
|
$this->must_attrs->push($attr);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (static::DEBUG_VERBOSE)
|
||||||
|
Log::debug(sprintf('%s:- Case MUST returned (%s) (%s)',self::LOGKEY,$this->must_attrs->join(','),$this->may_force->join(',')));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'MAY':
|
||||||
|
$attrs = collect();
|
||||||
|
|
||||||
|
$i = $this->parseList(++$i,$strings,$attrs);
|
||||||
|
|
||||||
|
if (static::DEBUG_VERBOSE)
|
||||||
|
Log::debug(sprintf('%s:- parseList returned %d (%s)',self::LOGKEY,$i,$attrs->join(',')));
|
||||||
|
|
||||||
|
foreach ($attrs as $string) {
|
||||||
|
$attr = new ObjectClassAttribute($string,$this->name);
|
||||||
|
$this->may_attrs->push($attr);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (static::DEBUG_VERBOSE)
|
||||||
|
Log::debug(sprintf('%s:- Case MAY returned (%s)',self::LOGKEY,$this->may_attrs->join(',')));
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
parent::parse_chunk($strings,$i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse an LDAP schema list
|
* Parse an LDAP schema list
|
||||||
*
|
*
|
||||||
|
@ -30,7 +30,7 @@ final class Server
|
|||||||
private Collection $matchingrules;
|
private Collection $matchingrules;
|
||||||
private Collection $objectclasses;
|
private Collection $objectclasses;
|
||||||
|
|
||||||
private Entry $rootDSE;
|
private Model $rootDSE;
|
||||||
|
|
||||||
/* ObjectClass Types */
|
/* ObjectClass Types */
|
||||||
public const OC_STRUCTURAL = 0x01;
|
public const OC_STRUCTURAL = 0x01;
|
||||||
@ -418,22 +418,18 @@ final class Server
|
|||||||
|
|
||||||
// Add the used in and required_by values.
|
// Add the used in and required_by values.
|
||||||
foreach ($this->schema('objectclasses') as $object_class) {
|
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.
|
// Add Used In.
|
||||||
foreach ($oclass_attrs as $attr_name)
|
foreach ($object_class->getAllAttrs()->pluck('name') as $attr_name)
|
||||||
if ($this->attributetypes->has(strtolower($attr_name)))
|
if ($this->attributetypes->has(strtolower($attr_name)))
|
||||||
$this->attributetypes[strtolower($attr_name)]->addUsedInObjectClass($object_class->name,$object_class->isStructural());
|
$this->attributetypes[strtolower($attr_name)]->addUsedInObjectClass($object_class->name,$object_class->isStructural());
|
||||||
|
|
||||||
// Add Required By.
|
// Add Required By.
|
||||||
foreach ($must_attrs as $attr_name)
|
foreach ($object_class->getMustAttrs()->pluck('name') as $attr_name)
|
||||||
if ($this->attributetypes->has(strtolower($attr_name)))
|
if ($this->attributetypes->has(strtolower($attr_name)))
|
||||||
$this->attributetypes[strtolower($attr_name)]->addRequiredByObjectClass($object_class->name,$object_class->isStructural());
|
$this->attributetypes[strtolower($attr_name)]->addRequiredByObjectClass($object_class->name,$object_class->isStructural());
|
||||||
|
|
||||||
// Force May
|
// Force May
|
||||||
foreach ($object_class->getForceMayAttrs() as $attr_name)
|
foreach ($object_class->may_force as $attr_name)
|
||||||
if ($this->attributetypes->has(strtolower($attr_name->name)))
|
if ($this->attributetypes->has(strtolower($attr_name->name)))
|
||||||
$this->attributetypes[strtolower($attr_name->name)]->setForceMay();
|
$this->attributetypes[strtolower($attr_name->name)]->setForceMay();
|
||||||
}
|
}
|
||||||
@ -486,7 +482,7 @@ final class Server
|
|||||||
|
|
||||||
// Now go through and reference the parent/child relationships
|
// Now go through and reference the parent/child relationships
|
||||||
foreach ($this->objectclasses as $o)
|
foreach ($this->objectclasses as $o)
|
||||||
foreach ($o->getSupClasses() as $parent) {
|
foreach ($o->sup_classes as $parent) {
|
||||||
$parent = strtolower($parent);
|
$parent = strtolower($parent);
|
||||||
|
|
||||||
if (! $this->objectclasses->contains($parent))
|
if (! $this->objectclasses->contains($parent))
|
||||||
|
@ -29,11 +29,5 @@ class AppServiceProvider extends ServiceProvider
|
|||||||
public function boot(): void
|
public function boot(): void
|
||||||
{
|
{
|
||||||
$this->loadViewsFrom(__DIR__.'/../../resources/themes/architect/views/','architect');
|
$this->loadViewsFrom(__DIR__.'/../../resources/themes/architect/views/','architect');
|
||||||
|
|
||||||
// Enable pluck on collections to work on private values
|
|
||||||
Collection::macro('ppluck',
|
|
||||||
fn($attr)=>$this
|
|
||||||
->map(fn($item)=>$item->{$attr})
|
|
||||||
->values());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -35,10 +35,10 @@
|
|||||||
<td>@lang('Inherits from')</td>
|
<td>@lang('Inherits from')</td>
|
||||||
<td colspan="3">
|
<td colspan="3">
|
||||||
<strong>
|
<strong>
|
||||||
@if($o->sup->count() === 0)
|
@if($o->sup_classes->count() === 0)
|
||||||
@lang('(none)')
|
@lang('(none)')
|
||||||
@else
|
@else
|
||||||
@foreach($o->sup as $sup)
|
@foreach($o->sup_classes as $sup)
|
||||||
@if($loop->index)</strong> <strong>@endif
|
@if($loop->index)</strong> <strong>@endif
|
||||||
<a class="objectclass" id="{{ strtolower($sup) }}" href="#{{ strtolower($sup) }}">{{ $sup }}</a>
|
<a class="objectclass" id="{{ strtolower($sup) }}" href="#{{ strtolower($sup) }}">{{ $sup }}</a>
|
||||||
@endforeach
|
@endforeach
|
||||||
@ -53,10 +53,10 @@
|
|||||||
<strong>
|
<strong>
|
||||||
@if(strtolower($o->name) === 'top')
|
@if(strtolower($o->name) === 'top')
|
||||||
<a class="objectclass" id="-all-">(all)</a>
|
<a class="objectclass" id="-all-">(all)</a>
|
||||||
@elseif(! $o->getChildObjectClasses()->count())
|
@elseif(! $o->child_classes->count())
|
||||||
@lang('(none)')
|
@lang('(none)')
|
||||||
@else
|
@else
|
||||||
@foreach($o->getChildObjectClasses() as $childoc)
|
@foreach($o->child_classes as $childoc)
|
||||||
@if($loop->index)</strong> <strong>@endif
|
@if($loop->index)</strong> <strong>@endif
|
||||||
<a class="objectclass" id="{{ strtolower($childoc) }}" href="#{{ strtolower($childoc) }}">{{ $childoc }}</a>
|
<a class="objectclass" id="{{ strtolower($childoc) }}" href="#{{ strtolower($childoc) }}">{{ $childoc }}</a>
|
||||||
@endforeach
|
@endforeach
|
||||||
|
Loading…
x
Reference in New Issue
Block a user