Add Attribute required by ObjectClasses in schema viewer,

Attribute is_rdn dynamically calculated,
Fix Required by Objectclasses when viewing a DN
This commit is contained in:
2025-03-14 23:44:44 +11:00
parent 8ab5b4f35c
commit 4a84c25ac7
8 changed files with 85 additions and 32 deletions

View File

@@ -20,9 +20,6 @@ class Attribute implements \Countable, \ArrayAccess, \Iterator
// Is this attribute an internal attribute
protected(set) bool $is_internal = FALSE;
// Is this attribute the RDN?
public bool $is_rdn = FALSE;
// MIN/MAX number of values
protected(set) int $min_values_count = 0;
protected(set) int $max_values_count = 0;
@@ -40,7 +37,7 @@ class Attribute implements \Countable, \ArrayAccess, \Iterator
protected(set) Collection $values_old;
// Current Values
public Collection $values;
// The other object classes of the entry that include this attribute
// The objectclasses of the entry that has this attribute
protected(set) Collection $oc;
/*
@@ -100,7 +97,7 @@ class Attribute implements \Countable, \ArrayAccess, \Iterator
* @param string $dn DN this attribute is used in
* @param string $name Name of the attribute
* @param array $values Current Values
* @param array $oc ObjectClasses that the DN has, that includes this attribute
* @param array $oc The objectclasses that the DN of this attribute has
*/
public function __construct(string $dn,string $name,array $values,array $oc=[])
{
@@ -143,6 +140,10 @@ class Attribute implements \Countable, \ArrayAccess, \Iterator
'hints' => $this->hints(),
// Can this attribute be edited
'is_editable' => $this->schema ? $this->schema->{$key} : NULL,
// Objectclasses that required this attribute for an LDAP entry
'required' => $this->required(),
// Is this attribute an RDN attribute
'is_rdn' => $this->isRDN(),
// We prefer the name as per the schema if it exists
'name' => $this->schema ? $this->schema->{$key} : $this->{$key},
// Attribute name in lower case
@@ -232,11 +233,8 @@ class Attribute implements \Countable, \ArrayAccess, \Iterator
// If this attribute name is an alias for the schema attribute name
// @todo
// objectClasses requiring this attribute
// @todo limit this to this DNs objectclasses
// eg: $result->put('required','Required by objectClasses: a,b');
if ($this->required_by->count())
$result->put(__('required'),sprintf('%s: %s',__('Required Attribute by ObjectClass(es)'),$this->required_by->join(',')));
if ($this->required()->count())
$result->put(__('required'),sprintf('%s: %s',__('Required Attribute by ObjectClass(es)'),$this->required()->join(', ')));
// This attribute has language tags
if ($this->lang_tags->count())
@@ -256,6 +254,22 @@ class Attribute implements \Countable, \ArrayAccess, \Iterator
|| ($this->values->diff($this->values_old)->count() !== 0);
}
/**
* Work out if this attribute is an RDN attribute
*
* @return bool
*/
public function isRDN(): bool
{
// If we dont have an DN, then we cant know
if (! $this->dn)
return FALSE;
$rdns = collect(explode('+',substr($this->dn,0,strpos($this->dn,','))));
return $rdns->filter(fn($item) => str_starts_with($item,$this->name.'='))->count() > 0;
}
/**
* Display the attribute value
*
@@ -287,6 +301,19 @@ class Attribute implements \Countable, \ArrayAccess, \Iterator
return Arr::get($this->values,$key);
}
/**
* Work out if this attribute is required by an objectClass the entry has
*
* @return Collection
*/
public function required(): Collection
{
// If we dont have any objectclasses then we cant know if it is required
return $this->oc->count()
? $this->oc->intersect($this->schema->required_by_object_classes->keys())->sort()
: collect();
}
/**
* If this attribute has RFC3866 Language Tags, this will enable those values to be captured
*

View File

@@ -21,15 +21,15 @@ final class ObjectClass extends Attribute
* @param string $dn DN this attribute is used in
* @param string $name Name of the attribute
* @param array $values Current Values
* @param array $oc ObjectClasses that the DN has, that includes this attribute
* @param array $oc The objectclasses that the DN of this attribute has
*/
public function __construct(string $dn,string $name,array $values,array $oc=[])
{
parent::__construct($dn,$name,$values,$oc);
parent::__construct($dn,$name,$values,['top']);
$this->oc_schema = config('server')
->schema('objectclasses')
->filter(fn($item)=>$this->values->contains($item->name));
->filter(fn($item)=>$this->values->merge($this->values_old)->unique()->contains($item->name));
}
public function __get(string $key): mixed

View File

@@ -320,11 +320,12 @@ final class AttributeType extends Base {
* that is the list of objectClasses which must have this attribute.
*
* @param string $name The name of the objectClass to add.
* @param bool $structural
*/
public function addRequiredByObjectClass(string $name): void
public function addRequiredByObjectClass(string $name,bool $structural): void
{
if (! $this->required_by_object_classes->contains($name))
$this->required_by_object_classes->push($name);
if (! $this->required_by_object_classes->has($name))
$this->required_by_object_classes->put($name,$structural);
}
/**
@@ -332,6 +333,7 @@ final class AttributeType extends Base {
* that is the list of objectClasses which provide this attribute.
*
* @param string $name The name of the objectClass to add.
* @param bool $structural
*/
public function addUsedInObjectClass(string $name,bool $structural): void
{
@@ -544,7 +546,7 @@ final class AttributeType extends Base {
*/
public function validation(array $array): ?array
{
// For each item in array, we need to get the OC heirachy
// For each item in array, we need to get the OC hierarchy
$heirachy = collect($array)
->filter()
->map(fn($item)=>config('server')

View File

@@ -428,7 +428,7 @@ final class Server
// 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);
$this->attributetypes[strtolower($attr_name)]->addRequiredByObjectClass($object_class->name,$object_class->isStructural());
// Force May
foreach ($object_class->getForceMayAttrs() as $attr_name)