Skip to content

Commit d4b2e55

Browse files
committed
Refactor for use with CSP and improve usability
1 parent de205b4 commit d4b2e55

17 files changed

Lines changed: 392 additions & 251 deletions

File tree

Classes/Controller/FileController.php

Lines changed: 131 additions & 106 deletions
Original file line numberDiff line numberDiff line change
@@ -17,153 +17,163 @@
1717

1818
use Evoweb\EwLlxml2xliff\File\Converter;
1919
use Evoweb\EwLlxml2xliff\Service\ExtensionService;
20-
use Psr\Http\Message\ResponseFactoryInterface;
2120
use Psr\Http\Message\ResponseInterface;
2221
use Psr\Http\Message\ServerRequestInterface;
2322
use TYPO3\CMS\Backend\Attribute\Controller;
24-
use TYPO3\CMS\Backend\Routing\UriBuilder;
23+
use TYPO3\CMS\Backend\Template\ModuleTemplate;
2524
use TYPO3\CMS\Backend\Template\ModuleTemplateFactory;
25+
use TYPO3\CMS\Core\Http\ImmediateResponseException;
26+
use TYPO3\CMS\Core\Imaging\Icon;
2627
use TYPO3\CMS\Core\Imaging\IconFactory;
2728
use TYPO3\CMS\Core\Localization\LanguageService;
28-
use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
29-
use TYPO3\CMS\Extbase\Http\ForwardResponse;
29+
use TYPO3\CMS\Core\Page\JavaScriptModuleInstruction;
30+
use TYPO3\CMS\Core\Page\PageRenderer;
3031

3132
#[Controller]
3233
class FileController
3334
{
3435
public function __construct(
35-
protected IconFactory $iconFactory,
36-
protected UriBuilder $uriBuilder,
37-
protected ModuleTemplateFactory $moduleTemplateFactory,
38-
protected ResponseFactoryInterface $responseFactory,
39-
protected Converter $fileConverter,
40-
protected ExtensionService $extensionService
36+
protected readonly ModuleTemplateFactory $moduleTemplateFactory,
37+
protected readonly PageRenderer $pageRenderer,
38+
protected readonly Converter $fileConverter,
39+
protected readonly ExtensionService $extensionService,
40+
protected readonly IconFactory $iconFactory,
4141
) {
4242
}
4343

4444
public function indexAction(ServerRequestInterface $request): ResponseInterface
4545
{
46-
$view = $this->moduleTemplateFactory->create($request);
47-
$view->setTitle(
48-
$this->getLanguageService()->sL(
49-
'LLL:EXT:ew_llxml2xliff/Resources/Private/Language/locallang_mod.xlf:mlang_tabs_tab'
50-
)
51-
);
46+
try {
47+
[$extensions] = $this->prepareExtensions($request, false);
48+
} catch (\Exception) {
49+
$extensions = [];
50+
}
51+
52+
$view = $this->initializeModuleTemplate($request);
5253

53-
$extensions = $this->extensionService->getLocalExtensions();
5454
$view->assign('extensions', $extensions);
5555

5656
return $view->renderResponse('File/Index');
5757
}
5858

59+
/**
60+
* @throws ImmediateResponseException
61+
*/
5962
public function showFilesAction(ServerRequestInterface $request): ResponseInterface
6063
{
61-
$extensions = $this->extensionService->getLocalExtensions();
62-
$selectedExtension = $this->isArgumentSetAndAvailable($request, $extensions, 'extension');
63-
64-
if (!$selectedExtension) {
65-
$response = new ForwardResponse('index');
66-
} else {
67-
$view = $this->moduleTemplateFactory->create($request);
68-
$view->setTitle(
69-
$this->getLanguageService()->sL(
70-
'LLL:EXT:ew_llxml2xliff/Resources/Private/Language/locallang_mod.xlf:mlang_tabs_tab'
71-
)
72-
);
73-
74-
$files = $this->extensionService->getFilesOfExtension($selectedExtension);
75-
76-
$view->assign('extensions', $extensions);
77-
$view->assign('selectedExtension', $selectedExtension);
78-
$view->assign('files', $files);
79-
80-
$response = $view->renderResponse('File/ShowFiles');
64+
[$extensions, $selectedExtension] = $this->prepareExtensions($request);
65+
try {
66+
[$files] = $this->prepareFiles($request, $selectedExtension, false);
67+
} catch (\Exception) {
68+
$files = [];
8169
}
8270

83-
return $response;
71+
$view = $this->initializeModuleTemplate($request);
72+
73+
$view->assignMultiple([
74+
'extensions' => $extensions,
75+
'selectedExtension' => $selectedExtension,
76+
'files' => $files,
77+
]);
78+
79+
return $view->renderResponse('File/ShowFiles');
8480
}
8581

82+
/**
83+
* @throws ImmediateResponseException
84+
*/
8685
public function confirmConversionAction(ServerRequestInterface $request): ResponseInterface
8786
{
88-
$extensions = $this->extensionService->getLocalExtensions();
89-
$selectedExtension = $this->isArgumentSetAndAvailable($request, $extensions, 'extension');
87+
[$extensions, $selectedExtension] = $this->prepareExtensions($request);
88+
[$files, $selectedFile] = $this->prepareFiles($request, $selectedExtension);
9089

91-
if (!$selectedExtension) {
92-
$response = new ForwardResponse('index');
93-
} else {
94-
$files = $this->extensionService->getFilesOfExtension($selectedExtension);
95-
$selectedFile = $this->isArgumentSetAndAvailable($request, $files, 'file');
96-
97-
if (!$selectedFile) {
98-
$response = new ForwardResponse('showFiles');
99-
} else {
100-
$view = $this->moduleTemplateFactory->create($request);
101-
$view->setTitle(
102-
$this->getLanguageService()->sL(
103-
'LLL:EXT:ew_llxml2xliff/Resources/Private/Language/locallang_mod.xlf:mlang_tabs_tab'
104-
)
105-
);
106-
107-
$view->assign('extensions', $extensions);
108-
$view->assign('selectedExtension', $selectedExtension);
109-
$view->assign('files', $files);
110-
$view->assign('selectedFile', $selectedFile);
111-
$response = $view->renderResponse('File/ConfirmConversion');
112-
}
113-
}
90+
$view = $this->initializeModuleTemplate($request);
11491

115-
return $response;
92+
$view->assignMultiple([
93+
'extensions' => $extensions,
94+
'selectedExtension' => $selectedExtension,
95+
'files' => $files,
96+
'selectedFile' => $selectedFile,
97+
]);
98+
99+
return $view->renderResponse('File/ConfirmConversion');
116100
}
117101

102+
/**
103+
* @throws ImmediateResponseException
104+
*/
118105
public function convertFileAction(ServerRequestInterface $request): ResponseInterface
106+
{
107+
[$extensions, $selectedExtension] = $this->prepareExtensions($request);
108+
[$files, $selectedFile] = $this->prepareFiles($request, $selectedExtension);
109+
110+
$conversionResult = $this->extensionService->convertLanguageFile($selectedExtension, $selectedFile, $files);
111+
112+
$view = $this->initializeModuleTemplate($request);
113+
114+
$view->assignMultiple([
115+
'extensions' => $extensions,
116+
'selectedExtension' => $selectedExtension,
117+
'files' => $files,
118+
'selectedFile' => $selectedFile,
119+
...$conversionResult,
120+
]);
121+
122+
return $view->renderResponse('File/ConvertFile');
123+
}
124+
125+
/**
126+
* @throws ImmediateResponseException
127+
*/
128+
protected function prepareExtensions(ServerRequestInterface $request, bool $selected = true): array
119129
{
120130
$extensions = $this->extensionService->getLocalExtensions();
121-
$selectedExtension = $this->isArgumentSetAndAvailable($request, $extensions, 'extension');
131+
$selectedExtension = $selected ? $this->getSelectedExtension($request, $extensions) : '';
132+
133+
foreach ($extensions as &$extension) {
134+
$extension['selected'] = $extension['key'] === $selectedExtension ? ' selected="selected"' : '';
135+
}
136+
137+
return [$extensions, $selectedExtension];
138+
}
139+
140+
/**
141+
* @throws ImmediateResponseException
142+
*/
143+
protected function prepareFiles(ServerRequestInterface $request, string $extension, bool $selected = true): array
144+
{
145+
$files = $this->extensionService->getFilesOfExtension($extension);
146+
$selectedFile = $selected ? $this->getSelectedFile($request, $files) : '';
147+
148+
foreach ($files as &$file) {
149+
$file['selected'] = $file['filename'] === $selectedFile ? ' selected="selected"' : '';
150+
}
151+
152+
return [$files, $selectedFile];
153+
}
122154

155+
/**
156+
* @throws ImmediateResponseException
157+
*/
158+
protected function getSelectedExtension(ServerRequestInterface $request, array $extensions): string
159+
{
160+
$selectedExtension = $this->isArgumentSetAndAvailable($request, $extensions, 'extension');
123161
if (!$selectedExtension) {
124-
$response = new ForwardResponse('index');
125-
} else {
126-
$files = $this->extensionService->getFilesOfExtension($selectedExtension);
127-
$selectedFile = $this->isArgumentSetAndAvailable($request, $files, 'file');
128-
129-
if (!$selectedFile) {
130-
$response = new ForwardResponse('showFiles');
131-
} else {
132-
$view = $this->moduleTemplateFactory->create($request);
133-
$view->setTitle(
134-
$this->getLanguageService()->sL(
135-
'LLL:EXT:ew_llxml2xliff/Resources/Private/Language/locallang_mod.xlf:mlang_tabs_tab'
136-
)
137-
);
138-
139-
$extensionPath = ExtensionManagementUtility::extPath($selectedExtension);
140-
if ($this->extensionService->xliffFileAlreadyExists($extensionPath, $selectedFile)) {
141-
$view->assign('wasConvertedPreviously', 1);
142-
} else {
143-
$this->fileConverter->setExtension($selectedExtension);
144-
if (str_contains($selectedFile, '.xml')) {
145-
$messages = $this->fileConverter->writeXmlAsXlfFilesInPlace($selectedFile);
146-
} else {
147-
$messages = $this->fileConverter->writePhpAsXlfFilesInPlace($selectedFile);
148-
}
149-
150-
if (!str_contains($messages, 'ERROR')) {
151-
$view->assign('fileConvertedSuccessfully', 1);
152-
}
153-
$view->assign('messages', $messages);
154-
unset($files[$selectedFile]);
155-
}
156-
157-
$view->assign('extensions', $extensions);
158-
$view->assign('selectedExtension', $selectedExtension);
159-
$view->assign('files', $files);
160-
$view->assign('selectedFile', '');
161-
$view->assign('convertedFile', $selectedFile);
162-
$response = $view->renderResponse('File/ConvertFile');
163-
}
162+
throw new ImmediateResponseException($this->indexAction($request));
164163
}
164+
return $selectedExtension;
165+
}
165166

166-
return $response;
167+
/**
168+
* @throws ImmediateResponseException
169+
*/
170+
protected function getSelectedFile(ServerRequestInterface $request, array $files): string
171+
{
172+
$selectedFile = $this->isArgumentSetAndAvailable($request, $files, 'file');
173+
if (!$selectedFile) {
174+
throw new ImmediateResponseException($this->showFilesAction($request));
175+
}
176+
return $selectedFile;
167177
}
168178

169179
protected function isArgumentSetAndAvailable(ServerRequestInterface $request, array $values, string $key): ?string
@@ -173,6 +183,21 @@ protected function isArgumentSetAndAvailable(ServerRequestInterface $request, ar
173183
return empty($values) || empty($formFieldValue) || !isset($values[$formFieldValue]) ? null : $formFieldValue;
174184
}
175185

186+
protected function initializeModuleTemplate(ServerRequestInterface $request): ModuleTemplate
187+
{
188+
$this->pageRenderer->getJavaScriptRenderer()->addJavaScriptModuleInstruction(
189+
JavaScriptModuleInstruction::create('@evoweb/ew-llxml2xliff/form.js')
190+
);
191+
$this->pageRenderer->addCssFile('EXT:ew_llxml2xliff/Resources/Public/Css/form.css');
192+
193+
$moduleTemplate = $this->moduleTemplateFactory->create($request);
194+
$moduleTemplate->setTitle(
195+
$this->getLanguageService()
196+
->sL('LLL:EXT:ew_llxml2xliff/Resources/Private/Language/locallang_mod.xlf:mlang_tabs_tab')
197+
);
198+
return $moduleTemplate;
199+
}
200+
176201
protected function getLanguageService(): LanguageService
177202
{
178203
return $GLOBALS['LANG'];

Classes/File/Converter.php

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
namespace Evoweb\EwLlxml2xliff\File;
2929

3030
use Evoweb\EwLlxml2xliff\Localization\Parser\LocallangXmlParser;
31+
use TYPO3\CMS\Core\Core\Environment;
3132
use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
3233
use TYPO3\CMS\Core\Utility\GeneralUtility;
3334

@@ -49,8 +50,6 @@ public function setExtension(string $extension): void
4950
* Function to convert llxml files
5051
*
5152
* @param string $sourceFile Absolute path to the selected ll-XML file
52-
*
53-
* @return string HTML content
5453
*/
5554
public function writeXmlAsXlfFilesInPlace(string $sourceFile): string
5655
{
@@ -87,7 +86,7 @@ public function writeXmlAsXlfFilesInPlace(string $sourceFile): string
8786
$output = '';
8887
foreach ($languages as $langKey) {
8988
$newFileName = $dirname . '/' . $this->localizedFileRef($sourceFileOriginal, $langKey);
90-
$output .= $this->writeNewXliffFile($sourceFile, $newFileName, $langKey) . '<br />';
89+
$output .= $this->writeNewXliffFile($sourceFile, $newFileName, $langKey) . '<br />' . LF;
9190
}
9291
return $output;
9392
}
@@ -96,8 +95,6 @@ public function writeXmlAsXlfFilesInPlace(string $sourceFile): string
9695
* Function to convert php language files
9796
*
9897
* @param string $sourceFile Absolute path to the selected ll-XML file
99-
*
100-
* @return string HTML content
10198
*/
10299
public function writePhpAsXlfFilesInPlace(string $sourceFile): string
103100
{
@@ -154,8 +151,8 @@ protected function localizedFileRef(string $fileRef, string $lang): string
154151
{
155152
$path = '';
156153
if (str_ends_with($fileRef, '.xml') || str_ends_with($fileRef, '.php')) {
157-
$lang = $lang === 'default' ? '' : $lang . '.';
158-
$path = $lang . pathinfo($fileRef, PATHINFO_FILENAME) . '.xlf';
154+
$languagePrefix = $lang === 'default' ? '' : $lang . '.';
155+
$path = $languagePrefix . pathinfo($fileRef, PATHINFO_FILENAME) . '.xlf';
159156
}
160157
return $path;
161158
}
@@ -174,11 +171,11 @@ protected function writeNewXliffFile(string $xmlFile, string $newFileName, strin
174171
$xml = $this->generateFileContent($xmlFile, $langKey);
175172

176173
$result = '';
177-
if (!file_exists($newFileName)) {
174+
if (!@file_exists($newFileName)) {
178175
GeneralUtility::writeFile($newFileName, $xml);
179-
180-
$result = $newFileName;
176+
$result = str_replace(Environment::getComposerRootPath(), '', $newFileName);
181177
}
178+
182179
return $result;
183180
}
184181

@@ -254,11 +251,11 @@ protected function generateFileContent(string $xmlFile, string $langKey): string
254251
*/
255252
protected function getCombinedTranslationFileContent(string $languageFile): array
256253
{
254+
$LOCAL_LANG = [];
257255
if (strpos($languageFile, '.xml')) {
258-
$ll = GeneralUtility::xml2array(file_get_contents($languageFile));
256+
$ll = $this->xml2array(file_get_contents($languageFile));
259257
$includedLanguages = array_keys($ll['data']);
260258

261-
$LOCAL_LANG = [];
262259
foreach ($includedLanguages as $langKey) {
263260
/** @var $parser LocallangXmlParser */
264261
$parser = GeneralUtility::makeInstance(LocallangXmlParser::class);
@@ -275,7 +272,6 @@ protected function getCombinedTranslationFileContent(string $languageFile): arra
275272
throw new \RuntimeException('data section not found in "' . $languageFile . '"', 1314187884);
276273
}
277274

278-
/** @noinspection PhpUndefinedVariableInspection */
279275
return $LOCAL_LANG;
280276
}
281277

0 commit comments

Comments
 (0)