Skip to content

Commit

Permalink
Merge 8188ba8 into 6996066
Browse files Browse the repository at this point in the history
  • Loading branch information
DivineOmega committed Mar 21, 2020
2 parents 6996066 + 8188ba8 commit e0ef5d4
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 90 deletions.
74 changes: 52 additions & 22 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -152,65 +152,95 @@ $migrator->setSource($pdoSource)

This migration will move data from the source `name` field into the destination `full_name` field, while still moving the `id` and `email` fields normally.

### Modifying data items during migration
### Transforming data rows during migration

The following example shows how you can use UXDM to modify items of data during the migration process.
Sometimes the data you want to move from source to destination needs transforming. This can be
changing existing items of data, adding new data items, or removing items you do not need.

UXDM allows you to create one or more transformer objects, and add them to the migration.
See the following examples of how to use transformers to manipulate your data.

#### Changing existing data items

This example shows how you can transform existing data items during migration.

```php
class NameCaseTransformer implements TransformerInterface
{
public function transform(DataRow $dataRow): void
{
$nameDataItem = $dataRow->getDataItemByFieldName('name');
$nameDataItem->value = ucwords(strtolower($nameDataItem->value));
}
}

$migrator = new Migrator;
$migrator->setSource($pdoSource)
->setDestination($pdoDestination)
->setFieldsToMigrate(['id', 'email', 'name'])
->setKeyFields(['id'])
->setDataItemManipulator(function($dataItem) {
if ($dataItem->fieldName=='name') {
$dataItem->value = strtoupper($dataItem->value);
}
})
->addTransformer(new NameCaseTransformer())
->withProgressBar()
->migrate();
```

This migration will move user data between two databases. However, it will also convert the value in the `name` field to uppercase.

### Modifying data rows during migration
This migration will ensure that all names fields have consistent case.

#### Adding data items

This examples shows how UXDM can modify each row of data while the migration is taking place.
This example shows how you can add new data items while the migration is taking place.

```php
class AddRandomNumberTransformer implements TransformerInterface
{
public function transform(DataRow &$dataRow): void
{
$dataRow->addDataItem(new DataItem('random_number', rand(1,1000)));
}
}

$migrator = new Migrator;
$migrator->setSource($pdoSource)
->setDestination($pdoDestination)
->setFieldsToMigrate(['id', 'email', 'name'])
->setKeyFields(['id'])
->setDataRowManipulator(function($dataRow) {
$dataRow->addDataItem(new DataItem('random_number', rand(1,1000)));
})
->addTransformer(new AddRandomNumberTransformer())
->withProgressBar()
->migrate();
```

This migration will add a random number into a field called `random_number` for each row of data. This will then be migrated to the destination database along with the other fields.
This migration will add a random number into a field called `random_number` for each row of data.
This will then be migrated to the destination database along with the other fields.

#### Removing data items

This example demonstrates how data items can be removed from a data row. You may wish to do this if you want to use its value, but not actually migrate it to the destination.
This example demonstrates how data items can be removed from a data row.
You may wish to do this if you want to use its value, but not actually
migrate it to the destination.

```php
class EmailToHashTransformer implements TransformerInterface
{
public function transform(DataRow $dataRow): void
{
$emailDataItem = $dataRow->getDataItemByFieldName('email');
$dataRow->addDataItem(new DataItem('email_hash', md5($emailDataItem->value)));
$dataRow->removeDataItem($emailDataItem);
}
}

$migrator = new Migrator;
$migrator->setSource($pdoSource)
->setDestination($pdoDestination)
->setFieldsToMigrate(['id', 'email', 'name'])
->setKeyFields(['id'])
->setDataRowManipulator(function($dataRow) {
$emailDataItem = $dataRow->getDataItemByFieldName('email');
$dataRow->addDataItem(new DataItem('email_hash', md5($emailDataItem->value)));
$dataRow->removeDataItem($emailDataItem);
})
->addTransformer(new EmailToHashTransformer())
->withProgressBar()
->migrate();
```

This migration gets the data from the `email` field in the source, creates a new `email_hash` data item which contains an md5 of the email address, and then removes the original `email` data item. This new `email_hash` will then be migrated to the destination database along with the other fields, excluding the removed `email` field.
This migration gets the data from the `email` field in the source, creates a
new `email_hash` data item which contains an md5 of the email address, and then
removes the original `email` data item. This new `email_hash` will then be
migrated to the destination database along with the other fields, excluding
the removed `email` field.
10 changes: 10 additions & 0 deletions src/Interfaces/TransformerInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php

namespace DivineOmega\uxdm\Interfaces;

use DivineOmega\uxdm\Objects\DataRow;

interface TransformerInterface
{
public function transform(DataRow &$dataRow): void;
}
13 changes: 1 addition & 12 deletions src/Objects/DataRow.php
Original file line number Diff line number Diff line change
Expand Up @@ -62,15 +62,11 @@ public function getKeyDataItems()
return $keyDataItems;
}

public function prepare(array $validationRules, array $keyFields, array $fieldMap, callable $dataItemManipulator)
public function prepare(array $validationRules, array $keyFields, array $fieldMap)
{
$this->validate($validationRules);
$this->setKeyFields($keyFields);
$this->mapFields($fieldMap);

if ($dataItemManipulator !== null) {
$this->callDataItemManipulator($dataItemManipulator);
}
}

public function validate(array $validationRules)
Expand Down Expand Up @@ -107,11 +103,4 @@ private function mapFields(array $fieldMap)
}
}
}

private function callDataItemManipulator(callable $dataItemManipulator)
{
foreach ($this->dataItems as $key => $dataItem) {
$dataItemManipulator($dataItem);
}
}
}
72 changes: 16 additions & 56 deletions src/Objects/Migrator.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use DivineOmega\CliProgressBar\ProgressBar;
use DivineOmega\uxdm\Interfaces\DestinationInterface;
use DivineOmega\uxdm\Interfaces\SourceInterface;
use DivineOmega\uxdm\Interfaces\TransformerInterface;
use DivineOmega\uxdm\Objects\Exceptions\MissingFieldToMigrateException;
use DivineOmega\uxdm\Objects\Exceptions\NoDestinationException;
use DivineOmega\uxdm\Objects\Exceptions\NoSourceException;
Expand All @@ -20,16 +21,14 @@ class Migrator
private $fieldsToMigrate = [];
private $keyFields = [];
private $fieldMap = [];
private $dataRowManipulator = null;
private $dataItemManipulator = null;
private $skipIfTrueCheck = null;
private $validationRules = [];
private $sourceCachePool;
private $sourceCacheKey;
private $sourceCacheExpiresAfter;
private $showProgressBar = false;
private $validateBeforeMigrating = false;
private $progressBar = null;
private $transformers;

/**
* Set the source object to migrate data from.
Expand Down Expand Up @@ -137,49 +136,17 @@ public function setFieldMap(array $fieldMap)
}

/**
* Set the data item manipulator.
* Adds a data row transformer.
*
* The data item manipulator is a function that is ran on every data item of every data row. It can be used to
* manipulate the values of data items during the migration process.
*
* Example that changes all name fields to be uppercase:
*
* function(DataItem $dataItem) {
* if ($dataItem->fieldName === 'name') {
* $dataItem->value = strtoupper($dataItem->value);
* }
* }
*
* @param callable $dataItemManipulator
*
* @return $this
*/
public function setDataItemManipulator(callable $dataItemManipulator)
{
$this->dataItemManipulator = $dataItemManipulator;

return $this;
}

/**
* Set the data row manipulator.
*
* The data row manipulator is a function that is ran on every data row. It can be used to manipulate the values of
* data items, add data items or remove data items, during the migration process.
*
* Example that adds a `random_number` data item to each data row:
*
* function(DataRow $dataRow) {
* $dataRow->addDataItem(new DataItem('random_number', rand(1,100));
* }
*
* @param callable $dataRowManipulator
* A transformer is an class which modifies a data row retrieved from the source, before it is
* transferred to the destination.
*
* @param TransformerInterface $transformer
* @return $this
*/
public function setDataRowManipulator(callable $dataRowManipulator)
public function addTransformer(TransformerInterface $transformer)
{
$this->dataRowManipulator = $dataRowManipulator;
$this->transformers[] = $transformer;

return $this;
}
Expand Down Expand Up @@ -394,7 +361,7 @@ public function migrate(): void
}

$this->prepareDataRows($dataRows);
$this->manipulateDataRows($dataRows);
$this->transformDataRows($dataRows);
$this->unsetDataRowsToSkip($dataRows);

foreach ($this->destinationContainers as $destinationContainer) {
Expand Down Expand Up @@ -425,33 +392,26 @@ public function migrate(): void
*/
private function prepareDataRows(&$dataRows): void
{
$nullDataItemManipulation = function () {
};

$dataItemManipulator = $this->dataItemManipulator;

foreach ($dataRows as $key => $dataRow) {
$dataRow->prepare(
$this->validationRules,
$this->keyFields,
$this->fieldMap,
$dataItemManipulator ? $dataItemManipulator : $nullDataItemManipulation
$this->fieldMap
);
}
}

/**
* Manipulates an array of data rows, by calling the specified data row manipulator function for each data row.
* Transforms an array of data rows, by passing each data row to each previously added transformer.
*
* @param array $dataRows
*/
private function manipulateDataRows(array &$dataRows): void
private function transformDataRows(array &$dataRows): void
{
$dataRowManipulator = $this->dataRowManipulator;

if (is_callable($dataRowManipulator)) {
foreach ($dataRows as $dataRow) {
$dataRowManipulator($dataRow);
foreach ($dataRows as $dataRow) {
foreach ($this->transformers as $transformer) {
/** @var TransformerInterface $transformer */
$dataRow = $transformer->transform($dataRow);
}
}
}
Expand Down

0 comments on commit e0ef5d4

Please sign in to comment.