Completed
Push — master ( 183075...9c0b34 )
by Peter
07:30
created

SimpleTreeTrait::initTree()   B

Complexity

Conditions 5
Paths 2

Size

Total Lines 45
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 14.6179

Importance

Changes 0
Metric Value
dl 0
loc 45
ccs 3
cts 11
cp 0.2727
rs 8.439
c 0
b 0
f 0
cc 5
eloc 16
nc 2
nop 0
crap 14.6179
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 1
	public function initTree()
54
	{
55 1
		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
					/**
83
					 * TODO Similar mechanism should be used to detect orphaned tree items.
84
					 * TODO Use exists here instead of raw finder.
85
					 * TODO investigate why rawfinder was used here.
86
					 */
87
					if (!(new RawFinder($this))->findByPk(new MongoId($this->parentId)))
88
					{
89
						$this->parentId = null;
90
						(new EntityManager($this))->update(['parentId']);
91
					}
92
				}
93
			};
94
			$onAfterRestore->bindTo($this);
95
			Event::on($this, TrashInterface::EventAfterRestore, $onAfterRestore);
96
		}
97 1
	}
98
99
	/**
100
	 * Move to a new parent
101
	 * @param string|MongoId $parentId
102
	 * @param string[]|MongoId[] $order
103
	 * @Ignored
104
	 */
105
	public function moveTo($parentId, $order = [])
106
	{
107
		$this->parentId = $parentId;
108
		(new EntityManager($this))->update(['parentId']);
109
110
		$i = 0;
111
112
		$node = new static;
113
		$em = new EntityManager($node);
114
		foreach ((array) $order as $id)
115
		{
116
			assert(property_exists($node, '_id'), sprintf('Property `_id` is required to use with `%s`', SimpleTreeTrait::class));
117
			$node->_id = $id;
118
			$node->order = $i++;
119
			$em->update(['order']);
120
		}
121
	}
122
123
}
124