first commit
This commit is contained in:
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
class WPML_Resolve_Object_Url_Helper_Factory {
|
||||
|
||||
const CURRENT_URL_RESOLVER = 'current';
|
||||
const ABSOLUTE_URL_RESOLVER = 'absolute';
|
||||
|
||||
/**
|
||||
* @return IWPML_Resolve_Object_Url
|
||||
*/
|
||||
public function create( $type = self::CURRENT_URL_RESOLVER ) {
|
||||
global $sitepress, $wp_query, $wpml_term_translations, $wpml_post_translations;
|
||||
|
||||
if ( self::CURRENT_URL_RESOLVER === $type ) {
|
||||
return new WPML_Resolve_Object_Url_Helper( $sitepress, $wp_query, $wpml_term_translations, $wpml_post_translations );
|
||||
}
|
||||
|
||||
if ( self::ABSOLUTE_URL_RESOLVER === $type ) {
|
||||
$absolute_links = new AbsoluteLinks();
|
||||
$absolute_to_permalinks = new WPML_Absolute_To_Permalinks( $sitepress );
|
||||
|
||||
$translate_links_target = new WPML_Translate_Link_Targets( $absolute_links, $absolute_to_permalinks );
|
||||
|
||||
$resolve_url = new WPML_Resolve_Absolute_Url( $sitepress, $translate_links_target );
|
||||
$url_persisted = WPML_Absolute_Url_Persisted::get_instance();
|
||||
|
||||
return new WPML_Resolve_Absolute_Url_Cached( $url_persisted, $resolve_url );
|
||||
}
|
||||
|
||||
throw new InvalidArgumentException( 'Unknown Resolve_Object_Url type: ' . $type );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,125 @@
|
||||
<?php
|
||||
|
||||
class WPML_Resolve_Object_Url_Helper implements IWPML_Resolve_Object_Url {
|
||||
const CACHE_GROUP = 'resolve_object_url';
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
protected $lock = false;
|
||||
|
||||
/**
|
||||
* @var SitePress
|
||||
*/
|
||||
private $sitepress;
|
||||
|
||||
/**
|
||||
* @var WP_Query
|
||||
*/
|
||||
private $wp_query;
|
||||
|
||||
/**
|
||||
* @var WPML_Term_Translation
|
||||
*/
|
||||
private $wpml_term_translations;
|
||||
|
||||
/**
|
||||
* @var WPML_Post_Translation
|
||||
*/
|
||||
private $wpml_post_translations;
|
||||
|
||||
/**
|
||||
* @param SitePress $sitepress
|
||||
* @param WP_Query $wp_query
|
||||
* @param WPML_Term_Translation $wpml_term_translations
|
||||
* @param WPML_Post_Translation $wpml_post_translations
|
||||
*/
|
||||
public function __construct(
|
||||
SitePress &$sitepress = null,
|
||||
WP_Query &$wp_query = null,
|
||||
WPML_Term_Translation $wpml_term_translations = null,
|
||||
WPML_Post_Translation $wpml_post_translations = null
|
||||
) {
|
||||
$this->sitepress = &$sitepress;
|
||||
$this->wp_query = &$wp_query;
|
||||
$this->wpml_term_translations = $wpml_term_translations;
|
||||
$this->wpml_post_translations = $wpml_post_translations;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Try to parse the URL to find a related post or term
|
||||
*
|
||||
* @param string $url
|
||||
* @param string $lang_code
|
||||
*
|
||||
* @return string|bool
|
||||
*/
|
||||
public function resolve_object_url( $url, $lang_code ) {
|
||||
if ( $this->lock ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->lock = true;
|
||||
$new_url = false;
|
||||
|
||||
$translations = $this->cached_retrieve_translations( $url );
|
||||
if ( $translations && isset( $translations[ $lang_code ]->element_type ) ) {
|
||||
|
||||
$current_lang = $this->sitepress->get_current_language();
|
||||
$this->sitepress->switch_lang( $lang_code );
|
||||
|
||||
$element = explode( '_', $translations[ $lang_code ]->element_type );
|
||||
$type = array_shift( $element );
|
||||
$subtype = implode( '_', $element );
|
||||
switch ( $type ) {
|
||||
case 'post':
|
||||
$new_url = get_permalink( $translations[ $lang_code ]->element_id );
|
||||
break;
|
||||
case 'tax':
|
||||
$term = get_term_by( 'term_taxonomy_id', $translations[ $lang_code ]->element_id, $subtype );
|
||||
$new_url = get_term_link( $term );
|
||||
break;
|
||||
}
|
||||
|
||||
$this->sitepress->switch_lang( $current_lang );
|
||||
}
|
||||
|
||||
$this->lock = false;
|
||||
return $new_url;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $url
|
||||
*
|
||||
* @return array<string,\stdClass>
|
||||
*/
|
||||
private function cached_retrieve_translations( $url ) {
|
||||
$cache_key = md5( $url );
|
||||
$cache_found = false;
|
||||
$cache = new WPML_WP_Cache( self::CACHE_GROUP );
|
||||
$translations = $cache->get( $cache_key, $cache_found );
|
||||
|
||||
if ( ! $cache_found && is_object( $this->wp_query ) ) {
|
||||
$translations = $this->retrieve_translations();
|
||||
$cache->set( $cache_key, $translations );
|
||||
}
|
||||
|
||||
return $translations;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string,\stdClass>
|
||||
*/
|
||||
private function retrieve_translations() {
|
||||
$this->sitepress->set_wp_query(); // Make sure $sitepress->wp_query is set
|
||||
$_wp_query_back = clone $this->wp_query;
|
||||
$wp_query = $this->sitepress->get_wp_query();
|
||||
$wp_query = is_object( $wp_query ) ? clone $wp_query : clone $_wp_query_back;
|
||||
|
||||
$languages_helper = new WPML_Languages( $this->wpml_term_translations, $this->sitepress, $this->wpml_post_translations );
|
||||
list( $translations) = $languages_helper->get_ls_translations( $wp_query, $_wp_query_back, $this->sitepress->get_wp_query() );
|
||||
|
||||
return $translations;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
class WPML_Absolute_Url_Persisted_Filters_Factory implements IWPML_Backend_Action_Loader, IWPML_AJAX_Action_Loader {
|
||||
|
||||
public function create() {
|
||||
$url_persisted = WPML_Absolute_Url_Persisted::get_instance();
|
||||
|
||||
if ( $url_persisted->has_urls() ) {
|
||||
return new WPML_Absolute_Url_Persisted_Filters( $url_persisted );
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
class WPML_Absolute_Url_Persisted_Filters implements IWPML_Action {
|
||||
|
||||
/** @var WPML_Absolute_Url_Persisted $url_persisted */
|
||||
private $url_persisted;
|
||||
|
||||
public function __construct( WPML_Absolute_Url_Persisted $url_persisted ) {
|
||||
$this->url_persisted = $url_persisted;
|
||||
}
|
||||
|
||||
public function add_hooks() {
|
||||
add_filter( 'wp_insert_post_data', [ $this, 'reset' ] );
|
||||
add_action( 'delete_post', [ $this, 'reset' ] );
|
||||
|
||||
add_filter( 'wp_update_term_data', [ $this, 'reset' ] );
|
||||
add_action( 'pre_delete_term', [ $this, 'reset' ] );
|
||||
|
||||
add_filter( 'rewrite_rules_array', [ $this, 'reset' ] );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $data
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function reset( $data = null ) {
|
||||
$this->url_persisted->reset();
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
interface IWPML_Resolve_Object_Url {
|
||||
|
||||
/**
|
||||
* @param string $url
|
||||
* @param string $lang
|
||||
*
|
||||
* @return string|false Will return the resolved URL or `false` if it could not be resolved.
|
||||
*/
|
||||
public function resolve_object_url( $url, $lang );
|
||||
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
<?php
|
||||
|
||||
class WPML_Absolute_Url_Persisted {
|
||||
|
||||
const OPTION_KEY = 'wpml_resolved_url_persist';
|
||||
|
||||
private static $instance;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $urls;
|
||||
|
||||
/**
|
||||
* @return WPML_Absolute_Url_Persisted
|
||||
*/
|
||||
public static function get_instance() {
|
||||
if ( null === self::$instance ) {
|
||||
self::$instance = new self();
|
||||
}
|
||||
|
||||
return self::$instance;
|
||||
}
|
||||
|
||||
protected function __construct() {}
|
||||
|
||||
private function __clone() {}
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
*/
|
||||
public function __wakeup() {
|
||||
throw new Exception( 'Cannot unserialize singleton' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns urls array.
|
||||
*
|
||||
* @return array Array with urls.
|
||||
*/
|
||||
private function get_urls() {
|
||||
if ( null === $this->urls ) {
|
||||
$this->urls = get_option( self::OPTION_KEY, array() );
|
||||
|
||||
if ( ! is_array( $this->urls ) ) {
|
||||
$this->urls = array();
|
||||
}
|
||||
}
|
||||
|
||||
return $this->urls;
|
||||
}
|
||||
|
||||
/** @return bool */
|
||||
public function has_urls() {
|
||||
return (bool) $this->get_urls();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $original_url
|
||||
* @param string $lang
|
||||
* @param string|false $converted_url A `false` value means that the URL could not be resolved
|
||||
*/
|
||||
public function set( $original_url, $lang, $converted_url ) {
|
||||
$this->get_urls();
|
||||
$this->urls[ $original_url ][ $lang ] = $converted_url;
|
||||
$this->persist_in_shutdown();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $original_url
|
||||
* @param string $lang
|
||||
*
|
||||
* @return string|false|null If the URL has already been processed but could not be resolved, it will return `false`
|
||||
*/
|
||||
public function get( $original_url, $lang ) {
|
||||
$this->get_urls();
|
||||
|
||||
if ( isset( $this->urls[ $original_url ][ $lang ] ) ) {
|
||||
return $this->urls[ $original_url ][ $lang ];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public function reset() {
|
||||
$this->urls = [];
|
||||
$this->persist();
|
||||
$this->urls = null;
|
||||
}
|
||||
|
||||
public function persist() {
|
||||
update_option( self::OPTION_KEY, $this->urls );
|
||||
}
|
||||
|
||||
private function persist_in_shutdown() {
|
||||
if ( ! has_action( 'shutdown', array( $this, 'persist' ) ) ) {
|
||||
add_action( 'shutdown', array( $this, 'persist' ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
class WPML_Resolve_Absolute_Url_Cached implements IWPML_Resolve_Object_Url {
|
||||
|
||||
/** @var WPML_Absolute_Url_Persisted $url_persisted */
|
||||
private $url_persisted;
|
||||
|
||||
/** @var WPML_Resolve_Absolute_Url $resolve_url */
|
||||
private $resolve_url;
|
||||
|
||||
public function __construct( WPML_Absolute_Url_Persisted $url_persisted, WPML_Resolve_Absolute_Url $resolve_url ) {
|
||||
$this->url_persisted = $url_persisted;
|
||||
$this->resolve_url = $resolve_url;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $url
|
||||
* @param string $lang
|
||||
*
|
||||
* @return false|string Will return `false` if the URL could not be resolved
|
||||
*/
|
||||
public function resolve_object_url( $url, $lang ) {
|
||||
$resolved_url = $this->url_persisted->get( $url, $lang );
|
||||
|
||||
if ( null === $resolved_url ) {
|
||||
$resolved_url = $this->resolve_url->resolve_object_url( $url, $lang );
|
||||
$this->url_persisted->set( $url, $lang, $resolved_url );
|
||||
}
|
||||
|
||||
return $resolved_url;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
class WPML_Resolve_Absolute_Url implements IWPML_Resolve_Object_Url {
|
||||
|
||||
/** @var SitePress $sitepress */
|
||||
private $sitepress;
|
||||
|
||||
/** @var WPML_Translate_Link_Targets */
|
||||
private $translate_link_targets;
|
||||
|
||||
/** @var bool */
|
||||
private $lock;
|
||||
|
||||
public function __construct( SitePress $sitepress, WPML_Translate_Link_Targets $translate_link_targets ) {
|
||||
$this->sitepress = $sitepress;
|
||||
$this->translate_link_targets = $translate_link_targets;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $url
|
||||
* @param string $lang
|
||||
*
|
||||
* @return string|false
|
||||
*/
|
||||
public function resolve_object_url( $url, $lang ) {
|
||||
if ( $this->lock ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->lock = true;
|
||||
$current_lang = $this->sitepress->get_current_language();
|
||||
$this->sitepress->switch_lang( $lang );
|
||||
|
||||
try {
|
||||
$new_url = $this->translate_link_targets->convert_url( $url );
|
||||
|
||||
if ( trailingslashit( $new_url ) === trailingslashit( $url ) ) {
|
||||
$new_url = false;
|
||||
}
|
||||
} catch ( Exception $e ) {
|
||||
$new_url = false;
|
||||
}
|
||||
|
||||
$this->sitepress->switch_lang( $current_lang );
|
||||
$this->lock = false;
|
||||
|
||||
return $new_url;
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user