-
Notifications
You must be signed in to change notification settings - Fork 40
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[TASK] Change Dropdown rendering for translations
Getting rid of x-classing is the goal and with v12 an event is provided manipulating the header of the RecordListController. In favour of using this event instead of x-classing the original class, an event listener is added generating the dropdown and adding top-most of the recordlist. This has effects on positioning of the translation dropdown, which now is rendered before the core dropdown instead of next to it.
- Loading branch information
Showing
10 changed files
with
244 additions
and
472 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace WebVision\Deepltranslate\Core\Event\Listener; | ||
|
||
use Psr\EventDispatcher\EventDispatcherInterface; | ||
use TYPO3\CMS\Backend\Controller\Event\RenderAdditionalContentToRecordListEvent; | ||
use TYPO3\CMS\Core\Site\Entity\Site; | ||
use WebVision\Deepltranslate\Core\Event\RenderLocalizationSelectAllowed; | ||
use WebVision\Deepltranslate\Core\Form\TranslationDropdownGenerator; | ||
|
||
final class RenderLocalizationSelect | ||
{ | ||
public function __construct( | ||
private readonly TranslationDropdownGenerator $generator, | ||
private readonly EventDispatcherInterface $eventDispatcher | ||
) { | ||
} | ||
|
||
public function __invoke(RenderAdditionalContentToRecordListEvent $event): void | ||
{ | ||
$request = $event->getRequest(); | ||
// Check, if some event listener doesn't allow rendering here. | ||
// For use cases see Event | ||
$renderingAllowedEvent = $this->eventDispatcher->dispatch(new RenderLocalizationSelectAllowed($request)); | ||
if ($renderingAllowedEvent->renderingAllowed === false) { | ||
return; | ||
} | ||
/** @var Site $site */ | ||
$site = $request->getAttribute('site'); | ||
$siteLanguages = $site->getLanguages(); | ||
$options = $this->generator->buildTranslateDropdownOptions($siteLanguages, (int)$request->getQueryParams()['id'], $request->getUri()); | ||
if ($options !== '') { | ||
$additionalHeader = '<div class="form-row">' | ||
. '<div class="form-group">' | ||
. '<select class="form-select" name="createNewLanguage" data-global-event="change" data-action-navigate="$value">' | ||
. $options | ||
. '</select>' | ||
. '</div>' | ||
. '</div>'; | ||
$event->addContentAbove($additionalHeader); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace WebVision\Deepltranslate\Core\Event; | ||
|
||
use Psr\Http\Message\RequestInterface; | ||
|
||
/** | ||
* Event deciding if the localization dropdown should be rendered. | ||
* Could be used avoiding rendering for special cases, e.g., glossary or access denied. | ||
*/ | ||
final class RenderLocalizationSelectAllowed | ||
{ | ||
public function __construct( | ||
public readonly RequestInterface $request, | ||
public bool $renderingAllowed = true | ||
) { | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace WebVision\Deepltranslate\Core\Form; | ||
|
||
use Psr\Http\Message\UriInterface; | ||
use TYPO3\CMS\Core\Authentication\BackendUserAuthentication; | ||
use TYPO3\CMS\Core\Database\Connection; | ||
use TYPO3\CMS\Core\Database\ConnectionPool; | ||
use TYPO3\CMS\Core\Database\Query\Restriction\DeletedRestriction; | ||
use TYPO3\CMS\Core\Database\Query\Restriction\WorkspaceRestriction; | ||
use TYPO3\CMS\Core\Localization\LanguageService; | ||
use TYPO3\CMS\Core\Localization\LanguageServiceFactory; | ||
use TYPO3\CMS\Core\Site\Entity\SiteLanguage; | ||
use TYPO3\CMS\Core\Utility\GeneralUtility; | ||
use WebVision\Deepltranslate\Core\Utility\DeeplBackendUtility; | ||
|
||
/** | ||
* Generates the dropdown for language selector | ||
* | ||
* @internal only for usage inside deepltranslate-core, no public API | ||
*/ | ||
final class TranslationDropdownGenerator | ||
{ | ||
public function __construct() | ||
{ | ||
} | ||
|
||
/** | ||
* @param iterable<SiteLanguage> $siteLanguages | ||
* @throws \Doctrine\DBAL\Exception | ||
* @throws \TYPO3\CMS\Backend\Routing\Exception\RouteNotFoundException | ||
*/ | ||
public function buildTranslateDropdownOptions( | ||
$siteLanguages, | ||
int $id, | ||
string|UriInterface $requestUri | ||
): string { | ||
$availableTranslations = []; | ||
foreach ($siteLanguages as $siteLanguage) { | ||
if ( | ||
$siteLanguage->getLanguageId() === 0 | ||
|| $siteLanguage->getLanguageId() === -1 | ||
) { | ||
continue; | ||
} | ||
$availableTranslations[$siteLanguage->getLanguageId()] = $siteLanguage->getTitle(); | ||
} | ||
// Then, subtract the languages which are already on the page: | ||
$localizationParentField = $GLOBALS['TCA']['pages']['ctrl']['transOrigPointerField']; | ||
$languageField = $GLOBALS['TCA']['pages']['ctrl']['languageField']; | ||
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('pages'); | ||
$queryBuilder->getRestrictions()->removeAll() | ||
->add(GeneralUtility::makeInstance(DeletedRestriction::class)) | ||
->add( | ||
GeneralUtility::makeInstance( | ||
WorkspaceRestriction::class, | ||
(int)$this->getBackendUser()?->workspace | ||
) | ||
); | ||
$statement = $queryBuilder | ||
->select('uid', $languageField) | ||
->from('pages') | ||
->where( | ||
$queryBuilder->expr()->eq( | ||
$localizationParentField, | ||
$queryBuilder->createNamedParameter($id, Connection::PARAM_INT) | ||
) | ||
) | ||
->executeQuery(); | ||
while ($pageTranslation = $statement->fetchAssociative()) { | ||
unset($availableTranslations[(int)$pageTranslation[$languageField]]); | ||
} | ||
// If any languages are left, make selector: | ||
if (!empty($availableTranslations)) { | ||
$output = ''; | ||
foreach ($availableTranslations as $languageUid => $languageTitle) { | ||
// check if language can be translated with DeepL | ||
// otherwise continue to next | ||
if (!DeeplBackendUtility::checkCanBeTranslated($id, $languageUid)) { | ||
continue; | ||
} | ||
// Build localize command URL to DataHandler (tce_db) | ||
// which redirects to FormEngine (record_edit) | ||
// which, when finished editing should return back to the current page (returnUrl) | ||
$parameters = [ | ||
'justLocalized' => 'pages:' . $id . ':' . $languageUid, | ||
'returnUrl' => (string)$requestUri, | ||
]; | ||
$redirectUrl = DeeplBackendUtility::buildBackendRoute('record_edit', $parameters); | ||
$params = []; | ||
$params['redirect'] = $redirectUrl; | ||
$params['cmd']['pages'][$id]['localize'] = $languageUid; | ||
$params['cmd']['localization']['custom']['mode'] = 'deepl'; | ||
$targetUrl = DeeplBackendUtility::buildBackendRoute('tce_db', $params); | ||
$output .= '<option value="' . htmlspecialchars($targetUrl) . '">' . htmlspecialchars($languageTitle) . '</option>'; | ||
} | ||
if ($output !== '') { | ||
$output = sprintf( | ||
'<option value="">%s</option>%s', | ||
htmlspecialchars($this->getLocalization()->sL('LLL:EXT:deepltranslate_core/Resources/Private/Language/locallang.xlf:backend.label')), | ||
$output | ||
); | ||
} | ||
|
||
return $output; | ||
} | ||
return ''; | ||
} | ||
|
||
private function getLocalization(): LanguageService | ||
{ | ||
return GeneralUtility::makeInstance(LanguageServiceFactory::class) | ||
->createFromUserPreferences($this->getBackendUser()); | ||
} | ||
|
||
private function getBackendUser(): ?BackendUserAuthentication | ||
{ | ||
return $GLOBALS['BE_USER'] ?? null; | ||
} | ||
} |
Oops, something went wrong.