1 | <?php |
||
39 | class ParentChildTrashHandlers |
||
40 | { |
||
41 | |||
42 | /** |
||
43 | * Register event handlers for parent of parent-child relation. |
||
44 | * |
||
45 | * @param AnnotatedInterface $parent |
||
46 | * @param string $childClass |
||
47 | */ |
||
48 | 4 | public function registerParent(AnnotatedInterface $parent, $childClass) |
|
49 | { |
||
50 | 4 | if (!ClassChecker::exists($childClass)) |
|
51 | { |
||
52 | throw new UnexpectedValueException(sprintf('Class `%s` not found', $childClass)); |
||
53 | } |
||
54 | // Delete all of this child items after removing from trash |
||
55 | 4 | $beforeDelete = function(ModelEvent $event) use($parent, $childClass) |
|
56 | { |
||
57 | 1 | $model = $event->sender; |
|
58 | 1 | $event->isValid = true; |
|
59 | 1 | if ($model instanceof $parent) |
|
60 | { |
||
61 | $child = new $childClass; |
||
62 | $criteria = new Criteria(null, $child); |
||
63 | $criteria->parentId = $this->getPk($model); |
||
64 | |||
65 | $event->isValid = $child->deleteAll($criteria); |
||
66 | } |
||
67 | 4 | }; |
|
68 | 4 | $beforeDelete->bindTo($this); |
|
69 | 4 | Event::on($parent, EntityManagerInterface::EventBeforeDelete, $beforeDelete); |
|
70 | |||
71 | // Trash all child items from parent item |
||
72 | 4 | $afterTrash = function(ModelEvent $event)use($parent, $childClass) |
|
73 | { |
||
74 | 4 | $model = $event->sender; |
|
75 | 4 | $event->isValid = true; |
|
76 | 4 | if ($model instanceof $parent) |
|
77 | { |
||
78 | 4 | $child = new $childClass; |
|
79 | 4 | $criteria = new Criteria(null, $child); |
|
80 | 4 | $criteria->parentId = $this->getPk($model); |
|
81 | |||
82 | 4 | $items = $child->findAll($criteria); |
|
83 | |||
84 | // No items found, so skip |
||
85 | 4 | if (empty($items)) |
|
86 | { |
||
87 | $event->isValid = true; |
||
88 | return true; |
||
89 | } |
||
90 | |||
91 | // Trash in loop all items |
||
92 | 4 | foreach ($items as $item) |
|
93 | { |
||
94 | 4 | if (!$item->trash()) |
|
95 | { |
||
96 | $event->isValid = false; |
||
97 | 4 | return false; |
|
98 | } |
||
99 | } |
||
100 | } |
||
101 | 4 | }; |
|
102 | 4 | $afterTrash->bindTo($this); |
|
103 | 4 | Event::on($parent, TrashInterface::EventAfterTrash, $afterTrash); |
|
104 | |||
105 | // Restore all child items from parent, but only those after it was trashed. |
||
106 | // This will keep previously trashed items in trash |
||
107 | 4 | $afterRestore = function(RestoreEvent $event)use($parent, $childClass) |
|
108 | { |
||
109 | 2 | $model = $event->sender; |
|
110 | 2 | if ($model instanceof $parent) |
|
111 | { |
||
112 | 2 | $child = new $childClass; |
|
113 | 2 | $trash = $event->getTrash(); |
|
114 | 2 | $criteria = new Criteria(null, $trash); |
|
115 | |||
116 | // Conditions decorator do not work with dots so sanitize manually. |
||
117 | 2 | $s = new Sanitizer($child); |
|
118 | |||
119 | 2 | $id = $s->write('parentId', $this->getPk($model)); |
|
120 | 2 | $criteria->addCond('data.parentId', '==', $id); |
|
121 | |||
122 | // Restore only child items trashed when parent was trashed. |
||
123 | // Skip earlier items |
||
124 | 2 | assert(isset($trash->createDate), sprintf('When implementing `%s`, `createDate` field is required and must be set to date of deletion', TrashInterface::class)); |
|
125 | 2 | $criteria->addCond('createDate', 'gte', $trash->createDate); |
|
126 | |||
127 | 2 | $trashedItems = $trash->findAll($criteria); |
|
128 | 2 | if (empty($trashedItems)) |
|
129 | { |
||
130 | $event->isValid = true; |
||
131 | return true; |
||
132 | } |
||
133 | |||
134 | // Restore all items |
||
135 | 2 | foreach ($trashedItems as $trashedItem) |
|
136 | { |
||
137 | 2 | $trashedItem->restore(); |
|
138 | } |
||
139 | } |
||
140 | 2 | $event->isValid = true; |
|
141 | 4 | }; |
|
142 | 4 | $afterRestore->bindTo($this); |
|
143 | 4 | Event::on($parent, TrashInterface::EventAfterRestore, $afterRestore); |
|
144 | 4 | } |
|
145 | |||
146 | /** |
||
147 | * Register event handlers for child item of parent-child relation. |
||
148 | * |
||
149 | * @param AnnotatedInterface $child |
||
150 | * @param string $parentClass |
||
151 | * @throws UnexpectedValueException |
||
152 | */ |
||
153 | 4 | public function registerChild(AnnotatedInterface $child, $parentClass) |
|
180 | |||
181 | 4 | private function getPk(AnnotatedInterface $model) |
|
187 | |||
188 | } |
||
189 |