acf-options-for-polylang
acf-options-for-polylang copied to clipboard
Should be able to migrate data
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.
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' );
}
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,