49 خطوط
1.5 KiB
PHP
49 خطوط
1.5 KiB
PHP
<?php
|
|
|
|
namespace App\Modules\Taxonomy\Application;
|
|
|
|
use App\Modules\Taxonomy\Domain\TaxonomyNode;
|
|
use Illuminate\Validation\ValidationException;
|
|
|
|
final class TaxonomyHierarchy
|
|
{
|
|
public function assertValidParent(string $organizationId, string $taxonomyTypeId, ?string $parentId, ?string $movingNodeId = null): void
|
|
{
|
|
if ($parentId === null) {
|
|
return;
|
|
}
|
|
|
|
if ($parentId === $movingNodeId) {
|
|
$this->invalidParent();
|
|
}
|
|
|
|
$parent = TaxonomyNode::query()
|
|
->where('organization_id', $organizationId)
|
|
->where('taxonomy_type_id', $taxonomyTypeId)
|
|
->find($parentId);
|
|
|
|
if (! $parent) {
|
|
$this->invalidParent('The selected parent does not belong to this taxonomy.');
|
|
}
|
|
|
|
$visited = [];
|
|
$cursor = $parent;
|
|
|
|
while ($cursor !== null) {
|
|
if (isset($visited[$cursor->getKey()]) || $cursor->getKey() === $movingNodeId) {
|
|
$this->invalidParent('The selected parent would create a circular hierarchy.');
|
|
}
|
|
|
|
$visited[$cursor->getKey()] = true;
|
|
$cursor = $cursor->parent_id
|
|
? TaxonomyNode::query()->where('organization_id', $organizationId)->find($cursor->parent_id)
|
|
: null;
|
|
}
|
|
}
|
|
|
|
private function invalidParent(string $message = 'A taxonomy node cannot be its own parent.'): never
|
|
{
|
|
throw ValidationException::withMessages(['parentId' => [$message]]);
|
|
}
|
|
}
|