Completed
Push — fix/flickr-shortcode ( 3e5712...02d728 )
by
unknown
24:33 queued 14:33
created

Admin_Bar_Notice   A

Complexity

Total Complexity 23

Size/Duplication

Total Lines 183
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 2

Importance

Changes 0
Metric Value
dl 0
loc 183
rs 10
c 0
b 0
f 0
wmc 23
lcom 1
cbo 2

9 Methods

Rating   Name   Duplication   Size   Complexity  
A instance() 0 8 2
A init_hooks() 0 9 2
A get_threat_count() 0 8 3
A should_try_to_display_notice() 0 19 4
A enqueue_toolbar_script() 0 21 2
A add_inline_styles() 0 14 3
A add_threats_to_toolbar() 0 35 4
A get_icon() 0 3 1
A has_threats() 0 8 2
1
<?php
2
/**
3
 * A class that adds the scan notice to the admin bar.
4
 *
5
 * @package automattic/jetpack
6
 */
7
8
namespace Automattic\Jetpack\Scan;
9
10
use Automattic\Jetpack\Assets;
11
use Automattic\Jetpack\Redirect;
12
13
/**
14
 * Class Main
15
 *
16
 * Responsible for loading the admin bar notice if threats are found.
17
 *
18
 * @package Automattic\Jetpack\Scan
19
 */
20
class Admin_Bar_Notice {
21
	const SCRIPT_NAME    = 'jetpack-scan-show-notice';
22
	const SCRIPT_VERSION = '1';
23
24
	/**
25
	 * The singleton instance of this class.
26
	 *
27
	 * @var Admin_Bar_Notice
28
	 */
29
	protected static $instance;
30
31
	/**
32
	 * Get the singleton instance of the class.
33
	 *
34
	 * @return Admin_Bar_Notice
35
	 */
36
	public static function instance() {
37
		if ( ! isset( self::$instance ) ) {
38
			self::$instance = new Admin_Bar_Notice();
39
			self::$instance->init_hooks();
40
		}
41
42
		return self::$instance;
43
	}
44
	/**
45
	 * Initalize the hooks as needed.
46
	 */
47
	private function init_hooks() {
48
		if ( ! $this->should_try_to_display_notice() ) {
49
			return;
50
		}
51
52
		add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_toolbar_script' ) );
53
		add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_toolbar_script' ) );
54
		add_action( 'admin_bar_menu', array( $this, 'add_threats_to_toolbar' ), 999 );
55
	}
56
57
	/**
58
	 * Whether to even try to display the notice or now.
59
	 *
60
	 * @return bool
61
	 */
62
	private function should_try_to_display_notice() {
63
		// Jetpack Scan is currently not supported on multisite.
64
		if ( is_multisite() ) {
65
			return false;
66
		}
67
68
		// Check if VaultPress is active, the assumtion there is that VaultPress is working.
69
		// It has its own notice in the admin bar.
70
		if ( class_exists( 'VaultPress' ) ) {
71
			return false;
72
		}
73
74
		// Only show the notice to admins.
75
		if ( ! current_user_can( 'manage_options' ) ) {
76
			return false;
77
		}
78
79
		return true;
80
	}
81
82
	/**
83
	 * Add the inline styles and scripts if they are needed.
84
	 */
85
	public function enqueue_toolbar_script() {
86
		$this->add_inline_styles();
87
88
		if ( ! is_null( $this->has_threats() ) ) {
89
			return;
90
		}
91
92
		// We don't know about threats in the cache lets load the JS that fetches the info and updates the admin bar.
93
		Assets::enqueue_async_script( self::SCRIPT_NAME, '_inc/build/scan/admin-bar-notice.min.js', 'modules/scan/admin-bar-notice.js', array(), self::SCRIPT_VERSION, true );
0 ignored issues
show
Documentation introduced by
self::SCRIPT_VERSION is of type string, but the function expects a boolean.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
94
95
		$script_data = array(
96
			'nonce'              => wp_create_nonce( 'wp_rest' ),
97
			'scan_endpoint'      => get_rest_url( null, 'jetpack/v4/scan' ),
98
			'scan_dashboard_url' => Redirect::get_url( 'calypso-scanner' ),
99
			/* translators: %s is the alert icon */
100
			'singular'           => sprintf( esc_html__( '%s Threat found', 'jetpack' ), $this->get_icon() ),
101
			/* translators: %s is the alert icon */
102
			'multiple'           => sprintf( esc_html__( '%s Threats found', 'jetpack' ), $this->get_icon() ),
103
		);
104
		wp_localize_script( self::SCRIPT_NAME, 'Jetpack_Scan', $script_data );
105
	}
106
107
	/**
108
	 * Adds the inline styles if they are needed.
109
	 */
110
	public function add_inline_styles() {
111
		// We know there are no threats so lets not include any css.
112
		if ( false === $this->has_threats() ) {
113
			return;
114
		}
115
116
		// We might be showing the threats in the admin bar lets make sure that they look great!
117
		$hide_wording_on_mobile = '#wp-admin-bar-jetpack-scan-notice .is-hidden { display:none; } @media screen and (max-width: 959px ) { #wpadminbar #wp-admin-bar-jetpack-scan-notice { width:32px; } #wpadminbar #wp-admin-bar-jetpack-scan-notice a { color: transparent!important; }';
118
		$style                  = '#wp-admin-bar-jetpack-scan-notice svg { float:left; margin-top: 4px; margin-right: 6px; width: 18px; height: 22px; }' . $hide_wording_on_mobile;
119
		if ( is_rtl() ) {
120
			$style = '#wp-admin-bar-jetpack-scan-notice svg { float:right; margin-top: 4px; margin-left: 6px; width: 18px; height: 22px; }' . $hide_wording_on_mobile;
121
		}
122
		wp_add_inline_style( 'admin-bar', $style );
123
	}
124
125
	/**
126
	 * Add the link to the admin bar.
127
	 *
128
	 * @param WP_Admin_Bar $wp_admin_bar WP Admin Bar class object.
129
	 */
130
	public function add_threats_to_toolbar( $wp_admin_bar ) {
131
		if ( ! $this->should_try_to_display_notice() ) {
132
			return;
133
		}
134
135
		$has_threats = $this->has_threats();
136
		if ( false === $has_threats ) {
137
			return;
138
		}
139
140
		$node = array(
141
			'id'     => 'jetpack-scan-notice',
142
			'title'  => '',
143
			'parent' => 'top-secondary',
144
			'meta'   => array(
145
				'title' => esc_attr__( 'View security scan details', 'jetpack' ),
146
				'class' => 'error is-hidden',
147
			),
148
		);
149
150
		if ( $has_threats ) {
151
			$node['href']            = esc_url( Redirect::get_url( 'calypso-scanner' ) );
152
			$node['meta']['onclick'] = 'window.open( this.href ); return false;';
153
			$node['meta']['class']   = 'error';
154
			$node['title']           = sprintf(
155
				esc_html(
156
				/* translators: %s is the alert icon */
157
					_n( '%s Threat found', '%s Threats found', $this->get_threat_count(), 'jetpack' )
158
				),
159
				$this->get_icon()
160
			);
161
		}
162
163
		$wp_admin_bar->add_node( $node );
164
	}
165
166
	/**
167
	 * Returns the shield icon.
168
	 *
169
	 * @return string
170
	 */
171
	private function get_icon() {
172
		return '<svg width="18" height="22" viewBox="0 0 18 22" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M9 0L0 4V10C0 15.55 3.84 20.74 9 22C14.16 20.74 18 15.55 18 10V4L9 0Z" fill="#D63638"/><path d="M7.99121 6.00894H10.0085V11.9968H7.99121V6.00894Z" fill="#FFF"/><path d="M7.99121 14.014H10.0085V15.9911H7.99121V14.014Z" fill="#FFF"/></svg>';
173
	}
174
175
	/**
176
	 *
177
	 * Return Whether boolean cached threats exist or null if the state is unknown.
178
	 * * @return boolean or null
179
	 */
180
	public function has_threats() {
181
		$scan_state = get_transient( 'jetpack_scan_state' );
182
		if ( empty( $scan_state ) ) {
183
			return null;
184
		}
185
		// Return true if there is at least one threat found.
186
		return (bool) isset( $scan_state->threats[0] );
187
	}
188
189
	/**
190
	 * Returns the number of threats found or 0.
191
	 *
192
	 * @return int
193
	 */
194
	public function get_threat_count() {
195
		if ( ! $this->has_threats() ) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->has_threats() of type null|boolean is loosely compared to false; this is ambiguous if the boolean can be false. You might want to explicitly use !== null instead.

If an expression can have both false, and null as possible values. It is generally a good practice to always use strict comparison to clearly distinguish between those two values.

$a = canBeFalseAndNull();

// Instead of
if ( ! $a) { }

// Better use one of the explicit versions:
if ($a !== null) { }
if ($a !== false) { }
if ($a !== null && $a !== false) { }
Loading history...
196
			return 0;
197
		}
198
199
		$scan_state = get_transient( 'jetpack_scan_state' );
200
		return is_array( $scan_state->threats ) ? count( $scan_state->threats ) : 0;
201
	}
202
}
203