From 4900c4249fed560b83e69eab9195169e4ba69edd Mon Sep 17 00:00:00 2001 From: priethor <27339341+priethor@users.noreply.github.com> Date: Thu, 13 Nov 2025 20:04:17 +0100 Subject: [PATCH 1/3] Use entity prefix for keys when duplicating entities --- includes/class-acf-internal-post-type.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/includes/class-acf-internal-post-type.php b/includes/class-acf-internal-post-type.php index 67925f8c..898896e3 100644 --- a/includes/class-acf-internal-post-type.php +++ b/includes/class-acf-internal-post-type.php @@ -724,7 +724,7 @@ public function duplicate_post( $id = 0, $new_post_id = 0 ) { // Update attributes. $post['ID'] = $new_post_id; - $post['key'] = uniqid( 'group_' ); + $post['key'] = uniqid( $this->post_key_prefix ); // Add (copy) to title when appropriate. if ( ! $new_post_id ) { From 90de127cdb464e99f89ce63cf44bb7d0f88edc16 Mon Sep 17 00:00:00 2001 From: priethor <27339341+priethor@users.noreply.github.com> Date: Fri, 14 Nov 2025 12:01:17 +0100 Subject: [PATCH 2/3] Add tests --- .../test-class-acf-internal-post-type.php | 195 ++++++++++++++++++ 1 file changed, 195 insertions(+) create mode 100644 tests/php/includes/test-class-acf-internal-post-type.php diff --git a/tests/php/includes/test-class-acf-internal-post-type.php b/tests/php/includes/test-class-acf-internal-post-type.php new file mode 100644 index 00000000..7fa19a7c --- /dev/null +++ b/tests/php/includes/test-class-acf-internal-post-type.php @@ -0,0 +1,195 @@ +field_group = new ACF_Field_Group(); + $this->post_type = new ACF_Post_Type(); + + // Create a real field group post in the database. + $this->field_group_id = wp_insert_post( + array( + 'post_type' => 'acf-field-group', + 'post_title' => 'Test Field Group', + 'post_status' => 'publish', + 'post_content' => wp_json_encode( + array( + 'fields' => array(), + 'location' => array(), + ) + ), + ) + ); + + // Set required ACF post meta. + update_post_meta( $this->field_group_id, 'acf-key', 'group_test_' . uniqid() ); + + // Create a real post type post in the database. + $this->post_type_id = wp_insert_post( + array( + 'post_type' => 'acf-post-type', + 'post_title' => 'Test Post Type', + 'post_status' => 'publish', + 'post_content' => wp_json_encode( array() ), + ) + ); + + // Set required ACF post meta. + update_post_meta( $this->post_type_id, 'acf-key', 'post_type_test_' . uniqid() ); + } + + /** + * Clean up test data. + */ + public function tearDown(): void { + if ( $this->field_group_id ) { + wp_delete_post( $this->field_group_id, true ); + } + if ( $this->post_type_id ) { + wp_delete_post( $this->post_type_id, true ); + } + parent::tearDown(); + } + + /** + * Test field group duplication generates correct key prefix. + */ + public function test_duplicate_post_generates_group_prefix_key() { + $duplicated = $this->field_group->duplicate_post( $this->field_group_id ); + + $this->assertIsArray( $duplicated, 'duplicate_post should return an array' ); + $this->assertArrayHasKey( 'key', $duplicated, 'Duplicated post should have key' ); + $this->assertStringStartsWith( + 'group_', + $duplicated['key'], + 'Duplicated field group key should start with group_ prefix' + ); + } + + /** + * Test duplicated field group title contains (copy). + */ + public function test_duplicate_post_appends_copy_to_title() { + $duplicated = $this->field_group->duplicate_post( $this->field_group_id ); + + $this->assertStringContainsString( + '(copy)', + $duplicated['title'], + 'Duplicated field group title should contain (copy)' + ); + } + + /** + * Test duplicate generates unique keys each time. + */ + public function test_duplicate_post_generates_unique_keys() { + $duplicate1 = $this->field_group->duplicate_post( $this->field_group_id ); + $duplicate2 = $this->field_group->duplicate_post( $this->field_group_id ); + + $this->assertNotEquals( + $duplicate1['key'], + $duplicate2['key'], + 'Each duplicate should have a unique key' + ); + + // Both should still have group_ prefix + $this->assertStringStartsWith( 'group_', $duplicate1['key'] ); + $this->assertStringStartsWith( 'group_', $duplicate2['key'] ); + } + + /** + * Test duplicate does not add (copy) when new_post_id is provided. + */ + public function test_duplicate_post_skips_copy_suffix_with_new_post_id() { + $original = $this->field_group->get_post( $this->field_group_id ); + $original_title = $original['title']; + + $duplicated = $this->field_group->duplicate_post( $this->field_group_id, 999 ); + + $this->assertEquals( + $original_title, + $duplicated['title'], + 'Title should not have (copy) appended when new_post_id is provided' + ); + } + + /** + * Test duplicate returns false for non-existent post. + */ + public function test_duplicate_post_returns_false_for_invalid_post() { + $result = $this->field_group->duplicate_post( 99999 ); + + $this->assertFalse( $result, 'duplicate_post should return false for non-existent post' ); + } + + /** + * Test post type duplication uses correct prefix (not group_). + * + * Post types should use 'post_type_' prefix, not the 'group_' prefix used by field groups. + * See https://github.com/WordPress/secure-custom-fields/pull/240 + */ + public function test_duplicate_post_type_uses_correct_prefix() { + $duplicated = $this->post_type->duplicate_post( $this->post_type_id ); + + $this->assertIsArray( $duplicated, 'duplicate_post should return an array' ); + $this->assertArrayHasKey( 'key', $duplicated, 'Duplicated post should have key' ); + $this->assertStringStartsWith( + 'post_type_', + $duplicated['key'], + 'Duplicated post type key should start with post_type_ prefix' + ); + $this->assertFalse( + strpos( $duplicated['key'], 'group_' ) === 0, + 'Post type key should not start with group_ prefix' + ); + } +} From 1149b6b17696ba783579b36de5ac681dfb080f12 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A9ctor?= <27339341+priethor@users.noreply.github.com> Date: Fri, 14 Nov 2025 12:47:19 +0100 Subject: [PATCH 3/3] Document the code change Added comment to clarify the purpose of uniqid function. --- includes/class-acf-internal-post-type.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/includes/class-acf-internal-post-type.php b/includes/class-acf-internal-post-type.php index 898896e3..c8aa6f93 100644 --- a/includes/class-acf-internal-post-type.php +++ b/includes/class-acf-internal-post-type.php @@ -724,7 +724,7 @@ public function duplicate_post( $id = 0, $new_post_id = 0 ) { // Update attributes. $post['ID'] = $new_post_id; - $post['key'] = uniqid( $this->post_key_prefix ); + $post['key'] = uniqid( $this->post_key_prefix ); // See https://github.com/WordPress/secure-custom-fields/pull/240 // Add (copy) to title when appropriate. if ( ! $new_post_id ) {