PluginProbe ʕ •ᴥ•ʔ
Code Manager / 1.0.27
Code Manager v1.0.27
1.0.47 trunk 1.0.0 1.0.1 1.0.10 1.0.11 1.0.12 1.0.13 1.0.14 1.0.15 1.0.16 1.0.17 1.0.18 1.0.19 1.0.2 1.0.20 1.0.21 1.0.22 1.0.23 1.0.24 1.0.25 1.0.26 1.0.27 1.0.28 1.0.3 1.0.30 1.0.31 1.0.32 1.0.33 1.0.34 1.0.35 1.0.36 1.0.37 1.0.38 1.0.39 1.0.4 1.0.40 1.0.41 1.0.42 1.0.43 1.0.44 1.0.45 1.0.46 1.0.5 1.0.6 1.0.7 1.0.8 1.0.9
code-manager / Code_Manager / Code_Manager_List.php
code-manager / Code_Manager Last commit date
Code_Manager.php 2 years ago Code_Manager_Dashboard.php 2 years ago Code_Manager_Export.php 2 years ago Code_Manager_Form.php 2 years ago Code_Manager_Import.php 2 years ago Code_Manager_Import_File.php 2 years ago Code_Manager_List.php 2 years ago Code_Manager_List_View.php 2 years ago Code_Manager_Model.php 2 years ago Code_Manager_Preview.php 2 years ago Code_Manager_Settings.php 2 years ago Code_Manager_Tabs.php 2 years ago Message_Box.php 2 years ago WP_List_Table.php 2 years ago
Code_Manager_List.php
1058 lines
1 <?php
2 /**
3 * Code Manager list mode
4 *
5 * @package Code_Manager
6 */
7
8 namespace Code_Manager {
9
10 /**
11 * Class Code_Manager
12 *
13 * Implements list mode view for Code Manager. Extends WordPress class WP_List_Table.
14 *
15 * @author Peter Schulz
16 * @since 1.0.0
17 */
18 class Code_Manager_List extends WP_List_Table {
19
20 /**
21 * Row number in the list
22 *
23 * @var int
24 */
25 protected static $list_number = 0;
26
27 /**
28 * Sortable columns
29 *
30 * @var array[]
31 */
32 protected static $sortable_columns = array(
33 'code_id' => array( 'code_id', false ),
34 'code_name' => array( 'code_name', false ),
35 'code_type' => array( 'code_type', false ),
36 'code_enabled' => array( 'code_type', false ),
37 'code_author' => array( 'code_author', false ),
38 'code_description' => array( 'code_description', false ),
39 );
40
41 /**
42 * Code types
43 *
44 * @var array
45 */
46 protected $code_types = array();
47
48 /**
49 * WP nonce to (de)activate preview mode for a specific code id
50 *
51 * @var string
52 */
53 protected $wpnonce;
54
55 /**
56 * Constructor
57 *
58 * @param array $args Constructor arguments.
59 */
60 public function __construct( $args = array() ) {
61 parent::__construct( $args );
62
63 $this->wpnonce = wp_create_nonce( 'code-manager-' . Code_manager::get_current_user_login() );
64 $code_manager_tabs_class = CODE_MANAGER_TAB_CLASS;
65 $code_manager_tabs = new $code_manager_tabs_class();
66 $code_type_groups = $code_manager_tabs->get_code_types();
67 foreach ( $code_type_groups as $code_type_group ) {
68 foreach ( $code_type_group as $key => $value ) {
69 $this->code_types[ $key ] = $value;
70 }
71 }
72 }
73
74 /**
75 * Show list table
76 *
77 * @since 1.0.0
78 */
79 public function show() {
80 ?>
81 <div class="wrap">
82 <?php
83 $this->show_title();
84 $this->show_body();
85 ?>
86 </div>
87 <script type="text/javascript">
88 var wpnonce = '<?php echo esc_attr( $this->wpnonce ); ?>';
89 jQuery(function () {
90 jQuery('#cb-select-all-1').on('click', function (event) {
91 if (jQuery('#cb-select-all-1').is(':checked')) {
92 jQuery('[name="bulk-selected[]"]').prop('checked', true);
93 jQuery('#cb-select-all-2').prop('checked', true);
94 } else {
95 jQuery('[name="bulk-selected[]"]').prop('checked', false);
96 jQuery('#cb-select-all-2').prop('checked', false);
97 }
98 });
99 jQuery('#cb-select-all-2').on('click', function (event) {
100 if (jQuery('#cb-select-all-2').is(':checked')) {
101 jQuery('[name="bulk-selected[]"]').prop('checked', true);
102 jQuery('#cb-select-all-1').prop('checked', true);
103 } else {
104 jQuery('[name="bulk-selected[]"]').prop('checked', false);
105 jQuery('#cb-select-all-1').prop('checked', false);
106 }
107 });
108 });
109 </script>
110 <?php
111 }
112
113 /**
114 * Add title to page
115 *
116 * @since 1.0.0
117 */
118 protected function show_title() {
119 ?>
120 <h1 class="wp-heading-inline">
121 <?php echo CODE_MANAGER_H1_TITLE . ' - list mode'; ?>
122 </h1>
123 <?php
124 }
125
126 /**
127 * Add page body
128 *
129 * JavaScript depending on server variables not available in the browser are added here. Generic JavaScript
130 * code is added as a script file.
131 *
132 * @since 1.0.0
133 */
134 protected function show_body() {
135 $code_manager_selected_code_type = '';
136 if ( isset( $_REQUEST['selected_code_type'] ) ) {
137 $code_manager_selected_code_type = sanitize_text_field( wp_unslash( $_REQUEST['selected_code_type'] ) );
138 } elseif ( isset( $_COOKIE[ CODE_MANAGER_COOKIES_LIST ] ) ) {
139 $code_manager_selected_code_type = sanitize_text_field( wp_unslash( $_COOKIE[ CODE_MANAGER_COOKIES_LIST ] ) );
140 }
141
142 $this->add_import_container();
143 ?>
144 <iframe id="cm_stealth_mode" style="display:none;"></iframe>
145 <div id="cm_invisible_container" style="display:none;"></div>
146 <div>
147 <form id="cm_list_table" method="post" action="?page=<?php echo CODE_MANAGER_MENU_SLUG; ?>">
148 <?php
149 $this->show_form();
150 ?>
151 </form>
152 </div>
153 <script type="text/javascript">
154 var code_manager_code_groups = [];
155 <?php
156 $code_manager_tab_class = CODE_MANAGER_TAB_CLASS;
157 $code_manager_tab = new $code_manager_tab_class();
158 $code_types = $code_manager_tab->get_code_types();
159 foreach ( $code_types as $code_type_group => $value ) {
160 echo 'code_manager_code_group = [];';
161 foreach ( $value as $code_type => $code_type_label ) {
162 echo "code_manager_code_group['" . esc_attr( $code_type ) . "'] = '" . esc_attr( $code_type_label ) . "';";
163 }
164 echo "code_manager_code_groups['" . esc_attr( $code_type_group ) . "'] = code_manager_code_group;";
165 }
166 ?>
167 var code_manager_selected_code_type = '<?php echo esc_attr( $code_manager_selected_code_type ); ?>';
168 </script>
169 <?php
170 }
171
172 /**
173 * Add form to page (including search box)
174 *
175 * @since 1.0.0
176 */
177 protected function show_form() {
178 $this->prepare_items();
179 $this->search_box( 'search', 'search_id' );
180 $this->display();
181 wp_nonce_field( 'code-manager-export' . Code_manager::get_current_user_login(), '_expnonce', false );
182 wp_nonce_field( 'code-manager-delete' . Code_manager::get_current_user_login(), '_delnonce', false );
183 }
184
185 /**
186 * Add import container to list table
187 *
188 * @since 1.0.0
189 */
190 public function add_import_container() {
191 $file_uploads_enabled = @ini_get( 'file_uploads' );
192 ?>
193 <script type='text/javascript'>
194 function before_submit_upload() {
195 if (jQuery('#filename').val() == '') {
196 alert('<?php echo __( 'No file to import!', 'code-manager' ); ?>');
197 return false;
198 }
199 if (!(jQuery('#filename')[0].files[0].size < <?php echo Code_Manager_Export::convert_memory_to_decimal( @ini_get( 'upload_max_filesize' ) ); ?>)) {
200 alert("<?php echo __( 'File exceeds maximum size of', 'code-manager' ); ?> <?php echo @ini_get( 'upload_max_filesize' ); ?>!");
201 return false;
202 }
203 }
204 </script>
205 <style>
206 .cm_upload {
207 background: #fff;
208 border-top: 1px solid #ccc;
209 border-bottom: 1px solid #ccc;
210 padding-left: 20px;
211 padding-bottom: 10px;
212 }
213 </style>
214 <div id="upload_file_container" style="display: none">
215 <br/>
216 <div class="cm_upload">
217 <?php if ( $file_uploads_enabled ) { ?>
218 <p>
219 <strong><?php echo __( 'IMPORTS CODE MANAGER DATA ONLY', 'code-manager' ); ?></strong>
220 </p>
221 <p>
222 <?php
223 echo __( 'Supports only file type', 'code-manager' ) .
224 ' <strong>sql</strong>. ' .
225 __( 'Maximum supported file size is', 'code-manager' ) .
226 ' <strong>' . @ini_get( 'upload_max_filesize' ) . '</strong>.';
227 ?>
228 </p>
229 <form id="form_import_table" method="post" enctype="multipart/form-data">
230 <input type="file" name="filename" id="filename" accept=".sql">
231 <input type="submit" value="<?php echo __( 'Import file', 'code-manager' ); ?>"
232 class="button button-secondary"
233 onclick="return before_submit_upload()">
234 <input type="button"
235 onclick="jQuery('#upload_file_container').hide()"
236 class="button button-secondary"
237 value="<?php echo __( 'Cancel', 'code-manager' ); ?>">
238 <input type="hidden" name="action" value="import">
239 <?php wp_nonce_field( 'code-manager-import' . Code_manager::get_current_user_login(), '_impnonce', false ); ?>
240 </form>
241 <?php } else { ?>
242 <p>
243 <strong><?php echo __( 'ERROR', 'code-manager' ); ?></strong>
244 </p>
245 <p>
246 <?php
247 echo __( 'Your configuration does not allow file uploads!', 'code-manager' );
248 echo ' ';
249 echo __( 'Set', 'code-manager' );
250 echo ' <strong>';
251 echo __( 'file_uploads', 'code-manager' );
252 echo '</strong> ';
253 echo __( 'to', 'code-manager' );
254 echo ' <strong>';
255 echo __( 'On', 'code-manager' );
256 echo '.';
257 echo '</strong>';
258 ?>
259 </p>
260 <?php } ?>
261 </div>
262 <div>&nbsp;</div>
263 </div>
264 <?php
265 }
266
267 /**
268 * Perform database query
269 *
270 * Called from method prepare_items().
271 *
272 * @since 1.0.0
273 *
274 * @param int $per_page Items shown per page.
275 * @param int $page_number Current page number.
276 *
277 * @return array Contains rows found.
278 */
279 public static function get_codes( $per_page = 10, $page_number = 1 ) {
280 global $wpdb;
281
282 $where = '';
283
284 $selected_code_type = '';
285 if ( isset( $_REQUEST['selected_code_type'] ) && '' !== $_REQUEST['selected_code_type'] ) {
286 if ( '*' === $_REQUEST['selected_code_type'] ) {
287 $selected_code_type = '';
288 } else {
289 $selected_code_type = sanitize_text_field( wp_unslash( $_REQUEST['selected_code_type'] ) ); // input var okay.
290 }
291 } elseif ( isset( $_COOKIE[ CODE_MANAGER_COOKIES_LIST ] ) ) {
292 if ( '*' === $_COOKIE[ CODE_MANAGER_COOKIES_LIST ] ) {
293 $selected_code_type = '';
294 } else {
295 $selected_code_type = sanitize_text_field( wp_unslash( $_COOKIE[ CODE_MANAGER_COOKIES_LIST ] ) );
296 }
297 }
298 if ( '' !== $selected_code_type ) {
299 $where .= $wpdb->prepare(
300 ' where `code_type` = %s',
301 array(
302 $selected_code_type,
303 )
304 ); // phpcs:ignore Standard.Category.SniffName.ErrorCode.
305 }
306
307 $search_value = '';
308 if ( isset( $_REQUEST[ CODE_MANAGER_SEARCH_ITEM_NAME ] ) ) {
309 $search_value = sanitize_text_field( wp_unslash( $_REQUEST[ CODE_MANAGER_SEARCH_ITEM_NAME ] ) ); // input var okay.
310 } elseif ( isset( $_COOKIE[ CODE_MANAGER_COOKIES_SEARCH ] ) ) {
311 $search_value = sanitize_text_field( wp_unslash( $_COOKIE[ CODE_MANAGER_COOKIES_SEARCH ] ) );
312 }
313 if ( '' !== $search_value ) {
314 $prepare_where =
315 ( '' === $where ? ' where ' : ' and ' ) .
316 " (`code_name` like '%s' " .
317 " or `code_type` like '%s' " .
318 " or `code` like '%s' ) ";
319 $where .= $wpdb->prepare(
320 $prepare_where,
321 array(
322 '%' . esc_sql( $search_value ) . '%',
323 '%' . esc_sql( $search_value ) . '%',
324 '%' . esc_sql( $search_value ) . '%',
325 )
326 ); // phpcs:ignore Standard.Category.SniffName.ErrorCode.
327 }
328
329 $code_manager_model_class = CODE_MANAGER_MODEL_CLASS;
330 $code_manager_model = new $code_manager_model_class();
331 $sql = 'select * from ' . $code_manager_model::get_base_table_name();
332 if ( '' !== $where ) {
333 $sql .= $where;
334 }
335 if ( ! empty( $_REQUEST['orderby'] ) && isset( self::$sortable_columns[ $_REQUEST['orderby'] ] ) ) {
336 // To prevent SQL injection $_REQUEST['orderby'] is checked against available sortable columns.
337 // sanitize_sql_orderby unnecessary: sanitization already handled on line 336.
338 $sql .= ' ORDER BY ' . sanitize_sql_orderby( wp_unslash( $_REQUEST['orderby'] ) );
339 $sql .= ! empty( $_REQUEST['order'] ) && 'asc' !== strtolower( $_REQUEST['order'] ) ? ' DESC' : ' ASC';
340 }
341 $sql .= " LIMIT $per_page";
342 $sql .= ' OFFSET ' . ( $page_number - 1 ) * $per_page;
343
344 return $wpdb->get_results( $sql, 'ARRAY_A' );
345 }
346
347 /**
348 * Return number of records found
349 *
350 * @since 1.0.0
351 *
352 * @return array Contains rows found.
353 */
354 public static function record_count() {
355 global $wpdb;
356
357 $where = '';
358
359 $selected_code_type = '';
360 if ( isset( $_REQUEST['selected_code_type'] ) && '' !== $_REQUEST['selected_code_type'] ) {
361 if ( '*' === $_REQUEST['selected_code_type'] ) {
362 $selected_code_type = '';
363 } else {
364 $selected_code_type = sanitize_text_field( wp_unslash( $_REQUEST['selected_code_type'] ) ); // input var okay.
365 }
366 } elseif ( isset( $_COOKIE[ CODE_MANAGER_COOKIES_LIST ] ) ) {
367 if ( '*' === $_COOKIE[ CODE_MANAGER_COOKIES_LIST ] ) {
368 $selected_code_type = '';
369 } else {
370 $selected_code_type = sanitize_text_field( wp_unslash( $_COOKIE[ CODE_MANAGER_COOKIES_LIST ] ) );
371 }
372 }
373 if ( '' !== $selected_code_type ) {
374 $where .= $wpdb->prepare(
375 ' where `code_type` = %s',
376 array(
377 $selected_code_type,
378 )
379 ); // phpcs:ignore Standard.Category.SniffName.ErrorCode.
380 }
381
382 $search_value = '';
383 if ( isset( $_REQUEST[ CODE_MANAGER_SEARCH_ITEM_NAME ] ) ) {
384 $search_value = sanitize_text_field( wp_unslash( $_REQUEST[ CODE_MANAGER_SEARCH_ITEM_NAME ] ) ); // input var okay.
385 } elseif ( isset( $_COOKIE[ CODE_MANAGER_COOKIES_SEARCH ] ) ) {
386 $search_value = sanitize_text_field( wp_unslash( $_COOKIE[ CODE_MANAGER_COOKIES_SEARCH ] ) );
387 }
388 if ( '' !== $search_value ) {
389 $prepare_where =
390 ( '' === $where ? ' where ' : ' and ' ) .
391 " (`code_name` like '%s' " .
392 " or `code_type` like '%s' " .
393 " or `code` like '%s' ) ";
394 $where .= $wpdb->prepare(
395 $prepare_where,
396 array(
397 '%' . esc_attr( $search_value ) . '%',
398 '%' . esc_attr( $search_value ) . '%',
399 '%' . esc_attr( $search_value ) . '%',
400 )
401 ); // phpcs:ignore Standard.Category.SniffName.ErrorCode.
402 }
403
404 $code_manager_model_class = CODE_MANAGER_MODEL_CLASS;
405 $code_manager_model = new $code_manager_model_class();
406 $sql = 'select count(*) from ' . $code_manager_model::get_base_table_name();
407 $sql .= $where;
408
409 return $wpdb->get_var( $sql );
410 }
411
412 /**
413 * Overwrite method (WP_List_Table.)search_box to handle cookies in search
414 *
415 * @since 1.0.0
416 *
417 * @param string $text Search box id.
418 * @param string $input_id Input id.
419 */
420 public function search_box( $text, $input_id ) {
421 // Always show search box!!! This plugin uses cookies. If the search box is disabled when nothing is
422 // found, it is not possible to remove the search criterion.
423
424 $input_id = $input_id . '-search-input';
425
426 $search_value = '';
427 if ( isset( $_REQUEST[ CODE_MANAGER_SEARCH_ITEM_NAME ] ) ) {
428 $search_value = sanitize_text_field( wp_unslash( $_REQUEST[ CODE_MANAGER_SEARCH_ITEM_NAME ] ) ); // input var okay.
429 } elseif ( isset( $_COOKIE[ CODE_MANAGER_COOKIES_SEARCH ] ) ) {
430 $search_value = sanitize_text_field( wp_unslash( $_COOKIE[ CODE_MANAGER_COOKIES_SEARCH ] ) );
431 }
432
433 if ( ! empty( $_REQUEST['orderby'] ) ) {
434 echo '<input type="hidden" name="orderby" value="' . esc_attr( sanitize_text_field( wp_unslash( $_REQUEST['orderby'] ) ) ) . '" />';
435 }
436 if ( ! empty( $_REQUEST['order'] ) ) {
437 echo '<input type="hidden" name="order" value="' . esc_attr( sanitize_text_field( wp_unslash( $_REQUEST['order'] ) ) ) . '" />';
438 }
439 if ( ! empty( $_REQUEST['post_mime_type'] ) ) {
440 echo '<input type="hidden" name="post_mime_type" value="' . esc_attr( sanitize_text_field( wp_unslash( $_REQUEST['post_mime_type'] ) ) ) . '" />';
441 }
442 if ( ! empty( $_REQUEST['detached'] ) ) {
443 echo '<input type="hidden" name="detached" value="' . esc_attr( sanitize_text_field( wp_unslash( $_REQUEST['detached'] ) ) ) . '" />';
444 }
445 ?>
446 <p class="search-box">
447 <label class="screen-reader-text" for="<?php echo esc_attr( $input_id ); ?>"><?php echo esc_attr( $text ); ?>:</label>
448 <input type="search" id="<?php echo esc_attr( $input_id ); ?>" name="<?php echo CODE_MANAGER_SEARCH_ITEM_NAME; ?>" value="<?php echo esc_attr( $search_value ); ?>" />
449 <?php submit_button( $text, '', '', false, array( 'id' => 'search-submit' ) ); ?>
450 </p>
451 <?php
452 }
453
454 /**
455 * Overwrite method (WP_List_Table.)display_tablenav to handle cookies
456 *
457 * If bulk actions are hidden when nothing is found, the user cannot change the code type selection.
458 *
459 * @since 1.0.0
460 *
461 * @param string $which Top or bottom.
462 */
463 protected function display_tablenav( $which ) {
464 // Always show bulk actions.
465 if ( 'top' === $which ) {
466 wp_nonce_field( 'bulk-' . $this->_args['plural'] );
467 }
468 ?>
469 <div class="tablenav <?php echo esc_attr( $which ); ?>">
470 <div class="alignleft actions bulkactions">
471 <?php $this->bulk_actions( $which ); ?>
472 </div>
473 <?php
474 $this->extra_tablenav( $which );
475 $this->pagination( $which );
476 ?>
477 <br class="clear" />
478 </div>
479 <?php
480 }
481
482 /**
483 * Overwrite method (WP_List_Table.)column_default to:
484 * (1) Add edit code link (@see Code_Manager_List::column_default_add_action_edit())
485 * (2) Add delete code link (@see Code_Manager_List::column_default_add_action_delete())
486 * (3) Add copy shortcode link (for shortcodes only)
487 * (4) Add code enable/disable checkbox/listbox
488 *
489 * @since 1.0.0
490 *
491 * @param array $item Available columns.
492 * @param string $column_name Column name.
493 *
494 * @return mixed|string|void
495 */
496 public function column_default( $item, $column_name ) {
497 if ( 'code_id' === $column_name ) {
498 if ( ! isset( $this->code_types[ $item['code_type'] ] ) ) {
499 $actions['noactions'] = 'No actions';
500 } else {
501 $actions['edit'] = $this->column_default_add_action_edit( $item, $column_name );
502 $actions['delete'] = $this->column_default_add_action_delete( $item, $column_name );
503 }
504
505 return sprintf( '%1$s %2$s', $item[ $column_name ], $this->row_actions( $actions ) );
506 }
507
508 if ( 'code_type' === $column_name ) {
509 if ( strpos( $item[ $column_name ], 'shortcode' ) !== false ) {
510 $shortcode_id = '[' . CODE_MANAGER_SHORT_CODE . " id=\"{$item['code_id']}\"]";
511 $shortcode_name = '[' . CODE_MANAGER_SHORT_CODE . " name=\"{$item['code_name']}\"]";
512 $title = __( 'Copy shortcode to clipboard', 'code-manager' );
513 $message = __( 'Shortcode copied to clipboard', 'code-manager' );
514 if ( isset( $this->code_types[ $item[ $column_name ] ] ) ) {
515 $output = $this->code_types[ $item[ $column_name ] ] . '<div style="height:10px"></div>';
516 }
517 $output .= '<a href="javascript:void(0)" class="dashicons dashicons-image-rotate" ' .
518 'onclick="jQuery(\'#cm_copy_id_' . self::$list_number . '\').toggle(); ' .
519 'jQuery(\'#cm_copy_name_' . self::$list_number . '\').toggle();"' .
520 '></a>&nbsp;' .
521 '<span id="cm_copy_id_' . self::$list_number . '" style="display:none">' .
522 $shortcode_id . ' ' .
523 '<a href="javascript:void(0)" class="dashicons dashicons-clipboard c2c" ' .
524 "onclick='jQuery.notify(\"{$message}\", \"info\")' " .
525 "data-clipboard-text='{$shortcode_id}' title='{$title}'" .
526 '></a></span>' .
527 '<span id="cm_copy_name_' . self::$list_number . '">' .
528 $shortcode_name . ' ' .
529 '<a href="javascript:void(0)" class="dashicons dashicons-clipboard c2c" ' .
530 "onclick='jQuery.notify(\"{$message}\", \"info\")' " .
531 "data-clipboard-text='{$shortcode_name}' title='{$title}'" .
532 '></a></span>';
533 return $output;
534 } else {
535 if ( isset( $this->code_types[ $item[ $column_name ] ] ) ) {
536 return $this->code_types[ $item[ $column_name ] ];
537 }
538 }
539 return __( 'Unknown code type', 'code-manager' ) . ': ' . $item[ $column_name ];
540 }
541
542 if ( 'code_enabled' === $column_name ) {
543 $id = $item['code_id'];
544 $wp_nonce = wp_create_nonce( 'code-manager-' . Code_manager::get_current_user_login() );
545 $checked = '1' === $item['code_enabled'] ? 'checked' : '';
546 return "<label style='white-space:nowrap' title='Enable code' class='cm_tooltip'>
547 <input type='checkbox'
548 id='code_enabled_{$id}'
549 $checked
550 onclick='activate_code($id,\"$wp_nonce\")'
551 >Enable
552 </label><br/>" .
553 $this->add_preview_switch( $id );
554 }
555
556 if ( 'code' === $column_name ) {
557 $code = '<pre>' . esc_html( str_replace( '&', '&amp;', (string) $item[ $column_name ] ) ) . '</pre>';
558 $code = str_replace( '`', '\`', (string) $code );
559 $title = "({$item['code_id']}) {$item['code_name']} ({$item['code_type']})";
560
561 $function = 'show_code_' . self::$list_number;
562 $dialog = 'dialog_' . self::$list_number;
563
564 return "<script type='text/javascript'>
565 function {$function}() {
566 html = `<div>{$code}</div>`;
567 height = jQuery(window).height() * 0.6;
568 var {$dialog} = jQuery(html).dialog({
569 dialogClass: 'no-close',
570 title: '{$title}',
571 modal: true,
572 width: '60%',
573 height: height,
574 buttons: {
575 'OK': function() {
576 {$dialog}.dialog('destroy');
577 }
578 }
579 });
580 }
581 </script>
582 <a href='javascript:void(0)' onclick='{$function}()'>
583 <span class='dashicons dashicons-editor-code cm_menu_title'
584 title='Click to view code'
585 ></span>
586 </a>";
587 }
588
589 return esc_html( str_replace( '&', '&amp;', (string) $item[ $column_name ] ) );
590 }
591
592 /**
593 * Switch preview mode on or off
594 *
595 * @param integer $id Code ID.
596 * @return string
597 */
598 protected function add_preview_switch( $id ) {
599 if ( Code_Manager_Preview::is_code_id_preview_enabled( $id ) ) {
600 $checked = 'checked';
601 } else {
602 $checked = '';
603 }
604 return "<label style='white-space:nowrap' title='Enable preview mode for this code' class='cm_tooltip'>
605 <input type='checkbox'
606 id='code_preview_{$id}'
607 $checked
608 onclick='set_code_preview($id,\"{$this->wpnonce}\",jQuery(this).is(\":checked\"))'
609 >Preview
610 </label>";
611 }
612
613 /**
614 * Override method (WP_List_Table.)column_cb
615 *
616 * @since 1.0.0
617 *
618 * @param object $item Item.
619 *
620 * @return string|void
621 */
622 public function column_cb( $item ) {
623 return "<input type='checkbox' name='bulk-selected[]' value='" . esc_attr( $item['code_id'] ) . "' />";
624 }
625
626 /**
627 * Adds edit code link to a given row
628 *
629 * @since 1.0.0
630 *
631 * @param array $item Available columns.
632 * @param string $column_name Column name.
633 *
634 * @return string
635 */
636 protected function column_default_add_action_edit( $item, $column_name ) {
637 return '<a href="?page=' . CODE_MANAGER_MENU_SLUG .
638 '&action=edit&code_id=' . esc_attr( $item[ $column_name ] ) .
639 '" class="edit">Edit</a>';
640 }
641
642 /**
643 * Adds delete code link to a given row
644 *
645 * @since 1.0.0
646 *
647 * @param array $item Available columns.
648 * @param string $column_name Column name.
649 *
650 * @return string
651 */
652 protected function column_default_add_action_delete( $item, $column_name ) {
653 $page = isset( $_REQUEST['paged'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['paged'] ) ) : 1;
654 $wp_nonce = wp_create_nonce( 'code-manager-delete' . Code_manager::get_current_user_login() );
655 $form_id = '_' . ( self::$list_number++ );
656 $esc_attr = 'esc_attr';
657 $menu_slug = CODE_MANAGER_MENU_SLUG;
658 $delete_form = <<<EOT
659 <form id='delete_form{$esc_attr( $form_id )}'
660 action='?page={$esc_attr( $menu_slug )}'
661 method='post'
662 >
663 <input type='hidden' name='code_id' value='{$esc_attr( $item[ $column_name ] )}' />
664 <input type='hidden' name='action' value='delete' />
665 <input type='hidden' name='paged' value='{$esc_attr( $page )}' />
666 <input type='hidden' name='_wpnonce' value='{$esc_attr( $wp_nonce )}' />
667 </form>
668 EOT;
669 ?>
670
671 <script type='text/javascript'>
672 jQuery("#cm_invisible_container").append("<?php echo str_replace( array( "\n", "\r" ), '', (string) $delete_form ); ?>");
673 function delete_code<?php echo esc_attr( $form_id ); ?>() {
674 html = "<div>You are about to permanently delete this code from your site. This action cannot be undone. 'No' to stop, 'Yes' to delete.</div>";
675 var dialog = jQuery(html).dialog({
676 dialogClass: 'no-close',
677 title: 'Delete code?',
678 buttons: {
679 'Yes': function() {
680 dialog.dialog('destroy');
681 jQuery('#delete_form<?php echo esc_attr( $form_id ); ?>').submit();
682 },
683 'No': function() {
684 dialog.dialog('destroy');
685 },
686 'Cancel': function() {
687 dialog.dialog('destroy');
688 }
689 }
690 });
691 }
692 </script>
693
694 <?php
695 return sprintf(
696 '<a href="javascript:void(0)" class="delete" onclick="delete_code%s()">Delete</a>',
697 esc_attr( $form_id )
698 );
699 }
700
701 /**
702 * Overwrite method to remove class fixed (prevents wrapping shortcode)
703 *
704 * @since 1.0.0
705 *
706 * @return array|string[]
707 */
708 protected function get_table_classes() {
709 return array( 'widefat', 'striped', $this->_args['plural'] );
710 }
711
712 /**
713 * Overrides method (WP_List_Table.)prepare_items
714 *
715 * @since 1.0.0
716 */
717 public function prepare_items() {
718 $columns = $this->get_columns();
719 $hidden = $this->get_hidden_columns();
720 $sortable = $this->get_sortable_columns();
721 $primary = $this->get_primary_column();
722 $this->_column_headers = array( $columns, $hidden, $sortable, $primary );
723
724 $this->process_bulk_action();
725
726 $per_page = $this->get_items_per_page( 'code_manager_rows_per_page', 10 );
727 $current_page = $this->get_pagenum();
728 $total_items = static::record_count();
729
730 $this->set_pagination_args(
731 array(
732 'total_items' => $total_items,
733 'per_page' => $per_page,
734 )
735 );
736
737 $this->items = static::get_codes( $per_page, $current_page );
738 }
739
740 /**
741 * Overrides method (WP_List_Table.)get_bulk_actions
742 *
743 * @since 1.0.0
744 *
745 * @return array|string[]
746 */
747 public function get_bulk_actions() {
748 $actions = array(
749 'bulk-delete' => 'Delete Permanently',
750 'export' => 'Export',
751 );
752
753 return $actions;
754 }
755
756 /**
757 * Implements bulk actions recognition
758 *
759 * @since 1.0.0
760 */
761 public function process_bulk_action() {
762 if ( 'delete' === $this->current_action() ) {
763 $this->code_delete();
764 } elseif ( 'bulk-delete' === $this->current_action() ) {
765 $this->code_bulk_delete();
766 } elseif ( 'export' === $this->current_action() ) {
767 $this->code_export();
768 } elseif ( 'import' === $this->current_action() ) {
769 $this->code_import();
770 }
771 }
772
773 /**
774 * Implement code delete action
775 *
776 * @since 1.0.0
777 */
778 protected function code_delete() {
779 $wp_nonce = isset( $_REQUEST['_wpnonce'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['_wpnonce'] ) ) : ''; // input var okay.
780 if ( ! wp_verify_nonce( $wp_nonce, 'code-manager-delete' . Code_manager::get_current_user_login() ) ) {
781 $msg = new Message_Box(
782 array(
783 'message_text' => __( 'Not authorized', 'code-manager' ),
784 'message_type' => 'error',
785 'message_is_dismissible' => false,
786 )
787 );
788 $msg->box();
789
790 return;
791 }
792
793 if ( isset( $_REQUEST['code_id'] ) ) {
794 $code_id = sanitize_text_field( wp_unslash( $_REQUEST['code_id'] ) ); // input var okay.
795 $code_manager_model_class = CODE_MANAGER_MODEL_CLASS;
796 $code_manager_model = new $code_manager_model_class();
797 $delete_failed = 1 !== $code_manager_model::dml_delete( $code_id );
798 } else {
799 $delete_failed = true;
800 }
801
802 if ( $delete_failed ) {
803 $msg = new Message_Box(
804 array(
805 'message_text' => __( 'Delete action failed', 'code-manager' ),
806 'message_type' => 'error',
807 'message_is_dismissible' => false,
808 )
809 );
810 $msg->box();
811 } else {
812 $msg = new Message_Box(
813 array(
814 'message_text' => __( 'Succesfully deleted code', 'code-manager' ),
815 )
816 );
817 $msg->box();
818 }
819 }
820
821 /**
822 * Implement code delete bulk action
823 *
824 * @since 1.0.0
825 */
826 protected function code_bulk_delete() {
827 if ( isset( $_REQUEST['bulk-selected'] ) ) {
828 $wp_nonce = isset( $_REQUEST['_delnonce'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['_delnonce'] ) ) : ''; // input var okay.
829 if ( ! wp_verify_nonce( $wp_nonce, 'code-manager-delete' . Code_manager::get_current_user_login() ) ) {
830 $msg = new Message_Box(
831 array(
832 'message_text' => __( 'Not authorized', 'code-manager' ),
833 'message_type' => 'error',
834 'message_is_dismissible' => false,
835 )
836 );
837 $msg->box();
838
839 return;
840 }
841
842 $bulk_rows = wp_unslash( $_REQUEST['bulk-selected'] );
843 $delete_failed = 0;
844 foreach ( $bulk_rows as $bulk_row ) {
845 $code_id = sanitize_text_field( wp_unslash( $bulk_row ) ); // input var okay.
846 $code_manager_model_class = CODE_MANAGER_MODEL_CLASS;
847 $code_manager_model = new $code_manager_model_class();
848
849 if ( 1 !== $code_manager_model::dml_delete( $code_id ) ) {
850 $delete_failed ++;
851 }
852 }
853
854 if ( $delete_failed > 0 ) {
855 if ( count( $bulk_rows ) === $delete_failed ) {
856 $msg = new Message_Box(
857 array(
858 'message_text' => __( 'Some delete actions failed', 'code-manager' ),
859 'message_type' => 'error',
860 'message_is_dismissible' => false,
861 )
862 );
863 $msg->box();
864 } else {
865 $msg = new Message_Box(
866 array(
867 'message_text' => __( 'Could not delete code', 'code-manager' ),
868 'message_type' => 'error',
869 'message_is_dismissible' => false,
870 )
871 );
872 $msg->box();
873 }
874 } else {
875 $msg = new Message_Box(
876 array(
877 'message_text' => __( 'Succesfully deleted code', 'code-manager' ),
878 )
879 );
880 $msg->box();
881 }
882 } else {
883 $msg = new Message_Box(
884 array(
885 'message_text' => __( 'Nothing to delete', 'code-manager' ),
886 )
887 );
888 $msg->box();
889 }
890 }
891
892 /**
893 * Export code.
894 */
895 protected function code_export() {
896 if ( isset( $_REQUEST['bulk-selected'] ) ) {
897 $wp_nonce = isset( $_REQUEST['_expnonce'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['_expnonce'] ) ) : ''; // input var okay.
898 if ( ! wp_verify_nonce( $wp_nonce, 'code-manager-export' . Code_manager::get_current_user_login() ) ) {
899 $msg = new Message_Box(
900 array(
901 'message_text' => __( 'Not authorized', 'code-manager' ),
902 'message_type' => 'error',
903 'message_is_dismissible' => false,
904 )
905 );
906 $msg->box();
907
908 return;
909 }
910
911 $bulk_rows = wp_unslash( $_REQUEST['bulk-selected'] );
912 $code_ids = array();
913 $rows = 0;
914 foreach ( $bulk_rows as $bulk_row ) {
915 $code_id = sanitize_text_field( wp_unslash( $bulk_row ) ); // input var okay.
916 if ( is_numeric( $code_id ) ) {
917 $code_ids[] = "cid[{$rows}]={$code_id}";
918 $rows++;
919 }
920 }
921
922 ?>
923 <script type="text/javascript">
924 let url = ajaxurl + "?action=code_manager_export&wpnonce=<?php echo esc_attr( $wp_nonce ); ?>";
925 <?php
926 foreach ( $code_ids as $code_id ) {
927 ?>
928 url += "&<?php echo esc_attr( $code_id ); ?>";
929 <?php
930 }
931 ?>
932 jQuery(function() {
933 jQuery("#cm_stealth_mode").attr("src", url);
934 });
935 </script>
936 <?php
937 } else {
938 $msg = new Message_Box(
939 array(
940 'message_text' => __( 'Nothing to export', 'code-manager' ),
941 )
942 );
943 $msg->box();
944 }
945 }
946
947 /**
948 * Import code.
949 */
950 protected function code_import() {
951 $wp_nonce = isset( $_REQUEST['_impnonce'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['_impnonce'] ) ) : ''; // input var okay.
952 if ( ! wp_verify_nonce( $wp_nonce, 'code-manager-import' . Code_manager::get_current_user_login() ) ) {
953 $msg = new Message_Box(
954 array(
955 'message_text' => __( 'Not authorized', 'code-manager' ),
956 'message_type' => 'error',
957 'message_is_dismissible' => false,
958 )
959 );
960 $msg->box();
961
962 return;
963 }
964
965 Code_Manager_Import::import();
966 }
967
968 /**
969 * Overrides method (WP_List_Table.)get_columns
970 *
971 * @since 1.0.0
972 *
973 * @return array
974 */
975 public function get_columns() {
976 return static::get_column_labels_default();
977 }
978
979 /**
980 * Returns all column labels
981 *
982 * Defined as static method to be used in multiple situations and maintained in one location.
983 *
984 * @since 1.0.0
985 *
986 * @return array
987 */
988 public static function get_column_labels_default() {
989 return array(
990 'cb' => '<input type="checkbox" />',
991 'code_id' => __( 'ID', 'code-manager' ),
992 'code_name' => __( 'Name', 'code-manager' ),
993 'code_type' => __( 'Shortcode', 'code-manager' ),
994 'code_enabled' => __( 'Status', 'code-manager' ),
995 'code' => __( 'Code', 'code-manager' ),
996 'code_author' => __( 'Author', 'code-manager' ),
997 'code_description' => __( 'Description', 'code-manager' ),
998 );
999 }
1000
1001 /**
1002 * Returns hidden columns (taken from usermeta)
1003 *
1004 * @since 1.0.0
1005 *
1006 * @return string[]
1007 */
1008 public function get_hidden_columns() {
1009 $hidden = get_user_meta(
1010 get_current_user_id(),
1011 'manage' . get_current_screen()->id . 'columnshidden'
1012 );
1013
1014 return 0 === count( $hidden ) ? self::get_hidden_columns_default() : $hidden[0];
1015 }
1016
1017 /**
1018 * Returns default hidden columns
1019 *
1020 * Can be changed by the user in screen options.
1021 *
1022 * @since 1.0.0
1023 *
1024 * @return string[]
1025 */
1026 public static function get_hidden_columns_default() {
1027 return array(
1028 'code_url',
1029 'code',
1030 );
1031 }
1032
1033 /**
1034 * Overrides method (WP_List_Table.)get_sortable_columns
1035 *
1036 * @since 1.0.0
1037 *
1038 * @return array|array[]
1039 */
1040 public function get_sortable_columns() {
1041 return self::$sortable_columns;
1042 }
1043
1044 /**
1045 * Overrides method (WP_List_Table.)get_primary_column
1046 *
1047 * @since 1.0.0
1048 *
1049 * @return int|string
1050 */
1051 public function get_primary_column() {
1052 return 'code_id';
1053 }
1054
1055 }
1056
1057 }
1058