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