Completed
Push — master ( 898d30...0483c4 )
by Peter
21:25
created

SimpleTreeTrait::moveTo()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 16
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 4
Bugs 0 Features 0
Metric Value
c 4
b 0
f 0
dl 0
loc 16
ccs 0
cts 14
cp 0
rs 9.4286
cc 2
eloc 10
nc 2
nop 2
crap 6
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 http://maslosoft.com/mangan/
12
 */
13
14
namespace Maslosoft\Mangan\Traits\Model;
15
16
use Maslosoft\Addendum\Interfaces\AnnotatedInterface;
17
use Maslosoft\Mangan\Criteria;
18
use Maslosoft\Mangan\EntityManager;
19
use Maslosoft\Mangan\Events\Event;
20
use Maslosoft\Mangan\Events\ModelEvent;
21
use Maslosoft\Mangan\Finder;
22
use Maslosoft\Mangan\Helpers\RawFinder;
23
use Maslosoft\Mangan\Interfaces\FinderInterface;
24
use Maslosoft\Mangan\Interfaces\SimpleTreeInterface;
25
use Maslosoft\Mangan\Interfaces\TrashInterface;
26
use MongoId;
27
28
/**
29
 * TreeTrait
30
 * TODO Simple tree needs serious refactor
31
 * @see SimpleTreeInterface
32
 * @author Piotr
33
 */
34
trait SimpleTreeTrait
35
{
36
37
	use WithParentTrait;
38
39
	/**
40
	 * @DbRefArray
41
	 * @RelatedArray(parentId)
42
	 * @var AnnotatedInterface[]
43
	 */
44
	public $children = [];
45
46
	/**
47
	 * @Label('Manual sort')
48
	 * @var int
49
	 */
50
	public $order = 1000000;
51
52
	/**
53
	 * NOTE: This must be called by class using this trait
54
	 * @Ignored
55
	 */
56
	public function initTree()
57
	{
58
		$loadItems = function()
59
		{
60
			if (empty($this->children) && $this->parentId !== null)
61
			{
62
				$criteria = new Criteria();
63
				$criteria->parentId = $this->_id;
64
				$this->children = (new Finder($this))->withCursor(false)->findAll($criteria);
65
			}
66
		};
67
		$loadItems->bindTo($this);
68
69
		Event::on($this, FinderInterface::EventAfterFind, $loadItems);
70
71
72
		if ($this instanceof TrashInterface)
73
		{
74
			// Trash related events
75
			$onBeforeTrash = function(ModelEvent $event)
76
			{
77
				$event->handled = true;
78
			};
79
			$onBeforeTrash->bindTo($this);
80
			Event::on($this, TrashInterface::EventBeforeTrash, $onBeforeTrash);
81
82
83
			$onAfterTrash = function(ModelEvent $event)
84
			{
85
				foreach ($event->sender->children as $child)
86
				{
87
					$child->trash();
88
				}
89
			};
90
			$onAfterTrash->bindTo($this);
91
			Event::on($this, TrashInterface::EventAfterTrash, $onAfterTrash);
92
93
94
			$onAfterRestore = function(ModelEvent $event)
95
			{
96
				// Root nodes does not have parentId
97
				if ($this->parentId)
98
				{
99
					// Put node to root if parent does not exists
100
					/**
101
					 * TODO Use exists here instead of raw finder.
102
					 * TODO investigate why rawfinder was used here.
103
					 */
104
					if (!(new RawFinder($this))->findByPk(new MongoId($this->parentId)))
105
					{
106
						$this->parentId = null;
107
						(new EntityManager($this))->update(['parentId']);
108
					}
109
				}
110
			};
111
			$onAfterRestore->bindTo($this);
112
			Event::on($this, TrashInterface::EventAfterRestore, $onAfterRestore);
113
		}
114
	}
115
116
	/**
117
	 * Move to a new parent
118
	 * @param string|MongoId $parentId
119
	 * @param string[]|MongoId[] $order
120
	 * @Ignored
121
	 */
122
	public function moveTo($parentId, $order = [])
123
	{
124
		$this->parentId = $parentId;
125
		(new EntityManager($this))->update(['parentId']);
126
127
		$i = 0;
128
129
		$node = new static;
130
		$em = new EntityManager($node);
131
		foreach ((array) $order as $id)
132
		{
133
			$node->_id = $id;
134
			$node->order = $i++;
135
			$em->update(['order']);
136
		}
137
	}
138
139
}
140