Lingotek Translation - Version 1.4.5

Version Description

(2019-12-3) = * Removed Translation Modal * Changed API to be compatible with new Lingotek Update Document * Updated delete functionality

Download this release

Release Info

Developer elliothanna
Plugin Icon 128x128 Lingotek Translation
Version 1.4.5
Comparing to
See all releases

Code changes from version 1.4.4 to 1.4.5

admin/actions.php CHANGED
@@ -80,9 +80,9 @@ abstract class Lingotek_Actions {
80
  public function __construct( $type ) {
81
  // confirm message.
82
  self::$confirm_message = sprintf( ' onclick = "return confirm(\'%s\');"', __( 'You are about to overwrite existing translations. Are you sure?', 'lingotek-translation' ) );
83
- self::$confirm_delete = sprintf(' onclick = "return confirm(\'%s\');"', __( 'You are about to delete existing translations from your Lingotek community. Are you sure?', 'lingotek-translation' ) );
84
  self::$confirm_cancel = sprintf(' onclick = "return confirm(\'%s\');"', __( 'You are about to cancel existing translations in your Lingotek community. Are you sure?', 'lingotek-translation' ) );
85
- self::$confirm_delete_translation = sprintf(' onclick = "return confirm(\'%s\');"', __( 'You are about to delete this translation from your Lingotek community. Are you sure?', 'lingotek-translation' ) );
86
  self::$confirm_cancel_translation = sprintf(' onclick = "return confirm(\'%s\');"', __( 'You are about to cancel this translation in your Lingotek community. Are you sure?', 'lingotek-translation' ) );
87
  // row actions.
88
  self::$actions = array(
@@ -221,8 +221,6 @@ abstract class Lingotek_Actions {
221
  }
222
  add_action( 'wp_ajax_lingotek_progress_' . $this->type . '_' . $action , array( &$this, 'ajax_' . $action ) );
223
  }
224
-
225
- add_action( 'wp_ajax_lingotek_upload_with_target', array(&$this, 'ajax_upload_with_target'));
226
  }
227
 
228
  /**
@@ -491,9 +489,6 @@ abstract class Lingotek_Actions {
491
  $desc_array = $document->desc_array;
492
  unset( $desc_array['lingotek'] );
493
  $data = array( $this->type => $id, 'action' => 'upload' );
494
- if ('edited' !== $document->status){
495
- $data['show_target_dialog'] = 1;
496
- }
497
  if ( count( $desc_array ) >= 2 ) {
498
  $actions['lingotek-upload'] = $this->get_action_link( $data , true );
499
  } else {
@@ -512,7 +507,7 @@ abstract class Lingotek_Actions {
512
  $actions['lingotek-download'] = $this->get_action_link( array( 'document_id' => $document->document_id, 'action' => 'download' ) );
513
  }
514
  } else {
515
- $actions['lingotek-upload'] = $this->get_action_link( array( $this->type => $id, 'show_target_dialog' => 1, 'action' => 'upload' ) );
516
  }
517
  } elseif ( isset( $document->translations ) ) {
518
  // translations to download ?
@@ -548,7 +543,7 @@ abstract class Lingotek_Actions {
548
  $actions['lingotek-status'] = $this->get_action_link( array( 'document_id' => $document->document_id, 'action' => 'status' ) );
549
  }
550
  } elseif ( empty( $document->source ) ) {
551
- $actions['lingotek-upload'] = $this->get_action_link( array( $this->type => $id, 'show_target_dialog' => 1, 'action' => 'upload' ), true );
552
  }
553
 
554
  $target_locale = $this->get_language($target_id)->locale;
@@ -583,13 +578,12 @@ abstract class Lingotek_Actions {
583
  if ( ! empty( $text ) ) {
584
  printf( '<div id="lingotek-progressdialog" style="display:none" title="%s"><div id="lingotek-progressbar"></div></div>', esc_html( $text ) );
585
  }
586
- printf( '<div id="lingotek-targetselector" style="display:none" title="New Document">Choose which targets you wish to upload with this document<select id="target-select"></select></div>');
587
 
588
  return $bulk_actions;
589
  }
590
 
591
  /**
592
- * Outputs javascript data for progress.js and target-dialog.js
593
  * wp_localize_script($handle, $name, $data) $handle needs to be lingotek_myhandle
594
  * where myhandle is handle of script you loaded previously with wp_enqueue_script (probably in admin.php)
595
  *
@@ -597,22 +591,14 @@ abstract class Lingotek_Actions {
597
  */
598
  public function admin_enqueue_scripts() {
599
  foreach ( array_keys( self::$actions ) as $action ) {
600
- if (null !== filter_input( INPUT_GET, "show_target_dialog") && $action === 'upload' && null!== filter_input( INPUT_GET, "bulk-lingotek-upload")){
601
- wp_localize_script('lingotek_target-dialog', 'lingotek_upload_data', array(
602
- 'sendback' => remove_query_arg( array( "bulk-lingotek-$action", 'ids', 'lingotek_warning', 'show_target_dialog' ), wp_get_referer() ),
603
- 'show' => null !== filter_input( INPUT_GET, 'show_target_dialog'),
604
- 'locales' => array_keys(array_flip( $this->pllm->get_languages_list( array( 'fields' => 'locale' ) ))),
605
- 'bulk' => true,
606
- ));
607
- return;
608
- }
609
- else if ( null !== filter_input( INPUT_GET, "bulk-lingotek-$action" ) ) {
610
  $data = array(
611
  'action' => null === filter_input( INPUT_GET, 'page' ) ? (null === filter_input( INPUT_GET, 'taxonomy' ) ? "post_$action" : "term_$action") : "string_$action",
612
  'taxonomy' => null === filter_input( INPUT_GET, 'taxonomy' ) || ! taxonomy_exists( wp_unslash( filter_input( INPUT_GET, 'taxonomy' ) ) ) ? '' : filter_input( INPUT_GET, 'taxonomy' ),
613
- 'sendback' => remove_query_arg( array( "bulk-lingotek-$action", 'ids', 'lingotek_warning', 'show_target_dialog' , 'locales'), wp_get_referer() ),
614
  'ids' => array_map( 'intval', explode( ',', filter_input( INPUT_GET, 'ids' ) ) ),
615
- 'warning' => null === filter_input( INPUT_GET, 'lingotek_warning' ) ? (null === filter_input(INPUT_GET, 'lingotek_remove') ? '' : __("You are about to $action existing translations from your Lingotek community. Are you sure?", 'lingotek-translation')) : __( 'You are about to overwrite existing translations. Are you sure?', 'lingotek-translation' ),
616
  'nonce' => wp_create_nonce( 'lingotek_progress' ),
617
  );
618
  if (null!== filter_input( INPUT_GET, 'locales')){
@@ -621,23 +607,6 @@ abstract class Lingotek_Actions {
621
  wp_localize_script('lingotek_progress', 'lingotek_data', $data);
622
  return;
623
  }
624
- else if (null !== filter_input( INPUT_GET, "show_target_dialog") && $action === 'upload'){
625
- $locales = array_keys(array_flip( $this->pllm->get_languages_list( array( 'fields' => 'locale' ) )));
626
- $source_locale = filter_input( INPUT_GET, 'source');
627
- if (($key = array_search($source_locale, $locales)) !== false){
628
- array_splice($locales, $key, 1);
629
- }
630
- wp_localize_script('lingotek_target-dialog', 'lingotek_upload_data', array(
631
- 'taxonomy' => null === filter_input( INPUT_GET, 'taxonomy' ) || ! taxonomy_exists( wp_unslash( filter_input( INPUT_GET, 'taxonomy' ) ) ) ? '' : filter_input( INPUT_GET, 'taxonomy' ),
632
- 'sendback' => remove_query_arg( array( 'lingotek-upload', 'show_target_dialog' ), wp_get_referer() ),
633
- 'show' => null !== filter_input( INPUT_GET, 'show_target_dialog'),
634
- 'id' => filter_input( INPUT_GET, 'id'),
635
- 'type' => filter_input( INPUT_GET, 'type'),
636
- 'locales' => $locales,
637
- 'nonce' => wp_create_nonce('lingotek_target_upload'),
638
- ));
639
- return;
640
- }
641
  }
642
  }
643
 
@@ -730,41 +699,6 @@ abstract class Lingotek_Actions {
730
  return true;
731
  }
732
 
733
- /**
734
- * Ajax request to tms for upload doc with target locales
735
- * Requested by target-dialog.js
736
- * Passes in by POST a data object (all string)
737
- * id: document id
738
- * type: page type - post (page, posts), term(category, tag), string (doesn't work currently)
739
- * locales: json array of selectedLocales ex ['zh-CN', 'ja', 'es-AR']
740
- * taxonomy: taxonomy of page (empty for posts, for term its category or post_tag)
741
- *
742
- */
743
- public function ajax_upload_with_target(){
744
- check_ajax_referer( 'lingotek_target_upload', '_lingotek_target_nonce');
745
- $id = (int)filter_input(INPUT_POST, 'id');
746
- $type = filter_input(INPUT_POST, 'type');
747
- //in the received post, locales are in format "['ja','lv]"
748
- //wp locales for changing status of locales to pending
749
- $wp_locales = json_decode(filter_input( INPUT_POST, 'locales'));
750
- //ltk locales for upload api request
751
- $lingotek_locales = array_map('Lingotek::map_to_lingotek_locale', $wp_locales);
752
- $lingotek_locales = array('translation_locale_code' => $lingotek_locales);
753
-
754
- // not sure if pll_locale is ever different from the one selected but it does this in request translation as well
755
- $wp_locales = array_map(array($this->pllm, 'get_language'), $wp_locales);
756
- $wp_locales = array_column($wp_locales, 'locale');
757
-
758
- switch($type){
759
- case 'post':
760
- $this->lgtm->upload_post($id, $lingotek_locales, $wp_locales);
761
- case 'term':
762
- $taxonomy = filter_input( INPUT_POST, 'taxonomy');
763
- $this->lgtm->upload_term($id, $taxonomy, $lingotek_locales, $wp_locales);
764
- }
765
- die();
766
- }
767
-
768
  /**
769
  * Ajax response to download translations and showing progress
770
  *
80
  public function __construct( $type ) {
81
  // confirm message.
82
  self::$confirm_message = sprintf( ' onclick = "return confirm(\'%s\');"', __( 'You are about to overwrite existing translations. Are you sure?', 'lingotek-translation' ) );
83
+ self::$confirm_delete = sprintf(' onclick = "return confirm(\'%s\');"', __( 'Content will be deleted from WordPress. The associated content in the TMS will be cancelled. Are you sure?', 'lingotek-translation' ) );
84
  self::$confirm_cancel = sprintf(' onclick = "return confirm(\'%s\');"', __( 'You are about to cancel existing translations in your Lingotek community. Are you sure?', 'lingotek-translation' ) );
85
+ self::$confirm_delete_translation = sprintf(' onclick = "return confirm(\'%s\');"', __( 'Translation will be deleted from WordPress. The associated translation in the TMS will be cancelled. Are you sure?', 'lingotek-translation' ) );
86
  self::$confirm_cancel_translation = sprintf(' onclick = "return confirm(\'%s\');"', __( 'You are about to cancel this translation in your Lingotek community. Are you sure?', 'lingotek-translation' ) );
87
  // row actions.
88
  self::$actions = array(
221
  }
222
  add_action( 'wp_ajax_lingotek_progress_' . $this->type . '_' . $action , array( &$this, 'ajax_' . $action ) );
223
  }
 
 
224
  }
225
 
226
  /**
489
  $desc_array = $document->desc_array;
490
  unset( $desc_array['lingotek'] );
491
  $data = array( $this->type => $id, 'action' => 'upload' );
 
 
 
492
  if ( count( $desc_array ) >= 2 ) {
493
  $actions['lingotek-upload'] = $this->get_action_link( $data , true );
494
  } else {
507
  $actions['lingotek-download'] = $this->get_action_link( array( 'document_id' => $document->document_id, 'action' => 'download' ) );
508
  }
509
  } else {
510
+ $actions['lingotek-upload'] = $this->get_action_link( array( $this->type => $id, 'action' => 'upload' ) );
511
  }
512
  } elseif ( isset( $document->translations ) ) {
513
  // translations to download ?
543
  $actions['lingotek-status'] = $this->get_action_link( array( 'document_id' => $document->document_id, 'action' => 'status' ) );
544
  }
545
  } elseif ( empty( $document->source ) ) {
546
+ $actions['lingotek-upload'] = $this->get_action_link( array( $this->type => $id, 'action' => 'upload' ), true );
547
  }
548
 
549
  $target_locale = $this->get_language($target_id)->locale;
578
  if ( ! empty( $text ) ) {
579
  printf( '<div id="lingotek-progressdialog" style="display:none" title="%s"><div id="lingotek-progressbar"></div></div>', esc_html( $text ) );
580
  }
 
581
 
582
  return $bulk_actions;
583
  }
584
 
585
  /**
586
+ * Outputs javascript data for progress.js
587
  * wp_localize_script($handle, $name, $data) $handle needs to be lingotek_myhandle
588
  * where myhandle is handle of script you loaded previously with wp_enqueue_script (probably in admin.php)
589
  *
591
  */
592
  public function admin_enqueue_scripts() {
593
  foreach ( array_keys( self::$actions ) as $action ) {
594
+ if ( null !== filter_input( INPUT_GET, "bulk-lingotek-$action" ) ) {
595
+ $action_message = $action === 'delete' ? 'cancel' : $action;
 
 
 
 
 
 
 
 
596
  $data = array(
597
  'action' => null === filter_input( INPUT_GET, 'page' ) ? (null === filter_input( INPUT_GET, 'taxonomy' ) ? "post_$action" : "term_$action") : "string_$action",
598
  'taxonomy' => null === filter_input( INPUT_GET, 'taxonomy' ) || ! taxonomy_exists( wp_unslash( filter_input( INPUT_GET, 'taxonomy' ) ) ) ? '' : filter_input( INPUT_GET, 'taxonomy' ),
599
+ 'sendback' => remove_query_arg( array( "bulk-lingotek-$action", 'ids', 'lingotek_warning', 'locales'), wp_get_referer() ),
600
  'ids' => array_map( 'intval', explode( ',', filter_input( INPUT_GET, 'ids' ) ) ),
601
+ 'warning' => null === filter_input( INPUT_GET, 'lingotek_warning' ) ? (null === filter_input(INPUT_GET, 'lingotek_remove') ? '' : __("You are about to $action_message existing translations from your Lingotek community. Are you sure?", 'lingotek-translation')) : __( 'You are about to overwrite existing translations. Are you sure?', 'lingotek-translation' ),
602
  'nonce' => wp_create_nonce( 'lingotek_progress' ),
603
  );
604
  if (null!== filter_input( INPUT_GET, 'locales')){
607
  wp_localize_script('lingotek_progress', 'lingotek_data', $data);
608
  return;
609
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
610
  }
611
  }
612
 
699
  return true;
700
  }
701
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
702
  /**
703
  * Ajax response to download translations and showing progress
704
  *
admin/admin.php CHANGED
@@ -197,7 +197,6 @@ class Lingotek_Admin {
197
  $scripts = array(
198
  'progress' => array( array( 'edit', 'upload', 'edit-tags', 'translation_page_lingotek-translation_manage', 'translation_page_lingotek-translation_settings' ), array( 'jquery-ui-progressbar', 'jquery-ui-dialog', 'wp-ajax-response' ), 1 ),
199
  'updater' => array( array( 'edit', 'upload', 'edit-tags' ), array( 'jquery-ui-progressbar', 'jquery-ui-dialog', 'wp-ajax-response' ), 1 ),
200
- 'target-dialog' => array( array( 'edit', 'upload', 'edit-tags' ), array( 'jquery-ui-dialog', 'jquery-ui-autocomplete' ), 1),
201
  );
202
 
203
  $styles = array(
197
  $scripts = array(
198
  'progress' => array( array( 'edit', 'upload', 'edit-tags', 'translation_page_lingotek-translation_manage', 'translation_page_lingotek-translation_settings' ), array( 'jquery-ui-progressbar', 'jquery-ui-dialog', 'wp-ajax-response' ), 1 ),
199
  'updater' => array( array( 'edit', 'upload', 'edit-tags' ), array( 'jquery-ui-progressbar', 'jquery-ui-dialog', 'wp-ajax-response' ), 1 ),
 
200
  );
201
 
202
  $styles = array(
admin/filters-columns.php CHANGED
@@ -12,7 +12,6 @@ class Lingotek_Filters_Columns extends PLL_Admin_Filters_Columns {
12
  * @var object
13
  */
14
  public $lgtm;
15
-
16
  /**
17
  * Constructor
18
  *
@@ -24,7 +23,6 @@ class Lingotek_Filters_Columns extends PLL_Admin_Filters_Columns {
24
  parent::__construct( $polylang );
25
 
26
  $this->lgtm = &$GLOBALS['wp_lingotek']->model;
27
-
28
  // FIXME remove quick edit and bulk edit for now waiting for a solution to remove it only for uploaded documents.
29
  remove_filter( 'quick_edit_custom_box', array( &$this, 'quick_edit_custom_box' ), 10, 2 );
30
  remove_filter( 'bulk_edit_custom_box', array( &$this, 'quick_edit_custom_box' ), 10, 2 );
@@ -47,7 +45,8 @@ class Lingotek_Filters_Columns extends PLL_Admin_Filters_Columns {
47
  $end = array_slice( $columns, $n );
48
  $columns = array_slice( $columns, 0, $n );
49
  }
50
-
 
51
  foreach ( $this->model->get_languages_list() as $language ) {
52
  $columns[ 'language_' . $language->locale ] = $language->flag ? $language->flag :
53
  sprintf('<a href="" title="%s">%s</a>',
@@ -59,6 +58,40 @@ class Lingotek_Filters_Columns extends PLL_Admin_Filters_Columns {
59
  return isset( $end ) ? array_merge( $columns, $end ) : $columns;
60
  }
61
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
62
  /**
63
  * Fills the language and translations columns in the posts and taxonomies lists tables
64
  * take care that when doing ajax inline edit, the post or term may not be updated in database yet
@@ -115,7 +148,6 @@ class Lingotek_Filters_Columns extends PLL_Admin_Filters_Columns {
115
  $profile = Lingotek_Model::get_profile( $this->content_type, $language, $object_id );
116
 
117
  $disabled = 'disabled' === $profile['profile'] || !Lingotek::is_allowed_tms_locale($language->lingotek_locale);
118
- // error_log('bool: ' . print_r($disabled, true) . PHP_EOL, 3, '/var/www/html/wp-content/plugins/lingotek-translation/error.log');
119
  // post ready for upload.
120
  if ( $this->lgtm->can_upload( $type, $object_id ) && $object_id === $id ) {
121
  return $disabled ? ('post' === $type ? parent::post_column( $column, $object_id ) : parent::term_column( '', $column, $object_id ))
@@ -169,7 +201,7 @@ class Lingotek_Filters_Columns extends PLL_Admin_Filters_Columns {
169
  }
170
  // no translation.
171
  else {
172
- return '<div class="lingotek-color dashicons dashicons-no"></div>';
173
  }
174
  }
175
 
12
  * @var object
13
  */
14
  public $lgtm;
 
15
  /**
16
  * Constructor
17
  *
23
  parent::__construct( $polylang );
24
 
25
  $this->lgtm = &$GLOBALS['wp_lingotek']->model;
 
26
  // FIXME remove quick edit and bulk edit for now waiting for a solution to remove it only for uploaded documents.
27
  remove_filter( 'quick_edit_custom_box', array( &$this, 'quick_edit_custom_box' ), 10, 2 );
28
  remove_filter( 'bulk_edit_custom_box', array( &$this, 'quick_edit_custom_box' ), 10, 2 );
45
  $end = array_slice( $columns, $n );
46
  $columns = array_slice( $columns, 0, $n );
47
  }
48
+ $this->print_patch_error();
49
+ $this->print_cancel_error();
50
  foreach ( $this->model->get_languages_list() as $language ) {
51
  $columns[ 'language_' . $language->locale ] = $language->flag ? $language->flag :
52
  sprintf('<a href="" title="%s">%s</a>',
58
  return isset( $end ) ? array_merge( $columns, $end ) : $columns;
59
  }
60
 
61
+ private function print_cancel_error() {
62
+ if (get_option('disassociate_source_failed', FALSE)) {
63
+ printf('<div class="notice notice-warning is-dismissible">
64
+ <p>Could not cancel source. Associated documents will not be deleted from WordPress.</p>
65
+ </div>');
66
+ update_option('disassociate_source_failed', FALSE);
67
+ } elseif (get_option('disassociate_target_failed', FALSE)) {
68
+ printf('<div class="notice notice-warning is-dismissible">
69
+ <p>Could not cancel target. Target will not be deleted from WordPress.</p>
70
+ </div>');
71
+ update_option('disassociate_target_failed', FALSE);
72
+ } elseif (get_option('cancel_source_failed', FALSE)) {
73
+ printf('<div class="notice notice-warning is-dismissible">
74
+ <p>Could not cancel source. Process failed or source is already completed. Check TMS for details.</p>
75
+ </div>');
76
+ update_option('cancel_source_failed', FALSE);
77
+ } elseif (get_option('cancel_target_failed', FALSE)) {
78
+ printf('<div class="notice notice-warning is-dismissible">
79
+ <p>Could not cancel target. Process failed or target is already completed. Check TMS for details.</p>
80
+ </div>');
81
+ update_option('cancel_target_failed', FALSE);
82
+ }
83
+ }
84
+
85
+ private function print_patch_error() {
86
+ $lingotek_log_errors = get_option('lingotek_log_errors');
87
+ if (empty($lingotek_log_errors['patch_document_error'])) {
88
+ return;
89
+ }
90
+ printf('<div class="notice notice-error is-dismissible"><p>%s</p></div>', $lingotek_log_errors['patch_document_error']);
91
+ unset($lingotek_log_errors['patch_document_error']);
92
+ update_option('lingotek_log_errors', $lingotek_log_errors);
93
+ }
94
+
95
  /**
96
  * Fills the language and translations columns in the posts and taxonomies lists tables
97
  * take care that when doing ajax inline edit, the post or term may not be updated in database yet
148
  $profile = Lingotek_Model::get_profile( $this->content_type, $language, $object_id );
149
 
150
  $disabled = 'disabled' === $profile['profile'] || !Lingotek::is_allowed_tms_locale($language->lingotek_locale);
 
151
  // post ready for upload.
152
  if ( $this->lgtm->can_upload( $type, $object_id ) && $object_id === $id ) {
153
  return $disabled ? ('post' === $type ? parent::post_column( $column, $object_id ) : parent::term_column( '', $column, $object_id ))
201
  }
202
  // no translation.
203
  else {
204
+ return '<div class="lingotek-color dashicons dashicons-no"></div>';
205
  }
206
  }
207
 
admin/filters-post.php CHANGED
@@ -267,6 +267,9 @@ class Lingotek_Filters_Post extends PLL_CRUD_Posts {
267
  * @param int $post_id
268
  */
269
  public function trash_post($post_id) {
 
 
 
270
  $group = $this->lgtm->get_group('post', $post_id);
271
 
272
  if (isset($this->lingotek_prefs['trash_linked_content']['enabled'])) {
267
  * @param int $post_id
268
  */
269
  public function trash_post($post_id) {
270
+ if (get_option("ignore_delete_pref", FALSE)) {
271
+ return;
272
+ }
273
  $group = $this->lgtm->get_group('post', $post_id);
274
 
275
  if (isset($this->lingotek_prefs['trash_linked_content']['enabled'])) {
admin/manage/view-edit-profile.php CHANGED
@@ -116,13 +116,15 @@ unset($settings['secondary_filter_id']['options'][$primary_filter_id]);
116
 
117
  <h3><?php _e('Target languages', 'lingotek-translation'); ?></h3>
118
 
119
- <table class="form-table"><?php
120
  unset($settings['upload']); // we don't want this for target languages
121
  unset($settings['project_id']); // FIXME disable the possibility to have a different project per target language for now
122
  // Filters not needed for target languages
123
  unset($settings['primary_filter_id']);
124
  unset($settings['secondary_filter_id']);
125
-
 
 
126
  foreach ($this->pllm->get_languages_list() as $language) { ?>
127
  <tr>
128
  <th scope="row"><?php printf('<label for="%s">%s (%s)</label>', esc_attr($language->slug) , esc_html($language->name), esc_attr($language->locale)); ?><?php
@@ -143,20 +145,43 @@ unset($settings['secondary_filter_id']['options'][$primary_filter_id]);
143
  '' //__('Show', 'lingotek-translation')
144
 
145
  ); ?></th>
146
- <td><?php
147
  printf('<select name="targets[%1$s]" id="targets[%1$s]" onchange="%2$s">',
148
  esc_attr($language->slug),
149
  "
150
  dl = document.getElementById('{$language->slug}_details_link');
151
  d = document.getElementById('{$language->slug}_details');
 
152
  if ('custom' == this.value) {
153
  d.style.display = dl.style.display = '';
154
  dl.className = 'dashicons dashicons-arrow-down';
 
 
 
155
  }
156
  else {
157
  d.style.display = dl.style.display = 'none';
158
  dl.className = 'dashicons dashicons-arrow-right';
159
- }"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
160
  );
161
  foreach ($target_settings as $id => $title) {
162
  $selected = (empty($profile['targets'][$language->slug]) && 'default' == $id) || (isset($profile['targets'][$language->slug]) && $profile['targets'][$language->slug] == $id) ? 'selected="selected"' : '';
@@ -165,6 +190,31 @@ unset($settings['secondary_filter_id']['options'][$primary_filter_id]);
165
  </select>
166
 
167
  </td>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
168
  </tr>
169
  <tr id="<?php echo esc_attr($language->slug); ?>_details" style="display:none;">
170
  <td colspan="2" style="padding:0;">
@@ -193,6 +243,31 @@ unset($settings['secondary_filter_id']['options'][$primary_filter_id]);
193
  </tr>
194
  <?php
195
  } ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
196
  </table>
197
 
198
  <?php $metadata = array(
116
 
117
  <h3><?php _e('Target languages', 'lingotek-translation'); ?></h3>
118
 
119
+ <table class="form-table target-table"><?php
120
  unset($settings['upload']); // we don't want this for target languages
121
  unset($settings['project_id']); // FIXME disable the possibility to have a different project per target language for now
122
  // Filters not needed for target languages
123
  unset($settings['primary_filter_id']);
124
  unset($settings['secondary_filter_id']);
125
+ ?>
126
+ <?php
127
+ $custom_profile_chosen = false;
128
  foreach ($this->pllm->get_languages_list() as $language) { ?>
129
  <tr>
130
  <th scope="row"><?php printf('<label for="%s">%s (%s)</label>', esc_attr($language->slug) , esc_html($language->name), esc_attr($language->locale)); ?><?php
145
  '' //__('Show', 'lingotek-translation')
146
 
147
  ); ?></th>
148
+ <td class="target-table-td"><?php
149
  printf('<select name="targets[%1$s]" id="targets[%1$s]" onchange="%2$s">',
150
  esc_attr($language->slug),
151
  "
152
  dl = document.getElementById('{$language->slug}_details_link');
153
  d = document.getElementById('{$language->slug}_details');
154
+ var target_warning = document.getElementById('target_warning');
155
  if ('custom' == this.value) {
156
  d.style.display = dl.style.display = '';
157
  dl.className = 'dashicons dashicons-arrow-down';
158
+ if (target_warning) {
159
+ target_warning.style.display = 'block';
160
+ }
161
  }
162
  else {
163
  d.style.display = dl.style.display = 'none';
164
  dl.className = 'dashicons dashicons-arrow-right';
165
+ }
166
+ var target_checkbox = document.getElementById('target_locales[{$language->slug}]');
167
+ var label = document.getElementById('target_locales_label[{$language->slug}]');
168
+ if ('disabled' === this.value || 'copy' === this.value) {
169
+ if (target_checkbox) {
170
+ target_checkbox.checked = false;
171
+ target_checkbox.style.display = 'none';
172
+ }
173
+ if (label) {
174
+ label.style.display = 'none';
175
+ }
176
+ return;
177
+ }
178
+ if (target_checkbox) {
179
+ target_checkbox.style.display = 'inline-block';
180
+ }
181
+ if (label) {
182
+ label.style.display = 'inline';
183
+ }
184
+ "
185
  );
186
  foreach ($target_settings as $id => $title) {
187
  $selected = (empty($profile['targets'][$language->slug]) && 'default' == $id) || (isset($profile['targets'][$language->slug]) && $profile['targets'][$language->slug] == $id) ? 'selected="selected"' : '';
190
  </select>
191
 
192
  </td>
193
+ <?php
194
+ if (isset($profile['targets'][$language->slug]) && 'custom' === $profile['targets'][$language->slug]) {
195
+ $custom_profile_chosen = true;
196
+ }
197
+ $checked = empty($profile['target_locales'][$language->slug]) ? '' : 'checked="checked"';
198
+ $display = '';
199
+ if (isset($profile['targets'][$language->slug]) && ('disabled' === $profile['targets'][$language->slug] || 'copy' === $profile['targets'][$language->slug])) {
200
+ $display = 'style="display:none;"';
201
+ }
202
+ ?>
203
+ <td><input
204
+ <?php echo $checked; ?>
205
+ <?php echo $display; ?>
206
+ type="checkbox"
207
+ class="ltk-target-checkbox"
208
+ value="<?php echo esc_attr($language->lingotek_locale); ?>"
209
+ id="target_locales[<?php echo esc_attr($language->slug); ?>]"
210
+ name="target_locales[<?php echo esc_attr($language->slug); ?>]"
211
+ >
212
+ <label
213
+ <?php echo $display; ?>
214
+ for="target_locales[<?php echo esc_attr($language->slug); ?>]"
215
+ id="target_locales_label[<?php echo esc_attr($language->slug); ?>]">Auto-request with document upload
216
+ </label>
217
+ </td>
218
  </tr>
219
  <tr id="<?php echo esc_attr($language->slug); ?>_details" style="display:none;">
220
  <td colspan="2" style="padding:0;">
243
  </tr>
244
  <?php
245
  } ?>
246
+ <tr>
247
+ <td></td>
248
+ <td class="target-table-td"></td>
249
+ <td>
250
+ <?php
251
+ $select_all_on_change = "
252
+ var elements = document.getElementsByClassName('ltk-target-checkbox');
253
+ var checked = event.target && event.target.checked;
254
+ for (var i = 0; i < elements.length; ++i) {
255
+ if (elements[i].style.display !== 'none') {
256
+ elements[i].checked = checked;
257
+ }
258
+ }
259
+ ";
260
+ ?>
261
+ <input type="checkbox" name="target_select_all" id="target_select_all" onchange="<?php echo $select_all_on_change; ?>">
262
+ <label for="target_select_all">Select All</label></td>
263
+ </tr>
264
+ <?php
265
+ $target_warning = $custom_profile_chosen ? '' : 'style="display:none"';
266
+ ?>
267
+ <tr>
268
+ <td colspan="3"><span id='target_warning' <?php echo $target_warning; ?>><b>Note:</b> If any targets are selected to be uploaded and at the same time a custom workflow is selected
269
+ for any of them, all targets to be uploaded must have a non-project-default workflow selected.</span></td>
270
+ </tr>
271
  </table>
272
 
273
  <?php $metadata = array(
admin/manage/view-profiles.php CHANGED
@@ -41,10 +41,11 @@ if (!empty($_POST)) {
41
  unset($profiles[$profile_id][$key]);
42
  }
43
 
 
44
  foreach ($this->pllm->get_languages_list() as $language) {
45
  switch($_POST['targets'][$language->slug]) {
46
  case 'custom':
47
- foreach (array('download', 'project_id', 'workflow_id') as $key) {
48
  if (isset($_POST['custom'][$key][$language->slug]) && in_array($_POST['custom'][$key][$language->slug], array_keys($settings[$key]['options']))) {
49
  $profiles[$profile_id]['custom'][$key][$language->slug] = $_POST['custom'][$key][$language->slug];
50
  }
@@ -53,17 +54,27 @@ if (!empty($_POST)) {
53
  unset($profiles[$profile_id]['custom'][$key][$language->slug]);
54
  }
55
  }
 
56
 
57
  case 'disabled':
58
  case 'copy':
59
  $profiles[$profile_id]['targets'][$language->slug] = $_POST['targets'][$language->slug];
 
 
 
60
  break;
61
 
62
  case 'default':
63
  unset($profiles[$profile_id]['targets'][$language->slug]);
 
 
 
64
  }
65
  }
66
 
 
 
 
67
  // hardcode default values for automatic and manual profiles as the process above emptied them
68
  $profiles['automatic']['upload'] = $profiles['automatic']['download'] = 'automatic';
69
  $profiles['manual']['upload'] = $profiles['manual']['download'] = 'manual';
41
  unset($profiles[$profile_id][$key]);
42
  }
43
 
44
+ $custom_profile_keys = array('download', 'project_id', 'workflow_id');
45
  foreach ($this->pllm->get_languages_list() as $language) {
46
  switch($_POST['targets'][$language->slug]) {
47
  case 'custom':
48
+ foreach ($custom_profile_keys as $key) {
49
  if (isset($_POST['custom'][$key][$language->slug]) && in_array($_POST['custom'][$key][$language->slug], array_keys($settings[$key]['options']))) {
50
  $profiles[$profile_id]['custom'][$key][$language->slug] = $_POST['custom'][$key][$language->slug];
51
  }
54
  unset($profiles[$profile_id]['custom'][$key][$language->slug]);
55
  }
56
  }
57
+ break;
58
 
59
  case 'disabled':
60
  case 'copy':
61
  $profiles[$profile_id]['targets'][$language->slug] = $_POST['targets'][$language->slug];
62
+ foreach ($custom_profile_keys as $key) {
63
+ unset($profiles[$profile_id]['custom'][$key][$language->slug]);
64
+ }
65
  break;
66
 
67
  case 'default':
68
  unset($profiles[$profile_id]['targets'][$language->slug]);
69
+ foreach ($custom_profile_keys as $key) {
70
+ unset($profiles[$profile_id]['custom'][$key][$language->slug]);
71
+ }
72
  }
73
  }
74
 
75
+ // Add target locales to request
76
+ $profiles[$profile_id]['target_locales'] = empty($_POST['target_locales']) ? array() : $_POST['target_locales'];
77
+
78
  // hardcode default values for automatic and manual profiles as the process above emptied them
79
  $profiles['automatic']['upload'] = $profiles['automatic']['download'] = 'automatic';
80
  $profiles['manual']['upload'] = $profiles['manual']['download'] = 'manual';
admin/post-actions.php CHANGED
@@ -195,7 +195,6 @@ class Lingotek_Post_actions extends Lingotek_Actions {
195
  }
196
  }
197
  }
198
- $redirect = add_query_arg( 'show_target_dialog', 1, $redirect);
199
 
200
  case 'bulk-lingotek-request':
201
  case 'bulk-lingotek-download':
@@ -218,19 +217,13 @@ class Lingotek_Post_actions extends Lingotek_Actions {
218
  }
219
  $redirect = add_query_arg( $action, 1, $redirect );
220
  $redirect = add_query_arg( 'ids', implode( ',', $post_ids ), $redirect );
221
-
222
  break;
223
 
224
  case 'lingotek-upload':
225
  check_admin_referer( 'lingotek-upload' );
226
  $id = filter_input( INPUT_GET, 'post');
227
  $document = $this->lgtm->get_group('post', $id);
228
- if (!$document || 'edited' !== $document->status){
229
- $redirect = add_query_arg( 'show_target_dialog', 1, $redirect);
230
- } else{
231
- $this->lgtm->upload_post($id);
232
- break;
233
- }
234
  $redirect = add_query_arg( 'id', $id, $redirect);
235
  $redirect = add_query_arg( 'type', 'post', $redirect);
236
  $redirect = add_query_arg( 'source', $this->pllm->post->get_language($id)->locale, $redirect);
@@ -269,7 +262,7 @@ class Lingotek_Post_actions extends Lingotek_Actions {
269
 
270
  $wp_locales = array_map(array($this->pllm, 'get_language'), $wp_locales);
271
  $wp_locales = array_column($wp_locales, 'locale');
272
- $this->lgtm->upload_post($id, $lingotek_locales, $wp_locales);
273
  die();
274
  }
275
 
@@ -360,8 +353,7 @@ class Lingotek_Post_actions extends Lingotek_Actions {
360
  $disassociate_url = wp_nonce_url( add_query_arg( $args, $url ), 'lingotek-delete' );
361
  $remove_post = 'post=' . $post->ID;
362
  $disassociate_url = str_replace( $remove_post, '', $disassociate_url );
363
- $prefs = Lingotek_Model::get_prefs();
364
- $confirm_message = isset( $prefs['delete_document_from_tms'] ) === false ? __( 'Are you sure you want to do this?', 'lingotek-translation' ) : __( 'Are you sure you want to do this? The document will be deleted in your Lingotek community.', 'lingotek-translation' );
365
  $confirm_message = sprintf( ' onclick = "return confirm(\'%s\');"', esc_html( $confirm_message ) );
366
  printf( '<strong>%s</strong><br><br>', esc_html( __( 'Translation Profile', 'lingotek-translation' ) ) );
367
  printf( '<em>%s</em><br>', esc_html( __( 'Delete this content from your Lingotek community to change the Translation Profile', 'lingotek-translation' ) ) );
195
  }
196
  }
197
  }
 
198
 
199
  case 'bulk-lingotek-request':
200
  case 'bulk-lingotek-download':
217
  }
218
  $redirect = add_query_arg( $action, 1, $redirect );
219
  $redirect = add_query_arg( 'ids', implode( ',', $post_ids ), $redirect );
 
220
  break;
221
 
222
  case 'lingotek-upload':
223
  check_admin_referer( 'lingotek-upload' );
224
  $id = filter_input( INPUT_GET, 'post');
225
  $document = $this->lgtm->get_group('post', $id);
226
+ $this->lgtm->upload_post($id);
 
 
 
 
 
227
  $redirect = add_query_arg( 'id', $id, $redirect);
228
  $redirect = add_query_arg( 'type', 'post', $redirect);
229
  $redirect = add_query_arg( 'source', $this->pllm->post->get_language($id)->locale, $redirect);
262
 
263
  $wp_locales = array_map(array($this->pllm, 'get_language'), $wp_locales);
264
  $wp_locales = array_column($wp_locales, 'locale');
265
+ $this->lgtm->upload_post($id);
266
  die();
267
  }
268
 
353
  $disassociate_url = wp_nonce_url( add_query_arg( $args, $url ), 'lingotek-delete' );
354
  $remove_post = 'post=' . $post->ID;
355
  $disassociate_url = str_replace( $remove_post, '', $disassociate_url );
356
+ $confirm_message = __( 'Are you sure you want to do this?', 'lingotek-translation' );
 
357
  $confirm_message = sprintf( ' onclick = "return confirm(\'%s\');"', esc_html( $confirm_message ) );
358
  printf( '<strong>%s</strong><br><br>', esc_html( __( 'Translation Profile', 'lingotek-translation' ) ) );
359
  printf( '<em>%s</em><br>', esc_html( __( 'Delete this content from your Lingotek community to change the Translation Profile', 'lingotek-translation' ) ) );
admin/term-actions.php CHANGED
@@ -136,7 +136,6 @@ class Lingotek_Term_actions extends Lingotek_Actions {
136
  unset($term_ids[$key]);
137
  }
138
  }
139
- $redirect = add_query_arg( 'show_target_dialog', 1, $redirect);
140
  case 'bulk-lingotek-request':
141
  case 'bulk-lingotek-download':
142
  case 'bulk-lingotek-status':
@@ -158,12 +157,7 @@ class Lingotek_Term_actions extends Lingotek_Actions {
158
  check_admin_referer('lingotek-upload');
159
  $id = filter_input( INPUT_GET, 'term');
160
  $document = $this->lgtm->get_group('term', $id);
161
- if (!$document || 'edited' !== $document->status){
162
- $redirect = add_query_arg( 'show_target_dialog', 1, $redirect);
163
- } else{
164
- $this->lgtm->upload_post($id);
165
- break;
166
- }
167
  $redirect = add_query_arg( 'id', filter_input( INPUT_GET, 'term'), $redirect);
168
  $redirect = add_query_arg( 'type', 'term', $redirect);
169
  $redirect = add_query_arg( 'source', $this->pllm->term->get_language($id)->locale, $redirect);
@@ -195,17 +189,9 @@ class Lingotek_Term_actions extends Lingotek_Actions {
195
  public function ajax_upload() {
196
  check_ajax_referer('lingotek_progress', '_lingotek_nonce');
197
  $id = (int)filter_input(INPUT_POST, 'id');
198
- $wp_locales = json_decode(filter_input( INPUT_POST, 'locales'));
199
-
200
- $lingotek_locales = array_map('Lingotek::map_to_lingotek_locale', $wp_locales);
201
- $lingotek_locales = array('translation_locale_code' => $lingotek_locales);
202
-
203
- $wp_locales = array_map(array($this->pllm, 'get_language'), $wp_locales);
204
- $wp_locales = array_column($wp_locales, 'locale');
205
-
206
  $taxonomy = filter_input( INPUT_POST, 'taxonomy');
207
  if (taxonomy_exists($_POST['taxonomy']))
208
- $this->lgtm->upload_term($id, $taxonomy, $lingotek_locales, $wp_locales);
209
  die();
210
  }
211
  }
136
  unset($term_ids[$key]);
137
  }
138
  }
 
139
  case 'bulk-lingotek-request':
140
  case 'bulk-lingotek-download':
141
  case 'bulk-lingotek-status':
157
  check_admin_referer('lingotek-upload');
158
  $id = filter_input( INPUT_GET, 'term');
159
  $document = $this->lgtm->get_group('term', $id);
160
+ $this->lgtm->upload_post($id);
 
 
 
 
 
161
  $redirect = add_query_arg( 'id', filter_input( INPUT_GET, 'term'), $redirect);
162
  $redirect = add_query_arg( 'type', 'term', $redirect);
163
  $redirect = add_query_arg( 'source', $this->pllm->term->get_language($id)->locale, $redirect);
189
  public function ajax_upload() {
190
  check_ajax_referer('lingotek_progress', '_lingotek_nonce');
191
  $id = (int)filter_input(INPUT_POST, 'id');
 
 
 
 
 
 
 
 
192
  $taxonomy = filter_input( INPUT_POST, 'taxonomy');
193
  if (taxonomy_exists($_POST['taxonomy']))
194
+ $this->lgtm->upload_term($id, $taxonomy);
195
  die();
196
  }
197
  }
css/admin.css CHANGED
@@ -33,73 +33,6 @@
33
  .ui-dialog button:hover {
34
  background-color: #007fb4;
35
  }
36
-
37
- /* target select modal text */
38
- .ui-dialog.targetSelector .ui-dialog-content{
39
- font-weight:normal;
40
- font-style :italic;
41
- font-size :11px;
42
- }
43
-
44
- .ui-dialog.targetSelector .ui-dialog-title{
45
- font-size:16px;
46
- }
47
-
48
- .ui-dialog.targetSelector {
49
- padding: 12px 0px 68px 12px;
50
- background-color: white;
51
- }
52
-
53
- .ui-dialog.targetSelector button{
54
- background-color: #0091CD;
55
- color: white;
56
- font-size:12px;
57
- text-transform: uppercase;
58
- margin-top: 25px;
59
- height: 32px;
60
- width: 68px;
61
- }
62
-
63
- .requestButton{
64
- margin-left : 8px;
65
- margin-right: 12px;
66
- }
67
-
68
- .ui-dialog.targetSelector button:hover {
69
- background-color: #007fb4;
70
- }
71
-
72
-
73
- .ui-dialog.targetSelector button:disabled {
74
- background-color: #b0b0b0;
75
- }
76
-
77
- .ui-dialog.targetSelector .ui-dialog-titlebar-close{
78
- display: none;
79
- }
80
-
81
- .select2-selection--multiple {
82
- font-size:12px;
83
- font-style:normal;
84
- border-width: 0px 0px 1px 0px !important;
85
- border-radius: 0px !important;
86
- margin: 15px 0px 0px;
87
- padding: 0px;
88
- }
89
-
90
- .select2-selection__rendered {
91
- padding-left: 0px !important;
92
- }
93
-
94
- .select2-selection__choice {
95
- font-weight:700;
96
- margin-bottom: 0px !important;
97
- }
98
- /*tag fonts
99
- .targetSelect{
100
-
101
- }*/
102
-
103
  /* icons color */
104
  .lingotek-color {
105
  color: #ff7b12; /* lingotek color */
@@ -189,6 +122,14 @@ a.dashicons {
189
  clear: none !important;
190
  }
191
 
 
 
 
 
 
 
 
 
192
  .lingotek-profiles {
193
  clear: none !important;
194
  }
33
  .ui-dialog button:hover {
34
  background-color: #007fb4;
35
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
36
  /* icons color */
37
  .lingotek-color {
38
  color: #ff7b12; /* lingotek color */
122
  clear: none !important;
123
  }
124
 
125
+ .target-table {
126
+ width: 50%;
127
+ }
128
+
129
+ .target-table-td {
130
+ width: 205px;
131
+ }
132
+
133
  .lingotek-profiles {
134
  clear: none !important;
135
  }
include/api.php CHANGED
@@ -113,13 +113,18 @@ class Lingotek_API extends Lingotek_HTTP {
113
  $args = wp_parse_args($args, array('format' => 'JSON', 'project_id' => $this->defaults['project_id'], 'workflow_id' => $this->get_workflow_id()));
114
  $this->format_as_multipart($args);
115
  $response = $this->post($this->api_url . '/document', $args);
116
-
117
  $this->update_lingotek_error_option($response, $wp_id, 'upload_document', sprintf(__('There was an error uploading WordPress item %1$s', 'lingotek-translation'), $wp_id));
118
-
119
- if (!is_wp_error($response) && 202 == wp_remote_retrieve_response_code($response)) {
120
  $b = json_decode(wp_remote_retrieve_body($response));
121
  Lingotek_Logger::info('Document uploaded', array('document_id' => $b->properties->id, 'wp_id' => $wp_id));
122
  return $b->properties->id;
 
 
 
 
 
 
123
  }
124
  return false;
125
  }
@@ -134,41 +139,94 @@ class Lingotek_API extends Lingotek_HTTP {
134
  * @return bool false if something got wrong
135
  */
136
  public function patch_document($id, $args, $wp_id = null) {
137
- $args = wp_parse_args($args, array('format' => 'JSON'));
 
 
 
138
  $this->format_as_multipart($args);
139
  $response = $this->patch($this->api_url . '/document/' . $id, $args);
 
 
 
 
 
 
 
140
 
141
- $this->update_lingotek_error_option($response, $wp_id, 'patch_document', sprintf(__('There was an error updating WordPress item %1$s', 'lingotek-translation'), $wp_id), array('document_id' => $id));
142
-
143
- $is_success = !is_wp_error($response) && 202 == wp_remote_retrieve_response_code($response);
144
- if ($is_success) { Lingotek_Logger::info('Document updated', array('document_id' => $id, 'wp_id' => $wp_id)); }
145
-
146
- return $is_success;
147
- }
148
-
149
- /**
150
- * deletes a document
151
- *
152
- * @since 0.1
153
- *
154
- * @param string $id document id
155
- */
156
- public function delete_document($id, $wp_id = null) {
157
- $response = $this->delete("$this->api_url/document/$id");
158
-
159
- if ($wp_id) {
160
- $arr = get_option('lingotek_log_errors');
161
- if (isset($arr[$wp_id])) {
162
- unset($arr[$wp_id]);
163
- update_option('lingotek_log_errors', $arr);
164
  }
 
165
  }
166
 
167
- $this->log_error_on_response_failure($response, 'DeleteDocument: Error occured', array('id' => $id, 'wordpress_id' => $wp_id));
168
- $is_success = !is_wp_error($response) && (204 == wp_remote_retrieve_response_code($response) || 202 == wp_remote_retrieve_response_code($response));
169
- if ($is_success) { Lingotek_Logger::info('Document deleted', array('document_id' => $id, 'wp_id' => $wp_id)); }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
170
 
171
- return $is_success;
 
 
 
 
 
 
172
  }
173
 
174
  /**
@@ -486,15 +544,48 @@ class Lingotek_API extends Lingotek_HTTP {
486
  * @return bool true if the request succeeded
487
  */
488
  public function request_translation($id, $locale, $args = array(), $wp_id = null) {
 
 
489
  $locale = Lingotek::map_to_lingotek_locale($locale);
490
- $args = wp_parse_args($args, array('workflow_id' => $this->get_workflow_id()));
491
  $args = array_merge(array('locale_code' => $locale), $args);
492
  $response = $this->post($this->api_url . '/document/' . $id . '/translation', $args);
493
-
494
  if ($wp_id) {
495
- $arr = get_option('lingotek_log_errors');
496
-
497
- if (201 == wp_remote_retrieve_response_code($response)) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
498
  if (isset($arr[$wp_id])) {
499
  unset($arr[$wp_id]['wp_error']);
500
  unset($arr[$wp_id]['request_translation'][$locale]);
@@ -502,19 +593,19 @@ class Lingotek_API extends Lingotek_HTTP {
502
  unset($arr[$wp_id]);
503
  }
504
  }
505
- }
506
- else if (is_wp_error($response)) {
507
  $arr[$wp_id]['wp_error'] = __('Make sure you have internet connectivity', 'lingotek-translation');
508
- }
509
- else if (400 == wp_remote_retrieve_response_code($response) || 404 == wp_remote_retrieve_response_code($response)) {
510
  $arr[$wp_id]['request_translation'][$locale] = sprintf(
511
  __('There was an error requesting translation %1$s for WordPress item %2$s', 'lingotek-translation'), $locale, $wp_id
512
  );
513
  }
514
  update_option('lingotek_log_errors', $arr);
515
  }
516
- $this->log_error_on_response_failure($response, "RequestTranslation: Error Occurred", ['document_id' => $id, 'locale' => $locale, 'args' => $args]);
517
- return !is_wp_error($response) && 201 == wp_remote_retrieve_response_code($response);
 
 
518
  }
519
 
520
  /**
@@ -533,8 +624,15 @@ class Lingotek_API extends Lingotek_HTTP {
533
 
534
  if ($wp_id) {
535
  $arr = get_option('lingotek_log_errors');
536
-
537
- if (200 == wp_remote_retrieve_response_code($response)) {
 
 
 
 
 
 
 
538
  if (isset($arr[$wp_id])) {
539
  unset($arr[$wp_id]['wp_error']);
540
  unset($arr[$wp_id]['get_translation'][$locale]);
@@ -542,11 +640,9 @@ class Lingotek_API extends Lingotek_HTTP {
542
  unset($arr[$wp_id]);
543
  }
544
  }
545
- }
546
- else if (is_wp_error($response)) {
547
  $arr[$wp_id]['wp_error'] = __('Make sure you have internet connectivity', 'lingotek-translation');
548
- }
549
- else if (400 == wp_remote_retrieve_response_code($response) || 404 == wp_remote_retrieve_response_code($response)) {
550
  $arr[$wp_id]['get_translation'][$locale] = sprintf(
551
  __('There was an error downloading translation %1$s for WordPress item %2$s'), $locale, $wp_id
552
  );
@@ -554,31 +650,7 @@ class Lingotek_API extends Lingotek_HTTP {
554
  update_option('lingotek_log_errors', $arr);
555
  }
556
  $this->log_error_on_response_failure($response, "GetTranslation: Error Occurred", ['document_id' => $doc_id, 'locale' => $locale]);
557
- return !is_wp_error($response) && 200 == wp_remote_retrieve_response_code($response) ? wp_remote_retrieve_body($response) : false;
558
- }
559
-
560
- /**
561
- * deletes a translation
562
- *
563
- * @since 0.1
564
- *
565
- * @param string $id document id
566
- * @param string $locale Lingotek locale
567
- */
568
- public function delete_translation($id, $locale, $wp_id = null) {
569
- $response = $this->delete("$this->api_url/document/$id/translation/$locale");
570
-
571
- if ($wp_id) {
572
- $arr = get_option('lingotek_log_errors');
573
- if (isset($arr[$wp_id])) {
574
- unset($arr[$wp_id]);
575
- update_option('lingotek_log_errors', $arr);
576
- }
577
- }
578
- $this->log_error_on_response_failure($response, "DeleteTranslation: Error occurred", ['id' -> $id, 'wordpress_id' => $wp_id]);
579
- $is_success = !is_wp_error($response) && (204 == wp_remote_retrieve_response_code($response) || 202 == wp_remote_retrieve_response_code($response));
580
- if ($is_success) { Lingotek_Logger::info('Target deleted', ['document_id' => $id, 'wp_id' => $wp_id]); }
581
- return $is_success;
582
  }
583
 
584
  /**
@@ -726,6 +798,9 @@ class Lingotek_API extends Lingotek_HTTP {
726
  if ($wp_id){
727
  $arr = get_option('lingotek_log_errors');
728
  $response_message_code = wp_remote_retrieve_response_code($response);
 
 
 
729
 
730
  if (200 == $response_message_code || 202 == $response_message_code) {
731
  if (isset($arr[$wp_id])) {
@@ -760,6 +835,9 @@ class Lingotek_API extends Lingotek_HTTP {
760
 
761
  private function get_error_message_from_response($response){
762
  $responseBody = json_decode(wp_remote_retrieve_body($response));
 
 
 
763
  return property_exists($responseBody, "messages") && is_array($responseBody->messages) ? implode(" ",$responseBody->messages) : false;
764
  }
765
  }
113
  $args = wp_parse_args($args, array('format' => 'JSON', 'project_id' => $this->defaults['project_id'], 'workflow_id' => $this->get_workflow_id()));
114
  $this->format_as_multipart($args);
115
  $response = $this->post($this->api_url . '/document', $args);
 
116
  $this->update_lingotek_error_option($response, $wp_id, 'upload_document', sprintf(__('There was an error uploading WordPress item %1$s', 'lingotek-translation'), $wp_id));
117
+ $code = wp_remote_retrieve_response_code($response);
118
+ if (!is_wp_error($response) && 202 == $code) {
119
  $b = json_decode(wp_remote_retrieve_body($response));
120
  Lingotek_Logger::info('Document uploaded', array('document_id' => $b->properties->id, 'wp_id' => $wp_id));
121
  return $b->properties->id;
122
+ } elseif ($code == 402) {
123
+ $lingotek_log_errors = get_option('lingotek_log_errors');
124
+ $error_message = $this->get_error_message_from_response($response) !== false ?
125
+ $this->get_error_message_from_response($response) : "No error message set by Lingotek";
126
+ $lingotek_log_errors['patch_document_error'] = __("Payment required. Message: $error_message", 'lingotek-translation');
127
+ update_option('lingotek_log_errors', $lingotek_log_errors);
128
  }
129
  return false;
130
  }
139
  * @return bool false if something got wrong
140
  */
141
  public function patch_document($id, $args, $wp_id = null) {
142
+ $lgtm = $GLOBALS['wp_lingotek']->model;
143
+ $document = $lgtm->get_group_by_id($id);
144
+ $args = $unformatted_args = wp_parse_args($args, array('format' => 'JSON'));
145
+ $title = isset($args['title']) ? $args['title'] : $id;
146
  $this->format_as_multipart($args);
147
  $response = $this->patch($this->api_url . '/document/' . $id, $args);
148
+ $status_code = wp_remote_retrieve_response_code($response);
149
+ $body = json_decode(wp_remote_retrieve_body($response));
150
+ if ($status_code == 423) {
151
+ $document->document_id = $body->next_document_id;
152
+ $document->save();
153
+ return $this->patch_document($body->next_document_id, $unformatted_args, $wp_id);
154
+ }
155
 
156
+ // We will handle patch errors separately. All we want to do is return the result of the current patch request to the user if payment is required
157
+ // (although in theory this will never happen, because the WP model is document count based, and it will not allow them to upload documents until
158
+ // they choose to buy more documents)
159
+ $this->update_patch_error_message($response, $status_code, $title);
160
+ // The current behavior sends no body, so we will just check to see if the body is empty for now in order to maintain current behavior
161
+ if (empty($body)) {
162
+ $success = !is_wp_error($response) && 202 == wp_remote_retrieve_response_code($response);
163
+ if ($success) {
164
+ Lingotek_Logger::info('Document updated', array('document_id' => $id, 'wp_id' => $wp_id));
165
+ } else {
166
+ Lingotek_Logger::error('Document failed to update', array('document_id' => $id, 'wp_id' => $wp_id));
 
 
 
 
 
 
 
 
 
 
 
 
167
  }
168
+ return $success;
169
  }
170
 
171
+ if ($status_code == 410) {
172
+ Lingotek_Logger::info("Document ID was archived, reuploading document", array('old_document_id' => $id, 'wp_id' => $wp_id, 'args' => $args));
173
+ $targets = array_keys($document->translations);
174
+ $unformatted_args['translation_locale_code'] = $targets;
175
+ $this->format_args_for_upload($unformatted_args, $wp_id);
176
+ foreach ($document->translations as $locale) {
177
+ $document->translations[$locale] = 'pending';
178
+ }
179
+ $document->document_id = NULL;
180
+ unset($document->desc_array['lingotek']);
181
+ $document->save();
182
+ return $this->upload_document($unformatted_args, $wp_id);
183
+ }
184
+ if ($status_code == 402) {
185
+ Lingotek_Logger::error('There was an error updating WordPress item', array('error' => $this->get_error_message_from_response($response)));
186
+ $document->source_failed();
187
+ return FALSE;
188
+ }
189
+ if ($status_code == 202 && !is_wp_error($response)) {
190
+ Lingotek_Logger::info('Document updated', array('old_document_id' => $id, 'new_document_id' => $body->next_document_id, 'wp_id' => $wp_id));
191
+ $document->document_id = $body->next_document_id;
192
+ $document->save();
193
+ return $body->next_document_id;
194
+ }
195
+ return FALSE;
196
+ }
197
+
198
+ private function format_args_for_upload(&$args, $wp_id) {
199
+ $lgtm = $GLOBALS['wp_lingotek']->model;
200
+ $post = get_post($wp_id);
201
+ $language = PLL()->model->post->get_language($wp_id);
202
+ $project_id = $lgtm->get_profile_option('project_id', $post->post_type, $language, false, $wp_id);
203
+ $workflow_id = $lgtm->get_profile_option('workflow_id', $post->post_type, $language, false, $wp_id);
204
+ $locale_code = $language->lingotek_locale;
205
+ unset($args['format']);
206
+ $args['locale_code'] = $locale_code;
207
+ $args['project_id'] = $project_id;
208
+ $args['workflow_id'] = $workflow_id;
209
+ }
210
+
211
+ private function update_patch_error_message($response, $status_code, $title) {
212
+ // Do not inform user if call was successful.
213
+ if ($status_code == 202 || $status_code == 410) {
214
+ return;
215
+ }
216
+ $lingotek_log_errors = get_option('lingotek_log_errors', array());
217
+ if (!is_array($lingotek_log_errors)) {
218
+ $lingotek_log_errors = array();
219
+ }
220
+ $error_message = $this->get_error_message_from_response($response) !== FALSE ?
221
+ $this->get_error_message_from_response($response) : "No error message set by Lingotek.";
222
 
223
+ if ($status_code == 402) {
224
+ $lingotek_log_errors['patch_document_error'] = __("Payment required. Message: $error_message", 'lingotek-translation');
225
+ }
226
+ else {
227
+ $lingotek_log_errors['patch_document_error'] = __("Error occurred while updating document $title. Message: $error_message", 'lingotek-translation');
228
+ }
229
+ update_option('lingotek_log_errors', $lingotek_log_errors);
230
  }
231
 
232
  /**
544
  * @return bool true if the request succeeded
545
  */
546
  public function request_translation($id, $locale, $args = array(), $wp_id = null) {
547
+ $lgtm = $GLOBALS['wp_lingotek']->model;
548
+ $document = $lgtm->get_group_by_id($id);
549
  $locale = Lingotek::map_to_lingotek_locale($locale);
550
+ $args = $unformatted_args = wp_parse_args($args, array('workflow_id' => $this->get_workflow_id()));
551
  $args = array_merge(array('locale_code' => $locale), $args);
552
  $response = $this->post($this->api_url . '/document/' . $id . '/translation', $args);
553
+ $title = isset($args['title']) ? $args['title'] : $id;
554
  if ($wp_id) {
555
+ $arr = get_option('lingotek_log_errors', array());
556
+ $status_code = wp_remote_retrieve_response_code($response);
557
+ $body = json_decode(wp_remote_retrieve_body($response));
558
+ $this->update_patch_error_message($response, $status_code, $title);
559
+ if (423 === $status_code) {
560
+ $document->document_id = $body->next_document_id;
561
+ $document->save();
562
+ return $this->request_translation($body->next_document_id, $locale, $unformatted_args, $wp_id);
563
+ }
564
+ if (402 === $status_code) {
565
+ Lingotek_Logger::error('There was an error updating WordPress item', array('error' => $this->get_error_message_from_response($response)));
566
+ $document->source_failed();
567
+ return false;
568
+ }
569
+ if (410 === $status_code) {
570
+ // WP hooks automatically check source status so this might not get called
571
+ $targets = array_keys($document->translations);
572
+ $targets[] = $locale;
573
+ $unformatted_args['translation_locale_code'] = $targets;
574
+ $this->format_args_for_upload($unformatted_args, $wp_id);
575
+ unset($document->desc_array['lingotek']);
576
+ $document->save();
577
+ foreach ($document->translations as $locale) {
578
+ $document->translations[$locale] = 'pending';
579
+ }
580
+ return $this->upload_document($unformatted_args, $wp_id);
581
+ }
582
+ if (400 === $status_code &&
583
+ !empty($body->messages) &&
584
+ strpos($body->messages[0], 'already exists')) {
585
+ // Translation has already been requested, treat it as a 201 response
586
+ $status_code = 201;
587
+ }
588
+ if (201 === $status_code) {
589
  if (isset($arr[$wp_id])) {
590
  unset($arr[$wp_id]['wp_error']);
591
  unset($arr[$wp_id]['request_translation'][$locale]);
593
  unset($arr[$wp_id]);
594
  }
595
  }
596
+ } elseif (is_wp_error($response)) {
 
597
  $arr[$wp_id]['wp_error'] = __('Make sure you have internet connectivity', 'lingotek-translation');
598
+ } elseif (400 == $status_code || 404 == $status_code) {
 
599
  $arr[$wp_id]['request_translation'][$locale] = sprintf(
600
  __('There was an error requesting translation %1$s for WordPress item %2$s', 'lingotek-translation'), $locale, $wp_id
601
  );
602
  }
603
  update_option('lingotek_log_errors', $arr);
604
  }
605
+ if (201 !== $status_code) {
606
+ $this->log_error_on_response_failure($response, "RequestTranslation: Error Occurred", ['document_id' => $id, 'locale' => $locale, 'args' => $args]);
607
+ }
608
+ return !is_wp_error($response) && 201 === $status_code;
609
  }
610
 
611
  /**
624
 
625
  if ($wp_id) {
626
  $arr = get_option('lingotek_log_errors');
627
+ $status_code = wp_remote_retrieve_response_code($response);
628
+ if (410 == $status_code) {
629
+ $lgtm = $GLOBALS['wp_lingotek']->model;
630
+ $document = $lgtm->get_group_by_id($doc_id);
631
+ $document->source_failed();
632
+ //TODO IS THIS SETTING ERROR PROPERLY?
633
+ $arr[$wp_id]['wp_error'] = __("Document $doc_id has been archived. Please re-upload source", 'lingotek-translation');
634
+ return false;
635
+ } else if (200 == $status_code) {
636
  if (isset($arr[$wp_id])) {
637
  unset($arr[$wp_id]['wp_error']);
638
  unset($arr[$wp_id]['get_translation'][$locale]);
640
  unset($arr[$wp_id]);
641
  }
642
  }
643
+ } else if (is_wp_error($response)) {
 
644
  $arr[$wp_id]['wp_error'] = __('Make sure you have internet connectivity', 'lingotek-translation');
645
+ } else if (400 == $status_code || 404 == $status_code) {
 
646
  $arr[$wp_id]['get_translation'][$locale] = sprintf(
647
  __('There was an error downloading translation %1$s for WordPress item %2$s'), $locale, $wp_id
648
  );
650
  update_option('lingotek_log_errors', $arr);
651
  }
652
  $this->log_error_on_response_failure($response, "GetTranslation: Error Occurred", ['document_id' => $doc_id, 'locale' => $locale]);
653
+ return !is_wp_error($response) && 200 == $status_code ? wp_remote_retrieve_body($response) : false;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
654
  }
655
 
656
  /**
798
  if ($wp_id){
799
  $arr = get_option('lingotek_log_errors');
800
  $response_message_code = wp_remote_retrieve_response_code($response);
801
+ if (empty($arr)) {
802
+ return;
803
+ }
804
 
805
  if (200 == $response_message_code || 202 == $response_message_code) {
806
  if (isset($arr[$wp_id])) {
835
 
836
  private function get_error_message_from_response($response){
837
  $responseBody = json_decode(wp_remote_retrieve_body($response));
838
+ if (empty($responseBody)) {
839
+ return false;
840
+ }
841
  return property_exists($responseBody, "messages") && is_array($responseBody->messages) ? implode(" ",$responseBody->messages) : false;
842
  }
843
  }
include/callback.php CHANGED
@@ -30,85 +30,120 @@ class Lingotek_Callback {
30
  if (empty($query_vars['lingotek'])) {
31
  return $query_vars;
32
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
33
 
34
- if (isset($_GET['type'], $_GET['document_id']) && $document = $this->lgtm->get_group_by_id($_GET['document_id'])) {
35
- // url for in context review
36
- if (isset($_GET['locale']) && 'get' == $_GET['type']) {
37
- $locale = Lingotek::map_to_wp_locale($_GET['locale']); // map to WP locale
38
- Lingotek_Logger::info('Callback received', array('Callback Parameters' => $_GET));
39
- // posts
40
- if (post_type_exists($document->type)) {
41
- if ($id = PLL()->model->post->get($document->source, $locale)) {
42
- wp_redirect(get_permalink($id), 301);
43
- exit();
44
- }
45
- else {
46
- wp_redirect(get_permalink($document->source), 302);
47
- exit();
48
- }
49
  }
50
-
51
- // taxonomy terms
52
- elseif (taxonomy_exists($document->type) && $id = $document->pllm->get_term($document->source, $locale)) {
53
- wp_redirect(get_term_link($id, $document->type), 301);
54
  exit();
55
  }
56
-
57
- status_header(404); // no document found
58
- die();
59
  }
60
-
61
- if ('document_uploaded' == $_GET['type']) {
62
- $document->source_ready();
63
- $callback_parameters = array(
64
- 'Document ID' => isset($_GET['document_id']) ? $_GET['document_id'] : NULL,
65
- 'Project ID' => isset($_GET['projectId']) ? (int)$_GET['projectId'] : NULL,
66
- 'Community ID' => isset($_GET['community_id']) ? $_GET['community_id'] : NULL,
67
- 'Progress' => isset($_GET['progress']) ? (int)$_GET['progress'] : NULL,
68
- 'Complete' => isset($_GET['complete']) ? $_GET['complete'] : NULL,
69
- 'Type' => isset($_GET['type']) ? $_GET['type'] : NULL,
70
- 'Document Status' => isset($_GET['doc_status']) ? $_GET['doc_status'] : NULL,
71
- );
72
- Lingotek_Logger::info('Callback received', array('Callback Parameters' => $callback_parameters));
73
- if ($document->is_automatic_upload()) {
74
- $document->request_translations();
75
- }
76
  }
77
 
78
- if ((isset($_GET['locale']) && 'target' == $_GET['type']) || (isset($_GET['locale']) && $_GET['type'] == 'phase')) {
79
- $callback_parameters = array(
80
- 'Target Locale' => isset($_GET['locale_code']) ? $_GET['locale_code'] : NULL,
81
- 'Phase Name' => isset($_GET['phase_name']) ? $_GET['phase_name'] : NULL,
82
- 'Status' => isset($_GET['status']) ? $_GET['status'] : NULL,
83
- 'Document ID' => isset($_GET['document_id']) ? $_GET['document_id'] : NULL,
84
- 'Project ID' => isset($_GET['projectId']) ? (int)$_GET['projectId'] : NULL,
85
- 'Community ID' => isset($_GET['community_id']) ? $_GET['community_id'] : NULL,
86
- 'Progress' => isset($_GET['progress']) ? (int)$_GET['progress'] : NULL,
87
- 'Complete' => isset($_GET['complete']) ? $_GET['complete'] : NULL,
88
- 'Type' => isset($_GET['type']) ? $_GET['type'] : NULL,
89
- 'Document Status' => isset($_GET['doc_status']) ? $_GET['doc_status'] : NULL,
90
- );
91
- Lingotek_Logger::info('Callback received', array('Callback Parameters' => $callback_parameters));
92
- // We will need access to PLL_Admin_Sync::copy_post_metas
93
- global $polylang;
94
- $polylang->sync = new PLL_Admin_Sync($polylang);
95
- $locale = Lingotek::map_to_wp_locale($_GET['locale']); // map to WP locale
96
- $document->is_automatic_download($locale) ? $document->create_translation($locale, true, $_GET['type']) : $document->translation_ready($locale);
97
- }
98
 
99
- if (isset($_GET['type'], $_GET['document_id']) && $_GET['type'] == 'import_failure' && $document = $this->lgtm->get_group_by_id($_GET['document_id'])) {
100
- $callback_parameters = array(
101
- 'Document ID' => isset($_GET['document_id']) ? $_GET['document_id'] : NULL,
102
- 'Type' => isset($_GET['type']) ? $_GET['type'] : NULL,
103
- );
104
- Lingotek_Logger::info('Callback received', array('Callback Parameters' => $callback_parameters));
105
- $document->source_failed();
106
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
107
 
108
- status_header(200); // useless as it the default value
109
- die();
 
 
 
 
 
 
 
 
 
 
 
 
110
  }
111
- status_header(404); // no document found
112
- die();
113
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
114
  }
30
  if (empty($query_vars['lingotek'])) {
31
  return $query_vars;
32
  }
33
+ $type = $_GET['type'];
34
+ if (isset($type, $_GET['document_id']) && $document = $this->lgtm->get_group_by_id($_GET['document_id'])) {
35
+ switch ($type) {
36
+ case 'get':
37
+ $this->handleGet($document);
38
+ break;
39
+ case 'target':
40
+ case 'phase':
41
+ $this->handleTargetOrPhase($document, $type);
42
+ break;
43
+ case 'document_uploaded':
44
+ case 'document_updated':
45
+ $this->handleDocumentUploadedOrUpdated($document);
46
+ break;
47
+ case 'import_failure':
48
+ $this->handleImportFailure($document);
49
+ break;
50
+ case 'document_archived':
51
+ case 'document_deleted':
52
+ $this->handleDocumentArchivedOrDeleted($document);
53
+ break;
54
+ default:
55
+ Lingotek_Logger::info('Callback received, no handler for type', array('Type' => $type));
56
+ }
57
+ status_header(200); // useless as it the default value
58
+ die();
59
+ }
60
+ status_header(404); // no document found
61
+ die();
62
+ }
63
 
64
+ public function handleGet($document) {
65
+ // url for in context review
66
+ if (isset($_GET['locale'])) {
67
+ $locale = Lingotek::map_to_wp_locale($_GET['locale']); // map to WP locale
68
+ Lingotek_Logger::info('Callback received', array('Callback Parameters' => $_GET));
69
+ // posts
70
+ if (post_type_exists($document->type)) {
71
+ if ($id = PLL()->model->post->get($document->source, $locale)) {
72
+ wp_redirect(get_permalink($id), 301);
73
+ exit();
 
 
 
 
 
74
  }
75
+ else {
76
+ wp_redirect(get_permalink($document->source), 302);
 
 
77
  exit();
78
  }
 
 
 
79
  }
80
+ // taxonomy terms
81
+ elseif (taxonomy_exists($document->type) && $id = $document->pllm->get_term($document->source, $locale)) {
82
+ wp_redirect(get_term_link($id, $document->type), 301);
83
+ exit();
 
 
 
 
 
 
 
 
 
 
 
 
84
  }
85
 
86
+ status_header(404); // no document found
87
+ die();
88
+ }
89
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
90
 
91
+ public function handleTargetOrPhase($document, $type) {
92
+ if (isset($_GET['locale'])) {
93
+ $callback_parameters = array(
94
+ 'Target Locale' => isset($_GET['locale_code']) ? $_GET['locale_code'] : NULL,
95
+ 'Phase Name' => isset($_GET['phase_name']) ? $_GET['phase_name'] : NULL,
96
+ 'Status' => isset($_GET['status']) ? $_GET['status'] : NULL,
97
+ 'Document ID' => isset($_GET['document_id']) ? $_GET['document_id'] : NULL,
98
+ 'Project ID' => isset($_GET['projectId']) ? (int)$_GET['projectId'] : NULL,
99
+ 'Community ID' => isset($_GET['community_id']) ? $_GET['community_id'] : NULL,
100
+ 'Progress' => isset($_GET['progress']) ? (int)$_GET['progress'] : NULL,
101
+ 'Complete' => isset($_GET['complete']) ? $_GET['complete'] : NULL,
102
+ 'Type' => isset($_GET['type']) ? $_GET['type'] : NULL,
103
+ 'Document Status' => isset($_GET['doc_status']) ? $_GET['doc_status'] : NULL,
104
+ );
105
+ Lingotek_Logger::info('Callback received', array('Callback Parameters' => $callback_parameters));
106
+ // We will need access to PLL_Admin_Sync::copy_post_metas
107
+ global $polylang;
108
+ $polylang->sync = new PLL_Admin_Sync($polylang);
109
+ $locale = Lingotek::map_to_wp_locale($_GET['locale']); // map to WP locale
110
+ $document->is_automatic_download($locale) ? $document->create_translation($locale, true, $type) : $document->translation_ready($locale);
111
+ }
112
+ }
113
 
114
+ public function handleDocumentUploadedOrUpdated($document) {
115
+ $document->source_ready();
116
+ $callback_parameters = array(
117
+ 'Document ID' => isset($_GET['document_id']) ? $_GET['document_id'] : NULL,
118
+ 'Project ID' => isset($_GET['projectId']) ? (int)$_GET['projectId'] : NULL,
119
+ 'Community ID' => isset($_GET['community_id']) ? $_GET['community_id'] : NULL,
120
+ 'Progress' => isset($_GET['progress']) ? (int)$_GET['progress'] : NULL,
121
+ 'Complete' => isset($_GET['complete']) ? $_GET['complete'] : NULL,
122
+ 'Type' => isset($_GET['type']) ? $_GET['type'] : NULL,
123
+ 'Document Status' => isset($_GET['doc_status']) ? $_GET['doc_status'] : NULL,
124
+ );
125
+ Lingotek_Logger::info('Callback received', array('Callback Parameters' => $callback_parameters));
126
+ if ($document->is_automatic_upload()) {
127
+ $document->request_translations();
128
  }
 
 
129
  }
130
+
131
+ public function handleImportFailure($document) {
132
+ $callback_parameters = array(
133
+ 'Document ID' => isset($_GET['document_id']) ? $_GET['document_id'] : NULL,
134
+ 'Type' => isset($_GET['type']) ? $_GET['type'] : NULL,
135
+ );
136
+ if (isset($_GET['prev_document_id'])) {
137
+ Lingotek_Logger::info("Document update failed. Reverting to previous id", $callback_parameters);
138
+ $document->id = $_GET['prev_document_id'];
139
+ }
140
+ Lingotek_Logger::info('Callback received', array('Callback Parameters' => $callback_parameters));
141
+ $document->source_failed();
142
+ }
143
+
144
+ public function handleDocumentArchivedOrDeleted($document) {
145
+ unset($document->desc_array['lingotek']);
146
+ $document->save();
147
+ }
148
+
149
  }
include/group-string.php CHANGED
@@ -85,7 +85,7 @@ class Lingotek_Group_String extends Lingotek_Group {
85
 
86
  $res = $client->patch_document($this->document_id, $params, $group);
87
 
88
- if ($res) {
89
  $this->md5 = md5($content);
90
  $this->status = 'importing';
91
  $this->translations = array_fill_keys(array_keys($this->translations), 'pending');
85
 
86
  $res = $client->patch_document($this->document_id, $params, $group);
87
 
88
+ if ($res !== FALSE) {
89
  $this->md5 = md5($content);
90
  $this->status = 'importing';
91
  $this->translations = array_fill_keys(array_keys($this->translations), 'pending');
include/group.php CHANGED
@@ -106,9 +106,20 @@ abstract class Lingotek_Group {
106
  */
107
  public function disassociate() {
108
  $client = new Lingotek_API();
109
- $client->delete_document($this->document_id, $this->source);
110
- unset($this->desc_array['lingotek']);
111
- $this->save();
 
 
 
 
 
 
 
 
 
 
 
112
  }
113
 
114
 
@@ -119,9 +130,12 @@ abstract class Lingotek_Group {
119
  */
120
  public function cancel() {
121
  $client = new Lingotek_API();
122
- $client->cancel_document($this->document_id, $this->source);
123
- unset($this->desc_array['lingotek']);
124
- $this->save();
 
 
 
125
  }
126
 
127
  /**
@@ -130,11 +144,17 @@ abstract class Lingotek_Group {
130
  * @param bool $cancel whether to cancel the Lingotek document or not
131
  */
132
  public function delete_translation($language, $id){
133
- $client = new Lingotek_API();
134
- $client->delete_translation($this->document_id, $language->lingotek_locale, $id);
135
- unset($this->desc_array['lingotek']['translations'][$language->locale]);
136
- unset($this->desc_array[$language->locale]);
137
- $this->save();
 
 
 
 
 
 
138
  }
139
 
140
  /**
@@ -142,11 +162,14 @@ abstract class Lingotek_Group {
142
  *
143
  * @param bool $cancel whether to cancel the Lingotek document or not
144
  */
145
- public function cancel_translation($language, $id){
146
  $client = new Lingotek_API();
147
- $client->cancel_translation($this->document_id, $language->lingotek_locale, $id);
148
- $this->desc_array['lingotek']['translations'][$language->locale] = 'cancelled';
149
- $this->save();
 
 
 
150
  }
151
 
152
  /*
@@ -169,7 +192,8 @@ abstract class Lingotek_Group {
169
 
170
  $res = $client->patch_document($this->document_id, $params, $this->source);
171
 
172
- if ($res) {
 
173
  $this->status = 'importing';
174
  $this->translations = array_fill_keys(array_keys($this->translations), 'pending');
175
  $this->save();
@@ -241,7 +265,7 @@ abstract class Lingotek_Group {
241
  */
242
  protected function _request_translations($source_language) {
243
 
244
- $type_id;
245
  $client = new Lingotek_API();
246
 
247
  foreach ($this->pllm->get_languages_list() as $lang) {
106
  */
107
  public function disassociate() {
108
  $client = new Lingotek_API();
109
+ if ($client->cancel_document($this->document_id, $this->source)) {
110
+ update_option("ignore_delete_pref", TRUE);
111
+ unset($this->desc_array['lingotek']);
112
+ foreach ($this->desc_array as $locale) {
113
+ if ($locale !== $this->source) {
114
+ wp_trash_post( $locale );
115
+ unset($this->desc_array[$locale]);
116
+ }
117
+ }
118
+ $this->save();
119
+ update_option("ignore_delete_pref", FALSE);
120
+ } else {
121
+ update_option('disassociate_source_failed', TRUE);
122
+ }
123
  }
124
 
125
 
130
  */
131
  public function cancel() {
132
  $client = new Lingotek_API();
133
+ if ($client->cancel_document($this->document_id, $this->source)) {
134
+ unset($this->desc_array['lingotek']);
135
+ $this->save();
136
+ } else {
137
+ update_option('cancel_source_failed', TRUE);
138
+ }
139
  }
140
 
141
  /**
144
  * @param bool $cancel whether to cancel the Lingotek document or not
145
  */
146
  public function delete_translation($language, $id){
147
+ $client = new Lingotek_API();
148
+ if ($client->cancel_translation($this->document_id, $language->lingotek_locale, $id)) {
149
+ update_option("ignore_delete_pref", TRUE);
150
+ $this->desc_array['lingotek']['translations'][$language->locale] = 'cancelled';
151
+ unset($this->desc_array[$language->locale]);
152
+ wp_trash_post($id);
153
+ $this->save();
154
+ update_option("ignore_delete_pref", FALSE);
155
+ } else {
156
+ update_option('disassociate_target_failed', TRUE);
157
+ }
158
  }
159
 
160
  /**
162
  *
163
  * @param bool $cancel whether to cancel the Lingotek document or not
164
  */
165
+ public function cancel_translation($language, $id) {
166
  $client = new Lingotek_API();
167
+ if ($client->cancel_translation($this->document_id, $language->lingotek_locale, $id)) {
168
+ $this->desc_array['lingotek']['translations'][$language->locale] = 'cancelled';
169
+ $this->save();
170
+ } else {
171
+ update_option('cancel_target_failed', TRUE);
172
+ }
173
  }
174
 
175
  /*
192
 
193
  $res = $client->patch_document($this->document_id, $params, $this->source);
194
 
195
+ if ($res !== FALSE) {
196
+ $this->document_id = $res;
197
  $this->status = 'importing';
198
  $this->translations = array_fill_keys(array_keys($this->translations), 'pending');
199
  $this->save();
265
  */
266
  protected function _request_translations($source_language) {
267
 
268
+ $type_id = NULL;
269
  $client = new Lingotek_API();
270
 
271
  foreach ($this->pllm->get_languages_list() as $lang) {
include/http.php CHANGED
@@ -27,7 +27,7 @@ class Lingotek_HTTP {
27
  foreach($value as $k => $v) {
28
  $data .= '--' . $boundary . "\r\n";
29
  $data .= 'Content-Disposition: form-data; name="' . $key;
30
- if ($key != 'translation_locale_code'){ //request targets cannot be in an array, they need to have the same key
31
  $data .= '[' . $k . ']';
32
  }
33
  $data.= "\"\r\n\r\n";
@@ -89,10 +89,10 @@ class Lingotek_HTTP {
89
  * @since 0.1
90
  */
91
  public function patch($url, $args = array()) {
92
- Lingotek::log("PATCH $url");
93
- if (!empty($args)) {
94
- Lingotek::log($args);
95
- }
96
- return wp_remote_request($url, array('method' => 'PATCH', 'headers' => $this->headers, 'body' => $args, 'timeout' => self::TIMEOUT));
97
  }
98
  }
27
  foreach($value as $k => $v) {
28
  $data .= '--' . $boundary . "\r\n";
29
  $data .= 'Content-Disposition: form-data; name="' . $key;
30
+ if ($key !== 'translation_locale_code' && $key !== 'translation_workflow_id'){ //request targets cannot be in an array, they need to have the same key
31
  $data .= '[' . $k . ']';
32
  }
33
  $data.= "\"\r\n\r\n";
89
  * @since 0.1
90
  */
91
  public function patch($url, $args = array()) {
92
+ Lingotek::log("PATCH $url");
93
+ if (!empty($args)) {
94
+ Lingotek::log($args);
95
+ }
96
+ return wp_remote_request($url, array('method' => 'PATCH', 'headers' => $this->headers, 'body' => $args, 'timeout' => self::TIMEOUT));
97
  }
98
  }
include/model.php CHANGED
@@ -182,7 +182,7 @@ class Lingotek_Model {
182
  return $profile[$item];
183
 
184
  $defaults = get_option('lingotek_defaults');
185
- return $defaults[$item];
186
  }
187
 
188
  /*
@@ -277,16 +277,14 @@ class Lingotek_Model {
277
  self::$copying_term = false;
278
  }
279
 
280
- /*
281
  * uploads a new post to Lingotek TMS and requests the targets specified
282
  *
283
  * @since 0.1
284
  *
285
  * @param int $post_id
286
- * @param array $target_locales ('translation_locale_code' => lingotek_locale_codes)
287
- * @param array $wp_target_locales (['ja','zh_CN'])
288
  */
289
- public function upload_post($post_id, $target_locales = array(), $wp_target_locales = array()) {
290
  $post = get_post($post_id);
291
  $language = PLL()->model->post->get_language($post_id);
292
  if (empty($post) || empty($language))
@@ -307,28 +305,11 @@ class Lingotek_Model {
307
 
308
  $client = new Lingotek_API();
309
  $external_url = add_query_arg(array('lingotek' => 1, 'document_id' => '{document_id}', 'locale' => '{locale}', 'type' => 'get'), site_url());
310
-
311
- $params = array(
312
- 'title' => $post->post_title,
313
- 'content' => Lingotek_Group_Post::get_content($post),
314
- 'locale_code' => $language->lingotek_locale,
315
- 'project_id' => self::get_profile_option('project_id', $post->post_type, $language, false, $post_id),
316
- 'workflow_id' => self::get_profile_option('workflow_id', $post->post_type, $language, false, $post_id),
317
- 'external_url' => $external_url,
318
- );
319
- foreach (array('author_email', 'author_name','division','unit','campaign_id','channel','contact_email','contact_name','description','domain','style_id','purchase_order','reference_url','region','require_review') as $key) {
320
- if (isset($profile[$key]) )
321
- $params[$key] = $profile[$key];
322
- }
323
- $filter_ids = array();
324
- if (self::get_profile_option('primary_filter_id', $post->post_type, $language, false, $post_id)) {
325
- $filter_ids['fprm_id'] = self::get_profile_option('primary_filter_id',$post->post_type, $language, false, $post_id);
326
- }
327
- if (self::get_profile_option('secondary_filter_id', $post->post_type, $language, false, $post_id)) {
328
- $filter_ids['fprm_subfilter_id'] = self::get_profile_option('secondary_filter_id',$post->post_type, $language, false, $post_id);
329
- }
330
  $params = array_merge($params, $filter_ids);
331
- $params = array_merge($params, $target_locales);
332
  if (($document = $this->get_group('post', $post_id)) && 'edited' == $document->status) {
333
  $document->patch($post->post_title, $post, $external_url, $filter_ids);
334
  }
@@ -337,7 +318,7 @@ class Lingotek_Model {
337
  $document_id = $client->upload_document($params, $post->ID);
338
 
339
  if ($document_id) {
340
- Lingotek_Group_Post::create($post->ID , $language, $document_id, $wp_target_locales);
341
  $document = $this->get_group_by_id( $document_id );
342
  foreach ($wp_target_locales as $locale){
343
  $document->translations[$locale] = 'pending';
@@ -355,16 +336,15 @@ class Lingotek_Model {
355
  }
356
  }
357
 
358
- /*
359
  * uploads a new term to Lingotek TMS
360
  *
361
  * @since 0.2
362
  *
363
  * @param int $term_id
364
  * @param string $taxonomy
365
- * @param array $target_locales ('translation_locale_code' => lingotek_locale_codes)
366
  */
367
- public function upload_term($term_id, $taxonomy, $target_locales = array(), $wp_target_locales = array()) {
368
  $term = get_term($term_id, $taxonomy);
369
  $language = PLL()->model->term->get_language($term_id);
370
  if (empty($term) || empty($language))
@@ -383,24 +363,10 @@ class Lingotek_Model {
383
  }
384
 
385
  $client = new Lingotek_API();
386
-
387
- $params = array(
388
- 'title' => $term->name,
389
- 'content' => Lingotek_Group_Term::get_content($term),
390
- 'locale_code' => $language->lingotek_locale,
391
- 'project_id' => self::get_profile_option('project_id', $taxonomy, $language),
392
- 'workflow_id' => self::get_profile_option('workflow_id', $taxonomy, $language)
393
- );
394
-
395
- $filter_ids = array();
396
- if (self::get_profile_option('primary_filter_id', $taxonomy, $language)) {
397
- $filter_ids['fprm_id'] = self::get_profile_option('primary_filter_id', $taxonomy, $language);
398
- }
399
- if (self::get_profile_option('secondary_filter_id', $taxonomy, $language)) {
400
- $filter_ids['fprm_subfilter_id'] = self::get_profile_option('secondary_filter_id', $taxonomy, $language);
401
- }
402
  $params = array_merge($params, $filter_ids);
403
- $params = array_merge($params, $target_locales);
404
 
405
  if (($document = $this->get_group('term', $term_id)) && 'edited' == $document->status) {
406
  $document->patch($term->name, $term, '', $filter_ids);
@@ -410,7 +376,7 @@ class Lingotek_Model {
410
  $document_id = $client->upload_document($params, $term_id);
411
 
412
  if ($document_id) {
413
- Lingotek_Group_Term::create($term_id, $taxonomy , $language, $document_id, $target_locales);
414
  $document = $this->get_group_by_id( $document_id );
415
  foreach ($wp_target_locales as $locale){
416
  $document->translations[$locale] = 'pending';
@@ -419,7 +385,7 @@ class Lingotek_Model {
419
 
420
  // If a translation profile has targets set to copy then copy them
421
  $targets_to_copy = $this->targets_to_be_copied($profile);
422
- if (!empty($targets_to_copy) && $upload == 'automatic') {
423
  foreach ($targets_to_copy as $target) {
424
  $this->copy_term($term, $target, $taxonomy);
425
  }
@@ -436,8 +402,9 @@ class Lingotek_Model {
436
  * @param string $group
437
  */
438
  public function upload_strings($group) {
 
439
  $language = $this->pllm->get_language($this->pllm->options['default_lang']);
440
- $profile = self::get_profile('string', $language);
441
 
442
  if ('disabled' == $profile['profile'])
443
  return;
@@ -452,26 +419,13 @@ class Lingotek_Model {
452
  return;
453
 
454
  $client = new Lingotek_API();
455
-
456
- $params = array(
457
- 'title' => $group,
458
- 'content' => Lingotek_Group_String::get_content($group),
459
- 'locale_code' => $language->lingotek_locale,
460
- 'project_id' => self::get_profile_option('project_id', 'string', $language),
461
- 'workflow_id' => self::get_profile_option('workflow_id', 'string', $language)
462
- );
463
-
464
- $filter_ids = array();
465
- if (self::get_profile_option('primary_filter_id', 'string', $language)) {
466
- $filter_ids['fprm_id'] = self::get_profile_option('primary_filter_id', 'string', $language);
467
- }
468
- if (self::get_profile_option('secondary_filter_id', 'string', $language)) {
469
- $filter_ids['fprm_subfilter_id'] = self::get_profile_option('secondary_filter_id', 'string', $language);
470
- }
471
  $params = array_merge($params, $filter_ids);
472
 
473
- if (($document = $this->get_group('string', $group)) && 'edited' == $document->status) {
474
- $document->patch($group);
475
  }
476
  else {
477
  $document_id = $client->upload_document($params, $group);
@@ -542,12 +496,12 @@ class Lingotek_Model {
542
  $client = new Lingotek_API();
543
 
544
  if ($document->source == $object_id) {
545
- $client->delete_document($document->document_id, $object_id);
546
  }
547
  else {
548
  PLL()->model->post->delete_translation($object_id);
549
  $lang = PLL()->model->post->get_language($object_id);
550
- $client->delete_translation($document->document_id, $lang->lingotek_locale, $object_id);
551
  }
552
  }
553
  }
@@ -581,15 +535,14 @@ class Lingotek_Model {
581
  public function delete_term($object_id) {
582
  if ($document = $this->get_group('term', $object_id)) {
583
  $client = new Lingotek_API();
584
-
585
  if ($document->source == $object_id) {
586
- $client->delete_document($document->document_id, $object_id);
587
  }
588
  else {
589
  $lang = PLL()->model->term->get_language($object_id);
590
  PLL()->model->term->delete_language($object_id);
591
  PLL()->model->term->delete_translation($object_id);
592
- $client->delete_translation($document->document_id, $lang->lingotek_locale, $object_id);
593
  }
594
  }
595
  }
@@ -839,4 +792,116 @@ class Lingotek_Model {
839
  // $total -= array_sum($disabled);
840
  return $r[$taxonomy] = compact('sources', 'targets', 'total');
841
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
842
  }
182
  return $profile[$item];
183
 
184
  $defaults = get_option('lingotek_defaults');
185
+ return isset($defaults[$item]) ? $defaults[$item] : null;
186
  }
187
 
188
  /*
277
  self::$copying_term = false;
278
  }
279
 
280
+ /**
281
  * uploads a new post to Lingotek TMS and requests the targets specified
282
  *
283
  * @since 0.1
284
  *
285
  * @param int $post_id
 
 
286
  */
287
+ public function upload_post($post_id) {
288
  $post = get_post($post_id);
289
  $language = PLL()->model->post->get_language($post_id);
290
  if (empty($post) || empty($language))
305
 
306
  $client = new Lingotek_API();
307
  $external_url = add_query_arg(array('lingotek' => 1, 'document_id' => '{document_id}', 'locale' => '{locale}', 'type' => 'get'), site_url());
308
+ $content = Lingotek_Group_Post::get_content($post);
309
+ $params = $this->build_params($post->post_title, $post->post_type, $content, $language, $profile, $post_id, $wp_target_locales);
310
+ $filter_ids = $this->get_filter_ids($post->post_type, $language, $post_id);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
311
  $params = array_merge($params, $filter_ids);
312
+
313
  if (($document = $this->get_group('post', $post_id)) && 'edited' == $document->status) {
314
  $document->patch($post->post_title, $post, $external_url, $filter_ids);
315
  }
318
  $document_id = $client->upload_document($params, $post->ID);
319
 
320
  if ($document_id) {
321
+ Lingotek_Group_Post::create($post->ID , $language, $document_id);
322
  $document = $this->get_group_by_id( $document_id );
323
  foreach ($wp_target_locales as $locale){
324
  $document->translations[$locale] = 'pending';
336
  }
337
  }
338
 
339
+ /**
340
  * uploads a new term to Lingotek TMS
341
  *
342
  * @since 0.2
343
  *
344
  * @param int $term_id
345
  * @param string $taxonomy
 
346
  */
347
+ public function upload_term($term_id, $taxonomy) {
348
  $term = get_term($term_id, $taxonomy);
349
  $language = PLL()->model->term->get_language($term_id);
350
  if (empty($term) || empty($language))
363
  }
364
 
365
  $client = new Lingotek_API();
366
+ $content = Lingotek_Group_Term::get_content($term);
367
+ $params = $this->build_params($term->name, $taxonomy, $content, $language, $profile, $term_id, $wp_target_locales);
368
+ $filter_ids = $this->get_filter_ids($taxonomy, $language, $term_id);
 
 
 
 
 
 
 
 
 
 
 
 
 
369
  $params = array_merge($params, $filter_ids);
 
370
 
371
  if (($document = $this->get_group('term', $term_id)) && 'edited' == $document->status) {
372
  $document->patch($term->name, $term, '', $filter_ids);
376
  $document_id = $client->upload_document($params, $term_id);
377
 
378
  if ($document_id) {
379
+ Lingotek_Group_Term::create($term_id, $taxonomy , $language, $document_id);
380
  $document = $this->get_group_by_id( $document_id );
381
  foreach ($wp_target_locales as $locale){
382
  $document->translations[$locale] = 'pending';
385
 
386
  // If a translation profile has targets set to copy then copy them
387
  $targets_to_copy = $this->targets_to_be_copied($profile);
388
+ if (!empty($targets_to_copy) && $profile['upload'] == 'automatic') {
389
  foreach ($targets_to_copy as $target) {
390
  $this->copy_term($term, $target, $taxonomy);
391
  }
402
  * @param string $group
403
  */
404
  public function upload_strings($group) {
405
+ $type = 'string';
406
  $language = $this->pllm->get_language($this->pllm->options['default_lang']);
407
+ $profile = self::get_profile($type, $language);
408
 
409
  if ('disabled' == $profile['profile'])
410
  return;
419
  return;
420
 
421
  $client = new Lingotek_API();
422
+ $content = Lingotek_Group_String::get_content($group);
423
+ $params = $this->build_params($group, $type, $content, $language, $profile, null);
424
+ $filter_ids = $this->get_filter_ids($type, $language, null);
 
 
 
 
 
 
 
 
 
 
 
 
 
425
  $params = array_merge($params, $filter_ids);
426
 
427
+ if (($document = $this->get_group($type, $group)) && 'edited' == $document->status) {
428
+ $document->patch($params['title'], $params['content'], '', $filter_ids);
429
  }
430
  else {
431
  $document_id = $client->upload_document($params, $group);
496
  $client = new Lingotek_API();
497
 
498
  if ($document->source == $object_id) {
499
+ $client->cancel_document($document->document_id, $object_id);
500
  }
501
  else {
502
  PLL()->model->post->delete_translation($object_id);
503
  $lang = PLL()->model->post->get_language($object_id);
504
+ $client->cancel_translation($document->document_id, $lang->lingotek_locale, $object_id);
505
  }
506
  }
507
  }
535
  public function delete_term($object_id) {
536
  if ($document = $this->get_group('term', $object_id)) {
537
  $client = new Lingotek_API();
 
538
  if ($document->source == $object_id) {
539
+ $client->cancel_document($document->document_id, $object_id);
540
  }
541
  else {
542
  $lang = PLL()->model->term->get_language($object_id);
543
  PLL()->model->term->delete_language($object_id);
544
  PLL()->model->term->delete_translation($object_id);
545
+ $client->cancel_translation($document->document_id, $lang->lingotek_locale, $object_id);
546
  }
547
  }
548
  }
792
  // $total -= array_sum($disabled);
793
  return $r[$taxonomy] = compact('sources', 'targets', 'total');
794
  }
795
+
796
+ private function build_params($title, $type, $content, $language, $profile, $wp_id, &$wp_target_locales = array()) {
797
+
798
+ $translation_workflow_id = self::get_profile_option('workflow_id', $type, $language, false, $wp_id);
799
+ if ($translation_workflow_id === 'project-default' || $translation_workflow_id === false) {
800
+ $translation_workflow_id = null;
801
+ }
802
+
803
+ $params = array(
804
+ 'title' => $title,
805
+ 'content' => $content,
806
+ 'locale_code' => $language->lingotek_locale,
807
+ 'project_id' => self::get_profile_option('project_id', $type, $language, false, $wp_id),
808
+ );
809
+
810
+ if ($wp_id) {
811
+ $external_url = add_query_arg(array('lingotek' => 1, 'document_id' => '{document_id}', 'locale' => '{locale}', 'type' => 'get'), site_url());
812
+ $params['external_url'] = $external_url;
813
+ }
814
+
815
+ $lingotek_metadata_keys = array('author_email',
816
+ 'author_name',
817
+ 'division',
818
+ 'unit',
819
+ 'campaign_id',
820
+ 'channel',
821
+ 'contact_email',
822
+ 'contact_name',
823
+ 'description',
824
+ 'domain',
825
+ 'style_id',
826
+ 'purchase_order',
827
+ 'reference_url',
828
+ 'region',
829
+ 'require_review',
830
+ );
831
+
832
+ foreach ($lingotek_metadata_keys as $key) {
833
+ if (isset($profile[$key]) )
834
+ $params[$key] = $profile[$key];
835
+ }
836
+
837
+ if ($translation_workflow_id !== null) {
838
+ $params['translation_workflow_id'] = $translation_workflow_id;
839
+ }
840
+
841
+ // Get target locales to send up from profile
842
+ $target_locales = array();
843
+ if (!empty($profile['target_locales'])) {
844
+ if (isset($profile['target_locales'][$language->slug])) {
845
+ unset($profile['target_locales'][$language->slug]);
846
+ }
847
+ if (isset($profile['custom']['workflow_id'][$language->slug])) {
848
+ unset($profile['custom']['workflow_id'][$language->slug]);
849
+ }
850
+ $target_locales['translation_locale_code'] = array_values($profile['target_locales']);
851
+ $wp_target_locales = array_keys($profile['target_locales']);
852
+
853
+ // Add workflows
854
+ if (!empty($profile['custom']['workflow_id'])) {
855
+ $temp_workflow_ids = array();
856
+ $num_project_default = 0;
857
+ foreach ($wp_target_locales as $language_slug) {
858
+ if (isset($profile['custom']['workflow_id'][$language_slug])) {
859
+ if ($profile['custom']['workflow_id'][$language_slug] === 'project-default') {
860
+ $temp_workflow_ids[] = null;
861
+ ++$num_project_default;
862
+ }
863
+ else {
864
+ $workflow_id = $profile['custom']['workflow_id'][$language_slug] === 'project-default' ? null : $profile['custom']['workflow_id'][$language_slug];
865
+ $temp_workflow_ids[] = $workflow_id;
866
+ if ($workflow_id === null) {
867
+ ++$num_project_default;
868
+ }
869
+ }
870
+ }
871
+ else {
872
+ $temp_workflow_ids[] = $translation_workflow_id;
873
+ if ($translation_workflow_id === null) {
874
+ ++$num_project_default;
875
+ }
876
+ }
877
+ }
878
+ if (count($temp_workflow_ids) !== $num_project_default) {
879
+ $params['translation_workflow_id'] = $temp_workflow_ids;
880
+ }
881
+ else {
882
+ // All selected languages will use the project default workflow, therefore unset the workflow
883
+ unset($params['translation_workflow_id']);
884
+ }
885
+ }
886
+ }
887
+ else {
888
+ // No targets being sent up to TMS, unset the workflow
889
+ unset($params['translation_workflow_id']);
890
+ }
891
+
892
+ $params = array_merge($params, $target_locales);
893
+
894
+ return $params;
895
+ }
896
+
897
+ private function get_filter_ids($type, $language, $wp_id) {
898
+ $filter_ids = array();
899
+ if (self::get_profile_option('primary_filter_id', $type, $language, false, $wp_id)) {
900
+ $filter_ids['fprm_id'] = self::get_profile_option('primary_filter_id',$type, $language, false, $wp_id);
901
+ }
902
+ if (self::get_profile_option('secondary_filter_id', $type, $language, false, $wp_id)) {
903
+ $filter_ids['fprm_subfilter_id'] = self::get_profile_option('secondary_filter_id',$type, $language, false, $wp_id);
904
+ }
905
+ return $filter_ids;
906
+ }
907
  }
js/target-dialog.js DELETED
@@ -1,162 +0,0 @@
1
- jQuery(document).ready(function($) {
2
- function singleUpload() {
3
- var data = {
4
- action: "lingotek_upload_with_target",
5
- taxonomy: lingotek_upload_data.taxonomy,
6
- id: lingotek_upload_data.id,
7
- type: lingotek_upload_data.type,
8
- locales: JSON.stringify($("#target-select").select2('data').map(a => a.text)), //select2('data') gets selected objects
9
- _lingotek_target_nonce: lingotek_upload_data.nonce,
10
- }
11
- $.ajax({
12
- type: "POST",
13
- url: ajaxurl,
14
- data: data,
15
- contentType: "application/x-www-form-urlencoded; charset=UTF-8",
16
- success: function(data){
17
- jQuery(location).attr('href', lingotek_upload_data.sendback);
18
- }
19
- });
20
- }
21
-
22
- function bulkUpload(){
23
- var urlParts = window.location.href.split('?');
24
- var params = new URLSearchParams(urlParts[1]);
25
- params.delete('show_target_dialog');
26
- params.append('locales', $("#target-select").select2('data').map(a => a.text));
27
- var redirect = urlParts[0] + '?' + params.toString();
28
- window.location.replace(redirect);
29
- }
30
-
31
- if ('undefined' != typeof(lingotek_upload_data)) {
32
- if (lingotek_upload_data.show) {
33
- var d = $("#lingotek-targetselector");
34
- if (d.length) {
35
- d.dialog({
36
- width: 410,
37
- dialogClass: "targetSelector",
38
- buttons: [
39
- {
40
- id: "request-button",
41
- class: "requestButton",
42
- text: "Save",
43
- click: function(){
44
- lingotek_upload_data.bulk ? bulkUpload() : singleUpload();
45
- },
46
- disabled: true,
47
- },
48
- {
49
- text:"Cancel",
50
- click: function(){
51
- $(this).dialog('close');
52
- }
53
- },
54
- ]
55
- });
56
- d.bind("dialogclose", function(e) {
57
- window.location = lingotek_upload_data.sendback;
58
- });
59
-
60
- var locales = lingotek_upload_data.locales.map((x, i) => {
61
- var obj = {};
62
- obj.id = i;
63
- obj.text = x;
64
- return obj;
65
- });
66
-
67
- //Make backspace delete tags instead of changing text thanks ghilios (select2 github issue 3354)
68
- $.fn.select2.amd.require(['select2/selection/search'], function (Search) {
69
- Search.prototype.searchRemoveChoice = function (decorated, item) {
70
- this.trigger('unselect', {
71
- data: item
72
- });
73
-
74
- this.$search.val('');
75
- this.handleSearch();
76
- };
77
- }, null, true);
78
-
79
- let $select2 = $("#target-select").select2({
80
- multiple: true,
81
- data: locales,
82
- placeholder: "Select Targets",
83
- width: 398,
84
- closeOnSelect: false,
85
- sorter: data => data.sort((a, b) => a.text.localeCompare(b.text)),
86
- templateResult: function(value){
87
- if (value && !value.selected){
88
- return $('<span>' + value.text + "</span>");
89
- }
90
- },
91
- });
92
-
93
- //make selected tags always append, but preserve order when removed. Thanks vol7ron for this fix (select2 github issue 3106)
94
- //modified a bit since didn't work properly for this case
95
- /**
96
- * select2_renderselections
97
- * @param {jQuery Select2 object}
98
- * @return {null}
99
- */
100
- function select2_renderSelections($select2){
101
- const order = $select2.data('preserved-order') || [];
102
- const $container = $select2.next('.select2-container');
103
- const $tags = $container.find('li.select2-selection__choice');
104
- const $input = $tags.last().next();
105
-
106
- // apply tag order
107
- order.forEach(val=>{
108
- for (let i =0; i < $tags.length; i++){
109
- $el = $tags[i];
110
- if ($el.title === val.text){
111
- break;
112
- }
113
- }
114
- $input.before( $el );
115
- });
116
- }
117
- /**
118
- * selectionHandler
119
- * @param {Select2 Event Object}
120
- * @return {null}
121
- */
122
- function selectionHandler(e){
123
- const $select2 = $(this);
124
- const val = e.params.data.id;
125
- const text = e.params.data.text;
126
- const order = $select2.data('preserved-order') || [];
127
-
128
- switch (e.type){
129
- case 'select2:select':
130
- order[order.length] = { id: val, text: text};
131
- break;
132
- case 'select2:unselect':
133
- let found_index = order.map(a => a.id).indexOf(val);
134
- if (found_index >= 0 ) {
135
- order.splice(found_index,1);
136
- }
137
- break;
138
- }
139
- $select2.data('preserved-order', order); // store it for later
140
- select2_renderSelections($select2);
141
- }
142
-
143
- $select2.on('select2:select select2:unselect', selectionHandler);
144
-
145
- //disable button until at least one target selected
146
- $select2.on('change', function(e){
147
- if ($(this).find(':selected').length == 0){
148
- $('#request-button').prop("disabled",true);
149
- } else{
150
- $('#request-button').prop("disabled", false);
151
- }
152
- //refresh after each choice instead of highlighting
153
- $select2.select2("close");
154
- $select2.select2("open");
155
- })
156
- }
157
-
158
- } else {
159
- jQuery(location).attr('href', lingotek_upload_data.sendback);
160
- }
161
- }
162
- });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
js/updater.js CHANGED
@@ -230,13 +230,13 @@ jQuery(document).ready(function($) {
230
  } else if($(disassociate).length > 0 ){
231
  $(disassociate).off("click");
232
  $(disassociate).click(function(){
233
- return confirm('You are about to delete existing translations from your Lingotek community. Are you sure?');
234
  });
235
  $(disassociate).before(status_update_link);
236
  } else if($(disassociate_translation).length > 0){
237
  $(disassociate_translation).off("click");
238
  $(disassociate_translation).click(function(){
239
- return confirm('You are about to delete this translation from your Lingotek community. Are you sure?');
240
  });
241
  $(disassociate_translation).before(status_update_link);
242
  } else {
230
  } else if($(disassociate).length > 0 ){
231
  $(disassociate).off("click");
232
  $(disassociate).click(function(){
233
+ return confirm('You are about to cancel existing translations in your Lingotek community. Are you sure?');
234
  });
235
  $(disassociate).before(status_update_link);
236
  } else if($(disassociate_translation).length > 0){
237
  $(disassociate_translation).off("click");
238
  $(disassociate_translation).click(function(){
239
+ return confirm('You are about to cancel this translations in your Lingotek community. Are you sure?');
240
  });
241
  $(disassociate_translation).before(status_update_link);
242
  } else {
lingotek.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  Plugin name: Lingotek Translation
4
  Plugin URI: http://lingotek.com/wordpress#utm_source=wpadmin&utm_medium=plugin&utm_campaign=wplingotektranslationplugin
5
- Version: 1.4.4
6
  Author: Lingotek and Frédéric Demarle
7
  Author uri: http://lingotek.com
8
  Description: Lingotek offers convenient cloud-based localization and translation.
@@ -16,7 +16,7 @@ if ( ! function_exists( 'add_action' ) ) {
16
  exit();
17
  }
18
 
19
- define( 'LINGOTEK_VERSION', '1.4.4' ); // plugin version (should match above meta).
20
  define( 'LINGOTEK_MIN_PLL_VERSION', '1.8' );
21
  define( 'LINGOTEK_BASENAME', plugin_basename( __FILE__ ) ); // plugin name as known by WP.
22
  define( 'LINGOTEK_PLUGIN_SLUG', 'lingotek-translation' );// plugin slug (should match above meta: Text Domain).
2
  /**
3
  Plugin name: Lingotek Translation
4
  Plugin URI: http://lingotek.com/wordpress#utm_source=wpadmin&utm_medium=plugin&utm_campaign=wplingotektranslationplugin
5
+ Version: 1.4.5
6
  Author: Lingotek and Frédéric Demarle
7
  Author uri: http://lingotek.com
8
  Description: Lingotek offers convenient cloud-based localization and translation.
16
  exit();
17
  }
18
 
19
+ define( 'LINGOTEK_VERSION', '1.4.5' ); // plugin version (should match above meta).
20
  define( 'LINGOTEK_MIN_PLL_VERSION', '1.8' );
21
  define( 'LINGOTEK_BASENAME', plugin_basename( __FILE__ ) ); // plugin name as known by WP.
22
  define( 'LINGOTEK_PLUGIN_SLUG', 'lingotek-translation' );// plugin slug (should match above meta: Text Domain).
readme.txt CHANGED
@@ -3,8 +3,8 @@ Contributors: chouby, smithworx, erichie, robertdhanna, ipoulsen, elliothanna, l
3
  Donate link: http://lingotek.com/
4
  Tags: automation, bilingual, international, language, Lingotek, localization, multilanguage, multilingual, translate, translation
5
  Requires at least: 3.8
6
- Tested up to: 5.2.2
7
- Stable tag: 1.4.4
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
 
@@ -122,7 +122,13 @@ For more, visit the [Lingotek documentation site](https://lingotek.atlassian.net
122
  5. The Lingotek Translation plugin provides the ability to Copy, Translate, and Ignore each specific custom field. Our plugin supports Wordpress custom fields and advanced custom fields.
123
 
124
  == Changelog ==
125
- = 1.4.4 (2019-11-7)
 
 
 
 
 
 
126
  * Changed upload process to allow user to select targets on source upload
127
 
128
  = 1.4.3 (2019-7-23) =
3
  Donate link: http://lingotek.com/
4
  Tags: automation, bilingual, international, language, Lingotek, localization, multilanguage, multilingual, translate, translation
5
  Requires at least: 3.8
6
+ Tested up to: 5.3
7
+ Stable tag: 1.4.5
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
 
122
  5. The Lingotek Translation plugin provides the ability to Copy, Translate, and Ignore each specific custom field. Our plugin supports Wordpress custom fields and advanced custom fields.
123
 
124
  == Changelog ==
125
+
126
+ = 1.4.5 (2019-12-3) =
127
+ * Removed Translation Modal
128
+ * Changed API to be compatible with new Lingotek Update Document
129
+ * Updated delete functionality
130
+
131
+ = 1.4.4 (2019-11-7) =
132
  * Changed upload process to allow user to select targets on source upload
133
 
134
  = 1.4.3 (2019-7-23) =