-
Notifications
You must be signed in to change notification settings - Fork 44
/
Copy pathTestService.php
153 lines (131 loc) · 4.57 KB
/
TestService.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
<?php
declare(strict_types=1);
namespace Tests;
use flight\Engine;
use Monolog\Logger;
class TestService
{
private TestDataStore $_store;
private Logger $_logger;
private Engine $_app;
public function __construct(TestDataStore $store, Logger $logger)
{
$this->_store = $store;
$this->_logger = $logger;
$this->_app = new Engine();
$this->_app->set('flight.log_errors', true);
$this->_app->route('GET /', function () {
$this->_app->json($this->getStatus());
});
$this->_app->route('POST /', function () {
$params = self::parseRequestJson($this->_app->request()->getBody());
$id = $this->createClient($params);
header("Location:/clients/$id");
});
$this->_app->route('DELETE /', function () {
$this->_logger->info('Test harness has told us to quit');
});
$this->_app->route('POST /clients/@id', function ($id) {
$c = $this->getClient($id);
if (!$c) {
http_response_code(404);
return;
}
$params = self::parseRequestJson($this->_app->request()->getBody());
$resp = $c->doCommand($params);
if ($resp === false) {
http_response_code(400);
} elseif (is_array($resp)) {
$this->_app->json($resp);
}
});
$this->_app->route("DELETE /clients/@id", function ($id) {
if (!$this->deleteClient($id)) {
http_response_code(404);
}
});
}
public function start(): void
{
$this->_app->start();
}
public function getStatus(): array
{
return [
'name' => 'php-server-sdk',
'capabilities' => [
'php',
'server-side',
'all-flags-client-side-only',
'all-flags-details-only-for-tracked-flags',
'all-flags-with-reasons',
'context-type',
'secure-mode-hash',
'migrations',
'event-sampling',
'inline-context-all',
'instance-id',
'anonymous-redaction',
'client-prereq-events',
'big-segments'
],
'clientVersion' => \LaunchDarkly\LDClient::VERSION
];
}
public function createClient(mixed $params): string
{
$this->_logger->info("Creating client with parameters: " . json_encode($params));
$client = new SdkClientEntity($params, true, $this->_logger); // just to verify that the config is valid
return $this->_store->addClientParams($params);
}
public function deleteClient(string $id): bool
{
$c = $this->getClient($id);
if ($c) {
$c->close();
$this->_store->deleteClientParams($id);
return true;
}
return false;
}
private function getClient(string $id): ?SdkClientEntity
{
$params = $this->_store->getClientParams($id);
if ($params === null) {
return null;
}
return new SdkClientEntity($params, false);
}
// The following methods for normalizing parsed JSON are a workaround for PHP's inability to distinguish
// between an empty JSON array [] and an empty JSON object {} if you parse JSON into associative arrays.
// In order for some contract tests to work which involve empty object values, we need to be able to
// make such a distinction. But, we don't want to parse all of the JSON parameters as objects, because
// associative arrays are much more convenient for most of our logic. The solution is to parse everything
// as an object first, then convert every object to an array UNLESS it is an empty object.
private static function parseRequestJson(string $json): array
{
return self::normalizeParsedData(json_decode($json));
}
private static function normalizeParsedData(mixed $value): mixed
{
if (is_array($value)) {
$ret = [];
foreach ($value as $element) {
$ret[] = self::normalizeParsedData($element);
}
return $ret;
}
if (!is_object($value)) {
return $value;
}
$props = get_object_vars($value);
if (count($props) === 0) {
return $value;
}
$ret = [];
foreach ($props as $k => $v) {
$ret[$k] = self::normalizeParsedData($v);
}
return $ret;
}
}