1<?php
2/*
3 * Copyright 2015-2017 MongoDB, Inc.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 *   http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18namespace MongoDB\Operation;
19
20use MongoDB\Driver\Exception\RuntimeException as DriverRuntimeException;
21use MongoDB\Driver\Server;
22use MongoDB\Exception\InvalidArgumentException;
23use MongoDB\Exception\UnsupportedException;
24use MongoDB\UpdateResult;
25use function is_array;
26use function is_object;
27use function MongoDB\is_first_key_operator;
28use function MongoDB\is_pipeline;
29
30/**
31 * Operation for updating multiple documents with the update command.
32 *
33 * @api
34 * @see \MongoDB\Collection::updateMany()
35 * @see http://docs.mongodb.org/manual/reference/command/update/
36 */
37class UpdateMany implements Executable, Explainable
38{
39    /** @var Update */
40    private $update;
41
42    /**
43     * Constructs an update command.
44     *
45     * Supported options:
46     *
47     *  * arrayFilters (document array): A set of filters specifying to which
48     *    array elements an update should apply.
49     *
50     *    This is not supported for server versions < 3.6 and will result in an$
51     *    exception at execution time if used.
52     *
53     *  * bypassDocumentValidation (boolean): If true, allows the write to
54     *    circumvent document level validation.
55     *
56     *    For servers < 3.2, this option is ignored as document level validation
57     *    is not available.
58     *
59     *  * collation (document): Collation specification.
60     *
61     *    This is not supported for server versions < 3.4 and will result in an
62     *    exception at execution time if used.
63     *
64     *  * session (MongoDB\Driver\Session): Client session.
65     *
66     *    Sessions are not supported for server versions < 3.6.
67     *
68     *  * upsert (boolean): When true, a new document is created if no document
69     *    matches the query. The default is false.
70     *
71     *  * writeConcern (MongoDB\Driver\WriteConcern): Write concern.
72     *
73     * @param string       $databaseName   Database name
74     * @param string       $collectionName Collection name
75     * @param array|object $filter         Query by which to filter documents
76     * @param array|object $update         Update to apply to the matched documents
77     * @param array        $options        Command options
78     * @throws InvalidArgumentException for parameter/option parsing errors
79     */
80    public function __construct($databaseName, $collectionName, $filter, $update, array $options = [])
81    {
82        if (! is_array($update) && ! is_object($update)) {
83            throw InvalidArgumentException::invalidType('$update', $update, 'array or object');
84        }
85
86        if (! is_first_key_operator($update) && ! is_pipeline($update)) {
87            throw new InvalidArgumentException('Expected an update document with operator as first key or a pipeline');
88        }
89
90        $this->update = new Update(
91            $databaseName,
92            $collectionName,
93            $filter,
94            $update,
95            ['multi' => true] + $options
96        );
97    }
98
99    /**
100     * Execute the operation.
101     *
102     * @see Executable::execute()
103     * @param Server $server
104     * @return UpdateResult
105     * @throws UnsupportedException if collation is used and unsupported
106     * @throws DriverRuntimeException for other driver errors (e.g. connection errors)
107     */
108    public function execute(Server $server)
109    {
110        return $this->update->execute($server);
111    }
112
113    public function getCommandDocument(Server $server)
114    {
115        return $this->update->getCommandDocument($server);
116    }
117}
118