diff --git a/src/Sync/SyncResult.php b/src/Sync/SyncResult.php new file mode 100644 index 0000000..01d9790 --- /dev/null +++ b/src/Sync/SyncResult.php @@ -0,0 +1,116 @@ + */ + private array $errors; + + /** + * @param array $errors Error messages. + */ + private function __construct( bool $successful, int $created, int $updated, int $skipped, int $conflicts, array $errors ) { + $this->successful = $successful; + $this->created = max( 0, $created ); + $this->updated = max( 0, $updated ); + $this->skipped = max( 0, $skipped ); + $this->conflicts = max( 0, $conflicts ); + $this->errors = array_values( array_map( 'strval', $errors ) ); + } + + /** + * @param array $counts Result counts. + */ + public static function success( array $counts = array() ): self { + return new self( + true, + (int) ( $counts['created'] ?? 0 ), + (int) ( $counts['updated'] ?? 0 ), + (int) ( $counts['skipped'] ?? 0 ), + (int) ( $counts['conflicts'] ?? 0 ), + array() + ); + } + + /** + * @param array $errors Error messages. + */ + public static function failure( array $errors ): self { + return new self( false, 0, 0, 0, 0, $errors ); + } + + /** + * @param array $results Results to merge. + */ + public static function merge( array $results ): self { + $successful = true; + $created = 0; + $updated = 0; + $skipped = 0; + $conflicts = 0; + $errors = array(); + + foreach ( $results as $result ) { + $successful = $successful && $result->isSuccessful(); + $created += $result->created(); + $updated += $result->updated(); + $skipped += $result->skipped(); + $conflicts += $result->conflicts(); + $errors = array_merge( $errors, $result->errors() ); + } + + return new self( $successful, $created, $updated, $skipped, $conflicts, $errors ); + } + + public function isSuccessful(): bool { + return $this->successful; + } + + public function created(): int { + return $this->created; + } + + public function updated(): int { + return $this->updated; + } + + public function skipped(): int { + return $this->skipped; + } + + public function conflicts(): int { + return $this->conflicts; + } + + /** + * @return array + */ + public function errors(): array { + return $this->errors; + } + + /** + * @return array + */ + public function toArray(): array { + return array( + 'successful' => $this->successful, + 'created' => $this->created, + 'updated' => $this->updated, + 'skipped' => $this->skipped, + 'conflicts' => $this->conflicts, + 'errors' => $this->errors, + ); + } +} diff --git a/tests/Unit/Sync/SyncResultTest.php b/tests/Unit/Sync/SyncResultTest.php new file mode 100644 index 0000000..48c3511 --- /dev/null +++ b/tests/Unit/Sync/SyncResultTest.php @@ -0,0 +1,72 @@ + 2, + 'updated' => 3, + 'skipped' => 1, + 'conflicts' => 1, + ) + ); + + self::assertTrue( $result->isSuccessful() ); + self::assertSame( 2, $result->created() ); + self::assertSame( 3, $result->updated() ); + self::assertSame( 1, $result->skipped() ); + self::assertSame( 1, $result->conflicts() ); + self::assertSame( array(), $result->errors() ); + self::assertSame( + array( + 'successful' => true, + 'created' => 2, + 'updated' => 3, + 'skipped' => 1, + 'conflicts' => 1, + 'errors' => array(), + ), + $result->toArray() + ); + } + + public function test_it_tracks_failed_results(): void { + $result = SyncResult::failure( array( 'posts import failed.' ) ); + + self::assertFalse( $result->isSuccessful() ); + self::assertSame( array( 'posts import failed.' ), $result->errors() ); + } + + public function test_it_merges_multiple_results(): void { + $result = SyncResult::merge( + array( + SyncResult::success( array( 'created' => 1 ) ), + SyncResult::success( + array( + 'updated' => 2, + 'skipped' => 1, + 'conflicts' => 1, + ) + ), + SyncResult::failure( array( 'terms import failed.' ) ), + ) + ); + + self::assertFalse( $result->isSuccessful() ); + self::assertSame( 1, $result->created() ); + self::assertSame( 2, $result->updated() ); + self::assertSame( 1, $result->skipped() ); + self::assertSame( 1, $result->conflicts() ); + self::assertSame( array( 'terms import failed.' ), $result->errors() ); + } +}