Files
doitinpoland.com/wp-content/plugins/sitepress-multilingual-cms/classes/core-abstract-classes/class-wpml-element-translation.php
2023-09-12 21:41:04 +02:00

340 lines
9.8 KiB
PHP

<?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 );
}
}