first commit
This commit is contained in:
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
namespace WPML\PostTranslation\SpecialPage;
|
||||
|
||||
class Hooks implements \IWPML_Backend_Action {
|
||||
|
||||
public function add_hooks() {
|
||||
add_action( 'current_screen', [ $this, 'deleteCacheOnSettingPage' ] );
|
||||
}
|
||||
|
||||
public function deleteCacheOnSettingPage( \WP_Screen $currentScreen ) {
|
||||
if ( 'options-reading' === $currentScreen->id ) {
|
||||
\WPML_Pre_Option_Page::clear_cache();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
class WPML_Post_Edit_Terms_Hooks_Factory implements IWPML_Backend_Action_Loader {
|
||||
|
||||
public function create() {
|
||||
global $sitepress, $wpdb;
|
||||
|
||||
if ( $this->is_saving_post_data_with_terms() ) {
|
||||
return new WPML_Post_Edit_Terms_Hooks( $sitepress, $wpdb );
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private function is_saving_post_data_with_terms() {
|
||||
return isset( $_POST['action'] )
|
||||
&& in_array( $_POST['action'], array( 'editpost', 'inline-save' ) )
|
||||
&& ! empty( $_POST['tax_input'] );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
<?php
|
||||
|
||||
class WPML_Post_Edit_Terms_Hooks implements IWPML_Action {
|
||||
|
||||
const AFTER_POST_DATA_SANITIZED_ACTION = 'init';
|
||||
|
||||
/** @var IWPML_Current_Language $language */
|
||||
private $language;
|
||||
|
||||
/** @var wpdb $wpdb */
|
||||
private $wpdb;
|
||||
|
||||
public function __construct( IWPML_Current_Language $current_language, wpdb $wpdb ) {
|
||||
$this->language = $current_language;
|
||||
$this->wpdb = $wpdb;
|
||||
}
|
||||
|
||||
public function add_hooks() {
|
||||
add_action( self::AFTER_POST_DATA_SANITIZED_ACTION, array( $this, 'set_tags_input_with_ids' ) );
|
||||
}
|
||||
|
||||
public function set_tags_input_with_ids() {
|
||||
$tag_names = $this->get_tags_from_tax_input();
|
||||
|
||||
if ( $tag_names ) {
|
||||
$sql = "SELECT t.name, t.term_id FROM {$this->wpdb->terms} AS t
|
||||
LEFT JOIN {$this->wpdb->term_taxonomy} AS tt
|
||||
ON tt.term_id = t.term_id
|
||||
LEFT JOIN {$this->wpdb->prefix}icl_translations AS tr
|
||||
ON tr.element_id = tt.term_taxonomy_id AND tr.element_type = 'tax_post_tag'
|
||||
WHERE tr.language_code = %s AND t.name IN(" . wpml_prepare_in( $tag_names ) . ")";
|
||||
|
||||
$tags = $this->wpdb->get_results( $this->wpdb->prepare( $sql, $this->language->get_current_language() ) );
|
||||
|
||||
foreach ( $tags as $tag ) {
|
||||
$_POST['tags_input'][] = (int) $tag->term_id;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function get_tags_from_tax_input() {
|
||||
if ( ! empty( $_POST['tax_input']['post_tag'] ) ) {
|
||||
$tags = $_POST['tax_input']['post_tag'];
|
||||
|
||||
if ( ! is_array( $tags ) ) {
|
||||
/**
|
||||
* This code is following the logic from `edit_post()` in core
|
||||
* where the terms name are converted into IDs.
|
||||
*
|
||||
* @see edit_post
|
||||
*/
|
||||
$delimiter = _x( ',', 'tag delimiter' );
|
||||
$tags = explode( $delimiter, trim( $tags, " \n\t\r\0\x0B," ) );
|
||||
}
|
||||
|
||||
return array_map( 'trim', $tags );
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,217 @@
|
||||
<?php
|
||||
|
||||
class WPML_Post_Status extends WPML_WPDB_User {
|
||||
|
||||
private $needs_update = array();
|
||||
private $status = array();
|
||||
private $preload_done = false;
|
||||
private $wp_api;
|
||||
|
||||
public function __construct( &$wpdb, $wp_api ) {
|
||||
parent::__construct( $wpdb );
|
||||
$this->wp_api = $wp_api;
|
||||
}
|
||||
|
||||
public function needs_update( $post_id ) {
|
||||
global $wpml_post_translations, $wpml_cache_factory;
|
||||
|
||||
if ( !isset( $this->needs_update[ $post_id ] ) ) {
|
||||
$this->maybe_preload();
|
||||
|
||||
$trid = $wpml_post_translations->get_element_trid ( $post_id );
|
||||
|
||||
$cache = $wpml_cache_factory->get( 'WPML_Post_Status::needs_update' );
|
||||
$found = false;
|
||||
$results = $cache->get( $trid, $found );
|
||||
if ( ! $found ) {
|
||||
$results = $this->wpdb->get_results(
|
||||
$this->wpdb->prepare(
|
||||
"SELECT ts.needs_update, it.language_code
|
||||
FROM {$this->wpdb->prefix}icl_translation_status ts
|
||||
JOIN {$this->wpdb->prefix}icl_translations it
|
||||
ON it.translation_id = ts.translation_id
|
||||
WHERE it.trid = %d",
|
||||
$trid
|
||||
)
|
||||
);
|
||||
$cache->set( $trid, $results );
|
||||
}
|
||||
$language = $wpml_post_translations->get_element_lang_code ( $post_id );
|
||||
|
||||
$needs_update = false;
|
||||
foreach( $results as $result ) {
|
||||
if ( $result->language_code == $language ) {
|
||||
$needs_update = $result->needs_update;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
$this->needs_update [ $post_id ] = $needs_update;
|
||||
|
||||
}
|
||||
|
||||
return $this->needs_update [ $post_id ];
|
||||
}
|
||||
|
||||
private function maybe_preload() {
|
||||
global $wpml_post_translations, $wpml_cache_factory;
|
||||
|
||||
if ( ! $this->preload_done ) {
|
||||
|
||||
$trids = $wpml_post_translations->get_trids();
|
||||
$trids = implode( ',', $trids );
|
||||
|
||||
if ( $trids ) {
|
||||
|
||||
$cache = $wpml_cache_factory->get( 'WPML_Post_Status::needs_update' );
|
||||
|
||||
$results = $this->wpdb->get_results(
|
||||
"SELECT ts.needs_update, it.language_code, it.trid
|
||||
FROM {$this->wpdb->prefix}icl_translation_status ts
|
||||
JOIN {$this->wpdb->prefix}icl_translations it
|
||||
ON it.translation_id = ts.translation_id
|
||||
WHERE it.trid IN ( {$trids} )"
|
||||
);
|
||||
|
||||
$groups = array();
|
||||
foreach ( $results as $result ) {
|
||||
if ( ! isset( $groups[ $result->trid ] ) ) {
|
||||
$groups[ $result->trid ] = array();
|
||||
}
|
||||
$groups[ $result->trid ][] = $result;
|
||||
}
|
||||
foreach ( $groups as $trid => $group ) {
|
||||
$cache->set( $trid, $group );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$this->preload_done = true;
|
||||
}
|
||||
}
|
||||
public function reload() {
|
||||
$this->needs_update = array();
|
||||
$this->status = array();
|
||||
$this->preload_done = false;
|
||||
}
|
||||
|
||||
public function set_update_status( $post_id, $update ) {
|
||||
global $wpml_post_translations;
|
||||
|
||||
$update = (bool) $update;
|
||||
$translation_id = $this->wpdb->get_var (
|
||||
$this->wpdb->prepare (
|
||||
"SELECT ts.translation_id
|
||||
FROM {$this->wpdb->prefix}icl_translations it
|
||||
JOIN {$this->wpdb->prefix}icl_translation_status ts
|
||||
ON it.translation_id = ts.translation_id
|
||||
WHERE it.trid = %d AND it.language_code = %s",
|
||||
$wpml_post_translations->get_element_trid ( $post_id ),
|
||||
$wpml_post_translations->get_element_lang_code ( $post_id )
|
||||
)
|
||||
);
|
||||
|
||||
if ( $translation_id ) {
|
||||
$res = $this->wpdb->update (
|
||||
$this->wpdb->prefix . 'icl_translation_status',
|
||||
array( 'needs_update' => $update ),
|
||||
array( 'translation_id' => $translation_id )
|
||||
);
|
||||
}
|
||||
|
||||
$this->needs_update[ $post_id ] = (bool) $update;
|
||||
|
||||
do_action( 'wpml_translation_status_update',
|
||||
array(
|
||||
'post_id' => $post_id,
|
||||
'type' => 'needs_update',
|
||||
'value' => $update
|
||||
)
|
||||
);
|
||||
|
||||
return isset( $res );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $post_id
|
||||
* @param int $status
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function set_status( $post_id, $status ) {
|
||||
global $wpml_post_translations;
|
||||
|
||||
if ( ! $post_id ) {
|
||||
throw new InvalidArgumentException(
|
||||
'Tried to set status' . $status . ' for falsy post_id ' . serialize( $post_id ) );
|
||||
}
|
||||
|
||||
/** @var \stdClass $translation_id */
|
||||
$translation_id = $this->wpdb->get_row (
|
||||
$this->wpdb->prepare (
|
||||
"SELECT it.translation_id AS transid, ts.translation_id AS status_id
|
||||
FROM {$this->wpdb->prefix}icl_translations it
|
||||
LEFT JOIN {$this->wpdb->prefix}icl_translation_status ts
|
||||
ON it.translation_id = ts.translation_id
|
||||
WHERE it.trid = %d AND it.language_code = %s
|
||||
LIMIT 1",
|
||||
$wpml_post_translations->get_element_trid ( $post_id ),
|
||||
$wpml_post_translations->get_element_lang_code ( $post_id )
|
||||
)
|
||||
);
|
||||
|
||||
if ( $translation_id->status_id && $translation_id->transid ) {
|
||||
$res = $this->wpdb->update (
|
||||
$this->wpdb->prefix . 'icl_translation_status',
|
||||
array( 'status' => $status ),
|
||||
array( 'translation_id' => $translation_id->transid )
|
||||
);
|
||||
$this->status[ $post_id ] = $status;
|
||||
} else {
|
||||
$res = $this->wpdb->insert (
|
||||
$this->wpdb->prefix . 'icl_translation_status',
|
||||
array( 'status' => $status, 'translation_id' => $translation_id->transid )
|
||||
);
|
||||
}
|
||||
|
||||
do_action( 'wpml_translation_status_update',
|
||||
array(
|
||||
'post_id' => $post_id,
|
||||
'type' => 'status',
|
||||
'value' => $status
|
||||
)
|
||||
);
|
||||
|
||||
|
||||
return $res;
|
||||
}
|
||||
|
||||
public function get_status( $post_id, $trid = false, $lang_code = false ) {
|
||||
global $wpml_post_translations;
|
||||
|
||||
$trid = $trid !== false ? $trid : $wpml_post_translations->get_element_trid ( $post_id );
|
||||
$lang_code = $lang_code !== false ? $lang_code : $wpml_post_translations->get_element_lang_code ( $post_id );
|
||||
$post_id = $post_id ? $post_id : $wpml_post_translations->get_element_id ( $lang_code, $trid );
|
||||
if ( !$post_id ) {
|
||||
$status = ICL_TM_NOT_TRANSLATED;
|
||||
$post_id = $lang_code . $trid;
|
||||
} else {
|
||||
$status = $this->is_duplicate( $post_id )
|
||||
? ICL_TM_DUPLICATE : ( $this->needs_update ( $post_id ) ? ICL_TM_NEEDS_UPDATE : ICL_TM_COMPLETE );
|
||||
}
|
||||
$status = apply_filters (
|
||||
'wpml_translation_status',
|
||||
$status,
|
||||
$trid,
|
||||
$lang_code,
|
||||
true
|
||||
);
|
||||
$this->status[ $post_id ] = $status;
|
||||
|
||||
return $status;
|
||||
}
|
||||
|
||||
public function is_duplicate( $post_id ) {
|
||||
return (bool) $this->wp_api->get_post_meta ( $post_id, '_icl_lang_duplicate_of', true );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
<?php
|
||||
|
||||
class WPML_Pre_Option_Page extends WPML_WPDB_And_SP_User {
|
||||
|
||||
const CACHE_GROUP = 'wpml_pre_option_page';
|
||||
|
||||
private $switched;
|
||||
private $lang;
|
||||
|
||||
public function __construct( &$wpdb, &$sitepress, $switched, $lang ) {
|
||||
parent::__construct( $wpdb, $sitepress );
|
||||
|
||||
$this->switched = $switched;
|
||||
$this->lang = $lang;
|
||||
}
|
||||
|
||||
public function get( $type, $from_language = null ) {
|
||||
|
||||
$cache_key = $type;
|
||||
$cache_found = false;
|
||||
|
||||
$cache = new WPML_WP_Cache( self::CACHE_GROUP );
|
||||
$results = $cache->get( $cache_key, $cache_found );
|
||||
|
||||
if ( ( ( ! $cache_found || ! isset ( $results[ $type ] ) ) && ! $this->switched )
|
||||
|| ( $this->switched && $this->sitepress->get_setting( 'setup_complete' ) )
|
||||
) {
|
||||
$results = [];
|
||||
$results[ $type ] = [];
|
||||
// Fetch for all languages and cache them.
|
||||
$values = $this->wpdb->get_results(
|
||||
$this->wpdb->prepare(
|
||||
" SELECT element_id, language_code
|
||||
FROM {$this->wpdb->prefix}icl_translations
|
||||
WHERE trid =
|
||||
(SELECT trid
|
||||
FROM {$this->wpdb->prefix}icl_translations
|
||||
WHERE element_type = 'post_page'
|
||||
AND element_id = (SELECT option_value
|
||||
FROM {$this->wpdb->options}
|
||||
WHERE option_name=%s
|
||||
LIMIT 1))
|
||||
",
|
||||
$type
|
||||
)
|
||||
);
|
||||
|
||||
if ( count( $values ) ) {
|
||||
foreach ( $values as $lang_result ) {
|
||||
$results [ $type ] [ $lang_result->language_code ] = $lang_result->element_id;
|
||||
}
|
||||
}
|
||||
|
||||
$cache->set( $cache_key, $results );
|
||||
}
|
||||
|
||||
$target_language = $from_language ? $from_language : $this->lang;
|
||||
|
||||
return isset( $results[ $type ][ $target_language ] ) ? $results[ $type ][ $target_language ] : false;
|
||||
}
|
||||
|
||||
public static function clear_cache() {
|
||||
$cache = new WPML_WP_Cache( self::CACHE_GROUP );
|
||||
$cache->flush_group_cache();
|
||||
}
|
||||
|
||||
function fix_trashed_front_or_posts_page_settings( $post_id ) {
|
||||
if ( 'page' !== get_post_type( $post_id ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$post_id = (int) $post_id;
|
||||
$page_on_front_current = (int) $this->get( 'page_on_front' );
|
||||
$page_for_posts_current = (int) $this->get( 'page_for_posts' );
|
||||
|
||||
$page_on_front_default = (int) $this->get( 'page_on_front', $this->sitepress->get_default_language() );
|
||||
$page_for_posts_default = (int) $this->get( 'page_for_posts', $this->sitepress->get_default_language() );
|
||||
|
||||
if ( $page_on_front_current === $post_id && $page_on_front_current !== $page_on_front_default ) {
|
||||
remove_filter( 'pre_option_page_on_front', array( $this->sitepress, 'pre_option_page_on_front' ) );
|
||||
update_option( 'page_on_front', $page_on_front_default );
|
||||
add_filter( 'pre_option_page_on_front', array( $this->sitepress, 'pre_option_page_on_front' ) );
|
||||
}
|
||||
if ( $page_for_posts_current === $post_id && $page_for_posts_current !== $page_for_posts_default ) {
|
||||
remove_filter( 'pre_option_page_for_posts', array( $this->sitepress, 'pre_option_page_for_posts' ) );
|
||||
update_option( 'page_for_posts', $page_for_posts_default );
|
||||
add_filter( 'pre_option_page_for_posts', array( $this->sitepress, 'pre_option_page_for_posts' ) );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
namespace WPML\Posts;
|
||||
|
||||
use WPML\API\PostTypes;
|
||||
use WPML\Collect\Support\Collection;
|
||||
use WPML\FP\Fns;
|
||||
use WPML\FP\Lst;
|
||||
use WPML\LIB\WP\PostType;
|
||||
|
||||
class CountPerPostType {
|
||||
public function run( Collection $data, \wpdb $wpdb ) {
|
||||
$postTypes = $data->get( 'postTypes', PostTypes::getAutomaticTranslatable() );
|
||||
$postIn = wpml_prepare_in( $postTypes );
|
||||
|
||||
$query = "
|
||||
SELECT posts.post_type, COUNT(posts.ID)
|
||||
FROM {$wpdb->posts} posts
|
||||
INNER JOIN {$wpdb->prefix}icl_translations translations ON translations.element_id = posts.ID AND translations.element_type = CONCAT('post_', posts.post_type)
|
||||
WHERE posts.post_type IN ({$postIn}) AND posts.post_status = %s AND translations.source_language_code IS NULL
|
||||
GROUP BY posts.post_type
|
||||
";
|
||||
|
||||
$postCountPerType = $wpdb->get_results( $wpdb->prepare( $query, 'publish' ), ARRAY_N );
|
||||
|
||||
// $setPluralPostName :: [ 'post' => '1' ] -> [ 'Posts' => 1 ]
|
||||
$setPluralPostName = function ( $postType ) {
|
||||
return [ PostType::getPluralName( $postType[0] )->getOrElse( $postType[0] ) => (int) $postType[1] ];
|
||||
};
|
||||
|
||||
// $setCountToZero :: 'post' -> [ 'post' => 0 ]
|
||||
$setCountToZero = Lst::makePair( Fns::__, 0 );
|
||||
|
||||
return wpml_collect( $postTypes )
|
||||
->map( $setCountToZero )
|
||||
->merge( $postCountPerType )
|
||||
->mapWithKeys( $setPluralPostName )
|
||||
->toArray();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace WPML\Posts;
|
||||
|
||||
use WPML\Collect\Support\Collection;
|
||||
use WPML\DatabaseQueries\TranslatedPosts;
|
||||
use WPML\FP\Either;
|
||||
use WPML\FP\Fns;
|
||||
use WPML\FP\Lst;
|
||||
use function WPML\FP\partialRight;
|
||||
|
||||
class DeleteTranslatedContentOfLanguages {
|
||||
|
||||
public function run( Collection $data ) {
|
||||
$deleteTranslatedContent = Fns::unary( partialRight( 'wp_delete_post', true ) );
|
||||
|
||||
return Either::of( $data->get( 'language_code' ) )
|
||||
->filter( Lst::length() )
|
||||
->map( [ TranslatedPosts::class, 'getIdsForLangs' ] )
|
||||
->map( Fns::map( $deleteTranslatedContent ) )
|
||||
->coalesce( Fns::identity(), Fns::identity() );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
<?php
|
||||
|
||||
namespace WPML\Posts;
|
||||
|
||||
use WPML\API\PostTypes;
|
||||
use WPML\Collect\Support\Collection;
|
||||
use WPML\Element\API\Languages;
|
||||
use WPML\FP\Fns;
|
||||
use WPML\FP\Lst;
|
||||
use WPML\FP\Str;
|
||||
use WPML\LIB\WP\PostType;
|
||||
|
||||
class UntranslatedCount {
|
||||
|
||||
public function run( Collection $data, \wpdb $wpdb ) {
|
||||
$postTypes = $data->get( 'postTypes', PostTypes::getAutomaticTranslatable() );
|
||||
|
||||
$postIn = wpml_prepare_in( Fns::map( Str::concat( 'post_' ), $postTypes ) );
|
||||
$statuses = wpml_prepare_in( [ ICL_TM_NOT_TRANSLATED, ICL_TM_ATE_CANCELLED ] );
|
||||
|
||||
$query = "
|
||||
SELECT translations.post_type, COUNT(translations.ID)
|
||||
FROM (
|
||||
SELECT RIGHT(element_type, LENGTH(element_type) - 5) as post_type, posts.ID
|
||||
FROM {$wpdb->prefix}icl_translations
|
||||
INNER JOIN {$wpdb->prefix}posts posts ON element_id = ID
|
||||
WHERE element_type IN ({$postIn})
|
||||
AND post_status = 'publish'
|
||||
AND source_language_code IS NULL
|
||||
AND language_code = %s
|
||||
AND (
|
||||
SELECT COUNT(trid)
|
||||
FROM {$wpdb->prefix}icl_translations icl_translations_inner
|
||||
INNER JOIN {$wpdb->prefix}icl_translation_status icl_translations_status
|
||||
on icl_translations_inner.translation_id = icl_translations_status.translation_id
|
||||
WHERE icl_translations_inner.trid = {$wpdb->prefix}icl_translations.trid
|
||||
AND icl_translations_status.status NOT IN ({$statuses})
|
||||
) < %d
|
||||
) as translations
|
||||
GROUP BY translations.post_type;
|
||||
";
|
||||
|
||||
$untranslatedPosts = $wpdb->get_results(
|
||||
$wpdb->prepare( $query, Languages::getDefaultCode(), Lst::length( Languages::getSecondaries() ) ),
|
||||
ARRAY_N
|
||||
);
|
||||
|
||||
// $setPluralPostName :: [ 'post' => '1' ] -> [ 'Posts' => 1 ]
|
||||
$setPluralPostName = function ( $postType ) {
|
||||
return [ PostType::getPluralName( $postType[0] )->getOrElse( $postType[0] ) => (int) $postType[1] ];
|
||||
};
|
||||
|
||||
// $setCountToZero :: 'post' -> [ 'post' => 0 ]
|
||||
$setCountToZero = Lst::makePair( Fns::__, 0 );
|
||||
|
||||
|
||||
return wpml_collect( $postTypes )
|
||||
->map( $setCountToZero )
|
||||
->merge( $untranslatedPosts )
|
||||
->mapWithKeys( $setPluralPostName )
|
||||
->toArray();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user