DeployCmd::getAllDeploymentIds()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 19
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 11
dl 0
loc 19
rs 9.9
c 0
b 0
f 0
cc 2
nc 2
nop 1
1
<?php
2
3
namespace Jabe\Impl\Cmd;
4
5
use Jabe\Application\{
6
    ProcessApplicationReferenceInterface,
7
    ProcessApplicationRegistrationInterface
8
};
9
use Jabe\{
10
    ProcessEngineInterface,
11
    RepositoryServiceInterface
12
};
13
use Jabe\Exception\{
14
    NotFoundException,
15
    NotValidException
16
};
17
use Jabe\History\UserOperationLogEntryInterface;
18
use Jabe\Impl\ProcessEngineLogger;
19
use Jabe\Impl\Bpmn\Deployer\BpmnDeployer;
20
use Jabe\Impl\Cfg\{
21
    TransactionLogger,
22
    TransactionState
23
};
24
use Jabe\Impl\Interceptor\{
25
    CommandInterface,
26
    CommandContext
27
};
28
use Jabe\Impl\Persistence\Deploy\DeploymentFailListener;
29
use Jabe\Impl\Persistence\Entity\{
30
    DeploymentEntity,
31
    DeploymentManager,
32
    ProcessApplicationDeploymentImpl,
33
    ProcessDefinitionManager,
34
    PropertyChange,
35
    ResourceEntity,
36
    ResourceManager,
37
    UserOperationLogManager
38
};
39
use Jabe\Impl\Repository\{
40
    CandidateDeploymentImpl,
41
    DeploymentBuilderImpl,
42
    ProcessApplicationDeploymentBuilderImpl
43
};
44
use Jabe\Impl\Util\{
45
    ClockUtil,
46
    StringUtil
47
};
48
use Jabe\Repository\{
49
    CandidateDeploymentInterface,
50
    DeploymentInterface,
51
    DeploymentHandlerInterface,
52
    DeploymentWithDefinitionsInterface,
53
    ProcessApplicationDeploymentInterface,
54
    ProcessApplicationDeploymentBuilderInterface,
55
    ProcessDefinitionInterface,
56
    ResourceInterface,
57
    ResumePreviousBy
58
};
59
use Bpmn\{
60
    Bpmn,
61
    BpmnModelInstanceInterface
62
};
63
use Bpmn\Instance\ProcessInterface;
64
65
class DeployCmd implements CommandInterface
66
{
67
    //private static final CommandLogger LOG = ProcessEngineLogger.CMD_LOGGER;
68
    //private static final TransactionLogger TX_LOG = ProcessEngineLogger.TX_LOGGER;
69
70
    protected $deploymentBuilder;
71
    protected $deploymentHandler;
72
73
    public function __construct(DeploymentBuilderImpl $deploymentBuilder)
74
    {
75
        $this->deploymentBuilder = $deploymentBuilder;
76
    }
77
78
    public function execute(CommandContext $commandContext)
79
    {
80
        return $this->doExecute($commandContext);
81
    }
82
83
    protected function doExecute(CommandContext $commandContext): DeploymentWithDefinitionsInterface
84
    {
85
        $deploymentManager = $commandContext->getDeploymentManager();
86
87
        // load deployment handler
88
        $processEngine = $commandContext->getProcessEngineConfiguration()->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

88
        $processEngine = $commandContext->getProcessEngineConfiguration()->/** @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...
89
        $this->deploymentHandler = $commandContext->getProcessEngineConfiguration()
90
            ->getDeploymentHandlerFactory()
0 ignored issues
show
Bug introduced by
The method getDeploymentHandlerFactory() 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

90
            ->/** @scrutinizer ignore-call */ getDeploymentHandlerFactory()

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...
91
            ->buildDeploymentHandler($processEngine);
92
93
        $deploymentIds = $this->getAllDeploymentIds($this->deploymentBuilder);
94
        if (!empty($deploymentIds)) {
95
            $deploymentIdArray = $deploymentIds;
96
            $deployments = $deploymentManager->findDeploymentsByIds($deploymentIdArray);
97
            $this->ensureDeploymentsWithIdsExists($deploymentIds, $deployments);
98
        }
99
100
        $this->checkCreateAndReadDeployments($commandContext, $deploymentIds);
101
102
        // set deployment name if it should retrieved from an existing deployment
103
        $nameFromDeployment = $this->deploymentBuilder->getNameFromDeployment();
104
        $this->setDeploymentName($nameFromDeployment, $this->deploymentBuilder, $commandContext);
105
106
        // get resources to re-deploy
107
        $resources = $this->getResources($this->deploymentBuilder, $commandContext);
108
        // .. and add them the builder
109
        $this->addResources($resources, $this->deploymentBuilder);
110
111
        $resourceNames = $this->deploymentBuilder->getResourceNames();
112
        if (empty($resourceNames)) {
113
            throw new NotValidException("No deployment resources contained to deploy.");
114
        }
115
116
        // perform deployment
117
        $self = $this;
118
        $deployment = $commandContext->runWithoutAuthorization(function () use ($self, $commandContext) {
119
            $self->acquireExclusiveLock($commandContext);
120
            $deploymentToRegister = $self->initDeployment();
121
            $resourcesToDeploy = $self->resolveResourcesToDeploy($commandContext, $deploymentToRegister);
122
            $resourcesToIgnore = $deploymentToRegister->getResources();
123
            foreach (array_keys($resourcesToDeploy) as $key) {
124
                if (array_key_exists($key, $resourcesToIgnore)) {
125
                    unset($resourcesToIgnore[$key]);
126
                }
127
            }
128
            // save initial deployment resources before they are replaced with only the deployed ones
129
            $candidateDeployment =
130
                CandidateDeploymentImpl::fromDeploymentEntity($deploymentToRegister);
131
            if (!empty($resourcesToDeploy)) {
132
                //LOG.debugCreatingNewDeployment();
133
                $deploymentToRegister->setResources($resourcesToDeploy);
134
                $self->deploy($commandContext, $deploymentToRegister);
135
            } else {
136
                // if there are no resources to be deployed, find an existing deployment
137
                $duplicateDeploymentId = $self->deploymentHandler->determineDuplicateDeployment($candidateDeployment);
138
                $deploymentToRegister = $commandContext->getDeploymentManager()->findDeploymentById($duplicateDeploymentId);
139
            }
140
141
            $self->scheduleProcessDefinitionActivation($commandContext, $deploymentToRegister);
142
143
            if ($self->deploymentBuilder instanceof ProcessApplicationDeploymentBuilderInterface) {
144
                // for process application deployments, job executor registration
145
                // is managed by the ProcessApplicationManager
146
                $registration = $self->registerProcessApplication(
147
                    $commandContext,
148
                    $deploymentToRegister,
149
                    $candidateDeployment,
150
                    array_values($resourcesToIgnore)
151
                );
152
153
                return new ProcessApplicationDeploymentImpl($deploymentToRegister, $registration);
154
            } else {
155
                $self->registerWithJobExecutor($commandContext, $deploymentToRegister);
156
            }
157
158
            return $deploymentToRegister;
159
        });
160
161
        $this->createUserOperationLog($this->deploymentBuilder, $deployment, $commandContext);
0 ignored issues
show
Bug introduced by
It seems like $deployment can also be of type null; however, parameter $deployment of Jabe\Impl\Cmd\DeployCmd::createUserOperationLog() does only seem to accept Jabe\Repository\DeploymentInterface, 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

161
        $this->createUserOperationLog($this->deploymentBuilder, /** @scrutinizer ignore-type */ $deployment, $commandContext);
Loading history...
162
163
        return $deployment;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $deployment could return the type null which is incompatible with the type-hinted return Jabe\Repository\DeploymentWithDefinitionsInterface. Consider adding an additional type-check to rule them out.
Loading history...
164
    }
165
166
    protected function acquireExclusiveLock(CommandContext $commandContext): void
167
    {
168
        if ($commandContext->getProcessEngineConfiguration()->isDeploymentLockUsed()) {
0 ignored issues
show
Bug introduced by
The method isDeploymentLockUsed() 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

168
        if ($commandContext->getProcessEngineConfiguration()->/** @scrutinizer ignore-call */ isDeploymentLockUsed()) {

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...
169
            // Acquire global exclusive lock: this ensures that there can be only one
170
            // transaction in the cluster which is allowed to perform deployments.
171
            // This is important to ensure that duplicate filtering works correctly
172
            // in a multi-node cluster. See also https://app.camunda.com/jira/browse/CAM-2128
173
174
            // It is also important to ensure the uniqueness of a process definition key,
175
            // version and tenant-id since there is no database constraint to check it.
176
177
            $commandContext->getPropertyManager()->acquireExclusiveLock();
178
        } else {
179
            //LOG.warnDisabledDeploymentLock();
180
        }
181
    }
182
183
    protected function resolveResourcesToDeploy(
184
        CommandContext $commandContext,
185
        DeploymentEntity $candidateDeployment
186
    ): array {
187
188
        $resourcesToDeploy = [];
189
        $candidateResources = $candidateDeployment->getResources();
190
191
        if ($this->deploymentBuilder->isDuplicateFilterEnabled()) {
192
            $source = $candidateDeployment->getSource();
193
            if ($source == null || empty($source)) {
194
                $source = ProcessApplicationDeploymentInterface::PROCESS_APPLICATION_DEPLOYMENT_SOURCE;
195
            }
196
197
            $existingResources = $commandContext
198
                ->getResourceManager()
199
                ->findLatestResourcesByDeploymentName(
200
                    $candidateDeployment->getName(),
201
                    array_keys($candidateResources),
202
                    $source,
203
                    $candidateDeployment->getTenantId()
0 ignored issues
show
Bug introduced by
It seems like $candidateDeployment->getTenantId() can also be of type null; however, parameter $tenantId of Jabe\Impl\Persistence\En...urcesByDeploymentName() 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

203
                    /** @scrutinizer ignore-type */ $candidateDeployment->getTenantId()
Loading history...
204
                );
205
206
            foreach ($candidateResources as $key => $deployedResource) {
207
                $resourceName = $deployedResource->getName();
208
                $existingResource = null;
209
                if (array_key_exists($resourceName, $existingResources)) {
210
                    $existingResource = $existingResources[$resourceName];
211
                }
212
213
                if (
214
                    $existingResource == null
215
                    || $existingResource->isGenerated()
216
                    || $this->deploymentHandler->shouldDeployResource($deployedResource, $existingResource)
217
                ) {
218
                    if ($this->deploymentBuilder->isDeployChangedOnly()) {
219
                        // resource should be deployed
220
                        $resourcesToDeploy[$resourceName] = $deployedResource;
221
                    } else {
222
                        // all resources should be deployed
223
                        $resourcesToDeploy = $candidateResources;
224
                        break;
225
                    }
226
                }
227
            }
228
        } else {
229
            $resourcesToDeploy = $candidateResources;
230
        }
231
232
        return $resourcesToDeploy;
233
    }
234
235
    protected function deploy(CommandContext $commandContext, DeploymentEntity $deployment): void
236
    {
237
        $deployment->setNew(true);
238
        $commandContext->getDeploymentManager()->insertDeployment($deployment);
239
    }
240
241
    protected function scheduleProcessDefinitionActivation(
242
        CommandContext $commandContext,
243
        DeploymentWithDefinitionsInterface $deployment
244
    ): void {
245
246
        if ($this->deploymentBuilder->getProcessDefinitionsActivationDate() !== null) {
0 ignored issues
show
introduced by
The condition $this->deploymentBuilder...tivationDate() !== null is always true.
Loading history...
247
            $repositoryService = $commandContext->getProcessEngineConfiguration()
248
                ->getRepositoryService();
0 ignored issues
show
Bug introduced by
The method getRepositoryService() 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

248
                ->/** @scrutinizer ignore-call */ getRepositoryService();

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...
249
250
            foreach ($this->getDeployedProcesses($commandContext, $deployment) as $processDefinition) {
251
                // If activation date is set, we first suspend all the process definition
252
                $repositoryService
253
                    ->updateProcessDefinitionSuspensionState()
254
                    ->byProcessDefinitionId($processDefinition->getId())
255
                    ->suspend();
256
257
                // And we schedule an activation at the provided date
258
                $repositoryService
259
                    ->updateProcessDefinitionSuspensionState()
260
                    ->byProcessDefinitionId($processDefinition->getId())
261
                    ->executionDate($this->deploymentBuilder->getProcessDefinitionsActivationDate())
262
                    ->activate();
263
            }
264
        }
265
    }
266
267
    protected function registerProcessApplication(
268
        CommandContext $commandContext,
269
        DeploymentEntity $deploymentToRegister,
270
        CandidateDeploymentInterface $candidateDeployment,
271
        array $ignoredResources
272
    ): ProcessApplicationRegistrationInterface {
273
274
        $appDeploymentBuilder = $this->deploymentBuilder;
275
        $appReference = $appDeploymentBuilder->getProcessApplicationReference();
0 ignored issues
show
introduced by
The method getProcessApplicationReference() does not exist on Jabe\Impl\Repository\DeploymentBuilderImpl. Maybe you want to declare this class abstract? ( Ignorable by Annotation )

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

275
        /** @scrutinizer ignore-call */ 
276
        $appReference = $appDeploymentBuilder->getProcessApplicationReference();
Loading history...
276
277
        // build set of deployment ids this process app should be registered for:
278
        $deploymentsToRegister = [$deploymentToRegister->getId()];
279
        if ($appDeploymentBuilder->isResumePreviousVersions()) {
0 ignored issues
show
introduced by
The method isResumePreviousVersions() does not exist on Jabe\Impl\Repository\DeploymentBuilderImpl. Maybe you want to declare this class abstract? ( Ignorable by Annotation )

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

279
        if ($appDeploymentBuilder->/** @scrutinizer ignore-call */ isResumePreviousVersions()) {
Loading history...
280
            $resumePreviousBy = $appDeploymentBuilder->getResumePreviousVersionsBy();
0 ignored issues
show
introduced by
The method getResumePreviousVersionsBy() does not exist on Jabe\Impl\Repository\DeploymentBuilderImpl. Maybe you want to declare this class abstract? ( Ignorable by Annotation )

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

280
            /** @scrutinizer ignore-call */ 
281
            $resumePreviousBy = $appDeploymentBuilder->getResumePreviousVersionsBy();
Loading history...
281
            switch ($resumePreviousBy) {
282
                case ResumePreviousBy::RESUME_BY_DEPLOYMENT_NAME:
283
                    $deploymentsToRegister = array_merge(
284
                        $deploymentsToRegister,
285
                        $this->deploymentHandler->determineDeploymentsToResumeByDeploymentName($candidateDeployment)
286
                    );
287
                    break;
288
289
                case ResumePreviousBy::RESUME_BY_PROCESS_DEFINITION_KEY:
290
                default:
291
                    $processDefinitionKeys = $this->getProcessDefinitionsFromResources(
292
                        $commandContext,
293
                        $deploymentToRegister,
294
                        $ignoredResources
295
                    );
296
297
                    // only determine deployments to resume if there are actual process definitions to look for
298
                    if (count($processDefinitionKeys) > 0) {
299
                        $deploymentsToRegister = array_merge(
300
                            $deploymentsToRegister,
301
                            $this->deploymentHandler->determineDeploymentsToResumeByProcessDefinitionKey($processDefinitionKeys)
302
                        );
303
                    }
304
                    break;
305
            }
306
        }
307
308
        // register process application for deployments
309
        return (new RegisterProcessApplicationCmd($deploymentsToRegister, $appReference))->execute($commandContext);
310
    }
311
312
    protected function registerWithJobExecutor(CommandContext $commandContext, DeploymentInterface $deployment): void
313
    {
314
        try {
315
            (new RegisterDeploymentCmd($deployment->getId()))->execute($commandContext);
316
        } finally {
317
            $listener = new DeploymentFailListener(
318
                $deployment->getId(),
319
                $commandContext->getProcessEngineConfiguration()->getCommandExecutorTxRequiresNew()
0 ignored issues
show
Bug introduced by
The method getCommandExecutorTxRequiresNew() 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

319
                $commandContext->getProcessEngineConfiguration()->/** @scrutinizer ignore-call */ getCommandExecutorTxRequiresNew()

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...
320
            );
321
            try {
322
                $commandContext->getTransactionContext()->addTransactionListener(TransactionState::ROLLED_BACK, $listener);
323
            } catch (\Exception $e) {
324
                //TX_LOG.debugTransactionOperation("Could not register transaction synchronization. Probably the TX has already been rolled back by application code.");
325
                $listener->execute($commandContext);
326
            }
327
        }
328
    }
329
330
    // setters, initializers etc.
331
332
    protected function createUserOperationLog(DeploymentBuilderImpl $deploymentBuilder, DeploymentInterface $deployment, CommandContext $commandContext): void
333
    {
334
        $logManager = $commandContext->getOperationLogManager();
335
        $properties = [];
336
337
        $filterDuplicate = new PropertyChange("duplicateFilterEnabled", null, $deploymentBuilder->isDuplicateFilterEnabled());
338
        $properties[] = $filterDuplicate;
339
340
        if ($deploymentBuilder->isDuplicateFilterEnabled()) {
341
            $deployChangedOnly = new PropertyChange("deployChangedOnly", null, $deploymentBuilder->isDeployChangedOnly());
342
            $properties[] = $deployChangedOnly;
343
        }
344
345
        $logManager->logDeploymentOperation(UserOperationLogEntryInterface::OPERATION_TYPE_CREATE, $deployment->getId(), $properties);
346
    }
347
348
    protected function initDeployment(): DeploymentEntity
349
    {
350
        $deployment = $this->deploymentBuilder->getDeployment();
351
        $deployment->setDeploymentTime(ClockUtil::getCurrentTime());
0 ignored issues
show
Bug introduced by
Jabe\Impl\Util\ClockUtil::getCurrentTime() of type DateTime is incompatible with the type string expected by parameter $deploymentTime of Jabe\Impl\Persistence\En...ty::setDeploymentTime(). ( Ignorable by Annotation )

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

351
        $deployment->setDeploymentTime(/** @scrutinizer ignore-type */ ClockUtil::getCurrentTime());
Loading history...
352
        return $deployment;
353
    }
354
355
    protected function setDeploymentName(?string $deploymentId, DeploymentBuilderImpl $deploymentBuilder, CommandContext $commandContext): void
356
    {
357
        if (!empty($deploymentId)) {
358
            $deploymentManager = $commandContext->getDeploymentManager();
359
            $deployment = $deploymentManager->findDeploymentById($deploymentId);
360
            $deploymentBuilder->getDeployment()->setName($deployment->getName());
361
        }
362
    }
363
364
    protected function addResources(array $resources, DeploymentBuilderImpl $deploymentBuilder): void
365
    {
366
        $deployment = $deploymentBuilder->getDeployment();
367
        $existingResources = $deployment->getResources();
368
369
        foreach ($resources as $resource) {
370
            $resourceName = $resource->getName();
371
372
            if (!empty($existingResources) && array_key_exists($resourceName, $existingResources)) {
373
                $message = sprintf("Cannot add resource with id '%s' and name '%s' from "
374
                    . "deployment with id '%s' to new deployment because the new deployment contains "
375
                    . "already a resource with same name.", $resource->getId(), $resourceName, $resource->getDeploymentId());
376
377
                throw new NotValidException($message);
378
            }
379
380
            $inputStream = $resource->getBytes();
381
            $deploymentBuilder->addInputStream($resourceName, $inputStream);
382
        }
383
    }
384
385
    // getters
386
387
    protected function getMissingElements(array $expected, array $actual): array
388
    {
389
        $missingElements = [];
390
        foreach ($expected as $value) {
391
            if (!array_key_exists($value, $actual)) {
392
                $missingElements[] = $value;
393
            }
394
        }
395
        return $missingElements;
396
    }
397
398
    protected function getResources(DeploymentBuilderImpl $deploymentBuilder, CommandContext $commandContext): array
399
    {
400
        $resources = [];
0 ignored issues
show
Unused Code introduced by
The assignment to $resources is dead and can be removed.
Loading history...
401
402
        $deploymentIds = $deploymentBuilder->getDeployments();
403
        $resources = $this->getResourcesByDeploymentId($deploymentIds, $commandContext);
404
405
        $deploymentResourcesById = $deploymentBuilder->getDeploymentResourcesById();
406
        $resources = array_merge($resources, $this->getResourcesById($deploymentResourcesById, $commandContext));
407
408
        $deploymentResourcesByName = $deploymentBuilder->getDeploymentResourcesByName();
409
        $resources = array_merge($resources, $this->getResourcesByName($deploymentResourcesByName, $commandContext));
410
411
        $this->checkDuplicateResourceName($resources);
412
413
        return $resources;
414
    }
415
416
    protected function getResourcesByDeploymentId(array $deploymentIds, CommandContext $commandContext): array
417
    {
418
        $result = [];
419
420
        if (!empty($deploymentIds)) {
421
            $deploymentManager = $commandContext->getDeploymentManager();
422
423
            foreach ($deploymentIds as $deploymentId) {
424
                $deployment = $deploymentManager->findDeploymentById($deploymentId);
425
                $resources = $deployment->getResources();
426
                $values = array_values($resources);
427
                $result = array_merge($result, $values);
428
            }
429
        }
430
431
        return $result;
432
    }
433
434
    protected function getResourcesById(array $resourcesById, CommandContext $commandContext): array
435
    {
436
        $result = [];
437
438
        $resourceManager = $commandContext->getResourceManager();
439
440
        foreach (array_keys($resourcesById) as $deploymentId) {
441
            $resourceIds = $resourcesById[$deploymentId];
442
443
            $resourceIdArray = $resourceIds;
444
            $resources = $resourceManager->findResourceByDeploymentIdAndResourceIds($deploymentId, $resourceIdArray);
445
446
            $this->ensureResourcesWithIdsExist($deploymentId, $resourceIds, $resources);
447
448
            $result = array_merge($result, $resources);
449
        }
450
451
        return $result;
452
    }
453
454
    protected function getResourcesByName(array $resourcesByName, CommandContext $commandContext): array
455
    {
456
        $result = [];
457
458
        $resourceManager = $commandContext->getResourceManager();
459
460
        foreach (array_keys($resourcesByName) as $deploymentId) {
461
            $resourceNames = $resourcesByName[$deploymentId];
462
463
            $resourceNameArray = $resourceNames;
464
            $resources = $resourceManager->findResourceByDeploymentIdAndResourceNames($deploymentId, $resourceNameArray);
465
466
            $this->ensureResourcesWithNamesExist($deploymentId, $resourceNames, $resources);
467
468
            $result = array_merge($result, $resources);
469
        }
470
        return $result;
471
    }
472
473
    protected function getDeployedProcesses(CommandContext $commandContext, DeploymentWithDefinitionsInterface $deployment): array
474
    {
475
        $deployedProcessDefinitions = $deployment->getDeployedProcessDefinitions();
476
        if (empty($deployedProcessDefinitions)) {
477
            // existing deployment
478
            $manager = $commandContext->getProcessDefinitionManager();
479
            $deployedProcessDefinitions = $manager->findProcessDefinitionsByDeploymentId($deployment->getId());
480
        }
481
        return $deployedProcessDefinitions;
482
    }
483
484
    protected function getProcessDefinitionsFromResources(
485
        CommandContext $commandContext,
486
        DeploymentEntity $deploymentToRegister,
487
        array $ignoredResources
488
    ): array {
489
490
        $processDefinitionKeys = [];
0 ignored issues
show
Unused Code introduced by
The assignment to $processDefinitionKeys is dead and can be removed.
Loading history...
491
492
        // get process definition keys for already available process definitions
493
        $processDefinitionKeys = $this->parseProcessDefinitionKeys($ignoredResources);
494
495
        // get process definition keys for updated process definitions
496
        foreach ($this->getDeployedProcesses($commandContext, $deploymentToRegister) as $processDefinition) {
497
            if ($processDefinition->getVersion() > 1) {
498
                $processDefinitionKeys[] = $processDefinition->getKey();
499
            }
500
        }
501
502
        return $processDefinitionKeys;
503
    }
504
505
    protected function parseProcessDefinitionKeys(array $resources): array
506
    {
507
        $processDefinitionKeys = [];
508
509
        foreach ($resources as $resource) {
510
            if ($this->isBpmnResource($resource)) {
511
                $byteStream = $resource->getBytes();
512
                $file = tmpfile();
513
                fwrite($file, $byteStream);
514
                $model = Bpmn::readModelFromStream($file);
515
                foreach ($model->getDefinitions()->getChildElementsByType(ProcessInterface::class) as $process) {
516
                    $processDefinitionKeys[] = $process->getId();
517
                }
518
            }
519
            /*elseif (isCmmnResource(resource)) {
520
                ByteArrayInputStream byteStream = new ByteArrayInputStream(resource.getBytes());
521
                CmmnModelInstance model = Cmmn.readModelFromStream(byteStream);
522
                for (Case cmmnCase : model.getDefinitions().getCases()) {
523
                    processDefinitionKeys.add(cmmnCase.getId());
524
                }
525
            }*/
526
        }
527
        return $processDefinitionKeys;
528
    }
529
530
    protected function getAllDeploymentIds(DeploymentBuilderImpl $deploymentBuilder): array
531
    {
532
        $result = [];
533
534
        $nameFromDeployment = $deploymentBuilder->getNameFromDeployment();
535
        if (!empty($nameFromDeployment)) {
536
            $result[] = $nameFromDeployment;
537
        }
538
539
        $deployments = $deploymentBuilder->getDeployments();
540
        $result = array_merge($result, $deployments);
541
542
        $deployments = array_keys($deploymentBuilder->getDeploymentResourcesById());
543
        $result = array_merge($result, $deployments);
544
545
        $deployments = array_keys($deploymentBuilder->getDeploymentResourcesByName());
546
        $result = array_merge($result, $deployments);
547
548
        return $result;
549
    }
550
551
    // checkers
552
553
    protected function checkDuplicateResourceName(array $resources): void
554
    {
555
        $resourceMap = [];
556
557
        foreach ($resources as $resource) {
558
            $name = $resource->getName();
559
560
            if (array_key_exists($name, $resourceMap)) {
561
                $duplicate = $resourceMap[$name];
562
                $deploymentId = $resource->getDeploymentId();
563
                if ($deploymentId != $duplicate->getDeploymentId()) {
564
                    $message = sprintf("The deployments with id '%s' and '%s' contain a resource with same name '%s'.", $deploymentId, $duplicate->getDeploymentId(), $name);
565
                    throw new NotValidException($message);
566
                }
567
            }
568
            $resourceMap[$name] = $resource;
569
        }
570
    }
571
572
    protected function checkCreateAndReadDeployments(CommandContext $commandContext, array $deploymentIds): void
573
    {
574
        foreach ($commandContext->getProcessEngineConfiguration()->getCommandCheckers() as $checker) {
0 ignored issues
show
Bug introduced by
The method getCommandCheckers() 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

574
        foreach ($commandContext->getProcessEngineConfiguration()->/** @scrutinizer ignore-call */ getCommandCheckers() as $checker) {

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...
575
            $checker->checkCreateDeployment();
576
            foreach ($deploymentIds as $deploymentId) {
577
                $checker->checkReadDeployment($deploymentId);
578
            }
579
        }
580
    }
581
582
    protected function isBpmnResource(ResourceInterface $resourceEntity): bool
583
    {
584
        return StringUtil::hasAnySuffix($resourceEntity->getName(), BpmnDeployer::BPMN_RESOURCE_SUFFIXES);
585
    }
586
587
    /*protected function isCmmnResource(Resource resourceEntity): bool
588
    {
589
        return StringUtil.hasAnySuffix(resourceEntity.getName(), CmmnDeployer.CMMN_RESOURCE_SUFFIXES);
590
    }*/
591
592
    // ensures
593
    protected function ensureDeploymentsWithIdsExists(array $expected, array $actual): void
594
    {
595
        $deploymentMap = [];
596
        foreach ($actual as $deployment) {
597
            $deploymentMap[$deployment->getId()] = $deployment;
598
        }
599
600
        $missingDeployments = $this->getMissingElements($expected, $deploymentMap);
601
602
        if (!empty($missingDeployments)) {
603
            $builder = "";
604
605
            $builder .= "The following deployments are not found by id: ";
606
            $builder .= StringUtil::join($missingDeployments);
607
608
            throw new NotFoundException($builder);
609
        }
610
    }
611
612
    protected function ensureResourcesWithIdsExist(string $deploymentId, array $expectedIds, array $actual): void
613
    {
614
        $resources = [];
615
        foreach ($actual as $resource) {
616
            $resources[$resource->getId()] = $resource;
617
        }
618
        $this->ensureResourcesWithKeysExist($deploymentId, $expectedIds, $resources, "id");
619
    }
620
621
    protected function ensureResourcesWithNamesExist(string $deploymentId, array $expectedNames, array $actual): void
622
    {
623
        $resources = [];
624
        foreach ($actual as $resource) {
625
            $resources[$resource->getName()] = $resource;
626
        }
627
        $this->ensureResourcesWithKeysExist($deploymentId, $expectedNames, $resources, "name");
628
    }
629
630
    protected function ensureResourcesWithKeysExist(string $deploymentId, array $expectedKeys, array $actual, string $valueProperty): void
631
    {
632
        $missingResources = $this->getMissingElements($expectedKeys, $actual);
633
634
        if (!empty($missingResources)) {
635
            $builder = "";
636
            $builder .= "The deployment with id '";
637
            $builder .= $deploymentId;
638
            $builder .= "' does not contain the following resources with ";
639
            $builder .= $valueProperty;
640
            $builder .= ": ";
641
            $builder .= StringUtil::join($missingResources);
642
            throw new NotFoundException($builder);
643
        }
644
    }
645
646
    public function isRetryable(): bool
647
    {
648
        return true;
649
    }
650
}
651