PluginProbe
Docket Cache – Object Cache Accelerator / trunk
Docket Cache – Object Cache Accelerator vtrunk
26.04.05 trunk 22.07.01 22.07.02 22.07.03 22.07.04 22.07.05 23.08.01 23.08.02 24.07.01 24.07.02 24.07.03 24.07.04 24.07.05 24.07.06 24.07.07 26.04.03 26.04.04
docket-cache / includes / src / TermCount.php

TermCount.php in Docket Cache – Object Cache Accelerator trunk, at includes/src/TermCount.php

206 lines 6.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Docket Cache.
4 *
5 * @author Nawawi Jamili
6 * @license MIT
7 *
8 * @see https://github.com/nawawi/docket-cache
9 */
10
11 namespace Nawawi\DocketCache;
12
13 \defined('ABSPATH') || exit;
14
15 final class TermCount
16 {
17 public $counted_status;
18 public $counted_terms;
19
20 public function __construct()
21 {
22 $this->counted_status = ['publish'];
23 $this->counted_terms = [];
24 }
25
26 public function register()
27 {
28 if (nwdcx_construe('WP_CLI') || nwdcx_construe('WP_IMPORTING') || wp_doing_cron()) {
29 return;
30 }
31
32 if (!nwdcx_wpdb()) {
33 return;
34 }
35
36 add_action(
37 'init',
38 function () {
39 wp_defer_term_counting(true);
40 remove_action('transition_post_status', '_update_term_count_on_transition_post_status');
41
42 add_action('transition_post_status', [$this, 'transition_post_status'], 10, 3);
43 add_action('added_term_relationship', [$this, 'added_term_relationship'], 10, 3);
44 add_action('deleted_term_relationships', [$this, 'deleted_term_relationships'], 10, 3);
45 add_action('edit_term', [$this, 'maybe_recount_posts_for_term'], 10, 3);
46 }
47 );
48 }
49
50 public function added_term_relationship($object_id, $tt_id, $taxonomy)
51 {
52 $this->handle_term_relationship_change($object_id, (array) $tt_id, $taxonomy, 'increment');
53 }
54
55 public function deleted_term_relationships($object_id, $tt_ids, $taxonomy)
56 {
57 $this->handle_term_relationship_change($object_id, $tt_ids, $taxonomy, 'decrement');
58 }
59
60 private function handle_term_relationship_change($object_id, $tt_ids, $taxonomy, $transition_type)
61 {
62 $post = get_post($object_id);
63
64 if (!$post || !is_object_in_taxonomy($post->post_type, $taxonomy)) {
65 $this->quick_update_terms_count($object_id, $tt_ids, $taxonomy, $transition_type);
66 } elseif (\in_array(get_post_status($post), $this->counted_status, true)) {
67 $this->quick_update_terms_count($object_id, $tt_ids, $taxonomy, $transition_type);
68 } else {
69 clean_term_cache($tt_ids, '', false);
70 }
71 }
72
73 public function transition_post_status($new_status, $old_status, $post)
74 {
75 $object_taxonomies = (array) get_object_taxonomies($post->post_type);
76 foreach ($object_taxonomies as $taxonomy) {
77 $tt_ids = wp_get_object_terms($post->ID, $taxonomy, ['fields' => 'tt_ids']);
78
79 if (!empty($tt_ids) && !is_wp_error($tt_ids)) {
80 $this->quick_update_terms_count(
81 $post->ID,
82 $tt_ids,
83 $taxonomy,
84 $this->transition_type($new_status, $old_status)
85 );
86 }
87 }
88
89 if ('attachment' !== $post->post_type) {
90 $attachments = new \WP_Query(
91 [
92 'post_type' => 'attachment',
93 'post_parent' => $post->ID,
94 'post_status' => 'inherit',
95 'ignore_sticky_posts' => true,
96 'no_found_rows' => true,
97 'posts_per_page' => -1,
98 'fields' => 'ids',
99 'orderby' => 'ID',
100 'order' => 'ASC',
101 ]
102 );
103
104 if ($attachments->have_posts()) {
105 foreach ($attachments->posts as $attachment_id) {
106 $this->transition_post_status(
107 $new_status,
108 $old_status,
109 (object) [
110 'ID' => $attachment_id,
111 'post_type' => 'attachment',
112 ]
113 );
114 }
115 }
116 }
117 }
118
119 public function quick_update_terms_count($object_id, $tt_ids, $taxonomy, $transition_type)
120 {
121 if (!nwdcx_wpdb($wpdb)) {
122 return;
123 }
124
125 if (!$transition_type) {
126 return;
127 }
128
129 $taxonomy_get = get_taxonomy($taxonomy);
130 if ($taxonomy_get) {
131 $tt_ids = array_filter(array_map('intval', (array) $tt_ids));
132
133 if (!empty($taxonomy_get->update_count_callback)) {
134 \call_user_func($taxonomy_get->update_count_callback, $tt_ids, $taxonomy_get);
135 } elseif (!empty($tt_ids)) {
136 if (!isset($this->counted_terms[$object_id][$taxonomy][$transition_type])) {
137 $this->counted_terms[$object_id][$taxonomy][$transition_type] = [];
138 }
139
140 $tt_ids = array_diff($tt_ids, $this->counted_terms[$object_id][$taxonomy][$transition_type]);
141
142 if (empty($tt_ids)) {
143 return;
144 }
145
146 $this->counted_terms[$object_id][$taxonomy][$transition_type] = array_merge(
147 $this->counted_terms[$object_id][$taxonomy][$transition_type],
148 $tt_ids
149 );
150
151 $tt_ids = array_map('absint', $tt_ids);
152 $tt_ids_string = '('.implode(',', $tt_ids).')';
153
154 $taxonomy_table = $wpdb->term_taxonomy;
155 if ('increment' === $transition_type) {
156 $update_query = sprintf('UPDATE `%s` AS tt SET tt.count = tt.count + 1 WHERE tt.term_taxonomy_id IN %s', $taxonomy_table, $tt_ids_string);
157 } else {
158 $update_query = sprintf('UPDATE `%s` AS tt SET tt.count = tt.count - 1 WHERE tt.term_taxonomy_id IN %s AND tt.count > 0', $taxonomy_table, $tt_ids_string);
159 }
160
161 foreach ($tt_ids as $tt_id) {
162 do_action('edit_term_taxonomy', $tt_id, $taxonomy);
163 }
164
165 $wpdb->query($update_query);
166 foreach ($tt_ids as $tt_id) {
167 do_action('edited_term_taxonomy', $tt_id, $taxonomy);
168 }
169 }
170
171 clean_term_cache($tt_ids, '', false);
172 }
173 }
174
175 public function transition_type($new, $old)
176 {
177 if (!\is_array($this->counted_status) || !$this->counted_status) {
178 return false;
179 }
180
181 $new_is_counted = \in_array($new, $this->counted_status, true);
182 $old_is_counted = \in_array($old, $this->counted_status, true);
183
184 if ($new_is_counted && !$old_is_counted) {
185 return 'increment';
186 } elseif ($old_is_counted && !$new_is_counted) {
187 return 'decrement';
188 }
189
190 return false;
191 }
192
193 public function maybe_recount_posts_for_term($term_id, $tt_id, $taxonomy)
194 {
195 $screen = \function_exists('get_current_screen') ? get_current_screen() : '';
196 if (!($screen instanceof \WP_Screen)) {
197 return false;
198 }
199 if ('edit-'.$taxonomy === $screen->id) {
200 wp_update_term_count_now([$tt_id], $taxonomy);
201 }
202
203 return true;
204 }
205 }
206