Lingotek Translation - Version 1.4.13

Version Description

(2021-6-14) = * Updated code base to be compatible with PHP 8 * Updated cancel action behavior to be more consistent.

Download this release

Release Info

Developer sowmiya2021
Plugin Icon 128x128 Lingotek Translation
Version 1.4.13
Comparing to
See all releases

Code changes from version 1.4.12 to 1.4.13

admin/actions.php CHANGED
@@ -276,7 +276,7 @@ abstract class Lingotek_Actions {
276
  * @since 0.2
277
  *
278
  * @param int|string $object_id
279
- * @param bool $warning
280
  */
281
  public function upload_icon( $object_id, $confirm = false ) {
282
  $args = array( $this->type => $object_id, 'action' => 'lingotek-upload', 'noheader' => true );
@@ -288,12 +288,35 @@ abstract class Lingotek_Actions {
288
  return self::display_icon( 'upload', $link, $confirm ? self::$confirm_message : '' );
289
  }
290
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
291
  /**
292
  * Outputs a copy icon
293
  *
294
  * @param int|string $object_id
295
- * @param string $target
296
- * @param bool $warning
297
  */
298
  public function copy_icon( $object_id, $target, $confirm = false ) {
299
  $args = array( $this->type => $object_id, 'target' => $target, 'action' => 'lingotek-copy', 'noheader' => true );
@@ -384,17 +407,17 @@ abstract class Lingotek_Actions {
384
  self::link_to_settings_if_not_connected($link);
385
 
386
  switch($action){
387
- case 'cancel':
388
- $message = self::$confirm_cancel;
389
- break;
390
- case 'cancel-translation':
391
- $message = self::$confirm_cancel_translation;
392
  break;
393
  case 'delete':
394
  $message = self::$confirm_delete;
395
  break;
396
- case 'delete-translation':
397
- $message = self::$confirm_delete_translation;
 
 
 
398
  break;
399
  default:
400
  $message = self::$confirm_message;
@@ -602,7 +625,7 @@ abstract class Lingotek_Actions {
602
  /**it was left as disassociate so that the delete functionality wouldn't break as it
603
  * did when changing disassociate to delete/cancel in other connectors
604
  */
605
- $document->disassociate();
606
  if ( null !== filter_input( INPUT_GET, 'lingotek_redirect' ) && filter_input( INPUT_GET, 'lingotek_redirect' ) === true ) {
607
  $site_id = get_current_blog_id();
608
  wp_safe_redirect( get_site_url( $site_id, '/wp-admin/edit.php?post_type=page' ) );
@@ -711,7 +734,7 @@ abstract class Lingotek_Actions {
711
  /**it was left as disassociate so that the delete functionality wouldn't break as it
712
  * did when changing disassociate to delete/cancel in other connectors
713
  */
714
- $document->disassociate();
715
  } else if ($document && $document->source != $id && $language) {
716
  $document->delete_translation($language, $id);
717
  }
276
  * @since 0.2
277
  *
278
  * @param int|string $object_id
279
+ * @param bool $warning
280
  */
281
  public function upload_icon( $object_id, $confirm = false ) {
282
  $args = array( $this->type => $object_id, 'action' => 'lingotek-upload', 'noheader' => true );
288
  return self::display_icon( 'upload', $link, $confirm ? self::$confirm_message : '' );
289
  }
290
 
291
+ /**
292
+ * Outputs a cancelled icon
293
+ *
294
+ * @since 1.4.13
295
+ *
296
+ * @param int|string $object_id
297
+ * id of the object
298
+ * @param bool $target
299
+ * boolean to show if icon is for a target or source document
300
+ * @param bool $confirm
301
+ * boolean to enable the cancel confirm pop up
302
+ */
303
+ public function cancelled_icon( $object_id, $target = false, $confirm = false ) {
304
+ $action = $target ? 'edit' : 'lingotek-upload';
305
+ $args = array( $this->type => $object_id, 'action' => $action, 'noheader' => true );
306
+ if (isset($args['string'])) {
307
+ $args['string'] = urlencode($args['string']);
308
+ }
309
+ $link = wp_nonce_url( defined( 'DOING_AJAX' ) && DOING_AJAX ? add_query_arg( $args, wp_get_referer() ) : add_query_arg( $args ), $action);
310
+ self::link_to_settings_if_not_connected($link);
311
+ return self::display_icon( 'cancelled', $link, $confirm ? self::$confirm_message : '');
312
+ }
313
+
314
  /**
315
  * Outputs a copy icon
316
  *
317
  * @param int|string $object_id
318
+ * @param string $target
319
+ * @param bool $warning
320
  */
321
  public function copy_icon( $object_id, $target, $confirm = false ) {
322
  $args = array( $this->type => $object_id, 'target' => $target, 'action' => 'lingotek-copy', 'noheader' => true );
407
  self::link_to_settings_if_not_connected($link);
408
 
409
  switch($action){
410
+ case 'delete-translation':
411
+ $message = self::$confirm_delete_translation;
 
 
 
412
  break;
413
  case 'delete':
414
  $message = self::$confirm_delete;
415
  break;
416
+ case 'cancel-translation':
417
+ $message = self::$confirm_cancel_translation;
418
+ break;
419
+ case 'cancel':
420
+ $message = self::$confirm_cancel;
421
  break;
422
  default:
423
  $message = self::$confirm_message;
625
  /**it was left as disassociate so that the delete functionality wouldn't break as it
626
  * did when changing disassociate to delete/cancel in other connectors
627
  */
628
+ $document->delete();
629
  if ( null !== filter_input( INPUT_GET, 'lingotek_redirect' ) && filter_input( INPUT_GET, 'lingotek_redirect' ) === true ) {
630
  $site_id = get_current_blog_id();
631
  wp_safe_redirect( get_site_url( $site_id, '/wp-admin/edit.php?post_type=page' ) );
734
  /**it was left as disassociate so that the delete functionality wouldn't break as it
735
  * did when changing disassociate to delete/cancel in other connectors
736
  */
737
+ $document->delete();
738
  } else if ($document && $document->source != $id && $language) {
739
  $document->delete_translation($language, $id);
740
  }
admin/filters-columns.php CHANGED
@@ -93,7 +93,7 @@ class Lingotek_Filters_Columns extends PLL_Admin_Filters_Columns {
93
  }
94
  printf('<div class="notice notice-error is-dismissible"><p>%s</p></div>', $lingotek_log_errors['patch_document_error']);
95
  unset($lingotek_log_errors['patch_document_error']);
96
- update_option('lingotek_log_errors', $lingotek_log_errors);
97
  }
98
 
99
  /**
@@ -146,12 +146,11 @@ class Lingotek_Filters_Columns extends PLL_Admin_Filters_Columns {
146
 
147
  // FIXME not very clean.
148
  $actions = 'post' === $type ? $GLOBALS['wp_lingotek']->post_actions : $GLOBALS['wp_lingotek']->term_actions;
149
-
150
  $profile = Lingotek_Model::get_profile( $this->content_type, $language, $object_id );
151
-
152
  $disabled = 'disabled' === $profile['profile'] || !Lingotek::is_allowed_tms_locale($language->lingotek_locale);
153
  // post ready for upload.
154
- if ( $this->lgtm->can_upload( $type, $object_id ) && $object_id === $id ) {
155
  return $disabled ? ('post' === $type ? parent::post_column( $column, $object_id ) : parent::term_column( '', $column, $object_id ))
156
  : ($document && (count( $document->desc_array ) >= 3) ? $actions->upload_icon( $object_id, true ) : $actions->upload_icon( $object_id ));
157
  } // if language is set to copy and profile is manual.
@@ -174,8 +173,9 @@ class Lingotek_Filters_Columns extends PLL_Admin_Filters_Columns {
174
  ! isset( $document->translations[ $language->locale ] ) ) || !Lingotek::is_allowed_tms_locale($language->lingotek_locale) ) {
175
  return 'post' === $type ? parent::post_column( $column, $object_id ) : parent::term_column( '', $column, $object_id );
176
  } // source post is uploaded.
177
- elseif ( isset( $document->source ) && $document->source === $id ) {
178
  // source ready for upload.
 
179
  delete_option( $document->source );
180
  if ( $this->lgtm->can_upload( $type, $id ) ) {
181
  return $actions->upload_icon( $id );
@@ -202,11 +202,19 @@ class Lingotek_Filters_Columns extends PLL_Admin_Filters_Columns {
202
  elseif ($document->status == 'failed') {
203
  return $actions->failed_import_icon($document->status, $object_id);
204
  }
205
- elseif ($document->status === 'cancelled') {
206
- return parent::post_column( $column, $object_id );
 
207
  }
208
  // no translation.
209
  else {
 
 
 
 
 
 
 
210
  return '<div class="lingotek-color dashicons dashicons-no"></div>';
211
  }
212
  }
@@ -221,6 +229,9 @@ class Lingotek_Filters_Columns extends PLL_Admin_Filters_Columns {
221
  * @param int $post_id post id.
222
  */
223
  public function post_column( $column, $post_id ) {
 
 
 
224
  $this->content_type = get_post_type( $post_id );
225
 
226
  $allowed_html = array(
@@ -274,6 +285,9 @@ class Lingotek_Filters_Columns extends PLL_Admin_Filters_Columns {
274
  * @param int $term_id term id.
275
  */
276
  public function term_column( $custom_data, $column, $term_id ) {
 
 
 
277
  $allowed_html = array(
278
  'a' => array(
279
  'href' => array(),
93
  }
94
  printf('<div class="notice notice-error is-dismissible"><p>%s</p></div>', $lingotek_log_errors['patch_document_error']);
95
  unset($lingotek_log_errors['patch_document_error']);
96
+ update_option('lingotek_log_errors', $lingotek_log_errors, false);
97
  }
98
 
99
  /**
146
 
147
  // FIXME not very clean.
148
  $actions = 'post' === $type ? $GLOBALS['wp_lingotek']->post_actions : $GLOBALS['wp_lingotek']->term_actions;
 
149
  $profile = Lingotek_Model::get_profile( $this->content_type, $language, $object_id );
150
+ $cancelled = isset($document->status) ? $document->status === 'cancelled': false;
151
  $disabled = 'disabled' === $profile['profile'] || !Lingotek::is_allowed_tms_locale($language->lingotek_locale);
152
  // post ready for upload.
153
+ if (!$cancelled && $this->lgtm->can_upload( $type, $object_id ) && $object_id === $id ) {
154
  return $disabled ? ('post' === $type ? parent::post_column( $column, $object_id ) : parent::term_column( '', $column, $object_id ))
155
  : ($document && (count( $document->desc_array ) >= 3) ? $actions->upload_icon( $object_id, true ) : $actions->upload_icon( $object_id ));
156
  } // if language is set to copy and profile is manual.
173
  ! isset( $document->translations[ $language->locale ] ) ) || !Lingotek::is_allowed_tms_locale($language->lingotek_locale) ) {
174
  return 'post' === $type ? parent::post_column( $column, $object_id ) : parent::term_column( '', $column, $object_id );
175
  } // source post is uploaded.
176
+ elseif ( !$cancelled && isset( $document->source ) && $document->source === $id ) {
177
  // source ready for upload.
178
+ // TODO: We don't need that anymore
179
  delete_option( $document->source );
180
  if ( $this->lgtm->can_upload( $type, $id ) ) {
181
  return $actions->upload_icon( $id );
202
  elseif ($document->status == 'failed') {
203
  return $actions->failed_import_icon($document->status, $object_id);
204
  }
205
+ elseif ($this->lgtm->can_upload( $type, $id ) && $document->status === 'cancelled') {
206
+ return $disabled ? ('post' === $type ? parent::post_column( $column, $object_id ) : parent::term_column( '', $column, $object_id ))
207
+ : ($document && (count( $document->desc_array ) >= 3) ? $actions->cancelled_icon( $object_id, false, true ) : $actions->cancelled_icon( $object_id ));
208
  }
209
  // no translation.
210
  else {
211
+ /**
212
+ * There is no record of a translation, but the entire document has been cancelled
213
+ * so we just mark all locales as cancelled since the user will have to re upload the document
214
+ */
215
+ if ($document->status === 'cancelled') {
216
+ return $actions->cancelled_icon($object_id, true);
217
+ }
218
  return '<div class="lingotek-color dashicons dashicons-no"></div>';
219
  }
220
  }
229
  * @param int $post_id post id.
230
  */
231
  public function post_column( $column, $post_id ) {
232
+ if ( false === strpos( $column, 'language_' )) {
233
+ return;
234
+ }
235
  $this->content_type = get_post_type( $post_id );
236
 
237
  $allowed_html = array(
285
  * @param int $term_id term id.
286
  */
287
  public function term_column( $custom_data, $column, $term_id ) {
288
+ if ( false === strpos( $column, 'language_' )) {
289
+ return;
290
+ }
291
  $allowed_html = array(
292
  'a' => array(
293
  'href' => array(),
admin/filters-post.php CHANGED
@@ -321,10 +321,6 @@ class Lingotek_Filters_Post extends PLL_CRUD_Posts {
321
  if (empty($old_term)) {
322
  wp_insert_term($document_id, 'lingotek_hash', array('description' => $new_hash));
323
  }
324
- else {
325
- wp_update_term((int) $old_term->term_id, 'lingotek_hash', array('description' => $new_hash));
326
- }
327
-
328
  wp_set_object_terms($post_after->ID, $document_id, 'lingotek_hash');
329
  return true;
330
  }
321
  if (empty($old_term)) {
322
  wp_insert_term($document_id, 'lingotek_hash', array('description' => $new_hash));
323
  }
 
 
 
 
324
  wp_set_object_terms($post_after->ID, $document_id, 'lingotek_hash');
325
  return true;
326
  }
admin/import/view-settings.php CHANGED
@@ -46,7 +46,7 @@ if (!empty($_POST)) {
46
  }
47
 
48
 
49
- update_option('lingotek_import_prefs', $options);
50
 
51
  add_settings_error('lingotek_prefs', 'prefs', __('Your preferences were successfully updated.', 'wp-lingotek'), 'updated');
52
  settings_errors();
46
  }
47
 
48
 
49
+ update_option('lingotek_import_prefs', $options, false);
50
 
51
  add_settings_error('lingotek_prefs', 'prefs', __('Your preferences were successfully updated.', 'wp-lingotek'), 'updated');
52
  settings_errors();
admin/manage/view-content.php CHANGED
@@ -71,7 +71,7 @@ else {
71
  }
72
  }
73
 
74
- update_option('lingotek_content_type', $content_types);
75
  add_settings_error('lingotek_content_types', 'default', __('Your content types were sucessfully saved.', 'lingotek-translation'), 'updated');
76
  settings_errors();
77
  }
71
  }
72
  }
73
 
74
+ update_option('lingotek_content_type', $content_types, false);
75
  add_settings_error('lingotek_content_types', 'default', __('Your content types were sucessfully saved.', 'lingotek-translation'), 'updated');
76
  settings_errors();
77
  }
admin/manage/view-custom-fields.php CHANGED
@@ -14,9 +14,9 @@ if (!empty($_POST)) {
14
 
15
  if (isset($_POST['default_custom_fields'])) {
16
  $default_custom_fields = $_POST['default_custom_fields'];
17
- update_option('lingotek_default_custom_fields', $default_custom_fields);
18
  }
19
- update_option('lingotek_custom_fields', $arr);
20
  $post_types = get_post_types();
21
  foreach ($post_types as $post_type) {
22
  $cache_key = 'content_type_fields_' . $post_type;
@@ -45,7 +45,7 @@ if (!empty($_POST)) {
45
  }
46
  }
47
  }
48
- update_option('lingotek_custom_fields', $arr);
49
  }
50
 
51
  if (!empty($_POST['refresh'])) {
14
 
15
  if (isset($_POST['default_custom_fields'])) {
16
  $default_custom_fields = $_POST['default_custom_fields'];
17
+ update_option('lingotek_default_custom_fields', $default_custom_fields, false);
18
  }
19
+ update_option('lingotek_custom_fields', $arr, false);
20
  $post_types = get_post_types();
21
  foreach ($post_types as $post_type) {
22
  $cache_key = 'content_type_fields_' . $post_type;
45
  }
46
  }
47
  }
48
+ update_option('lingotek_custom_fields', $arr, false);
49
  }
50
 
51
  if (!empty($_POST['refresh'])) {
admin/manage/view-edit-profile.php CHANGED
@@ -37,7 +37,7 @@ if ($settings['primary_filter_id']['options'] == $default_filters) {
37
  $default_filters_exist = TRUE;
38
  $defaults['primary_filter_id'] = $primary_filter_id;
39
  $defaults['secondary_filter_id'] = $secondary_filter_id;
40
- update_option('lingotek_defaults', $defaults);
41
  }
42
  else {
43
  $num = count(array_diff_assoc($settings['primary_filter_id']['options'], $default_filters));
@@ -47,7 +47,7 @@ else {
47
  else {
48
  $defaults['primary_filter_id'] = '';
49
  $defaults['secondary_filter_id'] = '';
50
- update_option('lingotek_defaults', $defaults);
51
  $no_filters_exist = TRUE;
52
  }
53
  }
37
  $default_filters_exist = TRUE;
38
  $defaults['primary_filter_id'] = $primary_filter_id;
39
  $defaults['secondary_filter_id'] = $secondary_filter_id;
40
+ update_option('lingotek_defaults', $defaults, false);
41
  }
42
  else {
43
  $num = count(array_diff_assoc($settings['primary_filter_id']['options'], $default_filters));
47
  else {
48
  $defaults['primary_filter_id'] = '';
49
  $defaults['secondary_filter_id'] = '';
50
+ update_option('lingotek_defaults', $defaults, false);
51
  $no_filters_exist = TRUE;
52
  }
53
  }
admin/manage/view-profiles.php CHANGED
@@ -11,7 +11,7 @@ if (isset($_GET['lingotek_action']) && 'delete-profile' == $_GET['lingotek_actio
11
  // check again that usage empty
12
  if (!empty($profiles[$_GET['profile']]) && empty($profiles[$_GET['profile']]['usage'])) {
13
  unset($profiles[$_GET['profile']]);
14
- update_option('lingotek_profiles', $profiles);
15
  add_settings_error('lingotek_profile', 'default', __('Your translation profile was sucessfully deleted.', 'lingotek-translation'), 'updated');
16
  set_transient('settings_errors', get_settings_errors(), 30);
17
  wp_redirect(admin_url('admin.php?page=lingotek-translation_manage&sm=profiles&settings-updated=1'));
@@ -90,7 +90,7 @@ if (!empty($_POST)) {
90
  $profiles['manual']['upload'] = $profiles['manual']['download'] = 'manual';
91
  $profiles['automatic']['name'] = 'Automatic'; $profiles['manual']['name'] = 'Manual'; $profiles['disabled']['name'] = 'Disabled';// do not localize names here
92
 
93
- update_option('lingotek_profiles', $profiles);
94
  add_settings_error('lingotek_profile', 'default', __('Your translation profile was sucessfully saved.', 'lingotek-translation'), 'updated');
95
 
96
  if (isset($_POST['update_callback'])) {
11
  // check again that usage empty
12
  if (!empty($profiles[$_GET['profile']]) && empty($profiles[$_GET['profile']]['usage'])) {
13
  unset($profiles[$_GET['profile']]);
14
+ update_option('lingotek_profiles', $profiles, false);
15
  add_settings_error('lingotek_profile', 'default', __('Your translation profile was sucessfully deleted.', 'lingotek-translation'), 'updated');
16
  set_transient('settings_errors', get_settings_errors(), 30);
17
  wp_redirect(admin_url('admin.php?page=lingotek-translation_manage&sm=profiles&settings-updated=1'));
90
  $profiles['manual']['upload'] = $profiles['manual']['download'] = 'manual';
91
  $profiles['automatic']['name'] = 'Automatic'; $profiles['manual']['name'] = 'Manual'; $profiles['disabled']['name'] = 'Disabled';// do not localize names here
92
 
93
+ update_option('lingotek_profiles', $profiles, false);
94
  add_settings_error('lingotek_profile', 'default', __('Your translation profile was sucessfully saved.', 'lingotek-translation'), 'updated');
95
 
96
  if (isset($_POST['update_callback'])) {
admin/post-actions.php CHANGED
@@ -114,9 +114,9 @@ class Lingotek_Post_actions extends Lingotek_Actions {
114
 
115
  public function manage_promotions() {
116
  if (null !== filter_input(INPUT_GET, 'ltk-promotion') && 'dismiss' === filter_input(INPUT_GET, 'ltk-promotion')) {
117
- update_option('lingotek_professional_promotion_shown', true);
118
  } else if (null !== filter_input(INPUT_GET, 'ltk-promotion') && 'view' === filter_input(INPUT_GET, 'ltk-promotion')) {
119
- update_option('lingotek_professional_promotion_shown', true);
120
  wp_safe_redirect( 'admin.php?page=lingotek-translation_tutorial&sm=content&tutorial=ltk-prof#ltk-prof-trans-header' );
121
  die();
122
  }
114
 
115
  public function manage_promotions() {
116
  if (null !== filter_input(INPUT_GET, 'ltk-promotion') && 'dismiss' === filter_input(INPUT_GET, 'ltk-promotion')) {
117
+ update_option('lingotek_professional_promotion_shown', true, false);
118
  } else if (null !== filter_input(INPUT_GET, 'ltk-promotion') && 'view' === filter_input(INPUT_GET, 'ltk-promotion')) {
119
+ update_option('lingotek_professional_promotion_shown', true, false);
120
  wp_safe_redirect( 'admin.php?page=lingotek-translation_tutorial&sm=content&tutorial=ltk-prof#ltk-prof-trans-header' );
121
  die();
122
  }
admin/settings/view-preferences.php CHANGED
@@ -2,43 +2,51 @@
2
  global $wp_post_statuses;
3
  $setting_details = array(
4
  'download_post_status' => array(
5
- 'type' => 'dropdown',
6
- 'label' => __( 'Download translation status', 'lingotek-translation' ),
7
- 'description' => __( 'The post status for newly downloaded translations', 'lingotek-translation' ),
8
- 'values' => array(
9
- Lingotek_Group_Post::SAME_AS_SOURCE => __( 'Same as source post', 'lingotek-translation' )
 
10
  ),
11
- ),
12
  'auto_upload_post_statuses' => array( // blacklist.
13
- 'type' => 'checkboxes',
14
- 'label' => __( 'Auto upload statuses', 'lingotek-translation' ),
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(
27
- 'type' => 'checkboxes',
28
- 'label' => __( 'Import', 'wp-lingotek' ),
29
- 'description' => __( 'When checked, an "Import" submenu will appear.', 'wp-lingotek' ),
30
- 'values' => array(
31
- 'enabled' => __( 'Enable importing from Lingotek Content Cloud. (beta)', 'wp-lingotek' ),
 
32
  ),
33
- ),
34
- 'auto_update_status' => array(
35
- 'type' => 'dropdown',
36
- 'label' => __( 'Automatic Status Update Interval', 'wp-lingotek' ),
37
- 'description' => __( 'Changes the rate at which content statuses update automatically.', 'wp-lingotek' ),
38
- 'values' => array(
39
- '10' => '10 seconds', '30' => '30 seconds', '60' => '60 seconds', '-1' => 'Do not update automatically'
 
 
 
 
 
 
 
 
40
  ),
41
- ),
42
  );
43
 
44
  function map_wp_post_status($status){
2
  global $wp_post_statuses;
3
  $setting_details = array(
4
  'download_post_status' => array(
5
+ 'type' => 'dropdown',
6
+ 'label' => __( 'Download translation status', 'lingotek-translation' ),
7
+ 'description' => __( 'The post status for newly downloaded translations', 'lingotek-translation' ),
8
+ 'values' => array(
9
+ Lingotek_Group_Post::SAME_AS_SOURCE => __( 'Same as source post', 'lingotek-translation' )
10
+ ),
11
  ),
 
12
  'auto_upload_post_statuses' => array( // blacklist.
13
+ 'type' => 'checkboxes',
14
+ 'label' => __( 'Auto upload statuses', 'lingotek-translation' ),
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(
27
+ 'type' => 'checkboxes',
28
+ 'label' => __( 'Import', 'wp-lingotek' ),
29
+ 'description' => __( 'When checked, an "Import" submenu will appear.', 'wp-lingotek' ),
30
+ 'values' => array(
31
+ 'enabled' => __( 'Enable importing from Lingotek Content Cloud. (beta)', 'wp-lingotek' ),
32
+ ),
33
  ),
34
+ 'auto_update_status' => array(
35
+ 'type' => 'dropdown',
36
+ 'label' => __( 'Automatic Status Update Interval', 'wp-lingotek' ),
37
+ 'description' => __( 'Changes the rate at which content statuses update automatically.', 'wp-lingotek' ),
38
+ 'values' => array(
39
+ '10' => '10 seconds', '30' => '30 seconds', '60' => '60 seconds', '-1' => 'Do not update automatically'
40
+ ),
41
+ ),
42
+ 'enable_lingotek_logs' => array(
43
+ 'type' => 'checkboxes',
44
+ 'label' => __('Enable Lingotek Debug Logs', 'wp-lingotek'),
45
+ 'description' => __( 'Enables Lingotek\'s logs for debugging purposes.' , 'wp-lingotek'),
46
+ 'values' => array(
47
+ 'enabled' => __( 'Enable Lingotek Logs', 'wp-lingotek' )
48
+ ),
49
  ),
 
50
  );
51
 
52
  function map_wp_post_status($status){
admin/utilities.php CHANGED
@@ -139,7 +139,7 @@ class Lingotek_Utilities {
139
  public function ajax_utility_disassociate() {
140
  check_ajax_referer('lingotek_progress', '_lingotek_nonce');
141
  if ($group = $this->lgtm->get_group_by_id($_POST['id']))
142
- $group->disassociate('lingotek_progress_disassociate_and_delete' == $_POST['action']);
143
  die();
144
  }
145
 
139
  public function ajax_utility_disassociate() {
140
  check_ajax_referer('lingotek_progress', '_lingotek_nonce');
141
  if ($group = $this->lgtm->get_group_by_id($_POST['id']))
142
+ $group->delete('lingotek_progress_disassociate_and_delete' == $_POST['action']);
143
  die();
144
  }
145
 
admin/workflows/professional-translation-workflow.php CHANGED
@@ -365,7 +365,7 @@ class Lingotek_Professional_Translation_Workflow extends Lingotek_Workflow {
365
  if ($document = $lgtm->get_group($type, $item_id)) {
366
  if (isset(self::$pre_uploaded[$document->document_id])) { return; }
367
  self::$pre_uploaded[$document->document_id] = true;
368
- $document->disassociate();
369
  }
370
  }
371
 
365
  if ($document = $lgtm->get_group($type, $item_id)) {
366
  if (isset(self::$pre_uploaded[$document->document_id])) { return; }
367
  self::$pre_uploaded[$document->document_id] = true;
368
+ $document->delete();
369
  }
370
  }
371
 
include/api.php CHANGED
@@ -129,7 +129,7 @@ class Lingotek_API extends Lingotek_HTTP {
129
  $error_message = $this->get_error_message_from_response($response) !== false ?
130
  $this->get_error_message_from_response($response) : "No error message set by Lingotek";
131
  $lingotek_log_errors['patch_document_error'] = __("Payment required. Message: $error_message", 'lingotek-translation');
132
- update_option('lingotek_log_errors', $lingotek_log_errors);
133
  }
134
  return false;
135
  }
@@ -162,7 +162,7 @@ class Lingotek_API extends Lingotek_HTTP {
162
  $document->translations[$locale] = 'pending';
163
  }
164
  }
165
- $document->document_id = NULL;
166
  unset($document->desc_array['lingotek']);
167
  $document->save();
168
  return $this->upload_document($unformatted_args, $wp_id);
@@ -196,7 +196,7 @@ class Lingotek_API extends Lingotek_HTTP {
196
  foreach ($document->translations as $locale) {
197
  $document->translations[$locale] = 'pending';
198
  }
199
- $document->document_id = NULL;
200
  unset($document->desc_array['lingotek']);
201
  $document->save();
202
  return $this->upload_document($unformatted_args, $wp_id);
@@ -256,26 +256,35 @@ class Lingotek_API extends Lingotek_HTTP {
256
  *
257
  * @param string $id document id
258
  */
259
- public function cancel_document($id, $wp_id = null) {
260
  $args = wp_parse_args(array('cancelled_reason' => "CANCELLED_BY_AUTHOR"));
261
  $response = $this->post("$this->api_url/document/$id/cancel", $args);
262
  if($wp_id) {
263
  $arr = get_option('lingotek_log_errors');
264
  if(isset($arr[$wp_id])) {
265
  unset($arr[$wp_id]);
266
- update_option('lingotek_log_errors', $arr);
267
  }
268
  }
269
  $this->log_error_on_response_failure($response, "CancelDocument: Error occurred", array('id' => $id, 'wordpress_id' => $wp_id));
270
  $is_success = !is_wp_error($response) && (204 == wp_remote_retrieve_response_code($response) || 202 == wp_remote_retrieve_response_code($response));
 
 
 
 
271
  if ($is_success) {
 
272
  Lingotek_Logger::info('Document cancelled', array('document_id' => $id, 'wp_id' => $wp_id));
273
- $lgtm = $GLOBALS['wp_lingotek']->model;
274
- $document = $lgtm->get_group_by_id($id);
275
- $document->status = 'cancelled';
276
  $document->save();
277
  return $is_success;
 
 
 
 
 
 
278
  }
 
279
  $lingotek_log_errors = get_option('lingotek_log_errors', array());
280
  if (!is_array($lingotek_log_errors)) {
281
  $lingotek_log_errors = array();
@@ -283,7 +292,7 @@ class Lingotek_API extends Lingotek_HTTP {
283
  $error_message = $this->get_error_message_from_response($response) !== FALSE ?
284
  $this->get_error_message_from_response($response) : "No error message set by Lingotek.";
285
  $lingotek_log_errors['disassociate_document_error'] = $error_message;
286
- update_option('lingotek_log_errors', $lingotek_log_errors);
287
  return $is_success;
288
  }
289
 
@@ -633,7 +642,7 @@ class Lingotek_API extends Lingotek_HTTP {
633
  __('There was an error requesting translation %1$s for WordPress item %2$s', 'lingotek-translation'), $locale, $wp_id
634
  );
635
  }
636
- update_option('lingotek_log_errors', $arr);
637
  }
638
  if (201 !== $status_code) {
639
  $this->log_error_on_response_failure($response, "RequestTranslation: Error Occurred", ['document_id' => $id, 'locale' => $locale, 'args' => $args]);
@@ -680,7 +689,7 @@ class Lingotek_API extends Lingotek_HTTP {
680
  __('There was an error downloading translation %1$s for WordPress item %2$s'), $locale, $wp_id
681
  );
682
  }
683
- update_option('lingotek_log_errors', $arr);
684
  }
685
  $this->log_error_on_response_failure($response, "GetTranslation: Error Occurred", ['document_id' => $doc_id, 'locale' => $locale]);
686
  return !is_wp_error($response) && 200 == $status_code ? wp_remote_retrieve_body($response) : false;
@@ -702,7 +711,7 @@ class Lingotek_API extends Lingotek_HTTP {
702
  $arr = get_option('lingotek_log_errors');
703
  if(isset($arr[$wp_id])) {
704
  unset($arr[$wp_id]);
705
- update_option('lingotek_log_errors', $arr);
706
  }
707
  }
708
  $this->log_error_on_response_failure($response, "CancelTranslation: Error occurred", array('id' => $id, 'wordpress_id' => $wp_id));
@@ -715,10 +724,12 @@ class Lingotek_API extends Lingotek_HTTP {
715
  if (!is_array($lingotek_log_errors)) {
716
  $lingotek_log_errors = array();
717
  }
718
- $error_message = $this->get_error_message_from_response($response) !== FALSE ?
719
- $this->get_error_message_from_response($response) : "No error message set by Lingotek.";
 
 
720
  $lingotek_log_errors['disassociate_document_error'] = $error_message;
721
- update_option('lingotek_log_errors', $lingotek_log_errors);
722
 
723
  return $is_success;
724
  }
@@ -825,7 +836,7 @@ class Lingotek_API extends Lingotek_HTTP {
825
  $arr[$wp_id][$action][$locale] = $error_message;
826
  Lingotek_Logger::error($action.": Error occured", array_merge(array('response_message_code'=>$response_message_code, 'wordpress_id'=>$wp_id, 'response_message'=>$this->get_error_message_from_response($response)), $extra_data));
827
  }
828
- update_option('lingotek_log_errors', $arr);
829
  }
830
  }
831
 
@@ -859,7 +870,7 @@ class Lingotek_API extends Lingotek_HTTP {
859
  $arr[$wp_id][$action] = $error_message;
860
  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));
861
  }
862
- update_option('lingotek_log_errors', $arr);
863
  }
864
  }
865
 
129
  $error_message = $this->get_error_message_from_response($response) !== false ?
130
  $this->get_error_message_from_response($response) : "No error message set by Lingotek";
131
  $lingotek_log_errors['patch_document_error'] = __("Payment required. Message: $error_message", 'lingotek-translation');
132
+ update_option('lingotek_log_errors', $lingotek_log_errors, false);
133
  }
134
  return false;
135
  }
162
  $document->translations[$locale] = 'pending';
163
  }
164
  }
165
+ $document->document_id = '';
166
  unset($document->desc_array['lingotek']);
167
  $document->save();
168
  return $this->upload_document($unformatted_args, $wp_id);
196
  foreach ($document->translations as $locale) {
197
  $document->translations[$locale] = 'pending';
198
  }
199
+ $document->document_id = '';
200
  unset($document->desc_array['lingotek']);
201
  $document->save();
202
  return $this->upload_document($unformatted_args, $wp_id);
256
  *
257
  * @param string $id document id
258
  */
259
+ public function cancel_document(&$id, $wp_id = null) {
260
  $args = wp_parse_args(array('cancelled_reason' => "CANCELLED_BY_AUTHOR"));
261
  $response = $this->post("$this->api_url/document/$id/cancel", $args);
262
  if($wp_id) {
263
  $arr = get_option('lingotek_log_errors');
264
  if(isset($arr[$wp_id])) {
265
  unset($arr[$wp_id]);
266
+ update_option('lingotek_log_errors', $arr, false);
267
  }
268
  }
269
  $this->log_error_on_response_failure($response, "CancelDocument: Error occurred", array('id' => $id, 'wordpress_id' => $wp_id));
270
  $is_success = !is_wp_error($response) && (204 == wp_remote_retrieve_response_code($response) || 202 == wp_remote_retrieve_response_code($response));
271
+ $lgtm = $GLOBALS['wp_lingotek']->model;
272
+ $document = $lgtm->get_group_by_id($id);
273
+ $current_status = $document->status;
274
+ $document->status = 'cancelled';
275
  if ($is_success) {
276
+ wp_remove_object_terms($wp_id, "lingotek_hash_{$wp_id}", "lingotek_hash");
277
  Lingotek_Logger::info('Document cancelled', array('document_id' => $id, 'wp_id' => $wp_id));
 
 
 
278
  $document->save();
279
  return $is_success;
280
+ } elseif (403 != wp_remote_retrieve_response_code($response)) {
281
+ wp_remove_object_terms($wp_id, "lingotek_hash_{$wp_id}", "lingotek_hash");
282
+ Lingotek_Logger::warning('Document was not cancelled in TMS', array('document' => $id, 'wp_id' => $wp_id));
283
+ $document->document_id = $id = '';
284
+ $document->save();
285
+ return true;
286
  }
287
+ $document->status = $current_status;
288
  $lingotek_log_errors = get_option('lingotek_log_errors', array());
289
  if (!is_array($lingotek_log_errors)) {
290
  $lingotek_log_errors = array();
292
  $error_message = $this->get_error_message_from_response($response) !== FALSE ?
293
  $this->get_error_message_from_response($response) : "No error message set by Lingotek.";
294
  $lingotek_log_errors['disassociate_document_error'] = $error_message;
295
+ update_option('lingotek_log_errors', $lingotek_log_errors, false);
296
  return $is_success;
297
  }
298
 
642
  __('There was an error requesting translation %1$s for WordPress item %2$s', 'lingotek-translation'), $locale, $wp_id
643
  );
644
  }
645
+ update_option('lingotek_log_errors', $arr, false);
646
  }
647
  if (201 !== $status_code) {
648
  $this->log_error_on_response_failure($response, "RequestTranslation: Error Occurred", ['document_id' => $id, 'locale' => $locale, 'args' => $args]);
689
  __('There was an error downloading translation %1$s for WordPress item %2$s'), $locale, $wp_id
690
  );
691
  }
692
+ update_option('lingotek_log_errors', $arr, false);
693
  }
694
  $this->log_error_on_response_failure($response, "GetTranslation: Error Occurred", ['document_id' => $doc_id, 'locale' => $locale]);
695
  return !is_wp_error($response) && 200 == $status_code ? wp_remote_retrieve_body($response) : false;
711
  $arr = get_option('lingotek_log_errors');
712
  if(isset($arr[$wp_id])) {
713
  unset($arr[$wp_id]);
714
+ update_option('lingotek_log_errors', $arr, false);
715
  }
716
  }
717
  $this->log_error_on_response_failure($response, "CancelTranslation: Error occurred", array('id' => $id, 'wordpress_id' => $wp_id));
724
  if (!is_array($lingotek_log_errors)) {
725
  $lingotek_log_errors = array();
726
  }
727
+ // Use the response message if it's an authorization error
728
+ $response_error_message = 403 == wp_remote_retrieve_response_code($response) && $this->get_error_message_from_response($response) !== FALSE ?
729
+ $this->get_error_message_from_response($response) : FALSE;
730
+ $error_message = $response_error_message ? $response_error_message : "{$locale} was already completed in the TMS and cannot be cancelled unless the entire document is cancelled.";
731
  $lingotek_log_errors['disassociate_document_error'] = $error_message;
732
+ update_option('lingotek_log_errors', $lingotek_log_errors, false);
733
 
734
  return $is_success;
735
  }
836
  $arr[$wp_id][$action][$locale] = $error_message;
837
  Lingotek_Logger::error($action.": Error occured", array_merge(array('response_message_code'=>$response_message_code, 'wordpress_id'=>$wp_id, 'response_message'=>$this->get_error_message_from_response($response)), $extra_data));
838
  }
839
+ update_option('lingotek_log_errors', $arr, false);
840
  }
841
  }
842
 
870
  $arr[$wp_id][$action] = $error_message;
871
  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));
872
  }
873
+ update_option('lingotek_log_errors', $arr, false);
874
  }
875
  }
876
 
include/callback.php CHANGED
@@ -40,6 +40,9 @@ class Lingotek_Callback {
40
  case 'phase':
41
  $this->handleTargetOrPhase($document, $type);
42
  break;
 
 
 
43
  case 'document_uploaded':
44
  case 'document_updated':
45
  $this->handleDocumentUploadedOrUpdated($document);
@@ -51,6 +54,9 @@ class Lingotek_Callback {
51
  case 'document_deleted':
52
  $this->handleDocumentArchivedOrDeleted($document);
53
  break;
 
 
 
54
  default:
55
  Lingotek_Logger::info('Callback received, no handler for type', array('Type' => $type));
56
  }
@@ -142,8 +148,49 @@ class Lingotek_Callback {
142
  }
143
 
144
  public function handleDocumentArchivedOrDeleted($document) {
 
 
 
 
 
 
145
  unset($document->desc_array['lingotek']);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
146
  $document->save();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
147
  }
148
 
149
  }
40
  case 'phase':
41
  $this->handleTargetOrPhase($document, $type);
42
  break;
43
+ case 'target_cancelled':
44
+ $this->handleTargetCancelled($document);
45
+ break;
46
  case 'document_uploaded':
47
  case 'document_updated':
48
  $this->handleDocumentUploadedOrUpdated($document);
54
  case 'document_deleted':
55
  $this->handleDocumentArchivedOrDeleted($document);
56
  break;
57
+ case 'document_cancelled';
58
+ $this->handleDocumentCancelled($document);
59
+ break;
60
  default:
61
  Lingotek_Logger::info('Callback received, no handler for type', array('Type' => $type));
62
  }
148
  }
149
 
150
  public function handleDocumentArchivedOrDeleted($document) {
151
+ $callback_parameters = array (
152
+ 'Document ID' => isset($_GET['document_id']) ? $_GET['document_id'] : NULL,
153
+ 'Type' => isset($_GET['type']) ? $_GET['type'] : NULL,
154
+ );
155
+ Lingotek_Logger::info('Callback received', array('Callback Parameters' => $callback_parameters));
156
+ $wp_id = isset($document->desc_array['lingotek']['source']) ? $document->desc_array['lingotek']['source'] : NULL;
157
  unset($document->desc_array['lingotek']);
158
+ $document->document_id = '';
159
+ $document->save();
160
+ wp_remove_object_terms($wp_id, "lingotek_hash_{$wp_id}", "lingotek_hash");
161
+ }
162
+
163
+ public function handleDocumentCancelled($document) {
164
+ $callback_parameters = array(
165
+ 'Document ID' => isset($_GET['document_id']) ? $_GET['document_id'] : NULL,
166
+ 'Type' => isset($_GET['type']) ? $_GET['type'] : NULL,
167
+ );
168
+ if (isset($document->desc_array['lingotek']['translations']) && count($document->desc_array['lingotek']['translations']) > 0 ) {
169
+ unset($document->desc_array['lingotek']['translations']);
170
+ $document->desc_array['lingotek']['status'] = 'cancelled';
171
+ } else {
172
+ unset($document->desc_array['lingotek']);
173
+ }
174
+ $wp_id = isset($document->desc_array['lingotek']['source']) ? $document->desc_array['lingotek']['source'] : NULL;
175
+ $document->status = 'cancelled';
176
  $document->save();
177
+ wp_remove_object_terms($wp_id, "lingotek_hash_{$wp_id}", "lingotek_hash");
178
+ Lingotek_Logger::info('Callback Received', array('Callback Parameters' => $callback_parameters));
179
+ }
180
+
181
+ public function handleTargetCancelled($document) {
182
+ $callback_parameters = array(
183
+ 'Document ID' => isset($_GET['document_id']) ? $_GET['document_id'] : NULL,
184
+ 'Type' => isset($_GET['type']) ? $_GET['type'] : NULL,
185
+ 'Locale' => isset($_GET['locale']) ? $_GET['locale'] : NULL,
186
+ );
187
+ $locale = Lingotek::map_to_wp_locale($_GET['locale']); // map to WP locale
188
+ if (!isset($document->desc_array['lingotek']['translations'][$locale])) {
189
+ $document->desc_array['lingotek']['translations'][] = $locale;
190
+ }
191
+ $document->desc_array['lingotek']['translations'][$locale] = 'cancelled';
192
+ $document->save();
193
+ Lingotek_Logger::info('Callback received', array('Callback Parameters' => $callback_parameters));
194
  }
195
 
196
  }
include/group-post.php CHANGED
@@ -65,7 +65,7 @@ class Lingotek_Group_Post extends Lingotek_Group {
65
  // add the custom fields from the lingotek_custom_fields option
66
  $custom_fields = get_option('lingotek_custom_fields', array());
67
 
68
- if (!empty($custom_fields)) {
69
  foreach ($custom_fields as $cf => $setting) {
70
  if ('translate' == $setting) {
71
  $arr['metas'][$cf] = $cf;
@@ -188,6 +188,9 @@ class Lingotek_Group_Post extends Lingotek_Group {
188
  $custom_fields_from_wpml = self::get_custom_fields_from_wpml();
189
  $custom_fields_from_postmeta = self::get_custom_fields_from_wp_postmeta($post_ID);
190
  $custom_fields_from_lingotek = get_option('lingotek_custom_fields', array());
 
 
 
191
  $default_custom_fields = get_option('lingotek_default_custom_fields') ? get_option('lingotek_default_custom_fields') : 'ignore';
192
  $custom_fields = array();
193
  $items = array();
@@ -217,9 +220,10 @@ class Lingotek_Group_Post extends Lingotek_Group {
217
  }
218
 
219
  if ($post_ID) {
220
- $custom_fields = array_merge($custom_fields_from_lingotek, $custom_fields);
 
221
  }
222
- update_option('lingotek_custom_fields', $custom_fields);
223
  }
224
 
225
  /*
65
  // add the custom fields from the lingotek_custom_fields option
66
  $custom_fields = get_option('lingotek_custom_fields', array());
67
 
68
+ if (is_array($custom_fields) && !empty($custom_fields)) {
69
  foreach ($custom_fields as $cf => $setting) {
70
  if ('translate' == $setting) {
71
  $arr['metas'][$cf] = $cf;
188
  $custom_fields_from_wpml = self::get_custom_fields_from_wpml();
189
  $custom_fields_from_postmeta = self::get_custom_fields_from_wp_postmeta($post_ID);
190
  $custom_fields_from_lingotek = get_option('lingotek_custom_fields', array());
191
+ if (!is_array($custom_fields_from_lingotek)) {
192
+ $custom_fields_from_lingotek = array();
193
+ }
194
  $default_custom_fields = get_option('lingotek_default_custom_fields') ? get_option('lingotek_default_custom_fields') : 'ignore';
195
  $custom_fields = array();
196
  $items = array();
220
  }
221
 
222
  if ($post_ID) {
223
+ // get_option sometimes returns empty string for `lingotek_custom_fields`
224
+ $custom_fields = is_array($custom_fields_from_lingotek) ? array_merge($custom_fields_from_lingotek, $custom_fields) : $custom_fields;
225
  }
226
+ update_option('lingotek_custom_fields', $custom_fields, false);
227
  }
228
 
229
  /*
include/group.php CHANGED
@@ -42,7 +42,15 @@ abstract class Lingotek_Group {
42
  * @since 0.2
43
  */
44
  public function save() {
45
- wp_update_term((int) $this->term_id, $this->taxonomy, array('slug' => $this->document_id, 'name' => $this->document_id, 'description' => serialize($this->desc_array)));
 
 
 
 
 
 
 
 
46
  }
47
 
48
  /*
@@ -95,16 +103,14 @@ abstract class Lingotek_Group {
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
  *
105
  * @param bool $delete whether to delete the Lingotek document or not
106
  */
107
- public function disassociate() {
108
  $client = new Lingotek_API();
109
  if ($client->cancel_document($this->document_id, $this->source)) {
110
  update_option("ignore_delete_pref", TRUE);
@@ -132,17 +138,16 @@ abstract class Lingotek_Group {
132
  public function cancel() {
133
  $client = new Lingotek_API();
134
  if ($client->cancel_document($this->document_id, $this->source)) {
135
- if (count ($this->desc_array['lingotek']['translations']) > 0) {
136
  unset($this->desc_array['lingotek']['translations']);
137
  $this->desc_array['lingotek']['status'] = 'cancelled';
138
  } else {
139
  unset($this->desc_array['lingotek']);
140
  }
141
-
142
- $this->save();
143
  } else {
144
  update_option('cancel_source_failed', TRUE);
145
  }
 
146
  }
147
 
148
  /**
@@ -569,10 +574,9 @@ abstract class Lingotek_Group {
569
  * @param string $item_id
570
  * @return void
571
  */
572
- private function get_workflow_object( $source_language, $locale = false, $type, $item_id ) {
573
  $target_language = ($locale) ? $this->pllm->get_language($locale) : false;
574
  $source_language = (!$source_language) ? PLL()->model->post->get_language( $this->source ) : $source_language;
575
- $workflow_id;
576
  if ($type === 'post') {
577
  $post = ($item_id) ? get_post($item_id) : get_post( $this->source );
578
  $workflow_id = Lingotek_Model::get_profile_option( 'workflow_id', $post->post_type, $source_language, $target_language , $this->source );
42
  * @since 0.2
43
  */
44
  public function save() {
45
+ $args = array(
46
+ 'description' => serialize($this->desc_array),
47
+ 'slug' => $this->document_id,
48
+ );
49
+ if (!empty($this->document_id)) {
50
+ // Name is required for the term, cannot be null or empty
51
+ $args['name'] = $this->document_id;
52
+ }
53
+ $update = wp_update_term((int) $this->term_id, $this->taxonomy, $args);
54
  }
55
 
56
  /*
103
  }
104
 
105
  /*
106
+ * deletes translations downloaded from the Lingotek TMS
 
 
107
  *
108
  *
109
  * @since 0.2
110
  *
111
  * @param bool $delete whether to delete the Lingotek document or not
112
  */
113
+ public function delete() {
114
  $client = new Lingotek_API();
115
  if ($client->cancel_document($this->document_id, $this->source)) {
116
  update_option("ignore_delete_pref", TRUE);
138
  public function cancel() {
139
  $client = new Lingotek_API();
140
  if ($client->cancel_document($this->document_id, $this->source)) {
141
+ if (isset($this->desc_array['lingotek']['translations']) && count ($this->desc_array['lingotek']['translations']) > 0) {
142
  unset($this->desc_array['lingotek']['translations']);
143
  $this->desc_array['lingotek']['status'] = 'cancelled';
144
  } else {
145
  unset($this->desc_array['lingotek']);
146
  }
 
 
147
  } else {
148
  update_option('cancel_source_failed', TRUE);
149
  }
150
+ $this->save();
151
  }
152
 
153
  /**
574
  * @param string $item_id
575
  * @return void
576
  */
577
+ private function get_workflow_object( $source_language, $locale = false, $type = null, $item_id = null ) {
578
  $target_language = ($locale) ? $this->pllm->get_language($locale) : false;
579
  $source_language = (!$source_language) ? PLL()->model->post->get_language( $this->source ) : $source_language;
 
580
  if ($type === 'post') {
581
  $post = ($item_id) ? get_post($item_id) : get_post( $this->source );
582
  $workflow_id = Lingotek_Model::get_profile_option( 'workflow_id', $post->post_type, $source_language, $target_language , $this->source );
include/logger.php CHANGED
@@ -7,8 +7,6 @@
7
  */
8
  class Lingotek_Logger {
9
 
10
- protected static $logging = false;
11
-
12
  public static function fatal($message, $extra_data = null, $error = null){ Lingotek_Logger::log("fatal", $message, $extra_data, $error); }
13
  public static function error($message, $extra_data = null, $error = null){ Lingotek_Logger::log("error", $message, $extra_data, $error); }
14
  public static function warning($message, $extra_data = null, $error = null){ Lingotek_Logger::log("warning", $message, $extra_data, $error); }
@@ -19,8 +17,10 @@ class Lingotek_Logger {
19
  try{
20
  do_action( 'lingotek_log', $level, $message, $extra_data, $error );
21
  do_action( 'lingotek_log_'.$level, $message, $extra_data, $error );
22
-
23
- if (Lingotek_Logger::$logging){
 
 
24
  $serialized_extra_data = Lingotek_Logger::serialize_extra_data($extra_data);
25
  $errorMessage = isset($error) && !isempty($error) ? ", Error: ".$error : "";
26
  error_log($level.": ".$message.$errorMessage.", ExtraData: ".$serialized_extra_data);
7
  */
8
  class Lingotek_Logger {
9
 
 
 
10
  public static function fatal($message, $extra_data = null, $error = null){ Lingotek_Logger::log("fatal", $message, $extra_data, $error); }
11
  public static function error($message, $extra_data = null, $error = null){ Lingotek_Logger::log("error", $message, $extra_data, $error); }
12
  public static function warning($message, $extra_data = null, $error = null){ Lingotek_Logger::log("warning", $message, $extra_data, $error); }
17
  try{
18
  do_action( 'lingotek_log', $level, $message, $extra_data, $error );
19
  do_action( 'lingotek_log_'.$level, $message, $extra_data, $error );
20
+ $prefs = Lingotek_Model::get_prefs();
21
+ $logging = isset($prefs['enable_lingotek_logs']) && '1' === $prefs['enable_lingotek_logs']['enabled'] ? true : false;
22
+ $is_logging = $logging ? "true" : "false";
23
+ if ($logging){
24
  $serialized_extra_data = Lingotek_Logger::serialize_extra_data($extra_data);
25
  $errorMessage = isset($error) && !isempty($error) ? ", Error: ".$error : "";
26
  error_log($level.": ".$message.$errorMessage.", ExtraData: ".$serialized_extra_data);
include/model.php CHANGED
@@ -131,17 +131,28 @@ class Lingotek_Model {
131
  * @return array
132
  */
133
  static public function get_profile($type, $language, $post_id = null) {
134
- $content_types = get_option('lingotek_content_type');
135
- $profiles = get_option('lingotek_profiles');
 
 
 
 
 
 
 
 
 
 
136
 
137
  // If a profile is set for a specific post/page get that first
138
  if ($post_id) {
139
- $terms = get_terms('lingotek_profile', 'orderby=count&hide_empty=0');
140
- foreach ($terms as $term) {
141
- $extracted_post_id = str_replace('lingotek_profile_', '', $term->name);
142
- if ($extracted_post_id == $post_id) {
143
- return $profiles[$term->description];
144
- }
 
145
  }
146
  }
147
 
@@ -149,10 +160,17 @@ class Lingotek_Model {
149
  $default = 'post' === $type || 'page' === $type ? 'manual' : 'disabled';
150
 
151
  $profile = is_object($language) && isset($content_types[$type]['sources'][$language->slug]) ?
152
- $content_types[$type]['sources'][$language->slug] :
153
- (isset($content_types[$type]['profile']) ? $content_types[$type]['profile'] : $default);
154
 
155
- return $profiles[$profile];
 
 
 
 
 
 
 
156
  }
157
 
158
  static public function get_prefs() {
@@ -168,7 +186,8 @@ class Lingotek_Model {
168
  'trash_linked_content' => array(
169
 
170
  ),
171
- 'auto_update_status' => '10'
 
172
  );
173
  $prefs = array_merge($default, get_option('lingotek_prefs', $default)); // ensure defaults are set for missing keys
174
  return $prefs;
@@ -333,8 +352,8 @@ class Lingotek_Model {
333
  $content = Lingotek_Group_Post::get_content($post);
334
  $hash_terms = wp_get_object_terms($post->ID, 'lingotek_hash');
335
  $hash_term = array_pop($hash_terms);
 
336
  if (!empty($hash_term)) {
337
- $new_hash = md5( $content );
338
  if ( $hash_term->description == $new_hash ) {
339
  return;
340
  }
@@ -355,9 +374,16 @@ class Lingotek_Model {
355
  $params = $this->build_params($external_url, $post->post_title, $post->post_type, $content, $language, $profile, $post_id, $wp_target_locales);
356
  $filter_ids = $this->get_filter_ids($post->post_type, $language, $post_id);
357
  $params = array_merge($params, $filter_ids);
358
- if ($document && in_array($document->status, array('edited', 'importing', 'current')) && $document_id) {
359
  $document->patch($this->format_patch_params($params, $profile, $language));
360
- wp_update_term($hash_term->term_id, 'lingotek_hash', array('description' => $new_hash));
 
 
 
 
 
 
 
361
  } elseif (!Lingotek_Group::$creating_translation && !self::$copying_post && (!$document || $document->document_id )) {
362
  $document_id = $client->upload_document($params, $post->ID);
363
 
131
  * @return array
132
  */
133
  static public function get_profile($type, $language, $post_id = null) {
134
+ global $profileInformation, $ltk_profiles, $ltk_contentTypes;
135
+
136
+ if (is_null($ltk_profiles)) {
137
+ $ltk_profiles = get_option('lingotek_profiles');
138
+ }
139
+ if ($post_id && $profileInformation && isset($profileInformation[$type]) && isset($profileInformation[$type][$language->locale]) && isset($profileInformation[$type][$language->locale][$post_id])) {
140
+ return $ltk_profiles[$profileInformation[$type][$language->locale][$post_id]];
141
+ }
142
+
143
+ if (is_null($ltk_contentTypes)) {
144
+ $ltk_contentTypes = get_option('lingotek_content_type');
145
+ }
146
 
147
  // If a profile is set for a specific post/page get that first
148
  if ($post_id) {
149
+ $profileOverride = get_term_by('name', 'lingotek_profile_' . $post_id, 'lingotek_profile');
150
+ if ($profileOverride) {
151
+ if (!isset($profileInformation)) { $profileInformation = array(); }
152
+ if (!isset($profileInformation[$type])) { $profileInformation[$type] = array(); }
153
+ if (!isset($profileInformation[$type][$language->locale])) { $profileInformation[$type][$language->locale] = array(); }
154
+ $profileInformation[$type][$language->locale][$post_id] = $profileOverride->description;
155
+ return $ltk_profiles[$profileOverride->description];
156
  }
157
  }
158
 
160
  $default = 'post' === $type || 'page' === $type ? 'manual' : 'disabled';
161
 
162
  $profile = is_object($language) && isset($content_types[$type]['sources'][$language->slug]) ?
163
+ $ltk_contentTypes[$type]['sources'][$language->slug] :
164
+ (isset($ltk_contentTypes[$type]['profile']) ? $ltk_contentTypes[$type]['profile'] : $default);
165
 
166
+ if ($post_id) {
167
+ if (!isset($profileInformation)) { $profileInformation = array(); }
168
+ if (!isset($profileInformation[$type])) { $profileInformation[$type] = array(); }
169
+ if (!isset($profileInformation[$type][$language->locale])) { $profileInformation[$type][$language->locale] = array(); }
170
+ $profileInformation[$type][$language->locale][$post_id] = $profile;
171
+ }
172
+
173
+ return $ltk_profiles[$profile];
174
  }
175
 
176
  static public function get_prefs() {
186
  'trash_linked_content' => array(
187
 
188
  ),
189
+ 'auto_update_status' => '10',
190
+ 'enable_lingotek_logs' => 0,
191
  );
192
  $prefs = array_merge($default, get_option('lingotek_prefs', $default)); // ensure defaults are set for missing keys
193
  return $prefs;
352
  $content = Lingotek_Group_Post::get_content($post);
353
  $hash_terms = wp_get_object_terms($post->ID, 'lingotek_hash');
354
  $hash_term = array_pop($hash_terms);
355
+ $new_hash = md5( $content );
356
  if (!empty($hash_term)) {
 
357
  if ( $hash_term->description == $new_hash ) {
358
  return;
359
  }
374
  $params = $this->build_params($external_url, $post->post_title, $post->post_type, $content, $language, $profile, $post_id, $wp_target_locales);
375
  $filter_ids = $this->get_filter_ids($post->post_type, $language, $post_id);
376
  $params = array_merge($params, $filter_ids);
377
+ if ($document && in_array($document->status, array('edited', 'importing', 'current', 'cancelled')) && $document_id) {
378
  $document->patch($this->format_patch_params($params, $profile, $language));
379
+ // Re-establish hash relation if needed
380
+ if (!isset($hash_term->term_id)) {
381
+ $hash_terms = wp_set_post_terms($post->ID, 'lingotek_hash_' . $post->ID, "lingotek_hash");
382
+ $hash_term_id = array_pop($hash_terms);
383
+ } else {
384
+ $hash_term_id = $hash_term->id;
385
+ }
386
+ wp_update_term($hash_term_id, 'lingotek_hash', array('description' => $new_hash));
387
  } elseif (!Lingotek_Group::$creating_translation && !self::$copying_post && (!$document || $document->document_id )) {
388
  $document_id = $client->upload_document($params, $post->ID);
389
 
js/updater.js CHANGED
@@ -56,17 +56,9 @@ jQuery(document).ready(function($) {
56
  ignoreClicks();
57
  var doc_id_present = false;
58
  for(var key in data){
59
- if(data[key].doc_id !== null && data[key].doc_id !== undefined){
60
  doc_id_present = true;
61
  }
62
- }
63
- if(doc_id_present === true){
64
- $('.lingotek-request').remove();
65
- $('.lingotek-status').remove();
66
- $('.lingotek-upload').remove();
67
- $('.lingotek-download').remove();
68
- }
69
- for(var key in data){
70
  var source_id = key != data[key]['source_id'] && data[key]['source_id'] !== null
71
  ? data[key]['source_id']
72
  : key;
@@ -78,6 +70,13 @@ jQuery(document).ready(function($) {
78
  if(key.indexOf('_nonce') > -1) {
79
  continue;
80
  }
 
 
 
 
 
 
 
81
  for(var locale in data[key]){
82
  if(locale === 'source' || locale === 'doc_id' || locale === 'source_id' || locale === 'source_status' || locale === 'existing_trans'){
83
  continue;
@@ -110,8 +109,12 @@ jQuery(document).ready(function($) {
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 'failed':
117
  updateFailedIndicator(td, data, key, locale);
@@ -248,7 +251,7 @@ jQuery(document).ready(function($) {
248
  function updateUploadBulkLink(tr, data, key, action, title, text){
249
  var row_actions = $(tr).find('.row-actions');
250
  if($(row_actions).find('.lingotek-' + action).length === 0){
251
- var pipe_separator = data[key].doc_id == null ? '">' + text + '</a> </span>' : '">' + text + '</a> | </span>';
252
  var status_update_link = $('<span class="lingotek-'+ action +'"><a class="lingotek-color"'
253
  + ' title="' + title + '" '
254
  + 'href="?'
56
  ignoreClicks();
57
  var doc_id_present = false;
58
  for(var key in data){
59
+ if(data[key].doc_id !== null && data[key].doc_id !== undefined && data[key].source_status === 'current'){
60
  doc_id_present = true;
61
  }
 
 
 
 
 
 
 
 
62
  var source_id = key != data[key]['source_id'] && data[key]['source_id'] !== null
63
  ? data[key]['source_id']
64
  : key;
70
  if(key.indexOf('_nonce') > -1) {
71
  continue;
72
  }
73
+ if (doc_id_present === true) {
74
+ // Get rid of these if the document id is present and the source status is current
75
+ $(tr).find($('.lingotek-request')).remove();
76
+ $(tr).find($('.lingotek-status')).remove();
77
+ $(tr).find($('.lingotek-upload')).remove();
78
+ $(tr).find($('.lingotek-download')).remove();
79
+ }
80
  for(var locale in data[key]){
81
  if(locale === 'source' || locale === 'doc_id' || locale === 'source_id' || locale === 'source_status' || locale === 'existing_trans'){
82
  continue;
109
  updateIndicator(td, data, key, locale, 'download', 'Ready to download', 'download');
110
  break;
111
  case 'cancelled':
112
+ if (locale === data[key]['source']){
113
+ updateUploadBulkLink(tr, data, key, 'upload' , 'Upload cancelled item to Lingotek TMS', 'Upload to Lingotek');
114
+ updateIndicator(td, data, key, locale, 'cancelled', 'Upload cancelled item', 'warning');
115
+ } else {
116
+ updateIndicator(td, data, key, locale, 'cancelled', 'Target is cancelled', 'warning');
117
+ }
118
  break;
119
  case 'failed':
120
  updateFailedIndicator(td, data, key, locale);
251
  function updateUploadBulkLink(tr, data, key, action, title, text){
252
  var row_actions = $(tr).find('.row-actions');
253
  if($(row_actions).find('.lingotek-' + action).length === 0){
254
+ var pipe_separator = data[key].doc_id == null || data[key].source_status == 'cancelled' ? '">' + text + '</a> </span>' : '">' + text + '</a> | </span>';
255
  var status_update_link = $('<span class="lingotek-'+ action +'"><a class="lingotek-color"'
256
  + ' title="' + title + '" '
257
  + 'href="?'
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.12
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.12' ); // 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).
@@ -309,23 +309,28 @@ class Lingotek {
309
  }
310
 
311
  public function lingotek_plugin_migration() {
312
- $updatesHaveRun = false;
313
- if ($this->needs_to_run_updates('1.4.11')) {
314
- // Add the updates introduced in 1.4.11.
315
- $this->update_1_4_11_for_removing_custom_fields_from_postTypes_settings();
316
- $this->update_1_4_11_for_removing_custom_fields_autoload();
317
- $this->update_1_4_11_for_removing_community_resources_autoload();
318
- $updatesHaveRun = true;
319
- }
320
- // If any update happened, inform the user and update the version.
321
- if ($updatesHaveRun) {
322
- update_option('lingotek_plugin_version', LINGOTEK_VERSION);
323
- add_action('admin_notices', function() {
324
- echo '<div class="notice notice-success is-dismissible">
325
- <p>' . __('Upgrades for the lingotek translation module have completed.', 'lingotek-translation') . '</p>
 
 
 
 
 
326
  </div>';
327
- });
328
- }
329
  }
330
 
331
  /**
@@ -383,6 +388,30 @@ class Lingotek {
383
  update_option('lingotek_community_resources', $settings, false);
384
  }
385
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
386
  /**
387
  * Return the plugin slug.
388
  *
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.13
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.13' ); // 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).
309
  }
310
 
311
  public function lingotek_plugin_migration() {
312
+ $updatesHaveRun = false;
313
+ if ( $this->needs_to_run_updates( '1.4.11' ) ) {
314
+ // Add the updates introduced in 1.4.11.
315
+ $this->update_1_4_11_for_removing_custom_fields_from_postTypes_settings();
316
+ $this->update_1_4_11_for_removing_custom_fields_autoload();
317
+ $this->update_1_4_11_for_removing_community_resources_autoload();
318
+ $updatesHaveRun = true;
319
+ }
320
+ if ( $this->needs_to_run_updates( '1.4.13' ) ) {
321
+ // Add the updates introduced in 1.4.13.
322
+ $this->update_1_4_13_for_disabling_autoload_for_all_wpoptions();
323
+ $updatesHaveRun = true;
324
+ }
325
+ // If any update happened, inform the user and update the version.
326
+ if ( $updatesHaveRun ) {
327
+ update_option( 'lingotek_plugin_version', LINGOTEK_VERSION, false );
328
+ add_action( 'admin_notices', function () {
329
+ echo '<div class="notice notice-success is-dismissible">
330
+ <p>' . __( 'Upgrades for the lingotek translation module have completed.', 'lingotek-translation' ) . '</p>
331
  </div>';
332
+ } );
333
+ }
334
  }
335
 
336
  /**
388
  update_option('lingotek_community_resources', $settings, false);
389
  }
390
 
391
+ /**
392
+ * Set the lingotek_custom_fields option as not autoloaded.
393
+ *
394
+ * @since 1.4.13
395
+ */
396
+ public function update_1_4_13_for_disabling_autoload_for_all_wpoptions()
397
+ {
398
+ $wpoptions = array(
399
+ 'lingotek_base_url',
400
+ 'lingotek_plugin_version',
401
+ 'lingotek_community',
402
+ 'lingotek_defaults',
403
+ 'lingotek_profiles',
404
+ 'lingotek_token',
405
+ );
406
+ foreach ($wpoptions as $wpoption) {
407
+ $settings = get_option($wpoption);
408
+ if ($wpoption !== false) {
409
+ update_option($wpoption, 'fakeValueSoWeForceAutoloadToFalse', false);
410
+ update_option($wpoption, $settings, false);
411
+ }
412
+ }
413
+ }
414
+
415
  /**
416
  * Return the plugin slug.
417
  *
readme.txt CHANGED
@@ -4,7 +4,7 @@ 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.6
7
- Stable tag: 1.4.12
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
 
@@ -122,6 +122,10 @@ For more, visit the [Lingotek documentation site](https://lingotek.atlassian.net
122
  5. The Lingotek Translation plugin provides the ability to Copy, Translate, and Ignore each specific custom field. Our plugin supports Wordpress custom fields and advanced custom fields.
123
 
124
  == Changelog ==
 
 
 
 
125
  = 1.4.12 (2021-5-6) =
126
  * Changed deprecated Polylang method
127
 
4
  Tags: automation, bilingual, international, language, Lingotek, localization, multilanguage, multilingual, translate, translation
5
  Requires at least: 3.8
6
  Tested up to: 5.6
7
+ Stable tag: 1.4.13
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
 
122
  5. The Lingotek Translation plugin provides the ability to Copy, Translate, and Ignore each specific custom field. Our plugin supports Wordpress custom fields and advanced custom fields.
123
 
124
  == Changelog ==
125
+ = 1.4.13 (2021-6-14) =
126
+ * Updated code base to be compatible with PHP 8
127
+ * Updated cancel action behavior to be more consistent.
128
+
129
  = 1.4.12 (2021-5-6) =
130
  * Changed deprecated Polylang method
131