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