PluginProbe ʕ •ᴥ•ʔ
Code Manager / 1.0.14
Code Manager v1.0.14
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 4 years ago Code_Manager_Dashboard.php 4 years ago Code_Manager_Export.php 4 years ago Code_Manager_Form.php 4 years ago Code_Manager_Import.php 4 years ago Code_Manager_Import_File.php 4 years ago Code_Manager_List.php 4 years ago Code_Manager_List_View.php 4 years ago Code_Manager_Model.php 4 years ago Code_Manager_Preview.php 4 years ago Code_Manager_Settings.php 4 years ago Code_Manager_Tabs.php 4 years ago Message_Box.php 4 years ago WP_List_Table.php 4 years ago
Code_Manager_List.php
1080 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 <span class="material-icons cm_menu_title">tab</span></a>
131 <a href="?page=<?php echo CODE_MANAGER_MENU_SLUG; ?>&action=new"
132 title="Add new code"
133 id="header_new">
134 <span class="material-icons cm_menu_title">add_circle_outline</span></a>
135 <a href="javascript:void(0)" title="Import code"
136 onclick="jQuery('#upload_file_container').toggle()">
137 <span class="material-icons cm_menu_title">arrow_circle_up</span></a>
138 <a href="<?php echo CODE_MANAGER_HELP_URL; ?>" target="_blank"
139 title="Plugin help - opens in a new tab or window">
140 <span class="material-icons cm_menu_title">help_outline</span></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 <input type='hidden' name='code_id' value='{$esc_attr( $item[ $column_name ] )}' />
686 <input type='hidden' name='action' value='delete' />
687 <input type='hidden' name='paged' value='{$esc_attr( $page )}' />
688 <input type='hidden' name='_wpnonce' value='{$esc_attr( $wp_nonce )}' />
689 </form>
690 EOT;
691 ?>
692
693 <script type='text/javascript'>
694 jQuery("#cm_invisible_container").append("<?php echo str_replace( "\n", '', $delete_form ); ?>");
695 function delete_code<?php echo esc_attr( $form_id ); ?>() {
696 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>";
697 var dialog = jQuery(html).dialog({
698 dialogClass: 'no-close',
699 title: 'Delete code?',
700 buttons: {
701 'Yes': function() {
702 dialog.dialog('destroy');
703 jQuery('#delete_form<?php echo esc_attr( $form_id ); ?>').submit();
704 },
705 'No': function() {
706 dialog.dialog('destroy');
707 },
708 'Cancel': function() {
709 dialog.dialog('destroy');
710 }
711 }
712 });
713 }
714 </script>
715
716 <?php
717 return sprintf(
718 '<a href="javascript:void(0)" class="delete" onclick="delete_code%s()">Delete</a>',
719 esc_attr( $form_id )
720 );
721 }
722
723 /**
724 * Overwrite method to remove class fixed (prevents wrapping shortcode)
725 *
726 * @since 1.0.0
727 *
728 * @return array|string[]
729 */
730 protected function get_table_classes() {
731 return array( 'widefat', 'striped', $this->_args['plural'] );
732 }
733
734 /**
735 * Overrides method (WP_List_Table.)prepare_items
736 *
737 * @since 1.0.0
738 */
739 public function prepare_items() {
740 $columns = $this->get_columns();
741 $hidden = $this->get_hidden_columns();
742 $sortable = $this->get_sortable_columns();
743 $primary = $this->get_primary_column();
744 $this->_column_headers = array( $columns, $hidden, $sortable, $primary );
745
746 $this->process_bulk_action();
747
748 $per_page = $this->get_items_per_page( 'code_manager_rows_per_page', 10 );
749 $current_page = $this->get_pagenum();
750 $total_items = static::record_count();
751
752 $this->set_pagination_args(
753 array(
754 'total_items' => $total_items,
755 'per_page' => $per_page,
756 )
757 );
758
759 $this->items = static::get_codes( $per_page, $current_page );
760 }
761
762 /**
763 * Overrides method (WP_List_Table.)get_bulk_actions
764 *
765 * @since 1.0.0
766 *
767 * @return array|string[]
768 */
769 public function get_bulk_actions() {
770 $actions = array(
771 'bulk-delete' => 'Delete Permanently',
772 'export' => 'Export',
773 );
774
775 return $actions;
776 }
777
778 /**
779 * Implements bulk actions recognition
780 *
781 * @since 1.0.0
782 */
783 public function process_bulk_action() {
784 if ( 'delete' === $this->current_action() ) {
785 $this->code_delete();
786 } elseif ( 'bulk-delete' === $this->current_action() ) {
787 $this->code_bulk_delete();
788 } elseif ( 'export' === $this->current_action() ) {
789 $this->code_export();
790 } elseif ( 'import' === $this->current_action() ) {
791 $this->code_import();
792 }
793 }
794
795 /**
796 * Implement code delete action
797 *
798 * @since 1.0.0
799 */
800 protected function code_delete() {
801 $wp_nonce = isset( $_REQUEST['_wpnonce'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['_wpnonce'] ) ) : ''; // input var okay.
802 if ( ! wp_verify_nonce( $wp_nonce, 'code-manager-delete' . Code_manager::get_current_user_login() ) ) {
803 $msg = new Message_Box(
804 array(
805 'message_text' => __( 'Not authorized', 'code-manager' ),
806 'message_type' => 'error',
807 'message_is_dismissible' => false,
808 )
809 );
810 $msg->box();
811
812 return;
813 }
814
815 if ( isset( $_REQUEST['code_id'] ) ) {
816 $code_id = sanitize_text_field( wp_unslash( $_REQUEST['code_id'] ) ); // input var okay.
817 $code_manager_model_class = CODE_MANAGER_MODEL_CLASS;
818 $code_manager_model = new $code_manager_model_class();
819 $delete_failed = 1 !== $code_manager_model::dml_delete( $code_id );
820 } else {
821 $delete_failed = true;
822 }
823
824 if ( $delete_failed ) {
825 $msg = new Message_Box(
826 array(
827 'message_text' => __( 'Delete action failed', 'code-manager' ),
828 'message_type' => 'error',
829 'message_is_dismissible' => false,
830 )
831 );
832 $msg->box();
833 } else {
834 $msg = new Message_Box(
835 array(
836 'message_text' => __( 'Succesfully deleted code', 'code-manager' ),
837 )
838 );
839 $msg->box();
840 }
841 }
842
843 /**
844 * Implement code delete bulk action
845 *
846 * @since 1.0.0
847 */
848 protected function code_bulk_delete() {
849 if ( isset( $_REQUEST['bulk-selected'] ) ) {
850 $wp_nonce = isset( $_REQUEST['_delnonce'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['_delnonce'] ) ) : ''; // input var okay.
851 if ( ! wp_verify_nonce( $wp_nonce, 'code-manager-delete' . Code_manager::get_current_user_login() ) ) {
852 $msg = new Message_Box(
853 array(
854 'message_text' => __( 'Not authorized', 'code-manager' ),
855 'message_type' => 'error',
856 'message_is_dismissible' => false,
857 )
858 );
859 $msg->box();
860
861 return;
862 }
863
864 $bulk_rows = wp_unslash( $_REQUEST['bulk-selected'] );
865 $delete_failed = 0;
866 foreach ( $bulk_rows as $bulk_row ) {
867 $code_id = sanitize_text_field( wp_unslash( $bulk_row ) ); // input var okay.
868 $code_manager_model_class = CODE_MANAGER_MODEL_CLASS;
869 $code_manager_model = new $code_manager_model_class();
870
871 if ( 1 !== $code_manager_model::dml_delete( $code_id ) ) {
872 $delete_failed ++;
873 }
874 }
875
876 if ( $delete_failed > 0 ) {
877 if ( count( $bulk_rows ) === $delete_failed ) {
878 $msg = new Message_Box(
879 array(
880 'message_text' => __( 'Some delete actions failed', 'code-manager' ),
881 'message_type' => 'error',
882 'message_is_dismissible' => false,
883 )
884 );
885 $msg->box();
886 } else {
887 $msg = new Message_Box(
888 array(
889 'message_text' => __( 'Could not delete code', 'code-manager' ),
890 'message_type' => 'error',
891 'message_is_dismissible' => false,
892 )
893 );
894 $msg->box();
895 }
896 } else {
897 $msg = new Message_Box(
898 array(
899 'message_text' => __( 'Succesfully deleted code', 'code-manager' ),
900 )
901 );
902 $msg->box();
903 }
904 } else {
905 $msg = new Message_Box(
906 array(
907 'message_text' => __( 'Nothing to delete', 'code-manager' ),
908 )
909 );
910 $msg->box();
911 }
912 }
913
914 /**
915 * Export code.
916 */
917 protected function code_export() {
918 if ( isset( $_REQUEST['bulk-selected'] ) ) {
919 $wp_nonce = isset( $_REQUEST['_expnonce'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['_expnonce'] ) ) : ''; // input var okay.
920 if ( ! wp_verify_nonce( $wp_nonce, 'code-manager-export' . Code_manager::get_current_user_login() ) ) {
921 $msg = new Message_Box(
922 array(
923 'message_text' => __( 'Not authorized', 'code-manager' ),
924 'message_type' => 'error',
925 'message_is_dismissible' => false,
926 )
927 );
928 $msg->box();
929
930 return;
931 }
932
933 $bulk_rows = wp_unslash( $_REQUEST['bulk-selected'] );
934 $code_ids = array();
935 $rows = 0;
936 foreach ( $bulk_rows as $bulk_row ) {
937 $code_id = sanitize_text_field( wp_unslash( $bulk_row ) ); // input var okay.
938 if ( is_numeric( $code_id ) ) {
939 $code_ids[] = "cid[{$rows}]={$code_id}";
940 $rows++;
941 }
942 }
943
944 ?>
945 <script type="text/javascript">
946 let url = ajaxurl + "?action=code_manager_export&wpnonce=<?php echo esc_attr( $wp_nonce ); ?>";
947 <?php
948 foreach ( $code_ids as $code_id ) {
949 ?>
950 url += "&<?php echo esc_attr( $code_id ); ?>";
951 <?php
952 }
953 ?>
954 jQuery(function() {
955 jQuery("#cm_stealth_mode").attr("src", url);
956 });
957 </script>
958 <?php
959 } else {
960 $msg = new Message_Box(
961 array(
962 'message_text' => __( 'Nothing to export', 'code-manager' ),
963 )
964 );
965 $msg->box();
966 }
967 }
968
969 /**
970 * Import code.
971 */
972 protected function code_import() {
973 $wp_nonce = isset( $_REQUEST['_impnonce'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['_impnonce'] ) ) : ''; // input var okay.
974 if ( ! wp_verify_nonce( $wp_nonce, 'code-manager-import' . Code_manager::get_current_user_login() ) ) {
975 $msg = new Message_Box(
976 array(
977 'message_text' => __( 'Not authorized', 'code-manager' ),
978 'message_type' => 'error',
979 'message_is_dismissible' => false,
980 )
981 );
982 $msg->box();
983
984 return;
985 }
986
987 Code_Manager_Import::import();
988 }
989
990 /**
991 * Overrides method (WP_List_Table.)get_columns
992 *
993 * @since 1.0.0
994 *
995 * @return array
996 */
997 public function get_columns() {
998 return static::get_column_labels_default();
999 }
1000
1001 /**
1002 * Returns all column labels
1003 *
1004 * Defined as static method to be used in multiple situations and maintained in one location.
1005 *
1006 * @since 1.0.0
1007 *
1008 * @return array
1009 */
1010 public static function get_column_labels_default() {
1011 return array(
1012 'cb' => '<input type="checkbox" />',
1013 'code_id' => __( 'ID', 'code-manager' ),
1014 'code_name' => __( 'Name', 'code-manager' ),
1015 'code_type' => __( 'Shortcode', 'code-manager' ),
1016 'code_enabled' => __( 'Status', 'code-manager' ),
1017 'code' => __( 'Code', 'code-manager' ),
1018 'code_author' => __( 'Author', 'code-manager' ),
1019 'code_description' => __( 'Description', 'code-manager' ),
1020 );
1021 }
1022
1023 /**
1024 * Returns hidden columns (taken from usermeta)
1025 *
1026 * @since 1.0.0
1027 *
1028 * @return string[]
1029 */
1030 public function get_hidden_columns() {
1031 $hidden = get_user_meta(
1032 get_current_user_id(),
1033 'manage' . get_current_screen()->id . 'columnshidden'
1034 );
1035
1036 return 0 === count( $hidden ) ? self::get_hidden_columns_default() : $hidden[0];
1037 }
1038
1039 /**
1040 * Returns default hidden columns
1041 *
1042 * Can be changed by the user in screen options.
1043 *
1044 * @since 1.0.0
1045 *
1046 * @return string[]
1047 */
1048 public static function get_hidden_columns_default() {
1049 return array(
1050 'code_url',
1051 'code',
1052 );
1053 }
1054
1055 /**
1056 * Overrides method (WP_List_Table.)get_sortable_columns
1057 *
1058 * @since 1.0.0
1059 *
1060 * @return array|array[]
1061 */
1062 public function get_sortable_columns() {
1063 return self::$sortable_columns;
1064 }
1065
1066 /**
1067 * Overrides method (WP_List_Table.)get_primary_column
1068 *
1069 * @since 1.0.0
1070 *
1071 * @return int|string
1072 */
1073 public function get_primary_column() {
1074 return 'code_id';
1075 }
1076
1077 }
1078
1079 }
1080