Skip to content

Commit 26d0527

Browse files
authored
Merge pull request #10 from fetzi/feature/binding-require-opt-in
Bindings should not be required by default
2 parents dbd0d93 + b111986 commit 26d0527

File tree

7 files changed

+101
-32
lines changed

7 files changed

+101
-32
lines changed

.phpspec-watcher.yml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
fileMask: '*.php'
2+
checkInterval: 1
3+
directories:
4+
- src
5+
- tests/specs
6+
phpspec:
7+
binary: vendor/bin/phpspec
8+
arguments: [format=dot]
9+
notifications:
10+
onError: true
11+
onSuccess: true

src/Bindings/AliasBinding.php

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,16 +19,23 @@ class AliasBinding implements Binding
1919
*/
2020
private $jsonField;
2121

22+
/**
23+
* @var bool
24+
*/
25+
private $isRequired;
26+
2227
/**
2328
* AliasBinding constructor.
2429
*
25-
* @param string $property the property to bind to
26-
* @param string $jsonField the json field
30+
* @param string $property the property to bind to
31+
* @param string $jsonField the json field
32+
* @param bool $isRequired defines if the field value is required during decoding
2733
*/
28-
public function __construct($property, $jsonField)
34+
public function __construct($property, $jsonField, $isRequired = false)
2935
{
3036
$this->property = $property;
3137
$this->jsonField = $jsonField;
38+
$this->isRequired = $isRequired;
3239
}
3340

3441
/**
@@ -44,13 +51,17 @@ public function __construct($property, $jsonField)
4451
*/
4552
public function bind($jsonDecoder, $jsonData, $propertyAccessor)
4653
{
47-
if (!array_key_exists($this->jsonField, $jsonData)) {
54+
if (array_key_exists($this->jsonField, $jsonData)) {
55+
$propertyAccessor->set($jsonData[$this->jsonField]);
56+
57+
return;
58+
}
59+
60+
if ($this->isRequired) {
4861
throw new JsonValueException(
4962
sprintf('the value "%s" for property "%s" does not exist', $this->jsonField, $this->property)
5063
);
5164
}
52-
53-
$propertyAccessor->set($jsonData[$this->jsonField]);
5465
}
5566

5667
/**

src/Bindings/ArrayBinding.php

Lines changed: 24 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -24,18 +24,25 @@ class ArrayBinding implements Binding
2424
*/
2525
private $type;
2626

27+
/**
28+
* @var bool
29+
*/
30+
private $isRequired;
31+
2732
/**
2833
* ArrayBinding constructor.
2934
*
30-
* @param string $property the property to bind to
31-
* @param string $jsonField the json field
32-
* @param string $type the desired type of the property
35+
* @param string $property the property to bind to
36+
* @param string $jsonField the json field
37+
* @param string $type the desired type of the property
38+
* @param bool $isRequired defines if the field value is required during decoding
3339
*/
34-
public function __construct($property, $jsonField, $type)
40+
public function __construct($property, $jsonField, $type, $isRequired = false)
3541
{
3642
$this->property = $property;
3743
$this->jsonField = $jsonField;
3844
$this->type = $type;
45+
$this->isRequired = $isRequired;
3946
}
4047

4148
/**
@@ -51,21 +58,23 @@ public function __construct($property, $jsonField, $type)
5158
*/
5259
public function bind($jsonDecoder, $jsonData, $propertyAccessor)
5360
{
54-
if (!array_key_exists($this->jsonField, $jsonData)) {
55-
throw new JsonValueException(
56-
sprintf('the value "%s" for property "%s" does not exist', $this->jsonField, $this->property)
57-
);
58-
}
61+
if (array_key_exists($this->jsonField, $jsonData)) {
62+
$data = $jsonData[$this->jsonField];
63+
$values = [];
5964

60-
$data = $jsonData[$this->jsonField];
61-
$values = [];
65+
if (is_array($data)) {
66+
foreach ($data as $item) {
67+
$values[] = $jsonDecoder->decodeArray($item, $this->type);
68+
}
6269

63-
if (is_array($data)) {
64-
foreach ($data as $item) {
65-
$values[] = $jsonDecoder->decodeArray($item, $this->type);
70+
$propertyAccessor->set($values);
6671
}
72+
}
6773

68-
$propertyAccessor->set($values);
74+
if ($this->isRequired) {
75+
throw new JsonValueException(
76+
sprintf('the value "%s" for property "%s" does not exist', $this->jsonField, $this->property)
77+
);
6978
}
7079
}
7180

src/Bindings/FieldBinding.php

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,18 +24,25 @@ class FieldBinding implements Binding
2424
*/
2525
private $type;
2626

27+
/**
28+
* @var bool
29+
*/
30+
private $isRequired;
31+
2732
/**
2833
* FieldBinding constructor.
2934
*
30-
* @param string $property the property to bind to
31-
* @param string $jsonField the json field
32-
* @param string $type the desired type of the property
35+
* @param string $property the property to bind to
36+
* @param string $jsonField the json field
37+
* @param string $type the desired type of the property
38+
* @param bool $isRequired defines if the field value is required during decoding
3339
*/
34-
public function __construct($property, $jsonField, $type)
40+
public function __construct($property, $jsonField, $type, $isRequired = false)
3541
{
3642
$this->property = $property;
3743
$this->jsonField = $jsonField;
3844
$this->type = $type;
45+
$this->isRequired = $isRequired;
3946
}
4047

4148
/**
@@ -51,14 +58,16 @@ public function __construct($property, $jsonField, $type)
5158
*/
5259
public function bind($jsonDecoder, $jsonData, $propertyAccessor)
5360
{
54-
if (!array_key_exists($this->jsonField, $jsonData)) {
61+
if (array_key_exists($this->jsonField, $jsonData)) {
62+
$data = $jsonData[$this->jsonField];
63+
$propertyAccessor->set($jsonDecoder->decodeArray($data, $this->type));
64+
}
65+
66+
if ($this->isRequired) {
5567
throw new JsonValueException(
5668
sprintf('the value "%s" for property "%s" does not exist', $this->jsonField, $this->property)
5769
);
5870
}
59-
60-
$data = $jsonData[$this->jsonField];
61-
$propertyAccessor->set($jsonDecoder->decodeArray($data, $this->type));
6271
}
6372

6473
/**

tests/specs/Bindings/AliasBindingSpec.php

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use Karriere\JsonDecoder\JsonDecoder;
88
use Karriere\JsonDecoder\PropertyAccessor;
99
use PhpSpec\ObjectBehavior;
10+
use Prophecy\Argument;
1011

1112
class AliasBindingSpec extends ObjectBehavior
1213
{
@@ -25,11 +26,20 @@ public function it_should_return_bound_property()
2526
$this->property()->shouldReturn('property');
2627
}
2728

28-
public function it_should_throw_an_exception_if_json_field_is_not_available(JsonDecoder $jsonDecoder)
29+
public function it_should_throw_an_exception_if_json_field_is_required_and_not_available(JsonDecoder $jsonDecoder)
2930
{
31+
$this->beConstructedWith('property', 'field', true);
32+
3033
$this->shouldThrow(JsonValueException::class)->duringBind($jsonDecoder, [], new \stdClass());
3134
}
3235

36+
public function it_should_not_set_the_json_value_when_value_is_not_required(JsonDecoder $jsonDecoder, PropertyAccessor $propertyAccessor)
37+
{
38+
$propertyAccessor->set(Argument::any())->shouldNotBeCalled();
39+
40+
$this->bind($jsonDecoder, [], $propertyAccessor);
41+
}
42+
3343
public function it_should_set_the_json_value_to_the_property(JsonDecoder $jsonDecoder, PropertyAccessor $propertyAccessor)
3444
{
3545
$propertyAccessor->set('value')->shouldBeCalled();

tests/specs/Bindings/ArrayBindingSpec.php

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,20 @@ public function it_should_return_the_property_name()
2626
$this->property()->shouldReturn('property');
2727
}
2828

29-
public function it_should_throw_anc_exception_if_json_field_does_not_exist(JsonDecoder $jsonDecoder, PropertyAccessor $propertyAccessor)
29+
public function it_should_throw_an_exception_if_json_field_does_not_exist_and_is_required(JsonDecoder $jsonDecoder, PropertyAccessor $propertyAccessor)
3030
{
31+
$this->beConstructedWith('property', 'field', Sample::class, true);
32+
3133
$this->shouldThrow(JsonValueException::class)->duringBind($jsonDecoder, [], $propertyAccessor);
3234
}
3335

36+
public function it_should_not_set_value_when_json_field_does_not_exist_and_is_not_required(JsonDecoder $jsonDecoder, PropertyAccessor $propertyAccessor)
37+
{
38+
$jsonDecoder->decodeArray(Argument::any())->shouldNotBeCalled();
39+
40+
$this->bind($jsonDecoder, [], $propertyAccessor);
41+
}
42+
3443
public function it_should_decode_the_array(JsonDecoder $jsonDecoder, PropertyAccessor $propertyAccessor)
3544
{
3645
$jsonDecoder->decodeArray([], Sample::class)->shouldBeCalledTimes(2);

tests/specs/Bindings/FieldBindingSpec.php

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use Karriere\JsonDecoder\JsonDecoder;
88
use Karriere\JsonDecoder\PropertyAccessor;
99
use PhpSpec\ObjectBehavior;
10+
use Prophecy\Argument;
1011

1112
class FieldBindingSpec extends ObjectBehavior
1213
{
@@ -25,11 +26,20 @@ public function it_should_return_the_property_name()
2526
$this->property()->shouldReturn('property');
2627
}
2728

28-
public function it_should_throw_an_exception_if_the_json_field_does_not_exist(JsonDecoder $jsonDecoder, PropertyAccessor $propertyAccessor)
29+
public function it_should_throw_an_exception_if_the_json_field_does_not_exist_and_is_required(JsonDecoder $jsonDecoder, PropertyAccessor $propertyAccessor)
2930
{
31+
$this->beConstructedWith('property', 'field', FieldBindingSample::class, true);
32+
3033
$this->shouldThrow(JsonValueException::class)->duringBind($jsonDecoder, [], $propertyAccessor);
3134
}
3235

36+
public function it_should_not_set_value_if_the_json_field_does_not_exist_and_is_not_required(JsonDecoder $jsonDecoder, PropertyAccessor $propertyAccessor)
37+
{
38+
$propertyAccessor->set(Argument::any())->shouldNotBeCalled();
39+
40+
$this->bind($jsonDecoder, [], $propertyAccessor);
41+
}
42+
3343
public function it_should_bind_the_decoded_value(JsonDecoder $jsonDecoder, PropertyAccessor $propertyAccessor)
3444
{
3545
$jsonDecoder->decodeArray([], FieldBindingSample::class)->willReturn('data')->shouldBeCalled();

0 commit comments

Comments
 (0)