PluginProbe
Defender Security – Malware Scanner, Login Security & Firewall / 6.3.0
Defender Security – Malware Scanner, Login Security & Firewall v6.3.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
← All changes | src/controller/class-dashboard.php +138 -15 6.0.0 → 6.3.0 View file →
@@ -6,8 +6,9 @@
6 6 */
7 7
8 8 namespace WP_Defender\Controller;
9 9
10 +use WP_Defender\Component\Audit;
10 11 use WP_Defender\Event;
11 12 use Calotes\Helper\HTTP;
12 13 use Calotes\Helper\Route;
13 14 use WP_Defender\Model\Setting\Login_Lockout;
@@ -21,8 +22,9 @@
21 22 use WP_Defender\Behavior\WPMUDEV;
22 23 use WP_Defender\Component\Feature_Modal;
23 24 use WP_Defender\Component\Hub_Connector as Hub_Connector_Component;
24 25 use WP_Defender\Model\Setting\Audit_Logging as Audit_Logging_Settings;
26 +use WP_Defender\Model\Audit_Log;
25 27 use WP_Defender\Model\Setting\Global_Ip_Lockout;
26 28 use WP_Defender\Component\Config\Config_Hub_Helper;
27 29 use WP_Defender\Component\IP\Global_IP as Global_IP_Component;
28 30 use WP_Defender\Model\Setting\Session_Protection;
@@ -44,8 +46,18 @@
44 46 */
45 47 public $slug = 'wp-defender';
46 48
47 49 /**
50 + * Site option key for the one-time report-schedule upgrade notice.
51 + */
52 + public const REPORT_SCHEDULE_NOTICE_OPTION = 'wd_show_report_schedule_notice';
53 +
54 + /**
55 + * Site-wide dismissal key for the Dashboard plugin required modal.
56 + */
57 + public const DASHBOARD_REQUIRED_NOTICE_OPTION = 'wpdef_dashboard_required_notice_dismissed';
58 +
59 + /**
48 60 * Initializes the model and service, registers routes, and sets up scheduled events if the model is active.
49 61 */
50 62 public function __construct() {
51 63 $this->attach_behavior( WPMUDEV::class, WPMUDEV::class );
@@ -53,8 +65,9 @@
53 65 $this->register_routes();
54 66 add_action( 'defender_enqueue_assets', array( $this, 'enqueue_assets' ) );
55 67 add_filter( 'custom_menu_order', '__return_true' );
56 68 add_filter( 'menu_order', array( $this, 'menu_order' ) );
69 + add_filter( 'plugins_api', array( $this, 'filter_dashboard_plugin_info' ), 101, 3 );
57 70 add_action( 'admin_init', array( $this, 'maybe_redirect_notification_request' ), 99 );
58 71 }
59 72
60 73 /**
@@ -138,10 +151,23 @@
138 151 $security_tweaks = wd_di()->get( \WP_Defender\Controller\Security_Tweaks::class );
139 152 $security_tweaks->refresh_tweaks_status();
140 153 $security_tweaks_data = $security_tweaks->dashboard_widget();
141 154
142 - $audit_model = wd_di()->get( Audit_Logging_Settings::class );
143 - $firewall = wd_di()->get( Firewall::class )->get_summary();
155 + $audit_model = wd_di()->get( Audit_Logging_Settings::class );
156 + $enabled_audit = $audit_model->is_active();
157 + // Audit summary.
158 + $audit_events_logged = 0;
159 + $last_event_time = esc_html__( '-', 'defender-security' );
160 + if ( $enabled_audit ) {
161 + $audit_events_logged = Audit::get_audit_events_per_week();
162 + $audit_last = Audit_Log::get_last();
163 + if ( is_object( $audit_last ) ) {
164 + $last_event_time = $this->get_date( $audit_last->timestamp );
165 + }
166 + }
167 +
168 + // Firewall summary.
169 + $firewall = wd_di()->get( Firewall::class )->get_summary();
144 170 // Different lockout types.
145 171 $enabled_login = wd_di()->get( Login_Lockout::class )->enabled;
146 172 $enabled_nf = wd_di()->get( Notfound_Lockout::class )->enabled;
147 173 $enabled_ua = wd_di()->get( User_Agent_Lockout::class )->enabled;
@@ -146,17 +172,16 @@
146 172 $enabled_nf = wd_di()->get( Notfound_Lockout::class )->enabled;
147 173 $enabled_ua = wd_di()->get( User_Agent_Lockout::class )->enabled;
148 174
149 175 return array(
150 - 'hide_onboarding' => ! wd_di()->get( HUB::class )->get_onboarding_status(),
151 - 'defenderSetupNonce' => wp_create_nonce( 'defender_quick_setup' ),
152 - 'securityTweaks' => $security_tweaks_data['summary']['issues_count'],
153 - 'scanData' => array(
176 + 'defenderSetupNonce' => wp_create_nonce( 'defender_quick_setup' ),
177 + 'securityTweaks' => $security_tweaks_data['summary']['issues_count'],
178 + 'scanData' => array(
154 179 'numberIssues' => wd_di()->get( \WP_Defender\Component\Scan::class )->indicator_issue_count(),
155 180 'settings' => wd_di()->get( \WP_Defender\Model\Setting\Scan::class )->export(),
156 181 // Scan routes & nonces are set above.
157 182 ),
158 - 'firewallData' => array(
183 + 'firewallData' => array(
159 184 'enabledLocalFirewall' => $enabled_login || $enabled_nf || $enabled_ua,
160 185 'enabledLogin' => $enabled_login,
161 186 'enabledNotFound' => $enabled_nf,
162 187 'enabledUserAgent' => $enabled_ua,
@@ -164,13 +189,17 @@
164 189 'nfLockoutMonth' => $firewall['lockout_404_this_month'],
165 190 'uaLockoutMonth' => $firewall['lockout_ua_this_month'],
166 191 'antibot' => wd_di()->get( Antibot_Global_Firewall::class )->data_frontend(),
167 192 ),
168 - 'site_id' => wd_di()->get( WPMUDEV::class )->get_site_id(),
169 - 'auditData' => array(
170 - 'enabled' => $audit_model->is_active(),
193 + 'site_id' => wd_di()->get( WPMUDEV::class )->get_site_id(),
194 + 'auditData' => array(
195 + 'enabled' => $enabled_audit,
196 + 'eventsLogged' => $audit_events_logged,
197 + 'lastEvent' => $last_event_time,
171 198 ),
172 - 'sessionProtection' => wd_di()->get( Session_Protection::class )->export(),
199 + 'sessionProtection' => wd_di()->get( Session_Protection::class )->export(),
200 + 'showReportScheduleNotice' => ! defender_is_wp_org_version()
201 + && (bool) get_site_option( self::REPORT_SCHEDULE_NOTICE_OPTION, false ),
173 202 );
174 203 }
175 204
176 205 /**
@@ -183,8 +212,9 @@
183 212 }
184 213
185 214 $wizard_action = HTTP::get( 'wizard_action' );
186 215 $wizard_source = HTTP::get( 'source' );
216 + $nonce = HTTP::get( '_wpnonce' );
187 217
188 218 // Fallback completion marker for setup wizard integrations rendered on dashboard.
189 219 // This prevents onboarding loops if client-side completion request fails.
190 220 if (
@@ -190,8 +220,10 @@
190 220 if (
191 221 'setup_wizard' === $wizard_source
192 222 && in_array( $wizard_action, array( 'view_results', 'close_wizard', 'finish_wizard' ), true )
193 223 && current_user_can( 'manage_options' )
224 + && is_string( $nonce )
225 + && false !== wp_verify_nonce( $nonce, 'wpdef_setup_wizard' )
194 226 ) {
195 227 update_site_option( 'wp_defender_shown_activator', true );
196 228 }
197 229
@@ -250,11 +282,12 @@
250 282 // Welcome modal's details.
251 283 wd_di()->get( Feature_Modal::class )->get_dashboard_modals(),
252 284 // Specific data.
253 285 array(
254 - 'showOnboarding' => $show_onboarding,
255 - 'routes' => $routes,
256 - 'nonces' => $nonces,
286 + 'showOnboarding' => $show_onboarding,
287 + 'dashboardRequiredNotice' => $this->get_dashboard_required_notice_data(),
288 + 'routes' => $routes,
289 + 'nonces' => $nonces,
257 290 ),
258 291 $setup_wizard_data,
259 292 $tracking_data,
260 293 wd_di()->get( \WP_Defender\Controller\Scan::class )->get_initial_scan_data()
@@ -262,9 +295,9 @@
262 295 );
263 296
264 297 wp_enqueue_style(
265 298 $handle,
266 - WP_DEFENDER_BASE_URL . 'assets/css/showcase.css',
299 + WP_DEFENDER_BASE_URL . 'assets/css/core-ui.css',
267 300 array(),
268 301 DEFENDER_VERSION
269 302 );
270 303
@@ -271,8 +304,71 @@
271 304 $this->enqueue_main_assets();
272 305 }
273 306
274 307 /**
308 + * Get the state and action URLs for the Dashboard plugin required modal.
309 + *
310 + * @return array
311 + */
312 + private function get_dashboard_required_notice_data(): array {
313 + return array(
314 + 'isProPlugin' => WP_DEFENDER_PRO_PATH === DEFENDER_PLUGIN_BASENAME,
315 + 'dashboardActive' => $this->is_dash_activated(),
316 + 'dashboardInstalled' => $this->is_dash_installed(),
317 + 'dashboardPageUrl' => network_admin_url( 'admin.php?page=wpmudev' ),
318 + 'activateUrl' => add_query_arg(
319 + array(
320 + '_wpnonce' => wp_create_nonce( 'activate-plugin_wpmudev-updates/update-notifications.php' ),
321 + 'action' => 'activate',
322 + 'plugin' => 'wpmudev-updates/update-notifications.php',
323 + ),
324 + network_admin_url( 'plugins.php' )
325 + ),
326 + 'installUrl' => add_query_arg(
327 + array(
328 + '_wpnonce' => wp_create_nonce( 'install-plugin_install_wpmudev_dash' ),
329 + 'action' => 'install-plugin',
330 + 'plugin' => 'install_wpmudev_dash',
331 + ),
332 + network_admin_url( 'update.php' )
333 + ),
334 + 'dismissed' => (bool) get_site_option( self::DASHBOARD_REQUIRED_NOTICE_OPTION, false ),
335 + );
336 + }
337 +
338 + /**
339 + * Supply WordPress with the WPMU DEV Dashboard package details.
340 + *
341 + * @param mixed $result Existing Plugins API result.
342 + * @param string $action Requested Plugins API action.
343 + * @param object $args Requested plugin arguments.
344 + *
345 + * @return mixed
346 + */
347 + public function filter_dashboard_plugin_info( $result, $action, $args ) {
348 + if (
349 + 'plugin_information' !== $action
350 + || ! is_object( $args )
351 + || ! isset( $args->slug )
352 + || '' === trim( (string) $args->slug )
353 + || false === strpos( $args->slug, 'install_wpmudev_dash' )
354 + ) {
355 + return $result;
356 + }
357 +
358 + $plugin = new \stdClass();
359 + $plugin->name = 'WPMU DEV Dashboard';
360 + $plugin->slug = 'wpmu-dev-dashboard';
361 + $plugin->version = '';
362 + $plugin->rating = 100;
363 + $plugin->homepage = 'https://wpmudev.com/project/wpmu-dev-dashboard/';
364 + $plugin->download_link = 'https://wpmudev.com/api/dashboard/v1/download-dashboard';
365 + $plugin->tested = get_bloginfo( 'version' );
366 +
367 + return $plugin;
368 + }
369 +
370 + /**
275 371 * Adds onboarding body classes on dashboard when onboarding wizard is active.
276 372 *
277 373 * @param string $classes Existing admin body classes.
278 374 *
@@ -387,8 +483,32 @@
387 483 return new Response( true, array() );
388 484 }
389 485
390 486 /**
487 + * Dismiss the one-time report-schedule notice set during the 6.1.0 upgrade.
488 + *
489 + * @return Response
490 + * @defender_route
491 + */
492 + public function dismiss_report_schedule_notice(): Response {
493 + delete_site_option( self::REPORT_SCHEDULE_NOTICE_OPTION );
494 +
495 + return new Response( true, array() );
496 + }
497 +
498 + /**
499 + * Permanently dismiss the Dashboard plugin required modal for this site.
500 + *
501 + * @return Response
502 + * @defender_route
503 + */
504 + public function dismiss_dashboard_required_notice(): Response {
505 + update_site_option( self::DASHBOARD_REQUIRED_NOTICE_OPTION, true );
506 +
507 + return new Response( true, array() );
508 + }
509 +
510 + /**
391 511 * Toggle a dashboard feature by feature key.
392 512 *
393 513 * @param Request $request The current request data.
394 514 *
@@ -427,8 +547,10 @@
427 547 * Removes settings for all submodules.
428 548 */
429 549 public function remove_settings() {
430 550 wd_di()->get( Feature_Modal::class )->upgrade_site_options();
551 +
552 + delete_site_option( self::REPORT_SCHEDULE_NOTICE_OPTION );
431 553 }
432 554
433 555 /**
434 556 * Delete all the data & the cache.
@@ -433,8 +555,9 @@
433 555 /**
434 556 * Delete all the data & the cache.
435 557 */
436 558 public function remove_data() {
559 + delete_site_option( self::DASHBOARD_REQUIRED_NOTICE_OPTION );
437 560 }
438 561
439 562 /**
440 563 * Provides data for the frontend.