1<?php
2
3namespace Illuminate\Database\Schema;
4
5use Closure;
6use BadMethodCallException;
7use Illuminate\Support\Fluent;
8use Illuminate\Database\Connection;
9use Illuminate\Support\Traits\Macroable;
10use Illuminate\Database\SQLiteConnection;
11use Illuminate\Database\Schema\Grammars\Grammar;
12
13class Blueprint
14{
15    use Macroable;
16
17    /**
18     * The table the blueprint describes.
19     *
20     * @var string
21     */
22    protected $table;
23
24    /**
25     * The prefix of the table.
26     *
27     * @var string
28     */
29    protected $prefix;
30
31    /**
32     * The columns that should be added to the table.
33     *
34     * @var \Illuminate\Database\Schema\ColumnDefinition[]
35     */
36    protected $columns = [];
37
38    /**
39     * The commands that should be run for the table.
40     *
41     * @var \Illuminate\Support\Fluent[]
42     */
43    protected $commands = [];
44
45    /**
46     * The storage engine that should be used for the table.
47     *
48     * @var string
49     */
50    public $engine;
51
52    /**
53     * The default character set that should be used for the table.
54     */
55    public $charset;
56
57    /**
58     * The collation that should be used for the table.
59     */
60    public $collation;
61
62    /**
63     * Whether to make the table temporary.
64     *
65     * @var bool
66     */
67    public $temporary = false;
68
69    /**
70     * Create a new schema blueprint.
71     *
72     * @param  string  $table
73     * @param  \Closure|null  $callback
74     * @param  string  $prefix
75     * @return void
76     */
77    public function __construct($table, Closure $callback = null, $prefix = '')
78    {
79        $this->table = $table;
80        $this->prefix = $prefix;
81
82        if (! is_null($callback)) {
83            $callback($this);
84        }
85    }
86
87    /**
88     * Execute the blueprint against the database.
89     *
90     * @param  \Illuminate\Database\Connection  $connection
91     * @param  \Illuminate\Database\Schema\Grammars\Grammar  $grammar
92     * @return void
93     */
94    public function build(Connection $connection, Grammar $grammar)
95    {
96        foreach ($this->toSql($connection, $grammar) as $statement) {
97            $connection->statement($statement);
98        }
99    }
100
101    /**
102     * Get the raw SQL statements for the blueprint.
103     *
104     * @param  \Illuminate\Database\Connection  $connection
105     * @param  \Illuminate\Database\Schema\Grammars\Grammar  $grammar
106     * @return array
107     */
108    public function toSql(Connection $connection, Grammar $grammar)
109    {
110        $this->addImpliedCommands($grammar);
111
112        $statements = [];
113
114        // Each type of command has a corresponding compiler function on the schema
115        // grammar which is used to build the necessary SQL statements to build
116        // the blueprint element, so we'll just call that compilers function.
117        $this->ensureCommandsAreValid($connection);
118
119        foreach ($this->commands as $command) {
120            $method = 'compile'.ucfirst($command->name);
121
122            if (method_exists($grammar, $method)) {
123                if (! is_null($sql = $grammar->$method($this, $command, $connection))) {
124                    $statements = array_merge($statements, (array) $sql);
125                }
126            }
127        }
128
129        return $statements;
130    }
131
132    /**
133     * Ensure the commands on the blueprint are valid for the connection type.
134     *
135     * @param  \Illuminate\Database\Connection  $connection
136     * @return void
137     *
138     * @throws \BadMethodCallException
139     */
140    protected function ensureCommandsAreValid(Connection $connection)
141    {
142        if ($connection instanceof SQLiteConnection) {
143            if ($this->commandsNamed(['dropColumn', 'renameColumn'])->count() > 1) {
144                throw new BadMethodCallException(
145                    "SQLite doesn't support multiple calls to dropColumn / renameColumn in a single modification."
146                );
147            }
148
149            if ($this->commandsNamed(['dropForeign'])->count() > 0) {
150                throw new BadMethodCallException(
151                    "SQLite doesn't support dropping foreign keys (you would need to re-create the table)."
152                );
153            }
154        }
155    }
156
157    /**
158     * Get all of the commands matching the given names.
159     *
160     * @param  array  $names
161     * @return \Illuminate\Support\Collection
162     */
163    protected function commandsNamed(array $names)
164    {
165        return collect($this->commands)->filter(function ($command) use ($names) {
166            return in_array($command->name, $names);
167        });
168    }
169
170    /**
171     * Add the commands that are implied by the blueprint's state.
172     *
173     * @param  \Illuminate\Database\Schema\Grammars\Grammar  $grammar
174     * @return void
175     */
176    protected function addImpliedCommands(Grammar $grammar)
177    {
178        if (count($this->getAddedColumns()) > 0 && ! $this->creating()) {
179            array_unshift($this->commands, $this->createCommand('add'));
180        }
181
182        if (count($this->getChangedColumns()) > 0 && ! $this->creating()) {
183            array_unshift($this->commands, $this->createCommand('change'));
184        }
185
186        $this->addFluentIndexes();
187
188        $this->addFluentCommands($grammar);
189    }
190
191    /**
192     * Add the index commands fluently specified on columns.
193     *
194     * @return void
195     */
196    protected function addFluentIndexes()
197    {
198        foreach ($this->columns as $column) {
199            foreach (['primary', 'unique', 'index', 'spatialIndex'] as $index) {
200                // If the index has been specified on the given column, but is simply equal
201                // to "true" (boolean), no name has been specified for this index so the
202                // index method can be called without a name and it will generate one.
203                if ($column->{$index} === true) {
204                    $this->{$index}($column->name);
205
206                    continue 2;
207                }
208
209                // If the index has been specified on the given column, and it has a string
210                // value, we'll go ahead and call the index method and pass the name for
211                // the index since the developer specified the explicit name for this.
212                elseif (isset($column->{$index})) {
213                    $this->{$index}($column->name, $column->{$index});
214
215                    continue 2;
216                }
217            }
218        }
219    }
220
221    /**
222     * Add the fluent commands specified on any columns.
223     *
224     * @param  \Illuminate\Database\Schema\Grammars\Grammar  $grammar
225     * @return void
226     */
227    public function addFluentCommands(Grammar $grammar)
228    {
229        foreach ($this->columns as $column) {
230            foreach ($grammar->getFluentCommands() as $commandName) {
231                $attributeName = lcfirst($commandName);
232
233                if (! isset($column->{$attributeName})) {
234                    continue;
235                }
236
237                $value = $column->{$attributeName};
238
239                $this->addCommand(
240                    $commandName, compact('value', 'column')
241                );
242            }
243        }
244    }
245
246    /**
247     * Determine if the blueprint has a create command.
248     *
249     * @return bool
250     */
251    protected function creating()
252    {
253        return collect($this->commands)->contains(function ($command) {
254            return $command->name === 'create';
255        });
256    }
257
258    /**
259     * Indicate that the table needs to be created.
260     *
261     * @return \Illuminate\Support\Fluent
262     */
263    public function create()
264    {
265        return $this->addCommand('create');
266    }
267
268    /**
269     * Indicate that the table needs to be temporary.
270     *
271     * @return void
272     */
273    public function temporary()
274    {
275        $this->temporary = true;
276    }
277
278    /**
279     * Indicate that the table should be dropped.
280     *
281     * @return \Illuminate\Support\Fluent
282     */
283    public function drop()
284    {
285        return $this->addCommand('drop');
286    }
287
288    /**
289     * Indicate that the table should be dropped if it exists.
290     *
291     * @return \Illuminate\Support\Fluent
292     */
293    public function dropIfExists()
294    {
295        return $this->addCommand('dropIfExists');
296    }
297
298    /**
299     * Indicate that the given columns should be dropped.
300     *
301     * @param  array|mixed  $columns
302     * @return \Illuminate\Support\Fluent
303     */
304    public function dropColumn($columns)
305    {
306        $columns = is_array($columns) ? $columns : func_get_args();
307
308        return $this->addCommand('dropColumn', compact('columns'));
309    }
310
311    /**
312     * Indicate that the given columns should be renamed.
313     *
314     * @param  string  $from
315     * @param  string  $to
316     * @return \Illuminate\Support\Fluent
317     */
318    public function renameColumn($from, $to)
319    {
320        return $this->addCommand('renameColumn', compact('from', 'to'));
321    }
322
323    /**
324     * Indicate that the given primary key should be dropped.
325     *
326     * @param  string|array|null  $index
327     * @return \Illuminate\Support\Fluent
328     */
329    public function dropPrimary($index = null)
330    {
331        return $this->dropIndexCommand('dropPrimary', 'primary', $index);
332    }
333
334    /**
335     * Indicate that the given unique key should be dropped.
336     *
337     * @param  string|array  $index
338     * @return \Illuminate\Support\Fluent
339     */
340    public function dropUnique($index)
341    {
342        return $this->dropIndexCommand('dropUnique', 'unique', $index);
343    }
344
345    /**
346     * Indicate that the given index should be dropped.
347     *
348     * @param  string|array  $index
349     * @return \Illuminate\Support\Fluent
350     */
351    public function dropIndex($index)
352    {
353        return $this->dropIndexCommand('dropIndex', 'index', $index);
354    }
355
356    /**
357     * Indicate that the given spatial index should be dropped.
358     *
359     * @param  string|array  $index
360     * @return \Illuminate\Support\Fluent
361     */
362    public function dropSpatialIndex($index)
363    {
364        return $this->dropIndexCommand('dropSpatialIndex', 'spatialIndex', $index);
365    }
366
367    /**
368     * Indicate that the given foreign key should be dropped.
369     *
370     * @param  string|array  $index
371     * @return \Illuminate\Support\Fluent
372     */
373    public function dropForeign($index)
374    {
375        return $this->dropIndexCommand('dropForeign', 'foreign', $index);
376    }
377
378    /**
379     * Indicate that the given indexes should be renamed.
380     *
381     * @param  string  $from
382     * @param  string  $to
383     * @return \Illuminate\Support\Fluent
384     */
385    public function renameIndex($from, $to)
386    {
387        return $this->addCommand('renameIndex', compact('from', 'to'));
388    }
389
390    /**
391     * Indicate that the timestamp columns should be dropped.
392     *
393     * @return void
394     */
395    public function dropTimestamps()
396    {
397        $this->dropColumn('created_at', 'updated_at');
398    }
399
400    /**
401     * Indicate that the timestamp columns should be dropped.
402     *
403     * @return void
404     */
405    public function dropTimestampsTz()
406    {
407        $this->dropTimestamps();
408    }
409
410    /**
411     * Indicate that the soft delete column should be dropped.
412     *
413     * @param  string  $column
414     * @return void
415     */
416    public function dropSoftDeletes($column = 'deleted_at')
417    {
418        $this->dropColumn($column);
419    }
420
421    /**
422     * Indicate that the soft delete column should be dropped.
423     *
424     * @param  string  $column
425     * @return void
426     */
427    public function dropSoftDeletesTz($column = 'deleted_at')
428    {
429        $this->dropSoftDeletes($column);
430    }
431
432    /**
433     * Indicate that the remember token column should be dropped.
434     *
435     * @return void
436     */
437    public function dropRememberToken()
438    {
439        $this->dropColumn('remember_token');
440    }
441
442    /**
443     * Indicate that the polymorphic columns should be dropped.
444     *
445     * @param  string  $name
446     * @param  string|null  $indexName
447     * @return void
448     */
449    public function dropMorphs($name, $indexName = null)
450    {
451        $this->dropIndex($indexName ?: $this->createIndexName('index', ["{$name}_type", "{$name}_id"]));
452
453        $this->dropColumn("{$name}_type", "{$name}_id");
454    }
455
456    /**
457     * Rename the table to a given name.
458     *
459     * @param  string  $to
460     * @return \Illuminate\Support\Fluent
461     */
462    public function rename($to)
463    {
464        return $this->addCommand('rename', compact('to'));
465    }
466
467    /**
468     * Specify the primary key(s) for the table.
469     *
470     * @param  string|array  $columns
471     * @param  string|null  $name
472     * @param  string|null  $algorithm
473     * @return \Illuminate\Support\Fluent
474     */
475    public function primary($columns, $name = null, $algorithm = null)
476    {
477        return $this->indexCommand('primary', $columns, $name, $algorithm);
478    }
479
480    /**
481     * Specify a unique index for the table.
482     *
483     * @param  string|array  $columns
484     * @param  string|null  $name
485     * @param  string|null  $algorithm
486     * @return \Illuminate\Support\Fluent
487     */
488    public function unique($columns, $name = null, $algorithm = null)
489    {
490        return $this->indexCommand('unique', $columns, $name, $algorithm);
491    }
492
493    /**
494     * Specify an index for the table.
495     *
496     * @param  string|array  $columns
497     * @param  string|null  $name
498     * @param  string|null  $algorithm
499     * @return \Illuminate\Support\Fluent
500     */
501    public function index($columns, $name = null, $algorithm = null)
502    {
503        return $this->indexCommand('index', $columns, $name, $algorithm);
504    }
505
506    /**
507     * Specify a spatial index for the table.
508     *
509     * @param  string|array  $columns
510     * @param  string|null  $name
511     * @return \Illuminate\Support\Fluent
512     */
513    public function spatialIndex($columns, $name = null)
514    {
515        return $this->indexCommand('spatialIndex', $columns, $name);
516    }
517
518    /**
519     * Specify a foreign key for the table.
520     *
521     * @param  string|array  $columns
522     * @param  string|null  $name
523     * @return \Illuminate\Support\Fluent|\Illuminate\Database\Schema\ForeignKeyDefinition
524     */
525    public function foreign($columns, $name = null)
526    {
527        return $this->indexCommand('foreign', $columns, $name);
528    }
529
530    /**
531     * Create a new auto-incrementing integer (4-byte) column on the table.
532     *
533     * @param  string  $column
534     * @return \Illuminate\Database\Schema\ColumnDefinition
535     */
536    public function increments($column)
537    {
538        return $this->unsignedInteger($column, true);
539    }
540
541    /**
542     * Create a new auto-incrementing integer (4-byte) column on the table.
543     *
544     * @param  string  $column
545     * @return \Illuminate\Database\Schema\ColumnDefinition
546     */
547    public function integerIncrements($column)
548    {
549        return $this->unsignedInteger($column, true);
550    }
551
552    /**
553     * Create a new auto-incrementing tiny integer (1-byte) column on the table.
554     *
555     * @param  string  $column
556     * @return \Illuminate\Database\Schema\ColumnDefinition
557     */
558    public function tinyIncrements($column)
559    {
560        return $this->unsignedTinyInteger($column, true);
561    }
562
563    /**
564     * Create a new auto-incrementing small integer (2-byte) column on the table.
565     *
566     * @param  string  $column
567     * @return \Illuminate\Database\Schema\ColumnDefinition
568     */
569    public function smallIncrements($column)
570    {
571        return $this->unsignedSmallInteger($column, true);
572    }
573
574    /**
575     * Create a new auto-incrementing medium integer (3-byte) column on the table.
576     *
577     * @param  string  $column
578     * @return \Illuminate\Database\Schema\ColumnDefinition
579     */
580    public function mediumIncrements($column)
581    {
582        return $this->unsignedMediumInteger($column, true);
583    }
584
585    /**
586     * Create a new auto-incrementing big integer (8-byte) column on the table.
587     *
588     * @param  string  $column
589     * @return \Illuminate\Database\Schema\ColumnDefinition
590     */
591    public function bigIncrements($column)
592    {
593        return $this->unsignedBigInteger($column, true);
594    }
595
596    /**
597     * Create a new char column on the table.
598     *
599     * @param  string  $column
600     * @param  int|null  $length
601     * @return \Illuminate\Database\Schema\ColumnDefinition
602     */
603    public function char($column, $length = null)
604    {
605        $length = $length ?: Builder::$defaultStringLength;
606
607        return $this->addColumn('char', $column, compact('length'));
608    }
609
610    /**
611     * Create a new string column on the table.
612     *
613     * @param  string  $column
614     * @param  int|null  $length
615     * @return \Illuminate\Database\Schema\ColumnDefinition
616     */
617    public function string($column, $length = null)
618    {
619        $length = $length ?: Builder::$defaultStringLength;
620
621        return $this->addColumn('string', $column, compact('length'));
622    }
623
624    /**
625     * Create a new text column on the table.
626     *
627     * @param  string  $column
628     * @return \Illuminate\Database\Schema\ColumnDefinition
629     */
630    public function text($column)
631    {
632        return $this->addColumn('text', $column);
633    }
634
635    /**
636     * Create a new medium text column on the table.
637     *
638     * @param  string  $column
639     * @return \Illuminate\Database\Schema\ColumnDefinition
640     */
641    public function mediumText($column)
642    {
643        return $this->addColumn('mediumText', $column);
644    }
645
646    /**
647     * Create a new long text column on the table.
648     *
649     * @param  string  $column
650     * @return \Illuminate\Database\Schema\ColumnDefinition
651     */
652    public function longText($column)
653    {
654        return $this->addColumn('longText', $column);
655    }
656
657    /**
658     * Create a new integer (4-byte) column on the table.
659     *
660     * @param  string  $column
661     * @param  bool  $autoIncrement
662     * @param  bool  $unsigned
663     * @return \Illuminate\Database\Schema\ColumnDefinition
664     */
665    public function integer($column, $autoIncrement = false, $unsigned = false)
666    {
667        return $this->addColumn('integer', $column, compact('autoIncrement', 'unsigned'));
668    }
669
670    /**
671     * Create a new tiny integer (1-byte) column on the table.
672     *
673     * @param  string  $column
674     * @param  bool  $autoIncrement
675     * @param  bool  $unsigned
676     * @return \Illuminate\Database\Schema\ColumnDefinition
677     */
678    public function tinyInteger($column, $autoIncrement = false, $unsigned = false)
679    {
680        return $this->addColumn('tinyInteger', $column, compact('autoIncrement', 'unsigned'));
681    }
682
683    /**
684     * Create a new small integer (2-byte) column on the table.
685     *
686     * @param  string  $column
687     * @param  bool  $autoIncrement
688     * @param  bool  $unsigned
689     * @return \Illuminate\Database\Schema\ColumnDefinition
690     */
691    public function smallInteger($column, $autoIncrement = false, $unsigned = false)
692    {
693        return $this->addColumn('smallInteger', $column, compact('autoIncrement', 'unsigned'));
694    }
695
696    /**
697     * Create a new medium integer (3-byte) column on the table.
698     *
699     * @param  string  $column
700     * @param  bool  $autoIncrement
701     * @param  bool  $unsigned
702     * @return \Illuminate\Database\Schema\ColumnDefinition
703     */
704    public function mediumInteger($column, $autoIncrement = false, $unsigned = false)
705    {
706        return $this->addColumn('mediumInteger', $column, compact('autoIncrement', 'unsigned'));
707    }
708
709    /**
710     * Create a new big integer (8-byte) column on the table.
711     *
712     * @param  string  $column
713     * @param  bool  $autoIncrement
714     * @param  bool  $unsigned
715     * @return \Illuminate\Database\Schema\ColumnDefinition
716     */
717    public function bigInteger($column, $autoIncrement = false, $unsigned = false)
718    {
719        return $this->addColumn('bigInteger', $column, compact('autoIncrement', 'unsigned'));
720    }
721
722    /**
723     * Create a new unsigned integer (4-byte) column on the table.
724     *
725     * @param  string  $column
726     * @param  bool  $autoIncrement
727     * @return \Illuminate\Database\Schema\ColumnDefinition
728     */
729    public function unsignedInteger($column, $autoIncrement = false)
730    {
731        return $this->integer($column, $autoIncrement, true);
732    }
733
734    /**
735     * Create a new unsigned tiny integer (1-byte) column on the table.
736     *
737     * @param  string  $column
738     * @param  bool  $autoIncrement
739     * @return \Illuminate\Database\Schema\ColumnDefinition
740     */
741    public function unsignedTinyInteger($column, $autoIncrement = false)
742    {
743        return $this->tinyInteger($column, $autoIncrement, true);
744    }
745
746    /**
747     * Create a new unsigned small integer (2-byte) column on the table.
748     *
749     * @param  string  $column
750     * @param  bool  $autoIncrement
751     * @return \Illuminate\Database\Schema\ColumnDefinition
752     */
753    public function unsignedSmallInteger($column, $autoIncrement = false)
754    {
755        return $this->smallInteger($column, $autoIncrement, true);
756    }
757
758    /**
759     * Create a new unsigned medium integer (3-byte) column on the table.
760     *
761     * @param  string  $column
762     * @param  bool  $autoIncrement
763     * @return \Illuminate\Database\Schema\ColumnDefinition
764     */
765    public function unsignedMediumInteger($column, $autoIncrement = false)
766    {
767        return $this->mediumInteger($column, $autoIncrement, true);
768    }
769
770    /**
771     * Create a new unsigned big integer (8-byte) column on the table.
772     *
773     * @param  string  $column
774     * @param  bool  $autoIncrement
775     * @return \Illuminate\Database\Schema\ColumnDefinition
776     */
777    public function unsignedBigInteger($column, $autoIncrement = false)
778    {
779        return $this->bigInteger($column, $autoIncrement, true);
780    }
781
782    /**
783     * Create a new float column on the table.
784     *
785     * @param  string  $column
786     * @param  int  $total
787     * @param  int  $places
788     * @return \Illuminate\Database\Schema\ColumnDefinition
789     */
790    public function float($column, $total = 8, $places = 2)
791    {
792        return $this->addColumn('float', $column, compact('total', 'places'));
793    }
794
795    /**
796     * Create a new double column on the table.
797     *
798     * @param  string  $column
799     * @param  int|null  $total
800     * @param  int|null  $places
801     * @return \Illuminate\Database\Schema\ColumnDefinition
802     */
803    public function double($column, $total = null, $places = null)
804    {
805        return $this->addColumn('double', $column, compact('total', 'places'));
806    }
807
808    /**
809     * Create a new decimal column on the table.
810     *
811     * @param  string  $column
812     * @param  int  $total
813     * @param  int  $places
814     * @return \Illuminate\Database\Schema\ColumnDefinition
815     */
816    public function decimal($column, $total = 8, $places = 2)
817    {
818        return $this->addColumn('decimal', $column, compact('total', 'places'));
819    }
820
821    /**
822     * Create a new unsigned decimal column on the table.
823     *
824     * @param  string  $column
825     * @param  int  $total
826     * @param  int  $places
827     * @return \Illuminate\Database\Schema\ColumnDefinition
828     */
829    public function unsignedDecimal($column, $total = 8, $places = 2)
830    {
831        return $this->addColumn('decimal', $column, [
832            'total' => $total, 'places' => $places, 'unsigned' => true,
833        ]);
834    }
835
836    /**
837     * Create a new boolean column on the table.
838     *
839     * @param  string  $column
840     * @return \Illuminate\Database\Schema\ColumnDefinition
841     */
842    public function boolean($column)
843    {
844        return $this->addColumn('boolean', $column);
845    }
846
847    /**
848     * Create a new enum column on the table.
849     *
850     * @param  string  $column
851     * @param  array  $allowed
852     * @return \Illuminate\Database\Schema\ColumnDefinition
853     */
854    public function enum($column, array $allowed)
855    {
856        return $this->addColumn('enum', $column, compact('allowed'));
857    }
858
859    /**
860     * Create a new set column on the table.
861     *
862     * @param  string  $column
863     * @param  array  $allowed
864     * @return \Illuminate\Database\Schema\ColumnDefinition
865     */
866    public function set($column, array $allowed)
867    {
868        return $this->addColumn('set', $column, compact('allowed'));
869    }
870
871    /**
872     * Create a new json column on the table.
873     *
874     * @param  string  $column
875     * @return \Illuminate\Database\Schema\ColumnDefinition
876     */
877    public function json($column)
878    {
879        return $this->addColumn('json', $column);
880    }
881
882    /**
883     * Create a new jsonb column on the table.
884     *
885     * @param  string  $column
886     * @return \Illuminate\Database\Schema\ColumnDefinition
887     */
888    public function jsonb($column)
889    {
890        return $this->addColumn('jsonb', $column);
891    }
892
893    /**
894     * Create a new date column on the table.
895     *
896     * @param  string  $column
897     * @return \Illuminate\Database\Schema\ColumnDefinition
898     */
899    public function date($column)
900    {
901        return $this->addColumn('date', $column);
902    }
903
904    /**
905     * Create a new date-time column on the table.
906     *
907     * @param  string  $column
908     * @param  int  $precision
909     * @return \Illuminate\Database\Schema\ColumnDefinition
910     */
911    public function dateTime($column, $precision = 0)
912    {
913        return $this->addColumn('dateTime', $column, compact('precision'));
914    }
915
916    /**
917     * Create a new date-time column (with time zone) on the table.
918     *
919     * @param  string  $column
920     * @param  int  $precision
921     * @return \Illuminate\Database\Schema\ColumnDefinition
922     */
923    public function dateTimeTz($column, $precision = 0)
924    {
925        return $this->addColumn('dateTimeTz', $column, compact('precision'));
926    }
927
928    /**
929     * Create a new time column on the table.
930     *
931     * @param  string  $column
932     * @param  int  $precision
933     * @return \Illuminate\Database\Schema\ColumnDefinition
934     */
935    public function time($column, $precision = 0)
936    {
937        return $this->addColumn('time', $column, compact('precision'));
938    }
939
940    /**
941     * Create a new time column (with time zone) on the table.
942     *
943     * @param  string  $column
944     * @param  int  $precision
945     * @return \Illuminate\Database\Schema\ColumnDefinition
946     */
947    public function timeTz($column, $precision = 0)
948    {
949        return $this->addColumn('timeTz', $column, compact('precision'));
950    }
951
952    /**
953     * Create a new timestamp column on the table.
954     *
955     * @param  string  $column
956     * @param  int  $precision
957     * @return \Illuminate\Database\Schema\ColumnDefinition
958     */
959    public function timestamp($column, $precision = 0)
960    {
961        return $this->addColumn('timestamp', $column, compact('precision'));
962    }
963
964    /**
965     * Create a new timestamp (with time zone) column on the table.
966     *
967     * @param  string  $column
968     * @param  int  $precision
969     * @return \Illuminate\Database\Schema\ColumnDefinition
970     */
971    public function timestampTz($column, $precision = 0)
972    {
973        return $this->addColumn('timestampTz', $column, compact('precision'));
974    }
975
976    /**
977     * Add nullable creation and update timestamps to the table.
978     *
979     * @param  int  $precision
980     * @return void
981     */
982    public function timestamps($precision = 0)
983    {
984        $this->timestamp('created_at', $precision)->nullable();
985
986        $this->timestamp('updated_at', $precision)->nullable();
987    }
988
989    /**
990     * Add nullable creation and update timestamps to the table.
991     *
992     * Alias for self::timestamps().
993     *
994     * @param  int  $precision
995     * @return void
996     */
997    public function nullableTimestamps($precision = 0)
998    {
999        $this->timestamps($precision);
1000    }
1001
1002    /**
1003     * Add creation and update timestampTz columns to the table.
1004     *
1005     * @param  int  $precision
1006     * @return void
1007     */
1008    public function timestampsTz($precision = 0)
1009    {
1010        $this->timestampTz('created_at', $precision)->nullable();
1011
1012        $this->timestampTz('updated_at', $precision)->nullable();
1013    }
1014
1015    /**
1016     * Add a "deleted at" timestamp for the table.
1017     *
1018     * @param  string  $column
1019     * @param  int  $precision
1020     * @return \Illuminate\Database\Schema\ColumnDefinition
1021     */
1022    public function softDeletes($column = 'deleted_at', $precision = 0)
1023    {
1024        return $this->timestamp($column, $precision)->nullable();
1025    }
1026
1027    /**
1028     * Add a "deleted at" timestampTz for the table.
1029     *
1030     * @param  string  $column
1031     * @param  int  $precision
1032     * @return \Illuminate\Database\Schema\ColumnDefinition
1033     */
1034    public function softDeletesTz($column = 'deleted_at', $precision = 0)
1035    {
1036        return $this->timestampTz($column, $precision)->nullable();
1037    }
1038
1039    /**
1040     * Create a new year column on the table.
1041     *
1042     * @param  string  $column
1043     * @return \Illuminate\Database\Schema\ColumnDefinition
1044     */
1045    public function year($column)
1046    {
1047        return $this->addColumn('year', $column);
1048    }
1049
1050    /**
1051     * Create a new binary column on the table.
1052     *
1053     * @param  string  $column
1054     * @return \Illuminate\Database\Schema\ColumnDefinition
1055     */
1056    public function binary($column)
1057    {
1058        return $this->addColumn('binary', $column);
1059    }
1060
1061    /**
1062     * Create a new uuid column on the table.
1063     *
1064     * @param  string  $column
1065     * @return \Illuminate\Database\Schema\ColumnDefinition
1066     */
1067    public function uuid($column)
1068    {
1069        return $this->addColumn('uuid', $column);
1070    }
1071
1072    /**
1073     * Create a new IP address column on the table.
1074     *
1075     * @param  string  $column
1076     * @return \Illuminate\Database\Schema\ColumnDefinition
1077     */
1078    public function ipAddress($column)
1079    {
1080        return $this->addColumn('ipAddress', $column);
1081    }
1082
1083    /**
1084     * Create a new MAC address column on the table.
1085     *
1086     * @param  string  $column
1087     * @return \Illuminate\Database\Schema\ColumnDefinition
1088     */
1089    public function macAddress($column)
1090    {
1091        return $this->addColumn('macAddress', $column);
1092    }
1093
1094    /**
1095     * Create a new geometry column on the table.
1096     *
1097     * @param  string  $column
1098     * @return \Illuminate\Database\Schema\ColumnDefinition
1099     */
1100    public function geometry($column)
1101    {
1102        return $this->addColumn('geometry', $column);
1103    }
1104
1105    /**
1106     * Create a new point column on the table.
1107     *
1108     * @param  string  $column
1109     * @param  int|null  $srid
1110     * @return \Illuminate\Database\Schema\ColumnDefinition
1111     */
1112    public function point($column, $srid = null)
1113    {
1114        return $this->addColumn('point', $column, compact('srid'));
1115    }
1116
1117    /**
1118     * Create a new linestring column on the table.
1119     *
1120     * @param  string  $column
1121     * @return \Illuminate\Database\Schema\ColumnDefinition
1122     */
1123    public function lineString($column)
1124    {
1125        return $this->addColumn('linestring', $column);
1126    }
1127
1128    /**
1129     * Create a new polygon column on the table.
1130     *
1131     * @param  string  $column
1132     * @return \Illuminate\Database\Schema\ColumnDefinition
1133     */
1134    public function polygon($column)
1135    {
1136        return $this->addColumn('polygon', $column);
1137    }
1138
1139    /**
1140     * Create a new geometrycollection column on the table.
1141     *
1142     * @param  string  $column
1143     * @return \Illuminate\Database\Schema\ColumnDefinition
1144     */
1145    public function geometryCollection($column)
1146    {
1147        return $this->addColumn('geometrycollection', $column);
1148    }
1149
1150    /**
1151     * Create a new multipoint column on the table.
1152     *
1153     * @param  string  $column
1154     * @return \Illuminate\Database\Schema\ColumnDefinition
1155     */
1156    public function multiPoint($column)
1157    {
1158        return $this->addColumn('multipoint', $column);
1159    }
1160
1161    /**
1162     * Create a new multilinestring column on the table.
1163     *
1164     * @param  string  $column
1165     * @return \Illuminate\Database\Schema\ColumnDefinition
1166     */
1167    public function multiLineString($column)
1168    {
1169        return $this->addColumn('multilinestring', $column);
1170    }
1171
1172    /**
1173     * Create a new multipolygon column on the table.
1174     *
1175     * @param  string  $column
1176     * @return \Illuminate\Database\Schema\ColumnDefinition
1177     */
1178    public function multiPolygon($column)
1179    {
1180        return $this->addColumn('multipolygon', $column);
1181    }
1182
1183    /**
1184     * Create a new multipolygon column on the table.
1185     *
1186     * @param  string  $column
1187     * @return \Illuminate\Database\Schema\ColumnDefinition
1188     */
1189    public function multiPolygonZ($column)
1190    {
1191        return $this->addColumn('multipolygonz', $column);
1192    }
1193
1194    /**
1195     * Create a new generated, computed column on the table.
1196     *
1197     * @param  string  $column
1198     * @param  string  $expression
1199     * @return \Illuminate\Database\Schema\ColumnDefinition
1200     */
1201    public function computed($column, $expression)
1202    {
1203        return $this->addColumn('computed', $column, compact('expression'));
1204    }
1205
1206    /**
1207     * Add the proper columns for a polymorphic table.
1208     *
1209     * @param  string  $name
1210     * @param  string|null  $indexName
1211     * @return void
1212     */
1213    public function morphs($name, $indexName = null)
1214    {
1215        $this->string("{$name}_type");
1216
1217        $this->unsignedBigInteger("{$name}_id");
1218
1219        $this->index(["{$name}_type", "{$name}_id"], $indexName);
1220    }
1221
1222    /**
1223     * Add nullable columns for a polymorphic table.
1224     *
1225     * @param  string  $name
1226     * @param  string|null  $indexName
1227     * @return void
1228     */
1229    public function nullableMorphs($name, $indexName = null)
1230    {
1231        $this->string("{$name}_type")->nullable();
1232
1233        $this->unsignedBigInteger("{$name}_id")->nullable();
1234
1235        $this->index(["{$name}_type", "{$name}_id"], $indexName);
1236    }
1237
1238    /**
1239     * Add the proper columns for a polymorphic table using UUIDs.
1240     *
1241     * @param  string  $name
1242     * @param  string|null  $indexName
1243     * @return void
1244     */
1245    public function uuidMorphs($name, $indexName = null)
1246    {
1247        $this->string("{$name}_type");
1248
1249        $this->uuid("{$name}_id");
1250
1251        $this->index(["{$name}_type", "{$name}_id"], $indexName);
1252    }
1253
1254    /**
1255     * Add nullable columns for a polymorphic table using UUIDs.
1256     *
1257     * @param  string  $name
1258     * @param  string|null  $indexName
1259     * @return void
1260     */
1261    public function nullableUuidMorphs($name, $indexName = null)
1262    {
1263        $this->string("{$name}_type")->nullable();
1264
1265        $this->uuid("{$name}_id")->nullable();
1266
1267        $this->index(["{$name}_type", "{$name}_id"], $indexName);
1268    }
1269
1270    /**
1271     * Adds the `remember_token` column to the table.
1272     *
1273     * @return \Illuminate\Database\Schema\ColumnDefinition
1274     */
1275    public function rememberToken()
1276    {
1277        return $this->string('remember_token', 100)->nullable();
1278    }
1279
1280    /**
1281     * Add a new index command to the blueprint.
1282     *
1283     * @param  string  $type
1284     * @param  string|array  $columns
1285     * @param  string  $index
1286     * @param  string|null  $algorithm
1287     * @return \Illuminate\Support\Fluent
1288     */
1289    protected function indexCommand($type, $columns, $index, $algorithm = null)
1290    {
1291        $columns = (array) $columns;
1292
1293        // If no name was specified for this index, we will create one using a basic
1294        // convention of the table name, followed by the columns, followed by an
1295        // index type, such as primary or index, which makes the index unique.
1296        $index = $index ?: $this->createIndexName($type, $columns);
1297
1298        return $this->addCommand(
1299            $type, compact('index', 'columns', 'algorithm')
1300        );
1301    }
1302
1303    /**
1304     * Create a new drop index command on the blueprint.
1305     *
1306     * @param  string  $command
1307     * @param  string  $type
1308     * @param  string|array  $index
1309     * @return \Illuminate\Support\Fluent
1310     */
1311    protected function dropIndexCommand($command, $type, $index)
1312    {
1313        $columns = [];
1314
1315        // If the given "index" is actually an array of columns, the developer means
1316        // to drop an index merely by specifying the columns involved without the
1317        // conventional name, so we will build the index name from the columns.
1318        if (is_array($index)) {
1319            $index = $this->createIndexName($type, $columns = $index);
1320        }
1321
1322        return $this->indexCommand($command, $columns, $index);
1323    }
1324
1325    /**
1326     * Create a default index name for the table.
1327     *
1328     * @param  string  $type
1329     * @param  array  $columns
1330     * @return string
1331     */
1332    protected function createIndexName($type, array $columns)
1333    {
1334        $index = strtolower($this->prefix.$this->table.'_'.implode('_', $columns).'_'.$type);
1335
1336        return str_replace(['-', '.'], '_', $index);
1337    }
1338
1339    /**
1340     * Add a new column to the blueprint.
1341     *
1342     * @param  string  $type
1343     * @param  string  $name
1344     * @param  array  $parameters
1345     * @return \Illuminate\Database\Schema\ColumnDefinition
1346     */
1347    public function addColumn($type, $name, array $parameters = [])
1348    {
1349        $this->columns[] = $column = new ColumnDefinition(
1350            array_merge(compact('type', 'name'), $parameters)
1351        );
1352
1353        return $column;
1354    }
1355
1356    /**
1357     * Remove a column from the schema blueprint.
1358     *
1359     * @param  string  $name
1360     * @return $this
1361     */
1362    public function removeColumn($name)
1363    {
1364        $this->columns = array_values(array_filter($this->columns, function ($c) use ($name) {
1365            return $c['name'] != $name;
1366        }));
1367
1368        return $this;
1369    }
1370
1371    /**
1372     * Add a new command to the blueprint.
1373     *
1374     * @param  string  $name
1375     * @param  array  $parameters
1376     * @return \Illuminate\Support\Fluent
1377     */
1378    protected function addCommand($name, array $parameters = [])
1379    {
1380        $this->commands[] = $command = $this->createCommand($name, $parameters);
1381
1382        return $command;
1383    }
1384
1385    /**
1386     * Create a new Fluent command.
1387     *
1388     * @param  string  $name
1389     * @param  array  $parameters
1390     * @return \Illuminate\Support\Fluent
1391     */
1392    protected function createCommand($name, array $parameters = [])
1393    {
1394        return new Fluent(array_merge(compact('name'), $parameters));
1395    }
1396
1397    /**
1398     * Get the table the blueprint describes.
1399     *
1400     * @return string
1401     */
1402    public function getTable()
1403    {
1404        return $this->table;
1405    }
1406
1407    /**
1408     * Get the columns on the blueprint.
1409     *
1410     * @return \Illuminate\Database\Schema\ColumnDefinition[]
1411     */
1412    public function getColumns()
1413    {
1414        return $this->columns;
1415    }
1416
1417    /**
1418     * Get the commands on the blueprint.
1419     *
1420     * @return \Illuminate\Support\Fluent[]
1421     */
1422    public function getCommands()
1423    {
1424        return $this->commands;
1425    }
1426
1427    /**
1428     * Get the columns on the blueprint that should be added.
1429     *
1430     * @return \Illuminate\Database\Schema\ColumnDefinition[]
1431     */
1432    public function getAddedColumns()
1433    {
1434        return array_filter($this->columns, function ($column) {
1435            return ! $column->change;
1436        });
1437    }
1438
1439    /**
1440     * Get the columns on the blueprint that should be changed.
1441     *
1442     * @return \Illuminate\Database\Schema\ColumnDefinition[]
1443     */
1444    public function getChangedColumns()
1445    {
1446        return array_filter($this->columns, function ($column) {
1447            return (bool) $column->change;
1448        });
1449    }
1450}
1451