nur-sery/nur_src/ldap/LdapAttr.php

226 lines
6.5 KiB
PHP

<?php
namespace nur\ldap;
use ArrayAccess;
use Countable;
use Iterator;
use nur\A;
use nur\b\coll\TIterableArray;
use nur\ldap\syntaxes\AbstractSyntax;
use nur\str;
class LdapAttr implements ArrayAccess, Countable, Iterator {
use TIterableArray;
const MONOVALUED = 1, BINARY = 2, ORDERED = 4, NOT_HUMAN_READABLE = 8;
function __construct(string $name, ?array &$values, ?AbstractSyntax $syntax, ?int $flags) {
$this->name = $name;
$this->syntax = $syntax;
$this->flags = $flags;
$this->reset($values);
}
/** @var string */
protected $name;
function name(): string {
return $this->name;
}
/** @var ?array */
protected $data;
function reset(?array &$values): self {
$this->data =& $values;
return $this;
}
/** @var AbstractSyntax */
protected $syntax;
/** @var int */
protected $flags;
function isMonovalued(): bool {
return $this->flags !== null && $this->flags & self::MONOVALUED != 0;
}
function isBinary(): bool {
return $this->flags !== null && $this->flags & self::BINARY != 0;
}
function isOrdered(): bool {
return $this->flags !== null && $this->flags & self::ORDERED != 0;
}
function isNotHumanReadable(): bool {
return $this->flags !== null && $this->flags & self::NOT_HUMAN_READABLE != 0;
}
protected function fromLdap($value) {
$syntax = $this->syntax;
if ($syntax !== null) {
if ($this->isMonovalued()) $value = $syntax->fromMonovaluedLdap($value);
else $value = $syntax->fromMultivaluedLdap($value);
}
return $value;
}
protected function fromPhp($value): ?iterable {
$syntax = $this->syntax;
if ($syntax !== null) $value = $syntax->fromPhp($value);
else A::ensure_narray($value);
return $value;
}
/** retourner un tableau si multivalué, une valeur scalaire si monovalué */
function get($index=null) {
$value = $this->fromLdap($this->data);
if ($index !== null && is_array($value)) {
$value = array_key_exists($index, $value)? $value[$index]: null;
}
return $value;
}
/**
* retourner toutes les valeurs
*
* @param string $checkPrefixDel ne retourner que les valeurs qui commencent
* par ce préfixe ET enlever le préfixe
*/
function all(?string $checkPrefixDel=null): ?array {
if ($this->syntax === null) $values = $this->data;
else $values = $this->syntax->fromMultivaluedLdap($this->data);
if ($checkPrefixDel !== null) {
$filtered = [];
foreach ($values as $value) {
if (str::del_prefix($value, $checkPrefixDel)) {
$filtered[] = $value;
}
}
$values = $filtered;
}
return $values;
}
/** retourner la première valeur */
function first(?string $checkPrefixDel=null) {
return A::first($this->all($checkPrefixDel));
}
function set($values, bool $unlessNn=false): self {
if ($values instanceof LdapAttr) $values = $values->array();
if (!$unlessNn || $this->data === null) {
$this->data = $this->fromPhp($values);
}
return $this;
}
protected static function in_array(string $needle, array $haystack, bool $strict, ?int &$index=null): bool {
if (!$strict) $needle = strtolower($needle);
foreach ($haystack as $index => $hay) {
if ($strict && $hay === $needle) return true;
if (!$strict && strtolower($hay) == $needle) return true;
}
return false;
}
/** vérifier si la valeur spécifiée figure dans l'attribut */
function contains($value, bool $strict=false): bool {
$value = A::first($this->fromPhp($value));
if ($value === null || $this->data === null) return false;
return self::in_array($value, $this->data, $strict);
}
/**
* l'unicité est calculée ainsi:
* - en mode strict, ce doit être une égalité parfaite
* - en mode non strict, la comparaison est insensible à la casse
* XXX à terme, implémenter la comparaison en fonction de la syntaxe
*/
function add($value, bool $unique=true, bool $strict=false): self {
$value = A::first($this->fromPhp($value));
if ($value !== null) {
if (!$unique || $this->data === null ||
!self::in_array($value, $this->data, $strict)) {
$this->data[] = $value;
}
}
return $this;
}
function addAll(?iterable $values): self {
if ($values !== null) {
foreach ($values as $value) {
$this->add($value);
}
}
return $this;
}
function del($value, int $maxCount=-1, bool $strict=false): self {
if ($value !== null && $this->data !== null) {
$value = A::first($this->fromPhp($value));
$rekey = false;
while ($maxCount != 0) {
if (!self::in_array($value, $this->data, $strict, $index)) break;
unset($this->data[$index]);
$rekey = true;
if ($maxCount > 0) $maxCount--;
}
if ($rekey) $this->data = array_values($this->data);
}
return $this;
}
function ins(int $index, $value): self {
$value = A::first($this->fromPhp($value));
if ($value !== null) {
A::insert($this->data, $index, $value);
}
return $this;
}
function unset(int $index): self {
if ($this->data !== null) {
$count = count($this->array());
if ($count > 0 && $index < 0) {
while ($index < 0) $index += $count;
}
unset($this->data[$index]);
$this->data = array_values($this->data);
}
return $this;
}
function key() { return $this->_key(); }
function current() {
$current = $this->_current();
$syntax = $this->syntax;
if ($syntax !== null) $current = $syntax->ldap2php($current);
return $current;
}
#############################################################################
# données au format LDAP
function __toString() {
return implode("\n", $this->data);
}
/** retourner les données au format LDAP */
function &array(): ?array { return $this->data; }
function count(): int { return count($this->data); }
function keys(): array { return array_keys($this->data); }
function offsetExists($key) {
return $this->data !== null && array_key_exists($key, $this->data);
}
function offsetGet($key) { return array_key_exists($key, $this->data)? $this->data[$key]: null; }
function offsetSet($key, $value) { $this->data[$key] = $value; }
function offsetUnset($key) { unset($this->data[$key]); }
function __isset($key) { return $this->offsetExists($key); }
function __get($key) { return $this->offsetGet($key); }
function __set($key, $value) { $this->offsetSet($key, $value); }
function __unset($key) { $this->offsetUnset($key); }
}