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