[TASK] Rework Condition apply/applies/negate methods. use reusable methods
[TYPO3CMS/Extensions/powermailCond.git] / Classes / Domain / Model / Condition.php
1 <?php
2 namespace In2code\PowermailCond\Domain\Model;
3
4 /***************************************************************
5 * Copyright notice
6 *
7 * (c) 2015 in2code.de
8 * Alex Kellner <alexander.kellner@in2code.de>,
9 * Oliver Eglseder <oliver.eglseder@in2code.de>
10 *
11 * All rights reserved
12 *
13 * This script is part of the TYPO3 project. The TYPO3 project is
14 * free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 3 of the License, or
17 * (at your option) any later version.
18 *
19 * The GNU General Public License can be found at
20 * http://www.gnu.org/copyleft/gpl.html.
21 *
22 * This script is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU General Public License for more details.
26 *
27 * This copyright notice MUST APPEAR in all copies of the script!
28 ***************************************************************/
29
30 use In2code\Powermail\Domain\Model\Field;
31 use In2code\Powermail\Domain\Model\Form;
32 use In2code\Powermail\Domain\Model\Page;
33 use TYPO3\CMS\Extbase\DomainObject\AbstractEntity;
34
35 /**
36 * Condition Model
37 *
38 * @package powermail_cond
39 * @license http://www.gnu.org/licenses/lgpl.html
40 * GNU Lesser General Public License, version 3 or later
41 */
42 class Condition extends AbstractEntity {
43
44 const CONJUNCTION_OR = 'OR';
45 const CONJUNCTION_AND = 'AND';
46 const ACTION_HIDE = 0;
47 const ACTION_UN_HIDE = 1;
48 const ACTION_HIDE_STRING = 'hide';
49 const ACTION_UN_HIDE_STRING = 'un_hide';
50 const INDEX_TODO = 'todo';
51 const INDEX_ACTION = 'action';
52 const INDEX_MATCHING_CONDITION = 'matching_condition';
53
54 /**
55 * @var \In2code\Powermail\Domain\Repository\FieldRepository
56 * @inject
57 */
58 protected $fieldRepository;
59
60 /**
61 * @var \In2code\Powermail\Domain\Repository\PageRepository
62 * @inject
63 */
64 protected $pageRepository;
65
66 /**
67 * @var string
68 */
69 protected $title = '';
70
71 /**
72 * @var \TYPO3\CMS\Extbase\Persistence\ObjectStorage<\In2code\PowermailCond\Domain\Model\Rule>
73 */
74 protected $rules = NULL;
75
76 /**
77 * @var string
78 */
79 protected $targetField = '';
80
81 /**
82 * 0 hide
83 * 1 unhide
84 *
85 * @var int
86 */
87 protected $actions = 0;
88
89 /**
90 * @var string
91 */
92 protected $filterSelectField = '';
93
94 /**
95 * "OR"
96 * "AND"
97 *
98 * @var string
99 */
100 protected $conjunction = '';
101
102 /**
103 * @var \In2code\Powermail\Domain\Model\Form
104 */
105 protected $form = '';
106
107 /**
108 * @return string
109 */
110 public function getTitle() {
111 return $this->title;
112 }
113
114 /**
115 * @param string $title
116 * @return Condition
117 */
118 public function setTitle($title) {
119 $this->title = $title;
120 return $this;
121 }
122
123 /**
124 * @return \TYPO3\CMS\Extbase\Persistence\ObjectStorage
125 */
126 public function getRules() {
127 return $this->rules;
128 }
129
130 /**
131 * @param \TYPO3\CMS\Extbase\Persistence\ObjectStorage $rules
132 * @return Condition
133 */
134 public function setRules($rules) {
135 $this->rules = $rules;
136 return $this;
137 }
138
139 /**
140 * @return Field|Page|NULL
141 */
142 public function getTargetField() {
143 $targetField = $this->targetField;
144 if (is_numeric($targetField)) {
145 return $this->fieldRepository->findByUid((int) $targetField);
146 }
147 if (stristr($targetField, 'fieldset:')) {
148 return $this->pageRepository->findByUid((int) trim($targetField, 'fieldset:'));
149 }
150 return NULL;
151 }
152
153 /**
154 * @param string $targetField
155 * @return Condition
156 */
157 public function setTargetField($targetField) {
158 $this->targetField = $targetField;
159 return $this;
160 }
161
162 /**
163 * @return int
164 */
165 public function getActions() {
166 return $this->actions;
167 }
168
169 /**
170 * @param int $actions
171 * @return Condition
172 */
173 public function setActions($actions) {
174 $this->actions = $actions;
175 return $this;
176 }
177
178 /**
179 * @return string
180 */
181 public function getFilterSelectField() {
182 return $this->filterSelectField;
183 }
184
185 /**
186 * @param string $filterSelectField
187 * @return Condition
188 */
189 public function setFilterSelectField($filterSelectField) {
190 $this->filterSelectField = $filterSelectField;
191 return $this;
192 }
193
194 /**
195 * @return string
196 */
197 public function getConjunction() {
198 return $this->conjunction;
199 }
200
201 /**
202 * @param string $conjunction
203 * @return Condition
204 */
205 public function setConjunction($conjunction) {
206 $this->conjunction = $conjunction;
207 return $this;
208 }
209
210 /**
211 * @return Form
212 */
213 public function getForm() {
214 return $this->form;
215 }
216
217 /**
218 * @param Form $form
219 * @return Condition
220 */
221 public function setForm($form) {
222 $this->form = $form;
223 return $this;
224 }
225
226 /**
227 * @param Form $form
228 * @return bool
229 */
230 public function applies(Form $form) {
231 // If conjunction is or set $isOr to TRUE
232 $isOr = ($this->conjunction === self::CONJUNCTION_OR);
233
234 /** @var Rule $rule */
235 foreach ($this->rules as $rule) {
236 if ($rule->applies($form)) {
237 if ($isOr === TRUE) {
238
239 // if it is the first matching rule in an OR conjunction return TRUE
240 return TRUE;
241 }
242 } elseif ($isOr === FALSE) {
243
244 // if it is the first NOT matching rule in an AND conjunction return FALSE
245 return FALSE;
246 }
247 }
248 // if OR and no field matched: return TRUE
249 // if AND and no field matched NOT: return FALSE
250 return ($isOr !== TRUE);
251 }
252
253 /**
254 * @param Form $form
255 * @param array $arguments
256 * @return array
257 */
258 public function apply(Form $form, array $arguments) {
259 if ($this->actions === self::ACTION_HIDE) {
260 $action = self::ACTION_HIDE_STRING;
261 } elseif ($this->actions === self::ACTION_UN_HIDE) {
262 $action = self::ACTION_UN_HIDE_STRING;
263 } else {
264 return $arguments;
265 }
266 return $this->process($form, $arguments, $action);
267 }
268
269 /**
270 * @param Form $form
271 * @param array $arguments
272 * @return array
273 */
274 public function negate(Form $form, array $arguments) {
275 if ($this->actions === self::ACTION_HIDE) {
276 $action = self::ACTION_UN_HIDE_STRING;
277 } elseif ($this->actions === self::ACTION_UN_HIDE) {
278 $action = self::ACTION_HIDE_STRING;
279 } else {
280 return $arguments;
281 }
282 return $this->process($form, $arguments, $action);
283 }
284
285 /**
286 * @param Form $form
287 * @param array $arguments
288 * @param string $action
289 * @return array
290 */
291 protected function process(Form $form, array $arguments, $action) {
292 if (strpos($this->targetField, 'fieldset') !== FALSE) {
293 $targetPageUid = (int) substr($this->targetField, 9);
294 } else {
295 $this->targetField = (int) $this->targetField;
296 $targetPageUid = FALSE;
297 }
298
299 $formUid = $form->getUid();
300 /** @var Page $page */
301 foreach ($form->getPages() as $page) {
302 $pageUid = $page->getUid();
303 if ($targetPageUid && $pageUid === $targetPageUid) {
304 return $this->applyOnPage($formUid, $page, $arguments, $action);
305 } else {
306 /** @var Field $field */
307 foreach ($page->getFields() as $field) {
308 if ($field->getUid() === $this->targetField) {
309 return $this->applyOnField($formUid, $pageUid, $field, $arguments, $action);
310 }
311 }
312 }
313 }
314 return $arguments;
315 }
316
317 /**
318 * Show/Hide the Field if the Page is not hidden
319 *
320 * @param int $formUid
321 * @param int $pageUid
322 * @param Field $field
323 * @param array $arguments
324 * @param string $action
325 * @return array
326 */
327 protected function applyOnField($formUid, $pageUid, Field $field, array $arguments, $action) {
328 if ($action === self::ACTION_UN_HIDE && !empty($arguments[self::INDEX_TODO][$formUid][$pageUid][self::INDEX_ACTION])) {
329 if ($arguments[self::INDEX_TODO][$formUid][$pageUid][self::INDEX_ACTION] === self::ACTION_HIDE_STRING) {
330 return $arguments;
331 }
332 }
333 $fieldMarker = $field->getMarker();
334 $conditionUid = $this->getUid();
335 $arguments[self::INDEX_TODO][$formUid][$pageUid][$fieldMarker][self::INDEX_ACTION] = $action;
336 $arguments[self::INDEX_TODO][$formUid][$pageUid][$fieldMarker][self::INDEX_MATCHING_CONDITION][$conditionUid] = $conditionUid;
337 return $arguments;
338 }
339
340 /**
341 * @param int $formUid
342 * @param Page $page
343 * @param array $arguments
344 * @param string $action
345 * @return array
346 */
347 protected function applyOnPage($formUid, Page $page, array $arguments, $action) {
348 $pageUid = $page->getUid();
349 foreach ($page->getFields() as $field) {
350 $arguments = $this->applyOnField($formUid, $pageUid, $field, $arguments, $action);
351 }
352 $conditionUid = $this->getUid();
353 $arguments[self::INDEX_TODO][$formUid][$pageUid][self::INDEX_ACTION] = $action;
354 $arguments[self::INDEX_TODO][$formUid][$pageUid][self::INDEX_MATCHING_CONDITION][$conditionUid] = $conditionUid;
355 return $arguments;
356 }
357 }