Skip to content

Commit d7c22eb

Browse files
authored
Merge pull request #189 from web-vision/feature/188
[FEATURE] Rework and centralize api client operation
2 parents aa0f639 + be84235 commit d7c22eb

File tree

12 files changed

+816
-508
lines changed

12 files changed

+816
-508
lines changed

Classes/Client.php

Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace WebVision\WvDeepltranslate;
6+
7+
use Psr\Http\Message\ResponseInterface;
8+
use TYPO3\CMS\Core\Http\RequestFactory;
9+
use TYPO3\CMS\Core\Utility\GeneralUtility;
10+
use WebVision\WvDeepltranslate\Exception\ClientNotValidUrlException;
11+
12+
final class Client
13+
{
14+
private const API_VERSION = 'v2';
15+
16+
public const GLOSSARY_ENTRY_FORMAT = "%s\t%s\n";
17+
18+
/**
19+
* @var Configuration
20+
*/
21+
private $configuration;
22+
23+
/**
24+
* @var RequestFactory
25+
*/
26+
private $requestFactory;
27+
28+
public function __construct()
29+
{
30+
$this->configuration = GeneralUtility::makeInstance(Configuration::class);
31+
$this->requestFactory = GeneralUtility::makeInstance(RequestFactory::class);
32+
}
33+
34+
public function translate(string $content, string $sourceLang, string $targetLang, string $glossary = ''): ResponseInterface
35+
{
36+
$baseUrl = $this->buildBaseUrl('translate');
37+
38+
$postFields = [
39+
'text' => $content,
40+
'source_lang' => $sourceLang,
41+
'target_lang' => $targetLang,
42+
'tag_handling' => 'xml',
43+
];
44+
45+
if (!empty($glossary)) {
46+
$postFields['glossary_id'] = $glossary;
47+
}
48+
49+
$postFields['formality'] = $this->configuration->getFormality();
50+
51+
return $this->requestFactory->request($baseUrl, 'POST', $this->mergeRequiredRequestOptions([
52+
'form_params' => $postFields,
53+
]));
54+
}
55+
56+
public function getSupportedTargetLanguage(string $type = 'target'): ResponseInterface
57+
{
58+
$baseUrl = $this->buildBaseUrl('languages?type=' . $type);
59+
60+
return $this->requestFactory->request($baseUrl, 'GET', $this->mergeRequiredRequestOptions());
61+
}
62+
63+
public function getGlossaryLanguagePairs(): ResponseInterface
64+
{
65+
$baseUrl = $this->buildBaseUrl('glossary-language-pairs');
66+
67+
return $this->requestFactory->request($baseUrl, 'GET', $this->mergeRequiredRequestOptions());
68+
}
69+
70+
public function getAllGlossaries(): ResponseInterface
71+
{
72+
$baseUrl = $this->buildBaseUrl('glossaries');
73+
74+
return $this->requestFactory->request($baseUrl, 'GET', $this->mergeRequiredRequestOptions());
75+
}
76+
77+
public function getGlossary(string $glossaryId): ResponseInterface
78+
{
79+
$baseUrl = $this->buildBaseUrl(sprintf('glossaries/%s', $glossaryId));
80+
81+
return $this->requestFactory->request($baseUrl, 'GET', $this->mergeRequiredRequestOptions());
82+
}
83+
84+
public function createGlossary(
85+
string $glossaryName,
86+
string $sourceLang,
87+
string $targetLang,
88+
array $entries,
89+
string $entriesFormat = 'tsv'
90+
): ResponseInterface {
91+
$baseUrl = $this->buildBaseUrl('glossaries');
92+
93+
$postFields = [
94+
'name' => $glossaryName,
95+
'source_lang' => $sourceLang,
96+
'target_lang' => $targetLang,
97+
'entries_format' => $entriesFormat,
98+
];
99+
100+
$formatEntries = '';
101+
foreach ($entries as $source => $target) {
102+
$formatEntries .= sprintf(self::GLOSSARY_ENTRY_FORMAT, $source, $target);
103+
}
104+
105+
$postFields['entries'] = $formatEntries;
106+
107+
return $this->requestFactory->request($baseUrl, 'POST', $this->mergeRequiredRequestOptions([
108+
'form_params' => $postFields,
109+
]));
110+
}
111+
112+
public function deleteGlossary(string $glossaryId): ResponseInterface
113+
{
114+
$baseUrl = $this->buildBaseUrl(sprintf('glossaries/%s', $glossaryId));
115+
116+
return $this->requestFactory->request($baseUrl, 'DELETE', $this->mergeRequiredRequestOptions());
117+
}
118+
119+
public function getGlossaryEntries(string $glossaryId): ResponseInterface
120+
{
121+
$baseUrl = $this->buildBaseUrl(sprintf('glossaries/%s/entries', $glossaryId));
122+
123+
return $this->requestFactory->request($baseUrl, 'GET', $this->mergeRequiredRequestOptions());
124+
}
125+
126+
private function buildBaseUrl(string $path): string
127+
{
128+
$url = sprintf(
129+
'%s://%s/%s/%s',
130+
$this->configuration->getApiScheme(),
131+
$this->configuration->getApiUrl(),
132+
self::API_VERSION,
133+
$path
134+
);
135+
136+
if (!GeneralUtility::isValidUrl($url)) {
137+
throw new ClientNotValidUrlException(sprintf('BaseURL "%s" is not valid', $url), 1676125513);
138+
}
139+
140+
return $url;
141+
}
142+
143+
/**
144+
* @param array<string, mixed> $options
145+
* @return array<string, mixed>
146+
*/
147+
private function mergeRequiredRequestOptions(array $options = []): array
148+
{
149+
return array_merge_recursive(
150+
[
151+
'headers' => [
152+
'Authorization' => sprintf('DeepL-Auth-Key %s', $this->configuration->getApiKey()),
153+
'User-Agent' => 'TYPO3.WvDeepltranslate/1.0',
154+
],
155+
],
156+
$options
157+
);
158+
}
159+
}

Classes/Configuration.php

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace WebVision\WvDeepltranslate;
6+
7+
use TYPO3\CMS\Core\Configuration\ExtensionConfiguration;
8+
use TYPO3\CMS\Core\Utility\GeneralUtility;
9+
10+
class Configuration
11+
{
12+
/**
13+
* @var string
14+
*/
15+
private $apiKey = '';
16+
17+
/**
18+
* @var string
19+
*/
20+
private $apiUrl = '';
21+
22+
/**
23+
* @var string
24+
*/
25+
private $formality = '';
26+
27+
public function __construct()
28+
{
29+
$extensionConfiguration = GeneralUtility::makeInstance(ExtensionConfiguration::class)->get('wv_deepltranslate');
30+
31+
if (isset($extensionConfiguration['apiKey'])) {
32+
$this->apiKey = (string)$extensionConfiguration['apiKey'] ?? '';
33+
}
34+
35+
if (isset($extensionConfiguration['apiUrl'])) {
36+
// api url free is default
37+
$this->apiUrl = (string)$extensionConfiguration['apiUrl'] ?? 'https://api-free.deepl.com/';
38+
}
39+
40+
// In einer zukünftigen version sollte "Formality" in die SiteConfig verschoben werden
41+
if (isset($extensionConfiguration['deeplFormality'])) {
42+
$this->formality = (string)$extensionConfiguration['deeplFormality'] ?? 'default';
43+
}
44+
}
45+
46+
public function getApiKey(): string
47+
{
48+
return $this->apiKey;
49+
}
50+
51+
public function getApiUrl(): string
52+
{
53+
return $this->getApiHost()
54+
. ($this->getApiPort() ? ':' . $this->getApiPort() : '');
55+
}
56+
57+
public function getApiScheme(): string
58+
{
59+
return parse_url($this->apiUrl)['scheme'] ?? 'https';
60+
}
61+
62+
public function getApiHost(): string
63+
{
64+
return parse_url($this->apiUrl)['host'] ?? 'localhost';
65+
}
66+
67+
public function getApiPort(): ?int
68+
{
69+
$port = parse_url($this->apiUrl)['port'] ?? null;
70+
return $port ? (int)$port : null;
71+
}
72+
73+
public function getFormality(): string
74+
{
75+
return $this->formality;
76+
}
77+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace WebVision\WvDeepltranslate\Exception;
6+
7+
class ClientNotValidUrlException extends \Exception
8+
{
9+
}

0 commit comments

Comments
 (0)