PluginProbe
404 Solution / trunk
404 Solution vtrunk
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 / upgrades / DatabaseUpgradesEtc.php

DatabaseUpgradesEtc.php in 404 Solution trunk, at includes/database/upgrades/DatabaseUpgradesEtc.php

292 lines 9.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3
4 if (!defined('ABSPATH')) {
5 exit;
6 }
7
8 require_once __DIR__ . '/DatabaseUpgradeCoordinator.php';
9 require_once __DIR__ . '/DatabaseUpgradeComponent.php';
10 require_once __DIR__ . '/DatabaseUpgradeRuntimeState.php';
11 require_once __DIR__ . '/DatabaseUpgradesDependencies.php';
12 require_once __DIR__ . '/DatabaseUpgradeComponentRegistry.php';
13 require_once __DIR__ . '/DatabaseUpgradeNGram.php';
14 require_once __DIR__ . '/DatabaseUpgradeEngineNormalization.php';
15 require_once __DIR__ . '/DatabaseUpgradeCollationDrift.php';
16 require_once __DIR__ . '/DatabaseUpgradeSelfHeal.php';
17 require_once __DIR__ . '/DatabaseUpgradeCanonicalUrlBackfill.php';
18 require_once __DIR__ . '/DatabaseUpgradeDailyMaintenance.php';
19 require_once __DIR__ . '/DatabaseUpgradePluginUpdate.php';
20 require_once __DIR__ . '/DatabaseUpgradeTableRepair.php';
21 require_once __DIR__ . '/DatabaseUpgradeIndexes.php';
22 require_once __DIR__ . '/DatabaseUpgradeOrphanAdoption.php';
23 require_once __DIR__ . '/DatabaseUpgradeMultiSite.php';
24 require_once __DIR__ . '/DatabaseUpgradeSchemaDiff.php';
25 require_once __DIR__ . '/DatabaseUpgradeBootstrap.php';
26
27 /**
28 * Public entry point for the database-upgrade subsystem.
29 *
30 * This is a thin facade: it owns the component registry and the shared
31 * dependency map, and hands callers the registry through {@see self::components()}.
32 * All upgrade operations live on the 13 component classes (reached via the
33 * registry's typed accessors); all runtime-state values live on
34 * {@see ABJ_404_Solution_DatabaseUpgradeRuntimeState}. Callers run an operation
35 * with, for example:
36 *
37 * ABJ_404_Solution_DatabaseUpgradesEtc::getInstance()
38 * ->components()->bootstrapUpgrade()->createDatabaseTables();
39 *
40 * `components()` refreshes the dependency map before returning the registry, so
41 * every component access sees the current collaborators (this preserves the old
42 * per-operation "refresh then delegate" behavior in a single place).
43 */
44 class ABJ_404_Solution_DatabaseUpgradesEtc {
45
46 /** @var self|null */
47 private static $instance = null;
48
49 /** @var ABJ_404_Solution_DataAccess */
50 private $dao;
51
52 /** @var ABJ_404_Solution_DatabaseCore */
53 private $dbCore;
54
55 /** @var ABJ_404_Solution_ContentRepositoryInterface */
56 private $contentRepo;
57
58 /** @var ABJ_404_Solution_ViewReadServiceInterface */
59 private $viewRead;
60
61 /** @var ABJ_404_Solution_LogsRepositoryInterface */
62 private $logsRepo;
63
64 /** @var ABJ_404_Solution_Logging */
65 private $logger;
66
67 /** @var ABJ_404_Solution_Functions */
68 private $f;
69
70 /** @var ABJ_404_Solution_PermalinkCache */
71 private $permalinkCache;
72
73 /** @var ABJ_404_Solution_SynchronizationUtils */
74 private $syncUtils;
75
76 /** @var ABJ_404_Solution_PluginLogicInterface */
77 private $logic;
78
79 /** @var ABJ_404_Solution_NGramFilter */
80 private $ngramFilter;
81
82 /** @var mixed */
83 private $ngramExtractor;
84
85 /** @var mixed */
86 private $ngramCacheRepository;
87
88 /** @var mixed */
89 private $ngramCoveragePolicy;
90
91 /** @var mixed */
92 private $ngramRebuilder;
93
94 /** @var ABJ_404_Solution_CronScheduler|null */
95 private $cronScheduler;
96
97 /** @var ABJ_404_Solution_DatabaseUpgradeComponentRegistry */
98 private $components;
99
100 /**
101 * Constructor with dependency injection.
102 *
103 * @param ABJ_404_Solution_DatabaseUpgradesDependencies|null $dependencies Upgrade facade collaborators.
104 */
105 public function __construct(?ABJ_404_Solution_DatabaseUpgradesDependencies $dependencies = null) {
106 $dependencies = $dependencies !== null ? $dependencies : new ABJ_404_Solution_DatabaseUpgradesDependencies();
107
108 $this->dao = $dependencies->getDataAccess();
109 $this->logger = $dependencies->getLogging();
110 $this->f = $dependencies->getFunctions();
111 $this->permalinkCache = $dependencies->getPermalinkCache();
112 $this->syncUtils = $dependencies->getSyncUtils();
113 $this->logic = $dependencies->getPluginLogic();
114 $this->ngramFilter = $dependencies->getNGramFilter();
115 $this->ngramExtractor = $dependencies->getNGramExtractor();
116 $this->ngramCacheRepository = $dependencies->getNGramCacheRepository();
117 $this->ngramCoveragePolicy = $dependencies->getNGramCoveragePolicy();
118 $this->ngramRebuilder = $dependencies->getNGramRebuilder();
119 $this->cronScheduler = $dependencies->getCronScheduler();
120
121 $this->dbCore = $this->dao->getDbCore();
122 $this->contentRepo = $this->dao->getContentRepo();
123 $this->viewRead = $this->dao->getViewReadService();
124 $this->logsRepo = $this->dao->getLogsRepo();
125
126 $this->components = new ABJ_404_Solution_DatabaseUpgradeComponentRegistry($this->buildComponentDependencyMap());
127 }
128
129 /**
130 * Return the current singleton instance without consulting the container
131 * or building a new one. Mirrors the peekInstance pattern on
132 * PluginLogic / Logging / DataAccess so abj_service() can honor a
133 * caller-installed singleton override.
134 *
135 * @return self|null
136 */
137 public static function peekInstance() {
138 return self::$instance;
139 }
140
141 /**
142 * Install a singleton instance directly. Symmetric with `peekInstance()`;
143 * the canonical seam for tests that need to swap in a test double, and
144 * for callers that have already constructed a fully configured instance.
145 * Pass `null` to clear the cached singleton.
146 *
147 * @param self|null $instance
148 * @return void
149 */
150 public static function setInstance($instance) {
151 self::$instance = $instance;
152 }
153
154 /** @return self */
155 public static function getInstance() {
156 if (self::$instance == null) {
157 self::$instance = new ABJ_404_Solution_DatabaseUpgradesEtc();
158 ABJ_404_Solution_DatabaseUpgradeRuntimeState::initializeRuntimeId();
159 }
160
161 return self::$instance;
162 }
163
164 /**
165 * Refresh component dependencies, then return the component registry.
166 *
167 * This is the single public seam external callers use to reach an upgrade
168 * component. Refreshing here means every component access sees the current
169 * collaborators (e.g. after a test swaps in a mock DataAccess), which
170 * preserves the behavior of the former per-operation refresh-then-delegate
171 * methods in one place.
172 *
173 * @return ABJ_404_Solution_DatabaseUpgradeComponentRegistry
174 */
175 public function components(): ABJ_404_Solution_DatabaseUpgradeComponentRegistry {
176 $this->refreshUpgradeComponentDependencies();
177 return $this->components;
178 }
179
180 // -------------------------------------------------------------------------
181 // Lifecycle entry points.
182 //
183 // These are the facade's concrete public API: the operations the rest of the
184 // plugin (boot, cron, activation, retention) invokes. Each delegates to the
185 // component that owns the work. They are intentionally explicit methods (not
186 // a __call bridge or string registry) and their presence is enforced by
187 // DatabaseUpgradeCompositionGateTest::testProductionLifecycleMethodsAreConcreteFacadeMethods.
188 // Non-lifecycle component operations are reached through components().
189 // -------------------------------------------------------------------------
190
191 /**
192 * @param bool $updatingToNewVersion
193 * @return void
194 */
195 public function createDatabaseTables($updatingToNewVersion = false) {
196 $this->components()->bootstrapUpgrade()->createDatabaseTables($updatingToNewVersion);
197 }
198
199 /** @return void */
200 public function correctCollations() {
201 $this->components()->collationDriftUpgrade()->correctCollations();
202 }
203
204 /** @return void */
205 public function runSelfHealPrologue() {
206 $this->components()->selfHealUpgrade()->runSelfHealPrologue();
207 }
208
209 /**
210 * Bounded, never-throwing missing-table repair for a user-facing request.
211 *
212 * @return void
213 */
214 public function repairMissingTablesForRequest() {
215 $this->components()->selfHealUpgrade()->repairMissingTablesForRequest();
216 }
217
218 /** @return void */
219 public function runDatabaseMaintenanceTasks() {
220 $this->components()->dailyMaintenanceUpgrade()->runDatabaseMaintenanceTasks();
221 }
222
223 /** @return void */
224 public function updatePluginCheck() {
225 $this->components()->pluginUpdateUpgrade()->updatePluginCheck();
226 }
227
228 /** @return mixed */
229 public function scheduleNGramCacheRebuild() {
230 return $this->components()->nGramUpgrade()->scheduleNGramCacheRebuild();
231 }
232
233 /**
234 * @param int $offset
235 * @return void
236 */
237 public function rebuildNGramCacheAsync($offset = 0) {
238 $this->components()->nGramUpgrade()->rebuildNGramCacheAsync($offset);
239 }
240
241 /** @return bool */
242 public function processMultisiteActivationBatch(): bool {
243 return $this->components()->multiSiteUpgrade()->processMultisiteActivationBatch();
244 }
245
246 /** @return bool */
247 public function processMultisiteUpgradeBatch(): bool {
248 return $this->components()->multiSiteUpgrade()->processMultisiteUpgradeBatch();
249 }
250
251 /** @return int */
252 public function backfillLogsv2CanonicalUrl(): int {
253 return $this->components()->canonicalUrlBackfillUpgrade()->backfillLogsv2CanonicalUrl();
254 }
255
256 /**
257 * @return array<string, mixed>
258 */
259 private function buildComponentDependencyMap(): array {
260 return [
261 'dao' => $this->dao,
262 'dbCore' => $this->dbCore,
263 'contentRepo' => $this->contentRepo,
264 'viewRead' => $this->viewRead,
265 'logsRepo' => $this->logsRepo,
266 'logger' => $this->logger,
267 'f' => $this->f,
268 'permalinkCache' => $this->permalinkCache,
269 'syncUtils' => $this->syncUtils,
270 'logic' => $this->logic,
271 'ngramFilter' => $this->ngramFilter,
272 'ngramExtractor' => $this->ngramExtractor,
273 'ngramCacheRepository' => $this->ngramCacheRepository,
274 'ngramCoveragePolicy' => $this->ngramCoveragePolicy,
275 'ngramRebuilder' => $this->ngramRebuilder,
276 'cronScheduler' => $this->cronScheduler,
277 ];
278 }
279
280 /**
281 * Rebuild the dependency map from the facade's current collaborators and
282 * push it to every component. Called by {@see self::components()} on each
283 * access; also a public seam tests use to re-sync components after swapping
284 * the DAO on the facade.
285 *
286 * @return void
287 */
288 public function refreshUpgradeComponentDependencies(): void {
289 $this->components->refreshDependencies($this->buildComponentDependencyMap());
290 }
291 }
292