Changeset 8338
- Timestamp:
- 02/24/2019 06:22:00 PM (6 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
sites/trunk/wordpress.org/public_html/wp-content/plugins/wporg-gp-customizations/inc/cli/class-language-pack.php
r8146 r8338 7 7 use stdClass; 8 8 use WP_CLI; 9 use WP_CLI\Utils; 9 10 use WP_CLI_Command; 10 11 use WP_Error; … … 18 19 19 20 /** 21 * Whether a language pack should be enforced. 22 * 23 * @var bool 24 */ 25 private $force = false; 26 27 /** 20 28 * Generates a language pack. 21 29 * … … 36 44 * [--version] 37 45 * : Current version of the theme or plugin. 46 * 47 * [--force] 48 * : Generate language pack even when threshold is not reached or no updates exist. 38 49 */ 39 50 public function generate( $args, $assoc_args ) { 40 51 $type = $args[0]; 41 52 $slug = $args[1]; 53 54 $this->force = Utils\get_flag_value( $assoc_args, 'force' ); 42 55 43 56 $args = wp_parse_args( $assoc_args, [ … … 221 234 * 222 235 * @param string $prefix Optional. The prefix for the directory, 'hello-dolly' for example. 223 *224 236 * @return string The temporary directory. 225 237 */ … … 246 258 * 247 259 * @param string $dir The directory which should be removed. 248 *249 260 * @return bool False if directory is removed, false otherwise. 250 261 */ … … 261 272 * 262 273 * @param string $plugin_slug Slug of a plugin. 263 *264 274 * @return false|string False on failure, stable tag on success. 265 275 */ … … 279 289 * 280 290 * @param string $theme_slug Slug of a theme. 281 *282 291 * @return false|string False on failure, version on success. 283 292 */ … … 297 306 * 298 307 * @param string $plugin_slug Slug of a plugin. 299 *300 308 * @return false|string False on failure, version on success. 301 309 */ … … 375 383 376 384 /** 385 * Build a mapping of JS files to translation entries occurring in those files. 386 * Translation entries occurring in other files are added to the 'po' key. 387 * 388 * @param Translation_Entry[] $entries The translation entries to map. 389 * @return array The mapping of sources to translation entries. 390 */ 391 private function build_mapping( $entries ) { 392 $mapping = []; 393 394 foreach ( $entries as $entry ) { 395 /** @var Translation_Entry $entry */ 396 397 // Find all unique sources this translation originates from. 398 $sources = array_map( function ( $reference ) { 399 $parts = explode( ':', $reference ); 400 $file = $parts[0]; 401 402 if ( substr( $file, -7 ) === '.min.js' ) { 403 return substr( $file, 0, -7 ) . '.js'; 404 } 405 406 if ( substr( $file, -3 ) === '.js' ) { 407 return $file; 408 } 409 return 'po'; 410 }, $entry->references ); 411 412 // Always add all entries to the PO file. 413 $sources[] = 'po'; 414 415 $sources = array_unique( $sources ); 416 417 foreach ( $sources as $source ) { 418 $mapping[ $source ][] = $entry; 419 } 420 } 421 422 return $mapping; 423 } 424 425 /** 426 * Builds a a separate JSON file with translations for each JavaScript file. 427 * 428 * @param GP_Project $gp_project The GlotPress project. 429 * @param GP_Locale $gp_locale The GlotPress locale. 430 * @param GP_Translation_Set $set The translation set. 431 * @param array $mapping A mapping of files to translation entries. 432 * @param string $base_dest Destination file name. 433 * @return array An array of translation files built, may be empty if no translations in JS files exist. 434 */ 435 private function build_json_files( $gp_project, $gp_locale, $set, $mapping, $base_dest ) { 436 $files = array(); 437 $format = gp_array_get( GP::$formats, 'jed1x' ); 438 439 foreach ( $mapping as $file => $entries ) { 440 // Don't create JSON files for source files. 441 if ( 0 === strpos( $file, 'src/' ) || false !== strpos( $file, '/src/' ) ) { 442 continue; 443 } 444 445 // Get the translations in Jed 1.x compatible JSON format. 446 $json_content = $format->print_exported_file( $gp_project, $gp_locale, $set, $entries ); 447 448 // Decode and add comment with file reference for debugging. 449 $json_content_decoded = json_decode( $json_content ); 450 $json_content_decoded->comment = [ 'reference' => $file ]; 451 452 $json_content = wp_json_encode( $json_content_decoded ); 453 454 $hash = md5( $file ); 455 $dest = "{$base_dest}-{$hash}.json"; 456 457 file_put_contents( $dest, $json_content ); 458 459 $files[] = $dest; 460 } 461 462 return $files; 463 } 464 465 /** 377 466 * Builds a PO file for translations. 378 467 * 379 * @param GP_Project $gp_project The GlotPress project. 380 * @param GP_Locale $gp_locale The GlotPress locale. 381 * @param GP_Translation_Set $set The translation set. 382 * @param string $dest Destination file name. 468 * @param GP_Project $gp_project The GlotPress project. 469 * @param GP_Locale $gp_locale The GlotPress locale. 470 * @param GP_Translation_Set $set The translation set. 471 * @param Translation_Entry[] $entries The translation entries. 472 * @param string $dest Destination file name. 383 473 * @return string|WP_Error Last updated date on success, WP_Error on failure. 384 474 */ 385 private function build_po_file( $gp_project, $gp_locale, $set, $dest ) { 386 $entries = GP::$translation->for_export( $gp_project, $set, [ 'status' => 'current' ] ); 387 if ( ! $entries ) { 388 return new WP_Error( 'no_translations', 'No current translations available.' ); 389 } 390 475 private function build_po_file( $gp_project, $gp_locale, $set, $entries, $dest ) { 391 476 $format = gp_array_get( GP::$formats, 'po' ); 392 477 $po_content = $format->print_exported_file( $gp_project, $gp_locale, $set, $entries ); … … 407 492 * 408 493 * @param string $command The escaped command to execute. 409 *410 494 * @return true|WP_Error True on success, WP_Error on failure. 411 495 */ … … 428 512 * @param string $version Version of the theme/plugin. 429 513 * @param string $updated Last updated. 430 * @return string|WP_Error 'updated' when language pack was updated, 'inserted' if it's a new 431 * language pack. WP_Error on failure. 514 * @return true|WP_Error true when language pack was updated, WP_Error on failure. 432 515 */ 433 516 private function insert_language_pack( $type, $domain, $language, $version, $updated ) { … … 444 527 445 528 if ( $existing ) { 446 return new WP_Error( 'language_pack_exists', 'The language pack is already imported for this version.' );529 return true; 447 530 } 448 531 … … 474 557 ) ); 475 558 476 if ( $wpdb->rows_affected ) { 477 return 'updated'; 478 } else { 479 return 'inserted'; 480 } 559 return true; 481 560 } 482 561 … … 488 567 private function build_language_packs( $data ) { 489 568 $existing_packs = $this->get_active_language_packs( $data->type, $data->domain, $data->version ); 490 $svn_command = $this->get_svn_command();569 $svn_command = $this->get_svn_command(); 491 570 492 571 foreach ( $data->translation_sets as $set ) { … … 511 590 // Check if percent translated is above threshold. 512 591 $percent_translated = $set->percent_translated(); 513 if ( $percent_translated < self::PACKAGE_THRESHOLD ) {592 if ( ! $this->force && $percent_translated < self::PACKAGE_THRESHOLD ) { 514 593 WP_CLI::log( "Skip {$wp_locale}, translations below threshold ({$percent_translated}%)." ); 515 594 continue; … … 517 596 518 597 // Check if new translations are available since last build. 519 if ( isset( $existing_packs[ $wp_locale ] ) ) {598 if ( ! $this->force && isset( $existing_packs[ $wp_locale ] ) ) { 520 599 $pack_time = strtotime( $existing_packs[ $wp_locale ]->updated ); 521 600 $glotpress_time = strtotime( $set->last_modified() ); … … 527 606 } 528 607 529 $export_directory = "{$data->svn_checkout}/{$data->domain}/{$data->version}/{$wp_locale}"; 530 $build_directory = self::BUILD_DIR . "/{$data->type}s/{$data->domain}/{$data->version}"; 531 $filename = "{$data->domain}-{$wp_locale}"; 532 $po_file = "{$export_directory}/{$filename}.po"; 533 $mo_file = "{$export_directory}/{$filename}.mo"; 534 $zip_file = "{$export_directory}/{$filename}.zip"; 535 $build_zip_file = "{$build_directory}/{$wp_locale}.zip"; 608 $entries = GP::$translation->for_export( $data->gp_project, $set, [ 'status' => 'current' ] ); 609 if ( ! $entries ) { 610 WP_CLI::warning( "No current translations available for {$wp_locale}." ); 611 continue; 612 } 613 614 $working_directory = "{$data->svn_checkout}/{$data->domain}"; 615 $export_directory = "{$working_directory}/{$data->version}/{$wp_locale}"; 616 $build_directory = self::BUILD_DIR . "/{$data->type}s/{$data->domain}/{$data->version}"; 617 618 $filename = "{$data->domain}-{$wp_locale}"; 619 $json_file_base = "{$export_directory}/{$filename}"; 620 $po_file = "{$export_directory}/{$filename}.po"; 621 $mo_file = "{$export_directory}/{$filename}.mo"; 622 $zip_file = "{$export_directory}/{$filename}.zip"; 623 $build_zip_file = "{$build_directory}/{$wp_locale}.zip"; 536 624 537 625 // Update/create directories. 538 626 $this->update_svn_directory( $export_directory ); 539 627 628 // Build a mapping based on where the translation entries occur and separate the po entries. 629 $mapping = $this->build_mapping( $entries ); 630 $po_entries = array_key_exists( 'po', $mapping ) ? $mapping['po'] : []; 631 632 unset( $mapping['po'] ); 633 634 // Create JED json files for each JS file. 635 $json_files = $this->build_json_files( $data->gp_project, $gp_locale, $set, $mapping, $json_file_base ); 636 540 637 // Create PO file. 541 $last_modified = $this->build_po_file( $data->gp_project, $gp_locale, $set, $po_ file );638 $last_modified = $this->build_po_file( $data->gp_project, $gp_locale, $set, $po_entries, $po_file ); 542 639 543 640 if ( is_wp_error( $last_modified ) ) { … … 545 642 546 643 // Clean up. 547 $this->execute_command( "rm -rf {$data->svn_checkout}/{$data->domain}");644 $this->execute_command( sprintf( 'rm -rf %s', escapeshellarg( $working_directory ) ) ); 548 645 549 646 continue; … … 562 659 563 660 // Clean up. 564 $this->execute_command( "rm -rf {$data->svn_checkout}/{$data->domain}");661 $this->execute_command( sprintf( 'rm -rf %s', escapeshellarg( $working_directory ) ) ); 565 662 566 663 continue; … … 569 666 // Create ZIP file. 570 667 $result = $this->execute_command( sprintf( 571 'zip -9 -j %s %s %s 2>&1',668 'zip -9 -j %s %s %s %s 2>&1', 572 669 escapeshellarg( $zip_file ), 573 670 escapeshellarg( $po_file ), 574 escapeshellarg( $mo_file ) 671 escapeshellarg( $mo_file ), 672 implode( ' ', array_map( 'escapeshellarg', $json_files ) ) 575 673 ) ); 576 674 … … 580 678 581 679 // Clean up. 582 $this->execute_command( "rm -rf {$data->svn_checkout}/{$data->domain}");680 $this->execute_command( sprintf( 'rm -rf %s', escapeshellarg( $working_directory ) ) ); 583 681 584 682 continue; … … 596 694 597 695 // Clean up. 598 $this->execute_command( "rm -rf {$data->svn_checkout}/{$data->domain}");696 $this->execute_command( sprintf( 'rm -rf %s', escapeshellarg( $working_directory ) ) ); 599 697 600 698 continue; … … 613 711 614 712 // Clean up. 615 $this->execute_command( "rm -rf {$data->svn_checkout}/{$data->domain}");713 $this->execute_command( sprintf( 'rm -rf %s', escapeshellarg( $working_directory ) ) ); 616 714 617 715 continue; … … 625 723 626 724 // Clean up. 627 $this->execute_command( "rm -rf {$data->svn_checkout}/{$data->domain}");725 $this->execute_command( sprintf( 'rm -rf %s', escapeshellarg( $working_directory ) ) ); 628 726 629 727 continue; … … 650 748 651 749 // Clean up. 652 $this->execute_command( "rm -rf {$data->svn_checkout}/{$data->domain}");750 $this->execute_command( sprintf( 'rm -rf %s', escapeshellarg( $working_directory ) ) ); 653 751 654 752 continue; … … 656 754 657 755 // Clean up. 658 $this->execute_command( "rm -rf {$data->svn_checkout}/{$data->domain}");756 $this->execute_command( sprintf( 'rm -rf %s', escapeshellarg( $working_directory ) ) ); 659 757 660 758 WP_CLI::success( "Language pack for {$wp_locale} generated." );
Note: See TracChangeset
for help on using the changeset viewer.