Completed
Push — master-stable ( 9f5d88...ed6d22 )
by
unknown
59:24 queued 50:15
created

class.jetpack-admin.php (3 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;
29
30
		// TODO: reactify
0 ignored issues
show
Coding Style Best Practice introduced by
Comments for TODO tasks are often forgotten in the code; it might be better to use a dedicated issue tracker.
Loading history...
31
		require_once JETPACK__PLUGIN_DIR . 'sync/class.jetpack-sync-dashboard.php';
32
		$this->sync_dashboard = new Jetpack_Sync_Dashboard;
0 ignored issues
show
The property sync_dashboard does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

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