Skip to content

Commit 23004c7

Browse files
committed
Include overwrite logic within post update flows with supporting unit tests
1 parent bd053eb commit 23004c7

5 files changed

Lines changed: 286 additions & 10 deletions

File tree

dt-posts/dt-posts-endpoints.php

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -593,7 +593,7 @@ public function create_post( WP_REST_Request $request ) {
593593
$overwrite_existing_fields = isset( $get_params['overwrite_existing_fields'] ) && $get_params['overwrite_existing_fields'] === 'true';
594594
$post = DT_Posts::create_post( $url_params['post_type'], $fields, $silent, true, [
595595
'check_for_duplicates' => $check_dups,
596-
'overwrite_existing_fields' => $overwrite_existing_fields
596+
'do_not_overwrite_existing_fields' => !$overwrite_existing_fields
597597
] );
598598
return $post;
599599
}
@@ -609,7 +609,10 @@ public function update_post( WP_REST_Request $request ){
609609
$url_params = $request->get_url_params();
610610
$get_params = $request->get_query_params();
611611
$silent = isset( $get_params['silent'] ) && $get_params['silent'] === 'true';
612-
return DT_Posts::update_post( $url_params['post_type'], $url_params['id'], $fields, $silent );
612+
$overwrite_existing_fields = isset( $get_params['overwrite_existing_fields'] ) && $get_params['overwrite_existing_fields'] === 'true';
613+
return DT_Posts::update_post( $url_params['post_type'], $url_params['id'], $fields, $silent, true, [
614+
'do_not_overwrite_existing_fields' => !$overwrite_existing_fields
615+
] );
613616
}
614617

615618
public function delete_post( WP_REST_Request $request ){

dt-posts/dt-posts-hooks.php

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,7 @@ public static function dt_create_check_for_duplicate_posts( $duplicates, $post_t
230230
* @param $post_id
231231
*/
232232
public static function dt_ignore_duplicated_post_fields( $updated_fields, $fields, $post_type, $post_id ) {
233-
$existing_fields = DT_Posts::get_post( $post_type, $post_id );
233+
$existing_fields = DT_Posts::get_post( $post_type, $post_id, true, false );
234234
if ( !empty( $existing_fields ) && !is_wp_error( $existing_fields ) ) {
235235
$field_settings = DT_Posts::get_post_field_settings( $post_type );
236236
foreach ( $fields as $field_key => $field_value ) {
@@ -293,14 +293,26 @@ public static function dt_ignore_duplicated_post_fields( $updated_fields, $field
293293
break;
294294
case 'communication_channel':
295295
$values = [];
296+
$existing_field_values = $existing_fields[ $field_key ];
297+
296298
foreach ( $field_value ?? [] as $value ) {
297299
$key = 'value';
298-
$found = array_filter( $existing_fields[ $field_key ], function ( $option ) use ( $value, $key ) {
299-
return isset( $option[$key] ) && $option[$key] == $value['value'];
300-
} );
300+
$found = array_values( array_filter( $value, function ( $option ) use ( $existing_field_values, $key ) {
301301

302-
if ( empty( $found ) || count( $found ) == 0 ) {
303-
$values[] = $value;
302+
$hit = false;
303+
foreach ( $existing_field_values as $existing_field_value ) {
304+
if ( !$hit && isset( $option[$key] ) && $option[$key] != $existing_field_value[$key] ) {
305+
$hit = true;
306+
}
307+
}
308+
return $hit;
309+
} ) );
310+
if ( !empty( $found ) ) {
311+
foreach ( $found as $found_value ) {
312+
$values[] = [
313+
'value' => $found_value[$key]
314+
];
315+
}
304316
}
305317
}
306318
if ( !empty( $values ) ) {

dt-posts/dt-posts.php

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ public static function create_post( string $post_type, array $fields, bool $sile
9797
* to have them removed from importing fields.
9898
*/
9999

100-
if ( isset( $args['overwrite_existing_fields'] ) && !$args['overwrite_existing_fields'] ) {
100+
if ( isset( $args['do_not_overwrite_existing_fields'] ) && $args['do_not_overwrite_existing_fields'] ) {
101101
$fields = apply_filters( 'dt_ignore_duplicated_post_fields', [], $fields, $post_type, $duplicate_post_id );
102102
}
103103

@@ -401,7 +401,7 @@ public static function create_post( string $post_type, array $fields, bool $sile
401401
*
402402
* @return array|WP_Error
403403
*/
404-
public static function update_post( string $post_type, int $post_id, array $fields, bool $silent = false, bool $check_permissions = true ){
404+
public static function update_post( string $post_type, int $post_id, array $fields, bool $silent = false, bool $check_permissions = true, $args = [] ){
405405
$post_types = self::get_post_types();
406406
if ( !in_array( $post_type, $post_types ) ){
407407
return new WP_Error( __FUNCTION__, 'Post type does not exist', [ 'status' => 403 ] );
@@ -425,6 +425,15 @@ public static function update_post( string $post_type, int $post_id, array $fiel
425425
return new WP_Error( __FUNCTION__, 'post does not exist', [ 'status' => 404 ] );
426426
}
427427

428+
/**
429+
* If field overwrite has been disabled for existing fields, then ensure
430+
* to have them removed from importing fields.
431+
*/
432+
433+
if ( isset( $args['do_not_overwrite_existing_fields'] ) && $args['do_not_overwrite_existing_fields'] ) {
434+
$fields = apply_filters( 'dt_ignore_duplicated_post_fields', [], $fields, $post_type, $post_id );
435+
}
436+
428437
$existing_post = self::get_post( $post_type, $post_id, false, false );
429438
//get extra fields and defaults
430439
$fields = apply_filters( 'dt_post_update_fields', $fields, $post_type, $post_id, $existing_post );

tests/dt-posts/dt-posts/unit-test-create-post.php

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,4 +170,107 @@ public function test_custom_number_field_min_max_error() {
170170
$contact4 = DT_Posts::create_post( 'contacts', [ 'name' => 'one', 'number_test' => '' ], true, false );
171171
$this->assertNotWPError( $contact4 );
172172
}
173+
174+
/**
175+
* @testdox do_not_overwrite_existing_fields: create with duplicate detection
176+
*/
177+
public function test_do_not_overwrite_existing_fields_create() {
178+
// Create initial contact
179+
$initial_contact = DT_Posts::create_post('contacts', [
180+
'name' => 'John Doe',
181+
'contact_phone' => [ 'values' => [ [ 'value' => '123-456-7890' ] ] ],
182+
'overall_status' => 'active',
183+
'nickname' => 'Johnny'
184+
], true, false);
185+
$this->assertNotWPError( $initial_contact );
186+
187+
// Try to create duplicate with do_not_overwrite_existing_fields = true
188+
$duplicate_fields = [
189+
'name' => 'John Doe',
190+
'contact_phone' => [ 'values' => [ [ 'value' => '123-456-7890' ] ] ],
191+
'overall_status' => 'paused', // Different value
192+
'nickname' => 'John', // Different value
193+
'contact_email' => [ 'values' => [ [ 'value' => 'john@example.com' ] ] ] // New field
194+
];
195+
196+
$result = DT_Posts::create_post('contacts', $duplicate_fields, true, false, [
197+
'check_for_duplicates' => [ 'contact_phone' ],
198+
'do_not_overwrite_existing_fields' => true
199+
]);
200+
201+
$this->assertNotWPError( $result );
202+
// Should still only have one contact_phone entry.
203+
$this->assertSame( 1, count( $result['contact_phone'] ) );
204+
// Should update to new values, as they are different.
205+
$this->assertSame( 'paused', $result['overall_status']['key'] );
206+
$this->assertSame( 'John', $result['nickname'] );
207+
// Should add new fields.
208+
$this->assertSame( 'john@example.com', $result['contact_email'][0]['value'] );
209+
}
210+
211+
/**
212+
* @testdox do_not_overwrite_existing_fields: create with overwrite enabled
213+
*/
214+
public function test_overwrite_existing_fields_create() {
215+
// Create initial contact
216+
$initial_contact = DT_Posts::create_post('contacts', [
217+
'name' => 'Jane Doe',
218+
'contact_phone' => [ 'values' => [ [ 'value' => '987-654-3210' ] ] ],
219+
'overall_status' => 'active',
220+
'nickname' => 'Janie'
221+
], true, false);
222+
$this->assertNotWPError( $initial_contact );
223+
224+
// Try to create duplicate with do_not_overwrite_existing_fields = false
225+
$duplicate_fields = [
226+
'name' => 'Jane Doe',
227+
'contact_phone' => [ 'values' => [ [ 'value' => '987-654-3210' ] ] ],
228+
'overall_status' => 'paused', // Different value
229+
'nickname' => 'Jane', // Different value
230+
'contact_email' => [ 'values' => [ [ 'value' => 'jane@example.com' ] ] ] // New field
231+
];
232+
233+
$result = DT_Posts::create_post('contacts', $duplicate_fields, true, false, [
234+
'check_for_duplicates' => [ 'contact_phone' ],
235+
'do_not_overwrite_existing_fields' => false
236+
]);
237+
238+
$this->assertNotWPError( $result );
239+
// Should update existing fields with new values
240+
$this->assertSame( 'paused', $result['overall_status']['key'] );
241+
$this->assertSame( 'Jane', $result['nickname'] );
242+
// Should add new fields
243+
$this->assertSame( 'jane@example.com', $result['contact_email'][0]['value'] );
244+
}
245+
246+
/**
247+
* @testdox do_not_overwrite_existing_fields: multi-select fields
248+
*/
249+
public function test_do_not_overwrite_multi_select_fields_create() {
250+
// Create initial contact with tags
251+
$initial_contact = DT_Posts::create_post('contacts', [
252+
'name' => 'Multi Test',
253+
'contact_phone' => [ 'values' => [ [ 'value' => '555-0001' ] ] ],
254+
'tags' => [ 'values' => [ [ 'value' => 'existing_tag' ] ] ]
255+
], true, false);
256+
$this->assertNotWPError( $initial_contact );
257+
258+
// Try to create duplicate with additional tags
259+
$duplicate_fields = [
260+
'name' => 'Multi Test',
261+
'contact_phone' => [ 'values' => [ [ 'value' => '555-0001' ] ] ],
262+
'tags' => [ 'values' => [ [ 'value' => 'existing_tag' ], [ 'value' => 'new_tag' ] ] ]
263+
];
264+
265+
$result = DT_Posts::create_post('contacts', $duplicate_fields, true, false, [
266+
'check_for_duplicates' => [ 'contact_phone' ],
267+
'do_not_overwrite_existing_fields' => true
268+
]);
269+
270+
$this->assertNotWPError( $result );
271+
// Should only add new tags, not duplicate existing ones
272+
$this->assertContains( 'existing_tag', $result['tags'] );
273+
$this->assertContains( 'new_tag', $result['tags'] );
274+
$this->assertSame( 2, count( $result['tags'] ) );
275+
}
173276
}

tests/dt-posts/dt-posts/unit-test-update-post.php

Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,4 +192,153 @@ public function test_dt_private_fields(){
192192
$this->assertArrayNotHasKey( 'tags_test_private', $contact2 );
193193
$this->assertArrayNotHasKey( 'number_test_private', $contact2 );
194194
}
195+
196+
/**
197+
* @testdox do_not_overwrite_existing_fields: update with protection enabled
198+
*/
199+
public function test_do_not_overwrite_existing_fields_update() {
200+
// Create a contact with initial values
201+
$contact = DT_Posts::create_post('contacts', [
202+
'name' => 'Update Test',
203+
'overall_status' => 'active',
204+
'nickname' => 'Original Nick',
205+
'contact_phone' => [ 'values' => [ [ 'value' => '111-222-3333' ] ] ]
206+
], true, false);
207+
$this->assertNotWPError( $contact );
208+
209+
// Update with do_not_overwrite_existing_fields = true
210+
$update_fields = [
211+
'overall_status' => 'paused', // Try to change existing field
212+
'nickname' => 'New Nick', // Try to change existing field
213+
'contact_email' => [ 'values' => [ [ 'value' => 'test@example.com' ] ] ] // Add new field
214+
];
215+
216+
$result = DT_Posts::update_post('contacts', $contact['ID'], $update_fields, true, false, [
217+
'do_not_overwrite_existing_fields' => true
218+
]);
219+
220+
$this->assertNotWPError( $result );
221+
// Should still only have one contact_phone entry.
222+
$this->assertSame( 1, count( $result['contact_phone'] ) );
223+
// Should update to new values, as they are different.
224+
$this->assertSame( 'paused', $result['overall_status']['key'] );
225+
$this->assertSame( 'New Nick', $result['nickname'] );
226+
// Should add new fields
227+
$this->assertSame( 'test@example.com', $result['contact_email'][0]['value'] );
228+
}
229+
230+
/**
231+
* @testdox do_not_overwrite_existing_fields: update with protection disabled
232+
*/
233+
public function test_overwrite_existing_fields_update() {
234+
// Create a contact with initial values
235+
$contact = DT_Posts::create_post('contacts', [
236+
'name' => 'Overwrite Test',
237+
'overall_status' => 'active',
238+
'nickname' => 'Original Nick'
239+
], true, false);
240+
$this->assertNotWPError( $contact );
241+
242+
// Update with do_not_overwrite_existing_fields = false (default behavior)
243+
$update_fields = [
244+
'overall_status' => 'paused',
245+
'nickname' => 'New Nick',
246+
'contact_email' => [ 'values' => [ [ 'value' => 'overwrite@example.com' ] ] ]
247+
];
248+
249+
$result = DT_Posts::update_post('contacts', $contact['ID'], $update_fields, true, false, [
250+
'do_not_overwrite_existing_fields' => false
251+
]);
252+
253+
$this->assertNotWPError( $result );
254+
// Should update existing fields with new values
255+
$this->assertSame( 'paused', $result['overall_status']['key'] );
256+
$this->assertSame( 'New Nick', $result['nickname'] );
257+
// Should add new fields
258+
$this->assertSame( 'overwrite@example.com', $result['contact_email'][0]['value'] );
259+
}
260+
261+
/**
262+
* @testdox do_not_overwrite_existing_fields: empty vs non-empty fields
263+
*/
264+
public function test_do_not_overwrite_empty_fields_update() {
265+
// Create a contact with some empty fields
266+
$contact = DT_Posts::create_post('contacts', [
267+
'name' => 'Empty Field Test',
268+
'overall_status' => 'active'
269+
// nickname is not set (empty)
270+
], true, false);
271+
$this->assertNotWPError( $contact );
272+
273+
// Update with do_not_overwrite_existing_fields = true
274+
$update_fields = [
275+
'overall_status' => 'paused', // Try to change existing field
276+
'nickname' => 'Should Be Added' // Add to empty field
277+
];
278+
279+
$result = DT_Posts::update_post('contacts', $contact['ID'], $update_fields, true, false, [
280+
'do_not_overwrite_existing_fields' => true
281+
]);
282+
283+
$this->assertNotWPError( $result );
284+
// Should update to new values, as they are different and not duplicates.
285+
$this->assertSame( 'paused', $result['overall_status']['key'] );
286+
// Should add value to empty field
287+
$this->assertSame( 'Should Be Added', $result['nickname'] );
288+
}
289+
290+
/**
291+
* @testdox do_not_overwrite_existing_fields: communication channel fields
292+
*/
293+
public function test_do_not_overwrite_communication_channels_update() {
294+
// Create a contact with phone number
295+
$contact = DT_Posts::create_post('contacts', [
296+
'name' => 'Communication Test',
297+
'contact_phone' => [ 'values' => [ [ 'value' => '444-555-6666' ] ] ]
298+
], true, false);
299+
$this->assertNotWPError( $contact );
300+
301+
// Update with additional phone and email
302+
$update_fields = [
303+
'contact_phone' => [ 'values' => [ [ 'value' => '444-555-6666' ], [ 'value' => '777-888-9999' ] ] ],
304+
'contact_email' => [ 'values' => [ [ 'value' => 'comm@example.com' ] ] ]
305+
];
306+
307+
$result = DT_Posts::update_post('contacts', $contact['ID'], $update_fields, true, false, [
308+
'do_not_overwrite_existing_fields' => true
309+
]);
310+
311+
$this->assertNotWPError( $result );
312+
// Should keep existing phone and add new one
313+
$phone_values = array_column( $result['contact_phone'], 'value' );
314+
$this->assertContains( '444-555-6666', $phone_values );
315+
$this->assertContains( '777-888-9999', $phone_values );
316+
// Should add new email
317+
$this->assertSame( 'comm@example.com', $result['contact_email'][0]['value'] );
318+
}
319+
320+
/**
321+
* @testdox do_not_overwrite_existing_fields: date fields
322+
*/
323+
public function test_do_not_overwrite_date_fields_update() {
324+
// Create a contact with baptism date
325+
$contact = DT_Posts::create_post('contacts', [
326+
'name' => 'Date Test',
327+
'baptism_date' => '2020-01-01'
328+
], true, false);
329+
$this->assertNotWPError( $contact );
330+
331+
// Try to update baptism date
332+
$update_fields = [
333+
'baptism_date' => '2023-12-25'
334+
];
335+
336+
$result = DT_Posts::update_post('contacts', $contact['ID'], $update_fields, true, false, [
337+
'do_not_overwrite_existing_fields' => true
338+
]);
339+
340+
$this->assertNotWPError( $result );
341+
// Should update to new values, as they are different and not duplicates.
342+
$this->assertSame( '2023-12-25', $result['baptism_date']['formatted'] );
343+
}
195344
}

0 commit comments

Comments
 (0)