<?php

declare(strict_types=1);

namespace Acms\Services\Installer;

/**
 * インストーラーで入力される DB 名・テーブル接頭辞の検証。
 *
 * install の Database ステップは `CREATE DATABASE \`{db_name}\`` / `ALTER DATABASE ...` を
 * バッククォートで囲むだけで発行しており、バッククォートを含む値を渡すと SQL を抜けられる。
 * 接頭辞（db_prefix）は全テーブル名に連結されるため同様に危険。ここで許可リスト方式に倒し、
 * 想定外の文字を含む入力を CREATE/ALTER 前に弾く。判定のみの純粋ロジックとする。
 */
final class DatabaseNameValidator
{
    /**
     * DB 名の許可パターン。英数字・アンダースコアのみ（ハイフンは許可しない）。
     * バッククォート/空白/記号を排除して識別子エスケープの不備を無害化する。
     * MySQL の識別子仕様上はバッククォートで囲めばハイフンも安全だが、CLI ツールへの
     * 引数渡し等バッククォートに依存しない文脈での再利用に備え、接頭辞と同じ許可リストに揃える。
     */
    private const DATABASE_NAME_PATTERN = '/\A[A-Za-z0-9_]+\z/';

    /**
     * テーブル接頭辞の許可パターン。テーブル名に連結されるためハイフンは許可しない。
     * 空文字（接頭辞なし運用）も許可する。
     */
    private const PREFIX_PATTERN = '/\A[A-Za-z0-9_]*\z/';

    /**
     * MySQL の識別子最大長。
     */
    private const MAX_IDENTIFIER_LENGTH = 64;

    public function isValidDatabaseName(string $name): bool
    {
        if ($name === '' || strlen($name) > self::MAX_IDENTIFIER_LENGTH) {
            return false;
        }

        return preg_match(self::DATABASE_NAME_PATTERN, $name) === 1;
    }

    public function isValidPrefix(string $prefix): bool
    {
        if (strlen($prefix) > self::MAX_IDENTIFIER_LENGTH) {
            return false;
        }

        return preg_match(self::PREFIX_PATTERN, $prefix) === 1;
    }
}
