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,18 @@
<?php
class WPML_TM_Jobs_Daily_Summary_Report_Model implements WPML_TM_Jobs_Summary_Report_Model {
/**
* @return string
*/
public function get_subject() {
return __( 'Translation updates for %1$s for %2$s', 'wpml-translation-management' );
}
/**
* @return string
*/
public function get_summary_text() {
return __( 'Today %1$s had the following %2$s translation updates', 'wpml-translation-management' );
}
}

View File

@@ -0,0 +1,81 @@
<?php
class WPML_TM_Jobs_Summary_Report_Process_Factory {
/** @var WPML_TM_Jobs_Summary_Report_View $template */
private $template;
/** @var WPML_TM_Jobs_Summary_Report_Process $weekly_report */
private $weekly_report;
/** @var WPML_TM_Jobs_Summary_Report_Process $daily_report */
private $daily_report;
/**
* @return WPML_TM_Jobs_Summary_Report_Process
*/
public function create_weekly_report() {
if ( ! $this->weekly_report ) {
$summary_report = $this->get_summary_report( WPML_TM_Jobs_Summary::WEEKLY_REPORT );
$this->weekly_report = new WPML_TM_Jobs_Summary_Report_Process(
$this->get_template(),
new WPML_TM_Jobs_Weekly_Summary_Report_Model(),
$summary_report->get_jobs()
);
}
return $this->weekly_report;
}
/**
* @return WPML_TM_Jobs_Summary_Report_Process
*/
public function create_daily_report() {
if ( ! $this->daily_report ) {
$summary_report = $this->get_summary_report( WPML_TM_Jobs_Summary::DAILY_REPORT );
$this->daily_report = new WPML_TM_Jobs_Summary_Report_Process(
$this->get_template(),
new WPML_TM_Jobs_Daily_Summary_Report_Model(),
$summary_report->get_jobs()
);
}
return $this->daily_report;
}
/**
* @param string $frequency
*
* @return WPML_TM_Jobs_Summary_Report
*/
private function get_summary_report( $frequency ) {
global $sitepress, $wpdb;
$word_count_records_factory = new WPML_TM_Word_Count_Records_Factory();
$word_count_records = $word_count_records_factory->create();
$single_process_factory = new WPML_TM_Word_Count_Single_Process_Factory();
$single_process = $single_process_factory->create();
return new WPML_TM_Jobs_Summary_Report(
new WPML_Translation_Jobs_Collection( $wpdb, array() ),
new WPML_TM_String( false, $word_count_records, $single_process ),
new WPML_TM_Post( false, $word_count_records, $single_process ),
$frequency,
new WPML_Translation_Element_Factory( $sitepress )
);
}
/**
* @return WPML_TM_Jobs_Summary_Report_View
*/
private function get_template() {
if ( ! $this->template ) {
$template_service_factory = new WPML_TM_Email_Twig_Template_Factory();
$this->template = new WPML_TM_Jobs_Summary_Report_View( $template_service_factory->create() );
}
return $this->template;
}
}

View File

@@ -0,0 +1,57 @@
<?php
class WPML_TM_Jobs_Summary_Report_Process {
/**
* @var WPML_TM_Jobs_Summary_Report_View
*/
private $view;
/**
* @var WPML_TM_Jobs_Summary_Report_Model
*/
private $report_model;
/**
* @var array
*/
private $jobs;
public function __construct(
WPML_TM_Jobs_Summary_Report_View $view,
WPML_TM_Jobs_Summary_Report_Model $report_model,
array $jobs
) {
$this->view = $view;
$this->report_model = $report_model;
$this->jobs = $jobs;
}
public function send() {
foreach ( $this->jobs as $manager_id => $jobs ) {
if ( array_key_exists( WPML_TM_Jobs_Summary::JOBS_COMPLETED_KEY, $jobs ) ) {
$this->view
->set_jobs( $jobs )
->set_manager_id( $manager_id )
->set_summary_text( $this->report_model->get_summary_text() );
$this->send_email( $manager_id );
}
}
}
/**
* @param int $manager_id
*/
private function send_email( $manager_id ) {
wp_mail(
get_userdata( $manager_id )->user_email,
sprintf( $this->report_model->get_subject(), get_bloginfo( 'name' ), date( 'd/F/Y', time() ) ),
$this->view->get_report_content(),
array(
'MIME-Version: 1.0',
'Content-type: text/html; charset=UTF-8',
)
);
}
}

View File

@@ -0,0 +1,108 @@
<?php
class WPML_TM_Jobs_Summary_Report_View extends WPML_TM_Email_View {
const WEEKLY_SUMMARY_TEMPLATE = 'notification/summary/summary.twig';
/**
* @var array
*/
private $jobs;
/**
* @var int
*/
private $manager_id;
/**
* @var string
*/
private $summary_text;
/**
* @return string
*/
public function get_report_content() {
$model = $this->get_model();
$content = $this->render_header( $model['username'] );
$content .= $this->template_service->show( $model, self::WEEKLY_SUMMARY_TEMPLATE );
$content .= $this->render_email_footer();
return $content;
}
/**
* @return array
*/
private function get_model() {
return array(
'username' => get_userdata( $this->manager_id )->display_name,
'jobs' => $this->jobs,
'text' => $this->summary_text,
'site_name' => get_bloginfo( 'name' ),
'number_of_updates' => isset( $this->jobs['completed'] ) ? count( $this->jobs['completed'] ) : 0,
'strings' => array(
'jobs_waiting' => __( 'Jobs that are waiting for translation', 'wpml-translation-management' ),
'original_page' => __( 'Original Page', 'wpml-translation-management' ),
'translation' => __( 'Translation', 'wpml-translation-management' ),
'translator' => __( 'Translator', 'wpml-translation-management' ),
'updated' => __( 'Updated / Translated', 'wpml-translation-management' ),
'date' => __( 'Date', 'wpml-translation-management' ),
'your_deadline' => __( 'Your deadline', 'wpml-translation-management' ),
'translation_languages' => __( 'Translation languages', 'wpml-translation-management' ),
'number_of_pages' => __( 'Number of pages', 'wpml-translation-management' ),
'number_of_strings' => __( 'Number of strings', 'wpml-translation-management' ),
'number_of_words' => __( 'Number of words', 'wpml-translation-management' ),
'undefined' => __( 'Undefined', 'wpml-translation-management' ),
),
'improve_quality' => array(
'title' => __( 'Want to improve the quality of your sites translation?', 'wpml-translation-management' ),
'options' => array(
array(
'link_url' => admin_url( 'admin.php?page=' . WPML_PLUGIN_FOLDER . '/menu/languages.php#wpml-translation-feedback-options' ),
'link_text' => __( 'Translation Feedback', 'wpml-translation-management' ),
'text' => __( 'Allow visitors to tell you about translation issues by enabling %s', 'wpml-translation-management' ),
),
array(
'link_url' => admin_url( 'admin.php?page=' . WPML_TM_FOLDER . '/menu/main.php&sm=translators' ),
'link_text' => __( 'translation services that are integrated with WPML', 'wpml-translation-management' ),
'text' => __( 'Try one of the %s', 'wpml-translation-management' ),
),
)
),
);
}
/**
* @param array $jobs
*
* @return $this
*/
public function set_jobs( $jobs ) {
$this->jobs = $jobs;
return $this;
}
/**
* @param int $manager_id
*
* @return $this
*/
public function set_manager_id( $manager_id ) {
$this->manager_id = $manager_id;
return $this;
}
/**
* @param string $summary_text
*
* @return $this
*/
public function set_summary_text( $summary_text ) {
$this->summary_text = $summary_text;
return $this;
}
}

View File

@@ -0,0 +1,158 @@
<?php
class WPML_TM_Jobs_Summary_Report {
/**
* @var WPML_Translation_Jobs_Collection
*/
private $jobs_collection;
/**
* @var array
*/
private $jobs = array();
/**
* @var WPML_TM_String
*/
private $string_counter;
/**
* @var WPML_TM_Post
*/
private $post_counter;
/**
* @var string
*/
private $type;
/**
* @var WPML_Translation_Element_Factory
*/
private $element_factory;
public function __construct(
WPML_Translation_Jobs_Collection $jobs_collection,
WPML_TM_String $string_counter,
WPML_TM_Post $post_counter,
$type,
WPML_Translation_Element_Factory $element_factory
) {
$this->jobs_collection = $jobs_collection;
$this->string_counter = $string_counter;
$this->post_counter = $post_counter;
$this->type = $type;
$this->element_factory = $element_factory;
$this->build_completed_jobs();
$this->build_waiting_jobs();
}
private function build_completed_jobs() {
$jobs = $this->jobs_collection->get_jobs( array(
'any_translation_service' => true,
'status' => ICL_TM_COMPLETE
)
);
foreach ( $jobs as $job ) {
$completed_date = $job instanceof WPML_Post_Translation_Job || $job instanceof WPML_Element_Translation_Job ? $job->get_completed_date() : '';
$out_of_period = strtotime( $completed_date ) < strtotime( '-' . WPML_TM_Jobs_Summary::WEEKLY_SCHEDULE );
if ( WPML_TM_Jobs_Summary::DAILY_REPORT === $this->type ) {
$out_of_period = strtotime( $completed_date ) < strtotime( '-' . WPML_TM_Jobs_Summary::DAILY_SCHEDULE );
}
if ( ! $completed_date || $out_of_period ) {
continue;
}
$original_element = $this->element_factory->create( $job->get_original_element_id(), $job->get_type() );
$translation_element = $original_element->get_translation( $job->get_language_code() );
$this->jobs[ $job->get_basic_data()->manager_id ][ WPML_TM_Jobs_Summary::JOBS_COMPLETED_KEY ][] = array(
'completed_date' => date_i18n( get_option( 'date_format', 'F d, Y' ), strtotime( $job->get_completed_date() ) ),
'original_page' => array(
'title' => $job->get_title(),
'url' => $job->get_url( true ),
),
'translated_page' => array(
'title' => get_the_title( $translation_element->get_element_id() ) . ' (' . $job->get_language_code() . ')',
'url' => get_the_permalink( $translation_element->get_element_id() ),
),
'translator' => $this->get_translator_name( $job ),
'deadline' => $job->get_deadline_date() ?
date_i18n( get_option( 'date_format', 'F d, Y' ), strtotime( $job->get_deadline_date() ) ) :
'',
'status' => $job->get_status(),
'overdue' => $job->get_deadline_date() &&
strtotime( $job->get_deadline_date() ) < strtotime( $job->get_completed_date() )
);
}
}
private function build_waiting_jobs() {
$jobs = $this->jobs_collection->get_jobs( array(
'any_translation_service' => true,
'status' => ICL_TM_WAITING_FOR_TRANSLATOR
)
);
$counters = array();
$number_of_strings = 0;
$number_of_words_in_strings = 0;
foreach ( $jobs as $job ) {
$manager_id = isset( $job->get_basic_data()->manager_id ) ? $job->get_basic_data()->manager_id : 0;
$lang_pair = $job->get_source_language_code() . '|' . $job->get_language_code();
if ( ! isset( $counters[ $manager_id ][ $lang_pair ]['number_of_strings'], $counters[ $manager_id ][ $lang_pair ]['number_of_words'], $counters[ $manager_id ][ $lang_pair ]['number_of_pages'] ) ) {
$counters[ $manager_id ][ $lang_pair ]['number_of_strings'] = 0;
$counters[ $manager_id ][ $lang_pair ]['number_of_words'] = 0;
$counters[ $manager_id ][ $lang_pair ]['number_of_pages'] = 0;
}
if ( 'String' === $job->get_type() ) {
$this->string_counter->set_id( $job->get_original_element_id() );
$number_of_strings ++;
$number_of_words_in_strings += $this->string_counter->get_words_count();
} else {
$this->post_counter->set_id( $job->get_original_element_id() );
$counters[ $manager_id ][ $lang_pair ]['number_of_pages'] += 1;
$counters[ $manager_id ][ $lang_pair ]['number_of_words'] += $this->post_counter->get_words_count();
$this->jobs[ $manager_id ][ WPML_TM_Jobs_Summary::JOBS_WAITING_KEY ][ $lang_pair ] = array(
'lang_pair' => $job->get_source_language_code( true ) . ' ' . __( 'to', 'wpml-translation-management' ) . ' ' . $job->get_language_code( true ),
'number_of_strings' => $number_of_strings,
'number_of_words' => $counters[ $manager_id ][ $lang_pair ]['number_of_words'] + $number_of_words_in_strings,
'number_of_pages' => $counters[ $manager_id ][ $lang_pair ]['number_of_pages'],
);
}
}
}
/**
* @param WPML_Element_Translation_Job $job
*
* @return string
*/
private function get_translator_name( WPML_Element_Translation_Job $job ) {
$translator_name = $job->get_translation_service() ?
TranslationProxy::get_service_name( $job->get_translation_service() ) :
$job->get_translator_name();
if ( 'local' === $job->get_translation_service() ) {
$user = get_userdata( $job->get_translator_id() );
$translator_name = $user->display_name . ' (' . $user->user_login . ')';
}
return $translator_name;
}
/**
* @return array
*/
public function get_jobs() {
return $this->jobs;
}
}

View File

@@ -0,0 +1,11 @@
<?php
class WPML_TM_Jobs_Summary {
const WEEKLY_REPORT = 'weekly';
const DAILY_REPORT = 'daily';
const DAILY_SCHEDULE = '1 day';
const WEEKLY_SCHEDULE = '1 week';
const JOBS_COMPLETED_KEY = 'completed';
const JOBS_WAITING_KEY = 'waiting';
}

View File

@@ -0,0 +1,18 @@
<?php
class WPML_TM_Jobs_Weekly_Summary_Report_Model implements WPML_TM_Jobs_Summary_Report_Model {
/**
* @return string
*/
public function get_subject() {
return __( 'Translation updates for %1$s until %2$s', 'wpml-translation-management' );
}
/**
* @return string
*/
public function get_summary_text() {
return __( 'This week %1$s had the following %2$s translation updates', 'wpml-translation-management' );
}
}

View File

@@ -0,0 +1,14 @@
<?php
interface WPML_TM_Jobs_Summary_Report_Model {
/**
* @return string
*/
public function get_subject();
/**
* @return string
*/
public function get_summary_text();
}

View File

@@ -0,0 +1,16 @@
<?php
class WPML_TM_Jobs_Summary_Report_Hooks_Factory implements IWPML_Frontend_Action_Loader, IWPML_Backend_Action_Loader {
/**
* @return WPML_TM_Jobs_Summary_Report_Hooks
*/
public function create() {
global $iclTranslationManagement;
return new WPML_TM_Jobs_Summary_Report_Hooks(
new WPML_TM_Jobs_Summary_Report_Process_Factory(),
$iclTranslationManagement
);
}
}

View File

@@ -0,0 +1,78 @@
<?php
class WPML_TM_Jobs_Summary_Report_Hooks {
const EVENT_HOOK = 'wpml_tm_send_summary_report';
const EVENT_CALLBACK = 'send_summary_report';
/**
* @var WPML_TM_Jobs_Summary_Report_Process_Factory
*/
private $process_factory;
/**
* @var TranslationManagement
*/
private $tm;
public function __construct( WPML_TM_Jobs_Summary_Report_Process_Factory $process_factory, TranslationManagement $tm ) {
$this->process_factory = $process_factory;
$this->tm = $tm;
}
public function add_hooks() {
if ( $this->notification_setting_allow_scheduling() ) {
add_action( self::EVENT_HOOK, array( $this, self::EVENT_CALLBACK ) );
add_action( 'init', array( $this, 'schedule_email' ) );
}
}
/**
* @return bool
*/
private function notification_setting_allow_scheduling() {
$schedulable_settings = array(
WPML_TM_Emails_Settings::NOTIFY_DAILY,
WPML_TM_Emails_Settings::NOTIFY_WEEKLY
);
return isset( $this->tm->settings['notification'][ WPML_TM_Emails_Settings::COMPLETED_JOB_FREQUENCY ] ) &&
in_array(
(int) $this->tm->settings['notification'][ WPML_TM_Emails_Settings::COMPLETED_JOB_FREQUENCY ],
$schedulable_settings,
true
);
}
public function send_summary_report() {
if ( WPML_TM_Emails_Settings::NOTIFY_DAILY === (int) $this->tm->settings['notification'][ WPML_TM_Emails_Settings::COMPLETED_JOB_FREQUENCY ] ) {
$summary_report_process = $this->process_factory->create_daily_report();
} else {
$summary_report_process = $this->process_factory->create_weekly_report();
}
if ( $summary_report_process ) {
$summary_report_process->send();
}
}
public function schedule_email() {
if ( ! wp_next_scheduled( self::EVENT_HOOK ) ) {
wp_schedule_single_event( $this->get_schedule_time(), self::EVENT_HOOK );
}
}
/**
* @return int
*/
private function get_schedule_time() {
$schedule_time = strtotime( '+ ' . WPML_TM_Jobs_Summary::DAILY_SCHEDULE );
if ( WPML_TM_Emails_Settings::NOTIFY_WEEKLY === (int) $this->tm->settings['notification'][ WPML_TM_Emails_Settings::COMPLETED_JOB_FREQUENCY ] ) {
$schedule_time = strtotime( '+ ' . WPML_TM_Jobs_Summary::WEEKLY_SCHEDULE );
}
return $schedule_time;
}
}