Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
49 / 49
100.00% covered (success)
100.00%
8 / 8
CRAP
100.00% covered (success)
100.00%
1 / 1
TableDefinition
100.00% covered (success)
100.00%
49 / 49
100.00% covered (success)
100.00%
8 / 8
17
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 column
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
1
 index
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
1
 check
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 renderColumns
100.00% covered (success)
100.00%
13 / 13
100.00% covered (success)
100.00%
1 / 1
5
 renderIndexes
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
1 / 1
3
 renderChecks
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
2
 sql
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
1 / 1
3
1<?php declare(strict_types=1);
2/*
3 * This file is part of Aplus Framework Database Library.
4 *
5 * (c) Natan Felles <natanfelles@gmail.com>
6 *
7 * For the full copyright and license information, please view the LICENSE
8 * file that was distributed with this source code.
9 */
10namespace Framework\Database\Definition\Table;
11
12use Closure;
13use Framework\Database\Database;
14use Framework\Database\Definition\Table\Columns\ColumnDefinition;
15use Framework\Database\Definition\Table\Indexes\IndexDefinition;
16
17/**
18 * Class TableDefinition.
19 *
20 * @package database
21 */
22class TableDefinition extends DefinitionPart
23{
24    protected Database $database;
25    /**
26     * @var array<int,array<string,mixed>>
27     */
28    protected array $columns = [];
29    /**
30     * @var array<int,array<string,mixed>>
31     */
32    protected array $indexes = [];
33    /**
34     * @var array<int,Check>
35     */
36    protected array $checks = [];
37    protected ?string $condition = null;
38
39    /**
40     * TableDefinition constructor.
41     *
42     * @param Database $database
43     * @param string|null $condition
44     */
45    public function __construct(Database $database, string $condition = null)
46    {
47        $this->database = $database;
48        $this->condition = $condition;
49    }
50
51    /**
52     * Adds a column to the Table Definition list.
53     *
54     * @param string $name Column name
55     * @param string|null $changeName New column name. Used on ALTER TABLE CHANGE
56     *
57     * @return ColumnDefinition
58     */
59    public function column(string $name, string $changeName = null) : ColumnDefinition
60    {
61        $definition = new ColumnDefinition($this->database);
62        $this->columns[] = [
63            'name' => $name,
64            'change_name' => $changeName,
65            'definition' => $definition,
66        ];
67        return $definition;
68    }
69
70    /**
71     * Adds an index to the Table Definition list.
72     *
73     * @param string|null $name Index name
74     *
75     * @return IndexDefinition
76     */
77    public function index(string $name = null) : IndexDefinition
78    {
79        $definition = new IndexDefinition($this->database, $name);
80        $this->indexes[] = [
81            'name' => $name,
82            'definition' => $definition,
83        ];
84        return $definition;
85    }
86
87    /**
88     * Adds a check constraint to the Table Definition list.
89     *
90     * @param Closure $expression Must return a string with the check expression.
91     * The function receives a Database instance in the first parameter.
92     *
93     * @return Check
94     */
95    public function check(Closure $expression) : Check
96    {
97        return $this->checks[] = new Check($this->database, $expression);
98    }
99
100    protected function renderColumns(string $prefix = null) : string
101    {
102        if ($prefix) {
103            $prefix .= ' COLUMN';
104        }
105        if ($this->condition) {
106            $prefix .= ' ' . $this->condition;
107        }
108        $sql = [];
109        foreach ($this->columns as $column) {
110            $name = $this->database->protectIdentifier($column['name']);
111            $changeName = $column['change_name']
112                ? ' ' . $this->database->protectIdentifier($column['change_name'])
113                : null;
114            $definition = $column['definition']->sql();
115            $sql[] = " {$prefix} {$name}{$changeName}{$definition}";
116        }
117        return \implode(',' . \PHP_EOL, $sql);
118    }
119
120    protected function renderIndexes(string $prefix = null) : string
121    {
122        $sql = [];
123        foreach ($this->indexes as $index) {
124            $definition = $index['definition']->sql();
125            if ($this->condition) {
126                $definition = \explode('(', $definition, 2);
127                $definition = $definition[0] . $this->condition . ' (' . $definition[1];
128            }
129            $sql[] = " {$prefix}{$definition}";
130        }
131        return \implode(',' . \PHP_EOL, $sql);
132    }
133
134    protected function renderChecks() : string
135    {
136        $sql = [];
137        foreach ($this->checks as $check) {
138            $sql[] = ' ' . $check->sql();
139        }
140        return \implode(',' . \PHP_EOL, $sql);
141    }
142
143    protected function sql(string $prefix = null) : string
144    {
145        $sql = $this->renderColumns($prefix);
146        $part = $this->renderIndexes($prefix);
147        if ($part) {
148            $sql .= ',' . \PHP_EOL . $part;
149        }
150        $part = $this->renderChecks();
151        if ($part) {
152            $sql .= ',' . \PHP_EOL . $part;
153        }
154        return $sql;
155    }
156}