Blueprint.php 7.59 KB
Newer Older
Jens Segers's avatar
Jens Segers committed
1 2 3
<?php

namespace Jenssegers\Mongodb\Schema;
4 5 6

use Illuminate\Database\Connection;

Jens Segers's avatar
Jens Segers committed
7 8
class Blueprint extends \Illuminate\Database\Schema\Blueprint
{
Jens Segers's avatar
Jens Segers committed
9 10
    /**
     * The MongoConnection object for this blueprint.
11
     * @var \Jenssegers\Mongodb\Connection
Jens Segers's avatar
Jens Segers committed
12 13 14 15 16
     */
    protected $connection;

    /**
     * The MongoCollection object for this blueprint.
17
     * @var \Jenssegers\Mongodb\Collection|\MongoDB\Collection
Jens Segers's avatar
Jens Segers committed
18 19 20 21 22 23 24
     */
    protected $collection;

    /**
     * Fluent columns.
     * @var array
     */
25
    protected $columns = [];
Jens Segers's avatar
Jens Segers committed
26 27

    /**
Divine's avatar
Divine committed
28
     * {@inheritdoc}
Jens Segers's avatar
Jens Segers committed
29 30 31 32 33
     */
    public function __construct(Connection $connection, $collection)
    {
        $this->connection = $connection;

34
        $this->collection = $this->connection->getCollection($collection);
Jens Segers's avatar
Jens Segers committed
35 36 37
    }

    /**
Divine's avatar
Divine committed
38
     * {@inheritdoc}
Jens Segers's avatar
Jens Segers committed
39
     */
40
    public function index($columns = null, $name = null, $algorithm = null, $options = [])
Jens Segers's avatar
Jens Segers committed
41 42 43 44
    {
        $columns = $this->fluent($columns);

        // Columns are passed as a default array.
Jens Segers's avatar
Jens Segers committed
45
        if (is_array($columns) && is_int(key($columns))) {
Jens Segers's avatar
Jens Segers committed
46
            // Transform the columns to the required array format.
47
            $transform = [];
Jens Segers's avatar
Jens Segers committed
48

Jens Segers's avatar
Jens Segers committed
49
            foreach ($columns as $column) {
Jens Segers's avatar
Jens Segers committed
50 51 52 53 54 55
                $transform[$column] = 1;
            }

            $columns = $transform;
        }

56 57 58 59
        if ($name !== null) {
            $options['name'] = $name;
        }

Craig Morris's avatar
Craig Morris committed
60
        $this->collection->createIndex($columns, $options);
Jens Segers's avatar
Jens Segers committed
61 62 63 64

        return $this;
    }

65
    /**
Divine's avatar
Divine committed
66
     * {@inheritdoc}
67
     */
68
    public function primary($columns = null, $name = null, $algorithm = null, $options = [])
69
    {
70
        return $this->unique($columns, $name, $algorithm, $options);
71 72
    }

Jens Segers's avatar
Jens Segers committed
73
    /**
Divine's avatar
Divine committed
74
     * {@inheritdoc}
Jens Segers's avatar
Jens Segers committed
75
     */
Mike Nichols's avatar
Mike Nichols committed
76
    public function dropIndex($indexOrColumns = null)
Jens Segers's avatar
Jens Segers committed
77
    {
78
        $indexOrColumns = $this->transformColumns($indexOrColumns);
Jens Segers's avatar
Jens Segers committed
79

80
        $this->collection->dropIndex($indexOrColumns);
Jens Segers's avatar
Jens Segers committed
81

82 83
        return $this;
    }
Jens Segers's avatar
Jens Segers committed
84

85 86 87 88 89 90 91 92 93 94
    /**
     * Indicate that the given index should be dropped, but do not fail if it didn't exist.
     *
     * @param  string|array  $indexOrColumns
     * @return Blueprint
     */
    public function dropIndexIfExists($indexOrColumns = null)
    {
        if ($this->hasIndex($indexOrColumns)) {
            $this->dropIndex($indexOrColumns);
Jens Segers's avatar
Jens Segers committed
95
        }
Divine's avatar
Divine committed
96

Jens Segers's avatar
Jens Segers committed
97 98 99
        return $this;
    }

100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117
    /**
     * Check whether the given index exists.
     *
     * @param  string|array  $indexOrColumns
     * @return bool
     */
    public function hasIndex($indexOrColumns = null)
    {
        $indexOrColumns = $this->transformColumns($indexOrColumns);
        foreach ($this->collection->listIndexes() as $index) {
            if (is_array($indexOrColumns) && in_array($index->getName(), $indexOrColumns)) {
                return true;
            }

            if (is_string($indexOrColumns) && $index->getName() == $indexOrColumns) {
                return true;
            }
        }
Divine's avatar
Divine committed
118

119 120 121 122 123 124 125 126
        return false;
    }

    /**
     * @param  string|array  $indexOrColumns
     * @return string
     */
    protected function transformColumns($indexOrColumns)
Jens Segers's avatar
Jens Segers committed
127
    {
Mike Nichols's avatar
Mike Nichols committed
128 129
        if (is_array($indexOrColumns)) {
            $indexOrColumns = $this->fluent($indexOrColumns);
Jens Segers's avatar
Jens Segers committed
130

Mike Nichols's avatar
Mike Nichols committed
131
            // Transform the columns to the index name.
132
            $transform = [];
Jens Segers's avatar
Jens Segers committed
133

134 135 136 137 138 139 140 141 142 143 144
            foreach ($indexOrColumns as $key => $value) {
                if (is_int($key)) {
                    // There is no sorting order, use the default.
                    $column = $value;
                    $sorting = '1';
                } else {
                    // This is a column with sorting order e.g 'my_column' => -1.
                    $column = $key;
                    $sorting = $value;
                }

Divine's avatar
Divine committed
145
                $transform[$column] = $column.'_'.$sorting;
Jens Segers's avatar
Jens Segers committed
146 147
            }

148
            $indexOrColumns = implode('_', $transform);
Jens Segers's avatar
Jens Segers committed
149
        }
Divine's avatar
Divine committed
150

151
        return $indexOrColumns;
Jens Segers's avatar
Jens Segers committed
152 153 154
    }

    /**
Divine's avatar
Divine committed
155
     * {@inheritdoc}
Jens Segers's avatar
Jens Segers committed
156
     */
157
    public function unique($columns = null, $name = null, $algorithm = null, $options = [])
Jens Segers's avatar
Jens Segers committed
158 159 160
    {
        $columns = $this->fluent($columns);

161 162
        $options['unique'] = true;

163
        $this->index($columns, $name, $algorithm, $options);
Jens Segers's avatar
Jens Segers committed
164 165 166 167 168 169

        return $this;
    }

    /**
     * Specify a non blocking index for the collection.
Jens Segers's avatar
Jens Segers committed
170
     * @param string|array $columns
Jens Segers's avatar
Jens Segers committed
171 172 173 174 175 176
     * @return Blueprint
     */
    public function background($columns = null)
    {
        $columns = $this->fluent($columns);

177
        $this->index($columns, null, null, ['background' => true]);
Jens Segers's avatar
Jens Segers committed
178 179 180 181 182 183

        return $this;
    }

    /**
     * Specify a sparse index for the collection.
Jens Segers's avatar
Jens Segers committed
184 185
     * @param string|array $columns
     * @param array $options
Jens Segers's avatar
Jens Segers committed
186 187
     * @return Blueprint
     */
188
    public function sparse($columns = null, $options = [])
Jens Segers's avatar
Jens Segers committed
189 190
    {
        $columns = $this->fluent($columns);
191 192 193

        $options['sparse'] = true;

194
        $this->index($columns, null, null, $options);
Jens Segers's avatar
Jens Segers committed
195 196 197 198

        return $this;
    }

199 200
    /**
     * Specify a geospatial index for the collection.
Jens Segers's avatar
Jens Segers committed
201 202 203
     * @param string|array $columns
     * @param string $index
     * @param array $options
204 205 206 207
     * @return Blueprint
     */
    public function geospatial($columns = null, $index = '2d', $options = [])
    {
Dmitry Borzyonok's avatar
Dmitry Borzyonok committed
208
        if ($index == '2d' || $index == '2dsphere') {
209 210 211 212 213 214 215 216 217 218 219 220 221 222
            $columns = $this->fluent($columns);

            $columns = array_flip($columns);

            foreach ($columns as $column => $value) {
                $columns[$column] = $index;
            }

            $this->index($columns, null, null, $options);
        }

        return $this;
    }

Jens Segers's avatar
Jens Segers committed
223 224 225
    /**
     * Specify the number of seconds after wich a document should be considered expired based,
     * on the given single-field index containing a date.
Jens Segers's avatar
Jens Segers committed
226 227
     * @param string|array $columns
     * @param int $seconds
Jens Segers's avatar
Jens Segers committed
228 229 230 231 232 233
     * @return Blueprint
     */
    public function expire($columns, $seconds)
    {
        $columns = $this->fluent($columns);

234
        $this->index($columns, null, null, ['expireAfterSeconds' => $seconds]);
Jens Segers's avatar
Jens Segers committed
235 236 237 238 239

        return $this;
    }

    /**
Ditty's avatar
Ditty committed
240 241 242
     * Indicate that the collection needs to be created.
     * @param array $options
     * @return void
Jens Segers's avatar
Jens Segers committed
243
     */
244
    public function create($options = [])
Jens Segers's avatar
Jens Segers committed
245
    {
Craig Morris's avatar
Craig Morris committed
246
        $collection = $this->collection->getCollectionName();
Jens Segers's avatar
Jens Segers committed
247 248 249 250

        $db = $this->connection->getMongoDB();

        // Ensure the collection is created.
251
        $db->createCollection($collection, $options);
Jens Segers's avatar
Jens Segers committed
252 253 254
    }

    /**
Divine's avatar
Divine committed
255
     * {@inheritdoc}
Jens Segers's avatar
Jens Segers committed
256 257 258 259 260 261 262
     */
    public function drop()
    {
        $this->collection->drop();
    }

    /**
Divine's avatar
Divine committed
263
     * {@inheritdoc}
Jens Segers's avatar
Jens Segers committed
264
     */
265
    public function addColumn($type, $name, array $parameters = [])
Jens Segers's avatar
Jens Segers committed
266 267 268 269 270 271
    {
        $this->fluent($name);

        return $this;
    }

272 273
    /**
     * Specify a sparse and unique index for the collection.
Jens Segers's avatar
Jens Segers committed
274 275
     * @param string|array $columns
     * @param array $options
276 277 278 279 280 281 282 283 284
     * @return Blueprint
     */
    public function sparse_and_unique($columns = null, $options = [])
    {
        $columns = $this->fluent($columns);

        $options['sparse'] = true;
        $options['unique'] = true;

Pooya Parsa's avatar
Pooya Parsa committed
285
        $this->index($columns, null, null, $options);
286 287 288 289

        return $this;
    }

Jens Segers's avatar
Jens Segers committed
290 291
    /**
     * Allow fluent columns.
Jens Segers's avatar
Jens Segers committed
292
     * @param string|array $columns
Jens Segers's avatar
Jens Segers committed
293 294 295 296
     * @return string|array
     */
    protected function fluent($columns = null)
    {
Simon Schaufelberger's avatar
Simon Schaufelberger committed
297
        if ($columns === null) {
Jens Segers's avatar
Jens Segers committed
298
            return $this->columns;
Jens Segers's avatar
Jens Segers committed
299
        } elseif (is_string($columns)) {
300
            return $this->columns = [$columns];
Jens Segers's avatar
Jens Segers committed
301
        } else {
Jens Segers's avatar
Jens Segers committed
302 303 304 305 306 307
            return $this->columns = $columns;
        }
    }

    /**
     * Allows the use of unsupported schema methods.
308 309
     * @param $method
     * @param $args
Jens Segers's avatar
Jens Segers committed
310 311 312 313 314 315 316
     * @return Blueprint
     */
    public function __call($method, $args)
    {
        // Dummy.
        return $this;
    }
317
}