PluginProbe
ElasticPress / 4.5.1
ElasticPress v4.5.1
5.3.5 5.3.4 3.6.5 3.6.6 4.0.0 4.0.1 4.1.0 4.2.0 4.2.1 4.2.2 4.3.0 4.3.1 4.4.0 4.4.1 4.5.0 4.5.1 4.5.2 4.6.0 4.6.1 4.7.0 4.7.1 4.7.2 5.0.0 5.0.1 5.0.2 All 108 releases
elasticpress / includes / classes / SyncManager.php

SyncManager.php in ElasticPress 4.5.1, at includes/classes/SyncManager.php

284 lines 6.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * SyncManager common functionality
4 *
5 * @package elasticpress
6 * @since 3.0
7 */
8
9 namespace ElasticPress;
10
11 use ElasticPress\Utils;
12
13 /**
14 * Abstract sync manager class to be extended for each indexable
15 */
16 abstract class SyncManager {
17
18 /**
19 * Save objects for indexing later
20 *
21 * @since 3.0
22 * @var array
23 */
24 public $sync_queue = [];
25
26 /**
27 * Indexable slug
28 *
29 * @var string
30 * @since 3.0
31 */
32 public $indexable_slug;
33
34 /**
35 * Create new SyncManager
36 *
37 * @param string $indexable_slug Indexable slug.
38 * @since 3.0
39 */
40 public function __construct( $indexable_slug ) {
41 $this->indexable_slug = $indexable_slug;
42
43 if ( defined( 'EP_SYNC_CHUNK_LIMIT' ) && is_numeric( EP_SYNC_CHUNK_LIMIT ) ) {
44 /**
45 * We also sync when we exceed Chunk limit set.
46 * This is sometimes useful when posts are generated programatically.
47 */
48 add_action( 'ep_after_add_to_queue', [ $this, 'index_sync_on_chunk_limit' ] );
49 }
50 /**
51 * We do all syncing on shutdown or redirect
52 */
53 add_action( 'shutdown', [ $this, 'index_sync_queue' ] );
54 add_filter( 'wp_redirect', [ $this, 'index_sync_queue_on_redirect' ], 10, 1 );
55
56 /**
57 * Actions for multisite
58 */
59 add_action( 'delete_blog', array( $this, 'action_delete_blog_from_index' ) );
60 add_action( 'make_delete_blog', array( $this, 'action_delete_blog_from_index' ) );
61 add_action( 'make_spam_blog', array( $this, 'action_delete_blog_from_index' ) );
62 add_action( 'archive_blog', array( $this, 'action_delete_blog_from_index' ) );
63 add_action( 'deactivate_blog', array( $this, 'action_delete_blog_from_index' ) );
64
65 // Implemented by children.
66 $this->setup();
67 }
68
69 /**
70 * Add an object to the sync queue.
71 *
72 * @param id $object_id object ID to sync
73 * @since 3.1.2
74 * @return boolean
75 */
76 public function add_to_queue( $object_id ) {
77 if ( ! is_numeric( $object_id ) ) {
78 return false;
79 }
80 $this->sync_queue[ $object_id ] = true;
81
82 /**
83 * Fires after item is added to sync queue
84 *
85 * @hook ep_after_add_to_queue
86 * @param {int} $object_id ID of object
87 * @param {array} $sync_queue Current sync queue
88 * @since 3.1.2
89 */
90 do_action( 'ep_after_add_to_queue', $object_id, $this->sync_queue );
91
92 return true;
93 }
94
95 /**
96 * Remove an object from the sync queue.
97 *
98 * @param id $object_id object ID to remove from the queue
99 * @since 3.5
100 * @return boolean
101 */
102 public function remove_from_queue( $object_id ) {
103 if ( ! is_numeric( $object_id ) ) {
104 return false;
105 }
106
107 unset( $this->sync_queue[ $object_id ] );
108
109 /**
110 * Fires after item is removed from sync queue
111 *
112 * @hook ep_after_remove_from_queue
113 * @param {int} $object_id ID of object
114 * @param {array} $sync_queue Current sync queue
115 * @since 3.5
116 */
117 do_action( 'ep_after_remove_from_queue', $object_id, $this->sync_queue );
118
119 return true;
120 }
121
122 /**
123 * Sync queued objects if the EP_SYNC_CHUNK_LIMIT is reached.
124 *
125 * @since 3.1.2
126 * @return boolean
127 */
128 public function index_sync_on_chunk_limit() {
129 if ( defined( 'EP_SYNC_CHUNK_LIMIT' ) && is_numeric( EP_SYNC_CHUNK_LIMIT ) &&
130 is_array( $this->sync_queue ) && count( $this->sync_queue ) > EP_SYNC_CHUNK_LIMIT ) {
131 $this->index_sync_queue();
132 }
133 return true;
134 }
135
136 /**
137 * Sync queued objects before a redirect occurs. Hackish but very important since
138 * shutdown won't be firing
139 *
140 * @param string $location Redirect location.
141 * @since 3.0
142 * @return string
143 */
144 public function index_sync_queue_on_redirect( $location ) {
145 $this->index_sync_queue();
146
147 return $location;
148 }
149
150
151 /**
152 * Sync objects in queue.
153 *
154 * @since 3.0
155 */
156 public function index_sync_queue() {
157 if ( empty( $this->sync_queue ) ) {
158 return;
159 }
160
161 /**
162 * Allow other code to intercept the sync process
163 *
164 * @hook pre_ep_index_sync_queue
165 * @param {boolean} $bail True to skip the rest of index_sync_queue(), false to continue normally
166 * @param {SyncManager} $sync_manager SyncManager instance for the indexable
167 * @param {string} $indexable_slug Slug of the indexable being synced
168 * @since 3.5
169 */
170 if ( apply_filters( 'pre_ep_index_sync_queue', false, $this, $this->indexable_slug ) ) {
171 return;
172 }
173
174 /**
175 * Backwards compat for pre-3.0
176 */
177 foreach ( $this->sync_queue as $object_id => $value ) {
178 /**
179 * Fires when object in queue are synced
180 *
181 * @hook ep_sync_on_meta_update_queue
182 * @param {int} $object_id ID of object
183 */
184 do_action( 'ep_sync_on_meta_update', $object_id );
185 }
186
187 // Bulk sync them all.
188 Indexables::factory()->get( $this->indexable_slug )->bulk_index_dynamically( array_keys( $this->sync_queue ) );
189
190 /**
191 * Make sure to reset sync queue in case an shutdown happens before a redirect
192 * when a redirect has already been triggered.
193 */
194 $this->sync_queue = [];
195 }
196
197 /**
198 * Check if we can index content in the current blog
199 *
200 * @since 3.5
201 * @return boolean
202 */
203 public function can_index_site() {
204 if ( ( defined( 'EP_IS_NETWORK' ) && EP_IS_NETWORK ) && ! Utils\is_site_indexable() ) {
205 $this->tear_down();
206 return false;
207 }
208
209 return true;
210 }
211
212 /**
213 * Determine whether syncing an indexable should take place.
214 *
215 * Returns true or false depending on the value of the WP_IMPORTING global.
216 * Contains the 'ep_sync_indexable_kill' filter that enables overriding the default behavior.
217 *
218 * @since 3.4.2
219 * @return bool
220 */
221 public function kill_sync() {
222
223 $is_importing = defined( 'WP_IMPORTING' ) && true === WP_IMPORTING;
224
225 /**
226 * Filter whether to bypass sync.
227 *
228 * @since 3.4.2
229 * @hook ep_sync_indexable_kill
230 * @param {boolean} $kill True if WP_IMPORTING is defined and true, else false.
231 * @param {array} $indexable_slug Indexable slug.
232 */
233 return apply_filters( 'ep_sync_indexable_kill', $is_importing, $this->indexable_slug );
234 }
235
236 /**
237 * Remove blog from index when a site is deleted, archived, or deactivated
238 *
239 * @param int $blog_id WP Blog ID.
240 */
241 public function action_delete_blog_from_index( $blog_id ) {
242 if ( $this->kill_sync() ) {
243 return;
244 }
245
246 $indexable = Indexables::factory()->get( $this->indexable_slug );
247
248 // Don't delete global indexes
249 if ( $indexable->global ) {
250 return;
251 }
252
253 /**
254 * Filter to whether to keep index on site deletion
255 *
256 * @hook ep_keep_index
257 * @since 3.0
258 * @since 3.6.2 Moved from Post\SyncManager to the main SyncManager class
259 * @since 3.6.5 Added `$blog_id` and `$indexable_slug`
260 * @param {bool} $keep True means don't delete index
261 * @param {int} $blog_id WP Blog ID
262 * @param {string} $indexable_slug Indexable slug
263 * @return {bool} New value
264 */
265 if ( $indexable->index_exists( $blog_id ) && ! apply_filters( 'ep_keep_index', false, $blog_id, $this->indexable_slug ) ) {
266 $indexable->delete_index( $blog_id );
267 }
268 }
269
270 /**
271 * Implementation should setup hooks/filters
272 *
273 * @since 3.0
274 */
275 abstract public function setup();
276
277 /**
278 * Implementation (for multisite) should un-setup hooks/filters if applicable.
279 *
280 * @since 4.0
281 */
282 abstract public function tear_down();
283 }
284