Файловый менеджер - Редактировать - /var/www/xthruster/html/wp-content/uploads/flags/translation-proxy.tar
Назад
ui/wpml-tp-extra-field-display.php 0000644 00000004212 14721654666 0013157 0 ustar 00 <?php /** * @author OnTheGo Systems */ class WPML_TP_Extra_Field_Display { private $fields_with_items = array( 'select', 'radio', 'checkbox' ); /** * WPML_TP_Extra_Field_Display constructor. */ public function __construct() { } public function render( $field ) { if ( $this->must_render( $field ) ) { $field_id = 'wpml-tp-extra-field-' . $field->name; $row = '<tr>'; $row .= '<th scope="row">'; $row .= '<label for="' . esc_attr( $field_id ) . '">' . esc_html( $field->label ) . '</label>'; $row .= '</th>'; $row .= '<td>'; switch ( $field->type ) { case 'select': $row .= '<select id="' . esc_attr( $field_id ) . '" name="' . esc_attr( $field->name ) . '">'; foreach ( $field->items as $id => $name ) { $row .= '<option value="' . esc_attr( $id ) . '">' . esc_html( $name ) . '</option>'; } $row .= '</select>'; break; case 'textarea': $row .= '<textarea id="' . esc_attr( $field_id ) . '" name="' . esc_attr( $field->name ) . '"></textarea>'; break; case 'radio': case 'checkbox': $row .= '<ol>'; foreach ( $field->items as $id => $name ) { $row .= '<li>'; $row .= '<input id="' . esc_attr( $field_id . '-' . $id ) . '" type="' . esc_attr( $field->type ) . '" name="' . esc_attr( $field->name ) . '" value="' . esc_attr( $id ) . '"> '; $row .= '<label for="' . esc_attr( $field_id . '-' . $id ) . '">' . esc_html( $name ) . '</label>'; $row .= '</li>'; } $row .= '</ol>'; break; case 'text': default: $type = null !== $field->type ? $field->type : 'text'; $row .= '<input id="' . esc_attr( $field_id ) . '" type="' . esc_attr( $type ) . '" name="' . esc_attr( $field->name ) . '">'; break; } $row .= '</td>'; $row .= '</tr>'; return $row; } return ''; } /** * @param $field * * @return bool */ private function must_render( $field ) { $must_render = isset( $field->type ) && $field->type; if ( $must_render && in_array( $field->type, $this->fields_with_items, true ) ) { $must_render = isset( $field->items ) && $field->items; } return $must_render; } } class-wpml-tp-translator.php 0000644 00000000465 14721654666 0012175 0 ustar 00 <?php /** * Class WPML_TP_Translator */ class WPML_TP_Translator { /** * Return translator status array. * * @param bool $force * * @return array */ public function get_icl_translator_status( $force = false ) { return TranslationProxy_Translator::get_icl_translator_status( $force ); } } class-wpml-tm-cms-id.php 0000644 00000012420 14721654666 0011147 0 ustar 00 <?php /** * Class WPML_TM_CMS_ID */ class WPML_TM_CMS_ID extends WPML_TM_Record_User { private $cms_id_parts_glue = '_'; private $cms_id_parts_fallback_glue = '|||'; /** @var WPML_Translation_Job_Factory $tm_job_factory */ private $job_factory; /** @var wpdb $wpdb */ private $wpdb; /** * WPML_TM_CMS_ID constructor. * * @param WPML_TM_Records $tm_records * @param WPML_Translation_Job_Factory $job_factory */ public function __construct( &$tm_records, &$job_factory ) { parent::__construct( $tm_records ); $this->job_factory = &$job_factory; $this->wpdb = $this->tm_records->wpdb(); } /** * @param int $post_id * @param string $post_type * @param string $source_language * @param string $target_language * * @return string */ public function build_cms_id( $post_id, $post_type, $source_language, $target_language ) { $cms_id_parts = array( $post_type, $post_id, $source_language, $target_language ); return implode( $this->cms_id_parts_glue, $cms_id_parts ); } /** * Returns the cms_id for a given job * * @param int $job_id * * @return false|string */ function cms_id_from_job_id( $job_id ) { $original_element_row = $this->wpdb->get_row( $this->wpdb->prepare( "SELECT o.element_id, o.element_type, o.language_code as source_lang, i.language_code as target_lang FROM {$this->wpdb->prefix}icl_translations o JOIN {$this->wpdb->prefix}icl_translations i ON i.trid = o.trid AND i.source_language_code = o.language_code JOIN {$this->wpdb->prefix}icl_translation_status s ON s.translation_id = i.translation_id JOIN {$this->wpdb->prefix}icl_translate_job j ON j.rid = s.rid WHERE j.job_id = %d LIMIT 1", $job_id ) ); $type_parts = (bool) $original_element_row === true ? explode( '_', $original_element_row->element_type, 2 ) : false; return is_array( $type_parts ) && count( $type_parts ) === 2 ? $this->build_cms_id( $original_element_row->element_id, end( $type_parts ), $original_element_row->source_lang, $original_element_row->target_lang ) : false; } /** * @param string $cms_id * * @return array; */ public function parse_cms_id( $cms_id ) { if ( $this->is_standard_format( $cms_id ) ) { $parts = array_filter( explode( $this->cms_id_parts_glue, $cms_id ) ); while ( count( $parts ) > 4 ) { $parts_copy = $parts; $parts[0] = $parts_copy[0] . $this->cms_id_parts_glue . $parts_copy[1]; unset( $parts_copy[0] ); unset( $parts_copy[1] ); $parts = array_merge( array( $parts[0] ), array_values( array_filter( $parts_copy ) ) ); } } else { $parts = explode( $this->cms_id_parts_fallback_glue, $cms_id ); } return array_pad( array_slice( $parts, 0, 4 ), 4, false ); } /** * @param string $cms_id * @param bool|TranslationProxy_Service $translation_service * * @return int|null translation id for the given cms_id's target */ public function get_translation_id( $cms_id, $translation_service = false ) { list( $post_type, $element_id, , $target_lang ) = $this->parse_cms_id( $cms_id ); $translation = $this->wpdb->get_row( $this->wpdb->prepare( " SELECT t.translation_id, j.job_id, t.element_id FROM {$this->wpdb->prefix}icl_translations t JOIN {$this->wpdb->prefix}icl_translations o ON o.trid = t.trid AND o.element_type = t.element_type LEFT JOIN {$this->wpdb->prefix}icl_translation_status st ON st.translation_id = t.translation_id LEFT JOIN {$this->wpdb->prefix}icl_translate_job j ON j.rid = st.rid WHERE o.element_id=%d AND t.language_code=%s AND o.element_type LIKE %s LIMIT 1", $element_id, $target_lang, '%_' . $post_type ) ); $translation_id = $this->maybe_cleanup_broken_row( $translation, $translation_service ); if ( $translation_service && ! isset( $translation_id ) && $translation_service ) { $job_id = $this->job_factory->create_local_post_job( $element_id, $target_lang ); $job = $this->job_factory->get_translation_job( $job_id, false, false, true ); $translation_id = $job ? $job->get_translation_id() : 0; if ( $translation_id ) { $this->tm_records->icl_translation_status_by_translation_id( $translation_id )->update( array( 'status' => ICL_TM_IN_PROGRESS, 'translation_service' => $translation_service->id, ) ); } } return $translation_id; } private function maybe_cleanup_broken_row( $translation, $translation_service ) { if ( $translation && ( $translation_id = $translation->translation_id ) && ! $translation->element_id && $translation_service && ! $translation->job_id ) { $this->tm_records->icl_translations_by_translation_id( $translation_id )->delete(); $translation_id = null; } return isset( $translation_id ) ? $translation_id : null; } /** * @param $cms_id * * @return bool */ private function is_standard_format( $cms_id ) { return count( array_filter( explode( $this->cms_id_parts_fallback_glue, $cms_id ) ) ) < 3; } } class-wpml-tp-string-job.php 0000644 00000007324 14721654666 0012063 0 ustar 00 <?php class WPML_TP_String_Job extends WPML_WPDB_User { /** @var WPML_Translation_Basket $basket */ private $basket; /** @var WPML_Translation_Job_Factory $job_factory */ private $job_factory; /** * WPML_TP_String_Job constructor. * * @param wpdb $wpdb * @param WPML_Translation_Basket $basket * @param WPML_Translation_Job_Factory $job_factory */ public function __construct( &$wpdb, &$basket, &$job_factory ) { parent::__construct( $wpdb ); $this->basket = &$basket; $this->job_factory = &$job_factory; } function send_strings_to_translation_service( $string_ids, $target_language, $translator_id ) { /** @var WPML_String_Translation $WPML_String_Translation */ global $WPML_String_Translation; if ( sizeof( $string_ids ) > 0 ) { $project = $this->basket->get_project(); $strings = array(); $word_count = 0; $source_language = $this->basket->get_source_language(); foreach ( $string_ids as $string_id ) { $string_data_query = "SELECT id, context, name, value FROM {$this->wpdb->prefix}icl_strings WHERE id=%d"; $string_data_prepare = $this->wpdb->prepare( $string_data_query, $string_id ); $string_data = $this->wpdb->get_row( $string_data_prepare ); $word_count += $WPML_String_Translation->estimate_word_count( $string_data->value, $source_language ); $strings[] = $string_data; } $xliff = new WPML_TM_Xliff_Writer( $this->job_factory ); try { $tp_job_id = $project->send_to_translation_batch_mode( $xliff->get_strings_xliff_file( $strings, $source_language, $target_language ), 'String Translations', '', '', $source_language, $target_language, $word_count ); } catch ( Exception $e ) { return [ 'errors' => [ $e->getMessage() ] ]; } if ( $tp_job_id ) { foreach ( $strings as $string_data ) { $translation_service = TranslationProxy_Service::get_translator_data_from_wpml( $translator_id ); $string_translation_id = icl_add_string_translation( $string_data->id, $target_language, null, ICL_TM_IN_PROGRESS, $translation_service['translator_id'], $translation_service['translation_service'], TranslationProxy_Batch::update_translation_batch( $this->basket->get_name() ) ); if ( $string_translation_id ) { $data = array( 'rid' => $tp_job_id, 'string_translation_id' => $string_translation_id, 'timestamp' => date( 'Y-m-d H:i:s' ), 'md5' => md5( $string_data->value ), ); $current_rid = $this->wpdb->get_var( $this->wpdb->prepare( "SELECT rid FROM {$this->wpdb->prefix}icl_string_status WHERE string_translation_id=%d", $string_translation_id ) ); if ( $current_rid ) { $this->wpdb->update( $this->wpdb->prefix . 'icl_string_status', $data, array( 'rid' => $current_rid ) ); } else { $this->wpdb->insert( $this->wpdb->prefix . 'icl_string_status', $data ); // insert rid } } } $data = array( 'rid' => $tp_job_id, 'module' => '', 'origin' => $source_language, 'target' => $target_language, 'status' => ICL_TM_IN_PROGRESS, ); if ( ! empty( $current_rid ) ) { $data['ts_status'] = null; $this->wpdb->update( $this->wpdb->prefix . 'icl_core_status', $data, array( 'rid' => $current_rid ) ); } else { $this->wpdb->insert( $this->wpdb->prefix . 'icl_core_status', $data ); } if ( $project->errors && count( $project->errors ) ) { $tp_job_id['errors'] = $project->errors; } return $tp_job_id; } } return 0; } } class-wpml-tp-refresh-language-pairs.php 0000644 00000002420 14721654666 0014330 0 ustar 00 <?php class WPML_TP_Refresh_Language_Pairs { const AJAX_ACTION = 'wpml-tp-refresh-language-pairs'; /** * @var WPML_TP_Project_API */ private $tp_api; /** * WPML_TP_AJAX constructor. * * @param WPML_TP_Project_API $wpml_tp_api */ public function __construct( WPML_TP_Project_API $wpml_tp_api ) { $this->tp_api = $wpml_tp_api; } public function add_hooks() { add_action( 'wp_ajax_' . self::AJAX_ACTION, array( $this, 'refresh_language_pairs' ) ); } public function refresh_language_pairs() { if ( $this->is_valid_request() ) { try { $this->tp_api->refresh_language_pairs(); wp_send_json_success( array( 'msg' => __( 'Language pairs refreshed', 'wpml-translation-management' ), ) ); } catch ( Exception $e ) { wp_send_json_error( array( 'msg' => __( 'Language pairs not refreshed, please try again', 'wpml-translation-management' ), ) ); } } else { wp_send_json_error( array( 'msg' => __( 'Invalid Request', 'wpml-translation-management' ), ) ); } } /** * @return bool */ private function is_valid_request() { return array_key_exists( 'nonce', $_POST ) && wp_verify_nonce( filter_var( $_POST['nonce'], FILTER_SANITIZE_FULL_SPECIAL_CHARS ), self::AJAX_ACTION ); } } translations/apply/class-wpml-tp-apply-translation-strategy.php 0000644 00000000437 14721654666 0021172 0 ustar 00 <?php interface WPML_TP_Apply_Translation_Strategy { /** * @param WPML_TM_Job_Entity $job * @param WPML_TP_Translation_Collection $translations * * @return void */ public function apply( WPML_TM_Job_Entity $job, WPML_TP_Translation_Collection $translations ); } translations/apply/class-wpml-tp-apply-translation-post-strategy.php 0000644 00000003413 14721654666 0022152 0 ustar 00 <?php class WPML_TP_Apply_Translation_Post_Strategy implements WPML_TP_Apply_Translation_Strategy { /** @var WPML_TP_Jobs_API */ private $jobs_api; /** @var wpdb */ private $wpdb; /** * @param WPML_TP_Jobs_API $jobs_api */ public function __construct( WPML_TP_Jobs_API $jobs_api ) { $this->jobs_api = $jobs_api; global $wpdb; $this->wpdb = $wpdb; } /** * @param WPML_TM_Job_Entity $job * @param WPML_TP_Translation_Collection $translations * * @return void * @throws WPML_TP_API_Exception */ public function apply( WPML_TM_Job_Entity $job, WPML_TP_Translation_Collection $translations ) { if ( ! $job instanceof WPML_TM_Post_Job_Entity ) { throw new InvalidArgumentException( 'A job must have post type' ); } kses_remove_filters(); wpml_tm_save_data( $this->build_data( $job, $translations ) ); kses_init(); $this->jobs_api->update_job_state( $job, 'delivered' ); } /** * @param WPML_TM_Job_Entity $job * @param WPML_TP_Translation_Collection $translations * * @return array */ private function build_data( WPML_TM_Post_Job_Entity $job, WPML_TP_Translation_Collection $translations ) { $data = array( 'job_id' => $job->get_translate_job_id(), 'fields' => array(), 'complete' => 1 ); /** @var WPML_TP_Translation $translation */ foreach ( $translations as $translation ) { foreach ( $job->get_elements() as $element ) { if ( $element->get_type() === $translation->get_field() ) { $data['fields'][ $element->get_type() ] = array( 'data' => $translation->get_target(), 'finished' => 1, 'tid' => $element->get_id(), 'field_type' => $element->get_type(), 'format' => $element->get_format() ); } } } return $data; } } translations/apply/class-wpml-tp-apply-single-job.php 0000644 00000002002 14721654666 0017013 0 ustar 00 <?php class WPML_TP_Apply_Single_Job { /** @var WPML_TP_Translations_Repository */ private $translations_repository; /** @var WPML_TP_Apply_Translation_Strategies */ private $strategy_dispatcher; /** * @param WPML_TP_Translations_Repository $translations_repository * @param WPML_TP_Apply_Translation_Strategies $strategy_dispatcher */ public function __construct( WPML_TP_Translations_Repository $translations_repository, WPML_TP_Apply_Translation_Strategies $strategy_dispatcher ) { $this->translations_repository = $translations_repository; $this->strategy_dispatcher = $strategy_dispatcher; } /** * @param WPML_TM_Job_Entity $job * * @return WPML_TM_Job_Entity * @throws WPML_TP_API_Exception */ public function apply( WPML_TM_Job_Entity $job ) { $translations = $this->translations_repository->get_job_translations_by_job_entity( $job ); $this->strategy_dispatcher->get( $job )->apply( $job, $translations ); $job->set_status( ICL_TM_COMPLETE ); return $job; } } translations/apply/class-wpml-tp-apply-translation-strategies.php 0000644 00000002711 14721654666 0021477 0 ustar 00 <?php class WPML_TP_Apply_Translation_Strategies { /** @var WPML_TP_Apply_Translation_Post_Strategy */ private $post_strategy; /** @var WPML_TP_Apply_Translation_String_Strategy */ private $string_strategy; /** @var wpdb */ private $wpdb; /** * @param wpdb $wpdb */ public function __construct( wpdb $wpdb ) { $this->wpdb = $wpdb; } /** * @param WPML_TM_Job_Entity $job * * @return WPML_TP_Apply_Translation_Strategy */ public function get( WPML_TM_Job_Entity $job ) { switch ( $job->get_type() ) { case WPML_TM_Job_Entity::STRING_TYPE: return $this->get_string_strategy(); case WPML_TM_Job_Entity::POST_TYPE: case WPML_TM_Job_Entity::PACKAGE_TYPE: case WPML_TM_Job_Entity::STRING_BATCH: return $this->get_post_strategy(); default: throw new InvalidArgumentException( 'Job type: ' . $job->get_type() . ' is not supported' ); } } /** * @return WPML_TP_Apply_Translation_Post_Strategy */ private function get_post_strategy() { if ( ! $this->post_strategy ) { $this->post_strategy = new WPML_TP_Apply_Translation_Post_Strategy( wpml_tm_get_tp_jobs_api() ); } return $this->post_strategy; } /** * @return WPML_TP_Apply_Translation_String_Strategy */ private function get_string_strategy() { if ( ! $this->string_strategy ) { $this->string_strategy = new WPML_TP_Apply_Translation_String_Strategy( wpml_tm_get_tp_jobs_api(), $this->wpdb ); } return $this->string_strategy; } } translations/apply/class-wpml-tp-apply-translation-string-strategy.php 0000644 00000003216 14721654666 0022474 0 ustar 00 <?php class WPML_TP_Apply_Translation_String_Strategy implements WPML_TP_Apply_Translation_Strategy { /** @var WPML_TP_Jobs_API */ private $jobs_api; /** @var wpdb */ private $wpdb; /** * @param WPML_TP_Jobs_API $jobs_api * @param wpdb $wpdb */ public function __construct( WPML_TP_Jobs_API $jobs_api, wpdb $wpdb ) { $this->jobs_api = $jobs_api; $this->wpdb = $wpdb; } /** * @param WPML_TM_Job_Entity $job * @param WPML_TP_Translation_Collection $translations * * @return void * @throws WPML_TP_API_Exception */ public function apply( WPML_TM_Job_Entity $job, WPML_TP_Translation_Collection $translations ) { if ( ! icl_translation_add_string_translation( $job->get_tp_id(), $this->map_translations_to_legacy_array( $translations ), $translations->get_target_language() ) ) { throw new WPML_TP_API_Exception( 'Could not apply string translation!' ); } $this->update_local_job_status( $job, ICL_TM_COMPLETE ); $this->jobs_api->update_job_state( $job, 'delivered' ); } /** * @param WPML_TM_Job_Entity $job * @param int $status */ private function update_local_job_status( WPML_TM_Job_Entity $job, $status ) { $this->wpdb->update( $this->wpdb->prefix . 'icl_core_status', array( 'status' => $status ), array( 'id' => $job->get_id() ) ); } private function map_translations_to_legacy_array( WPML_TP_Translation_Collection $translations ) { $result = array(); /** @var WPML_TP_Translation $translation */ foreach ( $translations as $translation ) { $result[ $translation->get_field() ] = $translation->get_target(); } return $result; } } translations/class-wpml-tp-translation.php 0000644 00000001314 14721654666 0015055 0 ustar 00 <?php class WPML_TP_Translation { /** @var string */ private $field; /** @var string */ private $source; /** @var string */ private $target; /** * @param string $field * @param string $source * @param string $target */ public function __construct( $field, $source, $target ) { $this->field = $field; $this->source = $source; $this->target = $target; } /** * @return string */ public function get_field() { return $this->field; } /** * @return string */ public function get_source() { return $this->source; } /** * @return string */ public function get_target() { return $this->target; } public function to_array() { return get_object_vars( $this ); } } translations/class-wpml-tp-apply-translation.php 0000644 00000007000 14721654666 0016176 0 ustar 00 <?php class WPML_TP_Apply_Translations { /** @var WPML_TM_Jobs_Repository */ private $jobs_repository; /** @var WPML_TP_Apply_Single_Job */ private $apply_single_job; /** @var WPML_TP_Sync_Jobs */ private $tp_sync; /** * @param WPML_TM_Jobs_Repository $jobs_repository * @param WPML_TP_Apply_Single_Job $apply_single_job * @param WPML_TP_Sync_Jobs $tp_sync */ public function __construct( WPML_TM_Jobs_Repository $jobs_repository, WPML_TP_Apply_Single_Job $apply_single_job, WPML_TP_Sync_Jobs $tp_sync ) { $this->jobs_repository = $jobs_repository; $this->apply_single_job = $apply_single_job; $this->tp_sync = $tp_sync; } /** * @param array $params * * @return WPML_TM_Jobs_Collection * @throws WPML_TP_API_Exception */ public function apply( array $params ) { $jobs = $this->get_jobs( $params ); if ( $this->has_in_progress_jobs( $jobs ) ) { $jobs = $this->sync_jobs( $jobs ); } $cancelled_jobs = $jobs->filter_by_status( ICL_TM_NOT_TRANSLATED ); $downloaded_jobs = new WPML_TM_Jobs_Collection( $jobs->filter_by_status( [ ICL_TM_TRANSLATION_READY_TO_DOWNLOAD, ICL_TM_COMPLETE ] ) ->map( array( $this->apply_single_job, 'apply' ) ) ); return $downloaded_jobs->append( $cancelled_jobs ); } /** * @param WPML_TM_Jobs_Collection $jobs * * @return bool */ private function has_in_progress_jobs( WPML_TM_Jobs_Collection $jobs ) { return count( $jobs->filter_by_status( ICL_TM_IN_PROGRESS ) ) > 0; } /** * @param array $params * * @return WPML_TM_Jobs_Collection */ private function get_jobs( array $params ) { if ( $params ) { if ( isset( $params['original_element_id'], $params['element_type'] ) ) { $jobs = $this->get_jobs_by_original_element( $params['original_element_id'], $params['element_type'] ); } else { $jobs = $this->get_jobs_by_ids( $params ); } } else { $jobs = $this->get_all_ready_jobs(); } return $jobs; } /** * @param int $original_element_id * @param string $element_type * * @return WPML_TM_Jobs_Collection */ private function get_jobs_by_original_element( $original_element_id, $element_type ) { $params = new WPML_TM_Jobs_Search_Params(); $params->set_scope( WPML_TM_Jobs_Search_Params::SCOPE_REMOTE ); $params->set_original_element_id( $original_element_id ); $params->set_job_types( $element_type ); return $this->jobs_repository->get_collection( $params ); } /** * @param array $params * * @return WPML_TM_Jobs_Collection */ private function get_jobs_by_ids( array $params ) { $jobs = array(); foreach ( $params as $param ) { $jobs[] = $this->jobs_repository->get_job( $param['id'], $param['type'] ); } return new WPML_TM_Jobs_Collection( $jobs ); } /** * @return WPML_TM_Jobs_Collection */ private function get_all_ready_jobs() { return $this->jobs_repository->get_collection( new WPML_TM_Jobs_Search_Params( array( 'status' => array( ICL_TM_TRANSLATION_READY_TO_DOWNLOAD ), 'scope' => WPML_TM_Jobs_Search_Params::SCOPE_REMOTE, ) ) ); } /** * @param WPML_TM_Jobs_Collection $jobs * * @return WPML_TM_Jobs_Collection * @throws WPML_TP_API_Exception */ private function sync_jobs( WPML_TM_Jobs_Collection $jobs ) { $synced_jobs = $this->tp_sync->sync(); /** @var WPML_TM_Job_Entity $job */ foreach ( $jobs as $job ) { foreach ( $synced_jobs as $synced_job ) { if ( $job->is_equal( $synced_job ) ) { $job->set_status( $synced_job->get_status() ); break; } } } return $jobs; } } translations/class-wpml-tp-translation-collection.php 0000644 00000002316 14721654666 0017211 0 ustar 00 <?php use WPML\FP\Fns; use function WPML\FP\invoke; class WPML_TP_Translation_Collection implements IteratorAggregate { /** @var WPML_TP_Translation[] */ private $translations; /** @var string */ private $source_language; /** @var string */ private $target_language; /** * @param WPML_TP_Translation[] $translations * @param string $source_language * @param string $target_language */ public function __construct( array $translations, $source_language, $target_language ) { $this->translations = $translations; $this->source_language = $source_language; $this->target_language = $target_language; } /** * @return string */ public function get_source_language() { return $this->source_language; } /** * @return string */ public function get_target_language() { return $this->target_language; } public function getIterator(): Traversable { return new ArrayIterator( $this->translations ); } /** * @return array */ public function to_array() { return [ 'source_language' => $this->source_language, 'target_language' => $this->target_language, 'translations' => Fns::map( invoke( 'to_array' ), $this->translations ), ]; } } translations/class-wpml-tp-translations-repository.php 0000644 00000004152 14721654666 0017460 0 ustar 00 <?php class WPML_TP_Translations_Repository { /** @var WPML_TP_XLIFF_API */ private $xliff_api; /** @var WPML_TM_Jobs_Repository */ private $jobs_repository; /** * @param WPML_TP_XLIFF_API $xliff_api * @param WPML_TM_Jobs_Repository $jobs_repository */ public function __construct( WPML_TP_XLIFF_API $xliff_api, WPML_TM_Jobs_Repository $jobs_repository ) { $this->xliff_api = $xliff_api; $this->jobs_repository = $jobs_repository; } /** * @param int $job_id * @param int $job_type * @param bool $parse When true, it returns the parsed translation, otherwise, it returns the raw XLIFF. * * @return WPML_TP_Translation_Collection|string * @throws WPML_TP_API_Exception|InvalidArgumentException */ public function get_job_translations( $job_id, $job_type, $parse = true ) { $job = $this->jobs_repository->get_job( $job_id, $job_type ); if ( ! $job ) { throw new InvalidArgumentException( 'Cannot find job' ); } return $this->get_job_translations_by_job_entity( $job, $parse ); } /** * @param WPML_TM_Job_Entity $job * @param bool $parse When true, it returns the parsed translation, otherwise, it returns the raw XLIFF. * * @return WPML_TP_Translation_Collection|string * @throws WPML_TP_API_Exception */ public function get_job_translations_by_job_entity( WPML_TM_Job_Entity $job, $parse = true ) { $correct_states = array( ICL_TM_TRANSLATION_READY_TO_DOWNLOAD, ICL_TM_COMPLETE ); if ( ! in_array( $job->get_status(), $correct_states, true ) ) { throw new InvalidArgumentException( 'Job\'s translation is not ready.' ); } if ( ! $job->get_tp_id() ) { throw new InvalidArgumentException( 'This is only a local job.' ); } $translations = $this->xliff_api->get_remote_translations( $job->get_tp_id(), $parse ); if ( $parse ) { /** * It filters translations coming from the Translation Proxy. * * @param \WPML_TP_Translation_Collection|string $translations * @param \WPML_TM_Job_Entity $job */ $translations = apply_filters( 'wpml_tm_proxy_translations', $translations, $job ); } return $translations; } } class-wpml-tp-http-request-filter.php 0000644 00000005776 14721654666 0013746 0 ustar 00 <?php class WPML_TP_HTTP_Request_Filter { /** * @return array filtered response */ public function build_request_context( array $request ) { if ( ! $this->contains_resource( $request ) ) { $request['headers'] = 'Content-type: application/json'; $request['body'] = wp_json_encode( $request['body'] ); } else { list( $headers, $body ) = $this->_prepare_multipart_request( $request['body'] ); $request['headers'] = $headers; $request['body'] = $body; } if ( $request['method'] === 'GET' ) { unset( $request['body'] ); } return $request; } /** * Checks if a request contains a file resource handle * * @param array $request_snippet * * @return bool */ private function contains_resource( array $request_snippet ) { foreach ( $request_snippet as $part ) { if ( is_resource( $part ) === true || ( is_array( $part ) && $this->contains_resource( $part ) ) ) { return true; } } return false; } private function _prepare_multipart_request( $params ) { $boundary = '----' . microtime(); $header = "Content-Type: multipart/form-data; boundary=$boundary"; $content = self::_add_multipart_contents( $boundary, $params ); $content .= "--$boundary--\r\n"; return array( $header, $content ); } private function _add_multipart_contents( $boundary, $params, $context = array() ) { $initial_context = $context; $content = ''; foreach ( $params as $key => $value ) { $context = $initial_context; $context[] = $key; if ( is_array( $value ) ) { $content .= self::_add_multipart_contents( $boundary, $value, $context ); } else { $pieces = array_slice( $context, 1 ); if ( $pieces ) { $name = "{$context[0]}[" . implode( '][', $pieces ) . ']'; } else { $name = "{$context[0]}"; } $content .= "--$boundary\r\n" . "Content-Disposition: form-data; name=\"$name\""; if ( is_resource( $value ) ) { $filename = self::get_file_name( $params, $key ); $value = stream_get_contents( $value ); $value = $value ?: ''; $content .= "; filename=\"$filename\"\r\n" . "Content-Type: application/octet-stream\r\n\r\n" . gzencode( $value ) . "\r\n"; } else { $content .= "\r\n\r\n$value\r\n"; } } } return $content; } private function get_file_name( $params, $default = 'file' ) { $title = isset( $params['title'] ) ? sanitize_title_with_dashes( strtolower( filter_var( $params['title'], FILTER_SANITIZE_FULL_SPECIAL_CHARS, FILTER_FLAG_STRIP_LOW | FILTER_FLAG_STRIP_HIGH ) ) ) : ''; if ( str_replace( array( '-', '_' ), '', $title ) == '' ) { $title = $default; } $source_language = isset( $params['source_language'] ) ? $params['source_language'] : ''; $target_language = isset( $params['target_language'] ) ? $params['target_language'] : ''; $filename = implode( '-', array_filter( array( $title, $source_language, $target_language, ) ) ); return $filename . '.xliff.gz'; } } class-wpml-tp-project-user.php 0000644 00000000443 14721654666 0012422 0 ustar 00 <?php abstract class WPML_TP_Project_User { /** @var TranslationProxy_Project $project */ protected $project; /** * WPML_TP_Project_User constructor. * * @param TranslationProxy_Project $project */ public function __construct( &$project ) { $this->project = &$project; } } lock/wpml-tp-lock.php 0000644 00000001622 14721654666 0010555 0 ustar 00 <?php class WPML_TP_Lock { private $lockable_endpoints = array( '/jobs/{job_id}/xliff.json', ); /** @var WPML_WP_API $wp_api */ private $wp_api; public function __construct( WPML_WP_API $wp_api ) { $this->wp_api = $wp_api; } /** * @param string $url * * @return bool */ public function is_locked( $url ) { return $this->get_locker_reason() && $this->is_lockable( $url ); } /** * @return string|false */ public function get_locker_reason() { if ( 'test' === $this->wp_api->constant( 'WPML_ENVIRONMENT' ) ) { return __( 'The constant WPML_ENVIRONMENT is set to "Test".', 'wpml-translation-management' ); } return false; } /** * @param string $url * * @return bool */ private function is_lockable( $url ) { $endpoint = preg_replace( '#^' . OTG_TRANSLATION_PROXY_URL . '#', '', $url, 1 ); return in_array( $endpoint, $this->lockable_endpoints, true ); } } lock/wpml-tp-lock-notice.php 0000644 00000002047 14721654666 0012036 0 ustar 00 <?php class WPML_TP_Lock_Notice implements IWPML_Action { const NOTICE_GROUP = 'tp-lock'; const NOTICE_LOCKED = 'locked'; /** @var WPML_TP_Lock $tp_lock */ private $tp_lock; /** @var WPML_Notices $notices */ private $notices; public function __construct( WPML_TP_Lock $tp_lock, WPML_Notices $notices ) { $this->tp_lock = $tp_lock; $this->notices = $notices; } public function add_hooks() { add_action( 'admin_init', array( $this, 'handle_notice' ) ); } public function handle_notice() { $locker_reason = $this->tp_lock->get_locker_reason(); if ( (bool) $locker_reason ) { $text = '<p>' . __( 'Some communications with the translation proxy are locked.', 'wpml-translation-management' ) . '</p>'; $text .= '<p>' . $locker_reason . '</p>'; $notice = $this->notices->create_notice( self::NOTICE_LOCKED, $text, self::NOTICE_GROUP ); $notice->set_css_class_types( 'notice-warning' ); $this->notices->add_notice( $notice ); } else { $this->notices->remove_notice( self::NOTICE_GROUP, self::NOTICE_LOCKED ); } } } lock/wpml-tp-lock-factory.php 0000644 00000000166 14721654666 0012224 0 ustar 00 <?php class WPML_TP_Lock_Factory { public function create() { return new WPML_TP_Lock( new WPML_WP_API() ); } } lock/wpml-tp-lock-notice-factory.php 0000644 00000000436 14721654666 0013503 0 ustar 00 <?php class WPML_TP_Lock_Notice_Factory implements IWPML_Backend_Action_Loader { public function create() { $tp_lock_factory = new WPML_TP_Lock_Factory(); $notices = wpml_get_admin_notices(); return new WPML_TP_Lock_Notice( $tp_lock_factory->create(), $notices ); } } sync-jobs/class-wpml-tp-sync-jobs-status.php 0000644 00000003642 14721654666 0015143 0 ustar 00 <?php class WPML_TM_Sync_Jobs_Status { /** @var WPML_TM_Jobs_Repository */ private $jobs_repository; /** @var WPML_TP_Jobs_API */ private $tp_api; /** * WPML_TM_Sync_Jobs_Status constructor. * * @param WPML_TM_Jobs_Repository $jobs_repository * @param WPML_TP_Jobs_API $tp_api */ public function __construct( WPML_TM_Jobs_Repository $jobs_repository, WPML_TP_Jobs_API $tp_api ) { $this->jobs_repository = $jobs_repository; $this->tp_api = $tp_api; } /** * @return WPML_TM_Jobs_Collection * @throws WPML_TP_API_Exception */ public function sync() { return $this->update_tp_state_of_jobs( $this->jobs_repository->get_collection( new WPML_TM_Jobs_Search_Params( array( 'status' => array( ICL_TM_WAITING_FOR_TRANSLATOR, ICL_TM_IN_PROGRESS ), 'scope' => WPML_TM_Jobs_Search_Params::SCOPE_REMOTE, ) ) ) ); } /** * @param WPML_TM_Jobs_Collection $jobs * * @return WPML_TM_Jobs_Collection * @throws WPML_TP_API_Exception */ private function update_tp_state_of_jobs( WPML_TM_Jobs_Collection $jobs ) { $tp_ids = $this->extract_tp_id_from_jobs( $jobs ); if ( $tp_ids ) { $tp_statuses = $this->tp_api->get_jobs_statuses( $tp_ids ); foreach ( $tp_statuses as $job_status ) { $job = $jobs->get_by_tp_id( $job_status->get_tp_id() ); if ( $job ) { $job->set_status( WPML_TP_Job_States::map_tp_state_to_local( $job_status->get_status() ) ); $job->set_ts_status( $job_status->get_ts_status() ); if ( WPML_TP_Job_States::CANCELLED === $job_status->get_status() ) { do_action( 'wpml_tm_canceled_job_notification', $job ); } } } } return $jobs; } /** * @param WPML_TM_Jobs_Collection $jobs * * @return array */ private function extract_tp_id_from_jobs( WPML_TM_Jobs_Collection $jobs ) { $tp_ids = array(); foreach ( $jobs as $job ) { $tp_ids[] = $job->get_tp_id(); } return $tp_ids; } } sync-jobs/class-wpml-tp-sync-jobs-revision.php 0000644 00000003125 14721654666 0015452 0 ustar 00 <?php class WPML_TM_Sync_Jobs_Revision { /** @var WPML_TM_Jobs_Repository */ private $jobs_repository; /** @var WPML_TP_Jobs_API */ private $tp_api; /** * WPML_TM_Sync_Jobs_Revision constructor. * * @param WPML_TM_Jobs_Repository $jobs_repository * @param WPML_TP_Jobs_API $tp_api */ public function __construct( WPML_TM_Jobs_Repository $jobs_repository, WPML_TP_Jobs_API $tp_api ) { $this->jobs_repository = $jobs_repository; $this->tp_api = $tp_api; } /** * @return WPML_TM_Job_Entity[] * @throws WPML_TP_API_Exception */ public function sync() { $result = array(); $tp_statuses_of_revised_jobs = $this->tp_api->get_revised_jobs(); if ( $tp_statuses_of_revised_jobs ) { $revised_jobs = array(); foreach ( $tp_statuses_of_revised_jobs as $tp_job_status ) { $revised_jobs[ $tp_job_status->get_tp_id() ] = $tp_job_status->get_revision(); } $job_search = new WPML_TM_Jobs_Search_Params( array( 'scope' => WPML_TM_Jobs_Search_Params::SCOPE_REMOTE, 'tp_id' => array_keys( $revised_jobs ), ) ); /** @var WPML_TM_Job_Entity $job */ foreach ( $this->jobs_repository->get( $job_search ) as $job ) { if ( isset( $revised_jobs[ $job->get_tp_id() ] ) && $job->get_revision() < $revised_jobs[ $job->get_tp_id() ] ) { $job->set_status( WPML_TP_Job_States::map_tp_state_to_local( WPML_TP_Job_States::TRANSLATION_READY ) ); $job->set_revision( $revised_jobs[ $job->get_tp_id() ] ); $result[] = $job; do_action( 'wpml_tm_revised_job_notification', $job->get_id() ); } } } return $result; } } sync-jobs/class-wpml-tp-sync-ajax-handler.php 0000644 00000003351 14721654666 0015220 0 ustar 00 <?php class WPML_TP_Sync_Ajax_Handler { const AJAX_ACTION = 'wpml-tp-sync-job-states'; /** @var WPML_TP_Sync_Jobs */ private $tp_sync; /** @var WPML_TM_Last_Picked_Up $wpml_tm_last_picked_up */ private $wpml_tm_last_picked_up; /** * WPML_TP_Sync_Jobs constructor. * * @param WPML_TP_Sync_Jobs $tp_sync * @param WPML_TM_Last_Picked_Up $wpml_tm_last_picked_up */ public function __construct( WPML_TP_Sync_Jobs $tp_sync, WPML_TM_Last_Picked_Up $wpml_tm_last_picked_up ) { $this->tp_sync = $tp_sync; $this->wpml_tm_last_picked_up = $wpml_tm_last_picked_up; } public function add_hooks() { add_action( 'wp_ajax_' . self::AJAX_ACTION, array( $this, 'handle' ) ); } public function handle() { $nonce = isset( $_POST['nonce'] ) ? sanitize_text_field( $_POST['nonce'] ) : ''; if ( ! wp_verify_nonce( $nonce, 'sync-job-states' ) ) { wp_send_json_error( esc_html__( 'Invalid request!' ) ); } try { if ( isset( $_REQUEST['update_last_picked_up'] ) ) { $this->wpml_tm_last_picked_up->set(); } $jobs = $this->tp_sync->sync(); do_action( 'wpml_tm_empty_mail_queue' ); wp_send_json_success( $jobs->map( array( $this, 'map_job_to_result' ) ) ); return true; } catch ( Exception $e ) { wp_send_json_error( $e->getMessage(), 503 ); return false; } } /** * @param WPML_TM_Job_Entity $job * * @return array */ public function map_job_to_result( WPML_TM_Job_Entity $job ) { return array( 'id' => $job->get_id(), 'type' => $job->get_type(), 'status' => $job->get_status(), 'hasCompletedTranslation' => $job->has_completed_translation(), 'needsUpdate' => $job->does_need_update(), ); } } sync-jobs/wpml-tp-sync-orphan-jobs.php 0000644 00000002126 14721654666 0014000 0 ustar 00 <?php class WPML_TP_Sync_Orphan_Jobs { /** @var WPML_TM_Jobs_Repository */ private $jobs_repository; /** @var WPML_TP_Sync_Update_Job */ private $update_job; /** * @param WPML_TM_Jobs_Repository $jobs_repository * @param WPML_TP_Sync_Update_Job $update_job */ public function __construct( WPML_TM_Jobs_Repository $jobs_repository, WPML_TP_Sync_Update_Job $update_job ) { $this->jobs_repository = $jobs_repository; $this->update_job = $update_job; } /** * @return WPML_TM_Jobs_Collection */ public function cancel_orphans() { $params = new WPML_TM_Jobs_Search_Params( array( 'scope' => WPML_TM_Jobs_Search_Params::SCOPE_REMOTE, 'tp_id' => 0, 'status' => array( ICL_TM_WAITING_FOR_TRANSLATOR, ICL_TM_IN_PROGRESS ), ) ); return $this->jobs_repository->get( $params )->map( array( $this, 'cancel_job' ), true ); } /** * @param WPML_TM_Job_Entity $job * * @return WPML_TM_Job_Entity */ public function cancel_job( WPML_TM_Job_Entity $job ) { $job->set_status( ICL_TM_NOT_TRANSLATED ); return $this->update_job->update_state( $job ); } } sync-jobs/class-wpml-tp-sync-update-job.php 0000644 00000007024 14721654666 0014715 0 ustar 00 <?php use WPML\FP\Relation; use \WPML\LIB\WP\Post; class WPML_TP_Sync_Update_Job { private $strategies = array( WPML_TM_Job_Entity::POST_TYPE => 'update_post_job', WPML_TM_Job_Entity::STRING_TYPE => 'update_string_job', WPML_TM_Job_Entity::PACKAGE_TYPE => 'update_post_job', WPML_TM_Job_Entity::STRING_BATCH => 'update_post_job', ); /** @var wpdb */ private $wpdb; /** @var SitePress */ private $sitepress; /** * @param wpdb $wpdb */ public function __construct( wpdb $wpdb, SitePress $sitepress ) { $this->wpdb = $wpdb; $this->sitepress = $sitepress; } /** * @param WPML_TM_Job_Entity $job * * @return WPML_TM_Job_Entity */ public function update_state( WPML_TM_Job_Entity $job ) { if ( ! array_key_exists( $job->get_type(), $this->strategies ) ) { return $job; } $method = $this->strategies[ $job->get_type() ]; return call_user_func( array( $this, $method ), $job ); } /** * @param WPML_TM_Job_Entity $job * * @return WPML_TM_Job_Entity */ private function update_string_job( WPML_TM_Job_Entity $job ) { if ( $job->get_tp_id() ) { $this->wpdb->update( $this->wpdb->prefix . 'icl_core_status', array( 'status' => $job->get_status(), 'tp_revision' => $job->get_revision(), 'ts_status' => $this->get_ts_status_in_ts_format( $job ), ), array( 'rid' => $job->get_tp_id() ) ); } $data = array( 'status' => $job->get_status(), ); if ( ICL_TM_NOT_TRANSLATED === $job->get_status() ) { $data['translator_id'] = null; } $this->wpdb->update( $this->wpdb->prefix . 'icl_string_translations', $data, array( 'id' => $job->get_id() ) ); icl_update_string_status( $job->get_original_element_id() ); return $job; } /** * @param WPML_TM_Job_Entity $job * * @return WPML_TM_Job_Entity */ private function update_post_job( WPML_TM_Job_Entity $job ) { $job_id = $job->get_id(); if ( $job->get_status() === ICL_TM_NOT_TRANSLATED ) { $prev_status = $this->get_job_prev_status( $job_id ); if ( $prev_status && Relation::propEq( 'needs_update', '1', $prev_status ) ) { $this->wpdb->update( $this->wpdb->prefix . 'icl_translation_status', $prev_status, [ 'rid' => $job_id ] ); $job->set_needs_update( true ); return $job; } } $this->wpdb->update( $this->wpdb->prefix . 'icl_translation_status', array( 'status' => $job->get_status(), 'tp_revision' => $job->get_revision(), 'ts_status' => $this->get_ts_status_in_ts_format( $job ), ), array( 'rid' => $job_id ) ); if ( ICL_TM_NOT_TRANSLATED === $job->get_status() && ( $post_type = Post::getType( $job->get_original_element_id() ) ) ) { $this->sitepress->delete_orphan_element( $job->get_original_element_id(), 'post_' . $post_type, $job->get_target_language() ); } return $job; } private function get_job_prev_status( $job_id ) { $previous_state = $this->wpdb->get_var( $this->wpdb->prepare( "SELECT _prevstate FROM {$this->wpdb->prefix}icl_translation_status WHERE rid=%d LIMIT 1", $job_id ) ); return $previous_state ? unserialize( $previous_state ) : null; } /** * In the db, we store the exact json format that we get from TS. It includes an extra ts_status key * * @param WPML_TM_Job_Entity $job * * @return string */ private function get_ts_status_in_ts_format( WPML_TM_Job_Entity $job ) { $ts_status = $job->get_ts_status(); return $ts_status ? wp_json_encode( array( 'ts_status' => json_decode( (string) $ts_status ) ) ) : null; } } sync-jobs/wpml-tp-sync-orphan-jobs-factory.php 0000644 00000000437 14721654666 0015450 0 ustar 00 <?php class WPML_TP_Sync_Orphan_Jobs_Factory { /** * @return WPML_TP_Sync_Orphan_Jobs */ public function create() { global $wpdb, $sitepress; return new WPML_TP_Sync_Orphan_Jobs( wpml_tm_get_jobs_repository(), new WPML_TP_Sync_Update_Job( $wpdb, $sitepress ) ); } } sync-jobs/class-wpml-tp-sync-jobs.php 0000644 00000002174 14721654666 0013621 0 ustar 00 <?php class WPML_TP_Sync_Jobs { /** @var WPML_TM_Sync_Jobs_Status */ private $jobs_status_sync; /** @var WPML_TM_Sync_Jobs_Revision */ private $jobs_revision_sync; /** @var WPML_TP_Sync_Update_Job */ private $update_job; /** * WPML_TP_Sync_Jobs constructor. * * @param WPML_TM_Sync_Jobs_Status $jobs_status_sync * @param WPML_TM_Sync_Jobs_Revision $jobs_revision_sync * @param WPML_TP_Sync_Update_Job $update_job */ public function __construct( WPML_TM_Sync_Jobs_Status $jobs_status_sync, WPML_TM_Sync_Jobs_Revision $jobs_revision_sync, WPML_TP_Sync_Update_Job $update_job ) { $this->jobs_status_sync = $jobs_status_sync; $this->jobs_revision_sync = $jobs_revision_sync; $this->update_job = $update_job; } /** * @return WPML_TM_Jobs_Collection * @throws WPML_TP_API_Exception */ public function sync() { return new WPML_TM_Jobs_Collection( $this->jobs_status_sync ->sync() ->append( $this->jobs_revision_sync->sync() ) ->filter_by_status( array( ICL_TM_IN_PROGRESS, ICL_TM_WAITING_FOR_TRANSLATOR ), true ) ->map( array( $this->update_job, 'update_state' ) ) ); } } sync-jobs/class-wpml-tp-sync-installer-wrapper.php 0000644 00000000270 14721654666 0016332 0 ustar 00 <?php class WPML_TM_Sync_Installer_Wrapper { /** * @return bool */ public function is_wpml_registered() { return (bool) WP_Installer::instance()->get_site_key( 'wpml' ); } } services/AuthorizationFactory.php 0000644 00000000731 14721654666 0013312 0 ustar 00 <?php namespace WPML\TM\TranslationProxy\Services; use WPML\TM\TranslationProxy\Services\Project\Manager; use function WPML\Container\make; class AuthorizationFactory { /** * @return Authorization * @throws \Auryn\InjectionException */ public function create() { $projectManager = make( Manager::class, [ ':projectApi' => wpml_tm_get_tp_project_api(), ] ); return make( Authorization::class, [ ':projectManager' => $projectManager ] ); } } services/Authorization.php 0000644 00000003523 14721654666 0011764 0 ustar 00 <?php namespace WPML\TM\TranslationProxy\Services; use WPML\TM\TranslationProxy\Services\Project\Manager; class Authorization { /** @var Storage */ private $storage; /** @var Manager */ private $projectManager; /** * @param Storage $storage * @param Manager $projectManager */ public function __construct( Storage $storage, Manager $projectManager ) { $this->storage = $storage; $this->projectManager = $projectManager; } /** * @param \stdClass $credentials * * @throws \RuntimeException * @throws \WPML_TP_API_Exception */ public function authorize( \stdClass $credentials ) { $service = $this->getCurrentService(); $service->custom_fields_data = $credentials; $project = $this->projectManager->create( $service ); $this->storage->setCurrentService( $service ); do_action( 'wpml_tm_translation_service_authorized', $service, $project ); } /** * @param \stdClass $credentials * * @throws \WPML_TP_API_Exception */ public function updateCredentials( \stdClass $credentials ) { $service = $this->getCurrentService(); $this->projectManager->updateCredentials( $service, $credentials ); $service->custom_fields_data = $credentials; $this->storage->setCurrentService( $service ); } /** * @throws \RuntimeException */ public function deauthorize() { $service = $this->getCurrentService(); $service->custom_fields_data = null; $this->storage->setCurrentService( $service ); do_action( 'wpml_tp_service_de_authorized', $service ); } /** * @return \stdClass * @throws \RuntimeException */ private function getCurrentService() { $service = $this->storage->getCurrentService(); if ( (bool) $service === false ) { throw new \RuntimeException( 'Tried to authenticate a service, but no service is active!' ); } return $service; } } services/Storage.php 0000644 00000001406 14721654666 0010526 0 ustar 00 <?php namespace WPML\TM\TranslationProxy\Services; class Storage { /** @var \SitePress $sitepress */ private $sitepress; /** * @param \SitePress $sitepress */ public function __construct( \SitePress $sitepress ) { $this->sitepress = $sitepress; } /** * Gets the current translation service * * @return bool|\stdClass */ public function getCurrentService() { return $this->sitepress->get_setting( 'translation_service' ); } /** * Saves the input service as the current translation service setting. * * @param \stdClass $service */ public function setCurrentService( \stdClass $service ) { do_action( 'wpml_tm_before_set_translation_service', $service ); $this->sitepress->set_setting( 'translation_service', $service, true ); } } services/Project/Manager.php 0000644 00000004612 14721654666 0012104 0 ustar 00 <?php namespace WPML\TM\TranslationProxy\Services\Project; class Manager { /** @var \WPML_TP_Project_API */ private $projectApi; /** @var Storage */ private $projectStorage; /** @var SiteDetails */ private $siteDetails; /** * @param \WPML_TP_Project_API $projectApi * @param Storage $projectStorage * @param SiteDetails $siteDetails */ public function __construct( \WPML_TP_Project_API $projectApi, Storage $projectStorage, SiteDetails $siteDetails ) { $this->projectApi = $projectApi; $this->projectStorage = $projectStorage; $this->siteDetails = $siteDetails; } /** * @param \stdClass $service * * @return Project * @throws \WPML_TP_API_Exception */ public function create( \stdClass $service ) { $project = $this->projectStorage->getByService( $service ) ?: $this->fromTranslationProxy( $service ); $project->extraFields = $this->projectApi->get_extra_fields( $project ); $this->projectStorage->save( $service, $project ); do_action( 'wpml_tp_project_created', $service, $project, $this->projectStorage->getProjects()->toArray() ); return $project; } /** * @param \stdClass $service * @param \stdClass $credentials * * @return Project|null * @throws \WPML_TP_API_Exception */ public function updateCredentials( \stdClass $service, \stdClass $credentials ) { $project = $this->projectStorage->getByService( $service ); if ( ! $project ) { throw new \RuntimeException( 'Project does not exist' ); } $this->projectApi->update_project_credentials( $project, $credentials ); $project->extraFields = $this->projectApi->get_extra_fields( $project ); $this->projectStorage->save( $this->createServiceWithNewCredentials( $service, $credentials ), $project ); return $project; } /** * @param \stdClass $service * * @return Project * @throws \WPML_TP_API_Exception */ private function fromTranslationProxy( \stdClass $service ) { $response = $this->projectApi->create_project( $service, $this->siteDetails ); return Project::fromResponse( $response->project ); } /** * @param \stdClass $service * @param \stdClass $credentials * * @return \stdClass */ private function createServiceWithNewCredentials( \stdClass $service, \stdClass $credentials ) { $updatedService = clone $service; $updatedService->custom_fields_data = $credentials; return $updatedService; } } services/Project/Storage.php 0000644 00000002430 14721654666 0012132 0 ustar 00 <?php namespace WPML\TM\TranslationProxy\Services\Project; use WPML\Collect\Support\Collection; class Storage { /** @var \SitePress */ private $sitepress; /** * @param \SitePress $sitepress */ public function __construct( \SitePress $sitepress ) { $this->sitepress = $sitepress; } /** * @param \stdClass $service * * @return Project|null */ public function getByService( \stdClass $service ) { return $this->getProjects()->get( \TranslationProxy_Project::generate_service_index( $service ) ); } /** * @param \stdClass $service * @param Project $project */ public function save( \stdClass $service, Project $project ) { $index = \TranslationProxy_Project::generate_service_index( $service ); $this->sitepress->set_setting( 'icl_translation_projects', $this->getProjects()->put( $index, $project )->map( function ( Project $project ) { return $project->toArray(); } )->toArray(), true ); } /** * @return Collection */ public function getProjects() { $projects = $this->sitepress->get_setting( 'icl_translation_projects', [] ); if ( ! is_array( $projects ) ) { $projects = []; } return \wpml_collect( $projects )->map( function ( array $rawProject ) { return Project::fromArray( $rawProject ); } ); } } services/Project/Project.php 0000644 00000002317 14721654666 0012140 0 ustar 00 <?php namespace WPML\TM\TranslationProxy\Services\Project; class Project { /** @var int */ public $id; /** @var string */ public $accessKey; /** @var string */ public $tsId; /** @var string */ public $tsAccessKey; /** @var \stdClass */ public $extraFields; /** * @return array */ public function toArray() { return [ 'id' => $this->id, 'access_key' => $this->accessKey, 'ts_id' => $this->tsId, 'ts_access_key' => $this->tsAccessKey, 'extra_fields' => $this->extraFields, ]; } /** * @param array $data * * @return Project */ public static function fromArray( array $data ) { $project = new Project(); $project->id = $data['id']; $project->accessKey = $data['access_key']; $project->tsId = $data['ts_id']; $project->tsAccessKey = $data['ts_access_key']; $project->extraFields = $data['extra_fields']; return $project; } public static function fromResponse( \stdClass $response ) { $project = new Project(); $project->id = $response->id; $project->accessKey = $response->accesskey; $project->tsId = $response->ts_id; $project->tsAccessKey = $response->ts_accesskey; return $project; } } services/Project/SiteDetails.php 0000644 00000001622 14721654666 0012742 0 ustar 00 <?php namespace WPML\TM\TranslationProxy\Services\Project; class SiteDetails { /** @var \SitePress */ private $sitepress; /** * @param \SitePress $sitepress */ public function __construct( \SitePress $sitepress ) { $this->sitepress = $sitepress; } /** * @return string */ public function getDeliveryMethod() { return (int) $this->sitepress->get_setting( 'translation_pickup_method' ) === ICL_PRO_TRANSLATION_PICKUP_XMLRPC ? 'xmlrpc' : 'polling'; } /** * @return array */ public function getBlogInfo() { return [ 'url' => get_option( 'siteurl' ), 'name' => get_option( 'blogname' ), 'description' => get_option( 'blogdescription' ), ]; } /** * @return array */ public function getClientData() { $current_user = wp_get_current_user(); return [ 'email' => $current_user->user_email, 'name' => $current_user->display_name, ]; } } class-wpml-translation-proxy-networking.php 0000644 00000011715 14721654666 0015265 0 ustar 00 <?php class WPML_Translation_Proxy_Networking { const API_VERSION = 1.1; /** @var WP_Http $http */ private $http; /** @var WPML_TP_Lock $tp_lock */ private $tp_lock; public function __construct( WP_Http $http, WPML_TP_Lock $tp_lock ) { $this->http = $http; $this->tp_lock = $tp_lock; } /** * @param string $url * @param array $params * @param string $method * @param bool|true $has_return_value * @param bool|true $json_response * @param bool|true $has_api_response * * @return array|mixed|stdClass|string * @throws WPMLTranslationProxyApiException */ public function send_request( $url, $params = array(), $method = 'GET', $has_return_value = true, $json_response = true, $has_api_response = true ) { if ( $this->tp_lock->is_locked( $url ) ) { throw new WPMLTranslationProxyApiException( 'Communication with translation proxy is not allowed.' ); } if ( ! $url ) { throw new WPMLTranslationProxyApiException( 'Empty target URL given!' ); } $response = null; $method = strtoupper( $method ); if ( $params ) { $url = TranslationProxy_Api::add_parameters_to_url( $url, $params ); if ( 'GET' === $method ) { $url .= '?' . wpml_http_build_query( $params ); } } if ( ! isset( $params['api_version'] ) || ! $params['api_version'] ) { $params['api_version'] = self::API_VERSION; } WPML_TranslationProxy_Com_Log::log_call( $url, $params ); $api_response = $this->call_remote_api( $url, $params, $method, $has_return_value ); if ( $has_return_value ) { if ( ! isset( $api_response['headers'] ) && ! isset( $api_response['headers']['content-type'] ) ) { throw new WPMLTranslationProxyApiException( 'Invalid HTTP response, no content type in header given!' ); } $content_type = $api_response['headers']['content-type']; $api_response = $api_response['body']; $api_response = strpos( $content_type, 'zip' ) !== false ? gzdecode( $api_response ) : $api_response; WPML_TranslationProxy_Com_Log::log_response( $json_response ? $api_response : 'XLIFF received' ); if ( $json_response ) { $response = json_decode( $api_response ); if ( $has_api_response ) { if ( ! $response || ! isset( $response->status->code ) || $response->status->code !== 0 ) { $exception_message = $this->get_exception_message( $url, $method, $params, $response ); if ( isset( $response->status->message ) ) { $exception_message = ''; if ( isset( $response->status->code ) ) { $exception_message = '(' . $response->status->code . ') '; } $exception_message .= $response->status->message; } throw new WPMLTranslationProxyApiException( $exception_message ); } $response = $response->response; } } else { $response = $api_response; } } return $response; } public function get_extra_fields_remote( $project ) { $params = array( 'accesskey' => $project->access_key, 'api_version' => self::API_VERSION, 'project_id' => $project->id, ); return TranslationProxy_Api::proxy_request( '/projects/{project_id}/extra_fields.json', $params ); } /** * @param string $url * @param array $params * @param string $method * @param bool $has_return_value * * @throws \WPMLTranslationProxyApiException * * @return array */ private function call_remote_api( $url, $params, $method, $has_return_value = true ) { $context = $this->filter_request_params( $params, $method ); $response = $this->http->request( $url, $context ); if ( ( $has_return_value && (bool) $response === false ) || is_wp_error( $response ) || ( isset( $response['response']['code'] ) && $response['response']['code'] > 400 ) ) { throw new WPMLTranslationProxyApiException( $this->get_exception_message( $url, $method, $context, $response ) ); } return $response; } private function get_exception_message( $url, $method, $context, $response ) { $sanitized_url = WPML_TranslationProxy_Com_Log::sanitize_url( $url ); $sanitized_context = WPML_TranslationProxy_Com_Log::sanitize_data( $context ); $sanitized_response = WPML_TranslationProxy_Com_Log::sanitize_data( $response ); return 'Cannot communicate with the remote service |' . ' url: ' . '`' . $sanitized_url . '`' . ' method: ' . '`' . $method . '`' . ' param: ' . '`' . wp_json_encode( $sanitized_context ) . '`' . ' response: ' . '`' . wp_json_encode( $sanitized_response ) . '`'; } /** * @param array $params request parameters * @param string $method HTTP request method * * @return array */ private function filter_request_params( $params, $method ) { $request_filter = new WPML_TP_HTTP_Request_Filter(); return $request_filter->build_request_context( array( 'method' => $method, 'body' => $params, 'sslverify' => true, 'timeout' => 60, ) ); } } log/class-wpml-translationproxy-communication-log.php 0000644 00000007461 14721654666 0017231 0 ustar 00 <?php class WPML_TranslationProxy_Communication_Log { private $keys_to_block; private $sitepress; public function __construct( SitePress $sitepress ) { $this->keys_to_block = array( 'api_token', 'username', 'api_key', 'sitekey', 'accesskey', 'file', ); $this->sitepress = $sitepress; } public function log_call( $url, $params ) { $sanitized_params = $this->sanitize_data( $params ); $sanitized_url = $this->sanitize_url( $url ); $this->add_to_log( 'call - ' . $sanitized_url . ' - ' . json_encode( $sanitized_params ) ); } public function get_keys_to_block() { return $this->keys_to_block; } public function log_response( $response ) { $this->add_to_log( 'response - ' . $response ); } public function log_error( $message ) { $this->add_to_log( 'error - ' . $message ); } public function log_xml_rpc( $data ) { $this->add_to_log( 'xml-rpc - ' . json_encode( $data ) ); } public function get_log() { return get_option( 'wpml_tp_com_log', '' ); } public function clear_log() { $this->save_log( '' ); } public function is_logging_enabled() { return $this->sitepress->get_setting( 'tp-com-logging', true ); } /** * @param string|array|stdClass $params * * @return array|stdClass */ public function sanitize_data( $params ) { $sanitized_params = $params; if ( is_object( $sanitized_params ) ) { $sanitized_params = get_object_vars( $sanitized_params ); } if ( is_array( $sanitized_params ) ) { foreach ( $sanitized_params as $key => $value ) { $sanitized_params[ $key ] = $this->sanitize_data_item( $key, $sanitized_params[ $key ] ); } } return $sanitized_params; } /** * @param string $key * @param string|array|stdClass $item * * @return string|array|stdClass */ private function sanitize_data_item( $key, $item ) { if ( is_array( $item ) || is_object( $item ) ) { $item = $this->sanitize_data( $item ); } elseif ( in_array( $key, $this->get_keys_to_block(), true ) ) { $item = 'UNDISCLOSED'; } elseif ( $this->is_json( $item ) ) { $item = json_encode( $this->sanitize_data_item( $key, json_decode( $item ) ) ); } return $item; } /** * @param $url * * @return mixed */ public function sanitize_url( $url ) { $original_url_parsed = (string) wpml_parse_url( $url, PHP_URL_QUERY ); parse_str( $original_url_parsed, $original_query_vars ); $sanitized_query_vars = $this->sanitize_data( $original_query_vars ); return add_query_arg( $sanitized_query_vars, $url ); } public function set_logging_state( $state ) { $this->sitepress->set_setting( 'tp-com-logging', $state ); $this->sitepress->save_settings(); } public function add_com_log_link() { $url = esc_attr( 'admin.php?page=' . WPML_TM_FOLDER . '/menu/main.php&sm=com-log' ); ?> <?php printf( __( 'For retrieving debug information for communication between your%1$s site and the translation system, use the <a href="%2$s">communication log</a> page.', 'wpml-translation-management' ), '<br>', $url ); ?> </p> <?php } private function now() { return date( 'm/d/Y h:i:s a', time() ); } private function add_to_log( $string ) { if ( $this->is_logging_enabled() ) { $max_log_length = 10000; $string = $this->now() . ' - ' . $string; $log = $this->get_log(); $log .= $string; $log .= PHP_EOL; $log_length = strlen( $log ); if ( $log_length > $max_log_length ) { $log = substr( $log, $log_length - $max_log_length ); } $this->save_log( $log ); } } private function save_log( $log ) { update_option( 'wpml_tp_com_log', $log, false ); } /** * @param mixed $item * * @return bool */ private function is_json( $item ) { return is_string( $item ) && json_decode( $item ) && json_last_error() === JSON_ERROR_NONE; } } api/class-wpml-tp-jobs-api.php 0000644 00000010021 14721654666 0012246 0 ustar 00 <?php use WPML\FP\Obj; class WPML_TP_Jobs_API extends WPML_TP_API { const CHUNK_SIZE = 100; /** * @param int[] $tp_job_ids * * @return WPML_TP_Job_Status[] * @throws WPML_TP_API_Exception */ public function get_jobs_statuses( array $tp_job_ids ) { $this->log( 'Get jobs status', $tp_job_ids ); $chunks = array(); while ( $tp_job_ids ) { $chunk_ids = array_splice( $tp_job_ids, 0, self::CHUNK_SIZE ); $chunks[] = $this->get_chunk_of_job_statuses( $chunk_ids ); } $result = call_user_func_array( 'array_merge', $chunks ); return array_map( array( $this, 'build_job_status' ), $result ); } private function get_chunk_of_job_statuses( $tp_job_ids ) { $request = new WPML_TP_API_Request( '/jobs.json' ); $request->set_params( array( 'filter' => array( 'job_ids' => array_filter( $tp_job_ids, 'is_int' ), 'archived' => 1, ), 'accesskey' => $this->project->get_access_key(), ) ); return $this->client->send_request( $request ); } /** * @param array $cms_ids * @param bool $archived * * @return array|mixed|stdClass|string * @throws WPML_TP_API_Exception */ public function get_jobs_per_cms_ids( array $cms_ids, $archived = false ) { $request = new WPML_TP_API_Request( '/jobs.json' ); $filter = array( 'filter' => array( 'cms_ids' => $cms_ids, ), 'accesskey' => $this->project->get_access_key(), ); if ( $archived ) { $filter['filter']['archived'] = (int) $archived; $request->set_params( $filter ); } return $this->client->send_request( $request ); } /** * @param WPML_TM_Job_Entity $job * @param string $state * @param string $post_url * * @throws WPML_TP_API_Exception */ public function update_job_state( WPML_TM_Job_Entity $job, $state = WPML_TP_Job_States::DELIVERED, $post_url = null ) { $params = array( 'job_id' => $job->get_tp_id(), 'project_id' => $this->project->get_id(), 'accesskey' => $this->project->get_access_key(), 'job' => array( 'state' => $state, ), ); if ( $post_url ) { $params['job']['url'] = $post_url; } $request = new WPML_TP_API_Request( '/jobs/{job_id}.json' ); $request->set_params( $params ); $request->set_method( 'PUT' ); $this->client->send_request( $request ); } private function build_job_status( stdClass $raw_data ) { return new WPML_TP_Job_Status( $raw_data->id, isset( $raw_data->batch->id ) ? $raw_data->batch->id : 0, $raw_data->job_state, isset( $raw_data->translation_revision ) ? $raw_data->translation_revision : 1, $raw_data->ts_status ? new WPML_TM_Job_TS_Status( $raw_data->ts_status->status, $raw_data->ts_status->links ) : null ); } /** * @return WPML_TP_Job_Status[] * @throws WPML_TP_API_Exception */ public function get_revised_jobs() { $this->log( 'Get revised jobs' ); $request = new WPML_TP_API_Request( '/jobs.json' ); $request->set_params( array( 'filter' => array( 'job_state' => WPML_TP_Job_States::TRANSLATION_READY, 'archived' => 0, 'revision_greater_than' => 1, ), 'accesskey' => $this->project->get_access_key(), ) ); $result = $this->client->send_request( $request ); return array_map( array( $this, 'build_job_status' ), $result ); } /** * @param int $tp_job_id * * @return string * @throws WPML_TP_API_Exception When response is incorrect. */ public function get_translated_xliff_download_url( $tp_job_id ) { $request = new WPML_TP_API_Request( '/jobs.json' ); $params = [ 'filter' => [ 'job_ids' => $tp_job_id, ], 'accesskey' => $this->project->get_access_key(), ]; $request->set_params( $params ); $result = $this->client->send_request( $request ); if ( ! $result || ! is_array( $result ) || 0 === count( $result ) || ! is_object( $result[0] ) ) { throw new WPML_TP_API_Exception( 'XLIFF download link could not be fetched for tp_job: ' . $tp_job_id, $request ); } return Obj::propOr( '', 'translated_xliff_download_url', $result[0] ); } } api/class-wpml-translation-proxy-api-exception.php 0000644 00000000404 14721654666 0016405 0 ustar 00 <?php /** * @author OnTheGo Systems */ class WPMLTranslationProxyApiException extends Exception { public function __construct( $message, $code = 0 ) { WPML_TranslationProxy_Com_Log::log_error( $message ); parent::__construct( $message, $code ); } } api/class-wpml-tm-log.php 0000644 00000001564 14721654666 0011334 0 ustar 00 <?php class WPML_TM_Log implements WPML_TP_API_Log_Interface { const LOG_WP_OPTION = '_wpml_tp_api_Logger'; const LOG_MAX_SIZE = 500; public function log( $action, $data = array() ) { $log_base_data = array( 'timestamp' => false, 'action' => false, ); $log_item = array_merge( $log_base_data, $data ); $log_item['timestamp'] = date( 'Y-m-d H:i:s' ); $log_item['action'] = $action; $log = $this->get_log_data(); $log = array_slice( $log, - ( self::LOG_MAX_SIZE - 1 ) ); $log[] = $log_item; $this->update_log( $log ); } private function update_log( $log ) { return update_option( self::LOG_WP_OPTION, $log, false ); } public function flush_log() { return update_option( self::LOG_WP_OPTION, [], false ); } public function get_log_data() { $log = get_option( self::LOG_WP_OPTION, [] ); return is_array( $log ) ? $log : []; } } api/class-wpml-tp-job-states.php 0000644 00000002147 14721654666 0012627 0 ustar 00 <?php class WPML_TP_Job_States { const RECEIVED = 'received'; const WAITING_TRANSLATIONS = 'waiting_translation'; const TRANSLATION_READY = 'translation_ready'; const DELIVERED = 'delivered'; const CANCELLED = 'cancelled'; const ANY = 'any'; /** * @return array */ public static function get_possible_states() { return array( self::RECEIVED, self::WAITING_TRANSLATIONS, self::TRANSLATION_READY, self::DELIVERED, self::CANCELLED, self::ANY, ); } /** * @return string */ public static function get_default_state() { return self::WAITING_TRANSLATIONS; } /** * @return array */ public static function get_finished_states() { return array( self::TRANSLATION_READY, self::DELIVERED, self::CANCELLED, ); } public static function map_tp_state_to_local( $tp_state ) { switch ( $tp_state ) { case self::TRANSLATION_READY: case self::DELIVERED: return ICL_TM_TRANSLATION_READY_TO_DOWNLOAD; case self::CANCELLED: return ICL_TM_NOT_TRANSLATED; default: return ICL_TM_IN_PROGRESS; } } } api/class-wpml-tp-api-client.php 0000644 00000007264 14721654666 0012606 0 ustar 00 <?php use WPML\FP\Str; class WPML_TP_API_Client { /** @var string */ private $proxy_url; /** @var WP_Http $http */ private $http; /** @var WPML_TP_Lock $tp_lock */ private $tp_lock; /** @var WPML_TP_HTTP_Request_Filter */ private $request_filter; public function __construct( $proxy_url, WP_Http $http, WPML_TP_Lock $tp_lock, WPML_TP_HTTP_Request_Filter $request_filter ) { $this->proxy_url = $proxy_url; $this->http = $http; $this->tp_lock = $tp_lock; $this->request_filter = $request_filter; } /** * @param WPML_TP_API_Request $request * @param bool $raw_json_response * * @return array|mixed|stdClass|string * @throws WPML_TP_API_Exception */ public function send_request( WPML_TP_API_Request $request, $raw_json_response = false ) { if ( $this->tp_lock->is_locked( $request->get_url() ) ) { throw new WPML_TP_API_Exception( 'Communication with translation proxy is not allowed.', $request ); } WPML_TranslationProxy_Com_Log::log_call( $request->get_url(), $request->get_params() ); $response = $this->call_remote_api( $request ); if ( ! $response || is_wp_error( $response ) || ( isset( $response['response'] ) && isset( $response['response']['code'] ) && $response['response']['code'] >= 400 ) ) { throw new WPML_TP_API_Exception( 'Communication error', $request, $response ); } if ( isset( $response['headers'] ) && isset( $response['headers']['content-type'] ) ) { $content_type = $response['headers']['content-type']; $response = $response['body']; if ( strpos( $content_type, 'zip' ) !== false ) { $response = gzdecode( $response ); } else { WPML_TranslationProxy_Com_Log::log_response( $response ); } $json_response = json_decode( $response ); if ( $json_response ) { if ( $raw_json_response ) { $response = $json_response; } else { $response = $this->handle_json_response( $request, $json_response ); } } } return $response; } /** * @param WPML_TP_API_Request $request * * @return null|WP_Error|string */ private function call_remote_api( WPML_TP_API_Request $request ) { $context = $this->filter_request_params( $request->get_params(), $request->get_method() ); $url = $request->get_url(); if ( ! Str::startsWith( 'http://', $url ) && ! Str::startsWith( 'https://', $url ) ) { $url = $this->proxy_url . $url; } return $this->http->request( $url, $context ); } /** * @param array $params request parameters * @param string $method HTTP request method * * @return array */ private function filter_request_params( $params, $method ) { return $this->request_filter->build_request_context( array( 'method' => $method, 'body' => $params, 'sslverify' => true, 'timeout' => 60, ) ); } /** * @param WPML_TP_API_Request $request * @param stdClass $response * * @return mixed * @throws WPML_TP_API_Exception */ private function handle_json_response( WPML_TP_API_Request $request, $response ) { if ( $request->has_api_response() ) { if ( ! isset( $response->status->code ) || $response->status->code !== 0 ) { throw new WPML_TP_API_Exception( $this->generate_error_message_from_status_field( $response ), $request, $response ); } $response = $response->response; } return $response; } private function generate_error_message_from_status_field( $response ) { $message = ''; if ( isset( $response->status->message ) ) { if ( isset( $response->status->code ) ) { $message = '(' . $response->status->code . ') '; } $message .= $response->status->message; } else { $message = 'Unknown error'; } return $message; } } api/class-wpml-tp-job-status.php 0000644 00000002470 14721654666 0012646 0 ustar 00 <?php class WPML_TP_Job_Status { /** @var int */ private $tp_id; /** @var int */ private $batch_id; /** @var string */ private $status; /** @var int */ private $revision; /** @var WPML_TM_Job_TS_Status|null */ private $ts_status; /** * @param int $tp_id * @param int $batch_id * @param string $state * @param WPML_TM_Job_TS_Status|null $ts_status * @param int $revision */ public function __construct( $tp_id, $batch_id, $state, $revision = 1, $ts_status = null ) { $this->tp_id = (int) $tp_id; $this->batch_id = (int) $batch_id; if ( ! in_array( $state, WPML_TP_Job_States::get_possible_states(), true ) ) { $state = 'any'; } $this->status = $state; $this->revision = (int) $revision; $this->ts_status = $ts_status; } /** * @return int */ public function get_tp_id() { return $this->tp_id; } /** * @return int */ public function get_batch_id() { return $this->batch_id; } /** * @return string */ public function get_status() { return $this->status; } /** * @return int */ public function get_revision() { return $this->revision; } /** * @return WPML_TM_Job_TS_Status|null */ public function get_ts_status() { return $this->ts_status; } } api/class-wpml-tp-api-request.php 0000644 00000006773 14721654666 0013024 0 ustar 00 <?php use WPML\FP\Obj; use WPML\FP\Str; class WPML_TP_API_Request { const API_VERSION = 1.1; /** @var string */ private $url; /** @var array */ private $params = array( 'api_version' => self::API_VERSION ); /** @var string */ private $method = 'GET'; /** @var bool */ private $has_api_response = true; /** * @param string $url */ public function __construct( $url ) { if ( empty( $url ) ) { throw new InvalidArgumentException( 'Url cannot be empty' ); } // If we get absolute url(like XLIFF download url from TP) it can already contain // get parameters in the query string, so we should parse them correctly in such case. if ( Str::startsWith( 'http://', $url ) || Str::startsWith( 'https://', $url ) ) { $urlParts = wp_parse_url( $url ); if ( Obj::has( 'query', $urlParts ) && is_string( $urlParts['query'] ) ) { $params = explode( '&', $urlParts['query'] ); $params = array_reduce( $params, function( $params, $param ) { $paramParts = explode( '=', $param ); $params[ $paramParts[0] ] = $paramParts[1]; return $params; }, [] ); $this->params = array_merge( $this->params, $params ); $this->url = explode( '?', $url )[0]; } else { $this->url = $url; } } else { // This is the default case. $this->url = $url; } } /** * @param array $params */ public function set_params( array $params ) { $this->params = array_merge( $this->params, $params ); } /** * @param string $method */ public function set_method( $method ) { if ( ! in_array( $method, array( 'GET', 'POST', 'PUT', 'DELETE', 'HEAD' ), true ) ) { throw new InvalidArgumentException( 'HTTP request method has invalid value' ); } $this->method = $method; } /** * @param bool $has_api_response */ public function set_has_api_response( $has_api_response ) { $this->has_api_response = (bool) $has_api_response; } /** * @return string */ public function get_url() { $url = $this->url; if ( $this->get_params() ) { list( $url, $params_used_in_path ) = $this->add_parameters_to_path( $url, $this->get_params() ); if ( 'GET' === $this->get_method() ) { $url = $this->add_query_parameters( $params_used_in_path, $url ); } } return $url; } /** * @return array */ public function get_params() { return $this->params; } /** * @return string */ public function get_method() { return $this->method; } /** * @return bool */ public function has_api_response() { return $this->has_api_response; } private function add_parameters_to_path( $url, array $params ) { $used_params = array(); if ( preg_match_all( '/\{.+?\}/', $url, $symbs ) ) { foreach ( $symbs[0] as $symb ) { $without_braces = preg_replace( '/\{|\}/', '', $symb ); if ( preg_match_all( '/\w+/', $without_braces, $indexes ) ) { foreach ( $indexes[0] as $index ) { if ( isset( $params[ $index ] ) ) { $used_params[] = $index; $value = $params[ $index ]; $url = preg_replace( preg_quote( "/$symb/" ), $value, $url ); } } } } } return array( $url, $used_params ); } /** * @param $params_used_in_path * @param $url * * @return string */ private function add_query_parameters( $params_used_in_path, $url ) { $url .= '?' . preg_replace( '/\%5B\d+\%5D/', '%5B%5D', wpml_http_build_query( array_diff_key( $this->get_params(), array_fill_keys( $params_used_in_path, 1 ) ) ) ); return $url; } } api/class-wpml-tp-api-exception.php 0000644 00000001664 14721654666 0013324 0 ustar 00 <?php class WPML_TP_API_Exception extends Exception { public function __construct( $message, WPML_TP_API_Request $request = null, $response = null ) { if ( $request ) { $message .= ' ' . $this->get_exception_message( $request->get_url(), $request->get_method(), $request->get_params(), $response ); } parent::__construct( $message ); } private function get_exception_message( $url, $method, $params, $response ) { return 'Details: |' . ' url: ' . '`' . $url . '`' . ' method: ' . '`' . $method . '`' . ' param: ' . '`' . json_encode( $this->filter_params( $params ) ) . '`' . ' response: ' . '`' . json_encode( $response ) . '`'; } /** * @param array $params * * @return array mixed */ private function filter_params( $params ) { return wpml_collect( $params )->forget( 'accesskey' )->toArray(); } } api/class-wpml-tp-services.php 0000644 00000000753 14721654666 0012400 0 ustar 00 <?php class WPML_TP_Services { public function get_current_project() { return TranslationProxy::get_current_project(); } public function get_current_service() { return TranslationProxy::get_current_service(); } /** * @param $service_id * @param bool $custom_fields * * @throws WPMLTranslationProxyApiException */ public function select_service( $service_id, $custom_fields = false ) { TranslationProxy::select_service( $service_id, $custom_fields ); } } api/class-wpml-tp-project-api.php 0000644 00000005517 14721654666 0012775 0 ustar 00 <?php use WPML\TM\TranslationProxy\Services\Project\Project; use WPML\TM\TranslationProxy\Services\Project\SiteDetails; class WPML_TP_Project_API extends WPML_TP_API { const API_VERSION = 1.1; const PROJECTS_ENDPOINT = '/projects.json'; /** * @throws WPML_TP_API_Exception */ public function refresh_language_pairs() { $this->log( 'Refresh language pairs -> Request sent' ); $request = new WPML_TP_API_Request( self::PROJECTS_ENDPOINT ); $request->set_method( 'PUT' ); $request->set_params( [ 'project' => [ 'refresh_language_pairs' => 1 ], 'refresh_language_pairs' => 1, 'project_id' => $this->project->get_id(), 'accesskey' => $this->project->get_access_key(), ] ); $this->client->send_request( $request ); } /** * @param stdClass $service * @param SiteDetails $site_details * * @return stdClass * @throws WPML_TP_API_Exception */ public function create_project( \stdClass $service, SiteDetails $site_details ) { $project_data = array_merge( $site_details->getBlogInfo(), [ 'delivery_method' => $site_details->getDeliveryMethod(), 'sitekey' => WP_Installer_API::get_site_key( 'wpml' ), 'client_external_id' => WP_Installer_API::get_ts_client_id(), ] ); $params = [ 'api_version' => self::API_VERSION, 'service' => [ 'id' => $service->id ], 'project' => $project_data, 'custom_fields' => $service->custom_fields_data, 'client' => $site_details->getClientData(), 'linked_by' => \TranslationProxy::get_service_linked_by_suid( $service->suid ), ]; $request = new WPML_TP_API_Request( self::PROJECTS_ENDPOINT ); $request->set_method( 'POST' ); $request->set_params( $params ); return $this->client->send_request( $request ); } /** * @param Project $project * @param \stdClass $credentials * * @throws WPML_TP_API_Exception */ public function update_project_credentials( Project $project, \stdClass $credentials ) { $request = new WPML_TP_API_Request( self::PROJECTS_ENDPOINT ); $request->set_method( 'PUT' ); $request->set_params( [ 'api_version' => self::API_VERSION, 'accesskey' => $project->accessKey, 'project' => [ 'custom_fields' => (array) $credentials, ], ] ); $this->client->send_request( $request ); } /** * @param Project $project * * @return array|mixed|stdClass|string * @throws WPML_TP_API_Exception */ public function get_extra_fields( Project $project ) { $params = [ 'accesskey' => $project->accessKey, 'api_version' => self::API_VERSION, 'project_id' => $project->id, ]; $request = new WPML_TP_API_Request( '/projects/{project_id}/extra_fields.json' ); $request->set_method( 'GET' ); $request->set_params( $params ); return $this->client->send_request( $request ); } } api/class-wpml-tp-xliff-api.php 0000644 00000003324 14721654666 0012431 0 ustar 00 <?php use WPML\FP\Obj; class WPML_TP_XLIFF_API extends WPML_TP_API { /** @var WPML_TP_Xliff_Parser */ private $xliff_parser; /** @var WPML_TP_Jobs_API */ private $jobs_api; public function __construct( WPML_TP_API_Client $client, WPML_TP_Project $project, WPML_TP_API_Log_Interface $logger, WPML_TP_Xliff_Parser $xliff_parser, WPML_TP_Jobs_API $jobs_api ) { parent::__construct( $client, $project, $logger ); $this->xliff_parser = $xliff_parser; $this->jobs_api = $jobs_api; } /** * @param int $tp_job_id * @param bool $parse * * @return WPML_TP_Translation_Collection|string * @throws WPML_TP_API_Exception */ public function get_remote_translations( $tp_job_id, $parse = true ) { try { $download_url = $this->jobs_api->get_translated_xliff_download_url( $tp_job_id ); } catch ( \WPML_TP_API_Exception $e ) { // Use the old fashioned way if the url cannot be retrieved via the Translation Proxy API $download_url = '/jobs/{job_id}/xliff.json'; } $request = new WPML_TP_API_Request( $download_url ); $request->set_params( array( 'job_id' => $tp_job_id, 'accesskey' => $this->project->get_access_key(), ) ); $result = $this->client->send_request( $request ); if ( empty( $result ) || false === strpos( $result, 'xliff' ) ) { throw new WPML_TP_API_Exception( 'XLIFF file could not be fetched for tp_job: ' . $tp_job_id, $request ); } $result = apply_filters( 'wpml_tm_data_from_pro_translation', $result ); if ( ! $parse ) { return $result; } $xliff = @simplexml_load_string( $result ); if ( ! $xliff ) { throw new WPML_TP_API_Exception( 'XLIFF file could not be parsed.' ); } return $this->xliff_parser->parse( $xliff ); } } api/class-wpml-tp-xliff-parser.php 0000644 00000003606 14721654666 0013157 0 ustar 00 <?php class WPML_TP_Xliff_Parser { /** @var WPML_TM_Validate_HTML $validate_html */ private $validate_html; /** * WPML_TP_Xliff_Parser constructor. * * @param WPML_TM_Validate_HTML $validate_html */ public function __construct( WPML_TM_Validate_HTML $validate_html ) { $this->validate_html = $validate_html; } /** * @param SimpleXMLElement $xliff * * @return WPML_TP_Translation_Collection */ public function parse( SimpleXMLElement $xliff ) { $source_lang = (string) $xliff->file->attributes()->{'source-language'}; $target_lang = (string) $xliff->file->attributes()->{'target-language'}; $translations = array(); foreach ( $xliff->file->body->children() as $node ) { $source = $this->get_cdata_value( $node, 'source' ); $target = $this->get_cdata_value( $node, 'target' ); $sourceRestored = $this->validate_html->restore_html( $source ); $targetRestored = $this->validate_html->restore_html( $target ); $translations[] = new WPML_TP_Translation( (string) $node->attributes()->id, ( false !== $sourceRestored ) ? $sourceRestored : $source, ( false !== $targetRestored ) ? $targetRestored : $target ); } return new WPML_TP_Translation_Collection( $translations, $source_lang, $target_lang ); } /** * @param SimpleXMLElement $xliff_node * @param string $field * * @return string */ protected function get_cdata_value( SimpleXMLElement $xliff_node, $field ) { $value = ''; if ( isset( $xliff_node->$field->mrk ) ) { $value = (string) $xliff_node->$field->mrk; } elseif ( isset( $xliff_node->$field ) ) { $value = (string) $xliff_node->$field; } return self::restore_new_line( $value ); } /** * @param string $string * * @return string */ public static function restore_new_line( $string ) { return preg_replace( '/<br class="xliff-newline"\s*\/>/i', "\n", $string ); } } api/class-wpml-tp-api-log-interface.php 0000644 00000000143 14721654666 0014034 0 ustar 00 <?php interface WPML_TP_API_Log_Interface { public function log( $action, $data = array() ); } api/class-wpml-tp-batch-sync-api.php 0000644 00000002412 14721654666 0013351 0 ustar 00 <?php class WPML_TP_Batch_Sync_API extends WPML_TP_API { const INIT_SYNC = '/batches/sync.json'; const CHECK_STATUS = '/batches/sync/status.json'; /** * @param array $batch_ids * * @return int[] * @throws WPML_TP_API_Exception */ public function init_synchronization( array $batch_ids ) { $request = new WPML_TP_API_Request( self::INIT_SYNC ); $request->set_params( array( 'batch_id' => $batch_ids, 'accesskey' => $this->project->get_access_key(), ) ); return $this->handle_response( $request ); } /** * @return int[] * @throws WPML_TP_API_Exception */ public function check_progress() { $request = new WPML_TP_API_Request( self::CHECK_STATUS ); $request->set_params( array( 'accesskey' => $this->project->get_access_key() ) ); return $this->handle_response( $request ); } /** * @param WPML_TP_API_Request $request * * @return array * @throws WPML_TP_API_Exception */ private function handle_response( WPML_TP_API_Request $request ) { $result = $this->client->send_request( $request, true ); if ( empty( $result ) || ! isset( $result->queued_batches ) ) { throw new WPML_TP_API_Exception( 'Batch synchronization could not be initialized' ); } return array_map( 'intval', $result->queued_batches ); } } api/class-wpml-tp-api.php 0000644 00000001066 14721654666 0011324 0 ustar 00 <?php abstract class WPML_TP_API { /** @var WPML_TP_API_Client */ protected $client; /** @var WPML_TP_Project */ protected $project; /** @var WPML_TP_API_Log_Interface */ protected $logger; public function __construct( WPML_TP_API_Client $client, WPML_TP_Project $project, WPML_TP_API_Log_Interface $logger = null ) { $this->client = $client; $this->project = $project; $this->logger = $logger; } protected function log( $action, array $params = array() ) { if ( null !== $this->logger ) { $this->logger->log( $action, $params ); } } } class-wpml-translationproxy-com-log.php 0000644 00000003527 14721654666 0014360 0 ustar 00 <?php class WPML_TranslationProxy_Com_Log { private static $wrapped_class; /** * @return WPML_TranslationProxy_Communication_Log */ private static function get_wrapped_class_instance() { if ( null === self::$wrapped_class ) { global $sitepress; self::$wrapped_class = new WPML_TranslationProxy_Communication_Log( $sitepress ); } return self::$wrapped_class; } public static function log_call( $url, $params ) { self::get_wrapped_class_instance()->log_call( $url, $params ); } public static function get_keys_to_block() { return self::get_wrapped_class_instance()->get_keys_to_block(); } public static function log_response( $response ) { self::get_wrapped_class_instance()->log_response( $response ); } public static function log_error( $message ) { self::get_wrapped_class_instance()->log_error( $message ); } public static function log_xml_rpc( $data ) { self::get_wrapped_class_instance()->log_xml_rpc( $data ); } public static function get_log() { return self::get_wrapped_class_instance()->get_log(); } public static function clear_log() { self::get_wrapped_class_instance()->clear_log(); } public static function is_logging_enabled() { return self::get_wrapped_class_instance()->is_logging_enabled(); } /** * @param string|array|stdClass $params * * @return array|stdClass */ public static function sanitize_data( $params ) { return self::get_wrapped_class_instance()->sanitize_data( $params ); } /** * @param $url * * @return mixed */ public static function sanitize_url( $url ) { return self::get_wrapped_class_instance()->sanitize_url( $url ); } public static function set_logging_state( $state ) { self::get_wrapped_class_instance()->set_logging_state( $state ); } public static function add_com_log_link() { self::get_wrapped_class_instance()->add_com_log_link(); } } models/wpml-tp-extra-field.php 0000644 00000000335 14721654666 0012364 0 ustar 00 <?php /** * @author OnTheGo Systems */ class WPML_TP_Extra_Field { /** @var string */ public $type = 'text'; /** @var string */ public $label; /** @var string */ public $name; /** @var array */ public $items; } class-wpml-update-pickup-method.php 0000644 00000001522 14721654666 0013407 0 ustar 00 <?php class WPML_Update_PickUp_Method { private $sitepress; public function __construct( $sitepress ) { $this->sitepress = $sitepress; } public function update_pickup_method( $data, $project = false ) { $method = isset( $data['icl_translation_pickup_method'] ) ? intval( $data['icl_translation_pickup_method'] ) : null; $iclsettings['translation_pickup_method'] = $method; $response = 'ok'; try { if ( $project ) { $project->set_delivery_method( ICL_PRO_TRANSLATION_PICKUP_XMLRPC == $method ? 'xmlrpc' : 'polling' ); $this->sitepress->save_settings( $iclsettings ); } elseif ( ICL_PRO_TRANSLATION_PICKUP_XMLRPC == $method ) { $response = 'no-ts'; } } catch ( RuntimeException $e ) { $response = 'cant-update'; } return $response; } }
| ver. 1.4 |
Github
|
.
| PHP 7.4.3-4ubuntu2.24 | Генерация страницы: 0.02 |
proxy
|
phpinfo
|
Настройка