PluginProbe
Defender Security – Malware Scanner, Login Security & Firewall / 5.5.0
Defender Security – Malware Scanner, Login Security & Firewall v5.5.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.5.0, at src/traits/defender-bootstrap.php

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