[TASK] Update base extension
This commit is contained in:
parent
2e75454bb0
commit
47e55d8f48
0
.gitlab-ci.yml
Executable file → Normal file
0
.gitlab-ci.yml
Executable file → Normal file
13
Classes/Command/ContentElementCommand.php
Executable file → Normal file
13
Classes/Command/ContentElementCommand.php
Executable file → Normal file
@ -1,5 +1,7 @@
|
||||
<?php
|
||||
|
||||
namespace Evoweb\EwBase\Command;
|
||||
|
||||
/*
|
||||
* This file is developed by evoWeb.
|
||||
*
|
||||
@ -11,8 +13,6 @@
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Evoweb\EwBase\Command;
|
||||
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Helper\Table;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
@ -28,15 +28,18 @@ use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||
|
||||
class ContentElementCommand extends Command
|
||||
{
|
||||
public function __construct(protected ConnectionPool $connectionPool)
|
||||
protected ConnectionPool $connectionPool;
|
||||
|
||||
public function __construct(ConnectionPool $connectionPool)
|
||||
{
|
||||
$this->connectionPool = $connectionPool;
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
protected function configure(): void
|
||||
protected function configure()
|
||||
{
|
||||
$this
|
||||
->setAliases(['ce'])
|
||||
->setAliases(['kc-sitepackage'])
|
||||
->addOption(
|
||||
'pageId',
|
||||
'-p',
|
||||
|
||||
55
Classes/Configuration/AdditionalConfiguration.php
Executable file → Normal file
55
Classes/Configuration/AdditionalConfiguration.php
Executable file → Normal file
@ -2,19 +2,18 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Evoweb\EwBase\Configuration;
|
||||
|
||||
/*
|
||||
* This file is developed by evoWeb.
|
||||
* This file is part of TYPO3 CMS-based extension "container" by b13.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
namespace Evoweb\EwBase\Configuration;
|
||||
|
||||
use Mfc\OAuth2\ResourceServer\GitLab;
|
||||
use Mfc\OAuth2\ResourceServer\Registry;
|
||||
use TYPO3\CMS\Core\Core\Environment;
|
||||
use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
|
||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||
@ -23,6 +22,24 @@ class AdditionalConfiguration
|
||||
{
|
||||
protected string $extensionKey = 'ew_base';
|
||||
|
||||
protected array $oauthOptions = [
|
||||
'enabled' => true, // Enable/Disable the provider
|
||||
'arguments' => [
|
||||
'appId' => '',
|
||||
'appSecret' => '',
|
||||
'projectName' => '',
|
||||
'gitlabServer' => 'https://github.com',
|
||||
// User level at which the user will be given admin permissions
|
||||
'gitlabAdminUserLevel' => 30,
|
||||
// Groups to assign to the User (comma separated list possible)
|
||||
'gitlabDefaultGroups' => 1,
|
||||
// UserConfig db and/or file mount from groups
|
||||
'gitlabUserOption' => 3,
|
||||
// Blocks users with flag external from access the backend
|
||||
'blockExternalUser' => false,
|
||||
],
|
||||
];
|
||||
|
||||
protected array $developConfig = [
|
||||
'BE' => [
|
||||
'debug' => true,
|
||||
@ -57,8 +74,7 @@ class AdditionalConfiguration
|
||||
*/
|
||||
protected array $mailConfig = [
|
||||
'transport' => 'smtp',
|
||||
'transport_smtp_server' => '127.0.0.1:1025',
|
||||
'defaultMailFromAddress' => 'test@dev.arpa',
|
||||
'transport_smtp_server' => '127.0.0.1:1025'
|
||||
];
|
||||
|
||||
public function initialize(array $configuration = []): void
|
||||
@ -66,7 +82,6 @@ class AdditionalConfiguration
|
||||
$this->addContextToSitename();
|
||||
$this->addContextConfiguration($configuration);
|
||||
if (Environment::getContext() == 'Development') {
|
||||
$this->addBaseUrl();
|
||||
$this->addDebugConfiguration();
|
||||
}
|
||||
$this->addFurtherConfigurationFiles();
|
||||
@ -77,28 +92,6 @@ class AdditionalConfiguration
|
||||
$GLOBALS['TYPO3_CONF_VARS']['SYS']['sitename'] .= ' - ' . Environment::getContext();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the baseurl on local environments automatically
|
||||
*/
|
||||
protected function addBaseUrl(): void
|
||||
{
|
||||
if (Environment::isCli()) {
|
||||
return;
|
||||
}
|
||||
$remoteHost = GeneralUtility::getIndpEnv('HTTP_HOST');
|
||||
ExtensionManagementUtility::addTypoScript(
|
||||
$this->extensionKey,
|
||||
'constants',
|
||||
'
|
||||
// condition should trigger different cache hashes
|
||||
[request && request.getNormalizedParams().getHttpHost() == \'' . $remoteHost . '\']
|
||||
config.baseURL = ' . $remoteHost . '
|
||||
[end]
|
||||
',
|
||||
'defaultContentRendering'
|
||||
);
|
||||
}
|
||||
|
||||
protected function addDebugConfiguration(): void
|
||||
{
|
||||
$GLOBALS['TYPO3_CONF_VARS'] = $this->arrayMergeRecursive(
|
||||
|
||||
58
Classes/DataProcessing/ContainerProcessor.php
Normal file
58
Classes/DataProcessing/ContainerProcessor.php
Normal file
@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Evoweb\EwBase\DataProcessing;
|
||||
|
||||
/*
|
||||
* This file is part of TYPO3 CMS-based extension "container" by b13.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
use B13\Container\DataProcessing\ContainerProcessor as BaseContainerProcessor;
|
||||
use B13\Container\Domain\Model\Container;
|
||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||
use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer;
|
||||
use TYPO3\CMS\Frontend\ContentObject\RecordsContentObject;
|
||||
|
||||
class ContainerProcessor extends BaseContainerProcessor
|
||||
{
|
||||
protected function processColPos(
|
||||
ContentObjectRenderer $cObj,
|
||||
Container $container,
|
||||
int $colPos,
|
||||
string $as,
|
||||
array $processedData,
|
||||
array $processorConfiguration
|
||||
): array {
|
||||
$children = $container->getChildrenByColPos($colPos);
|
||||
|
||||
if (!$processorConfiguration['doNotProcessChildren']) {
|
||||
$contentRecordRenderer = new RecordsContentObject();
|
||||
$conf = [
|
||||
'tables' => 'tt_content'
|
||||
];
|
||||
foreach ($children as &$child) {
|
||||
if ($child['l18n_parent'] > 0) {
|
||||
$conf['source'] = $child['l18n_parent'];
|
||||
} else {
|
||||
$conf['source'] = $child['uid'];
|
||||
}
|
||||
if ($child['t3ver_oid'] > 0) {
|
||||
$conf['source'] = $child['t3ver_oid'];
|
||||
}
|
||||
$child['renderedContent'] = $cObj->render($contentRecordRenderer, $conf);
|
||||
/** @var ContentObjectRenderer $recordContentObjectRenderer */
|
||||
$recordContentObjectRenderer = GeneralUtility::makeInstance(ContentObjectRenderer::class);
|
||||
$recordContentObjectRenderer->start($child, 'tt_content');
|
||||
$child = $this->contentDataProcessor->process($recordContentObjectRenderer, $processorConfiguration, $child);
|
||||
}
|
||||
}
|
||||
|
||||
$processedData[$as] = $children;
|
||||
return $processedData;
|
||||
}
|
||||
}
|
||||
831
Classes/DataProcessing/DatabaseQueryProcessor.php
Normal file
831
Classes/DataProcessing/DatabaseQueryProcessor.php
Normal file
@ -0,0 +1,831 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* 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 Evoweb\EwBase\DataProcessing;
|
||||
|
||||
use Doctrine\DBAL\Exception as DBALException;
|
||||
use Doctrine\DBAL\Result;
|
||||
use TYPO3\CMS\Backend\FrontendBackendUserAuthentication;
|
||||
use TYPO3\CMS\Core\Context\Context;
|
||||
use TYPO3\CMS\Core\Context\LanguageAspect;
|
||||
use TYPO3\CMS\Core\Database\ConnectionPool;
|
||||
use TYPO3\CMS\Core\Database\Query\Expression\ExpressionBuilder;
|
||||
use TYPO3\CMS\Core\Database\Query\QueryBuilder;
|
||||
use TYPO3\CMS\Core\Database\Query\QueryHelper;
|
||||
use TYPO3\CMS\Core\Database\Query\Restriction\DocumentTypeExclusionRestriction;
|
||||
use TYPO3\CMS\Core\Database\Query\Restriction\FrontendRestrictionContainer;
|
||||
use TYPO3\CMS\Core\TimeTracker\TimeTracker;
|
||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||
use TYPO3\CMS\Core\Utility\MathUtility;
|
||||
use TYPO3\CMS\Core\Versioning\VersionState;
|
||||
use TYPO3\CMS\Frontend\ContentObject\ContentDataProcessor;
|
||||
use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer;
|
||||
use TYPO3\CMS\Frontend\ContentObject\DataProcessorInterface;
|
||||
use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController;
|
||||
|
||||
/**
|
||||
* Fetch records from the database, using the default .select syntax from TypoScript.
|
||||
*
|
||||
* This way, e.g. a FLUIDTEMPLATE cObject can iterate over the array of records.
|
||||
*
|
||||
* Example TypoScript configuration:
|
||||
*
|
||||
* 10 = TYPO3\CMS\Frontend\DataProcessing\DatabaseQueryProcessor
|
||||
* 10 {
|
||||
* table = tt_address
|
||||
* pidInList = 123
|
||||
* where = company="Acme" AND first_name="Ralph"
|
||||
* orderBy = sorting DESC
|
||||
* as = addresses
|
||||
* dataProcessing {
|
||||
* 10 = TYPO3\CMS\Frontend\DataProcessing\FilesProcessor
|
||||
* 10 {
|
||||
* references.fieldName = image
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* where "as" means the variable to be containing the result-set from the DB query.
|
||||
*/
|
||||
class DatabaseQueryProcessor implements DataProcessorInterface
|
||||
{
|
||||
protected ContentDataProcessor $contentDataProcessor;
|
||||
|
||||
protected ContentObjectRenderer $cObj;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->contentDataProcessor = GeneralUtility::makeInstance(ContentDataProcessor::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches records from the database as an array
|
||||
*
|
||||
* @param ContentObjectRenderer $cObj The data of the content element or page
|
||||
* @param array $contentObjectConfiguration The configuration of Content Object
|
||||
* @param array $processorConfiguration The configuration of this processor
|
||||
* @param array $processedData Key/value store of processed data (e.g. to be passed to a Fluid View)
|
||||
*
|
||||
* @return array the processed data as key/value store
|
||||
*/
|
||||
public function process(
|
||||
ContentObjectRenderer $cObj,
|
||||
array $contentObjectConfiguration,
|
||||
array $processorConfiguration,
|
||||
array $processedData
|
||||
) {
|
||||
$this->cObj = $cObj;
|
||||
if (isset($processorConfiguration['if.']) && !$cObj->checkIf($processorConfiguration['if.'])) {
|
||||
return $processedData;
|
||||
}
|
||||
|
||||
// the table to query, if none given, exit
|
||||
$tableName = $cObj->stdWrapValue('table', $processorConfiguration);
|
||||
if (empty($tableName)) {
|
||||
return $processedData;
|
||||
}
|
||||
if (isset($processorConfiguration['table.'])) {
|
||||
unset($processorConfiguration['table.']);
|
||||
}
|
||||
if (isset($processorConfiguration['table'])) {
|
||||
unset($processorConfiguration['table']);
|
||||
}
|
||||
|
||||
// The variable to be used within the result
|
||||
$targetVariableName = $cObj->stdWrapValue('as', $processorConfiguration, 'records');
|
||||
|
||||
// Execute a SQL statement to fetch the records
|
||||
$records = $this->getRecords($tableName, $processorConfiguration);
|
||||
$request = $cObj->getRequest();
|
||||
$processedRecordVariables = [];
|
||||
foreach ($records as $key => $record) {
|
||||
$recordContentObjectRenderer = GeneralUtility::makeInstance(ContentObjectRenderer::class);
|
||||
$recordContentObjectRenderer->start($record, $tableName, $request);
|
||||
$processedRecordVariables[$key] = ['data' => $record];
|
||||
$processedRecordVariables[$key] = $this->contentDataProcessor->process(
|
||||
$recordContentObjectRenderer,
|
||||
$processorConfiguration,
|
||||
$processedRecordVariables[$key]
|
||||
);
|
||||
}
|
||||
|
||||
$processedData[$targetVariableName] = $processedRecordVariables;
|
||||
|
||||
return $processedData;
|
||||
}
|
||||
|
||||
protected function getRecords(string $tableName, array $queryConfiguration): array
|
||||
{
|
||||
$records = [];
|
||||
|
||||
$statement = $this->exec_getQuery($tableName, $queryConfiguration);
|
||||
|
||||
$tsfe = $this->getTypoScriptFrontendController();
|
||||
while ($row = $statement->fetchAssociative()) {
|
||||
// Versioning preview:
|
||||
$tsfe->sys_page->versionOL($tableName, $row, true);
|
||||
|
||||
// Language overlay:
|
||||
if (is_array($row)) {
|
||||
$row = $tsfe->sys_page->getLanguageOverlay($tableName, $row);
|
||||
}
|
||||
|
||||
// Might be unset in the language overlay
|
||||
if (is_array($row)) {
|
||||
$records[] = $row;
|
||||
}
|
||||
}
|
||||
|
||||
return $records;
|
||||
}
|
||||
|
||||
protected function exec_getQuery(string $table, array $conf): Result
|
||||
{
|
||||
$statement = $this->getQuery($table, $conf);
|
||||
$connection = GeneralUtility::makeInstance(ConnectionPool::class)->getConnectionForTable($table);
|
||||
|
||||
return $connection->executeQuery($statement);
|
||||
}
|
||||
|
||||
public function getQuery($table, $conf, $returnQueryArray = false)
|
||||
{
|
||||
// Resolve stdWrap in these properties first
|
||||
$connection = GeneralUtility::makeInstance(ConnectionPool::class)->getConnectionForTable($table);
|
||||
$properties = [
|
||||
'pidInList',
|
||||
'uidInList',
|
||||
'languageField',
|
||||
'selectFields',
|
||||
'max',
|
||||
'begin',
|
||||
'groupBy',
|
||||
'orderBy',
|
||||
'join',
|
||||
'leftjoin',
|
||||
'rightjoin',
|
||||
'recursive',
|
||||
'where',
|
||||
];
|
||||
foreach ($properties as $property) {
|
||||
$conf[$property] = trim(
|
||||
isset($conf[$property . '.'])
|
||||
? (string)$this->cObj->stdWrap($conf[$property] ?? '', $conf[$property . '.'] ?? [])
|
||||
: (string)($conf[$property] ?? '')
|
||||
);
|
||||
if ($conf[$property] === '') {
|
||||
unset($conf[$property]);
|
||||
} elseif (in_array($property, ['languageField', 'selectFields', 'join', 'leftjoin', 'rightjoin', 'where'], true)) {
|
||||
$conf[$property] = QueryHelper::quoteDatabaseIdentifiers($connection, $conf[$property]);
|
||||
}
|
||||
if (isset($conf[$property . '.'])) {
|
||||
// stdWrapping already done, so remove the sub-array
|
||||
unset($conf[$property . '.']);
|
||||
}
|
||||
}
|
||||
// Handle PDO-style named parameter markers first
|
||||
$queryMarkers = $this->getQueryMarkers($table, $conf);
|
||||
// Replace the markers in the non-stdWrap properties
|
||||
foreach ($queryMarkers as $marker => $markerValue) {
|
||||
$properties = [
|
||||
'uidInList',
|
||||
'selectFields',
|
||||
'where',
|
||||
'max',
|
||||
'begin',
|
||||
'groupBy',
|
||||
'orderBy',
|
||||
'join',
|
||||
'leftjoin',
|
||||
'rightjoin',
|
||||
];
|
||||
foreach ($properties as $property) {
|
||||
if ($conf[$property] ?? false) {
|
||||
$conf[$property] = str_replace('###' . $marker . '###', (string)$markerValue, $conf[$property]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Construct WHERE clause:
|
||||
// Handle recursive function for the pidInList
|
||||
if (isset($conf['recursive'])) {
|
||||
$conf['recursive'] = (int)$conf['recursive'];
|
||||
if ($conf['recursive'] > 0) {
|
||||
$pidList = GeneralUtility::trimExplode(',', $conf['pidInList'], true);
|
||||
array_walk($pidList, function (&$storagePid) {
|
||||
if ($storagePid === 'this') {
|
||||
$storagePid = $this->getTypoScriptFrontendController()->id;
|
||||
}
|
||||
});
|
||||
$expandedPidList = $this->getTypoScriptFrontendController()->sys_page->getPageIdsRecursive($pidList, $conf['recursive']);
|
||||
$conf['pidInList'] = implode(',', $expandedPidList);
|
||||
}
|
||||
}
|
||||
if ((string)($conf['pidInList'] ?? '') === '') {
|
||||
$conf['pidInList'] = 'this';
|
||||
}
|
||||
|
||||
$queryParts = $this->getQueryConstraints($table, $conf);
|
||||
|
||||
$queryBuilder = $connection->createQueryBuilder();
|
||||
// @todo Check against getQueryConstraints, can probably use FrontendRestrictions
|
||||
// @todo here and remove enableFields there.
|
||||
$queryBuilder->getRestrictions()->removeAll();
|
||||
$queryBuilder->select('*')->from($table);
|
||||
|
||||
if ($queryParts['where'] ?? false) {
|
||||
$queryBuilder->where($queryParts['where']);
|
||||
}
|
||||
|
||||
if ($queryParts['groupBy'] ?? false) {
|
||||
$queryBuilder->groupBy(...$queryParts['groupBy']);
|
||||
}
|
||||
|
||||
if (is_array($queryParts['orderBy'] ?? false)) {
|
||||
foreach ($queryParts['orderBy'] as $orderBy) {
|
||||
$queryBuilder->addOrderBy(...$orderBy);
|
||||
}
|
||||
}
|
||||
|
||||
// Fields:
|
||||
if ($conf['selectFields'] ?? false) {
|
||||
$queryBuilder->selectLiteral($this->sanitizeSelectPart($conf['selectFields'], $table));
|
||||
}
|
||||
|
||||
// Setting LIMIT:
|
||||
$error = false;
|
||||
if (($conf['max'] ?? false) || ($conf['begin'] ?? false)) {
|
||||
// Finding the total number of records, if used:
|
||||
if (str_contains(strtolower(($conf['begin'] ?? '') . ($conf['max'] ?? '')), 'total')) {
|
||||
$countQueryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($table);
|
||||
$countQueryBuilder->getRestrictions()->removeAll();
|
||||
$countQueryBuilder->count('*')
|
||||
->from($table)
|
||||
->where($queryParts['where']);
|
||||
|
||||
if ($queryParts['groupBy']) {
|
||||
$countQueryBuilder->groupBy(...$queryParts['groupBy']);
|
||||
}
|
||||
|
||||
try {
|
||||
$count = $countQueryBuilder->executeQuery()->fetchOne();
|
||||
if (isset($conf['max'])) {
|
||||
$conf['max'] = str_ireplace('total', $count, (string)$conf['max']);
|
||||
}
|
||||
if (isset($conf['begin'])) {
|
||||
$conf['begin'] = str_ireplace('total', $count, (string)$conf['begin']);
|
||||
}
|
||||
} catch (DBALException $e) {
|
||||
$this->getTimeTracker()->setTSlogMessage($e->getPrevious()->getMessage());
|
||||
$error = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$error) {
|
||||
if (isset($conf['begin']) && $conf['begin'] > 0) {
|
||||
$conf['begin'] = MathUtility::forceIntegerInRange((int)ceil($this->calc($conf['begin'])), 0);
|
||||
$queryBuilder->setFirstResult($conf['begin']);
|
||||
}
|
||||
if (isset($conf['max'])) {
|
||||
$conf['max'] = MathUtility::forceIntegerInRange((int)ceil($this->calc($conf['max'])), 0);
|
||||
$queryBuilder->setMaxResults($conf['max'] ?: 100000);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!$error) {
|
||||
// Setting up tablejoins:
|
||||
if ($conf['join'] ?? false) {
|
||||
$joinParts = QueryHelper::parseJoin($conf['join']);
|
||||
$queryBuilder->join(
|
||||
$table,
|
||||
$joinParts['tableName'],
|
||||
$joinParts['tableAlias'],
|
||||
$joinParts['joinCondition']
|
||||
);
|
||||
} elseif ($conf['leftjoin'] ?? false) {
|
||||
$joinParts = QueryHelper::parseJoin($conf['leftjoin']);
|
||||
$queryBuilder->leftJoin(
|
||||
$table,
|
||||
$joinParts['tableName'],
|
||||
$joinParts['tableAlias'],
|
||||
$joinParts['joinCondition']
|
||||
);
|
||||
} elseif ($conf['rightjoin'] ?? false) {
|
||||
$joinParts = QueryHelper::parseJoin($conf['rightjoin']);
|
||||
$queryBuilder->rightJoin(
|
||||
$table,
|
||||
$joinParts['tableName'],
|
||||
$joinParts['tableAlias'],
|
||||
$joinParts['joinCondition']
|
||||
);
|
||||
}
|
||||
|
||||
// Convert the QueryBuilder object into a SQL statement.
|
||||
$query = $queryBuilder->getSQL();
|
||||
|
||||
// Replace the markers in the queryParts to handle stdWrap enabled properties
|
||||
foreach ($queryMarkers as $marker => $markerValue) {
|
||||
// @todo Ugly hack that needs to be cleaned up, with the current architecture
|
||||
// @todo for exec_Query / getQuery it's the best we can do.
|
||||
$query = str_replace('###' . $marker . '###', (string)$markerValue, $query);
|
||||
}
|
||||
|
||||
return $returnQueryArray ? $this->getQueryArray($queryBuilder) : $query;
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper to transform a QueryBuilder object into a queryParts array that can be used
|
||||
* with exec_SELECT_queryArray
|
||||
*
|
||||
* @return array
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
protected function getQueryArray(QueryBuilder $queryBuilder)
|
||||
{
|
||||
$fromClauses = [];
|
||||
$knownAliases = [];
|
||||
$queryParts = [];
|
||||
|
||||
// Loop through all FROM clauses
|
||||
foreach ($queryBuilder->getQueryPart('from') as $from) {
|
||||
if ($from['alias'] === null) {
|
||||
$tableSql = $from['table'];
|
||||
$tableReference = $from['table'];
|
||||
} else {
|
||||
$tableSql = $from['table'] . ' ' . $from['alias'];
|
||||
$tableReference = $from['alias'];
|
||||
}
|
||||
|
||||
$knownAliases[$tableReference] = true;
|
||||
|
||||
$fromClauses[$tableReference] = $tableSql . $this->getQueryArrayJoinHelper(
|
||||
$tableReference,
|
||||
$queryBuilder->getQueryPart('join'),
|
||||
$knownAliases
|
||||
);
|
||||
}
|
||||
|
||||
$queryParts['SELECT'] = implode(', ', $queryBuilder->getQueryPart('select'));
|
||||
$queryParts['FROM'] = implode(', ', $fromClauses);
|
||||
$queryParts['WHERE'] = (string)$queryBuilder->getQueryPart('where') ?: '';
|
||||
$queryParts['GROUPBY'] = implode(', ', $queryBuilder->getQueryPart('groupBy'));
|
||||
$queryParts['ORDERBY'] = implode(', ', $queryBuilder->getQueryPart('orderBy'));
|
||||
if ($queryBuilder->getFirstResult() > 0) {
|
||||
$queryParts['LIMIT'] = $queryBuilder->getFirstResult() . ',' . $queryBuilder->getMaxResults();
|
||||
} elseif ($queryBuilder->getMaxResults() > 0) {
|
||||
$queryParts['LIMIT'] = $queryBuilder->getMaxResults();
|
||||
}
|
||||
|
||||
return $queryParts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper to transform the QueryBuilder join part into a SQL fragment.
|
||||
*
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
protected function getQueryArrayJoinHelper(string $fromAlias, array $joinParts, array &$knownAliases): string
|
||||
{
|
||||
$sql = '';
|
||||
|
||||
if (isset($joinParts['join'][$fromAlias])) {
|
||||
foreach ($joinParts['join'][$fromAlias] as $join) {
|
||||
if (array_key_exists($join['joinAlias'], $knownAliases)) {
|
||||
throw new \RuntimeException(
|
||||
'Non unique join alias: "' . $join['joinAlias'] . '" found.',
|
||||
1472748872
|
||||
);
|
||||
}
|
||||
$sql .= ' ' . strtoupper($join['joinType'])
|
||||
. ' JOIN ' . $join['joinTable'] . ' ' . $join['joinAlias']
|
||||
. ' ON ' . ((string)$join['joinCondition']);
|
||||
$knownAliases[$join['joinAlias']] = true;
|
||||
}
|
||||
|
||||
foreach ($joinParts['join'][$fromAlias] as $join) {
|
||||
$sql .= $this->getQueryArrayJoinHelper($join['joinAlias'], $joinParts, $knownAliases);
|
||||
}
|
||||
}
|
||||
|
||||
return $sql;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds list of marker values for handling PDO-like parameter markers in select parts.
|
||||
* Marker values support stdWrap functionality thus allowing a way to use stdWrap functionality in various
|
||||
* properties of 'select' AND prevents SQL-injection problems by quoting and escaping of numeric values, strings,
|
||||
* NULL values and comma separated lists.
|
||||
*
|
||||
* @param string $table Table to select records from
|
||||
* @param array $conf Select part of CONTENT definition
|
||||
* @return array List of values to replace markers with
|
||||
* @internal
|
||||
* @see getQuery()
|
||||
*/
|
||||
public function getQueryMarkers(string $table, array $conf): array
|
||||
{
|
||||
if (!isset($conf['markers.']) || !is_array($conf['markers.'])) {
|
||||
return [];
|
||||
}
|
||||
// Parse markers and prepare their values
|
||||
$connection = GeneralUtility::makeInstance(ConnectionPool::class)->getConnectionForTable($table);
|
||||
$markerValues = [];
|
||||
foreach ($conf['markers.'] as $dottedMarker => $dummy) {
|
||||
$marker = rtrim($dottedMarker, '.');
|
||||
if ($dottedMarker != $marker . '.') {
|
||||
continue;
|
||||
}
|
||||
// Parse definition
|
||||
// todo else value is always null
|
||||
$tempValue = isset($conf['markers.'][$dottedMarker])
|
||||
? $this->cObj->stdWrap($conf['markers.'][$dottedMarker]['value'] ?? '', $conf['markers.'][$dottedMarker])
|
||||
: $conf['markers.'][$dottedMarker]['value'];
|
||||
// Quote/escape if needed
|
||||
if (is_numeric($tempValue)) {
|
||||
if ((int)$tempValue == $tempValue) {
|
||||
// Handle integer
|
||||
$markerValues[$marker] = (int)$tempValue;
|
||||
} else {
|
||||
// Handle float
|
||||
$markerValues[$marker] = (float)$tempValue;
|
||||
}
|
||||
} elseif ($tempValue === null) {
|
||||
// It represents NULL
|
||||
$markerValues[$marker] = 'NULL';
|
||||
} elseif (!empty($conf['markers.'][$dottedMarker]['commaSeparatedList'])) {
|
||||
// See if it is really a comma separated list of values
|
||||
$explodeValues = GeneralUtility::trimExplode(',', $tempValue);
|
||||
if (count($explodeValues) > 1) {
|
||||
// Handle each element of list separately
|
||||
$tempArray = [];
|
||||
foreach ($explodeValues as $listValue) {
|
||||
if (is_numeric($listValue)) {
|
||||
if ((int)$listValue == $listValue) {
|
||||
$tempArray[] = (int)$listValue;
|
||||
} else {
|
||||
$tempArray[] = (float)$listValue;
|
||||
}
|
||||
} else {
|
||||
// If quoted, remove quotes before
|
||||
// escaping.
|
||||
if (preg_match('/^\'([^\']*)\'$/', $listValue, $matches)) {
|
||||
$listValue = $matches[1];
|
||||
} elseif (preg_match('/^\\"([^\\"]*)\\"$/', $listValue, $matches)) {
|
||||
$listValue = $matches[1];
|
||||
}
|
||||
$tempArray[] = $connection->quote($listValue);
|
||||
}
|
||||
}
|
||||
$markerValues[$marker] = implode(',', $tempArray);
|
||||
} else {
|
||||
// Handle remaining values as string
|
||||
$markerValues[$marker] = $connection->quote($tempValue);
|
||||
}
|
||||
} else {
|
||||
// Handle remaining values as string
|
||||
$markerValues[$marker] = $connection->quote($tempValue);
|
||||
}
|
||||
}
|
||||
return $markerValues;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function for getQuery(), creating the WHERE clause of the SELECT query
|
||||
*
|
||||
* @param string $table The table name
|
||||
* @param array $conf The TypoScript configuration properties
|
||||
* @return array Associative array containing the prepared data for WHERE, ORDER BY and GROUP BY fragments
|
||||
* @throws \InvalidArgumentException
|
||||
* @see getQuery()
|
||||
*/
|
||||
protected function getQueryConstraints(string $table, array $conf): array
|
||||
{
|
||||
// Init:
|
||||
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($table);
|
||||
$expressionBuilder = $queryBuilder->expr();
|
||||
$tsfe = $this->getTypoScriptFrontendController();
|
||||
$constraints = [];
|
||||
$pid_uid_flag = 0;
|
||||
$enableFieldsIgnore = [];
|
||||
$queryParts = [
|
||||
'where' => null,
|
||||
'groupBy' => null,
|
||||
'orderBy' => null,
|
||||
];
|
||||
|
||||
$isInWorkspace = GeneralUtility::makeInstance(Context::class)->getPropertyFromAspect('workspace', 'isOffline');
|
||||
$considerMovePointers = (
|
||||
$isInWorkspace && $table !== 'pages'
|
||||
&& !empty($GLOBALS['TCA'][$table]['ctrl']['versioningWS'])
|
||||
);
|
||||
|
||||
if (trim($conf['uidInList'] ?? '')) {
|
||||
$listArr = GeneralUtility::intExplode(',', str_replace('this', (string)$tsfe->contentPid, $conf['uidInList']));
|
||||
|
||||
// If moved records shall be considered, select via t3ver_oid
|
||||
if ($considerMovePointers) {
|
||||
$constraints[] = (string)$expressionBuilder->orX(
|
||||
$expressionBuilder->in($table . '.uid', $listArr),
|
||||
$expressionBuilder->andX(
|
||||
$expressionBuilder->eq(
|
||||
$table . '.t3ver_state',
|
||||
(int)(string)VersionState::cast(VersionState::MOVE_POINTER)
|
||||
),
|
||||
$expressionBuilder->in($table . '.t3ver_oid', $listArr)
|
||||
)
|
||||
);
|
||||
} else {
|
||||
$constraints[] = (string)$expressionBuilder->in($table . '.uid', $listArr);
|
||||
}
|
||||
$pid_uid_flag++;
|
||||
}
|
||||
|
||||
// Static_* tables are allowed to be fetched from root page
|
||||
if (strpos($table, 'static_') === 0) {
|
||||
$pid_uid_flag++;
|
||||
}
|
||||
|
||||
if (trim($conf['pidInList'])) {
|
||||
$listArr = GeneralUtility::intExplode(',', str_replace('this', (string)$tsfe->contentPid, $conf['pidInList']));
|
||||
// Removes all pages which are not visible for the user!
|
||||
$listArr = $this->checkPidArray($listArr);
|
||||
if (GeneralUtility::inList($conf['pidInList'], 'root')) {
|
||||
$listArr[] = 0;
|
||||
}
|
||||
if (GeneralUtility::inList($conf['pidInList'], '-1')) {
|
||||
$listArr[] = -1;
|
||||
$enableFieldsIgnore['pid'] = true;
|
||||
}
|
||||
if (!empty($listArr)) {
|
||||
$constraints[] = $expressionBuilder->in($table . '.pid', array_map('intval', $listArr));
|
||||
$pid_uid_flag++;
|
||||
} else {
|
||||
// If not uid and not pid then uid is set to 0 - which results in nothing!!
|
||||
$pid_uid_flag = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// If not uid and not pid then uid is set to 0 - which results in nothing!!
|
||||
if (!$pid_uid_flag && trim($conf['pidInList'] ?? '') != 'ignore') {
|
||||
$constraints[] = $expressionBuilder->eq($table . '.uid', 0);
|
||||
}
|
||||
|
||||
$where = trim((string)$this->cObj->stdWrapValue('where', $conf ?? []));
|
||||
if ($where) {
|
||||
$constraints[] = QueryHelper::stripLogicalOperatorPrefix($where);
|
||||
}
|
||||
|
||||
// Check if the default language should be fetched (= doing overlays), or if only the records of a language should be fetched
|
||||
// but only do this for TCA tables that have languages enabled
|
||||
$languageConstraint = $this->getLanguageRestriction($expressionBuilder, $table, $conf, GeneralUtility::makeInstance(Context::class));
|
||||
if ($languageConstraint !== null) {
|
||||
$constraints[] = $languageConstraint;
|
||||
}
|
||||
|
||||
// Enablefields
|
||||
if ($table === 'pages') {
|
||||
$constraints[] = QueryHelper::stripLogicalOperatorPrefix($tsfe->sys_page->where_hid_del);
|
||||
$constraints[] = QueryHelper::stripLogicalOperatorPrefix($tsfe->sys_page->where_groupAccess);
|
||||
} else {
|
||||
$constraints[] = QueryHelper::stripLogicalOperatorPrefix($tsfe->sys_page->enableFields($table, -1, $enableFieldsIgnore));
|
||||
}
|
||||
|
||||
// MAKE WHERE:
|
||||
if (count($constraints) !== 0) {
|
||||
$queryParts['where'] = $expressionBuilder->andX(...$constraints);
|
||||
}
|
||||
// GROUP BY
|
||||
$groupBy = trim((string)$this->cObj->stdWrapValue('groupBy', $conf ?? []));
|
||||
if ($groupBy) {
|
||||
$queryParts['groupBy'] = QueryHelper::parseGroupBy($groupBy);
|
||||
}
|
||||
|
||||
// ORDER BY
|
||||
$orderByString = trim((string)$this->cObj->stdWrapValue('orderBy', $conf ?? []));
|
||||
if ($orderByString) {
|
||||
$queryParts['orderBy'] = QueryHelper::parseOrderBy($orderByString);
|
||||
}
|
||||
|
||||
// Return result:
|
||||
return $queryParts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes Page UID numbers from the input array which are not available due to enableFields() or the list of bad doktype numbers ($this->checkPid_badDoktypeList)
|
||||
*
|
||||
* @param int[] $pageIds Array of Page UID numbers for select and for which pages with enablefields and bad doktypes should be removed.
|
||||
* @return array Returns the array of remaining page UID numbers
|
||||
* @internal
|
||||
*/
|
||||
public function checkPidArray(array $pageIds): array
|
||||
{
|
||||
if (empty($pageIds)) {
|
||||
return [];
|
||||
}
|
||||
$restrictionContainer = GeneralUtility::makeInstance(FrontendRestrictionContainer::class);
|
||||
$restrictionContainer->add(GeneralUtility::makeInstance(
|
||||
DocumentTypeExclusionRestriction::class,
|
||||
GeneralUtility::intExplode(',', (string)$this->cObj->checkPid_badDoktypeList, true)
|
||||
));
|
||||
return $this->getTypoScriptFrontendController()->sys_page->filterAccessiblePageIds($pageIds, $restrictionContainer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds parts to the WHERE clause that are related to language.
|
||||
* This only works on TCA tables which have the [ctrl][languageField] field set or if they
|
||||
* have select.languageField = my_language_field set explicitly.
|
||||
*
|
||||
* It is also possible to disable the language restriction for a query by using select.languageField = 0,
|
||||
* if select.languageField is not explicitly set, the TCA default values are taken.
|
||||
*
|
||||
* If the table is "localizeable" (= any of the criteria above is met), then the DB query is restricted:
|
||||
*
|
||||
* If the current language aspect has overlays enabled, then the only records with language "0" or "-1" are
|
||||
* fetched (the overlays are taken care of later-on).
|
||||
* if the current language has overlays but also records without localization-parent (free mode) available,
|
||||
* then these are fetched as well. This can explicitly set via select.includeRecordsWithoutDefaultTranslation = 1
|
||||
* which overrules the overlayType within the language aspect.
|
||||
*
|
||||
* If the language aspect has NO overlays enabled, it behaves as in "free mode" (= only fetch the records
|
||||
* for the current language.
|
||||
*
|
||||
* @param ExpressionBuilder $expressionBuilder
|
||||
* @param string $table
|
||||
* @param array $conf
|
||||
* @param Context $context
|
||||
* @return string|\TYPO3\CMS\Core\Database\Query\Expression\CompositeExpression|null
|
||||
* @throws \TYPO3\CMS\Core\Context\Exception\AspectNotFoundException
|
||||
*/
|
||||
protected function getLanguageRestriction(ExpressionBuilder $expressionBuilder, string $table, array $conf, Context $context)
|
||||
{
|
||||
$languageField = '';
|
||||
$localizationParentField = $GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField'] ?? null;
|
||||
// Check if the table is translatable, and set the language field by default from the TCA information
|
||||
if (!empty($conf['languageField']) || !isset($conf['languageField'])) {
|
||||
if (isset($conf['languageField']) && !empty($GLOBALS['TCA'][$table]['columns'][$conf['languageField']])) {
|
||||
$languageField = $conf['languageField'];
|
||||
} elseif (!empty($GLOBALS['TCA'][$table]['ctrl']['languageField']) && !empty($localizationParentField)) {
|
||||
$languageField = $table . '.' . $GLOBALS['TCA'][$table]['ctrl']['languageField'];
|
||||
}
|
||||
}
|
||||
|
||||
// No language restriction enabled explicitly or available via TCA
|
||||
if (empty($languageField)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/** @var LanguageAspect $languageAspect */
|
||||
$languageAspect = $context->getAspect('language');
|
||||
if ($languageAspect->doOverlays() && !empty($localizationParentField)) {
|
||||
// Sys language content is set to zero/-1 - and it is expected that whatever routine processes the output will
|
||||
// OVERLAY the records with localized versions!
|
||||
$languageQuery = $expressionBuilder->in($languageField, [0, -1]);
|
||||
// Use this option to include records that don't have a default language counterpart ("free mode")
|
||||
// (originalpointerfield is 0 and the language field contains the requested language)
|
||||
if (isset($conf['includeRecordsWithoutDefaultTranslation']) || !empty($conf['includeRecordsWithoutDefaultTranslation.'])) {
|
||||
$includeRecordsWithoutDefaultTranslation = isset($conf['includeRecordsWithoutDefaultTranslation.'])
|
||||
? $this->cObj->stdWrap($conf['includeRecordsWithoutDefaultTranslation'], $conf['includeRecordsWithoutDefaultTranslation.'])
|
||||
: $conf['includeRecordsWithoutDefaultTranslation'];
|
||||
$includeRecordsWithoutDefaultTranslation = trim($includeRecordsWithoutDefaultTranslation) !== '';
|
||||
} else {
|
||||
// Option was not explicitly set, check what's in for the language overlay type.
|
||||
$includeRecordsWithoutDefaultTranslation = $languageAspect->getOverlayType() === $languageAspect::OVERLAYS_ON_WITH_FLOATING;
|
||||
}
|
||||
if ($includeRecordsWithoutDefaultTranslation) {
|
||||
$languageQuery = $expressionBuilder->orX(
|
||||
$languageQuery,
|
||||
$expressionBuilder->andX(
|
||||
$expressionBuilder->eq($table . '.' . $localizationParentField, 0),
|
||||
$expressionBuilder->eq($languageField, $languageAspect->getContentId())
|
||||
)
|
||||
);
|
||||
}
|
||||
return $languageQuery;
|
||||
}
|
||||
// No overlays = only fetch records given for the requested language and "all languages"
|
||||
return $expressionBuilder->in($languageField, [$languageAspect->getContentId(), -1]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function for getQuery, sanitizing the select part
|
||||
*
|
||||
* This functions checks if the necessary fields are part of the select
|
||||
* and adds them if necessary.
|
||||
*
|
||||
* @param string $selectPart Select part
|
||||
* @param string $table Table to select from
|
||||
* @return string Sanitized select part
|
||||
* @internal
|
||||
* @see getQuery
|
||||
*/
|
||||
protected function sanitizeSelectPart(string $selectPart, string $table): string
|
||||
{
|
||||
$connection = GeneralUtility::makeInstance(ConnectionPool::class)->getConnectionForTable($table);
|
||||
|
||||
// Pattern matching parts
|
||||
$matchStart = '/(^\\s*|,\\s*|' . $table . '\\.)';
|
||||
$matchEnd = '(\\s*,|\\s*$)/';
|
||||
$necessaryFields = ['uid', 'pid'];
|
||||
$wsFields = ['t3ver_state'];
|
||||
if (isset($GLOBALS['TCA'][$table]) && !preg_match($matchStart . '\\*' . $matchEnd, $selectPart) && !preg_match('/(count|max|min|avg|sum)\\([^\\)]+\\)|distinct/i', $selectPart)) {
|
||||
foreach ($necessaryFields as $field) {
|
||||
$match = $matchStart . $field . $matchEnd;
|
||||
if (!preg_match($match, $selectPart)) {
|
||||
$selectPart .= ', ' . $connection->quoteIdentifier($table . '.' . $field) . ' AS ' . $connection->quoteIdentifier($field);
|
||||
}
|
||||
}
|
||||
if ($GLOBALS['TCA'][$table]['ctrl']['versioningWS'] ?? false) {
|
||||
foreach ($wsFields as $field) {
|
||||
$match = $matchStart . $field . $matchEnd;
|
||||
if (!preg_match($match, $selectPart)) {
|
||||
$selectPart .= ', ' . $connection->quoteIdentifier($table . '.' . $field) . ' AS ' . $connection->quoteIdentifier($field);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return $selectPart;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs basic mathematical evaluation of the input string. Does NOT take parenthesis and operator precedence into account! (for that, see \TYPO3\CMS\Core\Utility\MathUtility::calculateWithPriorityToAdditionAndSubtraction())
|
||||
*
|
||||
* @param string $val The string to evaluate. Example: "3+4*10/5" will generate "35". Only integer numbers can be used.
|
||||
* @return int The result (might be a float if you did a division of the numbers).
|
||||
* @see \TYPO3\CMS\Core\Utility\MathUtility::calculateWithPriorityToAdditionAndSubtraction()
|
||||
*/
|
||||
public function calc($val)
|
||||
{
|
||||
$parts = GeneralUtility::splitCalc($val, '+-*/');
|
||||
$value = 0;
|
||||
foreach ($parts as $part) {
|
||||
$theVal = $part[1];
|
||||
$sign = $part[0];
|
||||
if ((string)(int)$theVal === (string)$theVal) {
|
||||
$theVal = (int)$theVal;
|
||||
} else {
|
||||
$theVal = 0;
|
||||
}
|
||||
if ($sign === '-') {
|
||||
$value -= $theVal;
|
||||
}
|
||||
if ($sign === '+') {
|
||||
$value += $theVal;
|
||||
}
|
||||
if ($sign === '/') {
|
||||
if ((int)$theVal) {
|
||||
$value /= (int)$theVal;
|
||||
}
|
||||
}
|
||||
if ($sign === '*') {
|
||||
$value *= $theVal;
|
||||
}
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return TimeTracker
|
||||
*/
|
||||
protected function getTimeTracker()
|
||||
{
|
||||
return GeneralUtility::makeInstance(TimeTracker::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current BE user.
|
||||
*
|
||||
* @return FrontendBackendUserAuthentication
|
||||
*/
|
||||
protected function getFrontendBackendUser()
|
||||
{
|
||||
return $GLOBALS['BE_USER'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return TypoScriptFrontendController|null
|
||||
*/
|
||||
protected function getTypoScriptFrontendController()
|
||||
{
|
||||
return $GLOBALS['TSFE'] ?? null;
|
||||
}
|
||||
}
|
||||
18
Classes/EventListener/CssMerger.php
Executable file → Normal file
18
Classes/EventListener/CssMerger.php
Executable file → Normal file
@ -1,19 +1,7 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is developed by evoWeb.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
namespace Evoweb\EwBase\EventListener;
|
||||
|
||||
use TYPO3\CMS\Core\Attribute\AsEventListener;
|
||||
use TYPO3\CMS\Core\Configuration\ExtensionConfiguration;
|
||||
use TYPO3\CMS\Core\Page\AssetCollector;
|
||||
use TYPO3\CMS\Core\Page\Event\BeforeStylesheetsRenderingEvent;
|
||||
@ -22,9 +10,10 @@ use TYPO3\CMS\Core\Utility\PathUtility;
|
||||
|
||||
class CssMerger
|
||||
{
|
||||
public function __construct(protected ExtensionConfiguration $extensionConfiguration) {}
|
||||
public function __construct(protected ExtensionConfiguration $extensionConfiguration)
|
||||
{
|
||||
}
|
||||
|
||||
#[AsEventListener('evoweb-ew-base-beforestylesheets', BeforeStylesheetsRenderingEvent::class)]
|
||||
public function __invoke(BeforeStylesheetsRenderingEvent $event): void
|
||||
{
|
||||
if ($event->isInline() && $event->isPriority()) {
|
||||
@ -45,7 +34,6 @@ class CssMerger
|
||||
$assetCollector->addInlineStyleSheet('ew_base', $styles, [], ['priority' => true]);
|
||||
} else {
|
||||
$temporaryFile = GeneralUtility::writeStyleSheetContentToTemporaryFile($styles);
|
||||
// @extensionScannerIgnoreLine
|
||||
$assetCollector->addStyleSheet('combined_styles', $temporaryFile);
|
||||
}
|
||||
}
|
||||
|
||||
25
Classes/EventListener/IsContentUsedOnPageLayout.php
Normal file
25
Classes/EventListener/IsContentUsedOnPageLayout.php
Normal file
@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
namespace Evoweb\EwBase\EventListener;
|
||||
|
||||
use TYPO3\CMS\Backend\ViEvoweb\Event\IsContentUsedOnPageLayoutEvent;
|
||||
|
||||
class IsContentUsedOnPageLayout
|
||||
{
|
||||
public function __invoke(IsContentUsedOnPageLayoutEvent $event): void
|
||||
{
|
||||
$event->setUsed($event->isRecordUsed() || $this->findCTypeBegin($event->getRecord()['CType']));
|
||||
}
|
||||
|
||||
public function findCTypeBegin($cType): bool
|
||||
{
|
||||
$found = false;
|
||||
foreach ($GLOBALS['TYPO3_CONF_VARS']['EXTENSIONS']['ew_base']['ContentUsedStrings'] ?? [] as $search) {
|
||||
if (strpos($cType, $search) !== false) {
|
||||
$found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return $found;
|
||||
}
|
||||
}
|
||||
13
Classes/EventListener/JsMerger.php
Executable file → Normal file
13
Classes/EventListener/JsMerger.php
Executable file → Normal file
@ -1,19 +1,7 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is developed by evoWeb.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
namespace Evoweb\EwBase\EventListener;
|
||||
|
||||
use TYPO3\CMS\Core\Attribute\AsEventListener;
|
||||
use TYPO3\CMS\Core\Page\AssetCollector;
|
||||
use TYPO3\CMS\Core\Page\Event\BeforeJavaScriptsRenderingEvent;
|
||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||
@ -21,7 +9,6 @@ use TYPO3\CMS\Core\Utility\PathUtility;
|
||||
|
||||
class JsMerger
|
||||
{
|
||||
#[AsEventListener('evoweb-ew-base-beforejavascript', BeforeJavaScriptsRenderingEvent::class)]
|
||||
public function __invoke(BeforeJavaScriptsRenderingEvent $event): void
|
||||
{
|
||||
if ($event->isInline() && $event->isPriority()) {
|
||||
|
||||
67
Classes/Form/Element/PickColorFromImage.php
Executable file → Normal file
67
Classes/Form/Element/PickColorFromImage.php
Executable file → Normal file
@ -2,6 +2,8 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Evoweb\EwBase\Form\Element;
|
||||
|
||||
/*
|
||||
* This file is developed by evoWeb.
|
||||
*
|
||||
@ -13,14 +15,8 @@ declare(strict_types=1);
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Evoweb\EwBase\Form\Element;
|
||||
|
||||
use Psr\EventDispatcher\EventDispatcherInterface;
|
||||
use TYPO3\CMS\Backend\Form\Element\AbstractFormElement;
|
||||
use TYPO3\CMS\Backend\Form\Event\ModifyImageManipulationPreviewUrlEvent;
|
||||
use TYPO3\CMS\Backend\Routing\UriBuilder;
|
||||
use TYPO3\CMS\Backend\View\BackendViewFactory;
|
||||
use TYPO3\CMS\Core\Crypto\HashService;
|
||||
use TYPO3\CMS\Core\Imaging\ImageManipulation\Area;
|
||||
use TYPO3\CMS\Core\Imaging\ImageManipulation\CropVariantCollection;
|
||||
use TYPO3\CMS\Core\Imaging\ImageManipulation\InvalidConfigurationException;
|
||||
@ -34,8 +30,6 @@ use TYPO3\CMS\Core\Utility\StringUtility;
|
||||
|
||||
class PickColorFromImage extends AbstractFormElement
|
||||
{
|
||||
private string $wizardRouteName = 'ajax_wizard_image_manipulation';
|
||||
|
||||
/**
|
||||
* Default element configuration
|
||||
*/
|
||||
@ -114,11 +108,9 @@ class PickColorFromImage extends AbstractFormElement
|
||||
|
||||
public function __construct(
|
||||
private readonly BackendViewFactory $backendViewFactory,
|
||||
private readonly UriBuilder $uriBuilder,
|
||||
private readonly EventDispatcherInterface $eventDispatcher,
|
||||
private readonly ResourceFactory $resourceFactory,
|
||||
private readonly HashService $hashService,
|
||||
) {}
|
||||
) {
|
||||
}
|
||||
|
||||
public function render(): array
|
||||
{
|
||||
@ -146,6 +138,14 @@ class PickColorFromImage extends AbstractFormElement
|
||||
$fieldWizardHtml = $fieldWizardResult['html'];
|
||||
$resultArray = $this->mergeChildReturnIntoExistingResult($resultArray, $fieldWizardResult, false);
|
||||
|
||||
$width = $this->formMaxWidth(
|
||||
MathUtility::forceIntegerInRange(
|
||||
$config['size'] ?? $this->defaultInputWidth,
|
||||
$this->minimumInputWidth,
|
||||
$this->maxInputWidth
|
||||
)
|
||||
);
|
||||
|
||||
$arguments = [
|
||||
'fieldInformation' => $fieldInformationHtml,
|
||||
'fieldControl' => $fieldControlHtml,
|
||||
@ -164,15 +164,12 @@ class PickColorFromImage extends AbstractFormElement
|
||||
'validation' => '[]',
|
||||
],
|
||||
'config' => $config,
|
||||
'wizardUri' => $this->getWizardUri(),
|
||||
'wizardPayload' => json_encode($this->getWizardPayload($config['cropVariants'], $file)),
|
||||
'previewUrl' => $this->eventDispatcher->dispatch(
|
||||
new ModifyImageManipulationPreviewUrlEvent($this->data['databaseRow'], $config, $file)
|
||||
)->getPreviewUrl(),
|
||||
'width' => $width,
|
||||
];
|
||||
|
||||
if ($arguments['isAllowedFileExtension']) {
|
||||
$fieldId = StringUtility::getUniqueId('formengine-color-');
|
||||
|
||||
$resultArray['stylesheetFiles'][] =
|
||||
'EXT:ew_base/Resources/Public/JavaScript/form-engine/element/pick-color-from-image.css';
|
||||
$resultArray['javaScriptModules'][] = JavaScriptModuleInstruction::create(
|
||||
@ -189,6 +186,9 @@ class PickColorFromImage extends AbstractFormElement
|
||||
}
|
||||
}
|
||||
$view = $this->backendViewFactory->create($this->data['request']);
|
||||
$templatePaths = $view->getRenderingContext()->getTemplatePaths();
|
||||
$templatePaths->setTemplateRootPaths(['EXT:ew_base/Resources/Private/Templates']);
|
||||
$templatePaths->setPartialRootPaths(['EXT:ew_base/Resources/Private/Partials']);
|
||||
$view->assignMultiple($arguments);
|
||||
$resultArray['html'] = $view->render('Form/ImageManipulationElement');
|
||||
|
||||
@ -211,19 +211,12 @@ class PickColorFromImage extends AbstractFormElement
|
||||
return $file;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws InvalidConfigurationException
|
||||
*/
|
||||
protected function populateConfiguration(array $baseConfiguration): array
|
||||
{
|
||||
$defaultConfig = self::$defaultConfig;
|
||||
|
||||
// If ratios are set do not add default options
|
||||
if (isset($baseConfiguration['cropVariants'])) {
|
||||
unset($defaultConfig['cropVariants']);
|
||||
}
|
||||
|
||||
$config = array_replace_recursive($defaultConfig, $baseConfiguration);
|
||||
$imageConfig = $this->data['processedTca']['columns'][$config['imageField']];
|
||||
$config['cropVariants'] = $imageConfig['config']['cropVariants'] ?? $defaultConfig['cropVariants'];
|
||||
|
||||
if (!is_array($config['cropVariants'])) {
|
||||
throw new InvalidConfigurationException('Crop variants configuration must be an array', 1485377267);
|
||||
@ -235,7 +228,7 @@ class PickColorFromImage extends AbstractFormElement
|
||||
$cropVariant['allowedAspectRatios'] = array_filter(
|
||||
$cropVariant['allowedAspectRatios'] ?? [],
|
||||
static function ($aspectRatio) {
|
||||
return !($aspectRatio['disabled'] ?? false);
|
||||
return !(bool)($aspectRatio['disabled'] ?? false);
|
||||
}
|
||||
);
|
||||
|
||||
@ -261,8 +254,8 @@ class PickColorFromImage extends AbstractFormElement
|
||||
|
||||
$config['cropVariants'] = $cropVariants;
|
||||
|
||||
// By default, we allow all image extensions that can be handled by the GFX functionality
|
||||
$config['allowedExtensions'] ??= $GLOBALS['TYPO3_CONF_VARS']['GFX']['imagefile_ext'];
|
||||
|
||||
return $config;
|
||||
}
|
||||
|
||||
@ -280,22 +273,4 @@ class PickColorFromImage extends AbstractFormElement
|
||||
);
|
||||
return $config;
|
||||
}
|
||||
|
||||
protected function getWizardUri(): string
|
||||
{
|
||||
return (string)$this->uriBuilder->buildUriFromRoute($this->wizardRouteName);
|
||||
}
|
||||
|
||||
protected function getWizardPayload(array $cropVariants, File $image): array
|
||||
{
|
||||
$uriArguments = [];
|
||||
$arguments = [
|
||||
'cropVariants' => $cropVariants,
|
||||
'image' => $image->getUid(),
|
||||
];
|
||||
$uriArguments['arguments'] = json_encode($arguments);
|
||||
$uriArguments['signature'] = $this->hashService->hmac((string)($uriArguments['arguments']), $this->wizardRouteName);
|
||||
|
||||
return $uriArguments;
|
||||
}
|
||||
}
|
||||
|
||||
34
Classes/Hooks/PageLayoutView.php
Normal file
34
Classes/Hooks/PageLayoutView.php
Normal file
@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
namespace Evoweb\EwBase\Hooks;
|
||||
|
||||
/*
|
||||
* This file is developed by evoWeb.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
class PageLayoutView
|
||||
{
|
||||
public function contentIsUsed(array $params): bool
|
||||
{
|
||||
return $params['used'] || $this->findCTypeBegin($params['record']['CType']);
|
||||
}
|
||||
|
||||
public function findCTypeBegin($cType): bool
|
||||
{
|
||||
$found = false;
|
||||
foreach ($GLOBALS['TYPO3_CONF_VARS']['EXTENSIONS']['ew_base']['ContentUsedStrings'] ?? [] as $search) {
|
||||
if (str_contains($cType, $search)) {
|
||||
$found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return $found;
|
||||
}
|
||||
}
|
||||
9
Classes/ToolbarItems/ReleaseToolbarItem.php
Executable file → Normal file
9
Classes/ToolbarItems/ReleaseToolbarItem.php
Executable file → Normal file
@ -1,5 +1,7 @@
|
||||
<?php
|
||||
|
||||
namespace Evoweb\EwBase\ToolbarItems;
|
||||
|
||||
/*
|
||||
* This file is developed by evoWeb.
|
||||
*
|
||||
@ -11,8 +13,6 @@
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Evoweb\EwBase\ToolbarItems;
|
||||
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use TYPO3\CMS\Backend\Toolbar\RequestAwareToolbarItemInterface;
|
||||
use TYPO3\CMS\Backend\Toolbar\ToolbarItemInterface;
|
||||
@ -25,7 +25,10 @@ class ReleaseToolbarItem implements ToolbarItemInterface, RequestAwareToolbarIte
|
||||
{
|
||||
private ServerRequestInterface $request;
|
||||
|
||||
public function __construct(private readonly BackendViewFactory $backendViewFactory) {}
|
||||
public function __construct(
|
||||
private readonly BackendViewFactory $backendViewFactory,
|
||||
) {
|
||||
}
|
||||
|
||||
public function setRequest(ServerRequestInterface $request): void
|
||||
{
|
||||
|
||||
96
Classes/Updates/GridelementsToContainerMigration.php
Normal file
96
Classes/Updates/GridelementsToContainerMigration.php
Normal file
@ -0,0 +1,96 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Evoweb\EwBase\Updates;
|
||||
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Psr\Log\LogLevel;
|
||||
use TYPO3\CMS\Core\Database\ConnectionPool;
|
||||
use TYPO3\CMS\Core\Database\Query\QueryBuilder;
|
||||
use TYPO3\CMS\Core\Database\Query\Restriction\EndTimeRestriction;
|
||||
use TYPO3\CMS\Core\Database\Query\Restriction\HiddenRestriction;
|
||||
use TYPO3\CMS\Core\Database\Query\Restriction\StartTimeRestriction;
|
||||
use TYPO3\CMS\Core\Log\LogManager;
|
||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||
use TYPO3\CMS\Install\Attribute\UpgradeWizard;
|
||||
use TYPO3\CMS\Install\Updates\DatabaseUpdatedPrerequisite;
|
||||
use TYPO3\CMS\Install\Updates\UpgradeWizardInterface;
|
||||
|
||||
/**
|
||||
* Migrate gridelements elements to container elements
|
||||
*/
|
||||
#[UpgradeWizard('gridelementsToContainer')]
|
||||
class GridelementsToContainerMigration implements UpgradeWizardInterface
|
||||
{
|
||||
private const TABLE_NAME = 'tt_content';
|
||||
|
||||
protected LoggerInterface $logger;
|
||||
|
||||
public function __construct(
|
||||
protected GridelementsToContainerService $service,
|
||||
protected LogManager $logManager,
|
||||
) {
|
||||
$this->logger = $logManager->getLogger(self::class);
|
||||
}
|
||||
|
||||
public function getTitle(): string
|
||||
{
|
||||
return 'Migrate gridelements to container';
|
||||
}
|
||||
|
||||
public function getDescription(): string
|
||||
{
|
||||
return 'Migrates content elements that are type gridelements to corresponding container elements';
|
||||
}
|
||||
|
||||
public function getPrerequisites(): array
|
||||
{
|
||||
return [
|
||||
DatabaseUpdatedPrerequisite::class
|
||||
];
|
||||
}
|
||||
|
||||
public function updateNecessary(): bool
|
||||
{
|
||||
return $this->hasRecordsToUpdate();
|
||||
}
|
||||
|
||||
public function executeUpdate(): bool
|
||||
{
|
||||
$updateSuccessful = true;
|
||||
try {
|
||||
$this->service->migrate();
|
||||
} catch (\Exception $exception) {
|
||||
$this->logger->log(LogLevel::ERROR, $exception->getMessage());
|
||||
$updateSuccessful = false;
|
||||
}
|
||||
|
||||
return $updateSuccessful;
|
||||
}
|
||||
|
||||
protected function hasRecordsToUpdate(): bool
|
||||
{
|
||||
return (bool)$this->getPreparedQueryBuilder()->count('uid')->executeQuery()->fetchOne();
|
||||
}
|
||||
|
||||
protected function getPreparedQueryBuilder(): QueryBuilder
|
||||
{
|
||||
$queryBuilder = $this->getConnectionPool()->getQueryBuilderForTable(self::TABLE_NAME);
|
||||
$queryBuilder->getRestrictions()
|
||||
->removeByType(HiddenRestriction::class)
|
||||
->removeByType(StartTimeRestriction::class)
|
||||
->removeByType(EndTimeRestriction::class);
|
||||
$queryBuilder
|
||||
->from(self::TABLE_NAME)
|
||||
->where(
|
||||
$queryBuilder->expr()->eq('CType', $queryBuilder->createNamedParameter('gridelements_pi1'))
|
||||
);
|
||||
return $queryBuilder;
|
||||
}
|
||||
|
||||
protected function getConnectionPool(): ConnectionPool
|
||||
{
|
||||
return GeneralUtility::makeInstance(ConnectionPool::class);
|
||||
}
|
||||
}
|
||||
268
Classes/Updates/GridelementsToContainerService.php
Normal file
268
Classes/Updates/GridelementsToContainerService.php
Normal file
@ -0,0 +1,268 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Evoweb\EwBase\Updates;
|
||||
|
||||
use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
|
||||
use TYPO3\CMS\Core\Database\ConnectionPool;
|
||||
use TYPO3\CMS\Core\Database\Query\QueryBuilder;
|
||||
use TYPO3\CMS\Core\Database\Query\Restriction\EndTimeRestriction;
|
||||
use TYPO3\CMS\Core\Database\Query\Restriction\HiddenRestriction;
|
||||
use TYPO3\CMS\Core\Database\Query\Restriction\StartTimeRestriction;
|
||||
use TYPO3\CMS\Core\DataHandling\DataHandler;
|
||||
use TYPO3\CMS\Core\Service\FlexFormService;
|
||||
use TYPO3\CMS\Core\Utility\ArrayUtility;
|
||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||
|
||||
/**
|
||||
$GLOBALS['TYPO3_CONF_VARS']['EXTENSIONS']['ew_base']['migrationResolveContainer'] = [];
|
||||
$GLOBALS['TYPO3_CONF_VARS']['EXTENSIONS']['ew_base']['migrationColPosOffset'] = 0;
|
||||
$GLOBALS['TYPO3_CONF_VARS']['EXTENSIONS']['ew_base']['migrationMapping'] = [
|
||||
'130' => [
|
||||
'CType' => 'three-col-columns',
|
||||
],
|
||||
'140' => [
|
||||
'CType' => [
|
||||
'search' => 'pi_flexform/type',
|
||||
'matches' => [
|
||||
0 => 'two-col-columns-11',
|
||||
1 => 'two-col-columns-12',
|
||||
2 => 'two-col-columns-21',
|
||||
],
|
||||
],
|
||||
'map' => [
|
||||
'pi_flexform/row_class' => 'frame_class',
|
||||
]
|
||||
],
|
||||
];
|
||||
*/
|
||||
|
||||
class GridelementsToContainerService
|
||||
{
|
||||
private const TABLE_NAME = 'tt_content';
|
||||
|
||||
protected array $resolveContainer = [];
|
||||
|
||||
protected int $colPosOffset = 0;
|
||||
|
||||
protected array $configuration = [];
|
||||
|
||||
public function __construct(
|
||||
protected ConnectionPool $connectionPool,
|
||||
protected DataHandler $dataHandler,
|
||||
protected FlexFormService $flexFormService,
|
||||
) {
|
||||
$config =& $GLOBALS['TYPO3_CONF_VARS']['EXTENSIONS']['ew_base'];
|
||||
$this->resolveContainer = $config['migrationResolveContainer'] ?? [];
|
||||
$this->colPosOffset = $config['migrationColPosOffset'] ?? 0;
|
||||
$this->configuration = $config['migrationMapping'] ?? [];
|
||||
}
|
||||
|
||||
public function migrate(): void
|
||||
{
|
||||
$this->initializeDataHandler();
|
||||
|
||||
// Move children out of container and remove container
|
||||
foreach ($this->resolveContainer as $containerId) {
|
||||
$this->resolveContainers((string)$containerId);
|
||||
}
|
||||
|
||||
$this->migrateConfiguredContainer();
|
||||
}
|
||||
|
||||
protected function initializeDataHandler(): void
|
||||
{
|
||||
$backendUser = GeneralUtility::makeInstance(BackendUserAuthentication::class);
|
||||
$backendUser->user = [
|
||||
'uid' => 0,
|
||||
'admin' => 1,
|
||||
];
|
||||
$this->dataHandler->start([], [], $backendUser);
|
||||
}
|
||||
|
||||
|
||||
protected function resolveContainers(string $layout): void
|
||||
{
|
||||
$containers = $this->getGridElementsByLayout($layout);
|
||||
foreach ($containers as $container) {
|
||||
$this->processContainerResolve($container);
|
||||
}
|
||||
}
|
||||
|
||||
protected function processContainerResolve(array $container): void
|
||||
{
|
||||
$children = $this->getGridContainerChildren($container['uid']);
|
||||
// move first child after container
|
||||
$moveAfterThis = $container;
|
||||
foreach ($children as $child) {
|
||||
[$moveAfterThis, $container] = $this->processContainerResolveChild($child, $moveAfterThis, $container);
|
||||
}
|
||||
|
||||
$this->deleteElement($container['uid']);
|
||||
}
|
||||
|
||||
protected function processContainerResolveChild(array $child, array $moveAfterThis, array $container): array
|
||||
{
|
||||
$this->updateElement(
|
||||
$child['uid'],
|
||||
[
|
||||
'tx_gridelements_container' => 0,
|
||||
'colPos' => $container['colPos'],
|
||||
'header' => $child['header'] ?: $container['header']
|
||||
]
|
||||
);
|
||||
$this->moveElementAfterElement($child['uid'], $moveAfterThis['uid']);
|
||||
// use this child to move the next child after
|
||||
$moveAfterThis = $child;
|
||||
// empty container header so only the first child gets the header
|
||||
$container['header'] = '';
|
||||
|
||||
return [$moveAfterThis, $container];
|
||||
}
|
||||
|
||||
protected function deleteElement(int $uid): void
|
||||
{
|
||||
$this->connectionPool
|
||||
->getConnectionForTable(self::TABLE_NAME)
|
||||
->update(self::TABLE_NAME, ['delete' => 1], ['uid' => $uid]);
|
||||
}
|
||||
|
||||
protected function moveElementAfterElement(int $elementToMove, int $elementToMoveAfter): void
|
||||
{
|
||||
$this->dataHandler->moveRecord(self::TABLE_NAME, $elementToMove, $elementToMoveAfter * -1);
|
||||
}
|
||||
|
||||
|
||||
protected function migrateConfiguredContainer(): void
|
||||
{
|
||||
array_walk($this->configuration, function($config, $key) {
|
||||
$containers = $this->getGridElementsByLayout((string)$key);
|
||||
foreach ($containers as $container) {
|
||||
$container['pi_flexform'] = $this->flexFormService->convertFlexFormContentToArray(
|
||||
$container['pi_flexform']
|
||||
);
|
||||
$this->processContainerMigration($container, $config);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected function processContainerMigration(array $container, array $config): void
|
||||
{
|
||||
$children = $this->getGridContainerChildren($container['uid']);
|
||||
foreach ($children as $child) {
|
||||
$this->processContainerMigrationChild($child, $container);
|
||||
}
|
||||
|
||||
$data = [
|
||||
'CType' => $this->getCType($container, $config),
|
||||
'tx_gridelements_backend_layout' => ''
|
||||
];
|
||||
|
||||
if (isset($config['map']) && is_array($config['map']) && !empty($container['pi_flexform'])) {
|
||||
$data = $this->addMappedValues($data, $container, $config['map']);
|
||||
}
|
||||
|
||||
$this->updateElement($container['uid'], $data);
|
||||
}
|
||||
|
||||
protected function processContainerMigrationChild(array $child, array $container): void
|
||||
{
|
||||
$this->updateElement(
|
||||
$child['uid'],
|
||||
[
|
||||
'hidden' => $child['hidden'] ?: $container['hidden'],
|
||||
'colPos' => $child['tx_gridelements_columns'] + $this->colPosOffset,
|
||||
'tx_container_parent' => $child['tx_gridelements_container'],
|
||||
'tx_gridelements_columns' => 0,
|
||||
'tx_gridelements_container' => 0,
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
protected function getCType(array $container, array $config): string
|
||||
{
|
||||
if (is_array($config['CType'])) {
|
||||
$value = ArrayUtility::getValueByPath($container, $config['CType']['search']);
|
||||
$result = $config['CType']['matches'][$value] ?? null;
|
||||
} else {
|
||||
$result = $config['CType'] ?? null;
|
||||
}
|
||||
|
||||
if (empty($result)) {
|
||||
throw new \Exception('CType must always be set');
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
protected function addMappedValues(array $data, array $container, array $config): array
|
||||
{
|
||||
foreach ($config as $from => $to) {
|
||||
try {
|
||||
$value = ArrayUtility::getValueByPath($container, $from);
|
||||
if (empty($container[$to]) && !empty($value)) {
|
||||
$data[$to] = $value;
|
||||
}
|
||||
} catch (\throwable) {}
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
|
||||
protected function updateElement(int $uid, array $changes): void
|
||||
{
|
||||
$this->connectionPool
|
||||
->getConnectionForTable(self::TABLE_NAME)
|
||||
->update(self::TABLE_NAME, $changes, ['uid' => $uid]);
|
||||
}
|
||||
|
||||
protected function getGridContainerChildren(int $containerUid): array
|
||||
{
|
||||
$queryBuilder = $this->getQueryBuilderForTable();
|
||||
|
||||
return $queryBuilder
|
||||
->select('*')
|
||||
->where(
|
||||
$queryBuilder->expr()->eq(
|
||||
'tx_gridelements_container',
|
||||
$queryBuilder->createNamedParameter($containerUid, \PDO::PARAM_INT)
|
||||
)
|
||||
)
|
||||
->orderBy('sorting')
|
||||
->executeQuery()
|
||||
->fetchAllAssociative();
|
||||
}
|
||||
|
||||
protected function getGridElementsByLayout(string $layout): array
|
||||
{
|
||||
$queryBuilder = $this->getQueryBuilderForTable();
|
||||
$expr = $queryBuilder->expr();
|
||||
|
||||
return $queryBuilder
|
||||
->select('*')
|
||||
->where(
|
||||
$expr->eq('CType', $queryBuilder->createNamedParameter('gridelements_pi1')),
|
||||
$expr->eq('tx_gridelements_backend_layout', $queryBuilder->createNamedParameter($layout))
|
||||
)
|
||||
->orderBy('sorting')
|
||||
->executeQuery()
|
||||
->fetchAllAssociative();
|
||||
}
|
||||
|
||||
protected function getQueryBuilderForTable(string $table = 'tt_content'): QueryBuilder
|
||||
{
|
||||
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
|
||||
->getQueryBuilderForTable($table);
|
||||
|
||||
$queryBuilder->getRestrictions()
|
||||
->removeByType(HiddenRestriction::class)
|
||||
->removeByType(StartTimeRestriction::class)
|
||||
->removeByType(EndTimeRestriction::class);
|
||||
|
||||
$queryBuilder->from($table);
|
||||
|
||||
return $queryBuilder;
|
||||
}
|
||||
}
|
||||
106
Classes/Updates/ParentChildToContainerMigration.php
Normal file
106
Classes/Updates/ParentChildToContainerMigration.php
Normal file
@ -0,0 +1,106 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Evoweb\EwBase\Updates;
|
||||
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Psr\Log\LogLevel;
|
||||
use TYPO3\CMS\Core\Database\ConnectionPool;
|
||||
use TYPO3\CMS\Core\Database\Query\QueryBuilder;
|
||||
use TYPO3\CMS\Core\Database\Query\Restriction\EndTimeRestriction;
|
||||
use TYPO3\CMS\Core\Database\Query\Restriction\HiddenRestriction;
|
||||
use TYPO3\CMS\Core\Database\Query\Restriction\StartTimeRestriction;
|
||||
use TYPO3\CMS\Core\Log\LogManager;
|
||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||
use TYPO3\CMS\Install\Attribute\UpgradeWizard;
|
||||
use TYPO3\CMS\Install\Updates\DatabaseUpdatedPrerequisite;
|
||||
use TYPO3\CMS\Install\Updates\UpgradeWizardInterface;
|
||||
|
||||
/**
|
||||
* Migrate parent child elements to container elements
|
||||
*/
|
||||
#[UpgradeWizard('parentChildToContainer')]
|
||||
class ParentChildToContainerMigration implements UpgradeWizardInterface
|
||||
{
|
||||
private const TABLE_NAME = 'tt_content';
|
||||
|
||||
protected LoggerInterface $logger;
|
||||
|
||||
public function __construct(
|
||||
protected ParentChildToContainerService $service,
|
||||
protected LogManager $logManager,
|
||||
) {
|
||||
$this->logger = $logManager->getLogger(self::class);
|
||||
}
|
||||
|
||||
public function getTitle(): string
|
||||
{
|
||||
return 'Migrate parent/child to container';
|
||||
}
|
||||
|
||||
public function getDescription(): string
|
||||
{
|
||||
return 'Migrates content elements that are type parent/child to corresponding container elements';
|
||||
}
|
||||
|
||||
public function getPrerequisites(): array
|
||||
{
|
||||
return [
|
||||
DatabaseUpdatedPrerequisite::class
|
||||
];
|
||||
}
|
||||
|
||||
public function updateNecessary(): bool
|
||||
{
|
||||
return $this->hasRecordsToUpdate();
|
||||
}
|
||||
|
||||
public function executeUpdate(): bool
|
||||
{
|
||||
$updateSuccessful = true;
|
||||
try {
|
||||
$this->service->migrate();
|
||||
} catch (\Exception $exception) {
|
||||
$this->logger->log(LogLevel::ERROR, $exception->getMessage());
|
||||
$updateSuccessful = false;
|
||||
}
|
||||
|
||||
return $updateSuccessful;
|
||||
}
|
||||
|
||||
protected function hasRecordsToUpdate(): bool
|
||||
{
|
||||
$queryBuilder = $this->getPreparedQueryBuilder();
|
||||
$tableColumns = $queryBuilder
|
||||
->getConnection()
|
||||
->createSchemaManager()
|
||||
->listTableColumns(self::TABLE_NAME);
|
||||
return isset($tableColumns['parent'])
|
||||
&& $queryBuilder
|
||||
->count('uid')
|
||||
->executeQuery()
|
||||
->fetchOne() > 0;
|
||||
}
|
||||
|
||||
protected function getPreparedQueryBuilder(): QueryBuilder
|
||||
{
|
||||
$queryBuilder = $this->getConnectionPool()->getQueryBuilderForTable(self::TABLE_NAME);
|
||||
$queryBuilder->getRestrictions()
|
||||
->removeByType(HiddenRestriction::class)
|
||||
->removeByType(StartTimeRestriction::class)
|
||||
->removeByType(EndTimeRestriction::class);
|
||||
$queryBuilder
|
||||
->from(self::TABLE_NAME)
|
||||
->where(
|
||||
// check if there are still records that have parent instead of tx_container_parent
|
||||
$queryBuilder->expr()->gt('parent', 0)
|
||||
);
|
||||
return $queryBuilder;
|
||||
}
|
||||
|
||||
protected function getConnectionPool(): ConnectionPool
|
||||
{
|
||||
return GeneralUtility::makeInstance(ConnectionPool::class);
|
||||
}
|
||||
}
|
||||
168
Classes/Updates/ParentChildToContainerService.php
Normal file
168
Classes/Updates/ParentChildToContainerService.php
Normal file
@ -0,0 +1,168 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Evoweb\EwBase\Updates;
|
||||
|
||||
use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
|
||||
use TYPO3\CMS\Core\Database\ConnectionPool;
|
||||
use TYPO3\CMS\Core\Database\Query\QueryBuilder;
|
||||
use TYPO3\CMS\Core\Database\Query\Restriction\EndTimeRestriction;
|
||||
use TYPO3\CMS\Core\Database\Query\Restriction\HiddenRestriction;
|
||||
use TYPO3\CMS\Core\Database\Query\Restriction\StartTimeRestriction;
|
||||
use TYPO3\CMS\Core\DataHandling\DataHandler;
|
||||
use TYPO3\CMS\Core\Service\FlexFormService;
|
||||
use TYPO3\CMS\Core\Utility\ArrayUtility;
|
||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||
|
||||
/**
|
||||
$GLOBALS['TYPO3_CONF_VARS']['EXTENSIONS']['ew_base']['childParentColPosOffset'] = 0;
|
||||
$GLOBALS['TYPO3_CONF_VARS']['EXTENSIONS']['ew_base']['childParentMigrationMapping'] = [
|
||||
'downloads' => [ 'CType' => 'container-downloads' ],
|
||||
];
|
||||
*/
|
||||
|
||||
class ParentChildToContainerService
|
||||
{
|
||||
private const TABLE_NAME = 'tt_content';
|
||||
|
||||
protected int $colPosOffset = 0;
|
||||
|
||||
protected array $configuration = [];
|
||||
|
||||
public function __construct(
|
||||
protected ConnectionPool $connectionPool,
|
||||
protected DataHandler $dataHandler,
|
||||
protected FlexFormService $flexFormService,
|
||||
) {
|
||||
$config =& $GLOBALS['TYPO3_CONF_VARS']['EXTENSIONS']['ew_base'];
|
||||
$this->colPosOffset = $config['childParentColPosOffset'] ?? 0;
|
||||
$this->configuration = $config['childParentMigrationMapping'] ?? [];
|
||||
}
|
||||
|
||||
public function migrate(): void
|
||||
{
|
||||
$this->initializeDataHandler();
|
||||
$this->migrateConfiguredContainer();
|
||||
}
|
||||
|
||||
protected function initializeDataHandler(): void
|
||||
{
|
||||
$backendUser = GeneralUtility::makeInstance(BackendUserAuthentication::class);
|
||||
$backendUser->user = [
|
||||
'uid' => 0,
|
||||
'admin' => 1,
|
||||
];
|
||||
$this->dataHandler->start([], [], $backendUser);
|
||||
}
|
||||
|
||||
|
||||
protected function migrateConfiguredContainer(): void
|
||||
{
|
||||
array_walk($this->configuration, function($config, $key) {
|
||||
$parents = $this->getParentsByCType((string)$key);
|
||||
foreach ($parents as $parent) {
|
||||
$this->processParentMigration($parent, $config);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected function processParentMigration(array $parent, array $config): void
|
||||
{
|
||||
$children = $this->getChildren($parent['uid']);
|
||||
foreach ($children as $child) {
|
||||
$this->processChildMigration($child, $parent);
|
||||
}
|
||||
|
||||
$this->updateElement(
|
||||
$parent['uid'],
|
||||
[
|
||||
'CType' => $this->getCType($parent, $config),
|
||||
'children' => 0,
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
protected function processChildMigration(array $child, array $parent): void
|
||||
{
|
||||
$this->updateElement(
|
||||
$child['uid'],
|
||||
[
|
||||
'tx_container_parent' => $parent['uid'],
|
||||
'colPos' => $child['colPos'] + $this->colPosOffset,
|
||||
'parent' => 0,
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
protected function getCType(array $container, array $config): string
|
||||
{
|
||||
if (is_array($config['CType'])) {
|
||||
$value = ArrayUtility::getValueByPath($container, $config['CType']['search']);
|
||||
$result = $config['CType']['matches'][$value] ?? null;
|
||||
} else {
|
||||
$result = $config['CType'] ?? null;
|
||||
}
|
||||
|
||||
if (empty($result)) {
|
||||
throw new \Exception('CType must always be set');
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
||||
protected function updateElement(int $uid, array $changes): void
|
||||
{
|
||||
$this->connectionPool
|
||||
->getConnectionForTable(self::TABLE_NAME)
|
||||
->update(self::TABLE_NAME, $changes, ['uid' => $uid]);
|
||||
}
|
||||
|
||||
protected function getChildren(int $parentUid): array
|
||||
{
|
||||
$queryBuilder = $this->getQueryBuilderForTable();
|
||||
|
||||
return $queryBuilder
|
||||
->select('*')
|
||||
->where(
|
||||
$queryBuilder->expr()->eq(
|
||||
'parent',
|
||||
$queryBuilder->createNamedParameter($parentUid, \PDO::PARAM_INT)
|
||||
)
|
||||
)
|
||||
->orderBy('sorting')
|
||||
->executeQuery()
|
||||
->fetchAllAssociative();
|
||||
}
|
||||
|
||||
protected function getParentsByCType(string $cType): array
|
||||
{
|
||||
$queryBuilder = $this->getQueryBuilderForTable();
|
||||
$expr = $queryBuilder->expr();
|
||||
|
||||
return $queryBuilder
|
||||
->select('*')
|
||||
->where(
|
||||
$expr->eq('CType', $queryBuilder->createNamedParameter($cType))
|
||||
)
|
||||
->orderBy('sorting')
|
||||
->executeQuery()
|
||||
->fetchAllAssociative();
|
||||
}
|
||||
|
||||
protected function getQueryBuilderForTable(string $table = 'tt_content'): QueryBuilder
|
||||
{
|
||||
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
|
||||
->getQueryBuilderForTable($table);
|
||||
|
||||
$queryBuilder->getRestrictions()
|
||||
->removeByType(HiddenRestriction::class)
|
||||
->removeByType(StartTimeRestriction::class)
|
||||
->removeByType(EndTimeRestriction::class);
|
||||
|
||||
$queryBuilder->from($table);
|
||||
|
||||
return $queryBuilder;
|
||||
}
|
||||
}
|
||||
16
Classes/User/AssetPath.php
Executable file → Normal file
16
Classes/User/AssetPath.php
Executable file → Normal file
@ -2,19 +2,9 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is developed by evoWeb.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
namespace Evoweb\EwBase\User;
|
||||
|
||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||
use TYPO3\CMS\Core\Utility\PathUtility;
|
||||
|
||||
/**
|
||||
@ -28,6 +18,8 @@ class AssetPath
|
||||
{
|
||||
public function getAbsolutePublicPath(string $content, array $conf): string
|
||||
{
|
||||
return $content . PathUtility::getAbsoluteWebPath($conf['file']);
|
||||
return $content
|
||||
. GeneralUtility::getIndpEnv('TYPO3_SITE_URL')
|
||||
. ltrim(PathUtility::getPublicResourceWebPath($conf['file']), '/');
|
||||
}
|
||||
}
|
||||
|
||||
15
Classes/ViewHelpers/Array/AddViewHelper.php
Executable file → Normal file
15
Classes/ViewHelpers/Array/AddViewHelper.php
Executable file → Normal file
@ -1,5 +1,7 @@
|
||||
<?php
|
||||
|
||||
namespace Evoweb\EwBase\ViewHelpers\Array;
|
||||
|
||||
/*
|
||||
* This file is developed by evoWeb.
|
||||
*
|
||||
@ -11,8 +13,6 @@
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Evoweb\EwBase\ViewHelpers\Array;
|
||||
|
||||
use TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface;
|
||||
use TYPO3Fluid\Fluid\Core\ViewHelper\AbstractViewHelper;
|
||||
use TYPO3Fluid\Fluid\Core\ViewHelper\Traits\CompileWithRenderStatic;
|
||||
@ -26,7 +26,7 @@ class AddViewHelper extends AbstractViewHelper
|
||||
*/
|
||||
protected $escapeOutput = false;
|
||||
|
||||
public function initializeArguments(): void
|
||||
public function initializeArguments()
|
||||
{
|
||||
parent::initializeArguments();
|
||||
$this->registerArgument('array', 'array', 'Array to add value to');
|
||||
@ -34,11 +34,18 @@ class AddViewHelper extends AbstractViewHelper
|
||||
$this->registerArgument('value', 'mixed', 'Value to add');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $arguments
|
||||
* @param \Closure $renderChildrenClosure
|
||||
* @param RenderingContextInterface $renderingContext
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function renderStatic(
|
||||
array $arguments,
|
||||
\Closure $renderChildrenClosure,
|
||||
RenderingContextInterface $renderingContext
|
||||
): array {
|
||||
) {
|
||||
$array = $arguments['array'] ?: [];
|
||||
$key = $arguments['key'];
|
||||
$value = !is_null($arguments['value']) ? $arguments['value'] : $renderChildrenClosure();
|
||||
|
||||
25
Classes/ViewHelpers/Be/ThumbnailViewHelper.php
Executable file → Normal file
25
Classes/ViewHelpers/Be/ThumbnailViewHelper.php
Executable file → Normal file
@ -15,7 +15,6 @@ declare(strict_types=1);
|
||||
|
||||
namespace Evoweb\EwBase\ViewHelpers\Be;
|
||||
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use TYPO3\CMS\Backend\Routing\UriBuilder;
|
||||
use TYPO3\CMS\Backend\Utility\BackendUtility;
|
||||
use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
|
||||
@ -30,7 +29,10 @@ class ThumbnailViewHelper extends AbstractViewHelper
|
||||
{
|
||||
use CompileWithRenderStatic;
|
||||
|
||||
public function initializeArguments(): void
|
||||
/**
|
||||
* Initializes the arguments
|
||||
*/
|
||||
public function initializeArguments()
|
||||
{
|
||||
parent::initializeArguments();
|
||||
$this->registerArgument('row', 'array', 'content data', true);
|
||||
@ -38,11 +40,20 @@ class ThumbnailViewHelper extends AbstractViewHelper
|
||||
$this->registerArgument('fieldName', 'string', 'field name', true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Render a constant
|
||||
*
|
||||
* @param array $arguments
|
||||
* @param \Closure $renderChildrenClosure
|
||||
* @param RenderingContextInterface $renderingContext
|
||||
*
|
||||
* @return string Value of constant
|
||||
*/
|
||||
public static function renderStatic(
|
||||
array $arguments,
|
||||
\Closure $renderChildrenClosure,
|
||||
RenderingContextInterface $renderingContext
|
||||
): string {
|
||||
) {
|
||||
$row = $arguments['row'];
|
||||
$tableName = $arguments['tableName'];
|
||||
$fieldName = $arguments['fieldName'];
|
||||
@ -75,8 +86,7 @@ class ThumbnailViewHelper extends AbstractViewHelper
|
||||
$row['uid'] => 'edit',
|
||||
],
|
||||
],
|
||||
// @extensionScannerIgnoreLine
|
||||
'returnUrl' => self::getRequest()->getAttribute('normalizedParams')->getRequestUri()
|
||||
'returnUrl' => $GLOBALS['TYPO3_REQUEST']->getAttribute('normalizedParams')->getRequestUri()
|
||||
. '#element-tt_content-' . $row['uid'],
|
||||
];
|
||||
/** @var UriBuilder $uriBuilder */
|
||||
@ -100,9 +110,4 @@ class ThumbnailViewHelper extends AbstractViewHelper
|
||||
{
|
||||
return $GLOBALS['LANG'];
|
||||
}
|
||||
|
||||
protected static function getRequest(): ServerRequestInterface
|
||||
{
|
||||
return $GLOBALS['TYPO3_REQUEST'];
|
||||
}
|
||||
}
|
||||
|
||||
23
Classes/ViewHelpers/Condition/InArrayViewHelper.php
Executable file → Normal file
23
Classes/ViewHelpers/Condition/InArrayViewHelper.php
Executable file → Normal file
@ -1,18 +1,14 @@
|
||||
<?php
|
||||
|
||||
namespace Evoweb\EwBase\ViewHelpers\Condition;
|
||||
|
||||
/*
|
||||
* This file is developed by evoWeb.
|
||||
*
|
||||
* 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.
|
||||
* This file is part of the FluidTYPO3/Vhs project under GPLv2 or later.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
* LICENSE.md file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Evoweb\EwBase\ViewHelpers\Condition;
|
||||
|
||||
use TYPO3Fluid\Fluid\Core\ViewHelper\AbstractConditionViewHelper;
|
||||
|
||||
/**
|
||||
@ -23,14 +19,21 @@ use TYPO3Fluid\Fluid\Core\ViewHelper\AbstractConditionViewHelper;
|
||||
*/
|
||||
class InArrayViewHelper extends AbstractConditionViewHelper
|
||||
{
|
||||
public function initializeArguments(): void
|
||||
/**
|
||||
* Initialize arguments
|
||||
*/
|
||||
public function initializeArguments()
|
||||
{
|
||||
parent::initializeArguments();
|
||||
$this->registerArgument('haystack', 'array', 'haystack', true);
|
||||
$this->registerArgument('needle', 'mixed', 'needle', true);
|
||||
}
|
||||
|
||||
protected static function evaluateCondition($arguments = null): bool
|
||||
/**
|
||||
* @param array $arguments
|
||||
* @return bool
|
||||
*/
|
||||
protected static function evaluateCondition($arguments = null)
|
||||
{
|
||||
$array = $arguments['haystack']->toArray();
|
||||
return in_array($arguments['needle'], $array);
|
||||
|
||||
25
Classes/ViewHelpers/Condition/StringContainsViewHelper.php
Executable file → Normal file
25
Classes/ViewHelpers/Condition/StringContainsViewHelper.php
Executable file → Normal file
@ -1,18 +1,14 @@
|
||||
<?php
|
||||
|
||||
namespace Evoweb\EwBase\ViewHelpers\Condition;
|
||||
|
||||
/*
|
||||
* This file is developed by evoWeb.
|
||||
*
|
||||
* 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.
|
||||
* This file is part of the FluidTYPO3/Vhs project under GPLv2 or later.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
* LICENSE.md file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Evoweb\EwBase\ViewHelpers\Condition;
|
||||
|
||||
use TYPO3Fluid\Fluid\Core\ViewHelper\AbstractConditionViewHelper;
|
||||
|
||||
/**
|
||||
@ -23,15 +19,22 @@ use TYPO3Fluid\Fluid\Core\ViewHelper\AbstractConditionViewHelper;
|
||||
*/
|
||||
class StringContainsViewHelper extends AbstractConditionViewHelper
|
||||
{
|
||||
public function initializeArguments(): void
|
||||
/**
|
||||
* Initialize arguments
|
||||
*/
|
||||
public function initializeArguments()
|
||||
{
|
||||
parent::initializeArguments();
|
||||
$this->registerArgument('haystack', 'string', 'haystack', true);
|
||||
$this->registerArgument('needle', 'string', 'need', true);
|
||||
}
|
||||
|
||||
protected static function evaluateCondition($arguments = null): bool
|
||||
/**
|
||||
* @param array $arguments
|
||||
* @return bool
|
||||
*/
|
||||
protected static function evaluateCondition($arguments = null)
|
||||
{
|
||||
return str_contains($arguments['haystack'], $arguments['needle']);
|
||||
return false !== strpos($arguments['haystack'], $arguments['needle']);
|
||||
}
|
||||
}
|
||||
|
||||
18
Classes/ViewHelpers/Context/DevelopmentViewHelper.php
Executable file → Normal file
18
Classes/ViewHelpers/Context/DevelopmentViewHelper.php
Executable file → Normal file
@ -1,24 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace Evoweb\EwBase\ViewHelpers\Context;
|
||||
|
||||
/*
|
||||
* This file is developed by evoWeb.
|
||||
*
|
||||
* 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.
|
||||
* This file is part of the FluidTYPO3/Vhs project under GPLv2 or later.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
* LICENSE.md file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Evoweb\EwBase\ViewHelpers\Context;
|
||||
|
||||
use TYPO3\CMS\Core\Core\Environment;
|
||||
use TYPO3Fluid\Fluid\Core\ViewHelper\AbstractConditionViewHelper;
|
||||
|
||||
class DevelopmentViewHelper extends AbstractConditionViewHelper
|
||||
{
|
||||
protected static function evaluateCondition($arguments = null): bool
|
||||
/**
|
||||
* @param array $arguments
|
||||
* @return bool
|
||||
*/
|
||||
protected static function evaluateCondition($arguments = null)
|
||||
{
|
||||
return Environment::getContext()->isDevelopment();
|
||||
}
|
||||
|
||||
18
Classes/ViewHelpers/Context/ProductionViewHelper.php
Executable file → Normal file
18
Classes/ViewHelpers/Context/ProductionViewHelper.php
Executable file → Normal file
@ -1,24 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace Evoweb\EwBase\ViewHelpers\Context;
|
||||
|
||||
/*
|
||||
* This file is developed by evoWeb.
|
||||
*
|
||||
* 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.
|
||||
* This file is part of the FluidTYPO3/Vhs project under GPLv2 or later.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
* LICENSE.md file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Evoweb\EwBase\ViewHelpers\Context;
|
||||
|
||||
use TYPO3\CMS\Core\Core\Environment;
|
||||
use TYPO3Fluid\Fluid\Core\ViewHelper\AbstractConditionViewHelper;
|
||||
|
||||
class ProductionViewHelper extends AbstractConditionViewHelper
|
||||
{
|
||||
protected static function evaluateCondition($arguments = null): bool
|
||||
/**
|
||||
* @param array $arguments
|
||||
* @return bool
|
||||
*/
|
||||
protected static function evaluateCondition($arguments = null)
|
||||
{
|
||||
return Environment::getContext()->isProduction();
|
||||
}
|
||||
|
||||
20
Classes/ViewHelpers/Context/StagingViewHelper.php
Executable file → Normal file
20
Classes/ViewHelpers/Context/StagingViewHelper.php
Executable file → Normal file
@ -1,25 +1,25 @@
|
||||
<?php
|
||||
|
||||
namespace Evoweb\EwBase\ViewHelpers\Context;
|
||||
|
||||
/*
|
||||
* This file is developed by evoWeb.
|
||||
*
|
||||
* 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.
|
||||
* This file is part of the FluidTYPO3/Vhs project under GPLv2 or later.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
* LICENSE.md file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Evoweb\EwBase\ViewHelpers\Context;
|
||||
|
||||
use TYPO3\CMS\Core\Core\Environment;
|
||||
use TYPO3Fluid\Fluid\Core\ViewHelper\AbstractConditionViewHelper;
|
||||
|
||||
class StagingViewHelper extends AbstractConditionViewHelper
|
||||
{
|
||||
protected static function evaluateCondition($arguments = null): bool
|
||||
/**
|
||||
* @param array $arguments
|
||||
* @return bool
|
||||
*/
|
||||
protected static function evaluateCondition($arguments = null)
|
||||
{
|
||||
return (string)Environment::getContext() === 'Production/Staging';
|
||||
return 'Production/Staging' === (string)Environment::getContext();
|
||||
}
|
||||
}
|
||||
|
||||
77
Classes/ViewHelpers/FixFlexformForExtbaseViewHelper.php
Normal file
77
Classes/ViewHelpers/FixFlexformForExtbaseViewHelper.php
Normal file
@ -0,0 +1,77 @@
|
||||
<?php
|
||||
|
||||
namespace Evoweb\EwBase\ViewHelpers;
|
||||
|
||||
/*
|
||||
* This file is developed by evoWeb.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
use TYPO3\CMS\Core\Configuration\FlexForm\FlexFormTools;
|
||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||
use TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface;
|
||||
use TYPO3Fluid\Fluid\Core\ViewHelper\Traits\CompileWithRenderStatic;
|
||||
use TYPO3Fluid\Fluid\Core\ViewHelper\AbstractViewHelper;
|
||||
|
||||
/**
|
||||
* = Examples =
|
||||
*
|
||||
* <code title="Simple Loop">
|
||||
* <ewb:fixFlexformForExtbase data="{data}">....</ewb:fixFlexformForExtbase>
|
||||
* </code>
|
||||
* <output>
|
||||
* fixed flexform data for extbase controller
|
||||
* </output>
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
class FixFlexformForExtbaseViewHelper extends AbstractViewHelper
|
||||
{
|
||||
use CompileWithRenderStatic;
|
||||
|
||||
/**
|
||||
* @var boolean
|
||||
*/
|
||||
protected $escapeOutput = false;
|
||||
|
||||
public function initializeArguments(): void
|
||||
{
|
||||
parent::initializeArguments();
|
||||
$this->registerArgument('data', 'array', 'The data array of content element', true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $arguments
|
||||
* @param \Closure $renderChildrenClosure
|
||||
* @param RenderingContextInterface $renderingContext
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function renderStatic(
|
||||
array $arguments,
|
||||
\Closure $renderChildrenClosure,
|
||||
RenderingContextInterface $renderingContext
|
||||
) {
|
||||
$templateVariableContainer = $renderingContext->getVariableProvider();
|
||||
|
||||
/** @var FlexFormTools $flexFormTools */
|
||||
$flexFormTools = GeneralUtility::makeInstance(FlexFormTools::class);
|
||||
|
||||
$data = $arguments['data'];
|
||||
if (is_array($data['pi_flexform'])) {
|
||||
$data['pi_flexform'] = $flexFormTools->flexArray2Xml($data['pi_flexform']);
|
||||
}
|
||||
|
||||
$templateVariableContainer->add('data', $data);
|
||||
$output = $renderChildrenClosure();
|
||||
$templateVariableContainer->remove('data');
|
||||
|
||||
return $output;
|
||||
}
|
||||
}
|
||||
80
Classes/ViewHelpers/FlexFormViewHelper.php
Normal file
80
Classes/ViewHelpers/FlexFormViewHelper.php
Normal file
@ -0,0 +1,80 @@
|
||||
<?php
|
||||
|
||||
namespace Evoweb\EwBase\ViewHelpers;
|
||||
|
||||
/*
|
||||
* This file is developed by evoWeb.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||
use TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface;
|
||||
use TYPO3Fluid\Fluid\Core\ViewHelper\AbstractViewHelper;
|
||||
use TYPO3Fluid\Fluid\Core\ViewHelper\Traits\CompileWithRenderStatic;
|
||||
|
||||
/**
|
||||
* = Examples =
|
||||
*
|
||||
* <code title="Simple Loop">
|
||||
* <ewb:flexForm data="{data}">....</ewb:flexForm>
|
||||
* </code>
|
||||
* <output>
|
||||
* fixed flexform data for extbase controller
|
||||
* </output>
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
class FlexFormViewHelper extends AbstractViewHelper
|
||||
{
|
||||
use CompileWithRenderStatic;
|
||||
|
||||
/**
|
||||
* @var boolean
|
||||
*/
|
||||
protected $escapeOutput = false;
|
||||
|
||||
public function initializeArguments()
|
||||
{
|
||||
parent::initializeArguments();
|
||||
$this->registerArgument('data', 'array', 'Array to get flex form data from', true);
|
||||
$this->registerArgument('fieldName', 'string', 'Field name', false, 'pi_flexform');
|
||||
$this->registerArgument('as', 'string', 'Name of the variable to assign', false, 'flexFormData');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $arguments
|
||||
* @param \Closure $renderChildrenClosure
|
||||
* @param RenderingContextInterface $renderingContext
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function renderStatic(
|
||||
array $arguments,
|
||||
\Closure $renderChildrenClosure,
|
||||
RenderingContextInterface $renderingContext
|
||||
) {
|
||||
$data = [];
|
||||
|
||||
if (is_array($arguments['data'])) {
|
||||
if (isset($arguments['data'][$arguments['fieldName']])) {
|
||||
$data = is_array($arguments['data'][$arguments['fieldName']]) ?
|
||||
$arguments['data'][$arguments['fieldName']] :
|
||||
GeneralUtility::xml2array($arguments['data'][$arguments['fieldName']]);
|
||||
$data = $data['data'] ?? $data;
|
||||
}
|
||||
}
|
||||
|
||||
$templateVariableContainer = $renderingContext->getVariableProvider();
|
||||
$templateVariableContainer->add($arguments['as'], $data);
|
||||
$content = $renderChildrenClosure();
|
||||
$templateVariableContainer->remove($arguments['as']);
|
||||
|
||||
return $content;
|
||||
}
|
||||
}
|
||||
24
Classes/ViewHelpers/HashViewHelper.php
Executable file → Normal file
24
Classes/ViewHelpers/HashViewHelper.php
Executable file → Normal file
@ -1,5 +1,7 @@
|
||||
<?php
|
||||
|
||||
namespace Evoweb\EwBase\ViewHelpers;
|
||||
|
||||
/*
|
||||
* This file is developed by evoWeb.
|
||||
*
|
||||
@ -11,10 +13,6 @@
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Evoweb\EwBase\ViewHelpers;
|
||||
|
||||
use TYPO3\CMS\Core\Crypto\HashService;
|
||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||
use TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface;
|
||||
use TYPO3Fluid\Fluid\Core\ViewHelper\AbstractViewHelper;
|
||||
use TYPO3Fluid\Fluid\Core\ViewHelper\Traits\CompileWithRenderStatic;
|
||||
@ -24,31 +22,37 @@ class HashViewHelper extends AbstractViewHelper
|
||||
use CompileWithRenderStatic;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
* @var boolean
|
||||
*/
|
||||
protected $escapeOutput = false;
|
||||
|
||||
public function initializeArguments(): void
|
||||
public function initializeArguments()
|
||||
{
|
||||
parent::initializeArguments();
|
||||
$this->registerArgument('action', 'string', 'Target action');
|
||||
$this->registerArgument('arguments', 'array', 'Arguments for the controller action, associative array');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $arguments
|
||||
* @param \Closure $renderChildrenClosure
|
||||
* @param RenderingContextInterface $renderingContext
|
||||
* @return string
|
||||
*/
|
||||
public static function renderStatic(
|
||||
array $arguments,
|
||||
\Closure $renderChildrenClosure,
|
||||
RenderingContextInterface $renderingContext
|
||||
): string {
|
||||
) {
|
||||
$result = '';
|
||||
if (
|
||||
$arguments['action'] !== null
|
||||
&& $arguments['arguments'] !== null
|
||||
&& isset($arguments['arguments']['user'])
|
||||
) {
|
||||
/** @var HashService $hashService */
|
||||
$hashService = GeneralUtility::makeInstance(HashService::class);
|
||||
$result = $hashService->hmac($arguments['action'] . '::' . $arguments['arguments']['user'], '');
|
||||
$result = \TYPO3\CMS\Core\Utility\GeneralUtility::hmac(
|
||||
$arguments['action'] . '::' . $arguments['arguments']['user']
|
||||
);
|
||||
}
|
||||
|
||||
return $result;
|
||||
|
||||
56
Classes/ViewHelpers/Iterator/AddViewHelper.php
Normal file
56
Classes/ViewHelpers/Iterator/AddViewHelper.php
Normal file
@ -0,0 +1,56 @@
|
||||
<?php
|
||||
|
||||
namespace Evoweb\EwBase\ViewHelpers\Iterator;
|
||||
|
||||
/*
|
||||
* This file is developed by evoWeb.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||
use TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface;
|
||||
use TYPO3Fluid\Fluid\Core\ViewHelper\AbstractViewHelper;
|
||||
use TYPO3Fluid\Fluid\Core\ViewHelper\Traits\CompileWithRenderStatic;
|
||||
|
||||
class AddViewHelper extends AbstractViewHelper
|
||||
{
|
||||
use CompileWithRenderStatic;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
protected $escapeOutput = false;
|
||||
|
||||
public function initializeArguments()
|
||||
{
|
||||
parent::initializeArguments();
|
||||
$this->registerArgument('array', 'array', 'Array to add value to');
|
||||
$this->registerArgument('key', 'string', 'Key to add value by', true);
|
||||
$this->registerArgument('value', 'mixed', 'Value to add');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $arguments
|
||||
* @param \Closure $renderChildrenClosure
|
||||
* @param RenderingContextInterface $renderingContext
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function renderStatic(
|
||||
array $arguments,
|
||||
\Closure $renderChildrenClosure,
|
||||
RenderingContextInterface $renderingContext
|
||||
) {
|
||||
$array = $arguments['array'] ?: [];
|
||||
$key = $arguments['key'];
|
||||
$value = $arguments['value'] ?: $renderChildrenClosure();
|
||||
|
||||
return array_merge($array, [$key => $value]);
|
||||
}
|
||||
}
|
||||
93
Classes/ViewHelpers/Iterator/ExplodeViewHelper.php
Normal file
93
Classes/ViewHelpers/Iterator/ExplodeViewHelper.php
Normal file
@ -0,0 +1,93 @@
|
||||
<?php
|
||||
|
||||
namespace Evoweb\EwBase\ViewHelpers\Iterator;
|
||||
|
||||
/*
|
||||
* This file is part of the FluidTYPO3/Vhs project under GPLv2 or later.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.md file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
use TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface;
|
||||
use TYPO3Fluid\Fluid\Core\ViewHelper\AbstractViewHelper;
|
||||
use TYPO3Fluid\Fluid\Core\ViewHelper\Traits\CompileWithRenderStatic;
|
||||
|
||||
/**
|
||||
* Explode ViewHelper
|
||||
*
|
||||
* Explodes a string by $glue.
|
||||
*
|
||||
* {data.header -> ewb:iterator.explode(glue: 'constant:LF')}
|
||||
*
|
||||
* <ewb:iterator.explode content="{data.header}" as="as" glue="constant:LF">
|
||||
* <span>{as}</span>
|
||||
* </ewb:iterator.explode>
|
||||
*/
|
||||
class ExplodeViewHelper extends AbstractViewHelper
|
||||
{
|
||||
use CompileWithRenderStatic;
|
||||
|
||||
protected static string $method = 'explode';
|
||||
|
||||
public function initializeArguments()
|
||||
{
|
||||
$this->registerArgument(
|
||||
'as',
|
||||
'string',
|
||||
'Template variable name to assign; if not specified the ViewHelper returns the variable instead.'
|
||||
);
|
||||
$this->registerArgument('content', 'string', 'String to be exploded by glue');
|
||||
$this->registerArgument(
|
||||
'glue',
|
||||
'string',
|
||||
'String used as glue in the string to be exploded. Use glue value of "constant:NAMEOFCONSTANT" ' .
|
||||
'(fx "constant:LF" for linefeed as glue)',
|
||||
false,
|
||||
','
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Render method
|
||||
*
|
||||
* @return string|array
|
||||
*/
|
||||
public static function renderStatic(
|
||||
array $arguments,
|
||||
\Closure $renderChildrenClosure,
|
||||
RenderingContextInterface $renderingContext
|
||||
) {
|
||||
$content = $arguments['content'] ?? $renderChildrenClosure();
|
||||
$glue = static::resolveGlue($arguments);
|
||||
$content = call_user_func_array(static::$method, [$glue, $content]);
|
||||
|
||||
$as = $arguments['as'];
|
||||
if (true === empty($as)) {
|
||||
$output = $content;
|
||||
} else {
|
||||
$templateVariableContainer = $renderingContext->getVariableProvider();
|
||||
$templateVariableContainer->add($as, $content);
|
||||
$output = $renderChildrenClosure();
|
||||
$templateVariableContainer->remove($as);
|
||||
}
|
||||
return $output;
|
||||
}
|
||||
|
||||
protected static function resolveGlue(array $arguments): string
|
||||
{
|
||||
$glue = $arguments['glue'];
|
||||
if (false !== strpos($glue, ':') && 1 < strlen($glue)) {
|
||||
// glue contains a special type identifier, resolve the actual glue
|
||||
list ($type, $value) = explode(':', $glue);
|
||||
switch ($type) {
|
||||
case 'constant':
|
||||
$glue = constant($value);
|
||||
break;
|
||||
default:
|
||||
$glue = $value;
|
||||
}
|
||||
}
|
||||
return $glue;
|
||||
}
|
||||
}
|
||||
26
Classes/ViewHelpers/PublicPathViewHelper.php
Executable file → Normal file
26
Classes/ViewHelpers/PublicPathViewHelper.php
Executable file → Normal file
@ -2,6 +2,8 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Evoweb\EwBase\ViewHelpers;
|
||||
|
||||
/*
|
||||
* This file is developed by evoWeb.
|
||||
*
|
||||
@ -13,8 +15,6 @@ declare(strict_types=1);
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Evoweb\EwBase\ViewHelpers;
|
||||
|
||||
use TYPO3\CMS\Core\Utility\PathUtility;
|
||||
use TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface;
|
||||
use TYPO3Fluid\Fluid\Core\ViewHelper\AbstractViewHelper;
|
||||
@ -37,27 +37,31 @@ class PublicPathViewHelper extends AbstractViewHelper
|
||||
use CompileWithRenderStatic;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
* @var boolean
|
||||
*/
|
||||
protected $escapeOutput = false;
|
||||
|
||||
public function initializeArguments(): void
|
||||
protected static ?array $frontendGroupIds = null;
|
||||
|
||||
public function initializeArguments()
|
||||
{
|
||||
parent::initializeArguments();
|
||||
$this->registerArgument('path', 'string', 'Extension resource path', true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $arguments
|
||||
* @param \Closure $renderChildrenClosure
|
||||
* @param RenderingContextInterface $renderingContext
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function renderStatic(
|
||||
array $arguments,
|
||||
\Closure $renderChildrenClosure,
|
||||
RenderingContextInterface $renderingContext
|
||||
): string {
|
||||
) {
|
||||
$path = (string)$arguments['path'];
|
||||
try {
|
||||
$path = PathUtility::getPublicResourceWebPath($path);
|
||||
} catch (\Exception) {
|
||||
$path = '';
|
||||
}
|
||||
return $path;
|
||||
return PathUtility::getPublicResourceWebPath($path);
|
||||
}
|
||||
}
|
||||
|
||||
14
Classes/ViewHelpers/ReplaceViewHelper.php
Executable file → Normal file
14
Classes/ViewHelpers/ReplaceViewHelper.php
Executable file → Normal file
@ -1,5 +1,7 @@
|
||||
<?php
|
||||
|
||||
namespace Evoweb\EwBase\ViewHelpers;
|
||||
|
||||
/*
|
||||
* This file is developed by evoWeb.
|
||||
*
|
||||
@ -11,8 +13,6 @@
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Evoweb\EwBase\ViewHelpers;
|
||||
|
||||
use TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface;
|
||||
use TYPO3Fluid\Fluid\Core\ViewHelper\AbstractViewHelper;
|
||||
use TYPO3Fluid\Fluid\Core\ViewHelper\Traits\CompileWithContentArgumentAndRenderStatic;
|
||||
@ -44,18 +44,24 @@ class ReplaceViewHelper extends AbstractViewHelper
|
||||
{
|
||||
use CompileWithContentArgumentAndRenderStatic;
|
||||
|
||||
public function initializeArguments(): void
|
||||
public function initializeArguments()
|
||||
{
|
||||
$this->registerArgument('value', 'string', 'String to replace in');
|
||||
$this->registerArgument('search', 'string', 'Search string');
|
||||
$this->registerArgument('replace', 'string', 'Replace value');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $arguments
|
||||
* @param \Closure $renderChildrenClosure
|
||||
* @param RenderingContextInterface $renderingContext
|
||||
* @return null
|
||||
*/
|
||||
public static function renderStatic(
|
||||
array $arguments,
|
||||
\Closure $renderChildrenClosure,
|
||||
RenderingContextInterface $renderingContext
|
||||
): string {
|
||||
) {
|
||||
$content = $arguments['value'];
|
||||
if ($content === null) {
|
||||
$content = $renderChildrenClosure();
|
||||
|
||||
63
Classes/ViewHelpers/SvgViewHelper.php
Executable file → Normal file
63
Classes/ViewHelpers/SvgViewHelper.php
Executable file → Normal file
@ -1,5 +1,7 @@
|
||||
<?php
|
||||
|
||||
namespace Evoweb\EwBase\ViewHelpers;
|
||||
|
||||
/*
|
||||
* This file is developed by evoWeb.
|
||||
*
|
||||
@ -11,15 +13,11 @@
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Evoweb\EwBase\ViewHelpers;
|
||||
|
||||
use TYPO3\CMS\Core\Imaging\Icon;
|
||||
use TYPO3\CMS\Core\Imaging\IconFactory;
|
||||
use TYPO3\CMS\Core\Imaging\IconSize;
|
||||
use TYPO3\CMS\Core\Imaging\IconState;
|
||||
use TYPO3\CMS\Core\Type\Icon\IconState;
|
||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||
use TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface;
|
||||
use TYPO3Fluid\Fluid\Core\ViewHelper\AbstractViewHelper;
|
||||
use TYPO3Fluid\Fluid\Core\ViewHelper\Traits\CompileWithRenderStatic;
|
||||
|
||||
/**
|
||||
@ -63,7 +61,7 @@ use TYPO3Fluid\Fluid\Core\ViewHelper\Traits\CompileWithRenderStatic;
|
||||
* </span>
|
||||
* </span>
|
||||
*/
|
||||
class SvgViewHelper extends AbstractViewHelper
|
||||
class SvgViewHelper extends \TYPO3Fluid\Fluid\Core\ViewHelper\AbstractViewHelper
|
||||
{
|
||||
use CompileWithRenderStatic;
|
||||
|
||||
@ -76,53 +74,30 @@ class SvgViewHelper extends AbstractViewHelper
|
||||
|
||||
public function initializeArguments(): void
|
||||
{
|
||||
$this->registerArgument(
|
||||
'identifier',
|
||||
'string',
|
||||
'Identifier of the icon as registered in the Icon Registry.',
|
||||
true
|
||||
);
|
||||
$this->registerArgument(
|
||||
'size',
|
||||
'string',
|
||||
'Desired size of the icon. All values of the Icons.sizes enum are allowed,'
|
||||
. ' these are: "small", "default", "large" and "overlay".',
|
||||
false,
|
||||
IconSize::SMALL
|
||||
);
|
||||
$this->registerArgument(
|
||||
'overlay',
|
||||
'string',
|
||||
'Identifier of an overlay icon as registered in the Icon Registry.',
|
||||
false,
|
||||
''
|
||||
);
|
||||
$this->registerArgument(
|
||||
'state',
|
||||
'string',
|
||||
'Sets the state of the icon. All values of the Icons.states enum are allowed,'
|
||||
. ' these are: "default" and "disabled".',
|
||||
false,
|
||||
IconState::STATE_DEFAULT
|
||||
);
|
||||
$this->registerArgument(
|
||||
'alternativeMarkupIdentifier',
|
||||
'string',
|
||||
'Alternative icon identifier. Takes precedence over the identifier if supported by the IconProvider.',
|
||||
false,
|
||||
''
|
||||
);
|
||||
$this->registerArgument('identifier', 'string', 'Identifier of the icon as registered in the Icon Registry.', true);
|
||||
$this->registerArgument('size', 'string', 'Desired size of the icon. All values of the Icons.sizes enum are allowed, these are: "small", "default", "large" and "overlay".', false, Icon::SIZE_SMALL);
|
||||
$this->registerArgument('overlay', 'string', 'Identifier of an overlay icon as registered in the Icon Registry.', false);
|
||||
$this->registerArgument('state', 'string', 'Sets the state of the icon. All values of the Icons.states enum are allowed, these are: "default" and "disabled".', false, IconState::STATE_DEFAULT);
|
||||
$this->registerArgument('alternativeMarkupIdentifier', 'string', 'Alternative icon identifier. Takes precedence over the identifier if supported by the IconProvider.', false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints icon html for $identifier key
|
||||
*
|
||||
* @param array $arguments
|
||||
* @param \Closure $renderChildrenClosure
|
||||
* @param RenderingContextInterface $renderingContext
|
||||
* @return string
|
||||
*/
|
||||
public static function renderStatic(
|
||||
array $arguments,
|
||||
\Closure $renderChildrenClosure,
|
||||
RenderingContextInterface $renderingContext
|
||||
): Icon {
|
||||
) {
|
||||
$identifier = $arguments['identifier'];
|
||||
$size = $arguments['size'];
|
||||
$overlay = $arguments['overlay'];
|
||||
$state = IconState::tryFrom($arguments['state']);
|
||||
$state = IconState::cast($arguments['state']);
|
||||
$alternativeMarkupIdentifier = $arguments['alternativeMarkupIdentifier'];
|
||||
$iconFactory = GeneralUtility::makeInstance(IconFactory::class);
|
||||
return $iconFactory->getIcon($identifier, $size, $overlay, $state)->getMarkup($alternativeMarkupIdentifier);
|
||||
|
||||
21
Classes/ViewHelpers/TrimViewHelper.php
Executable file → Normal file
21
Classes/ViewHelpers/TrimViewHelper.php
Executable file → Normal file
@ -1,5 +1,7 @@
|
||||
<?php
|
||||
|
||||
namespace Evoweb\EwBase\ViewHelpers;
|
||||
|
||||
/*
|
||||
* This file is developed by evoWeb.
|
||||
*
|
||||
@ -11,8 +13,6 @@
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Evoweb\EwBase\ViewHelpers;
|
||||
|
||||
use TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface;
|
||||
use TYPO3Fluid\Fluid\Core\ViewHelper\AbstractViewHelper;
|
||||
use TYPO3Fluid\Fluid\Core\ViewHelper\Traits\CompileWithRenderStatic;
|
||||
@ -26,20 +26,27 @@ class TrimViewHelper extends AbstractViewHelper
|
||||
*/
|
||||
protected $escapeOutput = false;
|
||||
|
||||
public function initializeArguments(): void
|
||||
public function initializeArguments()
|
||||
{
|
||||
parent::initializeArguments();
|
||||
$this->registerArgument('content', 'string', 'Content to be trimmed');
|
||||
$this->registerArgument('characters', 'string', 'Characters to be removed');
|
||||
$this->registerArgument('characters', 'string', 'Characters to be removed', false);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $arguments
|
||||
* @param \Closure $renderChildrenClosure
|
||||
* @param RenderingContextInterface $renderingContext
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function renderStatic(
|
||||
array $arguments,
|
||||
\Closure $renderChildrenClosure,
|
||||
RenderingContextInterface $renderingContext
|
||||
): string {
|
||||
$content = $arguments['content'] ?: $renderChildrenClosure();
|
||||
$characters = $arguments['characters'] ?: null;
|
||||
) {
|
||||
$content = $arguments['content'] ? $arguments['content'] : $renderChildrenClosure();
|
||||
$characters = $arguments['characters'] ? $arguments['characters'] : null;
|
||||
|
||||
if ($characters !== null) {
|
||||
$content = trim($content, $characters);
|
||||
|
||||
0
Configuration/Icons.php
Executable file → Normal file
0
Configuration/Icons.php
Executable file → Normal file
0
Configuration/JavaScriptModules.php
Executable file → Normal file
0
Configuration/JavaScriptModules.php
Executable file → Normal file
27
Configuration/Services.yaml
Executable file → Normal file
27
Configuration/Services.yaml
Executable file → Normal file
@ -14,5 +14,32 @@ services:
|
||||
description: 'Command to list all content elements for a given subtree'
|
||||
schedulable: false
|
||||
|
||||
Evoweb\EwBase\EventListener\CssMerger:
|
||||
tags: ['event.listener']
|
||||
|
||||
Evoweb\EwBase\EventListener\JsMerger:
|
||||
tags: ['event.listener']
|
||||
|
||||
Evoweb\EwBase\EventListener\IsContentUsedOnPageLayout:
|
||||
tags: ['event.listener']
|
||||
|
||||
Evoweb\EwBase\ToolbarItems\ReleaseToolbarItem:
|
||||
tags: ['backend.toolbar.item']
|
||||
|
||||
Evoweb\EwBase\Hooks\UsercentricsPostRenderHook:
|
||||
public: true
|
||||
|
||||
Evoweb\EwBase\Updates\GridelementsToContainerMigration:
|
||||
public: true
|
||||
|
||||
Evoweb\EwBase\Updates\GridelementsToContainerService:
|
||||
public: true
|
||||
|
||||
Evoweb\EwBase\Updates\ParentChildToContainerMigration:
|
||||
public: true
|
||||
|
||||
Evoweb\EwBase\Updates\ParentChildToContainerService:
|
||||
public: true
|
||||
|
||||
Evoweb\EwBase\Form\FormDataProvider\UsercentricsDatabaseEditRow:
|
||||
public: true
|
||||
|
||||
10
Configuration/TCA/Overrides/pages.php
Executable file → Normal file
10
Configuration/TCA/Overrides/pages.php
Executable file → Normal file
@ -15,14 +15,14 @@ $newColumns = [
|
||||
'suggestOptions' => [
|
||||
'default' => [
|
||||
'additionalSearchFields' => 'header, bodytext',
|
||||
'searchWholePhrase' => false,
|
||||
],
|
||||
'searchWholePhrase' => false
|
||||
]
|
||||
],
|
||||
'default' => 0,
|
||||
'behaviour' => [
|
||||
'allowLanguageSynchronization' => true,
|
||||
],
|
||||
],
|
||||
'allowLanguageSynchronization' => true
|
||||
]
|
||||
]
|
||||
],
|
||||
];
|
||||
|
||||
|
||||
0
Configuration/Yaml/Csp/Cookiebot.yaml
Executable file → Normal file
0
Configuration/Yaml/Csp/Cookiebot.yaml
Executable file → Normal file
0
Configuration/Yaml/Csp/GoogleAdsConversions.yaml
Executable file → Normal file
0
Configuration/Yaml/Csp/GoogleAdsConversions.yaml
Executable file → Normal file
0
Configuration/Yaml/Csp/GoogleAdsRemarketing.yaml
Executable file → Normal file
0
Configuration/Yaml/Csp/GoogleAdsRemarketing.yaml
Executable file → Normal file
0
Configuration/Yaml/Csp/GoogleAnalytics4.yaml
Executable file → Normal file
0
Configuration/Yaml/Csp/GoogleAnalytics4.yaml
Executable file → Normal file
0
Configuration/Yaml/Csp/GoogleAnalytics4Signals.yaml
Executable file → Normal file
0
Configuration/Yaml/Csp/GoogleAnalytics4Signals.yaml
Executable file → Normal file
0
Configuration/Yaml/Csp/GoogleAnalytics4SignalsEu.yaml
Executable file → Normal file
0
Configuration/Yaml/Csp/GoogleAnalytics4SignalsEu.yaml
Executable file → Normal file
0
Configuration/Yaml/Csp/GoogleOptimize.yaml
Executable file → Normal file
0
Configuration/Yaml/Csp/GoogleOptimize.yaml
Executable file → Normal file
0
Configuration/Yaml/Csp/GoogleTagManagerPreview.yaml
Executable file → Normal file
0
Configuration/Yaml/Csp/GoogleTagManagerPreview.yaml
Executable file → Normal file
0
Configuration/Yaml/Csp/MapBox.yaml
Executable file → Normal file
0
Configuration/Yaml/Csp/MapBox.yaml
Executable file → Normal file
0
Configuration/Yaml/Csp/UniversalAnalytics.yaml
Executable file → Normal file
0
Configuration/Yaml/Csp/UniversalAnalytics.yaml
Executable file → Normal file
0
Configuration/Yaml/Csp/Youtube.yaml
Executable file → Normal file
0
Configuration/Yaml/Csp/Youtube.yaml
Executable file → Normal file
0
Resources/Private/Language/locallang_core.xlf
Executable file → Normal file
0
Resources/Private/Language/locallang_core.xlf
Executable file → Normal file
0
Resources/Private/Language/locallang_db.xlf
Executable file → Normal file
0
Resources/Private/Language/locallang_db.xlf
Executable file → Normal file
0
Resources/Private/Language/locallang_siteconfiguration.xlf
Executable file → Normal file
0
Resources/Private/Language/locallang_siteconfiguration.xlf
Executable file → Normal file
0
Resources/Private/Templates/Form/ImageManipulationElement.html
Executable file → Normal file
0
Resources/Private/Templates/Form/ImageManipulationElement.html
Executable file → Normal file
4
Resources/Private/Templates/ToolbarItems/ShowReleaseDropDown.html
Executable file → Normal file
4
Resources/Private/Templates/ToolbarItems/ShowReleaseDropDown.html
Executable file → Normal file
@ -1,4 +1,6 @@
|
||||
<html xmlns:core="http://typo3.org/ns/TYPO3/CMS/Core/ViewHelpers" data-namespace-typo3-fluid="true">
|
||||
<html xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers"
|
||||
xmlns:core="http://typo3.org/ns/TYPO3/CMS/Core/ViewHelpers"
|
||||
data-namespace-typo3-fluid="true">
|
||||
|
||||
<h3 class="dropdown-headline"><f:translate id="LLL:EXT:ew_base/Resources/Private/Language/locallang_core.xlf:rm.release" /></h3>
|
||||
<table class="dropdown-table">
|
||||
|
||||
0
Resources/Private/Templates/ToolbarItems/ShowReleaseToolbarItem.html
Executable file → Normal file
0
Resources/Private/Templates/ToolbarItems/ShowReleaseToolbarItem.html
Executable file → Normal file
0
Resources/Public/Icons/Extension.svg
Executable file → Normal file
0
Resources/Public/Icons/Extension.svg
Executable file → Normal file
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.7 KiB |
0
Resources/Public/Icons/Extension_16.svg
Executable file → Normal file
0
Resources/Public/Icons/Extension_16.svg
Executable file → Normal file
|
Before Width: | Height: | Size: 413 B After Width: | Height: | Size: 413 B |
0
Resources/Public/Icons/usercentrics.svg
Executable file → Normal file
0
Resources/Public/Icons/usercentrics.svg
Executable file → Normal file
|
Before Width: | Height: | Size: 677 B After Width: | Height: | Size: 677 B |
0
Resources/Public/JavaScript/form-engine/element/pick-color-from-image.css
Executable file → Normal file
0
Resources/Public/JavaScript/form-engine/element/pick-color-from-image.css
Executable file → Normal file
0
Resources/Public/JavaScript/form-engine/element/pick-color-from-image.js
Executable file → Normal file
0
Resources/Public/JavaScript/form-engine/element/pick-color-from-image.js
Executable file → Normal file
24
composer.json
Executable file → Normal file
24
composer.json
Executable file → Normal file
@ -1,12 +1,10 @@
|
||||
{
|
||||
"name": "evoweb/ew-base",
|
||||
"type": "typo3-cms-extension",
|
||||
"license": ["GPL-2.0-or-later"],
|
||||
"config": {
|
||||
"bin-dir": "bin",
|
||||
"allow-plugins": {
|
||||
"typo3/class-alias-loader": true,
|
||||
"typo3/cms-composer-installers": true
|
||||
"version": "1.0.0",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Evoweb\\EwBase\\": "Classes/"
|
||||
}
|
||||
},
|
||||
"require": {
|
||||
@ -38,24 +36,12 @@
|
||||
"typo3/cms-tstemplate": "*",
|
||||
"typo3/cms-scheduler": "*",
|
||||
|
||||
"helhum/typo3-console": ">8.0",
|
||||
"helhum/typo3-console": "*",
|
||||
"clickstorm/cs-seo": "*"
|
||||
},
|
||||
"require-dev": {
|
||||
"friendsofphp/php-cs-fixer": "^3.57.1",
|
||||
"phpunit/phpunit": "^11.0.3",
|
||||
"typo3/testing-framework": "dev-main"
|
||||
},
|
||||
"minimum-stability": "dev",
|
||||
"prefer-stable": true,
|
||||
"extra": {
|
||||
"typo3/cms": {
|
||||
"extension-key": "ew_base"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Evoweb\\EwBase\\": "Classes/"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
2
ext_localconf.php
Executable file → Normal file
2
ext_localconf.php
Executable file → Normal file
@ -1,6 +1,6 @@
|
||||
<?php
|
||||
|
||||
defined('TYPO3') or die('access denied');
|
||||
defined('TYPO3') or die();
|
||||
|
||||
use Evoweb\EwBase\Form\Element\PickColorFromImage;
|
||||
|
||||
|
||||
0
ext_tables.sql
Executable file → Normal file
0
ext_tables.sql
Executable file → Normal file
Loading…
Reference in New Issue
Block a user