acf-options-for-polylang icon indicating copy to clipboard operation
acf-options-for-polylang copied to clipboard

Should be able to migrate data

Open simplenotezy opened this issue 5 years ago • 2 comments

What was expected

My old options page should be added upon plugin activation to the new options page. It's possible to fetch them like so:

get_options('name', 'options'); // for the default language
get_options('name_da', 'options'); // for the translated language

We have some quite huge options pages, so would be sweet if this was supported.

What happened instead

Options page is empty. I have to migrate all data manually.

simplenotezy avatar Sep 29 '20 15:09 simplenotezy

I wrote a little WP CLI command that could easily optionally be run on plugin activation. This should migrate data. I have tested on our application and it works. Thought I'd share here for anybody in need of the same, or perhaps it could be integrated in the repo.

/**
 * Sync ACF Options from WPML / other multi lang plugin (where options is stored in wp_options table as options_{language_if_not_default}_{field_name})
 * This will only COPY new data and not replace existing data, so it should be safe to run.
 * 
 * The idea here is that previously a field with name 'example' would be stored in wp_options as "options_en_example" for the translated language
 * and as "options_example" for the default language. In the new polylang acf options plugin, it is stored as: "options_en_US_example" and "options_da_DK_example" (if the
 * default language would be danish)
 * 
 * This script will search for all "options_da" or "options_" and create new options with same data to "optiosn_da_DK" and "options_en_US" given the
 * two languages is da_DK and en_US
 * 
 * Usage: `wp sync-acf-options-to-polylang`
 * 
 * @author Mattias Siø Fjellvang https://constantsolutions.dk
 */

	function sync_acf_options_to_polylang($args, $assoc_args) {
		global $wpdb;

		$default_lang = false;

		$languages = get_option('_transient_pll_languages_list');
		$polylang = get_option('polylang');
		$verbose = false;

		if (isset($assoc_args['verbose']) && $assoc_args['verbose']) {
			$verbose = true;

			WP_CLI::log( 'Verbose mode enabled' );
		} else {
			WP_CLI::confirm( 'Are you sure you wish to create migrate data to Polylang ACF? No keys will be deleted' );
		}

		if(isset($polylang['default_lang']) && $polylang['default_lang']) {
			$default_lang_slug = $polylang['default_lang'];
		}
		
		foreach ($languages as $lang) {
			if ($lang['slug'] == $default_lang_slug) {
				$default_lang = $lang;
				break;
			}
		}

		if (!$default_lang) {
			WP_CLI::error('No default lang found');
		}

		$locales = array_column($languages, 'locale'); // the illegal works it cannot contain (e.g. any existing da_DK)
		$not_like = '';

		foreach ($locales as $locale) {
			$not_like .= ' AND option_name NOT LIKE "%options_' . $locale . '_%"';
		}
	
		$query = "
			SELECT
				*
			FROM
				" . $wpdb->prefix . "options
			WHERE
				(option_name LIKE '_options_%' OR option_name LIKE 'options_%')" . $not_like . "
		";

		$acf_options = $wpdb->get_results($query);

		if(!$acf_options) {
			WP_CLI::error('Could not find any ACF options');
		}

		$new_options = [];
		foreach ($acf_options as $acf_option) {
			$option_name = $acf_option->option_name;
			$lang = false;

			foreach ($languages as $language) {
				if ($language['slug'] !== $default_lang_slug && strpos($option_name, '_' . $language['slug'] . '_')) {
					// contains e.g. _da_
					$lang = $language;
					break;
				}
			}

			if ($lang) {
				$option_name = str_replace('options_' . $lang['slug'], 'options_' . $lang['locale'], $option_name);
			} else {
				// no language slug was found, must be default language that does not contain slug
				$option_name = str_replace('options_', 'options_' . $default_lang['locale'] . '_', $option_name);
			}
			
			$value = get_option($acf_option->option_name);

			$new_options[$option_name] = [
				'old_name' => $acf_option->option_name,
				'new_name' => $option_name,
				'status' => (!$value) ? 'Skip (no value)' : 'OK',
				'value' => $value
			];
		}

		if (!$verbose) {
			$progress = \WP_CLI\Utils\make_progress_bar( 'Creating new options keys compatible with Polylang ACF', count($new_options) );

			foreach ($new_options as $option) {
				$success = false;
				$action = 'insert';

				if(!get_option($option['new_name'], $option['value'])) {
					$success = add_option($option['new_name'], $option['value']);
				} else if ($option['value']) {
					$action = 'update';
					$success = update_option($option['new_name'], $option['value']);
				}

				if (!$success && $option['value']) {
					WP_CLI::log('Failed to ' . $action . ' ' . $option['new_name'] . ' representing old ' . $option['old_name']);
				}

				$progress->tick();
			}

			$progress->finish();
		} else {
			WP_CLI\Utils\format_items( 'table', $new_options, array( 'old_name', 'new_name', 'status' ) );
		}
	}

	if ( defined( 'WP_CLI' ) && WP_CLI ) {
		WP_CLI::add_command( 'sync-acf-options-to-polylang', 'sync_acf_options_to_polylang' );
	}

simplenotezy avatar Sep 29 '20 18:09 simplenotezy

Hello,

This is to pmigratie from wpml to polylang ? If so, I think this wp-cli command should be on a separate package too :)

Nicolas,

Rahe avatar Jan 26 '21 17:01 Rahe