PluginProbe
SureCookie – GDPR Cookie Consent Banner, Cookie Scanner & Script Blocking / trunk
SureCookie – GDPR Cookie Consent Banner, Cookie Scanner & Script Blocking vtrunk
1.5.0 1.4.0 1.3.0 1.3.1 trunk 0.0.0-alpha.1 0.0.0-alpha.2 0.0.0-alpha.3 0.0.1-beta.1 0.0.1-beta.2 0.0.1-beta.3 0.0.1-beta.4 1.0.0 1.1.0 1.2.0 1.2.1 1.2.2 1.2.3 1.2.4
surecookie / loader.php

loader.php in SureCookie – GDPR Cookie Consent Banner, Cookie Scanner & Script Blocking trunk, at loader.php

389 lines 10.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Plugin Loader.
4 *
5 * @package SureCookie
6 * @since 0.0.1
7 */
8
9 namespace SureCookie;
10
11 use SureCookie\Admin\Analytics;
12 use SureCookie\Admin\Menu;
13 use SureCookie\Admin\Onboarding;
14 use SureCookie\Admin\Post_States;
15 use SureCookie\Admin\Rating_Notice;
16 use SureCookie\Admin\Sync;
17 use SureCookie\Core\Frontend as Frontend_App;
18 use SureCookie\Core\Maintenance;
19 use SureCookie\Inc\API\Init as API_Initializer;
20 use SureCookie\Inc\Database\Init as DB_Initializer;
21 use SureCookie\Inc\Functions\Get;
22 use SureCookie\Inc\Integrations\Init as Integrations_Initializer;
23 use SureCookie\Inc\Integrations\Wordpress\Init as Wordpress_Abilities_Initializer;
24 use SureCookie\Inc\Modules\GoogleConsentMode\Actions as Gcm_Actions;
25 use SureCookie\Inc\Modules\Init as Modules_Initiator;
26 use SureCookie\Inc\Modules\Mcp\Init as Mcp_Initializer;
27 use SureCookie\Inc\Utils\Settings_Metadata;
28
29 // Exit if accessed directly.
30 defined( 'ABSPATH' ) || exit;
31
32 /**
33 * SureCookie_Loader
34 *
35 * Handles plugin initialization, autoloading, constants, and text domain loading.
36 *
37 * @since 0.0.1
38 */
39 class SureCookie_Loader {
40 /**
41 * Instance
42 *
43 * @access private
44 * @var SureCookie_Loader|null Class instance.
45 * @since 0.0.1
46 */
47 private static $instance = null;
48
49 /**
50 * Constructor.
51 *
52 * @since 0.0.1
53 */
54 public function __construct() {
55 // Define plugin constants.
56 $this->define_constants();
57
58 // Register autoloader.
59 spl_autoload_register( [ $this, 'autoload' ] );
60
61 add_action( 'plugins_loaded', [ $this, 'register_settings_dataset' ], 1 );
62 add_action( 'plugins_loaded', [ $this, 'load_routes' ] );
63
64 // Initialize plugin hooks.
65 add_action( 'init', [ $this, 'load_textdomain' ], 1 );
66 add_action( 'init', [ $this, 'load_plugin' ], 999 );
67 add_action( 'admin_init', [ $this, 'activation_redirect' ] );
68
69 // Site initialization.
70 add_action( 'wp_initialize_site', [ $this, 'initialize_new_site' ] );
71
72 // Activation hooks.
73 register_activation_hook( SURECOOKIE_FILE, [ $this, 'activation' ] );
74 register_deactivation_hook( SURECOOKIE_FILE, [ $this, 'deactivation' ] );
75
76 // Remove this after the translation error is fixed.
77 add_filter( 'doing_it_wrong_trigger_error', [ $this, 'suppress_translation_error' ], 10, 4 );
78
79 // Prevent Query Monitor from collecting the error.
80 add_action( 'doing_it_wrong_run', [ $this, 'prevent_qm_collection' ], 5, 3 );
81 }
82
83 /**
84 * Get instance
85 *
86 * @since 0.0.1
87 * @return SureCookie_Loader Instance of the class.
88 */
89 public static function get_instance() {
90 if ( self::$instance === null ) {
91 self::$instance = new self();
92 }
93 return self::$instance;
94 }
95
96 /**
97 * Prevent Query Monitor from collecting textdomain errors.
98 *
99 * @param string $function_name The function that was called.
100 * @param string $message The error message.
101 * @param string $version The version.
102 * @return void
103 * @since 1.0.0
104 */
105 public function prevent_qm_collection( $function_name, $message, $version ): void {
106 if ( $function_name === '_load_textdomain_just_in_time' && strpos( $message, 'surecookie' ) !== false ) {
107 // Remove Query Monitor's action temporarily.
108 if ( class_exists( '\QM_Collectors' ) ) {
109 $collector = \QM_Collectors::get( 'doing_it_wrong' );
110 if ( $collector ) {
111 remove_action( 'doing_it_wrong_run', [ $collector, 'action_doing_it_wrong_run' ], 10 );
112
113 // Re-add it after this specific error.
114 add_action(
115 'shutdown',
116 static function() use ( $collector ): void {
117 if ( ! has_action( 'doing_it_wrong_run', [ $collector, 'action_doing_it_wrong_run' ] ) ) {
118 add_action( 'doing_it_wrong_run', [ $collector, 'action_doing_it_wrong_run' ], 10, 3 );
119 }
120 },
121 -1
122 );
123 }
124 }
125 }
126 }
127
128 /**
129 * Suppress translation error.
130 *
131 * @param bool $status Status.
132 * @param string $function_name Function name.
133 * @param string $message Message.
134 * @param string $version Version.
135 *
136 * @return bool
137 * @since 1.0.0
138 */
139 public function suppress_translation_error( $status, $function_name, $message, $version ) {
140 if ( $function_name === '_load_textdomain_just_in_time' && strpos( $message, 'surecookie' ) !== false ) {
141 return false;
142 }
143 return $status;
144 }
145
146 /**
147 * Define plugin constants.
148 *
149 * @since 0.0.1
150 * @return void
151 */
152 public function define_constants(): void {
153 ! defined( 'SURECOOKIE_DEVELOPMENT_MODE' ) && define( 'SURECOOKIE_DEVELOPMENT_MODE', false );
154
155 $css_suffix = SURECOOKIE_DEVELOPMENT_MODE ? '.css' : '.min.css';
156 $js_suffix = SURECOOKIE_DEVELOPMENT_MODE ? '.js' : '.min.js';
157
158 define( 'SURECOOKIE_CSS_SUFFIX', $css_suffix );
159 define( 'SURECOOKIE_JS_SUFFIX', $js_suffix );
160 }
161
162 /**
163 * Autoload plugin classes.
164 *
165 * @param string $class Class name.
166 * @return void
167 */
168 public function autoload( $class ): void {
169 if ( strpos( $class, __NAMESPACE__ ) !== 0 ) {
170 return;
171 }
172
173 $class_to_load = $class;
174
175 $filename = preg_replace( // phpcs:ignore Generic.PHP.ForbiddenFunctions.FoundWithAlternative
176 [ '/^' . __NAMESPACE__ . '\\\/', '/([a-z])([A-Z])/', '/_/', '/\\\/' ],
177 [ '', '$1-$2', '-', DIRECTORY_SEPARATOR ],
178 $class_to_load
179 );
180
181 if ( is_string( $filename ) ) {
182 $filename = strtolower( $filename );
183
184 $file = SURECOOKIE_DIR . $filename . '.php';
185
186 // if the file readable, include it.
187 if ( is_readable( $file ) ) {
188 require_once $file;
189 }
190 }
191 }
192
193 /**
194 * Register settings-dataset contributions that must exist before init:20.
195 *
196 * The MCP adapter builds the abilities registry at init:20, which freezes
197 * manage-settings' input schema and primes the static cache in
198 * Settings::get_settings_defaults(). Modules boot at init:999, so a module
199 * that contributes setting keys registers that one filter here instead;
200 * registering it in the module would leave those keys unwritable over MCP
201 * and absent from the defaults for the rest of the request.
202 *
203 * @since 1.4.0
204 * @return void
205 */
206 public function register_settings_dataset(): void {
207 add_filter( 'surecookie_plugin_settings_dataset', [ Gcm_Actions::class, 'add_gcm_settings_to_dataset' ] );
208
209 // Priority 20 so every contributor has added its keys first; the
210 // annotator only touches keys that already exist.
211 add_filter( 'surecookie_plugin_settings_dataset', [ Settings_Metadata::class, 'merge' ], 20 );
212 }
213
214 /**
215 * Load routes.
216 *
217 * @since 0.0.1
218 * @return void
219 */
220 public function load_routes(): void {
221 do_action( 'surecookie_before_load_routes' );
222
223 /* Maintenance & API Initializer tasks */
224 Maintenance::get_instance();
225 API_Initializer::get_instance();
226
227 /*
228 * MCP + abilities must hook before init:20, where the MCP Adapter fires
229 * mcp_adapter_init under WP-CLI (modules/integrations auto-load too late
230 * at init:999). Singletons, so the later auto-discovery calls are no-ops.
231 */
232 Mcp_Initializer::get_instance();
233 if ( function_exists( 'wp_register_ability' ) ) {
234 Wordpress_Abilities_Initializer::get_instance();
235 }
236
237 /* BSF Analytics */
238 Analytics::get_instance();
239
240 do_action( 'surecookie_after_load_routes' );
241 }
242
243 /**
244 * Load plugin classes and initialize.
245 *
246 * @since 0.0.1
247 * @return void
248 */
249 public function load_plugin(): void {
250 do_action( 'surecookie_before_load_components' );
251
252 /* Site scanning sync processor */
253 Sync::get_instance();
254
255 /* Include all modules */
256 Modules_Initiator::get_instance();
257
258 /* Initialize third-party integrations (Abilities API, etc.) */
259 Integrations_Initializer::get_instance();
260
261 if ( is_admin() ) {
262 /* Admin menu */
263 Menu::get_instance();
264 Post_States::get_instance();
265 Onboarding::get_instance();
266 Rating_Notice::get_instance();
267 } else {
268 /* Public app */
269 Frontend_App::get_instance();
270 }
271
272 do_action( 'surecookie_after_load_components' );
273
274 /**
275 * SureCookie Init.
276 *
277 * Fires when SureCookie is instantiated.
278 *
279 * @since 0.0.1
280 */
281 do_action( 'surecookie_loaded' );
282 }
283
284 /**
285 * Load plugin textdomain.
286 *
287 * @since 1.0.0
288 * @return void
289 */
290 public function load_textdomain(): void {
291 // Registered before the catalog loads so the very first lookup can
292 // already fall back from a regional locale (de_CH) to the shipped
293 // base-language file (de_DE) - for free and Pro alike (issue #1034).
294 \SureCookie\Inc\Utils\Locale_Fallback::register();
295
296 load_plugin_textdomain( 'surecookie', false, dirname( SURECOOKIE_BASE ) . '/languages/' );
297 }
298
299 /**
300 * Check if we should redirect.
301 *
302 * @since 0.0.1
303 * @return void
304 */
305 public function activation_redirect(): void {
306 // Avoid redirection in case of WP_CLI calls.
307 if ( defined( 'WP_CLI' ) && \WP_CLI ) {
308 return;
309 }
310
311 // Avoid redirection in case of ajax calls.
312 if ( wp_doing_ajax() ) {
313 return;
314 }
315
316 // Check if we should redirect.
317 $do_redirect = get_option( 'surecookie_do_activation_redirect' );
318
319 if ( $do_redirect ) {
320 // Clear the redirect option so it doesn't happen again.
321 delete_option( 'surecookie_do_activation_redirect' );
322
323 // Make sure we're not in a multisite network.
324 if ( ! is_multisite() ) {
325 $is_onboarding_completed = (bool) Get::option( SURECOOKIE_ONBOARDING_COMPLETED_OPTION, false );
326
327 // Always redirect to onboarding for fresh activations, dashboard if onboarding is completed.
328 $redirect_url = $is_onboarding_completed ? admin_url( 'admin.php?page=surecookie' ) : admin_url( 'admin.php?page=surecookie-onboarding' );
329
330 wp_safe_redirect( $redirect_url );
331 exit;
332 }
333 }
334 }
335
336 /**
337 * Initialize database tables when a new site is created in multisite.
338 *
339 * @param \WP_Site $site The new site's object.
340 * @since 0.0.1
341 * @return void
342 */
343 public function initialize_new_site( $site ): void {
344 DB_Initializer::initialize_new_site( $site );
345 }
346
347 /**
348 * Activation trigger.
349 *
350 * @since 0.0.1
351 * @return void
352 */
353 public function activation(): void {
354 update_option( 'surecookie_do_activation_redirect', true );
355 if ( get_option( 'surecookie_usage_installed_time', false ) === false ) {
356 add_option( 'surecookie_usage_installed_time', time(), '', false );
357 }
358 DB_Initializer::create_db_tables();
359 Maintenance::store_db_version();
360
361 // Warm the remote datasets shortly after activation (off-request) so the
362 // blocking + declared-cookie catalogs are current without waiting for the
363 // first daily cron tick. Bundled floors cover the interim.
364 if ( ! wp_next_scheduled( 'surecookie_refresh_datasets' ) ) {
365 wp_schedule_single_event( time() + MINUTE_IN_SECONDS, 'surecookie_refresh_datasets' );
366 }
367 }
368
369 /**
370 * Deactivation trigger.
371 *
372 * @since 0.0.1
373 * @return void
374 */
375 public function deactivation(): void {
376 wp_clear_scheduled_hook( 'surecookie_cleanup_consent_logs' );
377 wp_clear_scheduled_hook( 'surecookie_poll_scan_status' );
378 wp_clear_scheduled_hook( 'surecookie_auto_scan_run' );
379 wp_clear_scheduled_hook( 'surecookie_auto_scan_retry' );
380 wp_clear_scheduled_hook( 'surecookie_refresh_datasets' );
381 wp_clear_scheduled_hook( 'surecookie_first_party_detect' );
382 }
383 }
384
385 /**
386 * Kick off the plugin by calling get_instance().
387 */
388 SureCookie_Loader::get_instance();
389