PluginProbe
404 Solution / 4.2.0
404 Solution v4.2.0
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 / bootstrap.php

bootstrap.php in 404 Solution 4.2.0, at includes/bootstrap.php

364 lines 13.1 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 /**
9 * Bootstrap file for initializing the service container and registering services.
10 *
11 * This file sets up dependency injection for the plugin's core services,
12 * making dependencies explicit and testable.
13 */
14
15 /**
16 * Build the view-read service from the common DAO module dependencies.
17 *
18 * @param ABJ_404_Solution_ServiceContainer $container
19 * @param callable $daoModuleDeps
20 * @return ABJ_404_Solution_ViewReadService
21 */
22 function abj_404_solution_create_view_read_service($container, $daoModuleDeps) {
23 /** @var array{0: ABJ_404_Solution_DatabaseCore, 1: ABJ_404_Solution_Functions, 2: ABJ_404_Solution_Logging} $d */
24 $d = $daoModuleDeps($container);
25 /** @var ABJ_404_Solution_LogsRepository $logsRepository */
26 $logsRepository = $container->get('logs_repository');
27 /** @var ABJ_404_Solution_RedirectsRepository $redirectsRepository */
28 $redirectsRepository = $container->get('redirects_repository');
29 return new ABJ_404_Solution_ViewReadService(
30 $d[0], $logsRepository, $redirectsRepository, $d[1], $d[2]
31 );
32 }
33
34 /**
35 * Build and wire the view-build orchestrator service.
36 *
37 * @param ABJ_404_Solution_ServiceContainer $container
38 * @return ABJ_404_Solution_ViewBuildOrchestrator
39 */
40 function abj_404_solution_create_view_build_orchestrator($container) {
41 /** @var ABJ_404_Solution_DatabaseCore $dbCore */
42 $dbCore = $container->get('db_core');
43 /** @var ABJ_404_Solution_Functions $functions */
44 $functions = $container->get('functions');
45 /** @var ABJ_404_Solution_Logging $logging */
46 $logging = $container->get('logging');
47 /** @var ABJ_404_Solution_ViewReadService $viewReadService */
48 $viewReadService = $container->get('view_read_service');
49 /** @var ABJ_404_Solution_LogsRepository $logsRepository */
50 $logsRepository = $container->get('logs_repository');
51 $rebuildHealth = $container->get('rebuild_health');
52 $svc = new ABJ_404_Solution_ViewBuildOrchestrator(
53 $dbCore,
54 $functions,
55 $logging,
56 $rebuildHealth instanceof ABJ_404_Solution_RebuildHealthState ? $rebuildHealth : null
57 );
58 $svc->setViewReadService($viewReadService);
59 $svc->setLogsRepository($logsRepository);
60 $viewReadService->setViewBuildOrchestrator($svc);
61 return $svc;
62 }
63
64 /**
65 * Initialize all services in the dependency injection container.
66 *
67 * Services are registered with factory functions that define their dependencies.
68 * The container handles lazy instantiation and ensures each service is a singleton.
69 *
70 * @return void
71 */
72 function abj_404_solution_init_services() {
73 $container = ABJ_404_Solution_ServiceContainer::getInstance();
74
75 abj_404_solution_register_core_utilities($container);
76 abj_404_solution_register_data_layer($container);
77 abj_404_solution_register_business_logic($container);
78 abj_404_solution_register_matching_engines($container);
79 abj_404_solution_register_frontend_services($container);
80 abj_404_solution_register_presentation_layer($container);
81 }
82
83 /**
84 * @param ABJ_404_Solution_ServiceContainer $container
85 * @return void
86 */
87 function abj_404_solution_register_core_utilities($container) {
88 $container->set('functions', function($c) {
89 if (extension_loaded('mbstring')) {
90 return new ABJ_404_Solution_FunctionsMBString();
91 }
92 return new ABJ_404_Solution_FunctionsPreg();
93 });
94
95 $container->set('pii_redactor', function($c) {
96 return new ABJ_404_Solution_PiiRedactor($c->get('functions'));
97 });
98
99 $container->set('logging', function($c) {
100 return ABJ_404_Solution_Logging::createForContainer();
101 });
102
103 $container->set('clock', function($c) {
104 return new ABJ_404_Solution_SystemClock();
105 });
106
107 $container->set('rebuild_health', function($c) {
108 return new ABJ_404_Solution_RebuildHealthState(
109 $c->get('clock'),
110 $c->get('logging')
111 );
112 });
113
114 $container->set('error_handler', function($c) {
115 return 'ABJ_404_Solution_ErrorHandler';
116 });
117 }
118
119 /**
120 * @param ABJ_404_Solution_ServiceContainer $container
121 * @return void
122 */
123 function abj_404_solution_register_data_layer($container) {
124 $container->set('db_core', function($c) {
125 return new ABJ_404_Solution_DatabaseCore(
126 $c->get('functions'),
127 $c->get('logging')
128 );
129 });
130
131 $daoModuleDeps = function($c) { return [$c->get('db_core'), $c->get('functions'), $c->get('logging')]; };
132 $container->set('content_repository', function($c) use ($daoModuleDeps) {
133 return new ABJ_404_Solution_ContentRepository(...$daoModuleDeps($c));
134 });
135 $container->set('redirects_repository', function($c) use ($daoModuleDeps) {
136 return new ABJ_404_Solution_RedirectsRepository(...$daoModuleDeps($c));
137 });
138 $container->set('logs_repository', function($c) {
139 return new ABJ_404_Solution_LogsRepository(
140 $c->get('db_core'),
141 $c->get('functions'),
142 $c->get('logging'),
143 $c->get('rebuild_health')
144 );
145 });
146 $container->set('stats_repository', function($c) {
147 return new ABJ_404_Solution_StatsRepository(
148 $c->get('db_core'), $c->get('logs_repository'),
149 $c->get('functions'), $c->get('logging')
150 );
151 });
152 $container->set('view_read_service', function($c) use ($daoModuleDeps) { return abj_404_solution_create_view_read_service($c, $daoModuleDeps); });
153 $container->set('view_build_orchestrator', function($c) { return abj_404_solution_create_view_build_orchestrator($c); });
154 $container->set('data_access', function($c) {
155 return new ABJ_404_Solution_DataAccess($c->get('functions'), $c->get('logging'), $c->get('db_core'),
156 $c->get('content_repository'), $c->get('redirects_repository'),
157 $c->get('logs_repository'), $c->get('stats_repository'), $c->get('view_read_service'), $c->get('view_build_orchestrator'));
158 });
159
160 $container->set('database_upgrades', function($c) {
161 return new ABJ_404_Solution_DatabaseUpgradesEtc(
162 $c->get('data_access'),
163 $c->get('logging'),
164 $c->get('functions'),
165 $c->get('permalink_cache'),
166 $c->get('sync_utils'),
167 $c->get('plugin_logic'),
168 $c->get('ngram_filter')
169 );
170 });
171
172 $container->set('permalink_cache', function($c) {
173 return new ABJ_404_Solution_PermalinkCache($c->get('content_repository'),
174 $c->get('logging'), $c->get('plugin_logic'), $c->get('stats_repository'));
175 });
176
177 $container->set('ngram_filter', function($c) {
178 return new ABJ_404_Solution_NGramFilter($c->get('db_core'), $c->get('logging'), $c->get('functions'));
179 });
180 }
181
182 /**
183 * @param ABJ_404_Solution_ServiceContainer $container
184 * @return void
185 */
186 function abj_404_solution_register_business_logic($container) {
187 $container->set('plugin_logic', function($c) {
188 return new ABJ_404_Solution_PluginLogic(
189 $c->get('functions'),
190 $c->get('data_access'),
191 $c->get('logging')
192 );
193 });
194
195 $container->set('spell_checker', function($c) {
196 return new ABJ_404_Solution_SpellChecker($c->get('functions'), $c->get('plugin_logic'),
197 $c->get('content_repository'), $c->get('logging'), $c->get('permalink_cache'),
198 $c->get('ngram_filter'), $c->get('view_read_service'));
199 });
200 }
201
202 /**
203 * @param ABJ_404_Solution_ServiceContainer $container
204 * @return void
205 */
206 function abj_404_solution_register_matching_engines($container) {
207 $container->set('engine_slug', function($c) {
208 return new ABJ_404_Solution_SlugMatchingEngine($c->get('spell_checker'));
209 });
210
211 $container->set('engine_url_fix', function($c) {
212 return new ABJ_404_Solution_UrlFixEngine(
213 $c->get('spell_checker'),
214 $c->get('functions'),
215 $c->get('logging')
216 );
217 });
218
219 $container->set('engine_title', function($c) {
220 return new ABJ_404_Solution_TitleMatchingEngine(
221 $c->get('content_repository'),
222 $c->get('functions'),
223 $c->get('logging')
224 );
225 });
226
227 $container->set('engine_category_tag', function($c) {
228 return new ABJ_404_Solution_CategoryTagMatchingEngine(
229 $c->get('content_repository'),
230 $c->get('functions'),
231 $c->get('logging')
232 );
233 });
234
235 $container->set('engine_content', function($c) {
236 return new ABJ_404_Solution_ContentMatchingEngine(
237 $c->get('content_repository'),
238 $c->get('functions'),
239 $c->get('logging')
240 );
241 });
242
243 $container->set('engine_spelling', function($c) {
244 return new ABJ_404_Solution_SpellingMatchingEngine($c->get('spell_checker'));
245 });
246
247 $container->set('engine_archive_fallback', function($c) {
248 return new ABJ_404_Solution_ArchiveFallbackEngine(
249 $c->get('functions'),
250 $c->get('logging')
251 );
252 });
253
254 $container->set('matching_engines', function($c) {
255 $engines = [$c->get('engine_slug'), $c->get('engine_url_fix'), $c->get('engine_title'), $c->get('engine_category_tag'), $c->get('engine_content'), $c->get('engine_spelling'), $c->get('engine_archive_fallback')];
256 if (function_exists('apply_filters')) {
257 $filtered = apply_filters('abj404_matching_engines', $engines);
258 $engines = is_array($filtered) ? $filtered : [];
259 }
260 return $engines;
261 });
262 }
263
264 /**
265 * @param ABJ_404_Solution_ServiceContainer $container
266 * @return void
267 */
268 function abj_404_solution_register_frontend_services($container) {
269 $container->set('wordpress_connector', function($c) {
270 return new ABJ_404_Solution_WordPress_Connector($c->get('plugin_logic'),
271 $c->get('redirects_repository'), $c->get('logging'), $c->get('functions'),
272 $c->get('spell_checker'), $c->get('logs_repository'), $c->get('stats_repository'));
273 });
274
275 $container->set('slug_change_handler', function($c) {
276 return new ABJ_404_Solution_SlugChangeHandler($c->get('content_repository'),
277 $c->get('redirects_repository'), $c->get('logging'), $c->get('plugin_logic'));
278 });
279
280 $container->set('published_posts_provider', function($c) {
281 return new ABJ_404_Solution_PublishedPostsProvider($c->get('content_repository'));
282 });
283
284 $container->set('sync_utils', function($c) {
285 return new ABJ_404_Solution_SynchronizationUtils();
286 });
287
288 $container->set('request_context', function($c) {
289 return ABJ_404_Solution_RequestContext::getInstance();
290 });
291 }
292
293 /**
294 * @param ABJ_404_Solution_ServiceContainer $container
295 * @return void
296 */
297 function abj_404_solution_register_presentation_layer($container) {
298 $container->set('view', function($c) {
299 return new ABJ_404_Solution_View(
300 $c->get('functions'),
301 $c->get('plugin_logic'),
302 $c->get('view_read_service'),
303 $c->get('logging')
304 );
305 });
306
307 $container->set('view_suggestions', function($c) {
308 return new ABJ_404_Solution_View_Suggestions(
309 $c->get('functions')
310 );
311 });
312
313 $container->set('shortcode', function($c) {
314 return new ABJ_404_Solution_ShortCode();
315 });
316 }
317
318 /**
319 * Backward compatibility function for accessing services.
320 *
321 * This allows existing code to continue working while we migrate
322 * to the container pattern. Eventually this can be removed.
323 *
324 * @param string $className The class name to get an instance of
325 * @return mixed The service instance
326 */
327 function abj_get_instance($className) {
328 $container = ABJ_404_Solution_ServiceContainer::getInstance();
329
330 // Map class names to service names
331 $serviceMap = array(
332 'ABJ_404_Solution_Functions' => 'functions',
333 'ABJ_404_Solution_Logging' => 'logging',
334 'ABJ_404_Solution_DataAccess' => 'data_access',
335 'ABJ_404_Solution_PluginLogic' => 'plugin_logic',
336 'ABJ_404_Solution_View' => 'view',
337 'ABJ_404_Solution_SpellChecker' => 'spell_checker',
338 'ABJ_404_Solution_WordPress_Connector' => 'wordpress_connector',
339 // Error handler is static; no instance.
340 'ABJ_404_Solution_DatabaseUpgradesEtc' => 'database_upgrades',
341 'ABJ_404_Solution_PermalinkCache' => 'permalink_cache',
342 'ABJ_404_Solution_NGramFilter' => 'ngram_filter',
343 'ABJ_404_Solution_SlugChangeHandler' => 'slug_change_handler',
344 'ABJ_404_Solution_PublishedPostsProvider' => 'published_posts_provider',
345 'ABJ_404_Solution_SynchronizationUtils' => 'sync_utils',
346 'ABJ_404_Solution_View_Suggestions' => 'view_suggestions',
347 'ABJ_404_Solution_ShortCode' => 'shortcode',
348 'ABJ_404_Solution_RequestContext' => 'request_context',
349 );
350
351 if (isset($serviceMap[$className])) {
352 return $container->get($serviceMap[$className]);
353 }
354
355 // Fallback to calling the class's getInstance() method
356 if (method_exists($className, 'getInstance')) {
357 /** @var callable(): mixed $callback */
358 $callback = array($className, 'getInstance');
359 return call_user_func($callback);
360 }
361
362 throw new Exception("Cannot get instance of class: $className"); // allow-raw-error: pre-existing programmer assertion
363 }
364