<?php
declare(strict_types = 1);

/**
 * Méthodes de base de données pour MySQL.
 *
 * @license https://www.gnu.org/licenses/gpl-3.0.html
 * @link https://www.igalerie.org/
 */
class DBLayer
{
	/**
	 * Nom du SGBD.
	 *
	 * @var string
	 */
	const NAME = 'MySQL';

	/**
	 * Numéro de port du serveur par défaut.
	 *
	 * @var string
	 */
	const PORT_DEFAULT = '3306';

	/**
	 * Version minimale requise.
	 *
	 * @var string
	 */
	const VERSION_MIN = '5.5';



	/**
	 * Retourne des informations sur la base de données.
	 *
	 * @return array
	 */
	public static function getDetails(): array
	{
		if (DB::execute("SHOW VARIABLES"))
		{
			$variables = DB::fetchAll('Variable_name', 'Value');
			$details =
			[
				'innodb_lock_wait_timeout' =>
				[
					'text' => 'innodb_lock_wait_timeout',
					'value' => $variables['innodb_lock_wait_timeout'] ?? 'undefined'
				],
				'max_user_connections' =>
				[
					'text' => 'max_user_connections',
					'value' => $variables['max_user_connections'] ?? 'undefined'
				],
				'sql_mode' =>
				[
					'text' => 'sql_mode',
					'value' => $variables['sql_mode'] ?? 'undefined'
				]
			];
		}

		return $details ?? [];
	}

	/**
	 * Nettoie la base de données.
	 *
	 * @return bool
	 */
	public static function vacuum(): bool
	{
		foreach (System::DB_TABLES as &$table)
		{
			if (!DB::execute("OPTIMIZE TABLE {{$table}}"))
			{
				return FALSE;
			}
		}
		return TRUE;
	}



	/**
	 * Retourne le DSN pour se connecter à la base de données.
	 *
	 * @return string
	 */
	protected static function _getDSN(): string
	{
		return CONF_DB_TYPE . ':host=' . CONF_DB_HOST . ';port='
			 . CONF_DB_PORT . ';dbname=' . CONF_DB_NAME;
	}

	/**
	 * Paramètres d'initialisation.
	 *
	 * @param PDO $pdo
	 *
	 * @return bool
	 */
	protected static function _initialize(PDO $pdo): bool
	{
		$buffered_query = version_compare(PHP_VERSION, '8.4', '<')
			? PDO::MYSQL_ATTR_USE_BUFFERED_QUERY
			: Pdo\Mysql::ATTR_USE_BUFFERED_QUERY;
		if (!$pdo->setAttribute($buffered_query, TRUE))
		{
			return FALSE;
		}

		if (!DB::execute("SET NAMES utf8mb4"))
		{
			return FALSE;
		}

		// Remplace CONCAT(x,y) par x || y.
		if (!DB::execute("SET sql_mode = 'PIPES_AS_CONCAT'"))
		{
			return FALSE;
		}

		return TRUE;
	}

	/**
	 * Nom de la séquence d'objets (uniquement pour PostgreSQL).
	 *
	 * @param array $seq
	 *
	 * @return null
	 */
	protected static function _seqName(array $seq = [])
	{
		return NULL;
	}

	/**
	 * Code SQL à remplacer.
	 *
	 * @param string $sql
	 *
	 * @return string
	 */
	protected static function _replaceSQL(string $sql): string
	{
		// Remplacement de la fonction NOW().
		if (CONF_DB_DATE == 'php')
		{
			$sql = str_replace("NOW()", "'" . date('Y-m-d H:i:s') . "'", $sql);
		}

		if (substr($sql, 0, 12) == 'CREATE TABLE')
		{
			// Avec MySQL 5.6 et inférieur, la longueur des colonnes indexées
			// ne peut pas dépasser 255 caractères avec utf8 ou 191 caractères
			// avec utf8mb4. Pour les colonnes cat_path et item_path on utilise
			// donc VARBINARY au lieu de VARCHAR, car les types binaires ne
			// sont pas affectés par l'encodage utilisé.
			$sql = str_replace('VARCHAR(767)', 'VARBINARY(767)', $sql);

			$sql .= " ENGINE=InnoDB CHARACTER SET=utf8mb4 COLLATE=utf8mb4_unicode_ci";
		}

		return $sql;
	}
}
?>