Completed
Push — master ( cff413...7f9d4c )
by Peter
07:00
created

SimpleTreeTrait::initTree()   B

Complexity

Conditions 5
Paths 2

Size

Total Lines 47

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 18.9614

Importance

Changes 0
Metric Value
dl 0
loc 47
ccs 3
cts 17
cp 0.1765
rs 8.8452
c 0
b 0
f 0
cc 5
nc 2
nop 0
crap 18.9614
1
<?php
2
3
/**
4
 * This software package is licensed under AGPL or Commercial license.
5
 *
6
 * @package maslosoft/mangan
7
 * @licence AGPL or Commercial
8
 * @copyright Copyright (c) Piotr Masełkowski <[email protected]>
9
 * @copyright Copyright (c) Maslosoft
10
 * @copyright Copyright (c) Others as mentioned in code
11
 * @link https://maslosoft.com/mangan/
12
 */
13
14
namespace Maslosoft\Mangan\Traits\Model;
15
16
use Maslosoft\Addendum\Interfaces\AnnotatedInterface;
17
use Maslosoft\Mangan\EntityManager;
18
use Maslosoft\Mangan\Events\Event;
19
use Maslosoft\Mangan\Events\ModelEvent;
20
use Maslosoft\Mangan\Helpers\RawFinder;
21
use Maslosoft\Mangan\Interfaces\SimpleTreeInterface;
22
use Maslosoft\Mangan\Interfaces\TrashInterface;
23
use MongoId;
24
25
/**
26
 * Related Tree Trait
27
 * @see SimpleTreeInterface
28
 * @author Piotr
29
 */
30
trait SimpleTreeTrait
31
{
32
33
	use WithParentTrait;
34
35
	/**
36
	 * @RelatedArray('join' = {'_id' = 'parentId'}, 'updatable' = true)
37
	 * @RelatedOrdering('order')
38
	 * @var AnnotatedInterface[]
39
	 */
40
	public $children = [];
41
42
	/**
43
	 * @Label('Manual sort')
44
	 * @var int
45
	 */
46
	public $order = 0;
47
48
	/**
49
	 * NOTE: This must be called by class using this trait
50
	 * TODO Move event initializer to some other global event init, as events now handle traits too.
51
	 * @Ignored
52
	 */
53 7
	public function initTree()
54
	{
55 7
		if ($this instanceof TrashInterface)
56
		{
57
			// Trash related events
58
			$onBeforeTrash = function(ModelEvent $event)
59
			{
60
				$event->isValid = true;
61
			};
62
			Event::on($this, TrashInterface::EventBeforeTrash, $onBeforeTrash);
63
64
65
			$onAfterTrash = function(ModelEvent $event)
66
			{
67
				foreach ($event->sender->children as $child)
68
				{
69
					$child->trash();
70
				}
71
			};
72
73
			Event::on($this, TrashInterface::EventAfterTrash, $onAfterTrash);
74
75
76
			$onAfterRestore = function(ModelEvent $event)
77
			{
78
				// Root nodes does not have parentId
79
				if ($this->parentId)
80
				{
81
					// Put node to root if parent does not exists
82
					// RawFinder is used for performance reasons here
83
					// and to skip filters
84
					/**
85
					 * TODO Similar mechanism should be used to detect orphaned tree items.
86
					 * TODO Use exists here instead of raw finder.
87
					 *
88
					 */
89
					if (!(new RawFinder($this))->findByPk(new MongoId($this->parentId)))
90
					{
91
						$this->parentId = null;
92
						(new EntityManager($this))->update(['parentId']);
93
					}
94
				}
95
			};
96
			$onAfterRestore->bindTo($this);
97
			Event::on($this, TrashInterface::EventAfterRestore, $onAfterRestore);
98
		}
99 7
	}
100
101
	/**
102
	 * Move to a new parent
103
	 * @param string|MongoId $parentId
104
	 * @param string[]|MongoId[] $order
105
	 * @Ignored
106
	 */
107
	public function moveTo($parentId, $order = [])
108
	{
109
		$this->parentId = $parentId;
110
		(new EntityManager($this))->update(['parentId']);
111
112
		$i = 0;
113
114
		$node = new static;
115
		$em = new EntityManager($node);
116
		foreach ((array) $order as $id)
117
		{
118
			assert(property_exists($node, '_id'), sprintf('Property `_id` is required to use with `%s`', SimpleTreeTrait::class));
119
			$node->_id = $id;
120
			$node->order = $i++;
121
			$em->update(['order']);
122
		}
123
	}
124
125
}
126