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