Skip to content

Commit

Permalink
Added new DistinguishedName attribute and model methods
Browse files Browse the repository at this point in the history
- DistinguishedName attribute class added for easy DN operations
- isDescendantOf and isAncenstorOf are now recursive
- Added isChildOf and isParentOf to Model
- Closes #127
  • Loading branch information
stevebauman committed May 2, 2020
1 parent 43699fc commit 1d7109d
Show file tree
Hide file tree
Showing 4 changed files with 473 additions and 26 deletions.
214 changes: 214 additions & 0 deletions src/Models/Attributes/DistinguishedName.php
@@ -0,0 +1,214 @@
<?php

namespace LdapRecord\Models\Attributes;

use LdapRecord\Utilities;

class DistinguishedName
{
/**
* The underlying raw value.
*
* @var string|null
*/
protected $value;

/**
* Constructor.
*
* @param string|null $value
*/
public function __construct($value)
{
$this->value = $value;
}

/**
* Get the underlying value.
*
* @return string|null
*/
public function get()
{
return $this->value;
}

/**
* Set the underlying value.
*
* @param string|null $value
*
* @return $this
*/
public function set($value)
{
$this->value = $value;

return $this;
}

/**
* Get the Distinguished Name values without attributes.
*
* @return array
*/
public function values()
{
return Utilities::explodeDn($this->value, $withoutAttributes = true) ?: [];
}

/**
* Get the Distinguished Name components with attributes.
*
* @return array
*/
public function components()
{
return Utilities::explodeDn($this->value, $withoutAttributes = false) ?: [];
}

/**
* Get the name value.
*
* @return string|null
*/
public function name()
{
$values = $this->values();

return reset($values) ?: null;
}

/**
* Get the relative Distinguished name.
*
* @return string|null
*/
public function relative()
{
$components = $this->components();

return reset($components) ?: null;
}

/**
* Get the parent Distinguished name.
*
* @return string|null
*/
public function parent()
{
$components = $this->components();

array_shift($components);

return implode(',', $components) ?: null;
}

/**
* Determine if the current Distinguished Name is a parent of the given child.
*
* @param DistinguishedName $child
*
* @return bool
*/
public function isParentOf(DistinguishedName $child)
{
return $child->isChildOf($this);
}

/**
* Determine if the current Distinguished Name is a child of the given parent.
*
* @param DistinguishedName $parent
*
* @return bool
*/
public function isChildOf(DistinguishedName $parent)
{
if (
empty($components = $this->components()) ||
empty($parentComponents = $parent->components())
) {
return false;
}

array_shift($components);

return $this->compare($components, $parentComponents);
}

/**
* Determine if the current Distinguished Name is an ancestor of the descendant.
*
* @param DistinguishedName $descendant
*
* @return bool
*/
public function isAncestorOf(DistinguishedName $descendant)
{
return $descendant->isDescendantOf($this);
}

/**
* Determine if the current Distinguished Name is a descendant of the ancestor.
*
* @param DistinguishedName $ancestor
*
* @return bool
*/
public function isDescendantOf(DistinguishedName $ancestor)
{
if (
empty($components = $this->components()) ||
empty($ancestorComponents = $ancestor->components())
) {
return false;
}

if (! $length = count($components) - count($ancestorComponents)) {
return false;
}

array_splice($components, $offset = 0, $length);

return $this->compare($components, $ancestorComponents);
}

/**
* Compare whether the two Distinguished Name values are equal.
*
* @param array $values
* @param array $other
*
* @return bool
*/
protected function compare(array $values, array $other)
{
return $this->recase($values) == $this->recase($other);
}

/**
* Recase the array values.
*
* @param array $values
*
* @return array
*/
protected function recase(array $values)
{
return array_map([$this, 'normalize'], $values);
}

/**
* Normalize the string value.
*
* @param string $value
*
* @return string
*/
protected function normalize($value)
{
return strtolower($value);
}
}
60 changes: 36 additions & 24 deletions src/Models/Model.php
Expand Up @@ -5,7 +5,6 @@
use ArrayAccess;
use JsonSerializable;
use LdapRecord\Container;
use LdapRecord\Utilities;
use LdapRecord\Connection;
use InvalidArgumentException;
use LdapRecord\EscapesValues;
Expand All @@ -15,6 +14,7 @@
use LdapRecord\Models\Events\Renamed;
use LdapRecord\Models\Attributes\Guid;
use LdapRecord\Models\Events\Renaming;
use LdapRecord\Models\Attributes\DistinguishedName;

/** @mixin Builder */
abstract class Model implements ArrayAccess, JsonSerializable
Expand Down Expand Up @@ -745,11 +745,7 @@ public function getAnrAttributes()
*/
public function getName($dn = null)
{
if ($rdn = $this->getRdn($dn)) {
list($attribute, $name) = explode('=', $rdn);

return $name;
}
return (new DistinguishedName($dn ?? $this->dn))->name();
}

/**
Expand All @@ -761,9 +757,7 @@ public function getName($dn = null)
*/
public function getRdn($dn = null)
{
if ($parts = Utilities::explodeDn($dn ?? $this->dn, false)) {
return reset($parts) ?? null;
}
return (new DistinguishedName($dn ?? $this->dn))->relative();
}

/**
Expand All @@ -775,11 +769,7 @@ public function getRdn($dn = null)
*/
public function getParentDn($dn = null)
{
if ($parts = Utilities::explodeDn($dn ?? $this->dn, false)) {
array_shift($parts);

return implode(',', $parts);
}
return (new DistinguishedName($dn ?? $this->dn))->parent();
}

/**
Expand Down Expand Up @@ -811,6 +801,34 @@ public function getConvertedGuid()
/**
* Determine if the current model is a direct descendant of the given.
*
* @param static|string $parent
*
* @return bool
*/
public function isChildOf($parent)
{
return (new DistinguishedName($this->getDn()))->isChildOf(
new DistinguishedName((string) $parent)
);
}

/**
* Determine if the current model is a direct ascendant of the given.
*
* @param static|string $child
*
* @return bool
*/
public function isParentOf($child)
{
return (new DistinguishedName($this->getDn()))->isParentOf(
new DistinguishedName((string) $child)
);
}

/**
* Determine if the current model is a descendant of the given.
*
* @param static|string $model
*
* @return bool
Expand All @@ -821,7 +839,7 @@ public function isDescendantOf($model)
}

/**
* Determine if the current model is a direct ancestor of the given.
* Determine if the current model is a ancestor of the given.
*
* @param static|string $model
*
Expand All @@ -842,15 +860,9 @@ public function isAncestorOf($model)
*/
protected function dnIsInside($dn, $parentDn)
{
if (!$dn) {
return false;
}

if ($dn = $this->getParentDn($dn)) {
return strtolower($dn) == strtolower($parentDn);
}

return false;
return (new DistinguishedName((string) $dn))->isDescendantOf(
new DistinguishedName($parentDn)
);
}

/**
Expand Down

0 comments on commit 1d7109d

Please sign in to comment.