Completed
Push — 1.x ( 7f38e0...188fef )
by Akihito
21s queued 14s
created

JsonSchemaInterceptor::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 1

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 5
ccs 4
cts 4
cp 1
rs 9.4285
cc 1
eloc 3
nc 1
nop 2
crap 1
1
<?php
2
/**
3
 * This file is part of the BEAR.Resource package.
4
 *
5
 * @license http://opensource.org/licenses/MIT MIT
6
 */
7
namespace BEAR\Resource\Interceptor;
8
9
use BEAR\Resource\Annotation\JsonSchema;
10
use BEAR\Resource\Code;
11
use BEAR\Resource\Exception\JsonSchemaErrorException;
12
use BEAR\Resource\Exception\JsonSchemaException;
13
use BEAR\Resource\Exception\JsonSchemaNotFoundException;
14
use BEAR\Resource\ResourceObject;
15
use JsonSchema\Validator;
16
use Ray\Aop\MethodInterceptor;
17
use Ray\Aop\MethodInvocation;
18
use Ray\Aop\WeavedInterface;
19
use Ray\Di\Di\Named;
20
21
final class JsonSchemaInterceptor implements MethodInterceptor
22
{
23
    /**
24
     * @var string
25
     */
26
    private $schemaDir;
27
28
    /**
29
     * @var string
30
     */
31
    private $validateDir;
32
33
    /**
34
     * @param string $schemaDir
35
     * @param string $validateDir
36
     *
37
     * @Named("schemaDir=json_schema_dir,validateDir=json_validate_dir")
38
     */
39 5
    public function __construct($schemaDir, $validateDir)
40
    {
41 5
        $this->schemaDir = $schemaDir;
42 5
        $this->validateDir = $validateDir;
43 5
    }
44
45
    /**
46
     * {@inheritdoc}
47
     */
48 5
    public function invoke(MethodInvocation $invocation)
49
    {
50 5
        $ro = $invocation->proceed();
51
        /* @var $ro \BEAR\Resource\ResourceObject */
52 5
        if ($ro->code !== 200) {
53 1
            return $ro;
54
        }
55 4
        $jsonSchema = $invocation->getMethod()->getAnnotation(JsonSchema::class);
56
        /* @var $jsonSchema JsonSchema */
57 4
        if ($jsonSchema->request) {
58 2
            $this->validateRequest($jsonSchema, $ro);
59
        }
60 4
        $this->validateResponse($jsonSchema, $ro);
61
62 1
        return $ro;
63
    }
64
65 3
    public function validate($scanObject, $schemaFile)
66
    {
67 3
        $validator = new Validator;
68 3
        $validator->validate($scanObject, (object) ['$ref' => 'file://' . $schemaFile]);
69 3
        $isValid = $validator->isValid();
70 3
        if ($isValid) {
71 2
            return;
72
        }
73 2
        $e = null;
74 2
        foreach ($validator->getErrors() as $error) {
75 2
            $msg = sprintf('[%s] %s', $error['property'], $error['message']);
76 2
            $e = $e ? new JsonSchemaErrorException($msg, 0, $e) : new JsonSchemaErrorException($msg);
77
        }
78 2
        throw new JsonSchemaException($schemaFile, Code::ERROR, $e);
79
    }
80
81
    /**
82
     * @param $jsonSchema
0 ignored issues
show
Coding Style Documentation introduced by
Missing parameter name
Loading history...
83
     * @param $ro
0 ignored issues
show
Coding Style Documentation introduced by
Missing parameter name
Loading history...
84
     *
85
     * @return string
86
     */
87 2
    private function validateRequest($jsonSchema, $ro)
88
    {
89 2
        $schemaFile = $this->validateDir . '/' . $jsonSchema->request;
90 2
        $this->validateFileExists($schemaFile);
91 2
        $this->validate((object) $ro->uri->query, $schemaFile);
92 2
    }
93
94
    /**
95
     * @param $jsonSchema
0 ignored issues
show
Coding Style Documentation introduced by
Missing parameter name
Loading history...
96
     * @param $ro
0 ignored issues
show
Coding Style Documentation introduced by
Missing parameter name
Loading history...
97
     */
98 4
    private function validateResponse($jsonSchema, $ro)
99
    {
100 4
        $schemeFile = $this->getSchemaFile($jsonSchema, $ro);
101 3
        $body = isset($ro->body[$jsonSchema->key]) ? (object) $ro->body[$jsonSchema->key] : (object) $ro->body;
102 3
        $this->validate($body, $schemeFile);
103 1
    }
104
105 4
    private function getSchemaFile(JsonSchema $jsonSchema, ResourceObject $ro)
106
    {
107 4
        if (! $jsonSchema->schema) {
108
            // for BC only
109 1
            $ref = new \ReflectionClass($ro);
110 1
            $roFileName = $ro instanceof WeavedInterface ? $roFileName = $ref->getParentClass()->getFileName() : $ref->getFileName();
111 1
            $bcFile = str_replace('.php', '.json', $roFileName);
112 1
            if (file_exists($bcFile)) {
113 1
                return $bcFile;
114
            }
115
        }
116 3
        $schemaFile = $this->schemaDir . '/' . $jsonSchema->schema;
117 3
        $this->validateFileExists($schemaFile);
118
119 2
        return $schemaFile;
120
    }
121
122
    /**
123
     * @param $schemaFile
0 ignored issues
show
Coding Style Documentation introduced by
Missing parameter name
Loading history...
124
     */
125 3
    private function validateFileExists($schemaFile)
126
    {
127 3
        if (! file_exists($schemaFile) || is_dir($schemaFile)) {
128 1
            throw new JsonSchemaNotFoundException($schemaFile);
129
        }
130 2
    }
131
}
132