HierarchyCollection::replaceBy()   A
last analyzed

Complexity

Conditions 5
Paths 5

Size

Total Lines 14
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 5
eloc 10
nc 5
nop 3
dl 0
loc 14
rs 9.6111
c 1
b 0
f 0
1
<?php
2
3
namespace Blackmine\Collection;
4
5
use Blackmine\Model\ParentableInterface;
6
use Blackmine\Tool\Inflect;
7
8
class HierarchyCollection extends IdentityCollection
9
{
10
    protected array $orphans = [];
11
12
    public function __construct(array $elements = [], protected string $parent_field = "id")
13
    {
14
        parent::__construct($elements);
15
    }
16
17
    public function findBy(string $field, mixed $value, bool $recursive = false): mixed
18
    {
19
        foreach ($this->getElements() as $identity) {
20
            $getter = "get" . ucfirst(Inflect::camelize($field));
21
            if ($identity->$getter() === $value) {
22
                return $identity;
23
            }
24
25
            if ($recursive) {
26
                $children = $identity->getChildren();
27
                if ($children instanceof self) {
28
                    return $children->findBy($field, $value, $recursive);
29
                }
30
            }
31
        }
32
33
        return null;
34
    }
35
36
    public function replaceBy(string $field, ParentableInterface $value, bool $recursive = false): void
37
    {
38
        foreach ($this->getElements() as $element) {
39
            $getter = "get" . ucfirst(Inflect::camelize($field));
40
            if ($element->$getter() === $value->$getter()) {
41
                $idx = $this->indexOf($element);
42
                $this->set($idx, $value);
43
                return;
44
            }
45
46
            if ($recursive) {
47
                $children = $element->getChildren();
48
                if ($children instanceof self) {
49
                    $children->replaceBy($field, $value, $recursive);
50
                }
51
            }
52
        }
53
    }
54
55
    /**
56
     * @param ParentableInterface $element
57
     */
58
    public function add($element)
59
    {
60
        $has_parent = $element->getParent();
61
        if ($has_parent) {
62
            $getter = "get" . ucfirst(Inflect::camelize($this->parent_field));
63
            $parent = $this->findBy($this->parent_field, $element->getParent()?->$getter(), true);
64
            if ($parent) {
65
                $parent->addChild($element);
66
                $this->replaceBy($this->parent_field, $parent, true);
67
            } else {
68
                $this->orphans[$element->$getter()] = $element;
69
            }
70
        } else {
71
            parent::add($element);
72
            if (!empty($this->orphans)) {
73
                foreach ($this->orphans as $id => $orphan) {
74
                    $this->add($orphan);
75
                    unset($this->orphans[$id]);
76
                }
77
            }
78
        }
79
    }
80
81
    public function addDirect(ParentableInterface $element): void
82
    {
83
        parent::add($element);
84
    }
85
}
86