PluginProbe
Tag, Category, and Taxonomy Manager – Autotagger Automatically Add Terms / trunk
Tag, Category, and Taxonomy Manager – Autotagger Automatically Add Terms vtrunk
3.53.0 3.52.0 3.51.0 3.50.0 3.45.0 3.38.0 3.4.0 3.4.1 3.4.2 3.4.3 3.4.4 3.4.5 3.40.0 3.40.1 3.41.0 3.42.0 3.43.0 3.44.0 3.5.0 3.5.1 3.5.2 3.5.3 3.6.0 3.6.1 3.6.2 All 177 releases
simple-tags / inc / class.admin.mass.php

class.admin.mass.php in Tag, Category, and Taxonomy Manager – Autotagger Automatically Add Terms trunk, at inc/class.admin.mass.php

540 lines 23.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 // phpcs:disable Squiz.PHP.CommentedOutCode.Found,WordPress.DB.DirectDatabaseQuery.NoCaching,WordPress.DB.SlowDBQuery.slow_db_query_tax_query,WordPress.Security.NonceVerification.Recommended,WordPress.Security.ValidatedSanitizedInput.InputNotValidated -- Legacy TaxoPress file: keep behavior unchanged while documenting existing PHPCS exceptions.
4
5 class SimpleTags_Admin_Mass
6 {
7 public const MENU_SLUG = 'st_options';
8
9 /**
10 * SimpleTags_Admin_Mass constructor.
11 */
12 public function __construct()
13 {
14 // Ajax action, JS Helper and admin action
15 add_action('admin_init', array( __CLASS__, 'admin_init' ));
16
17 // Admin menu
18 add_action('admin_menu', array( __CLASS__, 'admin_menu' ));
19
20 // Register taxo, parent method...
21 SimpleTags_Admin::register_taxonomy();
22 }
23
24 /**
25 * Add WP admin menu for Tags
26 *
27 * @return void
28 * @author WebFactory Ltd
29 */
30 public static function admin_menu()
31 {
32 add_submenu_page(
33 self::MENU_SLUG,
34 esc_html__('Mass Edit Terms', 'simple-tags'),
35 esc_html__('Mass Edit Terms', 'simple-tags'),
36 'simple_tags',
37 'st_mass_terms',
38 array(
39 __CLASS__,
40 'pageMassEditTags',
41 )
42 );
43 }
44
45 /**
46 * Control POST data for mass edit tags
47 *
48 */
49 public static function admin_init()
50 {
51 if (! current_user_can('simple_tags')) {
52 return false;
53 }
54
55 // Get GET data
56 if (isset($_GET['post_type'])) {
57 $type = stripslashes(sanitize_text_field(wp_unslash($_GET['post_type'])));
58 }
59
60 if (isset($_POST['update_mass'])) {
61 // origination and intention
62 if (! (wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['secure_mass'])), 'st_mass_terms'))) {
63 add_settings_error(__CLASS__, __CLASS__, esc_html__('Security problem. Try again.', 'simple-tags'), 'error taxopress-notice');
64
65 return false;
66 }
67
68 if (isset($_POST['tags'])) {
69 $counter = 0;
70 foreach ((array) array_map('sanitize_text_field', wp_unslash($_POST['tags'])) as $object_id => $tag_list) {
71 // Trim data
72 $tag_list = trim(stripslashes($tag_list));
73
74 // String to array
75 $tags = explode(',', $tag_list);
76
77 // Remove empty and trim tag
78 $tags = array_filter($tags, '_delete_empty_element');
79
80 $show_slug = SimpleTags_Plugin::get_option_value('enable_mass-edit_terms_slug');
81
82 $term_ids = array();
83 foreach ($tags as $tag) {
84 $tag = trim($tag);
85 if (empty($tag)) {
86 continue;
87 }
88
89 if ($show_slug && preg_match('/^(.+?)\s*\(([^)]+)\)$/', $tag, $matches)) {
90 $term_name = trim($matches[1]);
91 $term_slug = trim($matches[2]);
92
93 $term = get_term_by('slug', $term_slug, SimpleTags_Admin::$taxonomy);
94
95 if ($term) {
96 if ($term->name === $term_name) {
97 $term_ids[] = $term->term_id;
98 } else {
99 $unique_slug = $term_slug;
100 $counter = 1;
101 while (get_term_by('slug', $unique_slug, SimpleTags_Admin::$taxonomy)) {
102 $unique_slug = $term_slug . '-' . $counter;
103 $counter++;
104 }
105 $new_term = wp_insert_term($term_name, SimpleTags_Admin::$taxonomy, array('slug' => $unique_slug));
106 if (!is_wp_error($new_term)) {
107 $term_ids[] = $new_term['term_id'];
108 }
109 }
110 } else {
111 $new_term = wp_insert_term($term_name, SimpleTags_Admin::$taxonomy, array('slug' => $term_slug));
112 if (!is_wp_error($new_term)) {
113 $term_ids[] = $new_term['term_id'];
114 }
115 }
116 } else {
117 if ($show_slug) {
118 $tag = trim(preg_replace('/\s*\([^)]+\)$/', '', $tag));
119 }
120
121 $term = get_term_by('name', $tag, SimpleTags_Admin::$taxonomy);
122 if ($term) {
123 $term_ids[] = $term->term_id;
124 } else {
125 $new_term = wp_insert_term($tag, SimpleTags_Admin::$taxonomy);
126 if (!is_wp_error($new_term)) {
127 $term_ids[] = $new_term['term_id'];
128 }
129 }
130 }
131 }
132
133 wp_set_object_terms($object_id, $term_ids, SimpleTags_Admin::$taxonomy);
134 $counter++;
135
136 // Clean cache
137 clean_post_cache($object_id);
138 }
139
140 add_settings_error(__CLASS__, __CLASS__, sprintf(esc_html__('%1$s %2$s(s) terms updated with success !', 'simple-tags'), (int) $counter, strtolower(SimpleTags_Admin::$post_type_name)), 'updated taxopress-notice');
141
142 return true;
143 }
144 }
145
146 return false;
147 }
148
149 /**
150 * Helper function to extract term name (ignoring slug in brackets)
151 */
152 private static function extractTermName($term)
153 {
154 return trim(preg_replace('/\s*\(.*?\)$/', '', $term));
155 }
156
157 /**
158 * WP Page - Mass edit tags
159 *
160 */
161 public static function pageMassEditTags()
162 {
163 global $wpdb, $wp_locale, $wp_query;
164 list($post_stati, $avail_post_stati) = self::edit_data_query();
165
166 if (! isset($_GET['paged'])) {
167 $_GET['paged'] = 1;
168 }
169
170 // Display message
171 settings_errors(__CLASS__);
172 ?>
173 <div class="taxopress-block-wrap">
174 <div class="wrap st_wrap tagcloudui st_mass_terms-page admin-settings">
175 <form id="posts-filter" action="" method="get">
176 <input type="hidden" name="page" value="st_mass_terms"/>
177 <input type="hidden" name="taxo" value="<?php echo esc_attr(SimpleTags_Admin::$taxonomy); ?>"/>
178 <input type="hidden" name="cpt" value="<?php echo esc_attr(SimpleTags_Admin::$post_type); ?>"/>
179
180 <h1><?php _e('Mass Edit Terms', 'simple-tags'); ?></h1>
181 <br>
182 <div class="taxopress-description"><?php esc_html_e('This feature allows users to quickly add or remove terms from multiple posts.', 'simple-tags'); ?></div>
183 <br>
184
185 <ul class="subsubsub">
186 <?php
187 $status_links = array();
188 $num_posts = wp_count_posts(SimpleTags_Admin::$post_type, 'readable');
189 $class = (empty($_GET['post_status']) && empty($_GET['post_type'])) ? ' class="current"' : '';
190 $status_links[] = '<li><a href="' . admin_url('admin.php') . '?page=st_mass_terms&amp;cpt=' . SimpleTags_Admin::$post_type . '&amp;taxo=' . SimpleTags_Admin::$taxonomy . '"' . $class . '>' . esc_html__('All', 'simple-tags') . '</a>';
191 foreach ($post_stati as $status => $label) {
192 $class = '';
193
194 if (! in_array($status, $avail_post_stati)) {
195 continue;
196 }
197
198 if (empty($num_posts->$status)) {
199 continue;
200 }
201 if (isset($_GET['post_status']) && $status == $_GET['post_status']) {
202 $class = ' class="current"';
203 }
204
205 $status_links[] = '<li><a href="' . admin_url('admin.php') . '?page=st_mass_terms&amp;cpt=' . SimpleTags_Admin::$post_type . '&amp;taxo=' . SimpleTags_Admin::$taxonomy . '&amp;post_status=' . $status . '"' . $class . '>' . sprintf(_n($label[2][0], $label[2][1], (int) $num_posts->$status), number_format_i18n($num_posts->$status)) . '</a>';
206 }
207 // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
208 echo implode(' |</li>', $status_links) . '</li>';
209 unset($status_links);
210
211 $class = (! empty($_GET['post_type'])) ? ' class="current"' : '';
212 ?>
213 </ul>
214
215 <?php if (isset($_GET['post_status'])) : ?>
216 <input type="hidden" name="post_status" value="<?php echo esc_attr(sanitize_text_field(wp_unslash($_GET['post_status']))) ?>"/>
217 <?php endif; ?>
218
219
220 <p class="search-box">
221 <input type="text" id="post-search-input" placeholder="<?php esc_attr_e('Search post title and content', 'simple-tags'); ?>" name="s" value="<?php the_search_query(); ?>"/>
222 <input type="submit" value="<?php _e('Search', 'simple-tags'); ?>" class="button"/>
223 </p>
224
225 <div class="tablenav custom-nav">
226 <?php
227 $posts_per_page = (isset($_GET['posts_per_page'])) ? (int) $_GET['posts_per_page'] : 0;
228 if ((int) $posts_per_page == 0) {
229 $posts_per_page = 15;
230 }
231
232 $page_links = paginate_links(array(
233 'base' => add_query_arg('paged', '%#%'),
234 'format' => '',
235 'total' => ceil($wp_query->found_posts / $posts_per_page),
236 'current' => ((int) $_GET['paged'])
237 ));
238
239 if ($page_links) {
240 // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
241 echo "<div class='tablenav-pages'>" . $page_links . "</div>";
242 }
243 ?>
244
245 <div style="float: left">
246 <?php
247 if (! is_singular()) {
248 $arc_result = $wpdb->get_results($wpdb->prepare("SELECT DISTINCT YEAR(post_date) AS yyear, MONTH(post_date) AS mmonth FROM $wpdb->posts WHERE post_type = %s ORDER BY post_date DESC", SimpleTags_Admin::$post_type));
249
250 $month_count = count($arc_result);
251
252 if (! isset($_GET['m'])) {
253 $_GET['m'] = '';
254 }
255
256 if ($month_count && ! (1 == $month_count && 0 == $arc_result[0]->mmonth)) {
257 ?>
258 <select name='m'>
259 <option <?php selected(@sanitize_text_field(wp_unslash($_GET['m'])), 0); ?>
260 value='0'><?php _e('Show all dates', 'simple-tags'); ?></option>
261 <?php
262 foreach ($arc_result as $arc_row) {
263 if ($arc_row->yyear == 0) {
264 continue;
265 }
266 $arc_row->mmonth = zeroise($arc_row->mmonth, 2);
267
268 if ($arc_row->yyear . $arc_row->mmonth == $_GET['m']) {
269 $default = ' selected="selected"';
270 } else {
271 $default = '';
272 }
273 // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
274 echo "<option$default value='$arc_row->yyear$arc_row->mmonth'>";
275 // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
276 echo esc_html($wp_locale->get_month($arc_row->mmonth)) . " " . esc_html($arc_row->yyear) . "";
277 echo "</option>\n";
278 }
279 ?>
280 </select>
281 <?php
282 }
283 ?>
284
285 <select name="posts_per_page" id="posts_per_page">
286 <option <?php if (! isset($_GET['posts_per_page'])) {
287 echo 'selected="selected"';
288 } ?> value=""><?php _e('Quantity&hellip;', 'simple-tags'); ?></option>
289 <option <?php selected($posts_per_page, 10); ?> value="10">10</option>
290 <option <?php selected($posts_per_page, 20); ?> value="20">20</option>
291 <option <?php selected($posts_per_page, 30); ?> value="30">30</option>
292 <option <?php selected($posts_per_page, 40); ?> value="40">40</option>
293 <option <?php selected($posts_per_page, 50); ?> value="50">50</option>
294 <option <?php selected($posts_per_page, 100); ?> value="100">100</option>
295 <option <?php selected($posts_per_page, 200); ?> value="200">200</option>
296 </select>
297
298 <?php
299
300 $current_filter_term = isset($_GET['massedit_filter_term']) ? sanitize_text_field(wp_unslash($_GET['massedit_filter_term'])) : '';
301 $selected_term_label = '';
302
303 if ($current_filter_term) {
304 $existing_term = get_term_by('slug', $current_filter_term, SimpleTags_Admin::$taxonomy);
305 if ($existing_term && !is_wp_error($existing_term)) {
306 $show_slug = (int) SimpleTags_Plugin::get_option_value('enable_mass-edit_terms_slug') === 1;
307
308 if ($show_slug) {
309 $selected_term_label = sprintf('%s (%s)', $existing_term->name, $existing_term->slug);
310 } else {
311 $selected_term_label = $existing_term->name;
312 }
313 }
314 }
315 ?>
316
317 <select name="massedit_filter_term" id="<?php echo esc_attr(SimpleTags_Admin::$taxonomy); ?>"
318 class="taxopress-select2-term-filter"
319 data-placeholder="<?php echo esc_attr__('Filter by term', 'simple-tags'); ?>"
320 style="min-width:200px;">
321 <option value=""><?php esc_html_e('All terms', 'simple-tags'); ?></option>
322 <?php if ($current_filter_term && $selected_term_label) : ?>
323 <option value="<?php echo esc_attr($current_filter_term); ?>" selected="selected">
324 <?php echo esc_html($selected_term_label); ?>
325 </option>
326 <?php endif; ?>
327 </select>
328
329 <input type="submit" id="post-query-submit" value="<?php _e('Filter', 'simple-tags'); ?>"
330 class="button-secondary"/>
331 <?php } ?>
332 <?php SimpleTags_Admin::boxSelectorTaxonomy('st_mass_terms'); ?>
333 </div>
334 <br style="clear:both;"/>
335 </div>
336 </form>
337
338 <div style="clear:both;margin-bottom: 6px;"></div>
339
340 <?php if (have_posts()) :
341 add_filter('the_title', 'esc_html');
342 ?>
343 <form name="post" id="post" method="post" class="st-mass-edit">
344 <table class="widefat post fixed">
345 <thead>
346 <tr>
347 <th class="manage-column"><?php esc_html_e('Post title', 'simple-tags'); ?></th>
348 <th class="manage-column"><?php printf(esc_html__('Terms : %s', 'simple-tags'), esc_html(SimpleTags_Admin::$taxo_name)); ?></th>
349 </tr>
350 </thead>
351 <tbody>
352 <?php
353 $class = 'alternate';
354 while (have_posts()) {
355 the_post();
356 $class = ($class == 'alternate') ? '' : 'alternate';
357 ?>
358 <tr valign="top" class="<?php echo esc_attr($class); ?>">
359 <th scope="row"><a
360 href="<?php echo esc_url(admin_url('post.php?action=edit&amp;post=' . get_the_ID())); ?>"
361 title="<?php esc_attr_e('Edit', 'simple-tags'); ?>"><?php echo (esc_html(get_the_title()) == '') ? (int)get_the_ID() : esc_html(get_the_title()); ?></a>
362 </th>
363 <td><input id="tags-input<?php the_ID(); ?>" class="autocomplete-input tags_input taxopress-mass-edit-input"
364 type="text" size="100" name="tags[<?php echo (int)get_the_ID(); ?>]"
365 value="<?php echo esc_attr(SimpleTags_Admin::getTermsToEdit(SimpleTags_Admin::$taxonomy, get_the_ID())); ?>"/>
366 </td>
367 </tr>
368 <?php
369 }
370 ?>
371 </tbody>
372 </table>
373
374 <p class="submit">
375 <input type="hidden" name="secure_mass"
376 value="<?php echo esc_attr(wp_create_nonce('st_mass_terms')); ?>"/>
377 <input class="button-primary" type="submit" name="update_mass"
378 value="<?php esc_attr_e('Update all &raquo;', 'simple-tags'); ?>"/>
379 </p>
380 </form>
381
382 <?php else : ?>
383 <p><?php _e('No content to edit.', 'simple-tags'); ?>
384
385 <?php endif; ?>
386
387 <?php SimpleTags_Admin::printAdminFooter(); ?>
388 </div>
389
390 <div class="taxopress-right-sidebar admin-settings-sidebar">
391 <?php do_action('taxopress_admin_after_sidebar'); ?>
392 </div>
393
394 </div>
395
396 <?php
397 do_action('simpletags-mass_terms', SimpleTags_Admin::$taxonomy);
398 }
399
400 /**
401 * Clone the core WP function, add the possibility to manage the post type
402 *
403 * @param bool $q
404 *
405 * @return array
406 * @author WebFactory Ltd
407 */
408 public static function edit_data_query($q = false)
409 {
410 if (false === $q) {
411 $q = $_GET;
412 }
413
414 if (! isset($q['massedit_filter_term'])) {
415 $q['massedit_filter_term'] = '';
416 }
417
418 // Date
419 if (isset($q['m'])) {
420 $q['m'] = (int) $q['m'];
421 }
422
423 // Category
424 if (isset($q['cat'])) {
425 $q['cat'] = (int) $q['cat'];
426 }
427
428 // Quantity
429 $q['posts_per_page'] = (isset($q['posts_per_page'])) ? (int) $q['posts_per_page'] : 0;
430 if ($q['posts_per_page'] == 0) {
431 $q['posts_per_page'] = 15;
432 }
433
434 // Pagination
435 $q['paged'] = isset($q['paged']) ? max(1, (int) $q['paged']) : 1;
436
437 // Content type
438 $q['post_type'] = SimpleTags_Admin::$post_type;
439
440 // Post status
441 $post_stati = array( // array( adj, noun )
442 'publish' => array(
443 _x('Published', 'post'),
444 __('Published posts'),
445 _n_noop('Published <span class="count">(%s)</span>', 'Published <span class="count">(%s)</span>')
446 ),
447 'future' => array(
448 _x('Scheduled', 'post'),
449 __('Scheduled posts'),
450 _n_noop('Scheduled <span class="count">(%s)</span>', 'Scheduled <span class="count">(%s)</span>')
451 ),
452 'pending' => array(
453 _x('Pending Review', 'post'),
454 __('Pending posts'),
455 _n_noop('Pending Review <span class="count">(%s)</span>', 'Pending Review <span class="count">(%s)</span>')
456 ),
457 'draft' => array(
458 _x('Draft', 'post'),
459 _x('Drafts', 'manage posts header'),
460 _n_noop('Draft <span class="count">(%s)</span>', 'Drafts <span class="count">(%s)</span>')
461 ),
462 'private' => array(
463 _x('Private', 'post'),
464 __('Private posts'),
465 _n_noop('Private <span class="count">(%s)</span>', 'Private <span class="count">(%s)</span>')
466 ),
467 'inherit' => array(
468 _x('Inherit', 'post'),
469 __('Inherit posts'),
470 _n_noop('Inherit <span class="count">(%s)</span>', 'Inherit <span class="count">(%s)</span>')
471 ),
472 );
473
474 $post_stati = apply_filters('post_stati', $post_stati);
475 $avail_post_stati = get_available_post_statuses(SimpleTags_Admin::$post_type);
476
477
478 if ($q['post_type'] === 'attachment') {
479 $q['post_status'] = 'inherit';
480 }
481
482 $post_status_q = '';
483 if (isset($q['post_status']) && in_array($q['post_status'], array_keys($post_stati))) {
484 $post_status_q = '&post_status=' . $q['post_status'];
485 $post_status_q .= '&perm=readable';
486 } elseif (! isset($q['post_status'])) {
487 $q['post_status'] = '';
488 }
489
490
491 if ('pending' === $q['post_status']) {
492 $order = 'ASC';
493 $orderby = 'modified';
494 } elseif ('draft' === $q['post_status']) {
495 $order = 'DESC';
496 $orderby = 'modified';
497 } else {
498 $order = 'DESC';
499 $orderby = 'date';
500 }
501
502 $args = array(
503 'post_type' => $q['post_type'],
504 'what_to_show' => 'posts',
505 'posts_per_page' => $q['posts_per_page'],
506 'paged' => $q['paged'],
507 'order' => $order,
508 'orderby' => $orderby,
509 );
510
511 if (! empty($q['post_status']) && in_array($q['post_status'], array_keys($post_stati), true)) {
512 $args['post_status'] = $q['post_status'];
513 $args['perm'] = 'readable';
514 }
515
516 if (! empty($q['s'])) {
517 $args['s'] = sanitize_text_field($q['s']);
518 }
519
520 if (! empty($q['m']) && (int) $q['m'] > 0) {
521 $args['m'] = (int) $q['m'];
522 }
523
524 if (! empty($q['massedit_filter_term'])) {
525 $args['tax_query'] = array(
526 array(
527 'taxonomy' => SimpleTags_Admin::$taxonomy,
528 'field' => 'slug',
529 'terms' => sanitize_text_field($q['massedit_filter_term']),
530 ),
531 );
532 }
533
534 $GLOBALS['wp_query'] = new WP_Query();
535 $GLOBALS['wp_query']->query($args);
536
537 return array( $post_stati, $avail_post_stati );
538 }
539 }
540