Completed
Push — master ( fd2b1b...7db631 )
by Thomas
11s
created

BulkInsert::execute()   A

Complexity

Conditions 5
Paths 9

Size

Total Lines 15
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 10
dl 0
loc 15
rs 9.6111
c 0
b 0
f 0
cc 5
nc 9
nop 0
1
<?php
2
3
namespace ORM;
4
5
use ORM\Dbal\Dbal;
6
use ORM\Exception\InvalidArgument;
7
8
class BulkInsert
9
{
10
    /** @var string */
11
    protected $class;
12
13
    /** @var Dbal */
14
    protected $dbal;
15
16
    /** @var int */
17
    protected $limit;
18
19
    /** @var callable */
20
    protected $onSync;
21
22
    /** @var bool */
23
    protected $useAutoIncrement = true;
24
25
    /** @var bool */
26
    protected $update = true;
27
28
    /** @var Entity[] */
29
    protected $new = [];
30
31
    /** @var Entity[] */
32
    protected $synced = [];
33
34
    /**
35
     * BulkInsert constructor.
36
     *
37
     * @param string $class
38
     * @param Dbal $dbal
39
     * @param int $limit
40
     */
41
    public function __construct(Dbal $dbal, $class, $limit = 20)
42
    {
43
        $this->class = $class;
44
        $this->dbal = $dbal;
45
        $this->limit = $limit;
46
        if (!$class::isAutoIncremented()) {
47
            $this->useAutoIncrement = false;
48
        }
49
    }
50
51
    /**
52
     * Add an entity to the bulk insert.
53
     *
54
     * @param Entity ...$entities
55
     * @throws InvalidArgument
56
     */
57
    public function add(Entity ...$entities)
58
    {
59
        foreach ($entities as $entity) {
60
            if (!$entity instanceof $this->class) {
61
                throw new InvalidArgument('Only entities from type ' . $this->class . ' can be added');
62
            }
63
        }
64
65
        array_push($this->new, ...$entities);
66
        while (count($this->new) >= $this->limit) {
67
            $this->execute();
68
        }
69
    }
70
71
    /**
72
     * Insert the outstanding entities and return all synced objects.
73
     *
74
     * @return Entity[]
75
     */
76
    public function finish()
77
    {
78
        if (!empty($this->new)) {
79
            $this->execute();
80
        }
81
        return $this->synced;
82
    }
83
84
    /**
85
     * Executes the bulk insert.
86
     */
87
    protected function execute()
88
    {
89
        $new = array_splice($this->new, 0, $this->limit);
90
91
        if (!$this->update) {
92
            $success = $this->dbal->insert(...$new);
93
        } elseif ($this->useAutoIncrement) {
94
            $success = $this->dbal->insertAndSyncWithAutoInc(...$new);
95
        } else {
96
            $success = $this->dbal->insertAndSync(...$new);
97
        }
98
99
        if ($success) {
100
            array_push($this->synced, ...$new);
101
            !$this->onSync || call_user_func($this->onSync, $new);
102
        }
103
    }
104
105
    /** @return int
106
     * @codeCoverageIgnore trivial */
107
    public function getLimit()
108
    {
109
        return $this->limit;
110
    }
111
112
    /**
113
     * Limit the amount of entities inserted at once.
114
     *
115
     * @param int $limit
116
     * @return $this
117
     * @codeCoverageIgnore trivial
118
     */
119
    public function limit($limit)
120
    {
121
        $this->limit = $limit;
122
        return $this;
123
    }
124
125
    /**
126
     * Enable updating the primary keys from autoincrement
127
     *
128
     * **Caution**: Your db access layer (DBAL) may not support this feature.
129
     *
130
     * @return $this
131
     * @codeCoverageIgnore trivial
132
     */
133
    public function useAutoincrement()
134
    {
135
        $this->useAutoIncrement = true;
136
        return $this;
137
    }
138
139
    /**
140
     * Disable updating the primary key by auto increment.
141
     *
142
     * **Caution**: If this is disabled updating could cause a IncompletePrimaryKey exception.
143
     *
144
     * @return $this
145
     * @codeCoverageIgnore trivial
146
     */
147
    public function noAutoIncrement()
148
    {
149
        $this->useAutoIncrement = false;
150
        return $this;
151
    }
152
153
    /**
154
     * Executes $callback after insert
155
     *
156
     * Provides an array of the just inserted entities in first argument.
157
     *
158
     * @param callable $callback
159
     * @return $this
160
     * @codeCoverageIgnore trivial
161
     */
162
    public function onSync(callable $callback = null)
163
    {
164
        $this->onSync = $callback;
165
        return $this;
166
    }
167
168
    /**
169
     * Disable updating entities after insert
170
     *
171
     * @return $this
172
     * @codeCoverageIgnore trivial
173
     */
174
    public function noUpdates()
175
    {
176
        $this->update = false;
177
        return $this;
178
    }
179
180
    /**
181
     * Enable updating entities after insert
182
     *
183
     * **Caution**: This option will need to update the primary key by autoincrement which maybe is not supported
184
     * by your db access layer (DBAL).
185
     *
186
     * @return $this
187
     * @codeCoverageIgnore trivial
188
     */
189
    public function updateEntities()
190
    {
191
        $this->update = true;
192
        return $this;
193
    }
194
}
195