Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Import QTS slugs options and meta data into QTX #1171

Merged
merged 32 commits into from
May 29, 2022
Merged
Show file tree
Hide file tree
Changes from 31 commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
31b6554
Import slugs meta in QTX
herrvigg May 21, 2022
d9d8dbd
Add dry-run mode, update new prefix
herrvigg May 21, 2022
7bfaf27
Rename QTS_META_PREFIX to QTX_SLUG_META_PREFIX
herrvigg May 21, 2022
379227d
Import QTS options
herrvigg May 22, 2022
06e747c
Remove QTS prefix and HTML ID for options
herrvigg May 22, 2022
c00df4e
Move import functions to separate file
herrvigg May 22, 2022
4fb5af5
Update admin notice
herrvigg May 22, 2022
a3f29bc
Rename QTX_SLUG_OLD_OPTIONS_NAME
herrvigg May 22, 2022
ee585ac
Rename import functions with `qtranxf_slugs` prefix
herrvigg May 22, 2022
d7d31ff
Cleanup, doc and rename
herrvigg May 22, 2022
3f1b669
Add check on slugs module state, minor fixes
herrvigg May 23, 2022
e913983
add termmeta data removal on qtx uninstall
spleen1981 May 24, 2022
5ed9b2e
add conditions to display/enable slugs import checkboxes
spleen1981 May 25, 2022
9253300
Import new QTS slugs only
herrvigg May 27, 2022
65be394
Add delete option
herrvigg May 27, 2022
8674988
Import options with conservative merge, retrofix keys
herrvigg May 28, 2022
47c64bd
Merge branch 'master' into slugs-import
herrvigg May 28, 2022
246c6c7
Fix residual QTS_META_PREFIX
herrvigg May 28, 2022
4b12303
Merge branch 'master' into slugs-import
herrvigg May 28, 2022
548c016
Merge branch 'master' into slugs-import
herrvigg May 28, 2022
cd7b0db
Rename QTS import file
herrvigg May 28, 2022
9208b41
Refactor import to migration QTS
herrvigg May 28, 2022
1cae835
Add temporary hack to restore QTS options for master dev
herrvigg May 28, 2022
76fe72b
Rename slugs import to migrate, complete descriptions
herrvigg May 28, 2022
7fffe69
Early exit if no QTS options to migrate
herrvigg May 28, 2022
bcf02d4
Pre-check QTS for conditional delete and migrate by table
herrvigg May 29, 2022
1700f0d
Fix sprintf message formatting
herrvigg May 29, 2022
7f44a11
Remove internal QTS filter hooks (#1176)
herrvigg May 29, 2022
63b2ea2
Merge branch 'master' into slugs-import
herrvigg May 29, 2022
c65ac51
Dry-run mode without SQL transaction
herrvigg May 29, 2022
007d683
Update labels for QTS migration
herrvigg May 29, 2022
98cab95
Merge branch 'master' into slugs-import
herrvigg May 29, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 32 additions & 1 deletion admin/qtx_activation_hook.php
Original file line number Diff line number Diff line change
Expand Up @@ -787,7 +787,6 @@ function qtranxf_activation_hook() {
// Migrate (rename/import) legacy options, temporary transitions during evolutions.
qtranxf_rename_legacy_option( 'qtranslate_modules', QTX_OPTIONS_MODULES_STATE );
qtranxf_import_legacy_option( 'acf_qtranslate', QTX_OPTIONS_MODULE_ACF, false );
qtranxf_import_legacy_option( 'qts_options', QTX_OPTIONS_MODULE_SLUGS, false );

$ts = time();
$next_thanks = get_option( 'qtranslate_next_thanks' );
Expand Down Expand Up @@ -932,6 +931,30 @@ function qtranxf_admin_notices_gutenberg() {

add_action( 'admin_notices', 'qtranxf_admin_notices_gutenberg' );

function qtranxf_admin_notices_slugs_migrate() {
if ( qtranxf_check_admin_notice( 'slugs-migrate' ) || ! QTX_Module_Loader::is_module_active( 'slugs' ) ) {
return;
}
$old_value = get_option( 'qts_options' ); // Very quick check to avoid loading more code.
if ( ! $old_value ) {
return;
}
require_once( QTRANSLATE_DIR . '/modules/slugs/admin/slugs-migrate-qts.php' );
$msg = qtranxf_slugs_check_migrate_qts(); // More advanced checks with QTS meta.
if ( empty( $msg ) ) {
return;
}
qtranxf_admin_notice_dismiss_script();
echo '<div class="notice notice-warning qtranxs-notice-ajax is-dismissible" id="qtranxs-slugs-migrate"><p>';
$options_link = admin_url( 'options-general.php?page=qtranslate-xt#import' );
echo '<p>' . sprintf( __( '%s : found slugs meta that can be migrated. Go to the <a href="%s">import settings</a> to migrate.', 'qtranslate' ), qtranxf_get_plugin_link(), $options_link ) . '</p>';
echo '<p>' . $msg . '</p>';
echo '</p><p><a class="button qtranxs-notice-dismiss" href="javascript:void(0);">' . __( 'I have already done it, dismiss this message.', 'qtranslate' );
echo '</a></p></div>';
}

add_action( 'admin_notices', 'qtranxf_admin_notices_slugs_migrate' );

function qtranxf_admin_notice_deactivate_plugin( $name, $plugin ) {
deactivate_plugins( $plugin, true );
$d = dirname( $plugin );
Expand Down Expand Up @@ -1028,6 +1051,14 @@ function qtranxf_update_option_admin_notices( $messages, $id, $set = true ) {
return $messages;
}

/**
* Update an admin notice to be set (hidden) / unset (shown).
*
* @param string $id
* @param bool $set true to set the message as seen (hide), false to unset (show)
*
* @return array|mixed
*/
function qtranxf_update_admin_notice( $id, $set ) {
$messages = get_option( 'qtranslate_admin_notices', array() );

Expand Down
14 changes: 14 additions & 0 deletions admin/qtx_admin_options_update.php
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,14 @@ function qtranxf_edit_config() {
if ( isset( $_POST['qtranslate_reset'] ) && isset( $_POST['qtranslate_reset2'] ) ) {
$messages[] = __( 'qTranslate has been reset.', 'qtranslate' );
} elseif ( isset( $_POST['default_language'] ) ) {
// TODO: remove temporary hack - restore QTS options for master dev before migration.
// Undo import legacy options in master before new options are saved with new keys...
$qts_options = get_option( 'qts_options' );
$new_options = get_option( QTX_OPTIONS_MODULE_SLUGS );
// Re-create original QTS options that can be properly imported again.
if ( ! $qts_options && $new_options && count( $new_options ) > 0 && strpos( array_keys( $new_options )[0], '_qts_' ) === 0 ) {
update_option( 'qts_options', $new_options, false );
}

qtranxf_update_settings();

Expand Down Expand Up @@ -971,6 +979,12 @@ function qtranxf_executeOnUpdate() {
$messages[] = $msg;
}
}

if ( isset( $_POST['qtranslate_import_slugs_migrate'] ) && $_POST['qtranslate_import_slugs_migrate'] ) {
require_once( QTRANSLATE_DIR . '/modules/slugs/admin/slugs-migrate-qts.php' );
$db_commit = isset( $_POST['qtranslate_import_slugs_confirm'] ) && $_POST['qtranslate_import_slugs_confirm'];
$messages[] = qtranxf_slugs_migrate_qts_data( $db_commit );
}
}

function qtranxf_mark_default( $text ) {
Expand Down
21 changes: 21 additions & 0 deletions admin/qtx_import_export.php
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,27 @@ function qtranxf_admin_section_import_export( $request_uri ) {
'text' => sprintf( __( 'Use plugin %s to import data.', 'qtranslate' ), '<a href="https://wordpress.org/plugins/w2q-wpml-to-qtranslate/" target="_blank">W2Q: WPML to qTranslate</a>' )
) ) ?>
<?php do_action( 'qtranslate_add_row_migrate' ) ?>
<?php if ( QTX_Module_Loader::is_module_active( 'slugs' ) ): ?>
<tr id="qtranslate-import-slugs">
<th scope="row"><?php _e( 'Migrate QTS slugs', 'qtranslate' ) ?></th>
<td>
<label for="qtranslate_import_slugs_migrate">
<input type="checkbox" name="qtranslate_import_slugs_migrate"
id="qtranslate_import_slugs_migrate"
value="1"
onclick="let c=jQuery('#qtranslate_import_slugs_confirm'); c.prop('disabled', !jQuery(this).prop('checked')); c.prop('checked', false);"/>
<?php _e( 'Migrate slugs options, post and term meta from legacy QTS plugin to qTranslate.', 'qtranslate' ); ?>
</label>
<br/>
<label for="qtranslate_import_slugs_confirm">
<input type="checkbox"
name="qtranslate_import_slugs_confirm"
id="qtranslate_import_slugs_confirm"
value="1" <?php disabled( true ) ?> /> <?php _e( "Confirm migration of QTS slugs in database. Attention! Existing slugs are replaced. Leave unchecked for a dry-run.", 'qtranslate' ) ?>
</label>
</td>
</tr>
<?php endif ?>
<tr>
<th scope="row"><?php _e( 'Reset qTranslate', 'qtranslate' ) ?></th>
<td>
Expand Down
107 changes: 52 additions & 55 deletions modules/slugs/admin/slugs-admin.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,6 @@
include_once( dirname( __FILE__ ) . '/slugs-settings.php' );

// add filters
add_filter( 'qts_validate_post_slug', 'qts_validate_post_slug', 0, 3 );
add_filter( 'qts_validate_post_slug', 'qts_unique_post_slug', 1, 3 );
add_filter( 'qts_validate_term_slug', 'qts_validate_term_slug', 0, 3 );
add_filter( 'qts_validate_term_slug', 'qts_unique_term_slug', 1, 3 );
add_filter( 'wp_get_object_terms', 'qts_get_object_terms', 0, 4 );
add_filter( 'get_terms', 'qts_get_terms', 0, 3 );
// admin actions
Expand Down Expand Up @@ -77,10 +73,11 @@ function qts_uninstall() {

$meta_keys = array();
foreach ( $q_config['enabled_languages'] as $lang ) {
$meta_keys[] = QTS_META_PREFIX . $lang;
$meta_keys[] = QTX_SLUGS_META_PREFIX . $lang;
}
$meta_keys = "'" . implode( "','", $meta_keys ) . "'";
$wpdb->query( "DELETE from $wpdb->postmeta WHERE meta_key IN ($meta_keys)" );
$wpdb->query( "DELETE from $wpdb->termmeta WHERE meta_key IN ($meta_keys)" );

qts_deactivate();

Expand Down Expand Up @@ -130,7 +127,7 @@ function qts_draw_meta_box( $post ) {
echo '<input type="hidden" name="qts_nonce" id="qts_nonce" value="' . wp_create_nonce( 'qts_nonce' ) . '" />' . PHP_EOL;
$flag_location = qtranxf_flag_location();
foreach ( $q_config['enabled_languages'] as $lang ):
$slug = get_post_meta( $post->ID, QTS_META_PREFIX . $lang, true );
$slug = get_post_meta( $post->ID, QTX_SLUGS_META_PREFIX . $lang, true );
$value = ( $slug ) ? htmlspecialchars( $slug, ENT_QUOTES ) : '';
$name = $q_config['language_name'][ $lang ];
$title = sprintf( __( 'Slug' ) . ' (%s)', $name );
Expand All @@ -143,27 +140,25 @@ function qts_draw_meta_box( $post ) {
}

/**
* Sanitize title as slug, if empty slug.
* Sanitize a post slug for a given language.
*
* @param $post (object) the post object
* @param $slug (string) the slug name
* @param $lang (string) the language
* @param string $slug slug name
* @param WP_Post $post the post object
* @param string $lang the language
*
* @return string the slug validated
* @return string sanitized slug
*/
function qts_validate_post_slug( $slug, $post, $lang ) {
function qts_sanitize_post_slug( $slug, $post, $lang ) {
$post_title = trim( qtranxf_use( $lang, $post->post_title ) );
$post_name = get_post_meta( $post->ID, QTS_META_PREFIX . $lang, true );
$post_name = get_post_meta( $post->ID, QTX_SLUGS_META_PREFIX . $lang, true );
if ( ! $post_name ) {
$post_name = $post->post_name;
}

//TODO: if has a slug, test and use it
//TODO: and then replace the default slug with the dafault language slug
//TODO: and then replace the default slug with the default language slug
$name = ( $post_title === '' ) ? $post_name : $post_title;

$slug = trim( $slug );

$slug = ( $slug === '' ) ? sanitize_title( $name ) : sanitize_title( $slug );

return htmlspecialchars( $slug, ENT_QUOTES );
Expand All @@ -172,9 +167,9 @@ function qts_validate_post_slug( $slug, $post, $lang ) {
/**
* Validates post slug against repetitions per language
*
* @param $post (object) the post object
* @param $slug (string) the slug name
* @param $lang (string) the language
* @param string $slug the slug name
* @param WP_Post $post the post object
* @param string $lang the language
*
* @return string the slug validated
*/
Expand Down Expand Up @@ -235,15 +230,15 @@ function qts_wp_unique_post_slug( $slug, $post_ID, $post_status, $post_type, $po
// TODO: update unique_slug :: missing hieararchical from current wp func ( 4.3.1 )
// Post slugs must be unique across all posts.
$check_sql = "SELECT $wpdb->postmeta.meta_value FROM $wpdb->posts,$wpdb->postmeta WHERE $wpdb->posts.ID = $wpdb->postmeta.post_id AND $wpdb->postmeta.meta_key = '%s' AND $wpdb->postmeta.meta_value = '%s' AND $wpdb->posts.post_type = %s AND $wpdb->posts.ID != %d LIMIT 1";
$post_name_check = $wpdb->get_var( $wpdb->prepare( $check_sql, QTS_META_PREFIX . $lang, $slug, $post_type, $post_ID ) );
$post_name_check = $wpdb->get_var( $wpdb->prepare( $check_sql, QTX_SLUGS_META_PREFIX . $lang, $slug, $post_type, $post_ID ) );

// TODO: update unique_slug :: missing check for conflict with dates archive from current wp func ( 4.3.1 )
if ( $post_name_check || in_array( $slug, $feeds ) || apply_filters( 'wp_unique_post_slug_is_bad_flat_slug', false, $slug, $post_type ) ) {
$suffix = 2;
do {
// TODO: update unique_slug :: same as above: differs from current wp func ( 4.3.1 )
$alt_post_name = substr( $slug, 0, 200 - ( strlen( $suffix ) + 1 ) ) . "-$suffix";
$post_name_check = $wpdb->get_var( $wpdb->prepare( $check_sql, QTS_META_PREFIX . $lang, $alt_post_name, $post_type, $post_ID ) );
$post_name_check = $wpdb->get_var( $wpdb->prepare( $check_sql, QTX_SLUGS_META_PREFIX . $lang, $alt_post_name, $post_type, $post_ID ) );
$suffix++;
} while ( $post_name_check );
$slug = $alt_post_name;
Expand All @@ -257,8 +252,8 @@ function qts_wp_unique_post_slug( $slug, $post_ID, $post_status, $post_type, $po
/**
* Saves the translated slug when the page is saved.
*
* @param $post_id int the post id
* @param $post object the post object
* @param int $post_id the post id
* @param WP_Post $post the post object
*
* @return void
*/
Expand All @@ -269,33 +264,35 @@ function qts_save_postdata( $post_id, $post = null ) {
}
$post_type_object = get_post_type_object( $post->post_type );

if ( ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) // check autosave
|| ( ! isset( $_POST['post_ID'] ) || $post_id != $_POST['post_ID'] ) // check revision
|| ( isset( $_POST['qts_nonce'] ) && ! wp_verify_nonce( $_POST['qts_nonce'], 'qts_nonce' ) ) // verify nonce
|| ( ! current_user_can( $post_type_object->cap->edit_post, $post_id ) ) ) { // check permission
if ( ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE )
|| ( ! isset( $_POST['post_ID'] ) || $post_id != $_POST['post_ID'] )
|| ( isset( $_POST['qts_nonce'] ) && ! wp_verify_nonce( $_POST['qts_nonce'], 'qts_nonce' ) )
|| ( ! current_user_can( $post_type_object->cap->edit_post, $post_id ) ) ) {
return;
}
foreach ( $q_config['enabled_languages'] as $lang ) {

// check required because it is not available inside quick edit
if ( isset( $_POST["qts_{$lang}_slug"] ) ) {
$meta_value = apply_filters( 'qts_validate_post_slug', $_POST["qts_{$lang}_slug"], $post, $lang );
delete_post_meta( $post_id, QTS_META_PREFIX . $lang );
update_post_meta( $post_id, QTS_META_PREFIX . $lang, $meta_value );
$slug = $_POST["qts_{$lang}_slug"];
$slug = qts_sanitize_post_slug( $slug, $post, $lang );
$slug = qts_unique_post_slug( $slug, $post, $lang );

delete_post_meta( $post_id, QTX_SLUGS_META_PREFIX . $lang );
update_post_meta( $post_id, QTX_SLUGS_META_PREFIX . $lang, $slug );
}
}
}

/**
* Sanitize title as slug, if empty slug.
* Sanitize a term slug.
*
* @param $term (object) the term object
* @param $slug (string) the slug name
* @param $lang (string) the language
* @param string $slug the slug name
* @param WP_Term $term the term object
* @param string $lang the language
*
* @return string the slug validated
* @return string sanitized slug
*/
function qts_validate_term_slug( $slug, $term, $lang ) {
function qts_sanitize_term_slug( $slug, $term, $lang ) {
global $q_config;

$term_name = trim( qtranxf_use( $lang, $term->name, false, true ) );
Expand All @@ -309,28 +306,28 @@ function qts_validate_term_slug( $slug, $term, $lang ) {
}

/**
* Will make slug unique per language, if it isn't already.
* Make a term slug unique for a given language.
*
* @param string $slug The string that will be tried for a unique slug
* @param object $term The term object that the $slug will belong too
* @param object $lang The language reference
* @param string $slug term slug to be made unique
* @param WP_Term $term the term object the slug belongs to
* @param object $lang language
*
* @return string Will return a true unique slug.
* @return string unique slug
*
* @since 1.0
*/
function qts_unique_term_slug( $slug, $term, $lang ) {
global $wpdb;

$query = $wpdb->prepare( "SELECT term_id FROM $wpdb->termmeta WHERE meta_key = '%s' AND meta_value = '%s' AND term_id != %d ", QTS_META_PREFIX . $lang, $slug, $term->term_id );
$query = $wpdb->prepare( "SELECT term_id FROM $wpdb->termmeta WHERE meta_key = '%s' AND meta_value = '%s' AND term_id != %d ", QTX_SLUGS_META_PREFIX . $lang, $slug, $term->term_id );
$exists_slug = $wpdb->get_results( $query );

if ( empty( $exists_slug ) ) {
return $slug;
}

// If we didn't get a unique slug, try appending a number to make it unique.
$query = $wpdb->prepare( "SELECT meta_value FROM $wpdb->termmeta WHERE meta_key = '%s' AND meta_value = '%s' AND term_id != %d", QTS_META_PREFIX . $lang, $slug, $term->term_id );
$query = $wpdb->prepare( "SELECT meta_value FROM $wpdb->termmeta WHERE meta_key = '%s' AND meta_value = '%s' AND term_id != %d", QTX_SLUGS_META_PREFIX . $lang, $slug, $term->term_id );

if ( $wpdb->get_var( $query ) ) {
$num = 2;
Expand All @@ -340,7 +337,7 @@ function qts_unique_term_slug( $slug, $term, $lang ) {
$slug_check = $wpdb->get_var(
$wpdb->prepare(
"SELECT meta_value FROM $wpdb->termmeta WHERE meta_key = '%s' AND meta_value = '%s'",
QTS_META_PREFIX . $lang,
QTX_SLUGS_META_PREFIX . $lang,
$alt_slug ) );
} while ( $slug_check );
$slug = $alt_slug;
Expand All @@ -361,22 +358,22 @@ function qts_unique_term_slug( $slug, $term, $lang ) {
function qts_save_term( $term_id, $tt_id, $taxonomy ) {
global $q_config;
$cur_screen = get_current_screen();
if ( ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) // check autosave
|| ( ! current_user_can( 'edit_posts' ) ) // check permission
if ( ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE )
|| ( ! current_user_can( 'edit_posts' ) )
|| ( isset( $cur_screen ) && $cur_screen->id === "nav-menus" ) //TODO: check if this condition is really needed
) {
return;
}

$term = get_term( $term_id, $taxonomy );
foreach ( $q_config['enabled_languages'] as $lang ) {
//condition is needed in case term is added through ajax e.g. in post edit page
$term_slug = isset( $_POST["qts_{$lang}_slug"] ) ? $_POST["qts_{$lang}_slug"] : '';

$meta_value = apply_filters( 'qts_validate_term_slug', $term_slug, $term, $lang );
// condition is needed in case term is added through ajax e.g. in post edit page
$slug = isset( $_POST["qts_{$lang}_slug"] ) ? $_POST["qts_{$lang}_slug"] : '';
$slug = qts_sanitize_term_slug( $slug, $term, $lang );
$slug = qts_unique_term_slug( $slug, $term, $lang );

delete_metadata( 'term', $term_id, QTS_META_PREFIX . $lang );
update_metadata( 'term', $term_id, QTS_META_PREFIX . $lang, $meta_value );
delete_metadata( 'term', $term_id, QTX_SLUGS_META_PREFIX . $lang );
update_metadata( 'term', $term_id, QTX_SLUGS_META_PREFIX . $lang, $slug );
}
}

Expand All @@ -393,7 +390,7 @@ function qts_show_list_term_fields( $term ) {
$flag_location = qtranxf_flag_location(); ?>
<ul class="qtranxs-slugs-list qtranxs-slugs-terms"><?php
foreach ( $q_config['enabled_languages'] as $lang ) {
$slug = is_object( $term ) ? get_metadata( 'term', $term->term_id, QTS_META_PREFIX . $lang, true ) : '';
$slug = is_object( $term ) ? get_metadata( 'term', $term->term_id, QTX_SLUGS_META_PREFIX . $lang, true ) : '';
$value = $slug ? htmlspecialchars( $slug, ENT_QUOTES ) : '';
$flag = $q_config['flag'][ $lang ];
$name = $q_config['language_name'][ $lang ];
Expand Down Expand Up @@ -536,7 +533,7 @@ function qts_taxonomy_custom_column( $str, $column_name, $term_id ) {
global $q_config;

if ( $column_name === 'qts-slug' ) {
echo get_metadata( 'term', $term_id, QTS_META_PREFIX . $q_config['language'], true );
echo get_metadata( 'term', $term_id, QTX_SLUGS_META_PREFIX . $q_config['language'], true );
}

return false;
Expand Down
Loading