Test Failed
Push — main ( d01f4c...5af89f )
by Bingo
15:56
created

postProcessDefinitions()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 4
dl 0
loc 9
rs 10
c 1
b 0
f 0
cc 2
nc 2
nop 3
1
<?php
2
3
namespace Jabe\Engine\Impl;
4
5
use Jabe\Engine\ProcessEngineException;
6
use Jabe\Engine\Impl\Cfg\{
7
    IdGeneratorInterface,
8
    ProcessEngineConfigurationImpl
9
};
10
use Jabe\Engine\Impl\Cmd\CommandLogger;
11
use Jabe\Engine\Impl\Context\Context;
12
use Jabe\Engine\Impl\Core\Model\Properties;
13
use Jabe\Engine\Impl\Interceptor\CommandContext;
14
use Jabe\Engine\Impl\Persistence\Deploy\DeployerInterface;
15
use Jabe\Engine\Impl\Persistence\Deploy\Cache\DeploymentCache;
16
use Jabe\Engine\Impl\Persistence\Entity\{
17
    DeploymentEntity,
18
    ResourceEntity
19
};
20
use Jabe\Engine\Impl\Repository\ResourceDefinitionEntityInterface;
21
22
abstract class AbstractDefinitionDeployer implements DeployerInterface
23
{
24
    public const DIAGRAM_SUFFIXES = [ "png", "jpg", "gif", "svg" ];
25
26
    //private final CommandLogger LOG = ProcessEngineLogger.CMD_LOGGER;
27
28
    protected $idGenerator;
29
30
    public function getIdGenerator(): IdGeneratorInterface
31
    {
32
        return $this->idGenerator;
33
    }
34
35
    public function setIdGenerator(IdGeneratorInterface $idGenerator): void
36
    {
37
        $this->idGenerator = $idGenerator;
38
    }
39
40
    public function deploy(DeploymentEntity $deployment): void
41
    {
42
        //LOG.debugProcessingDeployment(deployment.getName());
43
        $properties = new Properties();
44
        $definitions = $this->parseDefinitionResources($deployment, $properties);
45
        $this->ensureNoDuplicateDefinitionKeys($definitions);
46
        $this->postProcessDefinitions($deployment, $definitions, $properties);
47
    }
48
49
    protected function parseDefinitionResources(DeploymentEntity $deployment, Properties $properties): array
50
    {
51
        $definitions = [];
52
        foreach ($deployment->getResources() as $resource) {
53
            //LOG.debugProcessingResource(resource.getName());
54
            if ($this->isResourceHandled($resource)) {
55
                $definitions = array_merge($definitions, $this->transformResource($deployment, $resource, $properties));
56
            }
57
        }
58
        return $definitions;
59
    }
60
61
    protected function isResourceHandled(ResourceEntity $resource): bool
62
    {
63
        $resourceName = $resource->getName();
64
65
        foreach ($this->getResourcesSuffixes() as $suffix) {
66
            if (str_ends_with($resourceName, $suffix)) {
67
                return true;
68
            }
69
        }
70
71
        return false;
72
    }
73
74
    /**
75
     * @return the list of resource suffixes for this cacheDeployer
0 ignored issues
show
Bug introduced by
The type Jabe\Engine\Impl\the was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
76
     */
77
    abstract protected function getResourcesSuffixes(): array;
78
79
    protected function transformResource(DeploymentEntity $deployment, ResourceEntity $resource, Properties $properties): array
80
    {
81
        $resourceName = $resource->getName();
82
        $definitions = $this->transformDefinitions($deployment, $resource, $properties);
83
84
        foreach ($definitions as $definition) {
85
            $definition->setResourceName($resourceName);
86
87
            $diagramResourceName = $this->getDiagramResourceForDefinition($deployment, $resourceName, $definition, $deployment->getResources());
88
            if ($diagramResourceName != null) {
0 ignored issues
show
Bug introduced by
It seems like you are loosely comparing $diagramResourceName of type null|string against null; this is ambiguous if the string can be empty. Consider using a strict comparison !== instead.
Loading history...
89
                $definition->setDiagramResourceName($diagramResourceName);
90
            }
91
        }
92
93
        return $definitions;
94
    }
95
96
    /**
97
     * Transform the resource entity into definition entities.
98
     *
99
     * @param deployment the deployment the resources belongs to
100
     * @param resource the resource to transform
101
     * @return a list of transformed definition entities
102
     */
103
    abstract protected function transformDefinitions(DeploymentEntity $deployment, ResourceEntity $resource, Properties $properties): array;
104
105
    /**
106
     * Returns the default name of the image resource for a certain definition.
107
     *
108
     * It will first look for an image resource which matches the definition
109
     * specifically, before resorting to an image resource which matches the file
110
     * containing the definition.
111
     *
112
     * Example: if the deployment contains a BPMN 2.0 xml resource called
113
     * 'abc.bpmn20.xml' containing only one process with key 'myProcess', then
114
     * this method will look for an image resources called 'abc.myProcess.png'
115
     * (or .jpg, or .gif, etc.) or 'abc.png' if the previous one wasn't found.
116
     *
117
     * Example 2: if the deployment contains a BPMN 2.0 xml resource called
118
     * 'abc.bpmn20.xml' containing three processes (with keys a, b and c),
119
     * then this method will first look for an image resource called 'abc.a.png'
120
     * before looking for 'abc.png' (likewise for b and c).
121
     * Note that if abc.a.png, abc.b.png and abc.c.png don't exist, all
122
     * processes will have the same image: abc.png.
123
     *
124
     * @return null if no matching image resource is found.
125
     */
126
    protected function getDiagramResourceForDefinition(DeploymentEntity $deployment, string $resourceName, DefinitionEntity $definition, array $resources): ?string
0 ignored issues
show
Unused Code introduced by
The parameter $deployment 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

126
    protected function getDiagramResourceForDefinition(/** @scrutinizer ignore-unused */ DeploymentEntity $deployment, string $resourceName, DefinitionEntity $definition, array $resources): ?string

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...
Bug introduced by
The type Jabe\Engine\Impl\DefinitionEntity was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
127
    {
128
        foreach ($this->getDiagramSuffixes() as $diagramSuffix) {
129
            $definitionDiagramResource = $this->getDefinitionDiagramResourceName($resourceName, $definition, $diagramSuffix);
130
            $diagramForFileResource = $this->getGeneralDiagramResourceName($resourceName, $definition, $diagramSuffix);
131
            if (array_key_exists($definitionDiagramResource, $resources)) {
132
                return $definitionDiagramResource;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $definitionDiagramResource returns the type string which is incompatible with the documented return type null.
Loading history...
133
            } elseif (array_key_exists($diagramForFileResource, $resources)) {
134
                return $diagramForFileResource;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $diagramForFileResource returns the type string which is incompatible with the documented return type null.
Loading history...
135
            }
136
        }
137
        // no matching diagram found
138
        return null;
139
    }
140
141
    protected function getDefinitionDiagramResourceName(string $resourceName, DefinitionEntity $definition, string $diagramSuffix): string
142
    {
143
        $fileResourceBase = $this->stripDefinitionFileSuffix($resourceName);
144
        $definitionKey = $definition->getKey();
145
        return $fileResourceBase . $definitionKey . "." . $diagramSuffix;
146
    }
147
148
    protected function getGeneralDiagramResourceName(string $resourceName, DefinitionEntity $definition, string $diagramSuffix): string
0 ignored issues
show
Unused Code introduced by
The parameter $definition 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

148
    protected function getGeneralDiagramResourceName(string $resourceName, /** @scrutinizer ignore-unused */ DefinitionEntity $definition, string $diagramSuffix): string

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...
149
    {
150
        $fileResourceBase = $this->stripDefinitionFileSuffix($resourceName);
151
152
        return $fileResourceBase . $diagramSuffix;
153
    }
154
155
    protected function stripDefinitionFileSuffix(string $resourceName): string
156
    {
157
        foreach ($this->getResourcesSuffixes() as $suffix) {
158
            if (str_ends_with($resourceName, $suffix)) {
159
                return substr($resourceName, 0, strlen($resourceName) - strlen($suffix));
160
            }
161
        }
162
        return $resourceName;
163
    }
164
165
    protected function getDiagramSuffixes(): array
166
    {
167
        return self::DIAGRAM_SUFFIXES;
168
    }
169
170
    protected function ensureNoDuplicateDefinitionKeys(array $definitions): void
171
    {
172
        $keys = [];
173
174
        foreach ($definitions as $definition) {
175
            $key = $definition->getKey();
176
177
            if (in_array($key, $keys)) {
178
                throw new ProcessEngineException("The deployment contains definitions with the same key '" . $key . "' (id attribute), this is not allowed");
179
            }
180
181
            $keys[] = $key;
182
        }
183
    }
184
185
    protected function postProcessDefinitions(DeploymentEntity $deployment, array $definitions, Properties $properties): void
186
    {
187
        if ($deployment->isNew()) {
188
            // if the deployment is new persist the new definitions
189
            $this->persistDefinitions($deployment, $definitions, $properties);
190
        } else {
191
            // if the current deployment is not a new one,
192
            // then load the already existing definitions
193
            $this->loadDefinitions($deployment, $definitions, $properties);
194
        }
195
    }
196
197
    protected function persistDefinitions(DeploymentEntity $deployment, array $definitions, Properties $properties): void
198
    {
199
        foreach ($definitions as $definition) {
200
            $definitionKey = $definition->getKey();
201
            $tenantId = $deployment->getTenantId();
202
203
            $latestDefinition = $this->findLatestDefinitionByKeyAndTenantId($definitionKey, $tenantId);
0 ignored issues
show
Bug introduced by
It seems like $tenantId can also be of type null; however, parameter $tenantId of Jabe\Engine\Impl\Abstrac...itionByKeyAndTenantId() 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
            $latestDefinition = $this->findLatestDefinitionByKeyAndTenantId($definitionKey, /** @scrutinizer ignore-type */ $tenantId);
Loading history...
204
205
            $this->updateDefinitionByLatestDefinition($deployment, $definition, $latestDefinition);
206
207
            $this->persistDefinition($definition);
208
            $this->registerDefinition($deployment, $definition, $properties);
209
        }
210
    }
211
212
    protected function updateDefinitionByLatestDefinition(DeploymentEntity $deployment, DefinitionEntity $definition, DefinitionEntity $latestDefinition): void
213
    {
214
        $definition->setVersion($this->getNextVersion($deployment, $definition, $latestDefinition));
215
        $definition->setId($this->generateDefinitionId($deployment, $definition, $latestDefinition));
216
        $definition->setDeploymentId($deployment->getId());
217
        $definition->setTenantId($deployment->getTenantId());
218
    }
219
220
    protected function loadDefinitions(DeploymentEntity $deployment, array $definitions, Properties $properties): void
221
    {
222
        foreach ($definitions as $definition) {
223
            $deploymentId = $deployment->getId();
224
            $definitionKey = $definition->getKey();
225
226
            $persistedDefinition = $this->findDefinitionByDeploymentAndKey($deploymentId, $definitionKey);
0 ignored issues
show
Bug introduced by
It seems like $deploymentId can also be of type null; however, parameter $deploymentId of Jabe\Engine\Impl\Abstrac...ionByDeploymentAndKey() 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

226
            $persistedDefinition = $this->findDefinitionByDeploymentAndKey(/** @scrutinizer ignore-type */ $deploymentId, $definitionKey);
Loading history...
227
            $this->handlePersistedDefinition($definition, $persistedDefinition, $deployment, $properties);
228
        }
229
    }
230
231
    protected function handlePersistedDefinition(
232
        DefinitionEntity $definition,
233
        DefinitionEntity $persistedDefinition,
234
        DeploymentEntity $deployment,
235
        Properties $properties
236
    ): void {
237
        $this->persistedDefinitionLoaded($deployment, $definition, $persistedDefinition);
238
        $this->updateDefinitionByPersistedDefinition($deployment, $definition, $persistedDefinition);
239
        $this->registerDefinition($deployment, $definition, $properties);
240
    }
241
242
    protected function updateDefinitionByPersistedDefinition(DeploymentEntity $deployment, DefinitionEntity $definition, DefinitionEntity $persistedDefinition): void
243
    {
244
        $definition->setVersion($persistedDefinition->getVersion());
245
        $definition->setId($persistedDefinition->getId());
246
        $definition->setDeploymentId($deployment->getId());
247
        $definition->setTenantId($persistedDefinition->getTenantId());
248
    }
249
250
    /**
251
     * Called when a previous version of a definition was loaded from the persistent store.
252
     *
253
     * @param deployment the deployment of the definition
254
     * @param definition the definition entity
255
     * @param persistedDefinition the loaded definition entity
256
     */
257
    protected function persistedDefinitionLoaded(DeploymentEntity $deployment, DefinitionEntity $definition, DefinitionEntity $persistedDefinition): void
0 ignored issues
show
Unused Code introduced by
The parameter $persistedDefinition 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

257
    protected function persistedDefinitionLoaded(DeploymentEntity $deployment, DefinitionEntity $definition, /** @scrutinizer ignore-unused */ DefinitionEntity $persistedDefinition): 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...
Unused Code introduced by
The parameter $definition 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

257
    protected function persistedDefinitionLoaded(DeploymentEntity $deployment, /** @scrutinizer ignore-unused */ DefinitionEntity $definition, DefinitionEntity $persistedDefinition): 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...
Unused Code introduced by
The parameter $deployment 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

257
    protected function persistedDefinitionLoaded(/** @scrutinizer ignore-unused */ DeploymentEntity $deployment, DefinitionEntity $definition, DefinitionEntity $persistedDefinition): 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...
258
    {
259
        // do nothing;
260
    }
261
262
    /**
263
     * Find a definition entity by deployment id and definition key.
264
     * @param deploymentId the deployment id
265
     * @param definitionKey the definition key
266
     * @return the corresponding definition entity or null if non is found
267
     */
268
    abstract protected function findDefinitionByDeploymentAndKey(string $deploymentId, string $definitionKey): DefinitionEntity;
269
270
    /**
271
     * Find the last deployed definition entity by definition key and tenant id.
272
     *
273
     * @return the corresponding definition entity or null if non is found
274
     */
275
    abstract protected function findLatestDefinitionByKeyAndTenantId(string $definitionKey, string $tenantId): DefinitionEntity;
276
277
    /**
278
     * Persist definition entity into the database.
279
     * @param definition the definition entity
280
     */
281
    abstract protected function persistDefinition(DefinitionEntity $definition): void;
282
283
    protected function registerDefinition(DeploymentEntity $deployment, DefinitionEntity $definition, Properties $properties): void
284
    {
285
        $deploymentCache = $this->getDeploymentCache();
286
287
        // Add to cache
288
        $this->addDefinitionToDeploymentCache($deploymentCache, $definition);
289
290
        $this->definitionAddedToDeploymentCache($deployment, $definition, $properties);
291
292
        // Add to deployment for further usage
293
        $deployment->addDeployedArtifact($definition);
294
    }
295
296
    /**
297
     * Add a definition to the deployment cache
298
     *
299
     * @param deploymentCache the deployment cache
300
     * @param definition the definition to add
301
     */
302
    abstract protected function addDefinitionToDeploymentCache(DeploymentCache $deploymentCache, DefinitionEntity $definition): void;
303
304
    /**
305
     * Called after a definition was added to the deployment cache.
306
     *
307
     * @param deployment the deployment of the definition
308
     * @param definition the definition entity
309
     */
310
    protected function definitionAddedToDeploymentCache(DeploymentEntity $deployment, DefinitionEntity $definition, Properties $properties): void
0 ignored issues
show
Unused Code introduced by
The parameter $properties 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

310
    protected function definitionAddedToDeploymentCache(DeploymentEntity $deployment, DefinitionEntity $definition, /** @scrutinizer ignore-unused */ Properties $properties): 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...
Unused Code introduced by
The parameter $deployment 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

310
    protected function definitionAddedToDeploymentCache(/** @scrutinizer ignore-unused */ DeploymentEntity $deployment, DefinitionEntity $definition, Properties $properties): 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...
Unused Code introduced by
The parameter $definition 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

310
    protected function definitionAddedToDeploymentCache(DeploymentEntity $deployment, /** @scrutinizer ignore-unused */ DefinitionEntity $definition, Properties $properties): 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...
311
    {
312
        // do nothing
313
    }
314
315
    /**
316
     * per default we increment the latest definition version by one - but you
317
     * might want to hook in some own logic here, e.g. to align definition
318
     * versions with deployment / build versions.
319
     */
320
    protected function getNextVersion(DeploymentEntity $deployment, DefinitionEntity $newDefinition, DefinitionEntity $latestDefinition): int
0 ignored issues
show
Unused Code introduced by
The parameter $deployment 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

320
    protected function getNextVersion(/** @scrutinizer ignore-unused */ DeploymentEntity $deployment, DefinitionEntity $newDefinition, DefinitionEntity $latestDefinition): int

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...
Unused Code introduced by
The parameter $newDefinition 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

320
    protected function getNextVersion(DeploymentEntity $deployment, /** @scrutinizer ignore-unused */ DefinitionEntity $newDefinition, DefinitionEntity $latestDefinition): int

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...
321
    {
322
        $result = 1;
323
        if ($latestDefinition != null) {
324
            $latestVersion = $latestDefinition->getVersion();
325
            $result = $latestVersion + 1;
326
        }
327
        return $result;
328
    }
329
330
    /**
331
     * create an id for the definition. The default is to ask the {@link IdGenerator}
332
     * and add the definition key and version if that does not exceed 64 characters.
333
     * You might want to hook in your own implementation here.
334
     */
335
    protected function generateDefinitionId(DeploymentEntity $deployment, DefinitionEntity $newDefinition, DefinitionEntity $latestDefinition): string
0 ignored issues
show
Unused Code introduced by
The parameter $deployment 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

335
    protected function generateDefinitionId(/** @scrutinizer ignore-unused */ DeploymentEntity $deployment, DefinitionEntity $newDefinition, DefinitionEntity $latestDefinition): string

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...
Unused Code introduced by
The parameter $latestDefinition 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

335
    protected function generateDefinitionId(DeploymentEntity $deployment, DefinitionEntity $newDefinition, /** @scrutinizer ignore-unused */ DefinitionEntity $latestDefinition): string

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...
336
    {
337
        $nextId = $this->idGenerator->getNextId();
338
339
        $definitionKey = $newDefinition->getKey();
340
        $definitionVersion = $newDefinition->getVersion();
341
342
        $definitionId = $definitionKey
343
            . ":" . $definitionVersion
344
            . ":" . $nextId;
345
346
        // ACT-115: maximum id length is 64 characters
347
        if (strlen($definitionId) > 64) {
348
            $definitionId = $nextId;
349
        }
350
        return $definitionId;
351
    }
352
353
    protected function getProcessEngineConfiguration(): ProcessEngineConfigurationImpl
354
    {
355
        return Context::getProcessEngineConfiguration();
0 ignored issues
show
Bug Best Practice introduced by
The expression return Jabe\Engine\Impl\...ssEngineConfiguration() could return the type null which is incompatible with the type-hinted return Jabe\Engine\Impl\Cfg\Pro...EngineConfigurationImpl. Consider adding an additional type-check to rule them out.
Loading history...
356
    }
357
358
    protected function getCommandContext(): CommandContext
359
    {
360
        return Context::getCommandContext();
0 ignored issues
show
Bug Best Practice introduced by
The expression return Jabe\Engine\Impl\...xt::getCommandContext() could return the type null which is incompatible with the type-hinted return Jabe\Engine\Impl\Interceptor\CommandContext. Consider adding an additional type-check to rule them out.
Loading history...
361
    }
362
363
    protected function getDeploymentCache(): DeploymentCache
364
    {
365
        return $this->getProcessEngineConfiguration()->getDeploymentCache();
0 ignored issues
show
Bug introduced by
The method getDeploymentCache() does not exist on Jabe\Engine\Impl\Cfg\Pro...EngineConfigurationImpl. ( Ignorable by Annotation )

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

365
        return $this->getProcessEngineConfiguration()->/** @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...
366
    }
367
}
368