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

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
319
			return false;
320
		} else if ( array_key_exists( $info, $modules ) ) {
321
			return $info;
322
		}
323
	}
324
325
	/**
326
	 * Core switched their `display_tablenav()` method to protected, so we can't access it directly.
327
	 * Instead, let's include an access function to make it doable without errors!
328
	 *
329
	 * @see https://github.com/WordPress/WordPress/commit/d28f6344de97616de8ece543ed290c4ba2383622
330
	 *
331
	 * @param string $which
332
	 *
333
	 * @return mixed
334
	 */
335
	function unprotected_display_tablenav( $which = 'top' ) {
336
		return $this->display_tablenav( $which );
337
	}
338
339
}
340