packages/ztd-query-core/tests/Fake/FakeConnection.php

1<?php
2
3declare(strict_types=1);
4
5namespace Tests\Fake;
6
7use ZtdQuery\Connection\ConnectionInterface;
8use ZtdQuery\Connection\StatementInterface;
9use ZtdQuery\Schema\RowSet;
10use ZtdQuery\Schema\TableDefinition;
11
12/**
13 * Fake ConnectionInterface that returns pre-configured FakeStatements.
14 *
15 * Queries are recorded for inspection. Results can be pre-loaded per SQL string
16 * or a default result set can be provided. Specific queries can be configured to
17 * fail by returning false, enabling tests for error-handling branches.
18 *
19 * @phpstan-import-type Row from TableDefinition
20 */
21final class FakeConnection implements ConnectionInterface
22{
23    /**
24     * Recorded queries.
25     *
26     * @var array<int, string>
27     */
28    public array $queries = [];
29
30    /**
31     * Pre-configured results keyed by SQL.
32     *
33     * @var array<string, RowSet>
34     */
35    private array $results;
36
37    /**
38     * Default rows returned when no specific result is configured.
39     *
40     */
41    private RowSet $defaultRows;
42
43    /**
44     * SQL patterns that should return false (simulating query failure).
45     *
46     * @var array<int, string>
47     */
48    private array $failPatterns = [];
49
50    /**
51     * @param array<string, array<int, Row>> $results SQL => rows mapping.
52     * @param array<int, Row> $defaultRows Default rows for unconfigured queries.
53     */
54    public function __construct(array $results = [], array $defaultRows = [])
55    {
56        $this->results = [];
57        foreach ($results as $sql => $rows) {
58            $this->addResult($sql, $rows);
59        }
60        $this->defaultRows = new RowSet($defaultRows);
61    }
62
63    /**
64     * Query.
65     *
66     * @param string $sql
67     * @return StatementInterface|false
68     */
69    public function query(string $sql): StatementInterface|false
70    {
71        $this->queries[] = $sql;
72
73        foreach ($this->failPatterns as $pattern) {
74            if ($sql === $pattern) {
75                return false;
76            }
77        }
78
79        $rows = $this->results[$sql] ?? $this->defaultRows;
80
81        return new FakeStatement($rows->rows);
82    }
83
84    /**
85     * Pre-load a result for a specific SQL query.
86     *
87     * @param array<int, Row> $rows
88     */
89    public function addResult(string $sql, array $rows): void
90    {
91        $this->results[$sql] = new RowSet($rows);
92    }
93
94    /**
95     * Configure a query to return false (simulate failure).
96     */
97    public function failOnQuery(string $sql): void
98    {
99        $this->failPatterns[] = $sql;
100    }
101}
102