| 1 |
<?php |
| 2 |
|
| 3 |
if (!defined('ABSPATH')) { |
| 4 |
exit; |
| 5 |
} |
| 6 |
|
| 7 |
/** |
| 8 |
* LogsRepository subclass that stubs getMaxLogId() and getMinLogId() with |
| 9 |
* fixed values for tests that exercise the chunked-rebuild pipeline. |
| 10 |
* |
| 11 |
* The pipeline reads MIN/MAX from logsv2 to decide chunk boundaries. A real |
| 12 |
* DB would need rows; this subclass lets tests control the id range directly. |
| 13 |
*/ |
| 14 |
class ABJ_404_Solution_TrackingLogsRepository extends ABJ_404_Solution_LogsRepository { |
| 15 |
|
| 16 |
/** @var list<string> Query log forwarded from TrackingDatabaseCore */ |
| 17 |
public array $queries = []; |
| 18 |
/** @var array<int, list<mixed>> Query params forwarded from TrackingDatabaseCore */ |
| 19 |
public array $queryParams = []; |
| 20 |
/** @var int */ |
| 21 |
private int $minId; |
| 22 |
/** @var int */ |
| 23 |
private int $maxId; |
| 24 |
|
| 25 |
/** |
| 26 |
* @param ABJ_404_Solution_DatabaseCore $dbCore |
| 27 |
* @param ABJ_404_Solution_Functions|null $functions |
| 28 |
* @param ABJ_404_Solution_Logging|null $logger |
| 29 |
* @param int $minId Fixed return value for getMinLogId() |
| 30 |
* @param int $maxId Fixed return value for getMaxLogId() |
| 31 |
* @param ABJ_404_Solution_RebuildHealthState|null $rebuildHealth |
| 32 |
*/ |
| 33 |
public function __construct( |
| 34 |
ABJ_404_Solution_DatabaseCore $dbCore, |
| 35 |
$functions = null, |
| 36 |
$logger = null, |
| 37 |
int $minId = 0, |
| 38 |
int $maxId = 0, |
| 39 |
$rebuildHealth = null |
| 40 |
) { |
| 41 |
$rollup = new ABJ_404_Solution_TrackingLogsHitsRollupService( |
| 42 |
$dbCore, $logger, $rebuildHealth, $minId, $maxId |
| 43 |
); |
| 44 |
parent::__construct($dbCore, $functions, $logger, $rebuildHealth, $rollup); |
| 45 |
$this->minId = $minId; |
| 46 |
$this->maxId = $maxId; |
| 47 |
} |
| 48 |
|
| 49 |
function getMaxLogId() { return $this->maxId; } |
| 50 |
function getMinLogId() { return $this->minId; } |
| 51 |
|
| 52 |
/** |
| 53 |
* Replace the rollup collaborator wired into this repository. Test seam |
| 54 |
* for cases where the test needs to swap in a fully-prepared |
| 55 |
* TrackingLogsHitsRollupService with extra overrides. |
| 56 |
* |
| 57 |
* @param ABJ_404_Solution_LogsHitsRollupServiceInterface $rollup |
| 58 |
* @return void |
| 59 |
*/ |
| 60 |
public function setRollupForTests(ABJ_404_Solution_LogsHitsRollupServiceInterface $rollup): void { |
| 61 |
$ref = new ReflectionProperty(ABJ_404_Solution_LogsRepository::class, 'rollup'); |
| 62 |
$ref->setValue($this, $rollup); |
| 63 |
} |
| 64 |
} |
| 65 |
|
| 66 |
/** |
| 67 |
* LogsHitsRollupService subclass with fixed min/max log id values, so the |
| 68 |
* tracking rebuild pipeline (which now lives on the rollup service) sees the |
| 69 |
* same id range the test set up via TrackingLogsRepository. |
| 70 |
*/ |
| 71 |
class ABJ_404_Solution_TrackingLogsHitsRollupService extends ABJ_404_Solution_LogsHitsRollupService { |
| 72 |
/** @var int */ |
| 73 |
private int $minId; |
| 74 |
/** @var int */ |
| 75 |
private int $maxId; |
| 76 |
/** @var int|null */ |
| 77 |
private $storedMaxIdOverride = null; |
| 78 |
/** @var bool|null */ |
| 79 |
private $logsHitsTableExistsOverride = null; |
| 80 |
|
| 81 |
public function __construct( |
| 82 |
ABJ_404_Solution_DatabaseCore $dbCore, |
| 83 |
$logging = null, |
| 84 |
$rebuildHealth = null, |
| 85 |
int $minId = 0, |
| 86 |
int $maxId = 0 |
| 87 |
) { |
| 88 |
parent::__construct($dbCore, $logging, $rebuildHealth); |
| 89 |
$this->minId = $minId; |
| 90 |
$this->maxId = $maxId; |
| 91 |
} |
| 92 |
|
| 93 |
/** @var callable|null */ |
| 94 |
private $maxLogIdResolver = null; |
| 95 |
|
| 96 |
/** |
| 97 |
* Set a callable that produces getMaxLogId() on demand. Lets tests model |
| 98 |
* "MAX(id) grew during the insert window" without subclassing. |
| 99 |
* |
| 100 |
* @param callable():int $resolver |
| 101 |
*/ |
| 102 |
public function setMaxLogIdResolverForTests(callable $resolver): void { |
| 103 |
$this->maxLogIdResolver = $resolver; |
| 104 |
} |
| 105 |
|
| 106 |
public function getMaxLogId() { |
| 107 |
if ($this->maxLogIdResolver !== null) { |
| 108 |
return (int)call_user_func($this->maxLogIdResolver); |
| 109 |
} |
| 110 |
return $this->maxId; |
| 111 |
} |
| 112 |
public function getMinLogId() { return $this->minId; } |
| 113 |
|
| 114 |
/** Test seam: override the stored watermark value. */ |
| 115 |
public function setStoredMaxLogIdForTests(int $value): void { $this->storedMaxIdOverride = $value; } |
| 116 |
public function getStoredMaxLogId() { |
| 117 |
if ($this->storedMaxIdOverride !== null) { return $this->storedMaxIdOverride; } |
| 118 |
return parent::getStoredMaxLogId(); |
| 119 |
} |
| 120 |
|
| 121 |
/** Test seam: override logsHitsTableExists() boolean. */ |
| 122 |
public function setLogsHitsTableExistsForTests(bool $value): void { $this->logsHitsTableExistsOverride = $value; } |
| 123 |
public function logsHitsTableExists() { |
| 124 |
if ($this->logsHitsTableExistsOverride !== null) { return $this->logsHitsTableExistsOverride; } |
| 125 |
return parent::logsHitsTableExists(); |
| 126 |
} |
| 127 |
} |
| 128 |
|