1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace PPP\Module; |
4
|
|
|
|
5
|
|
|
use Deserializers\Exceptions\DeserializationException; |
6
|
|
|
use Exception; |
7
|
|
|
use PPP\DataModel\DeserializerFactory; |
8
|
|
|
use PPP\DataModel\SerializerFactory; |
9
|
|
|
use PPP\Module\DataModel\Deserializers\ModuleRequestDeserializer; |
10
|
|
|
use PPP\Module\DataModel\ModuleRequest; |
11
|
|
|
use PPP\Module\DataModel\ModuleResponse; |
12
|
|
|
use PPP\Module\DataModel\Serializers\ModuleResponseSerializer; |
13
|
|
|
|
14
|
|
|
/** |
15
|
|
|
* Entry point for Modules |
16
|
|
|
* |
17
|
|
|
* @licence MIT |
18
|
|
|
* @author Thomas Pellissier Tanon |
19
|
|
|
*/ |
20
|
|
|
class ModuleEntryPoint { |
21
|
|
|
|
22
|
|
|
/** |
23
|
|
|
* @var RequestHandler |
24
|
|
|
*/ |
25
|
|
|
private $requestHandler; |
26
|
|
|
|
27
|
|
|
/** |
28
|
|
|
* @param RequestHandler $requestHandler |
29
|
|
|
*/ |
30
|
7 |
|
public function __construct(RequestHandler $requestHandler) { |
31
|
7 |
|
$this->requestHandler = $requestHandler; |
32
|
7 |
|
} |
33
|
|
|
|
34
|
|
|
/** |
35
|
|
|
* Main function |
36
|
|
|
*/ |
37
|
7 |
|
public function exec() { |
38
|
|
|
try { |
39
|
7 |
|
$this->filterRequestMethod(); |
40
|
7 |
|
$request = $this->getRequest(); |
41
|
6 |
|
$responses = $this->requestHandler->buildResponse($request); |
42
|
5 |
|
$this->outputResponse($this->serializeResponse($this->cleanResponses($responses, $request))); |
43
|
7 |
|
} catch(HttpException $e) { |
44
|
1 |
|
$this->outputHttpException($e); |
45
|
2 |
|
} catch(Exception $e) { |
46
|
1 |
|
$this->outputHttpException(new HttpException($e->getMessage(), 500, $e)); |
47
|
|
|
} |
48
|
7 |
|
} |
49
|
|
|
|
50
|
7 |
|
private function filterRequestMethod() { |
51
|
7 |
|
if(!array_key_exists('REQUEST_METHOD', $_SERVER)) { |
52
|
7 |
|
return; |
53
|
|
|
} |
54
|
|
|
if($_SERVER['REQUEST_METHOD'] === 'OPTIONS') { |
55
|
|
|
exit(); |
|
|
|
|
56
|
|
|
} |
57
|
|
|
if($_SERVER['REQUEST_METHOD'] !== 'POST') { |
58
|
|
|
new HttpException('Bad request method: ' . $_SERVER['REQUEST_METHOD'], 405); |
59
|
|
|
} |
60
|
|
|
} |
61
|
|
|
|
62
|
|
|
/** |
63
|
|
|
* @return ModuleRequest |
64
|
|
|
*/ |
65
|
7 |
|
private function getRequest() { |
66
|
7 |
|
$requestJson = json_decode($this->getRequestBody(), true); |
67
|
|
|
try { |
68
|
7 |
|
return $this->buildRequestDeserializer()->deserialize($requestJson); |
69
|
1 |
|
} catch(DeserializationException $e) { |
70
|
1 |
|
throw new HttpException($e->getMessage(), 400, $e); |
71
|
|
|
} |
72
|
|
|
} |
73
|
|
|
|
74
|
|
|
public function getRequestBody() { |
75
|
|
|
return file_get_contents("php://input"); |
76
|
|
|
} |
77
|
|
|
|
78
|
5 |
|
private function cleanResponses(array $responses, ModuleRequest $request) { |
79
|
5 |
|
$cleanedResponses = array(); |
80
|
|
|
|
81
|
|
|
/** @var ModuleResponse $response */ |
82
|
5 |
|
foreach($responses as $response) { |
83
|
4 |
|
if($request->getSentenceTree()->equals($response->getSentenceTree())) { |
84
|
|
|
continue; |
85
|
|
|
} |
86
|
|
|
|
87
|
|
|
/** @var ModuleResponse $existingResponse */ |
88
|
4 |
|
foreach($cleanedResponses as $existingResponse) { |
89
|
1 |
|
if($existingResponse->getSentenceTree()->equals($response->getSentenceTree())) { |
90
|
1 |
|
continue 2; |
91
|
|
|
} |
92
|
4 |
|
} |
93
|
|
|
|
94
|
4 |
|
$cleanedResponses[] = new ModuleResponse( |
95
|
4 |
|
$response->getLanguageCode(), |
96
|
4 |
|
$response->getSentenceTree(), |
97
|
4 |
|
$response->getMeasures() + $request->getMeasures(), |
98
|
4 |
|
$response->getTrace() |
99
|
4 |
|
); |
100
|
5 |
|
} |
101
|
|
|
|
102
|
5 |
|
return $cleanedResponses; |
103
|
|
|
} |
104
|
|
|
|
105
|
5 |
|
private function outputResponse($serialization) { |
106
|
5 |
|
@header('Content-type: application/json'); |
107
|
5 |
|
echo json_encode($serialization); |
108
|
5 |
|
} |
109
|
|
|
|
110
|
5 |
|
private function serializeResponse(array $responses) { |
111
|
5 |
|
$serialization = array(); |
112
|
5 |
|
foreach($responses as $response) { |
113
|
4 |
|
$serialization[] = $this->buildResponseSerializer()->serialize($response); |
114
|
5 |
|
} |
115
|
5 |
|
return $serialization; |
116
|
|
|
} |
117
|
|
|
|
118
|
7 |
|
private function buildRequestDeserializer() { |
119
|
7 |
|
$deserializerFactory = new DeserializerFactory($this->requestHandler->getCustomResourceNodeDeserializers()); |
120
|
7 |
|
return new ModuleRequestDeserializer($deserializerFactory->newNodeDeserializer()); |
121
|
|
|
} |
122
|
|
|
|
123
|
4 |
|
private function buildResponseSerializer() { |
124
|
4 |
|
$serializerFactory = new SerializerFactory($this->requestHandler->getCustomResourceNodeSerializers()); |
125
|
4 |
|
return new ModuleResponseSerializer($serializerFactory->newNodeSerializer()); |
126
|
|
|
} |
127
|
|
|
|
128
|
2 |
|
private function outputHttpException(HttpException $exception) { |
129
|
2 |
|
$this->setHttpResponseCode($exception->getCode()); |
130
|
2 |
|
echo $exception->getMessage(); |
131
|
2 |
|
} |
132
|
|
|
|
133
|
2 |
|
private function setHttpResponseCode($code) { |
134
|
2 |
|
if(function_exists('http_response_code')) { |
135
|
2 |
|
@http_response_code($code); |
136
|
2 |
|
} else { |
137
|
|
|
@header('X-PHP-Response-Code: '. $code, true, $code); |
138
|
|
|
} |
139
|
2 |
|
} |
140
|
|
|
} |
141
|
|
|
|
An exit expression should only be used in rare cases. For example, if you write a short command line script.
In most cases however, using an
exit
expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.