Completed
Branch feature/pre-split (1fb89d)
by Anton
03:12
created

AbstractReference::sqlStatement()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 17
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 11
nc 1
nop 1
dl 0
loc 17
rs 9.4285
c 0
b 0
f 0
1
<?php
2
/**
3
 * components
4
 *
5
 * @author    Wolfy-J
6
 */
7
namespace Spiral\Database\Schemas\Prototypes;
8
9
use Spiral\Database\Entities\Driver;
10
use Spiral\Database\Exceptions\SchemaException;
11
use Spiral\Database\Schemas\ReferenceInterface;
12
13
/**
14
 * Abstract foreign schema with read (see ReferenceInterface) and write abilities. Must be
15
 * implemented by driver to support DBMS specific syntax and creation rules.
16
 */
17
abstract class AbstractReference extends AbstractElement implements ReferenceInterface
18
{
19
    /**
20
     * Local column name (key name).
21
     *
22
     * @var string
23
     */
24
    protected $column = '';
25
26
    /**
27
     * Referenced table name (including prefix).
28
     *
29
     * @var string
30
     */
31
    protected $foreignTable = '';
32
33
    /**
34
     * Linked foreign key name (foreign column).
35
     *
36
     * @var string
37
     */
38
    protected $foreignKey = '';
39
40
    /**
41
     * Action on foreign column value deletion.
42
     *
43
     * @var string
44
     */
45
    protected $deleteRule = self::NO_ACTION;
46
47
    /**
48
     * Action on foreign column value update.
49
     *
50
     * @var string
51
     */
52
    protected $updateRule = self::NO_ACTION;
53
54
    /**
55
     * {@inheritdoc}
56
     *
57
     * @param string $name
58
     */
59
    public function setName(string $name): AbstractElement
60
    {
61
        if (!empty($this->name)) {
62
            throw new SchemaException('Changing reference name is not allowed');
0 ignored issues
show
Unused Code introduced by
The call to SchemaException::__construct() has too many arguments starting with 'Changing reference name is not allowed'.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
63
        }
64
65
        return parent::setName($name);
66
    }
67
68
    /**
69
     * {@inheritdoc}
70
     */
71
    public function getName(): string
72
    {
73
        if (empty($this->name)) {
74
            //Generating name on a fly
75
            $this->setName($this->generateName());
76
        }
77
78
        return parent::getName();
79
    }
80
81
    /**
82
     * {@inheritdoc}
83
     */
84
    public function getColumn(): string
85
    {
86
        return $this->column;
87
    }
88
89
    /**
90
     * {@inheritdoc}
91
     */
92
    public function getForeignTable(): string
93
    {
94
        return $this->foreignTable;
95
    }
96
97
    /**
98
     * {@inheritdoc}
99
     */
100
    public function getForeignKey(): string
101
    {
102
        return $this->foreignKey;
103
    }
104
105
    /**
106
     * {@inheritdoc}
107
     */
108
    public function getDeleteRule(): string
109
    {
110
        return $this->deleteRule;
111
    }
112
113
    /**
114
     * {@inheritdoc}
115
     */
116
    public function getUpdateRule(): string
117
    {
118
        return $this->updateRule;
119
    }
120
121
    //--- MODIFICATIONS
122
123
    /**
124
     * Foreign key creation syntax.
125
     *
126
     * @param Driver $driver
127
     *
128
     * @return string
129
     */
130
    public function sqlStatement(Driver $driver): string
131
    {
132
        $statement = [];
133
134
        $statement[] = 'CONSTRAINT';
135
        $statement[] = $driver->identifier($this->name);
136
        $statement[] = 'FOREIGN KEY';
137
        $statement[] = '(' . $driver->identifier($this->column) . ')';
138
139
        $statement[] = 'REFERENCES ' . $driver->identifier($this->foreignTable);
140
        $statement[] = '(' . $driver->identifier($this->foreignKey) . ')';
141
142
        $statement[] = "ON DELETE {$this->deleteRule}";
143
        $statement[] = "ON UPDATE {$this->updateRule}";
144
145
        return implode(' ', $statement);
146
    }
147
148
    /**
149
     * {@inheritdoc}
150
     */
151
    public function compare(ReferenceInterface $initial): bool
152
    {
153
        return $this == clone $initial;
154
    }
155
156
    /**
157
     * Generate unique foreign key name.
158
     *
159
     * @return string
160
     */
161
    protected function generateName(): string
162
    {
163
        $name = $this->table . '_foreign_' . $this->column . '_' . uniqid();
164
165
        if (strlen($name) > 64) {
166
            //Many dbs has limitations on identifier length
167
            $name = md5($name);
168
        }
169
170
        return $name;
171
    }
172
}