[TASK] Cleanup and replace deprecations

This commit is contained in:
Sebastian Fischer 2024-12-26 21:44:19 +01:00
parent 47e55d8f48
commit c13476bcd0
49 changed files with 540 additions and 1932 deletions

7
.gitattributes vendored
View File

@ -1,5 +1,6 @@
/.github/ export-ignore
/Build/ export-ignore
/Tests/ export-ignore
/.github export-ignore
/Build export-ignore
/Tests export-ignore
/.gitattributes export-ignore
/.gitignore export-ignore
/.gitlab-ci.yml export-ignore

View File

@ -1,6 +1,6 @@
<?php
namespace Evoweb\EwBase\Command;
declare(strict_types=1);
/*
* This file is developed by evoWeb.
@ -13,6 +13,8 @@ namespace Evoweb\EwBase\Command;
* 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;
@ -36,7 +38,7 @@ class ContentElementCommand extends Command
parent::__construct();
}
protected function configure()
protected function configure(): void
{
$this
->setAliases(['kc-sitepackage'])

View File

@ -2,44 +2,22 @@
declare(strict_types=1);
namespace Evoweb\EwBase\Configuration;
/*
* This file is part of TYPO3 CMS-based extension "container" by b13.
* This file is part of TYPO3 CMS-based extension "ew-base" 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.
*/
use Mfc\OAuth2\ResourceServer\GitLab;
use Mfc\OAuth2\ResourceServer\Registry;
namespace Evoweb\EwBase\Configuration;
use TYPO3\CMS\Core\Core\Environment;
use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
use TYPO3\CMS\Core\Utility\GeneralUtility;
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,
@ -70,11 +48,11 @@ class AdditionalConfiguration
/**
* This is needed to override all mail settings instead of merging them.
*
* @var array|string[]
* @var array<string, string>
*/
protected array $mailConfig = [
'transport' => 'smtp',
'transport_smtp_server' => '127.0.0.1:1025'
'transport_smtp_server' => 'mailpit:1025'
];
public function initialize(array $configuration = []): void

View File

@ -1,58 +0,0 @@
<?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;
}
}

View File

@ -19,15 +19,16 @@ namespace Evoweb\EwBase\DataProcessing;
use Doctrine\DBAL\Exception as DBALException;
use Doctrine\DBAL\Result;
use TYPO3\CMS\Backend\FrontendBackendUserAuthentication;
use Psr\Http\Message\ServerRequestInterface;
use TYPO3\CMS\Core\Context\Context;
use TYPO3\CMS\Core\Context\Exception\AspectNotFoundException;
use TYPO3\CMS\Core\Context\LanguageAspect;
use TYPO3\CMS\Core\Database\Connection;
use TYPO3\CMS\Core\Database\ConnectionPool;
use TYPO3\CMS\Core\Database\Query\Expression\CompositeExpression;
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\Domain\Repository\PageRepository;
use TYPO3\CMS\Core\TimeTracker\TimeTracker;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Core\Utility\MathUtility;
@ -35,7 +36,7 @@ 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;
use TYPO3\CMS\Frontend\ContentObject\Exception\ContentRenderingException;
/**
* Fetch records from the database, using the default .select syntax from TypoScript.
@ -63,17 +64,13 @@ use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController;
*/
class DatabaseQueryProcessor implements DataProcessorInterface
{
protected ContentDataProcessor $contentDataProcessor;
protected ContentObjectRenderer $cObj;
/**
* Constructor
*/
public function __construct()
{
$this->contentDataProcessor = GeneralUtility::makeInstance(ContentDataProcessor::class);
}
protected ?ServerRequestInterface $request = null;
protected string $tableName = '';
public function __construct(protected readonly ContentDataProcessor $contentDataProcessor) {}
/**
* Fetches records from the database as an array
@ -84,14 +81,14 @@ class DatabaseQueryProcessor implements DataProcessorInterface
* @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
* @throws ContentRenderingException
*/
public function process(
ContentObjectRenderer $cObj,
array $contentObjectConfiguration,
array $processorConfiguration,
array $processedData
) {
$this->cObj = $cObj;
): array {
if (isset($processorConfiguration['if.']) && !$cObj->checkIf($processorConfiguration['if.'])) {
return $processedData;
}
@ -108,6 +105,13 @@ class DatabaseQueryProcessor implements DataProcessorInterface
unset($processorConfiguration['table']);
}
$this->request = $cObj->getRequest();
$this->tableName = $tableName;
$this->cObj = clone $cObj;
// @extensionScannerIgnoreLine
$this->cObj->start($cObj->data, $tableName);
$this->cObj->setRequest($this->request);
// The variable to be used within the result
$targetVariableName = $cObj->stdWrapValue('as', $processorConfiguration, 'records');
@ -116,8 +120,10 @@ class DatabaseQueryProcessor implements DataProcessorInterface
$request = $cObj->getRequest();
$processedRecordVariables = [];
foreach ($records as $key => $record) {
/** @var ContentObjectRenderer $recordContentObjectRenderer */
$recordContentObjectRenderer = GeneralUtility::makeInstance(ContentObjectRenderer::class);
$recordContentObjectRenderer->start($record, $tableName, $request);
$recordContentObjectRenderer->setRequest($request);
$recordContentObjectRenderer->start($record, $tableName);
$processedRecordVariables[$key] = ['data' => $record];
$processedRecordVariables[$key] = $this->contentDataProcessor->process(
$recordContentObjectRenderer,
@ -137,14 +143,14 @@ class DatabaseQueryProcessor implements DataProcessorInterface
$statement = $this->exec_getQuery($tableName, $queryConfiguration);
$tsfe = $this->getTypoScriptFrontendController();
$pageRepository = $this->getPageRepository();
while ($row = $statement->fetchAssociative()) {
// Versioning preview:
$tsfe->sys_page->versionOL($tableName, $row, true);
$pageRepository->versionOL($tableName, $row, true);
// Language overlay:
if (is_array($row)) {
$row = $tsfe->sys_page->getLanguageOverlay($tableName, $row);
$row = $pageRepository->getLanguageOverlay($tableName, $row);
}
// Might be unset in the language overlay
@ -158,16 +164,15 @@ class DatabaseQueryProcessor implements DataProcessorInterface
protected function exec_getQuery(string $table, array $conf): Result
{
$statement = $this->getQuery($table, $conf);
$connection = GeneralUtility::makeInstance(ConnectionPool::class)->getConnectionForTable($table);
$statement = $this->getQuery($connection, $table, $conf);
return $connection->executeQuery($statement);
}
public function getQuery($table, $conf, $returnQueryArray = false)
public function getQuery(Connection $connection, $table, $conf): string
{
// Resolve stdWrap in these properties first
$connection = GeneralUtility::makeInstance(ConnectionPool::class)->getConnectionForTable($table);
$properties = [
'pidInList',
'uidInList',
@ -200,7 +205,7 @@ class DatabaseQueryProcessor implements DataProcessorInterface
}
}
// Handle PDO-style named parameter markers first
$queryMarkers = $this->getQueryMarkers($table, $conf);
$queryMarkers = $this->cObj->getQueryMarkers($connection, $conf);
// Replace the markers in the non-stdWrap properties
foreach ($queryMarkers as $marker => $markerValue) {
$properties = [
@ -217,7 +222,7 @@ class DatabaseQueryProcessor implements DataProcessorInterface
];
foreach ($properties as $property) {
if ($conf[$property] ?? false) {
$conf[$property] = str_replace('###' . $marker . '###', (string)$markerValue, $conf[$property]);
$conf[$property] = str_replace('###' . $marker . '###', $markerValue, $conf[$property]);
}
}
}
@ -230,10 +235,11 @@ class DatabaseQueryProcessor implements DataProcessorInterface
$pidList = GeneralUtility::trimExplode(',', $conf['pidInList'], true);
array_walk($pidList, function (&$storagePid) {
if ($storagePid === 'this') {
$storagePid = $this->getTypoScriptFrontendController()->id;
$storagePid = $this->getRequest()->getAttribute('frontend.page.information')->getId();
}
});
$expandedPidList = $this->getTypoScriptFrontendController()->sys_page->getPageIdsRecursive($pidList, $conf['recursive']);
$pageRepository = $this->getPageRepository();
$expandedPidList = $pageRepository->getPageIdsRecursive($pidList, $conf['recursive']);
$conf['pidInList'] = implode(',', $expandedPidList);
}
}
@ -241,7 +247,7 @@ class DatabaseQueryProcessor implements DataProcessorInterface
$conf['pidInList'] = 'this';
}
$queryParts = $this->getQueryConstraints($table, $conf);
$queryParts = $this->getQueryConstraints($connection, $table, $conf);
$queryBuilder = $connection->createQueryBuilder();
// @todo Check against getQueryConstraints, can probably use FrontendRestrictions
@ -253,7 +259,7 @@ class DatabaseQueryProcessor implements DataProcessorInterface
$queryBuilder->where($queryParts['where']);
}
if ($queryParts['groupBy'] ?? false) {
if (($queryParts['groupBy'] ?? false) && is_array($queryParts['groupBy'])) {
$queryBuilder->groupBy(...$queryParts['groupBy']);
}
@ -265,15 +271,14 @@ class DatabaseQueryProcessor implements DataProcessorInterface
// Fields:
if ($conf['selectFields'] ?? false) {
$queryBuilder->selectLiteral($this->sanitizeSelectPart($conf['selectFields'], $table));
$queryBuilder->selectLiteral($this->sanitizeSelectPart($connection, $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 = $connection->createQueryBuilder();
$countQueryBuilder->getRestrictions()->removeAll();
$countQueryBuilder->count('*')
->from($table)
@ -293,237 +298,77 @@ class DatabaseQueryProcessor implements DataProcessorInterface
}
} catch (DBALException $e) {
$this->getTimeTracker()->setTSlogMessage($e->getPrevious()->getMessage());
$error = true;
return '';
}
}
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 (isset($conf['begin']) && $conf['begin'] > 0) {
$conf['begin'] = MathUtility::forceIntegerInRange((int)ceil($this->cObj->calc($conf['begin'])), 0);
$queryBuilder->setFirstResult($conf['begin']);
}
if (isset($conf['max'])) {
$conf['max'] = MathUtility::forceIntegerInRange((int)ceil($this->cObj->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;
// 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']
);
}
return '';
}
// Convert the QueryBuilder object into a SQL statement.
$query = $queryBuilder->getSQL();
/**
* 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
);
// 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);
}
$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;
return $query;
}
/**
* Helper function for getQuery(), creating the WHERE clause of the SELECT query
*
* @param Connection $connection
* @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
* @throws AspectNotFoundException
* @throws ContentRenderingException
* @see getQuery()
*/
protected function getQueryConstraints(string $table, array $conf): array
protected function getQueryConstraints(Connection $connection, string $table, array $conf): array
{
// Init:
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($table);
$queryBuilder = $connection->createQueryBuilder();
$expressionBuilder = $queryBuilder->expr();
$tsfe = $this->getTypoScriptFrontendController();
$request = $this->getRequest();
$contentPid = $request->getAttribute('frontend.page.information')->getContentFromPid();
$constraints = [];
$pid_uid_flag = 0;
$enableFieldsIgnore = [];
@ -540,16 +385,16 @@ class DatabaseQueryProcessor implements DataProcessorInterface
);
if (trim($conf['uidInList'] ?? '')) {
$listArr = GeneralUtility::intExplode(',', str_replace('this', (string)$tsfe->contentPid, $conf['uidInList']));
$listArr = GeneralUtility::intExplode(',', str_replace('this', (string)$contentPid, $conf['uidInList']));
// If moved records shall be considered, select via t3ver_oid
if ($considerMovePointers) {
$constraints[] = (string)$expressionBuilder->orX(
$constraints[] = (string)$expressionBuilder->or(
$expressionBuilder->in($table . '.uid', $listArr),
$expressionBuilder->andX(
$expressionBuilder->and(
$expressionBuilder->eq(
$table . '.t3ver_state',
(int)(string)VersionState::cast(VersionState::MOVE_POINTER)
VersionState::MOVE_POINTER->value
),
$expressionBuilder->in($table . '.t3ver_oid', $listArr)
)
@ -561,14 +406,14 @@ class DatabaseQueryProcessor implements DataProcessorInterface
}
// Static_* tables are allowed to be fetched from root page
if (strpos($table, 'static_') === 0) {
if (str_starts_with($table, 'static_')) {
$pid_uid_flag++;
}
if (trim($conf['pidInList'])) {
$listArr = GeneralUtility::intExplode(',', str_replace('this', (string)$tsfe->contentPid, $conf['pidInList']));
$listArr = GeneralUtility::intExplode(',', str_replace('this', (string)$contentPid, $conf['pidInList']));
// Removes all pages which are not visible for the user!
$listArr = $this->checkPidArray($listArr);
$listArr = $this->cObj->checkPidArray($listArr);
if (GeneralUtility::inList($conf['pidInList'], 'root')) {
$listArr[] = 0;
}
@ -586,11 +431,11 @@ class DatabaseQueryProcessor implements DataProcessorInterface
}
// If not uid and not pid then uid is set to 0 - which results in nothing!!
if (!$pid_uid_flag && trim($conf['pidInList'] ?? '') != 'ignore') {
if (!$pid_uid_flag && trim($conf['pidInList'] ?? '') !== 'ignore') {
$constraints[] = $expressionBuilder->eq($table . '.uid', 0);
}
$where = trim((string)$this->cObj->stdWrapValue('where', $conf ?? []));
$where = trim((string)$this->cObj->stdWrapValue('where', $conf));
if ($where) {
$constraints[] = QueryHelper::stripLogicalOperatorPrefix($where);
}
@ -602,26 +447,25 @@ class DatabaseQueryProcessor implements DataProcessorInterface
$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));
}
// default constraints from TCA
$pageRepository = $this->getPageRepository();
$constraints = array_merge(
$constraints,
array_values($pageRepository->getDefaultConstraints($table, $enableFieldsIgnore))
);
// MAKE WHERE:
if (count($constraints) !== 0) {
$queryParts['where'] = $expressionBuilder->andX(...$constraints);
if ($constraints !== []) {
$queryParts['where'] = $expressionBuilder->and(...$constraints);
}
// GROUP BY
$groupBy = trim((string)$this->cObj->stdWrapValue('groupBy', $conf ?? []));
$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 ?? []));
$orderByString = trim((string)$this->cObj->stdWrapValue('orderBy', $conf));
if ($orderByString) {
$queryParts['orderBy'] = QueryHelper::parseOrderBy($orderByString);
}
@ -630,26 +474,6 @@ class DatabaseQueryProcessor implements DataProcessorInterface
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
@ -669,15 +493,14 @@ class DatabaseQueryProcessor implements DataProcessorInterface
* 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
* @throws AspectNotFoundException
*/
protected function getLanguageRestriction(ExpressionBuilder $expressionBuilder, string $table, array $conf, Context $context)
{
protected function getLanguageRestriction(
ExpressionBuilder $expressionBuilder,
string $table,
array $conf,
Context $context
): string|CompositeExpression|null {
$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
@ -706,15 +529,16 @@ class DatabaseQueryProcessor implements DataProcessorInterface
$includeRecordsWithoutDefaultTranslation = isset($conf['includeRecordsWithoutDefaultTranslation.'])
? $this->cObj->stdWrap($conf['includeRecordsWithoutDefaultTranslation'], $conf['includeRecordsWithoutDefaultTranslation.'])
: $conf['includeRecordsWithoutDefaultTranslation'];
$includeRecordsWithoutDefaultTranslation = trim($includeRecordsWithoutDefaultTranslation) !== '';
$includeRecordsWithoutDefaultTranslation = trim((string)$includeRecordsWithoutDefaultTranslation);
$includeRecordsWithoutDefaultTranslation = $includeRecordsWithoutDefaultTranslation !== '' && $includeRecordsWithoutDefaultTranslation !== '0';
} 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->or(
$languageQuery,
$expressionBuilder->andX(
$expressionBuilder->and(
$expressionBuilder->eq($table . '.' . $localizationParentField, 0),
$expressionBuilder->eq($languageField, $languageAspect->getContentId())
)
@ -723,7 +547,7 @@ class DatabaseQueryProcessor implements DataProcessorInterface
return $languageQuery;
}
// No overlays = only fetch records given for the requested language and "all languages"
return $expressionBuilder->in($languageField, [$languageAspect->getContentId(), -1]);
return (string)$expressionBuilder->in($languageField, [$languageAspect->getContentId(), -1]);
}
/**
@ -732,21 +556,18 @@ class DatabaseQueryProcessor implements DataProcessorInterface
* 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
protected function sanitizeSelectPart(Connection $connection, 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'];
$languageField = $GLOBALS['TCA'][$table]['ctrl']['languageField'] ?? false;
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;
@ -754,6 +575,12 @@ class DatabaseQueryProcessor implements DataProcessorInterface
$selectPart .= ', ' . $connection->quoteIdentifier($table . '.' . $field) . ' AS ' . $connection->quoteIdentifier($field);
}
}
if (is_string($languageField)) {
$match = $matchStart . $languageField . $matchEnd;
if (!preg_match($match, $selectPart)) {
$selectPart .= ', ' . $connection->quoteIdentifier($table . '.' . $languageField) . ' AS ' . $connection->quoteIdentifier($languageField);
}
}
if ($GLOBALS['TCA'][$table]['ctrl']['versioningWS'] ?? false) {
foreach ($wsFields as $field) {
$match = $matchStart . $field . $matchEnd;
@ -766,66 +593,24 @@ class DatabaseQueryProcessor implements DataProcessorInterface
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)
protected function getPageRepository(): PageRepository
{
$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 GeneralUtility::makeInstance(PageRepository::class);
}
/**
* @return TimeTracker
*/
protected function getTimeTracker()
protected function getTimeTracker(): TimeTracker
{
return GeneralUtility::makeInstance(TimeTracker::class);
}
/**
* Returns the current BE user.
*
* @return FrontendBackendUserAuthentication
*/
protected function getFrontendBackendUser()
public function getRequest(): ServerRequestInterface
{
return $GLOBALS['BE_USER'];
}
/**
* @return TypoScriptFrontendController|null
*/
protected function getTypoScriptFrontendController()
{
return $GLOBALS['TSFE'] ?? null;
if ($this->request instanceof ServerRequestInterface) {
return $this->request;
}
throw new ContentRenderingException(
'PSR-7 request is missing in ContentObjectRenderer. Inject with start(), setRequest() or provide via $GLOBALS[\'TYPO3_REQUEST\'].',
1607172972
);
}
}

View File

@ -1,17 +1,33 @@
<?php
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\EventListener;
use TYPO3\CMS\Core\Configuration\ExtensionConfiguration;
use Psr\Http\Message\ServerRequestInterface;
use TYPO3\CMS\Core\Core\RequestId;
use TYPO3\CMS\Core\Page\AssetCollector;
use TYPO3\CMS\Core\Page\Event\BeforeStylesheetsRenderingEvent;
use TYPO3\CMS\Core\Site\Entity\Site;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Core\Utility\PathUtility;
class CssMerger
readonly class CssMerger
{
public function __construct(protected ExtensionConfiguration $extensionConfiguration)
{
public function __construct(
private RequestId $requestId
) {
}
public function __invoke(BeforeStylesheetsRenderingEvent $event): void
@ -29,12 +45,23 @@ class CssMerger
return;
}
$inlineCssStyles = $this->extensionConfiguration->get('ew_base', 'inlineCssStyles');
if ($inlineCssStyles) {
/** @var Site $site */
$site = $this->getRequest()->getAttribute('site');
if (
$site instanceof Site
&& ($siteSettings = $site->getSettings())
&& !$siteSettings->isEmpty()
&& $siteSettings->get('ew-base.inlineCssStyles')
) {
$assetCollector->addInlineStyleSheet('ew_base', $styles, [], ['priority' => true]);
} else {
$temporaryFile = GeneralUtility::writeStyleSheetContentToTemporaryFile($styles);
$assetCollector->addStyleSheet('combined_styles', $temporaryFile);
// @extensionScannerIgnoreLine
$assetCollector->addStyleSheet(
'ew_base_combined_styles',
$temporaryFile,
['nounce' => $this->requestId->nonce]
);
}
}
}
@ -96,4 +123,9 @@ class CssMerger
$content
);
}
protected function getRequest(): ServerRequestInterface
{
return $GLOBALS['TYPO3_REQUEST'];
}
}

View File

@ -1,25 +0,0 @@
<?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;
}
}

View File

@ -1,14 +1,32 @@
<?php
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\EventListener;
use TYPO3\CMS\Core\Core\RequestId;
use TYPO3\CMS\Core\Page\AssetCollector;
use TYPO3\CMS\Core\Page\Event\BeforeJavaScriptsRenderingEvent;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Core\Utility\PathUtility;
class JsMerger
readonly class JsMerger
{
public function __construct(private RequestId $requestId)
{
}
public function __invoke(BeforeJavaScriptsRenderingEvent $event): void
{
if ($event->isInline() && $event->isPriority()) {
@ -22,7 +40,11 @@ class JsMerger
$scripts = trim(implode(LF, $scripts));
if (!empty($scripts)) {
$temporaryFile = GeneralUtility::writeJavaScriptContentToTemporaryFile($scripts);
$assetCollector->addJavaScript('combined_scripts', $temporaryFile);
$assetCollector->addJavaScript(
'ew_base_combined_scripts',
$temporaryFile,
['nounce' => $this->requestId->nonce]
);
}
}
}
@ -90,7 +112,7 @@ class JsMerger
'url("' . $relativeFilePath . '/..',
'url(\'' . $relativeFilePath . '/..',
],
$content
$content,
);
}
}

View File

@ -0,0 +1,58 @@
<?php
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\EventListener;
use TYPO3\CMS\Backend\Backend\Event\SystemInformationToolbarCollectorEvent;
use TYPO3\CMS\Backend\Toolbar\InformationStatus;
use TYPO3\CMS\Core\Core\Environment;
use TYPO3\CMS\Core\Localization\LanguageService;
use TYPO3\CMS\Core\Utility\GeneralUtility;
class ReleaseToolbarItem
{
public function __invoke(SystemInformationToolbarCollectorEvent $event): void
{
$systemInformationToolbarItem = $event->getToolbarItem();
$release = $this->getRelease();
if ($release !== []) {
$label = $this->getLanguageService()->sL(
'LLL:EXT:ew_base/Resources/Private/Language/locallang_core.xlf:rm.release_label-'
. ($release['isTag'] ? 'tag' : 'branch')
);
$systemInformationToolbarItem->addSystemInformation(
$label,
$release['release'],
'information-git',
InformationStatus::OK
);
}
}
protected function getRelease(): array
{
$release = GeneralUtility::getUrl(Environment::getProjectPath() . '/release');
return $release ? [
'release' => trim($release),
'isTag' => str_contains($release, '.'),
] : [];
}
private function getLanguageService(): LanguageService
{
return $GLOBALS['LANG'];
}
}

View File

@ -2,8 +2,6 @@
declare(strict_types=1);
namespace Evoweb\EwBase\Form\Element;
/*
* This file is developed by evoWeb.
*
@ -15,11 +13,14 @@ namespace Evoweb\EwBase\Form\Element;
* LICENSE.txt file that was distributed with this source code.
*/
namespace Evoweb\EwBase\Form\Element;
use TYPO3\CMS\Backend\Form\Element\AbstractFormElement;
use TYPO3\CMS\Backend\View\BackendViewFactory;
use TYPO3\CMS\Core\Imaging\ImageManipulation\Area;
use TYPO3\CMS\Core\Imaging\ImageManipulation\CropVariantCollection;
use TYPO3\CMS\Core\Imaging\ImageManipulation\InvalidConfigurationException;
use TYPO3\CMS\Core\Imaging\ImageManipulation\Ratio;
use TYPO3\CMS\Core\Page\JavaScriptModuleInstruction;
use TYPO3\CMS\Core\Resource\Exception\FileDoesNotExistException;
use TYPO3\CMS\Core\Resource\File;
@ -127,15 +128,12 @@ class PickColorFromImage extends AbstractFormElement
$config = $this->processConfiguration($config, $parameterArray['itemFormElValue'], $file);
$fieldInformationResult = $this->renderFieldInformation();
$fieldInformationHtml = $fieldInformationResult['html'];
$resultArray = $this->mergeChildReturnIntoExistingResult($resultArray, $fieldInformationResult, false);
$fieldControlResult = $this->renderFieldControl();
$fieldControlHtml = $fieldControlResult['html'];
$resultArray = $this->mergeChildReturnIntoExistingResult($resultArray, $fieldControlResult, false);
$fieldWizardResult = $this->renderFieldWizard();
$fieldWizardHtml = $fieldWizardResult['html'];
$resultArray = $this->mergeChildReturnIntoExistingResult($resultArray, $fieldWizardResult, false);
$width = $this->formMaxWidth(
@ -147,9 +145,9 @@ class PickColorFromImage extends AbstractFormElement
);
$arguments = [
'fieldInformation' => $fieldInformationHtml,
'fieldControl' => $fieldControlHtml,
'fieldWizard' => $fieldWizardHtml,
'fieldInformation' => $fieldInformationResult['html'],
'fieldControl' => $fieldControlResult['html'],
'fieldWizard' => $fieldWizardResult['html'],
'isAllowedFileExtension' => in_array(
strtolower($file->getExtension()),
GeneralUtility::trimExplode(',', strtolower($config['allowedExtensions'])),
@ -185,10 +183,8 @@ class PickColorFromImage extends AbstractFormElement
$arguments['formEngine']['validation'] = $this->getValidationDataAsJsonString(['required' => true]);
}
}
$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 = $this->backendViewFactory->create($this->data['request'], ['evoweb/ew-base']);
$view->assignMultiple($arguments);
$resultArray['html'] = $view->render('Form/ImageManipulationElement');
@ -211,12 +207,19 @@ 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);
@ -225,12 +228,17 @@ class PickColorFromImage extends AbstractFormElement
$cropVariants = [];
foreach ($config['cropVariants'] as $id => $cropVariant) {
// Filter allowed aspect ratios
$cropVariant['allowedAspectRatios'] = array_filter(
$cropVariant['allowedAspectRatios'] ?? [],
static function ($aspectRatio) {
return !(bool)($aspectRatio['disabled'] ?? false);
}
);
$cropVariant['allowedAspectRatios'] = array_filter($cropVariant['allowedAspectRatios'] ?? [], static function (array $aspectRatio): bool {
return !(bool)($aspectRatio['disabled'] ?? false);
});
// Aspect ratios may not contain a "." character, see Ratio::__construct()
// To match them again properly, same replacement is required here.
$preparedAllowedAspectRatios = [];
foreach ($cropVariant['allowedAspectRatios'] as $aspectRatio => $aspectRatioDefinition) {
$preparedAllowedAspectRatios[Ratio::prepareAspectRatioId($aspectRatio)] = $aspectRatioDefinition;
}
$cropVariant['allowedAspectRatios'] = $preparedAllowedAspectRatios;
// Ignore disabled crop variants
if (!empty($cropVariant['disabled'])) {
@ -238,10 +246,7 @@ class PickColorFromImage extends AbstractFormElement
}
if (empty($cropVariant['allowedAspectRatios'])) {
throw new InvalidConfigurationException(
'Crop variants configuration ' . $id . ' contains no allowed aspect ratios',
1620147893
);
throw new InvalidConfigurationException('Crop variants configuration ' . $id . ' contains no allowed aspect ratios', 1620147893);
}
// Enforce a crop area (default is full image)
@ -254,8 +259,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;
}
@ -267,10 +272,7 @@ class PickColorFromImage extends AbstractFormElement
$elementValue = (string)$cropVariantCollection;
}
$config['cropVariants'] = $cropVariantCollection->asArray();
$config['allowedExtensions'] = implode(
', ',
GeneralUtility::trimExplode(',', $config['allowedExtensions'], true)
);
$config['allowedExtensions'] = implode(', ', GeneralUtility::trimExplode(',', $config['allowedExtensions'], true));
return $config;
}
}

View File

@ -1,34 +0,0 @@
<?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;
}
}

View File

@ -1,98 +0,0 @@
<?php
namespace Evoweb\EwBase\ToolbarItems;
/*
* 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 Psr\Http\Message\ServerRequestInterface;
use TYPO3\CMS\Backend\Toolbar\RequestAwareToolbarItemInterface;
use TYPO3\CMS\Backend\Toolbar\ToolbarItemInterface;
use TYPO3\CMS\Backend\View\BackendViewFactory;
use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
use TYPO3\CMS\Core\Core\Environment;
use TYPO3\CMS\Core\Utility\GeneralUtility;
class ReleaseToolbarItem implements ToolbarItemInterface, RequestAwareToolbarItemInterface
{
private ServerRequestInterface $request;
public function __construct(
private readonly BackendViewFactory $backendViewFactory,
) {
}
public function setRequest(ServerRequestInterface $request): void
{
$this->request = $request;
}
public function checkAccess(): bool
{
$result = false;
$backendUser = $this->getBackendUser();
if ($backendUser->isAdmin()) {
$result = true;
}
if ($backendUser->getTSConfig()['options.']['showSystemInformation'] ?? false) {
$result = true;
}
$release = $this->getRelease();
if (empty($release)) {
$result = false;
}
return $result;
}
public function getItem(): string
{
$view = $this->backendViewFactory->create($this->request, ['typo3/cms-backend', 'evoweb/ew-base']);
return $view->render('ToolbarItems/ShowReleaseToolbarItem');
}
public function hasDropDown(): bool
{
return true;
}
public function getDropDown(): string
{
$view = $this->backendViewFactory->create($this->request, ['typo3/cms-backend', 'evoweb/ew-base']);
$view->assignMultiple([
'release' => $this->getRelease(),
]);
return $view->render('ToolbarItems/ShowReleaseDropDown');
}
public function getAdditionalAttributes(): array
{
return [];
}
public function getIndex(): int
{
return 20;
}
protected function getRelease(): array
{
$release = GeneralUtility::getUrl(Environment::getProjectPath() . '/release');
return $release ? [
'release' => trim($release),
'isTag' => str_contains($release, '.'),
] : [];
}
protected function getBackendUser(): BackendUserAuthentication
{
return $GLOBALS['BE_USER'];
}
}

View File

@ -1,96 +0,0 @@
<?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);
}
}

View File

@ -1,268 +0,0 @@
<?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;
}
}

View File

@ -1,106 +0,0 @@
<?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);
}
}

View File

@ -1,168 +0,0 @@
<?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;
}
}

View File

@ -2,6 +2,17 @@
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;

View File

@ -1,6 +1,6 @@
<?php
namespace Evoweb\EwBase\ViewHelpers\Array;
declare(strict_types=1);
/*
* This file is developed by evoWeb.
@ -13,42 +13,29 @@ namespace Evoweb\EwBase\ViewHelpers\Array;
* LICENSE.txt file that was distributed with this source code.
*/
use TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface;
namespace Evoweb\EwBase\ViewHelpers\Array;
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()
public function initializeArguments(): void
{
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 = !is_null($arguments['value']) ? $arguments['value'] : $renderChildrenClosure();
public function render(): array
{
$array = $this->arguments['array'] ?: [];
$key = $this->arguments['key'];
$value = !is_null($this->arguments['value']) ? $this->arguments['value'] : $this->renderChildren();
return array_merge($array, [$key => $value]);
}

View File

@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
/*
* This file is developed by evoWeb.
*
@ -13,9 +15,7 @@
namespace Evoweb\EwBase\ViewHelpers\Array;
use TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface;
use TYPO3Fluid\Fluid\Core\ViewHelper\AbstractViewHelper;
use TYPO3Fluid\Fluid\Core\ViewHelper\Traits\CompileWithRenderStatic;
/**
* Explode ViewHelper
@ -30,9 +30,7 @@ use TYPO3Fluid\Fluid\Core\ViewHelper\Traits\CompileWithRenderStatic;
*/
class ExplodeViewHelper extends AbstractViewHelper
{
use CompileWithRenderStatic;
protected static string $method = 'explode';
protected string $method = 'explode';
public function initializeArguments(): void
{
@ -52,20 +50,17 @@ class ExplodeViewHelper extends AbstractViewHelper
);
}
public static function renderStatic(
array $arguments,
\Closure $renderChildrenClosure,
RenderingContextInterface $renderingContext
): mixed {
$content = $arguments['content'] ?? $renderChildrenClosure();
$glue = static::resolveGlue($arguments);
$content = call_user_func_array(static::$method, [$glue, $content]);
public function render(): mixed
{
$content = $this->arguments['content'] ?? $this->renderChildren();
$glue = $this->resolveGlue($this->arguments);
$content = call_user_func_array($this->method, [$glue, $content]);
$as = $arguments['as'];
$as = $this->arguments['as'];
if ($as !== null) {
$templateVariableContainer = $renderingContext->getVariableProvider();
$templateVariableContainer = $this->renderingContext->getVariableProvider();
$templateVariableContainer->add($as, $content);
$output = $renderChildrenClosure();
$output = $this->renderChildren();
$templateVariableContainer->remove($as);
} else {
$output = $content;
@ -73,7 +68,7 @@ class ExplodeViewHelper extends AbstractViewHelper
return $output;
}
protected static function resolveGlue(array $arguments): string
protected function resolveGlue(array $arguments): string
{
$glue = $arguments['glue'];
if (str_contains($glue, ':') && strlen($glue) > 1) {

View File

@ -15,24 +15,21 @@ 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;
use TYPO3\CMS\Core\Imaging\IconFactory;
use TYPO3\CMS\Core\Imaging\IconSize;
use TYPO3\CMS\Core\Localization\LanguageService;
use TYPO3\CMS\Core\Resource\ProcessedFile;
use TYPO3\CMS\Core\Type\Bitmask\Permission;
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 ThumbnailViewHelper extends AbstractViewHelper
{
use CompileWithRenderStatic;
/**
* Initializes the arguments
*/
public function initializeArguments()
public function initializeArguments(): void
{
parent::initializeArguments();
$this->registerArgument('row', 'array', 'content data', true);
@ -43,34 +40,47 @@ class ThumbnailViewHelper extends AbstractViewHelper
/**
* 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
) {
$row = $arguments['row'];
$tableName = $arguments['tableName'];
$fieldName = $arguments['fieldName'];
public function render(): string
{
$table = $this->arguments['tableName'];
$field = $this->arguments['fieldName'];
$row = $this->arguments['row'];
return self::linkEditContent(
BackendUtility::thumbCode(row: $row, table: $tableName, field: $fieldName, linkInfoPopup: false),
$row
$fileReferences = BackendUtility::resolveFileReferences($table, $field, $row);
$fileObject = is_array($fileReferences) ? $fileReferences[0]->getOriginalFile() : null;
if ($fileObject && $fileObject->isMissing()) {
/** @var IconFactory $iconFactory */
$iconFactory = GeneralUtility::makeInstance(IconFactory::class);
$label = $this->getLanguageService()->sL(
'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:warning.file_missing'
);
return $iconFactory
->getIcon('mimetypes-other-other', IconSize::MEDIUM, 'overlay-missing')
->setTitle($label . ' ' . $fileObject->getName())
->render();
}
$previewFile = $fileObject->process(
ProcessedFile::CONTEXT_IMAGEPREVIEW,
[
'width' => 64,
'height' => 64,
]
);
return $this->linkEditContent('<img src="' . $previewFile->getPublicUrl() . '"/>', $row );
}
protected static function linkEditContent(string $linkText, $row): string
protected function linkEditContent(string $linkText, $row): string
{
if (empty($linkText)) {
return $linkText;
}
$backendUser = self::getBackendUser();
$backendUser = $this->getBackendUser();
if (
$backendUser->check('tables_modify', 'tt_content')
&& $backendUser->recordEditAccessInternals('tt_content', $row)
@ -86,14 +96,15 @@ class ThumbnailViewHelper extends AbstractViewHelper
$row['uid'] => 'edit',
],
],
'returnUrl' => $GLOBALS['TYPO3_REQUEST']->getAttribute('normalizedParams')->getRequestUri()
// @extensionScannerIgnoreLine
'returnUrl' => $this->getRequest()->getAttribute('normalizedParams')->getRequestUri()
. '#element-tt_content-' . $row['uid'],
];
/** @var UriBuilder $uriBuilder */
$uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
$url = (string)$uriBuilder->buildUriFromRoute('record_edit', $urlParameters);
return '<a href="' . htmlspecialchars($url) . '" title="'
. htmlspecialchars(self::getLanguageService()->sL(
. htmlspecialchars($this->getLanguageService()->sL(
'LLL:EXT:typo3/sysext/backend/Resources/Private/Language/locallang_layout.xlf:edit'
))
. '">' . $linkText . '</a>';
@ -101,13 +112,18 @@ class ThumbnailViewHelper extends AbstractViewHelper
return $linkText;
}
protected static function getBackendUser(): BackendUserAuthentication
protected function getBackendUser(): BackendUserAuthentication
{
return $GLOBALS['BE_USER'];
}
protected static function getLanguageService(): LanguageService
protected function getLanguageService(): LanguageService
{
return $GLOBALS['LANG'];
}
protected function getRequest(): ServerRequestInterface
{
return $GLOBALS['TYPO3_REQUEST'];
}
}

View File

@ -1,14 +1,21 @@
<?php
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\ViewHelpers\Condition;
/*
* 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\AbstractConditionViewHelper;
/**
@ -19,21 +26,14 @@ use TYPO3Fluid\Fluid\Core\ViewHelper\AbstractConditionViewHelper;
*/
class InArrayViewHelper extends AbstractConditionViewHelper
{
/**
* Initialize arguments
*/
public function initializeArguments()
public function initializeArguments(): void
{
parent::initializeArguments();
$this->registerArgument('haystack', 'array', 'haystack', true);
$this->registerArgument('needle', 'mixed', 'needle', true);
}
/**
* @param array $arguments
* @return bool
*/
protected static function evaluateCondition($arguments = null)
public static function verdict(array $arguments, RenderingContextInterface $renderingContext): bool
{
$array = $arguments['haystack']->toArray();
return in_array($arguments['needle'], $array);

View File

@ -1,14 +1,21 @@
<?php
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\ViewHelpers\Condition;
/*
* 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\AbstractConditionViewHelper;
/**
@ -19,22 +26,15 @@ use TYPO3Fluid\Fluid\Core\ViewHelper\AbstractConditionViewHelper;
*/
class StringContainsViewHelper extends AbstractConditionViewHelper
{
/**
* Initialize arguments
*/
public function initializeArguments()
public function initializeArguments(): void
{
parent::initializeArguments();
$this->registerArgument('haystack', 'string', 'haystack', true);
$this->registerArgument('needle', 'string', 'need', true);
}
/**
* @param array $arguments
* @return bool
*/
protected static function evaluateCondition($arguments = null)
public static function verdict(array $arguments, RenderingContextInterface $renderingContext): bool
{
return false !== strpos($arguments['haystack'], $arguments['needle']);
return str_contains($arguments['haystack'], $arguments['needle']);
}
}

View File

@ -1,24 +1,27 @@
<?php
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\ViewHelpers\Context;
/*
* 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 TYPO3\CMS\Core\Core\Environment;
use TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface;
use TYPO3Fluid\Fluid\Core\ViewHelper\AbstractConditionViewHelper;
class DevelopmentViewHelper extends AbstractConditionViewHelper
{
/**
* @param array $arguments
* @return bool
*/
protected static function evaluateCondition($arguments = null)
public static function verdict(array $arguments, RenderingContextInterface $renderingContext): bool
{
return Environment::getContext()->isDevelopment();
}

View File

@ -1,24 +1,27 @@
<?php
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\ViewHelpers\Context;
/*
* 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 TYPO3\CMS\Core\Core\Environment;
use TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface;
use TYPO3Fluid\Fluid\Core\ViewHelper\AbstractConditionViewHelper;
class ProductionViewHelper extends AbstractConditionViewHelper
{
/**
* @param array $arguments
* @return bool
*/
protected static function evaluateCondition($arguments = null)
public static function verdict(array $arguments, RenderingContextInterface $renderingContext): bool
{
return Environment::getContext()->isProduction();
}

View File

@ -1,24 +1,27 @@
<?php
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\ViewHelpers\Context;
/*
* 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 TYPO3\CMS\Core\Core\Environment;
use TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface;
use TYPO3Fluid\Fluid\Core\ViewHelper\AbstractConditionViewHelper;
class StagingViewHelper extends AbstractConditionViewHelper
{
/**
* @param array $arguments
* @return bool
*/
protected static function evaluateCondition($arguments = null)
public static function verdict(array $arguments, RenderingContextInterface $renderingContext): bool
{
return 'Production/Staging' === (string)Environment::getContext();
}

View File

@ -1,6 +1,6 @@
<?php
namespace Evoweb\EwBase\ViewHelpers;
declare(strict_types=1);
/*
* This file is developed by evoWeb.
@ -13,10 +13,10 @@ namespace Evoweb\EwBase\ViewHelpers;
* LICENSE.txt file that was distributed with this source code.
*/
namespace Evoweb\EwBase\ViewHelpers;
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;
/**
@ -33,8 +33,6 @@ use TYPO3Fluid\Fluid\Core\ViewHelper\AbstractViewHelper;
*/
class FixFlexformForExtbaseViewHelper extends AbstractViewHelper
{
use CompileWithRenderStatic;
/**
* @var boolean
*/
@ -46,30 +44,20 @@ class FixFlexformForExtbaseViewHelper extends AbstractViewHelper
$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();
public function render(): string
{
$templateVariableContainer = $this->renderingContext->getVariableProvider();
/** @var FlexFormTools $flexFormTools */
$flexFormTools = GeneralUtility::makeInstance(FlexFormTools::class);
$data = $arguments['data'];
$data = $this->arguments['data'];
if (is_array($data['pi_flexform'])) {
$data['pi_flexform'] = $flexFormTools->flexArray2Xml($data['pi_flexform']);
}
$templateVariableContainer->add('data', $data);
$output = $renderChildrenClosure();
$output = $this->renderChildren();
$templateVariableContainer->remove('data');
return $output;

View File

@ -1,6 +1,6 @@
<?php
namespace Evoweb\EwBase\ViewHelpers;
declare(strict_types=1);
/*
* This file is developed by evoWeb.
@ -13,10 +13,10 @@ namespace Evoweb\EwBase\ViewHelpers;
* LICENSE.txt file that was distributed with this source code.
*/
namespace Evoweb\EwBase\ViewHelpers;
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 =
@ -32,14 +32,12 @@ use TYPO3Fluid\Fluid\Core\ViewHelper\Traits\CompileWithRenderStatic;
*/
class FlexFormViewHelper extends AbstractViewHelper
{
use CompileWithRenderStatic;
/**
* @var boolean
*/
protected $escapeOutput = false;
public function initializeArguments()
public function initializeArguments(): void
{
parent::initializeArguments();
$this->registerArgument('data', 'array', 'Array to get flex form data from', true);
@ -47,33 +45,23 @@ class FlexFormViewHelper extends AbstractViewHelper
$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
) {
public function render(): string
{
$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']]);
if (is_array($this->arguments['data'])) {
if (isset($this->arguments['data'][$this->arguments['fieldName']])) {
$data = is_array($this->arguments['data'][$this->arguments['fieldName']]) ?
$this->arguments['data'][$this->arguments['fieldName']] :
GeneralUtility::xml2array($this->arguments['data'][$this->arguments['fieldName']]);
$data = $data['data'] ?? $data;
}
}
$templateVariableContainer = $renderingContext->getVariableProvider();
$templateVariableContainer->add($arguments['as'], $data);
$content = $renderChildrenClosure();
$templateVariableContainer->remove($arguments['as']);
$templateVariableContainer = $this->renderingContext->getVariableProvider();
$templateVariableContainer->add($this->arguments['as'], $data);
$content = $this->renderChildren();
$templateVariableContainer->remove($this->arguments['as']);
return $content;
}

View File

@ -1,60 +0,0 @@
<?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 TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface;
use TYPO3Fluid\Fluid\Core\ViewHelper\AbstractViewHelper;
use TYPO3Fluid\Fluid\Core\ViewHelper\Traits\CompileWithRenderStatic;
class HashViewHelper extends AbstractViewHelper
{
use CompileWithRenderStatic;
/**
* @var boolean
*/
protected $escapeOutput = false;
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
) {
$result = '';
if (
$arguments['action'] !== null
&& $arguments['arguments'] !== null
&& isset($arguments['arguments']['user'])
) {
$result = \TYPO3\CMS\Core\Utility\GeneralUtility::hmac(
$arguments['action'] . '::' . $arguments['arguments']['user']
);
}
return $result;
}
}

View File

@ -1,56 +0,0 @@
<?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]);
}
}

View File

@ -1,93 +0,0 @@
<?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;
}
}

View File

@ -2,8 +2,6 @@
declare(strict_types=1);
namespace Evoweb\EwBase\ViewHelpers;
/*
* This file is developed by evoWeb.
*
@ -15,10 +13,11 @@ namespace Evoweb\EwBase\ViewHelpers;
* LICENSE.txt file that was distributed with this source code.
*/
namespace Evoweb\EwBase\ViewHelpers;
use TYPO3\CMS\Core\Resource\Exception\InvalidFileException;
use TYPO3\CMS\Core\Utility\PathUtility;
use TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface;
use TYPO3Fluid\Fluid\Core\ViewHelper\AbstractViewHelper;
use TYPO3Fluid\Fluid\Core\ViewHelper\Traits\CompileWithRenderStatic;
/**
* = Examples =
@ -34,34 +33,23 @@ use TYPO3Fluid\Fluid\Core\ViewHelper\Traits\CompileWithRenderStatic;
*/
class PublicPathViewHelper extends AbstractViewHelper
{
use CompileWithRenderStatic;
/**
* @var boolean
*/
protected $escapeOutput = false;
protected static ?array $frontendGroupIds = null;
public function initializeArguments()
public function initializeArguments(): void
{
parent::initializeArguments();
$this->registerArgument('path', 'string', 'Extension resource path', true);
}
/**
* @param array $arguments
* @param \Closure $renderChildrenClosure
* @param RenderingContextInterface $renderingContext
*
* @return bool
* @throws InvalidFileException
*/
public static function renderStatic(
array $arguments,
\Closure $renderChildrenClosure,
RenderingContextInterface $renderingContext
) {
$path = (string)$arguments['path'];
public function renderStatic(): string
{
$path = (string)$this->arguments['path'];
return PathUtility::getPublicResourceWebPath($path);
}
}

View File

@ -1,6 +1,6 @@
<?php
namespace Evoweb\EwBase\ViewHelpers;
declare(strict_types=1);
/*
* This file is developed by evoWeb.
@ -13,9 +13,9 @@ namespace Evoweb\EwBase\ViewHelpers;
* LICENSE.txt file that was distributed with this source code.
*/
use TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface;
namespace Evoweb\EwBase\ViewHelpers;
use TYPO3Fluid\Fluid\Core\ViewHelper\AbstractViewHelper;
use TYPO3Fluid\Fluid\Core\ViewHelper\Traits\CompileWithContentArgumentAndRenderStatic;
/**
* Variable assigning ViewHelper
@ -42,31 +42,20 @@ use TYPO3Fluid\Fluid\Core\ViewHelper\Traits\CompileWithContentArgumentAndRenderS
*/
class ReplaceViewHelper extends AbstractViewHelper
{
use CompileWithContentArgumentAndRenderStatic;
public function initializeArguments()
public function initializeArguments(): void
{
$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
) {
$content = $arguments['value'];
public function render(): string
{
$content = $this->arguments['value'];
if ($content === null) {
$content = $renderChildrenClosure();
$content = $this->renderChildren();
}
return str_replace($arguments['search'], $arguments['replace'], $content);
return str_replace($this->arguments['search'], $this->arguments['replace'], $content);
}
}

View File

@ -1,6 +1,6 @@
<?php
namespace Evoweb\EwBase\ViewHelpers;
declare(strict_types=1);
/*
* This file is developed by evoWeb.
@ -13,12 +13,13 @@ namespace Evoweb\EwBase\ViewHelpers;
* LICENSE.txt file that was distributed with this source code.
*/
use TYPO3\CMS\Core\Imaging\Icon;
namespace Evoweb\EwBase\ViewHelpers;
use TYPO3\CMS\Core\Imaging\IconSize;
use TYPO3\CMS\Core\Imaging\IconFactory;
use TYPO3\CMS\Core\Type\Icon\IconState;
use TYPO3\CMS\Core\Imaging\IconState;
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;
/**
* Displays icon identified by icon identifier.
@ -61,10 +62,8 @@ use TYPO3Fluid\Fluid\Core\ViewHelper\Traits\CompileWithRenderStatic;
* </span>
* </span>
*/
class SvgViewHelper extends \TYPO3Fluid\Fluid\Core\ViewHelper\AbstractViewHelper
class SvgViewHelper extends AbstractViewHelper
{
use CompileWithRenderStatic;
/**
* ViewHelper returns HTML, thus we need to disable output escaping
*
@ -75,30 +74,25 @@ class SvgViewHelper extends \TYPO3Fluid\Fluid\Core\ViewHelper\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, Icon::SIZE_SMALL);
$this->registerArgument('overlay', 'string', 'Identifier of an overlay icon as registered in the Icon Registry.', false);
$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.');
$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('alternativeMarkupIdentifier', 'string', 'Alternative icon identifier. Takes precedence over the identifier if supported by the IconProvider.');
}
/**
* 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
) {
$identifier = $arguments['identifier'];
$size = $arguments['size'];
$overlay = $arguments['overlay'];
$state = IconState::cast($arguments['state']);
$alternativeMarkupIdentifier = $arguments['alternativeMarkupIdentifier'];
public function render(): string
{
$identifier = $this->arguments['identifier'];
$size = $this->arguments['size'];
$overlay = $this->arguments['overlay'];
$state = IconState::tryFrom($this->arguments['state']);
$alternativeMarkupIdentifier = $this->arguments['alternativeMarkupIdentifier'];
/** @var IconFactory $iconFactory */
$iconFactory = GeneralUtility::makeInstance(IconFactory::class);
return $iconFactory->getIcon($identifier, $size, $overlay, $state)->getMarkup($alternativeMarkupIdentifier);
}

View File

@ -1,6 +1,6 @@
<?php
namespace Evoweb\EwBase\ViewHelpers;
declare(strict_types=1);
/*
* This file is developed by evoWeb.
@ -13,40 +13,28 @@ namespace Evoweb\EwBase\ViewHelpers;
* LICENSE.txt file that was distributed with this source code.
*/
use TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface;
namespace Evoweb\EwBase\ViewHelpers;
use TYPO3Fluid\Fluid\Core\ViewHelper\AbstractViewHelper;
use TYPO3Fluid\Fluid\Core\ViewHelper\Traits\CompileWithRenderStatic;
class TrimViewHelper extends AbstractViewHelper
{
use CompileWithRenderStatic;
/**
* @var bool
*/
protected $escapeOutput = false;
public function initializeArguments()
public function initializeArguments(): void
{
parent::initializeArguments();
$this->registerArgument('content', 'string', 'Content to be trimmed');
$this->registerArgument('characters', 'string', 'Characters to be removed', false);
$this->registerArgument('characters', 'string', 'Characters to be removed');
}
/**
* @param array $arguments
* @param \Closure $renderChildrenClosure
* @param RenderingContextInterface $renderingContext
*
* @return string
*/
public static function renderStatic(
array $arguments,
\Closure $renderChildrenClosure,
RenderingContextInterface $renderingContext
) {
$content = $arguments['content'] ? $arguments['content'] : $renderChildrenClosure();
$characters = $arguments['characters'] ? $arguments['characters'] : null;
public function render(): string
{
$content = $this->arguments['content'] ?: $this->renderChildren();
$characters = $this->arguments['characters'] ?: null;
if ($characters !== null) {
$content = trim($content, $characters);

View File

@ -1,6 +1,5 @@
<?php
use TYPO3\CMS\Core\Imaging\IconProvider\BitmapIconProvider;
use TYPO3\CMS\Core\Imaging\IconProvider\SvgIconProvider;
return [
@ -12,8 +11,4 @@ return [
'provider' => SvgIconProvider::class,
'source' => 'EXT:ew_base/Resources/Public/Icons/Extension_16.svg',
],
'ew-usercentrics' => [
'provider' => BitmapIconProvider::class,
'source' => 'EXT:ew_base/Resources/Public/Icons/usercentrics.svg',
],
];

View File

@ -16,29 +16,14 @@ services:
Evoweb\EwBase\EventListener\CssMerger:
tags: ['event.listener']
public: true
Evoweb\EwBase\EventListener\JsMerger:
tags: ['event.listener']
public: true
Evoweb\EwBase\EventListener\IsContentUsedOnPageLayout:
Evoweb\EwBase\EventListener\ReleaseToolbarItem:
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:

View File

@ -1,33 +1,11 @@
categories:
ew-base:
label: 'Evoweb Base'
settings:
ew-base.userCentrics.loader.preload:
default: ''
label: 'UserCentrics loader preloader'
type: string
description: 'Preloader for loader'
ew-base.userCentrics.loader.template:
default: ''
label: 'UserCentrics loader template'
type: string
description: 'Template for loader'
ew-base.userCentrics.main.preload:
default: ''
label: 'UserCentrics main preloader'
type: string
description: 'Preloader for main'
ew-base.userCentrics.main.template:
default: ''
label: 'UserCentrics main template'
type: string
description: 'Template for main'
ew-base.userCentrics.block.preload:
default: ''
label: 'UserCentrics block preloader'
type: string
description: 'Preloader for block'
ew-base.userCentrics.block.template:
default: ''
label: 'UserCentrics block template'
type: string
description: 'Template for block'
ew-base.inlineCssStyles:
default: false
label: 'Inline css'
type: bool
description: 'Weather the concatenated css should get added inline style tag or a css file'
category: ew-base

View File

@ -1,22 +1,2 @@
ew-base:
userCentrics:
loader:
preload: |
<link rel="preconnect" href="//app.usercentrics.eu">
<link rel="preconnect" href="//privacy-proxy.usercentrics.eu">
<link rel="preload" href="//app.usercentrics.eu/browser-ui/latest/loader.js" as="script">
template: |
<script src="//app.usercentrics.eu/browser-ui/latest/loader.js" data-settings-id="###ID###" id="usercentrics-cmp" async></script>
main:
preload: |
<link rel="preconnect" href="//app.usercentrics.eu">
<link rel="preconnect" href="//api.usercentrics.eu">
<link rel="preconnect" href="//privacy-proxy.usercentrics.eu">
<link rel="preload" href="//app.usercentrics.eu/latest/main.js" as="script">
template: |
<script src="//app.usercentrics.eu/latest/main.js" id="###ID###" type="application/javascript"></script>
block:
preload: |
<link rel="preload" href="//privacy-proxy.usercentrics.eu/latest/uc-block.bundle.js" as="script">
template: |
<script type="application/javascript" src="https://privacy-proxy.usercentrics.eu/latest/uc-block.bundle.js"></script>
inlineCssStyles: false

View File

@ -10,15 +10,15 @@ $newColumns = [
'type' => 'group',
'allowed' => 'tt_content',
'size' => 1,
'relationship' => 'manyToOne',
'default' => 0,
'maxitems' => 1,
'minitems' => 0,
'suggestOptions' => [
'default' => [
'additionalSearchFields' => 'header, bodytext',
'searchWholePhrase' => false
]
],
'default' => 0,
'behaviour' => [
'allowLanguageSynchronization' => true
]

View File

@ -1,19 +1 @@
# ew-base
## Usercentrics Hook Guide
Add this snippet to your config/sites to enable the hook
```yaml
usercentrics:
-
id: LNxzTaK8j
version: loader
useBlocker: false
applicationContext: "Production/Staging\r\nProduction\r\nDevelopment\r\n"
```
```
id - Usercentrics Id
version (loader | main) - loader is the v2 and main is v1 in usercentrics context
useBlocker - if the content blocker script should be rendered
applicationContext - multiline string of application contexts that the snippets should be rendered in
```

View File

@ -3,9 +3,6 @@
<file source-language="en" datatype="plaintext" original="messages" date="2023-02-07T14:19:01Z">
<header/>
<body>
<trans-unit id="rm.release">
<source>Release information</source>
</trans-unit>
<trans-unit id="rm.release_label-tag">
<source>Release tag</source>
</trans-unit>

View File

@ -1,33 +0,0 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
<file source-language="en" datatype="plaintext" original="messages" date="2020-02-07T14:19:01Z">
<header/>
<body>
<trans-unit id="site.usercentrics">
<source>UserCentrics</source>
</trans-unit>
<trans-unit id="site.usercentrics.description">
<source>Max one configuration per site</source>
</trans-unit>
<trans-unit id="site_usercentrics.ctrl.title">
<source>Usercentrics configuration</source>
</trans-unit>
<trans-unit id="site_usercentrics.column.id">
<source>ID</source>
</trans-unit>
<trans-unit id="site_usercentrics.column.id.description">
<source>ID defining what user centrics account to use</source>
</trans-unit>
<trans-unit id="site_usercentrics.column.version">
<source>Version</source>
</trans-unit>
<trans-unit id="site_usercentrics.column.applicationContext">
<source>Application Context</source>
</trans-unit>
<trans-unit id="site_usercentrics.column.useBlocker">
<source>use Blocker</source>
</trans-unit>
</body>
</file>
</xliff>

View File

@ -1,14 +0,0 @@
<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">
<tr>
<th data-type="icon"><core:icon identifier="information-git" size="small" /></th>
<th data-type="title"><f:translate id="LLL:EXT:ew_base/Resources/Private/Language/locallang_core.xlf:rm.release_label-{f:if(condition: release.isTag, then: 'tag', else: 'branch')}" /></th>
<td data-type="value" class="text-{f:if(condition: release.isTag, then: 'success', else: 'warning')}">{release.release -> f:format.htmlentities()}</td>
</tr>
</table>
</html>

View File

@ -1,8 +0,0 @@
<html xmlns:core="http://typo3.org/ns/TYPO3/CMS/Core/ViewHelpers" data-namespace-typo3-fluid="true">
<f:render partial="ToolbarItems/ToolbarItem" arguments="{
title: 'LLL:EXT:ew_base/Resources/Private/Language/locallang_core.xlf:rm.release',
icon: '{core:icon(identifier: \'ew-base-extension-small\', size: \'small\', alternativeMarkupIdentifier: \'inline\')}'
}" />
</html>

View File

@ -1,15 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 19.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="layer" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 176 176" style="enable-background:new 0 0 176 176;" xml:space="preserve">
<style type="text/css">
.st0{fill:#0095FF;}
.st1{fill:#B8CEE1;}
.st2{fill:#0D47A1;}
.st3{fill:#F25900;}
</style>
<circle class="st0" cx="90.9" cy="88.7" r="26.4"/>
<circle class="st1" cx="145.1" cy="35.4" r="10.2"/>
<circle class="st2" cx="124.8" cy="132" r="18.3"/>
<circle class="st3" cx="34.8" cy="110.9" r="14.2"/>
</svg>

Before

Width:  |  Height:  |  Size: 677 B

View File

@ -1,7 +1,6 @@
{
"name": "evoweb/ew-base",
"type": "typo3-cms-extension",
"version": "1.0.0",
"autoload": {
"psr-4": {
"Evoweb\\EwBase\\": "Classes/"

View File

@ -1,2 +0,0 @@
# cat=basic//10; type=boolean; label= Weather the content of css files gets inserted to the source code of the page as inline css
inlineCssStyles = 0

View File

@ -9,7 +9,7 @@ use Evoweb\EwBase\Form\Element\PickColorFromImage;
$GLOBALS['TYPO3_CONF_VARS']['SYS']['formEngine']['nodeRegistry'][1681197508] = [
'nodeName' => 'pick-color-from-image',
'priority' => '70',
'priority' => 70,
'class' => PickColorFromImage::class,
];
})();

View File

@ -1,7 +0,0 @@
#
# Table structure for table 'pages'
#
CREATE TABLE pages
(
sectionIndex_uid int(11) unsigned DEFAULT '0' NOT NULL
);