Skip to content

Commit

Permalink
Allow all data rows to be validated before migrating
Browse files Browse the repository at this point in the history
  • Loading branch information
Jordan Hall committed Jan 27, 2020
1 parent 6d413f9 commit a2ca6bf
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 5 deletions.
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,8 @@ This migration will move the `id`, `email` and `name` fields from the the `users
### Source data validation

You can use UXDM to validate the source data. If validation fails part way through a migration, the migration will
halt and a `ValidationException` will be thrown.
halt and a `ValidationException` will be thrown. However, if `->validateBeforeMigrating()` is called, all data rows
will be preemptively validated before the migration begins.

The code below shows how to validate various fields.

Expand All @@ -119,6 +120,7 @@ $migrator->setSource($pdoSource)
'email' => [new Required(), new IsString(), new IsEmail()],
'name' => [new Required(), new IsString()],
])
// ->validateBeforeMigrating()
->setKeyFields(['id'])
->withProgressBar()
->migrate();
Expand Down
6 changes: 2 additions & 4 deletions src/Objects/DataRow.php
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ public function prepare(array $validationRules, array $keyFields, array $fieldMa
}
}

private function validate(array $validationRules)
public function validate(array $validationRules)
{
if (!$this->dataItems) {
throw new NoDataItemsInDataRowException('Data row contains no data items. The specified source may be producing an invalid data row.');
Expand All @@ -82,9 +82,7 @@ private function validate(array $validationRules)
if ($validationRules) {
$validator = new Validator($this->toArray(), $validationRules);
if ($validator->fails()) {
$messages = print_r($validator->messages(), true);

throw new ValidationException($messages);
throw new ValidationException($validator->messages(), $this);
}
}
}
Expand Down
31 changes: 31 additions & 0 deletions src/Objects/Exceptions/ValidationException.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,39 @@

namespace DivineOmega\uxdm\Objects\Exceptions;

use DivineOmega\uxdm\Objects\DataRow;
use Exception;

class ValidationException extends Exception
{
private $validationMessages;
private $dataRow;

public function __construct(array $validationMessages, DataRow $dataRow)
{
$this->validationMessages = $validationMessages;
$this->dataRow = $dataRow;

parent::__construct($this->buildExceptionMessage());
}

private function buildExceptionMessage(): string
{
$message = 'Validation exception: '.PHP_EOL;
$message .= print_r($this->validationMessages, true).PHP_EOL;
$message .= 'Data row: '.PHP_EOL;
$message .= print_r($this->dataRow->toArray(), true.PHP_EOL);

return $message;
}

public function getValidationMessages(): array
{
return $this->validationMessages;
}

public function getDataRow(): DataRow
{
return $this->dataRow;
}
}
41 changes: 41 additions & 0 deletions src/Objects/Migrator.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ class Migrator
private $sourceCacheKey;
private $sourceCacheExpiresAfter;
private $showProgressBar = false;
private $validateBeforeMigrating = false;
private $progressBar = null;

/**
* Set the source object to migrate data from.
Expand Down Expand Up @@ -257,6 +259,18 @@ public function withProgressBar()
return $this;
}

/**
* Enables validation of all data rows before the migration begins.
*
* @return $this
*/
public function validateBeforeMigrating()
{
$this->validateBeforeMigrating = true;

return $this;
}

/**
* Retrieves one page of data rows from the source.
*
Expand Down Expand Up @@ -337,6 +351,33 @@ public function migrate(): void
{
$this->sanityCheck();

if ($this->validateBeforeMigrating) {
if ($this->showProgressBar) {
$this->progressBar = new ProgressBar();
$this->progressBar->setMessage('Validating...');
$this->progressBar->setMaxProgress($this->source->countPages() * count($this->destinationContainers));
$this->progressBar->display();
}

for ($page = 1; $page < PHP_INT_MAX; $page++) {
$dataRows = $this->getSourceDataRows($page);

if (!$dataRows) {
break;
}

foreach ($dataRows as $key => $dataRow) {
$dataRow->validate();
}

$this->advanceProgressBar();
}

if ($this->showProgressBar) {
$this->progressBar->complete();
}
}

if ($this->showProgressBar) {
$progressBar = new ProgressBar();
$progressBar->setMaxProgress($this->source->countPages() * count($this->destinationContainers));
Expand Down

0 comments on commit a2ca6bf

Please sign in to comment.