first commit
This commit is contained in:
@@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
interface IWPML_TM_Word_Calculator_Post {
|
||||
|
||||
public function count_words( WPML_Post_Element $post_element, $lang = null );
|
||||
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
<?php
|
||||
|
||||
class WPML_TM_Word_Calculator_Post_Custom_Fields implements IWPML_TM_Word_Calculator_Post {
|
||||
|
||||
/** @var WPML_TM_Word_Calculator $calculator */
|
||||
private $calculator;
|
||||
|
||||
/** @var array|null $cf_settings from `$sitepress_settings['translation-management']['custom_fields_translation']` */
|
||||
private $cf_settings;
|
||||
|
||||
/** @var array $fields_to_count */
|
||||
private $fields_to_count = array();
|
||||
|
||||
/**
|
||||
* WPML_TM_Word_Calculator_Post_Custom_Fields constructor.
|
||||
*
|
||||
* $cf_settings:
|
||||
*
|
||||
* <code>
|
||||
* $array = [
|
||||
* 'custom-field-1' => WPML_TRANSLATE_CUSTOM_FIELD,
|
||||
* 'custom-field-2' => WPML_COPY_CUSTOM_FIELD,
|
||||
* 'custom-field-3' => WPML_IGNORE_CUSTOM_FIELD,
|
||||
* 'custom-field-4' => WPML_IGNORE_CUSTOM_FIELD,
|
||||
* 'custom-field-5' => WPML_COPY_ONCE_CUSTOM_FIELD,
|
||||
* ]
|
||||
* </code>
|
||||
*
|
||||
* @param \WPML_TM_Word_Calculator $calculator An instance of WPML_TM_Word_Calculator.
|
||||
* @param array|null $cf_settings An associative array where they key is the name of the custom field and the value is an integer representing the translation method.
|
||||
*
|
||||
* @see inc/constants.php for the values of the constsnts
|
||||
*/
|
||||
public function __construct( WPML_TM_Word_Calculator $calculator, array $cf_settings = null ) {
|
||||
$this->calculator = $calculator;
|
||||
$this->cf_settings = $cf_settings;
|
||||
}
|
||||
|
||||
public function count_words( WPML_Post_Element $post_element, $lang = null ) {
|
||||
$words = 0;
|
||||
$post_id = $post_element->get_id();
|
||||
$post_lang = $post_element->get_language_code();
|
||||
|
||||
if ( ! $post_lang || ! $post_id || ! $this->is_registered_type( $post_element )
|
||||
|| empty( $this->cf_settings ) || ! is_array( $this->cf_settings )
|
||||
) {
|
||||
return $words;
|
||||
}
|
||||
|
||||
$cf_to_count = $this->get_translatable_fields_to_count( $post_id );
|
||||
|
||||
foreach ( $cf_to_count as $cf ) {
|
||||
$custom_fields_value = get_post_meta( $post_id, $cf );
|
||||
|
||||
if ( ! $custom_fields_value ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( is_scalar( $custom_fields_value ) ) {
|
||||
// only support scalar values for now
|
||||
$words += $this->calculator->count_words( $custom_fields_value, $post_lang );
|
||||
} else {
|
||||
|
||||
foreach ( $custom_fields_value as $custom_fields_value_item ) {
|
||||
|
||||
if ( $custom_fields_value_item && is_scalar( $custom_fields_value_item ) ) {
|
||||
// only support scalar values for now
|
||||
$words += $this->calculator->count_words( $custom_fields_value_item, $post_lang );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (int) $words;
|
||||
}
|
||||
|
||||
/** @return bool */
|
||||
private function is_registered_type( WPML_Post_Element $post_element ) {
|
||||
$post_types = get_post_types();
|
||||
return in_array( $post_element->get_type(), $post_types );
|
||||
}
|
||||
|
||||
/** @return array */
|
||||
private function get_translatable_fields_to_count( $post_id ) {
|
||||
if ( ! $this->fields_to_count ) {
|
||||
foreach ( $this->cf_settings as $cf => $mode ) {
|
||||
if ( in_array( (int) $mode, array( WPML_TRANSLATE_CUSTOM_FIELD, WPML_COPY_ONCE_CUSTOM_FIELD ), true ) ) {
|
||||
$this->fields_to_count[] = $cf;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Allow to modify the custom fields whose words will be counted.
|
||||
*
|
||||
* @param array $fields_to_count The fields to include when counting the words.
|
||||
* @param int $post_id The ID of the post for which we are counting the words.
|
||||
*
|
||||
* @see \WPML_TM_Word_Calculator_Post_Custom_Fields::__construct
|
||||
*/
|
||||
return apply_filters( 'wpml_words_count_custom_fields_to_count', $this->fields_to_count, $post_id );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
class WPML_TM_Word_Calculator_Post_Object implements IWPML_TM_Word_Calculator_Post {
|
||||
|
||||
/** @var WPML_TM_Word_Calculator $calculator */
|
||||
private $calculator;
|
||||
|
||||
/** @var WPML_TM_Word_Calculator_Post_Packages $packages_calculator */
|
||||
private $packages_calculator;
|
||||
|
||||
public function __construct(
|
||||
WPML_TM_Word_Calculator $calculator,
|
||||
WPML_TM_Word_Calculator_Post_Packages $packages_calculator
|
||||
) {
|
||||
$this->calculator = $calculator;
|
||||
$this->packages_calculator = $packages_calculator;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param WPML_Post_Element $post_element
|
||||
* @param string $lang
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function count_words( WPML_Post_Element $post_element, $lang = null ) {
|
||||
$words = 0;
|
||||
$wp_post = $post_element->get_wp_object();
|
||||
$source_lang = $post_element->get_language_code();
|
||||
|
||||
if ( $wp_post ) {
|
||||
$words += $this->calculator->count_words( $wp_post->post_title, $source_lang );
|
||||
$words += $this->calculator->count_words( $wp_post->post_excerpt, $source_lang );
|
||||
$words += $this->calculator->count_words( $wp_post->post_name, $source_lang );
|
||||
|
||||
if ( $this->has_string_packages( $post_element ) ) {
|
||||
$words += $this->packages_calculator->count_words( $post_element, $lang );
|
||||
} else {
|
||||
$words += $this->calculator->count_words( $wp_post->post_content, $source_lang );
|
||||
}
|
||||
}
|
||||
|
||||
return $words;
|
||||
}
|
||||
|
||||
private function has_string_packages( WPML_Post_Element $post_element ) {
|
||||
return (bool) $this->packages_calculator->count_words( $post_element, null );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
class WPML_TM_Word_Calculator_Post_Packages implements IWPML_TM_Word_Calculator_Post {
|
||||
|
||||
/** @var WPML_TM_Word_Count_Records $records */
|
||||
private $records;
|
||||
|
||||
/** @var WPML_TM_Count_Composite[] $package_counts */
|
||||
private $package_counts;
|
||||
|
||||
public function __construct( WPML_TM_Word_Count_Records $records ) {
|
||||
$this->records = $records;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param WPML_Post_Element $post_element
|
||||
* @param string|null $lang
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function count_words( WPML_Post_Element $post_element, $lang = null ) {
|
||||
if ( $lang ) {
|
||||
return $this->get_package_counts( $post_element )->get_words_to_translate( $lang );
|
||||
} else {
|
||||
return $this->get_package_counts( $post_element )->get_total_words();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param WPML_Post_Element $post_element
|
||||
*
|
||||
* @return WPML_TM_Count_Composite
|
||||
*/
|
||||
private function get_package_counts( WPML_Post_Element $post_element ) {
|
||||
$post_id = $post_element->get_id();
|
||||
|
||||
if ( ! isset( $this->package_counts[ $post_id ] ) ) {
|
||||
$counts = $this->records->get_packages_word_counts( $post_id );
|
||||
|
||||
$word_count_composite = new WPML_TM_Count_Composite();
|
||||
|
||||
foreach ( $counts as $count ) {
|
||||
$word_count_composite->add_count( $count );
|
||||
}
|
||||
|
||||
$this->package_counts[ $post_id ] = $word_count_composite;
|
||||
}
|
||||
|
||||
return $this->package_counts[ $post_id ];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @see https://onthegosystems.myjetbrains.com/youtrack/issue/wpmltm-2327
|
||||
*/
|
||||
class WPML_TM_Word_Calculator {
|
||||
|
||||
const ASIAN_LANGUAGE_CHAR_SIZE = 6;
|
||||
|
||||
/** @var WPML_PHP_Functions $php_functions */
|
||||
private $php_functions;
|
||||
|
||||
public function __construct( WPML_PHP_Functions $php_functions ) {
|
||||
$this->php_functions = $php_functions;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $string
|
||||
* @param string $language_code
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function count_words( $string, $language_code ) {
|
||||
$sanitized_source = $this->sanitize_string( $string );
|
||||
$words = 0;
|
||||
|
||||
if ( in_array( $language_code, self::get_asian_languages() ) ) {
|
||||
$words += strlen( strip_tags( $sanitized_source ) ) / self::ASIAN_LANGUAGE_CHAR_SIZE;
|
||||
} else {
|
||||
$words += count( preg_split( '/[\s,:;!\.\?\(\)\[\]\-_\'"\\/]+/', $sanitized_source, 0, PREG_SPLIT_NO_EMPTY ) );
|
||||
}
|
||||
|
||||
return (int) $words;
|
||||
}
|
||||
|
||||
/** @return bool */
|
||||
private function exclude_shortcodes_in_words_count() {
|
||||
if ( $this->php_functions->defined( 'EXCLUDE_SHORTCODES_IN_WORDS_COUNT' ) ) {
|
||||
return (bool) $this->php_functions->constant( 'EXCLUDE_SHORTCODES_IN_WORDS_COUNT' );
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $source
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function sanitize_string( $source ) {
|
||||
$result = $source;
|
||||
$result = html_entity_decode( $result );
|
||||
$result = strip_tags( $result );
|
||||
$result = trim( $result );
|
||||
$result = $this->strip_urls( $result );
|
||||
|
||||
if ( $this->exclude_shortcodes_in_words_count() ) {
|
||||
$result = strip_shortcodes( $result );
|
||||
} else {
|
||||
$result = $this->extract_content_in_shortcodes( $result );
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $string
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function extract_content_in_shortcodes( $string ) {
|
||||
return preg_replace( '#(?:\[/?)[^/\]]+/?\]#s', '', $string );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $string
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function strip_urls( $string ) {
|
||||
return preg_replace( '/\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|$!:,.;]*[A-Z0-9+&@#\/%=~_|$]/i', '', $string );
|
||||
}
|
||||
|
||||
public static function get_asian_languages() {
|
||||
return array( 'ja', 'ko', 'zh-hans', 'zh-hant', 'mn', 'ne', 'hi', 'pa', 'ta', 'th' );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
<?php
|
||||
|
||||
interface IWPML_TM_Word_Count_Set {
|
||||
|
||||
public function process( $id );
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
class WPML_TM_Word_Count_Set_Package {
|
||||
|
||||
/** @var WPML_ST_Package_Factory $package_factory */
|
||||
private $package_factory;
|
||||
|
||||
/** @var WPML_TM_Word_Count_Records $records */
|
||||
private $records;
|
||||
|
||||
/** @var array $active_langs */
|
||||
private $active_langs;
|
||||
|
||||
public function __construct(
|
||||
WPML_ST_Package_Factory $package_factory,
|
||||
WPML_TM_Word_Count_Records $records,
|
||||
array $active_langs
|
||||
) {
|
||||
$this->package_factory = $package_factory;
|
||||
$this->records = $records;
|
||||
$this->active_langs = $active_langs;
|
||||
}
|
||||
|
||||
/** @param int $package_id */
|
||||
public function process( $package_id ) {
|
||||
$package = $this->package_factory->create( $package_id );
|
||||
$word_counts = new WPML_TM_Count();
|
||||
|
||||
foreach ( $this->active_langs as $lang ) {
|
||||
if ( $package->get_package_language() === $lang ) {
|
||||
$word_counts->set_total_words(
|
||||
$this->records->get_string_words_to_translate_per_lang( null, $package_id )
|
||||
);
|
||||
} else {
|
||||
$word_counts->set_words_to_translate(
|
||||
$lang,
|
||||
$this->records->get_string_words_to_translate_per_lang( $lang, $package_id )
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
$this->records->set_package_word_count( $package_id, $word_counts );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
<?php
|
||||
|
||||
class WPML_TM_Word_Count_Set_Post {
|
||||
|
||||
/** @var WPML_Translation_Element_Factory $element_factory */
|
||||
private $element_factory;
|
||||
|
||||
/** @var WPML_TM_Word_Count_Records $records */
|
||||
private $records;
|
||||
|
||||
/** @var IWPML_TM_Word_Calculator_Post[] $post_calculators */
|
||||
private $post_calculators;
|
||||
|
||||
/** @var array $active_langs */
|
||||
private $active_langs;
|
||||
|
||||
/** @var WPML_Post_Element $post_element */
|
||||
private $post_element;
|
||||
|
||||
/**
|
||||
* @param WPML_Translation_Element_Factory $element_factory
|
||||
* @param WPML_TM_Word_Count_Records $records
|
||||
* @param IWPML_TM_Word_Calculator_Post[] $calculators
|
||||
* @param array $active_langs
|
||||
*/
|
||||
public function __construct(
|
||||
WPML_Translation_Element_Factory $element_factory,
|
||||
WPML_TM_Word_Count_Records $records,
|
||||
array $calculators,
|
||||
array $active_langs
|
||||
) {
|
||||
$this->element_factory = $element_factory;
|
||||
$this->records = $records;
|
||||
$this->post_calculators = $calculators;
|
||||
$this->active_langs = $active_langs;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $post_id
|
||||
*/
|
||||
public function process( $post_id ) {
|
||||
$this->post_element = $this->element_factory->create( $post_id, 'post' );
|
||||
$word_count = new WPML_TM_Count();
|
||||
|
||||
foreach ( $this->active_langs as $lang ) {
|
||||
if ( $this->post_element->get_language_code() === $lang ) {
|
||||
$word_count->set_total_words( $this->calculate_in_lang( null ) );
|
||||
} else {
|
||||
$word_count->set_words_to_translate( $lang, $this->calculate_in_lang( $lang ) );
|
||||
}
|
||||
}
|
||||
|
||||
$this->records->set_post_word_count( $post_id, $word_count );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $lang
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
private function calculate_in_lang( $lang ) {
|
||||
$words = 0;
|
||||
|
||||
foreach ( $this->post_calculators as $calculator ) {
|
||||
$words += $calculator->count_words( $this->post_element, $lang );
|
||||
}
|
||||
|
||||
return $words;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
class WPML_TM_Word_Count_Set_String {
|
||||
|
||||
/** @var WPML_TM_Word_Count_Records $records */
|
||||
private $records;
|
||||
|
||||
/** @var WPML_TM_Word_Calculator $calculator */
|
||||
private $calculator;
|
||||
|
||||
public function __construct( WPML_TM_Word_Count_Records $records, WPML_TM_Word_Calculator $calculator ) {
|
||||
$this->records = $records;
|
||||
$this->calculator = $calculator;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $string_id
|
||||
*/
|
||||
public function process( $string_id ) {
|
||||
$string = $this->records->get_string_value_and_language( $string_id );
|
||||
$word_count = $this->calculator->count_words( $string->value, $string->language );
|
||||
$this->records->set_string_word_count( $string_id, $word_count );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
class WPML_TM_Word_Count_Setters_Factory {
|
||||
|
||||
/**
|
||||
* @return IWPML_TM_Word_Count_Set[]
|
||||
*/
|
||||
public function create() {
|
||||
global $sitepress;
|
||||
|
||||
$records_factory = new WPML_TM_Word_Count_Records_Factory();
|
||||
$records = $records_factory->create();
|
||||
|
||||
$calculator = new WPML_TM_Word_Calculator( new WPML_PHP_Functions() );
|
||||
|
||||
$active_langs = array_keys( $sitepress->get_active_languages() );
|
||||
|
||||
$post_calculators = array(
|
||||
new WPML_TM_Word_Calculator_Post_Object( $calculator, new WPML_TM_Word_Calculator_Post_Packages( $records ) ),
|
||||
new WPML_TM_Word_Calculator_Post_Custom_Fields( $calculator, \WPML\TM\Settings\Repository::getCustomFields() ),
|
||||
);
|
||||
|
||||
$setters = array(
|
||||
'post' => new WPML_TM_Word_Count_Set_Post( new WPML_Translation_Element_Factory( $sitepress ), $records, $post_calculators, $active_langs ),
|
||||
);
|
||||
|
||||
if ( class_exists( 'WPML_ST_Package_Factory' ) ) {
|
||||
$setters['string'] = new WPML_TM_Word_Count_Set_String( $records, $calculator );
|
||||
$setters['package'] = new WPML_TM_Word_Count_Set_Package( new WPML_ST_Package_Factory(), $records, $active_langs );
|
||||
}
|
||||
|
||||
return $setters;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
class WPML_TM_Word_Count_Single_Process_Factory {
|
||||
|
||||
public function create() {
|
||||
/** @var wpdb $wpdb */
|
||||
global $wpdb;
|
||||
|
||||
$setters_factory = new WPML_TM_Word_Count_Setters_Factory();
|
||||
$dependencies_builder = null;
|
||||
|
||||
if ( class_exists( 'WPML_ST_String_Dependencies_Builder' ) ) {
|
||||
$dependencies_builder = new WPML_ST_String_Dependencies_Builder(
|
||||
new WPML_ST_String_Dependencies_Records( $wpdb )
|
||||
);
|
||||
}
|
||||
|
||||
return new WPML_TM_Word_Count_Single_Process( $setters_factory->create(), $dependencies_builder );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
class WPML_TM_Word_Count_Single_Process {
|
||||
|
||||
/** @var IWPML_TM_Word_Count_Set[] $setters */
|
||||
private $setters;
|
||||
|
||||
/** @var WPML_ST_String_Dependencies_Builder $dependencies_builder */
|
||||
private $dependencies_builder;
|
||||
|
||||
/**
|
||||
* @param IWPML_TM_Word_Count_Set[] $setters
|
||||
* @param WPML_ST_String_Dependencies_Builder $dependencies_builder
|
||||
*/
|
||||
public function __construct( array $setters, WPML_ST_String_Dependencies_Builder $dependencies_builder = null ) {
|
||||
$this->setters = $setters;
|
||||
$this->dependencies_builder = $dependencies_builder;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $element_type
|
||||
* @param int $element_id
|
||||
*/
|
||||
public function process( $element_type, $element_id ) {
|
||||
if ( $this->dependencies_builder ) {
|
||||
$dependencies_tree = $this->dependencies_builder->from( $element_type, $element_id );
|
||||
|
||||
while ( ! $dependencies_tree->iteration_completed() ) {
|
||||
$node = $dependencies_tree->get_next();
|
||||
$this->setters[ $node->get_type() ]->process( $node->get_id() );
|
||||
$node->detach();
|
||||
}
|
||||
} elseif ( 'post' === $element_type ) {
|
||||
$this->setters['post']->process( $element_id );
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user