diff --git a/README.md b/README.md index a5ebe9b..b048a3e 100644 --- a/README.md +++ b/README.md @@ -11,18 +11,212 @@ composer require shureban/laravel-object-mapper Add the following class to the `providers` array in `config/app.php`: ```php -Shureban\LaravelSearcher\ObjectMapperServiceProvider::class, +Shureban\LaravelObjectMapper\ObjectMapperServiceProvider::class, ``` You can also publish the config file to change implementations (ie. interface to specific class). ```shell -php artisan vendor:publish --provider="Shureban\LaravelSearcher\ObjectMapperServiceProvider" +php artisan vendor:publish --provider="Shureban\LaravelObjectMapper\ObjectMapperServiceProvider" ``` ## How to use -- base types -- class with constructor -- class without countruector -- setters +You have 3 options to use `ObjectMapper` + +### Inheritance + +Your mapped object (dto) must inheritance from `\Shureban\LaravelObjectMapper\MappableObject` + +```php +class User extends MappableObject +{ + public int $id; +} + +$user1 = (new User())->mapFromJson('{"id": 10}'); +$user2 = (new User())->mapFromArray(['id' => 10]); +$user3 = (new User())->mapFromRequest($formRequest); +``` + +### Using trait + +Your mapped object (dto) must use `\Shureban\LaravelObjectMapper\MappableTrait` + +```php +class User +{ + use MappableTrait; + + public int $id; +} + +$user1 = (new User())->mapFromJson('{"id": 10}'); +$user2 = (new User())->mapFromArray(['id' => 10]); +$user3 = (new User())->mapFromRequest($formRequest); +``` + +### Delegate mapping to ObjectMapper + +```php +class User { + public int $id; +} + +$user1 = (new ObjectMapper(new User()))->mapFromJson('{"id": 10}'); +$user2 = (new ObjectMapper(new User()))->mapFromArray(['id' => 10]); +$user3 = (new ObjectMapper(new User()))->mapFromRequest($formRequest); +``` + +## Mappable cases + +Below you will see cases which you can use for mapping data into your object + +### Simple types + +- `mixed` +- `string` +- `bool`, `boolean` +- `int`, `integer` +- `double`, `float` +- `array` +- `object` + +### Box types + +- `Carbon` +- `DateTime` +- `Collection` + +### Custom types + +- `CustomClass` +- `Enum` +- `EloquentModel` + +### Array of types + +That typo of mapping may be realized only via phpDoc notation + +- `int[]` +- `int[][]` +- `DateTime[]` +- `CustomClass[]` + +### Special cases + +#### Constructor + +If your type object has 1 required parameter and value is NOT an array, ObjectMapper will build instance of this type +via constructor call +If your type object has 0 or more than 1 required parameters, it will throw WrongConstructorParametersNumberException +exception + +Correct case: + +```php +class User +{ + public int $id; + + public function __construct(int $id) { + $this->id = $id; + } +} +``` + +Wrong case: + +```php +class User +{ + public int $id; + public string $name; + + public function __construct(int $id, string $name) { + $this->id = $id; + $this->name = $name; + } +} +``` + +#### PhpDoc + +PhpDoc type hinting has much more priority than main type. + +```php +class User +{ + /** + * @var int + */ + public int $id; + /** + * @var DateTime + */ + public $dateOfBirthday; + /** + * @var Address[] + */ + public array $addresses; +} +``` + +#### Setters + +If you want to realize your own logic for setting value, you may place setter method in your mapped object +This setter should start from `set` word and been in camelCase notation. + +```php +class User +{ + public string $id; + public DateTime $dateOfBirthday; + + public function setId(int $id, array $rawData = []): void + { + $this->id = Hash::make($id); + } + + public function setDateOfBirthday(string $dateOfBirthday, array $rawData = []): void + { + $this->dateOfBirthday = new DateTime($dateOfBirthday); + } +} + +$user = (new ObjectMapper(new User()))->mapFromArray(['id' => 10, 'dateOfBirthday' => '1991-01-01']); + +echo $user->id; // $2y$10$XqHrk0oXa7.9AihthdVxW.dd637zj9EhlTJX0eUEKiV61dbs7a7ZO +echo $user->dateOfBirthday->format('Y'); // 1991 +``` + +Some words about second parameter `$rawData`. Value of this parameter depends on method selected for mapping + +- mapFromJson - $rawData will be JSON +- mapFromArray - $rawData will be Array +- mapFromRequest - $rawData will be FormRequest object + +#### Readonly parameters + +Readonly parameters will always be skipped + +```php +class User +{ + public readonly int $id; +} + +$user = (new ObjectMapper(new User()))->mapFromArray(['id' => 10]); + +echo $user->id; // 0 +``` + +## Config rewriting + +In `object_mapper.php` config file have been presented all mappable types classes. You have opportunity to rewrite +mapping flow or realize you own one. + +If you need to create your own type mapping, follow this way: + +- create class inherited from `\Shureban\LaravelObjectMapper\Types\Type` +- place you type into config file in `type -> box` array diff --git a/composer.json b/composer.json index bdaa21b..6c8cec6 100644 --- a/composer.json +++ b/composer.json @@ -17,7 +17,7 @@ } ], "minimum-stability": "dev", - "version": "0.4.0", + "version": "1.0.0", "autoload": { "psr-4": { "Shureban\\LaravelObjectMapper\\": "src/" diff --git a/config/mapper.php b/config/mapper.php deleted file mode 100644 index b625128..0000000 --- a/config/mapper.php +++ /dev/null @@ -1,4 +0,0 @@ - [ + 'simple' => [ + 'string' => StringType::class, + 'float' => FloatType::class, + 'double' => FloatType::class, + 'int' => IntType::class, + 'integer' => IntType::class, + 'bool' => BoolType::class, + 'boolean' => BoolType::class, + 'array' => ArrayType::class, + 'object' => ObjectType::class, + 'mixed' => MixedType::class, + ], + 'box' => [ + DateTime::class => DateTimeType::class, + CarbonSupport::class => CarbonType::class, + Carbon::class => CarbonType::class, + 'Carbon' => CarbonType::class, + Collection::class => CollectionType::class, + 'Collection' => CollectionType::class, + ], + 'other' => [ + 'custom' => CustomType::class, + 'enum' => EnumType::class, + 'model' => ModelType::class, + ], + ], +]; diff --git a/src/ClassExtraInformation.php b/src/ClassExtraInformation.php index 39dac90..22e853d 100644 --- a/src/ClassExtraInformation.php +++ b/src/ClassExtraInformation.php @@ -13,6 +13,9 @@ class ClassExtraInformation private ReflectionClass $class; private string $content = ''; + /** + * @param ReflectionClass $class + */ public function __construct(ReflectionClass $class) { $this->class = $class; @@ -45,11 +48,7 @@ public function getFullObjectUseNamespace(string $objectName): ?string $namespace = sprintf('%s\%s', $this->getNamespace(), $objectName); - if (class_exists($namespace)) { - return $namespace; - } - - return null; + return class_exists($namespace) ? $namespace : null; } /** diff --git a/src/Exceptions/ObjectMapperException.php b/src/Exceptions/ObjectMapperException.php new file mode 100644 index 0000000..536aa84 --- /dev/null +++ b/src/Exceptions/ObjectMapperException.php @@ -0,0 +1,9 @@ +map($data); + } + + /** + * @param string $data + * + * @return $this + */ + public function mapFromJson(string $data): static + { + return (new ObjectMapper($this))->mapFromJson($data); + } + + /** + * @param array $data + * + * @return $this + */ + public function mapFromArray(array $data): static + { + return (new ObjectMapper($this))->mapFromArray($data); + } + + /** + * @param FormRequest $request + * @param bool $onlyValidated + * + * @return $this + */ + public function mapFromRequest(FormRequest $request, bool $onlyValidated = true): static + { + return (new ObjectMapper($this))->mapFromRequest($request, $onlyValidated); + } +} diff --git a/src/ObjectAnalyzer.php b/src/ObjectAnalyzer.php index 02c8267..25a9023 100644 --- a/src/ObjectAnalyzer.php +++ b/src/ObjectAnalyzer.php @@ -3,9 +3,7 @@ namespace Shureban\LaravelObjectMapper; use ReflectionClass; -use ReflectionException; use ReflectionProperty; -use Shureban\LaravelObjectMapper\Exceptions\UnknownPropertyTypeException; class ObjectAnalyzer { @@ -18,8 +16,6 @@ public function __construct(object $result) /** * @return array|Property[] - * @throws UnknownPropertyTypeException - * @throws ReflectionException */ public function getProperties(): array { diff --git a/src/ObjectMapper.php b/src/ObjectMapper.php index b68b224..4252889 100644 --- a/src/ObjectMapper.php +++ b/src/ObjectMapper.php @@ -3,10 +3,9 @@ namespace Shureban\LaravelObjectMapper; use Illuminate\Foundation\Http\FormRequest; -use ReflectionException; use Shureban\LaravelObjectMapper\Attributes\SetterName; +use Shureban\LaravelObjectMapper\Exceptions\ParseJsonException; use Shureban\LaravelObjectMapper\Exceptions\UnknownDataFormatException; -use Shureban\LaravelObjectMapper\Exceptions\UnknownPropertyTypeException; class ObjectMapper { @@ -23,9 +22,8 @@ public function __construct(object $result) /** * @param string|array|FormRequest $data * - * @return object - * @throws ReflectionException - * @throws UnknownPropertyTypeException + * @return mixed + * @throws ParseJsonException */ public function map(string|array|FormRequest $data): object { @@ -38,24 +36,28 @@ public function map(string|array|FormRequest $data): object } /** - * @param string $data + * @param string $json * - * @return object - * @throws ReflectionException - * @throws UnknownPropertyTypeException + * @return mixed + * @throws ParseJsonException */ - public function mapFromJson(string $data): object + public function mapFromJson(string $json): object { - return $this->mapData(json_decode($data, true), $data); + $data = json_decode($json, true); + $error = json_last_error_msg(); + + if (json_last_error() !== JSON_ERROR_NONE) { + throw new ParseJsonException($error); + } + + return $this->mapData($data, $json); } /** * @param array $data * @param string|array|FormRequest $defaultData * - * @return object - * @throws ReflectionException - * @throws UnknownPropertyTypeException + * @return mixed */ private function mapData(array $data, string|array|FormRequest $defaultData): object { @@ -79,6 +81,10 @@ private function mapData(array $data, string|array|FormRequest $defaultData): ob continue; } + if ($property->isReadOnly()) { + continue; + } + $this->result->{$objectPropertyName} = $property->convert($value); } @@ -88,9 +94,7 @@ private function mapData(array $data, string|array|FormRequest $defaultData): ob /** * @param array $data * - * @return object - * @throws UnknownPropertyTypeException - * @throws ReflectionException + * @return mixed */ public function mapFromArray(array $data): object { @@ -101,9 +105,7 @@ public function mapFromArray(array $data): object * @param FormRequest $request * @param bool $onlyValidated * - * @return object - * @throws ReflectionException - * @throws UnknownPropertyTypeException + * @return mixed */ public function mapFromRequest(FormRequest $request, bool $onlyValidated = true): object { diff --git a/src/PhpDoc.php b/src/PhpDoc.php index 1005882..c5d40aa 100644 --- a/src/PhpDoc.php +++ b/src/PhpDoc.php @@ -6,7 +6,6 @@ class PhpDoc { private const PropertyNameRegex = '/var(.*)?\$(?\w+)/'; private const TypeNameRegex = '/var (?[\\a-zA-Z0-9]+)([\[\]]+)? \$?/U'; - private const ArrayOfRegex = '/var [\\a-zA-Z0-9]+([[]]+) \$?/'; private string $phpDoc; @@ -55,7 +54,7 @@ public function getPropertyType(): mixed */ public function isArrayOf(): bool { - return (bool)preg_match(self::ArrayOfRegex, $this->phpDoc); + return $this->arrayNestedLevel() > 0; } /** diff --git a/src/Property.php b/src/Property.php index 888e1b3..86a1cc1 100644 --- a/src/Property.php +++ b/src/Property.php @@ -2,7 +2,6 @@ namespace Shureban\LaravelObjectMapper; -use ReflectionException; use ReflectionProperty; use Shureban\LaravelObjectMapper\Types\Factory; use Shureban\LaravelObjectMapper\Types\Type; @@ -15,8 +14,6 @@ class Property /** * @param ReflectionProperty $property - * - * @throws ReflectionException|Exceptions\UnknownPropertyTypeException */ public function __construct(ReflectionProperty $property) { @@ -59,6 +56,14 @@ public function convert(mixed $value): mixed return $this->type->convert($value); } + /** + * @return bool + */ + public function isReadOnly(): bool + { + return $this->property->isReadOnly(); + } + /** * @return Type */ diff --git a/src/Types/Custom/ArrayOfType.php b/src/Types/ArrayOfType.php similarity index 88% rename from src/Types/Custom/ArrayOfType.php rename to src/Types/ArrayOfType.php index 82442f2..9f1fcb0 100644 --- a/src/Types/Custom/ArrayOfType.php +++ b/src/Types/ArrayOfType.php @@ -1,8 +1,6 @@ customObject = $customObject; + $this->classNamespace = $classNamespace; } /** * @param mixed $value * * @return object + * @throws WrongConstructorParametersNumberException */ public function convert(mixed $value): object { - return (new ObjectMapper($this->customObject))->mapFromArray($value); + $reflection = new ReflectionClass($this->classNamespace); + $constructor = $reflection->getConstructor(); + $emptyConstructor = !is_null($constructor) && $constructor->getNumberOfParameters() === 0; + + if (is_null($constructor) || $emptyConstructor || is_array($value)) { + return (new ObjectMapper(new $this->classNamespace()))->mapFromArray($value); + } + + $tooManyRequiredParameters = $constructor->getNumberOfRequiredParameters() > 1; + + if ($tooManyRequiredParameters) { + throw new WrongConstructorParametersNumberException($this->classNamespace); + } + + return new $this->classNamespace($value); } } diff --git a/src/Types/Custom/ModelType.php b/src/Types/Custom/ModelType.php new file mode 100644 index 0000000..eb1f7fa --- /dev/null +++ b/src/Types/Custom/ModelType.php @@ -0,0 +1,26 @@ +modelNamespace = $modelNamespace; + } + + /** + * @param mixed $value + * + * @return Model + */ + public function convert(mixed $value): Model + { + return call_user_func([$this->modelNamespace, 'find'], $value); + } +} diff --git a/src/Types/CustomTypeFactory.php b/src/Types/CustomTypeFactory.php new file mode 100644 index 0000000..63846de --- /dev/null +++ b/src/Types/CustomTypeFactory.php @@ -0,0 +1,36 @@ +getDocComment()); if (!$property->hasType() && !$phpDoc->hasType()) { - return new MixedType(); + return SimpleTypeFactory::make('mixed'); } $type = $phpDoc->hasType() ? $phpDoc->getPropertyType() : $property->getType()->getName(); - $simpleType = match ($type) { - 'string' => new StringType(), - 'float', 'double' => new FloatType(), - 'int', 'integer' => new IntType(), - 'bool', 'boolean' => new BoolType(), - 'array' => new ArrayType(), - 'object' => new ObjectType(), - default => null, - }; + $simpleType = SimpleTypeFactory::make($type); if ($simpleType !== null) { return $phpDoc->isArrayOf() ? new ArrayOfType($simpleType, $phpDoc->arrayNestedLevel()) : $simpleType; } - $boxType = match ($type) { - DateTime::class => new DateTimeType(), - CarbonSupport::class, Carbon::class, 'Carbon' => new CarbonType(), - Collection::class, 'Collection' => new CollectionType(), - default => null, - }; + $boxType = BoxTypeFactory::make($type); if ($boxType !== null) { return $phpDoc->isArrayOf() ? new ArrayOfType($boxType, $phpDoc->arrayNestedLevel()) : $boxType; } - if (enum_exists($type)) { - $type = new EnumType($type); + $customType = CustomTypeFactory::make($type); - return $phpDoc->isArrayOf() ? new ArrayOfType($type, $phpDoc->arrayNestedLevel()) : $type; + if ($customType !== null) { + return $phpDoc->isArrayOf() ? new ArrayOfType($customType, $phpDoc->arrayNestedLevel()) : $customType; } - if (class_exists($type)) { - $type = new CustomType((new ReflectionClass($type))->newInstanceWithoutConstructor()); + $extraInformation = new ClassExtraInformation($property->getDeclaringClass()); + $namespace = $extraInformation->getFullObjectUseNamespace($type); + $customType = CustomTypeFactory::make($namespace); - return $phpDoc->isArrayOf() ? new ArrayOfType($type, $phpDoc->arrayNestedLevel()) : $type; - } - - $classUses = new ClassExtraInformation($property->getDeclaringClass()); - $namespace = $classUses->getFullObjectUseNamespace($type); - - if (enum_exists($namespace)) { - $type = new EnumType($namespace); - - return $phpDoc->isArrayOf() ? new ArrayOfType($type, $phpDoc->arrayNestedLevel()) : $type; - } - - if (class_exists($namespace)) { - $type = new CustomType((new ReflectionClass($namespace))->newInstanceWithoutConstructor()); - - return $phpDoc->isArrayOf() ? new ArrayOfType($type, $phpDoc->arrayNestedLevel()) : $type; + if ($customType !== null) { + return $phpDoc->isArrayOf() ? new ArrayOfType($customType, $phpDoc->arrayNestedLevel()) : $customType; } throw new UnknownPropertyTypeException($property->getName()); diff --git a/src/Types/SimpleTypeFactory.php b/src/Types/SimpleTypeFactory.php new file mode 100644 index 0000000..9d9140e --- /dev/null +++ b/src/Types/SimpleTypeFactory.php @@ -0,0 +1,18 @@ +assertEquals( + new CustomCorrectOneEmptyTypeParameterConstructorTypeClass(10), + (new ObjectMapper(new CustomTypeWithConstructorClass()))->mapFromJson('{"emptyTypeOne": 10}')->emptyTypeOne + ); + $this->assertEquals( + new CustomCorrectOneMixedTypeParameterConstructorTypeClass(10), + (new ObjectMapper(new CustomTypeWithConstructorClass()))->mapFromJson('{"mixedTypeOne": 10}')->mixedTypeOne + ); + $this->assertEquals( + new CustomCorrectOneIntTypeParameterConstructorTypeClass(10), + (new ObjectMapper(new CustomTypeWithConstructorClass()))->mapFromJson('{"intTypeOne": 10}')->intTypeOne + ); + } +} diff --git a/tests/Unit/CustomTypeTest.php b/tests/Unit/CustomTypeWithoutConstructorTest.php similarity index 98% rename from tests/Unit/CustomTypeTest.php rename to tests/Unit/CustomTypeWithoutConstructorTest.php index f1a13ad..814bc09 100644 --- a/tests/Unit/CustomTypeTest.php +++ b/tests/Unit/CustomTypeWithoutConstructorTest.php @@ -15,7 +15,7 @@ use Shureban\LaravelObjectMapper\Tests\Unit\Structs\CustomTypeStrictSimpleClass; use Tests\TestCase; -class CustomTypeTest extends TestCase +class CustomTypeWithoutConstructorTest extends TestCase { public function test_StrictTypes() { diff --git a/tests/Unit/ErrorsTest.php b/tests/Unit/ErrorsTest.php new file mode 100644 index 0000000..537701f --- /dev/null +++ b/tests/Unit/ErrorsTest.php @@ -0,0 +1,23 @@ +assertThrows(fn() => (new ObjectMapper(new stdClass()))->mapFromJson('{"int": 10"}'), ParseJsonException::class); + } + + public function test_WithTwoRequiredParametersConstructor() + { + $this->assertThrows(fn() => (new ObjectMapper(new CustomTypeWithConstructorClass()))->mapFromJson('{"twoRequired": 10}'), WrongConstructorParametersNumberException::class); + } +} diff --git a/tests/Unit/ModelTypeTest.php b/tests/Unit/ModelTypeTest.php new file mode 100644 index 0000000..3b26c5f --- /dev/null +++ b/tests/Unit/ModelTypeTest.php @@ -0,0 +1,21 @@ +phpDocModel = new SomeModel(10); + $model->setterModel = new SomeModel(20); + + $this->assertEquals($model->phpDocModel, (new ObjectMapper(new ModelTypeClass()))->mapFromJson('{"model_id": 10}')->phpDocModel); + $this->assertEquals($model->setterModel, (new ObjectMapper(new ModelTypeClass()))->mapFromJson('{"setterModel": 20}')->setterModel); + } +} diff --git a/tests/Unit/ReadOnlyTest.php b/tests/Unit/ReadOnlyTest.php new file mode 100644 index 0000000..744f8f8 --- /dev/null +++ b/tests/Unit/ReadOnlyTest.php @@ -0,0 +1,15 @@ +assertEquals(0, (new ObjectMapper(new ReadOnlyClass()))->mapFromJson('{"int": 10}')->int); + } +} diff --git a/tests/Unit/SetterNameTest.php b/tests/Unit/SetterNameTest.php index bd46da8..779ca2f 100644 --- a/tests/Unit/SetterNameTest.php +++ b/tests/Unit/SetterNameTest.php @@ -12,5 +12,6 @@ public function test_SetterName() $this->assertEquals('setSimple', (string)new SetterName('simple')); $this->assertEquals('setCamelCaseMethod', (string)new SetterName('camelCaseMethod')); $this->assertEquals('setSnakeCaseMethod', (string)new SetterName('snake_case_method')); + $this->assertEquals('setMixedCaseNotation', (string)new SetterName('mixedCase_notation')); } } diff --git a/tests/Unit/SimpleTypeTest.php b/tests/Unit/SimpleTypeTest.php index 20c0b5a..100f49d 100644 --- a/tests/Unit/SimpleTypeTest.php +++ b/tests/Unit/SimpleTypeTest.php @@ -8,6 +8,12 @@ class SimpleTypeTest extends TestCase { + public function test_mixed() + { + $this->assertEquals(10, (new ObjectMapper(new SimpleTypeClass()))->mapFromJson('{"mixed": 10}')->mixed); + $this->assertEquals(['mixed' => 'type'], (new ObjectMapper(new SimpleTypeClass()))->mapFromArray(['mixed' => ['mixed' => 'type']])->mixed); + } + public function test_int() { $this->assertEquals(10, (new ObjectMapper(new SimpleTypeClass()))->mapFromJson('{"int": 10}')->int); diff --git a/tests/Unit/Structs/CustomConstructorTypeClass.php b/tests/Unit/Structs/CustomConstructorTypeClass.php new file mode 100644 index 0000000..f565056 --- /dev/null +++ b/tests/Unit/Structs/CustomConstructorTypeClass.php @@ -0,0 +1,53 @@ +id = $id; + } +} + +class CustomCorrectOneMixedTypeParameterConstructorTypeClass +{ + public int $id; + + public function __construct(mixed $id) + { + $this->id = $id; + } +} + +class CustomCorrectOneIntTypeParameterConstructorTypeClass +{ + public int $id; + + public function __construct(int $id) + { + $this->id = $id; + } +} + +class CustomTwoRequiredParametersConstructorTypeClass +{ + public int $id; + + public function __construct(int $id, array $data) + { + // never will call + exit(); + } +} diff --git a/tests/Unit/Structs/ModelTypeClass.php b/tests/Unit/Structs/ModelTypeClass.php new file mode 100644 index 0000000..4201f3c --- /dev/null +++ b/tests/Unit/Structs/ModelTypeClass.php @@ -0,0 +1,37 @@ +id = $id; + } + + public static function find($id, $columns = []): ?SomeModel + { + return new SomeModel($id); + } +} + +class ModelTypeClass +{ + /** @var SomeModel $model_id */ + public SomeModel $phpDocModel; + public SomeModel $setterModel; + + /** + * @param mixed $value + */ + public function setSetterModel(mixed $value): void + { + $this->setterModel = SomeModel::find($value); + } +} diff --git a/tests/Unit/Structs/ReadOnlyClass.php b/tests/Unit/Structs/ReadOnlyClass.php new file mode 100644 index 0000000..cdd094d --- /dev/null +++ b/tests/Unit/Structs/ReadOnlyClass.php @@ -0,0 +1,13 @@ +int = 0; + } +} diff --git a/tests/Unit/Structs/SimpleTypeClass.php b/tests/Unit/Structs/SimpleTypeClass.php index 6edd7f7..9c6b4b7 100644 --- a/tests/Unit/Structs/SimpleTypeClass.php +++ b/tests/Unit/Structs/SimpleTypeClass.php @@ -4,6 +4,7 @@ class SimpleTypeClass { + public mixed $mixed; public int $int; public float $float; public string $string; diff --git a/tests/Unit/Structs/WithSetterClass.php b/tests/Unit/Structs/WithSetterClass.php index 2236822..6286bfc 100644 --- a/tests/Unit/Structs/WithSetterClass.php +++ b/tests/Unit/Structs/WithSetterClass.php @@ -6,23 +6,35 @@ class WithSetterClass { - public string $value; - public string $request_value; + /** @var string $from_json_value */ + public string $fromJsonValue; + public string $fromArrayValue; + public string $from_request_value; /** * @param string $value + * @param string $json */ - public function setValue(string $value): void + public function setFromJsonValue(string $value, string $json): void { - $this->value = sprintf('setter_%s', $value); + $this->fromJsonValue = sprintf('setter_%s', $value); + } + + /** + * @param string $value + * @param array $data + */ + public function setFromArrayValue(string $value, array $data): void + { + $this->fromArrayValue = sprintf('setter_%s', $value); } /** * @param string $value * @param FormRequest $request */ - public function setRequestValue(string $value, FormRequest $request): void + public function setFromRequestValue(string $value, FormRequest $request): void { - $this->request_value = sprintf('setter_%s', $value); + $this->from_request_value = sprintf('setter_%s', $value); } } diff --git a/tests/Unit/WithSetterTest.php b/tests/Unit/WithSetterTest.php index f3d205a..1d52f68 100644 --- a/tests/Unit/WithSetterTest.php +++ b/tests/Unit/WithSetterTest.php @@ -12,9 +12,10 @@ class WithSetterTest extends TestCase public function test_withSetter() { $request = new FormRequest(); - $request->merge(['request_value' => 'request_value']); + $request->merge(['from_request_value' => 'from_request_value']); - $this->assertEquals('setter_value', (new ObjectMapper(new WithSetterClass()))->mapFromJson('{"value": "value"}')->value); - $this->assertEquals('setter_request_value', (new ObjectMapper(new WithSetterClass()))->mapFromRequest($request, false)->request_value); + $this->assertEquals('setter_from_json_value', (new ObjectMapper(new WithSetterClass()))->mapFromJson('{"from_json_value": "from_json_value"}')->fromJsonValue); + $this->assertEquals('setter_fromArrayValue', (new ObjectMapper(new WithSetterClass()))->mapFromArray(['fromArrayValue' => 'fromArrayValue'])->fromArrayValue); + $this->assertEquals('setter_from_request_value', (new ObjectMapper(new WithSetterClass()))->mapFromRequest($request, false)->from_request_value); } }