WriteValidator.php
PHP
Path: src/Database/WriteValidator.php
<?php
namespace mini\Database;
use mini\ValidationException;
use mini\Validator\Purpose;
use function mini\validator;
/**
* Validates data before database writes
*
* Centralizes validation logic for insert/update operations.
* Both PDODatabase and VirtualDatabase use this to ensure consistent validation.
*
* Validation flow:
* 1. Purpose-scoped validation (Create or Update) - validates fields with that purpose
* 2. Core validation - validates fields without purpose (always runs)
*
* Both must pass for the write to proceed.
*/
final class WriteValidator
{
/**
* Validate data for INSERT operation
*
* @param string $entityClass Entity class with validation attributes
* @param array $data Data to be inserted (column => value)
* @throws ValidationException If validation fails
*/
public static function validateInsert(string $entityClass, array $data): void
{
self::validate($entityClass, $data, Purpose::Create);
}
/**
* Validate data for UPDATE operation
*
* Merges current row with changes, then validates the complete entity state.
*
* @param string $entityClass Entity class with validation attributes
* @param array $currentRow Current row data from database
* @param array $changes Changes to apply (column => value)
* @throws ValidationException If validation fails
*/
public static function validateUpdate(string $entityClass, array $currentRow, array $changes): void
{
// Merge current state with changes
$merged = array_merge($currentRow, $changes);
self::validate($entityClass, $merged, Purpose::Update);
}
/**
* Core validation logic
*
* @param string $entityClass Entity class with validation attributes
* @param array $data Data to validate
* @param Purpose $purpose Purpose::Create or Purpose::Update
* @throws ValidationException If validation fails
*/
private static function validate(string $entityClass, array $data, Purpose $purpose): void
{
// 1. Purpose-scoped validation (may be empty if no attributes have this purpose)
$purposeValidator = validator($entityClass, $purpose);
$error = $purposeValidator->isInvalid($data);
if ($error !== null) {
throw new ValidationException($error);
}
// 2. Core validation (always runs)
$coreValidator = validator($entityClass);
$error = $coreValidator->isInvalid($data);
if ($error !== null) {
throw new ValidationException($error);
}
}
}