Completed
Push — update/dialogue-focus-on-conte... ( 9f1745...fa862f )
by
unknown
80:03 queued 71:18
created

Jetpack_Modules_List_Table::views()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
nc 2
nop 0
dl 0
loc 10
rs 9.9332
c 0
b 0
f 0
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
		/**
21
		 * Filters the list of modules available to be displayed in the Jetpack Settings screen.
22
		 *
23
		 * @since 3.0.0
24
		 *
25
		 * @param array $modules Array of Jetpack modules.
26
		 */
27
		$this->all_items       = apply_filters( 'jetpack_modules_list_table_items', Jetpack_Admin::init()->get_modules() );
28
		$this->items           = $this->all_items;
29
		$this->items           = $this->filter_displayed_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
		/** This filter is already documented in class.jetpack-modules-list-table.php */
136
		$modules              = apply_filters( 'jetpack_modules_list_table_items', Jetpack_Admin::init()->get_modules() );
137
		$array_of_module_tags = wp_list_pluck( $modules, 'module_tags' );
138
		$module_tags          = array_merge( ...array_values( $array_of_module_tags ) );
139
		$module_tags_unique   = array_count_values( $module_tags );
140
		ksort( $module_tags_unique );
141
142
		$format  = '<a href="%3$s"%4$s data-title="%1$s">%1$s <span class="count">(%2$s)</span></a>';
143
		$title   = __( 'All', 'jetpack' );
144
		$count   = count( $modules );
145
		$url     = esc_url( remove_query_arg( 'module_tag' ) );
146
		$current = empty( $_GET['module_tag'] ) ? ' class="current all"' : ' class="all"';
147
		$views   = array(
148
			'all' => sprintf( $format, $title, $count, $url, $current ),
149
		);
150
		foreach ( $module_tags_unique as $title => $count ) {
151
			$key           = sanitize_title( $title );
152
			$display_title = esc_html( wptexturize( $title ) );
153
			$url           = esc_url( add_query_arg( 'module_tag', urlencode( $title ) ) );
154
			$current       = '';
155
			if ( ! empty( $_GET['module_tag'] ) && $title == $_GET['module_tag'] ) {
156
				$current = ' class="current"';
157
			}
158
			$views[ $key ] = sprintf( $format, $display_title, $count, $url, $current );
159
		}
160
		return $views;
161
	}
162
163
	function views() {
164
		$views = $this->get_views();
165
166
		echo "<ul class='subsubsub'>\n";
167
		foreach ( $views as $class => $view ) {
168
			$views[ $class ] = "\t<li class='$class'>$view</li>";
169
		}
170
		echo implode( "\n", $views ) . "\n";
171
		echo '</ul>';
172
	}
173
174
	function filter_displayed_table_items( $modules ) {
175
		return array_filter( $modules, array( $this, 'is_module_displayed' ) );
176
	}
177
178
	static function is_module_displayed( $module ) {
179
		// Handle module tag based filtering.
180
		if ( ! empty( $_REQUEST['module_tag'] ) ) {
181
			$module_tag = sanitize_text_field( $_REQUEST['module_tag'] );
182
			if ( ! in_array( $module_tag, $module['module_tags'] ) ) {
183
				return false;
184
			}
185
		}
186
187
		// If nothing rejected it, include it!
188
		return true;
189
	}
190
191 View Code Duplication
	static function sort_requires_connection_last( $module1, $module2 ) {
192
		if ( $module1['requires_connection'] == $module2['requires_connection'] ) {
193
			return 0;
194
		}
195
		if ( $module1['requires_connection'] ) {
196
			return 1;
197
		}
198
		if ( $module2['requires_connection'] ) {
199
			return -1;
200
		}
201
202
		return 0;
203
	}
204
205
	function get_columns() {
206
		$columns = array(
207
			'cb'   => '<input type="checkbox" />',
208
			'name' => __( 'Name', 'jetpack' ),
209
		);
210
		return $columns;
211
	}
212
213
	function get_bulk_actions() {
214
		$actions = array(
215
			'bulk-activate'   => __( 'Activate', 'jetpack' ),
216
			'bulk-deactivate' => __( 'Deactivate', 'jetpack' ),
217
		);
218
		return $actions;
219
	}
220
221
	function single_row( $item ) {
222
		static $i  = 0;
223
		$row_class = ( ++$i % 2 ) ? ' alternate' : '';
224
225
		if ( ! empty( $item['activated'] ) ) {
226
			$row_class .= ' active';
227
		}
228
229
		if ( ! Jetpack_Admin::is_module_available( $item ) ) {
230
			$row_class .= ' unavailable';
231
		}
232
233
		echo '<tr class="jetpack-module' . esc_attr( $row_class ) . '" id="' . esc_attr( $item['module'] ) . '">';
234
		$this->single_row_columns( $item );
235
		echo '</tr>';
236
	}
237
238
	function get_table_classes() {
239
		return array( 'table', 'table-bordered', 'wp-list-table', 'widefat', 'fixed', 'jetpack-modules' );
240
	}
241
242
	function column_cb( $item ) {
243
		if ( ! Jetpack_Admin::is_module_available( $item ) ) {
244
			return '';
245
		}
246
247
		return sprintf( '<input type="checkbox" name="modules[]" value="%s" />', $item['module'] );
248
	}
249
250
	function column_icon( $item ) {
251
		$badge_text = $free_text = '';
252
		ob_start();
253
		?>
254
		<a href="#TB_inline?width=600&height=550&inlineId=more-info-module-settings-modal" class="thickbox">
255
			<div class="module-image">
256
				<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>
257
			</div>
258
		</a>
259
		<?php
260
		return ob_get_clean();
261
262
	}
263
264
	function column_name( $item ) {
265
		$actions = array(
266
			'info' => sprintf( '<a href="%s" target="blank">%s</a>', esc_url( $item['learn_more_button'] ), esc_html__( 'Feature Info', 'jetpack' ) ),
267
		);
268
269
		if ( ! empty( $item['configurable'] ) ) {
270
			$actions['configure'] = $item['configurable'];
271
		}
272
273
		if ( empty( $item['activated'] ) && Jetpack_Admin::is_module_available( $item ) ) {
274
			$url                 = wp_nonce_url(
275
				Jetpack::admin_url(
276
					array(
277
						'page'   => 'jetpack',
278
						'action' => 'activate',
279
						'module' => $item['module'],
280
					)
281
				),
282
				'jetpack_activate-' . $item['module']
283
			);
284
			$actions['activate'] = sprintf( '<a href="%s">%s</a>', esc_url( $url ), esc_html__( 'Activate', 'jetpack' ) );
285
		} elseif ( ! empty( $item['activated'] ) ) {
286
			$url               = wp_nonce_url(
287
				Jetpack::admin_url(
288
					array(
289
						'page'   => 'jetpack',
290
						'action' => 'deactivate',
291
						'module' => $item['module'],
292
					)
293
				),
294
				'jetpack_deactivate-' . $item['module']
295
			);
296
			$actions['delete'] = sprintf( '<a href="%s">%s</a>', esc_url( $url ), esc_html__( 'Deactivate', 'jetpack' ) );
297
		}
298
299
		return $this->row_actions( $actions ) . wptexturize( $item['name'] );
300
	}
301
302
	function column_description( $item ) {
303
		ob_start();
304
		/** This action is documented in class.jetpack-admin.php */
305
		echo apply_filters( 'jetpack_short_module_description', $item['description'], $item['module'] );
0 ignored issues
show
Unused Code introduced by
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...
306
		/** This action is documented in class.jetpack-admin.php */
307
		do_action( 'jetpack_learn_more_button_' . $item['module'] );
308
		echo '<div id="more-info-' . $item['module'] . '" class="more-info">';
309
		/** This action is documented in class.jetpack-admin.php */
310
		do_action( 'jetpack_module_more_info_' . $item['module'] );
311
		echo '</div>';
312
		return ob_get_clean();
313
	}
314
315
	function column_module_tags( $item ) {
316
		$module_tags = array();
317
		foreach ( $item['module_tags'] as $module_tag ) {
318
			$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 ) ) ) );
319
		}
320
		return implode( ', ', $module_tags );
321
	}
322
323
	function column_default( $item, $column_name ) {
324
		switch ( $column_name ) {
325
			case 'icon':
326
			case 'name':
327
			case 'description':
328
				break;
329
			default:
330
				return print_r( $item, true );
331
		}
332
	}
333
334
	// Check if the info parameter provided in the URL corresponds to an actual module
335
	function module_info_check( $info, $modules ) {
336
		if ( false == $info ) {
337
			return false;
338
		} elseif ( array_key_exists( $info, $modules ) ) {
339
			return $info;
340
		}
341
	}
342
343
	/**
344
	 * Core switched their `display_tablenav()` method to protected, so we can't access it directly.
345
	 * Instead, let's include an access function to make it doable without errors!
346
	 *
347
	 * @see https://github.com/WordPress/WordPress/commit/d28f6344de97616de8ece543ed290c4ba2383622
348
	 *
349
	 * @param string $which
350
	 *
351
	 * @return mixed
352
	 */
353
	function unprotected_display_tablenav( $which = 'top' ) {
354
		return $this->display_tablenav( $which );
355
	}
356
357
}
358