PluginProbe
404 Solution / 4.1.19
404 Solution v4.1.19
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.1.19, at includes/bootstrap.php

371 lines 12.5 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 * Initialize all services in the dependency injection container.
17 *
18 * Services are registered with factory functions that define their dependencies.
19 * The container handles lazy instantiation and ensures each service is a singleton.
20 *
21 * @return void
22 */
23 function abj_404_solution_init_services() {
24 $container = ABJ_404_Solution_ServiceContainer::getInstance();
25
26 // =========================================================================
27 // Core Utilities (no dependencies)
28 // =========================================================================
29
30 /**
31 * Functions service - provides string manipulation and utility methods.
32 * Auto-selects between mbstring and preg implementations.
33 */
34 $container->set('functions', function($c) {
35 if (extension_loaded('mbstring')) {
36 return new ABJ_404_Solution_FunctionsMBString();
37 }
38 return new ABJ_404_Solution_FunctionsPreg();
39 });
40
41 /**
42 * Logging service - handles debug logging and error reporting.
43 */
44 $container->set('logging', function($c) {
45 return ABJ_404_Solution_Logging::createForContainer();
46 });
47
48 /**
49 * Clock service - injectable wall-clock so cooldown/rate-limit/cron-window
50 * code can be tested with a frozen virtual time. Production binds
51 * `SystemClock` (delegates to `time()` etc.); tests bind `FrozenClock`.
52 * See `docs/clock-injection-audit.md`.
53 */
54 $container->set('clock', function($c) {
55 return new ABJ_404_Solution_SystemClock();
56 });
57
58 /**
59 * Error handler service - manages error handling and reporting.
60 */
61 $container->set('error_handler', function($c) {
62 // Error handler is static; return class name for callers that want a handle.
63 return 'ABJ_404_Solution_ErrorHandler';
64 });
65
66 // =========================================================================
67 // Data Layer
68 // =========================================================================
69
70 /**
71 * Data access service - handles all database operations.
72 * Dependencies: functions, logging
73 */
74 $container->set('data_access', function($c) {
75 return new ABJ_404_Solution_DataAccess(
76 $c->get('functions'),
77 $c->get('logging')
78 );
79 });
80
81 /**
82 * Database upgrades - handles schema migrations and upgrades.
83 * Dependencies: data_access, logging, functions, permalink_cache, sync_utils, plugin_logic, ngram_filter
84 */
85 $container->set('database_upgrades', function($c) {
86 return new ABJ_404_Solution_DatabaseUpgradesEtc(
87 $c->get('data_access'),
88 $c->get('logging'),
89 $c->get('functions'),
90 $c->get('permalink_cache'),
91 $c->get('sync_utils'),
92 $c->get('plugin_logic'),
93 $c->get('ngram_filter')
94 );
95 });
96
97 /**
98 * Permalink cache - caches permalink lookups for performance.
99 * Dependencies: data_access, logging, plugin_logic
100 */
101 $container->set('permalink_cache', function($c) {
102 return new ABJ_404_Solution_PermalinkCache(
103 $c->get('data_access'),
104 $c->get('logging'),
105 $c->get('plugin_logic')
106 );
107 });
108
109 /**
110 * N-gram filter - provides N-gram based spell checker optimization.
111 * Dependencies: data_access, logging, functions
112 */
113 $container->set('ngram_filter', function($c) {
114 return new ABJ_404_Solution_NGramFilter(
115 $c->get('data_access'),
116 $c->get('logging'),
117 $c->get('functions')
118 );
119 });
120
121 // =========================================================================
122 // Business Logic Layer
123 // =========================================================================
124
125 /**
126 * Plugin logic service - core business logic and coordination.
127 * Dependencies: functions, data_access, logging
128 */
129 $container->set('plugin_logic', function($c) {
130 return new ABJ_404_Solution_PluginLogic(
131 $c->get('functions'),
132 $c->get('data_access'),
133 $c->get('logging')
134 );
135 });
136
137 /**
138 * Spell checker service - handles URL matching and suggestions.
139 * Dependencies: functions, plugin_logic, data_access, logging, permalink_cache, ngram_filter
140 */
141 $container->set('spell_checker', function($c) {
142 return new ABJ_404_Solution_SpellChecker(
143 $c->get('functions'),
144 $c->get('plugin_logic'),
145 $c->get('data_access'),
146 $c->get('logging'),
147 $c->get('permalink_cache'),
148 $c->get('ngram_filter')
149 );
150 });
151
152 // =========================================================================
153 // Matching Engines
154 // =========================================================================
155
156 /**
157 * Slug matching engine - exact slug lookup via SpellChecker.
158 * Dependencies: spell_checker
159 */
160 $container->set('engine_slug', function($c) {
161 return new ABJ_404_Solution_SlugMatchingEngine($c->get('spell_checker'));
162 });
163
164 /**
165 * URL fix engine - strips file extensions and trailing punctuation, then
166 * checks if the cleaned slug resolves to a real page.
167 * Dependencies: spell_checker, functions, logging
168 */
169 $container->set('engine_url_fix', function($c) {
170 return new ABJ_404_Solution_UrlFixEngine(
171 $c->get('spell_checker'),
172 $c->get('functions'),
173 $c->get('logging')
174 );
175 });
176
177 /**
178 * Title matching engine - keyword overlap between URL slug and post titles.
179 * Dependencies: data_access, functions, logging
180 */
181 $container->set('engine_title', function($c) {
182 return new ABJ_404_Solution_TitleMatchingEngine(
183 $c->get('data_access'),
184 $c->get('functions'),
185 $c->get('logging')
186 );
187 });
188
189 /**
190 * Category/tag matching engine - hierarchical path resolution and taxonomy keyword matching.
191 * Dependencies: data_access, functions, logging
192 */
193 $container->set('engine_category_tag', function($c) {
194 return new ABJ_404_Solution_CategoryTagMatchingEngine(
195 $c->get('data_access'),
196 $c->get('functions'),
197 $c->get('logging')
198 );
199 });
200
201 /**
202 * Content matching engine - keyword overlap between URL slug and post content.
203 * Dependencies: data_access, functions, logging
204 */
205 $container->set('engine_content', function($c) {
206 return new ABJ_404_Solution_ContentMatchingEngine(
207 $c->get('data_access'),
208 $c->get('functions'),
209 $c->get('logging')
210 );
211 });
212
213 /**
214 * Spelling matching engine - Levenshtein/N-gram matching via SpellChecker.
215 * Dependencies: spell_checker
216 */
217 $container->set('engine_spelling', function($c) {
218 return new ABJ_404_Solution_SpellingMatchingEngine($c->get('spell_checker'));
219 });
220
221 /**
222 * Archive fallback engine - redirects to post type archive pages.
223 * Dependencies: functions, logging
224 */
225 $container->set('engine_archive_fallback', function($c) {
226 return new ABJ_404_Solution_ArchiveFallbackEngine(
227 $c->get('functions'),
228 $c->get('logging')
229 );
230 });
231
232 /**
233 * Ordered list of matching engines for the frontend pipeline.
234 * Filterable via 'abj404_matching_engines' to add/remove/reorder engines.
235 */
236 $container->set('matching_engines', function($c) {
237 $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')];
238 if (function_exists('apply_filters')) {
239 $filtered = apply_filters('abj404_matching_engines', $engines);
240 $engines = is_array($filtered) ? $filtered : [];
241 }
242 return $engines;
243 });
244
245 /**
246 * WordPress connector - interfaces with WordPress core APIs.
247 * Dependencies: plugin_logic, data_access, logging, functions, spell_checker
248 */
249 $container->set('wordpress_connector', function($c) {
250 return new ABJ_404_Solution_WordPress_Connector(
251 $c->get('plugin_logic'),
252 $c->get('data_access'),
253 $c->get('logging'),
254 $c->get('functions'),
255 $c->get('spell_checker')
256 );
257 });
258
259 /**
260 * Slug change handler - detects and handles post slug changes.
261 */
262 $container->set('slug_change_handler', function($c) {
263 return new ABJ_404_Solution_SlugChangeHandler();
264 });
265
266 /**
267 * Published posts provider - manages published post lookups.
268 */
269 $container->set('published_posts_provider', function($c) {
270 return new ABJ_404_Solution_PublishedPostsProvider();
271 });
272
273 /**
274 * Synchronization utilities - handles data synchronization.
275 */
276 $container->set('sync_utils', function($c) {
277 return new ABJ_404_Solution_SynchronizationUtils();
278 });
279
280 /**
281 * Request context - request-scoped state holder (debug breadcrumbs,
282 * permalink cache, ignore flags). Replaces $_REQUEST[ABJ404_PP] as an
283 * intra-request message bus. Container scope guarantees one instance
284 * per PHP request, matching legacy `getInstance()` semantics.
285 */
286 $container->set('request_context', function($c) {
287 return ABJ_404_Solution_RequestContext::getInstance();
288 });
289
290 // =========================================================================
291 // Presentation Layer
292 // =========================================================================
293
294 /**
295 * View service - renders admin pages and UI components.
296 * Dependencies: functions, plugin_logic, data_access, logging
297 */
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('data_access'),
303 $c->get('logging')
304 );
305 });
306
307 /**
308 * View suggestions - renders suggestion UI components.
309 * Dependencies: functions
310 */
311 $container->set('view_suggestions', function($c) {
312 return new ABJ_404_Solution_View_Suggestions(
313 $c->get('functions')
314 );
315 });
316
317 /**
318 * Shortcode handler - processes WordPress shortcodes.
319 */
320 $container->set('shortcode', function($c) {
321 return new ABJ_404_Solution_ShortCode();
322 });
323 }
324
325 /**
326 * Backward compatibility function for accessing services.
327 *
328 * This allows existing code to continue working while we migrate
329 * to the container pattern. Eventually this can be removed.
330 *
331 * @param string $className The class name to get an instance of
332 * @return mixed The service instance
333 */
334 function abj_get_instance($className) {
335 $container = ABJ_404_Solution_ServiceContainer::getInstance();
336
337 // Map class names to service names
338 $serviceMap = array(
339 'ABJ_404_Solution_Functions' => 'functions',
340 'ABJ_404_Solution_Logging' => 'logging',
341 'ABJ_404_Solution_DataAccess' => 'data_access',
342 'ABJ_404_Solution_PluginLogic' => 'plugin_logic',
343 'ABJ_404_Solution_View' => 'view',
344 'ABJ_404_Solution_SpellChecker' => 'spell_checker',
345 'ABJ_404_Solution_WordPress_Connector' => 'wordpress_connector',
346 // Error handler is static; no instance.
347 'ABJ_404_Solution_DatabaseUpgradesEtc' => 'database_upgrades',
348 'ABJ_404_Solution_PermalinkCache' => 'permalink_cache',
349 'ABJ_404_Solution_NGramFilter' => 'ngram_filter',
350 'ABJ_404_Solution_SlugChangeHandler' => 'slug_change_handler',
351 'ABJ_404_Solution_PublishedPostsProvider' => 'published_posts_provider',
352 'ABJ_404_Solution_SynchronizationUtils' => 'sync_utils',
353 'ABJ_404_Solution_View_Suggestions' => 'view_suggestions',
354 'ABJ_404_Solution_ShortCode' => 'shortcode',
355 'ABJ_404_Solution_RequestContext' => 'request_context',
356 );
357
358 if (isset($serviceMap[$className])) {
359 return $container->get($serviceMap[$className]);
360 }
361
362 // Fallback to calling the class's getInstance() method
363 if (method_exists($className, 'getInstance')) {
364 /** @var callable(): mixed $callback */
365 $callback = array($className, 'getInstance');
366 return call_user_func($callback);
367 }
368
369 throw new Exception("Cannot get instance of class: $className");
370 }
371