Completed
Push — update/editor-blocks-icon-colo... ( 093ab2...3cfb5e )
by
unknown
08:47
created

class.jetpack-modules-list-table.php (1 issue)

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
use Automattic\Jetpack\Assets;
4
5
if ( ! class_exists( 'WP_List_Table' ) ) {
6
	require_once ABSPATH . 'wp-admin/includes/class-wp-list-table.php';
7
}
8
9
class Jetpack_Modules_List_Table extends WP_List_Table {
10
11
	function __construct() {
12
		parent::__construct();
13
14
		Jetpack::init();
15
16
		if ( $this->compat_fields && is_array( $this->compat_fields ) ) {
17
			array_push( $this->compat_fields, 'all_items' );
18
		}
19
20
		$this->items = $this->all_items = Jetpack_Admin::init()->get_modules();
21
		$this->items = $this->filter_displayed_table_items( $this->items );
22
		/**
23
		 * Filters the list of modules available to be displayed in the Jetpack Settings screen.
24
		 *
25
		 * @since 3.0.0
26
		 *
27
		 * @param array $this->items Array of Jetpack modules.
28
		 */
29
		$this->items           = apply_filters( 'jetpack_modules_list_table_items', $this->items );
30
		$this->_column_headers = array( $this->get_columns(), array(), array(), 'name' );
31
		$modal_info            = isset( $_GET['info'] ) ? $_GET['info'] : false;
32
33
		wp_register_script(
34
			'models.jetpack-modules',
35
			Assets::get_file_url_for_environment(
36
				'_inc/build/jetpack-modules.models.min.js',
37
				'_inc/jetpack-modules.models.js'
38
			),
39
			array( 'backbone', 'underscore' ),
40
			JETPACK__VERSION
41
		);
42
		wp_register_script(
43
			'views.jetpack-modules',
44
			Assets::get_file_url_for_environment(
45
				'_inc/build/jetpack-modules.views.min.js',
46
				'_inc/jetpack-modules.views.js'
47
			),
48
			array( 'backbone', 'underscore', 'wp-util' ),
49
			JETPACK__VERSION
50
		);
51
		wp_register_script(
52
			'jetpack-modules-list-table',
53
			Assets::get_file_url_for_environment(
54
				'_inc/build/jetpack-modules.min.js',
55
				'_inc/jetpack-modules.js'
56
			),
57
			array(
58
				'views.jetpack-modules',
59
				'models.jetpack-modules',
60
				'jquery',
61
			),
62
			JETPACK__VERSION,
63
			true
64
		);
65
66
		wp_localize_script(
67
			'jetpack-modules-list-table',
68
			'jetpackModulesData',
69
			array(
70
				'modules'   => Jetpack::get_translated_modules( $this->all_items ),
71
				'i18n'      => array(
72
					'search_placeholder' => __( 'Search Modules…', 'jetpack' ),
73
				),
74
				'modalinfo' => $this->module_info_check( $modal_info, $this->all_items ),
75
				'nonces'    => array(
76
					'bulk' => wp_create_nonce( 'bulk-jetpack_page_jetpack_modules' ),
77
				),
78
			)
79
		);
80
81
		wp_enqueue_script( 'jetpack-modules-list-table' );
82
83
		/**
84
		 * Filters the js_templates callback value.
85
		 *
86
		 * @since 3.6.0
87
		 *
88
		 * @param array array( $this, 'js_templates' ) js_templates callback.
89
		 */
90
		add_action( 'admin_footer', apply_filters( 'jetpack_modules_list_table_js_template_callback', array( $this, 'js_templates' ) ), 9 );
91
	}
92
93
	function js_templates() {
94
		?>
95
		<script type="text/html" id="tmpl-Jetpack_Modules_List_Table_Template">
96
			<# var i = 0;
97
			if ( data.items.length ) {
98
			_.each( data.items, function( item, key, list ) {
99
				if ( item === undefined ) return; #>
100
				<tr class="jetpack-module <# if ( ++i % 2 ) { #> alternate<# } #><# if ( item.activated ) { #> active<# } #><# if ( ! item.available ) { #> unavailable<# } #>" id="{{{ item.module }}}">
101
					<th scope="row" class="check-column">
102
						<# if ( 'videopress' !== item.module ) { #>
103
						<input type="checkbox" name="modules[]" value="{{{ item.module }}}" />
104
						<# } #>
105
					</th>
106
					<td class='name column-name'>
107
						<span class='info'><a href="{{{item.learn_more_button}}}" target="blank">{{{ item.name }}}</a></span>
108
						<div class="row-actions">
109
						<# if ( item.configurable ) { #>
110
							<span class='configure'>{{{ item.configurable }}}</span>
111
						<# } #>
112
						<# if ( item.activated && 'vaultpress' !== item.module && item.available && 'videopress' !== item.module ) { #>
113
							<span class='delete'><a href="<?php echo admin_url( 'admin.php' ); ?>?page=jetpack&#038;action=deactivate&#038;module={{{ item.module }}}&#038;_wpnonce={{{ item.deactivate_nonce }}}"><?php _e( 'Deactivate', 'jetpack' ); ?></a></span>
114
						<# } else if ( item.available && 'videopress' !== item.module ) { #>
115
							<span class='activate'><a href="<?php echo admin_url( 'admin.php' ); ?>?page=jetpack&#038;action=activate&#038;module={{{ item.module }}}&#038;_wpnonce={{{ item.activate_nonce }}}"><?php _e( 'Activate', 'jetpack' ); ?></a></span>
116
						<# } #>
117
						</div>
118
					</td>
119
				</tr>
120
				<#
121
			});
122
			} else {
123
				#>
124
				<tr class="no-modules-found">
125
					<td colspan="2"><?php esc_html_e( 'No Modules Found', 'jetpack' ); ?></td>
126
				</tr>
127
				<#
128
			}
129
			#>
130
		</script>
131
		<?php
132
	}
133
134
	function get_views() {
135
		$modules              = Jetpack_Admin::init()->get_modules();
136
		$array_of_module_tags = wp_list_pluck( $modules, 'module_tags' );
137
		$module_tags          = call_user_func_array( 'array_merge', $array_of_module_tags );
138
		$module_tags_unique   = array_count_values( $module_tags );
139
		ksort( $module_tags_unique );
140
141
		$format  = '<a href="%3$s"%4$s data-title="%1$s">%1$s <span class="count">(%2$s)</span></a>';
142
		$title   = __( 'All', 'jetpack' );
143
		$count   = count( $modules );
144
		$url     = esc_url( remove_query_arg( 'module_tag' ) );
145
		$current = empty( $_GET['module_tag'] ) ? ' class="current all"' : ' class="all"';
146
		$views   = array(
147
			'all' => sprintf( $format, $title, $count, $url, $current ),
148
		);
149
		foreach ( $module_tags_unique as $title => $count ) {
150
			$key           = sanitize_title( $title );
151
			$display_title = esc_html( wptexturize( $title ) );
152
			$url           = esc_url( add_query_arg( 'module_tag', urlencode( $title ) ) );
153
			$current       = '';
154
			if ( ! empty( $_GET['module_tag'] ) && $title == $_GET['module_tag'] ) {
155
				$current = ' class="current"';
156
			}
157
			$views[ $key ] = sprintf( $format, $display_title, $count, $url, $current );
158
		}
159
		return $views;
160
	}
161
162
	function views() {
163
		$views = $this->get_views();
164
165
		echo "<ul class='subsubsub'>\n";
166
		foreach ( $views as $class => $view ) {
167
			$views[ $class ] = "\t<li class='$class'>$view</li>";
168
		}
169
		echo implode( "\n", $views ) . "\n";
170
		echo '</ul>';
171
	}
172
173
	function filter_displayed_table_items( $modules ) {
174
		return array_filter( $modules, array( $this, 'is_module_displayed' ) );
175
	}
176
177
	static function is_module_displayed( $module ) {
178
		// Handle module tag based filtering.
179
		if ( ! empty( $_REQUEST['module_tag'] ) ) {
180
			$module_tag = sanitize_text_field( $_REQUEST['module_tag'] );
181
			if ( ! in_array( $module_tag, $module['module_tags'] ) ) {
182
				return false;
183
			}
184
		}
185
186
		// If nothing rejected it, include it!
187
		return true;
188
	}
189
190 View Code Duplication
	static function sort_requires_connection_last( $module1, $module2 ) {
191
		if ( $module1['requires_connection'] == $module2['requires_connection'] ) {
192
			return 0;
193
		}
194
		if ( $module1['requires_connection'] ) {
195
			return 1;
196
		}
197
		if ( $module2['requires_connection'] ) {
198
			return -1;
199
		}
200
201
		return 0;
202
	}
203
204
	function get_columns() {
205
		$columns = array(
206
			'cb'   => '<input type="checkbox" />',
207
			'name' => __( 'Name', 'jetpack' ),
208
		);
209
		return $columns;
210
	}
211
212
	function get_bulk_actions() {
213
		$actions = array(
214
			'bulk-activate'   => __( 'Activate', 'jetpack' ),
215
			'bulk-deactivate' => __( 'Deactivate', 'jetpack' ),
216
		);
217
		return $actions;
218
	}
219
220
	function single_row( $item ) {
221
		static $i  = 0;
222
		$row_class = ( ++$i % 2 ) ? ' alternate' : '';
223
224
		if ( ! empty( $item['activated'] ) ) {
225
			$row_class .= ' active';
226
		}
227
228
		if ( ! Jetpack_Admin::is_module_available( $item ) ) {
229
			$row_class .= ' unavailable';
230
		}
231
232
		echo '<tr class="jetpack-module' . esc_attr( $row_class ) . '" id="' . esc_attr( $item['module'] ) . '">';
233
		$this->single_row_columns( $item );
234
		echo '</tr>';
235
	}
236
237
	function get_table_classes() {
238
		return array( 'table', 'table-bordered', 'wp-list-table', 'widefat', 'fixed', 'jetpack-modules' );
239
	}
240
241
	function column_cb( $item ) {
242
		if ( ! Jetpack_Admin::is_module_available( $item ) ) {
243
			return '';
244
		}
245
246
		return sprintf( '<input type="checkbox" name="modules[]" value="%s" />', $item['module'] );
247
	}
248
249
	function column_icon( $item ) {
250
		$badge_text = $free_text = '';
251
		ob_start();
252
		?>
253
		<a href="#TB_inline?width=600&height=550&inlineId=more-info-module-settings-modal" class="thickbox">
254
			<div class="module-image">
255
				<p><span class="module-image-badge"><?php echo $badge_text; ?></span><span class="module-image-free" style="display: none"><?php echo $free_text; ?></span></p>
256
			</div>
257
		</a>
258
		<?php
259
		return ob_get_clean();
260
261
	}
262
263
	function column_name( $item ) {
264
		$actions = array(
265
			'info' => sprintf( '<a href="%s" target="blank">%s</a>', esc_url( $item['learn_more_button'] ), esc_html__( 'Feature Info', 'jetpack' ) ),
266
		);
267
268
		if ( ! empty( $item['configurable'] ) ) {
269
			$actions['configure'] = $item['configurable'];
270
		}
271
272
		if ( empty( $item['activated'] ) && Jetpack_Admin::is_module_available( $item ) ) {
273
			$url                 = wp_nonce_url(
274
				Jetpack::admin_url(
275
					array(
276
						'page'   => 'jetpack',
277
						'action' => 'activate',
278
						'module' => $item['module'],
279
					)
280
				),
281
				'jetpack_activate-' . $item['module']
282
			);
283
			$actions['activate'] = sprintf( '<a href="%s">%s</a>', esc_url( $url ), esc_html__( 'Activate', 'jetpack' ) );
284
		} elseif ( ! empty( $item['activated'] ) ) {
285
			$url               = wp_nonce_url(
286
				Jetpack::admin_url(
287
					array(
288
						'page'   => 'jetpack',
289
						'action' => 'deactivate',
290
						'module' => $item['module'],
291
					)
292
				),
293
				'jetpack_deactivate-' . $item['module']
294
			);
295
			$actions['delete'] = sprintf( '<a href="%s">%s</a>', esc_url( $url ), esc_html__( 'Deactivate', 'jetpack' ) );
296
		}
297
298
		return $this->row_actions( $actions ) . wptexturize( $item['name'] );
299
	}
300
301
	function column_description( $item ) {
302
		ob_start();
303
		/** This action is documented in class.jetpack-admin.php */
304
		echo apply_filters( 'jetpack_short_module_description', $item['description'], $item['module'] );
0 ignored issues
show
The call to apply_filters() has too many arguments starting with $item['module'].

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
305
		/** This action is documented in class.jetpack-admin.php */
306
		do_action( 'jetpack_learn_more_button_' . $item['module'] );
307
		echo '<div id="more-info-' . $item['module'] . '" class="more-info">';
308
		/** This action is documented in class.jetpack-admin.php */
309
		do_action( 'jetpack_module_more_info_' . $item['module'] );
310
		echo '</div>';
311
		return ob_get_clean();
312
	}
313
314
	function column_module_tags( $item ) {
315
		$module_tags = array();
316
		foreach ( $item['module_tags'] as $module_tag ) {
317
			$module_tags[] = sprintf( '<a href="%3$s" data-title="%2$s">%1$s</a>', esc_html( $module_tag ), esc_attr( $module_tag ), esc_url( add_query_arg( 'module_tag', urlencode( $module_tag ) ) ) );
318
		}
319
		return implode( ', ', $module_tags );
320
	}
321
322
	function column_default( $item, $column_name ) {
323
		switch ( $column_name ) {
324
			case 'icon':
325
			case 'name':
326
			case 'description':
327
				break;
328
			default:
329
				return print_r( $item, true );
330
		}
331
	}
332
333
	// Check if the info parameter provided in the URL corresponds to an actual module
334
	function module_info_check( $info = false, $modules ) {
335
		if ( false == $info ) {
336
			return false;
337
		} elseif ( array_key_exists( $info, $modules ) ) {
338
			return $info;
339
		}
340
	}
341
342
	/**
343
	 * Core switched their `display_tablenav()` method to protected, so we can't access it directly.
344
	 * Instead, let's include an access function to make it doable without errors!
345
	 *
346
	 * @see https://github.com/WordPress/WordPress/commit/d28f6344de97616de8ece543ed290c4ba2383622
347
	 *
348
	 * @param string $which
349
	 *
350
	 * @return mixed
351
	 */
352
	function unprotected_display_tablenav( $which = 'top' ) {
353
		return $this->display_tablenav( $which );
354
	}
355
356
}
357