diff --git a/.travis.yml b/.travis.yml index 3bfc224..2582b2c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,14 +11,26 @@ php: - 7.0 - 7.1 +env: + matrix: + - + - DEPENDENCIES=--prefer-lowest + +matrix: + fast_finish: true + +cache: + directories: + - .composer/cache + install: - alias composer=composer\ -n && composer selfupdate - composer validate - - composer --prefer-source install + - composer update $DEPENDENCIES script: - composer test -- --coverage-clover=build/logs/clover.xml after_success: - - composer --prefer-source require satooshi/php-coveralls + - composer require satooshi/php-coveralls - vendor/bin/coveralls -v diff --git a/README.md b/README.md index 84e6572..cb1e875 100644 --- a/README.md +++ b/README.md @@ -35,6 +35,7 @@ Contents 1. [Merge](#merge) 1. [TakeFirst](#takefirst) 1. [ToList](#tolist) + 1. [Translate](#translate) 1. [TryCatch](#trycatch) 1. [Type](#type) 1. [Unique](#unique) @@ -296,6 +297,7 @@ 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. @@ -683,6 +685,33 @@ 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. diff --git a/composer.json b/composer.json index 01f1ba8..16e2a7e 100644 --- a/composer.json +++ b/composer.json @@ -15,8 +15,8 @@ }, "require-dev": { "scriptfusion/static-class": "^1", - "phpunit/phpunit": "^4", - "mockery/mockery": "^0" + "phpunit/phpunit": "^4.8", + "mockery/mockery": "^0.9.4" }, "autoload": { "psr-4": { diff --git a/src/DataType.php b/src/DataType.php index 343a27d..be60995 100644 --- a/src/DataType.php +++ b/src/DataType.php @@ -5,6 +5,13 @@ /** * Specifies a PHP data type. + * + * @method static BOOLEAN() + * @method static INTEGER() + * @method static FLOAT() + * @method static STRING() + * @method static MAP() + * @method static OBJECT() */ final class DataType extends AbstractEnumeration { diff --git a/src/Strategy/Translate.php b/src/Strategy/Translate.php new file mode 100644 index 0000000..f49c8ef --- /dev/null +++ b/src/Strategy/Translate.php @@ -0,0 +1,35 @@ +mapping = $mapping; + } + + public function __invoke($data, $context = null) + { + $value = parent::__invoke($data, $context); + $mapping = $this->delegate($this->mapping, $data, $context); + + if (is_array($mapping) && array_key_exists($value, $mapping)) { + return $mapping[$value]; + } + } +} diff --git a/test/Functional/DocumentationTest.php b/test/Functional/DocumentationTest.php index 61264b1..ec64f34 100644 --- a/test/Functional/DocumentationTest.php +++ b/test/Functional/DocumentationTest.php @@ -16,6 +16,7 @@ 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; @@ -267,6 +268,20 @@ public function testToList() ); } + public function testTranslate() + { + self::assertSame( + 'bar', + (new Mapper)->map( + ['foo' => 'foo'], + new Translate( + new Copy('foo'), + ['foo' => 'bar'] + ) + ) + ); + } + public function testTryCatch() { self::assertSame( diff --git a/test/Integration/Mapper/Strategy/TranslateTest.php b/test/Integration/Mapper/Strategy/TranslateTest.php new file mode 100644 index 0000000..a767808 --- /dev/null +++ b/test/Integration/Mapper/Strategy/TranslateTest.php @@ -0,0 +1,26 @@ + 'bar']))->setMapper(new Mapper); + + self::assertSame('bar', $translate([])); + } + + public function testValueNotFound() + { + $translate = (new Translate(MockFactory::mockStrategy('foo'), ['bar' => 'bar']))->setMapper(new Mapper); + + self::assertNull($translate([])); + } +} diff --git a/test/MockFactory.php b/test/MockFactory.php index d7a29ed..b44c0a5 100644 --- a/test/MockFactory.php +++ b/test/MockFactory.php @@ -3,12 +3,23 @@ use Mockery\MockInterface; use ScriptFUSION\Mapper\Mapper; +use ScriptFUSION\Mapper\Strategy\Strategy; use ScriptFUSION\StaticClass; final class MockFactory { use StaticClass; + /** + * @param mixed $data + * + * @return Strategy|MockInterface + */ + public static function mockStrategy($data) + { + return \Mockery::mock(Strategy::class)->shouldReceive('__invoke')->andReturn($data)->getMock(); + } + /** * @param mixed $data *