PageRenderTime 26ms CodeModel.GetById 13ms app.highlight 9ms RepoModel.GetById 1ms app.codeStats 0ms

/wp-content/plugins/wordpress-seo/admin/import/plugins/class-abstract-plugin-importer.php

https://bitbucket.org/carloskikea/helpet
PHP | 318 lines | 151 code | 40 blank | 127 comment | 14 complexity | 0dc7962dd3116de2dacf2c4fcf516657 MD5 | raw file
  1<?php
  2/**
  3 * This file holds the abstract class for dealing with imports from other plugins.
  4 *
  5 * @package WPSEO\Admin\Import\Plugins
  6 */
  7
  8/**
  9 * Class WPSEO_Plugin_Importer
 10 *
 11 * Class with functionality to import meta data from other plugins.
 12 */
 13abstract class WPSEO_Plugin_Importer {
 14	/**
 15	 * Holds the import status object.
 16	 *
 17	 * @var WPSEO_Import_Status
 18	 */
 19	protected $status;
 20
 21	/**
 22	 * The plugin name.
 23	 *
 24	 * @var string
 25	 */
 26	protected $plugin_name;
 27
 28	/**
 29	 * Meta key, used in SQL LIKE clause for delete query.
 30	 *
 31	 * @var string
 32	 */
 33	protected $meta_key;
 34
 35	/**
 36	 * Array of meta keys to detect and import.
 37	 *
 38	 * @var array
 39	 */
 40	protected $clone_keys;
 41
 42	/**
 43	 * Class constructor.
 44	 */
 45	public function __construct() {
 46	}
 47
 48	/**
 49	 * Returns the string for the plugin we're importing from.
 50	 *
 51	 * @return string Plugin name.
 52	 */
 53	public function get_plugin_name() {
 54		return $this->plugin_name;
 55	}
 56
 57	/**
 58	 * Imports the settings and post meta data from another SEO plugin.
 59	 *
 60	 * @return WPSEO_Import_Status Import status object.
 61	 */
 62	public function run_import() {
 63		$this->status = new WPSEO_Import_Status( 'import', false );
 64
 65		if ( ! $this->detect() ) {
 66			return $this->status;
 67		}
 68
 69		$this->status->set_status( $this->import() );
 70
 71		// Flush the entire cache, as we no longer know what's valid and what's not.
 72		wp_cache_flush();
 73
 74		return $this->status;
 75	}
 76
 77	/**
 78	 * Handles post meta data to import.
 79	 *
 80	 * @return bool Import success status.
 81	 */
 82	protected function import() {
 83		return $this->meta_keys_clone( $this->clone_keys );
 84	}
 85
 86	/**
 87	 * Removes the plugin data from the database.
 88	 *
 89	 * @return WPSEO_Import_Status Import status object.
 90	 */
 91	public function run_cleanup() {
 92		$this->status = new WPSEO_Import_Status( 'cleanup', false );
 93
 94		if ( ! $this->detect() ) {
 95			return $this->status;
 96		}
 97
 98		return $this->status->set_status( $this->cleanup() );
 99	}
100
101	/**
102	 * Removes the plugin data from the database.
103	 *
104	 * @return bool Cleanup status.
105	 */
106	protected function cleanup() {
107		global $wpdb;
108		if ( empty( $this->meta_key ) ) {
109			return true;
110		}
111		$wpdb->query(
112			$wpdb->prepare(
113				"DELETE FROM {$wpdb->postmeta} WHERE meta_key LIKE %s",
114				$this->meta_key
115			)
116		);
117		$result = $wpdb->__get( 'result' );
118		if ( ! $result ) {
119			$this->cleanup_error_msg();
120		}
121
122		return $result;
123	}
124
125	/**
126	 * Sets the status message for when a cleanup has gone bad.
127	 *
128	 * @return void
129	 */
130	protected function cleanup_error_msg() {
131		/* translators: %s is replaced with the plugin's name. */
132		$this->status->set_msg( sprintf( __( 'Cleanup of %s data failed.', 'wordpress-seo' ), $this->plugin_name ) );
133	}
134
135	/**
136	 * Detects whether an import for this plugin is needed.
137	 *
138	 * @return WPSEO_Import_Status Import status object.
139	 */
140	public function run_detect() {
141		$this->status = new WPSEO_Import_Status( 'detect', false );
142
143		if ( ! $this->detect() ) {
144			return $this->status;
145		}
146
147		return $this->status->set_status( true );
148	}
149
150	/**
151	 * Detects whether there is post meta data to import.
152	 *
153	 * @return bool Boolean indicating whether there is something to import.
154	 */
155	protected function detect() {
156		global $wpdb;
157
158		$meta_keys    = wp_list_pluck( $this->clone_keys, 'old_key' );
159		$placeholders = implode( ', ', array_fill( 0, count( $meta_keys ), '%s' ) );
160		$result       = $wpdb->get_var(
161			$wpdb->prepare(
162				"SELECT COUNT(*) AS `count` FROM {$wpdb->postmeta} WHERE meta_key IN ( $placeholders )",
163				$meta_keys
164			)
165		);
166		if ( $result === '0' ) {
167			return false;
168		}
169
170		return true;
171	}
172
173	/**
174	 * Helper function to clone meta keys and (optionally) change their values in bulk.
175	 *
176	 * @param string $old_key        The existing meta key.
177	 * @param string $new_key        The new meta key.
178	 * @param array  $replace_values An array, keys old value, values new values.
179	 *
180	 * @return bool Clone status.
181	 */
182	protected function meta_key_clone( $old_key, $new_key, $replace_values = array() ) {
183		global $wpdb;
184
185		// First we create a temp table with all the values for meta_key.
186		$result = $wpdb->query(
187			$wpdb->prepare(
188				"CREATE TEMPORARY TABLE tmp_meta_table SELECT * FROM {$wpdb->postmeta} WHERE meta_key = %s",
189				$old_key
190			)
191		);
192		if ( $result === false ) {
193			$this->set_missing_db_rights_status();
194			return false;
195		}
196
197		// Delete all the values in our temp table for posts that already have data for $new_key.
198		$wpdb->query(
199			$wpdb->prepare(
200				"DELETE FROM tmp_meta_table WHERE post_id IN ( SELECT post_id FROM {$wpdb->postmeta} WHERE meta_key = %s )",
201				WPSEO_Meta::$meta_prefix . $new_key
202			)
203		);
204
205		// We set meta_id to NULL so on re-insert into the postmeta table, MYSQL can set new meta_id's and we don't get duplicates.
206		$wpdb->query( 'UPDATE tmp_meta_table SET meta_id = NULL' );
207
208		// Now we rename the meta_key.
209		$wpdb->query(
210			$wpdb->prepare(
211				'UPDATE tmp_meta_table SET meta_key = %s',
212				WPSEO_Meta::$meta_prefix . $new_key
213			)
214		);
215
216		$this->meta_key_clone_replace( $replace_values );
217
218		// With everything done, we insert all our newly cloned lines into the postmeta table.
219		$wpdb->query( "INSERT INTO {$wpdb->postmeta} SELECT * FROM tmp_meta_table" );
220
221		// Now we drop our temporary table.
222		$wpdb->query( 'DROP TEMPORARY TABLE IF EXISTS tmp_meta_table' );
223
224		return true;
225	}
226
227	/**
228	 * Clones multiple meta keys.
229	 *
230	 * @param array $clone_keys The keys to clone.
231	 *
232	 * @return bool Success status.
233	 */
234	protected function meta_keys_clone( $clone_keys ) {
235		foreach ( $clone_keys as $clone_key ) {
236			$result = $this->meta_key_clone( $clone_key['old_key'], $clone_key['new_key'], isset( $clone_key['convert'] ) ? $clone_key['convert'] : array() );
237			if ( ! $result ) {
238				return false;
239			}
240		}
241		return true;
242	}
243
244	/**
245	 * Sets the import status to false and returns a message about why it failed.
246	 */
247	protected function set_missing_db_rights_status() {
248		$this->status->set_status( false );
249		/* translators: %s is replaced with Yoast SEO. */
250		$this->status->set_msg( sprintf( __( 'The %s importer functionality uses temporary database tables. It seems your WordPress install does not have the capability to do this, please consult your hosting provider.', 'wordpress-seo' ), 'Yoast SEO' ) );
251	}
252
253	/**
254	 * Helper function to search for a key in an array and maybe save it as a meta field.
255	 *
256	 * @param string $plugin_key The key in the $data array to check.
257	 * @param string $yoast_key  The identifier we use in our meta settings.
258	 * @param array  $data       The array of data for this post to sift through.
259	 * @param int    $post_id    The post ID.
260	 *
261	 * @return void
262	 */
263	protected function import_meta_helper( $plugin_key, $yoast_key, $data, $post_id ) {
264		if ( ! empty( $data[ $plugin_key ] ) ) {
265			$this->maybe_save_post_meta( $yoast_key, $data[ $plugin_key ], $post_id );
266		}
267	}
268
269	/**
270	 * Saves a post meta value if it doesn't already exist.
271	 *
272	 * @param string $new_key The key to save.
273	 * @param mixed  $value   The value to set the key to.
274	 * @param int    $post_id The Post to save the meta for.
275	 */
276	protected function maybe_save_post_meta( $new_key, $value, $post_id ) {
277		// Big. Fat. Sigh. Mostly used for _yst_is_cornerstone, but might be useful for other hidden meta's.
278		$key        = WPSEO_Meta::$meta_prefix . $new_key;
279		$wpseo_meta = true;
280		if ( substr( $new_key, 0, 1 ) === '_' ) {
281			$key        = $new_key;
282			$wpseo_meta = false;
283		}
284
285		$existing_value = get_post_meta( $post_id, $key, true );
286		if ( empty( $existing_value ) ) {
287			if ( $wpseo_meta ) {
288				WPSEO_Meta::set_value( $new_key, $value, $post_id );
289				return;
290			}
291			update_post_meta( $post_id, $new_key, $value );
292		}
293	}
294
295	/**
296	 * Replaces values in our temporary table according to our settings.
297	 *
298	 * @param array $replace_values Key value pair of values to replace with other values.
299	 *
300	 * @return void
301	 */
302	protected function meta_key_clone_replace( $replace_values ) {
303		global $wpdb;
304
305		// Now we replace values if needed.
306		if ( is_array( $replace_values ) && $replace_values !== array() ) {
307			foreach ( $replace_values as $old_value => $new_value ) {
308				$wpdb->query(
309					$wpdb->prepare(
310						'UPDATE tmp_meta_table SET meta_value = %s WHERE meta_value = %s',
311						$new_value,
312						$old_value
313					)
314				);
315			}
316		}
317	}
318}