1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* @link https://github.com/old-town/old-town-workflow |
4
|
|
|
* @author Malofeykin Andrey <[email protected]> |
5
|
|
|
*/ |
6
|
|
|
namespace OldTown\Workflow\Loader; |
7
|
|
|
|
8
|
|
|
use OldTown\Workflow\Exception\ArgumentNotNumericException; |
9
|
|
|
use OldTown\Workflow\Exception\InternalWorkflowException; |
10
|
|
|
use OldTown\Workflow\Exception\InvalidArgumentException; |
11
|
|
|
use OldTown\Workflow\Exception\InvalidDescriptorException; |
12
|
|
|
use OldTown\Workflow\Exception\InvalidDtdSchemaException; |
13
|
|
|
use OldTown\Workflow\Exception\InvalidWorkflowDescriptorException; |
14
|
|
|
use DOMElement; |
15
|
|
|
use OldTown\Workflow\Exception\InvalidWriteWorkflowException; |
16
|
|
|
use OldTown\Workflow\Exception\RuntimeException; |
17
|
|
|
use SplObjectStorage; |
18
|
|
|
use DOMDocument; |
19
|
|
|
use DOMImplementation; |
20
|
|
|
use \LibXMLError; |
21
|
|
|
|
22
|
|
|
/** |
23
|
|
|
* Interface WorkflowDescriptor |
24
|
|
|
* |
25
|
|
|
* @package OldTown\Workflow\Loader |
26
|
|
|
*/ |
27
|
|
|
class WorkflowDescriptor extends AbstractDescriptor implements WriteXmlInterface |
28
|
|
|
{ |
29
|
|
|
/** |
30
|
|
|
* |
31
|
|
|
* |
32
|
|
|
* @var string |
33
|
|
|
*/ |
34
|
|
|
const DOCUMENT_TYPE_QUALIFIED_NAME = 'workflow'; |
35
|
|
|
|
36
|
|
|
/** |
37
|
|
|
* |
38
|
|
|
* |
39
|
|
|
* @var string |
40
|
|
|
*/ |
41
|
|
|
const DOCUMENT_TYPE_PUBLIC_ID = '-//OpenSymphony Group//DTD OSWorkflow 2.8//EN'; |
42
|
|
|
|
43
|
|
|
/** |
44
|
|
|
* |
45
|
|
|
* |
46
|
|
|
* @var string |
47
|
|
|
*/ |
48
|
|
|
const DOCUMENT_TYPE_SYSTEM_ID = 'http://www.opensymphony.com/osworkflow/workflow_2_8.dtd'; |
49
|
|
|
|
50
|
|
|
|
51
|
|
|
|
52
|
|
|
/** |
53
|
|
|
* @var ConditionsDescriptor|null |
54
|
|
|
*/ |
55
|
|
|
protected $globalConditions; |
56
|
|
|
|
57
|
|
|
/** |
58
|
|
|
* @var ActionDescriptor[]|SplObjectStorage |
59
|
|
|
*/ |
60
|
|
|
protected $globalActions; |
61
|
|
|
|
62
|
|
|
/** |
63
|
|
|
* @var SplObjectStorage|ActionDescriptor[] |
64
|
|
|
*/ |
65
|
|
|
protected $initialActions; |
66
|
|
|
|
67
|
|
|
/** |
68
|
|
|
* @var JoinDescriptor[]|SplObjectStorage |
69
|
|
|
*/ |
70
|
|
|
protected $joins; |
71
|
|
|
|
72
|
|
|
/** |
73
|
|
|
* @var RegisterDescriptor[]|SplObjectStorage |
74
|
|
|
*/ |
75
|
|
|
protected $registers; |
76
|
|
|
|
77
|
|
|
/** |
78
|
|
|
* @var SplitDescriptor[]|SplObjectStorage |
79
|
|
|
*/ |
80
|
|
|
protected $splits = []; |
81
|
|
|
|
82
|
|
|
/** |
83
|
|
|
* @var StepDescriptor[]|SplObjectStorage |
84
|
|
|
*/ |
85
|
|
|
protected $steps; |
86
|
|
|
|
87
|
|
|
/** |
88
|
|
|
* @var ActionDescriptor[] |
89
|
|
|
*/ |
90
|
|
|
protected $commonActions = []; |
91
|
|
|
|
92
|
|
|
/** |
93
|
|
|
* @var ActionDescriptor[]|SplObjectStorage |
94
|
|
|
*/ |
95
|
|
|
protected $commonActionsList = []; |
96
|
|
|
|
97
|
|
|
/** |
98
|
|
|
* @var array |
99
|
|
|
*/ |
100
|
|
|
protected $metaAttributes = []; |
101
|
|
|
|
102
|
|
|
/** |
103
|
|
|
* @var array |
104
|
|
|
*/ |
105
|
|
|
protected $timerFunctions = []; |
106
|
|
|
|
107
|
|
|
/** |
108
|
|
|
* Имя workflow |
109
|
|
|
* |
110
|
|
|
* @var string|null |
111
|
|
|
*/ |
112
|
|
|
protected $workflowName; |
113
|
|
|
|
114
|
|
|
/** |
115
|
|
|
* @param DOMElement $element |
116
|
|
|
* @throws InvalidArgumentException |
117
|
|
|
* @throws RuntimeException |
118
|
|
|
* @throws InternalWorkflowException |
119
|
|
|
* @throws \OldTown\Workflow\Exception\ArgumentNotNumericException |
120
|
|
|
*/ |
121
|
85 |
|
public function __construct(DOMElement $element = null) |
122
|
|
|
{ |
123
|
85 |
|
$this->registers = new SplObjectStorage(); |
124
|
85 |
|
$this->initialActions = new SplObjectStorage(); |
125
|
85 |
|
$this->globalActions = new SplObjectStorage(); |
126
|
85 |
|
$this->steps = new SplObjectStorage(); |
127
|
85 |
|
$this->joins = new SplObjectStorage(); |
128
|
85 |
|
$this->splits = new SplObjectStorage(); |
129
|
|
|
|
130
|
85 |
|
parent::__construct($element); |
131
|
|
|
|
132
|
85 |
|
if (null !== $element) { |
133
|
68 |
|
$this->init($element); |
134
|
63 |
|
} |
135
|
80 |
|
} |
136
|
|
|
|
137
|
|
|
/** |
138
|
|
|
* Возвращает имя workflow |
139
|
|
|
* |
140
|
|
|
* @return null|string |
141
|
|
|
*/ |
142
|
1 |
|
public function getName() |
143
|
|
|
{ |
144
|
1 |
|
return $this->workflowName; |
145
|
|
|
} |
146
|
|
|
|
147
|
|
|
|
148
|
|
|
/** |
149
|
|
|
* Устанавливает имя workflow |
150
|
|
|
* |
151
|
|
|
* @param string $workflowName |
152
|
|
|
* |
153
|
|
|
* @return $this |
154
|
|
|
*/ |
155
|
27 |
|
public function setName($workflowName) |
156
|
|
|
{ |
157
|
27 |
|
$this->workflowName = (string)$workflowName; |
158
|
|
|
|
159
|
27 |
|
return $this; |
160
|
|
|
} |
161
|
|
|
|
162
|
|
|
/** |
163
|
|
|
* Валидация workflow |
164
|
|
|
* |
165
|
|
|
* @throws InvalidWorkflowDescriptorException |
166
|
|
|
* @throws InternalWorkflowException |
167
|
|
|
* @throws InvalidDescriptorException |
168
|
|
|
* @throws InvalidWriteWorkflowException |
169
|
|
|
* @throws \OldTown\Workflow\Exception\InvalidDtdSchemaException |
170
|
|
|
* @return void |
171
|
|
|
*/ |
172
|
17 |
|
public function validate() |
173
|
|
|
{ |
174
|
17 |
|
$registers = $this->getRegisters(); |
175
|
17 |
|
$triggerFunctions = $this->getTriggerFunctions(); |
176
|
17 |
|
$globalActions = $this->getGlobalActions(); |
177
|
17 |
|
$initialActions = $this->getInitialActions(); |
178
|
17 |
|
$commonActions = $this->getCommonActions(); |
179
|
17 |
|
$steps = $this->getSteps(); |
180
|
17 |
|
$splits = $this->getSplits(); |
181
|
17 |
|
$joins = $this->getJoins(); |
182
|
|
|
|
183
|
|
|
|
184
|
17 |
|
ValidationHelper::validate($registers); |
185
|
17 |
|
ValidationHelper::validate($triggerFunctions); |
186
|
17 |
|
ValidationHelper::validate($globalActions); |
187
|
17 |
|
ValidationHelper::validate($initialActions); |
188
|
17 |
|
ValidationHelper::validate($commonActions); |
189
|
17 |
|
ValidationHelper::validate($steps); |
190
|
17 |
|
ValidationHelper::validate($splits); |
191
|
17 |
|
ValidationHelper::validate($joins); |
192
|
|
|
|
193
|
|
|
|
194
|
17 |
|
$actions = []; |
195
|
|
|
|
196
|
17 |
|
foreach ($globalActions as $action) { |
197
|
3 |
|
$actionId = $action->getId(); |
198
|
3 |
|
if (array_key_exists($actionId, $actions)) { |
199
|
1 |
|
$errMsg = sprintf( |
200
|
1 |
|
'Ошибка валидация. Действие с id %s уже существует', |
201
|
|
|
$actionId |
202
|
1 |
|
); |
203
|
1 |
|
throw new InvalidWorkflowDescriptorException($errMsg); |
204
|
|
|
} |
205
|
3 |
|
$actions[$actionId] = $actionId; |
206
|
17 |
|
} |
207
|
|
|
|
208
|
16 |
|
foreach ($steps as $step) { |
209
|
14 |
|
$j = $step->getActions(); |
210
|
|
|
|
211
|
14 |
|
foreach ($j as $action) { |
212
|
14 |
|
if (!$action->isCommon()) { |
213
|
13 |
|
$actionId = $action->getId(); |
214
|
13 |
|
if (array_key_exists($actionId, $actions)) { |
215
|
1 |
|
$errMsg = sprintf( |
216
|
1 |
|
'Действие с id %s найденное у шага %s является дубликатом', |
217
|
1 |
|
$actionId, |
218
|
1 |
|
$step->getId() |
219
|
1 |
|
); |
220
|
1 |
|
throw new InvalidWorkflowDescriptorException($errMsg); |
221
|
|
|
} |
222
|
12 |
|
$actions[$actionId] = $actionId; |
223
|
12 |
|
} |
224
|
13 |
|
} |
225
|
15 |
|
} |
226
|
|
|
|
227
|
|
|
|
228
|
15 |
|
foreach ($commonActions as $action) { |
229
|
2 |
|
$actionId = $action->getId(); |
230
|
2 |
|
if (array_key_exists($actionId, $actions)) { |
231
|
1 |
|
$errMsg = sprintf( |
232
|
1 |
|
'common-action с id %s является дубликатом', |
233
|
|
|
$actionId |
234
|
1 |
|
); |
235
|
1 |
|
throw new InvalidWorkflowDescriptorException($errMsg); |
236
|
|
|
} |
237
|
14 |
|
} |
238
|
|
|
|
239
|
|
|
|
240
|
14 |
|
$this->validateDtd(); |
241
|
12 |
|
} |
242
|
|
|
|
243
|
|
|
/** |
244
|
|
|
* Валидация схемы документа |
245
|
|
|
* |
246
|
|
|
* @return void |
247
|
|
|
* @throws InternalWorkflowException |
248
|
|
|
* @throws InvalidDescriptorException |
249
|
|
|
* @throws InvalidWriteWorkflowException |
250
|
|
|
* @throws \OldTown\Workflow\Exception\InvalidDtdSchemaException |
251
|
|
|
*/ |
252
|
14 |
|
private function validateDtd() |
253
|
|
|
{ |
254
|
14 |
|
$libxmlUseInternalErrors = libxml_use_internal_errors(true); |
255
|
14 |
|
$dom = $this->writeXml(); |
256
|
|
|
|
257
|
14 |
|
$secureDtdEntityResolver = new SecureDtdEntityResolver(); |
258
|
14 |
|
$dtd = $secureDtdEntityResolver->resolveEntity($dom->doctype); |
259
|
|
|
|
260
|
|
|
|
261
|
14 |
|
$systemId = 'data://text/plain;base64,'.base64_encode($dtd); |
262
|
|
|
|
263
|
14 |
|
$creator = new DOMImplementation; |
264
|
14 |
|
$doctype = $creator->createDocumentType( |
265
|
14 |
|
static::DOCUMENT_TYPE_QUALIFIED_NAME, |
266
|
14 |
|
static::DOCUMENT_TYPE_PUBLIC_ID, |
267
|
|
|
$systemId |
268
|
14 |
|
); |
269
|
14 |
|
$new = $creator->createDocument('', '', $doctype); |
270
|
|
|
|
271
|
14 |
|
$oldNode = $dom->getElementsByTagName(static::DOCUMENT_TYPE_QUALIFIED_NAME)->item(0); |
272
|
14 |
|
$newNode = $new->importNode($oldNode, true); |
273
|
14 |
|
$new->appendChild($newNode); |
274
|
|
|
|
275
|
14 |
|
if (!$new->validate()) { |
276
|
|
|
/** @var LibXMLError[] $errors */ |
277
|
2 |
|
$errors = libxml_get_errors(); |
278
|
2 |
|
$errMsgStack = []; |
279
|
2 |
|
foreach ($errors as $error) { |
280
|
2 |
|
$errMsgStack[] = $error->message; |
281
|
2 |
|
} |
282
|
2 |
|
$errMsg = implode(" \n", $errMsgStack); |
283
|
|
|
|
284
|
2 |
|
libxml_use_internal_errors($libxmlUseInternalErrors); |
285
|
2 |
|
throw new InvalidDtdSchemaException($errMsg); |
286
|
|
|
} |
287
|
12 |
|
libxml_use_internal_errors($libxmlUseInternalErrors); |
288
|
12 |
|
} |
289
|
|
|
|
290
|
|
|
/** |
291
|
|
|
* @param DOMElement $root |
292
|
|
|
* @throws InvalidArgumentException |
293
|
|
|
* @throws RuntimeException |
294
|
|
|
* @throws InternalWorkflowException |
295
|
|
|
* @throws \OldTown\Workflow\Exception\ArgumentNotNumericException |
296
|
|
|
*/ |
297
|
68 |
|
protected function init(DOMElement $root) |
298
|
|
|
{ |
299
|
68 |
|
$metaElements = XmlUtil::getChildElements($root, 'meta'); |
300
|
68 |
View Code Duplication |
foreach ($metaElements as $meta) { |
|
|
|
|
301
|
12 |
|
$value = XmlUtil::getText($meta); |
302
|
12 |
|
$name = XmlUtil::getRequiredAttributeValue($meta, 'name'); |
303
|
|
|
|
304
|
12 |
|
$this->metaAttributes[$name] = $value; |
305
|
68 |
|
} |
306
|
|
|
|
307
|
|
|
// handle registers - OPTIONAL |
308
|
68 |
|
$r = XmlUtil::getChildElement($root, 'registers'); |
309
|
68 |
View Code Duplication |
if (null !== $r) { |
|
|
|
|
310
|
15 |
|
$registers = XMLUtil::getChildElements($r, 'register'); |
311
|
|
|
|
312
|
15 |
|
foreach ($registers as $register) { |
313
|
15 |
|
$registerDescriptor = DescriptorFactory::getFactory()->createRegisterDescriptor($register); |
314
|
15 |
|
$registerDescriptor->setParent($this); |
315
|
15 |
|
$this->registers->attach($registerDescriptor); |
316
|
15 |
|
} |
317
|
15 |
|
} |
318
|
|
|
|
319
|
|
|
// handle global-conditions - OPTIONAL |
320
|
68 |
|
$globalConditionsElement = XMLUtil::getChildElement($root, 'global-conditions'); |
321
|
68 |
|
if ($globalConditionsElement !== null) { |
322
|
1 |
|
$globalConditions = XMLUtil::getChildElement($globalConditionsElement, 'conditions'); |
323
|
|
|
|
324
|
1 |
|
$conditionsDescriptor = DescriptorFactory::getFactory()->createConditionsDescriptor($globalConditions); |
325
|
1 |
|
$conditionsDescriptor->setParent($this); |
326
|
1 |
|
$this->globalConditions = $conditionsDescriptor; |
327
|
1 |
|
} |
328
|
|
|
|
329
|
|
|
// handle initial-steps - REQUIRED |
330
|
68 |
|
$initialActionsElement = XMLUtil::getChildElement($root, 'initial-actions'); |
331
|
68 |
|
$initialActions = XMLUtil::getChildElements($initialActionsElement, 'action'); |
|
|
|
|
332
|
|
|
|
333
|
68 |
|
foreach ($initialActions as $initialAction) { |
334
|
49 |
|
$actionDescriptor = DescriptorFactory::getFactory()->createActionDescriptor($initialAction); |
335
|
49 |
|
$actionDescriptor->setParent($this); |
336
|
49 |
|
$this->addInitialAction($actionDescriptor); |
337
|
68 |
|
} |
338
|
|
|
|
339
|
|
|
// handle global-actions - OPTIONAL |
340
|
67 |
|
$globalActionsElement = XMLUtil::getChildElement($root, 'global-actions'); |
341
|
|
|
|
342
|
67 |
View Code Duplication |
if (null !== $globalActionsElement) { |
|
|
|
|
343
|
7 |
|
$globalActions = XMLUtil::getChildElements($globalActionsElement, 'action'); |
344
|
|
|
|
345
|
7 |
|
foreach ($globalActions as $globalAction) { |
346
|
7 |
|
$actionDescriptor = DescriptorFactory::getFactory()->createActionDescriptor($globalAction); |
347
|
7 |
|
$actionDescriptor->setParent($this); |
348
|
7 |
|
$this->addGlobalAction($actionDescriptor); |
349
|
7 |
|
} |
350
|
7 |
|
} |
351
|
|
|
|
352
|
|
|
|
353
|
|
|
// handle common-actions - OPTIONAL |
354
|
|
|
// - Store actions in HashMap for now. When parsing Steps, we'll resolve |
355
|
|
|
// any common actions into local references. |
356
|
67 |
|
$commonActionsElement = XMLUtil::getChildElement($root, 'common-actions'); |
357
|
|
|
|
358
|
67 |
View Code Duplication |
if (null !== $commonActionsElement) { |
|
|
|
|
359
|
11 |
|
$commonActions = XMLUtil::getChildElements($commonActionsElement, 'action'); |
360
|
|
|
|
361
|
11 |
|
foreach ($commonActions as $commonAction) { |
362
|
11 |
|
$actionDescriptor = DescriptorFactory::getFactory()->createActionDescriptor($commonAction); |
363
|
11 |
|
$actionDescriptor->setParent($this); |
364
|
11 |
|
$this->addCommonAction($actionDescriptor); |
365
|
11 |
|
} |
366
|
11 |
|
} |
367
|
|
|
|
368
|
|
|
|
369
|
|
|
// handle timer-functions - OPTIONAL |
370
|
67 |
|
$timerFunctionsElement = XMLUtil::getChildElement($root, 'trigger-functions'); |
371
|
|
|
|
372
|
67 |
|
if (null !== $timerFunctionsElement) { |
373
|
3 |
|
$timerFunctions = XMLUtil::getChildElements($timerFunctionsElement, 'trigger-function'); |
374
|
|
|
|
375
|
3 |
|
foreach ($timerFunctions as $timerFunction) { |
376
|
3 |
|
$functionElement = XmlUtil::getRequiredChildElement($timerFunction, 'function'); |
377
|
3 |
|
$id = XmlUtil::getRequiredAttributeValue($timerFunction, 'id'); |
378
|
|
|
|
379
|
3 |
|
$function = DescriptorFactory::getFactory()->createFunctionDescriptor($functionElement); |
380
|
3 |
|
$function->setParent($this); |
381
|
|
|
|
382
|
3 |
|
$this->setTriggerFunction($id, $function); |
383
|
2 |
|
} |
384
|
2 |
|
} |
385
|
|
|
|
386
|
|
|
// handle steps - REQUIRED |
387
|
66 |
|
$stepsElement = XMLUtil::getChildElement($root, 'steps'); |
388
|
66 |
|
$steps = XMLUtil::getChildElements($stepsElement, 'step'); |
|
|
|
|
389
|
|
|
|
390
|
66 |
|
foreach ($steps as $step) { |
391
|
64 |
|
$stepDescriptor = DescriptorFactory::getFactory()->createStepDescriptor($step, $this); |
392
|
64 |
|
$this->addStep($stepDescriptor); |
393
|
66 |
|
} |
394
|
|
|
|
395
|
|
|
|
396
|
|
|
// handle splits - OPTIONAL: |
397
|
65 |
|
$splitsElement = XMLUtil::getChildElement($root, 'splits'); |
398
|
65 |
View Code Duplication |
if (null !== $splitsElement) { |
|
|
|
|
399
|
14 |
|
$split = XMLUtil::getChildElements($splitsElement, 'split'); |
400
|
14 |
|
foreach ($split as $s) { |
401
|
14 |
|
$splitDescriptor = DescriptorFactory::getFactory()->createSplitDescriptor($s); |
402
|
14 |
|
$splitDescriptor->setParent($this); |
403
|
14 |
|
$this->addSplit($splitDescriptor); |
404
|
14 |
|
} |
405
|
13 |
|
} |
406
|
|
|
|
407
|
|
|
|
408
|
|
|
// handle joins - OPTIONAL: |
409
|
64 |
|
$joinsElement = XMLUtil::getChildElement($root, 'joins'); |
410
|
64 |
View Code Duplication |
if (null !== $joinsElement) { |
|
|
|
|
411
|
14 |
|
$join = XMLUtil::getChildElements($joinsElement, 'join'); |
412
|
14 |
|
foreach ($join as $s) { |
413
|
14 |
|
$joinDescriptor = DescriptorFactory::getFactory()->createJoinDescriptor($s); |
414
|
14 |
|
$joinDescriptor->setParent($this); |
415
|
14 |
|
$this->addJoin($joinDescriptor); |
416
|
14 |
|
} |
417
|
13 |
|
} |
418
|
63 |
|
} |
419
|
|
|
|
420
|
|
|
/** |
421
|
|
|
* @return null|ConditionsDescriptor |
422
|
|
|
*/ |
423
|
25 |
|
public function getGlobalConditions() |
424
|
|
|
{ |
425
|
25 |
|
return $this->globalConditions; |
426
|
|
|
} |
427
|
|
|
|
428
|
|
|
|
429
|
|
|
/** |
430
|
|
|
* Добавляет новый переход между действиями |
431
|
|
|
* |
432
|
|
|
* @param ActionDescriptor $descriptor |
433
|
|
|
* @return $this |
434
|
|
|
* |
435
|
|
|
* @throws InvalidArgumentException |
436
|
|
|
* @throws RuntimeException |
437
|
|
|
*/ |
438
|
11 |
|
public function addCommonAction(ActionDescriptor $descriptor) |
439
|
|
|
{ |
440
|
11 |
|
$descriptor->setCommon(true); |
441
|
11 |
|
$this->addAction($this->commonActions, $descriptor); |
442
|
11 |
|
$this->addAction($this->commonActionsList, $descriptor); |
443
|
|
|
|
444
|
11 |
|
return $this; |
445
|
|
|
} |
446
|
|
|
|
447
|
|
|
/** |
448
|
|
|
* @param $actionsCollectionOrMap |
449
|
|
|
* @param ActionDescriptor $descriptor |
450
|
|
|
* |
451
|
|
|
* @return $this |
452
|
|
|
* @throws InvalidArgumentException |
453
|
|
|
* @throws RuntimeException |
454
|
|
|
*/ |
455
|
53 |
|
private function addAction(&$actionsCollectionOrMap, ActionDescriptor $descriptor) |
456
|
|
|
{ |
457
|
53 |
|
$descriptorId = $descriptor->getId(); |
458
|
53 |
|
$action = $this->getAction($descriptorId); |
459
|
53 |
|
if (null !== $action) { |
460
|
1 |
|
$errMsg = sprintf('Действие с id %s уже существует', $descriptorId); |
461
|
1 |
|
throw new InvalidArgumentException($errMsg); |
462
|
|
|
} |
463
|
|
|
|
464
|
53 |
|
if ($actionsCollectionOrMap instanceof SplObjectStorage) { |
465
|
49 |
|
$actionsCollectionOrMap->attach($descriptor); |
466
|
53 |
|
} elseif (is_array($actionsCollectionOrMap)) { |
467
|
11 |
|
$actionsCollectionOrMap[$descriptorId] = $descriptor; |
468
|
11 |
|
} |
469
|
|
|
|
470
|
53 |
|
return $this; |
471
|
|
|
} |
472
|
|
|
|
473
|
|
|
/** |
474
|
|
|
* Возвращает шаг по его id |
475
|
|
|
* |
476
|
|
|
* @param integer $id |
477
|
|
|
* @return StepDescriptor|null |
478
|
|
|
* @throws \OldTown\Workflow\Exception\ArgumentNotNumericException |
479
|
|
|
*/ |
480
|
65 |
|
public function getStep($id) |
481
|
|
|
{ |
482
|
65 |
|
if (!is_numeric($id)) { |
483
|
1 |
|
$errMsg = 'Аргумент должен быть числом'; |
484
|
1 |
|
throw new ArgumentNotNumericException($errMsg); |
485
|
|
|
} |
486
|
64 |
|
$id = (integer)$id; |
487
|
|
|
|
488
|
64 |
|
foreach ($this->getSteps() as $step) { |
489
|
35 |
|
if ($id === $step->getId()) { |
490
|
21 |
|
return $step; |
491
|
|
|
} |
492
|
64 |
|
} |
493
|
64 |
|
return null; |
494
|
|
|
} |
495
|
|
|
|
496
|
|
|
/** |
497
|
|
|
* @param integer $id |
498
|
|
|
* @return ActionDescriptor|null |
499
|
|
|
*/ |
500
|
53 |
|
public function getAction($id) |
501
|
|
|
{ |
502
|
53 |
|
$id = (integer)$id; |
503
|
|
|
|
504
|
53 |
|
foreach ($this->getGlobalActions() as $actionDescriptor) { |
505
|
7 |
|
if ($id === $actionDescriptor->getId()) { |
506
|
3 |
|
return $actionDescriptor; |
507
|
|
|
} |
508
|
53 |
|
} |
509
|
|
|
|
510
|
53 |
|
foreach ($this->getSteps() as $stepDescriptor) { |
511
|
3 |
|
$actionDescriptor = $stepDescriptor->getAction($id); |
512
|
3 |
|
if (null !== $actionDescriptor) { |
513
|
3 |
|
return $actionDescriptor; |
514
|
|
|
} |
515
|
53 |
|
} |
516
|
|
|
|
517
|
53 |
|
foreach ($this->getInitialActions() as $actionDescriptor) { |
518
|
9 |
|
if ($id === $actionDescriptor->getId()) { |
519
|
1 |
|
return $actionDescriptor; |
520
|
|
|
} |
521
|
53 |
|
} |
522
|
|
|
|
523
|
53 |
|
return null; |
524
|
|
|
} |
525
|
|
|
|
526
|
|
|
/** |
527
|
|
|
* @return ActionDescriptor[]|SplObjectStorage |
528
|
|
|
*/ |
529
|
56 |
|
public function getGlobalActions() |
530
|
|
|
{ |
531
|
56 |
|
return $this->globalActions; |
532
|
|
|
} |
533
|
|
|
|
534
|
|
|
/** |
535
|
|
|
* @return StepDescriptor[]|SplObjectStorage |
536
|
|
|
*/ |
537
|
70 |
|
public function getSteps() |
538
|
|
|
{ |
539
|
70 |
|
return $this->steps; |
540
|
|
|
} |
541
|
|
|
|
542
|
|
|
/** |
543
|
|
|
* @return ActionDescriptor[]|SplObjectStorage |
544
|
|
|
*/ |
545
|
57 |
|
public function getInitialActions() |
546
|
|
|
{ |
547
|
57 |
|
return $this->initialActions; |
548
|
|
|
} |
549
|
|
|
|
550
|
|
|
/** |
551
|
|
|
* @return ActionDescriptor[] |
552
|
|
|
*/ |
553
|
21 |
|
public function getCommonActions() |
554
|
|
|
{ |
555
|
21 |
|
return $this->commonActions; |
556
|
|
|
} |
557
|
|
|
|
558
|
|
|
/** |
559
|
|
|
* @param $id |
560
|
|
|
* |
561
|
|
|
* @return ActionDescriptor|null |
562
|
|
|
*/ |
563
|
14 |
|
public function getCommonAction($id) |
564
|
|
|
{ |
565
|
14 |
|
$id = (integer)$id; |
566
|
14 |
|
if (array_key_exists($id, $this->commonActions)) { |
567
|
7 |
|
return $this->commonActions[$id]; |
568
|
|
|
} |
569
|
8 |
|
return null; |
570
|
|
|
} |
571
|
|
|
|
572
|
|
|
|
573
|
|
|
/** |
574
|
|
|
* @param $id |
575
|
|
|
* |
576
|
|
|
* @return ActionDescriptor|null |
577
|
|
|
* @throws \OldTown\Workflow\Exception\ArgumentNotNumericException |
578
|
|
|
*/ |
579
|
22 |
View Code Duplication |
public function getInitialAction($id) |
|
|
|
|
580
|
|
|
{ |
581
|
22 |
|
if (!is_numeric($id)) { |
582
|
1 |
|
$errMsg = 'Аргумент должен быть числом'; |
583
|
1 |
|
throw new ArgumentNotNumericException($errMsg); |
584
|
|
|
} |
585
|
21 |
|
$id = (integer)$id; |
586
|
|
|
|
587
|
21 |
|
$initialActions = $this->getInitialActions(); |
588
|
21 |
|
foreach ($initialActions as $actionDescriptor) { |
589
|
20 |
|
if ($id === $actionDescriptor->getId()) { |
590
|
20 |
|
return $actionDescriptor; |
591
|
|
|
} |
592
|
6 |
|
} |
593
|
|
|
|
594
|
6 |
|
return null; |
595
|
|
|
} |
596
|
|
|
|
597
|
|
|
/** |
598
|
|
|
* @return JoinDescriptor[]|SplObjectStorage |
599
|
|
|
*/ |
600
|
22 |
|
public function getJoins() |
601
|
|
|
{ |
602
|
22 |
|
return $this->joins; |
603
|
|
|
} |
604
|
|
|
|
605
|
|
|
|
606
|
|
|
/** |
607
|
|
|
* @param $id |
608
|
|
|
* |
609
|
|
|
* @return JoinDescriptor|null |
610
|
|
|
* @throws \OldTown\Workflow\Exception\ArgumentNotNumericException |
611
|
|
|
*/ |
612
|
15 |
View Code Duplication |
public function getJoin($id) |
|
|
|
|
613
|
|
|
{ |
614
|
15 |
|
if (!is_numeric($id)) { |
615
|
1 |
|
$errMsg = 'Аргумент должен быть числом'; |
616
|
1 |
|
throw new ArgumentNotNumericException($errMsg); |
617
|
|
|
} |
618
|
14 |
|
$id = (integer)$id; |
619
|
|
|
|
620
|
14 |
|
$joins = $this->getJoins(); |
621
|
14 |
|
foreach ($joins as $joinDescriptor) { |
622
|
2 |
|
if ($id === $joinDescriptor->getId()) { |
623
|
2 |
|
return $joinDescriptor; |
624
|
|
|
} |
625
|
14 |
|
} |
626
|
|
|
|
627
|
14 |
|
return null; |
628
|
|
|
} |
629
|
|
|
|
630
|
|
|
/** |
631
|
|
|
* @return array |
632
|
|
|
*/ |
633
|
17 |
|
public function getMetaAttributes() |
634
|
|
|
{ |
635
|
17 |
|
return $this->metaAttributes; |
636
|
|
|
} |
637
|
|
|
|
638
|
|
|
/** |
639
|
|
|
* @return RegisterDescriptor[]|SplObjectStorage |
640
|
|
|
*/ |
641
|
39 |
|
public function getRegisters() |
642
|
|
|
{ |
643
|
39 |
|
return $this->registers; |
644
|
|
|
} |
645
|
|
|
|
646
|
|
|
/** |
647
|
|
|
* @return SplitDescriptor[]|SplObjectStorage |
648
|
|
|
*/ |
649
|
22 |
|
public function getSplits() |
650
|
|
|
{ |
651
|
22 |
|
return $this->splits; |
652
|
|
|
} |
653
|
|
|
|
654
|
|
|
|
655
|
|
|
|
656
|
|
|
/** |
657
|
|
|
* @param $id |
658
|
|
|
* |
659
|
|
|
* @return SplitDescriptor|null |
660
|
|
|
* @throws \OldTown\Workflow\Exception\ArgumentNotNumericException |
661
|
|
|
*/ |
662
|
15 |
View Code Duplication |
public function getSplit($id) |
|
|
|
|
663
|
|
|
{ |
664
|
15 |
|
if (!is_numeric($id)) { |
665
|
1 |
|
$errMsg = 'Аргумент должен быть числом'; |
666
|
1 |
|
throw new ArgumentNotNumericException($errMsg); |
667
|
|
|
} |
668
|
14 |
|
$id = (integer)$id; |
669
|
|
|
|
670
|
14 |
|
$splits = $this->getSplits(); |
671
|
14 |
|
foreach ($splits as $splitDescriptor) { |
672
|
13 |
|
if ($id === $splitDescriptor->getId()) { |
673
|
2 |
|
return $splitDescriptor; |
674
|
|
|
} |
675
|
14 |
|
} |
676
|
|
|
|
677
|
14 |
|
return null; |
678
|
|
|
} |
679
|
|
|
|
680
|
|
|
/** |
681
|
|
|
* @param integer $id |
682
|
|
|
* @param FunctionDescriptor $descriptor |
683
|
|
|
* @return $this |
684
|
|
|
* |
685
|
|
|
* @throws \OldTown\Workflow\Exception\ArgumentNotNumericException |
686
|
|
|
*/ |
687
|
3 |
|
public function setTriggerFunction($id, FunctionDescriptor $descriptor) |
688
|
|
|
{ |
689
|
3 |
|
if (!is_numeric($id)) { |
690
|
1 |
|
$errMsg = 'Аргумент должен быть числом'; |
691
|
1 |
|
throw new ArgumentNotNumericException($errMsg); |
692
|
|
|
} |
693
|
2 |
|
$id = (integer)$id; |
694
|
2 |
|
$this->timerFunctions[$id] = $descriptor; |
695
|
|
|
|
696
|
2 |
|
return $this; |
697
|
|
|
} |
698
|
|
|
|
699
|
|
|
/** |
700
|
|
|
* @param integer $id |
701
|
|
|
* @return FunctionDescriptor |
702
|
|
|
* @throws \OldTown\Workflow\Exception\ArgumentNotNumericException |
703
|
|
|
*/ |
704
|
3 |
|
public function getTriggerFunction($id) |
705
|
|
|
{ |
706
|
3 |
|
if (!is_numeric($id)) { |
707
|
1 |
|
$errMsg = 'Аргумент должен быть числом'; |
708
|
1 |
|
throw new ArgumentNotNumericException($errMsg); |
709
|
|
|
} |
710
|
2 |
|
$id = (integer)$id; |
711
|
|
|
|
712
|
2 |
|
if (!array_key_exists($id, $this->timerFunctions)) { |
713
|
1 |
|
$errMsg = sprintf('Не найдена trigger-function с id %s', $id); |
714
|
1 |
|
throw new ArgumentNotNumericException($errMsg); |
715
|
|
|
} |
716
|
|
|
|
717
|
1 |
|
$this->timerFunctions[$id]; |
718
|
|
|
|
719
|
1 |
|
return $this->timerFunctions[$id]; |
720
|
|
|
} |
721
|
|
|
|
722
|
|
|
/** |
723
|
|
|
* @return FunctionDescriptor[] |
724
|
|
|
*/ |
725
|
20 |
|
public function getTriggerFunctions() |
726
|
|
|
{ |
727
|
20 |
|
return $this->timerFunctions; |
728
|
|
|
} |
729
|
|
|
|
730
|
|
|
/** |
731
|
|
|
* @param ActionDescriptor $descriptor |
732
|
|
|
* @return $this |
733
|
|
|
* @throws InvalidArgumentException |
734
|
|
|
* @throws RuntimeException |
735
|
|
|
*/ |
736
|
7 |
|
public function addGlobalAction(ActionDescriptor $descriptor) |
737
|
|
|
{ |
738
|
7 |
|
$this->addAction($this->globalActions, $descriptor); |
739
|
7 |
|
return $this; |
740
|
|
|
} |
741
|
|
|
|
742
|
|
|
/** |
743
|
|
|
* @param ActionDescriptor $descriptor |
744
|
|
|
* @return $this |
745
|
|
|
* @throws InvalidArgumentException |
746
|
|
|
* @throws RuntimeException |
747
|
|
|
*/ |
748
|
49 |
|
public function addInitialAction(ActionDescriptor $descriptor) |
749
|
|
|
{ |
750
|
49 |
|
$this->addAction($this->initialActions, $descriptor); |
751
|
49 |
|
return $this; |
752
|
|
|
} |
753
|
|
|
|
754
|
|
|
|
755
|
|
|
/** |
756
|
|
|
* @param JoinDescriptor $descriptor |
757
|
|
|
* @return $this |
758
|
|
|
* @throws InvalidArgumentException |
759
|
|
|
* @throws \OldTown\Workflow\Exception\ArgumentNotNumericException |
760
|
|
|
*/ |
761
|
14 |
|
public function addJoin(JoinDescriptor $descriptor) |
762
|
|
|
{ |
763
|
14 |
|
$id = $descriptor->getId(); |
764
|
14 |
|
if (null !== $this->getJoin($id)) { |
765
|
1 |
|
$errMsg = sprintf('Объеденение с id %s уже существует', $id); |
766
|
1 |
|
throw new InvalidArgumentException($errMsg); |
767
|
|
|
} |
768
|
|
|
|
769
|
14 |
|
$this->getJoins()->attach($descriptor); |
770
|
14 |
|
return $this; |
771
|
|
|
} |
772
|
|
|
|
773
|
|
|
|
774
|
|
|
/** |
775
|
|
|
* @param SplitDescriptor $descriptor |
776
|
|
|
* @return $this |
777
|
|
|
* @throws InvalidArgumentException |
778
|
|
|
* @throws \OldTown\Workflow\Exception\ArgumentNotNumericException |
779
|
|
|
*/ |
780
|
14 |
|
public function addSplit(SplitDescriptor $descriptor) |
781
|
|
|
{ |
782
|
14 |
|
$id = $descriptor->getId(); |
783
|
14 |
|
if (null !== $this->getSplit($id)) { |
784
|
1 |
|
$errMsg = sprintf('Ветвление с id %s уже существует', $id); |
785
|
1 |
|
throw new InvalidArgumentException($errMsg); |
786
|
|
|
} |
787
|
|
|
|
788
|
14 |
|
$this->getSplits()->attach($descriptor); |
789
|
14 |
|
return $this; |
790
|
|
|
} |
791
|
|
|
|
792
|
|
|
/** |
793
|
|
|
* @param StepDescriptor $descriptor |
794
|
|
|
* @return $this |
795
|
|
|
* |
796
|
|
|
* @throws \OldTown\Workflow\Exception\InvalidArgumentException |
797
|
|
|
* @throws ArgumentNotNumericException |
798
|
|
|
*/ |
799
|
64 |
|
public function addStep(StepDescriptor $descriptor) |
800
|
|
|
{ |
801
|
64 |
|
$id = $descriptor->getId(); |
802
|
64 |
|
if (null !== $this->getStep($id)) { |
803
|
1 |
|
$errMsg = sprintf('Шаг с id %s уже существует', $id); |
804
|
1 |
|
throw new InvalidArgumentException($errMsg); |
805
|
|
|
} |
806
|
|
|
|
807
|
64 |
|
$this->getSteps()->attach($descriptor); |
808
|
64 |
|
return $this; |
809
|
|
|
} |
810
|
|
|
|
811
|
|
|
/** |
812
|
|
|
* Удаление action по id |
813
|
|
|
* |
814
|
|
|
* @param $id |
815
|
|
|
* |
816
|
|
|
* @return bool |
817
|
|
|
*/ |
818
|
2 |
|
public function removeActionActionById($id) |
819
|
|
|
{ |
820
|
2 |
|
$descriptor = $this->getAction($id); |
821
|
|
|
|
822
|
2 |
|
return $this->removeAction($descriptor); |
|
|
|
|
823
|
|
|
} |
824
|
|
|
|
825
|
|
|
/** |
826
|
|
|
* @param ActionDescriptor $actionToRemove |
827
|
|
|
* @return boolean |
828
|
|
|
*/ |
829
|
2 |
|
public function removeAction(ActionDescriptor $actionToRemove) |
830
|
|
|
{ |
831
|
2 |
|
$resultRemove = false; |
832
|
|
|
|
833
|
2 |
|
$actionToRemoveId = $actionToRemove->getId(); |
834
|
2 |
|
$globalActions = $this->getGlobalActions(); |
835
|
2 |
|
foreach ($globalActions as $actionDescriptor) { |
836
|
2 |
|
if ($actionToRemoveId === $actionDescriptor->getId()) { |
837
|
1 |
|
$globalActions->detach($actionDescriptor); |
838
|
|
|
|
839
|
1 |
|
$resultRemove = true; |
840
|
1 |
|
} |
841
|
2 |
|
} |
842
|
|
|
|
843
|
2 |
|
$steps = $this->getSteps(); |
844
|
2 |
|
foreach ($steps as $stepDescriptor) { |
845
|
2 |
|
$actionDescriptor = $stepDescriptor->getAction($actionToRemoveId); |
846
|
|
|
|
847
|
2 |
|
if (null !== $actionDescriptor) { |
848
|
1 |
|
$stepDescriptor->getActions()->detach($actionDescriptor); |
849
|
|
|
|
850
|
1 |
|
$resultRemove = true; |
851
|
1 |
|
} |
852
|
2 |
|
} |
853
|
|
|
|
854
|
2 |
|
return $resultRemove; |
855
|
|
|
} |
856
|
|
|
|
857
|
|
|
|
858
|
|
|
/** |
859
|
|
|
* Создает DOMElement - эквивалентный состоянию дескриптора |
860
|
|
|
* |
861
|
|
|
* @param DOMDocument|null $dom |
862
|
|
|
* |
863
|
|
|
* @return DOMDocument |
864
|
|
|
* @throws InternalWorkflowException |
865
|
|
|
* @throws InvalidDescriptorException |
866
|
|
|
* @throws InvalidWriteWorkflowException |
867
|
|
|
* |
868
|
|
|
*/ |
869
|
17 |
|
public function writeXml(DOMDocument $dom = null) |
870
|
|
|
{ |
871
|
17 |
|
if (null === $dom) { |
872
|
15 |
|
$imp = new DOMImplementation(); |
873
|
15 |
|
$dtd = $imp->createDocumentType( |
874
|
15 |
|
static::DOCUMENT_TYPE_QUALIFIED_NAME, |
875
|
15 |
|
static::DOCUMENT_TYPE_PUBLIC_ID, |
876
|
|
|
static::DOCUMENT_TYPE_SYSTEM_ID |
877
|
15 |
|
); |
878
|
15 |
|
$dom = $imp->createDocument('', '', $dtd); |
879
|
15 |
|
$dom->encoding = 'UTF-8'; |
880
|
15 |
|
$dom->xmlVersion = '1.0'; |
881
|
15 |
|
$dom->formatOutput = true; |
882
|
15 |
|
} |
883
|
|
|
|
884
|
17 |
|
$descriptor = $dom->createElement('workflow'); |
885
|
|
|
|
886
|
17 |
|
$metaAttributes = $this->getMetaAttributes(); |
887
|
17 |
|
$metaElementBase = $dom->createElement('meta'); |
888
|
17 |
View Code Duplication |
foreach ($metaAttributes as $metaAttributeName => $metaAttributeValue) { |
|
|
|
|
889
|
12 |
|
$metaAttributeNameEncode = XmlUtil::encode($metaAttributeName); |
890
|
12 |
|
$metaAttributeValueEnEncode = XmlUtil::encode($metaAttributeValue); |
891
|
|
|
|
892
|
12 |
|
$metaElement = clone $metaElementBase; |
893
|
12 |
|
$metaElement->setAttribute('name', $metaAttributeNameEncode); |
894
|
12 |
|
$metaValueElement = $dom->createTextNode($metaAttributeValueEnEncode); |
895
|
12 |
|
$metaElement->appendChild($metaValueElement); |
896
|
|
|
|
897
|
12 |
|
$descriptor->appendChild($metaElement); |
898
|
17 |
|
} |
899
|
|
|
|
900
|
17 |
|
$registers = $this->getRegisters(); |
901
|
17 |
|
if ($registers->count() > 0) { |
902
|
12 |
|
$registersElement = $dom->createElement('registers'); |
903
|
12 |
|
foreach ($registers as $register) { |
904
|
12 |
|
$registerElement = $register->writeXml($dom); |
905
|
12 |
|
$registersElement->appendChild($registerElement); |
906
|
12 |
|
} |
907
|
|
|
|
908
|
12 |
|
$descriptor->appendChild($registersElement); |
909
|
12 |
|
} |
910
|
|
|
|
911
|
|
|
|
912
|
17 |
|
$timerFunctions = $this->getTriggerFunctions(); |
913
|
17 |
|
if (count($timerFunctions) > 0) { |
914
|
1 |
|
$timerFunctionsElement = $dom->createElement('trigger-functions'); |
915
|
1 |
|
$timerFunctionElementBase = $dom->createElement('trigger-function'); |
916
|
1 |
|
foreach ($timerFunctions as $timerFunctionId => $timerFunction) { |
917
|
1 |
|
$timerFunctionElement = clone $timerFunctionElementBase; |
918
|
1 |
|
$timerFunctionElement->setAttribute('id', $timerFunctionId); |
919
|
|
|
|
920
|
1 |
|
$functionElement = $timerFunction->writeXml($dom); |
921
|
|
|
|
922
|
1 |
|
$timerFunctionElement->appendChild($functionElement); |
923
|
|
|
|
924
|
1 |
|
$timerFunctionsElement->appendChild($timerFunctionElement); |
925
|
1 |
|
} |
926
|
1 |
|
$descriptor->appendChild($timerFunctionsElement); |
927
|
1 |
|
} |
928
|
|
|
|
929
|
|
|
|
930
|
17 |
|
$globalConditions = $this->getGlobalConditions(); |
931
|
17 |
|
if (null !== $globalConditions) { |
932
|
1 |
|
$globalConditionsElement = $dom->createElement('global-conditions'); |
933
|
1 |
|
$globalConditionElement = $globalConditions->writeXml($dom); |
934
|
1 |
|
$globalConditionsElement->appendChild($globalConditionElement); |
935
|
1 |
|
$descriptor->appendChild($globalConditionsElement); |
936
|
1 |
|
} |
937
|
|
|
|
938
|
|
|
|
939
|
17 |
|
$initialActionsElement = $dom->createElement('initial-actions'); |
940
|
17 |
|
$initialActions = $this->getInitialActions(); |
941
|
17 |
|
foreach ($initialActions as $initialAction) { |
942
|
13 |
|
$initialActionElement = $initialAction->writeXml($dom); |
943
|
13 |
|
$initialActionsElement->appendChild($initialActionElement); |
944
|
17 |
|
} |
945
|
17 |
|
$descriptor->appendChild($initialActionsElement); |
946
|
|
|
|
947
|
|
|
|
948
|
17 |
|
$globalActions = $this->getGlobalActions(); |
949
|
17 |
|
if ($globalActions->count() > 0) { |
950
|
1 |
|
$globalActionsElement = $dom->createElement('global-actions'); |
951
|
1 |
|
foreach ($globalActions as $globalAction) { |
952
|
1 |
|
$globalActionElement = $globalAction->writeXml($dom); |
953
|
|
|
|
954
|
1 |
|
$globalActionsElement->appendChild($globalActionElement); |
955
|
1 |
|
} |
956
|
|
|
|
957
|
1 |
|
$descriptor->appendChild($globalActionsElement); |
958
|
1 |
|
} |
959
|
|
|
|
960
|
17 |
|
$commonActions = $this->getCommonActions(); |
961
|
17 |
|
if (count($commonActions) > 0) { |
962
|
3 |
|
$commonActionsElement = $dom->createElement('common-actions'); |
963
|
3 |
|
foreach ($commonActions as $commonAction) { |
964
|
3 |
|
$commonActionElement = $commonAction->writeXml($dom); |
965
|
3 |
|
$commonActionsElement->appendChild($commonActionElement); |
966
|
3 |
|
} |
967
|
|
|
|
968
|
3 |
|
$descriptor->appendChild($commonActionsElement); |
969
|
3 |
|
} |
970
|
|
|
|
971
|
|
|
|
972
|
17 |
|
$stepsElement = $dom->createElement('steps'); |
973
|
17 |
|
$steps = $this->getSteps(); |
974
|
17 |
|
foreach ($steps as $step) { |
975
|
14 |
|
$stepElement = $step->writeXml($dom); |
976
|
14 |
|
$stepsElement->appendChild($stepElement); |
977
|
17 |
|
} |
978
|
|
|
|
979
|
17 |
|
$descriptor->appendChild($stepsElement); |
980
|
|
|
|
981
|
17 |
|
$splits = $this->getSplits(); |
982
|
17 |
|
if ($splits->count() > 0) { |
983
|
12 |
|
$splitsElement = $dom->createElement('splits'); |
984
|
12 |
|
foreach ($splits as $split) { |
985
|
12 |
|
$splitElement = $split->writeXml($dom); |
986
|
12 |
|
$splitsElement->appendChild($splitElement); |
987
|
12 |
|
} |
988
|
|
|
|
989
|
12 |
|
$descriptor->appendChild($splitsElement); |
990
|
12 |
|
} |
991
|
|
|
|
992
|
17 |
|
$joins = $this->getJoins(); |
993
|
17 |
|
if ($joins->count() > 0) { |
994
|
12 |
|
$joinsElement = $dom->createElement('joins'); |
995
|
12 |
|
foreach ($joins as $join) { |
996
|
12 |
|
$joinElement = $join->writeXml($dom); |
997
|
12 |
|
$joinsElement->appendChild($joinElement); |
998
|
12 |
|
} |
999
|
|
|
|
1000
|
12 |
|
$descriptor->appendChild($joinsElement); |
1001
|
12 |
|
} |
1002
|
|
|
|
1003
|
17 |
|
$dom->appendChild($descriptor); |
1004
|
17 |
|
return $dom; |
|
|
|
|
1005
|
|
|
} |
1006
|
|
|
} |
1007
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.