Completed
Push — master ( e1ce3b...f144d1 )
by Anton
14s queued 12s
created

src/Command/Database/Update.php (1 issue)

Labels
Severity
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
     * Avoid opening transaction when no changes are expected.
55
     *
56
     * @return null|DatabaseInterface
57
     */
58
    public function getDatabase(): ?DatabaseInterface
59
    {
60
        if ($this->isEmpty()) {
61
            return null;
62
        }
63
64
        return parent::getDatabase();
65
    }
66
67
    /**
68
     * @inheritdoc
69
     */
70
    public function isReady(): bool
71
    {
72
        return $this->waitContext === [] && $this->waitScope === [];
73
    }
74
75
    /**
76
     * Update values, context not included.
77
     *
78
     * @return array
79
     */
80
    public function getData(): array
81
    {
82
        return array_merge($this->data, $this->context, $this->appendix);
83
    }
84
85
    /**
86
     * Update data in associated table.
87
     */
88
    public function execute(): void
89
    {
90
        if ($this->scope === []) {
91
            throw new CommandException('Unable to execute update command without a scope');
92
        }
93
94
        if (!$this->isEmpty()) {
95
            $this->db->update($this->table, $this->getData(), $this->scope)->run();
0 ignored issues
show
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

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