1<?php
2/**
3 * Phinx
4 *
5 * (The MIT license)
6 * Copyright (c) 2015 Rob Morgan
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a copy
9 * of this software and associated * documentation files (the "Software"), to
10 * deal in the Software without restriction, including without limitation the
11 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
12 * sell copies of the Software, and to permit persons to whom the Software is
13 * furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice shall be included in
16 * all copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
24 * IN THE SOFTWARE.
25 *
26 * @package    Phinx
27 * @subpackage Phinx\Db
28 */
29namespace Phinx\Db\Table;
30
31use Phinx\Db\Adapter\AdapterInterface;
32
33/**
34 *
35 * This object is based loosely on: http://api.rubyonrails.org/classes/ActiveRecord/ConnectionAdapters/Table.html.
36 */
37class Column
38{
39    /**
40     * @var string
41     */
42    protected $name;
43
44    /**
45     * @var string|\Phinx\Util\Literal
46     */
47    protected $type;
48
49    /**
50     * @var integer
51     */
52    protected $limit = null;
53
54    /**
55     * @var boolean
56     */
57    protected $null = false;
58
59    /**
60     * @var mixed
61     */
62    protected $default = null;
63
64    /**
65     * @var boolean
66     */
67    protected $identity = false;
68
69    /**
70     * @var integer
71     */
72    protected $scale;
73
74    /**
75     * @var string
76     */
77    protected $after;
78
79    /**
80     * @var string
81     */
82    protected $update;
83
84    /**
85     * @var string
86     */
87    protected $comment;
88
89    /**
90     * @var boolean
91     */
92    protected $signed = true;
93
94    /**
95     * @var boolean
96     */
97    protected $timezone = false;
98
99    /**
100     * @var array
101     */
102    protected $properties = [];
103
104    /**
105     * @var string
106     */
107    protected $collation;
108
109    /**
110     * @var string
111     */
112    protected $encoding;
113
114    /**
115     * @var array
116     */
117    protected $values;
118
119    /**
120     * Sets the column name.
121     *
122     * @param string $name
123     * @return \Phinx\Db\Table\Column
124     */
125    public function setName($name)
126    {
127        $this->name = $name;
128
129        return $this;
130    }
131
132    /**
133     * Gets the column name.
134     *
135     * @return string|null
136     */
137    public function getName()
138    {
139        return $this->name;
140    }
141
142    /**
143     * Sets the column type.
144     *
145     * @param string|\Phinx\Util\Literal $type Column type
146     * @return \Phinx\Db\Table\Column
147     */
148    public function setType($type)
149    {
150        $this->type = $type;
151
152        return $this;
153    }
154
155    /**
156     * Gets the column type.
157     *
158     * @return string|\Phinx\Util\Literal
159     */
160    public function getType()
161    {
162        return $this->type;
163    }
164
165    /**
166     * Sets the column limit.
167     *
168     * @param int $limit
169     * @return \Phinx\Db\Table\Column
170     */
171    public function setLimit($limit)
172    {
173        $this->limit = $limit;
174
175        return $this;
176    }
177
178    /**
179     * Gets the column limit.
180     *
181     * @return int
182     */
183    public function getLimit()
184    {
185        return $this->limit;
186    }
187
188    /**
189     * Sets whether the column allows nulls.
190     *
191     * @param bool $null
192     * @return \Phinx\Db\Table\Column
193     */
194    public function setNull($null)
195    {
196        $this->null = (bool)$null;
197
198        return $this;
199    }
200
201    /**
202     * Gets whether the column allows nulls.
203     *
204     * @return bool
205     */
206    public function getNull()
207    {
208        return $this->null;
209    }
210
211    /**
212     * Does the column allow nulls?
213     *
214     * @return bool
215     */
216    public function isNull()
217    {
218        return $this->getNull();
219    }
220
221    /**
222     * Sets the default column value.
223     *
224     * @param mixed $default
225     * @return \Phinx\Db\Table\Column
226     */
227    public function setDefault($default)
228    {
229        $this->default = $default;
230
231        return $this;
232    }
233
234    /**
235     * Gets the default column value.
236     *
237     * @return mixed
238     */
239    public function getDefault()
240    {
241        return $this->default;
242    }
243
244    /**
245     * Sets whether or not the column is an identity column.
246     *
247     * @param bool $identity
248     * @return \Phinx\Db\Table\Column
249     */
250    public function setIdentity($identity)
251    {
252        $this->identity = $identity;
253
254        return $this;
255    }
256
257    /**
258     * Gets whether or not the column is an identity column.
259     *
260     * @return bool
261     */
262    public function getIdentity()
263    {
264        return $this->identity;
265    }
266
267    /**
268     * Is the column an identity column?
269     *
270     * @return bool
271     */
272    public function isIdentity()
273    {
274        return $this->getIdentity();
275    }
276
277    /**
278     * Sets the name of the column to add this column after.
279     *
280     * @param string $after After
281     * @return \Phinx\Db\Table\Column
282     */
283    public function setAfter($after)
284    {
285        $this->after = $after;
286
287        return $this;
288    }
289
290    /**
291     * Returns the name of the column to add this column after.
292     *
293     * @return string
294     */
295    public function getAfter()
296    {
297        return $this->after;
298    }
299
300    /**
301     * Sets the 'ON UPDATE' mysql column function.
302     *
303     * @param  string $update On Update function
304     * @return \Phinx\Db\Table\Column
305     */
306    public function setUpdate($update)
307    {
308        $this->update = $update;
309
310        return $this;
311    }
312
313    /**
314     * Returns the value of the ON UPDATE column function.
315     *
316     * @return string
317     */
318    public function getUpdate()
319    {
320        return $this->update;
321    }
322
323    /**
324     * Sets the number precision for decimal or float column.
325     *
326     * For example `DECIMAL(5,2)`, 5 is the precision and 2 is the scale,
327     * and the column could store value from -999.99 to 999.99.
328     *
329     * @param int $precision Number precision
330     * @return \Phinx\Db\Table\Column
331     */
332    public function setPrecision($precision)
333    {
334        $this->setLimit($precision);
335
336        return $this;
337    }
338
339    /**
340     * Gets the number precision for decimal or float column.
341     *
342     * For example `DECIMAL(5,2)`, 5 is the precision and 2 is the scale,
343     * and the column could store value from -999.99 to 999.99.
344     *
345     * @return int
346     */
347    public function getPrecision()
348    {
349        return $this->limit;
350    }
351
352    /**
353     * Sets the number scale for decimal or float column.
354     *
355     * For example `DECIMAL(5,2)`, 5 is the precision and 2 is the scale,
356     * and the column could store value from -999.99 to 999.99.
357     *
358     * @param int $scale Number scale
359     * @return \Phinx\Db\Table\Column
360     */
361    public function setScale($scale)
362    {
363        $this->scale = $scale;
364
365        return $this;
366    }
367
368    /**
369     * Gets the number scale for decimal or float column.
370     *
371     * For example `DECIMAL(5,2)`, 5 is the precision and 2 is the scale,
372     * and the column could store value from -999.99 to 999.99.
373     *
374     * @return int
375     */
376    public function getScale()
377    {
378        return $this->scale;
379    }
380
381    /**
382     * Sets the number precision and scale for decimal or float column.
383     *
384     * For example `DECIMAL(5,2)`, 5 is the precision and 2 is the scale,
385     * and the column could store value from -999.99 to 999.99.
386     *
387     * @param int $precision Number precision
388     * @param int $scale Number scale
389     * @return \Phinx\Db\Table\Column
390     */
391    public function setPrecisionAndScale($precision, $scale)
392    {
393        $this->setLimit($precision);
394        $this->scale = $scale;
395
396        return $this;
397    }
398
399    /**
400     * Sets the column comment.
401     *
402     * @param string $comment
403     * @return \Phinx\Db\Table\Column
404     */
405    public function setComment($comment)
406    {
407        $this->comment = $comment;
408
409        return $this;
410    }
411
412    /**
413     * Gets the column comment.
414     *
415     * @return string
416     */
417    public function getComment()
418    {
419        return $this->comment;
420    }
421
422    /**
423     * Sets whether field should be signed.
424     *
425     * @param bool $signed
426     * @return \Phinx\Db\Table\Column
427     */
428    public function setSigned($signed)
429    {
430        $this->signed = (bool)$signed;
431
432        return $this;
433    }
434
435    /**
436     * Gets whether field should be signed.
437     *
438     * @return bool
439     */
440    public function getSigned()
441    {
442        return $this->signed;
443    }
444
445    /**
446     * Should the column be signed?
447     *
448     * @return bool
449     */
450    public function isSigned()
451    {
452        return $this->getSigned();
453    }
454
455    /**
456     * Sets whether the field should have a timezone identifier.
457     * Used for date/time columns only!
458     *
459     * @param bool $timezone
460     * @return \Phinx\Db\Table\Column
461     */
462    public function setTimezone($timezone)
463    {
464        $this->timezone = (bool)$timezone;
465
466        return $this;
467    }
468
469    /**
470     * Gets whether field has a timezone identifier.
471     *
472     * @return bool
473     */
474    public function getTimezone()
475    {
476        return $this->timezone;
477    }
478
479    /**
480     * Should the column have a timezone?
481     *
482     * @return bool
483     */
484    public function isTimezone()
485    {
486        return $this->getTimezone();
487    }
488
489    /**
490     * Sets field properties.
491     *
492     * @param array $properties
493     *
494     * @return \Phinx\Db\Table\Column
495     */
496    public function setProperties($properties)
497    {
498        $this->properties = $properties;
499
500        return $this;
501    }
502
503    /**
504     * Gets field properties
505     *
506     * @return array
507     */
508    public function getProperties()
509    {
510        return $this->properties;
511    }
512
513    /**
514     * Sets field values.
515     *
516     * @param array|string $values
517     *
518     * @return \Phinx\Db\Table\Column
519     */
520    public function setValues($values)
521    {
522        if (!is_array($values)) {
523            $values = preg_split('/,\s*/', $values);
524        }
525        $this->values = $values;
526
527        return $this;
528    }
529
530    /**
531     * Gets field values
532     *
533     * @return array
534     */
535    public function getValues()
536    {
537        return $this->values;
538    }
539
540    /**
541     * Sets the column collation.
542     *
543     * @param string $collation
544     *
545     * @throws \UnexpectedValueException If collation not allowed for type
546     * @return $this
547     */
548    public function setCollation($collation)
549    {
550        $allowedTypes = [
551            AdapterInterface::PHINX_TYPE_CHAR,
552            AdapterInterface::PHINX_TYPE_STRING,
553            AdapterInterface::PHINX_TYPE_TEXT,
554        ];
555        if (!in_array($this->getType(), $allowedTypes)) {
556            throw new \UnexpectedValueException('Collation may be set only for types: ' . implode(', ', $allowedTypes));
557        }
558
559        $this->collation = $collation;
560
561        return $this;
562    }
563
564    /**
565     * Gets the column collation.
566     *
567     * @return string
568     */
569    public function getCollation()
570    {
571        return $this->collation;
572    }
573
574    /**
575     * Sets the column character set.
576     *
577     * @param string $encoding
578     *
579     * @throws \UnexpectedValueException If character set not allowed for type
580     * @return $this
581     */
582    public function setEncoding($encoding)
583    {
584        $allowedTypes = [
585            AdapterInterface::PHINX_TYPE_CHAR,
586            AdapterInterface::PHINX_TYPE_STRING,
587            AdapterInterface::PHINX_TYPE_TEXT,
588        ];
589        if (!in_array($this->getType(), $allowedTypes)) {
590            throw new \UnexpectedValueException('Character set may be set only for types: ' . implode(', ', $allowedTypes));
591        }
592
593        $this->encoding = $encoding;
594
595        return $this;
596    }
597
598    /**
599     * Gets the column character set.
600     *
601     * @return string
602     */
603    public function getEncoding()
604    {
605        return $this->encoding;
606    }
607
608    /**
609     * Gets all allowed options. Each option must have a corresponding `setFoo` method.
610     *
611     * @return array
612     */
613    protected function getValidOptions()
614    {
615        return [
616            'limit',
617            'default',
618            'null',
619            'identity',
620            'scale',
621            'after',
622            'update',
623            'comment',
624            'signed',
625            'timezone',
626            'properties',
627            'values',
628            'collation',
629            'encoding',
630        ];
631    }
632
633    /**
634     * Gets all aliased options. Each alias must reference a valid option.
635     *
636     * @return array
637     */
638    protected function getAliasedOptions()
639    {
640        return [
641            'length' => 'limit',
642            'precision' => 'limit',
643        ];
644    }
645
646    /**
647     * Utility method that maps an array of column options to this objects methods.
648     *
649     * @param array $options Options
650     * @return \Phinx\Db\Table\Column
651     */
652    public function setOptions($options)
653    {
654        $validOptions = $this->getValidOptions();
655        $aliasOptions = $this->getAliasedOptions();
656
657        foreach ($options as $option => $value) {
658            if (isset($aliasOptions[$option])) {
659                // proxy alias -> option
660                $option = $aliasOptions[$option];
661            }
662
663            if (!in_array($option, $validOptions, true)) {
664                throw new \RuntimeException(sprintf('"%s" is not a valid column option.', $option));
665            }
666
667            $method = 'set' . ucfirst($option);
668            $this->$method($value);
669        }
670
671        return $this;
672    }
673}
674