Lingotek Translation - Version 1.4.3

Version Description

(2019-7-23) =

  • Fixed issue where Lingotek plugin would not refresh custom fields
  • Cancel and Delete implementation working for standard content types
  • Bulk actions now differentiate between target and source documents
  • Added enhanced logging for api and callbacks
  • Fixed other minor bugs
Download this release

Release Info

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

Code changes from version 1.4.2 to 1.4.3

admin/actions.php CHANGED
@@ -44,6 +44,34 @@ abstract class Lingotek_Actions {
44
  */
45
  public static $confirm_message;
46
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
47
  /**
48
  * Constructor
49
  *
@@ -52,7 +80,10 @@ abstract class Lingotek_Actions {
52
  public function __construct( $type ) {
53
  // confirm message.
54
  self::$confirm_message = sprintf( ' onclick = "return confirm(\'%s\');"', __( 'You are about to overwrite existing translations. Are you sure?', 'lingotek-translation' ) );
55
-
 
 
 
56
  // row actions.
57
  self::$actions = array(
58
  'upload' => array(
@@ -79,10 +110,28 @@ abstract class Lingotek_Actions {
79
  'description' => __( 'Download translations of this item from Lingotek TMS', 'lingotek-translation' ),
80
  ),
81
 
 
 
 
 
 
 
82
  'delete' => array(
83
- 'action' => __( 'Disassociate translations', 'lingotek-translation' ),
84
- 'progress' => __( 'Disassociating translations...', 'lingotek-translation' ),
85
- 'description' => __( 'Disassociate the translations of this item from Lingotek TMS', 'lingotek-translation' ),
 
 
 
 
 
 
 
 
 
 
 
 
86
  ),
87
  );
88
 
@@ -135,13 +184,18 @@ abstract class Lingotek_Actions {
135
 
136
  'error' => array(
137
  'title' => __( 'There was an error contacting Lingotek', 'lingotek-translation' ),
138
- 'icon' => 'warning',
139
  ),
140
 
141
  'copy' => array(
142
  'title' => __( 'Copy source language', 'lingotek-translation' ),
143
  'icon' => 'welcome-add-page',
144
  ),
 
 
 
 
 
145
  );
146
 
147
  $this->type = $type;
@@ -156,6 +210,9 @@ abstract class Lingotek_Actions {
156
  add_action( 'wp_ajax_get_ltk_terms_and_conditions', array( &$this, 'ajax_get_ltk_terms_and_conditions' ) );
157
 
158
  foreach ( array_keys( self::$actions ) as $action ) {
 
 
 
159
  add_action( 'wp_ajax_lingotek_progress_' . $this->type . '_' . $action , array( &$this, 'ajax_' . $action ) );
160
  }
161
  }
@@ -347,12 +404,30 @@ abstract class Lingotek_Actions {
347
  }
348
  $link = wp_nonce_url( defined( 'DOING_AJAX' ) && DOING_AJAX ? add_query_arg( $args, wp_get_referer() ) : add_query_arg( $args ), 'lingotek-' . $action );
349
  self::link_to_settings_if_not_connected($link);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
350
 
351
  return sprintf(
352
  '<a class="lingotek-color" title="%s" href="%s"%s>%s</a>',
353
  self::$actions[ $action ]['description'],
354
  $link,
355
- empty( $warning ) ? '' : self::$confirm_message,
356
  self::$actions[ $action ]['action']
357
  );
358
  }
@@ -378,8 +453,9 @@ abstract class Lingotek_Actions {
378
  if ( ! $this->get_language( $id ) ) {
379
  return $actions;
380
  }
381
-
382
  $document = $this->lgtm->get_group( $this->type, $id );
 
 
383
  if ( $this->type !== 'string' && isset( $document->desc_array['lingotek']['source'] ) ) {
384
  $id = $document->desc_array['lingotek']['source'];
385
  }
@@ -451,9 +527,13 @@ abstract class Lingotek_Actions {
451
  $actions['lingotek-upload'] = $this->get_action_link( array( $this->type => $id, 'action' => 'upload' ), true );
452
  }
453
 
454
- // offers to disassociate translations
455
- if ( isset( $document->source ) ) {
456
- $actions['lingotek-delete'] = $this->get_action_link( array( 'document_id' => $document->document_id, 'action' => 'delete' ) );
 
 
 
 
457
  }
458
 
459
  return $actions;
@@ -467,14 +547,15 @@ abstract class Lingotek_Actions {
467
  * @since 0.2
468
  */
469
  protected function _add_bulk_actions( $bulk_actions ) {
470
-
471
  foreach ( self::$actions as $action => $strings ) {
 
 
 
472
  $bulk_actions[ 'bulk-lingotek-' . $action ] = __( $strings['action'], $action );
473
  if ( null !== filter_input( INPUT_GET, 'bulk-lingotek-' . $action ) ) {
474
  $text = $strings['progress'];
475
  }
476
  }
477
-
478
  if ( ! empty( $text ) ) {
479
  printf( '<div id="lingotek-progressdialog" style="display:none" title="%s"><div id="lingotek-progressbar"></div></div>', esc_html( $text ) );
480
  }
@@ -489,13 +570,13 @@ abstract class Lingotek_Actions {
489
  */
490
  public function admin_enqueue_scripts() {
491
  foreach ( array_keys( self::$actions ) as $action ) {
492
- if ( null !== filter_input( INPUT_GET, 'bulk-lingotek-' . $action ) ) {
493
  wp_localize_script('lingotek_progress', 'lingotek_data', array(
494
- 'action' => null === filter_input( INPUT_GET, 'page' ) ? (null === filter_input( INPUT_GET, 'taxonomy' ) ? 'post_' . $action : 'term_' . $action) : 'string_' . $action,
495
  'taxonomy' => null === filter_input( INPUT_GET, 'taxonomy' ) || ! taxonomy_exists( wp_unslash( filter_input( INPUT_GET, 'taxonomy' ) ) ) ? '' : filter_input( INPUT_GET, 'taxonomy' ),
496
- 'sendback' => remove_query_arg( array( 'bulk-lingotek-' . $action, 'ids', 'lingotek_warning' ), wp_get_referer() ),
497
  'ids' => array_map( 'intval', explode( ',', filter_input( INPUT_GET, 'ids' ) ) ),
498
- 'warning' => null === filter_input( INPUT_GET, 'lingotek_warning' ) ? '' : __( 'You are about to overwrite existing translations. Are you sure?', 'lingotek-translation' ),
499
  'nonce' => wp_create_nonce( 'lingotek_progress' ),
500
  ));
501
  return;
@@ -538,6 +619,9 @@ abstract class Lingotek_Actions {
538
 
539
  case 'lingotek-delete':
540
  check_admin_referer( 'lingotek-delete' );
 
 
 
541
  $document->disassociate();
542
  if ( null !== filter_input( INPUT_GET, 'lingotek_redirect' ) && filter_input( INPUT_GET, 'lingotek_redirect' ) === true ) {
543
  $site_id = get_current_blog_id();
@@ -545,7 +629,43 @@ abstract class Lingotek_Actions {
545
  exit();
546
  }
547
  break;
 
 
 
 
 
 
 
 
 
 
548
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
549
  default:
550
  return false;
551
  }
@@ -560,7 +680,6 @@ abstract class Lingotek_Actions {
560
  */
561
  public function ajax_download() {
562
  check_ajax_referer( 'lingotek_progress', '_lingotek_nonce' );
563
-
564
  if ( $document = $this->lgtm->get_group( $this->type, filter_input( INPUT_POST, 'id' ) ) ) {
565
  foreach ( $document->translations as $locale => $status ) {
566
  if ( 'pending' === $status || 'ready' === $status || 'interim' === $status || 'current' === $status) {
@@ -599,14 +718,40 @@ abstract class Lingotek_Actions {
599
  }
600
 
601
  /**
602
- * Ajax response disassociate translations and showing progress
603
  *
604
  * @since 0.2
605
  */
606
  public function ajax_delete() {
607
  check_ajax_referer( 'lingotek_progress', '_lingotek_nonce' );
608
- if ( $document = $this->lgtm->get_group( $this->type, filter_input( INPUT_POST, 'id' ) ) ) {
 
 
 
 
 
 
609
  $document->disassociate();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
610
  }
611
  die();
612
  }
44
  */
45
  public static $confirm_message;
46
 
47
+ /**
48
+ * Confirm_delete
49
+ *
50
+ * @var string
51
+ */
52
+ public static $confirm_delete;
53
+
54
+ /**
55
+ * Confirm_cancel
56
+ *
57
+ * @var string
58
+ */
59
+ public static $confirm_cancel;
60
+
61
+ /**
62
+ * Confirm_delete_translation
63
+ *
64
+ * @var string
65
+ */
66
+ public static $confirm_delete_translation;
67
+
68
+ /**
69
+ * Confirm_cancel_translation
70
+ *
71
+ * @var string
72
+ */
73
+ public static $confirm_cancel_translation;
74
+
75
  /**
76
  * Constructor
77
  *
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(
89
  'upload' => array(
110
  'description' => __( 'Download translations of this item from Lingotek TMS', 'lingotek-translation' ),
111
  ),
112
 
113
+ 'cancel' => array(
114
+ 'action' => __( 'Cancel translations', 'lingotek-translation' ),
115
+ 'progress' => __( 'Cancelling translations...', 'lingotek-translation' ),
116
+ 'description' => __( 'Cancel the translations of this item from Lingotek TMS', 'lingotek-translation' ),
117
+ ),
118
+
119
  'delete' => array(
120
+ 'action' => __( 'Delete translations', 'lingotek-translation' ),
121
+ 'progress' => __( 'Deleting translations...', 'lingotek-translation' ),
122
+ 'description' => __( 'Delete the translations of this item from Lingotek TMS', 'lingotek-translation' ),
123
+ ),
124
+
125
+ 'cancel-translation' => array(
126
+ 'action' => __('Cancel translation', 'lingotek-translation'),
127
+ 'progress' => __('Cancelling translation', 'lingotek-translation'),
128
+ 'description' => __('Cancel this translation from Lingotek TMS', 'lingotek-translation'),
129
+ ),
130
+
131
+ 'delete-translation' => array(
132
+ 'action' => __('Delete translation', 'lingotek-translation'),
133
+ 'progress' => __('Deleting translation', 'lingotek-translation'),
134
+ 'description' => __('Delete this translation from Lingotek TMS', 'lingotek-translation'),
135
  ),
136
  );
137
 
184
 
185
  'error' => array(
186
  'title' => __( 'There was an error contacting Lingotek', 'lingotek-translation' ),
187
+ 'icon' => 'no',
188
  ),
189
 
190
  'copy' => array(
191
  'title' => __( 'Copy source language', 'lingotek-translation' ),
192
  'icon' => 'welcome-add-page',
193
  ),
194
+
195
+ 'cancelled' => array(
196
+ 'title' => __('Translation has been cancelled', 'lingotek-translation'),
197
+ 'icon' => 'warning',
198
+ ),
199
  );
200
 
201
  $this->type = $type;
210
  add_action( 'wp_ajax_get_ltk_terms_and_conditions', array( &$this, 'ajax_get_ltk_terms_and_conditions' ) );
211
 
212
  foreach ( array_keys( self::$actions ) as $action ) {
213
+ if(strpos($action, '-translation')){
214
+ continue;
215
+ }
216
  add_action( 'wp_ajax_lingotek_progress_' . $this->type . '_' . $action , array( &$this, 'ajax_' . $action ) );
217
  }
218
  }
404
  }
405
  $link = wp_nonce_url( defined( 'DOING_AJAX' ) && DOING_AJAX ? add_query_arg( $args, wp_get_referer() ) : add_query_arg( $args ), 'lingotek-' . $action );
406
  self::link_to_settings_if_not_connected($link);
407
+
408
+ switch($action){
409
+ case 'cancel':
410
+ $message = self::$confirm_cancel;
411
+ break;
412
+ case 'cancel-translation':
413
+ $message = self::$confirm_cancel_translation;
414
+ break;
415
+ case 'delete':
416
+ $message = self::$confirm_delete;
417
+ break;
418
+ case 'delete-translation':
419
+ $message = self::$confirm_delete_translation;
420
+ break;
421
+ default:
422
+ $message = self::$confirm_message;
423
+ break;
424
+ }
425
 
426
  return sprintf(
427
  '<a class="lingotek-color" title="%s" href="%s"%s>%s</a>',
428
  self::$actions[ $action ]['description'],
429
  $link,
430
+ empty( $warning ) ? '' : $message,
431
  self::$actions[ $action ]['action']
432
  );
433
  }
453
  if ( ! $this->get_language( $id ) ) {
454
  return $actions;
455
  }
 
456
  $document = $this->lgtm->get_group( $this->type, $id );
457
+
458
+ $target_id = $id;
459
  if ( $this->type !== 'string' && isset( $document->desc_array['lingotek']['source'] ) ) {
460
  $id = $document->desc_array['lingotek']['source'];
461
  }
527
  $actions['lingotek-upload'] = $this->get_action_link( array( $this->type => $id, 'action' => 'upload' ), true );
528
  }
529
 
530
+ $target_locale = $this->get_language($target_id)->locale;
531
+ if ( $id == $target_id && isset( $document->source ) ) {
532
+ $actions['lingotek-cancel'] = $this->get_action_link( array( 'document_id' => $document->document_id, 'action' => 'cancel' ), true );
533
+ $actions['lingotek-delete'] = $this->get_action_link( array( 'document_id' => $document->document_id, 'action' => 'delete' ), true );
534
+ } else if ( isset($document->source) && isset($document->translations[$target_locale]) && $document->translations[$target_locale] != 'cancelled' ) {
535
+ $actions['lingotek-cancel-translation'] = $this->get_action_link(array('document_id' => $document->document_id, 'target_id' => $target_id, 'target_locale' => $target_locale, 'action' => 'cancel-translation'), true);
536
+ $actions['lingotek-delete-translation'] = $this->get_action_link(array('document_id' => $document->document_id, 'target_id' => $target_id, 'target_locale' => $target_locale, 'action' => 'delete-translation'), true);
537
  }
538
 
539
  return $actions;
547
  * @since 0.2
548
  */
549
  protected function _add_bulk_actions( $bulk_actions ) {
 
550
  foreach ( self::$actions as $action => $strings ) {
551
+ if(strpos($action, '-translation')){
552
+ continue;
553
+ }
554
  $bulk_actions[ 'bulk-lingotek-' . $action ] = __( $strings['action'], $action );
555
  if ( null !== filter_input( INPUT_GET, 'bulk-lingotek-' . $action ) ) {
556
  $text = $strings['progress'];
557
  }
558
  }
 
559
  if ( ! empty( $text ) ) {
560
  printf( '<div id="lingotek-progressdialog" style="display:none" title="%s"><div id="lingotek-progressbar"></div></div>', esc_html( $text ) );
561
  }
570
  */
571
  public function admin_enqueue_scripts() {
572
  foreach ( array_keys( self::$actions ) as $action ) {
573
+ if ( null !== filter_input( INPUT_GET, "bulk-lingotek-$action" ) ) {
574
  wp_localize_script('lingotek_progress', 'lingotek_data', array(
575
+ 'action' => null === filter_input( INPUT_GET, 'page' ) ? (null === filter_input( INPUT_GET, 'taxonomy' ) ? "post_$action" : "term_$action") : "string_$action",
576
  'taxonomy' => null === filter_input( INPUT_GET, 'taxonomy' ) || ! taxonomy_exists( wp_unslash( filter_input( INPUT_GET, 'taxonomy' ) ) ) ? '' : filter_input( INPUT_GET, 'taxonomy' ),
577
+ 'sendback' => remove_query_arg( array( "bulk-lingotek-$action", 'ids', 'lingotek_warning' ), wp_get_referer() ),
578
  'ids' => array_map( 'intval', explode( ',', filter_input( INPUT_GET, 'ids' ) ) ),
579
+ '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' ),
580
  'nonce' => wp_create_nonce( 'lingotek_progress' ),
581
  ));
582
  return;
619
 
620
  case 'lingotek-delete':
621
  check_admin_referer( 'lingotek-delete' );
622
+ /**it was left as disassociate so that the delete functionality wouldn't break as it
623
+ * did when changing disassociate to delete/cancel in other connectors
624
+ */
625
  $document->disassociate();
626
  if ( null !== filter_input( INPUT_GET, 'lingotek_redirect' ) && filter_input( INPUT_GET, 'lingotek_redirect' ) === true ) {
627
  $site_id = get_current_blog_id();
629
  exit();
630
  }
631
  break;
632
+
633
+ case 'lingotek-cancel':
634
+ check_admin_referer( 'lingotek-cancel' );
635
+ $document->cancel();
636
+ if ( null !== filter_input( INPUT_GET, 'lingotek_redirect' ) && filter_input( INPUT_GET, 'lingotek_redirect' ) === true ) {
637
+ $site_id = get_current_blog_id();
638
+ wp_safe_redirect( get_site_url( $site_id, '/wp-admin/edit.php?post_type=page' ) );
639
+ exit();
640
+ }
641
+ break;
642
 
643
+ case 'lingotek-delete-translation':
644
+ check_admin_referer('lingotek-delete-translation');
645
+ $target_locale = filter_input(INPUT_GET, 'target_locale');
646
+ $target_id = filter_input(INPUT_GET, 'target_id');
647
+ $language = PLL()->model->post->get_language($target_id);
648
+ $document->delete_translation($language, $target_id);
649
+ if(null !== filter_input(INPUT_GET, 'lingotek_redirect') && filter_input(INPUT_GET, 'lingotek_redirect') === true) {
650
+ $site_id = get_current_blog_id();
651
+ wp_safe_redirect(get_site_url($site_id, '/wp-admin/edit.php?post_type=page'));
652
+ exit();
653
+ }
654
+ break;
655
+
656
+ case 'lingotek-cancel-translation':
657
+ check_admin_referer('lingotek-cancel-translation');
658
+ $target_locale = filter_input(INPUT_GET, 'target_locale');
659
+ $target_id = filter_input(INPUT_GET, 'target_id');
660
+ $language = PLL()->model->post->get_language($target_id);
661
+ $document->cancel_translation($language, $target_id);
662
+ if(null !== filter_input(INPUT_GET, 'lingotek_redirect') && filter_input(INPUT_GET, 'lingotek_redirect') === true) {
663
+ $site_id = get_current_blog_id();
664
+ wp_safe_redirect(get_site_url($site_id, '/wp-admin/edit.php?post_type=page'));
665
+ exit();
666
+ }
667
+ break;
668
+
669
  default:
670
  return false;
671
  }
680
  */
681
  public function ajax_download() {
682
  check_ajax_referer( 'lingotek_progress', '_lingotek_nonce' );
 
683
  if ( $document = $this->lgtm->get_group( $this->type, filter_input( INPUT_POST, 'id' ) ) ) {
684
  foreach ( $document->translations as $locale => $status ) {
685
  if ( 'pending' === $status || 'ready' === $status || 'interim' === $status || 'current' === $status) {
718
  }
719
 
720
  /**
721
+ * Ajax response delete translations and showing progress
722
  *
723
  * @since 0.2
724
  */
725
  public function ajax_delete() {
726
  check_ajax_referer( 'lingotek_progress', '_lingotek_nonce' );
727
+ $id = filter_input(INPUT_POST, 'id');
728
+ $language = PLL()->model->post->get_language($id);
729
+ $document = $this->lgtm->get_group( $this->type, $id );
730
+ if ( $document && $document->source == $id ) {
731
+ /**it was left as disassociate so that the delete functionality wouldn't break as it
732
+ * did when changing disassociate to delete/cancel in other connectors
733
+ */
734
  $document->disassociate();
735
+ } else if ($document && $document->source != $id && $language) {
736
+ $document->delete_translation($language, $id);
737
+ }
738
+ die();
739
+ }
740
+
741
+ /**
742
+ * Ajax response cancel translations and showing progress
743
+ *
744
+ */
745
+ public function ajax_cancel() {
746
+ check_ajax_referer( 'lingotek_progress', '_lingotek_nonce' );
747
+ $id = filter_input(INPUT_POST, 'id');
748
+ $language = PLL()->model->post->get_language($id);
749
+ $document = $this->lgtm->get_group( $this->type, $id);
750
+ if ( $document && $document->source == $id ) {
751
+ $document->cancel();
752
+ } else if ($document && $document->source != $id && $language){
753
+
754
+ $document->cancel_translation($language, $id);
755
  }
756
  die();
757
  }
admin/admin.php CHANGED
@@ -46,7 +46,7 @@ class Lingotek_Admin {
46
  $pllm = $GLOBALS['polylang']->model;
47
  $languages = pll_languages_list( array( 'fields' => 'locale' ) );
48
  $post_vars = filter_input_array(INPUT_POST);
49
- $object_ids = $post_vars['check_ids'];
50
  if ( null === $object_ids ) {
51
  return;
52
  }
@@ -96,7 +96,6 @@ class Lingotek_Admin {
96
  $content_metadata[ $id ]['source_status'] = $document->status;
97
  $target_status = 'edited' === $document->status || null === $document->status ? 'edited' : $document->status;
98
  $content_metadata[ $id ][ $source_language ]['status'] = $document->source === $object_id ? $document->status : $target_status;
99
-
100
  if ( is_array( $document->translations ) ) {
101
  foreach ( $document->translations as $locale => $translation_status ) {
102
  $content_metadata[ $id ][ $locale ]['status'] = $translation_status;
46
  $pllm = $GLOBALS['polylang']->model;
47
  $languages = pll_languages_list( array( 'fields' => 'locale' ) );
48
  $post_vars = filter_input_array(INPUT_POST);
49
+ $object_ids = isset($post_vars['check_ids']) ? $post_vars['check_ids'] : NULL;
50
  if ( null === $object_ids ) {
51
  return;
52
  }
96
  $content_metadata[ $id ]['source_status'] = $document->status;
97
  $target_status = 'edited' === $document->status || null === $document->status ? 'edited' : $document->status;
98
  $content_metadata[ $id ][ $source_language ]['status'] = $document->source === $object_id ? $document->status : $target_status;
 
99
  if ( is_array( $document->translations ) ) {
100
  foreach ( $document->translations as $locale => $translation_status ) {
101
  $content_metadata[ $id ][ $locale ]['status'] = $translation_status;
admin/filters-post.php CHANGED
@@ -23,6 +23,7 @@ class Lingotek_Filters_Post extends PLL_CRUD_Posts {
23
  $this->lgtm = &$GLOBALS['wp_lingotek']->model;
24
  $this->pllm = &$GLOBALS['polylang']->model;
25
  $this->lingotek_prefs = Lingotek_Model::get_prefs();
 
26
 
27
  // automatic upload
28
  add_action('post_updated', array(&$this, 'post_updated'), 10, 3);
@@ -36,6 +37,9 @@ class Lingotek_Filters_Post extends PLL_CRUD_Posts {
36
 
37
  add_filter('manage_pages_columns', array(&$this, 'add_profile_column'));
38
  add_action('manage_pages_custom_column', array(&$this, 'add_profile_column_data'), 10, 3);
 
 
 
39
  }
40
 
41
  /*
@@ -244,7 +248,7 @@ class Lingotek_Filters_Post extends PLL_CRUD_Posts {
244
  // don't synchronize disassociated posts
245
  $group = $this->lgtm->get_group('post', $post_id);
246
  if (empty($group->source))
247
- return array();
248
 
249
  if (isset($_REQUEST['media']) && is_array($_REQUEST['media']))
250
  $post_ids = array_map('intval', $_REQUEST['media']);
@@ -255,55 +259,6 @@ class Lingotek_Filters_Post extends PLL_CRUD_Posts {
255
  return array_diff(PLL()->model->post->get_translations($post_id), $post_ids);
256
  }
257
 
258
- /*
259
- * deletes the Lingotek document when a source document is deleted
260
- *
261
- * @since 0.1
262
- *
263
- * @param int $post_id
264
- */
265
- public function delete_post($post_id) {
266
- static $avoid_recursion = array();
267
- $group = $this->lgtm->get_group('post', $post_id);
268
-
269
- if (!wp_is_post_revision($post_id) && !in_array($post_id, $avoid_recursion)) {
270
- // sync delete is not needed when emptying the bin as trash is synced
271
- if (empty($_REQUEST['delete_all']) && isset($this->lingotek_prefs['delete_linked_content']['enabled'])) {
272
- $tr_ids = $this->get_translations_to_sync($post_id);
273
- $avoid_recursion = array_merge($avoid_recursion, array_values($tr_ids));
274
- foreach ($tr_ids as $tr_id) {
275
- wp_delete_post($tr_id, true); // forces deletion for the translations which are not already in the list
276
- }
277
- }
278
- if (is_object($group) && $group->source == $post_id) {
279
- $group->disassociate();
280
- }
281
- else if (is_object($group) && $group->source !== null) {
282
- $post_lang = pll_get_post_language($post_id, 'locale');
283
- if ($this->lingotek_prefs['delete_document_from_tms']) {
284
- unset($group->desc_array['lingotek']['translations'][$post_lang]);
285
- }
286
- else {
287
- $group->desc_array['lingotek']['translations'][$post_lang] = 'ready';
288
- }
289
- $group->save();
290
- }
291
- $this->lgtm->delete_post($post_id);
292
- }
293
- // delete lingotek_profile term upon post deletion
294
- $terms = wp_get_object_terms($post_id, 'lingotek_profile');
295
- $term = array_pop($terms);
296
- if ($term) {
297
- wp_delete_term($term->term_id, 'lingotek_profile');
298
- }
299
- //delete lingotek_hash term upon post deletion
300
- $hash_terms = wp_get_object_terms($post_id, 'lingotek_hash');
301
- $hash_term = array_pop($hash_terms);
302
- if ($hash_term) {
303
- wp_delete_term($hash_term->term_id, 'lingotek_hash');
304
- }
305
- }
306
-
307
  /*
308
  * sync trash
309
  *
@@ -312,13 +267,22 @@ class Lingotek_Filters_Post extends PLL_CRUD_Posts {
312
  * @param int $post_id
313
  */
314
  public function trash_post($post_id) {
315
- if (isset($this->lingotek_prefs['delete_linked_content']['enabled'])) {
 
 
316
  foreach ($this->get_translations_to_sync($post_id) as $tr_id)
317
  wp_trash_post($tr_id);
 
 
 
318
  }
319
  else {
320
  wp_trash_post($post_id);
 
 
 
321
  }
 
322
  }
323
 
324
  /*
23
  $this->lgtm = &$GLOBALS['wp_lingotek']->model;
24
  $this->pllm = &$GLOBALS['polylang']->model;
25
  $this->lingotek_prefs = Lingotek_Model::get_prefs();
26
+ $pll_filter = new PLL_Admin_Filters_Post($polylang);
27
 
28
  // automatic upload
29
  add_action('post_updated', array(&$this, 'post_updated'), 10, 3);
37
 
38
  add_filter('manage_pages_columns', array(&$this, 'add_profile_column'));
39
  add_action('manage_pages_custom_column', array(&$this, 'add_profile_column_data'), 10, 3);
40
+
41
+ //apply language filter to preserve Polylang behavior of only showing documents of the current language
42
+ add_action('parse_query', array($pll_filter, 'parse_query'));
43
  }
44
 
45
  /*
248
  // don't synchronize disassociated posts
249
  $group = $this->lgtm->get_group('post', $post_id);
250
  if (empty($group->source))
251
+ return [$post_id];
252
 
253
  if (isset($_REQUEST['media']) && is_array($_REQUEST['media']))
254
  $post_ids = array_map('intval', $_REQUEST['media']);
259
  return array_diff(PLL()->model->post->get_translations($post_id), $post_ids);
260
  }
261
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
262
  /*
263
  * sync trash
264
  *
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'])) {
273
  foreach ($this->get_translations_to_sync($post_id) as $tr_id)
274
  wp_trash_post($tr_id);
275
+ if(isset($group->source)){
276
+ $group->cancel();
277
+ }
278
  }
279
  else {
280
  wp_trash_post($post_id);
281
+ if(isset($group->source)){
282
+ $this->lgtm->cancel_post($post_id);
283
+ }
284
  }
285
+
286
  }
287
 
288
  /*
admin/filters-term.php CHANGED
@@ -166,4 +166,12 @@ class Lingotek_Filters_Term extends PLL_Admin_Filters_Term {
166
  }
167
  $this->lgtm->delete_term( $term_id );
168
  }
 
 
 
 
 
 
 
 
169
  }
166
  }
167
  $this->lgtm->delete_term( $term_id );
168
  }
169
+
170
+ public function cancel_term($term_id){
171
+ $taxonomy = substr(current_filter(), 7);
172
+ foreach($this->get_translations_to_sync($term_id) as $tr_id) {
173
+ wp_delete_term($tr_id, $taxonomy);
174
+ }
175
+ $this->lgtm->cancel_term($term_id);
176
+ }
177
  }
admin/manage/view-custom-fields.php CHANGED
@@ -19,30 +19,28 @@ if (!empty($_POST)) {
19
  update_option('lingotek_custom_fields', $arr);
20
  add_settings_error('lingotek_custom_fields_save', 'custom_fields', __('Your <i>Custom Fields</i> were sucessfully saved.', 'lingotek-translation'), 'updated');
21
  }
22
-
23
- if (!empty($_POST['submit2'])) {//Bulk Change
24
  $arr = empty($_POST['settings']) ? array() : $_POST['settings'];
25
-
26
  if (isset($_POST['custom_fields'])) {
27
  $custom_fields = $_POST['custom_fields'];
28
  }
29
- foreach ($_POST as $post => $value){
30
- if($value == 'value1'){
31
  $temp = explode('_', $post);
32
  $temp = implode(' ', $temp);
33
 
34
- foreach ($arr as $item => $val)
35
- {
36
  $temp2 = explode('_', $item);
37
  $temp2 = implode(' ', $temp2);
38
- if($temp == $temp2){
39
  $arr[$item] = $custom_fields;
40
  }
41
-
42
  }
43
  }
44
  }
45
- update_option('lingotek_custom_fields', $arr);
46
  }
47
 
48
  if (!empty($_POST['refresh'])) {
@@ -58,44 +56,48 @@ $default_custom_fields = get_option('lingotek_default_custom_fields');
58
  ?>
59
 
60
  <h3><?php _e('Custom Field Configuration', 'lingotek-translation'); ?></h3>
61
- <p class="description"><?php _e('Custom Fields can be translated, copied, or ignored. Click "Refresh Custom Fields" to identify and enable your custom fields.', 'lingotek-translation'); ?></p>
62
-
63
- <form id="lingotek-custom-fields" method="post" action="admin.php?page=lingotek-translation_manage&amp;sm=custom-fields" class="validate"><?php
64
- wp_nonce_field('lingotek-custom-fields', '_wpnonce_lingotek-custom-fields'); ?>
65
-
66
- <br>
67
- <label for="default_custom_fields">Default configuration for new Custom Fields</label>
68
- <select name="default_custom_fields"><?php
69
- foreach ($default_setting as $key => $title) {
70
- $selected = $key == $default_custom_fields ? 'selected="selected"' : '';
71
- echo "\n\t<option value='" . $key . "' $selected>" . $title . '</option>';
72
- } ?>
73
- </select>
74
- </br>
75
- <div id="d1" style="display: none;">
76
- <select name="custom_fields"><?php
77
- foreach ($default_setting as $key => $title) {
78
- $selected = $key == $default_custom_fields ? 'selected="selected"' : '';
79
- echo "\n\t<option value='" . $key . "' $selected>" . $title . '</option>';
80
- } ?>
81
- </select>
82
- <?php
83
- submit_button(__('Bulk Change', 'lingotek-translation'), 'primary', 'submit2', false);
84
- echo "</div>";
85
- $table = new Lingotek_Custom_Fields_Table();
86
- $table->prepare_items($items);
87
- $table->display();
88
- ?>
89
-
90
- <p>
91
- <?php submit_button(__('Save Changes', 'lingotek-translation'), 'primary', 'submit', false); ?>
92
- <?php submit_button(__( 'Refresh Custom Fields', 'lingotek-translation'), 'secondary', 'refresh', false ); ?>
93
- </p>
 
 
 
 
94
  </form>
95
 
96
 
97
  <?php
98
- echo"
99
  <script>
100
 
101
  function show(source){
19
  update_option('lingotek_custom_fields', $arr);
20
  add_settings_error('lingotek_custom_fields_save', 'custom_fields', __('Your <i>Custom Fields</i> were sucessfully saved.', 'lingotek-translation'), 'updated');
21
  }
22
+
23
+ if (!empty($_POST['submit2'])) { //Bulk Change
24
  $arr = empty($_POST['settings']) ? array() : $_POST['settings'];
25
+
26
  if (isset($_POST['custom_fields'])) {
27
  $custom_fields = $_POST['custom_fields'];
28
  }
29
+ foreach ($_POST as $post => $value) {
30
+ if ($value == 'value1') {
31
  $temp = explode('_', $post);
32
  $temp = implode(' ', $temp);
33
 
34
+ foreach ($arr as $item => $val) {
 
35
  $temp2 = explode('_', $item);
36
  $temp2 = implode(' ', $temp2);
37
+ if ($temp == $temp2) {
38
  $arr[$item] = $custom_fields;
39
  }
 
40
  }
41
  }
42
  }
43
+ update_option('lingotek_custom_fields', $arr);
44
  }
45
 
46
  if (!empty($_POST['refresh'])) {
56
  ?>
57
 
58
  <h3><?php _e('Custom Field Configuration', 'lingotek-translation'); ?></h3>
59
+ <p class="description">
60
+ <?php _e('Custom Fields can be translated, copied, or ignored. Click "Refresh Custom Fields" to identify and enable your custom fields.', 'lingotek-translation'); ?>
61
+ </p>
62
+
63
+ <form id="lingotek-custom-fields" method="post" action="admin.php?page=lingotek-translation_manage&amp;sm=custom-fields"
64
+ class="validate">
65
+ <?php
66
+ wp_nonce_field('lingotek-custom-fields', '_wpnonce_lingotek-custom-fields'); ?>
67
+
68
+ <br>
69
+ <label for="default_custom_fields">Default configuration for new Custom Fields</label>
70
+ <select name="default_custom_fields"><?php
71
+ foreach ($default_setting as $key => $title) {
72
+ $selected = $key == $default_custom_fields ? 'selected="selected"' : '';
73
+ echo "\n\t<option value='" . $key . "' $selected>" . $title . '</option>';
74
+ } ?>
75
+ </select>
76
+ </br>
77
+ <div id="d1" style="display: none;">
78
+ <select name="custom_fields"><?php
79
+ foreach ($default_setting as $key => $title) {
80
+ $selected = $key == $default_custom_fields ? 'selected="selected"' : '';
81
+ echo "\n\t<option value='" . $key . "' $selected>" . $title . '</option>';
82
+ } ?>
83
+ </select>
84
+ <?php
85
+ submit_button(__('Bulk Change', 'lingotek-translation'), 'primary', 'submit2', false);
86
+ echo "</div>";
87
+ $table = new Lingotek_Custom_Fields_Table();
88
+ $table->prepare_items($items);
89
+ $table->display();
90
+ ?>
91
+
92
+ <p>
93
+ <?php submit_button(__('Save Changes', 'lingotek-translation'), 'primary', 'submit', false); ?>
94
+ <?php submit_button(__('Refresh Custom Fields', 'lingotek-translation'), 'secondary', 'refresh', false); ?>
95
+ </p>
96
  </form>
97
 
98
 
99
  <?php
100
+ echo "
101
  <script>
102
 
103
  function show(source){
admin/post-actions.php CHANGED
@@ -200,6 +200,7 @@ class Lingotek_Post_actions extends Lingotek_Actions {
200
  case 'bulk-lingotek-download':
201
  case 'bulk-lingotek-status':
202
  case 'bulk-lingotek-delete':
 
203
  if ( empty( $post_ids ) ) {
204
  $type = empty( $typenow ) ? 'media' : 'post';
205
  $filtered_get = filter_input_array( INPUT_GET );
@@ -209,14 +210,16 @@ class Lingotek_Post_actions extends Lingotek_Actions {
209
 
210
  $post_ids = array_map( 'intval', $filtered_get[ $type ] );
211
  }
212
-
213
  empty( $typenow ) ? check_admin_referer( 'bulk-media' ) : check_admin_referer( 'bulk-posts' );
214
-
 
 
215
  $redirect = add_query_arg( $action, 1, $redirect );
216
  $redirect = add_query_arg( 'ids', implode( ',', $post_ids ), $redirect );
217
 
218
  break;
219
-
220
  case 'lingotek-upload':
221
  check_admin_referer( 'lingotek-upload' );
222
  $this->lgtm->upload_post( (int) filter_input( INPUT_GET, 'post' ) );
@@ -228,7 +231,7 @@ class Lingotek_Post_actions extends Lingotek_Actions {
228
  $target = filter_input( INPUT_GET, 'target' );
229
  $this->lgtm->copy_post( $post_to_copy, $target );
230
  break;
231
-
232
  default:
233
  if ( ! $this->_manage_actions( $action ) ) {
234
  return; // do not redirect if this is not one of our actions.
@@ -339,11 +342,11 @@ class Lingotek_Post_actions extends Lingotek_Actions {
339
  $remove_post = 'post=' . $post->ID;
340
  $disassociate_url = str_replace( $remove_post, '', $disassociate_url );
341
  $prefs = Lingotek_Model::get_prefs();
342
- $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 from Lingotek TMS.', 'lingotek-translation' );
343
  $confirm_message = sprintf( ' onclick = "return confirm(\'%s\');"', esc_html( $confirm_message ) );
344
  printf( '<strong>%s</strong><br><br>', esc_html( __( 'Translation Profile', 'lingotek-translation' ) ) );
345
- printf( '<em>%s</em><br>', esc_html( __( 'Disassociate this content to change the Translation Profile', 'lingotek-translation' ) ) );
346
- printf( ('<a class="button button-small" href="%s" %s>%s</a><br><br>'), esc_url( $disassociate_url ), esc_html( $confirm_message ), esc_html( __( 'Disassociate', 'lingotek-translation' ) ) );
347
  printf( '<select disabled class="lingotek-profile-setting" name="%1$s" id="%1$s">', esc_html( 'lingotek_profile_meta' ) );
348
  } else {
349
  printf( '<strong>%s</strong><br><br>', esc_html( __( 'Translation Profile', 'lingotek-translation' ) ) );
200
  case 'bulk-lingotek-download':
201
  case 'bulk-lingotek-status':
202
  case 'bulk-lingotek-delete':
203
+ case 'bulk-lingotek-cancel':
204
  if ( empty( $post_ids ) ) {
205
  $type = empty( $typenow ) ? 'media' : 'post';
206
  $filtered_get = filter_input_array( INPUT_GET );
210
 
211
  $post_ids = array_map( 'intval', $filtered_get[ $type ] );
212
  }
213
+
214
  empty( $typenow ) ? check_admin_referer( 'bulk-media' ) : check_admin_referer( 'bulk-posts' );
215
+ if( $action == 'bulk-lingotek-cancel' || $action == 'bulk-lingotek-delete'){
216
+ $redirect = add_query_arg( 'lingotek_remove', 1, $redirect );
217
+ }
218
  $redirect = add_query_arg( $action, 1, $redirect );
219
  $redirect = add_query_arg( 'ids', implode( ',', $post_ids ), $redirect );
220
 
221
  break;
222
+
223
  case 'lingotek-upload':
224
  check_admin_referer( 'lingotek-upload' );
225
  $this->lgtm->upload_post( (int) filter_input( INPUT_GET, 'post' ) );
231
  $target = filter_input( INPUT_GET, 'target' );
232
  $this->lgtm->copy_post( $post_to_copy, $target );
233
  break;
234
+
235
  default:
236
  if ( ! $this->_manage_actions( $action ) ) {
237
  return; // do not redirect if this is not one of our actions.
342
  $remove_post = 'post=' . $post->ID;
343
  $disassociate_url = str_replace( $remove_post, '', $disassociate_url );
344
  $prefs = Lingotek_Model::get_prefs();
345
+ $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' );
346
  $confirm_message = sprintf( ' onclick = "return confirm(\'%s\');"', esc_html( $confirm_message ) );
347
  printf( '<strong>%s</strong><br><br>', esc_html( __( 'Translation Profile', 'lingotek-translation' ) ) );
348
+ printf( '<em>%s</em><br>', esc_html( __( 'Delete this content from your Lingotek community to change the Translation Profile', 'lingotek-translation' ) ) );
349
+ printf( ('<a class="button button-small" href="%s" %s>%s</a><br><br>'), esc_url( $disassociate_url ), esc_html( $confirm_message ), esc_html( __( 'Delete', 'lingotek-translation' ) ) );
350
  printf( '<select disabled class="lingotek-profile-setting" name="%1$s" id="%1$s">', esc_html( 'lingotek_profile_meta' ) );
351
  } else {
352
  printf( '<strong>%s</strong><br><br>', esc_html( __( 'Translation Profile', 'lingotek-translation' ) ) );
admin/settings/view-preferences.php CHANGED
@@ -15,20 +15,12 @@ $setting_details = array(
15
  'description' => __( 'The post statuses checked above are enabled for automatic upload (when using automatic uploading translation profiles).', 'lingotek-translation' ),
16
  'values' => array(),
17
  ),
18
- 'delete_document_from_tms' => array(
19
  'type' => 'checkboxes',
20
- 'label' => __( 'Disassociation', 'lingotek-translation' ),
21
- 'description' => __( 'Your documents will remain in your WordPress site but will be deleted from the Lingotek TMS if this option is checked.', 'lingotek-translation' ),
22
  'values' => array(
23
- 'delete' => __( 'Delete documents from Lingotek TMS when disassociating.', 'lingotek-translation' ),
24
- ),
25
- ),
26
- 'delete_linked_content' => array(
27
- 'type' => 'checkboxes',
28
- 'label' => __( 'Deleting Content', 'wp-lingotek' ),
29
- 'description' => __( 'When enabled, deleting source or target content will also delete all linked content.', 'wp-lingotek' ),
30
- 'values' => array(
31
- 'enabled' => __( 'Delete linked content', 'wp-lingotek' ),
32
  ),
33
  ),
34
  'import_enabled' => array(
15
  'description' => __( 'The post statuses checked above are enabled for automatic upload (when using automatic uploading translation profiles).', 'lingotek-translation' ),
16
  'values' => array(),
17
  ),
18
+ 'trash_linked_content' => array(
19
  'type' => 'checkboxes',
20
+ 'label' => __( 'Trashed Content', 'wp-lingotek' ),
21
+ 'description' => __( 'When enabled, sending source or target content to the trash will also send all linked content to the trash. ', 'wp-lingotek' ),
22
  'values' => array(
23
+ 'enabled' => __( 'Sync trashed content', 'wp-lingotek' ),
 
 
 
 
 
 
 
 
24
  ),
25
  ),
26
  'import_enabled' => array(
admin/settings/view-utilities.php CHANGED
@@ -9,7 +9,15 @@ if ( ! empty( $_POST ) ) {
9
  if ( ! empty( $utility_disassociate ) ) {
10
  $ids = Lingotek_Utilities::get_all_document_ids();
11
  if ( ! empty( $ids ) ) {
12
- printf( '<div id="lingotek-progressdialog" title="%s"><div id="lingotek-progressbar"></div></div>', esc_html( __( 'Disassociating content...', 'lingotek-translation' ) ) );
 
 
 
 
 
 
 
 
13
  }
14
  }
15
 
@@ -41,21 +49,37 @@ if ( ! empty( $_POST ) ) {
41
  );
42
 
43
  ?>
44
- <h4><?php esc_html_e( 'Disassociation', 'lingotek-translation' ); ?></h4>
 
45
  <?php
46
 
47
  printf(
48
  '<p><input type="checkbox" name="%1$s" id="%1$s"/><label for="%1$s">%2$s</label></p>',
49
- 'utility_disassociate',
50
- esc_html( __( 'Disassociate all the content from Lingotek TMS.', 'lingotek-translation' ) )
51
  );
 
 
 
 
 
 
 
 
 
 
 
 
52
 
53
- $confirm_disassociate = __( 'You are about to disassociate all your content from Lingotek TMS. Are you sure ?', 'lingotek-translation' );
54
 
55
  $confirm_js = "
56
  d = document.getElementById('utility_disassociate');
 
57
  if (d.checked == true) {
58
- return confirm('$confirm_disassociate');
 
 
59
  }";
60
 
61
  submit_button( __( 'Run Utilities', 'lingotek-translation' ), 'primary', 'submit', true, sprintf( 'onclick="%s"', $confirm_js ) ); ?>
9
  if ( ! empty( $utility_disassociate ) ) {
10
  $ids = Lingotek_Utilities::get_all_document_ids();
11
  if ( ! empty( $ids ) ) {
12
+ printf( '<div id="lingotek-progressdialog" title="%s"><div id="lingotek-progressbar"></div></div>', esc_html( __( 'Deleting content...', 'lingotek-translation' ) ) );
13
+ }
14
+ }
15
+
16
+ $utility_cancel = filter_input(INPUT_POST, 'utility_cancel');
17
+ if(!empty($utility_cancel)){
18
+ $ids = Lingotek_Utilities::get_all_document_ids();
19
+ if(!empty($ids)){
20
+ printf('<div id="lingotek-progressdialog" title="%s"><div id="lingotek-progressbar"></div></div>', esc_html(__('Cancelling content...', 'lingotek-translation')));
21
  }
22
  }
23
 
49
  );
50
 
51
  ?>
52
+
53
+ <h4><?php esc_html_e('Cancellation', 'lingotek-translation');?></h4>
54
  <?php
55
 
56
  printf(
57
  '<p><input type="checkbox" name="%1$s" id="%1$s"/><label for="%1$s">%2$s</label></p>',
58
+ 'utility_cancel',
59
+ esc_html(__('Cancel any existing content from your Lingotek community', 'lingotek-translation'))
60
  );
61
+ ?>
62
+
63
+ <h4><?php esc_html_e( 'Deletion', 'lingotek-translation' ); ?></h4>
64
+ <?php
65
+
66
+ printf(
67
+ '<p><input type="checkbox" name="%1$s" id="%1$s"/><label for="%1$s">%2$s</label></p>',
68
+ 'utility_disassociate',
69
+ esc_html( __( 'Delete all the content from your Lingotek community.', 'lingotek-translation' ) ) . " <b>This is NOT recommended. Please cancel instead.</b>"
70
+ );
71
+
72
+ $confirm_delete = __( 'You are about to delete all your content from your Lingotek community. Are you sure ?', 'lingotek-translation' );
73
 
74
+ $confirm_cancel = __('You are about to cancel all of your content from your Lingotek community. Are you sure ?', 'lingotek-translation');
75
 
76
  $confirm_js = "
77
  d = document.getElementById('utility_disassociate');
78
+ c = document.getElementById('utility_cancel');
79
  if (d.checked == true) {
80
+ return confirm('$confirm_delete');
81
+ } else if (c.checked == true) {
82
+ return confirm('$confirm_cancel');
83
  }";
84
 
85
  submit_button( __( 'Run Utilities', 'lingotek-translation' ), 'primary', 'submit', true, sprintf( 'onclick="%s"', $confirm_js ) ); ?>
admin/tutorial/content.php CHANGED
@@ -102,7 +102,12 @@
102
  <th><?php _e('Translation Current', 'lingotek-translation') ?></th>
103
  <td><?php _e('The translation is complete. (Clicking on this icon will allow you to edit translations in the Lingotek Workbench)', 'lingotek-translation') ?></td>
104
  </tr>
105
- <tr>
 
 
 
 
 
106
  <td><span class="lingotek-color dashicons dashicons-no"></span></td>
107
  <th><?php _e('Out of Sync', 'lingotek-translation') ?></th>
108
  <td><?php _e('You have made changes to source content. The source must be sent to Lingotek again for additional translation.', 'lingotek-translation') ?></td>
102
  <th><?php _e('Translation Current', 'lingotek-translation') ?></th>
103
  <td><?php _e('The translation is complete. (Clicking on this icon will allow you to edit translations in the Lingotek Workbench)', 'lingotek-translation') ?></td>
104
  </tr>
105
+ <tr>
106
+ <td><span class="lingotek-color dashicons dashicons-warning"></span></td>
107
+ <th><?php _e('Translation Cancelled', 'lingotek-translation') ?></th>
108
+ <td><?php _e('The translation is cancelled. The source cannot be translated into this language again.', 'lingotek-translation') ?></td>
109
+ </tr>
110
+ <tr>
111
  <td><span class="lingotek-color dashicons dashicons-no"></span></td>
112
  <th><?php _e('Out of Sync', 'lingotek-translation') ?></th>
113
  <td><?php _e('You have made changes to source content. The source must be sent to Lingotek again for additional translation.', 'lingotek-translation') ?></td>
admin/utilities.php CHANGED
@@ -20,6 +20,7 @@ class Lingotek_Utilities {
20
  add_action('admin_enqueue_scripts', array(&$this, 'admin_enqueue_scripts'));
21
  add_action('wp_ajax_lingotek_progress_disassociate' , array(&$this, 'ajax_utility_disassociate'));
22
  add_action('wp_ajax_lingotek_progress_disassociate_and_delete' , array(&$this, 'ajax_utility_disassociate'));
 
23
  }
24
 
25
  /*
@@ -115,6 +116,18 @@ class Lingotek_Utilities {
115
  'nonce' => wp_create_nonce('lingotek_progress')
116
  ));
117
  }
 
 
 
 
 
 
 
 
 
 
 
 
118
  }
119
  }
120
 
@@ -129,4 +142,12 @@ class Lingotek_Utilities {
129
  $group->disassociate('lingotek_progress_disassociate_and_delete' == $_POST['action']);
130
  die();
131
  }
 
 
 
 
 
 
 
 
132
  }
20
  add_action('admin_enqueue_scripts', array(&$this, 'admin_enqueue_scripts'));
21
  add_action('wp_ajax_lingotek_progress_disassociate' , array(&$this, 'ajax_utility_disassociate'));
22
  add_action('wp_ajax_lingotek_progress_disassociate_and_delete' , array(&$this, 'ajax_utility_disassociate'));
23
+ add_action('wp_ajax_lingotek_progress_cancel', array(&$this, 'ajax_utility_cancel'));
24
  }
25
 
26
  /*
116
  'nonce' => wp_create_nonce('lingotek_progress')
117
  ));
118
  }
119
+ } else if (!empty($_POST['utility_cancel'])){
120
+ $ids = self::get_all_document_ids();
121
+ if(!empty($ids)){
122
+ wp_localize_script('lingotek_progress', 'lingotek_data', array(
123
+ 'action' => 'cancel' . ($_POST['utility_cancel_documents']),
124
+ 'taxonomy' => '',
125
+ 'sendback' => wp_get_referer(),
126
+ 'ids' => $ids, // Lingotek document ids
127
+ 'warning' => '',
128
+ 'nonce' => wp_create_nonce('lingotek_progress')
129
+ ));
130
+ }
131
  }
132
  }
133
 
142
  $group->disassociate('lingotek_progress_disassociate_and_delete' == $_POST['action']);
143
  die();
144
  }
145
+
146
+ public function ajax_utility_cancel() {
147
+ check_ajax_referer('lingotek_progress', '_lingotek_nonce');
148
+ if ($group = $this->lgtm->get_group_by_id($_POST['id'])){
149
+ $group->cancel('lingotek_progress_cancel' == $_POST['action']);
150
+ }
151
+ die();
152
+ }
153
  }
include/api.php CHANGED
@@ -108,6 +108,8 @@ class Lingotek_API extends Lingotek_HTTP {
108
  * @returns bool|string document_id, false if something got wrong
109
  */
110
  public function upload_document($args, $wp_id = null) {
 
 
111
  $args = wp_parse_args($args, array('format' => 'JSON', 'project_id' => $this->defaults['project_id'], 'workflow_id' => $this->get_workflow_id()));
112
  $this->format_as_multipart($args);
113
  $response = $this->post($this->api_url . '/document', $args);
@@ -152,7 +154,7 @@ class Lingotek_API extends Lingotek_HTTP {
152
  * @param string $id document id
153
  */
154
  public function delete_document($id, $wp_id = null) {
155
- $response = $this->delete($this->api_url . '/document/' . $id);
156
 
157
  if ($wp_id) {
158
  $arr = get_option('lingotek_log_errors');
@@ -165,7 +167,32 @@ class Lingotek_API extends Lingotek_HTTP {
165
  $this->log_error_on_response_failure($response, 'DeleteDocument: Error occured', array('id' => $id, 'wordpress_id' => $wp_id));
166
  $is_success = !is_wp_error($response) && (204 == wp_remote_retrieve_response_code($response) || 202 == wp_remote_retrieve_response_code($response));
167
  if ($is_success) { Lingotek_Logger::info('Document deleted', array('document_id' => $id, 'wp_id' => $wp_id)); }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
168
 
 
 
 
 
 
 
 
 
 
 
 
169
  return $is_success;
170
  }
171
 
@@ -262,13 +289,13 @@ class Lingotek_API extends Lingotek_HTTP {
262
  * @return string
263
  */
264
  public function get_document_content($doc_id) {
265
- $response = $this->get($this->api_url . '/document/' . $doc_id . '/content');
266
 
267
  if (!is_wp_error($response) && 200 == wp_remote_retrieve_response_code($response)) {
268
  $content = wp_remote_retrieve_body( $response );
269
  }
270
 
271
- $this->log_error_on_response_failure($response, 'GetDocumentContent: Error occured', array('document_id' => $doc_id));
272
  return $content;
273
  }
274
 
@@ -284,12 +311,13 @@ class Lingotek_API extends Lingotek_HTTP {
284
  public function get_translation_status($doc_id, $locale) {
285
  $locale = Lingotek::map_to_lingotek_locale($locale);
286
  $status = -1;
287
- $response = $this->get($this->api_url . '/document/' . $doc_id . '/translation/' . $locale);
288
  if (!is_wp_error($response) && 200 == wp_remote_retrieve_response_code($response)) {
289
  $b = json_decode(wp_remote_retrieve_body($response));
290
  $status = $b->properties->percent_complete;
291
  }
292
 
 
293
  return $status;
294
  }
295
 
@@ -306,7 +334,10 @@ class Lingotek_API extends Lingotek_HTTP {
306
  if (!is_wp_error($response) && 200 == wp_remote_retrieve_response_code($response)) {
307
  $b = json_decode(wp_remote_retrieve_body($response));
308
  foreach ($b->entities as $e) {
309
- $translations[$e->properties->locale_code] = $e->properties->percent_complete;
 
 
 
310
  }
311
  }
312
 
@@ -482,7 +513,7 @@ class Lingotek_API extends Lingotek_HTTP {
482
  }
483
  update_option('lingotek_log_errors', $arr);
484
  }
485
-
486
  return !is_wp_error($response) && 201 == wp_remote_retrieve_response_code($response);
487
  }
488
 
@@ -522,7 +553,7 @@ class Lingotek_API extends Lingotek_HTTP {
522
  }
523
  update_option('lingotek_log_errors', $arr);
524
  }
525
-
526
  return !is_wp_error($response) && 200 == wp_remote_retrieve_response_code($response) ? wp_remote_retrieve_body($response) : false;
527
  }
528
 
@@ -535,7 +566,7 @@ class Lingotek_API extends Lingotek_HTTP {
535
  * @param string $locale Lingotek locale
536
  */
537
  public function delete_translation($id, $locale, $wp_id = null) {
538
- $response = $this->delete($this->api_url . '/document/' . $id . '/translation/' . $locale);
539
 
540
  if ($wp_id) {
541
  $arr = get_option('lingotek_log_errors');
@@ -544,7 +575,36 @@ class Lingotek_API extends Lingotek_HTTP {
544
  update_option('lingotek_log_errors', $arr);
545
  }
546
  }
547
- // FIXME send a response
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
548
  }
549
 
550
  /**
@@ -559,13 +619,13 @@ class Lingotek_API extends Lingotek_HTTP {
559
  if(!is_null($env)){
560
  $base_url = self::PRODUCTION_URL;
561
  }
562
- return $base_url . "/auth/authorize.html?client_id=" . $client_id . "&redirect_uri=" . urlencode($redirect_uri) . "&response_type=token";
563
  }
564
 
565
  public function get_new_url($redirect_uri) {
566
  $base_url = self::PRODUCTION_URL;
567
  $client_id = $this->client_id;
568
- return $base_url . "/lingopoint/portal/requestAccount.action?client_id=" . $client_id . "&app=" . urlencode($redirect_uri) . "&response_type=token";
569
 
570
  }
571
 
@@ -599,7 +659,7 @@ class Lingotek_API extends Lingotek_HTTP {
599
 
600
  public function upload_filter($name, $type, $content) {
601
  $args = array('name' => $name, 'type' => $type, 'content' => $content);
602
- $response = $this->post($this->api_url . '/filter', $args);
603
  }
604
 
605
  private function start_bridge_call() {
@@ -674,11 +734,11 @@ class Lingotek_API extends Lingotek_HTTP {
674
  }
675
  else if (is_wp_error($response)) {
676
  $arr[$wp_id]['wp_error'] = __('Make sure you have internet connectivity', 'lingotek-translation');
677
- Lingotek_Logger::error($action.": Wordpress error occured, please make sure you have internet connectivity", array_merge(array('http_status'=>$response_message_code, 'wordpress_id'=>$wp_id), $extra_data));
678
  }
679
  else if (400 == $response_message_code || 404 == $response_message_code) {
680
  $arr[$wp_id][$action] = $error_message;
681
- Lingotek_Logger::error($action.": Error occured", array_merge(array('http_status'=>$response_message_code, 'wordpress_id'=>$wp_id, 'response_message'=>$this->get_error_message_from_response($response)), $extra_data));
682
  }
683
  update_option('lingotek_log_errors', $arr);
684
  }
108
  * @returns bool|string document_id, false if something got wrong
109
  */
110
  public function upload_document($args, $wp_id = null) {
111
+ Lingotek::log(debug_backtrace());
112
+ Lingotek::log('uploading document');
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);
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');
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
+ /**
175
+ * cancels a document
176
+ *
177
+ * @since 1.4.2
178
+ *
179
+ * @param string $id document id
180
+ */
181
+ public function cancel_document($id, $wp_id = null) {
182
+ $args = wp_parse_args(array('cancelled_reason' => "CANCELLED_BY_AUTHOR"));
183
+ $response = $this->post("$this->api_url/document/$id/cancel", $args);
184
 
185
+ if($wp_id) {
186
+ $arr = get_option('lingotek_log_errors');
187
+ if(isset($arr[$wp_id])) {
188
+ unset($arr[$wp_id]);
189
+ update_option('lingotek_log_errors', $arr);
190
+ }
191
+ }
192
+ $this->log_error_on_response_failure($response, "CancelDocument: Error occurred", array('id' => $id, 'wordpress_id' => $wp_id));
193
+ $is_success = !is_wp_error($response) && (204 == wp_remote_retrieve_response_code($response) || 202 == wp_remote_retrieve_response_code($response));
194
+ if ($is_success) { Lingotek_Logger::info('Document cancelled', array('document_id' => $id, 'wp_id' => $wp_id)); }
195
+
196
  return $is_success;
197
  }
198
 
289
  * @return string
290
  */
291
  public function get_document_content($doc_id) {
292
+ $response = $this->get($this->api_url . "/document/$doc_id/content");
293
 
294
  if (!is_wp_error($response) && 200 == wp_remote_retrieve_response_code($response)) {
295
  $content = wp_remote_retrieve_body( $response );
296
  }
297
 
298
+ $this->log_error_on_response_failure($response, 'GetDocumentContent: Error occured', ['document_id' => $doc_id]);
299
  return $content;
300
  }
301
 
311
  public function get_translation_status($doc_id, $locale) {
312
  $locale = Lingotek::map_to_lingotek_locale($locale);
313
  $status = -1;
314
+ $response = $this->get($this->api_url."/document/$doc_id/translation/$locale");
315
  if (!is_wp_error($response) && 200 == wp_remote_retrieve_response_code($response)) {
316
  $b = json_decode(wp_remote_retrieve_body($response));
317
  $status = $b->properties->percent_complete;
318
  }
319
 
320
+ $this->log_error_on_response_failure($response, 'GetTranslationStatus: Error occurred', ['document_id' => $doc_id, 'locale' => $locale]);
321
  return $status;
322
  }
323
 
334
  if (!is_wp_error($response) && 200 == wp_remote_retrieve_response_code($response)) {
335
  $b = json_decode(wp_remote_retrieve_body($response));
336
  foreach ($b->entities as $e) {
337
+ if($e->properties->status != 'CANCELLED') {
338
+ // cancelled is in a completed state, but it does not mean the translation is 100% complete
339
+ $translations[$e->properties->locale_code] = $e->properties->percent_complete;
340
+ }
341
  }
342
  }
343
 
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
 
553
  }
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
 
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');
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
+ /**
585
+ * cancels a translation
586
+ *
587
+ * @since 1.4.2
588
+ *
589
+ * @param string $id document id
590
+ * @param string $locale Lingotek locale
591
+ */
592
+ public function cancel_translation($id, $locale, $wp_id = null) {
593
+ $args = wp_parse_args(array('cancelled_reason' => "CANCELLED_BY_AUTHOR", 'mark_invoiceable' => true));
594
+ $response = $this->post("$this->api_url/document/$id/translation/$locale/cancel", $args);
595
+
596
+ if($wp_id) {
597
+ $arr = get_option('lingotek_log_errors');
598
+ if(isset($arr[$wp_id])) {
599
+ unset($arr[$wp_id]);
600
+ update_option('lingotek_log_errors', $arr);
601
+ }
602
+ }
603
+ $this->log_error_on_response_failure($response, "CancelTranslation: Error occurred", array('id' => $id, 'wordpress_id' => $wp_id));
604
+ $is_success = !is_wp_error($response) && (204 == wp_remote_retrieve_response_code($response) || 202 == wp_remote_retrieve_response_code($response));
605
+ if ($is_success) { Lingotek_Logger::info('Target cancelled', ['document_id' => $id, 'wp_id' => $wp_id]); }
606
+
607
+ return $is_success;
608
  }
609
 
610
  /**
619
  if(!is_null($env)){
620
  $base_url = self::PRODUCTION_URL;
621
  }
622
+ return "$base_url/auth/authorize.html?client_id=$client_id&redirect_uri=" . urlencode($redirect_uri) . "&response_type=token";
623
  }
624
 
625
  public function get_new_url($redirect_uri) {
626
  $base_url = self::PRODUCTION_URL;
627
  $client_id = $this->client_id;
628
+ return "$base_url/lingopoint/portal/requestAccount.action?client_id=$client_id&app=" . urlencode($redirect_uri) . "&response_type=token";
629
 
630
  }
631
 
659
 
660
  public function upload_filter($name, $type, $content) {
661
  $args = array('name' => $name, 'type' => $type, 'content' => $content);
662
+ $response = $this->post("$this->api_url/filter", $args);
663
  }
664
 
665
  private function start_bridge_call() {
734
  }
735
  else if (is_wp_error($response)) {
736
  $arr[$wp_id]['wp_error'] = __('Make sure you have internet connectivity', 'lingotek-translation');
737
+ Lingotek_Logger::error("$action: Wordpress error occured, please make sure you have internet connectivity", array_merge(array('http_status'=>$response_message_code, 'wordpress_id'=>$wp_id), $extra_data));
738
  }
739
  else if (400 == $response_message_code || 404 == $response_message_code) {
740
  $arr[$wp_id][$action] = $error_message;
741
+ Lingotek_Logger::error("$action: Error occured", array_merge(array('http_status'=>$response_message_code, 'wordpress_id'=>$wp_id, 'response_message'=>$this->get_error_message_from_response($response)), $extra_data));
742
  }
743
  update_option('lingotek_log_errors', $arr);
744
  }
include/callback.php CHANGED
@@ -15,7 +15,6 @@ class Lingotek_Callback {
15
  */
16
  public function __construct(&$model) {
17
  $this->lgtm = &$model;
18
-
19
  add_filter('request', array(&$this, 'request'));
20
  }
21
 
@@ -32,11 +31,10 @@ class Lingotek_Callback {
32
  return $query_vars;
33
 
34
  if (isset($_GET['type'], $_GET['document_id']) && $document = $this->lgtm->get_group_by_id($_GET['document_id'])) {
35
-
36
  // url for in context review
37
  if (isset($_GET['locale']) && 'get' == $_GET['type']) {
38
  $locale = Lingotek::map_to_wp_locale($_GET['locale']); // map to WP locale
39
-
40
  // posts
41
  if (post_type_exists($document->type)) {
42
  if ($id = PLL()->model->post->get($document->source, $locale)) {
@@ -61,13 +59,35 @@ class Lingotek_Callback {
61
 
62
  if ('document_uploaded' == $_GET['type']) {
63
  $document->source_ready();
64
-
 
 
 
 
 
 
 
 
 
65
  if ($document->is_automatic_upload()) {
66
  $document->request_translations();
67
  }
68
  }
69
 
70
  if ((isset($_GET['locale']) && 'target' == $_GET['type']) || (isset($_GET['locale']) && $_GET['type'] == 'phase')) {
 
 
 
 
 
 
 
 
 
 
 
 
 
71
  // We will need access to PLL_Admin_Sync::copy_post_metas
72
  global $polylang;
73
  $polylang->sync = new PLL_Admin_Sync($polylang);
15
  */
16
  public function __construct(&$model) {
17
  $this->lgtm = &$model;
 
18
  add_filter('request', array(&$this, 'request'));
19
  }
20
 
31
  return $query_vars;
32
 
33
  if (isset($_GET['type'], $_GET['document_id']) && $document = $this->lgtm->get_group_by_id($_GET['document_id'])) {
 
34
  // url for in context review
35
  if (isset($_GET['locale']) && 'get' == $_GET['type']) {
36
  $locale = Lingotek::map_to_wp_locale($_GET['locale']); // map to WP locale
37
+ Lingotek_Logger::info('Callback received', array('Callback Parameters' => $_GET));
38
  // posts
39
  if (post_type_exists($document->type)) {
40
  if ($id = PLL()->model->post->get($document->source, $locale)) {
59
 
60
  if ('document_uploaded' == $_GET['type']) {
61
  $document->source_ready();
62
+ $callback_parameters = array(
63
+ 'Document ID' => isset($_GET['document_id']) ? $_GET['document_id'] : NULL,
64
+ 'Project ID' => isset($_GET['projectId']) ? (int)$_GET['projectId'] : NULL,
65
+ 'Community ID' => isset($_GET['community_id']) ? $_GET['community_id'] : NULL,
66
+ 'Progress' => isset($_GET['progress']) ? (int)$_GET['progress'] : NULL,
67
+ 'Complete' => isset($_GET['complete']) ? $_GET['complete'] : NULL,
68
+ 'Type' => isset($_GET['type']) ? $_GET['type'] : NULL,
69
+ 'Document Status' => isset($_GET['doc_status']) ? $_GET['doc_status'] : NULL,
70
+ );
71
+ Lingotek_Logger::info('Callback received', array('Callback Parameters' => $callback_parameters));
72
  if ($document->is_automatic_upload()) {
73
  $document->request_translations();
74
  }
75
  }
76
 
77
  if ((isset($_GET['locale']) && 'target' == $_GET['type']) || (isset($_GET['locale']) && $_GET['type'] == 'phase')) {
78
+ $callback_parameters = array(
79
+ 'Target Locale' => isset($_GET['locale_code']) ? $_GET['locale_code'] : NULL,
80
+ 'Phase Name' => isset($_GET['phase_name']) ? $_GET['phase_name'] : NULL,
81
+ 'Status' => isset($_GET['status']) ? $_GET['status'] : NULL,
82
+ 'Document ID' => isset($_GET['document_id']) ? $_GET['document_id'] : NULL,
83
+ 'Project ID' => isset($_GET['projectId']) ? (int)$_GET['projectId'] : NULL,
84
+ 'Community ID' => isset($_GET['community_id']) ? $_GET['community_id'] : NULL,
85
+ 'Progress' => isset($_GET['progress']) ? (int)$_GET['progress'] : NULL,
86
+ 'Complete' => isset($_GET['complete']) ? $_GET['complete'] : NULL,
87
+ 'Type' => isset($_GET['type']) ? $_GET['type'] : NULL,
88
+ 'Document Status' => isset($_GET['doc_status']) ? $_GET['doc_status'] : NULL,
89
+ );
90
+ Lingotek_Logger::info('Callback received', array('Callback Parameters' => $callback_parameters));
91
  // We will need access to PLL_Admin_Sync::copy_post_metas
92
  global $polylang;
93
  $polylang->sync = new PLL_Admin_Sync($polylang);
include/dashboard.php CHANGED
@@ -26,6 +26,9 @@ class Lingotek_Dashboard {
26
  $response = array(
27
  'method' => $request_method
28
  );
 
 
 
29
  switch ($request_method) {
30
  case 'POST':
31
  if (isset($_REQUEST['code'], $_REQUEST['native'], $_REQUEST['direction'])) {
@@ -62,6 +65,17 @@ class Lingotek_Dashboard {
62
  'target' => self::get_counts_by_type($locale, 'targets')
63
  );
64
  status_header(200);
 
 
 
 
 
 
 
 
 
 
 
65
  }
66
  break;
67
 
26
  $response = array(
27
  'method' => $request_method
28
  );
29
+
30
+ error_log(print_r($request_method, true));
31
+
32
  switch ($request_method) {
33
  case 'POST':
34
  if (isset($_REQUEST['code'], $_REQUEST['native'], $_REQUEST['direction'])) {
65
  'target' => self::get_counts_by_type($locale, 'targets')
66
  );
67
  status_header(200);
68
+ } else {
69
+ $code = $_REQUEST['code'];
70
+ $native = $_REQUEST['native'];
71
+ $direction = $_REQUEST['direction'];
72
+ $response = [
73
+ 'request' => 'POST: add target language to CMS and and Lingotek Project Language',
74
+ 'success' => false,
75
+ 'message' => __("Missing locale, direction, or name. Locale: $code, Name: $native, Direction: $direction", 'lingotek-translation')
76
+ ];
77
+
78
+ status_header(400);
79
  }
80
  break;
81
 
include/group-post.php CHANGED
@@ -40,15 +40,15 @@ class Lingotek_Group_Post extends Lingotek_Group {
40
  * @param string $post_type
41
  * @return array
42
  */
43
- static public function get_content_type_fields($post_type, $post_ID = NULL) {
 
44
  $arr = 'attachment' == $post_type ?
45
  array(
46
  'post_title' => __('Title', 'lingotek-translation'),
47
  'post_excerpt' => __('Caption', 'lingotek-translation'),
48
  'metas' => array('_wp_attachment_image_alt' => __('Alternative Text', 'lingotek-translation')),
49
  'post_content' => __('Description', 'lingotek-translation'),
50
- ) :
51
- array(
52
  'post_title' => __('Title', 'lingotek-translation'),
53
  'post_name' => __('Slug', 'lingotek-translation'),
54
  'post_content' => __('Content', 'lingotek-translation'),
@@ -105,7 +105,9 @@ class Lingotek_Group_Post extends Lingotek_Group {
105
  *
106
  * @return array
107
  */
108
- static public function get_custom_fields_from_wp_postmeta($post_ID = NULL) {
 
 
109
  $custom_fields = get_option('lingotek_custom_fields', array());
110
  $meta_black_list = array('_encloseme', '_edit_last', '_edit_lock', '_wp_trash_meta_status', '_wp_trash_meta_time');
111
  $arr = array();
@@ -113,9 +115,8 @@ class Lingotek_Group_Post extends Lingotek_Group {
113
 
114
  if ($post_ID) {
115
  $p = get_post($post_ID);
116
- $posts [] = $p;
117
- }
118
- else {
119
  $posts = get_posts(array(
120
  'posts_per_page' => -1,
121
  'post_type' => 'post'
@@ -124,8 +125,25 @@ class Lingotek_Group_Post extends Lingotek_Group {
124
  'posts_per_page' => -1,
125
  'post_type' => 'page'
126
  ));
 
127
  $posts = array_merge($posts, $pages);
128
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
129
 
130
  foreach ($posts as $post) {
131
  $metadata = has_meta($post->ID);
@@ -133,10 +151,11 @@ class Lingotek_Group_Post extends Lingotek_Group {
133
  if (in_array($meta['meta_key'], $meta_black_list) || in_array($meta['meta_key'], $keys)) {
134
  unset($metadata[$key]);
135
  }
136
- $keys [] = $meta['meta_key'];
137
  }
138
  $arr = array_merge($arr, $metadata);
139
  }
 
140
  // allow plugins to modify the fields to translate
141
  return apply_filters('lingotek_post_custom_fields', $arr);
142
  }
@@ -148,8 +167,9 @@ class Lingotek_Group_Post extends Lingotek_Group {
148
  *
149
  * @return bool
150
  */
151
- protected static function is_advanced_custom_fields_meta($key, $value) {
152
- return ((substr($key, 0, strlen('_')) === '_') && (substr($value, 0, strlen('field_')) === 'field_' )) ? TRUE : FALSE;
 
153
  }
154
 
155
  /*
@@ -159,7 +179,8 @@ class Lingotek_Group_Post extends Lingotek_Group {
159
  *
160
  * @return array
161
  */
162
- public static function get_updated_meta_values($post_ID = NULL) {
 
163
  $custom_fields_from_wpml = self::get_custom_fields_from_wpml();
164
  $custom_fields_from_postmeta = self::get_custom_fields_from_wp_postmeta($post_ID);
165
  $custom_fields_from_lingotek = get_option('lingotek_custom_fields', array());
@@ -174,22 +195,22 @@ class Lingotek_Group_Post extends Lingotek_Group {
174
  continue;
175
  }
176
 
177
- // no lingotek setting
178
- if (!array_key_exists($cf['meta_key'], $custom_fields_from_lingotek)) {
179
- // no lingotek setting, but there's a wpml setting
180
- if (array_key_exists($cf['meta_key'], $custom_fields_from_wpml)) {
181
- $custom_fields[$cf['meta_key']] = $custom_fields_from_wpml[$cf['meta_key']];
182
- }
183
- // no lingotek setting, no wpml setting, so save default setting of ignore
184
- else {
185
  $custom_fields[$cf['meta_key']] = $default_custom_fields;
186
- }
187
  }
188
- // lingotek already has this field setting saved
189
- else {
190
  $custom_fields[$cf['meta_key']] = $custom_fields_from_lingotek[$cf['meta_key']];
191
- }
192
- }
193
 
194
  if ($post_ID) {
195
  $custom_fields = array_merge($custom_fields_from_lingotek, $custom_fields);
@@ -205,7 +226,8 @@ class Lingotek_Group_Post extends Lingotek_Group {
205
  * @return array
206
  */
207
 
208
- public static function get_cached_meta_values() {
 
209
  $custom_fields_from_lingotek = get_option('lingotek_custom_fields', array());
210
  $items = array();
211
 
@@ -218,7 +240,7 @@ class Lingotek_Group_Post extends Lingotek_Group {
218
  'meta_key' => $key,
219
  'setting' => $setting,
220
  );
221
- $items [] = $arr;
222
  }
223
  }
224
  return $items;
@@ -246,13 +268,11 @@ class Lingotek_Group_Post extends Lingotek_Group {
246
  }
247
 
248
  // send slug for translation only if it has been modified
249
- elseif('post_name' == $key && empty($content_types[$post->post_type]['fields'][$key])) {
250
  $default_slug = sanitize_title($post->post_title); // default slug created by WP
251
  // if ($default_slug != $post->post_name)
252
- $arr['post'][$key] = $post->$key;
253
- }
254
-
255
- elseif (empty($content_types[$post->post_type]['fields'][$key])) {
256
  $arr['post'][$key] = $post->$key;
257
  }
258
  }
@@ -260,10 +280,11 @@ class Lingotek_Group_Post extends Lingotek_Group {
260
  return json_encode($arr);
261
  }
262
 
263
- public static function is_valid_auto_upload_post_status($post_status) {
 
264
  $prefs = Lingotek_Model::get_prefs();
265
  $valid_statuses = $prefs['auto_upload_post_statuses'];
266
- $valid = isset( $valid_statuses[$post_status] ) && $valid_statuses[$post_status];
267
  return $valid;
268
  }
269
 
@@ -272,9 +293,10 @@ class Lingotek_Group_Post extends Lingotek_Group {
272
  *
273
  * @since 0.1
274
  */
275
- public function request_translations() {
 
276
  if (isset($this->source)) {
277
- $language = PLL()->model->post->get_language((int) $this->source);
278
  $this->_request_translations($language);
279
  }
280
  }
@@ -287,7 +309,8 @@ class Lingotek_Group_Post extends Lingotek_Group {
287
  *
288
  * @param string $locale
289
  */
290
- public function create_translation($locale, $automatic = false, $callback_type = NULL) {
 
291
  // Removes content sanitization so YouTube videos, links, etc don't get removed when inserting translations
292
  remove_filter('content_save_pre', 'wp_filter_post_kses');
293
  remove_filter('content_filtered_save_pre', 'wp_filter_post_kses');
@@ -299,7 +322,7 @@ class Lingotek_Group_Post extends Lingotek_Group {
299
  }
300
 
301
  $translation = $client->get_translation($this->document_id, $locale, $this->source);
302
- if (!$translation || $this->translation_not_ready( json_decode($translation, true) )) return; // If the request failed.
303
  $translation = json_decode($translation, true); // wp_insert_post expects array
304
 
305
  self::$creating_translation = true;
@@ -311,7 +334,7 @@ class Lingotek_Group_Post extends Lingotek_Group {
311
  }
312
 
313
  $post = get_post($this->source); // source post
314
- $tr_post['post_status'] = ($prefs['download_post_status'] === self::SAME_AS_SOURCE)? $post->post_status : $prefs['download_post_status']; // status
315
 
316
  // update existing translation
317
  if ($tr_id = PLL()->model->post->get($this->source, $locale)) {
@@ -328,8 +351,7 @@ class Lingotek_Group_Post extends Lingotek_Group {
328
  wp_update_post($tr_post);
329
  if ($status !== 100) {
330
  $this->safe_translation_status_update($locale, 'interim');
331
- }
332
- else {
333
  $this->safe_translation_status_update($locale, 'current');
334
  }
335
  }
@@ -340,7 +362,7 @@ class Lingotek_Group_Post extends Lingotek_Group {
340
  if (!isset($content_type_options[$post->post_type]['fields']['post_name'])) {
341
  unset($post->post_name); // forces the creation of a new default slug if not translated by Lingotek
342
  }
343
- $tr_post = array_merge((array) $post , $tr_post); // copy all untranslated fields from the original post
344
  $tr_post['ID'] = null; // will force the creation of a new post
345
 
346
  // translate parent
@@ -350,8 +372,7 @@ class Lingotek_Group_Post extends Lingotek_Group {
350
  $tr_id = wp_insert_attachment($tr_post);
351
  add_post_meta($tr_id, '_wp_attachment_metadata', get_post_meta($this->source, '_wp_attachment_metadata', true));
352
  add_post_meta($tr_id, '_wp_attached_file', get_post_meta($this->source, '_wp_attached_file', true));
353
- }
354
- else {
355
  $tr_id = wp_insert_post($tr_post);
356
  }
357
 
@@ -365,10 +386,10 @@ class Lingotek_Group_Post extends Lingotek_Group {
365
  wp_set_object_terms($tr_id, $this->term_id, 'post_translations');
366
 
367
  // Copies categories and tags
368
- $GLOBALS['polylang']->sync->copy_taxonomies($this->source, $tr_id, $tr_lang->slug);
369
 
370
  // assign terms and metas
371
- $GLOBALS['polylang']->sync->copy_post_metas($this->source, $tr_id, $tr_lang->slug);
372
 
373
  // copy or ignore metas
374
  self::copy_or_ignore_metas($post->ID, $tr_id);
@@ -379,7 +400,7 @@ class Lingotek_Group_Post extends Lingotek_Group {
379
  }
380
 
381
  if (class_exists('PLL_Share_Post_Slug', true) && $content_type_options[$post->post_type]['fields']['post_name'] == 1) {
382
- wp_update_post(array('ID' => $tr_id ,'post_name' => $post->post_name));
383
  }
384
  }
385
  }
@@ -392,17 +413,18 @@ class Lingotek_Group_Post extends Lingotek_Group {
392
  }
393
 
394
  /**
395
- * TMS will return an associative array with empty fields if the translation is not ready.
396
- *
397
- * @param array $translation the array returned from TMS.
398
- */
399
- private function translation_not_ready($translation) {
400
- $trimmed_title = trim( $translation['post']['post_title'] );
401
- $trimmed_content = trim( $translation['post']['post_content'] );
402
- $trimmed_excerpt = trim($translation['post']['post_excerpt'] );
403
- return empty( $trimmed_title ) &&
404
- empty( $trimmed_content ) &&
405
- empty( $trimmed_excerpt );
 
406
  }
407
 
408
  /*
@@ -411,15 +433,15 @@ class Lingotek_Group_Post extends Lingotek_Group {
411
  * @since 1.0.9
412
  */
413
 
414
- public static function copy_or_ignore_metas($post_id, $tr_id) {
 
415
  // copy or ignore metas
416
  $custom_fields = get_option('lingotek_custom_fields', array());
417
  foreach ($custom_fields as $key => $setting) {
418
  if ('copy' === $setting || 'hide-copy' === $setting) {
419
- $source_meta = current(get_post_meta($post_id, $key)) ;
420
  update_post_meta($tr_id, $key, $source_meta);
421
- }
422
- elseif ('ignore' === $setting) {
423
  delete_post_meta($tr_id, $key);
424
  }
425
  }
@@ -430,10 +452,11 @@ class Lingotek_Group_Post extends Lingotek_Group {
430
  *
431
  * @since 1.0.9
432
  */
433
- protected static function copy_translated_metas($translation_metas, $tr_id) {
 
434
  if (!empty($translation_metas)) {
435
  foreach ($translation_metas as $key => $meta)
436
- update_post_meta($tr_id, $key, $meta);
437
  }
438
  }
439
 
@@ -444,7 +467,8 @@ class Lingotek_Group_Post extends Lingotek_Group {
444
  *
445
  * @return bool
446
  */
447
- public function is_automatic_upload() {
 
448
  return 'automatic' == Lingotek_Model::get_profile_option('upload', get_post_type($this->source), $this->get_source_language(), false, $this->source) && parent::is_automatic_upload();
449
  }
450
 
@@ -455,7 +479,8 @@ class Lingotek_Group_Post extends Lingotek_Group {
455
  *
456
  * @return object
457
  */
458
- public function get_source_language() {
 
459
  return PLL()->model->post->get_language($this->source);
460
  }
461
 
@@ -464,7 +489,8 @@ class Lingotek_Group_Post extends Lingotek_Group {
464
  *
465
  * @since 1.0.9
466
  */
467
- protected static function save_hash_on_upload($object_id) {
 
468
  $post = get_post($object_id);
469
  $document_id = 'lingotek_hash_' . $post->ID;
470
  $new_hash = md5(Lingotek_Group_Post::get_content($post));
@@ -472,4 +498,4 @@ class Lingotek_Group_Post extends Lingotek_Group {
472
  wp_insert_term($document_id, 'lingotek_hash', array('description' => $new_hash));
473
  wp_set_object_terms($post->ID, $document_id, 'lingotek_hash');
474
  }
475
- }
40
  * @param string $post_type
41
  * @return array
42
  */
43
+ static public function get_content_type_fields($post_type, $post_ID = NULL)
44
+ {
45
  $arr = 'attachment' == $post_type ?
46
  array(
47
  'post_title' => __('Title', 'lingotek-translation'),
48
  'post_excerpt' => __('Caption', 'lingotek-translation'),
49
  'metas' => array('_wp_attachment_image_alt' => __('Alternative Text', 'lingotek-translation')),
50
  'post_content' => __('Description', 'lingotek-translation'),
51
+ ) : array(
 
52
  'post_title' => __('Title', 'lingotek-translation'),
53
  'post_name' => __('Slug', 'lingotek-translation'),
54
  'post_content' => __('Content', 'lingotek-translation'),
105
  *
106
  * @return array
107
  */
108
+ static public function get_custom_fields_from_wp_postmeta($post_ID = NULL)
109
+ {
110
+ $all_acf_fields = [];
111
  $custom_fields = get_option('lingotek_custom_fields', array());
112
  $meta_black_list = array('_encloseme', '_edit_last', '_edit_lock', '_wp_trash_meta_status', '_wp_trash_meta_time');
113
  $arr = array();
115
 
116
  if ($post_ID) {
117
  $p = get_post($post_ID);
118
+ $posts[] = $p;
119
+ } else {
 
120
  $posts = get_posts(array(
121
  'posts_per_page' => -1,
122
  'post_type' => 'post'
125
  'posts_per_page' => -1,
126
  'post_type' => 'page'
127
  ));
128
+
129
  $posts = array_merge($posts, $pages);
130
  }
131
+ //Only perform if ACF is installed and these functions are active
132
+ if (function_exists('acf_get_field_groups') && function_exists('acf_get_fields')) {
133
+ $groups = acf_get_field_groups();
134
+ $field_holder = [];
135
+ foreach ($groups as $group) {
136
+ if (isset($group['key'])) {
137
+ $field_holder = acf_get_fields($group['key']);
138
+ foreach ($field_holder as $field) {
139
+ $field_data = [];
140
+ $field_data['meta_key'] = $field['name'];
141
+ $field_data['meta_value'] = $field['key'];
142
+ $all_acf_fields[] = $field_data;
143
+ }
144
+ }
145
+ }
146
+ }
147
 
148
  foreach ($posts as $post) {
149
  $metadata = has_meta($post->ID);
151
  if (in_array($meta['meta_key'], $meta_black_list) || in_array($meta['meta_key'], $keys)) {
152
  unset($metadata[$key]);
153
  }
154
+ $keys[] = $meta['meta_key'];
155
  }
156
  $arr = array_merge($arr, $metadata);
157
  }
158
+ $arr = array_merge($arr, $all_acf_fields);
159
  // allow plugins to modify the fields to translate
160
  return apply_filters('lingotek_post_custom_fields', $arr);
161
  }
167
  *
168
  * @return bool
169
  */
170
+ protected static function is_advanced_custom_fields_meta($key, $value)
171
+ {
172
+ return ((substr($key, 0, strlen('_')) === '_') && (substr($value, 0, strlen('field_')) === 'field_')) ? TRUE : FALSE;
173
  }
174
 
175
  /*
179
  *
180
  * @return array
181
  */
182
+ public static function get_updated_meta_values($post_ID = NULL)
183
+ {
184
  $custom_fields_from_wpml = self::get_custom_fields_from_wpml();
185
  $custom_fields_from_postmeta = self::get_custom_fields_from_wp_postmeta($post_ID);
186
  $custom_fields_from_lingotek = get_option('lingotek_custom_fields', array());
195
  continue;
196
  }
197
 
198
+ // no lingotek setting
199
+ if (!array_key_exists($cf['meta_key'], $custom_fields_from_lingotek)) {
200
+ // no lingotek setting, but there's a wpml setting
201
+ if (array_key_exists($cf['meta_key'], $custom_fields_from_wpml)) {
202
+ $custom_fields[$cf['meta_key']] = $custom_fields_from_wpml[$cf['meta_key']];
203
+ }
204
+ // no lingotek setting, no wpml setting, so save default setting of ignore
205
+ else {
206
  $custom_fields[$cf['meta_key']] = $default_custom_fields;
207
+ }
208
  }
209
+ // lingotek already has this field setting saved
210
+ else {
211
  $custom_fields[$cf['meta_key']] = $custom_fields_from_lingotek[$cf['meta_key']];
212
+ }
213
+ }
214
 
215
  if ($post_ID) {
216
  $custom_fields = array_merge($custom_fields_from_lingotek, $custom_fields);
226
  * @return array
227
  */
228
 
229
+ public static function get_cached_meta_values()
230
+ {
231
  $custom_fields_from_lingotek = get_option('lingotek_custom_fields', array());
232
  $items = array();
233
 
240
  'meta_key' => $key,
241
  'setting' => $setting,
242
  );
243
+ $items[] = $arr;
244
  }
245
  }
246
  return $items;
268
  }
269
 
270
  // send slug for translation only if it has been modified
271
+ elseif ('post_name' == $key && empty($content_types[$post->post_type]['fields'][$key])) {
272
  $default_slug = sanitize_title($post->post_title); // default slug created by WP
273
  // if ($default_slug != $post->post_name)
274
+ $arr['post'][$key] = $post->$key;
275
+ } elseif (empty($content_types[$post->post_type]['fields'][$key])) {
 
 
276
  $arr['post'][$key] = $post->$key;
277
  }
278
  }
280
  return json_encode($arr);
281
  }
282
 
283
+ public static function is_valid_auto_upload_post_status($post_status)
284
+ {
285
  $prefs = Lingotek_Model::get_prefs();
286
  $valid_statuses = $prefs['auto_upload_post_statuses'];
287
+ $valid = isset($valid_statuses[$post_status]) && $valid_statuses[$post_status];
288
  return $valid;
289
  }
290
 
293
  *
294
  * @since 0.1
295
  */
296
+ public function request_translations()
297
+ {
298
  if (isset($this->source)) {
299
+ $language = PLL()->model->post->get_language((int)$this->source);
300
  $this->_request_translations($language);
301
  }
302
  }
309
  *
310
  * @param string $locale
311
  */
312
+ public function create_translation($locale, $automatic = false, $callback_type = NULL)
313
+ {
314
  // Removes content sanitization so YouTube videos, links, etc don't get removed when inserting translations
315
  remove_filter('content_save_pre', 'wp_filter_post_kses');
316
  remove_filter('content_filtered_save_pre', 'wp_filter_post_kses');
322
  }
323
 
324
  $translation = $client->get_translation($this->document_id, $locale, $this->source);
325
+ if (!$translation || $this->translation_not_ready(json_decode($translation, true))) return; // If the request failed.
326
  $translation = json_decode($translation, true); // wp_insert_post expects array
327
 
328
  self::$creating_translation = true;
334
  }
335
 
336
  $post = get_post($this->source); // source post
337
+ $tr_post['post_status'] = ($prefs['download_post_status'] === self::SAME_AS_SOURCE) ? $post->post_status : $prefs['download_post_status']; // status
338
 
339
  // update existing translation
340
  if ($tr_id = PLL()->model->post->get($this->source, $locale)) {
351
  wp_update_post($tr_post);
352
  if ($status !== 100) {
353
  $this->safe_translation_status_update($locale, 'interim');
354
+ } else {
 
355
  $this->safe_translation_status_update($locale, 'current');
356
  }
357
  }
362
  if (!isset($content_type_options[$post->post_type]['fields']['post_name'])) {
363
  unset($post->post_name); // forces the creation of a new default slug if not translated by Lingotek
364
  }
365
+ $tr_post = array_merge((array)$post, $tr_post); // copy all untranslated fields from the original post
366
  $tr_post['ID'] = null; // will force the creation of a new post
367
 
368
  // translate parent
372
  $tr_id = wp_insert_attachment($tr_post);
373
  add_post_meta($tr_id, '_wp_attachment_metadata', get_post_meta($this->source, '_wp_attachment_metadata', true));
374
  add_post_meta($tr_id, '_wp_attached_file', get_post_meta($this->source, '_wp_attached_file', true));
375
+ } else {
 
376
  $tr_id = wp_insert_post($tr_post);
377
  }
378
 
386
  wp_set_object_terms($tr_id, $this->term_id, 'post_translations');
387
 
388
  // Copies categories and tags
389
+ $GLOBALS['polylang']->sync->taxonomies->copy($this->source, $tr_id, $tr_lang->slug);
390
 
391
  // assign terms and metas
392
+ $GLOBALS['polylang']->sync->post_metas->copy($this->source, $tr_id, $tr_lang->slug);
393
 
394
  // copy or ignore metas
395
  self::copy_or_ignore_metas($post->ID, $tr_id);
400
  }
401
 
402
  if (class_exists('PLL_Share_Post_Slug', true) && $content_type_options[$post->post_type]['fields']['post_name'] == 1) {
403
+ wp_update_post(array('ID' => $tr_id, 'post_name' => $post->post_name));
404
  }
405
  }
406
  }
413
  }
414
 
415
  /**
416
+ * TMS will return an associative array with empty fields if the translation is not ready.
417
+ *
418
+ * @param array $translation the array returned from TMS.
419
+ */
420
+ private function translation_not_ready($translation)
421
+ {
422
+ $trimmed_title = trim($translation['post']['post_title']);
423
+ $trimmed_content = trim($translation['post']['post_content']);
424
+ $trimmed_excerpt = trim($translation['post']['post_excerpt']);
425
+ return empty($trimmed_title) &&
426
+ empty($trimmed_content) &&
427
+ empty($trimmed_excerpt);
428
  }
429
 
430
  /*
433
  * @since 1.0.9
434
  */
435
 
436
+ public static function copy_or_ignore_metas($post_id, $tr_id)
437
+ {
438
  // copy or ignore metas
439
  $custom_fields = get_option('lingotek_custom_fields', array());
440
  foreach ($custom_fields as $key => $setting) {
441
  if ('copy' === $setting || 'hide-copy' === $setting) {
442
+ $source_meta = current(get_post_meta($post_id, $key));
443
  update_post_meta($tr_id, $key, $source_meta);
444
+ } elseif ('ignore' === $setting) {
 
445
  delete_post_meta($tr_id, $key);
446
  }
447
  }
452
  *
453
  * @since 1.0.9
454
  */
455
+ protected static function copy_translated_metas($translation_metas, $tr_id)
456
+ {
457
  if (!empty($translation_metas)) {
458
  foreach ($translation_metas as $key => $meta)
459
+ update_post_meta($tr_id, $key, $meta);
460
  }
461
  }
462
 
467
  *
468
  * @return bool
469
  */
470
+ public function is_automatic_upload()
471
+ {
472
  return 'automatic' == Lingotek_Model::get_profile_option('upload', get_post_type($this->source), $this->get_source_language(), false, $this->source) && parent::is_automatic_upload();
473
  }
474
 
479
  *
480
  * @return object
481
  */
482
+ public function get_source_language()
483
+ {
484
  return PLL()->model->post->get_language($this->source);
485
  }
486
 
489
  *
490
  * @since 1.0.9
491
  */
492
+ protected static function save_hash_on_upload($object_id)
493
+ {
494
  $post = get_post($object_id);
495
  $document_id = 'lingotek_hash_' . $post->ID;
496
  $new_hash = md5(Lingotek_Group_Post::get_content($post));
498
  wp_insert_term($document_id, 'lingotek_hash', array('description' => $new_hash));
499
  wp_set_object_terms($post->ID, $document_id, 'lingotek_hash');
500
  }
501
+ }
include/group-string.php CHANGED
@@ -63,27 +63,7 @@ class Lingotek_Group_String extends Lingotek_Group {
63
  wp_set_object_terms($language->mo_id, $document_id, 'post_translations', true); // add terms
64
 
65
  }
66
-
67
- /*
68
- * disassociates translations from the Lingotek TMS
69
- *
70
- * @since 0.2
71
- *
72
- * @param bool $delete whether to delete the Lingotek document or not
73
- */
74
- public function disassociate() {
75
- $client = new Lingotek_API();
76
- $prefs = Lingotek_Model::get_prefs();
77
-
78
- if ($prefs['delete_document_from_tms']) {
79
- $client->delete_document($this->document_id, $this->name);
80
- wp_delete_term($this->term_id, 'post_translations');
81
- }
82
- else {
83
- wp_delete_term($this->term_id, 'post_translations');
84
- }
85
- }
86
-
87
  /*
88
  * uploads a modified source
89
  *
63
  wp_set_object_terms($language->mo_id, $document_id, 'post_translations', true); // add terms
64
 
65
  }
66
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
67
  /*
68
  * uploads a modified source
69
  *
include/group.php CHANGED
@@ -95,7 +95,10 @@ abstract class Lingotek_Group {
95
  }
96
 
97
  /*
98
- * disassociates translations from the Lingotek TMS
 
 
 
99
  *
100
  * @since 0.2
101
  *
@@ -103,18 +106,47 @@ abstract class Lingotek_Group {
103
  */
104
  public function disassociate() {
105
  $client = new Lingotek_API();
106
- $prefs = Lingotek_Model::get_prefs();
 
 
 
107
 
108
- if ($prefs['delete_document_from_tms']) {
109
- $client->delete_document($this->document_id, $this->source);
110
- unset($this->desc_array['lingotek']);
111
- $this->save();
112
- }
113
- else {
114
- unset($this->desc_array['lingotek']);
115
- $this->save();
116
- }
117
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
118
  }
119
 
120
  /*
@@ -294,8 +326,8 @@ abstract class Lingotek_Group {
294
  foreach ($translations as $lingotek_locale => $percent)
295
  {
296
  if (!isset($lingotek_locale_to_pll_locale[$lingotek_locale])) { continue; }
297
-
298
  $wp_locale = $lingotek_locale_to_pll_locale[$lingotek_locale];
 
299
  if ($translations[$lingotek_locale] < 100 && $this->translations[$wp_locale] !== 'interim') {
300
  $this->translations[$wp_locale] = 'pending';
301
  }
@@ -530,6 +562,6 @@ abstract class Lingotek_Group {
530
  */
531
  private function _is_disabled_target($target_language, $type, $item_id) {
532
  $profile = Lingotek_Model::get_profile($type, $target_language, $item_id);
533
- return isset($profile['targets'][$target_language->slug]) && ('disabled' == $profile['targets'][$target_language->slug] || 'copy' == $profile['targets'][$target_language->slug]);
534
  }
535
  }
95
  }
96
 
97
  /*
98
+ * deletes translations from the Lingotek TMS
99
+ * /**it was left as disassociate so that the delete functionality wouldn't break as it
100
+ * did when changing disassociate to delete/cancel in other connectors
101
+ *
102
  *
103
  * @since 0.2
104
  *
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
 
115
+ /**
116
+ * cancels translations from the Lingotek TMS
117
+ *
118
+ * @param bool $cancel whether to cancel the Lingotek document or not
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
+ /**
128
+ * delete translation from the Lingotek TMS
129
+ *
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[$locale]);
137
+ $this->save();
138
+ }
139
+
140
+ /**
141
+ * cancel target from the Lingotek TMS
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
  /*
326
  foreach ($translations as $lingotek_locale => $percent)
327
  {
328
  if (!isset($lingotek_locale_to_pll_locale[$lingotek_locale])) { continue; }
 
329
  $wp_locale = $lingotek_locale_to_pll_locale[$lingotek_locale];
330
+
331
  if ($translations[$lingotek_locale] < 100 && $this->translations[$wp_locale] !== 'interim') {
332
  $this->translations[$wp_locale] = 'pending';
333
  }
562
  */
563
  private function _is_disabled_target($target_language, $type, $item_id) {
564
  $profile = Lingotek_Model::get_profile($type, $target_language, $item_id);
565
+ return isset($profile['targets'][$target_language->slug]) && ('disabled' == $profile['targets'][$target_language->slug] || 'cancelled' == $profile['targets'][$target_language->slug] || 'copy' == $profile['targets'][$target_language->slug]);
566
  }
567
  }
include/http.php CHANGED
@@ -47,7 +47,7 @@ class Lingotek_HTTP {
47
  * @since 0.1
48
  */
49
  public function post($url, $args = array(), $custom_timeout = false) {
50
- Lingotek::log("POST " . $url);
51
  if (!empty($args)) {
52
  Lingotek::log($args);
53
  }
@@ -60,7 +60,7 @@ class Lingotek_HTTP {
60
  * @since 0.1
61
  */
62
  public function get($url, $args = array()) {
63
- Lingotek::log("GET " . $url);
64
  if (!empty($args)) {
65
  Lingotek::log($args);
66
  }
@@ -73,7 +73,7 @@ class Lingotek_HTTP {
73
  * @since 0.1
74
  */
75
  public function delete($url, $args = array()) {
76
- Lingotek::log("DELETE " . $url);
77
  if (!empty($args)) {
78
  Lingotek::log($args);
79
  }
@@ -86,7 +86,7 @@ class Lingotek_HTTP {
86
  * @since 0.1
87
  */
88
  public function patch($url, $args = array()) {
89
- Lingotek::log("PATCH " . $url);
90
  if (!empty($args)) {
91
  Lingotek::log($args);
92
  }
47
  * @since 0.1
48
  */
49
  public function post($url, $args = array(), $custom_timeout = false) {
50
+ Lingotek::log("POST $url");
51
  if (!empty($args)) {
52
  Lingotek::log($args);
53
  }
60
  * @since 0.1
61
  */
62
  public function get($url, $args = array()) {
63
+ Lingotek::log("GET $url");
64
  if (!empty($args)) {
65
  Lingotek::log($args);
66
  }
73
  * @since 0.1
74
  */
75
  public function delete($url, $args = array()) {
76
+ Lingotek::log("DELETE $url");
77
  if (!empty($args)) {
78
  Lingotek::log($args);
79
  }
86
  * @since 0.1
87
  */
88
  public function patch($url, $args = array()) {
89
+ Lingotek::log("PATCH $url");
90
  if (!empty($args)) {
91
  Lingotek::log($args);
92
  }
include/model.php CHANGED
@@ -150,11 +150,8 @@ class Lingotek_Model {
150
  'future' => 1,
151
  'private' => 0,
152
  ),
153
- 'delete_document_from_tms' => array(
154
- 'delete' => 1,
155
- ),
156
- 'delete_linked_content' => array(
157
- 'enabled' => 1,
158
  ),
159
  'auto_update_status' => '10'
160
  );
@@ -528,7 +525,6 @@ class Lingotek_Model {
528
  public function delete_post($object_id) {
529
  if ($document = $this->get_group('post', $object_id)) {
530
  $client = new Lingotek_API();
531
- $lingotek_prefs = Lingotek_Model::get_prefs();
532
 
533
  if ($document->source == $object_id) {
534
  $client->delete_document($document->document_id, $object_id);
@@ -536,9 +532,26 @@ class Lingotek_Model {
536
  else {
537
  PLL()->model->post->delete_translation($object_id);
538
  $lang = PLL()->model->post->get_language($object_id);
539
- if ($lingotek_prefs['delete_document_from_tms']) {
540
- $client->delete_translation($document->document_id, $lang->lingotek_locale, $object_id);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
541
  }
 
 
542
  }
543
  }
544
  }
@@ -566,6 +579,20 @@ class Lingotek_Model {
566
  }
567
  }
568
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
569
  /*
570
  * counts the number of targets per language
571
  *
150
  'future' => 1,
151
  'private' => 0,
152
  ),
153
+ 'trash_linked_content' => array(
154
+
 
 
 
155
  ),
156
  'auto_update_status' => '10'
157
  );
525
  public function delete_post($object_id) {
526
  if ($document = $this->get_group('post', $object_id)) {
527
  $client = new Lingotek_API();
 
528
 
529
  if ($document->source == $object_id) {
530
  $client->delete_document($document->document_id, $object_id);
532
  else {
533
  PLL()->model->post->delete_translation($object_id);
534
  $lang = PLL()->model->post->get_language($object_id);
535
+ $client->delete_translation($document->document_id, $lang->lingotek_locale, $object_id);
536
+ }
537
+ }
538
+ }
539
+
540
+ public function cancel_post($object_id) {
541
+ if ($document = $this->get_group('post', $object_id)) {
542
+ $client = new Lingotek_API();
543
+
544
+ if($document->source == $object_id) {
545
+ $client->cancel_document($document->document_id, $object_id);
546
+ }
547
+ else {
548
+ $lang = PLL()->model->post->get_language($object_id);
549
+ $locale = $lang->locale;
550
+ if(isset($document->desc_array['lingotek']['translations'][$locale])){
551
+ $document->desc_array['lingotek']['translations'][$locale] = 'cancelled';
552
  }
553
+ $document->save();
554
+ $client->cancel_translation($document->document_id, $lang->lingotek_locale, $object_id);
555
  }
556
  }
557
  }
579
  }
580
  }
581
 
582
+ public function cancel_term($object_id){
583
+ if ($document = $this->get_group('term', $object_id)){
584
+ $client = new Lingotek_API();
585
+ if($document->source == $object_id){
586
+ $client->cancel_document($document->document_id, $object_id);
587
+ } else {
588
+ $lang = PLL()->model->term->get_language($object_id);
589
+ PLL()->model->term->cancel_translation($object_id);
590
+ PLL()->model->term->delete_translation($object_id);
591
+ $client->cancel_translation($document->document_id, $lang->lingotek_locale, $object_id);
592
+ }
593
+ }
594
+ }
595
+
596
  /*
597
  * counts the number of targets per language
598
  *
js/updater.js CHANGED
@@ -1,4 +1,9 @@
1
  jQuery(document).ready(function($) {
 
 
 
 
 
2
  var current_ids = {};
3
  var post_data = {"check_ids" : current_ids};
4
  var url = window.location.href;
@@ -104,6 +109,10 @@ jQuery(document).ready(function($) {
104
  updateGenericBulkLink(tr, data, key, 'download' , 'Download translations of this item from Lingotek TMS', 'Download translations');
105
  updateIndicator(td, data, key, locale, 'download', 'Ready to download', 'download');
106
  break;
 
 
 
 
107
  case 'disabled':
108
  break;
109
  default:
@@ -196,10 +205,34 @@ jQuery(document).ready(function($) {
196
  + '&_wpnonce=' + data[action + '_nonce']
197
  + '">' + text + '</a> | </span>');
198
  var disassociate = $(row_actions).find('.lingotek-delete');
199
- if($(disassociate).length > 0){
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
200
  $(disassociate).before(status_update_link);
201
- }
202
- else {
 
 
 
 
 
203
  $(row_actions).append(status_update_link);
204
  }
205
  }
1
  jQuery(document).ready(function($) {
2
+ $('.edit-php a.submitdelete, .post-php a.submitdelete').click( function( event ) {
3
+ if( ! confirm( 'Content that is put into the trash will be cancelled in your Lingotek community. Are you sure you want to proceed?' ) ) {
4
+ event.preventDefault();
5
+ }
6
+ });
7
  var current_ids = {};
8
  var post_data = {"check_ids" : current_ids};
9
  var url = window.location.href;
109
  updateGenericBulkLink(tr, data, key, 'download' , 'Download translations of this item from Lingotek TMS', 'Download translations');
110
  updateIndicator(td, data, key, locale, 'download', 'Ready to download', 'download');
111
  break;
112
+ case 'cancelled':
113
+ updateGenericBulkLink(tr, data, key, 'status' , 'Update translations status of this item in Lingotek TMS', 'Update translations status ');
114
+ updateIndicator(td, data, key, locale, 'cancelled', 'Item has been cancelled', 'warning');
115
+ break;
116
  case 'disabled':
117
  break;
118
  default:
205
  + '&_wpnonce=' + data[action + '_nonce']
206
  + '">' + text + '</a> | </span>');
207
  var disassociate = $(row_actions).find('.lingotek-delete');
208
+ var cancel = $(row_actions).find('.lingotek-cancel');
209
+ var disassociate_translation = $(row_actions).find('.lingotek-delete-translation');
210
+ var cancel_translation = $(row_actions).find('.lingotek-cancel-translation');
211
+ if($(cancel_translation).length > 0){
212
+ $(cancel_translation).off("click");
213
+ $(cancel).click(function(){
214
+ return confirm('You are about to cancel existing translations in your Lingotek community. Are you sure?');
215
+ });
216
+ $(cancel_translation).before(status_update_link);
217
+ } else if($(cancel).length > 0){
218
+ $(cancel).off("click");
219
+ $(cancel).click(function(){
220
+ return confirm('You are about to cancel this translations in your Lingotek community. Are you sure?');
221
+ });
222
+ $(cancel).before(status_update_link);
223
+ } else if($(disassociate).length > 0 ){
224
+ $(disassociate).off("click");
225
+ $(disassociate).click(function(){
226
+ return confirm('You are about to delete existing translations from your Lingotek community. Are you sure?');
227
+ });
228
  $(disassociate).before(status_update_link);
229
+ } else if($(disassociate_translation).length > 0){
230
+ $(disassociate_translation).off("click");
231
+ $(disassociate_translation).click(function(){
232
+ return confirm('You are about to delete this translation from your Lingotek community. Are you sure?');
233
+ });
234
+ $(disassociate_translation).before(status_update_link);
235
+ } else {
236
  $(row_actions).append(status_update_link);
237
  }
238
  }
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.2
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.2' ); // 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).
@@ -531,7 +531,6 @@ class Lingotek {
531
  // admin side.
532
  if ( PLL_ADMIN && ! PLL_SETTINGS ) {
533
  $this->model = new Lingotek_Model();
534
-
535
  // overrides Polylang classes.
536
  $classes = array( 'Filters_Post', 'Filters_Term', 'Filters_Media', 'Filters_Columns' );
537
  foreach ( $classes as $class ) {
@@ -865,6 +864,10 @@ class Lingotek {
865
 
866
  return $default_profiles;
867
  }
 
 
 
 
868
  }
869
 
870
  $GLOBALS['wp_lingotek'] = Lingotek::get_instance();
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.3
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.3' ); // 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).
531
  // admin side.
532
  if ( PLL_ADMIN && ! PLL_SETTINGS ) {
533
  $this->model = new Lingotek_Model();
 
534
  // overrides Polylang classes.
535
  $classes = array( 'Filters_Post', 'Filters_Term', 'Filters_Media', 'Filters_Columns' );
536
  foreach ( $classes as $class ) {
864
 
865
  return $default_profiles;
866
  }
867
+ public static function mylog($message = '')
868
+ {
869
+ file_put_contents('php://stdout', "$message", FILE_APPEND);
870
+ }
871
  }
872
 
873
  $GLOBALS['wp_lingotek'] = Lingotek::get_instance();
readme.txt CHANGED
@@ -1,10 +1,10 @@
1
  === Lingotek Translation ===
2
- Contributors: chouby, smithworx, erichie, robertdhanna, ipoulsen
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
7
- Stable tag: 1.4.2
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
 
@@ -123,6 +123,14 @@ For more, visit the [Lingotek documentation site](https://lingotek.atlassian.net
123
 
124
  == Changelog ==
125
 
 
 
 
 
 
 
 
 
126
  = 1.4.2 (2019-5-9) =
127
 
128
  * Fixed issue where Polylang translations would not save when Lingotek plugin was activated
1
  === Lingotek Translation ===
2
+ Contributors: chouby, smithworx, erichie, robertdhanna, ipoulsen, elliothanna, lopez93
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.3
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
 
123
 
124
  == Changelog ==
125
 
126
+ = 1.4.3 (2019-7-23) =
127
+
128
+ * Fixed issue where Lingotek plugin would not refresh custom fields
129
+ * Cancel and Delete implementation working for standard content types
130
+ * Bulk actions now differentiate between target and source documents
131
+ * Added enhanced logging for api and callbacks
132
+ * Fixed other minor bugs
133
+
134
  = 1.4.2 (2019-5-9) =
135
 
136
  * Fixed issue where Polylang translations would not save when Lingotek plugin was activated