Skip to content

Commit

Permalink
Added second parameter (data) to Copy to replace Walk functionality.
Browse files Browse the repository at this point in the history
Removed Walk strategy.
Updated readme.
  • Loading branch information
Paul committed Jun 12, 2017
1 parent fb31788 commit d111f7a
Show file tree
Hide file tree
Showing 7 changed files with 96 additions and 156 deletions.
85 changes: 19 additions & 66 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,9 @@ Contents
1. [Merge](#merge)
1. [TakeFirst](#takefirst)
1. [ToList](#tolist)
1. [Translate](#translate)
1. [TryCatch](#trycatch)
1. [Type](#type)
1. [Unique](#unique)
1. [Walk](#walk)
1. [Others](#others)
1. [Debug](#debug)
1. [Requirements](#requirements)
Expand Down Expand Up @@ -287,7 +285,7 @@ The following strategies ship with Mapper and provide a suite of commonly used f

#### Fetchers

- [Copy](#copy) – Copies a portion of input data.
- [Copy](#copy) – Copies a portion of input data, or specified data, according to a lookup path.
- [CopyContext](#copycontext) – Copies a portion of context data.
- [CopyKey](#copykey) – Copies the current key.

Expand All @@ -305,29 +303,28 @@ The following strategies ship with Mapper and provide a suite of commonly used f
- [Merge](#merge) – Merges two data sets together giving precedence to the latter if keys collide.
- [TakeFirst](#takefirst) – Takes the first value from a collection one or more times.
- [ToList](#tolist) – Converts data to a single-element list unless it is already a list.
- [Translate](#translate) – Translates a value using a mapping.
- [TryCatch](#trycatch) – Tries the primary strategy and falls back to an expression if an exception is thrown.
- [Type](#type) – Casts data to the specified type.
- [Unique](#unique) – Creates a collection of unique values by removing duplicates.
- [Walk](#walk) – Walks a nested structure to the specified element in the same manner as `Copy`.

#### Others

- [Debug](#debug) – Debugs a mapping by breaking the debugger wherever this strategy is inserted.

### Copy

Copies a portion of the input data according to the specified path. Supports traversing nested arrays.
Copies a portion of input data, or specified data, according to a lookup path. Supports traversing nested arrays.

`Copy` is probably the most common strategy whether used by itself or injected into other strategies.
`Copy` is probably the most common strategy whether used by itself or injected into other strategies. Since both its *path* and *data* parameters can be mapped expressions it is highly versatile and can be combined with other strategies, or even itself, to produce powerful expressions.

#### Signature

```php
Copy(Strategy|Mapping|array|mixed $path)
Copy(Strategy|Mapping|array|mixed $path, Strategy|Mapping|array|mixed $data)
```

1. `$path` – Array of path components, string of `->`-delimited path components or a strategy or mapping resolving to such an expression.
2. `$data` – Optional. Array data or an expression that resolves to an array to be copied instead of input data.

#### Example

Expand All @@ -351,9 +348,22 @@ $data = [

> 123
#### Specified data example

When data is specified in the second parameter it is used instead of the data sent from `Mapper`.

```php
(new Mapper)->map(
['foo' => 'bar'],
new Copy('foo', ['foo' => 'baz'])
);
```

> 'baz'
#### Path resolver example

Since the path can be derived from other strategies we could nest `Copy` instances to look up values referenced by other keys.
Since the path can be derived from other strategies we can nest `Copy` instances to look up values referenced by other keys.

```php
(new Mapper)->map(
Expand Down Expand Up @@ -772,33 +782,6 @@ ToList(Strategy|Mapping|array|mixed $expression)

> ['bar']
### Translate

Translates a value using a mapping. The mapping may derived from any valid expression.

#### Signature

```php
Translate(Strategy $value, Strategy|Mapping|array|mixed $mapping)
```

1. `$value` – Value used to match against an entry in the mapping.
2. `$mapping` – Mapping that specifies what the value may be translated to.

#### Example

```php
(new Mapper)->map(
['foo' => 'foo'],
new Translate(
new Copy('foo'),
['foo' => 'bar']
)
);
```

> 'bar'
### TryCatch

Tries the primary strategy and falls back to an expression if an exception is thrown. The thrown exception is passed to the specified exception handler. The handler should throw an exception if it does not expect the exception type it receives.
Expand Down Expand Up @@ -882,36 +865,6 @@ Unique(Strategy|Mapping|array|mixed $collection)

> [1, 2, 3, 4, 5]
### Walk

Walks a nested structure to the specified element in the same manner as [`Copy`](#copy).

#### Signature

```php
Walk(Strategy|Mapping|array|mixed $expression, Strategy|Mapping|array|mixed $path)
```

1. `$expression` – Expression to walk.
2. `$path` – Array of path components, string of `->`-delimited path components or a strategy or mapping resolving to such an expression.

#### Example

```php
(new Mapper)->map(
[
'foo' => [
'bar' => [
'baz' => 123,
],
],
],
new Walk(new Copy('foo'), 'bar->baz')
)
```

> 123
### Debug

Debugs a mapping by breaking the debugger wherever this strategy is inserted. The specified expression will be mapped immediately before triggering the breakpoint. The debugger should see the current data, context and mapped expression.
Expand Down
29 changes: 28 additions & 1 deletion src/Strategy/Copy.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,32 @@
namespace ScriptFUSION\Mapper\Strategy;

use ScriptFUSION\ArrayWalker\ArrayWalker;
use ScriptFUSION\Mapper\Mapping;

/**
* Copies a portion of input data.
* Copies a portion of input data, or specified data, according to a lookup path.
*/
class Copy extends Delegate
{
const PATH_SEPARATOR = '->';

private $data;

/**
* Initializes this instance with the specified path. If data is specified it is always used instead of input data.
*
* @param Strategy|Mapping|array|mixed $path Array of path components, string of `->`-delimited path components or
* a strategy or mapping resolving to such an expression.
* @param Strategy|Mapping|array|mixed $data Optional. Array data or an expression that resolves to an array to be
* copied instead of input data.
*/
public function __construct($path, $data = null)
{
parent::__construct($path);

$this->data = $data;
}

/**
* @param mixed $record
* @param mixed $context
Expand All @@ -18,14 +36,23 @@ class Copy extends Delegate
*/
public function __invoke($record, $context = null)
{
// It is typically an error for record not to be an array but we prefer to avoid throwing exceptions.
if (!is_array($record)) {
return null;
}

// Resolve the path expression. Path will always be an array after this block.
if (!is_array($path = parent::__invoke($record, $context))) {
// If it's not an array treat it as a delimited string; implicitly casts other scalar types.
$path = explode(self::PATH_SEPARATOR, $path);
}

// Overwrite record with resolved data expression if set and ensure it is an array.
if ($this->data !== null && !is_array($record = $this->delegate($this->data, $record, $context))) {
return null;
}

// Walk path unless it is empty.
return $path ? ArrayWalker::walk($record, $path) : null;
}
}
31 changes: 0 additions & 31 deletions src/Strategy/Walk.php

This file was deleted.

30 changes: 11 additions & 19 deletions test/Functional/DocumentationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,9 @@
use ScriptFUSION\Mapper\Strategy\Merge;
use ScriptFUSION\Mapper\Strategy\TakeFirst;
use ScriptFUSION\Mapper\Strategy\ToList;
use ScriptFUSION\Mapper\Strategy\Translate;
use ScriptFUSION\Mapper\Strategy\TryCatch;
use ScriptFUSION\Mapper\Strategy\Type;
use ScriptFUSION\Mapper\Strategy\Unique;
use ScriptFUSION\Mapper\Strategy\Walk;
use ScriptFUSIONTest\Fixture\BarBucketAddressToAddresesMapping;
use ScriptFUSIONTest\Fixture\FooBookAddressToAddresesMapping;
use ScriptFUSIONTest\Fixture\FooToBarMapping;
Expand Down Expand Up @@ -100,6 +98,17 @@ public function testCopy()
self::assertSame($bar, (new Mapper)->map($data, new Copy(['foo', 'bar'])));
}

public function testSpecifiedDataCopy()
{
self::assertSame(
'baz',
(new Mapper)->map(
['foo' => 'bar'],
new Copy('foo', ['foo' => 'baz'])
)
);
}

public function testNestedCopy()
{
self::assertSame(
Expand Down Expand Up @@ -355,21 +364,4 @@ public function testUnique()
)
);
}

public function testWalk()
{
self::assertSame(
$baz = 123,
(new Mapper)->map(
[
'foo' => [
'bar' => [
'baz' => $baz,
],
],
],
new Walk(new Copy('foo'), 'bar->baz')
)
);
}
}
24 changes: 24 additions & 0 deletions test/Integration/Mapper/Strategy/CopyTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php
namespace ScriptFUSIONTest\Integration\Mapper\Strategy;

use ScriptFUSION\Mapper\Mapper;
use ScriptFUSION\Mapper\Strategy\Copy;

final class CopyTest extends \PHPUnit_Framework_TestCase
{
public function testWalkFixedPath()
{
$copy = (new Copy('foo->bar', ['foo' => ['bar' => 'baz']]))
->setMapper(new Mapper);

self::assertSame('baz', $copy([]));
}

public function testWalkStrategyPath()
{
$copy = (new Copy(new Copy('foo'), ['bar' => 'baz']))
->setMapper(new Mapper);

self::assertSame('baz', $copy(['foo' => 'bar']));
}
}
25 changes: 0 additions & 25 deletions test/Integration/Mapper/Strategy/WalkTest.php

This file was deleted.

28 changes: 14 additions & 14 deletions test/Unit/Mapper/Strategy/CopyTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,6 @@ final class CopyTest extends \PHPUnit_Framework_TestCase
{
use MockeryPHPUnitIntegration;

public function testNullRecord()
{
$copy = self::createStrategy(0);

self::assertNull($copy(null));
}

public function testNullPath()
{
$copy = self::createStrategy(null);

self::assertNull($copy([]));
}

public function testFalsyPathComponentString()
{
$copy = self::createStrategy('0');
Expand All @@ -41,6 +27,20 @@ public function testFalsyPathComponentArray()
self::assertSame('bar', $copy([['foo', 'bar']]));
}

public function testNullRecord()
{
$copy = self::createStrategy(0);

self::assertNull($copy(null));
}

public function testNullPath()
{
$copy = self::createStrategy(null);

self::assertNull($copy([]));
}

public function testEmptyPathString()
{
$copy = self::createStrategy('');
Expand Down

0 comments on commit d111f7a

Please sign in to comment.