index/src/Data/MariaDB/MariaDBBackend.php

122 lines
4 KiB
PHP

<?php
// MariaDBBackend.php
// Created: 2021-04-30
// Updated: 2023-01-01
namespace Index\Data\MariaDB;
use InvalidArgumentException;
use Index\Version;
use Index\Data\IDbBackend;
use Index\Data\IDbConnection;
use Index\Data\IDbConnectionInfo;
use Index\Net\EndPoint;
use Index\Net\UnixEndPoint;
/**
* Information about the MariaDB/MySQL database layer.
*/
class MariaDBBackend implements IDbBackend {
public function isAvailable(): bool {
return extension_loaded('mysqli');
}
/**
* @internal
*/
public static function intToVersion(int $version): Version {
$sub = $version % 100;
$version = floor($version / 100);
$minor = $version % 100;
$version = floor($version / 100);
$major = $version % 100;
return new Version($major, $minor, $sub);
}
/**
* Gets the version of the underlying client library.
*
* @return Version Version of the client library.
*/
public function getClientVersion(): Version {
return self::intToVersion(mysqli_get_client_version());
}
/**
* Creates a connection with a MariaDB or MySQL server.
*
* @param MariaDBConnectionInfo $connectionInfo Object that describes the desired connection.
* @return MariaDBConnection A connection with a MariaDB or MySQL server.
*/
public function createConnection(IDbConnectionInfo $connectionInfo): IDbConnection {
if(!($connectionInfo instanceof MariaDBConnectionInfo))
throw new InvalidArgumentException('$connectionInfo must by of type MariaDBConnectionInfo');
return new MariaDBConnection($connectionInfo);
}
/**
* @return MariaDBConnectionInfo MariaDB connection info.
*/
public function parseDsn(string|array $dsn): IDbConnectionInfo {
if(is_string($dsn)) {
$dsn = parse_url($dsn);
if($dsn === false)
throw new InvalidArgumentException('$dsn is not a valid uri.');
}
if(!isset($dsn['host']))
throw new InvalidArgumentException('Host is missing from DSN.');
if(!isset($dsn['path']))
throw new InvalidArgumentException('Path is missing from DSN.');
$host = $dsn['host'];
$needsUnix = $host === ':unix';
if(!$needsUnix && isset($dsn['port']))
$host .= ':' . $dsn['port'];
$user = $dsn['user'] ?? '';
$pass = $dsn['pass'] ?? '';
$endPoint = $needsUnix ? null : EndPoint::parse($host);
$dbName = str_replace('/', '_', trim($dsn['path'], '/')); // cute for table prefixes i think
if(!isset($dsn['query'])) {
$charSet = null;
$initCommand = null;
$keyPath = null;
$certPath = null;
$certAuthPath = null;
$trustedCertsPath = null;
$cipherAlgos = null;
$verifyCert = false;
$useCompression = false;
} else {
parse_str(str_replace('+', '%2B', $dsn['query']), $query);
$unixPath = $query['socket'] ?? null;
$charSet = $query['charset'] ?? null;
$initCommand = $query['init'] ?? null;
$keyPath = $query['enc_key'] ?? null;
$certPath = $query['enc_cert'] ?? null;
$certAuthPath = $query['enc_authority'] ?? null;
$trustedCertsPath = $query['enc_trusted_certs'] ?? null;
$cipherAlgos = $query['enc_ciphers'] ?? null;
$verifyCert = !empty($query['enc_verify']);
$useCompression = !empty($query['compress']);
}
if($needsUnix) {
if(empty($unixPath))
throw new InvalidArgumentException('Unix socket path is missing from DSN.');
$endPoint = new UnixEndPoint($unixPath);
}
return new MariaDBConnectionInfo(
$endPoint, $user, $pass, $dbName,
$charSet, $initCommand, $keyPath, $certPath,
$certAuthPath, $trustedCertsPath, $cipherAlgos,
$verifyCert, $useCompression
);
}
}