TaskEntity::deleteUserIdentityLink()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 2
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 2
nc 2
nop 2
1
<?php
2
3
namespace Jabe\Impl\Persistence\Entity;
4
5
use Jabe\{
6
    ProcessEngineInterface,
7
    ProcessEngineException,
8
    ProcessEngineServicesInterface
9
};
10
use Jabe\Delegate\{
11
    BpmnError,
12
    DelegateTaskInterface,
13
    ExpressionInterface,
14
    TaskListenerInterface
15
};
16
use Jabe\Exception\{
17
    NotFoundException,
18
    NullValueException
19
};
20
use Jabe\Form\FormRefInterface;
21
use Jabe\History\UserOperationLogEntryInterface;
22
use Jabe\Impl\ProcessEngineLogger;
23
use Jabe\Impl\Bpmn\Helper\{
24
    BpmnExceptionHandler,
25
    ErrorPropagationException,
26
    EscalationHandler
27
};
28
use Jabe\Impl\Cfg\ProcessEngineConfigurationImpl;
29
use Jabe\Impl\Cfg\Auth\ResourceAuthorizationProviderInterface;
30
use Jabe\Impl\Context\Context;
31
use Jabe\Impl\Core\Instance\CoreExecution;
32
use Jabe\Impl\Core\Variable\Event\VariableEvent;
33
use Jabe\Impl\Core\Variable\Scope\{
34
    AbstractVariableScope,
35
    VariableInstanceFactoryInterface,
36
    VariableInstanceLifecycleListenerInterface,
37
    VariableStore,
38
    VariablesProviderInterface
39
};
40
use Jabe\Impl\Db\{
41
    DbEntityInterface,
42
    EnginePersistenceLogger,
43
    HasDbReferencesInterface,
44
    HasDbRevisionInterface
45
};
46
use Jabe\Impl\Form\FormRefImpl;
47
use Jabe\Impl\Form\Handler\DefaultFormHandler;
48
use Jabe\Impl\History\Event\HistoryEventTypes;
49
use Jabe\Impl\Interceptor\{
50
    CommandContext,
51
    CommandContextListenerInterface,
52
    CommandInvocationContext
53
};
54
use Jabe\Impl\Pvm\Delegate\ActivityExecution;
55
use Jabe\Impl\Pvm\Runtime\PvmExecutionImpl;
56
use Jabe\Impl\Task\TaskDefinition;
57
use Jabe\Impl\Task\Delegate\TaskListenerInvocation;
58
use Jabe\Impl\Util\{
59
    ClockUtil,
60
    EnsureUtil
61
};
62
use Jabe\Management\Metrics;
63
use Jabe\Task\{
64
    DelegationState,
65
    IdentityLinkInterface,
66
    IdentityLinkType,
67
    TaskInterface
68
};
69
use Bpmn\BpmnModelInstanceInterface;
70
use Bpmn\Instance\UserTaskInterface;
71
72
class TaskEntity extends AbstractVariableScope implements TaskInterface, DelegateTaskInterface, \Serializable, DbEntityInterface, HasDbRevisionInterface, HasDbReferencesInterface, CommandContextListenerInterface, VariablesProviderInterface
73
{
74
    protected static $DEFAULT_VARIABLE_LIFECYCLE_LISTENERS;
75
76
    //protected static final EnginePersistenceLogger LOG = ProcessEngineLogger.PERSISTENCE_LOGGER;
77
78
    public const DELETE_REASON_COMPLETED = "completed";
79
    public const DELETE_REASON_DELETED   = "deleted";
80
81
    protected $id;
82
    protected $revision;
83
84
    protected $owner;
85
    protected $assignee;
86
    protected $delegationState;
87
88
    protected $parentTaskId;
89
    protected $parentTask;
90
91
    protected $name;
92
    protected $description;
93
    protected $priority = TaskInterface::PRIORITY_NORMAL;
94
    protected $createTime; // The time when the task has been created
95
    protected $dueDate;
96
    protected $followUpDate;
97
    protected $suspensionState;
98
    protected $lifecycleState = TaskState::STATE_INIT;
99
    protected $tenantId;
100
101
    protected $isIdentityLinksInitialized = false;
102
    protected $taskIdentityLinkEntities = [];
103
104
    // execution
105
    protected $executionId;
106
    protected $execution;
107
108
    protected $processInstanceId;
109
    protected $processInstance;
110
111
    protected $processDefinitionId;
112
113
    // caseExecution
114
    /*protected String caseExecutionId;
115
    protected transient CaseExecutionEntity caseExecution;
116
117
    protected String caseInstanceId;
118
    protected String caseDefinitionId;*/
119
120
    // taskDefinition
121
    protected $taskDefinition;
122
    protected $taskDefinitionKey;
123
124
    protected $isDeleted;
125
    protected $deleteReason;
126
127
    protected $eventName;
128
    protected $isFormKeyInitialized = false;
129
    protected $formKey;
130
    protected $formRef;
131
132
    protected $variableStore;
133
134
    protected $skipCustomListeners = false;
135
136
    /**
137
     * contains all changed properties of this entity
138
     */
139
    protected $propertyChanges = [];
140
141
    protected $identityLinkChanges = [];
142
143
    protected $customLifecycleListeners;
144
145
    // name references of tracked properties
146
    public const ASSIGNEE = "assignee";
147
    public const DELEGATION = "delegation";
148
    public const DELETE = "delete";
149
    public const DESCRIPTION = "description";
150
    public const DUE_DATE = "dueDate";
151
    public const FOLLOW_UP_DATE = "followUpDate";
152
    public const NAME = "name";
153
    public const OWNER = "owner";
154
    public const PARENT_TASK = "parentTask";
155
    public const PRIORITY = "priority";
156
    public const CASE_INSTANCE_ID = "caseInstanceId";
157
158
    public function __construct($data = null)
159
    {
160
        if (is_string($data)) {
161
            $this->id = $data;
162
            $this->isIdentityLinksInitialized = true;
163
            $this->setCreateTime(ClockUtil::getCurrentTime()->format('c'));
164
            $this->lifecycleState = TaskState::STATE_INIT;
165
        } elseif (is_int($data)) {
166
            $this->isIdentityLinksInitialized = true;
167
            $this->setCreateTime(ClockUtil::getCurrentTime()->format('c'));
168
            $this->lifecycleState = $data;
169
        } elseif ($data instanceof ExecutionEntity) {
170
            $this->isIdentityLinksInitialized = true;
171
            $this->setCreateTime(ClockUtil::getCurrentTime()->format('c'));
172
            $this->lifecycleState = TaskState::STATE_INIT;
173
            $this->setExecution($data);
174
            $this->skipCustomListeners = $data->isSkipCustomListeners();
175
            $this->setTenantId($this->execution->getTenantId());
0 ignored issues
show
Bug introduced by
The method getTenantId() does not exist on null. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

175
            $this->setTenantId($this->execution->/** @scrutinizer ignore-call */ getTenantId());

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
176
            $this->execution->addTask($this);
177
        } elseif ($data === null) {
178
            $this->lifecycleState = TaskState::STATE_CREATED;
179
            $this->variableStore = new VariableStore($this, new TaskEntityReferencer($this));
180
            $this->suspensionState = SuspensionState::active()->getStateCode();
181
        }
182
        if (self::$DEFAULT_VARIABLE_LIFECYCLE_LISTENERS === null) {
183
            self::$DEFAULT_VARIABLE_LIFECYCLE_LISTENERS = [
184
                VariableInstanceEntityPersistenceListener::instance(),
185
                VariableInstanceSequenceCounterListener::instance(),
186
                VariableInstanceHistoryListener::instance()
187
            ];
188
        }
189
    }
190
191
    /**
192
     * CMMN execution constructor
193
     */
194
    /*public TaskEntity(CaseExecutionEntity caseExecution) {
195
        this(TaskState::STATE_INIT);
196
        setCaseExecution(caseExecution);
197
    }*/
198
199
    public function insert(): void
200
    {
201
        $commandContext = Context::getCommandContext();
202
        $taskManager = $commandContext->getTaskManager();
203
        $taskManager->insertTask($this);
204
    }
205
206
    protected function propagateExecutionTenantId(?ExecutionEntity $execution): void
207
    {
208
        if ($execution !== null) {
209
            $this->setTenantId($execution->getTenantId());
210
        }
211
    }
212
213
    public function propagateParentTaskTenantId(): void
214
    {
215
        if ($this->parentTaskId !== null) {
216
            $parentTask = Context::getCommandContext()
217
                ->getTaskManager()
218
                ->findTaskById($this->parentTaskId);
219
220
            if ($this->tenantId !== null && !$this->tenantIdIsSame($parentTask)) {
221
                //throw LOG.cannotSetDifferentTenantIdOnSubtask(parentTaskId, parentTask->getTenantId(), tenantId);
222
                throw new \Exception("propagateParentTaskTenantId");
223
            }
224
225
            $this->setTenantId($parentTask->getTenantId());
226
        }
227
    }
228
229
    public function update(): void
230
    {
231
        $this->ensureTenantIdNotChanged();
232
233
        $this->registerCommandContextCloseListener();
234
235
        $commandContext = Context::getCommandContext();
236
        $dbEntityManger = $commandContext->getDbEntityManager();
237
238
        $dbEntityManger->merge($this);
239
    }
240
241
    protected function ensureTenantIdNotChanged(): void
242
    {
243
        $persistentTask = Context::getCommandContext()->getTaskManager()->findTaskById($this->id);
244
245
        if ($persistentTask !== null) {
246
            $changed = !$this->tenantIdIsSame($persistentTask);
247
248
            if ($changed) {
249
                //throw LOG.cannotChangeTenantIdOfTask(id, persistentTask.tenantId, tenantId);
250
                throw new \Exception("ensureTenantIdNotChanged");
251
            }
252
        }
253
    }
254
255
    protected function tenantIdIsSame(TaskEntity $otherTask): bool
256
    {
257
        $otherTenantId = $otherTask->getTenantId();
258
259
        if ($otherTenantId === null) {
260
            return $this->tenantId === null;
261
        } else {
262
            return $otherTenantId == $this->tenantId;
263
        }
264
    }
265
266
    public function complete(): void
267
    {
268
        if (
269
            TaskState::STATE_COMPLETED == $this->lifecycleState
270
            || TaskListenerInterface::EVENTNAME_COMPLETE == $this->eventName
271
            || TaskListenerInterface::EVENTNAME_DELETE == $this->eventName
272
        ) {
273
            //throw LOG.invokeTaskListenerException(new IllegalStateException("invalid task state"));
274
            throw new \Exception("invalid task state");
275
        }
276
        // if the task is associated with a case
277
        // execution then call complete on the
278
        // associated case execution. The case
279
        // execution handles the completion of
280
        // the task.
281
        /*if (caseExecutionId !== null) {
282
            getCaseExecution().manualComplete();
283
            return;
284
        }*/
285
286
        // in the other case:
287
288
        // ensure the the Task is not suspended
289
        $this->ensureTaskActive();
290
291
        // trigger TaskListenerInterface::complete event
292
        $shouldDeleteTask = $this->transitionTo(TaskState::STATE_COMPLETED);
293
294
        // shouldn't attempt to delete the task if the COMPLETE Task listener failed,
295
        // or managed to cancel the Process or Task Instance
296
        if ($shouldDeleteTask) {
297
            // delete the task
298
            // this method call doesn't invoke additional task listeners
299
            Context::getCommandContext()
300
            ->getTaskManager()
301
            ->deleteTask($this, TaskEntity::DELETE_REASON_COMPLETED, false, $this->skipCustomListeners);
302
303
            // if the task is associated with a
304
            // execution (and not a case execution)
305
            // and it's still in the same activity
306
            // then call signal an the associated
307
            // execution.
308
            if ($this->executionId !== null) {
309
                $execution = $this->getExecution();
310
                $execution->removeTask($this);
311
                $execution->signal(null, null);
0 ignored issues
show
Bug introduced by
null of type null is incompatible with the type string expected by parameter $signalName of Jabe\Impl\Pvm\Runtime\PvmExecutionImpl::signal(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

311
                $execution->signal(/** @scrutinizer ignore-type */ null, null);
Loading history...
312
            }
313
        }
314
    }
315
316
    /*public function caseExecutionCompleted(): void
317
    {
318
        // ensure the the Task is not suspended
319
        ensureTaskActive();
320
321
        // trigger TaskListenerInterface::complete event for a case execution associated task
322
        transitionTo(TaskState::STATE_COMPLETED);
323
324
        // delete the task
325
        Context
326
            ->getCommandContext()
327
            ->getTaskManager()
328
            ->deleteTask(this, TaskEntity::DELETE_REASON_COMPLETED, false, false);
329
    }*/
330
331
    public function delete(string $deleteReason, bool $cascade, ?bool $skipCustomListeners = null): void
332
    {
333
        if ($skipCustomListeners !== null) {
334
            $this->skipCustomListeners = $skipCustomListeners;
335
        }
336
337
        $this->deleteReason = $deleteReason;
338
339
        // only fire lifecycle events if task is actually cancelled/deleted
340
        if (
341
            !TaskEntity::DELETE_REASON_COMPLETED == $deleteReason
342
            && !TaskState::STATE_DELETED == $this->lifecycleState
343
        ) {
344
            $this->transitionTo(TaskState::STATE_DELETED);
345
        }
346
347
        Context::getCommandContext()
348
            ->getTaskManager()
349
            ->deleteTask($this, $deleteReason, $cascade, $this->skipCustomListeners);
350
351
        if ($this->executionId !== null) {
352
            $execution = $this->getExecution();
353
            $execution->removeTask($this);
354
        }
355
    }
356
357
    public function delegate(string $userId): void
358
    {
359
        $this->setDelegationState(DelegationState::PENDING);
360
        if ($this->getOwner() === null) {
0 ignored issues
show
introduced by
The condition $this->getOwner() === null is always false.
Loading history...
361
            $this->setOwner($this->getAssignee());
362
        }
363
        $this->setAssignee($userId);
364
    }
365
366
    public function resolve(): void
367
    {
368
        $this->setDelegationState(DelegationState::RESOLVED);
369
        $this->setAssignee($this->owner);
370
    }
371
372
    public function serialize()
373
    {
374
        return json_encode([
375
            'id' => $this->id,
376
            'name' => $this->name,
377
            'revision' => $this->revision,
378
            'assignee' => $this->assignee,
379
            'owner' => $this->owner,
380
            'priority' => $this->priority,
381
            'executionId' => $this->executionId,
382
            'processDefinitionId' => $this->processDefinitionId,
383
            'createTime' => $this->createTime,
384
            'description' => $this->description,
385
            'dueDate' => $this->dueDate,
386
            'followUpDate' => $this->followUpDate,
387
            'parentTaskId' => $this->parentTaskId,
388
            'delegationState' => $this->delegationState,
389
            'tenantId' => $this->tenantId,
390
            'suspensionState' => $this->suspensionState
391
        ]);
392
    }
393
394
    public function unserialize($data)
395
    {
396
        $json = json_decode($data);
397
        $this->id = $json->id;
398
        $this->name = $json->name;
399
        $this->revision = $json->revision;
400
        $this->assignee = $json->assignee;
401
        $this->owner = $json->owner;
402
        $this->priority = $json->priority;
403
        $this->executionId = $json->executionId;
404
        $this->processDefinitionId = $json->processDefinitionId;
405
        $this->createTime = $json->createTime;
406
        $this->description = $json->description;
407
        $this->dueDate = $json->dueDate;
408
        $this->followUpDate = $json->followUpDate;
409
        $this->parentTaskId = $json->parentTaskId;
410
        $this->delegationState = $json->delegationState;
411
        $this->tenantId = $json->tenantId;
412
        $this->suspensionState = $json->suspensionState;
413
    }
414
415
    public function getPersistentState()
416
    {
417
        $persistentState = [];
418
        $persistentState["assignee"] = $this->assignee;
419
        $persistentState["owner"] = $this->owner;
420
        $persistentState["name"] = $this->name;
421
        $persistentState["priority"] = $this->priority;
422
        if ($this->executionId !== null) {
423
            $persistentState["executionId"] = $this->executionId;
424
        }
425
        if ($this->processDefinitionId !== null) {
426
            $persistentState["processDefinitionId"] = $this->processDefinitionId;
427
        }
428
        /*if (caseExecutionId !== null) {
429
            persistentState.put("caseExecutionId", $this->caseExecutionId);
430
        }
431
        if (caseInstanceId !== null) {
432
            persistentState.put("caseInstanceId", $this->caseInstanceId);
433
        }
434
        if (caseDefinitionId !== null) {
435
            persistentState.put("caseDefinitionId", $this->caseDefinitionId);
436
        }*/
437
        if ($this->createTime !== null) {
438
            $persistentState["createTime"] = $this->createTime;
439
        }
440
        if ($this->description !== null) {
441
            $persistentState["description"] = $this->description;
442
        }
443
        if ($this->dueDate !== null) {
444
            $persistentState["dueDate"] = $this->dueDate;
445
        }
446
        if ($this->followUpDate !== null) {
447
            $persistentState["followUpDate"] = $this->followUpDate;
448
        }
449
        if ($this->parentTaskId !== null) {
450
            $persistentState["parentTaskId"] = $this->parentTaskId;
451
        }
452
        if ($this->delegationState !== null) {
453
            $persistentState["delegationState"] = $this->delegationState;
454
        }
455
        if ($this->tenantId !== null) {
456
            $persistentState["tenantId"] = $this->tenantId;
457
        }
458
459
        $persistentState["suspensionState"] = $this->suspensionState;
460
461
        return $persistentState;
462
    }
463
464
    public function getRevisionNext(): int
465
    {
466
        return $this->revision + 1;
467
    }
468
469
    public function ensureParentTaskActive(): void
470
    {
471
        if ($this->parentTaskId !== null) {
472
            $parentTask = Context::getCommandContext()
473
                ->getTaskManager()
474
                ->findTaskById($this->parentTaskId);
475
476
            EnsureUtil::ensureNotNull(\Exception::class, "Parent task with id '" . $this->parentTaskId . "' does not exist", "parentTask", $parentTask);
477
478
            if ($parentTask->suspensionState == SuspensionState::suspended()->getStateCode()) {
479
                //throw LOG.suspendedEntityException("parent task", id);
480
                throw new \Exception("ensureParentTaskActive");
481
            }
482
        }
483
    }
484
485
    protected function ensureTaskActive(): void
486
    {
487
        if ($this->suspensionState == SuspensionState::suspended()->getStateCode()) {
488
            //throw LOG.suspendedEntityException("task", id);
489
            throw new \Exception("ensureTaskActive");
490
        }
491
    }
492
493
    public function getBpmnModelElementInstance(): ?UserTaskInterface
494
    {
495
        $bpmnModelInstance = $this->getBpmnModelInstance();
496
        if ($bpmnModelInstance !== null) {
497
            $modelElementInstance = $bpmnModelInstance->getModelElementById($this->taskDefinitionKey);
498
            try {
499
                return $modelElementInstance;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $modelElementInstance could return the type Xml\Instance\ModelElementInstanceInterface which includes types incompatible with the type-hinted return Bpmn\Instance\UserTaskInterface|null. Consider adding an additional type-check to rule them out.
Loading history...
500
            } catch (\Exception $e) {
0 ignored issues
show
Unused Code introduced by
catch (\Exception $e) is not reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
501
                $elementType = $modelElementInstance->getElementType();
502
                //throw LOG.castModelInstanceException(modelElementInstance, "UserTask", elementType->getTypeName(),
503
                //    elementType->getTypeNamespace(), e);
504
                throw $e;
505
            }
506
        } else {
507
            return null;
0 ignored issues
show
Bug Best Practice introduced by
The expression return null returns the type null which is incompatible with the return type mandated by Jabe\Delegate\DelegateTa...nModelElementInstance() of Bpmn\Instance\UserTaskInterface.

In the issue above, the returned value is violating the contract defined by the mentioned interface.

Let's take a look at an example:

interface HasName {
    /** @return string */
    public function getName();
}

class Name {
    public $name;
}

class User implements HasName {
    /** @return string|Name */
    public function getName() {
        return new Name('foo'); // This is a violation of the ``HasName`` interface
                                // which only allows a string value to be returned.
    }
}
Loading history...
508
        }
509
    }
510
511
    public function getBpmnModelInstance(): ?BpmnModelInstanceInterface
512
    {
513
        if ($this->processDefinitionId !== null) {
514
            return Context::getProcessEngineConfiguration()
515
            ->getDeploymentCache()
0 ignored issues
show
Bug introduced by
The method getDeploymentCache() does not exist on Jabe\Impl\Cfg\ProcessEngineConfigurationImpl. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

515
            ->/** @scrutinizer ignore-call */ getDeploymentCache()

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
516
            ->findBpmnModelInstanceForProcessDefinition($this->processDefinitionId);
517
        } else {
518
            return null;
0 ignored issues
show
Bug Best Practice introduced by
The expression return null returns the type null which is incompatible with the return type mandated by Jabe\Delegate\BpmnModelE...:getBpmnModelInstance() of Bpmn\BpmnModelInstanceInterface.

In the issue above, the returned value is violating the contract defined by the mentioned interface.

Let's take a look at an example:

interface HasName {
    /** @return string */
    public function getName();
}

class Name {
    public $name;
}

class User implements HasName {
    /** @return string|Name */
    public function getName() {
        return new Name('foo'); // This is a violation of the ``HasName`` interface
                                // which only allows a string value to be returned.
    }
}
Loading history...
519
        }
520
    }
521
522
    // variables ////////////////////////////////////////////////////////////////
523
524
    protected function getVariableStore(): VariableStore
525
    {
526
        return $this->variableStore;
527
    }
528
529
    protected function getVariableInstanceFactory(): VariableInstanceFactoryInterface
530
    {
531
        return VariableInstanceEntityFactory::instance();
532
    }
533
534
    protected function getVariableInstanceLifecycleListeners(): array
535
    {
536
        if (empty($this->customLifecycleListeners)) {
537
            return self::$DEFAULT_VARIABLE_LIFECYCLE_LISTENERS;
538
        } else {
539
            $listeners = array_merge([], self::$DEFAULT_VARIABLE_LIFECYCLE_LISTENERS);
540
            $listeners = array_merge($listeners, $this->customLifecycleListeners);
541
            return $listeners;
542
        }
543
    }
544
545
    public function addCustomLifecycleListener(VariableInstanceLifecycleListenerInterface $customLifecycleListener): void
546
    {
547
        if ($this->customLifecycleListeners === null) {
548
            $this->customLifecycleListeners = [];
549
        }
550
551
        $this->customLifecycleListeners[] = $customLifecycleListener;
552
    }
553
554
    public function removeCustomLifecycleListener(
555
        VariableInstanceLifecycleListenerInterface $customLifecycleListener
556
    ): VariableInstanceLifecycleListenerInterface {
557
        if ($this->customLifecycleListeners !== null) {
558
            foreach ($this->customLifecycleListeners as $key => $listener) {
559
                if ($listener == $customLifecycleListener) {
560
                    unset($this->customLifecycleListeners[$key]);
561
                }
562
            }
563
        }
564
565
        return $customLifecycleListener;
566
    }
567
568
    public function dispatchEvent(VariableEvent $variableEvent): void
569
    {
570
        if ($this->execution !== null && $variableEvent->getVariableInstance()->getTaskId() === null) {
0 ignored issues
show
introduced by
The condition $variableEvent->getVaria...)->getTaskId() === null is always false.
Loading history...
571
            $this->execution->handleConditionalEventOnVariableChange($variableEvent);
572
        }
573
    }
574
575
    public function provideVariables(?array $variableNames = null): array
576
    {
577
        if (empty($variableNames)) {
578
            return Context::getCommandContext()
579
            ->getVariableInstanceManager()
580
            ->findVariableInstancesByTaskId($this->id);
581
        } else {
582
            return Context::getCommandContext()
583
                ->getVariableInstanceManager()
584
                ->findVariableInstancesByTaskIdAndVariableNames($this->id, $variableNames);
585
        }
586
    }
587
588
    public function getParentVariableScope(): ?AbstractVariableScope
589
    {
590
        if ($this->getExecution() !== null) {
591
            return $this->execution;
592
        }
593
        /*if ($this->getCaseExecution()!=null) {
594
            return caseExecution;
595
        }*/
596
        if ($this->getParentTask() !== null) {
597
            return $this->parentTask;
598
        }
599
        return null;
600
    }
601
602
    public function getVariableScopeKey(): string
603
    {
604
        return "task";
605
    }
606
607
    // execution ////////////////////////////////////////////////////////////////
608
609
    public function getParentTask(): TaskEntity
610
    {
611
        if ($this->parentTask === null && $this->parentTaskId !== null) {
612
            $this->parentTask = Context::getCommandContext()
613
                                    ->getTaskManager()
614
                                    ->findTaskById($this->parentTaskId);
615
        }
616
        return $this->parentTask;
617
    }
618
619
    public function getExecution(): ExecutionEntity
620
    {
621
        if (($this->execution === null) && ($this->executionId !== null)) {
622
            $this->execution = Context::getCommandContext()
623
            ->getExecutionManager()
624
            ->findExecutionById($this->executionId);
625
        }
626
        return $this->execution;
627
    }
628
629
    public function setExecution(PvmExecutionImpl $execution): void
630
    {
631
        if ($this->execution !== null) {
632
            $this->execution = $execution;
633
            $this->executionId = $this->execution->getId();
634
            $this->processInstanceId = $this->execution->getProcessInstanceId();
635
            $this->processDefinitionId = $this->execution->getProcessDefinitionId();
636
637
            // get the process instance
638
            $instance = $this->execution->getProcessInstance();
639
            if ($instance !== null) {
640
                // set case instance id on this task
641
                //$this->caseInstanceId = instance->getCaseInstanceId();
642
            }
643
        } else {
644
            $this->execution = null;
645
            $this->executionId = null;
646
            $this->processInstanceId = null;
647
            $this->processDefinitionId = null;
648
            //$this->caseInstanceId = null;
649
        }
650
    }
651
652
    // case execution ////////////////////////////////////////////////////////////////
653
654
    /*public CaseExecutionEntity getCaseExecution() {
655
        ensureCaseExecutionInitialized();
656
        return caseExecution;
657
    }
658
659
    protected void ensureCaseExecutionInitialized() {
660
        if ((caseExecution==null) && (caseExecutionId!=null) ) {
661
            caseExecution = Context
662
            ->getCommandContext()
663
            ->getCaseExecutionManager()
664
            ->findCaseExecutionById(caseExecutionId);
665
        }
666
    }
667
668
    public void setCaseExecution(CaseExecutionEntity caseExecution) {
669
        if (caseExecution!=null) {
670
671
            $this->caseExecution = caseExecution;
672
            $this->caseExecutionId = $this->caseExecution->getId();
673
            $this->caseInstanceId = $this->caseExecution->getCaseInstanceId();
674
            $this->caseDefinitionId = $this->caseExecution->getCaseDefinitionId();
675
            $this->tenantId = $this->caseExecution->getTenantId();
676
677
        } else {
678
            $this->caseExecution = null;
679
            $this->caseExecutionId = null;
680
            $this->caseInstanceId = null;
681
            $this->caseDefinitionId = null;
682
            $this->tenantId = null;
683
        }
684
    }
685
686
    public String getCaseExecutionId() {
687
        return caseExecutionId;
688
    }
689
690
    public void setCaseExecutionId(string $caseExecutionId) {
691
        $this->caseExecutionId = caseExecutionId;
692
    }
693
694
    public String getCaseInstanceId() {
695
        return caseInstanceId;
696
    }
697
698
    public void setCaseInstanceId(string $caseInstanceId) {
699
        registerCommandContextCloseListener();
700
        propertyChanged(CASE_INSTANCE_ID, $this->caseInstanceId, caseInstanceId);
701
        $this->caseInstanceId = caseInstanceId;
702
    }
703
704
    public CaseDefinitionEntity getCaseDefinition() {
705
        if (caseDefinitionId !== null) {
706
            return Context
707
                ->getProcessEngineConfiguration()
708
                ->getDeploymentCache()
709
                ->findDeployedCaseDefinitionById(caseDefinitionId);
710
        }
711
        return null;
712
    }
713
714
    public String getCaseDefinitionId() {
715
        return caseDefinitionId;
716
    }
717
718
    public void setCaseDefinitionId(string $caseDefinitionId) {
719
        $this->caseDefinitionId = caseDefinitionId;
720
    }*/
721
722
    // task assignment //////////////////////////////////////////////////////////
723
724
    public function addIdentityLink(?string $userId, ?string $groupId, string $type): IdentityLinkEntity
725
    {
726
        $this->ensureTaskActive();
727
728
        $identityLink = $this->newIdentityLink($userId, $groupId, $type);
0 ignored issues
show
Bug introduced by
It seems like $userId can also be of type null; however, parameter $userId of Jabe\Impl\Persistence\En...tity::newIdentityLink() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

728
        $identityLink = $this->newIdentityLink(/** @scrutinizer ignore-type */ $userId, $groupId, $type);
Loading history...
Bug introduced by
It seems like $groupId can also be of type null; however, parameter $groupId of Jabe\Impl\Persistence\En...tity::newIdentityLink() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

728
        $identityLink = $this->newIdentityLink($userId, /** @scrutinizer ignore-type */ $groupId, $type);
Loading history...
729
        $identityLink->insert();
730
        $this->getIdentityLinks();
731
        $this->taskIdentityLinkEntities[] = $identityLink;
732
733
        $this->fireAddIdentityLinkAuthorizationProvider($type, $userId, $groupId);
0 ignored issues
show
Bug introduced by
It seems like $groupId can also be of type null; however, parameter $groupId of Jabe\Impl\Persistence\En...AuthorizationProvider() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

733
        $this->fireAddIdentityLinkAuthorizationProvider($type, $userId, /** @scrutinizer ignore-type */ $groupId);
Loading history...
Bug introduced by
It seems like $userId can also be of type null; however, parameter $userId of Jabe\Impl\Persistence\En...AuthorizationProvider() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

733
        $this->fireAddIdentityLinkAuthorizationProvider($type, /** @scrutinizer ignore-type */ $userId, $groupId);
Loading history...
734
        return $identityLink;
735
    }
736
737
    public function fireIdentityLinkHistoryEvents(string $userId, string $groupId, string $type, HistoryEventTypes $historyEventType): void
738
    {
739
        $identityLinkEntity = newIdentityLink($userId, $groupId, $type);
0 ignored issues
show
Unused Code introduced by
The assignment to $identityLinkEntity is dead and can be removed.
Loading history...
Bug introduced by
The function newIdentityLink was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

739
        $identityLinkEntity = /** @scrutinizer ignore-call */ newIdentityLink($userId, $groupId, $type);
Loading history...
740
        $this->identityLinkEntity->fireHistoricIdentityLinkEvent($historyEventType);
0 ignored issues
show
Bug introduced by
The property identityLinkEntity does not exist on Jabe\Impl\Persistence\Entity\TaskEntity. Did you mean identityLinkChanges?
Loading history...
741
    }
742
743
    public function newIdentityLink(string $userId, string $groupId, string $type): IdentityLinkEntity
744
    {
745
        $identityLinkEntity = new IdentityLinkEntity();
746
        $identityLinkEntity->setTask($this);
747
        $identityLinkEntity->setUserId($userId);
748
        $identityLinkEntity->setGroupId($groupId);
749
        $identityLinkEntity->setType($type);
750
        $identityLinkEntity->setTenantId($this->getTenantId());
751
        return $identityLinkEntity;
752
    }
753
754
    public function deleteIdentityLink(?string $userId, ?string $groupId, string $type): void
755
    {
756
        $this->ensureTaskActive();
757
758
        $identityLinks = Context::getCommandContext()
759
            ->getIdentityLinkManager()
760
            ->findIdentityLinkByTaskUserGroupAndType($this->id, $userId, $groupId, $type);
0 ignored issues
show
Bug introduced by
It seems like $userId can also be of type null; however, parameter $userId of Jabe\Impl\Persistence\En...yTaskUserGroupAndType() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

760
            ->findIdentityLinkByTaskUserGroupAndType($this->id, /** @scrutinizer ignore-type */ $userId, $groupId, $type);
Loading history...
Bug introduced by
It seems like $groupId can also be of type null; however, parameter $groupId of Jabe\Impl\Persistence\En...yTaskUserGroupAndType() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

760
            ->findIdentityLinkByTaskUserGroupAndType($this->id, $userId, /** @scrutinizer ignore-type */ $groupId, $type);
Loading history...
761
762
        foreach ($identityLinks as $identityLink) {
763
            $this->fireDeleteIdentityLinkAuthorizationProvider($type, $userId, $groupId);
0 ignored issues
show
Bug introduced by
It seems like $userId can also be of type null; however, parameter $userId of Jabe\Impl\Persistence\En...AuthorizationProvider() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

763
            $this->fireDeleteIdentityLinkAuthorizationProvider($type, /** @scrutinizer ignore-type */ $userId, $groupId);
Loading history...
Bug introduced by
It seems like $groupId can also be of type null; however, parameter $groupId of Jabe\Impl\Persistence\En...AuthorizationProvider() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

763
            $this->fireDeleteIdentityLinkAuthorizationProvider($type, $userId, /** @scrutinizer ignore-type */ $groupId);
Loading history...
764
            $identityLink->delete();
765
        }
766
    }
767
768
    public function deleteIdentityLinks(): void
769
    {
770
        $identityLinkEntities = $this->getIdentityLinks();
771
        foreach ($identityLinkEntities as $identityLinkEntity) {
772
            $this->fireDeleteIdentityLinkAuthorizationProvider(
773
                $identityLinkEntity->getType(),
774
                $identityLinkEntity->getUserId(),
775
                $identityLinkEntity->getGroupId()
776
            );
777
            $identityLinkEntity->delete(false);
778
        }
779
        $this->isIdentityLinksInitialized = false;
780
    }
781
782
    public function getCandidates(): array
783
    {
784
        $potentialOwners = [];
785
        foreach ($this->getIdentityLinks() as $identityLinkEntity) {
786
            if (IdentityLinkType::CANDIDATE == $identityLinkEntity->getType()) {
787
                $potentialOwners[] = $identityLinkEntity;
788
            }
789
        }
790
        return $potentialOwners;
791
    }
792
793
    public function addCandidateUser(string $userId): void
794
    {
795
        $this->addIdentityLink($userId, null, IdentityLinkType::CANDIDATE);
796
    }
797
798
    public function addCandidateUsers(array $candidateUsers): void
799
    {
800
        foreach ($candidateUsers as $candidateUser) {
801
            $this->addCandidateUser($candidateUser);
802
        }
803
    }
804
805
    public function addCandidateGroup(string $groupId): void
806
    {
807
        $this->addIdentityLink(null, $groupId, IdentityLinkType::CANDIDATE);
808
    }
809
810
    public function addCandidateGroups(array $candidateGroups): void
811
    {
812
        foreach ($candidateGroups as $candidateGroup) {
813
            $this->addCandidateGroup($candidateGroup);
814
        }
815
    }
816
817
    public function addGroupIdentityLink(string $groupId, string $identityLinkType): void
818
    {
819
        $this->addIdentityLink(null, $groupId, $identityLinkType);
820
    }
821
822
    public function addUserIdentityLink(string $userId, string $identityLinkType): void
823
    {
824
        $this->addIdentityLink($userId, null, $identityLinkType);
825
    }
826
827
    public function deleteCandidateGroup(string $groupId): void
828
    {
829
        $this->deleteGroupIdentityLink($groupId, IdentityLinkType::CANDIDATE);
830
    }
831
832
    public function deleteCandidateUser(string $userId): void
833
    {
834
        $this->deleteUserIdentityLink($userId, IdentityLinkType::CANDIDATE);
835
    }
836
837
    public function deleteGroupIdentityLink(string $groupId, string $identityLinkType): void
838
    {
839
        if ($groupId !== null) {
0 ignored issues
show
introduced by
The condition $groupId !== null is always true.
Loading history...
840
            $this->deleteIdentityLink(null, $groupId, $identityLinkType);
841
        }
842
    }
843
844
    public function deleteUserIdentityLink(string $userId, string $identityLinkType): void
845
    {
846
        if ($userId !== null) {
0 ignored issues
show
introduced by
The condition $userId !== null is always true.
Loading history...
847
            $this->deleteIdentityLink($userId, null, $identityLinkType);
848
        }
849
    }
850
851
    public function getIdentityLinks(): array
852
    {
853
        if (!$this->isIdentityLinksInitialized) {
854
            $this->taskIdentityLinkEntities = Context::getCommandContext()
855
            ->getIdentityLinkManager()
856
            ->findIdentityLinksByTaskId(id);
0 ignored issues
show
Bug introduced by
The constant Jabe\Impl\Persistence\Entity\id was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
857
            $this->isIdentityLinksInitialized = true;
858
        }
859
860
        return $this->taskIdentityLinkEntities;
861
    }
862
863
    public function getActivityInstanceVariables(): array
864
    {
865
        if ($this->execution !== null) {
866
            return $this->execution->getVariables();
867
        }
868
        return [];
869
    }
870
871
    public function setExecutionVariables(array $parameters): void
872
    {
873
        $scope = $this->getParentVariableScope();
874
        if ($scope !== null) {
875
            $scope->setVariables($parameters);
876
        }
877
    }
878
879
    public function __toString()
880
    {
881
        return "Task[" . $this->id . "]";
882
    }
883
884
    // special setters //////////////////////////////////////////////////////////
885
886
    public function setName(string $taskName): void
887
    {
888
        $this->registerCommandContextCloseListener();
889
        $this->propertyChanged(self::NAME, $this->name, $taskName);
890
        $this->name = $taskName;
891
    }
892
893
    public function setDescription(string $description): void
894
    {
895
        $this->registerCommandContextCloseListener();
896
        $this->propertyChanged(self::DESCRIPTION, $this->description, $description);
897
        $this->description = $description;
898
    }
899
900
    public function setAssignee(?string $assignee): void
901
    {
902
        $timestamp = ClockUtil::getCurrentTime()->format('c');
903
        $this->ensureTaskActive();
904
        $this->registerCommandContextCloseListener();
905
906
        $oldAssignee = $this->assignee;
907
        if ($assignee === null && $oldAssignee === null) {
908
            return;
909
        }
910
911
        $this->addIdentityLinkChanges(IdentityLinkType::ASSIGNEE, $oldAssignee, $assignee);
0 ignored issues
show
Bug introduced by
It seems like $assignee can also be of type null; however, parameter $newProperty of Jabe\Impl\Persistence\En...ddIdentityLinkChanges() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

911
        $this->addIdentityLinkChanges(IdentityLinkType::ASSIGNEE, $oldAssignee, /** @scrutinizer ignore-type */ $assignee);
Loading history...
912
        $this->propertyChanged(self::ASSIGNEE, $oldAssignee, $assignee);
913
        $this->assignee = $assignee;
914
915
        $commandContext = Context::getCommandContext();
916
        // if there is no command context, then it means that the user is calling the
917
        // setAssignee outside a service method.  E.g. while creating a new task.
918
        if ($commandContext !== null) {
919
            if ($commandContext->getDbEntityManager()->contains($this)) {
920
                $this->fireAssigneeAuthorizationProvider($oldAssignee, $assignee);
0 ignored issues
show
Bug introduced by
It seems like $assignee can also be of type null; however, parameter $newAssignee of Jabe\Impl\Persistence\En...AuthorizationProvider() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

920
                $this->fireAssigneeAuthorizationProvider($oldAssignee, /** @scrutinizer ignore-type */ $assignee);
Loading history...
921
                $this->fireHistoricIdentityLinks();
922
            }
923
            if ($commandContext->getProcessEngineConfiguration()->isTaskMetricsEnabled() && $assignee !== null && $assignee != $oldAssignee) {
0 ignored issues
show
Bug introduced by
The method isTaskMetricsEnabled() does not exist on Jabe\Impl\Cfg\ProcessEngineConfigurationImpl. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

923
            if ($commandContext->getProcessEngineConfiguration()->/** @scrutinizer ignore-call */ isTaskMetricsEnabled() && $assignee !== null && $assignee != $oldAssignee) {

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
924
                // assignee has changed and is not null, so mark a new task worker
925
                $commandContext->getMeterLogManager()->insert(new TaskMeterLogEntity($assignee, $timestamp));
0 ignored issues
show
Bug introduced by
new Jabe\Impl\Persistenc...($assignee, $timestamp) of type Jabe\Impl\Persistence\Entity\TaskMeterLogEntity is incompatible with the type Jabe\Impl\Persistence\Entity\MeterLogEntity expected by parameter $meterLogEntity of Jabe\Impl\Persistence\En...terLogManager::insert(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

925
                $commandContext->getMeterLogManager()->insert(/** @scrutinizer ignore-type */ new TaskMeterLogEntity($assignee, $timestamp));
Loading history...
926
            }
927
        }
928
    }
929
930
    public function setOwner(string $owner): void
931
    {
932
        $this->ensureTaskActive();
933
        $this->registerCommandContextCloseListener();
934
935
        $oldOwner = $this->owner;
936
        if ($this->owner === null && $oldOwner === null) {
937
            return;
938
        }
939
940
        $this->addIdentityLinkChanges(IdentityLinkType::OWNER, $oldOwner, $this->owner);
941
        $this->propertyChanged(self::OWNER, $oldOwner, $this->owner);
942
        $this->owner = $owner;
943
944
        $commandContext = Context::getCommandContext();
945
        // if there is no command context, then it means that the user is calling the
946
        // setOwner outside a service method.  E.g. while creating a new task.
947
        if ($commandContext !== null && $commandContext->getDbEntityManager()->contains($this)) {
948
            $this->fireOwnerAuthorizationProvider($oldOwner, $this->owner);
949
            $this->fireHistoricIdentityLinks();
950
        }
951
    }
952
953
    public function setDueDate(string $dueDate): void
954
    {
955
        $this->registerCommandContextCloseListener();
956
        $this->propertyChanged(self::DUE_DATE, $this->dueDate, $dueDate);
957
        $this->dueDate = $dueDate;
958
    }
959
960
    public function setPriority(int $priority): void
961
    {
962
        $this->registerCommandContextCloseListener();
963
        $this->propertyChanged(self::PRIORITY, $this->priority, $priority);
964
        $this->priority = $priority;
965
    }
966
967
    public function setParentTaskId(string $parentTaskId): void
968
    {
969
        $this->registerCommandContextCloseListener();
970
        $this->propertyChanged(self::PARENT_TASK, $this->parentTaskId, $parentTaskId);
971
        $this->parentTaskId = $parentTaskId;
972
    }
973
974
    /* plain setter for persistence */
975
    public function setNameWithoutCascade(string $taskName): void
976
    {
977
        $this->name = $taskName;
978
    }
979
980
    /* plain setter for persistence */
981
    public function setDescriptionWithoutCascade(string $description): void
982
    {
983
        $this->description = $description;
984
    }
985
986
    /* plain setter for persistence */
987
    public function setAssigneeWithoutCascade(string $assignee): void
988
    {
989
        $this->assignee = $assignee;
990
    }
991
992
    /* plain setter for persistence */
993
    public function setOwnerWithoutCascade(string $owner): void
994
    {
995
        $this->owner = $owner;
996
    }
997
998
    public function setDueDateWithoutCascade(string $dueDate): void
999
    {
1000
        $this->dueDate = $dueDate;
1001
    }
1002
1003
    public function setPriorityWithoutCascade(int $priority): void
1004
    {
1005
        $this->priority = $priority;
1006
    }
1007
1008
    /* plain setter for persistence */
1009
    /*public function setCaseInstanceIdWithoutCascade(string $caseInstanceId): void
1010
    {
1011
        $this->caseInstanceId = caseInstanceId;
1012
    }*/
1013
1014
    public function setParentTaskIdWithoutCascade(string $parentTaskId): void
1015
    {
1016
        $this->parentTaskId = $parentTaskId;
1017
    }
1018
1019
    public function setTaskDefinitionKeyWithoutCascade(string $taskDefinitionKey): void
1020
    {
1021
        $this->taskDefinitionKey = $taskDefinitionKey;
1022
    }
1023
1024
    public function setDelegationStateWithoutCascade(string $delegationState): void
1025
    {
1026
        $this->delegationState = $delegationState;
1027
    }
1028
1029
    /**
1030
     * Setter for mybatis mapper.
1031
     *
1032
     * @param delegationState  the delegation state as string
1033
     */
1034
    public function setDelegationStateString(?string $delegationState): void
1035
    {
1036
        if ($delegationState === null) {
1037
            $this->setDelegationStateWithoutCascade(null);
0 ignored issues
show
Bug introduced by
null of type null is incompatible with the type string expected by parameter $delegationState of Jabe\Impl\Persistence\En...onStateWithoutCascade(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1037
            $this->setDelegationStateWithoutCascade(/** @scrutinizer ignore-type */ null);
Loading history...
1038
        } else {
1039
            $this->setDelegationStateWithoutCascade($delegationState);
1040
        }
1041
    }
1042
1043
    public function setFollowUpDateWithoutCascade(string $followUpDate): void
1044
    {
1045
        $this->followUpDate = $followUpDate;
1046
    }
1047
1048
    /**
1049
     * @return bool true if invoking the listener was successful;
1050
     *   if not successful, either false is returned (case: BPMN error propagation)
1051
     *   or an exception is thrown
1052
     */
1053
    public function fireEvent(string $taskEventName): bool
1054
    {
1055
        $taskEventListeners = $this->getListenersForEvent($taskEventName);
1056
1057
        if (!empty($taskEventListeners)) {
1058
            foreach ($taskEventListeners as $taskListener) {
1059
                if (!$this->invokeListener($taskEventName, $taskListener)) {
0 ignored issues
show
Bug introduced by
The call to Jabe\Impl\Persistence\En...ntity::invokeListener() has too few arguments starting with taskListener. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

1059
                if (!$this->/** @scrutinizer ignore-call */ invokeListener($taskEventName, $taskListener)) {

This check compares calls to functions or methods with their respective definitions. If the call has less arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
Bug introduced by
$taskEventName of type string is incompatible with the type Jabe\Impl\Core\Instance\CoreExecution|null expected by parameter $currentExecution of Jabe\Impl\Persistence\En...ntity::invokeListener(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1059
                if (!$this->invokeListener(/** @scrutinizer ignore-type */ $taskEventName, $taskListener)) {
Loading history...
1060
                    return false;
1061
                }
1062
            }
1063
        }
1064
1065
        return true;
1066
    }
1067
1068
    protected function getListenersForEvent(string $event): array
1069
    {
1070
        $resolvedTaskDefinition = $this->getTaskDefinition();
1071
        if ($resolvedTaskDefinition !== null) {
1072
            if ($this->skipCustomListeners) {
1073
                return $resolvedTaskDefinition->getBuiltinTaskListeners($event);
1074
            } else {
1075
                return $resolvedTaskDefinition->getTaskListeners($event);
1076
            }
1077
        } else {
1078
            return [];
1079
        }
1080
    }
1081
1082
    protected function getTimeoutListener(string $timeoutId): ?TaskListenerInterface
1083
    {
1084
        $resolvedTaskDefinition = $this->getTaskDefinition();
1085
        if ($resolvedTaskDefinition === null) {
1086
            return null;
1087
        } else {
1088
            return $resolvedTaskDefinition->getTimeoutTaskListener($timeoutId);
1089
        }
1090
    }
1091
1092
    /**
1093
     * @return bool true if the next listener can be invoked; false if not
1094
     */
1095
    protected function invokeListener(?CoreExecution $currentExecution, string $eventName, TaskListenerInterface $taskListener): bool
1096
    {
1097
        if ($currentExecution !== null) {
1098
            $isBpmnTask = $currentExecution instanceof ActivityExecution && $currentExecution !== null;
1099
            $listenerInvocation = new TaskListenerInvocation($taskListener, $this, $currentExecution);
1100
1101
            try {
1102
                Context::getProcessEngineConfiguration()
1103
                ->getDelegateInterceptor()
0 ignored issues
show
Bug introduced by
The method getDelegateInterceptor() does not exist on Jabe\Impl\Cfg\ProcessEngineConfigurationImpl. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

1103
                ->/** @scrutinizer ignore-call */ getDelegateInterceptor()

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
1104
                ->handleInvocation($listenerInvocation);
1105
            } catch (\Exception $ex) {
1106
                // exceptions on delete events are never handled as BPMN errors
1107
                if ($isBpmnTask && $eventName != TaskListenerInterface::EVENTNAME_DELETE) {
1108
                    try {
1109
                        BpmnExceptionHandler::propagateException($currentExecution, $ex);
1110
                        return false;
1111
                    } catch (ErrorPropagationException $e) {
1112
                        // exception has been logged by thrower
1113
                        // re-throw the original exception so that it is logged
1114
                        // and set as cause of the failure
1115
                        throw $ex;
1116
                    }
1117
                } else {
1118
                    throw $ex;
1119
                }
1120
            }
1121
            return true;
1122
        } else {
1123
            $popProcessDataContext = false;
1124
            $commandInvocationContext = Context::getCommandInvocationContext();
1125
            $execution = $this->getExecution();
1126
            if ($execution === null) {
1127
                //$execution = getCaseExecution();
1128
            } else {
1129
                if ($commandInvocationContext !== null) {
1130
                    $popProcessDataContext = $commandInvocationContext->getProcessDataContext()->pushSection($execution);
1131
                }
1132
            }
1133
            if ($execution !== null) {
1134
                $this->setEventName($eventName);
1135
            }
1136
            try {
1137
                $result = $this->invokeListener($execution, $eventName, $taskListener);
1138
                if ($popProcessDataContext) {
1139
                    $commandInvocationContext->getProcessDataContext()->popSection();
1140
                }
1141
                return $result;
1142
            } catch (\Exception $e) {
1143
                //throw LOG.invokeTaskListenerException(e);
1144
                throw $e;
1145
            }
1146
        }
1147
    }
1148
1149
    /**
1150
     * Tracks a property change. Therefore the original and new value are stored in a map.
1151
     * It tracks multiple changes and if a property finally is changed back to the original
1152
     * value, then the change is removed.
1153
     *
1154
     * @param propertyName
1155
     * @param orgValue
1156
     * @param newValue
1157
     */
1158
    protected function propertyChanged(string $propertyName, $orgValue, $newValue): void
1159
    {
1160
        if (array_key_exists($propertyName, $this->propertyChanges)) {// update an existing change to save the original value
1161
            $oldOrgValue = $this->propertyChanges[$propertyName]->getOrgValue();
1162
            if (
1163
                ($oldOrgValue === null && $newValue === null) // change back to null
1164
                || ($oldOrgValue !== null && $oldOrgValue == $newValue)
1165
            ) { // remove this change
1166
                unset($this->propertyChanges[$propertyName]);
1167
            } else {
1168
                $this->propertyChanges[$propertyName]->setNewValue($newValue);
1169
            }
1170
        } else { // save this change
1171
            if (
1172
                ($orgValue === null && $newValue !== null) // null to value
1173
                || ($orgValue !== null && $newValue === null) // value to null
1174
                || ($orgValue !== null && $orgValue != $newValue)
1175
            ) {
1176
                $this->propertyChanges[$propertyName] = new PropertyChange($propertyName, $orgValue, $newValue);
1177
            }
1178
        }
1179
    }
1180
1181
    // authorizations ///////////////////////////////////////////////////////////
1182
1183
    public function transitionTo(int $state): bool
1184
    {
1185
        $this->lifecycleState = $state;
1186
1187
        switch ($state) {
1188
            case TaskState::STATE_CREATED:
1189
                $commandContext = Context::getCommandContext();
1190
                if ($commandContext !== null) {
1191
                    $commandContext->getHistoricTaskInstanceManager()->createHistoricTask($this);
1192
                }
1193
                return $this->fireEvent(TaskListenerInterface::EVENTNAME_CREATE) && $this->fireAssignmentEvent();
1194
1195
            case TaskState::STATE_COMPLETED:
1196
                return $this->fireEvent(TaskListenerInterface::EVENTNAME_COMPLETE) && TaskState::STATE_COMPLETED == $this->lifecycleState;
1197
1198
            case TaskState::STATE_DELETED:
1199
                return $this->fireEvent(TaskListenerInterface::EVENTNAME_DELETE);
1200
1201
            case TaskState::STATE_INIT:
1202
            default:
1203
                throw new ProcessEngineException(sprintf("Task %s cannot transition into state %s.", $this->id, $state));
1204
        }
1205
    }
1206
1207
    public function triggerUpdateEvent(): bool
1208
    {
1209
        if ($this->lifecycleState == TaskState::STATE_CREATED) {
1210
            return $this->fireEvent(TaskListenerInterface::EVENTNAME_UPDATE) && $this->fireAssignmentEvent();
1211
        } else {
1212
            // silently ignore; no events are triggered in the other states
1213
            return true;
1214
        }
1215
    }
1216
1217
    /**
1218
     * @return bool true if invoking the listener was successful;
1219
     *   if not successful, either false is returned (case: BPMN error propagation)
1220
     *   or an exception is thrown
1221
     */
1222
    public function triggerTimeoutEvent(string $timeoutId): bool
1223
    {
1224
        $taskListener = $this->getTimeoutListener($timeoutId);
1225
        if ($taskListener === null) {
1226
            /* throw LOG.invokeTaskListenerException(new NotFoundException("Cannot find timeout taskListener with id '"
1227
                                                                            + timeoutId + "' for task " + $this->id));*/
1228
            throw new \Exception("triggerTimeoutEvent");
1229
        }
1230
        return $this->invokeListener(TaskListenerInterface::EVENTNAME_TIMEOUT, $taskListener);
0 ignored issues
show
Bug introduced by
$taskListener of type Jabe\Delegate\TaskListenerInterface is incompatible with the type string expected by parameter $eventName of Jabe\Impl\Persistence\En...ntity::invokeListener(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1230
        return $this->invokeListener(TaskListenerInterface::EVENTNAME_TIMEOUT, /** @scrutinizer ignore-type */ $taskListener);
Loading history...
Bug introduced by
The call to Jabe\Impl\Persistence\En...ntity::invokeListener() has too few arguments starting with taskListener. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

1230
        return $this->/** @scrutinizer ignore-call */ invokeListener(TaskListenerInterface::EVENTNAME_TIMEOUT, $taskListener);

This check compares calls to functions or methods with their respective definitions. If the call has less arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
Bug introduced by
Jabe\Delegate\TaskListen...face::EVENTNAME_TIMEOUT of type string is incompatible with the type Jabe\Impl\Core\Instance\CoreExecution|null expected by parameter $currentExecution of Jabe\Impl\Persistence\En...ntity::invokeListener(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1230
        return $this->invokeListener(/** @scrutinizer ignore-type */ TaskListenerInterface::EVENTNAME_TIMEOUT, $taskListener);
Loading history...
1231
    }
1232
1233
    protected function fireAssignmentEvent(): bool
1234
    {
1235
        if (array_key_exists(self::ASSIGNEE, $this->propertyChanges)) {
1236
            $assigneePropertyChange = $this->propertyChanges[self::ASSIGNEE];
0 ignored issues
show
Unused Code introduced by
The assignment to $assigneePropertyChange is dead and can be removed.
Loading history...
1237
            return $this->fireEvent(TaskListenerInterface::EVENTNAME_ASSIGNMENT);
1238
        }
1239
1240
        return true;
1241
    }
1242
1243
    protected function fireAssigneeAuthorizationProvider(string $oldAssignee, string $newAssignee): void
1244
    {
1245
        $this->fireAuthorizationProvider(self::ASSIGNEE, $oldAssignee, $newAssignee);
1246
    }
1247
1248
    protected function fireOwnerAuthorizationProvider(string $oldOwner, string $newOwner): void
1249
    {
1250
        $this->fireAuthorizationProvider(self::OWNER, $oldOwner, $newOwner);
1251
    }
1252
1253
    protected function fireAuthorizationProvider(?string $property = null, ?string $oldValue = null, ?string $newValue = null): void
1254
    {
1255
        if ($property === null && $oldValue === null && $newValue === null) {
1256
            if (array_key_exists(self::ASSIGNEE, $this->propertyChanges)) {
1257
                $assigneePropertyChange = $this->propertyChanges[self::ASSIGNEE];
1258
                $oldAssignee = $assigneePropertyChange->getOrgValueString();
1259
                $newAssignee = $assigneePropertyChange->getNewValueString();
1260
                $this->fireAssigneeAuthorizationProvider($oldAssignee, $newAssignee);
1261
            }
1262
1263
            if (array_key_exists(self::OWNER, $this->propertyChanges)) {
1264
                $ownerPropertyChange = $this->propertyChanges[self::OWNER];
1265
                $oldOwner = $ownerPropertyChange->getOrgValueString();
1266
                $newOwner = $ownerPropertyChange->getNewValueString();
1267
                $this->fireOwnerAuthorizationProvider($oldOwner, $newOwner);
1268
            }
1269
        } else {
1270
            if ($this->isAuthorizationEnabled()) { // && caseExecutionId === null
1271
                $provider = $this->getResourceAuthorizationProvider();
1272
1273
                $authorizations = null;
1274
                if (self::ASSIGNEE == $property) {
1275
                    $authorizations = $provider->newTaskAssignee($this, $oldValue, $newValue);
1276
                } elseif (self::OWNER == $property) {
1277
                    $authorizations = $provider->newTaskOwner($this, $oldValue, $newValue);
1278
                }
1279
1280
                $this->saveAuthorizations($authorizations);
1281
            }
1282
        }
1283
    }
1284
1285
    protected function fireAddIdentityLinkAuthorizationProvider(string $type, string $userId, string $groupId): void
1286
    {
1287
        if ($this->isAuthorizationEnabled()) { // && caseExecutionId === null
1288
            $provider = $this->getResourceAuthorizationProvider();
1289
1290
            $authorizations = null;
1291
            if ($userId !== null) {
0 ignored issues
show
introduced by
The condition $userId !== null is always true.
Loading history...
1292
                $authorizations = $provider->newTaskUserIdentityLink($this, $userId, $type);
1293
            } elseif ($groupId !== null) {
1294
                $authorizations = $provider->newTaskGroupIdentityLink($this, $groupId, $type);
1295
            }
1296
1297
            $this->saveAuthorizations($authorizations);
1298
        }
1299
    }
1300
1301
    protected function fireDeleteIdentityLinkAuthorizationProvider(string $type, string $userId, string $groupId): void
1302
    {
1303
        if ($this->isAuthorizationEnabled()) { // && caseExecutionId === null
1304
            $provider = $this->getResourceAuthorizationProvider();
1305
            $authorizations = null;
1306
            if ($userId !== null) {
0 ignored issues
show
introduced by
The condition $userId !== null is always true.
Loading history...
1307
                $authorizations = $provider->deleteTaskUserIdentityLink($this, $userId, $type);
1308
            } elseif ($groupId !== null) {
1309
                $authorizations = $provider->deleteTaskGroupIdentityLink($this, $groupId, $type);
1310
            }
1311
1312
            $this->deleteAuthorizations($authorizations);
1313
        }
1314
    }
1315
1316
    protected function getResourceAuthorizationProvider(): ?ResourceAuthorizationProviderInterface
1317
    {
1318
        $processEngineConfiguration = Context::getProcessEngineConfiguration();
1319
        return $processEngineConfiguration->getResourceAuthorizationProvider();
0 ignored issues
show
Bug introduced by
The method getResourceAuthorizationProvider() does not exist on Jabe\Impl\Cfg\ProcessEngineConfigurationImpl. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

1319
        return $processEngineConfiguration->/** @scrutinizer ignore-call */ getResourceAuthorizationProvider();

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
1320
    }
1321
1322
    protected function saveAuthorizations(array $authorizations): void
1323
    {
1324
        $commandContext = Context::getCommandContext();
1325
        $taskManager = $commandContext->getTaskManager();
1326
        $taskManager->saveDefaultAuthorizations($authorizations);
1327
    }
1328
1329
    protected function deleteAuthorizations(array $authorizations): void
1330
    {
1331
        $commandContext = Context::getCommandContext();
1332
        $taskManager = $commandContext->getTaskManager();
1333
        $taskManager->deleteDefaultAuthorizations($authorizations);
1334
    }
1335
1336
    protected function isAuthorizationEnabled(): bool
1337
    {
1338
        return Context::getProcessEngineConfiguration()->isAuthorizationEnabled();
1339
    }
1340
1341
    // modified getters and setters /////////////////////////////////////////////
1342
1343
    public function setTaskDefinition(TaskDefinition $taskDefinition): void
1344
    {
1345
        $this->taskDefinition = $taskDefinition;
1346
        $this->taskDefinitionKey = $taskDefinition->getKey();
1347
    }
1348
1349
    public function getTaskDefinition(): ?TaskDefinition
1350
    {
1351
        $taskDefinition = null;
1352
        if ($this->taskDefinition === null && $this->taskDefinitionKey !== null) {
1353
            $taskDefinitions = null;
1354
            if ($this->processDefinitionId !== null) {
1355
                $processDefinition = Context::getProcessEngineConfiguration()
1356
                    ->getDeploymentCache()
1357
                    ->findDeployedProcessDefinitionById($this->processDefinitionId);
1358
1359
                $taskDefinitions = $processDefinition->getTaskDefinitions();
1360
            } else {
1361
                /*CaseDefinitionEntity caseDefinition = Context
1362
                    ->getProcessEngineConfiguration()
1363
                    ->getDeploymentCache()
1364
                    ->findDeployedCaseDefinitionById(caseDefinitionId);
1365
1366
                taskDefinitions = caseDefinition->getTaskDefinitions();*/
1367
            }
1368
1369
            if ($taskDefinitions !== null) {
1370
                $taskDefinition = $taskDefinitions[$this->taskDefinitionKey];
1371
            }
1372
        }
1373
        return $taskDefinition;
1374
    }
1375
1376
    // getters and setters //////////////////////////////////////////////////////
1377
1378
    public function getId(): ?string
1379
    {
1380
        return $this->id;
1381
    }
1382
1383
    public function setId(string $id): void
1384
    {
1385
        $this->id = $id;
1386
    }
1387
1388
    public function getRevision(): int
1389
    {
1390
        return $this->revision;
1391
    }
1392
1393
    public function setRevision(int $revision): void
1394
    {
1395
        $this->revision = $revision;
1396
    }
1397
1398
    public function getName(): string
1399
    {
1400
        return $this->name;
1401
    }
1402
1403
    public function getDescription(): string
1404
    {
1405
        return $this->description;
1406
    }
1407
1408
    public function getDueDate(): string
1409
    {
1410
        return $this->dueDate;
1411
    }
1412
1413
    public function getPriority(): int
1414
    {
1415
        return $this->priority;
1416
    }
1417
1418
    public function getCreateTime(): string
1419
    {
1420
        return $this->createTime;
1421
    }
1422
1423
    public function setCreateTime(string $createTime): void
1424
    {
1425
        $this->createTime = $createTime;
1426
    }
1427
1428
    public function getExecutionId(): string
1429
    {
1430
        return $this->executionId;
1431
    }
1432
1433
    public function getProcessInstanceId(): string
1434
    {
1435
        return $this->processInstanceId;
1436
    }
1437
1438
    public function isStandaloneTask(): bool
1439
    {
1440
        return $this->executionId === null;// && caseExecutionId === null;
1441
    }
1442
1443
    public function getProcessDefinition(): ProcessDefinitionEntity
1444
    {
1445
        if ($this->processDefinitionId !== null) {
1446
            return Context::getProcessEngineConfiguration()
1447
                ->getDeploymentCache()
1448
                ->findDeployedProcessDefinitionById($this->processDefinitionId);
1449
        }
1450
        return null;
0 ignored issues
show
Bug Best Practice introduced by
The expression return null returns the type null which is incompatible with the type-hinted return Jabe\Impl\Persistence\En...ProcessDefinitionEntity.
Loading history...
1451
    }
1452
1453
    public function getProcessDefinitionId(): string
1454
    {
1455
        return $this->processDefinitionId;
1456
    }
1457
1458
    public function initializeFormKey(): void
1459
    {
1460
        $this->isFormKeyInitialized = true;
1461
        if ($this->taskDefinitionKey !== null) {
1462
            $taskDefinition = $this->getTaskDefinition();
1463
            if ($this->taskDefinition !== null) {
1464
                // initialize formKey
1465
                $formKey = $taskDefinition->getFormKey();
1466
                if ($formKey !== null) {
1467
                    $this->formKey = $formKey->getValue($this);
1468
                } else {
1469
                    // initialize form reference
1470
                    $formRef = $taskDefinition->getFormDefinitionKey();
1471
                    $formRefBinding = $taskDefinition->getFormDefinitionBinding();
1472
                    $formRefVersion = $taskDefinition->getFormDefinitionVersion();
1473
                    if ($formRef !== null && $formRefBinding !== null) {
1474
                        $formRefValue = $formRef->getValue($this);
1475
                        if ($formRefValue !== null) {
1476
                            $extFormRef = new FormRefImpl($formRefValue, $formRefBinding);
1477
                            if ($formRefBinding == DefaultFormHandler::FORM_REF_BINDING_VERSION && $formRefVersion !== null) {
1478
                                $formRefVersionValue = $formRefVersion->getValue($this);
1479
                                $extFormRef->setVersion(intval($formRefVersionValue));
1480
                            }
1481
                            $this->formRef = $extFormRef;
1482
                        }
1483
                    }
1484
                }
1485
            }
1486
        }
1487
    }
1488
1489
    public function getFormKey(): string
1490
    {
1491
        if (!$this->isFormKeyInitialized) {
1492
            //throw LOG.uninitializedFormKeyException();
1493
            throw new \Exception("uninitializedFormKeyException");
1494
        }
1495
        return $this->formKey;
1496
    }
1497
1498
    public function getFormRef(): FormRefInterface
1499
    {
1500
        if (!$this->isFormKeyInitialized) {
1501
            //throw LOG.uninitializedFormKeyException();
1502
            throw new \Exception("uninitializedFormKeyException");
1503
        }
1504
        return $this->formRef;
1505
    }
1506
1507
    public function setProcessDefinitionId(string $processDefinitionId): void
1508
    {
1509
        $this->processDefinitionId = $processDefinitionId;
1510
    }
1511
1512
    public function getAssignee(): string
1513
    {
1514
        return $this->assignee;
1515
    }
1516
1517
    public function getTaskDefinitionKey(): string
1518
    {
1519
        return $this->taskDefinitionKey;
1520
    }
1521
1522
    public function setTaskDefinitionKey(string $taskDefinitionKey): void
1523
    {
1524
        if (
1525
            ($taskDefinitionKey === null && $this->taskDefinitionKey !== null)
0 ignored issues
show
introduced by
The condition $taskDefinitionKey === null is always false.
Loading history...
1526
            || ($taskDefinitionKey !== null && $taskDefinitionKey == $this->taskDefinitionKey)
1527
        ) {
1528
            $this->taskDefinition = null;
1529
            $this->formKey = null;
1530
            $this->isFormKeyInitialized = false;
1531
        }
1532
1533
        $this->taskDefinitionKey = $taskDefinitionKey;
1534
    }
1535
1536
    public function getEventName(): string
1537
    {
1538
        return $this->eventName;
1539
    }
1540
1541
    public function setEventName(string $eventName): void
0 ignored issues
show
Unused Code introduced by
The parameter $eventName is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

1541
    public function setEventName(/** @scrutinizer ignore-unused */ string $eventName): void

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
1542
    {
1543
        $this->eventName = $this->eventName;
1544
    }
1545
1546
    public function setExecutionId(string $executionId): void
1547
    {
1548
        $this->executionId = $executionId;
1549
    }
1550
1551
    public function getProcessInstance(): ExecutionEntity
1552
    {
1553
        if ($this->processInstance === null && $this->processInstanceId !== null) {
1554
            $this->processInstance = Context::getCommandContext()->getExecutionManager()->findExecutionById($this->processInstanceId);
1555
        }
1556
        return $this->processInstance;
1557
    }
1558
1559
    public function setProcessInstance(ExecutionEntity $processInstance): void
1560
    {
1561
        $this->processInstance = $processInstance;
1562
    }
1563
1564
    public function setProcessInstanceId(string $processInstanceId): void
1565
    {
1566
        $this->processInstanceId = $processInstanceId;
1567
    }
1568
1569
    public function getOwner(): string
1570
    {
1571
        return $this->owner;
1572
    }
1573
1574
    public function getDelegationState(): string
1575
    {
1576
        return $this->delegationState;
1577
    }
1578
1579
    public function setDelegationState(string $delegationState): void
1580
    {
1581
        $this->propertyChanged(self::DELEGATION, $this->delegationState, $delegationState);
1582
        $this->delegationState = $delegationState;
1583
    }
1584
1585
    public function getDelegationStateString(): ?string
1586
    {
1587
        return strval($this->delegationState);
1588
    }
1589
1590
    public function isDeleted(): bool
1591
    {
1592
        return $this->isDeleted;
1593
    }
1594
1595
    public function getDeleteReason(): string
1596
    {
1597
        return $this->deleteReason;
1598
    }
1599
1600
    public function setDeleted(bool $isDeleted): void
1601
    {
1602
        $this->isDeleted = $isDeleted;
1603
    }
1604
1605
    public function getParentTaskId(): ?string
1606
    {
1607
        return $this->parentTaskId;
1608
    }
1609
1610
    public function getSuspensionState(): int
1611
    {
1612
        return $this->suspensionState;
1613
    }
1614
1615
    public function setSuspensionState(int $suspensionState): void
1616
    {
1617
        $this->suspensionState = $suspensionState;
1618
    }
1619
1620
    public function isSuspended(): bool
1621
    {
1622
        return $this->suspensionState == SuspensionState::suspended()->getStateCode();
1623
    }
1624
1625
    public function getFollowUpDate(): string
1626
    {
1627
        return $this->followUpDate;
1628
    }
1629
1630
    public function getTenantId(): ?string
1631
    {
1632
        return $this->tenantId;
1633
    }
1634
1635
    public function setTenantId(?string $tenantId): void
1636
    {
1637
        $this->tenantId = $tenantId;
1638
    }
1639
1640
    public function setFollowUpDate(string $followUpDate): void
1641
    {
1642
        $this->registerCommandContextCloseListener();
1643
        $this->propertyChanged(self::FOLLOW_UP_DATE, $this->followUpDate, $followUpDate);
1644
        $this->followUpDate = $followUpDate;
1645
    }
1646
1647
    public function getVariablesInternal(): array
1648
    {
1649
        return $this->variableStore->getVariables();
1650
    }
1651
1652
    public function onCommandContextClose(CommandContext $commandContext): void
1653
    {
1654
        if ($commandContext->getDbEntityManager()->isDirty($this)) {
1655
            $commandContext->getHistoricTaskInstanceManager()->updateHistoricTaskInstance($this);
1656
        }
1657
    }
1658
1659
    public function onCommandFailed(CommandContext $commandContext, \Throwable $t): void
1660
    {
1661
        // ignore
1662
    }
1663
1664
    protected function registerCommandContextCloseListener(): void
1665
    {
1666
        $commandContext = Context::getCommandContext();
1667
        if ($commandContext !== null) {
1668
            $commandContext->registerCommandContextListener($this);
1669
        }
1670
    }
1671
1672
    public function getPropertyChanges(): array
1673
    {
1674
        return $this->propertyChanges;
1675
    }
1676
1677
    public function logUserOperation(string $operation): void
1678
    {
1679
        if (
1680
            UserOperationLogEntryInterface::OPERATION_TYPE_COMPLETE == $operation ||
1681
            UserOperationLogEntryInterface::OPERATION_TYPE_DELETE == $operation
1682
        ) {
1683
            propertyChanged(self::DELETE, false, true);
0 ignored issues
show
Bug introduced by
The function propertyChanged was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

1683
            /** @scrutinizer ignore-call */ 
1684
            propertyChanged(self::DELETE, false, true);
Loading history...
1684
        }
1685
1686
        $commandContext = Context::getCommandContext();
1687
        if ($commandContext !== null) {
1688
            $values = array_values($this->propertyChanges);
1689
            $commandContext->getOperationLogManager()->logTaskOperations($operation, $this, $values);
0 ignored issues
show
Bug introduced by
$this of type Jabe\Impl\Persistence\Entity\TaskEntity is incompatible with the type Jabe\History\HistoricTaskInstanceInterface expected by parameter $task of Jabe\Impl\Persistence\En...er::logTaskOperations(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1689
            $commandContext->getOperationLogManager()->logTaskOperations($operation, /** @scrutinizer ignore-type */ $this, $values);
Loading history...
1690
            $this->fireHistoricIdentityLinks();
1691
            $this->propertyChanges = [];
1692
        }
1693
    }
1694
1695
    public function fireHistoricIdentityLinks(): void
1696
    {
1697
        foreach ($this->identityLinkChanges as $propertyChange) {
1698
            $oldValue = $propertyChange->getOrgValueString();
1699
            $propertyName = $propertyChange->getPropertyName();
1700
            if ($oldValue !== null) {
1701
                $this->fireIdentityLinkHistoryEvents($oldValue, null, $propertyName, HistoryEventTypes::identityLinkDelete());
0 ignored issues
show
Bug introduced by
null of type null is incompatible with the type string expected by parameter $groupId of Jabe\Impl\Persistence\En...tityLinkHistoryEvents(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1701
                $this->fireIdentityLinkHistoryEvents($oldValue, /** @scrutinizer ignore-type */ null, $propertyName, HistoryEventTypes::identityLinkDelete());
Loading history...
1702
            }
1703
            $newValue = $propertyChange->getNewValueString();
1704
            if ($newValue !== null) {
1705
                $this->fireIdentityLinkHistoryEvents($newValue, null, $propertyName, HistoryEventTypes::identityLinkAdd());
1706
            }
1707
        }
1708
        $this->identityLinkChanges = [];
1709
    }
1710
1711
    public function getProcessEngineServices(): ProcessEngineServicesInterface
1712
    {
1713
        return Context::getProcessEngineConfiguration()
1714
                ->getProcessEngine();
0 ignored issues
show
Bug introduced by
The method getProcessEngine() does not exist on Jabe\Impl\Cfg\ProcessEngineConfigurationImpl. Did you maybe mean getProcessEngineBootstrapCommand()? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

1714
                ->/** @scrutinizer ignore-call */ getProcessEngine();

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
1715
    }
1716
1717
    public function getProcessEngine(): ProcessEngineInterface
1718
    {
1719
        return Context::getProcessEngineConfiguration()->getProcessEngine();
1720
    }
1721
1722
    public function equals($obj = null): bool
1723
    {
1724
        if ($this == $obj) {
1725
            return true;
1726
        }
1727
        if ($obj === null) {
1728
            return false;
1729
        }
1730
        if (get_class($this) != get_class($obj)) {
1731
            return false;
1732
        }
1733
        if ($this->id === null) {
1734
            if ($obj->id !== null) {
1735
                return false;
1736
            }
1737
        } elseif ($this->id != $obj->id) {
1738
            return false;
1739
        }
1740
        return true;
1741
    }
1742
1743
    public function executeMetrics(string $metricsName, CommandContext $commandContext): void
1744
    {
1745
        $processEngineConfiguration = Context::getProcessEngineConfiguration();
1746
        if (Metrics::ACTIVTY_INSTANCE_START == $metricsName && $processEngineConfiguration->isMetricsEnabled()) {
0 ignored issues
show
Bug introduced by
The method isMetricsEnabled() does not exist on Jabe\Impl\Cfg\ProcessEngineConfigurationImpl. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

1746
        if (Metrics::ACTIVTY_INSTANCE_START == $metricsName && $processEngineConfiguration->/** @scrutinizer ignore-call */ isMetricsEnabled()) {

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
1747
            $processEngineConfiguration->getMetricsRegistry()->markOccurrence(Metrics::ACTIVTY_INSTANCE_START);
0 ignored issues
show
Bug introduced by
The method getMetricsRegistry() does not exist on Jabe\Impl\Cfg\ProcessEngineConfigurationImpl. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

1747
            $processEngineConfiguration->/** @scrutinizer ignore-call */ 
1748
                                         getMetricsRegistry()->markOccurrence(Metrics::ACTIVTY_INSTANCE_START);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
1748
        }
1749
        if (
1750
            Metrics::UNIQUE_TASK_WORKERS == $metricsName && $processEngineConfiguration->isTaskMetricsEnabled() &&
1751
            $this->assignee !== null && array_key_exists(self::ASSIGNEE, $this->propertyChanges)
1752
        ) {
1753
            // assignee has changed and is not null, so mark a new task worker
1754
            $commandContext->getMeterLogManager()->insert(new TaskMeterLogEntity($this->assignee, ClockUtil::getCurrentTime()->format('c')));
0 ignored issues
show
Bug introduced by
new Jabe\Impl\Persistenc...entTime()->format('c')) of type Jabe\Impl\Persistence\Entity\TaskMeterLogEntity is incompatible with the type Jabe\Impl\Persistence\Entity\MeterLogEntity expected by parameter $meterLogEntity of Jabe\Impl\Persistence\En...terLogManager::insert(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1754
            $commandContext->getMeterLogManager()->insert(/** @scrutinizer ignore-type */ new TaskMeterLogEntity($this->assignee, ClockUtil::getCurrentTime()->format('c')));
Loading history...
1755
        }
1756
    }
1757
1758
    public function addIdentityLinkChanges(string $type, string $oldProperty, string $newProperty): void
1759
    {
1760
        $this->identityLinkChanges[] = new PropertyChange($type, $oldProperty, $newProperty);
1761
    }
1762
1763
    public function setVariablesLocal(array $variables, ?bool $skipSerializationFormatCheck = null): void
1764
    {
1765
        parent::setVariablesLocal($variables, $skipSerializationFormatCheck);
1766
        Context::getCommandContext()->getDbEntityManager()->forceUpdate($this);
1767
    }
1768
1769
    public function getReferencedEntityIds(): array
1770
    {
1771
        $referencedEntityIds = [];
1772
        return $referencedEntityIds;
1773
    }
1774
1775
    public function getReferencedEntitiesIdAndClass(): array
1776
    {
1777
        $referenceIdAndClass = [];
1778
1779
        if ($this->processDefinitionId !== null) {
1780
            $referenceIdAndClass[$this->processDefinitionId] = ProcessDefinitionEntity::class;
1781
        }
1782
        if ($this->processInstanceId !== null) {
1783
            $referenceIdAndClass[$this->processInstanceId] = ExecutionEntity::class;
1784
        }
1785
        if ($this->executionId !== null) {
1786
            $referenceIdAndClass[$this->executionId] = ExecutionEntity::class;
1787
        }
1788
        /*if (caseDefinitionId !== null) {
1789
            referenceIdAndClass.put(caseDefinitionId, CaseDefinitionEntity::class);
1790
        }
1791
        if (caseExecutionId !== null) {
1792
            referenceIdAndClass.put(caseExecutionId, CaseExecutionEntity::class);
1793
        }*/
1794
1795
        return $referenceIdAndClass;
1796
    }
1797
1798
    public function bpmnError(string $errorCode, ?string $errorMessage, ?array $variables = null): void
1799
    {
1800
        $this->ensureTaskActive();
1801
        $activityExecution = $this->getExecution();
1802
        $bpmnError = null;
1803
        if ($errorMessage !== null) {
1804
            $bpmnError = new BpmnError($errorCode, $errorMessage);
0 ignored issues
show
Bug introduced by
$errorMessage of type string is incompatible with the type Throwable|null expected by parameter $previous of Jabe\Delegate\BpmnError::__construct(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1804
            $bpmnError = new BpmnError($errorCode, /** @scrutinizer ignore-type */ $errorMessage);
Loading history...
1805
        } else {
1806
            $bpmnError = new BpmnError($errorCode);
1807
        }
1808
        try {
1809
            if (!empty($variables)) {
1810
                $activityExecution->setVariables($variables);
1811
            }
1812
            BpmnExceptionHandler::propagateBpmnError($bpmnError, $activityExecution);
1813
        } catch (\Exception $ex) {
1814
            //throw ProcessEngineLogger.CMD_LOGGER.exceptionBpmnErrorPropagationFailed(errorCode, ex);
1815
            throw $ex;
1816
        }
1817
    }
1818
1819
    public function escalation(string $escalationCode, ?array $variables = null): void
1820
    {
1821
        $this->ensureTaskActive();
1822
        $activityExecution = $this->getExecution();
1823
1824
        if (!empty($variables)) {
1825
            $activityExecution->setVariables($variables);
1826
        }
1827
        EscalationHandler::propagateEscalation($activityExecution, $escalationCode);
1828
    }
1829
}
1830