PluginProbe
404 Solution / 4.3.3
404 Solution v4.3.3
4.3.5 4.3.4 4.3.3 4.3.2 4.3.1 4.3.0 4.2.0 4.1.19 4.1.18 4.1.17 4.1.16 4.1.15 4.1.13 4.1.12 4.1.11 4.1.10 4.1.9 4.1.8 4.1.7 4.1.6 4.1.5 4.1.4 4.1.3 trunk 2.30.0 All 109 releases
404-solution / includes / database / TrackingDatabaseCore.php

TrackingDatabaseCore.php in 404 Solution 4.3.3, at includes/database/TrackingDatabaseCore.php

107 lines 3.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 if (!defined('ABSPATH')) {
4 exit;
5 }
6
7 /**
8 * DatabaseCore subclass that records all queries and their params for assertion
9 * in tests. Optionally simulates failures at a specific chunk or phase.
10 *
11 * Used by the Phase 8 extraction tests that exercise LogsRepository's
12 * createRedirectsForViewHitsTable() chunked-rebuild pipeline. The pipeline
13 * calls $this->dbCore->queryAndGetResults(), so a tracking DatabaseCore is
14 * the DI seam that lets tests observe the SQL without hitting a real DB.
15 */
16 class ABJ_404_Solution_TrackingDatabaseCore extends ABJ_404_Solution_DatabaseCore {
17
18 /** @var array<int, string> */
19 public array $queries = [];
20 /** @var array<int, mixed> */
21 public array $queryParams = [];
22 /** @var array<string, array<string, mixed>> Per-pattern response overrides (substring => result array) */
23 public array $queryResponses = [];
24 /** @var int */
25 private int $failOnChunk;
26 /** @var bool */
27 private bool $failOnPhase2;
28 /** @var int */
29 private int $chunkInsertCount = 0;
30
31 /**
32 * @param mixed $functions
33 * @param mixed $logger
34 * @param int $failOnChunk Chunk number to simulate failure on (0 = none)
35 * @param bool $failOnPhase2 Whether to simulate a Phase 2 failure
36 */
37 /**
38 * @param ABJ_404_Solution_Functions|null $functions
39 * @param ABJ_404_Solution_Logging|null $logger
40 */
41 public function __construct($functions = null, $logger = null, int $failOnChunk = 0, bool $failOnPhase2 = false) {
42 parent::__construct($functions, $logger);
43 $this->failOnChunk = $failOnChunk;
44 $this->failOnPhase2 = $failOnPhase2;
45 }
46
47 public function queryAndGetResults($query, $options = array()): array {
48 $idx = count($this->queries);
49 $this->queries[$idx] = $query;
50 $this->queryParams[$idx] = $options['query_params'] ?? [];
51
52 foreach ($this->queryResponses as $pattern => $response) {
53 if (stripos($query, $pattern) !== false) {
54 return $response;
55 }
56 }
57
58 $normalized = strtolower((string)$query);
59 $isChunkInsert = stripos($normalized, 'insert into') !== false
60 && stripos($normalized, 'preagg') !== false
61 && stripos($normalized, 'where') !== false;
62
63 if ($isChunkInsert) {
64 $this->chunkInsertCount++;
65 if ($this->failOnChunk > 0 && $this->chunkInsertCount === $this->failOnChunk) {
66 return [
67 'rows' => [],
68 'last_error' => 'Simulated chunk failure',
69 'elapsed_time' => 0.1,
70 'last_result' => [],
71 'rows_affected' => 0,
72 'insert_id' => 0,
73 ];
74 }
75 }
76
77 $isPhase2 = stripos($normalized, 'insert into') !== false
78 && stripos($normalized, 'inner join') !== false
79 && stripos($normalized, 'preagg') !== false;
80 if ($isPhase2 && $this->failOnPhase2) {
81 return [
82 'rows' => [],
83 'last_error' => 'Simulated Phase 2 failure',
84 'elapsed_time' => 0.1,
85 'last_result' => [],
86 'rows_affected' => 0,
87 'insert_id' => 0,
88 ];
89 }
90
91 return [
92 'rows' => [],
93 'last_error' => '',
94 'elapsed_time' => 0.05,
95 'last_result' => [],
96 'rows_affected' => 0,
97 'insert_id' => 0,
98 ];
99 }
100
101 public function executeAsTransaction(array $statementArray): void {
102 foreach ($statementArray as $stmt) {
103 $this->queries[] = $stmt;
104 }
105 }
106 }
107