1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
declare(strict_types=1); |
4
|
|
|
|
5
|
|
|
namespace EdmondsCommerce\DoctrineStaticMeta\Schema; |
6
|
|
|
|
7
|
|
|
use EdmondsCommerce\DoctrineStaticMeta\ConfigInterface; |
8
|
|
|
use EdmondsCommerce\DoctrineStaticMeta\Exception\DoctrineStaticMetaException; |
9
|
|
|
use InvalidArgumentException; |
10
|
|
|
use mysqli; |
11
|
|
|
|
12
|
|
|
/** |
13
|
|
|
* Class Database |
14
|
|
|
* |
15
|
|
|
* Drop and Create the Actual Database using raw mysqli |
16
|
|
|
* |
17
|
|
|
* @package EdmondsCommerce\DoctrineStaticMeta\Schema |
18
|
|
|
*/ |
19
|
|
|
class Database |
20
|
|
|
{ |
21
|
|
|
|
22
|
|
|
/** |
23
|
|
|
* @see https://dev.mysql.com/doc/refman/5.7/en/identifiers.html |
24
|
|
|
*/ |
25
|
|
|
public const MAX_IDENTIFIER_LENGTH = 64; |
26
|
|
|
|
27
|
|
|
/** |
28
|
|
|
* @see https://dev.mysql.com/doc/refman/5.7/en/precision-math-decimal-characteristics.html |
29
|
|
|
*/ |
30
|
|
|
public const MAX_DECIMAL_PRECISION = 65; |
31
|
|
|
public const MAX_DECIMAL_SCALE = 30; |
32
|
|
|
|
33
|
|
|
/** |
34
|
|
|
* @see https://github.com/symfony/symfony-docs/issues/639 |
35
|
|
|
* basically, if we are using utf8mb4 then the max col length on strings is no longer 255 |
36
|
|
|
*/ |
37
|
|
|
public const MAX_VARCHAR_LENGTH = 190; |
38
|
|
|
|
39
|
|
|
public const MAX_INT_VALUE = 2147483647; |
40
|
|
|
|
41
|
|
|
/** |
42
|
|
|
* @var ConfigInterface |
43
|
|
|
*/ |
44
|
|
|
private $config; |
45
|
|
|
|
46
|
|
|
/** |
47
|
|
|
* @var null|mysqli |
48
|
|
|
*/ |
49
|
|
|
private $link; |
50
|
|
|
|
51
|
|
|
public function __construct(ConfigInterface $config) |
52
|
|
|
{ |
53
|
|
|
$this->config = $config; |
54
|
|
|
} |
55
|
|
|
|
56
|
|
|
/** |
57
|
|
|
* You have to pass in true to confirm you really want to do it |
58
|
|
|
* |
59
|
|
|
* @param bool $sure |
60
|
|
|
* |
61
|
|
|
* @return Database |
62
|
|
|
* @throws InvalidArgumentException |
63
|
|
|
* @throws DoctrineStaticMetaException |
64
|
|
|
*/ |
65
|
|
|
public function drop($sure): Database |
66
|
|
|
{ |
67
|
|
|
if (true !== $sure) { |
68
|
|
|
$this->throwUnsure(); |
69
|
|
|
} |
70
|
|
|
$link = $this->connect(); |
71
|
|
|
$sql = "DROP DATABASE IF EXISTS `{$this->config->get(ConfigInterface::PARAM_DB_NAME)}`"; |
72
|
|
|
if (true !== mysqli_query($link, $sql)) { |
73
|
|
|
$mysqlError = mysqli_errno($link) . ': ' . mysqli_error($link); |
74
|
|
|
throw new DoctrineStaticMetaException( |
75
|
|
|
'Failed to drop the database ' |
76
|
|
|
. $this->config->get(ConfigInterface::PARAM_DB_NAME) |
77
|
|
|
. ' Mysql Error - ' . $mysqlError |
78
|
|
|
); |
79
|
|
|
} |
80
|
|
|
|
81
|
|
|
return $this; |
82
|
|
|
} |
83
|
|
|
|
84
|
|
|
protected function throwUnsure(): void |
85
|
|
|
{ |
86
|
|
|
throw new InvalidArgumentException('You must pass in `true` to show you are sure'); |
87
|
|
|
} |
88
|
|
|
|
89
|
|
|
/** |
90
|
|
|
* @return mysqli |
91
|
|
|
* @throws DoctrineStaticMetaException |
92
|
|
|
*/ |
93
|
|
|
private function connect(): mysqli |
94
|
|
|
{ |
95
|
|
|
if (null === $this->link) { |
96
|
|
|
$this->link = mysqli_connect( |
|
|
|
|
97
|
|
|
$this->config->get(ConfigInterface::PARAM_DB_HOST), |
98
|
|
|
$this->config->get(ConfigInterface::PARAM_DB_USER), |
99
|
|
|
$this->config->get(ConfigInterface::PARAM_DB_PASS) |
100
|
|
|
); |
101
|
|
|
if (!$this->link) { |
102
|
|
|
throw new DoctrineStaticMetaException('Failed getting connection in ' . __METHOD__); |
103
|
|
|
} |
104
|
|
|
} |
105
|
|
|
|
106
|
|
|
return $this->link; |
107
|
|
|
} |
108
|
|
|
|
109
|
|
|
/** |
110
|
|
|
* You have to pass in true to confirm you really want to do it |
111
|
|
|
* |
112
|
|
|
* @param bool $sure |
113
|
|
|
* |
114
|
|
|
* @return Database |
115
|
|
|
* @throws InvalidArgumentException |
116
|
|
|
* @throws DoctrineStaticMetaException |
117
|
|
|
*/ |
118
|
|
|
public function create($sure): Database |
119
|
|
|
{ |
120
|
|
|
if (true !== $sure) { |
121
|
|
|
$this->throwUnsure(); |
122
|
|
|
} |
123
|
|
|
$link = $this->connect(); |
124
|
|
|
$sql = 'CREATE DATABASE IF NOT EXISTS `' |
125
|
|
|
. $this->config->get(ConfigInterface::PARAM_DB_NAME) |
126
|
|
|
. '` CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci'; |
127
|
|
|
if (true !== mysqli_query($link, $sql)) { |
128
|
|
|
throw new DoctrineStaticMetaException( |
129
|
|
|
'Failed to create the database ' |
130
|
|
|
. $this->config->get(ConfigInterface::PARAM_DB_NAME) |
131
|
|
|
); |
132
|
|
|
} |
133
|
|
|
|
134
|
|
|
return $this; |
135
|
|
|
} |
136
|
|
|
|
137
|
|
|
public function __destruct() |
138
|
|
|
{ |
139
|
|
|
$this->close(); |
140
|
|
|
} |
141
|
|
|
|
142
|
|
|
public function close(): void |
143
|
|
|
{ |
144
|
|
|
if (null !== $this->link) { |
145
|
|
|
mysqli_close($this->link); |
146
|
|
|
$this->link = null; |
147
|
|
|
} |
148
|
|
|
} |
149
|
|
|
} |
150
|
|
|
|
Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.
For example, imagine you have a variable
$accountId
that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to theid
property of an instance of theAccount
class. This class holds a proper account, so the id value must no longer be false.Either this assignment is in error or a type check should be added for that assignment.