Skip to content

Commit 196c3b7

Browse files
Quality/Use src folder + Bump PHPStan to level 9 + Add support for Symfony 7 (#7)
* Use src folder * Bump php and symfony versions * Add phpstan * Bump phpstan * Bump phpstan * Bump phpstan to max level * Line ending
1 parent 7881295 commit 196c3b7

11 files changed

Lines changed: 113 additions & 40 deletions

File tree

.editorconfig

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
root = true
2+
3+
[*]
4+
end_of_line = lf
5+
insert_final_newline = true
6+
indent_style = space
7+
indent_size = 4
8+
charset = utf-8
9+
10+
[*.json]
11+
indent_size = 2
12+
13+
[composer.json]
14+
indent_size = 4

.gitattributes

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
.* export-ignore
2+
*.md export-ignore
3+
tests export-ignore
4+
phpstan.dist.neon export-ignore

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
.DS_Store
22
.idea
3-
/vendor/
3+
composer.lock
4+
/vendor/

composer.json

Lines changed: 27 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,30 @@
11
{
2-
"name": "weglot/text-master-api",
3-
"type": "library",
4-
"license": "MIT",
5-
"authors": [
6-
{
7-
"name": "Etienne Dhennin",
8-
"email": "etienne@weglot.com",
9-
"role": "Developer"
2+
"name": "weglot/text-master-api",
3+
"type": "library",
4+
"license": "MIT",
5+
"authors": [
6+
{
7+
"name": "Etienne Dhennin",
8+
"email": "etienne@weglot.com",
9+
"role": "Developer"
10+
}
11+
],
12+
"require": {
13+
"php": ">=8.0",
14+
"ext-json": "*",
15+
"guzzlehttp/guzzle": "^7.0",
16+
"symfony/config": "^5.4 || ^6.0 || ^7.0",
17+
"symfony/dependency-injection": "^5.4 || ^6.0 || ^7.0",
18+
"symfony/http-kernel": "^5.4 || ^6.0 || ^7.0"
19+
},
20+
"require-dev": {
21+
"phpstan/phpstan": "1.11.*",
22+
"phpstan/phpstan-strict-rules": "1.6.*",
23+
"phpstan/phpstan-symfony": "1.4.*"
24+
},
25+
"autoload": {
26+
"psr-4": {
27+
"Weglot\\TextMasterBundle\\": "src/"
28+
}
1029
}
11-
],
12-
"require": {
13-
"php": ">=7.2",
14-
"ext-json": "*",
15-
"guzzlehttp/guzzle": "^7.0",
16-
"symfony/config": "^5.4 || ^6.0",
17-
"symfony/dependency-injection": "^5.4 || ^6.0",
18-
"symfony/http-kernel": "^5.4 || ^6.0"
19-
20-
},
21-
"autoload": {
22-
"psr-4": {
23-
"Weglot\\TextMasterBundle\\": ""
24-
}
25-
}
2630
}

phpstan.dist.neon

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
includes:
2+
- vendor/phpstan/phpstan-symfony/extension.neon
3+
- vendor/phpstan/phpstan-symfony/rules.neon
4+
- vendor/phpstan/phpstan-strict-rules/rules.neon
5+
- vendor/phpstan/phpstan/conf/bleedingEdge.neon
6+
7+
parameters:
8+
level: 9
9+
paths:
10+
- src/
11+
exceptions:
12+
check:
13+
missingCheckedExceptionInThrows: true
14+
tooWideThrowType: true
15+
reportUncheckedExceptionDeadCatch: true
16+
implicitThrows: false
17+
uncheckedExceptionClasses:
18+
- LogicException

DependencyInjection/WeglotTextMasterExtension.php renamed to src/DependencyInjection/WeglotTextMasterExtension.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@
99

1010
class WeglotTextMasterExtension extends Extension
1111
{
12+
/**
13+
* @throws \Exception
14+
*/
1215
public function load(array $configs, ContainerBuilder $container): void
1316
{
1417
$configuration = new Configuration();
File renamed without changes.
Lines changed: 45 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,7 @@
1313

1414
class TextMasterApi
1515
{
16-
/** @var Client */
17-
private $client;
18-
/** @var array */
19-
private $basicHeaders = [];
16+
private Client $client;
2017

2118
public const BASE_TM_API_URL = 'https://api.';
2219
public const API_URI = 'textmaster.com/v1/';
@@ -47,13 +44,16 @@ public function __construct(string $apiKey, string $apiSecret, string $textmaste
4744
$baseUri = self::BASE_TM_API_URL;
4845
$baseUri .= self::PROD_ENV === $textmasterEnv ? self::API_URI : self::SANDBOX_API_URI;
4946

50-
$this->basicHeaders['key'] = $apiKey;
51-
$this->basicHeaders['secret'] = $apiSecret;
52-
$this->basicHeaders['base_uri'] = $baseUri;
53-
$this->client = $this->createGuzzleClient($this->basicHeaders);
47+
$this->client = $this->createGuzzleClient([
48+
'key' => $apiKey,
49+
'secret' => $apiSecret,
50+
'base_uri' => $baseUri,
51+
]);
5452
}
5553

5654
/**
55+
* @param array<string, mixed> $project
56+
*
5757
* @throws GuzzleException
5858
*/
5959
public function createProject(array $project): ResponseInterface
@@ -64,14 +64,16 @@ public function createProject(array $project): ResponseInterface
6464
}
6565

6666
/**
67+
* @param array<string, mixed> $project
68+
*
6769
* @throws GuzzleException
6870
*/
69-
public function updateProject(string $textMasterProjectId, array $options): ResponseInterface
71+
public function updateProject(string $textMasterProjectId, array $project): ResponseInterface
7072
{
7173
$routeParams = self::ROUTES['updateProject'];
7274
$url = $this->formatUrl($routeParams['url'], ['{projectId}' => $textMasterProjectId]);
7375

74-
return $this->request($url, $routeParams['method'], ['project' => $options]);
76+
return $this->request($url, $routeParams['method'], ['project' => $project]);
7577
}
7678

7779
/**
@@ -86,6 +88,8 @@ public function launchProject(string $textMasterProjectId): ResponseInterface
8688
}
8789

8890
/**
91+
* @param array<string, mixed> $documents
92+
*
8993
* @throws GuzzleException
9094
*/
9195
public function addDocumentsToProject(string $textMasterProjectId, array $documents): ResponseInterface
@@ -108,14 +112,16 @@ public function completeDocument(string $documentId, string $textMasterProjectId
108112
}
109113

110114
/**
115+
* @param array<string, mixed> $project
116+
*
111117
* @throws GuzzleException
112118
*/
113-
public function setProjectOptions(string $textMasterProjectId, array $options): ResponseInterface
119+
public function setProjectOptions(string $textMasterProjectId, array $project): ResponseInterface
114120
{
115121
$routeParams = self::ROUTES['setOptions'];
116122
$url = $this->formatUrl($routeParams['url'], ['{projectId}' => $textMasterProjectId]);
117123

118-
return $this->request($url, $routeParams['method'], ['project' => $options]);
124+
return $this->request($url, $routeParams['method'], ['project' => $project]);
119125
}
120126

121127
/**
@@ -141,6 +147,8 @@ public function getDocument(string $textMasterProjectId, string $textMasterDocum
141147
}
142148

143149
/**
150+
* @param array<string, mixed> $project
151+
*
144152
* @throws GuzzleException
145153
*/
146154
public function getProjectQuotation(array $project): ResponseInterface
@@ -187,7 +195,20 @@ public function extractErrorFromResponse(ResponseInterface $response, string $fo
187195
$errorMsg = '';
188196
$lineBreaker = 'html' === $format ? '</br>' : "\n";
189197

190-
$decodedResponse = json_decode($response->getBody()->getContents(), true);
198+
try {
199+
$decodedResponse = json_decode($response->getBody()->getContents(), true, 512, \JSON_THROW_ON_ERROR);
200+
} catch (\Exception) {
201+
return $errorMsg;
202+
}
203+
204+
if (
205+
!\is_array($decodedResponse)
206+
|| !isset($decodedResponse['errors'])
207+
|| !\is_iterable($decodedResponse['errors'])
208+
) {
209+
return $errorMsg;
210+
}
211+
191212
foreach ($decodedResponse['errors'] as $type => $messagesArray) {
192213
$errorMsg .= "Type of error: $type ".$lineBreaker;
193214
if (is_array($messagesArray)) {
@@ -201,6 +222,8 @@ public function extractErrorFromResponse(ResponseInterface $response, string $fo
201222
}
202223

203224
/**
225+
* @param array<string, mixed> $payload
226+
*
204227
* @throws GuzzleException
205228
*/
206229
private function request(string $url, string $method, array $payload = []): ResponseInterface
@@ -210,10 +233,13 @@ private function request(string $url, string $method, array $payload = []): Resp
210233
return $this->client->send($request, [RequestOptions::JSON => $payload]);
211234
}
212235

236+
/**
237+
* @param array{key: string, secret: string, base_uri: string} $options
238+
*/
213239
private function createGuzzleClient(array $options): Client
214240
{
215241
$stack = HandlerStack::create();
216-
$stack->push(Middleware::mapRequest(function (RequestInterface $request) use ($options) {
242+
$stack->push(Middleware::mapRequest(static function (RequestInterface $request) use ($options) {
217243
$date = new \DateTime('now', new \DateTimeZone('UTC'));
218244

219245
return $request
@@ -222,13 +248,16 @@ private function createGuzzleClient(array $options): Client
222248
->withHeader('Signature', sha1($options['secret'].$date->format('Y-m-d H:i:s')))
223249
;
224250
}));
225-
unset($options['key']);
226-
unset($options['secret']);
251+
252+
unset($options['key'], $options['secret']);
227253
$options = array_merge($options, ['handler' => $stack]);
228254

229255
return new Client($options);
230256
}
231257

258+
/**
259+
* @param array<string, string> $parameters
260+
*/
232261
private function formatUrl(string $url, array $parameters): string
233262
{
234263
foreach ($parameters as $placeholder => $value) {

0 commit comments

Comments
 (0)