[ Index ]

PHP Cross Reference of GlotPress

title

Body

[close]

/gp-includes/routes/ -> translation.php (source)

   1  <?php
   2  /**
   3   * Routes: GP_Route_Translation class
   4   *
   5   * @package GlotPress
   6   * @subpackage Routes
   7   * @since 1.0.0
   8   */
   9  
  10  /**
  11   * Core class used to implement the translation route.
  12   *
  13   * @since 1.0.0
  14   */
  15  class GP_Route_Translation extends GP_Route_Main {
  16  
  17  	public function import_translations_get( $project_path, $locale_slug, $translation_set_slug ) {
  18          $project = GP::$project->by_path( $project_path );
  19          $locale  = GP_Locales::by_slug( $locale_slug );
  20  
  21          if ( ! $project || ! $locale ) {
  22              return $this->die_with_404();
  23          }
  24  
  25          $translation_set = GP::$translation_set->by_project_id_slug_and_locale( $project->id, $translation_set_slug, $locale_slug );
  26  
  27          if ( ! $translation_set ) {
  28              return $this->die_with_404();
  29          }
  30  
  31          $can_import_current = $this->can( 'approve', 'translation-set', $translation_set->id );
  32          $can_import_waiting = $can_import_current || $this->can( 'import-waiting', 'translation-set', $translation_set->id );
  33  
  34          if ( ! $can_import_current && ! $can_import_waiting ) {
  35              $this->redirect_with_error( __( 'You are not allowed to do that!', 'glotpress' ) );
  36              return;
  37          }
  38  
  39          $kind = 'translations';
  40          $this->tmpl( 'project-import', get_defined_vars() );
  41      }
  42  
  43  	public function import_translations_post( $project_path, $locale_slug, $translation_set_slug ) {
  44          $project = GP::$project->by_path( $project_path );
  45          $locale  = GP_Locales::by_slug( $locale_slug );
  46  
  47          if ( ! $project || ! $locale ) {
  48              return $this->die_with_404();
  49          }
  50  
  51          if ( $this->invalid_nonce_and_redirect( 'import-translations_' . $project->id ) ) {
  52              return;
  53          }
  54  
  55          $translation_set = GP::$translation_set->by_project_id_slug_and_locale( $project->id, $translation_set_slug, $locale_slug );
  56  
  57          if ( ! $translation_set ) {
  58              return $this->die_with_404();
  59          }
  60  
  61          $can_import_current = $this->can( 'approve', 'translation-set', $translation_set->id );
  62          $can_import_waiting = $can_import_current || $this->can( 'import-waiting', 'translation-set', $translation_set->id );
  63  
  64          if ( ! $can_import_current && ! $can_import_waiting ) {
  65              $this->redirect_with_error( __( 'You are not allowed to do that!', 'glotpress' ) );
  66              return;
  67          }
  68  
  69          $import_status = gp_post( 'status', 'waiting' );
  70  
  71          $allowed_import_status = array();
  72          if ( $can_import_current ) {
  73              $allowed_import_status[] = 'current';
  74          }
  75          if ( $can_import_waiting ) {
  76              $allowed_import_status[] = 'waiting';
  77          }
  78  
  79          if ( ! in_array( $import_status, $allowed_import_status, true ) ) {
  80              $this->redirect_with_error( __( 'Invalid translation status.', 'glotpress' ) );
  81              return;
  82          }
  83  
  84          if ( ! is_uploaded_file( $_FILES['import-file']['tmp_name'] ) ) {
  85              $this->redirect_with_error( __( 'Error uploading the file.', 'glotpress' ) );
  86              return;
  87          }
  88  
  89          $format = gp_get_import_file_format( gp_post( 'format', 'po' ), $_FILES['import-file']['name'] );
  90  
  91          if ( ! $format ) {
  92              $this->redirect_with_error( __( 'No such format.', 'glotpress' ) );
  93              return;
  94          }
  95  
  96          $translations = $format->read_translations_from_file( $_FILES['import-file']['tmp_name'], $project );
  97          if ( ! $translations ) {
  98              $this->redirect_with_error( __( 'Couldn&#8217;t load translations from file!', 'glotpress' ) );
  99              return;
 100          }
 101  
 102          $translations_added = $translation_set->import( $translations, $import_status );
 103          $this->notices[]    = sprintf(
 104              /* translators: %s: Translations count. */
 105              _n( '%s translation was added', '%s translations were added', $translations_added, 'glotpress' ),
 106              $translations_added
 107          );
 108  
 109          $this->redirect( gp_url_project( $project, gp_url_join( $locale->slug, $translation_set->slug ) ) );
 110      }
 111  
 112  	public function export_translations_get( $project_path, $locale_slug, $translation_set_slug ) {
 113          $project = GP::$project->by_path( $project_path );
 114          $locale  = GP_Locales::by_slug( $locale_slug );
 115  
 116          if ( ! $project || ! $locale ) {
 117              return $this->die_with_404();
 118          }
 119  
 120          $translation_set = GP::$translation_set->by_project_id_slug_and_locale( $project->id, $translation_set_slug, $locale_slug );
 121  
 122          if ( ! $translation_set ) {
 123              return $this->die_with_404();
 124          }
 125  
 126          $get_format = gp_get( 'format', 'po' );
 127  
 128          // If for some reason we were passed in an array or object from the get parameters, don't use it.
 129          if ( ! is_string( $get_format ) ) {
 130              $get_format = 'po';
 131          }
 132  
 133          /** @var GP_Format|null $format */
 134          $format = gp_array_get( GP::$formats, $get_format, null );
 135  
 136          if ( ! $format ) {
 137              return $this->die_with_404();
 138          }
 139  
 140          /**
 141           * Filter the locale in the file name of the translation set export.
 142           *
 143           * @since 1.0.0
 144           *
 145           * @param string    $slug   Slug of the locale.
 146           * @param GP_Locale $locale The current locale.
 147           */
 148          $export_locale = apply_filters( 'gp_export_locale', $locale->slug, $locale );
 149          $filename      = sprintf( $format->filename_pattern . '.' . $format->extension, str_replace( '/', '-', $project->path ), $export_locale );
 150  
 151          /**
 152           * Filter the filename of the translation set export.
 153           *
 154           * @since 1.0.0
 155           *
 156           * @param string             $filename        Filename of the exported translation set.
 157           * @param GP_Format          $format          Format of the export.
 158           * @param GP_Locale          $locale          Locale of the export.
 159           * @param GP_Project         $project         Project the translation set belongs to.
 160           * @param GP_Translation_Set $translation_set The translation set to be exported.
 161           */
 162          $filename = apply_filters( 'gp_export_translations_filename', $filename, $format, $locale, $project, $translation_set );
 163  
 164          $entries = GP::$translation->for_export( $project, $translation_set, gp_get( 'filters' ) );
 165  
 166          if ( gp_has_translation_been_updated( $translation_set ) ) {
 167              $last_modified = gmdate( 'D, d M Y H:i:s', gp_gmt_strtotime( GP::$translation->last_modified( $translation_set ) ) ) . ' GMT';
 168              $this->headers_for_download( $filename, $last_modified );
 169  
 170              // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped --
 171              echo $format->print_exported_file( $project, $locale, $translation_set, $entries );
 172          } else {
 173              // As has_translation_been_updated() compared against HTTP_IF_MODIFIED_SINCE here, send an appropriate header.
 174              $this->status_header( 304 );
 175          }
 176      }
 177  
 178  	public function translations_get( $project_path, $locale_slug, $translation_set_slug ) {
 179          $project = GP::$project->by_path( $project_path );
 180          $locale  = GP_Locales::by_slug( $locale_slug );
 181  
 182          if ( ! $project || ! $locale ) {
 183              return $this->die_with_404();
 184          }
 185  
 186          $translation_set = GP::$translation_set->by_project_id_slug_and_locale( $project->id, $translation_set_slug, $locale_slug );
 187  
 188          if ( ! $translation_set ) {
 189              return $this->die_with_404();
 190          }
 191  
 192          $glossary = $this->get_extended_glossary( $translation_set, $project );
 193  
 194          $page    = gp_get( 'page', 1 );
 195          $filters = gp_get( 'filters', array() );
 196          $sort    = gp_get( 'sort', array() );
 197  
 198          if ( is_array( $sort ) && 'random' === gp_array_get( $sort, 'by' ) ) {
 199              add_filter( 'gp_pagination', '__return_null' );
 200          }
 201  
 202          $per_page = (int) get_user_option( 'gp_per_page' );
 203          if ( 0 === $per_page ) {
 204              $per_page = GP::$translation->per_page;
 205          } else {
 206              GP::$translation->per_page = $per_page;
 207          }
 208  
 209          if ( ! is_array( $filters ) ) {
 210              $filters = array();
 211          }
 212  
 213          if ( ! is_array( $sort ) ) {
 214              $sort = array();
 215          }
 216  
 217          $translations             = GP::$translation->for_translation( $project, $translation_set, $page, $filters, $sort );
 218          $total_translations_count = GP::$translation->found_rows;
 219  
 220          $can_edit            = $this->can( 'edit', 'translation-set', $translation_set->id );
 221          $can_write           = $this->can( 'write', 'project', $project->id );
 222          $can_approve         = $this->can( 'approve', 'translation-set', $translation_set->id );
 223          $can_import_current  = $can_approve;
 224          $can_import_waiting  = $can_approve || $this->can( 'import-waiting', 'translation-set', $translation_set->id );
 225          $url                 = gp_url_project( $project, gp_url_join( $locale->slug, $translation_set->slug ) );
 226          $set_priority_url    = gp_url( '/originals/%original-id%/set_priority' );
 227          $discard_warning_url = gp_url_project( $project, gp_url_join( $locale->slug, $translation_set->slug, '-discard-warning' ) );
 228          $set_status_url      = gp_url_project( $project, gp_url_join( $locale->slug, $translation_set->slug, '-set-status' ) );
 229          $bulk_action         = gp_url_join( $url, '-bulk' );
 230  
 231          // Add action to use different font for translations
 232          add_action(
 233              'gp_head',
 234              function() use ( $locale ) {
 235                  return gp_preferred_sans_serif_style_tag( $locale );
 236              }
 237          );
 238  
 239          $this->tmpl( 'translations', get_defined_vars() );
 240      }
 241  
 242  	public function translations_post( $project_path, $locale_slug, $translation_set_slug ) {
 243          $project = GP::$project->by_path( $project_path );
 244          $locale  = GP_Locales::by_slug( $locale_slug );
 245  
 246          if ( ! $project || ! $locale ) {
 247              return $this->die_with_404();
 248          }
 249  
 250          $original_id = gp_post( 'original_id' );
 251  
 252          if ( ! $this->verify_nonce( 'add-translation_' . $original_id ) ) {
 253              return $this->die_with_error( __( 'An error has occurred. Please try again.', 'glotpress' ), 403 );
 254          }
 255  
 256          $translation_set = GP::$translation_set->by_project_id_slug_and_locale( $project->id, $translation_set_slug, $locale_slug );
 257  
 258          $this->can_or_forbidden( 'edit', 'translation-set', $translation_set->id );
 259  
 260          if ( ! $translation_set ) {
 261              return $this->die_with_404();
 262          }
 263  
 264          $glossary = $this->get_extended_glossary( $translation_set, $project );
 265  
 266          $output = array();
 267          foreach ( gp_post( 'translation', array() ) as $original_id => $translations ) {
 268              $data                       = compact( 'original_id' );
 269              $data['user_id']            = get_current_user_id();
 270              $data['translation_set_id'] = $translation_set->id;
 271  
 272              // Reduce range by one since we're starting at 0, see GH#516.
 273              foreach ( range( 0, GP::$translation->get_static( 'number_of_plural_translations' ) - 1 ) as $i ) {
 274                  if ( isset( $translations[ $i ] ) ) {
 275                      $data[ "translation_$i" ] = $translations[ $i ];
 276                  }
 277              }
 278  
 279              if ( isset( $data['status'] ) ) {
 280                  $set_status = $data['status'];
 281              } else {
 282                  $set_status = 'waiting';
 283              }
 284  
 285              $data['status'] = 'waiting';
 286  
 287              if ( $this->can( 'approve', 'translation-set', $translation_set->id ) || $this->can( 'write', 'project', $project->id ) ) {
 288                  $set_status = 'current';
 289              } else {
 290                  $set_status = 'waiting';
 291              }
 292  
 293              $original         = GP::$original->get( $original_id );
 294              $data['warnings'] = GP::$translation_warnings->check( $original->singular, $original->plural, $translations, $locale );
 295  
 296              $existing_translations = GP::$translation->for_translation(
 297                  $project,
 298                  $translation_set,
 299                  'no-limit',
 300                  array(
 301                      'original_id' => $original_id,
 302                      'status'      => 'current_or_waiting',
 303                  ),
 304                  array()
 305              );
 306              foreach ( $existing_translations as $e ) {
 307                  if ( array_pad( $translations, $locale->nplurals, null ) == $e->translations ) {
 308                      return $this->die_with_error( __( 'Identical current or waiting translation already exists.', 'glotpress' ), 200 );
 309                  }
 310              }
 311  
 312              $translation = GP::$translation->create( $data );
 313  
 314              if ( ! $translation ) {
 315                  return $this->die_with_error( __( 'Error in saving the translation!', 'glotpress' ) );
 316              }
 317  
 318              if ( ! $translation->validate() ) {
 319                  $error_output = '<ul>';
 320                  foreach ( $translation->errors as $error ) {
 321                      $error_output .= '<li>' . $error . '</li>';
 322                  }
 323                  $error_output .= '</ul>';
 324                  $translation->delete();
 325  
 326                  return $this->die_with_error( $error_output, 200 );
 327              } else {
 328                  if ( 'current' === $set_status ) {
 329                      $translation->set_status( 'current' );
 330                  }
 331  
 332                  $translations = GP::$translation->for_translation( $project, $translation_set, 'no-limit', array( 'translation_id' => $translation->id ), array() );
 333  
 334                  if ( ! empty( $translations ) ) {
 335                      $translation = $translations[0];
 336  
 337                      $can_edit                = $this->can( 'edit', 'translation-set', $translation_set->id );
 338                      $can_write               = $this->can( 'write', 'project', $project->id );
 339                      $can_approve             = $this->can( 'approve', 'translation-set', $translation_set->id );
 340                      $can_approve_translation = $this->can( 'approve', 'translation', $translation->id, array( 'translation' => $translation ) );
 341  
 342                      $output[ $original_id ] = gp_tmpl_get_output( 'translation-row', get_defined_vars() );
 343                  } else {
 344                      $output[ $original_id ] = false;
 345                  }
 346              }
 347          }
 348          echo wp_json_encode( $output );
 349      }
 350  
 351  	public function bulk_post( $project_path, $locale_slug, $translation_set_slug ) {
 352          $project = GP::$project->by_path( $project_path );
 353          $locale  = GP_Locales::by_slug( $locale_slug );
 354  
 355          if ( ! $project || ! $locale ) {
 356              return $this->die_with_404();
 357          }
 358  
 359          $translation_set = GP::$translation_set->by_project_id_slug_and_locale( $project->id, $translation_set_slug, $locale_slug );
 360  
 361          if ( ! $translation_set ) {
 362              return $this->die_with_404();
 363          }
 364  
 365          if ( $this->invalid_nonce_and_redirect( 'bulk-actions' ) ) {
 366              return;
 367          }
 368  
 369          if ( $this->cannot_and_redirect( 'approve', 'translation-set', $translation_set->id ) ) {
 370              return;
 371          }
 372  
 373          $bulk            = gp_post( 'bulk' );
 374          $bulk['row-ids'] = array_filter( explode( ',', $bulk['row-ids'] ) );
 375          if ( ! empty( $bulk['row-ids'] ) ) {
 376              switch ( $bulk['action'] ) {
 377                  case 'approve':
 378                  case 'reject':
 379                      $this->_bulk_approve( $bulk );
 380                      break;
 381                  case 'fuzzy':
 382                      $this->_bulk_fuzzy( $bulk );
 383                      break;
 384                  case 'set-priority':
 385                      $this->_bulk_set_priority( $project, $bulk );
 386              }
 387  
 388              /**
 389               * Bulk action for translation set allows handling of custom actions.
 390               *
 391               * @since 1.0.0
 392               *
 393               * @param GP_Project         $project         The current project.
 394               * @param GP_Locale          $locale          The current locale.
 395               * @param GP_Translation_Set $translation_set The current translation set.
 396               * @param array              $bulk            {
 397               *     The bulk action data, read from the POST.
 398               *
 399               *     @type string $action      Action value chosen from the drop down menu.
 400               *     @type string $priority    The selected value from the priority drop down menu.
 401               *     @type string $redirect_to The URL that after the bulk actions are executed the
 402               *                               browser is redirected to.
 403               *     @type array  $row-ids     An array of strings of row IDs.
 404               * }
 405               */
 406              do_action( 'gp_translation_set_bulk_action_post', $project, $locale, $translation_set, $bulk );
 407          } else {
 408              $this->errors[] = 'No translations were supplied.';
 409          }
 410  
 411          $bulk['redirect_to'] = esc_url_raw( $bulk['redirect_to'] );
 412          $this->redirect( $bulk['redirect_to'] );
 413      }
 414  
 415  	private function _bulk_approve( $bulk ) {
 416  
 417          $action = $bulk['action'];
 418  
 419          $ok         = $error = 0;
 420          $new_status = 'approve' == $action ? 'current' : 'rejected';
 421          foreach ( $bulk['row-ids'] as $row_id ) {
 422              $translation_id = gp_array_get( explode( '-', $row_id ), 1 );
 423              $translation    = GP::$translation->get( $translation_id );
 424              if ( ! $translation ) {
 425                  continue;
 426              }
 427              if ( $translation->set_status( $new_status ) ) {
 428                  $ok++;
 429              } else {
 430                  $error++;
 431              }
 432          }
 433  
 434          if ( 0 === $error ) {
 435              $this->notices[] = 'approve' == $action ?
 436                      sprintf(
 437                          /* translators: %d: Translations count. */
 438                          _n( '%d translation was approved.', '%d translations were approved.', $ok, 'glotpress' ),
 439                          $ok
 440                      ) :
 441                      sprintf(
 442                          /* translators: %d: Translations count. */
 443                          _n( '%d translation was rejected.', '%d translations were rejected.', $ok, 'glotpress' ),
 444                          $ok
 445                      );
 446          } else {
 447              if ( $ok > 0 ) {
 448                  $message = 'approve' == $action ?
 449                          sprintf(
 450                              /* translators: %s: Translations count. */
 451                              _n( 'Error with approving %s translation.', 'Error with approving %s translations.', $error, 'glotpress' ),
 452                              $error
 453                          ) :
 454                          sprintf(
 455                              /* translators: %s: Translations count. */
 456                              _n( 'Error with rejecting %s translation.', 'Error with rejecting %s translations.', $error, 'glotpress' ),
 457                              $error
 458                          );
 459                  $message .= ' ';
 460                  $message .= 'approve' == $action ?
 461                          sprintf(
 462                              /* translators: %s: Translations count. */
 463                              _n( 'The remaining %s translation was approved successfully.', 'The remaining %s translations were approved successfully.', $ok, 'glotpress' ),
 464                              $ok
 465                          ) :
 466                          sprintf(
 467                              /* translators: %s: Translations count. */
 468                              _n( 'The remaining %s translation was rejected successfully.', 'The remaining %s translations were rejected successfully.', $ok, 'glotpress' ),
 469                              $ok
 470                          );
 471                  $this->errors[] = $message;
 472              } else {
 473                  $this->errors[] = 'approve' == $action ?
 474                          sprintf(
 475                              /* translators: %s: Translations count. */
 476                              _n( 'Error with approving %s translation.', 'Error with approving all %s translations.', $error, 'glotpress' ),
 477                              $error
 478                          ) :
 479                          sprintf(
 480                              /* translators: %s: Translations count. */
 481                              _n( 'Error with rejecting %s translation.', 'Error with rejecting all %s translations.', $error, 'glotpress' ),
 482                              $error
 483                          );
 484              }
 485          }
 486      }
 487  
 488      /**
 489       * Processes the bulk action to set translations to fuzzy.
 490       *
 491       * @since 2.3.0
 492       *
 493       * @param array $bulk The bulk data to process.
 494       */
 495  	private function _bulk_fuzzy( $bulk ) {
 496          $ok = $error = 0;
 497  
 498          foreach ( $bulk['row-ids'] as $row_id ) {
 499              $translation_id = gp_array_get( explode( '-', $row_id ), 1 );
 500              $translation    = GP::$translation->get( $translation_id );
 501  
 502              if ( ! $translation ) {
 503                  continue;
 504              }
 505  
 506              if ( $translation->set_status( 'fuzzy' ) ) {
 507                  $ok++;
 508              } else {
 509                  $error++;
 510              }
 511          }
 512  
 513          if ( 0 === $error ) {
 514              $this->notices[] = sprintf(
 515                  /* translators: %d: Translations count. */
 516                  _n( '%d translation was marked as fuzzy.', '%d translations were marked as fuzzy.', $ok, 'glotpress' ),
 517                  $ok
 518              );
 519          } else {
 520              if ( $ok > 0 ) {
 521                  $message = sprintf(
 522                      /* translators: %d: Translations count. */
 523                      _n( 'Error with marking %d translation as fuzzy.', 'Error with marking %d translations as fuzzy.', $error, 'glotpress' ),
 524                      $error
 525                  );
 526                  $message .= ' ';
 527                  $message .= sprintf(
 528                      /* translators: %d: Translations count. */
 529                      _n( 'The remaining %d translation was marked as fuzzy successfully.', 'The remaining %d translations were marked as fuzzy successfully.', $ok, 'glotpress' ),
 530                      $ok
 531                  );
 532  
 533                  $this->errors[] = $message;
 534              } else {
 535                  $this->errors[] = sprintf(
 536                      /* translators: %d: Translations count. */
 537                      _n( 'Error with marking %d translation as fuzzy.', 'Error with marking all %d translation as fuzzy.', $error, 'glotpress' ),
 538                      $error
 539                  );
 540              }
 541          }
 542      }
 543  
 544  	private function _bulk_set_priority( $project, $bulk ) {
 545  
 546          if ( $this->cannot_and_redirect( 'write', 'project', $project->id ) ) {
 547              return;
 548          }
 549  
 550          $ok = $error = 0;
 551          foreach ( $bulk['row-ids'] as $row_id ) {
 552              $original_id = gp_array_get( explode( '-', $row_id ), 0 );
 553              $original    = GP::$original->get( $original_id );
 554  
 555              if ( ! $original ) {
 556                  continue;
 557              }
 558  
 559              $original->priority = $bulk['priority'];
 560  
 561              if ( ! $original->validate() ) {
 562                  return $this->die_with_error( 'Invalid priority value!' );
 563              }
 564  
 565              if ( ! $original->save() ) {
 566                  $error++;
 567              } else {
 568                  $ok ++;
 569              }
 570          }
 571  
 572          if ( 0 === $error ) {
 573              $this->notices[] = sprintf(
 574                  /* translators: %d: Originals count. */
 575                  _n( 'Priority of %d original was modified.', 'Priority of %d originals were modified.', $ok, 'glotpress' ),
 576                  $ok
 577              );
 578          } else {
 579              if ( $ok > 0 ) {
 580                  $message = sprintf(
 581                      /* translators: %d: Originals count. */
 582                      _n( 'Error modifying priority of %d original.', 'Error modifying priority of %d originals.', $error, 'glotpress' ),
 583                      $error
 584                  );
 585                  $message .= sprintf(
 586                      /* translators: %d: Originals count. */
 587                      _n( 'The remaining %d original was modified successfully.', 'The remaining %d originals were modified successfully.', $ok, 'glotpress' ),
 588                      $ok
 589                  );
 590  
 591                  $this->errors[] = $message;
 592              } else {
 593                  $this->errors[] = sprintf(
 594                      /* translators: %d: Originals count. */
 595                      _n( 'Error modifying priority of %d original.', 'Error modifying priority of all %d originals.', $error, 'glotpress' ),
 596                      $error
 597                  );
 598              }
 599          }
 600  
 601      }
 602  
 603  	public function discard_warning( $project_path, $locale_slug, $translation_set_slug ) {
 604          $index = gp_post( 'index' );
 605          $key   = gp_post( 'key' );
 606  
 607          if ( ! $this->verify_nonce( 'discard-warning_' . $index . $key ) ) {
 608              return $this->die_with_error( __( 'An error has occurred. Please try again.', 'glotpress' ), 403 );
 609          }
 610  
 611          return $this->edit_single_translation( $project_path, $locale_slug, $translation_set_slug, array( $this, 'discard_warning_edit_function' ) );
 612      }
 613  
 614  	public function set_status( $project_path, $locale_slug, $translation_set_slug ) {
 615          $status         = gp_post( 'status' );
 616          $translation_id = gp_post( 'translation_id' );
 617  
 618          if ( ! $this->verify_nonce( 'update-translation-status-' . $status . '_' . $translation_id ) ) {
 619              return $this->die_with_error( __( 'An error has occurred. Please try again.', 'glotpress' ), 403 );
 620          }
 621  
 622          return $this->edit_single_translation( $project_path, $locale_slug, $translation_set_slug, array( $this, 'set_status_edit_function' ) );
 623      }
 624  
 625      /**
 626       * Edits a single translation.
 627       *
 628       * @since 1.0.0
 629       *
 630       * @param string   $project_path         The path of the project.
 631       * @param string   $locale_slug          The locale slug.
 632       * @param string   $translation_set_slug The slug of the translation set.
 633       * @param callable $edit_function        The edit function to call on the translation.
 634       */
 635  	private function edit_single_translation( $project_path, $locale_slug, $translation_set_slug, $edit_function ) {
 636          $project = GP::$project->by_path( $project_path );
 637          $locale  = GP_Locales::by_slug( $locale_slug );
 638  
 639          if ( ! $project || ! $locale ) {
 640              return $this->die_with_404();
 641          }
 642  
 643          $translation_set = GP::$translation_set->by_project_id_slug_and_locale( $project->id, $translation_set_slug, $locale_slug );
 644  
 645          if ( ! $translation_set ) {
 646              return $this->die_with_404();
 647          }
 648  
 649          $glossary = $this->get_extended_glossary( $translation_set, $project );
 650  
 651          $translation = GP::$translation->get( gp_post( 'translation_id' ) );
 652  
 653          if ( ! $translation ) {
 654              return $this->die_with_error( 'Translation doesn&#8217;t exist!' );
 655          }
 656  
 657          $this->can_approve_translation_or_forbidden( $translation );
 658  
 659          $edit_function( $project, $locale, $translation_set, $translation );
 660  
 661          $translations = GP::$translation->for_translation(
 662              $project,
 663              $translation_set,
 664              'no-limit',
 665              array(
 666                  'translation_id' => $translation->id,
 667                  'status'         => 'either',
 668              ),
 669              array()
 670          );
 671          if ( ! empty( $translations ) ) {
 672              $translation = $translations[0];
 673  
 674              $can_edit                = $this->can( 'edit', 'translation-set', $translation_set->id );
 675              $can_write               = $this->can( 'write', 'project', $project->id );
 676              $can_approve             = $this->can( 'approve', 'translation-set', $translation_set->id );
 677              $can_approve_translation = $this->can( 'approve', 'translation', $translation->id, array( 'translation' => $translation ) );
 678  
 679              $this->tmpl( 'translation-row', get_defined_vars() );
 680          } else {
 681              return $this->die_with_error( 'Error in retrieving translation!' );
 682          }
 683      }
 684  
 685      /**
 686       * Discard a warning.
 687       *
 688       * @since 1.0.0
 689       *
 690       * @param GP_Project         $project         The project.
 691       * @param GP_Locale          $locale          The GlotPress locale.
 692       * @param GP_Translation_Set $translation_set The translation set.
 693       * @param GP_Translation     $translation     The translation object.
 694       */
 695  	private function discard_warning_edit_function( $project, $locale, $translation_set, $translation ) {
 696          if ( ! isset( $translation->warnings[ gp_post( 'index' ) ][ gp_post( 'key' ) ] ) ) {
 697              return $this->die_with_error( 'The warning doesn&#8217;exist!' );
 698          }
 699  
 700          $warning = array(
 701              'project_id'      => $project->id,
 702              'translation_set' => $translation_set->id,
 703              'translation'     => $translation->id,
 704              'warning'         => gp_post( 'key' ),
 705              'user'            => get_current_user_id(),
 706          );
 707  
 708          /**
 709           * Fires before a warning gets discarded.
 710           *
 711           * @since 1.0.0
 712           *
 713           * @param array $warning {
 714           *     @type string $project_id      ID of the project.
 715           *     @type string $translation_set ID of the translation set.
 716           *     @type string $translation     ID of the translation.
 717           *     @type string $warning         The warning key.
 718           *     @type int    $user            Current user's ID.
 719           * }
 720           */
 721          do_action_ref_array( 'gp_warning_discarded', $warning );
 722  
 723          unset( $translation->warnings[ gp_post( 'index' ) ][ gp_post( 'key' ) ] );
 724          if ( empty( $translation->warnings[ gp_post( 'index' ) ] ) ) {
 725              unset( $translation->warnings[ gp_post( 'index' ) ] );
 726          }
 727  
 728          $res = $translation->save();
 729  
 730          if ( false === $res || null === $res ) {
 731              return $this->die_with_error( 'Error in saving the translation!' );
 732          }
 733      }
 734  
 735  	private function set_status_edit_function( $project, $locale, $translation_set, $translation ) {
 736          $res = $translation->set_status( gp_post( 'status' ) );
 737  
 738          if ( ! $res ) {
 739              return $this->die_with_error( 'Error in saving the translation status!' );
 740          }
 741      }
 742  
 743  	private function can_approve_translation_or_forbidden( $translation ) {
 744          $can_reject_self = ( get_current_user_id() == $translation->user_id && 'waiting' == $translation->status );
 745          if ( $can_reject_self ) {
 746              return;
 747          }
 748          $this->can_or_forbidden( 'approve', 'translation', $translation->id, null, array( 'translation' => $translation ) );
 749      }
 750  
 751      /**
 752       * Get the glossary for the translation set.
 753       *
 754       * This also fetches contents from a potential locale glossary, as well as from a parent project.
 755       *
 756       * @since 2.3.0
 757       *
 758       * @param  GP_Translation_Set $translation_set Translation set for which to retrieve the glossary.
 759       * @param  GP_Project         $project         Project for finding potential parent projects.
 760       * @return GP_Glossary Extended glossary.
 761       */
 762  	protected function get_extended_glossary( $translation_set, $project ) {
 763          $glossary = GP::$glossary->by_set_or_parent_project( $translation_set, $project );
 764  
 765          $locale_glossary_project_id      = 0;
 766          $locale_glossary_translation_set = GP::$translation_set->by_project_id_slug_and_locale( $locale_glossary_project_id, $translation_set->slug, $translation_set->locale );
 767  
 768          if ( ! $locale_glossary_translation_set ) {
 769              return $glossary;
 770          }
 771  
 772          $locale_glossary = GP::$glossary->by_set_id( $locale_glossary_translation_set->id );
 773  
 774          // Return locale glossary if a project has no glossary.
 775          if ( false === $glossary && $locale_glossary instanceof GP_Glossary ) {
 776              return $locale_glossary;
 777          }
 778  
 779          if ( $glossary instanceof GP_Glossary && $locale_glossary instanceof GP_Glossary && $locale_glossary->id !== $glossary->id ) {
 780              $glossary->merge_with_glossary( $locale_glossary );
 781          }
 782  
 783          return $glossary;
 784      }
 785  }


Generated: Sat May 30 01:01:53 2020 Cross-referenced by PHPXref 0.7.1