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