PluginProbe
Defender Security – Malware Scanner, Login Security & Firewall / 5.4.0
Defender Security – Malware Scanner, Login Security & Firewall v5.4.0
6.3.0 6.2.3 6.2.4 6.2.0 6.2.1 6.2.2 6.1.0 5.3.1 5.4.0 5.4.1 5.5.0 5.5.1 5.6.0 5.6.1 5.6.2 5.7.0 5.7.1 5.7.2 5.8.0 5.8.1 5.9.0 6.0.0 6.0.1 3.0.1 3.1.0 All 141 releases
defender-security / src / traits / defender-bootstrap.php

defender-bootstrap.php in Defender Security – Malware Scanner, Login Security & Firewall 5.4.0, at src/traits/defender-bootstrap.php

657 lines 21.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Handle common bootstrap functionalities.
4 *
5 * @package WP_Defender\Traits
6 */
7
8 namespace WP_Defender\Traits;
9
10 use WP_CLI;
11 use Calotes\DB\Mapper;
12 use WP_Defender\Admin;
13 use WP_Defender\Component\Cli;
14 use Calotes\Helper\Array_Cache;
15 use WP_Defender\Controller\HUB;
16 use WP_Defender\Controller\WAF;
17 use WP_Defender\Controller\Scan;
18 use WP_Defender\Component\Crypt;
19 use WP_Defender\Behavior\WPMUDEV;
20 use WP_Defender\Controller\Onboard;
21 use WP_Defender\Controller\Webauthn;
22 use WP_Defender\Controller\Dashboard;
23 use WP_Defender\Controller\Recaptcha;
24 use WP_Defender\Controller\Mask_Login;
25 use WP_Defender\Controller\Quarantine;
26 use WP_Defender\Controller\Two_Factor;
27 use WP_Defender\Component\Hub_Connector;
28 use WP_Defender\Controller\Main_Setting;
29 use WP_Defender\Controller\Notification;
30 use WP_Defender\Controller\Audit_Logging;
31 use WP_Defender\Controller\Data_Tracking;
32 use WP_Defender\Controller\Advanced_Tools;
33 use WP_Defender\Controller\Password_Reset;
34 use WP_Defender\Controller\Strong_Password;
35 use WP_Defender\Controller\Expert_Services;
36 use WP_Defender\Controller\Security_Tweaks;
37 use WP_Defender\Controller\Security_Headers;
38 use WP_Defender\Controller\Blocklist_Monitor;
39 use WP_Defender\Controller\Session_Protection;
40 use WP_Defender\Controller\Password_Protection;
41 use WP_Defender\Component\Logger\Rotation_Logger;
42 use WP_Defender\Component\Firewall as Firewall_Component;
43 use WP_Defender\Controller\Firewall as Firewall_Controller;
44 use WP_Defender\Controller\Hub_Connector as Hub_Connector_Controller;
45 use WP_Defender\Model\Onboard as Onboard_Model;
46
47 trait Defender_Bootstrap {
48
49 /**
50 * Table name for quarantine.
51 *
52 * @var string
53 */
54 private $quarantine_table = 'defender_quarantine';
55 /**
56 * Table name for scan item.
57 *
58 * @var string
59 */
60 private $scan_item_table = 'defender_scan_item';
61
62 /**
63 * Check is all quarantine dependent table is having storage engine InnoDB.
64 *
65 * @return bool True if all dependent table is InnoDB else false.
66 */
67 private function is_quarantine_dependent_tables_innodb(): bool {
68 global $wpdb;
69
70 $tables = array( $wpdb->users, $wpdb->base_prefix . $this->scan_item_table );
71 $total_table = count( $tables );
72
73 return $wpdb->get_var( // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
74 $wpdb->prepare(
75 "SELECT COUNT(`ENGINE`) = %d FROM information_schema.TABLES WHERE TABLE_SCHEMA = %s AND `ENGINE` = %s AND TABLE_NAME IN ( '{$wpdb->users}', '{$wpdb->base_prefix}defender_scan_item' );",
76 $total_table,
77 $wpdb->dbname,
78 'innodb',
79 )
80 ) === '1';
81 }
82
83 /**
84 * Creates the quarantine table if it doesn't exist.
85 *
86 * @return void
87 */
88 public function create_table_quarantine() {
89 global $wpdb;
90
91 // Define table names and charset.
92 $quarantine_table = $wpdb->base_prefix . $this->quarantine_table;
93 $scan_item_table = $wpdb->base_prefix . $this->scan_item_table;
94 $charset_collate = $wpdb->get_charset_collate();
95 $unique_id = uniqid( $wpdb->prefix );
96
97 $common_columns = <<<SQL
98 `id` bigint UNSIGNED NOT NULL AUTO_INCREMENT,
99 `defender_scan_item_id` int UNSIGNED DEFAULT NULL,
100 `file_hash` char(53) NOT NULL,
101 `file_full_path` text NOT NULL,
102 `file_original_name` tinytext NOT NULL,
103 `file_extension` varchar(16) DEFAULT NULL,
104 `file_mime_type` varchar(64) DEFAULT NULL,
105 `file_rw_permission` smallint UNSIGNED DEFAULT NULL,
106 `file_owner` varchar(255) DEFAULT NULL,
107 `file_group` varchar(255) DEFAULT NULL,
108 `file_version` varchar(32) DEFAULT NULL,
109 `file_category` tinyint UNSIGNED DEFAULT 0,
110 `file_modified_time` datetime NOT NULL,
111 `source_slug` varchar(255) NOT NULL,
112 `created_time` datetime NOT NULL,
113 `created_by` bigint UNSIGNED DEFAULT NULL,
114 PRIMARY KEY (`id`)
115 SQL;
116
117 // Define key names.
118 $scan_item_key = "{$unique_id}_defender_scan_item_id";
119 $created_by_key = "{$unique_id}_created_by";
120
121 // Build the SQL statement based on the storage engine.
122 if ( $this->is_quarantine_dependent_tables_innodb() ) {
123 $sql = <<<SQL
124 CREATE TABLE IF NOT EXISTS `{$quarantine_table}` (
125 $common_columns,
126 CONSTRAINT `{$scan_item_key}`
127 FOREIGN KEY (`defender_scan_item_id`) REFERENCES {$scan_item_table}(`id`)
128 ON UPDATE CASCADE ON DELETE SET NULL,
129 CONSTRAINT `{$created_by_key}`
130 FOREIGN KEY (`created_by`) REFERENCES {$wpdb->users}(`ID`)
131 ON UPDATE CASCADE ON DELETE SET NULL
132 ) {$charset_collate};
133 SQL;
134 } else {
135 $sql = <<<SQL
136 CREATE TABLE IF NOT EXISTS `{$quarantine_table}` (
137 $common_columns,
138 KEY `{$scan_item_key}` (`defender_scan_item_id`),
139 KEY `{$created_by_key}` (`created_by`)
140 ) {$charset_collate};
141 SQL;
142 }
143
144 // Execute the SQL query.
145 $wpdb->query( $sql ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
146 }
147
148 /**
149 * Activation.
150 */
151 private function activation_hook_common(): void {
152 $this->create_database_tables();
153 $this->on_activation();
154 // Create a file with a random key if it doesn't exist.
155 ( new Crypt() )->create_key_file();
156 // If this is a plugin reactivatin, then track it. No need the check by 'wd_nofresh_install' key because the option is disabled by default.
157 $settings = wd_di()->get( Main_Setting::class );
158 $settings->set_intention( 'Reactivation' );
159 $settings->track_opt( true );
160
161 $service = wd_di()->get( Firewall_Component::class );
162 $service->auto_switch_ip_detection_option();
163 $service->maybe_show_misconfigured_ip_detection_option_notice();
164 $service->maybe_dismiss_cf_notice();
165 wp_schedule_single_event( time() + 5, 'wpdef_smart_ip_detection_ping' );
166 }
167
168 /**
169 * Deactivation.
170 */
171 public function deactivation_hook(): void {
172 wp_clear_scheduled_hook( 'firewall_clean_up_logs' );
173 wp_clear_scheduled_hook( 'audit_sync_events' );
174 wp_clear_scheduled_hook( 'audit_clean_up_logs' );
175 wp_clear_scheduled_hook( 'wdf_maybe_send_report' );
176 wp_clear_scheduled_hook( 'wp_defender_clear_logs' );
177 wp_clear_scheduled_hook( 'wpdef_sec_key_gen' );
178 wp_clear_scheduled_hook( 'wpdef_clear_scan_logs' );
179 wp_clear_scheduled_hook( 'wpdef_log_rotational_delete' );
180 wp_clear_scheduled_hook( 'wpdef_update_geoip' );
181 wp_clear_scheduled_hook( 'wpdef_fetch_global_ip_list' );
182 wp_clear_scheduled_hook( 'wpdef_quarantine_delete_expired' );
183 wp_clear_scheduled_hook( 'wpdef_firewall_clean_up_lockout' );
184 wp_clear_scheduled_hook( 'wpdef_firewall_send_compact_logs_to_api' );
185 wp_clear_scheduled_hook( 'wpdef_firewall_fetch_trusted_proxy_preset_ips' );
186 wp_clear_scheduled_hook( 'wpdef_firewall_clean_up_unlockout' );
187 wp_clear_scheduled_hook( 'wpdef_antibot_global_firewall_fetch_blocklist' );
188 wp_clear_scheduled_hook( 'wpdef_smart_ip_detection_ping' );
189 wp_clear_scheduled_hook( 'wpdef_confirm_antibot_toggle_on_hosting' );
190 wp_clear_scheduled_hook( 'wpdef_firewall_whitelist_server_public_ip' );
191 wp_clear_scheduled_hook( 'wpdef_rotate_bot_trap_secret_hash' );
192
193 // Remove old legacy cron jobs if they exist.
194 wp_clear_scheduled_hook( 'lockoutReportCron' );
195 wp_clear_scheduled_hook( 'auditReportCron' );
196 wp_clear_scheduled_hook( 'cleanUpOldLog' );
197 wp_clear_scheduled_hook( 'scanReportCron' );
198 wp_clear_scheduled_hook( 'tweaksSendNotification' );
199 }
200
201 /**
202 * Creates the 'defender_unlockout' table if it doesn't exist in the database.
203 *
204 * @return void
205 */
206 public function create_table_unlockout() {
207 global $wpdb;
208
209 $charset_collate = $wpdb->get_charset_collate();
210
211 $sql = <<<SQL
212 CREATE TABLE IF NOT EXISTS {$wpdb->base_prefix}defender_unlockout (
213 `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
214 `ip` varchar(45) DEFAULT NULL,
215 `type` varchar(16) NOT NULL,
216 `email` varchar(255) NOT NULL,
217 `status` varchar(16) NOT NULL,
218 `timestamp` int(11) NOT NULL,
219 PRIMARY KEY (`id`),
220 KEY `ip` (`ip`),
221 KEY `type` (`type`),
222 KEY `email` (`email`),
223 KEY `status` (`status`)
224 ) {$charset_collate};
225 SQL;
226 $wpdb->query( $sql ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
227 }
228
229 /**
230 * Create blocklist table.
231 *
232 * @since 2.8.0
233 * @return void
234 */
235 public function create_table_blocklist(): void {
236 global $wpdb;
237
238 $charset_collate = $wpdb->get_charset_collate();
239
240 $sql = <<<SQL
241 CREATE TABLE IF NOT EXISTS {$wpdb->base_prefix}defender_antibot (
242 `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
243 `ip` varchar(45) NOT NULL,
244 `unlocked` tinyint(1) DEFAULT NULL,
245 `unlocked_at` int(11) DEFAULT NULL,
246 PRIMARY KEY (`id`),
247 UNIQUE KEY ip (ip)
248 ) {$charset_collate};
249 SQL;
250 $wpdb->query( $sql ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared
251 }
252
253 /**
254 * Creates Defender's tables.
255 *
256 * @since 2.7.1 No use dbDelta because PHP v8.1 triggers an error when calling query "DESCRIBE {$table};" if the
257 * table doesn't exist.
258 */
259 protected function create_database_tables(): void {
260 global $wpdb;
261
262 $charset_collate = $wpdb->get_charset_collate();
263 // Hide errors.
264 $wpdb->hide_errors();
265 // Email log table.
266 $sql = "CREATE TABLE IF NOT EXISTS {$wpdb->base_prefix}defender_email_log (
267 `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
268 `timestamp` int NOT NULL,
269 `source` varchar(255) NOT NULL,
270 `to` varchar(255) NOT NULL,
271 PRIMARY KEY (`id`),
272 KEY `source` (`source`)
273 ) $charset_collate;";
274 $wpdb->query( $sql ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
275
276 // Audit log table. Though our data mainly store on API side, we will need a table for caching.
277 $sql = "CREATE TABLE IF NOT EXISTS {$wpdb->base_prefix}defender_audit_log (
278 `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
279 `timestamp` int NOT NULL,
280 `event_type` varchar(255) NOT NULL,
281 `action_type` varchar(255) NOT NULL,
282 `site_url` varchar(255) NOT NULL,
283 `user_id` int NOT NULL,
284 `context` varchar(255) NOT NULL,
285 `ip` varchar(45) NOT NULL,
286 `msg` varchar(255) NOT NULL,
287 `blog_id` int NOT NULL,
288 `synced` int NOT NULL,
289 `ttl` int NOT NULL,
290 PRIMARY KEY (`id`),
291 KEY `event_type` (`event_type`),
292 KEY `action_type` (`action_type`),
293 KEY `user_id` (`user_id`),
294 KEY `context` (`context`),
295 KEY `ip` (`ip`)
296 ) $charset_collate;";
297 $wpdb->query( $sql ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
298
299 // Scan item table.
300 $sql = "CREATE TABLE IF NOT EXISTS {$wpdb->base_prefix}defender_scan_item (
301 `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
302 `parent_id` int NOT NULL,
303 `type` varchar(255) NOT NULL,
304 `status` varchar(255) NOT NULL,
305 `raw_data` text NOT NULL,
306 PRIMARY KEY (`id`),
307 KEY `type` (`type`),
308 KEY `status` (`status`)
309 ) $charset_collate;";
310 $wpdb->query( $sql ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
311
312 // Scan table.
313 $sql = "CREATE TABLE IF NOT EXISTS {$wpdb->base_prefix}defender_scan (
314 `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
315 `percent` float NOT NULL,
316 `total_tasks` tinyint(4) NOT NULL,
317 `task_checkpoint` varchar(255) NOT NULL,
318 `status` varchar(255) NOT NULL,
319 `date_start` datetime NOT NULL,
320 `date_end` datetime NOT NULL,
321 `is_automation` bool NOT NULL,
322 PRIMARY KEY (`id`)
323 ) $charset_collate;";
324 $wpdb->query( $sql ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
325
326 // Lockout log table.
327 $sql = "CREATE TABLE IF NOT EXISTS {$wpdb->base_prefix}defender_lockout_log (
328 `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
329 `log` text,
330 `ip` varchar(45) DEFAULT NULL,
331 `date` int(11) DEFAULT NULL,
332 `type` varchar(16) DEFAULT NULL,
333 `user_agent` varchar(255) DEFAULT NULL,
334 `blog_id` int(11) DEFAULT NULL,
335 `tried` varchar(255),
336 `country_iso_code` char(2) DEFAULT NULL,
337 PRIMARY KEY (`id`),
338 KEY `ip` (`ip`),
339 KEY `type` (`type`),
340 KEY `tried` (`tried`),
341 KEY `country_iso_code` (`country_iso_code`)
342 ) $charset_collate;";
343 $wpdb->query( $sql ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
344
345 // Lockout table.
346 $sql = "CREATE TABLE IF NOT EXISTS {$wpdb->base_prefix}defender_lockout (
347 `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
348 `ip` varchar(45) DEFAULT NULL,
349 `status` varchar(16) DEFAULT NULL,
350 `lockout_message` text,
351 `release_time` int(11) DEFAULT NULL,
352 `lock_time` int(11) DEFAULT NULL,
353 `lock_time_404` int(11) DEFAULT NULL,
354 `attempt` int(11) DEFAULT NULL,
355 `attempt_404` int(11) DEFAULT NULL,
356 `meta` text,
357 PRIMARY KEY (`id`),
358 KEY `ip` (`ip`),
359 KEY `status` (`status`),
360 KEY `attempt` (`attempt`),
361 KEY `attempt_404` (`attempt_404`)
362 ) $charset_collate;";
363 $wpdb->query( $sql ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
364
365 $this->create_table_quarantine();
366
367 // Create Unlock table.
368 $this->create_table_unlockout();
369 // Create Blocklist table.
370 $this->create_table_blocklist();
371 }
372
373 /**
374 * Initializes the common modules of the application.
375 *
376 * @return void
377 */
378 private function init_modules_common(): void {
379 // Init main ORM.
380 Array_Cache::set( 'orm', new Mapper() );
381 /**
382 * Display Onboarding if:
383 * it's a fresh install and there were no requests from the Hub before,
384 * after Reset Settings.
385 *
386 * @var HUB
387 */
388 $hub_class = wd_di()->get( HUB::class );
389 $hub_class->set_onboarding_status( Onboard_Model::maybe_show_onboarding() );
390 if ( $hub_class->get_onboarding_status() && ! defender_is_wp_cli() ) {
391 // If it's cli we should start this normally.
392 Array_Cache::set( 'onboard', wd_di()->get( Onboard::class ) );
393 } else {
394 // Initialize the main controllers of every module.
395 wd_di()->get( Dashboard::class );
396 }
397 wd_di()->get( Security_Tweaks::class );
398 wd_di()->get( Scan::class );
399 wd_di()->get( Audit_Logging::class );
400 wd_di()->get( Firewall_Controller::class );
401 wd_di()->get( WAF::class );
402 wd_di()->get( Two_Factor::class );
403 wd_di()->get( Advanced_Tools::class );
404 wd_di()->get( Mask_Login::class );
405 wd_di()->get( Security_Headers::class );
406 wd_di()->get( Recaptcha::class );
407 wd_di()->get( Notification::class );
408 wd_di()->get( Main_Setting::class );
409 wd_di()->get( Blocklist_Monitor::class );
410 wd_di()->get( Password_Protection::class );
411 wd_di()->get( Password_Reset::class );
412 wd_di()->get( Webauthn::class );
413 wd_di()->get( Expert_Services::class );
414 wd_di()->get( Hub_Connector_Controller::class );
415 wd_di()->get( Strong_Password::class );
416 wd_di()->get( Session_Protection::class );
417
418 if ( class_exists( 'WP_Defender\Controller\Quarantine' ) ) {
419 wd_di()->get( Quarantine::class );
420 }
421 wd_di()->get( Data_Tracking::class );
422 }
423
424 /**
425 * Adds a specific class to the body tag if the current page is a Defender page.
426 *
427 * @param string $classes The existing body classes.
428 *
429 * @return string The modified body classes.
430 */
431 public function add_sui_to_body( $classes ) {
432 if ( ! is_defender_page() ) {
433 return $classes;
434 }
435 $classes .= sprintf( ' sui-%s ', DEFENDER_SUI );
436
437 return $classes;
438 }
439
440 /**
441 * Registers the necessary styles for the plugin.
442 *
443 * @return void
444 */
445 private function register_styles(): void {
446 wp_enqueue_style( 'defender-menu', WP_DEFENDER_BASE_URL . 'assets/css/defender-icon.css', array(), DEFENDER_VERSION );
447
448 $css_files = array(
449 'defender' => WP_DEFENDER_BASE_URL . 'assets/css/styles.css',
450 );
451
452 foreach ( $css_files as $slug => $file ) {
453 wp_register_style( $slug, $file, array(), DEFENDER_VERSION );
454 }
455 }
456
457 /**
458 * Registers the necessary scripts for the plugin.
459 *
460 * @return void
461 */
462 private function register_scripts(): void {
463 $base_url = WP_DEFENDER_BASE_URL;
464 $dependencies = array( 'def-vue', 'def-manifest', 'defender', 'wp-i18n' );
465 $js_files = array(
466 'wpmudev-sui' => array(
467 $base_url . 'assets/js/shared-ui.js',
468 ),
469 'defender' => array(
470 $base_url . 'assets/js/scripts.js',
471 ),
472 'def-vue' => array(
473 $base_url . 'assets/app/vendor.js',
474 ),
475 'def-manifest' => array(
476 $base_url . 'assets/app/manifest.js',
477 ),
478 'def-dashboard' => array(
479 $base_url . 'assets/app/dashboard.js',
480 $dependencies,
481 ),
482 'def-securitytweaks' => array(
483 $base_url . 'assets/app/security-tweak.js',
484 array_merge( $dependencies, array( 'clipboard', 'wpmudev-sui' ) ),
485 ),
486 'def-scan' => array(
487 $base_url . 'assets/app/scan.js',
488 array_merge( $dependencies, array( 'clipboard', 'wpmudev-sui' ) ),
489 ),
490 'def-audit' => array(
491 $base_url . 'assets/app/audit.js',
492 $dependencies,
493 ),
494 'def-iplockout' => array(
495 $base_url . 'assets/app/ip-lockout.js',
496 array_merge( $dependencies, array( 'wpmudev-sui' ) ),
497 ),
498 'def-advancedtools' => array(
499 $base_url . 'assets/app/advanced-tools.js',
500 $dependencies,
501 ),
502 'def-settings' => array(
503 $base_url . 'assets/app/settings.js',
504 $dependencies,
505 ),
506 'def-2fa' => array(
507 $base_url . 'assets/app/two-fa.js',
508 $dependencies,
509 ),
510 'def-notification' => array(
511 $base_url . 'assets/app/notification.js',
512 $dependencies,
513 ),
514 'def-waf' => array(
515 $base_url . 'assets/app/waf.js',
516 $dependencies,
517 ),
518 'def-onboard' => array(
519 $base_url . 'assets/app/onboard.js',
520 $dependencies,
521 ),
522 'def-expert-services' => array(
523 $base_url . '/assets/app/expert-services.js',
524 $dependencies,
525 ),
526 );
527
528 foreach ( $js_files as $slug => $file ) {
529 if ( isset( $file[1] ) ) {
530 wp_register_script( $slug, $file[0], $file[1], DEFENDER_VERSION, true );
531 wp_set_script_translations( $slug, 'defender-security' );
532 } else {
533 wp_register_script( $slug, $file[0], array( 'jquery' ), DEFENDER_VERSION, true );
534 }
535 }
536 }
537
538 /**
539 * Localizes the script by adding necessary data to the 'defender' object.
540 *
541 * @return void
542 */
543 private function localize_script(): void {
544 $wpmu_dev = new WPMUDEV();
545 global $wp_defender_central;
546
547 $misc = array();
548 $data_tracking = wd_di()->get( Data_Tracking::class );
549 $is_tracking = $data_tracking->show_tracking_modal();
550 if ( $is_tracking ) {
551 $misc = $data_tracking->get_tracking_modal();
552 }
553 $misc['high_contrast'] = defender_high_contrast();
554
555 wp_localize_script(
556 'def-vue',
557 'defender',
558 array(
559 'whitelabel' => defender_white_label_status(),
560 'misc' => $misc,
561 'home_url' => network_home_url(),
562 'site_url' => network_site_url(),
563 'admin_url' => network_admin_url(),
564 'defender_url' => WP_DEFENDER_BASE_URL,
565 'is_free' => $wpmu_dev->is_pro() ? 0 : 1,
566 'is_membership' => true,
567 'is_whitelabel' => $wpmu_dev->is_whitelabel_enabled() ? 'enabled' : 'disabled',
568 'wpmu_dev_url_action' => $wpmu_dev->hide_wpmu_dev_urls() ? 'hide' : 'show',
569 'opcache_save_comments' => $wp_defender_central->is_opcache_save_comments_disabled() ? 'disabled' : 'enabled',
570 'opcache_message' => $wp_defender_central->display_opcache_message(),
571 'wpmudev_url' => WP_DEFENDER_DOCS_LINK,
572 'wpmudev_support_ticket_text' => defender_support_ticket_text(),
573 'wpmudev_api_base_url' => $wpmu_dev->get_api_base_url(),
574 'upgrade_title' => esc_html__( 'UPGRADE TO PRO', 'defender-security' ),
575 'tracking_modal' => $is_tracking ? 'show' : 'hide',
576 'hosted' => $wpmu_dev->is_wpmu_hosting(),
577 'file_upload_nonce' => wp_create_nonce( 'defender_file_upload' ),
578 )
579 );
580
581 wp_localize_script( 'defender', 'defenderGetText', defender_gettext_translations() );
582 }
583
584 /**
585 * Register all core assets.
586 */
587 public function register_assets(): void {
588 $this->register_styles();
589 $this->register_scripts();
590 $this->localize_script();
591
592 do_action( 'defender_enqueue_assets' );
593 }
594
595 /**
596 * Trigger mandatory actions on activation.
597 */
598 private function on_activation(): void {
599 add_action(
600 'admin_init',
601 function () {
602 $security_tweaks = wd_di()->get( Security_Tweaks::class );
603 $security_tweaks->get_security_key()->cron_schedule();
604 }
605 );
606 }
607
608 /**
609 * Returns the cron schedules.
610 *
611 * @param array $schedules The existing cron schedules.
612 *
613 * @return array The updated cron schedules.
614 */
615 public function cron_schedules( array $schedules ) {
616 return defender_cron_schedules( $schedules );
617 }
618
619 /**
620 * Initialize the modules and register the plugin routes. Also include the admin class, adds WP-CLI commands.
621 *
622 * @return void
623 */
624 public function includes(): void {
625 // Initialize modules.
626 add_action(
627 'after_setup_theme',
628 function () {
629 add_filter( 'cron_schedules', array( $this, 'cron_schedules' ) );
630 $this->init_modules();
631 }
632 );
633 // Register routes.
634 add_action(
635 'init',
636 function () {
637 require_once WP_DEFENDER_DIR . 'src/routes.php';
638 },
639 9
640 );
641 // Register the Hub Connector early to handle the auth callback during the admin init hook.
642 add_action( 'plugins_loaded', array( wd_di()->get( Hub_Connector::class ), 'init' ) );
643 // Register the Cross-Sell module.
644 add_action( 'init', array( wd_di()->get( \WP_Defender\Component\Cross_Sell::class ), 'init' ), 9 );
645 // Include admin class. Don't use is_admin().
646 add_action( 'admin_init', array( ( new Admin() ), 'init' ) );
647 // Add WP-CLI commands.
648 if ( defender_is_wp_cli() ) {
649 WP_CLI::add_command( 'defender', Cli::class );
650 }
651 // Rotational logger initialization.
652 add_action( 'init', array( ( new Rotation_Logger() ), 'init' ), 99 );
653 // Handle plugin deactivation.
654 add_action( 'deactivated_plugin', array( ( new HUB() ), 'intercept_deactivate' ) );
655 }
656 }
657