Skip to content

Commit 659deec

Browse files
committed
Spec validation complete
1 parent e851778 commit 659deec

19 files changed

+945
-164
lines changed

src/Spec/Builder.php

Lines changed: 40 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,11 @@
1919

2020
namespace LaravelJsonApi\Spec;
2121

22-
use Illuminate\Pipeline\Pipeline;
23-
use LogicException;
24-
use function json_decode;
22+
use Illuminate\Routing\Pipeline;
23+
use Illuminate\Support\Arr;
24+
use JsonException;
2525

26-
class Builder
26+
abstract class Builder
2727
{
2828

2929
/**
@@ -32,14 +32,20 @@ class Builder
3232
private Pipeline $pipeline;
3333

3434
/**
35-
* @var string|null
35+
* @var array
3636
*/
37-
private ?string $expectedType = null;
37+
private array $pipes = [];
3838

3939
/**
40-
* @var string|null
40+
* @param object $json
41+
* @return Document
4142
*/
42-
private ?string $expectedId = null;
43+
abstract protected function create(object $json): Document;
44+
45+
/**
46+
* @return array
47+
*/
48+
abstract protected function pipes(): array;
4349

4450
/**
4551
* Builder constructor.
@@ -52,58 +58,54 @@ public function __construct(Pipeline $pipeline)
5258
}
5359

5460
/**
55-
* Expect the supplied resource type and id.
56-
*
57-
* @param string $resourceType
58-
* @param string|null $resourceId
61+
* @param $pipes
5962
* @return $this
6063
*/
61-
public function expects(string $resourceType, ?string $resourceId): self
64+
public function using($pipes): self
6265
{
63-
$this->expectedType = $resourceType;
64-
$this->expectedId = $resourceId;
66+
$this->pipes = array_merge($this->pipes, Arr::wrap($pipes));
6567

6668
return $this;
6769
}
6870

6971
/**
70-
* @param string|object $json
72+
* @param string $json
7173
* @return Document
74+
* @throws DocumentException
7275
*/
73-
public function build($json): Document
76+
public function build(string $json): Document
7477
{
75-
if (is_string($json)) {
76-
$json = json_decode($json, false, 512, JSON_THROW_ON_ERROR);
77-
}
78+
$document = $this->create(
79+
$this->decode($json)
80+
);
7881

79-
if (!is_object($json)) {
80-
throw new \InvalidArgumentException('Expecting a string or object.');
81-
}
82+
$pipes = array_merge($this->pipes(), $this->pipes);
8283

8384
return $this->pipeline
84-
->send(new Document($json, $this->expectedType, $this->expectedId))
85-
->through($this->pipes())
85+
->send($document)
86+
->through($pipes)
8687
->via('validate')
8788
->thenReturn();
8889
}
8990

9091
/**
91-
* @return string[]
92+
* @param string $json
93+
* @return object
9294
*/
93-
private function pipes(): array
95+
private function decode(string $json): object
9496
{
95-
if ($this->expectedType) {
96-
return [
97-
Validators\DataValidator::class,
98-
Validators\TypeValidator::class,
99-
Validators\ClientIdValidator::class,
100-
Validators\IdValidator::class,
101-
Validators\FieldsValidator::class,
102-
Validators\AttributesValidator::class,
103-
Validators\RelationshipsValidator::class,
104-
];
97+
try {
98+
if (is_string($json)) {
99+
$json = json_decode($json, false, 512, JSON_THROW_ON_ERROR);
100+
}
101+
} catch (JsonException $ex) {
102+
throw new DocumentException('Invalid JSON string.', 0, $ex);
103+
}
104+
105+
if (is_object($json)) {
106+
return $json;
105107
}
106108

107-
throw new LogicException('Cannot determine validation pipes.');
109+
throw new DocumentException('JSON does not decode to a string or object.');
108110
}
109111
}

src/Spec/Document.php

Lines changed: 3 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -29,44 +29,19 @@ class Document
2929
*/
3030
private object $document;
3131

32-
/**
33-
* @var string
34-
*/
35-
private string $resourceType;
36-
37-
/**
38-
* @var string|null
39-
*/
40-
private ?string $resourceId;
41-
42-
/**
43-
* @var string|null
44-
*/
45-
private ?string $relation;
46-
4732
/**
4833
* @var ErrorList
4934
*/
5035
private ErrorList $errors;
5136

5237
/**
53-
* Document constructor.
38+
* BaseDocument constructor.
5439
*
5540
* @param object $document
56-
* @param string $resourceType
57-
* @param string|null $resourceId
58-
* @param string|null $relation
5941
*/
60-
public function __construct(
61-
object $document,
62-
string $resourceType,
63-
?string $resourceId,
64-
string $relation = null
65-
) {
42+
public function __construct(object $document)
43+
{
6644
$this->document = $document;
67-
$this->resourceType = $resourceType;
68-
$this->resourceId = $resourceId;
69-
$this->relation = $relation;
7045
$this->errors = new ErrorList();
7146
}
7247

@@ -88,50 +63,6 @@ public function __get($name)
8863
return $this->document->{$name};
8964
}
9065

91-
/**
92-
* Get the document's expected resource type.
93-
*
94-
* @return string
95-
*/
96-
public function type(): string
97-
{
98-
return $this->resourceType;
99-
}
100-
101-
/**
102-
* @return string|null
103-
*/
104-
public function id(): ?string
105-
{
106-
return $this->resourceId;
107-
}
108-
109-
/**
110-
* Get the relation that the document represents.
111-
*
112-
* @return string|null
113-
*/
114-
public function relation(): ?string
115-
{
116-
return $this->relation;
117-
}
118-
119-
/**
120-
* @return bool
121-
*/
122-
public function isRelation(): bool
123-
{
124-
return is_string($this->relation);
125-
}
126-
127-
/**
128-
* @return bool
129-
*/
130-
public function isNotRelation(): bool
131-
{
132-
return !$this->isRelation();
133-
}
134-
13566
/**
13667
* Get a value from the document using dot notation.
13768
*

src/Spec/Validator.php renamed to src/Spec/DocumentException.php

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,9 @@
1919

2020
namespace LaravelJsonApi\Spec;
2121

22-
interface Validator
22+
use UnexpectedValueException;
23+
24+
class DocumentException extends UnexpectedValueException
2325
{
2426

25-
/**
26-
* Validate the document.
27-
*
28-
* @param Document $document
29-
* @param \Closure $next
30-
* @return Document
31-
*/
32-
public function validate(Document $document, \Closure $next): Document;
3327
}

src/Spec/RelationBuilder.php

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
<?php
2+
/**
3+
* Copyright 2020 Cloud Creativity Limited
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
declare(strict_types=1);
19+
20+
namespace LaravelJsonApi\Spec;
21+
22+
use LogicException;
23+
24+
class RelationBuilder extends Builder
25+
{
26+
27+
/**
28+
* @var string|null
29+
*/
30+
private ?string $expectedType = null;
31+
32+
/**
33+
* @var string|null
34+
*/
35+
private ?string $expectedId = null;
36+
37+
/**
38+
* Expect the document to be the provided resource type and id.
39+
*
40+
* @param string $resourceType
41+
* @param string $relation
42+
* @return $this
43+
*/
44+
public function expects(string $resourceType, string $relation): self
45+
{
46+
$this->expectedType = $resourceType;
47+
$this->expectedId = $relation;
48+
49+
return $this;
50+
}
51+
52+
/**
53+
* @inheritDoc
54+
*/
55+
protected function create(object $json): Document
56+
{
57+
if ($this->expectedType) {
58+
return new RelationDocument(
59+
$json,
60+
$this->expectedType,
61+
$this->expectedId
62+
);
63+
}
64+
65+
throw new LogicException('No expected resource type and relation name set.');
66+
}
67+
68+
/**
69+
* @inheritDoc
70+
*/
71+
protected function pipes(): array
72+
{
73+
return [
74+
Validators\RelationValidator::class,
75+
];
76+
}
77+
}

src/Spec/RelationDocument.php

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
<?php
2+
/**
3+
* Copyright 2020 Cloud Creativity Limited
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
declare(strict_types=1);
19+
20+
namespace LaravelJsonApi\Spec;
21+
22+
class RelationDocument extends Document
23+
{
24+
25+
/**
26+
* @var string
27+
*/
28+
private string $resourceType;
29+
30+
/**
31+
* @var string|null
32+
*/
33+
private string $relation;
34+
35+
/**
36+
* RelationDocument constructor.
37+
*
38+
* @param object $document
39+
* @param string $resourceType
40+
* @param string $relation
41+
*/
42+
public function __construct(object $document, string $resourceType, string $relation)
43+
{
44+
parent::__construct($document);
45+
$this->resourceType = $resourceType;
46+
$this->relation = $relation;
47+
}
48+
49+
/**
50+
* @return string
51+
*/
52+
public function type(): string
53+
{
54+
return $this->resourceType;
55+
}
56+
57+
/**
58+
* @return string
59+
*/
60+
public function relation(): string
61+
{
62+
return $this->relation;
63+
}
64+
65+
}

0 commit comments

Comments
 (0)