ulmus/src/Adapter/MySQL.php
2023-10-31 14:40:02 +00:00

161 lines
4.6 KiB
PHP

<?php
namespace Ulmus\Adapter;
use Ulmus\Entity\InformationSchema\Table;
use Ulmus\Migration\MigrateInterface;
use Ulmus\QueryBuilder;
use Ulmus\Repository;
use Ulmus\Common\PdoObject;
use Ulmus\Exception\AdapterConfigurationException;
use Ulmus\Ulmus;
use Ulmus\Migration\FieldDefinition;
class MySQL implements AdapterInterface, MigrateInterface, SqlAdapterInterface {
use SqlAdapterTrait;
const ALLOWED_ATTRIBUTES = [
'default', 'primary_key', 'auto_increment', 'update',
];
const DSN_PREFIX = "mysql";
public string $hostname;
public string $database;
protected string $username;
protected string $password;
public string $charset = "utf8mb4";
public ? string $socket;
public int $port = 3306;
public function __construct(
?string $hostname = null,
?string $database = null,
?string $username = null,
?string $password = null,
?int $port = null,
?string $charset = null
) {
if ($hostname) {
$this->hostname = $hostname;
}
if ($database) {
$this->database = $database;
}
if ($port) {
$this->port = $port;
}
if ($username) {
$this->username = $username;
}
if ($password) {
$this->password = $password;
}
if ($charset) {
$this->charset = $charset;
}
}
public function connect() : PdoObject
{
try {
$pdo = new PdoObject($this->buildDataSourceName(), $this->username, $this->password);
$pdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
$pdo->setAttribute(\PDO::ATTR_EMULATE_PREPARES, false);
$pdo->setAttribute(\PDO::ATTR_AUTOCOMMIT, false);
$pdo->setAttribute(\PDO::ATTR_DEFAULT_FETCH_MODE, \PDO::FETCH_ASSOC);
$pdo->setAttribute(\PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, false);
}
catch(\PDOException $ex){
throw $ex;
}
finally {
$this->password = str_repeat('*', random_int(8,16));
}
return $pdo;
}
public function buildDataSourceName() : string
{
if ( false !== ($this->socket ?? false) ) {
$parts[] = "unix_socket={$this->socket}";
}
else {
$parts[] = "host={$this->hostname}";
if ( false !== ( $this->port ?? false ) ) {
$parts[] = "port={$this->port}";
}
}
$parts[] = "dbname={$this->database}";
if ( $this->charset ?? false ) {
$parts[] = "charset={$this->charset}";
}
return static::DSN_PREFIX . ":" . implode(';', $parts);
}
public function setup(array $configuration) : void
{
$connection = array_change_key_case($configuration, \CASE_LOWER);
# Either Unix Socket is used, or Host / Port
if ( null === ( $this->socket = $connection['socket'] ?? null ) ) {
if ( "" === ( $this->hostname = $connection['host'] ?? "" ) ) {
throw new AdapterConfigurationException("Your `host` name is missing from your configuration array");
}
if ( false !== ( $configuration['port'] ?? false ) ) {
$this->port = $configuration['port'];
}
}
if ( false === ( $this->database = $connection['database'] ?? false ) ) {
throw new AdapterConfigurationException("Your `database` name is missing from your configuration array");
}
elseif ( false === ( $this->username = $connection['username'] ?? false ) ) {
throw new AdapterConfigurationException("Your `username` is missing from your configuration array");
}
elseif ( false === ( $this->password = $connection['password'] ?? false ) ) {
throw new AdapterConfigurationException("Your `password` is missing from your configuration array");
}
if ( false !== ( $configuration['charset'] ?? false ) ) {
$this->charset = $configuration['charset'];
}
}
public function escapeIdentifier(string $segment, int $type) : string
{
switch($type) {
case static::IDENTIFIER_DATABASE:
case static::IDENTIFIER_TABLE:
case static::IDENTIFIER_FIELD:
return "`" . trim(str_replace("`", "``", $segment), '`') . "`";
case static::IDENTIFIER_VALUE:
return "\"$segment\"";
}
}
public function defaultEngine(): ? string
{
return "InnoDB";
}
}