Passed
Push — 2.x ( 5e81a5...d097d1 )
by Aleksei
14:17
created

CommandGenerator::deleteEntity()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
nc 1
nop 2
dl 0
loc 3
ccs 2
cts 2
cp 1
crap 1
rs 10
c 1
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Cycle\ORM\Transaction;
6
7
use Cycle\ORM\Command\CommandInterface;
8
use Cycle\ORM\Command\Special\Sequence;
9
use Cycle\ORM\Command\Special\WrappedStoreCommand;
10
use Cycle\ORM\Command\StoreCommandInterface;
11
use Cycle\ORM\Heap\Node;
12
use Cycle\ORM\ORMInterface;
13
use Cycle\ORM\SchemaInterface;
14
15
/**
16
 * @internal
17
 */
18
class CommandGenerator implements CommandGeneratorInterface
19
{
20 2396
    public function generateStoreCommand(ORMInterface $orm, Tuple $tuple): ?CommandInterface
21
    {
22 2396
        $isNew = $tuple->node->getStatus() === Node::NEW;
23 2396
        $tuple->state->setStatus($isNew ? Node::SCHEDULED_INSERT : Node::SCHEDULED_UPDATE);
24 2396
        $schema = $orm->getSchema();
25
26 2396
        $commands = $this->storeParents($orm, $tuple, $isNew);
27 2396
        $entityCommand = $this->storeEntity($orm, $tuple, $isNew);
28 2396
        if ($entityCommand !== null) {
29 2396
            $commands[$tuple->node->getRole()] = $entityCommand;
30
        }
31
32 2396
        return match (\count($commands)) {
33
            0 => null,
34 1126
            1 => \current($commands),
35 2396
            default => $this->buildStoreSequence($schema, $commands, $tuple)
36
        };
37
    }
38
39 496
    public function generateDeleteCommand(ORMInterface $orm, Tuple $tuple): ?CommandInterface
40
    {
41
        // currently we rely on db to delete all nested records (or soft deletes)
42 496
        return $this->deleteEntity($orm, $tuple);
43
    }
44
45
    /**
46
     * @return array<string, CommandInterface>
47
     */
48 2396
    protected function storeParents(ORMInterface $orm, Tuple $tuple, bool $isNew): array
49
    {
50 2396
        $schema = $orm->getSchema();
51 2396
        $parents = $commands = [];
52 2396
        $parent = $schema->define($tuple->node->getRole(), SchemaInterface::PARENT);
53 2396
        while (is_string($parent)) {
54 152
            \array_unshift($parents, $parent);
55 152
            $parent = $schema->define($parent, SchemaInterface::PARENT);
56
        }
57 2396
        foreach ($parents as $parent) {
58 152
            $command = $this->generateParentStoreCommand($orm, $tuple, $parent, $isNew);
59 152
            if ($command !== null) {
60 152
                $commands[$parent] = $command;
61
            }
62
        }
63
64 2396
        return $commands;
65
    }
66
67 2396
    protected function storeEntity(ORMInterface $orm, Tuple $tuple, bool $isNew): ?CommandInterface
0 ignored issues
show
Unused Code introduced by
The parameter $orm 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

67
    protected function storeEntity(/** @scrutinizer ignore-unused */ ORMInterface $orm, Tuple $tuple, bool $isNew): ?CommandInterface

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...
68
    {
69 2396
        return $isNew
70 1700
            ? $tuple->mapper->queueCreate($tuple->entity, $tuple->node, $tuple->state)
71 2396
            : $tuple->mapper->queueUpdate($tuple->entity, $tuple->node, $tuple->state);
72
    }
73
74 496
    protected function deleteEntity(ORMInterface $orm, Tuple $tuple): ?CommandInterface
0 ignored issues
show
Unused Code introduced by
The parameter $orm 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

74
    protected function deleteEntity(/** @scrutinizer ignore-unused */ ORMInterface $orm, Tuple $tuple): ?CommandInterface

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...
75
    {
76 496
        return $tuple->mapper->queueDelete($tuple->entity, $tuple->node, $tuple->state);
77
    }
78
79
    /**
80
     * @param non-empty-string $parentRole
0 ignored issues
show
Documentation Bug introduced by
The doc comment non-empty-string at position 0 could not be parsed: Unknown type name 'non-empty-string' at position 0 in non-empty-string.
Loading history...
81
     */
82 152
    protected function generateParentStoreCommand(
83
        ORMInterface $orm,
84
        Tuple $tuple,
85
        string $parentRole,
86
        bool $isNew
87
    ): ?CommandInterface {
88 152
        $parentMapper = $orm->getMapper($parentRole);
89 152
        return $isNew
90 56
            ? $parentMapper->queueCreate($tuple->entity, $tuple->node, $tuple->state)
91 152
            : $parentMapper->queueUpdate($tuple->entity, $tuple->node, $tuple->state);
92
    }
93
94
    /**
95
     * @param array<string, StoreCommandInterface> $commands
96
     */
97 152
    private function buildStoreSequence(SchemaInterface $schema, array $commands, Tuple $tuple): CommandInterface
98
    {
99 152
        $parent = null;
100 152
        $result = [];
101 152
        foreach ($commands as $role => $command) {
102
            // Current parent has no parent
103 152
            if ($parent === null) {
104 152
                $result[] = $command;
105 152
                $parent = $role;
106 152
                continue;
107
            }
108
109 152
            $command = WrappedStoreCommand::wrapStoreCommand($command);
110
111
            // Transact PK from previous parent to current
112 152
            $parentKey = (array)($schema->define($role, SchemaInterface::PARENT_KEY)
113 152
                ?? $schema->define($parent, SchemaInterface::PRIMARY_KEY));
0 ignored issues
show
Bug introduced by
$parent of type null is incompatible with the type string expected by parameter $role of Cycle\ORM\SchemaInterface::define(). ( Ignorable by Annotation )

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

113
                ?? $schema->define(/** @scrutinizer ignore-type */ $parent, SchemaInterface::PRIMARY_KEY));
Loading history...
114 152
            $primaryKey = (array)$schema->define($role, SchemaInterface::PRIMARY_KEY);
115 152
            $result[] = $command->withBeforeExecution(
116 152
                static function (StoreCommandInterface $command) use ($tuple, $parentKey, $primaryKey): void {
117 152
                    foreach ($primaryKey as $i => $pk) {
118 152
                        $command->registerAppendix($pk, $tuple->state->getValue($parentKey[$i]));
119
                    }
120
                }
121
            );
122 152
            $parent = $role;
123
        }
124
125 152
        return (new Sequence())->addCommand(...$result);
126
    }
127
}
128