Initial commit - Typo3 11.5.41

This commit is contained in:
Matteo Gallo
2026-07-03 17:53:31 +02:00
commit 5ca4743197
6811 changed files with 568848 additions and 0 deletions

View File

@@ -0,0 +1,105 @@
<?php
namespace SJBR\StaticInfoTables\Cache;
/*
* Copyright notice
*
* (c) 2013-2022 Stanislas Rolland <typo3AAAA(arobas)sjbr.ca>
* All rights reserved
*
* This script is part of the TYPO3 project. The TYPO3 project is
* free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* The GNU General Public License can be found at
* http://www.gnu.org/copyleft/gpl.html.
* A copy is found in the textfile GPL.txt and important notices to the license
* from the author is found in LICENSE.txt distributed with these scripts.
*
*
* This script is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* This copyright notice MUST APPEAR in all copies of the script!
*/
use TYPO3\CMS\Core\Cache\CacheManager;
use TYPO3\CMS\Core\Utility\GeneralUtility;
/**
* Cached classes autoloader
*/
class CachedClassLoader
{
/**
* Extension key
*
* @var string
*/
protected static $extensionKey = 'static_info_tables';
/**
* Cached class loader class name
*
* @var string
*/
protected static $className = __CLASS__;
/**
* Name space of the Domain Model of StaticInfoTables
*
* @var string
*/
protected static $namespace = 'SJBR\\StaticInfoTables\\Domain\\Model\\';
/**
* The class loader is static, thus we do not allow instances of this class.
*/
private function __construct()
{
}
/**
* Registers the cached class loader
*
* @return bool TRUE in case of success
*/
public static function registerAutoloader()
{
return spl_autoload_register(static::$className . '::autoload', true, true);
}
/**
* Autoload function for cached classes
*
* @param string $className Class name
* @return void
*/
public static function autoload($className)
{
$className = ltrim($className, '\\');
if (strpos($className, static::$namespace) !== false) {
// Lookup the class in the array of static info entities and check its presence in the class cache
$entities = $GLOBALS['TYPO3_CONF_VARS']['EXTENSIONS'][static::$extensionKey]['entities'] ?? [];
// ClassCacheManager instantiation creates the class cache if not already available
$classCacheManager = GeneralUtility::makeInstance(ClassCacheManager::class);
$cacheManager = GeneralUtility::makeInstance(CacheManager::class);
$classCache = $cacheManager->getCache(static::$extensionKey);
foreach ($entities as $entity) {
if ($className === static::$namespace . $entity) {
$entryIdentifier = 'DomainModel' . $entity;
if (!$classCache->has($entryIdentifier)) {
// The class cache needs to be rebuilt
$classCacheManager->reBuild();
}
$classCache->requireOnce($entryIdentifier);
break;
}
}
}
}
}

View File

@@ -0,0 +1,284 @@
<?php
namespace SJBR\StaticInfoTables\Cache;
/*
* Copyright notice
* (c) 2012 Georg Ringer <typo3@ringerge.org>
* (c) 2013-2022 Stanislas Rolland <typo3AAAA(arobas)sjbr.ca>
*
* All rights reserved
*
* This script is part of the TYPO3 project. The TYPO3 project is
* free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
* The GNU General Public License can be found at
* http://www.gnu.org/copyleft/gpl.html.
* This script is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* This copyright notice MUST APPEAR in all copies of the script!
*/
use TYPO3\CMS\Core\Cache\Backend\FileBackend;
use TYPO3\CMS\Core\Cache\CacheManager;
use TYPO3\CMS\Core\Cache\Frontend\FrontendInterface;
use TYPO3\CMS\Core\Cache\Frontend\PhpFrontend;
use TYPO3\CMS\Core\SingletonInterface;
use TYPO3\CMS\Core\Utility\ArrayUtility;
use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
use TYPO3\CMS\Core\Utility\GeneralUtility;
/**
* Class Cache Manager
*/
class ClassCacheManager implements SingletonInterface
{
/**
* Extension key
*
* @var string
*/
protected $extensionKey = 'static_info_tables';
/**
* @var array Cache configurations
*/
protected $cacheConfiguration = [
'static_info_tables' => [
'frontend' => PhpFrontend::class,
'backend' => FileBackend::class,
'options' => [],
'groups' => ['all'],
],
];
/**
* Cache manager
*
* @var CacheManager
*/
private $cacheManager;
/**
* @var FrontendInterface
*/
protected $cacheInstance;
/**
* Constructor
*/
public function __construct(CacheManager $cacheManager)
{
$this->cacheManager = $cacheManager;
$this->initializeCache();
}
/**
* Initialize cache instance to be ready to use
*
* @return void
*/
protected function initializeCache()
{
if (!$this->cacheManager->hasCache($this->extensionKey)) {
if (isset($GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations'][$this->extensionKey]) &&
is_array($GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations'][$this->extensionKey])) {
ArrayUtility::mergeRecursiveWithOverrule($this->cacheConfiguration[$this->extensionKey], $GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations'][$this->extensionKey]);
}
$this->cacheManager->setCacheConfigurations($this->cacheConfiguration);
}
$this->cacheInstance = $this->cacheManager->getCache($this->extensionKey);
}
/**
* Builds and caches the proxy files
*
* @return void
* @throws \Exception
*/
public function build()
{
$extensibleExtensions = $this->getExtensibleExtensions();
$entities = $GLOBALS['TYPO3_CONF_VARS']['EXTENSIONS'][$this->extensionKey]['entities'] ?? [];
foreach ($entities as $entity) {
$key = 'Domain/Model/' . $entity;
// Get the file from static_info_tables itself, this needs to be loaded as first
$path = ExtensionManagementUtility::extPath($this->extensionKey) . 'Classes/' . $key . '.php';
if (!is_file($path)) {
throw new \Exception('given file "' . $path . '" does not exist');
}
$code = $this->parseSingleFile($path, false);
// Get the files from all other extensions that are extending this domain model class
if (isset($extensibleExtensions[$key]) && is_array($extensibleExtensions[$key]) && count($extensibleExtensions[$key]) > 0) {
$extensionsWithThisClass = array_keys($extensibleExtensions[$key]);
foreach ($extensionsWithThisClass as $extension) {
$path = ExtensionManagementUtility::extPath($extension) . 'Classes/' . $key . '.php';
if (is_file($path)) {
$code .= $this->parseSingleFile($path);
}
}
}
// Close the class definition and the php tag
$code = $this->closeClassDefinition($code);
// The file is added to the class cache
$entryIdentifier = str_replace('/', '', $key);
try {
$this->cacheInstance->set($entryIdentifier, $code);
} catch (\Exception $e) {
throw new \Exception($e->getMessage());
}
}
}
/**
* Get all loaded extensions which try to extend EXT:static_info_tables
*
* @return array
*/
protected function getExtensibleExtensions()
{
$loadedExtensions = array_unique(ExtensionManagementUtility::getLoadedExtensionListArray());
// Get the extensions which want to extend static_info_tables
$extensibleExtensions = [];
foreach ($loadedExtensions as $extensionKey) {
$extensionInfoFile = ExtensionManagementUtility::extPath($extensionKey) . 'Configuration/DomainModelExtension/StaticInfoTables.txt';
if (file_exists($extensionInfoFile)) {
$info = GeneralUtility::getUrl($extensionInfoFile);
$classes = GeneralUtility::trimExplode(LF, $info, true);
foreach ($classes as $class) {
$extensibleExtensions[$class][$extensionKey] = 1;
}
}
}
return $extensibleExtensions;
}
/**
* Parse a single file and does some magic
* - Remove the php tags
* - Remove the class definition (if set)
*
* @param string $filePath path of the file
* @param bool $removeClassDefinition If class definition should be removed
* @return string path of the saved file
* @throws \Exception
* @throws \InvalidArgumentException
*/
public function parseSingleFile($filePath, $removeClassDefinition = true)
{
if (!is_file($filePath)) {
throw new \InvalidArgumentException(sprintf('File "%s" could not be found', $filePath));
}
$code = GeneralUtility::getUrl($filePath);
return $this->changeCode($code, $filePath, $removeClassDefinition);
}
/**
* @param string $code
* @param string $filePath
* @param bool $removeClassDefinition
* @param bool $renderPartialInfo
* @return string
* @throws \Exception
*/
protected function changeCode($code, $filePath, $removeClassDefinition = true, $renderPartialInfo = true)
{
if (empty($code)) {
throw new \InvalidArgumentException(sprintf('File "%s" could not be fetched or is empty', $filePath));
}
$code = trim($code);
$code = str_replace(['<?php', '?>'], '', $code);
$code = trim($code);
// Remove everything before 'class ', including namespaces,
// comments and require-statements.
if ($removeClassDefinition) {
$pos = strpos($code, 'class ');
$pos2 = strpos($code, '{', $pos);
$code = substr($code, $pos2 + 1);
}
$code = trim($code);
// Add some information for each partial
if ($renderPartialInfo) {
$code = $this->getPartialInfo($filePath) . $code;
}
// Remove last }
$pos = strrpos($code, '}');
$code = substr($code, 0, $pos);
$code = trim($code);
return $code . LF . LF;
}
protected function getPartialInfo($filePath)
{
return '/*' . str_repeat('*', 70) . LF .
' * this is partial from: ' . $filePath . LF . str_repeat('*', 70) . '*/' . LF . chr(9);
}
protected function closeClassDefinition($code)
{
return $code . LF . '}';
}
/**
* Clear the class cache
*
* @return void
*/
public function clear()
{
$this->cacheInstance->flush();
if (isset($GLOBALS['BE_USER']) && isset($GLOBALS['BE_USER']->user)) {
$GLOBALS['BE_USER']->writelog(3, 1, 0, 0, '[StaticInfoTables]: User %s has cleared the class cache', [$GLOBALS['BE_USER']->user['username']]);
}
}
/**
* Rebuild the class cache
*
* @param array $parameters
* @return void
* @throws \Exception
*/
public function reBuild(array $parameters = [])
{
$isValidCall = (
empty($parameters)
|| (
!empty($parameters['cacheCmd'])
&& GeneralUtility::inList('all,temp_cached', $parameters['cacheCmd'])
&& isset($GLOBALS['BE_USER'])
)
);
if ($isValidCall) {
$this->clear();
$this->clearReflectionCache();
$this->build();
}
}
/**
* Drop the reflection cache
*/
protected function clearReflectionCache()
{
if ($this->cacheManager->hasCache('extbase_reflection')) {
$this->cacheManager->getCache('extbase_reflection')->flush();
}
if ($this->cacheManager->hasCache('extbase_datamapfactory_datamap')) {
$this->cacheManager->getCache('extbase_datamapfactory_datamap')->flush();
}
}
}

View File

@@ -0,0 +1,68 @@
<?php
namespace SJBR\StaticInfoTables\Configuration\Tca;
/*
* Copyright notice
*
* (c) 2017 Manuel Selbach <manuel_selbach@yahoo.de>
* (c) 2020-2022 Stanislas Rolland <typo3AAAA(arobas)sjbr.ca>
* All rights reserved
*
* This script is part of the TYPO3 project. The TYPO3 project is
* free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* The GNU General Public License can be found at
* http://www.gnu.org/copyleft/gpl.html.
* A copy is found in the text file GPL.txt and important notices to the license
* from the author is found in LICENSE.txt distributed with these scripts.
*
*
* This script is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* This copyright notice MUST APPEAR in all copies of the script!
*/
use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
class Provider
{
/**
* @var string Path to language file of labels in the backend
*/
protected static $LL = 'LLL:EXT:%s/Resources/Private/Language/locallang_db.xlf:%s_item.%s';
/**
* @param $additionalFields
* @param $tableName
* @return void
*/
public static function addTcaColumnConfiguration($extensionKey, $tableName, $additionalFields)
{
foreach ($additionalFields as $sourceField => $destField) {
$additionalColumns = [];
$additionalColumns[$destField] = $GLOBALS['TCA'][$tableName]['columns'][$sourceField] ?? [];
$additionalColumns[$destField]['label'] = sprintf(
static::$LL,
$extensionKey,
$tableName,
$destField
);
ExtensionManagementUtility::addTCAcolumns($tableName, $additionalColumns);
ExtensionManagementUtility::addToAllTCAtypes(
$tableName,
$destField,
'',
'after:' . $sourceField
);
// Add as search field
$GLOBALS['TCA'][$tableName]['ctrl']['searchFields'] .= ',' . $destField;
}
}
}

View File

@@ -0,0 +1,126 @@
<?php
namespace SJBR\StaticInfoTables\Configuration\TypoScript;
/*
* Copyright notice
*
* (c) 2013-2022 Stanislas Rolland <typo3AAAA(arobas)sjbr.ca>
* All rights reserved
*
* This script is part of the TYPO3 project. The TYPO3 project is
* free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* The GNU General Public License can be found at
* http://www.gnu.org/copyleft/gpl.html.
* A copy is found in the textfile GPL.txt and important notices to the license
* from the author is found in LICENSE.txt distributed with these scripts.
*
*
* This script is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* This copyright notice MUST APPEAR in all copies of the script!
*/
use SJBR\StaticInfoTables\Domain\Repository\CountryRepository;
use SJBR\StaticInfoTables\Domain\Repository\CountryZoneRepository;
use SJBR\StaticInfoTables\Domain\Repository\CurrencyRepository;
use SJBR\StaticInfoTables\Domain\Repository\LanguageRepository;
use SJBR\StaticInfoTables\Utility\HtmlElementUtility;
use TYPO3\CMS\Core\TypoScript\ExtendedTemplateService;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Extbase\Configuration\ConfigurationManager;
use TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface;
/**
* Class providing TypoScript configuration help for Static Info Tables
*/
class ConfigurationHelper
{
/**
* Renders a select element to select an entity
*
* @param array $params: Field information to be rendered
* @param \TYPO3\CMS\Core\TypoScript\ExtendedTemplateService $pObj: The calling parent object.
* @param mixed $arg
*
* @return string The HTML input field
*/
public function buildEntitySelector(array $params, ExtendedTemplateService $pObj, $arg = '')
{
$field = '';
switch ($params['fieldName'] ?? '') {
case 'data[plugin.tx_staticinfotables_pi1.countryCode]':
case 'data[plugin.tx_staticinfotables_pi1.countriesAllowed]':
$repository = GeneralUtility::makeInstance(CountryRepository::class);
$entities = $repository->findAllOrderedBy('nameLocalized');
break;
case 'data[plugin.tx_staticinfotables_pi1.countryZoneCode]':
$repository = GeneralUtility::makeInstance(CountryZoneRepository::class);
$countryCode = $this->getConfiguredCountryCode();
if ($countryCode) {
$countryRepository = GeneralUtility::makeInstance(CountryRepository::class);
$country = $countryRepository->findOneByIsoCodeA3($countryCode);
if (is_object($country)) {
$entities = $repository->findByCountryOrderedByLocalizedName($country);
}
}
if (!$countryCode || (empty($entities) && $params['fieldValue'])) {
$entities = $repository->findAllOrderedBy('nameLocalized');
}
break;
case 'data[plugin.tx_staticinfotables_pi1.currencyCode]':
$repository = GeneralUtility::makeInstance(CurrencyRepository::class);
$entities = $repository->findAllOrderedBy('nameLocalized');
break;
case 'data[plugin.tx_staticinfotables_pi1.languageCode]':
$repository = GeneralUtility::makeInstance(LanguageRepository::class);
$entities = $repository->findAllNonConstructedNonSacred();
$entities = $repository->localizedSort($entities);
break;
}
if (is_array($entities) && count($entities)) {
$options = [];
foreach ($entities as $entity) {
switch ($params['fieldName'] ?? '') {
case 'data[plugin.tx_staticinfotables_pi1.countryZoneCode]':
$value = $entity->getIsoCode();
$options[] = ['name' => $entity->getNameLocalized() . ' (' . $value . ')', 'value' => $value];
break;
case 'data[plugin.tx_staticinfotables_pi1.countryCode]':
case 'data[plugin.tx_staticinfotables_pi1.countriesAllowed]':
case 'data[plugin.tx_staticinfotables_pi1.currencyCode]':
$value = $entity->getIsoCodeA3();
$options[] = ['name' => $entity->getNameLocalized() . ' (' . $value . ')', 'value' => $value];
break;
case 'data[plugin.tx_staticinfotables_pi1.languageCode]':
$countryCode = $entity->getCountryIsoCodeA2();
$value = $entity->getIsoCodeA2() . ($countryCode ? '_' . $countryCode : '');
$options[] = ['name' => $entity->getNameLocalized() . ' (' . $value . ')', 'value' => $value];
break;
}
}
$outSelected = [];
$size = $params['fieldName'] == 'data[plugin.tx_staticinfotables_pi1.countriesAllowed]' ? 5 : 1;
$field = HtmlElementUtility::selectConstructor($options, [$params['fieldValue']], $outSelected, $params['fieldName'], '', '', '', '', $size);
}
return $field;
}
/**
* Gets the configured default country code
*
* @return string The configured default country code
*/
protected function getConfiguredCountryCode()
{
$configurationManager = GeneralUtility::makeInstance(ConfigurationManager::class);
$settings = $configurationManager->getConfiguration(ConfigurationManagerInterface::CONFIGURATION_TYPE_FULL_TYPOSCRIPT);
return $settings['plugin.']['tx_staticinfotables_pi1.']['countryCode'];
}
}

View File

@@ -0,0 +1,329 @@
<?php
namespace SJBR\StaticInfoTables\Controller;
/*
* Copyright notice
*
* (c) 2013-2021 Stanislas Rolland <typo3AAAA(arobas)sjbr.ca>
* All rights reserved
*
* This script is part of the TYPO3 project. The TYPO3 project is
* free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* The GNU General Public License can be found at
* http://www.gnu.org/copyleft/gpl.html.
* A copy is found in the textfile GPL.txt and important notices to the license
* from the author is found in LICENSE.txt distributed with these scripts.
*
*
* This script is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* This copyright notice MUST APPEAR in all copies of the script!
*/
use SJBR\StaticInfoTables\Domain\Model\Country;
use SJBR\StaticInfoTables\Domain\Model\CountryZone;
use SJBR\StaticInfoTables\Domain\Model\Language;
use SJBR\StaticInfoTables\Domain\Model\LanguagePack;
use SJBR\StaticInfoTables\Domain\Repository\CountryRepository;
use SJBR\StaticInfoTables\Domain\Repository\CountryZoneRepository;
use SJBR\StaticInfoTables\Domain\Repository\CurrencyRepository;
use SJBR\StaticInfoTables\Domain\Repository\LanguageRepository;
use SJBR\StaticInfoTables\Domain\Repository\LanguagePackRepository;
use SJBR\StaticInfoTables\Domain\Repository\TerritoryRepository;
use SJBR\StaticInfoTables\Utility\LocaleUtility;
use TYPO3\CMS\Core\Localization\Locales;
use TYPO3\CMS\Core\Messaging\AbstractMessage;
use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Extbase\Mvc\Controller\ActionController;
use TYPO3\CMS\Extbase\Utility\LocalizationUtility;
/**
* Static Info Tables Manager controller
*/
class ManagerController extends ActionController
{
/**
* @var string Name of the extension this controller belongs to
*/
protected $extensionName = 'StaticInfoTables';
/**
* @var CountryRepository
*/
protected $countryRepository;
/**
* Dependency injection of the Country Repository
*
* @param CountryRepository $countryRepository
* @return void
*/
public function injectCountryRepository(CountryRepository $countryRepository)
{
$this->countryRepository = $countryRepository;
}
/**
* @var CountryZoneRepository
*/
protected $countryZoneRepository;
/**
* Dependency injection of the Country Zone Repository
*
* @param CountryZoneRepository $countryZoneRepository
* @return void
*/
public function injectCountryZoneRepository(CountryZoneRepository $countryZoneRepository)
{
$this->countryZoneRepository = $countryZoneRepository;
}
/**
* @var CurrencyRepository
*/
protected $currencyRepository;
/**
* Dependency injection of the Currency Repository
*
* @param CurrencyRepository $currencyRepository
* @return void
*/
public function injectCurrencyRepository(CurrencyRepository $currencyRepository)
{
$this->currencyRepository = $currencyRepository;
}
/**
* @var LanguageRepository
*/
protected $languageRepository;
/**
* Dependency injection of the Language Repository
*
* @param LanguageRepository $languageRepository
* @return void
*/
public function injectLanguageRepository(LanguageRepository $languageRepository)
{
$this->languageRepository = $languageRepository;
}
/**
* @var TerritoryRepository
*/
protected $territoryRepository;
/**
* Dependency injection of the Territory Repository
*
* @param TerritoryRepository $territoryRepository
* @return void
*/
public function injectTerritoryRepository(TerritoryRepository $territoryRepository)
{
$this->territoryRepository = $territoryRepository;
}
/**
* Display general information
*/
public function informationAction()
{
$this->view->assign(
'actions',
[
[
'code' => 'newLanguagePack',
'title' => 'createLanguagePackTitle',
'description' => 'createLanguagePackDescription',
],
[
'code' => 'testForm',
'title' => 'testFormTitle',
'description' => 'testFormDescription',
],
[
'code' => 'sqlDumpNonLocalizedData',
'title' => 'sqlDumpNonLocalizedDataTitle',
'description' => 'sqlDumpNonLocalizedDataDescription',
],
]
);
}
/**
* Display the language pack creation form
*
* @param LanguagePack $languagePack
*/
public function newLanguagePackAction(LanguagePack $languagePack = null)
{
if (!is_object($languagePack)) {
$languagePack = new LanguagePack();
}
$languagePack->setVersion($GLOBALS['TYPO3_CONF_VARS']['EXTENSIONS'][GeneralUtility::camelCaseToLowerCaseUnderscored($this->extensionName)]['version']);
$languagePack->setAuthor($GLOBALS['BE_USER']->user['realName']);
$languagePack->setAuthorEmail($GLOBALS['BE_USER']->user['email']);
$localeUtility = GeneralUtility::makeInstance(LocaleUtility::class);
$this->view->assign('locales', $localeUtility->getLocales());
$this->view->assign('languagePack', $languagePack);
}
/**
* Creation/update a language pack for the Static Info Tables
*
* @param LanguagePack $languagePack
*/
public function createLanguagePackAction(LanguagePack $languagePack)
{
// Add the localization columns
$locale = $languagePack->getLocale();
// Get the English name of the locale
$localeUtility = new LocaleUtility();
$language = $localeUtility->getLanguageFromLocale($locale);
$languagePack->setLanguage($language);
$languagePack->setTypo3VersionRange($GLOBALS['TYPO3_CONF_VARS']['EXTENSIONS'][GeneralUtility::camelCaseToLowerCaseUnderscored($this->extensionName)]['constraints']['depends']['typo3']);
// If version is not set, use the version of the base extension
if (!$languagePack->getVersion()) {
$languagePack->setVersion($GLOBALS['TYPO3_CONF_VARS']['EXTENSIONS'][GeneralUtility::camelCaseToLowerCaseUnderscored($this->extensionName)]['version']);
}
$this->countryRepository->addLocalizationColumns($locale);
$this->countryZoneRepository->addLocalizationColumns($locale);
$this->currencyRepository->addLocalizationColumns($locale);
$this->languageRepository->addLocalizationColumns($locale);
$this->territoryRepository->addLocalizationColumns($locale);
// Store the Language Pack
$languagePackRepository = GeneralUtility::makeInstance(LanguagePackRepository::class);
$messages = $languagePackRepository->writeLanguagePack($languagePack);
if (count($messages)) {
foreach ($messages as $message) {
$this->addFlashMessage($message, '', AbstractMessage::OK);
}
}
$this->forward('information');
}
/**
* Display a test form
*
* @param Country $country
* @param CountryZone $countryZone
* @param Language $language
*/
public function testFormAction(Country $country = null, CountryZone $countryZone = null, Language $language = null)
{
if (is_object($country) && (is_object($countryZone) || !$country->getCountryZones()->count())) {
$this->forward('testFormResult', 'Manager', $this->extensionName, ['country' => $country, 'countryZone' => $countryZone, 'language' => $language]);
}
if (is_object($country)) {
$this->view->assign('selectedCountry', $country);
}
if (is_object($countryZone)) {
$this->view->assign('selectedCountryZone', $countryZone);
}
if (is_object($language)) {
$this->view->assign('selectedLanguage', $language);
}
}
/**
* Display the test form result
*
* @param Country $country
* @param CountryZone $countryZone
* @param Language $language
*/
public function testFormResultAction(Country $country = null, CountryZone $countryZone = null, Language $language = null)
{
$this->view->assign('country', $country);
$currencies = $this->currencyRepository->findByCountry($country);
if ($currencies->count()) {
$this->view->assign('currency', $currencies[0]);
}
if (is_object($countryZone)) {
$this->view->assign('countryZone', $countryZone);
}
$this->view->assign('language', $language);
$territories = $this->territoryRepository->findByCountry($country);
if ($territories->count()) {
$this->view->assign('territory', $territories[0]);
}
}
/**
* Creation/update a language pack for the Static Info Tables
*/
public function sqlDumpNonLocalizedDataAction()
{
// Create a SQL dump of non-localized data
$dumpContent = [];
$dumpContent[] = $this->countryRepository->sqlDumpNonLocalizedData();
$dumpContent[] = $this->countryZoneRepository->sqlDumpNonLocalizedData();
$dumpContent[] = $this->currencyRepository->sqlDumpNonLocalizedData();
$dumpContent[] = $this->languageRepository->sqlDumpNonLocalizedData();
$dumpContent[] = $this->territoryRepository->sqlDumpNonLocalizedData();
// Write the SQL dump file
$extensionKey = GeneralUtility::camelCaseToLowerCaseUnderscored($this->extensionName);
$extensionPath = ExtensionManagementUtility::extPath($extensionKey);
$filename = 'export-ext_tables_static+adt.sql';
GeneralUtility::writeFile($extensionPath . $filename, implode(LF, $dumpContent));
$message = LocalizationUtility::translate('sqlDumpCreated', $this->extensionName) . ' ' . $extensionPath . $filename;
$this->addFlashMessage($message, '', AbstractMessage::OK);
$this->forward('information');
}
/**
* Get the typo3-supported locale options for the language pack creation
*
* @return array An array of language objects
*/
protected function getLocales()
{
$localeArray = [];
$locales = GeneralUtility::makeInstance(Locales::class);
$languages = $locales->getLanguages();
foreach ($languages as $locale => $language) {
// No language pack for English
if ($locale != 'default') {
$languageObject = new Language();
$languageObject->setCollatingLocale($locale);
$localizedLanguage = LocalizationUtility::translate('lang_' . $locale, 'Lang');
$label = ($localizedLanguage ? $localizedLanguage : $language) . ' (' . $locale . ')';
$languageObject->setNameEn($label);
$localeArray[$label] = $languageObject;
}
}
ksort($localeArray);
return $localeArray;
}
/**
* Get language name from locale
*
* @param string $locale
* @return string Language name
*/
protected function getLanguageFromLocale($locale)
{
$locales = GeneralUtility::makeInstance(Locales::class);
$languages = $locales->getLanguages();
$language = $languages[$locale];
return $language . ' (' . $locale . ')';
}
protected function getErrorFlashMessage()
{
return false;
}
}

View File

@@ -0,0 +1,106 @@
<?php
namespace SJBR\StaticInfoTables\Domain\Model;
/*
* Copyright notice
*
* (c) 2013-2022 Stanislas Rolland <typo3AAAA(arobas)sjbr.ca>
* All rights reserved
*
* This script is part of the TYPO3 project. The TYPO3 project is
* free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* The GNU General Public License can be found at
* http://www.gnu.org/copyleft/gpl.html.
*
* This script is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* This copyright notice MUST APPEAR in all copies of the script!
*/
use SJBR\StaticInfoTables\Utility\LocalizationUtility;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMap;
use TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapper;
/**
* Abstract model for static entities
*/
class AbstractEntity extends \TYPO3\CMS\Extbase\DomainObject\AbstractEntity
{
/**
* @var DataMapper
*/
protected $dataMapper;
/**
* Name of the table from persistence mapping of this model
*
* @var string
*/
protected $tableName = '';
/**
* On initialization, get the columns mapping configuration
*/
public function initializeObject()
{
$this->dataMapper = GeneralUtility::makeInstance(DataMapper::class);
}
/**
* Localized name of the entity
*
* @var string
*/
protected $nameLocalized = '';
/**
* Sets the localized name of the entity
*
* @param string $nameLocalized
*
* @return void
*/
public function setNameLocalized($nameLocalized)
{
$this->nameLocalized = $nameLocalized;
}
/**
* Gets the localized name of the entity
*
* @return string
*/
public function getNameLocalized()
{
$language = LocalizationUtility::getCurrentLanguage();
$labelFields = LocalizationUtility::getLabelFields($this->tableName, $language);
foreach ($labelFields as $labelField => $map) {
if ($this->_hasProperty($map['mapOnProperty'] ?? '')) {
$value = $this->_getProperty($map['mapOnProperty'] ?? '');
if ($value) {
$this->nameLocalized = $value;
break;
}
}
}
return $this->nameLocalized;
}
/**
* Gets the table name
*
* @return string
*/
public function getTableName()
{
return $this->tableName;
}
}

View File

@@ -0,0 +1,617 @@
<?php
namespace SJBR\StaticInfoTables\Domain\Model;
/*
* Copyright notice
*
* (c) 2011-2012 Armin Rüdiger Vieweg <info@professorweb.de>
* (c) 2013-2021 Stanislas Rolland <typo3AAAA(arobas)sjbr.ca>
* All rights reserved
*
* This script is part of the TYPO3 project. The TYPO3 project is
* free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* The GNU General Public License can be found at
* http://www.gnu.org/copyleft/gpl.html.
*
* This script is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* This copyright notice MUST APPEAR in all copies of the script!
*/
use SJBR\StaticInfoTables\Domain\Model\CountryZone;
use TYPO3\CMS\Extbase\Annotation\ORM\Lazy;
use TYPO3\CMS\Extbase\Persistence\ObjectStorage;
/**
* The Country model
*/
class Country extends AbstractEntity
{
/**
* @var string
*/
protected $addressFormat = '';
/**
* @var string
*/
protected $capitalCity = '';
/**
* Country zones of this country
*
* @var \TYPO3\CMS\Extbase\Persistence\ObjectStorage<\SJBR\StaticInfoTables\Domain\Model\CountryZone>
* @Lazy
*/
protected $countryZones;
/**
* Currency code as number (i.e. 978)
* ISO 4217 Nr Currency code
*
* @var int
*/
protected $currencyIsoCodeNumber = 0;
/**
* Currency code as three digit string (i.e. EUR)
* ISO 4217 A3 Currency code
*
* @var string
*/
protected $currencyIsoCodeA3 = '';
/**
* Deletion status of the object
*
* @var bool
*/
protected $deleted = false;
/**
* Whether or not the country is a member of the European Union
*
* @var bool
*/
protected $euMember = false;
/**
* Country code as two digit string (i.e. AT)
* ISO 3166-1 A2 Country code
*
* @var string
*/
protected $isoCodeA2 = '';
/**
* Country code as three digit string (i.e. AUT)
* ISO 3166-1 A3 Country code
*
* @var string
*/
protected $isoCodeA3 = '';
/**
* Country code as number (i.e. 40)
* ISO 3166-1 Nr Country code
*
* @var int
*/
protected $isoCodeNumber = 0;
/**
* The official name of the country in English
*
* @var string
*/
protected $officialNameEn = '';
/**
* The official name of the country in local language and local script
*
* @var string
*/
protected $officialNameLocal = '';
/**
* UN number of territory in which the country is located
*
* @var int
*/
protected $parentTerritoryUnCodeNumber = 0;
/**
* The international phone prefix for the country
*
* @var int
*/
protected $phonePrefix = 0;
/**
* @var string
*/
protected $shortNameEn = '';
/**
* @var string
*/
protected $shortNameLocal = '';
/**
* Whether the country is a member of the UNO or not
*
* @var bool
*/
protected $unMember = false;
/**
* The Internet top level domain of the country
*
* @var string
*/
protected $topLevelDomain = '';
/**
* @var bool
*/
protected $zoneFlag = false;
/**
* On initialization, get the columns mapping configuration
*/
public function initializeObject()
{
parent::initializeObject();
$this->tableName = $this->dataMapper->getDataMap(self::class)->getTableName();
$this->countryZones = new ObjectStorage();
}
/**
* Sets the address format.
*
* @param string $addressFormat
*
* @return void
*/
public function setAddressFormat($addressFormat)
{
$this->addressFormat = $addressFormat;
}
/**
* Gets the address format.
*
* @return string
*/
public function getAddressFormat()
{
return $this->addressFormat;
}
/**
* Sets the name of the capital city
*
* @param string $capitalCity
*
* @return void
*/
public function setCapitalCity($capitalCity)
{
$this->capitalCity = $capitalCity;
}
/**
* Gets the name of the capital city
*
* @return string
*/
public function getCapitalCity()
{
return $this->capitalCity;
}
/**
* Sets the ISO A3 currency code.
*
* @param string $currencyIsoCodeA3
*
* @return void
*/
public function setCurrencyIsoCodeA3($currencyIsoCodeA3)
{
$this->currencyIsoCodeA3 = $currencyIsoCodeA3;
}
/**
* Gets the ISO A3 currency code.
*
* @return string
*/
public function getCurrencyIsoCodeA3()
{
return $this->currencyIsoCodeA3;
}
/**
* Sets the ISO numeric currency code
*
* @param int $currencyIsoCodeNumber
*
* @return void
*/
public function setCurrencyIsoCodeNumber($currencyIsoCodeNumber)
{
$this->currencyIsoCodeNumber = $currencyIsoCodeNumber;
}
/**
* Gets the ISO numeric currency code
*
* @return int
*/
public function getCurrencyIsoCodeNumber()
{
return $this->currencyIsoCodeNumber;
}
/**
* Sets whether this country is a member of the European Union.
*
* @param bool $euMember
*
* @return void
*/
public function setEuMember($euMember)
{
$this->euMember = $euMember;
}
/**
* Gets the deletion status of the entity
*
* @return bool
*/
public function getDeleted()
{
return $this->deleted;
}
/**
* Sets the deletion status of the entity
*
* @param bool $deleted
*
* @return void
*/
public function setDeleted($deleted)
{
$this->deleted = $deleted;
}
/**
* Gets whether this country is a member of the European Union.
*
* @return bool
*/
public function getEuMember()
{
return $this->euMember;
}
/**
* Gets whether this country is a member of the European Union.
*
* This method is a synonym for the getEuMember method.
*
* @return bool
*/
public function isEuMember()
{
return $this->getEuMember();
}
/**
* Sets the ISO alpha-2 code.
*
* @param string $isoCodeA2
*
* @return void
*/
public function setIsoCodeA2($isoCodeA2)
{
$this->isoCodeA2 = $isoCodeA2;
}
/**
* Gets the ISO alpha-2 code.
*
* @return string
*/
public function getIsoCodeA2()
{
return $this->isoCodeA2;
}
/**
* Sets the ISO alpha-3 code.
*
* @param string $isoCodeA3
*
* @return void
*/
public function setIsoCodeA3($isoCodeA3)
{
$this->isoCodeA3 = $isoCodeA3;
}
/**
* Gets the ISO alpha-3 code.
*
* @return string
*/
public function getIsoCodeA3()
{
return $this->isoCodeA3;
}
/**
* Sets the ISO code number.
*
* @param int $isoCodeNumber
*
* @return void
*/
public function setIsoCodeNumber($isoCodeNumber)
{
$this->isoCodeNumber = $isoCodeNumber;
}
/**
* Gets the ISO code number.
*
* @return int
*/
public function getIsoCodeNumber()
{
return $this->isoCodeNumber;
}
/**
* Sets the official name of the country in English
*
* @param string $officialNameEn
*
* @return void
*/
public function setOfficialNameEn($officialNameEn)
{
$this->officialNameEn = $officialNameEn;
}
/**
* Gets the official name of the country in English
*
* @return string
*/
public function getOfficialNameEn()
{
return $this->officialNameEn;
}
/**
* Sets the official name of the country in local language and script
*
* @param string $officialNameLocal
*
* @return void
*/
public function setOfficialNameLocal($officialNameLocal)
{
$this->officialNameLocal = $officialNameLocal;
}
/**
* Gets the official name of the country in local language and script
*
* @return string
*/
public function getOfficialNameLocal()
{
return $this->officialNameLocal;
}
/**
* Sets the parent territory UN numeric code.
*
* @param int $parentTerritoryUnCodeNumber
*
* @return void
*/
public function setParentTerritoryUnCodeNumber($parentTerritoryUnCodeNumber)
{
$this->parentTerritoryUnCodeNumber = $parentTerritoryUnCodeNumber;
}
/**
* Gets the parent territory UN numeric code.
*
* @return int
*/
public function getParentTerritoryUnCodeNumber()
{
return $this->parentTerritoryUnCodeNumber;
}
/**
* Sets the phone prefix.
*
* @param int $phonePrefix
*
* @return void
*/
public function setPhonePrefix($phonePrefix)
{
$this->phonePrefix = $phonePrefix;
}
/**
* Gets the phone prefix.
*
* @return int
*/
public function getPhonePrefix()
{
return $this->phonePrefix;
}
/**
* Sets the English short name.
*
* @param string $shortNameEn
*
* @return void
*/
public function setShortNameEn($shortNameEn)
{
$this->shortNameEn = $shortNameEn;
}
/**
* Gets the English short name.
*
* @return string
*/
public function getShortNameEn()
{
return $this->shortNameEn;
}
/**
* Sets the short local name.
*
* @param string $shortNameLocal
*
* @return void
*/
public function setShortNameLocal($shortNameLocal)
{
$this->shortNameLocal = $shortNameLocal;
}
/**
* Gets the short local name.
*
* @return string
*/
public function getShortNameLocal()
{
return $this->shortNameLocal;
}
/**
* Sets the top-level domain.
*
* @param string $topLevelDomain
*
* @return void
*/
public function setTopLevelDomain($topLevelDomain)
{
$this->topLevelDomain = $topLevelDomain;
}
/**
* Gets the top-level domain.
*
* @return string
*/
public function getTopLevelDomain()
{
return $this->topLevelDomain;
}
/**
* Sets whether this country is a member of the United Nations.
*
* @param bool $unMember
*
* @return void
*/
public function setUnMember($unMember)
{
$this->unMember = $unMember;
}
/**
* Gets whether this country is a member of the United Nations.
*
* @return bool
*/
public function getUnMember()
{
return $this->unMember;
}
/**
* Sets whether this country is a member of the United Nations.
*
* This method is a synonym for the getUnMember method.
*
* @return bool
*/
public function isUnMember()
{
return $this->getUnMember();
}
/**
* Sets the zone flag.
*
* @param bool $zoneFlag
*
* @return void
*/
public function setZoneFlag($zoneFlag)
{
$this->zoneFlag = $zoneFlag;
}
/**
* Gets the zone flag.
*
* @return bool
*/
public function getZoneFlag()
{
return $this->zoneFlag;
}
/**
* Sets the country zones
*
* @param \TYPO3\CMS\Extbase\Persistence\ObjectStorage<\SJBR\StaticInfoTables\Domain\Model\CountryZone> $countryZones
*
* @return void
*/
public function setCountryZones($countryZones)
{
$this->countryZones = $countryZones;
}
/**
* Gets the country zones
*
* @return \TYPO3\CMS\Extbase\Persistence\ObjectStorage<\SJBR\StaticInfoTables\Domain\Model\CountryZone> $countryZones
*/
public function getCountryZones()
{
return $this->countryZones;
}
}

View File

@@ -0,0 +1,255 @@
<?php
namespace SJBR\StaticInfoTables\Domain\Model;
/*
* Copyright notice
*
* (c) 2011-2012 Armin Rüdiger Vieweg <info@professorweb.de>
* (c) 2013-2021 Stanislas Rolland <typo3AAAA(arobas)sjbr.ca>
* All rights reserved
*
* This script is part of the TYPO3 project. The TYPO3 project is
* free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* The GNU General Public License can be found at
* http://www.gnu.org/copyleft/gpl.html.
*
* This script is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* This copyright notice MUST APPEAR in all copies of the script!
*/
/**
* The Country Zone model
*
* @copyright Copyright belongs to the respective authors
* @license http://www.gnu.org/licenses/gpl.html GNU General Public License, version 3 or later
*/
class CountryZone extends AbstractEntity
{
/**
* Country code as two digit string (i.e. AT)
* ISO 3166-1 A2 Country code
*
* @var string
*/
protected $countryIsoCodeA2 = '';
/**
* Country code as three digit string (i.e. AUT)
* ISO 3166-1 A3 Country code
*
* @var string
*/
protected $countryIsoCodeA3 = '';
/**
* Country code as number (i.e. 40)
* ISO 3166-1 Nr Country code
*
* @var int
*/
protected $countryIsoCodeNumber = 0;
/**
* Deletion status of the object
*
* @var bool
*/
protected $deleted = false;
/**
* Country zone code as string
* ISO 3166-2 Country Zone code
*
* @var string
*/
protected $isoCode = '';
/**
* Local name of the country zone
*
* @var string
*/
protected $localName = '';
/**
* English name of the country zone
*
* @var string
*/
protected $nameEn = '';
/**
* On initialization, get the columns mapping configuration
*/
public function initializeObject()
{
parent::initializeObject();
$this->tableName = $this->dataMapper->getDataMap(self::class)->getTableName();
}
/**
* Sets the country ISO alpha-2 code.
*
* @param string $countryIsoCodeA2
*
* @return void
*/
public function setCountryIsoCodeA2($countryIsoCodeA2)
{
$this->countryIsoCodeA2 = $countryIsoCodeA2;
}
/**
* Gets the country ISO alpha-2 code.
*
* @return string
*/
public function getCountryIsoCodeA2()
{
return $this->countryIsoCodeA2;
}
/**
* Sets the country ISO alpha-3 code.
*
* @param string $countryIsoCodeA3
*
* @return void
*/
public function setCountryIsoCodeA3($countryIsoCodeA3)
{
$this->countryIsoCodeA3 = $countryIsoCodeA3;
}
/**
* Gets the country ISO alpha-3 code.
*
* @return string
*/
public function getCountryIsoCodeA3()
{
return $this->countryIsoCodeA3;
}
/**
* Sets the country numeric ISO code
*
* @param int $countryIsoCodeNumber
*
* @return void
*/
public function setCountryIsoCodeNumber($countryIsoCodeNumber)
{
$this->countryIsoCodeNumber = $countryIsoCodeNumber;
}
/**
* Gets the country numeric ISO code
*
* @return int
*/
public function getCountryIsoCodeNumber()
{
return $this->countryIsoCodeNumber;
}
/**
* Gets the deletion status of the entity
*
* @return bool
*/
public function getDeleted()
{
return $this->deleted;
}
/**
* Sets the deletion status of the entity
*
* @param bool $deleted
*
* @return void
*/
public function setDeleted($deleted)
{
return $this->deleted = $deleted;
}
/**
* Sets the country zone ISO code.
*
* @param string $isoCode
*
* @return void
*/
public function setIsoCode($isoCode)
{
$this->isoCode = $isoCode;
}
/**
* Gets the country zone ISO code.
*
* @return string
*/
public function getIsoCode()
{
return $this->isoCode;
}
/**
* Sets the local name.
*
* @param string $localName
*
* @return void
*/
public function setLocalName($localName)
{
$this->localName = $localName;
}
/**
* Gets the local name.
*
* @return string
*/
public function getLocalName()
{
return $this->localName;
}
/**
* Sets the English name.
*
* @param string $nameEn
*
* @return void
*/
public function setNameEn($nameEn)
{
$this->nameEn = $nameEn;
}
/**
* Returns English name. If empty returns the localName.
*
* @return string
*/
public function getNameEn()
{
if ($this->nameEn === '') {
return $this->getLocalName();
}
return $this->nameEn;
}
}

View File

@@ -0,0 +1,424 @@
<?php
namespace SJBR\StaticInfoTables\Domain\Model;
/*
* Copyright notice
*
* (c) 2011-2012 Armin Rüdiger Vieweg <info@professorweb.de>
* (c) 2013-2021 Stanislas Rolland <typo3AAAA(arobas)sjbr.ca>
* All rights reserved
*
* This script is part of the TYPO3 project. The TYPO3 project is
* free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* The GNU General Public License can be found at
* http://www.gnu.org/copyleft/gpl.html.
*
* This script is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* This copyright notice MUST APPEAR in all copies of the script!
*/
/**
* The Currency model
*
* @copyright Copyright belongs to the respective authors
* @license http://www.gnu.org/licenses/gpl.html GNU General Public License, version 3 or later
*/
class Currency extends AbstractEntity
{
/**
* The number of decimals to be shown when an amount is presented in this currency
*
* @var int
*/
protected $decimalDigits = 0;
/**
* The character to be shown in front of the decimals when an amount is presented in this currency
*
* @var string
*/
protected $decimalPoint = '';
/**
* Deletion status of the object
*
* @var bool
*/
protected $deleted = false;
/**
* The divisor used to obtain the subdivision of the currency
*
* @var int
*/
protected $divisor = 0;
/**
* Currency code as three digit string (i.e. EUR)
* ISO 4217 alpha-3 currency code
*
* @var string
*/
protected $isoCodeA3 = '';
/**
* Currency code as number
* ISO 4217 numeric currency code
*
* @var int
*/
protected $isoCodeNumber = 0;
/**
* English name of the currency
*
* @var string
*/
protected $nameEn = '';
/**
* English name of the currency subdivision unit
*
* @var string
*/
protected $subdivisionNameEn = '';
/**
* The symbol to be shown to the left of an amount stated in units of the subdivision of the currency
*
* @var string
*/
protected $subdivisionSymbolLeft = '';
/**
* The symbol to be shown to the right of an amount stated in units of the subdivision of the currency
*
* @var string
*/
protected $subdivisionSymbolRight = '';
/**
* The symbol to be shown to the left of an amount stated in units of the currency
*
* @var string
*/
protected $symbolLeft = '';
/**
* The symbol to be shown to the right of an amount stated in units of the currency
*
* @var string
*/
protected $symbolRight = '';
/**
* Character to be used between every group of thousands of an amount stated in units of this currency
*
* @var string
*/
protected $thousandsPoint = '';
/**
* On initialization, get the columns mapping configuration
*/
public function initializeObject()
{
parent::initializeObject();
$this->tableName = $this->dataMapper->getDataMap(self::class)->getTableName();
}
/**
* Sets the number of decimal digits.
*
* @param int $decimalDigits
*
* @return void
*/
public function setDecimalDigits($decimalDigits)
{
$this->decimalDigits = $decimalDigits;
}
/**
* Gets the number of decimal digits.
*
* @return int
*/
public function getDecimalDigits()
{
return $this->decimalDigits;
}
/**
* Sets the decimal point character
*
* @param string $decimalPoint
*
* @return void
*/
public function setDecimalPoint($decimalPoint)
{
$this->decimalPoint = $decimalPoint;
}
/**
* Gets the decimal point character
*
* @return string
*/
public function getDecimalPoint()
{
return $this->decimalPoint;
}
/**
* Gets the deletion status of the entity
*
* @return bool
*/
public function getDeleted()
{
return $this->deleted;
}
/**
* Sets the deletion status of the entity
*
* @param bool $deleted
*
* @return void
*/
public function setDeleted($deleted)
{
return $this->deleted = $deleted;
}
/**
* Sets the divisor.
*
* @param int $divisor
*
* @return void
*/
public function setDivisor($divisor)
{
$this->divisor = $divisor;
}
/**
* Gets the divisor.
*
* @return int
*/
public function getDivisor()
{
return $this->divisor;
}
/**
* Sets the ISO alpha-3 code.
*
* @param string $isoCodeA3
*
* @return void
*/
public function setIsoCodeA3($isoCodeA3)
{
$this->isoCodeA3 = $isoCodeA3;
}
/**
* Gets the ISO alpha-3 code.
*
* @return string
*/
public function getIsoCodeA3()
{
return $this->isoCodeA3;
}
/**
* Sets the ISO code number.
*
* @param int $isoCodeNumber
*
* @return void
*/
public function setIsoCodeNumber($isoCodeNumber)
{
$this->isoCodeNumber = $isoCodeNumber;
}
/**
* Gets the ISO code number.
*
* @return int
*/
public function getIsoCodeNumber()
{
return $this->isoCodeNumber;
}
/**
* Sets the English name of the currency
*
* @param string $nameEn
*
* @return void
*/
public function setNameEn($nameEn)
{
$this->nameEn = $nameEn;
}
/**
* Gets the English name of the currency
*
* @return string
*/
public function getNameEn()
{
return $this->nameEn;
}
/**
* Sets the English name of the currency subdivision
*
* @param string $subdivisionNameEn
*
* @return void
*/
public function setSubdivisionNameEn($subdivisionNameEn)
{
$this->subdivisionNameEn = $subdivisionNameEn;
}
/**
* Gets the English name of the currency subdivision
*
* @return string
*/
public function getSubdivisionNameEn()
{
return $this->subdivisionNameEn;
}
/**
* Sets the left-hand side symbol for an amount stated in units of the subdivision of the currency
*
* @param string $subdivisionSymbolLeft
*
* @return void
*/
public function setSubdivisionSymbolLeft($subdivisionSymbolLeft)
{
$this->subdivisionSymbolLeft = $subdivisionSymbolLeft;
}
/**
* Gets the left-hand side symbol for an amount stated in units of the subdivision of the currency
*
* @return string
*/
public function getSubdivisionSymbolLeft()
{
return $this->subdivisionSymbolLeft;
}
/**
* Sets the right-hand side symbol for an amount stated in units of the subdivision of the currency
*
* @param string $subdivisionSymbolRight
*
* @return void
*/
public function setSubdivisionSymbolRight($subdivisionSymbolRight)
{
$this->subdivisionSymbolRight = $subdivisionSymbolRight;
}
/**
* Gets the right-hand side symbol for an amount stated in units of the subdivision of the currency
*
* @return string
*/
public function getSubdivisionSymbolRight()
{
return $this->subdivisionSymbolRight;
}
/**
* Sets the symbol to be shown to the left of an amount stated in units of the currency
*
* @param string $symbolLeft
*
* @return void
*/
public function setSymbolLeft($symbolLeft)
{
$this->symbolLeft = $symbolLeft;
}
/**
* Gets the symbol to be shown to the left of an amount stated in units of the currency
*
* @return string
*/
public function getSymbolLeft()
{
return $this->symbolLeft;
}
/**
* Sets the symbol to be shown to the right of an amount stated in units of the currency
*
* @param string $symbolRight
*
* @return void
*/
public function setSymbolRight($symbolRight)
{
$this->symbolRight = $symbolRight;
}
/**
* Gets the symbol to be shown to the right of an amount stated in units of the currency
*
* @return string
*/
public function getSymbolRight()
{
return $this->symbolRight;
}
/**
* Sets the thousands point/separator.
*
* @param string $thousandsPoint
*
* @return void
*/
public function setThousandsPoint($thousandsPoint)
{
$this->thousandsPoint = $thousandsPoint;
}
/**
* Gets the thousands point/separator.
*
* @return string
*/
public function getThousandsPoint()
{
return $this->thousandsPoint;
}
}

View File

@@ -0,0 +1,325 @@
<?php
namespace SJBR\StaticInfoTables\Domain\Model;
/***************************************************************
* Copyright notice
*
* (c) 2011-2012 Armin Rüdiger Vieweg <info@professorweb.de>
* (c) 2013-2021 Stanislas Rolland <typo3AAAA(arobas)sjbr.ca>
* All rights reserved
*
* This script is part of the TYPO3 project. The TYPO3 project is
* free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* The GNU General Public License can be found at
* http://www.gnu.org/copyleft/gpl.html.
*
* This script is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* This copyright notice MUST APPEAR in all copies of the script!
*/
/**
* The Language model
*
* @copyright Copyright belongs to the respective authors
* @license http://www.gnu.org/licenses/gpl.html GNU General Public License, version 3 or later
*/
class Language extends AbstractEntity
{
/**
* @var string
*/
protected $collatingLocale = '';
/**
* Country code as two digit string (i.e. AT)
* Identifies this language as a variant of the language identified by the ISO 639-1 A2 Language code
* See also RFC 4646
* ISO 3166-1 A2 Country code
*
* @var string
*/
protected $countryIsoCodeA2 = '';
/**
* @var bool
*/
protected $constructedLanguage = false;
/**
* Deletion status of the object
*
* @var bool
*/
protected $deleted = false;
/**
* ISO 639-1 A2 Language code
*
* @var string
*/
protected $isoCodeA2 = '';
/**
* Local name: name of language in the language itself
*
* @var string
*/
protected $localName = '';
/**
* English name
*
* @var string
*/
protected $nameEn = '';
/**
* @var bool
*/
protected $sacredLanguage = false;
/**
* @var string
*/
protected $typo3Code = '';
/**
* On initialization, get the columns mapping configuration
*/
public function initializeObject()
{
parent::initializeObject();
$this->tableName = $this->dataMapper->getDataMap(self::class)->getTableName();
}
/**
* Sets the collating locale.
*
* @param string $collatingLocale
*
* @return void
*/
public function setCollatingLocale($collatingLocale)
{
$this->collatingLocale = $collatingLocale;
}
/**
* Gets the collating locale.
*
* @return string
*/
public function getCollatingLocale()
{
return $this->collatingLocale;
}
/**
* Sets the ISO 3166-1 A2 Country code
*
* @param string $countryIsoCodeA2
*
* @return void
*/
public function setCountryIsoCodeA2($countryIsoCodeA2)
{
$this->countryIsoCodeA2 = $countryIsoCodeA2;
}
/**
* Gets the ISO 3166-1 A2 Country code
*
* @return string
*/
public function getCountryIsoCodeA2()
{
return $this->countryIsoCodeA2;
}
/**
* Sets whether this is a constructed language.
*
* @param bool $constructedLanguage
*
* @return void
*/
public function setConstructedLanguage($constructedLanguage)
{
$this->constructedLanguage = $constructedLanguage;
}
/**
* Gets whether this is a constructed language.
*
* @return bool
*/
public function getConstructedLanguage()
{
return $this->constructedLanguage;
}
/**
* Gets whether this is a constructed language.
*
* This method is a synonym for the getConstructedLanguage method.
*
* @return bool
*/
public function isConstructedLanguage()
{
return $this->getConstructedLanguage();
}
/**
* Gets the deletion status of the entity
*
* @return bool
*/
public function getDeleted()
{
return $this->deleted;
}
/**
* Sets the deletion status of the entity
*
* @param bool $deleted
*
* @return void
*/
public function setDeleted($deleted)
{
return $this->deleted = $deleted;
}
/**
* Sets the ISO 639-1 A2 Language code
*
* @param string $isoCodeA2
*
* @return void
*/
public function setIsoCodeA2($isoCodeA2)
{
$this->isoCodeA2 = $isoCodeA2;
}
/**
* Gets the ISO 639-1 A2 Language code
*
* @return string
*/
public function getIsoCodeA2()
{
return $this->isoCodeA2;
}
/**
* Sets the local name.
*
* @param string $localName
*
* @return void
*/
public function setLocalName($localName)
{
$this->localName = $localName;
}
/**
* Gets the local name.
*
* @return string
*/
public function getLocalName()
{
return $this->localName;
}
/**
* Sets the English name
*
* @param string $nameEn
*
* @return void
*/
public function setNameEn($nameEn)
{
$this->nameEn = $nameEn;
}
/**
* Gets the English name
*
* @return string
*/
public function getNameEn()
{
return $this->nameEn;
}
/**
* Sets whether this is a sacred language.
*
* @param bool $sacredLanguage
*
* @return void
*/
public function setSacredLanguage($sacredLanguage)
{
$this->sacredLanguage = $sacredLanguage;
}
/**
* Gets whether this is a sacred language.
*
* @return bool
*/
public function getSacredLanguage()
{
return $this->sacredLanguage;
}
/**
* Sets whether this is a sacred language.
*
* This method is a synonym for the getSacredLanguage method.
*
* @return bool
*/
public function isSacredLanguage()
{
return $this->getSacredLanguage();
}
/**
* Sets the TYPO3 language code.
*
* @param string $typo3Code
*
* @return void
*/
public function setTypo3Code($typo3Code)
{
$this->typo3Code = $typo3Code;
}
/**
* Gets the TYPO3 language code.
*
* @return string
*/
public function getTypo3Code()
{
return $this->typo3Code;
}
}

View File

@@ -0,0 +1,268 @@
<?php
namespace SJBR\StaticInfoTables\Domain\Model;
/*
* Copyright notice
*
* (c) 2013-2021 Stanislas Rolland <typo3AAAA(arobas)sjbr.ca>
* All rights reserved
*
* This script is part of the TYPO3 project. The TYPO3 project is
* free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* The GNU General Public License can be found at
* http://www.gnu.org/copyleft/gpl.html.
* A copy is found in the textfile GPL.txt and important notices to the license
* from the author is found in LICENSE.txt distributed with these scripts.
*
*
* This script is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* This copyright notice MUST APPEAR in all copies of the script!
*/
use SJBR\StaticInfoTables\Domain\Repository\CountryRepository;
use SJBR\StaticInfoTables\Domain\Repository\CountryZoneRepository;
use SJBR\StaticInfoTables\Domain\Repository\CurrencyRepository;
use SJBR\StaticInfoTables\Domain\Repository\LanguageRepository;
use SJBR\StaticInfoTables\Domain\Repository\TerritoryRepository;
use TYPO3\CMS\Core\Localization\Parser\XliffParser;
use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Extbase\Annotation\Validate;
use TYPO3\CMS\Extbase\DomainObject\AbstractEntity;
/**
* Language Pack object
*/
class LanguagePack extends AbstractEntity
{
/**
* Name of the extension this class belongs to
*
* @var string
*/
protected $extensionName = 'StaticInfoTables';
/**
* @var string
* @Validate("TYPO3\CMS\Extbase\Validation\Validator\NotEmptyValidator")
*/
protected $author;
/**
* @var string
*/
protected $authorCompany;
/**
* @var string
* @Validate("TYPO3\CMS\Extbase\Validation\Validator\NotEmptyValidator")
*/
protected $vendorName;
/**
* @var string
* @Validate("EmailAddress")
*/
protected $authorEmail;
/**
* @var string
*/
protected $locale;
/**
* @var string
*/
protected $language;
/**
* @var string
*/
protected $typo3VersionRange;
/**
* @var string
* @Validate("TYPO3\CMS\Extbase\Validation\Validator\NotEmptyValidator")
*/
protected $version;
/**
* @var CountryRepository
*/
protected $countryRepository;
/**
* @var CountryZoneRepository
*/
protected $countryZoneRepository;
/**
* @var CurrencyRepository
*/
protected $currencyRepository;
/**
* @var LanguageRepository
*/
protected $languageRepository;
/**
* @var TerritoryRepository
*/
protected $territoryRepository;
public function __construct(
$author = '',
$authorCompany = '',
$vendorName = '',
$authorEmail = '',
$locale = '',
$language = ''
) {
$this->countryRepository = GeneralUtility::makeInstance(CountryRepository::class);
$this->countryZoneRepository = GeneralUtility::makeInstance(CountryZoneRepository::class);
$this->currencyRepository = GeneralUtility::makeInstance(CurrencyRepository::class);
$this->languageRepository = GeneralUtility::makeInstance(LanguageRepository::class);
$this->territoryRepository = GeneralUtility::makeInstance(TerritoryRepository::class);
$this->setAuthor($author);
$this->setAuthorCompany($authorCompany);
$this->setVendorName($vendorName);
$this->setAuthorEmail($authorEmail);
$this->setLocale($locale);
$this->setLanguage($language);
}
public function setAuthor($author)
{
$this->author = $author;
}
public function getAuthor()
{
return $this->author;
}
public function setAuthorCompany($authorCompany)
{
$this->authorCompany = $authorCompany;
}
public function getAuthorCompany()
{
return $this->authorCompany;
}
public function setVendorName($vendorName)
{
$this->vendorName = $vendorName;
}
public function getVendorName()
{
return $this->vendorName;
}
public function setAuthorEmail($authorEmail)
{
$this->authorEmail = $authorEmail;
}
public function getAuthorEmail()
{
return $this->authorEmail;
}
public function setLocale($locale)
{
$this->locale = $locale;
}
public function getLocale()
{
return $this->locale;
}
public function setLanguage($language)
{
$this->language = $language;
}
public function getLanguage()
{
return $this->language;
}
public function setTypo3VersionRange($typo3VersionRange)
{
$this->typo3VersionRange = $typo3VersionRange;
}
public function getTypo3VersionRange()
{
return $this->typo3VersionRange;
}
public function setVersion($version)
{
$this->version = $version;
}
public function getVersion()
{
return $this->version;
}
/**
* Gets the localization labels for this language pack
*
* @return string localization labels in xliff format
*/
public function getLocalizationLabels()
{
// Build the localization labels of the language pack
$XliffParser = new XliffParser();
$extensionKey = GeneralUtility::camelCaseToLowerCaseUnderscored($this->extensionName);
$extensionPath = ExtensionManagementUtility::extPath($extensionKey);
$sourceXliffFilePath = $extensionPath . 'Resources/Private/Language/locallang_db.xlf';
$parsedData = $XliffParser->getParsedData($sourceXliffFilePath, 'default');
$localizationLabels = [];
$localeLowerCase = strtolower($this->getLocale());
$localeUpperCase = strtoupper($this->getLocale());
foreach ($parsedData['default'] as $translationElementId => $translationElement) {
if (substr($translationElementId, -3) == '_en') {
$localizationLabels[] = chr(9) . chr(9) . chr(9) . '<trans-unit id="' . substr($translationElementId, 0, -2) . $localeLowerCase . '" xml:space="preserve">';
$localizationLabels[] = chr(9) . chr(9) . chr(9) . chr(9) . '<source>' . str_replace('(EN)', '(' . $localeUpperCase . ')', $translationElement[0]['source']) . '</source>';
if ($translationElement[0]['target']) {
$localizationLabels[] = chr(9) . chr(9) . chr(9) . chr(9) . '<target>' . str_replace('(EN)', '(' . $localeUpperCase . ')', $translationElement[0]['target']) . '</target>';
}
$localizationLabels[] = chr(9) . chr(9) . chr(9) . '</trans-unit>';
}
}
return implode(LF, $localizationLabels);
}
/**
* Gets the update queries for this language pack
*
* @return string update queries in sql format
*/
public function getUpdateQueries()
{
$updateQueries = [];
$locale = $this->getLocale();
$updateQueries = array_merge($updateQueries, $this->countryRepository->getUpdateQueries($locale));
$updateQueries = array_merge($updateQueries, $this->countryZoneRepository->getUpdateQueries($locale));
$updateQueries = array_merge($updateQueries, $this->currencyRepository->getUpdateQueries($locale));
$updateQueries = array_merge($updateQueries, $this->languageRepository->getUpdateQueries($locale));
$updateQueries = array_merge($updateQueries, $this->territoryRepository->getUpdateQueries($locale));
return implode(LF, $updateQueries);
}
}

View File

@@ -0,0 +1,91 @@
<?php
namespace SJBR\StaticInfoTables\Domain\Model;
/***************************************************************
* Copyright notice
*
* (c) 2013-2017 Stanislas Rolland <typo3(arobas)sjbr.ca>
*
* All rights reserved
*
* This script is part of the TYPO3 project. The TYPO3 project is
* free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* The GNU General Public License can be found at
* http://www.gnu.org/copyleft/gpl.html.
*
* This script is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* This copyright notice MUST APPEAR in all copies of the script!
***************************************************************/
use TYPO3\CMS\Extbase\DomainObject\AbstractEntity;
/**
* The System Language model
*/
class SystemLanguage extends AbstractEntity
{
/**
* @var string System language name
*/
protected $title = '';
/**
* @var \SJBR\StaticInfoTables\Domain\Model\Language
*/
protected $isoLanguage = null;
/**
* Sets the language name
*
* @param string $title
*
* @return void
*/
public function setTitle($title)
{
$this->title = $title;
}
/**
* Gets the backend language name
*
* @return string
*/
public function getTitle()
{
return $this->title;
}
/**
* Sets the ISO language
*
* @param Language $isoLanguage
*
* @return void
*/
public function setIsoLanguage(Language $isoLanguage)
{
$this->isoLanguage = $isoLanguage;
}
/**
* Gets the ISO language
*
* @return Language
*/
public function getIsoLanguage()
{
if ($this->isoLanguage !== null) {
return clone $this->isoLanguage;
}
return $this->isoLanguage;
}
}

View File

@@ -0,0 +1,161 @@
<?php
namespace SJBR\StaticInfoTables\Domain\Model;
/***************************************************************
* Copyright notice
*
* (c) 2011-2012 Armin Rüdiger Vieweg <info@professorweb.de>
* (c) 2013-2022 Stanislas Rolland <typo3AAAA(arobas)sjbr.ca>
* All rights reserved
*
* This script is part of the TYPO3 project. The TYPO3 project is
* free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* The GNU General Public License can be found at
* http://www.gnu.org/copyleft/gpl.html.
*
* This script is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* This copyright notice MUST APPEAR in all copies of the script!
*/
/**
* The Territory model
*
* @copyright Copyright belongs to the respective authors
* @license http://www.gnu.org/licenses/gpl.html GNU General Public License, version 3 or later
*/
class Territory extends AbstractEntity
{
/**
* Deletion status of the object
*
* @var bool
*/
protected $deleted = false;
/**
* UN numeric territory code
*
* @var int
*/
protected $unCodeNumber = 0;
/**
* English name
*
* @var string
*/
protected $nameEn = '';
/**
* UN numeric territory code of parent territory
*
* @var int
*/
protected $parentTerritoryUnCodeNumber = 0;
/**
* On initialization, get the columns mapping configuration
*/
public function initializeObject()
{
parent::initializeObject();
$this->tableName = $this->dataMapper->getDataMap(self::class)->getTableName();
}
/**
* Gets the deletion status of the entity
*
* @return bool
*/
public function getDeleted()
{
return $this->deleted;
}
/**
* Sets the deletion status of the entity
*
* @param bool $deleted
*
* @return void
*/
public function setDeleted($deleted)
{
$this->deleted = $deleted;
}
/**
* Sets the English name
*
* @param string $nameEn
*
* @return void
*/
public function setNameEn($nameEn)
{
$this->nameEn = $nameEn;
}
/**
* Returns the English name
*
* @return string
*/
public function getNameEn()
{
return $this->nameEn;
}
/**
* Sets the UN territory numeric code
*
* @param int $unCodeNumber
*
* @return void
*/
public function setUnCodeNumber($unCodeNumber)
{
$this->unCodeNumber = $unCodeNumber;
}
/**
* Returns the UN territory numeric code
*
* @return int
*/
public function getUnCodeNumber()
{
return $this->unCodeNumber;
}
/**
* Sets the UN numeric territory code of the parent territory
*
* @param int $parentTerritoryUnCodeNumber
*
* @return void
*/
public function setParentTerritoryUnCodeNumber($parentTerritoryUnCodeNumber)
{
$this->parentTerritoryUnCodeNumber = $parentTerritoryUnCodeNumber;
}
/**
* Returns the UN numeric territory code of the parent territory
*
* @return int
*/
public function getParentTerritoryUnCodeNumber()
{
return $this->parentTerritoryUnCodeNumber;
}
}

View File

@@ -0,0 +1,423 @@
<?php
namespace SJBR\StaticInfoTables\Domain\Repository;
/*
* Copyright notice
*
* (c) 2011-2012 Armin Rüdiger Vieweg <info@professorweb.de>
* (c) 2013-2022 Stanislas Rolland <typo3AAAA(arobas)sjbr.ca>
* All rights reserved
*
* This script is part of the TYPO3 project. The TYPO3 project is
* free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* The GNU General Public License can be found at
* http://www.gnu.org/copyleft/gpl.html.
*
* This script is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* This copyright notice MUST APPEAR in all copies of the script!
*/
use Doctrine\DBAL\Schema\Column;
use Doctrine\DBAL\Schema\TableDiff;
use Doctrine\DBAL\Types\Type;
use SJBR\StaticInfoTables\Service\SqlSchemaMigrationService;
use SJBR\StaticInfoTables\Utility\DatabaseUtility;
use SJBR\StaticInfoTables\Utility\LocalizationUtility;
use TYPO3\CMS\Core\Database\ConnectionPool;
use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapper;
use TYPO3\CMS\Extbase\Persistence\Generic\QuerySettingsInterface;
use TYPO3\CMS\Extbase\Persistence\Generic\Typo3QuerySettings;
use TYPO3\CMS\Extbase\Persistence\QueryInterface;
use TYPO3\CMS\Extbase\Persistence\QueryResultInterface;
use TYPO3\CMS\Extbase\Persistence\Repository;
/**
* Abstract Repository for static entities
*
* @author Armin Rüdiger Vieweg <info@professorweb.de>
* @author Stanislas Rolland <typo3(arobas)sjbr.ca>
* @author Oliver Klee <typo3-coding@oliverklee.de>
*/
abstract class AbstractEntityRepository extends Repository
{
/**
* @var string Name of the extension this class belongs to
*/
protected $extensionName = 'StaticInfoTables';
/**
* @var DataMapper
*/
protected $dataMapper;
/**
* @var array ISO keys for this static table
*/
protected $isoKeys = [];
/**
* Injects the DataMapper to map nodes to objects
*
* @param DataMapper $dataMapper
*
* @return void
*/
public function injectDataMapper(DataMapper $dataMapper)
{
$this->dataMapper = $dataMapper;
}
/**
* Initializes the repository.
*
* @return void
*/
public function initializeObject()
{
$querySettings = GeneralUtility::makeInstance(Typo3QuerySettings::class);
$querySettings->setRespectStoragePage(false);
$this->setDefaultQuerySettings($querySettings);
}
/**
* Find all with deleted included
*
* @return \TYPO3\CMS\Extbase\Persistence\QueryResultInterface|array all entries
*/
public function findAllDeletedIncluded()
{
$querySettings = GeneralUtility::makeInstance(QuerySettingsInterface::class);
$querySettings->setStoragePageIds([0]);
$querySettings->setIncludeDeleted(true);
$this->setDefaultQuerySettings($querySettings);
return parent::findAll();
}
/**
* Find all objects with uid in list
*
* @param string $list: list of uid's
* @return QueryResultInterface|array all entries
*/
public function findAllByUidInList($list = '')
{
if (empty($list)) {
return [];
}
$query = $this->createQuery();
$list = GeneralUtility::trimExplode(',', $list, true);
$query->matching($query->in('uid', $list));
return $query->execute();
}
/**
* Find all ordered by the localized name
*
* @param string $orderDirection may be "asc" or "desc". Default is "asc".
* @return QueryResultInterface|array all entries ordered by localized name
*/
protected function findAllOrderedByLocalizedName($orderDirection = 'asc')
{
$entities = parent::findAll();
return $this->localizedSort($entities, $orderDirection);
}
/**
* Sort entities by the localized name
*
* @param QueryResultInterface $entities to be sorted
* @param string $orderDirection may be "asc" or "desc". Default is "asc".
*
* @return array entities ordered by localized name
*/
public function localizedSort(QueryResultInterface $entities, $orderDirection = 'asc')
{
$result = $entities->toArray();
$locale = LocalizationUtility::setCollatingLocale();
if ($locale !== false) {
if ($orderDirection === 'asc') {
uasort($result, [$this, 'strcollOnLocalizedName']);
} else {
uasort($result, [$this, 'strcollOnLocalizedNameDesc']);
}
}
return $result;
}
/**
* Using strcoll comparison on localized names
*
* @return int see strcoll
*
* @param mixed $entityA
* @param mixed $entityB
*/
protected function strcollOnLocalizedName($entityA, $entityB)
{
return strcoll($entityA->getNameLocalized(), $entityB->getNameLocalized());
}
/**
* Using strcoll comparison on localized names - descending order
*
* @return int see strcoll
*
* @param mixed $entityA
* @param mixed $entityB
*/
protected function strcollOnLocalizedNameDesc($entityA, $entityB)
{
return strcoll($entityB->getNameLocalized(), $entityA->getNameLocalized());
}
/**
* Find all ordered by given property name
*
* @param string $propertyName property name to order by
* @param string $orderDirection may be "asc" or "desc". Default is "asc".
* @return QueryResultInterface|array all entries ordered by $propertyName
*/
public function findAllOrderedBy($propertyName, $orderDirection = 'asc')
{
$queryResult = [];
if ($orderDirection !== 'asc' && $orderDirection !== 'desc') {
throw new \InvalidArgumentException('Order direction must be "asc" or "desc".', 1316607580);
}
if ($propertyName == 'nameLocalized') {
$queryResult = $this->findAllOrderedByLocalizedName($orderDirection);
} else {
$query = $this->createQuery();
$object = new $this->objectType();
if (!array_key_exists($propertyName, $object->_getProperties())) {
throw new \InvalidArgumentException('The model "' . $this->objectType . '" has no property "' . $propertyName . '" to order by.', 1316607579);
}
if ($orderDirection === 'asc') {
$orderDirection = QueryInterface::ORDER_ASCENDING;
} else {
$orderDirection = QueryInterface::ORDER_DESCENDING;
}
$query->setOrderings([$propertyName => $orderDirection]);
return $query->execute();
}
return $queryResult;
}
/**
* Adds localization columns, if needed
*
* @param string $locale: the locale for which localization columns should be added
* @return AbstractEntityRepository $this
*/
public function addLocalizationColumns($locale)
{
$dataMap = $this->dataMapper->getDataMap($this->objectType);
$tableName = $dataMap->getTableName();
$fieldsInfo = $this->getFieldsInfo();
$connectionPool = GeneralUtility::makeInstance(ConnectionPool::class);
foreach ($fieldsInfo as $field => $fieldInfo) {
if ($field != 'cn_official_name_en') {
$matches = [];
if (preg_match('#_en$#', $field, $matches)) {
// Make localization field name
$localizationField = preg_replace('#_en$#', '_' . $locale, $field);
// Add the field if it does not yet exist
if (!$fieldsInfo[$localizationField]) {
// Get field length
$matches = [];
if (preg_match('#\\(([0-9]+)\\)#', $fieldInfo['Type'] ?? '', $matches)) {
$localizationFieldLength = (int)($matches[1]);
// Add the localization field
$connection = $connectionPool->getConnectionForTable($tableName);
$column = new Column($localizationField, Type::getType(Type::STRING));
$column->setLength($localizationFieldLength)
->setNotnull(true)
->setDefault('');
$tableDiff = new TableDiff($tableName, [$column]);
$query = $connection->getDatabasePlatform()->getAlterTableSQL($tableDiff);
$connection->executeUpdate($query[0]);
}
}
}
}
}
return $this;
}
/**
* Get the information on the table fields
*
* @return array table fields information array
*/
protected function getFieldsInfo()
{
$fieldsInfo = [];
$dataMap = $this->dataMapper->getDataMap($this->objectType);
$tableName = $dataMap->getTableName();
$connectionPool = GeneralUtility::makeInstance(ConnectionPool::class);
$connection = $connectionPool->getConnectionForTable($tableName);
$query = $connection->getDatabasePlatform()->getListTableColumnsSQL($tableName, $connection->getDatabase());
$columnsInfo = $connection->executeQuery($query);
foreach ($columnsInfo as $fieldRow) {
$fieldsInfo[$fieldRow['Field']] = $fieldRow;
}
return $fieldsInfo;
}
/**
* Get update queries for the localization columns for a given locale
*
* @return array Update queries
* @param mixed $locale
*/
public function getUpdateQueries($locale)
{
// Get the information of the table and its fields
$dataMap = $this->dataMapper->getDataMap($this->objectType);
$tableName = $dataMap->getTableName();
$tableFields = array_keys($this->getFieldsInfo());
$connectionPool = GeneralUtility::makeInstance(ConnectionPool::class);
$connection = $connectionPool->getConnectionForTable($tableName);
$updateQueries = [];
// If the language pack is not yet created or not yet installed, the localization columns are not yet part of the domain model
$exportFields = [];
foreach ($tableFields as $field) {
$matches = [];
if (preg_match('#_' . strtolower($locale) . '$#', $field, $matches)) {
$exportFields[] = $field;
}
}
if (count($exportFields)) {
$updateQueries[] = '## ' . $tableName;
$exportFields = array_merge($exportFields, $this->isoKeys);
$queryBuilder = $connectionPool->getQueryBuilderForTable($tableName);
$queryBuilder->getRestrictions()->removeAll();
$queryBuilder->select($exportFields[0]);
array_shift($exportFields);
foreach ($exportFields as $exportField) {
$queryBuilder->addSelect($exportField);
}
$rows = $queryBuilder
->from($tableName)
->execute()
->fetchAll();
foreach ($rows as $row) {
$set = [];
foreach ($row as $field => $value) {
if (!in_array($field, $this->isoKeys)) {
$set[] = $field . '=' . $connection->quote($value);
}
}
$whereClause = '';
foreach ($this->isoKeys as $field) {
$whereClause .= ($whereClause ? ' AND ' : ' WHERE ') . $field . '=' . $connection->quote($row[$field]);
}
$updateQueries[] = 'UPDATE ' . $tableName . ' SET ' . implode(',', $set) . $whereClause . ';';
}
}
return $updateQueries;
}
/**
* Dump non-localized contents of the repository
*/
public function sqlDumpNonLocalizedData()
{
// Get the information of the table and its fields
$dataMap = $this->dataMapper->getDataMap($this->objectType);
$tableName = $dataMap->getTableName();
$sqlSchemaMigrationService = GeneralUtility::makeInstance(SqlSchemaMigrationService::class);
$dbFieldDefinitions = $sqlSchemaMigrationService->getFieldDefinitions_database();
$dbFields = [];
$dbFields[$tableName] = $dbFieldDefinitions[$tableName];
$extensionKey = GeneralUtility::camelCaseToLowerCaseUnderscored($this->extensionName);
$extensionPath = ExtensionManagementUtility::extPath($extensionKey);
$ext_tables = @file_get_contents($extensionPath . 'ext_tables.sql');
$tableFields = array_keys($dbFields[$tableName]['fields']);
foreach ($tableFields as $field) {
// This is a very simple check if the field is from static_info_tables and not from a language pack
$match = [];
if (!preg_match('#' . preg_quote($field, '#') . '#m', $ext_tables, $match)) {
unset($dbFields[$tableName]['fields'][$field]);
}
}
$databaseUtility = GeneralUtility::makeInstance(DatabaseUtility::class);
return $databaseUtility->dumpStaticTables($dbFields);
}
/**
* Adds an object to this repository.
*
* @param object $object The object to add
* @return void
* @throws \BadMethodCallException(
*/
public function add($object)
{
throw new \BadMethodCallException(
'This is a read-only repository in which the add method must not be called.',
1420485488
);
}
/**
* Removes an object from this repository.
*
* @param object $object The object to remove
* @return void
* @throws \BadMethodCallException(
*/
public function remove($object)
{
throw new \BadMethodCallException(
'This is a read-only repository in which the remove method must not be called.',
1420485646
);
}
/**
* Replaces an existing object with the same identifier by the given object.
*
* @return void
* @throws \BadMethodCallException(
*/
public function update($modifiedObject)
{
throw new \BadMethodCallException(
'This is a read-only repository in which the update method must not be called.',
1420485660
);
}
/**
* Removes all objects of this repository as if remove() was called for all of them.
*
* @return void
* @throws \BadMethodCallException(
*/
public function removeAll()
{
throw new \BadMethodCallException(
'This is a read-only repository in which the removeAll method must not be called.',
1420485668
);
}
}

View File

@@ -0,0 +1,119 @@
<?php
namespace SJBR\StaticInfoTables\Domain\Repository;
/*
* Copyright notice
*
* (c) 2011-2012 Armin Rädiger Vieweg <info@professorweb.de>
* (c) 2013-2016 Stanislas Rolland <typo3(arobas)sjbr.ca>
*
* All rights reserved
*
* This script is part of the TYPO3 project. The TYPO3 project is
* free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* The GNU General Public License can be found at
* http://www.gnu.org/copyleft/gpl.html.
*
* This script is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* This copyright notice MUST APPEAR in all copies of the script!
*/
use SJBR\StaticInfoTables\Domain\Model\Territory;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Extbase\Persistence\QueryResultInterface;
/**
* Repository for \SJBR\StaticInfoTables\Domain\Model\Country
*/
class CountryRepository extends AbstractEntityRepository
{
/**
* ISO keys for this static table
*
* @var array
*/
protected $isoKeys = ['cn_iso_2'];
/**
* @var TerritoryRepository
*/
protected $territoryRepository;
/**
* Dependency injection of the Territory Repository
*
* @param TerritoryRepository $territoryRepository
* @return void
*/
public function injectTerritoryRepository(TerritoryRepository $territoryRepository)
{
$this->territoryRepository = $territoryRepository;
}
/**
* Finds countries by territory
*
* @param Territory $territory
* @return QueryResultInterface|array
*/
public function findByTerritory(Territory $territory)
{
$unCodeNumbers = [$territory->getUnCodeNumber()];
// Get UN code numbers of subterritories (recursively)
$subterritories = $this->territoryRepository->findWithinTerritory($territory);
foreach ($subterritories as $subterritory) {
$unCodeNumbers[] = $subterritory->getUnCodeNumber();
}
$query = $this->createQuery();
$query->matching(
$query->in('parentTerritoryUnCodeNumber', $unCodeNumbers)
);
return $query->execute();
}
/**
* Finds countries by territory ordered by localized name
*
* @param Territory $territory
* @return array Countries of the territory sorted by localized name
*/
public function findByTerritoryOrderedByLocalizedName(Territory $territory)
{
$entities = $this->findByTerritory($territory);
return $this->localizedSort($entities);
}
/**
* Finds a set of allowed countries
*
* @param string $allowedCountries: list of alpha-3 country codes
* @return array the selected countries
*/
public function findAllowedByIsoCodeA3($allowedCountries = '')
{
$query = $this->createQuery();
$countries = GeneralUtility::trimExplode(',', $allowedCountries, true);
$query->matching(
$query->in('isoCodeA3', $countries)
);
$entities = $query->execute();
$orderedCountries = [];
foreach ($countries as $isoCodeA3) {
foreach ($entities as $entity) {
if ($entity->getIsoCodeA3() === $isoCodeA3) {
$orderedCountries[] = $entity;
break;
}
}
}
return $orderedCountries;
}
}

View File

@@ -0,0 +1,68 @@
<?php
namespace SJBR\StaticInfoTables\Domain\Repository;
/*
* Copyright notice
*
* (c) 2011-2012 Armin Rüdiger Vieweg <info@professorweb.de>
* (c) 2013-2021 Stanislas Rolland <typo3AAAA(arobas)sjbr.ca>
*
* All rights reserved
*
* This script is part of the TYPO3 project. The TYPO3 project is
* free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* The GNU General Public License can be found at
* http://www.gnu.org/copyleft/gpl.html.
*
* This script is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* This copyright notice MUST APPEAR in all copies of the script!
*/
use SJBR\StaticInfoTables\Domain\Model\Country;
use TYPO3\CMS\Extbase\Persistence\QueryResultInterface;
/**
* Repository for \SJBR\StaticInfoTables\Domain\Model\CountryZone
*/
class CountryZoneRepository extends AbstractEntityRepository
{
/**
* @var array ISO keys for this static table
*/
protected $isoKeys = ['zn_country_iso_2', 'zn_code'];
/**
* Finds country zones by country
*
* @param Country $country
* @return QueryResultInterface|array
*/
public function findByCountry(Country $country)
{
$query = $this->createQuery();
$query->matching(
$query->equals('countryIsoCodeNumber', $country->getIsoCodeNumber())
);
return $query->execute();
}
/**
* Finds country zones by country ordered by localized name
*
* @param Country $country
* @return array Country zones of the country sorted by localized name
*/
public function findByCountryOrderedByLocalizedName(Country $country)
{
$entities = $this->findByCountry($country);
return $this->localizedSort($entities);
}
}

View File

@@ -0,0 +1,56 @@
<?php
namespace SJBR\StaticInfoTables\Domain\Repository;
/*
* Copyright notice
*
* (c) 2011-2012 Armin Rüdiger Vieweg <info@professorweb.de>
* (c) 2013-2021 Stanislas Rolland <typo3AAAA(arobas)sjbr.ca>
*
* All rights reserved
*
* This script is part of the TYPO3 project. The TYPO3 project is
* free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* The GNU General Public License can be found at
* http://www.gnu.org/copyleft/gpl.html.
*
* This script is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* This copyright notice MUST APPEAR in all copies of the script!
*/
use SJBR\StaticInfoTables\Domain\Model\Country;
use TYPO3\CMS\Extbase\Persistence\QueryResultInterface;
/**
* Repository for \SJBR\StaticInfoTables\Domain\Model\Currency
*/
class CurrencyRepository extends AbstractEntityRepository
{
/**
* @var array ISO keys for this static table
*/
protected $isoKeys = ['cu_iso_3'];
/**
* Finds currency by country
*
* @param Country $country
* @return QueryResultInterface|array
*/
public function findByCountry(Country $country)
{
$query = $this->createQuery();
$query->matching(
$query->equals('isoCodeNumber', $country->getCurrencyIsoCodeNumber())
);
return $query->execute();
}
}

View File

@@ -0,0 +1,159 @@
<?php
namespace SJBR\StaticInfoTables\Domain\Repository;
/*
* Copyright notice
*
* (c) 2013-2021 Stanislas Rolland <typo3AAAA(arobas)sjbr.ca>
* All rights reserved
*
* This script is part of the TYPO3 project. The TYPO3 project is
* free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* The GNU General Public License can be found at
* http://www.gnu.org/copyleft/gpl.html.
* A copy is found in the textfile GPL.txt and important notices to the license
* from the author is found in LICENSE.txt distributed with these scripts.
*
*
* This script is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* This copyright notice MUST APPEAR in all copies of the script!
*/
use SJBR\StaticInfoTables\Cache\ClassCacheManager;
use SJBR\StaticInfoTables\Domain\Model\LanguagePack;
use SJBR\StaticInfoTables\Utility\VersionNumberUtility;
use TYPO3\CMS\Core\Cache\CacheManager;
use TYPO3\CMS\Core\Core\Environment;
use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Extbase\Persistence\Repository;
use TYPO3\CMS\Extbase\Utility\LocalizationUtility;
use TYPO3\CMS\Extensionmanager\Utility\InstallUtility;
class LanguagePackRepository extends Repository
{
/**
* @var string Name of the extension this class belongs to
*/
protected $extensionName = 'StaticInfoTables';
/**
* Writes the language pack files
*
* @param LanguagePack the object to be stored
* @return array localized messages
*/
public function writeLanguagePack(LanguagePack $languagePack)
{
$content = [];
$extensionKey = GeneralUtility::camelCaseToLowerCaseUnderscored($this->extensionName);
$extensionPath = ExtensionManagementUtility::extPath($extensionKey);
$content = [];
$locale = $languagePack->getLocale();
$localeLowerCase = strtolower($locale);
$localeUpperCase = strtoupper($locale);
$localeCamel = GeneralUtility::underscoredToUpperCamelCase(strtolower($locale));
$languagePackExtensionKey = $extensionKey . '_' . $localeLowerCase;
$languagePackExtensionPath = Environment::getPublicPath() . '/typo3conf/ext/' . $languagePackExtensionKey . '/';
// Cleanup any pre-existing language pack
if (is_dir($languagePackExtensionPath)) {
GeneralUtility::rmdir($languagePackExtensionPath, true);
}
// Create language pack directory structure
if (!is_dir($languagePackExtensionPath)) {
GeneralUtility::mkdir_deep($languagePackExtensionPath);
}
if (!is_dir($languagePackExtensionPath . 'Classes/Domain/Model/')) {
GeneralUtility::mkdir_deep($languagePackExtensionPath . 'Classes/Domain/Model/');
}
if (!is_dir($languagePackExtensionPath . 'Configuration/DomainModelExtension/')) {
GeneralUtility::mkdir_deep($languagePackExtensionPath . 'Configuration/DomainModelExtension/');
}
if (!is_dir($languagePackExtensionPath . 'Configuration/TCA/Overrides/')) {
GeneralUtility::mkdir_deep($languagePackExtensionPath . 'Configuration/TCA/Overrides/');
}
if (!is_dir($languagePackExtensionPath . 'Configuration/PageTSconfig/')) {
GeneralUtility::mkdir_deep($languagePackExtensionPath . 'Configuration/PageTSconfig/');
}
if (!is_dir($languagePackExtensionPath . 'Configuration/Extbase/Persistence/')) {
GeneralUtility::mkdir_deep($languagePackExtensionPath . 'Configuration/Extbase/Persistence/');
}
if (!is_dir($languagePackExtensionPath . 'Resources/Private/Language/')) {
GeneralUtility::mkdir_deep($languagePackExtensionPath . 'Resources/Private/Language/');
}
if (!is_dir($languagePackExtensionPath . 'Resources/Public/Icons/')) {
GeneralUtility::mkdir_deep($languagePackExtensionPath . 'Resources/Public/Icons/');
}
// Get the source files of the language pack template
$sourcePath = $extensionPath . 'Resources/Private/LanguagePackTemplate/';
$sourceFiles = [];
$sourceFiles = GeneralUtility::getAllFilesAndFoldersInPath($sourceFiles, $sourcePath);
$sourceFiles = GeneralUtility::removePrefixPathFromList($sourceFiles, $sourcePath);
$typo3VersionRange = VersionNumberUtility::splitVersionRange($languagePack->getTypo3VersionRange());
$typo3VersionMinArray = VersionNumberUtility::convertVersionStringToArray($typo3VersionRange[0]);
$typo3VersionMaxArray = VersionNumberUtility::convertVersionStringToArray(VersionNumberUtility::raiseVersionNumber('main', $typo3VersionRange[1]));
// Set markers replacement values
$replace = [
'###LANG_ISO_LOWER###' => $localeLowerCase,
'###LANG_ISO_UPPER###' => $localeUpperCase,
'###LANG_ISO_CAMEL###' => $localeCamel,
'###TYPO3_VERSION_RANGE###' => $languagePack->getTypo3VersionRange(),
'###TYPO3_VERSION_MIN###' => $typo3VersionMinArray['version_main'] . '.' . $typo3VersionMinArray['version_sub'],
'###TYPO3_VERSION_MAX###' => $typo3VersionMaxArray['version_main'] . '.0',
'###VERSION###' => $languagePack->getVersion(),
'###LANG_NAME###' => $languagePack->getLanguage(),
'###AUTHOR###' => $languagePack->getAuthor(),
'###AUTHOR_EMAIL###' => $languagePack->getAuthorEmail(),
'###AUTHOR_COMPANY###' => $languagePack->getAuthorCompany(),
'###VENDOR_NAME###' => $languagePack->getVendorName(),
'###VERSION_BASE###' => $GLOBALS['TYPO3_CONF_VARS']['EXTENSIONS'][$extensionKey]['version'],
'###LANG_TCA_LABELS###' => $languagePack->getLocalizationLabels(),
'###LANG_SQL_UPDATE###' => $languagePack->getUpdateQueries(),
];
// Create the language pack files
$success = true;
foreach ($sourceFiles as $hash => $file) {
$fileContent = @file_get_contents($sourcePath . $file);
foreach ($replace as $marker => $replacement) {
$fileContent = str_replace($marker, $replacement, $fileContent);
}
$success = GeneralUtility::writeFile($languagePackExtensionPath . str_replace('.code', '.php', $file), $fileContent);
if (!$success) {
$content[] = LocalizationUtility::translate('couldNotWriteFile', $this->extensionName) . ' ' . $languagePackExtensionPath . $file;
break;
}
}
if ($success) {
$cacheManager = GeneralUtility::makeInstance(CacheManager::class);
$classCacheManager = new ClassCacheManager($cacheManager);
$installUtility = GeneralUtility::makeInstance(InstallUtility::class);
$installed = ExtensionManagementUtility::isLoaded($languagePackExtensionKey);
if ($installed) {
$content[] = LocalizationUtility::translate('languagePack', $this->extensionName)
. ' ' . $languagePackExtensionKey
. ' ' . LocalizationUtility::translate('languagePackUpdated', $this->extensionName);
} else {
$content[] = LocalizationUtility::translate('languagePackCreated', $this->extensionName) . ' ' . $languagePack->getLanguage() . ' (' . $locale . ')';
$installUtility->install($languagePackExtensionKey);
$content[] = LocalizationUtility::translate('languagePack', $this->extensionName)
. ' ' . $languagePackExtensionKey
. ' ' . LocalizationUtility::translate('wasInstalled', $this->extensionName);
}
$classCacheManager->reBuild();
}
return $content;
}
}

View File

@@ -0,0 +1,65 @@
<?php
namespace SJBR\StaticInfoTables\Domain\Repository;
/*
* Copyright notice
*
* (c) 2013-2021 Stanislas Rolland <typo3AAAA(arobas)sjbr.ca>
*
* All rights reserved
*
* This script is part of the TYPO3 project. The TYPO3 project is
* free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* The GNU General Public License can be found at
* http://www.gnu.org/copyleft/gpl.html.
*
* This script is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* This copyright notice MUST APPEAR in all copies of the script!
*/
use TYPO3\CMS\Extbase\Persistence\QueryResultInterface;
/**
* Repository for \SJBR\StaticInfoTables\Domain\Model\Language
*/
class LanguageRepository extends AbstractEntityRepository
{
/**
* @var array ISO keys for this static table
*/
protected $isoKeys = ['lg_iso_2', 'lg_country_iso_2'];
/**
* Find all neither constructed nor sacred languages
*
* @return QueryResultInterface|array all languages neither constructed nor sacred
*/
public function findAllNonConstructedNonSacred()
{
$query = $this->createQuery();
$query->matching($query->logicalAnd([$query->equals('constructedLanguage', false), $query->equals('sacredLanguage', false)]));
return $query->execute();
}
/**
* Find the language object with the specified iso codes
*
* @param string $languageIsoCodeA2
* @param string $countryIsoCodeA2
* @return QueryResultInterface|array all entries ordered by $propertyName
*/
public function findOneByIsoCodes($languageIsoCodeA2, $countryIsoCodeA2 = '')
{
$query = $this->createQuery();
$query->matching($query->logicalAnd([$query->equals('isoCodeA2', $languageIsoCodeA2), $query->equals('countryIsoCodeA2', $countryIsoCodeA2)]));
return $query->execute()->getFirst();
}
}

View File

@@ -0,0 +1,57 @@
<?php
namespace SJBR\StaticInfoTables\Domain\Repository;
/***************************************************************
* Copyright notice
*
* (c) 2013-2017 Stanislas Rolland <typo3@sjbr.ca>
* All rights reserved
*
* This script is part of the TYPO3 project. The TYPO3 project is
* free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* The GNU General Public License can be found at
* http://www.gnu.org/copyleft/gpl.html.
* A copy is found in the textfile GPL.txt and important notices to the license
* from the author is found in LICENSE.txt distributed with these scripts.
*
*
* This script is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* This copyright notice MUST APPEAR in all copies of the script!
***************************************************************/
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Extbase\Persistence\QueryResultInterface;
use TYPO3\CMS\Extbase\Persistence\Repository;
/**
* System language repository
*/
class SystemLanguageRepository extends Repository
{
/**
* Find all system language objects with uid in list
* If no list is provided, find all system language objects
*
* @param string $list: list of uid's
*
* @return QueryResultInterface|array all entries
*/
public function findAllByUidInList($list = '')
{
if (empty($list)) {
return $this->findAll();
}
$query = $this->createQuery();
$list = GeneralUtility::trimExplode(',', $list, true);
$query->matching($query->in('uid', $list));
return $query->execute();
}
}

View File

@@ -0,0 +1,107 @@
<?php
namespace SJBR\StaticInfoTables\Domain\Repository;
/*
* Copyright notice
*
* (c) 2011-2012 Armin Rüdiger Vieweg <info@professorweb.de>
* (c) 2013-2021 Stanislas Rolland <typo3AAAA(arobas)sjbr.ca>
*
* All rights reserved
*
* This script is part of the TYPO3 project. The TYPO3 project is
* free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* The GNU General Public License can be found at
* http://www.gnu.org/copyleft/gpl.html.
*
* This script is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* This copyright notice MUST APPEAR in all copies of the script!
*/
use SJBR\StaticInfoTables\Domain\Model\Country;
use SJBR\StaticInfoTables\Domain\Model\Territory;
use TYPO3\CMS\Extbase\Persistence\QueryResultInterface;
/**
* Repository for \SJBR\StaticInfoTables\Domain\Model\Territory
*/
class TerritoryRepository extends AbstractEntityRepository
{
/**
* ISO keys for this static table
*
* @var array
*/
protected $isoKeys = ['tr_iso_nr'];
/**
* Finds the territory within which a country is located
*
* @param Country $country
* @return QueryResultInterface|array
*/
public function findByCountry(Country $country)
{
$query = $this->createQuery();
$query->matching(
$query->equals('unCodeNumber', $country->getParentTerritoryUnCodeNumber())
);
return $query->execute();
}
/**
* Finds territories that have a given territory as parent territory
*
* @param Territory $territory
* @return QueryResultInterface|array
*/
public function findByTerritory(Territory $territory)
{
$query = $this->createQuery();
$query->matching(
$query->equals('parentTerritoryUnCodeNumber', $territory->getUnCodeNumber())
);
return $query->execute();
}
/**
* Finds all territories within a territory recursively
*
* @param Territory $territory
* @param array $unCodeNumbers array of UN territory code numbers used for recursive retrieval of sub-territories
* @return QueryResultInterface|array
*/
public function findWithinTerritory(Territory $territory, &$unCodeNumbers = [])
{
if (empty($unCodeNumbers)) {
$unCodeNumbers = [$territory->getUnCodeNumber()];
}
$initialCount = count($unCodeNumbers);
$query = $this->createQuery();
$query->matching(
$query->in('parentTerritoryUnCodeNumber', $unCodeNumbers)
);
$territories = $query->execute();
// Get UN code numbers of new subterritories
foreach ($territories as $subterritory) {
$unCodeNumbers[] = $subterritory->getUnCodeNumber();
}
$unCodeNumbers = array_unique($unCodeNumbers);
// Call recursively until no additional subterritories are found
if (count($unCodeNumbers) > $initialCount) {
$territories = $this->findWithinTerritory($territory, $unCodeNumbers);
}
return $territories;
}
}

View File

@@ -0,0 +1,165 @@
<?php
namespace SJBR\StaticInfoTables\EventListener;
/*
* Copyright notice
*
* (c) 2022 Stanislas Rolland <typo3AAAA(arobas)sjbr.ca>
* All rights reserved
*
* This script is part of the Typo3 project. The Typo3 project is
* free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* The GNU General Public License can be found at
* http://www.gnu.org/copyleft/gpl.html.
*
* This script is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* This copyright notice MUST APPEAR in all copies of the script!
*/
use SJBR\StaticInfoTables\Cache\ClassCacheManager;
use SJBR\StaticInfoTables\Utility\DatabaseUpdateUtility;
use TYPO3\CMS\Core\Registry;
use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Extbase\Utility\LocalizationUtility;
/*
* AfterPackageActivation event listener
*
* Always run the extension update script except on first install of base extension
*/
abstract class AbstractEventListener
{
/**
* @var string Name of the extension this controller belongs to
*/
protected $extensionName = 'StaticInfoTables';
/**
* @var Registry
*/
protected $registry;
/**
* @param Registry $registry
*/
public function __construct(Registry $registry)
{
$this->registry = $registry;
}
/**
* Execute the update
*
* @return void
*/
public function executeUpdate()
{
$databaseUpdateUtility = GeneralUtility::makeInstance(DatabaseUpdateUtility::class);
// Clear the class cache
$classCacheManager = GeneralUtility::makeInstance(ClassCacheManager::class);
$classCacheManager->reBuild();
if ($this->isUpdateRequired()) {
// Process the database updates of this base extension (we want to re-process these updates every time the update script is invoked)
// unless there was no change in the version numbers of the static info tables and language packs installed
$extensionSitePath = ExtensionManagementUtility::extPath(GeneralUtility::camelCaseToLowerCaseUnderscored($this->extensionName));
if (isset($GLOBALS['BE_USER'])) {
$GLOBALS['BE_USER']->writelog(3, 1, 0, 0, '[StaticInfoTables]: ' . LocalizationUtility::translate('updateTables', $this->extensionName) ?? '', [$GLOBALS['BE_USER']->user['username']]);
}
$databaseUpdateUtility->importStaticSqlFile($extensionSitePath);
// Get the extensions which want to extend static_info_tables
$loadedExtensions = array_unique(ExtensionManagementUtility::getLoadedExtensionListArray());
$languagePackUpdated = false;
foreach ($loadedExtensions as $extensionKey) {
if ($this->isStaticInfoTablesExtension($extensionKey)) {
// We need to reprocess the database structure update sql statements (ext_tables)
$databaseUpdateUtility->processDatabaseUpdates($extensionKey);
// Now we process the static data updates (ext_tables_static+adt)
// Note: The Install Tool Utility does not handle sql update statements
$databaseUpdateUtility->doUpdate($extensionKey);
if (isset($GLOBALS['BE_USER'])) {
$GLOBALS['BE_USER']->writelog(3, 1, 0, 0, '[StaticInfoTables]: ' . LocalizationUtility::translate('updateLanguageLabels', $this->extensionName, [$extensionKey]) ?? '', [$GLOBALS['BE_USER']->user['username']]);
}
$languagePackUpdated = true;
}
}
$this->storeLastUpdateStatus();
}
}
/**
* Is an update required?
*
* Returns true when the last stored update status is different from the current status
* or the forceUpdate GET parameter is provided.
*
* @return bool
*/
public function isUpdateRequired(): bool
{
$lastUpdateStatus = $this->registry->get('static_info_tables', 'last_update_status', false);
if (!$lastUpdateStatus) {
return true;
}
$extensionVersionInfo = $this->buildExtensionVersionInfo();
return $lastUpdateStatus !== $extensionVersionInfo;
}
/**
* Saves the last update status in the TYPO3 registry.
*/
protected function storeLastUpdateStatus()
{
$extensionVersionInfo = $this->buildExtensionVersionInfo();
$this->registry->set('static_info_tables', 'last_update_status', $extensionVersionInfo);
}
/**
* Loops over all loaded Extensions and collects the version info of every installed static_info_tables
* Extension. The Extension keys and version numbers are concated to a string:
*
* extension_key1:1.2.3
* extension_key2:2.3.4
* ...
*
* @return string
*/
protected function buildExtensionVersionInfo()
{
$mainVersion = ExtensionManagementUtility::getExtensionVersion('static_info_tables');
$extensionVersions = ['static_info_tables:' . $mainVersion];
$loadedExtensions = array_unique(ExtensionManagementUtility::getLoadedExtensionListArray());
foreach ($loadedExtensions as $extensionKey) {
if (!$this->isStaticInfoTablesExtension($extensionKey)) {
continue;
}
$extensionVersion = ExtensionManagementUtility::getExtensionVersion($extensionKey);
$extensionVersions[] = $extensionKey . ':' . $extensionVersion;
}
return implode(LF, $extensionVersions);
}
/**
* Returns true when the StaticInfoTables.txt configuration file exists in the given Extension.
*
* @param string $extensionKey
* @return bool
*/
protected function isStaticInfoTablesExtension($extensionKey)
{
$extensionInfoFile = ExtensionManagementUtility::extPath($extensionKey)
. 'Configuration/DomainModelExtension/StaticInfoTables.txt';
return file_exists($extensionInfoFile);
}
}

View File

@@ -0,0 +1,61 @@
<?php
namespace SJBR\StaticInfoTables\EventListener;
/*
* Copyright notice
*
* (c) 2022 Stanislas Rolland <typo3AAAA(arobas)sjbr.ca>
* All rights reserved
*
* This script is part of the Typo3 project. The Typo3 project is
* free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* The GNU General Public License can be found at
* http://www.gnu.org/copyleft/gpl.html.
*
* This script is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* This copyright notice MUST APPEAR in all copies of the script!
*/
use TYPO3\CMS\Extensionmanager\Event\AfterExtensionStaticDatabaseContentHasBeenImportedEvent;
use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
use TYPO3\CMS\Core\Utility\PathUtility;
/*
* AfterExtensionStaticDatabaseContentHasBeenImported event listener
*
* Run the update script after base data was re-imported
*/
class AfterExtensionStaticDatabaseContentHasBeenImportedEventListener extends AbstractEventListener
{
/**
* If the installed extension is static_info_tables or a language pack, execute the update
*
* @param AfterExtensionStaticDatabaseContentHasBeenImportedEvent $event
* @return void
*/
public function __invoke(AfterExtensionStaticDatabaseContentHasBeenImportedEvent $event): void
{
$extensionKey = $event->getPackageKey();
if (strpos($extensionKey, 'static_info_tables') === 0) {
$extensionKeyParts = explode('_', $extensionKey);
if (count($extensionKeyParts) === 3) {
$extTablesStaticSqlRelFile = PathUtility::stripPathSitePrefix(ExtensionManagementUtility::extPath($extensionKey)) . 'ext_tables_static+adt.sql';
}
if (
// Base extension with data already imported once
(count($extensionKeyParts) === 3 && $this->registry->get('extensionDataImport', $extTablesStaticSqlRelFile))
) {
$this->registry->remove('static_info_tables', 'last_update_status');
$this->executeUpdate();
}
}
}
}

View File

@@ -0,0 +1,64 @@
<?php
namespace SJBR\StaticInfoTables\EventListener;
/*
* Copyright notice
*
* (c) 2022 Stanislas Rolland <typo3AAAA(arobas)sjbr.ca>
* All rights reserved
*
* This script is part of the Typo3 project. The Typo3 project is
* free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* The GNU General Public License can be found at
* http://www.gnu.org/copyleft/gpl.html.
*
* This script is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* This copyright notice MUST APPEAR in all copies of the script!
*/
use TYPO3\CMS\Core\Package\Event\AfterPackageActivationEvent;
use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
use TYPO3\CMS\Core\Utility\PathUtility;
/*
* AfterPackageActivation event listener
*
* Always run the extension update script except on first install of base extension
*/
class AfterPackageActivationEventListener extends AbstractEventListener
{
/**
* If the installed extension is static_info_tables or a language pack, execute the update
*
* @param AfterPackageActivationEvent $event
* @return void
*/
public function __invoke(AfterPackageActivationEvent $event): void
{
$extensionKey = $event->getPackageKey();
$packageType = $event->getType();
if ($packageType === 'typo3-cms-extension' && strpos($extensionKey, 'static_info_tables') === 0) {
$extensionKeyParts = explode('_', $extensionKey);
if (count($extensionKeyParts) === 3) {
$extTablesStaticSqlRelFile = PathUtility::stripPathSitePrefix(ExtensionManagementUtility::extPath($extensionKey)) . 'ext_tables_static+adt.sql';
}
if (
// Base extension with data already imported once
(count($extensionKeyParts) === 3 && $this->registry->get('extensionDataImport', $extTablesStaticSqlRelFile))
// Language pack
|| (count($extensionKeyParts) === 4 && strlen($extensionKeyParts[3]) === 2)
|| (count($extensionKeyParts) === 5 && strlen($extensionKeyParts[3]) === 2 && strlen($extensionKeyParts[4]) === 2)
) {
$this->executeUpdate();
}
}
}
}

View File

@@ -0,0 +1,60 @@
<?php
namespace SJBR\StaticInfoTables\Hook\Backend\Form\FormDataProvider;
/*
* Copyright notice
*
* (c) 2017 Stanislas Rolland <typo3(arobas)sjbr.ca>
* All rights reserved
*
* This script is part of the Typo3 project. The Typo3 project is
* free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
* The GNU General Public License can be found at
* http://www.gnu.org/copyleft/gpl.html.
*
* This script is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* This copyright notice MUST APPEAR in all copies of the script!
*/
use SJBR\StaticInfoTables\Utility\LocalizationUtility;
use TYPO3\CMS\Backend\Form\Wizard\SuggestWizardDefaultReceiver;
/**
* Processor for suggest items
*/
class SuggestLabelProcessor
{
/**
* Translate label of entity in suggest selector
*
* @param array $params: table, uid, row, entry
* @param SuggestWizardDefaultReceiver $parentObj
*
* @return void
*/
public function translateLabel(array &$params, SuggestWizardDefaultReceiver $parentObj)
{
$path = $params['entry']['path'];
if (mb_strlen($path, 'utf-8') > 30) {
$croppedPath = '<abbr title="' . htmlspecialchars($path) . '">' .
htmlspecialchars(
mb_substr($path, 0, 10, 'utf-8')
. '...'
. mb_substr($path, -20, null, 'utf-8')
) .
'</abbr>';
} else {
$croppedPath = htmlspecialchars($path);
}
$label = LocalizationUtility::translate(['uid' => $params['uid']], $params['table']);
$params['entry']['text'] = '<span class="suggest-label">' . $label . '</span><span class="suggest-uid">[' . $params['uid'] . ']</span><br />
<span class="suggest-path">' . $croppedPath . '</span>';
}
}

View File

@@ -0,0 +1,136 @@
<?php
namespace SJBR\StaticInfoTables\Hook\Backend\Form\FormDataProvider;
/*
* Copyright notice
*
* (c) 2013-2022 Stanislas Rolland <typo3AAAA(arobas)sjbr.ca>
* All rights reserved
*
* This script is part of the Typo3 project. The Typo3 project is
* free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
* The GNU General Public License can be found at
* http://www.gnu.org/copyleft/gpl.html.
*
* This script is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* This copyright notice MUST APPEAR in all copies of the script!
*/
use Psr\Http\Message\ServerRequestInterface;
use SJBR\StaticInfoTables\Domain\Model\Country;
use SJBR\StaticInfoTables\Domain\Model\Currency;
use SJBR\StaticInfoTables\Domain\Model\Language;
use SJBR\StaticInfoTables\Domain\Model\Territory;
use SJBR\StaticInfoTables\Domain\Repository\CountryRepository;
use SJBR\StaticInfoTables\Domain\Repository\CurrencyRepository;
use SJBR\StaticInfoTables\Domain\Repository\LanguageRepository;
use SJBR\StaticInfoTables\Domain\Repository\TerritoryRepository;
use SJBR\StaticInfoTables\Utility\LocalizationUtility;
use TYPO3\CMS\Core\Http\ApplicationType;
use TYPO3\CMS\Core\Utility\GeneralUtility;
/**
* Processor for TCA select items
*/
class TcaLabelProcessor
{
/**
* @var TerritoryRepository
*/
protected $territoryRepository;
/**
* @param TerritoryRepository $territoryRepository
*/
public function injectTerritoryRepository(TerritoryRepository $territoryRepository)
{
$this->territoryRepository = $territoryRepository;
}
/**
* Add ISO codes to the label of entities
*
* @param array $PA: parameters: items, config, TSconfig, table, row, field
* @return void
*/
public function addIsoCodeToLabel(&$PA)
{
if (!isset($PA['row']['uid'])) {
return;
}
$PA['title'] = LocalizationUtility::translate(['uid' => $PA['row']['uid']], $PA['table']);
if (($GLOBALS['TYPO3_REQUEST'] ?? null) instanceof ServerRequestInterface
&& ApplicationType::fromRequest($GLOBALS['TYPO3_REQUEST'])->isBackend()) {
switch ($PA['table']) {
case 'static_territories':
$isoCode = $PA['row']['tr_iso_nr'] ?? 0;
if (!$isoCode) {
$territory = $this->territoryRepository->findByUid($PA['row']['uid']);
if ($territory instanceof Territory) {
$isoCode = $territory->getUnCodeNumber();
}
}
if ($isoCode) {
$PA['title'] .= ' (' . $isoCode . ')';
}
break;
case 'static_countries':
$isoCode = $PA['row']['cn_iso_2'] ?? '';
if (!$isoCode) {
$countryRepository = GeneralUtility::makeInstance(CountryRepository::class);
$country = $countryRepository->findByUid($PA['row']['uid']);
if ($country instanceof Country) {
$isoCode = $country->getIsoCodeA2();
}
}
if ($isoCode) {
$PA['title'] .= ' (' . $isoCode . ')';
}
break;
case 'static_languages':
$isoCodes = [$PA['row']['lg_iso_2'] ?? ''];
if ($PA['row']['lg_country_iso_2'] ?? '') {
$isoCodes[] = $PA['row']['lg_country_iso_2'];
}
$isoCode = implode('_', $isoCodes);
if (!$isoCode || !($PA['row']['lg_country_iso_2'] ?? '')) {
$languageRepository = GeneralUtility::makeInstance(LanguageRepository::class);
$language = $languageRepository->findByUid($PA['row']['uid']);
if ($language instanceof Language) {
$isoCodes = [$language->getIsoCodeA2()];
if ($language->getCountryIsoCodeA2()) {
$isoCodes[] = $language->getCountryIsoCodeA2();
}
$isoCode = implode('_', $isoCodes);
}
}
if ($isoCode) {
$PA['title'] .= ' (' . $isoCode . ')';
}
break;
case 'static_currencies':
$isoCode = $PA['row']['cu_iso_3'] ?? '';
if (!$isoCode) {
$currencyRepository = GeneralUtility::makeInstance(CurrencyRepository::class);
$currency = $currencyRepository->findByUid($PA['row']['uid']);
if ($currency instanceof Currency) {
$isoCode = $currency->getIsoCodeA3();
}
}
if ($isoCode) {
$PA['title'] .= ' (' . $isoCode . ')';
}
break;
default:
break;
}
}
}
}

View File

@@ -0,0 +1,280 @@
<?php
namespace SJBR\StaticInfoTables\Hook\Backend\Form\FormDataProvider;
/*
* Copyright notice
*
* (c) 2013-2022 Stanislas Rolland <typo3AAAA(arobas)sjbr.ca>
* All rights reserved
*
* This script is part of the Typo3 project. The Typo3 project is
* free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* The GNU General Public License can be found at
* http://www.gnu.org/copyleft/gpl.html.
*
* This script is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* This copyright notice MUST APPEAR in all copies of the script!
*/
use SJBR\StaticInfoTables\Domain\Model\Country;
use SJBR\StaticInfoTables\Domain\Model\CountryZone;
use SJBR\StaticInfoTables\Domain\Model\Currency;
use SJBR\StaticInfoTables\Domain\Model\Language;
use SJBR\StaticInfoTables\Domain\Model\Territory;
use SJBR\StaticInfoTables\Domain\Repository\CountryRepository;
use SJBR\StaticInfoTables\Domain\Repository\CountryZoneRepository;
use SJBR\StaticInfoTables\Domain\Repository\CurrencyRepository;
use SJBR\StaticInfoTables\Domain\Repository\LanguageRepository;
use SJBR\StaticInfoTables\Domain\Repository\TerritoryRepository;
use SJBR\StaticInfoTables\Utility\LocalizationUtility;
use TYPO3\CMS\Backend\Form\FormDataProvider\TcaSelectItems;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapper;
/**
* Processor for TCA select items
*/
class TcaSelectItemsProcessor
{
/**
* Translate and sort the territories selector using the current locale
*
* @param array $PA: parameters: items, config, TSconfig, table, row, field
* @param DataPreprocessor $fObj
* @return void
*/
public function translateTerritoriesSelector($PA, TcaSelectItems $fObj)
{
switch ($PA['table'] ?? '') {
case 'static_territories':
// Avoid circular relation
$row = $PA['row'] ?? [];
foreach (($PA['items'] ?? []) as $index => $item) {
if ($item[1] == $row['uid']) {
unset($PA['items'][$index]);
}
}
break;
}
$PA['items'] = $this->translateSelectorItems($PA['items'], 'static_territories');
$PA['items'] = $this->replaceSelectorIndexField($PA);
}
/**
* Translate and sort the countries selector using the current locale
*
* @param array $PA: parameters: items, config, TSconfig, table, row, field
* @param DataPreprocessor $fObj
*
* @return void
*/
public function translateCountriesSelector($PA, TcaSelectItems $fObj)
{
$PA['items'] = $this->translateSelectorItems($PA['items'], 'static_countries');
$PA['items'] = $this->replaceSelectorIndexField($PA);
}
/**
* Translate and sort the country zones selector using the current locale
*
* @param array $PA: parameters: items, config, TSconfig, table, row, field
* @param DataPreprocessor $fObj
*
* @return void
*/
public function translateCountryZonesSelector($PA, TcaSelectItems $fObj)
{
$PA['items'] = $this->translateSelectorItems($PA['items'], 'static_country_zones');
$PA['items'] = $this->replaceSelectorIndexField($PA);
}
/**
* Translate and sort the currencies selector using the current locale
*
* @param array $PA: parameters: items, config, TSconfig, table, row, field
* @param DataPreprocessor $fObj
*
* @return void
*/
public function translateCurrenciesSelector($PA, TcaSelectItems $fObj)
{
$PA['items'] = $this->translateSelectorItems($PA['items'], 'static_currencies');
$PA['items'] = $this->replaceSelectorIndexField($PA);
}
/**
* Translate and sort the languages selector using the current locale
*
* @param array $PA: parameters: items, config, TSconfig, table, row, field
* @param DataPreprocessor $fObj
*
* @return void
*/
public function translateLanguagesSelector($PA, TcaSelectItems $fObj)
{
$PA['items'] = $this->translateSelectorItems($PA['items'], 'static_languages');
$PA['items'] = $this->replaceSelectorIndexField($PA);
}
/**
* Translate selector items array
*
* @param array $items: array of value/label pairs
* @param string $tableName: name of static info tables
*
* @return array array of value/translated label pairs
*/
protected function translateSelectorItems($items, $tableName)
{
$translatedItems = $items;
if (isset($translatedItems) && is_array($translatedItems)) {
foreach ($translatedItems as $key => $item) {
if (is_array($translatedItems[$key]) && array_key_exists(1, $translatedItems[$key]) && ($translatedItems[$key][1] ?? '')) {
//Get isocode if present
$code = strstr($item[0], '(');
$code2 = strstr(substr($code, 1), '(');
$code = $code2 ? $code2 : $code;
// Translate
$translatedItems[$key][0] = LocalizationUtility::translate(['uid' => $item[1]], $tableName);
// Re-append isocode, if present
$translatedItems[$key][0] = $translatedItems[$key][0] . ($code ? ' ' . $code : '');
}
}
$currentLocale = setlocale(LC_COLLATE, '0');
$locale = LocalizationUtility::setCollatingLocale();
if ($locale !== false) {
uasort($translatedItems, [$this, 'strcollOnLabels']);
}
setlocale(LC_COLLATE, $currentLocale);
}
$items = $translatedItems;
return $items;
}
/**
* Using strcoll comparison on labels
*
* @return int see strcoll
*
* @param mixed $itemA
* @param mixed $itemB
*/
protected function strcollOnLabels($itemA, $itemB)
{
return strcoll($itemA[0], $itemB[0]);
}
/**
* Replace the selector's uid index with configured indexField
*
* @param array $PA: TCA select field parameters array
* @return array The new $items array
*/
protected function replaceSelectorIndexField($PA)
{
$items = $PA['items'] ?? [];
$indexFields = GeneralUtility::trimExplode(',', $PA['config']['itemsProcFunc_config']['indexField'] ?? '', true);
if (!empty($indexFields)) {
$rows = [];
// Collect items uid's
$uids = [];
foreach ($items as $key => $item) {
if (is_array($items[$key]) && array_key_exists(1, $items[$key]) && ($items[$key][1] ?? 0)) {
$uids[] = $item[1];
}
}
$uidList = implode(',', $uids);
if (!empty($uidList)) {
switch ($PA['config']['foreign_table'] ?? '') {
case 'static_territories':
/** @var $territoryRepository TerritoryRepository */
$territoryRepository = GeneralUtility::makeInstance(TerritoryRepository::class);
$objects = $territoryRepository->findAllByUidInList($uidList)->toArray();
break;
case 'static_countries':
/** @var $countryRepository CountryRepository */
$countryRepository = GeneralUtility::makeInstance(CountryRepository::class);
$objects = $countryRepository->findAllByUidInList($uidList)->toArray();
break;
case 'static_country_zones':
/** @var $countryZoneRepository CountryZoneRepository */
$countryZoneRepository = GeneralUtility::makeInstance(CountryZoneRepository::class);
$objects = $countryZoneRepository->findAllByUidInList($uidList)->toArray();
break;
case 'static_languages':
/** @var $languageRepository LanguageRepository */
$languageRepository = GeneralUtility::makeInstance(LanguageRepository::class);
$objects = $languageRepository->findAllByUidInList($uidList)->toArray();
break;
case 'static_currencies':
/** @var $currencyRepository CurrencyRepository */
$currencyRepository = GeneralUtility::makeInstance(CurrencyRepository::class);
$objects = $currencyRepository->findAllByUidInList($uidList)->toArray();
break;
default:
break;
}
if (!empty($objects)) {
$columnsMapping = $this->getColumnsMapping($objects[0]);
// Map table column to object property
$indexProperties = [];
foreach ($indexFields as $indexField) {
if ($columnsMapping[$indexField]['mapOnProperty'] ?? '') {
$indexProperties[] = $columnsMapping[$indexField]['mapOnProperty'];
} else {
$indexProperties[] = GeneralUtility::underscoredToLowerCamelCase($indexField);
}
}
// Index rows by uid
$uidIndexedRows = [];
foreach ($objects as $object) {
$uidIndexedObjects[$object->getUid()] = $object;
}
// Replace the items index field
foreach ($items as $key => $item) {
if (is_array($items[$key]) && array_key_exists(1, $items[$key]) && ($items[$key][1] ?? 0)) {
$object = $uidIndexedObjects[$items[$key][1]];
$items[$key][1] = $object->_getProperty($indexProperties[0]);
if (($indexFields[1] ?? false) && $object->_getProperty($indexProperties[1] ?? '')) {
$items[$key][1] .= '_' . $object->_getProperty($indexProperties[1]);
}
}
}
}
}
}
return $items;
}
/**
* Get the columns mapping for the object
*
* @param object $object
* @return array
*/
protected function getColumnsMapping($object)
{
$columnsMapping = [];
$dataMapper = GeneralUtility::makeInstance(DataMapper::class);
$className = get_class($object);
$dataMap = $dataMapper->getDataMap($className);
$properties = $object->_getProperties();
foreach ($properties as $propertyName => $propertyValue) {
if (!$dataMap->isPersistableProperty($propertyName)) {
continue;
}
$columnMap = $dataMap->getColumnMap($propertyName);
$columnName = $columnMap->getColumnName();
$columnsMapping[$columnName] = ['mapOnProperty' => $propertyName];
}
return $columnsMapping;
}
}

View File

@@ -0,0 +1,121 @@
<?php
namespace SJBR\StaticInfoTables\Hook\Backend\Form\Wizard;
/*
* Copyright notice
*
* (c) 2007-2011 Andreas Wolf <andreas.wolf@ikt-werk.de>
* (c) 2013-2021 Stanislas Rolland <typo3AAAA(arobas)sjbr.ca>
* All rights reserved
*
* This script is part of the TYPO3 project. The TYPO3 project is
* free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* The GNU General Public License can be found at
* http://www.gnu.org/copyleft/gpl.html.
* A copy is found in the textfile GPL.txt and important notices to the license
* from the author is found in LICENSE.txt distributed with these scripts.
*
*
* This script is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
use SJBR\StaticInfoTables\Utility\LocalizationUtility;
use TYPO3\CMS\Backend\Form\Wizard\SuggestWizardDefaultReceiver;
use TYPO3\CMS\Core\Utility\GeneralUtility;
/**
* Default implementation of a handler class for an ajax record selector.
*
* Normally other implementations should be inherited from this one.
* queryTable() should not be overwritten under normal circumstances.
*
* @author Andreas Wolf <andreas.wolf@ikt-werk.de>
* @author Benjamin Mack <benni@typo3.org>
* @author Stanislas Rolland <typo3(arobas)sjbr.ca>
*/
class SuggestReceiver extends SuggestWizardDefaultReceiver
{
/**
* Prepare the statement for selecting the records which will be returned to the selector. May also return some
* other records (e.g. from a mm-table) which will be used later on to select the real records
*
* @return void
*/
protected function prepareSelectStatement()
{
$expressionBuilder = $this->queryBuilder->expr();
$searchWholePhrase = !isset($this->config['searchWholePhrase']) || $this->config['searchWholePhrase'];
$searchString = $this->params['value'];
$searchUid = (int)$searchString;
if ($searchString !== '') {
$likeCondition = ($searchWholePhrase ? '%' : '') . $this->queryBuilder->escapeLikeWildcards($searchString) . '%';
// Get the label field for the current language, if any is available
$lang = LocalizationUtility::getCurrentLanguage();
$lang = LocalizationUtility::getIsoLanguageKey($lang);
$labelFields = LocalizationUtility::getLabelFields($this->table, $lang);
$selectFieldsList = $labelFields[0] . ',' . $this->config['additionalSearchFields'];
$selectFields = GeneralUtility::trimExplode(',', $selectFieldsList, true);
$selectFields = array_unique($selectFields);
$selectParts = $expressionBuilder->orX();
foreach ($selectFields as $field) {
$selectParts->add($expressionBuilder->like($field, $this->queryBuilder->createPositionalParameter($likeCondition)));
}
$searchClause = $expressionBuilder->orX($selectParts);
if ($searchUid > 0 && $searchUid == $searchString) {
$searchClause->add($expressionBuilder->eq('uid', $searchUid));
}
$this->queryBuilder->andWhere($expressionBuilder->orX($searchClause));
}
if (!empty($this->allowedPages)) {
$pidList = array_map('intval', $this->allowedPages);
if (!empty($pidList)) {
$this->queryBuilder->andWhere(
$expressionBuilder->in('pid', $pidList)
);
}
}
// add an additional search condition comment
if (isset($this->config['searchCondition']) && $this->config['searchCondition'] !== '') {
$this->queryBuilder->andWhere(QueryHelper::stripLogicalOperatorPrefix($this->config['searchCondition']));
}
}
/**
* Prepares the clause by which the result elements are sorted. See description of ORDER BY in
* SQL standard for reference.
*
* @return void
*/
protected function prepareOrderByStatement()
{
// Get the label field for the current language, if any is available
$lang = LocalizationUtility::getCurrentLanguage();
$lang = LocalizationUtility::getIsoLanguageKey($lang);
$labelFields = LocalizationUtility::getLabelFields($this->table, $lang);
if (!empty($labelFields)) {
foreach ($labelFields as $labelField) {
$this->queryBuilder->addOrderBy($labelField);
}
} elseif ($GLOBALS['TCA'][$this->table]['ctrl']['label']) {
$this->queryBuilder->addOrderBy($GLOBALS['TCA'][$this->table]['ctrl']['label']);
}
}
/**
* Manipulate a record before using it to render the selector; may be used to replace a MM-relation etc.
*
* @param array $row
*/
protected function manipulateRecord(&$row)
{
// Localize the record
$row[$GLOBALS['TCA'][$this->table]['ctrl']['label']] = LocalizationUtility::translate(['uid' => $row['uid']], $this->table);
}
}

View File

@@ -0,0 +1,70 @@
<?php
namespace SJBR\StaticInfoTables\Hook\Backend\Recordlist;
/*
* Copyright notice
*
* (c) 2018-2022 Stanislas Rolland <typo3AAAA(arobas)sjbr.ca>
* All rights reserved
*
* This script is part of the Typo3 project. The Typo3 project is
* free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
* The GNU General Public License can be found at
* http://www.gnu.org/copyleft/gpl.html.
*
* This script is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* This copyright notice MUST APPEAR in all copies of the script!
*/
use TYPO3\CMS\Core\Database\Query\QueryBuilder;
use TYPO3\CMS\Core\Database\Query\QueryHelper;
use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
/**
* Order records according to language field of current language
*/
class ModifyQuery
{
/**
* Specify records order
*
* @param array $parameters
* @param string $table
* @param int $pageId
* @param string $additionalConstraints
* @param string $fieldList
* @param QueryBuilder $queryBuilder
* @return void
*/
public function modifyQuery(&$parameters, $table, $pageId, $additionalConstraints, $fieldList, QueryBuilder $queryBuilder)
{
if (in_array($table, array_keys($GLOBALS['TYPO3_CONF_VARS']['EXTENSIONS']['static_info_tables']['tables'] ?? []))) {
$lang = substr(strtolower($this->getLanguageService()->lang), 0, 2);
if (ExtensionManagementUtility::isLoaded('static_info_tables_' . $lang) &&
isset($GLOBALS['TYPO3_CONF_VARS']['EXTENSIONS']['static_info_tables']['tables'][$table]['label_fields']) &&
is_array($GLOBALS['TYPO3_CONF_VARS']['EXTENSIONS']['static_info_tables']['tables'][$table]['label_fields'])) {
$label = array_key_first($GLOBALS['TYPO3_CONF_VARS']['EXTENSIONS']['static_info_tables']['tables'][$table]['label_fields']);
if ($label) {
$orderBy = str_replace('##', $lang, $label);
$orderByFields = QueryHelper::parseOrderBy((string)$orderBy);
foreach ($orderByFields as $fieldNameAndSorting) {
list($fieldName, $sorting) = $fieldNameAndSorting;
$queryBuilder->orderBy($fieldName, $sorting);
}
}
}
}
}
protected function getLanguageService()
{
return $GLOBALS['LANG'];
}
}

View File

@@ -0,0 +1,145 @@
<?php
namespace SJBR\StaticInfoTables\Hook\Core\DataHandling;
/*
* Copyright notice
*
* (c) 2013-2022 Stanislas Rolland <typo3AAAA(arobas)sjbr.ca>
* All rights reserved
*
* This script is part of the Typo3 project. The Typo3 project is
* free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* The GNU General Public License can be found at
* http://www.gnu.org/copyleft/gpl.html.
*
* This script is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* This copyright notice MUST APPEAR in all copies of the script!
*/
use SJBR\StaticInfoTables\Domain\Repository\CountryRepository;
use SJBR\StaticInfoTables\Domain\Repository\CurrencyRepository;
use SJBR\StaticInfoTables\Domain\Repository\TerritoryRepository;
use TYPO3\CMS\Core\Database\ConnectionPool;
use TYPO3\CMS\Core\Utility\GeneralUtility;
/**
* Hook on Core/DataHandling/DataHandler to manage redundancy of ISO codes in static info tables
*/
class ProcessDataMap
{
protected $countryRepository;
public function injectCountryRepository(CountryRepository $countryRepository)
{
$this->countryRepository = $countryRepository;
}
protected $currencyRepository;
public function injectCurrencyRepository(CurrencyRepository $currencyRepository)
{
$this->currencyRepository = $currencyRepository;
}
protected $territoryRepository;
public function injectTerritoryRepository(TerritoryRepository $territoryRepository)
{
$this->territoryRepository = $territoryRepository;
}
/**
* Post-process redundant ISO codes fields
*
* @param object $fobj TCEmain object reference
* @param mixed $status
* @param mixed $table
* @param mixed $id
* @return void
*/
public function processDatamap_postProcessFieldArray($status, $table, $id, &$incomingFieldArray, &$fObj)
{
switch ($table) {
case 'static_territories':
//Post-process containing territory ISO numeric code
if ($incomingFieldArray['tr_parent_territory_uid'] ?? 0) {
$territory = $this->territoryRepository->findOneByUid((int)$incomingFieldArray['tr_parent_territory_uid']);
if (is_object($territory)) {
$incomingFieldArray['tr_parent_iso_nr'] = $territory->getUnCodeNumber();
}
} elseif (isset($incomingFieldArray['tr_parent_territory_uid'])) {
$incomingFieldArray['tr_parent_iso_nr'] = 0;
}
break;
case 'static_countries':
//Post-process containing territory ISO numeric code
if ($incomingFieldArray['cn_parent_territory_uid'] ?? 0) {
$territory = $this->territoryRepository->findOneByUid((int)$incomingFieldArray['cn_parent_territory_uid']);
if (is_object($territory)) {
$incomingFieldArray['cn_parent_tr_iso_nr'] = $territory->getUnCodeNumber();
}
} elseif (isset($incomingFieldArray['cn_parent_territory_uid'])) {
$incomingFieldArray['cn_parent_tr_iso_nr'] = 0;
}
//Post-process currency ISO numeric and A3 codes
if ($incomingFieldArray['cn_currency_uid'] ?? 0) {
$currency = $this->currencyRepository->findOneByUid((int)$incomingFieldArray['cn_currency_uid']);
if (is_object($currency)) {
$incomingFieldArray['cn_currency_iso_nr'] = $currency->getIsoCodeNumber();
$incomingFieldArray['cn_currency_iso_3'] = $currency->getIsoCodeA3();
}
} elseif (isset($incomingFieldArray['cn_currency_uid'])) {
$incomingFieldArray['cn_currency_iso_nr'] = 0;
$incomingFieldArray['cn_currency_iso_3'] = '';
}
break;
}
}
/**
* Post-process redundant ISO codes fields of IRRE child
*
* @param object $fobj TCEmain object reference
* @param mixed $status
* @param mixed $table
* @param mixed $id
* @return void
*/
public function processDatamap_afterDatabaseOperations($status, $table, $id, &$fieldArray, &$fObj)
{
switch ($table) {
case 'static_countries':
//Post-process country ISO numeric, A2 and A3 codes on country zones
// Get the country record uid
if ($status === 'new') {
$id = $fObj->substNEWwithIDs[$id];
}
// Get the country
$country = $this->countryRepository->findOneByUid((int)$id);
// Get the country zones
$countryZones = $country->getCountryZones()->toArray();
if (count($countryZones)) {
$connection = GeneralUtility::makeInstance(ConnectionPool::class)->getConnectionForTable('static_country_zones');
foreach ($countryZones as $countryZone) {
$connection->update(
'static_country_zones',
[
'zn_country_iso_nr' => (int)$country->getIsoCodeNumber(),
'zn_country_iso_2' => $country->getIsoCodeA2(),
'zn_country_iso_3' => $country->getIsoCodeA3(),
],
['uid' => (int)$countryZone->getUid()]
);
}
}
break;
}
}
}

View File

@@ -0,0 +1,622 @@
<?php
namespace SJBR\StaticInfoTables;
/*
* Copyright notice
*
* (c) 2004-2022 Stanislas Rolland <typo3AAAA(arobas)sjbr.ca>
* All rights reserved
*
* This script is part of the Typo3 project. The Typo3 project is
* free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* The GNU General Public License can be found at
* http://www.gnu.org/copyleft/gpl.html.
* A copy is found in the textfile GPL.txt and important notices to the license
* from the author is found in LICENSE.txt distributed with these scripts.
*
*
* This script is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* This copyright notice MUST APPEAR in all copies of the script!
*/
use Psr\Http\Message\ServerRequestInterface;
use SJBR\StaticInfoTables\Domain\Model\Currency;
use SJBR\StaticInfoTables\Domain\Repository\CountryRepository;
use SJBR\StaticInfoTables\Domain\Repository\CurrencyRepository;
use SJBR\StaticInfoTables\Utility\HtmlElementUtility;
use SJBR\StaticInfoTables\Utility\LocalizationUtility;
use TYPO3\CMS\Core\Database\ConnectionPool;
use TYPO3\CMS\Core\Database\Query\QueryHelper;
use TYPO3\CMS\Core\Database\Query\Restriction\FrontendRestrictionContainer;
use TYPO3\CMS\Core\Http\ApplicationType;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Frontend\Plugin\AbstractPlugin;
/**
* Class for handling static info tables: countries, and subdivisions, currencies, languages and taxes
*/
class PiBaseApi extends AbstractPlugin
{
/**
* The backReference to the mother cObj object set at call time
*/
public $cObj;
// Same as class name
public $prefixId = 'tx_staticinfotables_pi1';
// Path to this script relative to the extension dir.
public $scriptRelPath = 'pi1/class.tx_staticinfotables_pi1.php';
/**
* The extension key
*
* @var string
*/
public $extKey = 'static_info_tables';
public $conf = [];
// Default currency
public $currency;
public $currencyInfo = [];
public $defaultCountry;
public $defaultCountryZone;
public $defaultLanguage;
public $types = ['TERRITORIES', 'COUNTRIES', 'SUBDIVISIONS', 'CURRENCIES', 'LANGUAGES'];
public $tables = [
'TERRITORIES' => 'static_territories',
'COUNTRIES' => 'static_countries',
'SUBDIVISIONS' => 'static_country_zones',
'CURRENCIES' => 'static_currencies',
'LANGUAGES' => 'static_languages',
];
/**
* @var CountryRepository
*/
protected $countryRepository;
/**
* @var CurrencyRepository
*/
protected $currencyRepository;
/**
* Whether the class has been initialized
*
* @var bool
*/
protected $bHasBeenInitialised = false;
/**
* Returns info if the tx_staticinfotables_pi1 object has already been initialised.
* You need to initialise this object only once.
*
* @return bool Always returns true
*/
public function needsInit()
{
return !$this->bHasBeenInitialised;
}
/**
* Initializing the class: sets the language based on the TS configuration language property
*
* @param array $conf ... overwriting setup of extension
* @return bool Always returns true
*/
public function init($conf = [])
{
if (($GLOBALS['TYPO3_REQUEST'] ?? null) instanceof ServerRequestInterface
&& ApplicationType::fromRequest($GLOBALS['TYPO3_REQUEST'])->isFrontend()) {
$this->conf = $GLOBALS['TSFE']->tmpl->setup['plugin.'][$this->prefixId . '.'] ?? [];
}
$this->countryRepository = GeneralUtility::makeInstance(CountryRepository::class);
$this->currencyRepository = GeneralUtility::makeInstance(CurrencyRepository::class);
//Get the default currency and make sure it does exist in table static_currencies
$this->currency = $conf['currencyCode'] ?? '';
if (!$this->currency) {
$this->currency = (trim($this->conf['currencyCode'] ?? '')) ? trim($this->conf['currencyCode']) : 'EUR';
}
//If nothing is set, we use the Euro because TYPO3 is spread more in this area
if (!$this->getStaticInfoName('CURRENCIES', $this->currency)) {
$this->currency = 'EUR';
}
$this->currencyInfo = $this->loadCurrencyInfo($this->currency);
$this->defaultCountry = $conf['countryCode'] ?? '';
if (!$this->defaultCountry) {
$this->defaultCountry = trim($this->conf['countryCode'] ?? '');
}
if (!$this->getStaticInfoName('COUNTRIES', $this->defaultCountry)) {
$this->defaultCountry = 'DEU';
}
$this->defaultCountryZone = $conf['countryZoneCode'] ?? '';
if (!$this->defaultCountryZone) {
$this->defaultCountryZone = trim($this->conf['countryZoneCode'] ?? '');
}
if (!$this->getStaticInfoName('SUBDIVISIONS', $this->defaultCountryZone, $this->defaultCountry)) {
if ($this->defaultCountry == 'DEU') {
$this->defaultCountryZone = 'NW';
} else {
$this->defaultCountryZone = '';
}
}
$this->defaultLanguage = $conf['languageCode'] ?? '';
if (!$this->defaultLanguage) {
$this->defaultLanguage = trim($this->conf['languageCode'] ?? '');
}
if (!$this->getStaticInfoName('LANGUAGES', $this->defaultLanguage)) {
$this->defaultLanguage = 'EN';
}
$this->bHasBeenInitialised = true;
return true;
}
/**
* Getting the name of a country, country subdivision, currency, language, tax
*
* @param string Defines the type of entry of the requested name: 'TERRITORIES', 'COUNTRIES', 'SUBDIVISIONS', 'CURRENCIES', 'LANGUAGES'
* @param string The ISO alpha-3 code of a territory, country or currency, or the ISO alpha-2 code of a language or the code of a country subdivision, can be a comma ',' separated string, then all the single items are looked up and returned
* @param string The value of the country code (cn_iso_3) for which a name of type 'SUBDIVISIONS' is requested (meaningful only in this case)
* @param string Not used
* @param bool local name only - if set local title is returned
* @param mixed $type
* @param mixed $code
* @param mixed $country
* @param mixed $countrySubdivision
* @param mixed $local
*
* @return string|bool The name of the object in the current language or false
*/
public function getStaticInfoName($type = 'COUNTRIES', $code = '', $country = '', $countrySubdivision = '', $local = false)
{
$names = false;
if (in_array($type, $this->types) && trim($code)) {
$codeArray = GeneralUtility::trimExplode(',', ($code));
$tableName = $this->tables[$type];
if (!$tableName) {
return false;
}
$nameArray = [];
foreach ($codeArray as $item) {
$isoCodeArray = [];
$isoCodeArray[] = $item;
switch ($type) {
case 'SUBDIVISIONS':
$isoCodeArray[] = trim($country) ? trim($country) : $this->defaultCountry;
break;
case 'LANGUAGES':
$isoCodeArray = GeneralUtility::trimExplode('_', $code, 1);
break;
}
$nameArray[] = LocalizationUtility::translate(['iso' => $isoCodeArray], $tableName, $local);
}
$names = implode(',', $nameArray);
}
return $names;
}
/**
* Buils a HTML drop-down selector of countries, country subdivisions, currencies or languages
*
* @param string $type: Defines the type of entries to be presented in the drop-down selector: 'COUNTRIES', 'SUBDIVISIONS', 'CURRENCIES' or 'LANGUAGES'
* @param string $name: A value for the name attribute of the <select> tag
* @param string $class: A value for the class attribute of the <select> tag
* @param array $selectedArray: The values of the code of the entries to be pre-selected in the drop-down selector: value of cn_iso_3, zn_code, cu_iso_3 or lg_iso_2
* @param string $country: The value of the country code (cn_iso_3) for which a drop-down selector of type 'SUBDIVISIONS' is requested (meaningful only in this case)
* @param boolean/string $submit: If set to 1, an onchange attribute will be added to the <select> tag for immediate submit of the changed value; if set to other than 1, overrides the onchange script
* @param string $id: A value for the id attribute of the <select> tag
* @param string $title: A value for the title attribute of the <select> tag
* @param string $addWhere: A where clause for the records
* @param string $lang: language to be used
* @param bool $local: If set, we are looking for the "local" title field
* @param array $mergeArray: additional array to be merged as key => value pair
* @param int $size: max elements that can be selected. Default: 1
* @param array $outSelectedArray: resulting selected array with the ISO alpha-3 code of the countries (passed by reference)
*
* @return string A set of HTML <select> and <option> tags
*/
public function buildStaticInfoSelector($type = 'COUNTRIES', $name = '', $class = '', $selectedArray = [], $country = '', $submit = 0, $id = '', $title = '', $addWhere = '', $lang = '', $local = false, $mergeArray = [], $size = 1, &$outSelectedArray = [])
{
$selector = '';
if (isset($selectedArray) && !is_array($selectedArray)) {
$selectedArray = GeneralUtility::trimExplode(',', $selectedArray);
}
$country = trim($country);
$onChange = '';
if ($submit) {
if ($submit == 1) {
$onChange = $this->conf['onChangeAttribute'];
} else {
$onChange = $submit;
}
}
switch ($type) {
case 'COUNTRIES':
$nameArray = $this->initCountries('ALL', $lang, $local, $addWhere);
$defaultSelectedArray = [$this->defaultCountry];
break;
case 'SUBDIVISIONS':
$param = (trim($country) ? trim($country) : $this->defaultCountry);
$nameArray = $this->initCountrySubdivisions($param, $addWhere);
if ($param == $this->defaultCountry) {
$defaultSelectedArray = [$this->defaultCountryZone];
}
break;
case 'CURRENCIES':
$nameArray = $this->initCurrencies($addWhere);
$defaultSelectedArray = [$this->currency];
break;
case 'LANGUAGES':
$nameArray = $this->initLanguages($addWhere);
$defaultSelectedArray = [$this->defaultLanguage];
break;
}
if (!isset($defaultSelectedArray) || !$defaultSelectedArray) {
reset($nameArray);
$defaultSelectedArray = [key($nameArray)];
}
$bEmptySelected = (empty($selectedArray) || ((count($selectedArray) == 1) && empty($selectedArray[0])));
$selectedArray = ((!$bEmptySelected || count($mergeArray)) ? $selectedArray : $defaultSelectedArray);
if (count($mergeArray)) {
$nameArray = array_merge($nameArray, $mergeArray);
uasort($nameArray, 'strcoll');
}
if (count($nameArray) > 0) {
$items = [];
foreach ($nameArray as $itemKey => $itemName) {
$items[] = ['name' => $itemName, 'value' => $itemKey];
}
$selector = HtmlElementUtility::selectConstructor($items, $selectedArray, $outSelectedArray, $name, $class, $id, $title, $onChange, $size);
}
return $selector;
}
/**
* Getting all countries into an array
* where the key is the ISO alpha-3 code of the country
* and where the value is the name of the country in the current language
*
* @param string $param: It defines a selection: 'ALL', 'UN', 'EU'
* @param string $lang: language to be used
* @param bool $local: If set, we are looking for the "local" title field
* @param string $addWhere: additional WHERE clause
*
* @return array An array of names of countries
*/
public function initCountries($param = 'UN', $lang = '', $local = false, $addWhere = '')
{
$nameArray = [];
$table = $this->tables['COUNTRIES'];
if (!$lang) {
$lang = LocalizationUtility::getCurrentLanguage();
$lang = LocalizationUtility::getIsoLanguageKey($lang);
}
$titleFields = LocalizationUtility::getLabelFields($table, $lang, $local);
$prefixedTitleFields = [];
$prefixedTitleFields[] = $table . '.cn_iso_3';
foreach ($titleFields as $titleField => $map) {
$prefixedTitleFields[] = $table . '.' . $titleField;
}
array_unique($prefixedTitleFields);
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
->getQueryBuilderForTable($table);
$queryBuilder->setRestrictions(GeneralUtility::makeInstance(FrontendRestrictionContainer::class));
$queryBuilder
->select($prefixedTitleFields[0])
->from($table);
array_shift($prefixedTitleFields);
foreach ($prefixedTitleFields as $titleField) {
$queryBuilder->addSelect($titleField);
}
if ($param === 'UN') {
$queryBuilder->where($queryBuilder->expr()->eq('cn_uno_member', $queryBuilder->createNamedParameter(1, \PDO::PARAM_INT)));
} elseif ($param === 'EU') {
$queryBuilder->where($queryBuilder->expr()->eq('cn_eu_member', $queryBuilder->createNamedParameter(1, \PDO::PARAM_INT)));
}
if ($addWhere) {
$addWhere = QueryHelper::stripLogicalOperatorPrefix($addWhere);
if (empty($queryBuilder->getQueryPart('where'))) {
$queryBuilder->where($addWhere);
} else {
$queryBuilder->andWhere($addWhere);
}
}
$query = $queryBuilder->execute();
while ($row = $query->fetch()) {
foreach ($titleFields as $titleField => $map) {
if ($row[$titleField] ?? false) {
$nameArray[$row['cn_iso_3']] = $row[$titleField];
break;
}
}
}
if (isset($this->conf['countriesAllowed']) && $this->conf['countriesAllowed'] != '') {
$countriesAllowedArray = GeneralUtility::trimExplode(',', $this->conf['countriesAllowed']);
$newNameArray = [];
foreach ($countriesAllowedArray as $iso3) {
if (isset($nameArray[$iso3])) {
$newNameArray[$iso3] = $nameArray[$iso3];
}
}
$nameArray = $newNameArray;
} else {
uasort($nameArray, 'strcoll');
}
return $nameArray;
}
/**
* Getting all country subdivisions of a given country into an array
* where the key is the code of the subdivision
* and where the value is the name of the country subdivision in the current language
* You can leave the ISO code empty and use the additional WHERE clause instead of it.
*
* @param string The ISO alpha-3 code of a country
* @param string additional WHERE clause
* @param mixed $param
* @param mixed $addWhere
*
* @return array An array of names of country subdivisions
*/
public function initCountrySubdivisions($param, $addWhere='')
{
$nameArray = [];
$table = $this->tables['SUBDIVISIONS'];
$lang = LocalizationUtility::getCurrentLanguage();
$lang = LocalizationUtility::getIsoLanguageKey($lang);
$titleFields = LocalizationUtility::getLabelFields($table, $lang);
$prefixedTitleFields = [];
foreach ($titleFields as $titleField => $map) {
$prefixedTitleFields[] = $table . '.' . $titleField;
}
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
->getQueryBuilderForTable($table);
$queryBuilder->setRestrictions(GeneralUtility::makeInstance(FrontendRestrictionContainer::class));
$queryBuilder
->select($table . '.zn_code')
->from($table);
foreach ($prefixedTitleFields as $titleField) {
$queryBuilder->addSelect($titleField);
}
if (strlen($param) == 3) {
$queryBuilder->where($queryBuilder->expr()->eq('zn_country_iso_3', $queryBuilder->createNamedParameter($param, \PDO::PARAM_STR)));
}
if ($addWhere) {
$addWhere = QueryHelper::stripLogicalOperatorPrefix($addWhere);
if (empty($queryBuilder->getQueryPart('where'))) {
$queryBuilder->where($addWhere);
} else {
$queryBuilder->andWhere($addWhere);
}
}
$query = $queryBuilder->execute();
while ($row = $query->fetch()) {
foreach ($titleFields as $titleField => $map) {
if ($row[$titleField] ?? false) {
$nameArray[$row['zn_code']] = $row[$titleField];
break;
}
}
}
uasort($nameArray, 'strcoll');
return $nameArray;
}
/**
* Getting all currencies into an array
* where the key is the ISO alpha-3 code of the currency
* and where the value are the name of the currency in the current language
*
* @param string additional WHERE clause
* @param mixed $addWhere
*
* @return array An array of names of currencies
*/
public function initCurrencies($addWhere='')
{
$nameArray = [];
$table = $this->tables['CURRENCIES'];
$lang = LocalizationUtility::getCurrentLanguage();
$lang = LocalizationUtility::getIsoLanguageKey($lang);
$titleFields = LocalizationUtility::getLabelFields($table, $lang);
$prefixedTitleFields = [];
foreach ($titleFields as $titleField => $map) {
$prefixedTitleFields[] = $table . '.' . $titleField;
}
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
->getQueryBuilderForTable($table);
$queryBuilder->setRestrictions(GeneralUtility::makeInstance(FrontendRestrictionContainer::class));
$queryBuilder
->select($table . '.cu_iso_3')
->from($table);
foreach ($prefixedTitleFields as $titleField) {
$queryBuilder->addSelect($titleField);
}
if ($addWhere) {
$addWhere = QueryHelper::stripLogicalOperatorPrefix($addWhere);
$queryBuilder->where($addWhere);
}
$query = $queryBuilder->execute();
while ($row = $query->fetch()) {
foreach ($titleFields as $titleField => $map) {
if ($row[$titleField] ?? false) {
$nameArray[$row['cu_iso_3']] = $row[$titleField];
break;
}
}
}
uasort($nameArray, 'strcoll');
return $nameArray;
}
/**
* Getting all languages into an array
* where the key is the ISO alpha-2 code of the language
* and where the value are the name of the language in the current language
* Note: we exclude sacred and constructed languages
*
* @param string $addWhere: additional WHERE clause
*
* @return array An array of names of languages
*/
public function initLanguages($addWhere = '')
{
$nameArray = [];
$table = $this->tables['LANGUAGES'];
$lang = LocalizationUtility::getCurrentLanguage();
$lang = LocalizationUtility::getIsoLanguageKey($lang);
$titleFields = LocalizationUtility::getLabelFields($table, $lang);
$prefixedTitleFields = [];
foreach ($titleFields as $titleField => $map) {
$prefixedTitleFields[] = $table . '.' . $titleField;
}
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
->getQueryBuilderForTable($table);
$queryBuilder->setRestrictions(GeneralUtility::makeInstance(FrontendRestrictionContainer::class));
$queryBuilder
->select($table . '.lg_iso_2')
->addSelect($table . '.lg_country_iso_2')
->from($table);
foreach ($prefixedTitleFields as $titleField) {
$queryBuilder->addSelect($titleField);
}
$queryBuilder->where(
$queryBuilder->expr()->eq('lg_sacred', $queryBuilder->createNamedParameter(0, \PDO::PARAM_INT)),
$queryBuilder->expr()->eq('lg_constructed', $queryBuilder->createNamedParameter(0, \PDO::PARAM_INT))
);
if ($addWhere) {
$addWhere = QueryHelper::stripLogicalOperatorPrefix($addWhere);
$queryBuilder->andWhere($addWhere);
}
$query = $queryBuilder->execute();
while ($row = $query->fetch()) {
$code = $row['lg_iso_2'] . ($row['lg_country_iso_2'] ? '_' . $row['lg_country_iso_2'] : '');
foreach ($titleFields as $titleField => $map) {
if ($row[$titleField] ?? false) {
$nameArray[$code] = $row[$titleField];
break;
}
}
}
uasort($nameArray, 'strcoll');
return $nameArray;
}
/**
* Loading currency display parameters from Static Info Tables
*
* @param string $currencyCode: An ISO alpha-3 currency code
*
* @return array An array of information regarding the currrency
*/
public function loadCurrencyInfo($currencyCode)
{
// Fetching the currency record
$this->currencyInfo['cu_iso_3'] = trim($currencyCode);
$this->currencyInfo['cu_iso_3'] = $this->currencyInfo['cu_iso_3'] ?: $this->currency;
$currency = $this->currencyRepository->findOneByIsoCodeA3($this->currencyInfo['cu_iso_3']);
// If not found we fetch the default currency!
if (!($currency instanceof Currency)) {
$this->currencyInfo['cu_iso_3'] = $this->currency;
$currency = $this->currencyRepository->findOneByIsoCodeA3($this->currencyInfo['cu_iso_3']);
}
if ($currency instanceof Currency) {
$this->currencyInfo['cu_name'] = $this->getStaticInfoName('CURRENCIES', $this->currencyInfo['cu_iso_3']);
$this->currencyInfo['cu_symbol_left'] = $currency->getSymbolLeft();
$this->currencyInfo['cu_symbol_right'] = $currency->getSymbolRight();
$this->currencyInfo['cu_decimal_digits'] = $currency->getDecimalDigits();
$this->currencyInfo['cu_decimal_point'] = $currency->getDecimalPoint();
$this->currencyInfo['cu_thousands_point'] = $currency->getThousandsPoint();
}
return $this->currencyInfo;
}
/**
* Formatting an amount in the currency loaded by loadCurrencyInfo($currencyCode)
*
* '' - the currency code is not displayed
* 'RIGHT' - the code is displayed at the right of the amount
* 'LEFT' - the code is displayed at the left of the amount
*
* @param float $amount: An amount to be displayed in the loaded currency
* @param string $displayCurrencyCode: A flag specifying if the the currency code should be displayed:
*
* @return string The formated amounted
*/
public function formatAmount($amount, $displayCurrencyCode = '')
{
$formatedAmount = '';
if ($displayCurrencyCode === 'LEFT') {
$formatedAmount .= $this->currencyInfo['cu_iso_3'] . chr(32);
}
$formatedAmount .= $this->currencyInfo['cu_symbol_left'];
$formatedAmount .= number_format($amount, (int)$this->currencyInfo['cu_decimal_digits'], $this->currencyInfo['cu_decimal_point'], (($this->currencyInfo['cu_thousands_point']) ? $this->currencyInfo['cu_thousands_point'] : chr(32)));
$formatedAmount .= (($this->currencyInfo['cu_symbol_right']) ? chr(32) : '') . $this->currencyInfo['cu_symbol_right'];
if ($displayCurrencyCode === 'RIGHT') {
$formatedAmount .= chr(32) . $this->currencyInfo['cu_iso_3'];
}
return $formatedAmount;
}
/**
* Formatting an address in the format specified
*
* @param string $delim: A delimiter for the fields of the returned address
* @param string $streetAddress: A street address
* @param string $city: A city
* @param string $zip: A zip code
* @param string $subdivisionCode: A country subdivision code (zn_code)
* @param string $countryCode: A ISO alpha-3 country code (cn_iso_3)
*
* @return string The formated address using the country address format (cn_address_format)
*/
public function formatAddress($delim, $streetAddress, $city, $zip, $subdivisionCode = '', $countryCode = '')
{
$formatedAddress = '';
$countryCode = ($countryCode ? trim($countryCode) : $this->defaultCountry);
$subdivisionCode = ($subdivisionCode ? trim($subdivisionCode) : ($countryCode == $this->defaultCountry ? $this->defaultCountryZone : ''));
// Get country name
$countryName = $this->getStaticInfoName('COUNTRIES', $countryCode);
if ($countryName) {
// Get address format
$country = $this->countryRepository->findOneByIsoCodeA3($countryCode);
if (is_object($country)) {
$addressFormat = $country->getAddressFormat();
// Get country subdivision name
$countrySubdivisionName = $this->getStaticInfoName('SUBDIVISIONS', $subdivisionCode, $countryCode);
// Format the address
$formatedAddress = $this->conf['addressFormat.'][$addressFormat];
$formatedAddress = str_replace('%street', $streetAddress, $formatedAddress);
$formatedAddress = str_replace('%city', $city, $formatedAddress);
$formatedAddress = str_replace('%zip', $zip, $formatedAddress);
$formatedAddress = str_replace('%countrySubdivisionCode', $subdivisionCode, $formatedAddress);
$formatedAddress = str_replace('%countrySubdivisionName', $countrySubdivisionName, $formatedAddress);
$formatedAddress = str_replace('%countryName', strtoupper($countryName), $formatedAddress);
$formatedAddress = implode($delim, GeneralUtility::trimExplode(';', $formatedAddress, 1));
}
}
return $formatedAddress;
}
}
class_alias('SJBR\\StaticInfoTables\\PiBaseApi', 'tx_staticinfotables_pi1');

View File

@@ -0,0 +1,153 @@
<?php
namespace SJBR\StaticInfoTables\Service;
/*
* This file is part of the TYPO3 CMS project.
*
* It is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, either version 2
* of the License, or any later version.
*
* For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code.
*
* The TYPO3 project - inspiring people to share!
*/
use TYPO3\CMS\Core\Database\ConnectionPool;
use TYPO3\CMS\Core\Utility\GeneralUtility;
/**
* Verify TYPO3 DB table structure. Mainly used in install tool
* compare wizard and extension manager.
* Removed form Install extension in TYPO3 9 LTS
*/
class SqlSchemaMigrationService
{
/**
* @constant Maximum field width of MySQL
*/
const MYSQL_MAXIMUM_FIELD_WIDTH = 64;
/**
* @var string Prefix of deleted tables
*/
protected $deletedPrefixKey = 'zzz_deleted_';
/**
* @var array Caching output "SHOW CHARACTER SET"
*/
protected $character_sets = [];
/**
* Reads the field definitions for the current database
*
* @return array Array with information about table.
*/
public function getFieldDefinitions_database()
{
$total = [];
$tempKeys = [];
$tempKeysPrefix = [];
$connection = GeneralUtility::makeInstance(ConnectionPool::class)->getConnectionByName('Default');
$statement = $connection->query('SHOW TABLE STATUS FROM `' . $connection->getDatabase() . '`');
$tables = [];
while ($theTable = $statement->fetch()) {
$tables[$theTable['Name']] = $theTable;
}
foreach ($tables as $tableName => $tableStatus) {
// Fields
$statement = $connection->query('SHOW FULL COLUMNS FROM `' . $tableName . '`');
$fieldInformation = [];
while ($fieldRow = $statement->fetch()) {
$fieldInformation[$fieldRow['Field']] = $fieldRow;
}
foreach ($fieldInformation as $fN => $fieldRow) {
$total[$tableName]['fields'][$fN] = $this->assembleFieldDefinition($fieldRow);
}
// Keys
$statement = $connection->query('SHOW KEYS FROM `' . $tableName . '`');
$keyInformation = [];
while ($keyRow = $statement->fetch()) {
$keyInformation[] = $keyRow;
}
foreach ($keyInformation as $keyRow) {
$keyName = $keyRow['Key_name'];
$colName = $keyRow['Column_name'];
if ($keyRow['Sub_part'] && $keyRow['Index_type'] !== 'SPATIAL') {
$colName .= '(' . $keyRow['Sub_part'] . ')';
}
$tempKeys[$tableName][$keyName][$keyRow['Seq_in_index']] = $colName;
if ($keyName === 'PRIMARY') {
$prefix = 'PRIMARY KEY';
} else {
if ($keyRow['Index_type'] === 'FULLTEXT') {
$prefix = 'FULLTEXT';
} elseif ($keyRow['Index_type'] === 'SPATIAL') {
$prefix = 'SPATIAL';
} elseif ($keyRow['Non_unique']) {
$prefix = 'KEY';
} else {
$prefix = 'UNIQUE';
}
$prefix .= ' ' . $keyName;
}
$tempKeysPrefix[$tableName][$keyName] = $prefix;
}
// Table status (storage engine, collaction, etc.)
if (is_array($tableStatus)) {
$tableExtraFields = [
'Engine' => 'ENGINE',
'Collation' => 'COLLATE',
];
foreach ($tableExtraFields as $mysqlKey => $internalKey) {
if (isset($tableStatus[$mysqlKey])) {
$total[$tableName]['extra'][$internalKey] = $tableStatus[$mysqlKey];
}
}
}
}
// Compile key information:
if (!empty($tempKeys)) {
foreach ($tempKeys as $table => $keyInf) {
foreach ($keyInf as $kName => $index) {
ksort($index);
$total[$table]['keys'][$kName] = $tempKeysPrefix[$table][$kName] . ' (' . implode(',', $index) . ')';
}
}
}
return $total;
}
/**
* Converts a result row with field information into the SQL field definition string
*
* @param array $row MySQL result row
*
* @return string Field definition
*/
public function assembleFieldDefinition($row)
{
$field = [$row['Type']];
if ($row['Null'] === 'NO') {
$field[] = 'NOT NULL';
}
if (!strstr($row['Type'], 'blob') && !strstr($row['Type'], 'text')) {
// Add a default value if the field is not auto-incremented (these fields never have a default definition)
if (!stristr($row['Extra'], 'auto_increment')) {
if ($row['Default'] === null) {
$field[] = 'default NULL';
} else {
$field[] = 'default \'' . addslashes($row['Default']) . '\'';
}
}
}
if ($row['Extra']) {
$field[] = $row['Extra'];
}
if (trim($row['Comment'] ?? '') !== '') {
$field[] = "COMMENT '" . $row['Comment'] . "'";
}
return implode(' ', $field);
}
}

View File

@@ -0,0 +1,160 @@
<?php
namespace SJBR\StaticInfoTables\Utility;
/*
* Copyright notice
*
* (c) 2013-2022 StanislasRolland <typo3AAAA(arobas)sjbr.ca>
* All rights reserved
*
* This script is part of the Typo3 project. The Typo3 project is
* free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* The GNU General Public License can be found at
* http://www.gnu.org/copyleft/gpl.html.
*
* This script is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* This copyright notice MUST APPEAR in all copies of the script!
*/
use Doctrine\DBAL\DBALException;
use TYPO3\CMS\Core\Database\ConnectionPool;
use TYPO3\CMS\Core\Database\Schema\SchemaMigrator;
use TYPO3\CMS\Core\Database\Schema\SqlReader;
use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Extensionmanager\Utility\InstallUtility;
/**
* Utility used by the update script of the base extension and of the language packs
*/
class DatabaseUpdateUtility
{
/**
* @var string Name of the extension this class belongs to
*/
protected $extensionName = 'StaticInfoTables';
/**
* Do the language pack update
*
* @param string $extensionKey: extension key of the language pack
* @return void
*/
public function doUpdate($extensionKey)
{
$result = [];
$connectionPool = GeneralUtility::makeInstance(ConnectionPool::class);
$insertStatements = [];
$updateStatements = [];
$extPath = ExtensionManagementUtility::extPath($extensionKey);
$statements = explode(LF, @file_get_contents($extPath . 'ext_tables_static+adt.sql'));
foreach ($statements as $statement) {
$statement = trim($statement);
// Only handle update statements and extract the table at the same time. Extracting
// the table name is required to perform the inserts on the right connection.
if (preg_match('/^UPDATE\\s+`?(\\w+)`?(.*)/i', $statement, $matches)) {
list(, $tableName, $sqlFragment) = $matches;
$updateStatements[$tableName][] = sprintf(
'UPDATE %s %s',
$connectionPool->getConnectionForTable($tableName)->quoteIdentifier($tableName),
rtrim($sqlFragment, ';')
);
}
}
foreach ($updateStatements as $tableName => $perTableStatements) {
$connection = $connectionPool->getConnectionForTable($tableName);
foreach ((array)$perTableStatements as $statement) {
try {
$connection->executeUpdate($statement);
$result[$statement] = '';
} catch (DBALException $e) {
$result[$statement] = $e->getPrevious()->getMessage();
}
}
}
}
/**
* Imports a static tables SQL File (ext_tables_static+adt)
*
* @param string $extensionSitePath
* @return void
*/
public function importStaticSqlFile($extensionSitePath)
{
$extTablesStaticSqlFile = $extensionSitePath . 'ext_tables_static+adt.sql';
$extTablesStaticSqlContent = '';
if (file_exists($extTablesStaticSqlFile)) {
$extTablesStaticSqlContent .= GeneralUtility::getUrl($extTablesStaticSqlFile);
}
if ($extTablesStaticSqlContent !== '') {
$connectionPool = GeneralUtility::makeInstance(ConnectionPool::class);
// Drop all tables
foreach (array_keys($GLOBALS['TYPO3_CONF_VARS']['EXTENSIONS']['static_info_tables']['tables'] ?? []) as $tableName) {
$connection = $connectionPool->getConnectionForTable($tableName);
try {
$connection->executeUpdate($connection->getDatabasePlatform()
->getDropTableSQL($connection->quoteIdentifier($tableName)));
} catch (TableNotFoundException $e) {
// Ignore table not found exception
}
}
// Re-create all tables
$this->processDatabaseUpdates(GeneralUtility::camelCaseToLowerCaseUnderscored($this->extensionName));
$installTool = GeneralUtility::makeInstance(InstallUtility::class);
$installTool->importStaticSql($extTablesStaticSqlContent);
}
}
/**
* Processes the tables SQL File (ext_tables)
*
* @param string $extensionKey
* @return void
*/
public function processDatabaseUpdates($extensionKey)
{
$extensionSitePath = ExtensionManagementUtility::extPath($extensionKey);
$extTablesSqlFile = $extensionSitePath . 'ext_tables.sql';
$extTablesSqlContent = '';
if (file_exists($extTablesSqlFile)) {
$extTablesSqlContent .= GeneralUtility::getUrl($extTablesSqlFile);
}
if ($extTablesSqlContent !== '') {
// Prevent the DefaultTcaSchema from enriching our definitions
$tcaBackup = $GLOBALS['TCA'];
$GLOBALS['TCA'] = [];
$sqlReader = GeneralUtility::makeInstance(SqlReader::class);
$schemaMigrator = GeneralUtility::makeInstance(SchemaMigrator::class);
$sqlStatements = [];
$sqlStatements[] = $extTablesSqlContent;
$sqlStatements = $sqlReader->getCreateTableStatementArray(implode(LF . LF, array_filter($sqlStatements)));
$updateStatements = $schemaMigrator->getUpdateSuggestions($sqlStatements);
$updateStatements = array_merge_recursive(...array_values($updateStatements));
$selectedStatements = [];
foreach (['add', 'change', 'create_table', 'change_table'] as $action) {
if (empty($updateStatements[$action])) {
continue;
}
$selectedStatements = array_merge(
$selectedStatements,
array_combine(
array_keys($updateStatements[$action]),
array_fill(0, count($updateStatements[$action]), true)
)
);
}
$schemaMigrator->migrate($sqlStatements, $selectedStatements);
$GLOBALS['TCA'] = $tcaBackup;
}
}
}

View File

@@ -0,0 +1,145 @@
<?php
namespace SJBR\StaticInfoTables\Utility;
/*
* This file is part of the TYPO3 CMS project.
*
* It is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, either version 2
* of the License, or any later version.
*
* For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code.
*
* The TYPO3 project - inspiring people to share!
*/
use TYPO3\CMS\Core\Database\ConnectionPool;
use TYPO3\CMS\Core\SingletonInterface;
use TYPO3\CMS\Core\Utility\GeneralUtility;
/**
* Utility for dealing with database related operations
*/
class DatabaseUtility implements SingletonInterface
{
/**
* @var string
*/
const MULTI_LINEBREAKS = '
';
/**
* Dump content for static tables
*
* @param array $dbFields
* @return string
*/
public function dumpStaticTables($dbFields)
{
$out = '';
// Traverse the table list and dump each:
foreach ($dbFields as $table => $fields) {
if (isset($dbFields[$table]['fields']) && is_array($dbFields[$table]['fields'])) {
$header = $this->dumpHeader();
$tableHeader = $this->dumpTableHeader($table, $dbFields[$table], true);
$insertStatements = $this->dumpTableContent($table, $dbFields[$table]['fields']);
$out .= $header . self::MULTI_LINEBREAKS . $tableHeader . self::MULTI_LINEBREAKS . $insertStatements . self::MULTI_LINEBREAKS;
}
}
return $out;
}
/**
* Header comments of the SQL dump file
*
* @return string Table header
*/
protected function dumpHeader()
{
return trim('
# TYPO3 Extension Manager dump 1.1
#--------------------------------------------------------
');
}
/**
* Dump CREATE TABLE definition
*
* @param string $table
* @param array $fieldKeyInfo
* @param bool $dropTableIfExists
*
* @return string
*/
protected function dumpTableHeader($table, array $fieldKeyInfo, $dropTableIfExists = false)
{
$lines = [];
$dump = '';
// Create field definitions
if (isset($fieldKeyInfo['fields']) && is_array($fieldKeyInfo['fields'])) {
foreach ($fieldKeyInfo['fields'] as $fieldN => $data) {
$lines[] = ' ' . $fieldN . ' ' . $data;
}
}
// Create index key definitions
if (isset($fieldKeyInfo['keys']) && is_array($fieldKeyInfo['keys'])) {
foreach ($fieldKeyInfo['keys'] as $fieldN => $data) {
$lines[] = ' ' . $data;
}
}
// Compile final output:
if (!empty($lines)) {
$dump = trim('
#
# Table structure for table "' . $table . '"
#
' . ($dropTableIfExists ? 'DROP TABLE IF EXISTS ' . $table . ';
' : '') . 'CREATE TABLE ' . $table . ' (
' . implode((',' . LF), $lines) . '
);');
}
return $dump;
}
/**
* Dump table content
* Is DBAL compliant, but the dump format is written as MySQL standard.
* If the INSERT statements should be imported in a DBMS using other
* quoting than MySQL they must first be translated.
*
* @param string $table Table name
* @param array $fieldStructure Field structure
*
* @return string SQL Content of dump (INSERT statements)
*/
protected function dumpTableContent($table, array $fieldStructure)
{
// Substitution of certain characters (borrowed from phpMySQL):
$search = ['\\', '\'', "\0", "\n", "\r", "\x1A"];
$replace = ['\\\\', '\\\'', '\\0', '\\n', '\\r', '\\Z'];
$lines = [];
// Names of inserted fields
$fieldList = implode (', ', array_keys($fieldStructure));
// Select all rows from the table:
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
->getQueryBuilderForTable($table);
$queryBuilder->getRestrictions()
->removeAll();
$result = $queryBuilder->select('*')
->from($table)
->execute();
// Traverse the selected rows and dump each row as a line in the file:
while ($row = $result->fetch()) {
$values = [];
foreach ($fieldStructure as $field => $structure) {
$values[] = isset($row[$field]) ? '\'' . str_replace($search, $replace, $row[$field]) . '\'' : 'NULL';
}
$lines[] = 'INSERT INTO ' . $table . ' (' . $fieldList . ')' . ' VALUES (' . implode(', ', $values) . ');';
}
// Implode lines and return:
return implode(LF, $lines);
}
}

View File

@@ -0,0 +1,119 @@
<?php
namespace SJBR\StaticInfoTables\Utility;
/***************************************************************
* Copyright notice
*
* (c) 2013-2017 StanislasRolland <typo3@sjbr.ca>
* All rights reserved
*
* This script is part of the Typo3 project. The Typo3 project is
* free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* The GNU General Public License can be found at
* http://www.gnu.org/copyleft/gpl.html.
*
* This script is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* This copyright notice MUST APPEAR in all copies of the script!
***************************************************************/
/**
* HTML form element utility functions
*/
class HtmlElementUtility
{
/**
* Buils a HTML drop-down selector of countries, country subdivisions, currencies or languages
*
* @param array $items: An array of couples ('name', 'value) where the names will be the texts of an <option> tags and values will be the values of the tags
* @param array $selected: The values of the code of the entries to be pre-selected in the drop-down selector
* @param array $outSelected: resulting array of keys of selected items
* @param string $name: A value for the name attribute of the <select> tag
* @param string $class: A value for the class attribute of the <select> tag
* @param string $id: A value for the id attribute of the <select> tag
* @param string $title: A value for the title attribute of the <select> tag
* @param string $onChange: A value for the onChange attribute of the <select> tag
* @param int $size: max elements that can be selected. Default: 1
*
* @return string A set of HTML <select> and <option> tags
*/
public static function selectConstructor($items, $selected = [], &$outSelected = [], $name = '', $class = '', $id = '', $title = '', $onChange = '', $size = 1)
{
$selector = '';
if (is_array($items) && count($items) > 0) {
$idAttribute = (trim($id)) ? 'id="' . htmlspecialchars(trim($id)) . '" ' : '';
$nameAttribute = (trim($name)) ? 'name="' . htmlspecialchars(trim($name)) . '" ' : '';
$titleAttribute = (trim($title)) ? 'title="' . htmlspecialchars(trim($title)) . '" ' : '';
$classAttribute = (trim($class)) ? 'class="' . htmlspecialchars(trim($class)) . '" ' : '';
if ($onChange) {
$onChangeAttribute = $onChange;
$onChangeAttribute = str_replace('"', '\'', $onChangeAttribute);
$onChangeAttribute = self::quoteJsValue($onChangeAttribute);
$onChangeAttribute = 'onchange=' . $onChangeAttribute . ' ';
} else {
$onChangeAttribute = '';
}
if ($size > 1) {
$multiple = 'multiple="multiple" ';
$name .= '[]';
} else {
$multiple = '';
}
$selector = '<select size="' . $size . '" ' . $idAttribute . $nameAttribute . $titleAttribute . $classAttribute . $onChangeAttribute . $multiple . '>' . LF;
$selector .= self::optionsConstructor($items, $selected, $outSelected);
$selector .= '</select>' . LF;
}
return $selector;
}
/**
* Builds a list of <option> tags
*
* @param array $items: An array where the values will be the texts of an <option> tags and keys will be the values of the tags
* @param string $selected: array of pre-selected values: if the value appears as a key, the <option> tag will bear a 'selected' attribute
* @param array $outSelected: resulting array of keys of selected items
*
* @return string A string of HTML <option> tags
*/
public static function optionsConstructor($items, $selected = [], &$outSelected = [])
{
$options = '';
foreach ($items as $item) {
$options .= '<option value="' . $item['value'] . '"';
if (in_array($item['value'], $selected)) {
$options .= ' selected="selected"';
$outSelected[] = $item['value'];
}
$options .= '>' . $item['name'] . '</option>' . LF;
}
if (!isset($outSelected) || count($outSelected) == 0) {
reset($items);
$outSelected = [$items[0]['value']];
}
return $options;
}
/**
* Quotes a string for usage as JS parameter.
*
* @param string The string to encode.
* @param mixed $value
*
* @return string The encoded value already quoted
*/
protected static function quoteJsValue($value)
{
$value = addcslashes($value, '"' . LF . CR);
$value = htmlspecialchars($value);
return '"' . $value . '"';
}
}

View File

@@ -0,0 +1,79 @@
<?php
namespace SJBR\StaticInfoTables\Utility;
/*
* Copyright notice
*
* (c) 2013-2021 Stanislas Rolland <typo3AAAA(arobas)sjbr.ca>
* All rights reserved
*
* This script is part of the Typo3 project. The Typo3 project is
* free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* The GNU General Public License can be found at
* http://www.gnu.org/copyleft/gpl.html.
*
* This script is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* This copyright notice MUST APPEAR in all copies of the script!
*/
use SJBR\StaticInfoTables\Domain\Model\Language;
use TYPO3\CMS\Core\Localization\Locales;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Extbase\Utility\LocalizationUtility;
/**
* Locale-related functions
*/
class LocaleUtility
{
/**
* @var string Name of the extension this class belongs to
*/
protected $extensionName = 'StaticInfoTables';
/**
* Get the typo3-supported locale options
*
* @return array An array of language objects
*/
public function getLocales()
{
$localeArray = [];
$locales = GeneralUtility::makeInstance(Locales::class);
$languages = $locales->getLanguages();
foreach ($languages as $locale => $language) {
// No language pack for English
if ($locale != 'default') {
$languageObject = new Language();
$languageObject->setCollatingLocale($locale);
$localizedLanguage = LocalizationUtility::translate('lang_' . $locale, $this->extensionName);
$label = ($localizedLanguage ? $localizedLanguage : $language) . ' (' . $locale . ')';
$languageObject->setNameEn($label);
$localeArray[$label] = $languageObject;
}
}
ksort($localeArray);
return $localeArray;
}
/**
* Get language name from locale
*
* @param string $locale
* @return string Language name
*/
public function getLanguageFromLocale($locale)
{
$locales = GeneralUtility::makeInstance(Locales::class);
$languages = $locales->getLanguages();
return $languages[$locale];
}
}

View File

@@ -0,0 +1,378 @@
<?php
namespace SJBR\StaticInfoTables\Utility;
/*
* Copyright notice
*
* (c) 2009 Sebastian Kurfürst <sebastian@typo3.org>
* (c) 2013-2022 Stanislas Rolland <typo3AAAA@sjbr.ca>
* All rights reserved
*
* This script is part of the TYPO3 project. The TYPO3 project is
* free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* The GNU General Public License can be found at
* http://www.gnu.org/copyleft/gpl.html.
*
* This script is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* This copyright notice MUST APPEAR in all copies of the script!
*/
use Psr\Http\Message\ServerRequestInterface;
use SJBR\StaticInfoTables\Domain\Model\Language;
use SJBR\StaticInfoTables\Domain\Repository\LanguageRepository;
use TYPO3\CMS\Core\Database\ConnectionPool;
use TYPO3\CMS\Core\Http\ApplicationType;
use TYPO3\CMS\Core\Localization\LanguageService;
use TYPO3\CMS\Core\Localization\Locales;
use TYPO3\CMS\Core\Site\Entity\SiteLanguage;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Core\Utility\MathUtility;
use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController;
/**
* Localization helper which should be used to fetch localized labels for static info entities.
*/
class LocalizationUtility
{
/**
* Key of the language to use
*
* @var string
*/
protected static $languageKey = 'default';
/**
* Pointer to alternative fall-back language to use
*
* @var array
*/
protected static $alternativeLanguageKeys = [];
/**
* Collating locale for the language in use
*
* @var string
*/
protected static $collatingLocale = '';
/**
* Returns the localized label for a static info entity
*
* @param array $identifiers An array with key 1- 'uid' containing a uid and/or 2- 'iso' containing one or two iso codes (i.e. country zone code and country code, or language code and country code)
* @param string $tableName The name of the table
* @param bool local name only - if set local labels are returned
* @param mixed $local
* @return string The value from the label field of the table
*/
public static function translate($identifiers, $tableName, $local = false)
{
$value = '';
self::setLanguageKeys();
$isoLanguage = self::getIsoLanguageKey(self::$languageKey);
$value = self::getLabelFieldValue($identifiers, $tableName, $isoLanguage, $local);
return $value;
}
/**
* Get the localized value for the label field
*
* @param array $identifiers An array with key 1- 'uid' containing a uid and/or 2- 'iso' containing one or two iso codes (i.e. country zone code and country code, or language code and country code)
* @param string $tableName The name of the table
* @param string language ISO code
* @param bool local name only - if set local labels are returned
* @param mixed $language
* @param mixed $local
*
* @return string the value for the label field
*/
public static function getLabelFieldValue($identifiers, $tableName, $language, $local = false)
{
$value = '';
$labelFields = self::getLabelFields($tableName, $language, $local);
if (count($labelFields)) {
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($tableName);
$queryBuilder->from($tableName)->select('uid');
foreach ($labelFields as $labelField => $map) {
$queryBuilder->addSelect($labelField);
}
$whereCount = 0;
if ($identifiers['uid'] ?? false) {
$queryBuilder->where(
$queryBuilder->expr()->eq('uid', $queryBuilder->createNamedParameter((int)$identifiers['uid']), \PDO::PARAM_INT)
);
$whereCount++;
} elseif (!empty($identifiers['iso'])) {
$isoCode = is_array($identifiers['iso']) ? $identifiers['iso'] : [$identifiers['iso']];
foreach ($isoCode as $index => $code) {
if ($code) {
$field = self::getIsoCodeField($tableName, $code, $index);
if ($field) {
if ($whereCount) {
$queryBuilder->andWhere(
$queryBuilder->expr()->eq($field, $queryBuilder->createNamedParameter($code))
);
$whereCount++;
} else {
$queryBuilder->where(
$queryBuilder->expr()->eq($field, $queryBuilder->createNamedParameter($code))
);
$whereCount++;
}
}
}
}
}
// Get the entity
if ($whereCount) {
$row = $queryBuilder->execute()->fetch();
if ($row) {
foreach ($labelFields as $labelField => $map) {
if ($row[$labelField]) {
$value = $row[$labelField];
break;
}
}
}
}
}
return $value;
}
/**
* Returns the label fields for a given language
*
* @param string table name
* @param string ISO language code to be used
* @param bool If set, we are looking for the "local" title field
* @param mixed $tableName
* @param mixed $lang
* @param mixed $local
* @return array field names
*/
public static function getLabelFields($tableName, $lang, $local = false)
{
$labelFields = [];
if (isset($GLOBALS['TYPO3_CONF_VARS']['EXTENSIONS']['static_info_tables']['tables'][$tableName]['label_fields'])
&& is_array($GLOBALS['TYPO3_CONF_VARS']['EXTENSIONS']['static_info_tables']['tables'][$tableName]['label_fields'])) {
$alternativeLanguages = [];
if (count(self::$alternativeLanguageKeys)) {
$alternativeLanguages = array_reverse(self::$alternativeLanguageKeys);
}
foreach ($GLOBALS['TYPO3_CONF_VARS']['EXTENSIONS']['static_info_tables']['tables'][$tableName]['label_fields'] as $field => $map) {
if ($local) {
$labelField = str_replace('##', 'local', $field);
$property = str_replace('##', 'Local', $map['mapOnProperty']);
} else {
$labelField = str_replace('##', strtolower($lang), $field);
$property = str_replace('##', ucfirst(strtolower($lang)), $map['mapOnProperty']);
}
// Make sure the resulting field name exists in the table
if (isset($GLOBALS['TCA'][$tableName]['columns'][$labelField])
&& is_array($GLOBALS['TCA'][$tableName]['columns'][$labelField])
) {
$labelFields[$labelField] = ['mapOnProperty' => $property];
}
// Add fields for alternative languages
if (strpos($field, '##') !== false && count($alternativeLanguages)) {
foreach ($alternativeLanguages as $language) {
$labelField = str_replace('##', strtolower($language), $field);
$property = str_replace('##', ucfirst(strtolower($language)), $map['mapOnProperty']);
// Make sure the resulting field name exists in the table
if (is_array($GLOBALS['TCA'][$tableName]['columns'][$labelField])) {
$labelFields[$labelField] = ['mapOnProperty' => $property];
}
}
}
}
}
return $labelFields;
}
/**
* Returns a iso code field for the passed table name, iso code and index
*
* @param string table name
* @param string iso code
* @param int index in the table's isocode_field configuration array
* @param mixed $table
* @param mixed $isoCode
* @param mixed $index
* @return string field name
*/
public static function getIsoCodeField($table, $isoCode, $index = 0)
{
$isoCodeField = '';
$isoCodeFieldTemplate = $GLOBALS['TYPO3_CONF_VARS']['EXTENSIONS']['static_info_tables']['tables'][$table]['isocode_field'][$index] ?? '';
if ($isoCode && $table && $isoCodeFieldTemplate) {
$field = str_replace('##', self::isoCodeType($isoCode), $isoCodeFieldTemplate);
if (is_array($GLOBALS['TCA'][$table]['columns'][$field])) {
$isoCodeField = $field;
}
}
return $isoCodeField;
}
/**
* Returns the type of an iso code: nr, 2, 3
*
* @param string iso code
* @param mixed $isoCode
*
* @return string iso code type
*/
protected static function isoCodeType($isoCode)
{
$type = '';
$isoCodeAsInteger = MathUtility::canBeInterpretedAsInteger($isoCode);
if ($isoCodeAsInteger) {
$type = 'nr';
} elseif (strlen($isoCode) == 2) {
$type = '2';
} elseif (strlen($isoCode) == 3) {
$type = '3';
}
return $type;
}
/**
* Get the ISO language key corresponding to a TYPO3 language key
*
* @param string $key The TYPO3 language key
*
* @return string the ISO language key
*/
public static function getIsoLanguageKey($key)
{
return $key === 'default' ? 'EN' : $key;
}
/**
* Get the current TYPO3 language
*
* @return string the TYP3 language key
*/
public static function getCurrentLanguage()
{
if (self::$languageKey === 'default') {
self::setLanguageKeys();
}
return self::$languageKey;
}
/**
* Sets the currently active language/language_alt keys.
* Default values are "default" for language key and "" for language_alt key.
*
* @return void
*/
protected static function setLanguageKeys()
{
self::$languageKey = 'default';
self::$alternativeLanguageKeys = [];
if (($GLOBALS['TYPO3_REQUEST'] ?? null) instanceof ServerRequestInterface
&& ApplicationType::fromRequest($GLOBALS['TYPO3_REQUEST'])->isFrontend()
) {
$tsfe = static::getTypoScriptFrontendController();
$siteLanguage = self::getCurrentSiteLanguage();
// Get values from site language, which takes precedence over TypoScript settings
if ($siteLanguage instanceof SiteLanguage) {
self::$languageKey = $siteLanguage->getTypo3Language();
} elseif (isset($tsfe->config['config']['language'])) {
self::$languageKey = $tsfe->config['config']['language'];
}
if (isset($tsfe->config['config']['language_alt'])) {
self::$alternativeLanguageKeys[] = $tsfe->config['config']['language_alt'];
}
if (empty(self::$alternativeLanguageKeys)) {
$locales = GeneralUtility::makeInstance(Locales::class);
if (in_array(self::$languageKey, $locales->getLocales())) {
foreach ($locales->getLocaleDependencies(self::$languageKey) as $language) {
self::$alternativeLanguageKeys[] = $language;
}
}
}
} else {
if (!empty($GLOBALS['BE_USER']->uc['lang'])) {
self::$languageKey = $GLOBALS['BE_USER']->uc['lang'];
} elseif (!empty(static::getLanguageService()->lang)) {
self::$languageKey = static::getLanguageService()->lang;
}
// Get standard locale dependencies for the backend
$locales = GeneralUtility::makeInstance(Locales::class);
if (in_array(self::$languageKey, $locales->getLocales())) {
foreach ($locales->getLocaleDependencies(self::$languageKey) as $language) {
self::$alternativeLanguageKeys[] = $language;
}
}
}
if (!self::$languageKey || self::$languageKey === 'default') {
self::$languageKey = 'EN';
}
}
/**
* Set the collating locale
*
* @return mixed the set locale or false
*/
public static function setCollatingLocale()
{
if (self::$collatingLocale === '') {
$languageCode = self::getCurrentLanguage();
$languageRepository = GeneralUtility::makeInstance(LanguageRepository::class);
$languageCodeParts = explode('_', $languageCode, 2);
$languageIsoCodeA2 = $languageCodeParts[0] ?? '';
$countryIsoCodeA2 = $languageCodeParts[1] ?? '';
$language = $languageRepository->findOneByIsoCodes($languageIsoCodeA2, $countryIsoCodeA2 ?? '');
// If $language is NULL, current language was not found in the Language repository. Most probably, the repository is empty.
self::$collatingLocale = ($language instanceof Language) ? $language->getCollatingLocale() : 'en_GB';
}
return setlocale(
LC_COLLATE,
[
self::$collatingLocale . '.UTF-8',
self::$collatingLocale . '.UTF8',
self::$collatingLocale . '.utf8',
]
);
}
/**
* Returns the currently configured "site language" if a site is configured (= resolved)
* in the current request.
*
* @return SiteLanguage|null
*/
protected static function getCurrentSiteLanguage(): ?SiteLanguage
{
if ($GLOBALS['TYPO3_REQUEST'] instanceof ServerRequestInterface) {
return $GLOBALS['TYPO3_REQUEST']->getAttribute('language', null);
}
return null;
}
/**
* @return TypoScriptFrontendController
*/
protected static function getTypoScriptFrontendController()
{
return $GLOBALS['TSFE'];
}
/**
* @return LanguageService
*/
protected static function getLanguageService()
{
return $GLOBALS['LANG'];
}
}

View File

@@ -0,0 +1,108 @@
<?php
/*
* This file is part of the TYPO3 CMS project.
*
* It is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, either version 2
* of the License, or any later version.
*
* For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code.
*
* The TYPO3 project - inspiring people to share!
*/
namespace SJBR\StaticInfoTables\Utility;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Core\Utility\MathUtility;
/**
* Class with helper functions for version number handling
*/
class VersionNumberUtility
{
/**
* Splits a version range into an array.
*
* If a single version number is given, it is considered a minimum value.
* If a dash is found, the numbers left and right are considered as minimum and maximum. Empty values are allowed.
* If no version can be parsed "0.0.0" — "0.0.0" is the result
*
* @param string $version A string with a version range.
* @return array
*/
public static function splitVersionRange($version)
{
$versionRange = [];
if (strpos($version, '-') !== false) {
$versionRange = explode('-', $version, 2);
} else {
$versionRange[0] = $version;
$versionRange[1] = '';
}
if (!$versionRange[0]) {
$versionRange[0] = '0.0.0';
}
if (!$versionRange[1]) {
$versionRange[1] = '0.0.0';
}
return $versionRange;
}
/**
* Parses the version number x.x.x and returns an array with the various parts.
* It also forces each … 0 to 999
*
* @param string $version Version code, x.x.x
* @return array
*/
public static function convertVersionStringToArray($version)
{
$parts = GeneralUtility::intExplode('.', $version . '..');
$parts[0] = MathUtility::forceIntegerInRange($parts[0], 0, 999);
$parts[1] = MathUtility::forceIntegerInRange($parts[1], 0, 999);
$parts[2] = MathUtility::forceIntegerInRange($parts[2], 0, 999);
$result = [];
$result['version'] = $parts[0] . '.' . $parts[1] . '.' . $parts[2];
$result['version_int'] = (int)($parts[0] * 1000000 + $parts[1] * 1000 + $parts[2]);
$result['version_main'] = $parts[0];
$result['version_sub'] = $parts[1];
$result['version_dev'] = $parts[2];
return $result;
}
/**
* Method to raise a version number
*
* @param string $raise one of "main", "sub", "dev" - the version part to raise by one
* @param string $version (like 4.1.20)
* @return string
*/
public static function raiseVersionNumber($raise, $version)
{
if (!in_array($raise, ['main', 'sub', 'dev'])) {
throw new Exception('RaiseVersionNumber expects one of "main", "sub" or "dev".', 1342639555);
}
$parts = GeneralUtility::intExplode('.', $version . '..');
$parts[0] = MathUtility::forceIntegerInRange($parts[0], 0, 999);
$parts[1] = MathUtility::forceIntegerInRange($parts[1], 0, 999);
$parts[2] = MathUtility::forceIntegerInRange($parts[2], 0, 999);
switch ((string)$raise) {
case 'main':
$parts[0]++;
$parts[1] = 0;
$parts[2] = 0;
break;
case 'sub':
$parts[1]++;
$parts[2] = 0;
break;
case 'dev':
$parts[2]++;
break;
}
return $parts[0] . '.' . $parts[1] . '.' . $parts[2];
}
}

View File

@@ -0,0 +1,316 @@
<?php
namespace SJBR\StaticInfoTables\ViewHelpers\Form;
/*
* Copyright notice
*
* (c) 2014 Carsten Biebricher <carsten.biebricher@hdnet.de>
* (c) 2016-2022 Stanislas Rolland <typo3AAAA(arobas)sjbr.ca>
* All rights reserved
*
* This script is part of the Typo3 project. The Typo3 project is
* free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* The GNU General Public License can be found at
* http://www.gnu.org/copyleft/gpl.html.
*
* This script is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* This copyright notice MUST APPEAR in all copies of the script!
*/
use SJBR\StaticInfoTables\Domain\Repository\CountryRepository;
use SJBR\StaticInfoTables\Domain\Repository\CountryZoneRepository;
use SJBR\StaticInfoTables\Domain\Repository\CurrencyRepository;
use SJBR\StaticInfoTables\Domain\Repository\LanguageRepository;
use SJBR\StaticInfoTables\Domain\Repository\TerritoryRepository;
use TYPO3\CMS\Core\Utility\MathUtility;
use TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface;
/**
* StaticInfoTables SelectViewHelper
*
* Display the Values of the selected StaticInfoTable.
*
* Default usage:
* <code>
* <sit:form.select name="staticInfoTablesTestCountry" staticInfoTable="country" options="{}"/>
* <sit:form.select name="staticInfoTablesTestLanguage" staticInfoTable="language" options="{}"/>
* <sit:form.select name="staticInfoTablesTestTerritory" staticInfoTable="territory" options="{}"/>
* <sit:form.select name="staticInfoTablesTestCurrency" staticInfoTable="currency" options="{}"/>
* <sit:form.select name="staticInfoTablesTestCountryZones" staticInfoTable="countryZone" options="{}"/>
* </code>
*
* Optional Usage:
* <code>
* <sit:form.select name="staticInfoTablesTestCountry" id="staticInfoTablesTestCountry" staticInfoTable="country" options="{}" optionLabelField="isoCodeA2"/>
* <sit:form.select name="staticInfoTablesTestCountry" id="staticInfoTablesTestCountry" staticInfoTable="country" options="{}" optionLabelField="capitalCity"/>
* </code>
*
* Subselect Usage: (only CountryZones of Germany)
* <sit:form.select name="staticInfoTablesTestCountryZones" id="staticInfoTablesTestCountryZones" staticInfoTable="countryZone" options="{}" staticInfoTableSubselect="{country: 54}"/>
*
* if you specify the Label-Field for the table use the Variable-Name from the StaticInfoTable-Model. (@see \SJBR\StaticInfoTables\Domain\Model\Country, ...)
*
* use name or property!
*
* Available Tables:
* country
* language
* territory
* currency
* countryZone
*/
class SelectViewHelper extends \TYPO3\CMS\Fluid\ViewHelpers\Form\SelectViewHelper
{
/**
* Extension name
*
* @var string
*/
protected $extensionName = 'StaticInfoTables';
/**
* Settings
*
* @var array
*/
protected $settings;
/**
* Country repository
*
* @var \SJBR\StaticInfoTables\Domain\Repository\CountryRepository
*/
protected $countryRepository;
/**
* Dependency injection of the Country Repository
*
* @param CountryRepository $countryRepository
* @return void
*/
public function injectCountryRepository(CountryRepository $countryRepository)
{
$this->countryRepository = $countryRepository;
}
/**
* Language repository
*
* @var \SJBR\StaticInfoTables\Domain\Repository\LanguageRepository
*/
protected $languageRepository;
/**
* Dependency injection of the Language Repository
*
* @param LanguageRepository $languageRepository
* @return void
*/
public function injectLanguageRepository(LanguageRepository $languageRepository)
{
$this->languageRepository = $languageRepository;
}
/**
* Territory repository
*
* @var \SJBR\StaticInfoTables\Domain\Repository\TerritoryRepository
*/
protected $territoryRepository;
/**
* Dependency injection of the Territory Repository
*
* @param TerritoryRepository $territoryRepository
* @return void
*/
public function injectTerritoryRepository(TerritoryRepository $territoryRepository)
{
$this->territoryRepository = $territoryRepository;
}
/**
* Currency repository
*
* @var \SJBR\StaticInfoTables\Domain\Repository\CurrencyRepository
*/
protected $currencyRepository;
/**
* Dependency injection of the Currency Repository
*
* @param CurrencyRepository $currencyRepository
* @return void
*/
public function injectCurrencyRepository(CurrencyRepository $currencyRepository)
{
$this->currencyRepository = $currencyRepository;
}
/**
* Country Zone repository
*
* @var \SJBR\StaticInfoTables\Domain\Repository\CountryZoneRepository
*/
protected $countryZoneRepository;
/**
* Dependency injection of the CountryZone Repository
*
* @param CountryZoneRepository $countryZoneRepository
* @return void
*/
public function injectCountryZoneRepository(CountryZoneRepository $countryZoneRepository)
{
$this->countryZoneRepository = $countryZoneRepository;
}
/**
* Initialize arguments.
*
* @return void
*/
public function initializeArguments()
{
parent::initializeArguments();
$this->registerArgument('staticInfoTable', 'string', 'set the tablename of the StaticInfoTable to build the Select-Tag.');
$this->registerArgument('staticInfoTableSubselect', 'array', '{fieldname: fieldvalue}');
$this->registerArgument('defaultOptionLabel', 'string', 'if set, add default option with given label');
$this->registerArgument('defaultOptionValue', 'string', 'if set, add default option with given label');
}
/**
* Render the Options.
*
* @throws Exception
* @return string
*
* @api
*/
public function getOptions()
{
$this->settings = $this->configurationManager->getConfiguration(ConfigurationManagerInterface::CONFIGURATION_TYPE_SETTINGS, $this->extensionName);
if (!$this->hasArgument('staticInfoTable') || ($this->arguments['staticInfoTable'] ?? '') == '') {
throw new \Exception('Please configure the "staticInfoTable"-Argument for this ViewHelper.', 1378136534);
}
/** @var \SJBR\StaticInfoTables\Domain\Repository\AbstractEntityRepository $repository */
$repository = lcfirst($this->arguments['staticInfoTable']) . 'Repository';
if (!array_key_exists($repository, get_object_vars($this))) {
throw new \Exception('Please configure the right table in the "staticInfoTable"-Argument for this ViewHelper.', 1378136533);
}
/** @var array $items */
$items = $this->getItems($repository);
/** @var string $valueFunction */
$valueFunction = $this->getMethodnameFromArgumentsAndUnset('optionValueField', 'uid');
/** @var string $labelFunction */
$labelFunction = $this->getMethodnameFromArgumentsAndUnset('optionLabelField', 'nameLocalized');
if (!($this->settings['countriesAllowed'] ?? false) && (!$this->hasArgument('sortByOptionLabel') || ($this->arguments['sortByOptionLabel'] ?? '') == '')) {
$this->arguments['sortByOptionLabel'] = true;
}
/** @var bool $test Test only the first item if they have the needed functions */
$test = true;
$options = [];
/** @var \SJBR\StaticInfoTables\Domain\Model\AbstractEntity $item */
foreach ($items as $item) {
if ($test && !method_exists($item, $valueFunction)) {
throw new \Exception('Wrong optionValueField.', 1378136535);
}
if ($test && !method_exists($item, $labelFunction)) {
throw new \Exception('Wrong optionLabelField.', 1378136536);
}
$test = false;
$value = $item->{$valueFunction}();
$label = $item->{$labelFunction}();
if ($value != '' && $label != '') {
$options[$value] = $label;
}
}
$this->arguments['options'] = $options;
$sortedOptions = parent::getOptions();
// Put default option after sorting to get it to the top of the items
if ($this->hasArgument('defaultOptionLabel')) {
$defaultOptionLabel = $this->arguments['defaultOptionLabel'];
$defaultOptionValue = $this->hasArgument('defaultOptionValue') ? $this->arguments['defaultOptionValue'] : 0;
$sortedOptions = [$defaultOptionValue => $defaultOptionLabel] + $sortedOptions;
}
return $sortedOptions;
}
/**
* Get Items
*
* @param string $repository
* @return array
*/
protected function getItems($repository)
{
if ($this->hasArgument('staticInfoTableSubselect')) {
$items = $this->getItemsWithSubselect($repository);
} elseif ($repository === 'countryRepository') {
if (isset($this->settings['countriesAllowed']) && $this->settings['countriesAllowed']) {
$items = $this->{$repository}->findAllowedByIsoCodeA3($this->settings['countriesAllowed']);
} else {
$items = $this->{$repository}->findAll()
->toArray();
}
} elseif ($repository === 'languageRepository') {
$items = $this->{$repository}->findAllNonConstructedNonSacred()
->toArray();
} else {
$items = $this->{$repository}->findAll()
->toArray();
}
return $items;
}
/**
* Get items with custom sub select.
*
* @param string $repository
* @return array
*/
protected function getItemsWithSubselect($repository)
{
$items = [];
$subselects = $this->arguments['staticInfoTableSubselect'] ?? [];
foreach ($subselects as $fieldname => $fieldvalue) {
// default implemented Subselect
if (strtolower($fieldname) === 'country' && MathUtility::canBeInterpretedAsInteger($fieldvalue)) {
$findby = 'findBy' . ucfirst($fieldname);
$fieldvalue = $this->countryRepository->findByUid((int)$fieldvalue);
$items = call_user_func_array([
$this->{$repository},
$findby,
], [$fieldvalue]);
$items = $items->toArray();
}
}
return $items;
}
/**
* Return the in the arguments defined field, prepend 'get' and return it.
* If the field is in the arguments not set it return the in the default defined value.
*
* @param string $field fieldname like 'optionLabelField'
* @param string $default default value like 'nameLocalized'
* @return string
*/
protected function getMethodnameFromArgumentsAndUnset($field, $default)
{
if (!$this->hasArgument($field) || $this->arguments[$field] == '') {
$this->arguments[$field] = $default;
}
$methodName = 'get' . ucfirst($this->arguments[$field]);
unset($this->arguments[$field]);
return $methodName;
}
}