first commit

This commit is contained in:
2023-09-12 21:41:04 +02:00
commit 3361a7f053
13284 changed files with 2116755 additions and 0 deletions

View File

@@ -0,0 +1,339 @@
<?php
/**
* WPML_Element_Translation Class
*
* @package wpml-core
* @abstract
*/
abstract class WPML_Element_Translation extends WPML_WPDB_User {
/** @var array[] $element_data */
protected $element_data = [];
/** @var array[] $translations */
protected $translations = [];
/** @var array[] $trid_groups */
protected $trid_groups = [];
/** @var array[] $trid_groups */
protected $translation_ids_element = [];
/** @var int $type_prefix_length */
private $type_prefix_length;
/**
* @param wpdb $wpdb
*/
public function __construct( &$wpdb ) {
parent::__construct( $wpdb );
$this->type_prefix_length = strlen( $this->get_type_prefix() );
}
abstract protected function get_element_join();
abstract protected function get_type_prefix();
/**
* Clears the cached translations.
*/
public function reload() {
$this->element_data = [];
$this->translations = [];
$this->trid_groups = [];
$this->translation_ids_element = [];
}
public function get_element_trid( $element_id ) {
return $this->maybe_populate_cache( $element_id )
? $this->element_data[ $element_id ]['trid'] : null;
}
/**
* @param int $element_id
* @param string $lang
* @param bool|false $original_fallback if true will return input $element_id if no translation is found
*
* @return null|int
*/
public function element_id_in( $element_id, $lang, $original_fallback = false ) {
$result = ( $original_fallback ? (int) $element_id : null );
if ( $this->maybe_populate_cache( $element_id ) && isset( $this->translations[ $element_id ][ $lang ] ) ) {
$result = (int) $this->translations[ $element_id ][ $lang ];
}
return $result;
}
/**
* @param int $element_id
* @param bool $root if true gets the root element of the trid which itself
* has no original. Otherwise returns the direct original of the given
* element_id.
*
* @return int|null null if the element has no original
*/
public function get_original_element( $element_id, $root = false ) {
$element_id = (int) $element_id;
$source_lang = $this->maybe_populate_cache( $element_id )
? $this->element_data[ $element_id ]['source_lang'] : null;
if ( null === $source_lang ) {
return null;
}
if ( ! $root && isset( $this->translations[ $element_id ][ $source_lang ] ) ) {
return (int) $this->translations[ $element_id ][ $source_lang ];
}
if ( $root ) {
foreach ( $this->translations[ $element_id ] as $trans_id ) {
if ( ! $this->element_data[ $trans_id ]['source_lang'] ) {
return (int) $trans_id;
}
}
}
return null;
}
public function get_element_id( $lang, $trid ) {
$this->maybe_populate_cache( false, $trid );
return isset( $this->trid_groups [ $trid ][ $lang ] ) ? $this->trid_groups [ $trid ][ $lang ] : null;
}
/**
* @param int $element_id
*
* @return null|string
*/
public function get_element_lang_code( $element_id ) {
$result = null;
if ( $this->maybe_populate_cache( $element_id ) ) {
$result = $this->element_data[ $element_id ]['lang'];
}
return $result;
}
/**
* @param int $element_id
* @param string $output
*
* @return array|null|stdClass
*/
public function get_element_language_details( $element_id, $output = OBJECT ) {
$result = null;
if ( $element_id && $this->maybe_populate_cache( $element_id ) ) {
$result = new stdClass();
$result->element_id = $element_id;
$result->trid = $this->element_data[ $element_id ]['trid'];
$result->language_code = $this->element_data[ $element_id ]['lang'];
$result->source_language_code = $this->element_data[ $element_id ]['source_lang'];
}
if ( $output == ARRAY_A ) {
return $result ? get_object_vars( $result ) : null;
} elseif ( $output == ARRAY_N ) {
return $result ? array_values( get_object_vars( $result ) ) : null;
} else {
return $result;
}
}
public function get_source_lang_code( $element_id ) {
return $this->maybe_populate_cache( $element_id )
? $this->element_data[ $element_id ]['source_lang'] : null;
}
public function get_type( $element_id ) {
return $this->maybe_populate_cache( $element_id ) ? $this->element_data[ $element_id ]['type'] : null;
}
public function get_source_lang_from_translation_id( $translation_id ) {
$lang = array(
'code' => null,
'found' => false,
);
$element_id = $this->get_element_from_translation_id( $translation_id );
if ( $element_id ) {
$lang['code'] = $this->get_source_lang_code( $element_id );
$lang['found'] = true;
}
return $lang;
}
public function get_translation_id( $element_id ) {
return $this->maybe_populate_cache( $element_id )
? $this->element_data[ $element_id ]['translation_id'] : null;
}
public function get_translations_ids() {
$translation_ids = array();
foreach ( $this->element_data as $data ) {
$translation_ids[] = $data['translation_id'];
}
return $translation_ids;
}
/**
* @param int $element_id
* @param int|false $trid
* @param bool $actual_translations_only
*
* @return array<int,int>
*/
public function get_element_translations( $element_id, $trid = false, $actual_translations_only = false ) {
$valid_element = $this->maybe_populate_cache( $element_id, $trid );
if ( $element_id ) {
$res = $valid_element
? ( $actual_translations_only
? $this->filter_for_actual_trans( $element_id ) : $this->translations[ $element_id ] ) : array();
} elseif ( $trid ) {
$res = isset( $this->trid_groups[ $trid ] ) ? $this->trid_groups[ $trid ] : array();
}
return isset( $res ) ? $res : array();
}
public function get_element_from_translation_id( $translation_id ) {
return isset( $this->translation_ids_element[ $translation_id ] ) ? $this->translation_ids_element[ $translation_id ] : null;
}
public function get_trid_from_translation_id( $translation_id ) {
$trid = null;
$element_id = $this->get_element_from_translation_id( $translation_id );
if ( $element_id ) {
$trid = $this->get_element_trid( $element_id );
}
return $trid;
}
public function get_trids() {
return array_keys( $this->trid_groups );
}
public function prefetch_ids( $element_ids ) {
$element_ids = (array) $element_ids;
$element_ids = array_diff( $element_ids, array_keys( $this->element_data ) );
if ( (bool) $element_ids === false ) {
return;
}
$trid_snippet = ' tridt.element_id IN (' . wpml_prepare_in( $element_ids, '%d' ) . ')';
$sql = $this->build_sql( $trid_snippet );
$elements = $this->wpdb->get_results( $sql, ARRAY_A );
$this->group_and_populate_cache( $elements );
}
/**
* @param string $trid_snippet
*
* @return string
*/
private function build_sql( $trid_snippet ) {
return 'SELECT wpml_translations.translation_id, wpml_translations.element_id, wpml_translations.language_code, wpml_translations.source_language_code, wpml_translations.trid, wpml_translations.element_type
' . $this->get_element_join() . "
JOIN {$this->wpdb->prefix}icl_translations tridt
ON tridt.element_type = wpml_translations.element_type
AND tridt.trid = wpml_translations.trid
WHERE {$trid_snippet}";
}
private function maybe_populate_cache( $element_id, $trid = false ) {
if ( ! $element_id && ! $trid ) {
return false;
}
if ( ! $element_id && isset( $this->trid_groups [ $trid ] ) ) {
return true;
}
if ( ! $element_id || ! isset( $this->translations[ $element_id ] ) ) {
if ( ! $element_id ) {
$trid_snippet = $this->wpdb->prepare( ' tridt.trid = %d ', $trid );
} else {
$trid_snippet = $this->wpdb->prepare(
' tridt.trid = (SELECT trid ' . $this->get_element_join() . ' WHERE element_id = %d LIMIT 1)',
$element_id
);
}
$sql = $this->build_sql( $trid_snippet );
$elements = $this->wpdb->get_results( $sql, ARRAY_A );
$this->populate_cache( $elements );
if ( $element_id && ! isset( $this->translations[ $element_id ] ) ) {
$this->translations[ $element_id ] = array();
}
}
return ! empty( $this->translations[ $element_id ] );
}
private function group_and_populate_cache( $elements ) {
$trids = array();
foreach ( $elements as $element ) {
$trid = $element['trid'];
if ( ! isset( $trids[ $trid ] ) ) {
$trids[ $trid ] = array();
}
$trids[ $trid ][] = $element;
}
foreach ( $trids as $trid_group ) {
$this->populate_cache( $trid_group );
}
}
private function populate_cache( $elements ) {
if ( ! $elements ) {
return;
}
$element_ids = array();
foreach ( $elements as $element ) {
$element_id = $element['element_id'];
$language_code = $element['language_code'];
$element_ids[ $language_code ] = $element_id;
$this->element_data[ $element_id ] = array(
'translation_id' => $element['translation_id'],
'trid' => $element['trid'],
'lang' => $language_code,
'source_lang' => $element['source_language_code'],
'type' => substr( $element['element_type'], $this->type_prefix_length ),
);
$this->translation_ids_element[ $element['translation_id'] ] = $element_id;
}
foreach ( $element_ids as $element_id ) {
$trid = $this->element_data[ $element_id ]['trid'];
$this->trid_groups[ $trid ] = $element_ids;
$this->translations[ $element_id ] = &$this->trid_groups[ $trid ];
}
}
private function filter_for_actual_trans( $element_id ) {
$res = $this->translations[ $element_id ];
foreach ( $res as $lang => $element ) {
if ( $this->element_data[ $element ]['source_lang'] !== $this->element_data[ $element_id ]['lang'] ) {
unset( $res[ $lang ] );
}
}
return $res;
}
/**
* @param int $post_id
*
* @return bool
*/
public function is_a_duplicate( $post_id ) {
return (bool) get_post_meta( $post_id, '_icl_lang_duplicate_of', true );
}
}

View File

@@ -0,0 +1,20 @@
<?php
/**
* Class WPML_WPDB_And_SP_User
*/
abstract class WPML_Full_PT_API extends WPML_WPDB_And_SP_User {
/** @var WPML_Post_Translation $post_translations */
protected $post_translations;
/**
* @param wpdb $wpdb
* @param SitePress $sitepress
* @param WPML_Post_Translation $post_translations
*/
public function __construct( &$wpdb, &$sitepress, &$post_translations ) {
parent::__construct( $wpdb, $sitepress );
$this->post_translations = &$post_translations;
}
}

View File

@@ -0,0 +1,18 @@
<?php
class WPML_Full_Translation_API extends WPML_Full_PT_API {
/** @var WPML_Term_Translation $term_translations */
protected $term_translations;
/**
* @param SitePress $sitepress
* @param wpdb $wpdb
* @param WPML_Post_Translation $post_translations
* @param WPML_Term_Translation $term_translations
*/
function __construct( &$sitepress, &$wpdb, &$post_translations, &$term_translations ) {
parent::__construct( $wpdb, $sitepress, $post_translations );
$this->term_translations = &$term_translations;
}
}

View File

@@ -0,0 +1,242 @@
<?php
abstract class WPML_Hierarchy_Sync extends WPML_WPDB_User {
const CACHE_GROUP = __CLASS__;
protected $original_elements_table_alias = 'org';
protected $translated_elements_table_alias = 'tra';
protected $original_elements_language_table_alias = 'iclo';
protected $translated_elements_language_table_alias = 'iclt';
protected $correct_parent_table_alias = 'corr';
protected $correct_parent_language_table_alias = 'iclc';
protected $original_parent_table_alias = 'parents';
protected $original_parent_language_table_alias = 'parent_lang';
protected $element_id_column;
protected $parent_element_id_column;
protected $parent_id_column;
protected $element_type_column;
protected $element_type_prefix;
protected $elements_table;
protected $lang_info_table;
/**
* @param wpdb $wpdb
*/
public function __construct( &$wpdb ) {
parent::__construct( $wpdb );
$this->lang_info_table = $wpdb->prefix . 'icl_translations';
add_action( 'clean_post_cache', [ $this, 'clean_cache' ] );
add_action( 'set_object_terms', [ $this, 'clean_cache' ] );
add_action( 'wpml_sync_term_hierarchy_done', [ $this, 'clean_cache' ] );
}
public function clean_cache() {
WPML_Non_Persistent_Cache::flush_group( self::CACHE_GROUP );
}
public function get_unsynced_elements( $element_types, $ref_lang_code = false ) {
$element_types = (array) $element_types;
$results = array();
if ( $element_types ) {
$key = md5( wp_json_encode( array( $element_types, $ref_lang_code ) ) );
$found = false;
$results = WPML_Non_Persistent_Cache::get( $key, self::CACHE_GROUP, $found );
if ( ! $found ) {
$results_sql_parts = array();
$results_sql_parts['source_element_table'] = $this->get_source_element_table();
$results_sql_parts['source_element_join'] = $this->get_source_element_join();
$results_sql_parts['join_translation_language_data'] = $this->get_join_translation_language_data( $ref_lang_code );
$results_sql_parts['translated_element_join'] = $this->get_translated_element_join();
$results_sql_parts['original_parent_join'] = $this->get_original_parent_join();
$results_sql_parts['original_parent_language_join'] = $this->get_original_parent_language_join();
$results_sql_parts['correct_parent_language_join'] = $this->get_correct_parent_language_join();
$results_sql_parts['correct_parent_element_join'] = $this->get_correct_parent_element_join();
$results_sql_parts['where_statement'] = $this->get_where_statement(
$element_types,
$ref_lang_code
);
$results_sql = $this->get_select_statement();
$results_sql .= ' FROM ';
$results_sql .= implode( ' ', $results_sql_parts );
$results = $this->wpdb->get_results( $results_sql );
WPML_Non_Persistent_Cache::set( $key, $results, self::CACHE_GROUP );
}
}
return $results;
}
/**
* @param string|array $element_types
* @param bool $ref_lang_code
*/
public function sync_element_hierarchy( $element_types, $ref_lang_code = false ) {
$hierarchical_element_types = wpml_collect( $element_types )->filter( [ $this, 'is_hierarchical' ] );
if ( $hierarchical_element_types->isEmpty() ) {
return;
}
$unsynced = $this->get_unsynced_elements( $hierarchical_element_types->toArray(), $ref_lang_code );
foreach ( $unsynced as $row ) {
$this->update_hierarchy_for_element( $row );
}
}
/**
* @param string $element_type
*
* @return mixed
*/
abstract public function is_hierarchical( $element_type );
private function update_hierarchy_for_element( $row ) {
$update = $this->validate_parent_synchronization( $row );
if ( $update ) {
$target_element_id = $row->translated_id;
$new_parent = (int) $row->correct_parent;
$this->wpdb->update( $this->elements_table, array( $this->parent_id_column => $new_parent ), array( $this->element_id_column => $target_element_id ) );
}
}
private function validate_parent_synchronization( $row ) {
$is_valid = false;
$is_for_posts = ( $this->elements_table === $this->wpdb->posts );
if ( ! $is_for_posts ) {
$is_valid = true;
}
if ( $row && $is_for_posts ) {
global $sitepress;
$target_element_id = $row->translated_id;
$target_post = get_post( $target_element_id );
if ( $target_post ) {
$parent_must_empty = false;
$post_type = $target_post->post_type;
$element_type = 'post_' . $post_type;
$target_element_language = $sitepress->get_element_language_details( $target_element_id, $element_type );
$original_element_id = $sitepress->get_original_element_id( $target_element_id, $element_type );
if ( $original_element_id ) {
$parent_has_translation_in_target_language = false;
$original_element = get_post( $original_element_id );
$original_post_parent_id = $original_element->post_parent;
if ( $original_post_parent_id ) {
$original_post_parent_trid = $sitepress->get_element_trid( $original_post_parent_id, $element_type );
$original_post_parent_translations = $sitepress->get_element_translations( $original_post_parent_trid, $element_type );
foreach ( $original_post_parent_translations as $original_post_parent_translation ) {
if ( $original_post_parent_translation->language_code == $target_element_language->language_code ) {
$parent_has_translation_in_target_language = true;
break;
}
}
} else {
$parent_must_empty = true;
}
/**
* Check if the parent of the original post has a translation in the language of the target post or if the parent must be set to 0
*/
$is_valid = $parent_has_translation_in_target_language || $parent_must_empty;
}
}
}
return $is_valid;
}
private function get_source_element_join() {
return "JOIN {$this->lang_info_table} {$this->original_elements_language_table_alias}
ON {$this->original_elements_table_alias}.{$this->element_id_column}
= {$this->original_elements_language_table_alias}.element_id
AND {$this->original_elements_language_table_alias}.element_type
= CONCAT('{$this->element_type_prefix}', {$this->original_elements_table_alias}.{$this->element_type_column})";
}
private function get_translated_element_join() {
return "JOIN {$this->elements_table} {$this->translated_elements_table_alias}
ON {$this->translated_elements_table_alias}.{$this->element_id_column}
= {$this->translated_elements_language_table_alias}.element_id ";
}
private function get_source_element_table() {
return " {$this->elements_table} {$this->original_elements_table_alias} ";
}
private function get_join_translation_language_data( $ref_language_code ) {
$res = " JOIN {$this->lang_info_table} {$this->translated_elements_language_table_alias}
ON {$this->translated_elements_language_table_alias}.trid
= {$this->original_elements_language_table_alias}.trid ";
if ( (bool) $ref_language_code === true ) {
$res .= "AND {$this->translated_elements_language_table_alias}.language_code
!= {$this->original_elements_language_table_alias}.language_code ";
} else {
$res .= " AND {$this->translated_elements_language_table_alias}.source_language_code
= {$this->original_elements_language_table_alias}.language_code ";
}
return $res;
}
private function get_select_statement() {
return " SELECT {$this->translated_elements_table_alias}.{$this->element_id_column} AS translated_id
, IFNULL({$this->correct_parent_table_alias}.{$this->parent_element_id_column}, 0) AS correct_parent ";
}
private function get_original_parent_join() {
return " LEFT JOIN {$this->elements_table} {$this->original_parent_table_alias}
ON {$this->original_parent_table_alias}.{$this->parent_element_id_column}
= {$this->original_elements_table_alias}.{$this->parent_id_column} ";
}
private function get_original_parent_language_join() {
return " LEFT JOIN {$this->lang_info_table} {$this->original_parent_language_table_alias}
ON {$this->original_parent_table_alias}.{$this->element_id_column}
= {$this->original_parent_language_table_alias}.element_id
AND {$this->original_parent_language_table_alias}.element_type
= CONCAT('{$this->element_type_prefix}', {$this->original_parent_table_alias}.{$this->element_type_column}) ";
}
private function get_correct_parent_language_join() {
return " LEFT JOIN {$this->lang_info_table} {$this->correct_parent_language_table_alias}
ON {$this->correct_parent_language_table_alias}.language_code
= {$this->translated_elements_language_table_alias}.language_code
AND {$this->original_parent_language_table_alias}.trid
= {$this->correct_parent_language_table_alias}.trid ";
}
private function get_correct_parent_element_join() {
return " LEFT JOIN {$this->elements_table} {$this->correct_parent_table_alias}
ON {$this->correct_parent_table_alias}.{$this->element_id_column}
= {$this->correct_parent_language_table_alias}.element_id ";
}
private function get_where_statement( $element_types, $ref_lang_code ) {
$filter_originals_snippet = $ref_lang_code
? $this->wpdb->prepare( " AND {$this->original_elements_language_table_alias}.language_code = %s ", $ref_lang_code )
: " AND {$this->translated_elements_language_table_alias}.source_language_code IS NOT NULL ";
return " WHERE {$this->original_elements_table_alias}.{$this->element_type_column}
IN (" . wpml_prepare_in( $element_types ) . ")
AND IFNULL({$this->correct_parent_table_alias}.{$this->parent_element_id_column}, 0)
!= {$this->translated_elements_table_alias}.{$this->parent_id_column} " . $filter_originals_snippet;
}
}

View File

@@ -0,0 +1,418 @@
<?php
class WPML_Set_Language extends WPML_Full_Translation_API {
/**
* @param int $el_id the element's ID (for terms we use the `term_taxonomy_id`)
* @param string $el_type
* @param int|bool|null $trid Trid the element is to be assigned to. Input that is == false will cause the term to
* be assigned a new trid and potential translation relations to/from it to disappear.
* @param string $language_code
* @param null|string $src_language_code
* @param bool $check_duplicates
*
* @return bool|int|null|string
*/
public function set(
$el_id,
$el_type,
$trid,
$language_code,
$src_language_code = null,
$check_duplicates = true
) {
if ( strlen( $el_type ) > 60 ) {
throw new InvalidArgumentException( 'The element type "' . $el_type . '" is too long' );
}
$this->clear_cache();
if ( $check_duplicates && $el_id && (bool) ( $el_type_db = $this->check_duplicate(
$el_type,
$el_id
) ) === true
) {
throw new InvalidArgumentException( 'element_id and type do not match for element_id:' . $el_id . ' the database contains ' . $el_type_db . ' while this function was called with ' . $el_type );
}
$context = explode( '_', $el_type );
$context = $context[0];
$src_language_code = $src_language_code === $language_code ? null : $src_language_code;
if ( $trid ) { // it's a translation of an existing element
/** @var int $trid is an integer if not falsy */
$this->maybe_delete_orphan( $trid, $language_code, $el_id );
if ( $el_id && (bool) ( $translation_id = $this->is_language_change( $el_id, $el_type, $trid ) ) === true
&& (bool) $this->trid_lang_trans_id( $trid, $language_code ) === false
) {
$this->wpdb->update(
$this->wpdb->prefix . 'icl_translations',
array( 'language_code' => $language_code ),
array( 'translation_id' => $translation_id )
);
do_action(
'wpml_translation_update',
array(
'type' => 'update',
'trid' => $trid,
'element_id' => $el_id,
'element_type' => $el_type,
'translation_id' => $translation_id,
'context' => $context,
)
);
} elseif ( $el_id && (bool) ( $translation_id = $this->existing_element( $el_id, $el_type ) ) === true ) {
$this->change_translation_of( $trid, $el_id, $el_type, $language_code, $src_language_code );
} elseif ( (bool) ( $translation_id = $this->is_placeholder_update( $trid, $language_code ) ) === true ) {
$this->wpdb->update(
$this->wpdb->prefix . 'icl_translations',
array( 'element_id' => $el_id ),
array( 'translation_id' => $translation_id )
);
do_action(
'wpml_translation_update',
array(
'type' => 'update',
'trid' => $trid,
'element_id' => $el_id,
'element_type' => $el_type,
'translation_id' => $translation_id,
'context' => $context,
)
);
} elseif ( (bool) ( $translation_id = $this->trid_lang_trans_id( $trid, $language_code ) ) === false ) {
$translation_id = $this->insert_new_row( $el_id, $trid, $el_type, $language_code, $src_language_code );
}
} else { // it's a new element or we are removing it from a trid
$this->delete_existing_row( $el_type, $el_id );
$translation_id = $this->insert_new_row( $el_id, false, $el_type, $language_code, $src_language_code );
}
$this->clear_cache();
if ( $translation_id && substr( $el_type, 0, 4 ) === 'tax_' ) {
$taxonomy = substr( $el_type, 4 );
do_action( 'created_term_translation', $taxonomy, $el_id, $language_code );
}
do_action( 'icl_set_element_language', $translation_id, $el_id, $language_code, $trid );
return $translation_id;
}
/**
* Returns the translation id belonging to a specific trid, language_code combination
*
* @param int $trid
* @param string $lang
*
* @return null|int
*/
private function trid_lang_trans_id( $trid, $lang ) {
return $this->wpdb->get_var(
$this->wpdb->prepare(
"SELECT translation_id
FROM {$this->wpdb->prefix}icl_translations
WHERE trid = %d
AND language_code = %s
LIMIT 1",
$trid,
$lang
)
);
}
/**
* Changes the source_language_code of an element
*
* @param int $trid
* @param int $el_id
* @param string $el_type
* @param string $language_code
* @param string $src_language_code
*/
private function change_translation_of( $trid, $el_id, $el_type, $language_code, $src_language_code ) {
$src_language_code = empty( $src_language_code )
? $this->sitepress->get_source_language_by_trid( $trid ) : $src_language_code;
if ( $src_language_code !== $language_code ) {
$this->wpdb->update(
$this->wpdb->prefix . 'icl_translations',
array(
'trid' => $trid,
'language_code' => $language_code,
'source_language_code' => $src_language_code,
),
array(
'element_type' => $el_type,
'element_id' => $el_id,
)
);
$context = explode( '_', $el_type );
do_action(
'wpml_translation_update',
array(
'type' => 'update',
'trid' => $trid,
'element_id' => $el_id,
'element_type' => $el_type,
'context' => $context[0],
)
);
}
}
/**
* @param string $el_type
* @param int $el_id
*/
private function delete_existing_row( $el_type, $el_id ) {
$context = explode( '_', $el_type );
$update_args = array(
'element_id' => $el_id,
'element_type' => $el_type,
'context' => $context[0],
);
do_action( 'wpml_translation_update', array_merge( $update_args, array( 'type' => 'before_delete' ) ) );
$this->wpdb->query(
$this->wpdb->prepare(
"DELETE FROM {$this->wpdb->prefix}icl_translations
WHERE element_type = %s
AND element_id = %d",
$el_type,
$el_id
)
);
do_action( 'wpml_translation_update', array_merge( $update_args, array( 'type' => 'after_delete' ) ) );
}
/**
* Inserts a new row into icl_translations
*
* @param int $el_id
* @param int $trid
* @param string $el_type
* @param string $language_code
* @param string $src_language_code
*
* @return int Translation ID of the new row
*/
private function insert_new_row( $el_id, $trid, $el_type, $language_code, $src_language_code ) {
$new = array(
'element_type' => $el_type,
'language_code' => $language_code,
);
if ( $trid === false ) {
$trid = 1 + (int) $this->wpdb->get_var( "SELECT MAX(trid) FROM {$this->wpdb->prefix}icl_translations" );
} else {
$src_language_code = empty( $src_language_code )
? $this->sitepress->get_source_language_by_trid( $trid ) : $src_language_code;
$new['source_language_code'] = $src_language_code;
}
$new['trid'] = $trid;
if ( $el_id ) {
$new['element_id'] = $el_id;
}
$this->wpdb->insert( $this->wpdb->prefix . 'icl_translations', $new );
$translation_id = $this->wpdb->insert_id;
$context = explode( '_', $el_type );
do_action(
'wpml_translation_update',
array(
'type' => 'insert',
'trid' => $trid,
'element_id' => $el_id,
'element_type' => $el_type,
'translation_id' => $translation_id,
'context' => $context[0],
)
);
return $translation_id;
}
/**
* Checks if a row exists for a concrete id, type and trid combination
* in icl_translations.
*
* @param int $el_id
* @param string $el_type
* @param int $trid
*
* @return null|int
*/
private function is_language_change( $el_id, $el_type, $trid ) {
return $this->wpdb->get_var(
$this->wpdb->prepare(
"SELECT translation_id
FROM {$this->wpdb->prefix}icl_translations
WHERE element_type = %s
AND element_id = %d
AND trid = %d",
$el_type,
$el_id,
$trid
)
);
}
/**
* Checks if a given trid, language_code combination contains a placeholder with NULL element_id
* and if so returns the translation id of this row.
*
* @param int $trid
* @param string $language_code
*
* @return null|string translation id
*/
private function is_placeholder_update( $trid, $language_code ) {
return $this->wpdb->get_var(
$this->wpdb->prepare(
" SELECT translation_id
FROM {$this->wpdb->prefix}icl_translations
WHERE trid=%d
AND language_code = %s
AND element_id IS NULL",
$trid,
$language_code
)
);
}
/**
* Checks if a row in icl_translations exists for a concrete element type and id combination
*
* @param int $el_id
* @param string $el_type
*
* @return null|int
*/
private function existing_element( $el_id, $el_type ) {
return $this->wpdb->get_var(
$this->wpdb->prepare(
"SELECT translation_id
FROM {$this->wpdb->prefix}icl_translations
WHERE element_type= %s
AND element_id= %d
LIMIT 1",
$el_type,
$el_id
)
);
}
/**
* Checks if a trid contains an existing translation other than a specific element id and deletes that row if it
* exists.
*
* @param int $trid
* @param string $language_code
* @param int $correct_element_id
*/
private function maybe_delete_orphan( $trid, $language_code, $correct_element_id ) {
/** @var \stdClass $result */
$result = $this->wpdb->get_row(
$this->wpdb->prepare(
"SELECT translation_id, element_type, element_id
FROM {$this->wpdb->prefix}icl_translations
WHERE trid = %d
AND language_code = %s
AND element_id <> %d
AND source_language_code IS NOT NULL
",
$trid,
$language_code,
$correct_element_id
)
);
$translation_id = ( null != $result ? $result->translation_id : null );
if ( $translation_id ) {
$context = explode( '_', $result->element_type );
$update_args = array(
'trid' => $trid,
'element_id' => $result->element_id,
'element_type' => $result->element_type,
'translation_id' => $translation_id,
'context' => $context[0],
);
do_action( 'wpml_translation_update', array_merge( $update_args, array( 'type' => 'before_delete' ) ) );
$this->wpdb->query(
$this->wpdb->prepare(
"DELETE FROM {$this->wpdb->prefix}icl_translations WHERE translation_id=%d",
$translation_id
)
);
do_action( 'wpml_translation_update', array_merge( $update_args, array( 'type' => 'after_delete' ) ) );
}
}
/**
* Checks if a duplicate element_id already exists with a different than the input type.
* This only applies to posts and taxonomy terms.
*
* @param string $el_type
* @param int $el_id
*
* @return null|string null if no duplicate icl translations entry is found
* having a different than the input element type, the element type if a
* duplicate row is found.
*/
private function check_duplicate( $el_type, $el_id ) {
$res = false;
$exp = explode( '_', $el_type );
$_type = $exp[0];
if ( in_array( $_type, array( 'post', 'tax' ) ) ) {
$res = $this->duplicate_from_db( $el_id, $el_type, $_type );
if ( $res ) {
$fix_assignments = new WPML_Fix_Type_Assignments( $this->sitepress );
$fix_assignments->run();
$res = $this->duplicate_from_db( $el_id, $el_type, $_type );
}
}
return $res;
}
private function duplicate_from_db( $el_id, $el_type, $_type ) {
return $this->wpdb->get_var(
$this->wpdb->prepare(
"SELECT element_type
FROM {$this->wpdb->prefix}icl_translations
WHERE element_id = %d
AND element_type <> %s
AND element_type LIKE %s",
$el_id,
$el_type,
$_type . '%'
)
);
}
private function clear_cache() {
$this->term_translations->reload();
$this->post_translations->reload();
$this->sitepress->get_translations_cache()->clear();
}
}

View File

@@ -0,0 +1,16 @@
<?php
abstract class WPML_SP_And_PT_User extends WPML_SP_User {
/** @var WPML_Post_Translation $post_translation */
protected $post_translation;
/**
* @param WPML_Post_Translation $post_translation
* @param SitePress $sitepress
*/
public function __construct( &$post_translation, &$sitepress ) {
parent::__construct( $sitepress );
$this->post_translation = &$post_translation;
}
}

View File

@@ -0,0 +1,21 @@
<?php
/**
* Class WPML_SP_User
*
* Superclass for all WPML classes using the @global SitePress $sitepress directly
*
* @since 3.2.3
*/
abstract class WPML_SP_User {
/** @var SitePress $sitepress */
protected $sitepress;
/**
* @param SitePress $sitepress
*/
public function __construct( &$sitepress ) {
$this->sitepress = &$sitepress;
}
}

View File

@@ -0,0 +1,16 @@
<?php
class WPML_TM_User {
/** @var TranslationManagement $tm_instance */
protected $tm_instance;
/**
* WPML_Custom_Field_Setting_Factory constructor.
*
* @param TranslationManagement $tm_instance
*/
public function __construct( TranslationManagement $tm_instance ) {
$this->tm_instance = $tm_instance;
}
}

View File

@@ -0,0 +1,20 @@
<?php
/**
* Class WPML_URL_Converter_User
*
* @since 3.2.3
*/
abstract class WPML_URL_Converter_User {
/** @var WPML_URL_Converter */
protected $url_converter;
/**
* @param \WPML_URL_Converter $url_converter
*/
public function __construct( &$url_converter ) {
$this->url_converter = &$url_converter;
}
}

View File

@@ -0,0 +1,19 @@
<?php
/**
* Class WPML_WPDB_And_SP_User
*/
abstract class WPML_WPDB_And_SP_User extends WPML_WPDB_User {
/** @var SitePress $sitepress */
protected $sitepress;
/**
* @param wpdb $wpdb
* @param SitePress $sitepress
*/
public function __construct( &$wpdb, &$sitepress ) {
parent::__construct( $wpdb );
$this->sitepress = &$sitepress;
}
}

View File

@@ -0,0 +1,25 @@
<?php
/**
* Class WPML_WPDB_User
*
* Superclass for all WPML classes using the @global wpdb $wpdb
*
* @since 3.2.3
*/
abstract class WPML_WPDB_User {
/** @var wpdb $wpdb */
public $wpdb;
/**
* @param wpdb $wpdb
*/
public function __construct( &$wpdb ) {
$this->wpdb = &$wpdb;
}
public function get_wpdb() {
return $this->wpdb;
}
}