Completed
Pull Request — master (#25)
by
unknown
03:13
created

MongoWriteBatch::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %
Metric Value
dl 0
loc 6
rs 9.4286
cc 1
eloc 4
nc 1
nop 3
1
<?php
2
/*
3
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
4
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
5
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
6
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
7
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
8
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
9
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
10
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
11
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
12
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
13
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
14
 */
15
16
use Alcaeus\MongoDbAdapter\TypeConverter;
17
use Alcaeus\MongoDbAdapter\Helper\WriteConcernRaw;
18
19
/**
20
 * MongoWriteBatch allows you to "batch up" multiple operations (of same type)
21
 * and shipping them all to MongoDB at the same time. This can be especially
22
 * useful when operating on many documents at the same time to reduce roundtrips.
23
 *
24
 * @see http://php.net/manual/en/class.mongowritebatch.php
25
 */
26
class MongoWriteBatch
1 ignored issue
show
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
27
{
28
    use WriteConcernRaw;
29
30
    const COMMAND_INSERT = 1;
31
    const COMMAND_UPDATE = 2;
32
    const COMMAND_DELETE = 3;
33
34
    /**
35
     * @var MongoCollection
36
     */
37
    private $collection;
38
39
    /**
40
     * @var int
41
     */
42
    private $batchType;
43
44
    /**
45
     * @var arrray
46
     */
47
    private $writeOptions;
48
49
    /**
50
     * @var arrray
51
     */
52
    private $items = [];
53
54
    /**
55
     * Creates a new batch of write operations
56
     *
57
     * @see http://php.net/manual/en/mongowritebatch.construct.php
58
     * @param MongoCollection $collection
59
     * @param int $batchType
60
     * @param array $writeOptions
61
     */
62
    protected function __construct(MongoCollection $collection, $batchType, $writeOptions)
63
    {
64
        $this->collection = $collection;
65
        $this->batchType = $batchType;
66
        $this->writeOptions = $writeOptions;
0 ignored issues
show
Documentation Bug introduced by
It seems like $writeOptions of type array is incompatible with the declared type object<arrray> of property $writeOptions.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
67
    }
68
69
    /**
70
     * Adds a write operation to a batch
71
     *
72
     * @see http://php.net/manual/en/mongowritebatch.add.php
73
     * @param array|object $item
74
     * @return boolean
75
     */
76
    public function add($item)
77
    {
78
        if (is_object($item)) {
79
            $item = (array)$item;
80
        }
81
82
        $this->validate($item);
83
        $this->addItem($item);
84
85
        return true;
86
    }
87
88
    /**
89
     * Executes a batch of write operations
90
     *
91
     * @see http://php.net/manual/en/mongowritebatch.execute.php
92
     * @param array $writeOptions
93
     * @return array
94
     */
95
    final public function execute(array $writeOptions = [])
96
    {
97
        $writeOptions += $this->writeOptions;
98
        if (! count($this->items)) {
99
            return ['ok' => true];
100
        }
101
102
        if (isset($writeOptions['j'])) {
103
            trigger_error('j parameter is not supported', E_WARNING);
104
        }
105
        if (isset($writeOptions['fsync'])) {
106
            trigger_error('fsync parameter is not supported', E_WARNING);
107
        }
108
109
        $options['writeConcern'] = $this->createWriteConcernFromArray($writeOptions);
0 ignored issues
show
Coding Style Comprehensibility introduced by
$options was never initialized. Although not strictly required by PHP, it is generally a good practice to add $options = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
110
        if (isset($writeOptions['ordered'])) {
111
            $options['ordered'] = $writeOptions['ordered'];
112
        }
113
114
        $collection = $this->collection->getCollection();
115
        try {
116
            $result = $collection->BulkWrite($this->items, $options);
117
        } catch (\MongoDB\Driver\Exception\BulkWriteException $e) {
1 ignored issue
show
Bug introduced by
The class MongoDB\Driver\Exception\BulkWriteException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
118
            $result = $e->getWriteResult();
119
            return [
120
                'ok' => 0.0,
121
                'nInserted' => $result->getInsertedCount(),
122
                'nMatched' => $result->getMatchedCount(),
123
                'nModified' => $result->getModifiedCount(),
124
                'nUpserted' => $result->getUpsertedCount(),
125
                'nRemoved' => $result->getDeletedCount(),
126
            ];
127
        }
128
129
        $this->items = [];
0 ignored issues
show
Documentation Bug introduced by
It seems like array() of type array is incompatible with the declared type object<arrray> of property $items.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
130
131
        return [
132
            'ok' => 1.0,
133
            'nInserted' => $result->getInsertedCount(),
134
            'nMatched' => $result->getMatchedCount(),
135
            'nModified' => $result->getModifiedCount(),
136
            'nUpserted' => $result->getUpsertedCount(),
137
            'nRemoved' => $result->getDeletedCount(),
138
        ];
139
    }
140
141
    private function validate(array $item)
142
    {
143
        switch ($this->batchType) {
144
            case self::COMMAND_UPDATE:
145
                if (! isset($item['q']) || ! isset($item['u'])) {
146
                    throw new Exception('invalid item');
147
                }
148
                break;
149
150
            case self::COMMAND_DELETE:
151
                if (! isset($item['q']) || ! isset($item['limit'])) {
152
                    throw new Exception('invalid item');
153
                }
154
                break;
155
        }
156
    }
157
158
    private function addItem(array $item)
159
    {
160
        switch ($this->batchType) {
161
            case self::COMMAND_UPDATE:
162
                $method = isset($item['multi']) ? 'updateMany' : 'updateOne';
163
164
                $options = [];
165
                if (isset($item['upsert']) && $item['upsert']) {
166
                    $options['upsert'] = true;
167
                }
168
169
                $this->items[] = [$method => [TypeConverter::fromLegacy($item['q']), TypeConverter::fromLegacy($item['u']), $options]];
170
                break;
171
172
            case self::COMMAND_INSERT:
173
                $this->items[] = ['insertOne' => [TypeConverter::fromLegacy($item)]];
174
                break;
175
176
            case self::COMMAND_DELETE:
177
                $method = $item['limit'] === 0 ? 'deleteMany' : 'deleteOne';
178
179
                $this->items[] = [$method => [TypeConverter::fromLegacy($item['q'])]];
180
                break;
181
        }
182
    }
183
}
184