Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

namespace WordPressdotorg\Pattern_Directory;

use function WordPressdotorg\Pattern_Directory\Pattern_Post_Type\get_contains_block_types;
use const WordPressdotorg\Pattern_Directory\Pattern_Post_Type\{ POST_TYPE };

// This script should only be called in a CLI environment.
Expand Down Expand Up @@ -79,17 +80,9 @@

while ( $query->have_posts() ) {
$query->the_post();
$pattern = get_post();
$pattern_id = $pattern->ID;
$blocks = parse_blocks( $pattern->post_content );
$all_blocks = _flatten_blocks( $blocks );

// Get the list of block names and convert it to a single string.
$block_names = wp_list_pluck( $all_blocks, 'blockName' );
$block_names = array_filter( $block_names );
$block_names = array_unique( $block_names );
sort( $block_names );
$used_blocks = implode( ',', $block_names );
$pattern = get_post();
$pattern_id = $pattern->ID;
$used_blocks = get_contains_block_types( $pattern->post_content );

if ( $opts['apply'] ) {
$result = update_post_meta( $pattern_id, 'wpop_contains_block_types', $used_blocks );
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -586,17 +586,26 @@ function update_contains_block_types_meta( $pattern_id ) {
return;
}

$blocks = parse_blocks( $pattern->post_content );
update_post_meta( $pattern->ID, 'wpop_contains_block_types', get_contains_block_types( $pattern->post_content ) );
}

/**
* Block types used in pattern content, as stored in `wpop_contains_block_types`.
*
* @param string $content Pattern content.
* @return string Sorted, comma-separated block names.
*/
function get_contains_block_types( $content ) {
$blocks = parse_blocks( $content );
$all_blocks = _flatten_blocks( $blocks );

// Get the list of block names and convert it to a single string.
$block_names = wp_list_pluck( $all_blocks, 'blockName' );
$block_names = array_filter( $block_names ); // Filter out null values (extra line breaks).
$block_names = array_unique( $block_names );
sort( $block_names );
$used_blocks = implode( ',', $block_names );

update_post_meta( $pattern->ID, 'wpop_contains_block_types', $used_blocks );
return implode( ',', $block_names );
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,20 +96,144 @@ public function test_typed_control_character_escape_stays_text(): void {
$this->assertDoesNotMatchRegularExpression( '#<!--\s+wp:shortcode#', get_post( $post_id )->post_content );
}

/**
* Storing the same translation again leaves the post and its terms alone, backslashes included.
*/
public function test_unchanged_translation_is_not_rewritten(): void {
$category = self::factory()->term->create( array( 'taxonomy' => 'wporg-pattern-category' ) );
wp_set_object_terms( self::$parent_id, array( $category ), 'wporg-pattern-category' );

$replacements = array(
'Title' => 'Titre \ barre',
'Description' => 'Chemin C:\Temp',
'Subtitle' => 'C:\Temp',
);
$post_id = create_or_update_translated_pattern( $this->translate( $replacements ) );

$saves = did_action( 'save_post_' . POST_TYPE );
$term_sets = did_action( 'set_object_terms' );

$this->assertSame( $post_id, create_or_update_translated_pattern( $this->translate( $replacements, $post_id ), $written ) );
$this->assertFalse( $written );
$this->assertSame( $saves, did_action( 'save_post_' . POST_TYPE ) );
$this->assertSame( $term_sets, did_action( 'set_object_terms' ) );
}

/**
* A stale parent `wpop_contains_block_types` doesn't force rewrites.
*/
public function test_stale_parent_block_types_do_not_force_rewrites(): void {
update_post_meta( self::$parent_id, 'wpop_contains_block_types', '' );

$post_id = create_or_update_translated_pattern( $this->translate( array( 'Title' => 'Titre' ) ) );
// Saving changed strings runs the `post_updated` hook, which recomputes the value.
create_or_update_translated_pattern( $this->translate( array( 'Title' => 'Nouveau titre' ), $post_id ) );
create_or_update_translated_pattern( $this->translate( array( 'Title' => 'Nouveau titre' ), $post_id ), $written );

$this->assertFalse( $written );
$this->assertSame( 'core/heading', get_post_meta( $post_id, 'wpop_contains_block_types', true ) );
}

/**
* A changed translator string reaches the stored translation.
*/
public function test_changed_string_is_stored(): void {
$post_id = create_or_update_translated_pattern( $this->translate( array( 'Title' => 'Titre' ) ) );
create_or_update_translated_pattern( $this->translate( array( 'Title' => 'Nouveau titre' ), $post_id ), $written );

$this->assertTrue( $written );
$this->assertSame( 'Nouveau titre', get_post( $post_id )->post_title );
}

/**
* A change to only the parent's meta, or only the translated description, is stored.
*/
public function test_meta_only_changes_are_stored(): void {
$post_id = create_or_update_translated_pattern( $this->translate( array( 'Description' => 'Une description' ) ) );

update_post_meta( self::$parent_id, 'wpop_wp_version', '6.9' );
create_or_update_translated_pattern( $this->translate( array( 'Description' => 'Une description' ), $post_id ), $written );

$this->assertTrue( $written );
$this->assertSame( '6.9', get_post_meta( $post_id, 'wpop_wp_version', true ) );

create_or_update_translated_pattern( $this->translate( array( 'Description' => 'Autre description' ), $post_id ), $written );

$this->assertTrue( $written );
$this->assertSame( 'Autre description', get_post_meta( $post_id, 'wpop_description', true ) );
}

/**
* Fields the job doesn't translate are still reset when edited on a translation.
*/
public function test_edited_password_is_reset(): void {
$post_id = create_or_update_translated_pattern( $this->translate( array( 'Title' => 'Titre' ) ) );
wp_update_post(
array(
'ID' => $post_id,
'post_password' => 'secret',
)
);

create_or_update_translated_pattern( $this->translate( array( 'Title' => 'Titre' ), $post_id ) );

$this->assertSame( '', get_post( $post_id )->post_password );
}

/**
* A change to only the parent's terms is copied without rewriting the post.
*/
public function test_parent_term_change_is_copied(): void {
$post_id = create_or_update_translated_pattern( $this->translate( array( 'Title' => 'Titre' ) ) );

$category = self::factory()->term->create( array( 'taxonomy' => 'wporg-pattern-category' ) );
wp_set_object_terms( self::$parent_id, array( $category ), 'wporg-pattern-category' );

$saves = did_action( 'save_post_' . POST_TYPE );
create_or_update_translated_pattern( $this->translate( array( 'Title' => 'Titre' ), $post_id ), $written );

$this->assertTrue( $written );
$this->assertSame( $saves, did_action( 'save_post_' . POST_TYPE ) );
$this->assertSame( array( $category ), wp_get_object_terms( $post_id, 'wporg-pattern-category', array( 'fields' => 'ids' ) ) );
}

/**
* A change to only the parent's status is copied.
*/
public function test_parent_status_change_is_copied(): void {
$post_id = create_or_update_translated_pattern( $this->translate( array( 'Title' => 'Titre' ) ) );

wp_update_post(
array(
'ID' => self::$parent_id,
'post_status' => 'draft',
)
);
create_or_update_translated_pattern( $this->translate( array( 'Title' => 'Titre' ), $post_id ), $written );

$this->assertTrue( $written );
$this->assertSame( 'draft', get_post_status( $post_id ) );
}

/**
* Run the parent through the parser with the given translator strings, as the job does.
*
* @param array $replacements Translations keyed by original string.
* @param int $existing_id Optional. The stored translation the job would find.
* @return Translations_Pattern The assembled translation.
*/
protected function translate( array $replacements ): Translations_Pattern {
protected function translate( array $replacements, int $existing_id = 0 ): Translations_Pattern {
$parent = Translations_Pattern::from_post( get_post( self::$parent_id ) );

$pattern = ( new PatternParser( $parent ) )->replace_strings_with_kses( $replacements );
$pattern->ID = 0;
$pattern->ID = $existing_id;
$pattern->locale = self::LOCALE;
$pattern->parent = $parent;

if ( $existing_id ) {
$pattern->name = get_post( $existing_id )->post_name;
}

return $pattern;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -102,12 +102,15 @@ function () {

$translated = $pattern->to_locale( $locale );
if ( $translated ) {
log_message( "\t{$locale} - " . ( $translated->ID ? 'Updating' : 'Creating' ) . ' Translated pattern.' );
$result = create_or_update_translated_pattern( $translated );
$result = create_or_update_translated_pattern( $translated, $written );
if ( is_wp_error( $result ) ) {
// phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log -- failures need to reach the server log, not only the job output.
error_log( "Pattern translation import failed for {$pattern->name} ({$locale}): " . $result->get_error_message() );
log_message( "\t{$locale} - ERROR: {$result->get_error_message()}" );
} elseif ( ! $written ) {
log_message( "\t{$locale} - Translated pattern unchanged." );
} else {
log_message( "\t{$locale} - " . ( $translated->ID ? 'Updated' : 'Created' ) . ' Translated pattern.' );
}
} else {
log_message( "\t{$locale} - No Translations exist yet." );
Expand Down
Loading
Loading