2009-06-30 20:46:00 +10:00
|
|
|
<?php
|
2021-12-08 23:26:12 +11:00
|
|
|
|
|
|
|
namespace App\Classes\LDAP;
|
2009-07-01 16:09:17 +10:00
|
|
|
|
2023-03-31 15:55:08 +11:00
|
|
|
use Illuminate\Contracts\View\View;
|
2025-01-16 12:47:55 +11:00
|
|
|
use Illuminate\Support\Arr;
|
2023-02-19 20:25:32 +11:00
|
|
|
use Illuminate\Support\Collection;
|
|
|
|
|
2023-03-02 14:41:38 +11:00
|
|
|
use App\Classes\LDAP\Schema\AttributeType;
|
|
|
|
|
2009-07-01 16:09:17 +10:00
|
|
|
/**
|
2021-12-08 23:26:12 +11:00
|
|
|
* Represents an attribute of an LDAP Object
|
2009-06-30 20:46:00 +10:00
|
|
|
*/
|
2025-01-17 17:00:36 +11:00
|
|
|
class Attribute implements \Countable, \ArrayAccess, \Iterator
|
2021-12-08 23:26:12 +11:00
|
|
|
{
|
2023-02-19 20:25:32 +11:00
|
|
|
// Attribute Name
|
|
|
|
protected string $name;
|
2025-01-17 17:00:36 +11:00
|
|
|
private int $counter = 0;
|
2023-02-19 20:25:32 +11:00
|
|
|
|
2023-03-02 18:21:53 +11:00
|
|
|
protected ?AttributeType $schema = NULL;
|
2023-03-02 14:41:38 +11:00
|
|
|
|
2021-12-08 23:26:12 +11:00
|
|
|
/*
|
2009-07-01 16:09:17 +10:00
|
|
|
# Source of this attribute definition
|
|
|
|
protected $source;
|
2021-12-08 23:26:12 +11:00
|
|
|
*/
|
2009-06-30 20:46:00 +10:00
|
|
|
|
2023-02-19 20:25:32 +11:00
|
|
|
// Current and Old Values
|
|
|
|
protected Collection $values;
|
|
|
|
|
2023-03-02 09:54:30 +11:00
|
|
|
// Is this attribute an internal attribute
|
2023-03-02 18:21:53 +11:00
|
|
|
protected bool $is_internal = FALSE;
|
2023-03-02 14:41:38 +11:00
|
|
|
|
|
|
|
// Is this attribute the RDN?
|
|
|
|
protected bool $is_rdn = FALSE;
|
|
|
|
|
2023-03-02 14:55:06 +11:00
|
|
|
// MIN/MAX number of values
|
|
|
|
protected int $min_values_count = 0;
|
|
|
|
protected int $max_values_count = 0;
|
2009-06-30 20:46:00 +10:00
|
|
|
|
2023-03-27 16:19:37 +11:00
|
|
|
// RFC3866 Language Tags
|
|
|
|
protected Collection $lang_tags;
|
|
|
|
|
2024-01-09 17:44:50 +11:00
|
|
|
// The old values for this attribute - helps with isDirty() to determine if there is an update pending
|
|
|
|
protected Collection $oldValues;
|
|
|
|
|
2023-03-02 14:55:06 +11:00
|
|
|
/*
|
2009-06-30 20:46:00 +10:00
|
|
|
# Has the attribute been modified
|
2009-07-01 16:09:17 +10:00
|
|
|
protected $modified = false;
|
|
|
|
# Is the attribute being deleted because of an object class removal
|
|
|
|
protected $forcedelete = false;
|
2009-06-30 20:46:00 +10:00
|
|
|
# Is the attribute visible
|
2009-07-01 16:09:17 +10:00
|
|
|
protected $visible = false;
|
|
|
|
protected $forcehide = false;
|
2009-06-30 20:46:00 +10:00
|
|
|
# Is the attribute modifiable
|
2009-07-01 16:09:17 +10:00
|
|
|
protected $readonly = false;
|
|
|
|
# LDAP attribute type MUST/MAY
|
|
|
|
protected $ldaptype = null;
|
|
|
|
# Attribute property type (eg password, select, multiselect)
|
|
|
|
protected $type = '';
|
|
|
|
# Attribute value to keep unique
|
|
|
|
protected $unique = false;
|
2009-06-30 20:46:00 +10:00
|
|
|
|
|
|
|
# Display parameters
|
2009-07-01 16:09:17 +10:00
|
|
|
protected $display = '';
|
|
|
|
protected $icon = '';
|
|
|
|
protected $hint = '';
|
|
|
|
# Helper details
|
|
|
|
protected $helper = array();
|
|
|
|
protected $helpervalue = array();
|
|
|
|
# Onchange details
|
|
|
|
protected $onchange = array();
|
|
|
|
# Show spacer after this attribute is rendered
|
|
|
|
protected $spacer = false;
|
|
|
|
protected $verify = false;
|
|
|
|
|
|
|
|
# Component size
|
|
|
|
protected $size = 0;
|
|
|
|
# Value max length
|
|
|
|
protected $maxlength = 0;
|
|
|
|
# Text Area sizings
|
|
|
|
protected $cols = 0;
|
|
|
|
protected $rows = 0;
|
|
|
|
|
|
|
|
# Public for sorting
|
|
|
|
public $page = 1;
|
|
|
|
public $order = 255;
|
|
|
|
public $ordersort = 255;
|
|
|
|
|
|
|
|
# Schema Aliases for this attribute (stored in lowercase)
|
|
|
|
protected $aliases = array();
|
|
|
|
|
|
|
|
# Configuration for automatically generated values
|
|
|
|
protected $autovalue = array();
|
|
|
|
protected $postvalue = array();
|
2021-12-08 23:26:12 +11:00
|
|
|
*/
|
2009-07-01 16:09:17 +10:00
|
|
|
|
2023-02-19 20:25:32 +11:00
|
|
|
public function __construct(string $name,array $values)
|
|
|
|
{
|
2021-12-08 23:26:12 +11:00
|
|
|
$this->name = $name;
|
2023-02-19 20:25:32 +11:00
|
|
|
$this->values = collect($values);
|
2023-03-27 16:19:37 +11:00
|
|
|
$this->lang_tags = collect();
|
2024-01-20 10:36:30 +11:00
|
|
|
$this->oldValues = collect($values);
|
2009-06-30 20:46:00 +10:00
|
|
|
|
2025-02-21 22:56:15 +11:00
|
|
|
$this->schema = (new Server)
|
|
|
|
->schema('attributetypes',$name);
|
2023-03-02 14:41:38 +11:00
|
|
|
|
2021-12-08 23:26:12 +11:00
|
|
|
/*
|
2009-07-01 16:09:17 +10:00
|
|
|
# Should this attribute be hidden
|
|
|
|
if ($server->isAttrHidden($this->name))
|
|
|
|
$this->forcehide = true;
|
2009-06-30 20:46:00 +10:00
|
|
|
|
2009-07-01 16:09:17 +10:00
|
|
|
# Should this attribute value be read only
|
|
|
|
if ($server->isAttrReadOnly($this->name))
|
|
|
|
$this->readonly = true;
|
2009-06-30 20:46:00 +10:00
|
|
|
|
2009-07-01 16:09:17 +10:00
|
|
|
# Should this attribute value be unique
|
|
|
|
if ($server->isAttrUnique($this->name))
|
|
|
|
$this->unique = true;
|
2021-12-08 23:26:12 +11:00
|
|
|
*/
|
|
|
|
}
|
|
|
|
|
2023-03-02 09:54:30 +11:00
|
|
|
public function __get(string $key): mixed
|
|
|
|
{
|
2023-03-02 14:41:38 +11:00
|
|
|
return match ($key) {
|
2023-09-02 20:28:04 +10:00
|
|
|
// List all the attributes
|
|
|
|
'attributes' => $this->attributes(),
|
2023-03-02 14:41:38 +11:00
|
|
|
// Can this attribute have more values
|
2023-03-02 14:55:06 +11:00
|
|
|
'can_addvalues' => $this->schema && (! $this->schema->is_single_value) && ((! $this->max_values_count) || ($this->values->count() < $this->max_values_count)),
|
2023-03-02 14:41:38 +11:00
|
|
|
// Schema attribute description
|
|
|
|
'description' => $this->schema ? $this->schema->{$key} : NULL,
|
|
|
|
// Attribute hints
|
|
|
|
'hints' => $this->hints(),
|
2023-04-12 08:17:57 +10:00
|
|
|
// Can this attribute be edited
|
|
|
|
'is_editable' => $this->schema ? $this->schema->{$key} : NULL,
|
2023-03-02 14:41:38 +11:00
|
|
|
// Is this an internal attribute
|
|
|
|
'is_internal' => isset($this->{$key}) && $this->{$key},
|
2023-03-31 15:55:08 +11:00
|
|
|
// Is this attribute the RDN
|
|
|
|
'is_rdn' => $this->is_rdn,
|
2023-03-02 14:41:38 +11:00
|
|
|
// We prefer the name as per the schema if it exists
|
|
|
|
'name' => $this->schema ? $this->schema->{$key} : $this->{$key},
|
|
|
|
// Attribute name in lower case
|
|
|
|
'name_lc' => strtolower($this->name),
|
2024-01-20 10:36:30 +11:00
|
|
|
// Old Values
|
|
|
|
'old_values' => $this->oldValues,
|
2023-03-31 15:55:08 +11:00
|
|
|
// Attribute values
|
|
|
|
'values' => $this->values,
|
2025-02-04 08:55:10 +11:00
|
|
|
// Required by Object Classes
|
2025-02-23 18:14:41 +11:00
|
|
|
'required_by' => $this->schema?->required_by_object_classes ?: collect(),
|
2025-02-04 08:55:10 +11:00
|
|
|
// Used in Object Classes
|
2025-02-23 18:14:41 +11:00
|
|
|
'used_in' => $this->schema?->used_in_object_classes ?: collect(),
|
2023-03-02 14:41:38 +11:00
|
|
|
|
|
|
|
default => throw new \Exception('Unknown key:' . $key),
|
|
|
|
};
|
2023-03-02 09:54:30 +11:00
|
|
|
}
|
|
|
|
|
2024-01-20 10:36:30 +11:00
|
|
|
public function __set(string $key,mixed $values): void
|
|
|
|
{
|
|
|
|
switch ($key) {
|
|
|
|
case 'value':
|
|
|
|
$this->values = collect($values);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-09-02 20:28:04 +10:00
|
|
|
public function __toString(): string
|
|
|
|
{
|
2024-01-20 10:36:30 +11:00
|
|
|
return $this->name;
|
2023-09-02 20:28:04 +10:00
|
|
|
}
|
|
|
|
|
2024-01-11 08:59:40 +11:00
|
|
|
public function addValue(string $value): void
|
|
|
|
{
|
|
|
|
$this->values->push($value);
|
|
|
|
}
|
|
|
|
|
2025-01-17 17:00:36 +11:00
|
|
|
public function current(): mixed
|
|
|
|
{
|
|
|
|
return $this->values->get($this->counter);
|
|
|
|
}
|
|
|
|
|
|
|
|
public function next(): void
|
|
|
|
{
|
|
|
|
$this->counter++;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function key(): mixed
|
|
|
|
{
|
|
|
|
return $this->counter;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function valid(): bool
|
|
|
|
{
|
|
|
|
return $this->values->has($this->counter);
|
|
|
|
}
|
|
|
|
|
|
|
|
public function rewind(): void
|
|
|
|
{
|
|
|
|
$this->counter = 0;
|
|
|
|
}
|
|
|
|
|
2024-01-09 17:44:50 +11:00
|
|
|
public function count(): int
|
|
|
|
{
|
|
|
|
return $this->values->count();
|
|
|
|
}
|
|
|
|
|
|
|
|
public function offsetExists(mixed $offset): bool
|
|
|
|
{
|
2025-01-17 17:00:36 +11:00
|
|
|
return ! is_null($this->values->has($offset));
|
2024-01-09 17:44:50 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
public function offsetGet(mixed $offset): mixed
|
|
|
|
{
|
|
|
|
return $this->values->get($offset);
|
|
|
|
}
|
|
|
|
|
|
|
|
public function offsetSet(mixed $offset, mixed $value): void
|
|
|
|
{
|
|
|
|
// We cannot set new values using array syntax
|
|
|
|
}
|
|
|
|
|
|
|
|
public function offsetUnset(mixed $offset): void
|
|
|
|
{
|
|
|
|
// We cannot clear values using array syntax
|
|
|
|
}
|
|
|
|
|
2023-03-02 14:41:38 +11:00
|
|
|
/**
|
|
|
|
* Return the hints about this attribute, ie: RDN, Required, etc
|
|
|
|
*
|
|
|
|
* @return array
|
|
|
|
*/
|
|
|
|
public function hints(): array
|
|
|
|
{
|
|
|
|
$result = collect();
|
|
|
|
|
|
|
|
// Is this Attribute an RDN
|
|
|
|
if ($this->is_rdn)
|
|
|
|
$result->put(__('rdn'),__('This attribute is required for the RDN'));
|
|
|
|
|
|
|
|
// If this attribute name is an alias for the schema attribute name
|
|
|
|
// @todo
|
|
|
|
|
|
|
|
// objectClasses requiring this attribute
|
|
|
|
// 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(',')));
|
|
|
|
|
2023-03-27 16:19:37 +11:00
|
|
|
// This attribute has language tags
|
|
|
|
if ($this->lang_tags->count())
|
|
|
|
$result->put(__('language tags'),sprintf('%s: %d',__('This Attribute has Language Tags'),$this->lang_tags->count()));
|
|
|
|
|
2023-03-02 14:41:38 +11:00
|
|
|
return $result->toArray();
|
|
|
|
}
|
|
|
|
|
2024-01-09 17:44:50 +11:00
|
|
|
/**
|
|
|
|
* Determine if this attribute has changes
|
|
|
|
*
|
|
|
|
* @return bool
|
|
|
|
*/
|
|
|
|
public function isDirty(): bool
|
|
|
|
{
|
2025-01-16 10:33:45 +11:00
|
|
|
return ($this->oldValues->count() !== $this->values->count())
|
|
|
|
|| ($this->values->diff($this->oldValues)->count() !== 0);
|
2024-01-09 17:44:50 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
public function oldValues(array $array): void
|
|
|
|
{
|
|
|
|
$this->oldValues = collect($array);
|
|
|
|
}
|
|
|
|
|
2023-04-02 22:07:15 +10:00
|
|
|
/**
|
|
|
|
* Display the attribute value
|
|
|
|
*
|
2025-01-15 23:29:53 +11:00
|
|
|
* @param bool $edit Render an edit form
|
|
|
|
* @param bool $old Use old value
|
|
|
|
* @param bool $new Enable adding values
|
2023-04-02 22:07:15 +10:00
|
|
|
* @return View
|
|
|
|
*/
|
2024-01-20 10:36:30 +11:00
|
|
|
public function render(bool $edit=FALSE,bool $old=FALSE,bool $new=FALSE): View
|
2023-03-31 15:55:08 +11:00
|
|
|
{
|
|
|
|
return view('components.attribute')
|
2024-01-20 10:36:30 +11:00
|
|
|
->with('o',$this)
|
2023-03-31 15:55:08 +11:00
|
|
|
->with('edit',$edit)
|
2024-01-20 10:36:30 +11:00
|
|
|
->with('old',$old)
|
|
|
|
->with('new',$new);
|
2023-03-31 15:55:08 +11:00
|
|
|
}
|
|
|
|
|
2025-01-16 12:47:55 +11:00
|
|
|
public function render_item_old(int $key): ?string
|
|
|
|
{
|
|
|
|
return Arr::get($this->old_values,$key);
|
|
|
|
}
|
|
|
|
|
|
|
|
public function render_item_new(int $key): ?string
|
|
|
|
{
|
|
|
|
return Arr::get($this->values,$key);
|
|
|
|
}
|
|
|
|
|
2023-03-27 16:19:37 +11:00
|
|
|
/**
|
|
|
|
* If this attribute has RFC3866 Language Tags, this will enable those values to be captured
|
|
|
|
*
|
|
|
|
* @param string $tag
|
|
|
|
* @param array $value
|
|
|
|
* @return void
|
|
|
|
*/
|
|
|
|
public function setLangTag(string $tag,array $value): void
|
|
|
|
{
|
|
|
|
$this->lang_tags->put($tag,$value);
|
|
|
|
}
|
|
|
|
|
2023-03-02 14:41:38 +11:00
|
|
|
public function setRDN(): void
|
|
|
|
{
|
|
|
|
$this->is_rdn = TRUE;
|
|
|
|
}
|
2021-12-08 23:26:12 +11:00
|
|
|
}
|