diff --git a/app/Classes/LDAP/Schema/Base.php b/app/Classes/LDAP/Schema/Base.php index 74265c83..b53e1dca 100644 --- a/app/Classes/LDAP/Schema/Base.php +++ b/app/Classes/LDAP/Schema/Base.php @@ -2,6 +2,8 @@ namespace App\Classes\LDAP\Schema; +use Illuminate\Support\Facades\Log; + 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. * 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; // Record the LDAP String - private string $line; + private(set) string $line; // The schema item's name. - protected string $name = ''; + protected(set) string $name = ''; // The OID of this schema item. - protected string $oid = ''; + protected(set) string $oid = ''; # The description of this schema item. - protected string $description = ''; + protected(set) string $description = ''; // Boolean value indicating whether this objectClass is obsolete - private bool $is_obsolete = FALSE; + private(set) bool $is_obsolete = FALSE; public function __construct(string $line) { $this->line = $line; + + $this->parse($line); } public function __get(string $key): mixed { 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 'oid': return $this->oid; default: throw new InvalidUsage('Unknown key:'.$key); @@ -58,65 +60,91 @@ abstract class Base { return $this->name; } - /** - * @return string - * @deprecated replace with $class->description - */ - public function getDescription(): string + protected function parse(string $line): void { - 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); + } } - /** - * Gets whether this item is flagged as obsolete by the LDAP server. - * - * @deprecated replace with $this->is_obsolete - */ - public function getIsObsolete(): bool + protected function parse_chunk(array $strings,int &$i): void { - return $this->is_obsolete; - } + switch ($strings[$i]) { + case '(': + case ')': + break; - /** - * Return the objects name. - * - * @param boolean $lower Return the name in lower case (default) - * @return string The name - * @deprecated use object->name - */ - public function getName(bool $lower=TRUE): string - { - return $lower ? strtolower($this->name) : $this->name; - } + case 'NAME': + if ($strings[$i+1] !== '(') { + do { + $this->name .= (strlen($this->name) ? ' ' : '').$strings[++$i]; + } while (! preg_match('/\'$/s',$strings[$i])); - /** - * Return the objects name. - * - * @return string The name - * @deprecated use object->oid - */ - public function getOID(): string - { - return $this->oid; - } + } else { + $i++; - public function setDescription(string $desc): void - { - $this->description = $desc; - } + do { + $this->name .= (strlen($this->name) ? ' ' : '').$strings[++$i]; + } while (! preg_match('/\'$/s',$strings[$i])); - /** - * Sets this attribute's name. - * - * @param string $name The new name to give this attribute. - */ - public function setName($name): void - { - $this->name = $name; - } + do { + $i++; + } while (! preg_match('/\)+\)?/',$strings[$i])); + } - public function setOID(string $oid): void - { - $this->oid = $oid; + $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 '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])); + } } } \ No newline at end of file diff --git a/app/Classes/LDAP/Schema/ObjectClass.php b/app/Classes/LDAP/Schema/ObjectClass.php index 8cfb4cae..3b6b8d0e 100644 --- a/app/Classes/LDAP/Schema/ObjectClass.php +++ b/app/Classes/LDAP/Schema/ObjectClass.php @@ -16,8 +16,13 @@ use App\Exceptions\InvalidUsage; */ 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 - private Collection $sup_classes; + private(set) Collection $sup_classes; // One of STRUCTURAL, ABSTRACT, or AUXILIARY private int $type; @@ -29,187 +34,14 @@ final class ObjectClass extends Base private Collection $may_attrs; // Arrays of attribute names that this objectClass has been forced to MAY attrs, due to configuration - private Collection $may_force; - - // Array of objectClasses which inherit from this one - private Collection $child_objectclasses; + private(set) Collection $may_force; 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 { return match ($key) { 'attributes' => $this->getAllAttrs(TRUE), - 'sup' => $this->sup_classes, 'type_name' => match ($this->type) { Server::OC_STRUCTURAL => 'Structural', Server::OC_ABSTRACT => 'Abstract', @@ -229,11 +61,8 @@ final class ObjectClass extends Base */ public function getAllAttrs(bool $parents=FALSE): Collection { - return $this->getMustAttrs($parents) - ->transform(function($item) { - $item->required = true; - return $item; - }) + return $this + ->getMustAttrs($parents) ->merge($this->getMayAttrs($parents)); } @@ -245,57 +74,8 @@ final class ObjectClass extends Base */ public function addChildObjectClass(string $name): void { - if (! $this->child_objectclasses->contains($name)) - $this->child_objectclasses->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; + if (! $this->child_classes->contains($name)) + $this->child_classes->push($name); } /** @@ -313,42 +93,16 @@ final class ObjectClass extends Base */ 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; - foreach ($this->getParents() as $object_class) - $attrs = $attrs->merge($object_class->getMayAttrs($parents)); - - // Remove any duplicates - $attrs = $attrs->unique(function($item) { return $item->name; }); + if ($parents) + foreach ($this->getParents() as $object_class) + $attrs = $attrs->merge($object_class->getMayAttrs($parents)); // Return a sorted list - return $attrs->sortBy(function($item) { return 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'); + return $attrs + ->unique(fn($item)=>$item->name) + ->sortBy(fn($item)=>strtolower($item->name.$item->source)); } /** @@ -365,41 +119,16 @@ final class ObjectClass extends Base */ 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; - foreach ($this->getParents() as $object_class) - $attrs = $attrs->merge($object_class->getMustAttrs($parents)); - - // Remove any duplicates - $attrs = $attrs->unique(function($item) { return $item->name; }); + if ($parents) + foreach ($this->getParents() as $object_class) + $attrs = $attrs->merge($object_class->getMustAttrs($parents)); // Return a sorted list - return $attrs->sortBy(function($item) { return 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'); + return $attrs + ->unique(fn($item)=>$item->name) + ->sortBy(fn($item)=>strtolower($item->name.$item->source)); } /** @@ -426,27 +155,6 @@ final class ObjectClass extends Base 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 * @@ -462,27 +170,9 @@ final class ObjectClass extends Base */ public function isForceMay(string $attr): bool { - return $this->may_force->ppluck('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; + return $this->may_force + ->pluck('name') + ->contains($attr); } public function isStructural(): bool @@ -490,6 +180,143 @@ final class ObjectClass extends Base 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 * diff --git a/app/Classes/LDAP/Server.php b/app/Classes/LDAP/Server.php index 59aafb85..39f478be 100644 --- a/app/Classes/LDAP/Server.php +++ b/app/Classes/LDAP/Server.php @@ -30,7 +30,7 @@ final class Server private Collection $matchingrules; private Collection $objectclasses; - private Entry $rootDSE; + private Model $rootDSE; /* ObjectClass Types */ public const OC_STRUCTURAL = 0x01; @@ -418,22 +418,18 @@ final class Server // 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) + foreach ($object_class->getAllAttrs()->pluck('name') as $attr_name) if ($this->attributetypes->has(strtolower($attr_name))) $this->attributetypes[strtolower($attr_name)]->addUsedInObjectClass($object_class->name,$object_class->isStructural()); // 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))) $this->attributetypes[strtolower($attr_name)]->addRequiredByObjectClass($object_class->name,$object_class->isStructural()); // 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))) $this->attributetypes[strtolower($attr_name->name)]->setForceMay(); } @@ -486,7 +482,7 @@ final class Server // Now go through and reference the parent/child relationships foreach ($this->objectclasses as $o) - foreach ($o->getSupClasses() as $parent) { + foreach ($o->sup_classes as $parent) { $parent = strtolower($parent); if (! $this->objectclasses->contains($parent)) diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php index 21081cc3..cbd94227 100644 --- a/app/Providers/AppServiceProvider.php +++ b/app/Providers/AppServiceProvider.php @@ -29,11 +29,5 @@ class AppServiceProvider extends ServiceProvider public function boot(): void { $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()); } } \ No newline at end of file diff --git a/resources/views/fragment/schema/objectclasses.blade.php b/resources/views/fragment/schema/objectclasses.blade.php index a941f295..8895a6e3 100644 --- a/resources/views/fragment/schema/objectclasses.blade.php +++ b/resources/views/fragment/schema/objectclasses.blade.php @@ -35,10 +35,10 @@ @lang('Inherits from') - @if($o->sup->count() === 0) + @if($o->sup_classes->count() === 0) @lang('(none)') @else - @foreach($o->sup as $sup) + @foreach($o->sup_classes as $sup) @if($loop->index) @endif {{ $sup }} @endforeach @@ -53,10 +53,10 @@ @if(strtolower($o->name) === 'top') (all) - @elseif(! $o->getChildObjectClasses()->count()) + @elseif(! $o->child_classes->count()) @lang('(none)') @else - @foreach($o->getChildObjectClasses() as $childoc) + @foreach($o->child_classes as $childoc) @if($loop->index) @endif {{ $childoc }} @endforeach