PluginProbe
ElasticPress / 4.7.1
ElasticPress v4.7.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 / Upgrades.php

Upgrades.php in ElasticPress 4.7.1, at includes/classes/Upgrades.php

374 lines 9.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Handle upgrades.
4 *
5 * @since 3.x
6 * @package elasticpress
7 */
8
9 namespace ElasticPress;
10
11 use ElasticPress\Utils;
12
13 if ( ! defined( 'ABSPATH' ) ) {
14 exit; // Exit if accessed directly.
15 }
16
17 /**
18 * Class Upgrades
19 *
20 * @package ElasticPress
21 */
22 class Upgrades {
23
24 /**
25 * Store the version number before performing upgrades.
26 * Set in the `setup()` method.
27 *
28 * @var null|string
29 */
30 protected $old_version;
31
32 /**
33 * Initialize class
34 */
35 public function setup() {
36 $this->old_version = Utils\get_option( 'ep_version', false );
37
38 /**
39 * An array with the upgrades routines.
40 * Indexes are the ElasticPress version and values
41 * are an array with the method name and, if needed,
42 * the action name where it should be hooked.
43 */
44 $routines = [
45 '3.5.2' => [ 'upgrade_3_5_2', 'init' ],
46 '3.5.3' => [ 'upgrade_3_5_3', 'init' ],
47 '3.6.6' => [ 'upgrade_3_6_6', 'init' ],
48 '4.2.2' => [ 'upgrade_4_2_2', 'init' ],
49 '4.4.0' => [ 'upgrade_4_4_0', 'init' ],
50 '4.5.0' => [ 'upgrade_4_5_0', 'init' ],
51 '4.7.0' => [ 'upgrade_4_7_0', 'init' ],
52 ];
53
54 array_walk( $routines, [ $this, 'run_upgrade_routine' ] );
55
56 /**
57 * Check if a reindex is needed.
58 */
59 add_action( 'plugins_loaded', [ $this, 'check_reindex_needed' ], 5 );
60
61 /**
62 * Update the version number.
63 * Note: if a upgrade routine method is hooked to some action,
64 * this code will be executed *earlier* than the routine method.
65 */
66 Utils\update_option( 'ep_version', sanitize_text_field( EP_VERSION ) );
67
68 add_filter( 'ep_admin_notices', [ $this, 'resync_notice_4_0_0_instant_results' ] );
69 }
70
71 /**
72 * Run the upgrade routine, if needed.
73 *
74 * @param array $routine Array with the info about the method to call.
75 * If needed to be run in an action, it'll contain the action name.
76 * @param string $version The version number to be tested.
77 */
78 protected function run_upgrade_routine( $routine, $version ) {
79 if ( version_compare( $this->old_version, $version, '<' ) ) {
80 $function_name = $routine[0];
81 $action_tag = $routine[1];
82 $priority = ( ! empty( $routine[2] ) ) ? $routine[2] : 10;
83 if ( $action_tag ) {
84 add_action( $action_tag, [ $this, $function_name ], $priority );
85 } else {
86 $this->$function_name();
87 }
88 }
89 }
90
91 /**
92 * Upgrade routine of v3.5.2.
93 *
94 * If weighting options exist and the WooCommerce feature is enabled,
95 * this method will enable the SKU field.
96 */
97 public function upgrade_3_5_2() {
98 $weighting_options = get_option( 'elasticpress_weighting', [] );
99 if ( empty( $weighting_options ) ) {
100 return;
101 }
102
103 $woocommerce = Features::factory()->get_registered_feature( 'woocommerce' );
104 if ( ! $woocommerce->is_active() ) {
105 return;
106 }
107
108 if ( empty( $weighting_options['product'] ) ) {
109 return;
110 }
111
112 if ( ! empty( $weighting_options['product']['author_name'] ) ) {
113 unset( $weighting_options['product']['author_name'] );
114 }
115
116 $weighting_options['product']['meta._sku.value'] = array(
117 'enabled' => true,
118 'weight' => 1,
119 );
120
121 update_option( 'elasticpress_weighting', $weighting_options );
122 }
123
124 /**
125 * Upgrade routine of v3.5.3.
126 *
127 * Check if synonyms post has the correct post type, otherwise,
128 * change it to the correct one.
129 */
130 public function upgrade_3_5_3() {
131 delete_option( 'elasticpress_synonyms_post_id' );
132 delete_site_option( 'elasticpress_synonyms_post_id' );
133 }
134
135 /**
136 * Upgrade routine of v3.6.6.
137 *
138 * Delete all synonyms that have the post content identical to the example we set.
139 * In previous versions we had a bug that created several posts with it.
140 *
141 * @see https://github.com/10up/ElasticPress/issues/2516
142 */
143 public function upgrade_3_6_6() {
144 global $wpdb;
145
146 $synonyms = \ElasticPress\Features::factory()->get_registered_feature( 'search' )->synonyms;
147
148 if ( ! $synonyms ) {
149 return;
150 }
151
152 // phpcs:disable WordPress.DB.DirectDatabaseQuery
153 $synonyms_example_ids = $wpdb->get_col(
154 $wpdb->prepare(
155 "SELECT ID FROM {$wpdb->posts} WHERE post_type = %s AND post_content = %s LIMIT 100",
156 $synonyms::POST_TYPE_NAME,
157 $synonyms->example_synonym_list()
158 )
159 );
160 // phpcs:enable WordPress.DB.DirectDatabaseQuery
161
162 if ( ! $synonyms_example_ids ) {
163 return;
164 }
165
166 foreach ( $synonyms_example_ids as $synonym_post_id ) {
167 wp_delete_post( $synonym_post_id, true );
168 }
169 }
170
171 /**
172 * Upgrade routine of v4.2.2.
173 *
174 * Delete the transient with ES info, so EP is forced to fetch it again,
175 * determining the correct software type (elasticsearch or opensearch, for example)
176 *
177 * @see https://github.com/10up/ElasticPress/issues/2882
178 */
179 public function upgrade_4_2_2() {
180 if ( defined( 'EP_IS_NETWORK' ) && EP_IS_NETWORK ) {
181 delete_site_transient( 'ep_es_info' );
182 } else {
183 delete_transient( 'ep_es_info' );
184 }
185 }
186
187 /**
188 * Upgrade routine of v4.4.0.
189 *
190 * Delete the ep_prefix option, as that is now obtained via ep_credentials
191 *
192 * @see https://github.com/10up/ElasticPress/issues/2739
193 */
194 public function upgrade_4_4_0() {
195 Utils\delete_option( 'ep_prefix' );
196 }
197
198 /**
199 * Upgrade routine of v4.5.0.
200 *
201 * Add the ElasticPress capability to admins
202 *
203 * @see https://github.com/10up/ElasticPress/pull/3313
204 */
205 public function upgrade_4_5_0() {
206 setup_roles();
207 }
208
209 /**
210 * Upgrade routine of v4.7.0.
211 *
212 * Remove old total_fields_limit transients
213 * Remove cached autosuggest requests
214 *
215 * @see https://github.com/10up/ElasticPress/pull/3552
216 */
217 public function upgrade_4_7_0() {
218 global $wpdb;
219
220 if ( is_multisite() ) {
221 $sites = \get_sites( [ 'number' => 0 ] );
222 foreach ( $sites as $site ) {
223 $blog_option = get_blog_option( $site->blog_id, 'ep_indexable' );
224 if ( $blog_option ) {
225 update_site_meta( $site->blog_id, 'ep_indexable', $blog_option );
226 }
227 }
228 }
229
230 $transients = $wpdb->get_col( // phpcs:ignore WordPress.DB.DirectDatabaseQuery
231 "SELECT option_name
232 FROM {$wpdb->prefix}options
233 WHERE option_name LIKE '_transient_ep_total_fields_limit_%'"
234 );
235
236 foreach ( $transients as $transient ) {
237 $transient_name = str_replace( '_transient_', '', $transient );
238 delete_site_transient( $transient_name );
239 delete_transient( $transient_name );
240 }
241
242 if ( function_exists( 'wp_cache_supports' ) && wp_cache_supports( 'flush_group' ) ) {
243 wp_cache_flush_group( 'ep_autosuggest' );
244 }
245 delete_transient( 'ep_autosuggest_query_request_cache' );
246 }
247
248 /**
249 * Adjust the upgrade sync notice to warn users about Instant Results.
250 *
251 * As 4.0.0 introduces this new feature and it requires a resync, admin users
252 * might want to enable the feature before the resync (and then resync only once.)
253 *
254 * @since 4.0.0
255 * @param array $notices All admin notices
256 * @return array
257 */
258 public function resync_notice_4_0_0_instant_results( $notices ) {
259 if ( ! isset( $notices['upgrade_sync'] ) ) {
260 return $notices;
261 }
262
263 $instant_results = \ElasticPress\Features::factory()->get_registered_feature( 'instant-results' );
264 if ( $instant_results->is_active() ) {
265 return $notices;
266 }
267
268 $feature_status = $instant_results->requirements_status();
269 $appended_message = '';
270 if ( 1 >= $feature_status->code ) {
271 if ( defined( 'EP_IS_NETWORK' ) && EP_IS_NETWORK ) {
272 $features_url = admin_url( 'network/admin.php?page=elasticpress' );
273 } else {
274 $features_url = admin_url( 'admin.php?page=elasticpress' );
275 }
276
277 $appended_message = wp_kses_post(
278 sprintf(
279 /* translators: 1: <a> tag (Zendesk article); 2. </a>; 3: <a> tag (link to Features screen); 4. </a>; */
280 __( '%1$sInstant Results%2$s is now available in ElasticPress, but requires a re-sync before activation. If you would like to use Instant Results, click %3$shere%4$s to activate the feature and start your sync.', 'elasticpress' ),
281 '<a href="https://elasticpress.zendesk.com/hc/en-us/articles/360050447492#instant-results">',
282 '</a>',
283 '<a href="' . $features_url . '">',
284 '</a>'
285 )
286 );
287 } else {
288 $appended_message = wp_kses_post(
289 sprintf(
290 /* translators: 1: <a> tag (Zendesk article about Instant Results); 2. </a>; 3: <a> tag (Zendesk article about self hosted Elasticsearch setups); 4. </a>; */
291 __( '%1$sInstant Results%2$s is now available in ElasticPress, but requires a re-sync before activation. If you would like to use Instant Results, since you are not using ElasticPress.io, you will also need to %3$sinstall and configure a PHP proxy%4$s.', 'elasticpress' ),
292 '<a href="https://elasticpress.zendesk.com/hc/en-us/articles/360050447492#instant-results">',
293 '</a>',
294 '<a href="https://elasticpress.zendesk.com/hc/en-us/articles/4413938931853-Considerations-for-self-hosted-Elasticsearch-setups">',
295 '</a>'
296 )
297 );
298 }
299
300 $notices['upgrade_sync']['html'] .= '<br><br>' . $appended_message;
301
302 return $notices;
303 }
304
305 /**
306 * Check if a reindex is needed based on the version number.
307 */
308 public function check_reindex_needed() {
309 if ( ! is_admin() || defined( 'DOING_AJAX' ) ) {
310 return;
311 }
312
313 $last_sync = Utils\get_option( 'ep_last_sync', 'never' );
314
315 // No need to upgrade since we've never synced.
316 if ( empty( $last_sync ) || 'never' === $last_sync ) {
317 return;
318 }
319
320 /**
321 * Reindex if we cross a reindex version in the upgrade
322 */
323 $reindex_versions = apply_filters(
324 'ep_reindex_versions',
325 array(
326 '2.2',
327 '2.3.1',
328 '2.4',
329 '2.5.1',
330 '2.6',
331 '2.7',
332 '3.0',
333 '3.1',
334 '3.3',
335 '3.4',
336 '3.6.0',
337 '3.6.1',
338 '4.0.0-beta.1',
339 '4.0.0',
340 )
341 );
342
343 $need_upgrade_sync = false;
344
345 if ( false !== $this->old_version ) {
346 $last_reindex_version = $reindex_versions[ count( $reindex_versions ) - 1 ];
347
348 if ( -1 === version_compare( $this->old_version, $last_reindex_version ) && 0 <= version_compare( EP_VERSION, $last_reindex_version ) ) {
349 $need_upgrade_sync = true;
350 }
351 }
352
353 if ( $need_upgrade_sync ) {
354 Utils\update_option( 'ep_need_upgrade_sync', true );
355 }
356 }
357
358 /**
359 * Return singleton instance of class
360 *
361 * @return self
362 */
363 public static function factory() {
364 static $instance = false;
365
366 if ( ! $instance ) {
367 $instance = new self();
368 $instance->setup();
369 }
370
371 return $instance;
372 }
373 }
374