Passed
Push — master ( 1522ca...6450ac )
by Anton
04:25
created

Update::waitContext()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 2
dl 0
loc 4
rs 10
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * Cycle DataMapper ORM
5
 *
6
 * @license   MIT
7
 * @author    Anton Titov (Wolfy-J)
8
 */
9
10
declare(strict_types=1);
11
12
namespace Cycle\ORM\Command\Database;
13
14
use Cycle\ORM\Command\ContextCarrierInterface;
15
use Cycle\ORM\Command\DatabaseCommand;
16
use Cycle\ORM\Command\ScopeCarrierInterface;
17
use Cycle\ORM\Command\Traits\ContextTrait;
18
use Cycle\ORM\Command\Traits\ErrorTrait;
19
use Cycle\ORM\Command\Traits\ScopeTrait;
20
use Cycle\ORM\Exception\CommandException;
21
use Spiral\Database\DatabaseInterface;
22
23
/**
24
 * Update data CAN be modified by parent commands using context.
25
 *
26
 * This is conditional command, it would not be executed when no fields are given!
27
 */
28
final class Update extends DatabaseCommand implements ContextCarrierInterface, ScopeCarrierInterface
29
{
30
    use ContextTrait;
31
    use ScopeTrait;
32
    use ErrorTrait;
33
34
    /** @var array */
35
    protected $data = [];
36
37
    /** @var array */
38
    protected $appendix = [];
39
40
    /**
41
     * @param DatabaseInterface $db
42
     * @param string            $table
43
     * @param array             $data
44
     * @param array             $where
45
     */
46
    public function __construct(DatabaseInterface $db, string $table, array $data = [], array $where = [])
47
    {
48
        parent::__construct($db, $table);
49
        $this->data = $data;
50
        $this->scope = $where;
51
    }
52
53
    /**
54
     * Wait for the context value.
55
     *
56
     * @param string $key
57
     * @param bool   $required
58
     */
59
    public function waitContext(string $key, bool $required = true): void
60
    {
61
        // update command are always "soft" and must wait for all incoming keys
62
        $this->waitContext[$key] = null;
63
    }
64
65
    /**
66
     * Avoid opening transaction when no changes are expected.
67
     *
68
     * @return null|DatabaseInterface
69
     */
70
    public function getDatabase(): ?DatabaseInterface
71
    {
72
        if ($this->isEmpty()) {
73
            return null;
74
        }
75
76
        return parent::getDatabase();
77
    }
78
79
    /**
80
     * @inheritdoc
81
     */
82
    public function isReady(): bool
83
    {
84
        return $this->waitContext === [] && $this->waitScope === [];
85
    }
86
87
    /**
88
     * Update values, context not included.
89
     *
90
     * @return array
91
     */
92
    public function getData(): array
93
    {
94
        return array_merge($this->data, $this->context, $this->appendix);
95
    }
96
97
    /**
98
     * Update data in associated table.
99
     */
100
    public function execute(): void
101
    {
102
        if ($this->scope === []) {
103
            throw new CommandException('Unable to execute update command without a scope');
104
        }
105
106
        if (!$this->isEmpty()) {
107
            $this->db->update($this->table, $this->getData(), $this->scope)->run();
0 ignored issues
show
Bug introduced by
It seems like $this->table can also be of type null; however, parameter $table of Spiral\Database\DatabaseInterface::update() 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

107
            $this->db->update(/** @scrutinizer ignore-type */ $this->table, $this->getData(), $this->scope)->run();
Loading history...
108
        }
109
110
        parent::execute();
111
    }
112
113
    /**
114
     * {@inheritdoc}
115
     */
116
    public function isEmpty(): bool
117
    {
118
        return ($this->data === [] && $this->context === []) || $this->scope === [];
119
    }
120
121
    /**
122
     * @inheritdoc
123
     */
124
    public function register(string $key, $value, bool $fresh = false, int $stream = self::DATA): void
125
    {
126
        if ($stream == self::SCOPE) {
127
            if (empty($value)) {
128
                return;
129
            }
130
131
            $this->freeScope($key);
132
            $this->setScope($key, $value);
133
134
            return;
135
        }
136
137
        if ($fresh || $value !== null) {
138
            $this->freeContext($key);
139
        }
140
141
        if ($fresh) {
142
            // we only accept context when context has changed to avoid un-necessary
143
            // update commands
144
            $this->setContext($key, $value);
145
        }
146
    }
147
148
    /**
149
     * Register optional value to store in database. Having this value would not cause command to be executed
150
     * if data or context is empty.
151
     *
152
     * Example: $update->registerAppendix("updated_at", new DateTime());
153
     *
154
     * @param string $key
155
     * @param mixed  $value
156
     */
157
    public function registerAppendix(string $key, $value): void
158
    {
159
        $this->appendix[$key] = $value;
160
    }
161
}
162