Completed
Push — add/theme-switch-name ( 3e6989 )
by
unknown
11:52
created

class.jetpack-admin.php (4 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
4
// Build the Jetpack admin menu as a whole
5
class Jetpack_Admin {
6
7
	/**
8
	 * @var Jetpack_Admin
9
	 **/
10
	private static $instance = null;
11
12
	/**
13
	 * @var Jetpack
14
	 **/
15
	private $jetpack;
16
17
	static function init() {
18
		if ( is_null( self::$instance ) ) {
19
			self::$instance = new Jetpack_Admin;
20
		}
21
		return self::$instance;
22
	}
23
24
	private function __construct() {
25
		$this->jetpack = Jetpack::init();
26
27
		jetpack_require_lib( 'admin-pages/class.jetpack-react-page' );
28
		$this->jetpack_react = new Jetpack_React_Page;
0 ignored issues
show
The property jetpack_react does not seem to exist. Did you mean jetpack?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
29
30
		jetpack_require_lib( 'admin-pages/class.jetpack-settings-page' );
31
		$this->fallback_page = new Jetpack_Settings_Page;
32
33
		add_action( 'admin_menu',                    array( $this->jetpack_react, 'add_actions' ), 998 );
34
		add_action( 'jetpack_admin_menu',            array( $this->jetpack_react, 'jetpack_add_dashboard_sub_nav_item' ) );
35
		add_action( 'jetpack_admin_menu',            array( $this->jetpack_react, 'jetpack_add_settings_sub_nav_item' ) );
36
		add_action( 'jetpack_admin_menu',            array( $this, 'admin_menu_debugger' ) );
37
		add_action( 'jetpack_admin_menu',            array( $this->fallback_page, 'add_actions' ) );
38
39
		// Add redirect to current page for activation/deactivation of modules
40
		add_action( 'jetpack_pre_activate_module',   array( $this, 'fix_redirect' ), 10, 2 );
41
		add_action( 'jetpack_pre_deactivate_module', array( $this, 'fix_redirect' ) );
42
43
		// Add module bulk actions handler
44
		add_action( 'jetpack_unrecognized_action',   array( $this, 'handle_unrecognized_action' ) );
45
	}
46
47 View Code Duplication
	static function sort_requires_connection_last( $module1, $module2 ) {
48
		if ( $module1['requires_connection'] == $module2['requires_connection'] ) {
49
			return 0;
50
		} elseif ( $module1['requires_connection'] ) {
51
			return 1;
52
		} elseif ( $module2['requires_connection'] ) {
53
			return -1;
54
		}
55
56
		return 0;
57
	}
58
59
	// Produce JS understandable objects of modules containing information for
60
	// presentation like description, name, configuration url, etc.
61
	function get_modules() {
62
		include_once( JETPACK__PLUGIN_DIR . 'modules/module-info.php' );
63
		$available_modules = $this->jetpack->get_available_modules();
64
		$active_modules    = $this->jetpack->get_active_modules();
65
		$modules           = array();
66
		$jetpack_active = Jetpack::is_active() || Jetpack::is_development_mode();
67
		foreach ( $available_modules as $module ) {
68
			if ( $module_array = $this->jetpack->get_module( $module ) ) {
69
				/**
70
				 * Filters each module's short description.
71
				 *
72
				 * @since 3.0.0
73
				 *
74
				 * @param string $module_array['description'] Module description.
75
				 * @param string $module Module slug.
76
				 */
77
				$short_desc = apply_filters( 'jetpack_short_module_description', $module_array['description'], $module );
78
				// Fix: correct multibyte strings truncate with checking for mbstring extension
79
				$short_desc_trunc = ( function_exists( 'mb_strlen' ) )
80
							? ( ( mb_strlen( $short_desc ) > 143 )
81
								? mb_substr( $short_desc, 0, 140 ) . '...'
82
								: $short_desc )
83
							: ( ( strlen( $short_desc ) > 143 )
84
								? substr( $short_desc, 0, 140 ) . '...'
85
								: $short_desc );
86
87
				$module_array['module']            = $module;
88
				$module_array['activated']         = ( $jetpack_active ? in_array( $module, $active_modules ) : false );
89
				$module_array['deactivate_nonce']  = wp_create_nonce( 'jetpack_deactivate-' . $module );
90
				$module_array['activate_nonce']    = wp_create_nonce( 'jetpack_activate-' . $module );
91
				$module_array['available']         = self::is_module_available( $module_array );
92
				$module_array['short_description'] = $short_desc_trunc;
93
				$module_array['configure_url']     = Jetpack::module_configuration_url( $module );
94
95
				ob_start();
96
				/**
97
				 * Allow the display of a "Learn More" button.
98
				 * The dynamic part of the action, $module, is the module slug.
99
				 *
100
				 * @since 3.0.0
101
				 */
102
				do_action( 'jetpack_learn_more_button_' . $module );
103
				$module_array['learn_more_button'] = ob_get_clean();
104
105
				ob_start();
106
				/**
107
				 * Allow the display of information text when Jetpack is connected to WordPress.com.
108
				 * The dynamic part of the action, $module, is the module slug.
109
				 *
110
				 * @since 3.0.0
111
				 */
112
				do_action( 'jetpack_module_more_info_' . $module );
113
114
				/**
115
				* Filter the long description of a module.
116
	 			*
117
	 			* @since 3.5.0
118
	 			*
119
	 			* @param string ob_get_clean() The module long description.
120
				* @param string $module The module name.
121
	 			*/
122
				$module_array['long_description'] = apply_filters( 'jetpack_long_module_description', ob_get_clean(), $module );
123
124
				ob_start();
125
				/**
126
				 * Filter the search terms for a module
127
				 *
128
				 * Search terms are typically added to the module headers, under "Additional Search Queries".
129
				 *
130
				 * Use syntax:
131
				 * function jetpack_$module_search_terms( $terms ) {
132
				 *  $terms = _x( 'term 1, term 2', 'search terms', 'jetpack' );
133
				 *  return $terms;
134
				 * }
135
				 * add_filter( 'jetpack_search_terms_$module', 'jetpack_$module_search_terms' );
136
				 *
137
				 * @since 3.5.0
138
				 *
139
				 * @param string The search terms (comma separated).
140
				 */
141
				echo apply_filters( 'jetpack_search_terms_' . $module, $module_array['additional_search_queries'] );
142
				$module_array['search_terms'] = ob_get_clean();
143
144
				$module_array['configurable'] = false;
145
				if (
146
					current_user_can( 'manage_options' ) &&
147
					/**
148
					 * Allow the display of a configuration link in the Jetpack Settings screen.
149
					 *
150
					 * @since 3.0.0
151
					 *
152
					 * @param string $module Module name.
153
					 * @param bool false Should the Configure module link be displayed? Default to false.
154
					 */
155
					apply_filters( 'jetpack_module_configurable_' . $module, false )
156
				) {
157
					$module_array['configurable'] = sprintf( '<a href="%1$s">%2$s</a>', esc_url( Jetpack::module_configuration_url( $module ) ), __( 'Configure', 'jetpack' ) );
158
				}
159
160
				$modules[ $module ] = $module_array;
161
			}
162
		}
163
164
		uasort( $modules, array( $this->jetpack, 'sort_modules' ) );
165
166
		if ( ! Jetpack::is_active() ) {
167
			uasort( $modules, array( __CLASS__, 'sort_requires_connection_last' ) );
168
		}
169
170
		return $modules;
171
	}
172
173
	static function is_module_available( $module ) {
174
		if ( ! is_array( $module ) || empty( $module ) )
175
			return false;
176
177
		/**
178
		 * We never want to show VaultPress as activatable through Jetpack.
179
		 */
180
		if ( 'vaultpress' === $module['module'] ) {
181
			return false;
182
		}
183
184
		if ( Jetpack::is_development_mode() ) {
185
			return ! ( $module['requires_connection'] );
186
		} else {
187
			return Jetpack::is_active();
188
		}
189
	}
190
191
	function handle_unrecognized_action( $action ) {
192
		switch( $action ) {
193
			case 'bulk-activate' :
194
				if ( ! current_user_can( 'jetpack_activate_modules' ) ) {
195
					break;
196
				}
197
198
				$modules = (array) $_GET['modules'];
199
				$modules = array_map( 'sanitize_key', $modules );
200
				check_admin_referer( 'bulk-jetpack_page_jetpack_modules' );
201
				foreach( $modules as $module ) {
202
					Jetpack::log( 'activate', $module );
203
					Jetpack::activate_module( $module, false );
204
				}
205
				// The following two lines will rarely happen, as Jetpack::activate_module normally exits at the end.
206
				wp_safe_redirect( wp_get_referer() );
207
				exit;
0 ignored issues
show
Coding Style Compatibility introduced by
The method handle_unrecognized_action() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
208 View Code Duplication
			case 'bulk-deactivate' :
209
				if ( ! current_user_can( 'jetpack_deactivate_modules' ) ) {
210
					break;
211
				}
212
213
				$modules = (array) $_GET['modules'];
214
				$modules = array_map( 'sanitize_key', $modules );
215
				check_admin_referer( 'bulk-jetpack_page_jetpack_modules' );
216
				foreach ( $modules as $module ) {
217
					Jetpack::log( 'deactivate', $module );
218
					Jetpack::deactivate_module( $module );
219
					Jetpack::state( 'message', 'module_deactivated' );
220
				}
221
				Jetpack::state( 'module', $modules );
0 ignored issues
show
$modules is of type array, but the function expects a string|null.

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...
222
				wp_safe_redirect( wp_get_referer() );
223
				exit;
0 ignored issues
show
Coding Style Compatibility introduced by
The method handle_unrecognized_action() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
224
			default:
225
				return;
226
		}
227
	}
228
229
	function fix_redirect( $module, $redirect = true ) {
230
		if ( ! $redirect ) {
231
			return;
232
		}
233
		if ( wp_get_referer() ) {
234
			add_filter( 'wp_redirect', 'wp_get_referer' );
235
		}
236
	}
237
238
	function admin_menu_debugger() {
239
		Jetpack_Debugger::disconnect_and_redirect();
240
		$debugger_hook = add_submenu_page( null, __( 'Jetpack Debugging Center', 'jetpack' ), '', 'manage_options', 'jetpack-debugger', array( $this, 'debugger_page' ) );
241
		add_action( "admin_head-$debugger_hook", array( 'Jetpack_Debugger', 'jetpack_debug_admin_head' ) );
242
	}
243
244
	function debugger_page() {
245
		nocache_headers();
246
		if ( ! current_user_can( 'manage_options' ) ) {
247
			die( '-1' );
248
		}
249
		Jetpack_Debugger::jetpack_debug_display_handler();
250
	}
251
}
252
Jetpack_Admin::init();
253