TYPO3 v15 dev-main snapshot ()
This commit is contained in:
@@ -0,0 +1,111 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
namespace TYPO3\CMS\Core\Database\Query\Restriction;
|
||||
|
||||
use TYPO3\CMS\Core\Database\Query\Expression\CompositeExpression;
|
||||
use TYPO3\CMS\Core\Database\Query\Expression\ExpressionBuilder;
|
||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||
|
||||
/**
|
||||
* Base class for query restriction collections
|
||||
*/
|
||||
abstract class AbstractRestrictionContainer implements QueryRestrictionContainerInterface
|
||||
{
|
||||
/**
|
||||
* @var QueryRestrictionInterface[]
|
||||
*/
|
||||
protected $restrictions = [];
|
||||
|
||||
/**
|
||||
* @var QueryRestrictionInterface[]
|
||||
*/
|
||||
protected $enforcedRestrictions = [];
|
||||
|
||||
/**
|
||||
* Main method to build expressions for given tables.
|
||||
* Iterating over all registered expressions and combine them with AND
|
||||
*
|
||||
* @param array $queriedTables Array of tables, where array key is table alias and value is a table name
|
||||
* @param ExpressionBuilder $expressionBuilder Expression builder instance to add restrictions with
|
||||
* @return CompositeExpression The result of query builder expression(s)
|
||||
*/
|
||||
public function buildExpression(array $queriedTables, ExpressionBuilder $expressionBuilder): CompositeExpression
|
||||
{
|
||||
$constraints = [];
|
||||
foreach ($this->restrictions as $restriction) {
|
||||
$constraints[] = $restriction->buildExpression($queriedTables, $expressionBuilder);
|
||||
}
|
||||
return $expressionBuilder->and(...$constraints);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all restrictions stored within this container
|
||||
*/
|
||||
public function removeAll(): QueryRestrictionContainerInterface
|
||||
{
|
||||
$this->restrictions = $this->enforcedRestrictions;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove restriction of a given type
|
||||
*
|
||||
* @param string $restrictionType Class name of the restriction to be removed
|
||||
*/
|
||||
public function removeByType(string $restrictionType): QueryRestrictionContainerInterface
|
||||
{
|
||||
foreach ($this->restrictions as $type => $instance) {
|
||||
if ($instance instanceof $restrictionType) {
|
||||
unset($this->restrictions[$type]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($this->enforcedRestrictions as $type => $instance) {
|
||||
if ($instance instanceof $restrictionType) {
|
||||
unset($this->enforcedRestrictions[$type]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a new restriction instance to this collection
|
||||
*/
|
||||
public function add(QueryRestrictionInterface $restriction): QueryRestrictionContainerInterface
|
||||
{
|
||||
$this->restrictions[get_class($restriction)] = $restriction;
|
||||
if ($restriction instanceof EnforceableQueryRestrictionInterface && $restriction->isEnforced()) {
|
||||
$this->enforcedRestrictions[get_class($restriction)] = $restriction;
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Factory method for restrictions.
|
||||
* Currently only instantiates the class.
|
||||
*
|
||||
* @param string $restrictionClass
|
||||
*/
|
||||
protected function createRestriction($restrictionClass): QueryRestrictionInterface
|
||||
{
|
||||
return GeneralUtility::makeInstance($restrictionClass);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
namespace TYPO3\CMS\Core\Database\Query\Restriction;
|
||||
|
||||
/**
|
||||
* This is the container with restrictions, that are added to any doctrine query
|
||||
*/
|
||||
class DefaultRestrictionContainer extends AbstractRestrictionContainer
|
||||
{
|
||||
/**
|
||||
* Default restriction classes.
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
protected $defaultRestrictionTypes = [
|
||||
DeletedRestriction::class,
|
||||
HiddenRestriction::class,
|
||||
StartTimeRestriction::class,
|
||||
EndTimeRestriction::class,
|
||||
];
|
||||
|
||||
/**
|
||||
* Creates instances of the registered default restriction classes
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
foreach ($this->defaultRestrictionTypes as $restrictionType) {
|
||||
$this->add($this->createRestriction($restrictionType));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
namespace TYPO3\CMS\Core\Database\Query\Restriction;
|
||||
|
||||
use TYPO3\CMS\Core\Database\Query\Expression\CompositeExpression;
|
||||
use TYPO3\CMS\Core\Database\Query\Expression\ExpressionBuilder;
|
||||
use TYPO3\CMS\Core\Schema\Capability\TcaSchemaCapability;
|
||||
use TYPO3\CMS\Core\Schema\TcaSchemaFactory;
|
||||
|
||||
/**
|
||||
* Restriction to respect the soft-delete functionality of TYPO3.
|
||||
* Filters out records, that were marked as deleted.
|
||||
*/
|
||||
class DeletedRestriction implements QueryRestrictionInterface
|
||||
{
|
||||
/**
|
||||
* Main method to build expressions for given tables
|
||||
* Evaluates the ctrl/delete flag of the table and adds the according restriction if set
|
||||
*
|
||||
* @param array $queriedTables Array of tables, where array key is table alias and value is a table name
|
||||
* @param ExpressionBuilder $expressionBuilder Expression builder instance to add restrictions with
|
||||
* @return CompositeExpression The result of query builder expression(s)
|
||||
*/
|
||||
public function buildExpression(array $queriedTables, ExpressionBuilder $expressionBuilder): CompositeExpression
|
||||
{
|
||||
$tcaSchemaFactory = $expressionBuilder->getContainer()->get(TcaSchemaFactory::class);
|
||||
$constraints = [];
|
||||
foreach ($queriedTables as $tableAlias => $tableName) {
|
||||
if (!$tcaSchemaFactory->has($tableName)) {
|
||||
continue;
|
||||
}
|
||||
$schema = $tcaSchemaFactory->get($tableName);
|
||||
if ($schema->hasCapability(TcaSchemaCapability::SoftDelete)) {
|
||||
$constraints[] = $expressionBuilder->eq(
|
||||
$tableAlias . '.' . $schema->getCapability(TcaSchemaCapability::SoftDelete)->getFieldName(),
|
||||
0
|
||||
);
|
||||
}
|
||||
}
|
||||
return $expressionBuilder->and(...$constraints);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
namespace TYPO3\CMS\Core\Database\Query\Restriction;
|
||||
|
||||
use TYPO3\CMS\Core\Database\Query\Expression\CompositeExpression;
|
||||
use TYPO3\CMS\Core\Database\Query\Expression\ExpressionBuilder;
|
||||
|
||||
/**
|
||||
* Restriction to make queries for pages doktype-aware.
|
||||
*/
|
||||
class DocumentTypeExclusionRestriction implements QueryRestrictionInterface
|
||||
{
|
||||
/**
|
||||
* @var int[]
|
||||
*/
|
||||
protected $doktypes;
|
||||
|
||||
/**
|
||||
* @param int[]|int $doktype
|
||||
*/
|
||||
public function __construct($doktype)
|
||||
{
|
||||
if (is_array($doktype)) {
|
||||
$this->doktypes = $doktype;
|
||||
} else {
|
||||
$this->doktypes = [$doktype];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Main method to build expressions for given tables
|
||||
*
|
||||
* @param array $queriedTables Array of tables, where array key is table alias and value is a table name
|
||||
* @param ExpressionBuilder $expressionBuilder Expression builder instance to add restrictions with
|
||||
* @return CompositeExpression The result of query builder expression(s)
|
||||
*/
|
||||
public function buildExpression(array $queriedTables, ExpressionBuilder $expressionBuilder): CompositeExpression
|
||||
{
|
||||
$constraints = [];
|
||||
|
||||
foreach ($queriedTables as $tableAlias => $tableName) {
|
||||
if ($tableName !== 'pages') {
|
||||
continue;
|
||||
}
|
||||
|
||||
$constraints[] = $expressionBuilder->notIn($tableAlias . '.doktype', $this->doktypes);
|
||||
}
|
||||
|
||||
return $expressionBuilder->and(...$constraints);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
namespace TYPO3\CMS\Core\Database\Query\Restriction;
|
||||
|
||||
use TYPO3\CMS\Core\Database\Query\Expression\CompositeExpression;
|
||||
use TYPO3\CMS\Core\Database\Query\Expression\ExpressionBuilder;
|
||||
use TYPO3\CMS\Core\Schema\Capability\TcaSchemaCapability;
|
||||
use TYPO3\CMS\Core\Schema\TcaSchemaFactory;
|
||||
|
||||
/**
|
||||
* Restriction to filter records with an end time set that has passed
|
||||
*/
|
||||
class EndTimeRestriction implements QueryRestrictionInterface
|
||||
{
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
protected $accessTimeStamp;
|
||||
|
||||
public function __construct(?int $accessTimeStamp = null)
|
||||
{
|
||||
$this->accessTimeStamp = $accessTimeStamp ?: ($GLOBALS['SIM_ACCESS_TIME'] ?? null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Main method to build expressions for given tables
|
||||
* Evaluates the ctrl/enablecolumns/endtime flag of the table and adds the according restriction if set
|
||||
*
|
||||
* @param array $queriedTables Array of tables, where array key is table alias and value is a table name
|
||||
* @param ExpressionBuilder $expressionBuilder Expression builder instance to add restrictions with
|
||||
* @return CompositeExpression The result of query builder expression(s)
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function buildExpression(array $queriedTables, ExpressionBuilder $expressionBuilder): CompositeExpression
|
||||
{
|
||||
$tcaSchemaFactory = $expressionBuilder->getContainer()->get(TcaSchemaFactory::class);
|
||||
$constraints = [];
|
||||
foreach ($queriedTables as $tableAlias => $tableName) {
|
||||
if (!$tcaSchemaFactory->has($tableName)) {
|
||||
continue;
|
||||
}
|
||||
$schema = $tcaSchemaFactory->get($tableName);
|
||||
if ($schema->hasCapability(TcaSchemaCapability::RestrictionEndTime)) {
|
||||
if (empty($this->accessTimeStamp)) {
|
||||
throw new \RuntimeException(
|
||||
'accessTimeStamp needs to be set to an integer value, but is empty! Maybe $GLOBALS[\'SIM_ACCESS_TIME\'] has been overridden somewhere?',
|
||||
1462821084
|
||||
);
|
||||
}
|
||||
$fieldName = $tableAlias . '.' . $schema->getCapability(TcaSchemaCapability::RestrictionEndTime)->getFieldName();
|
||||
$constraints[] = $expressionBuilder->or(
|
||||
$expressionBuilder->eq($fieldName, 0),
|
||||
$expressionBuilder->gt($fieldName, (int)$this->accessTimeStamp)
|
||||
);
|
||||
}
|
||||
}
|
||||
return $expressionBuilder->and(...$constraints);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
namespace TYPO3\CMS\Core\Database\Query\Restriction;
|
||||
|
||||
/**
|
||||
* Can be added to QueryRestrictionInterface implementations.
|
||||
* Restrictions implementing this interface will not be removed when removeAll()
|
||||
* is called on the container and isEnforced() returns true.
|
||||
* It can be removed though, when explicitly calling removeByType()
|
||||
*/
|
||||
interface EnforceableQueryRestrictionInterface
|
||||
{
|
||||
/**
|
||||
* When returning false, restriction will be removed when removeAll()
|
||||
* is called on the container
|
||||
*/
|
||||
public function isEnforced(): bool;
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
namespace TYPO3\CMS\Core\Database\Query\Restriction;
|
||||
|
||||
use TYPO3\CMS\Core\Context\Context;
|
||||
use TYPO3\CMS\Core\Context\UserAspect;
|
||||
use TYPO3\CMS\Core\Database\Query\Expression\CompositeExpression;
|
||||
use TYPO3\CMS\Core\Database\Query\Expression\ExpressionBuilder;
|
||||
use TYPO3\CMS\Core\Schema\Capability\TcaSchemaCapability;
|
||||
use TYPO3\CMS\Core\Schema\TcaSchemaFactory;
|
||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||
|
||||
/**
|
||||
* Restriction to filter records, which are limited to the given user groups
|
||||
*/
|
||||
class FrontendGroupRestriction implements QueryRestrictionInterface
|
||||
{
|
||||
protected array $frontendGroupIds;
|
||||
|
||||
/**
|
||||
* @param array|null $frontendGroupIds Normalized array with user groups of currently logged in user (typically found in the Frontend Context)
|
||||
*/
|
||||
public function __construct(?array $frontendGroupIds = null)
|
||||
{
|
||||
if ($frontendGroupIds !== null) {
|
||||
$this->frontendGroupIds = $frontendGroupIds;
|
||||
} else {
|
||||
/** @var UserAspect $frontendUserAspect */
|
||||
$frontendUserAspect = GeneralUtility::makeInstance(Context::class)->getAspect('frontend.user');
|
||||
$this->frontendGroupIds = $frontendUserAspect->getGroupIds();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Main method to build expressions for given tables
|
||||
* Evaluates the ctrl/enablecolumns/fe_group flag of the table and adds the according restriction if set
|
||||
*
|
||||
* @param array $queriedTables Array of tables, where array key is table alias and value is a table name
|
||||
* @param ExpressionBuilder $expressionBuilder Expression builder instance to add restrictions with
|
||||
* @return CompositeExpression The result of query builder expression(s)
|
||||
*/
|
||||
public function buildExpression(array $queriedTables, ExpressionBuilder $expressionBuilder): CompositeExpression
|
||||
{
|
||||
$tcaSchemaFactory = $expressionBuilder->getContainer()->get(TcaSchemaFactory::class);
|
||||
$constraints = [];
|
||||
foreach ($queriedTables as $tableAlias => $tableName) {
|
||||
if (!$tcaSchemaFactory->has($tableName)) {
|
||||
continue;
|
||||
}
|
||||
$schema = $tcaSchemaFactory->get($tableName);
|
||||
if ($schema->hasCapability(TcaSchemaCapability::RestrictionUserGroup)) {
|
||||
$fieldName = $tableAlias . '.' . $schema->getCapability(TcaSchemaCapability::RestrictionUserGroup)->getFieldName();
|
||||
// Allow records where no group access has been configured (field values NULL, 0 or empty string)
|
||||
$tableConstraints = [
|
||||
$expressionBuilder->isNull($fieldName),
|
||||
$expressionBuilder->eq($fieldName, $expressionBuilder->literal('')),
|
||||
$expressionBuilder->eq($fieldName, $expressionBuilder->literal('0')),
|
||||
];
|
||||
foreach ($this->frontendGroupIds as $frontendGroupId) {
|
||||
$tableConstraints[] = $expressionBuilder->inSet(
|
||||
$fieldName,
|
||||
$expressionBuilder->literal((string)($frontendGroupId ?? ''))
|
||||
);
|
||||
}
|
||||
$constraints[] = $expressionBuilder->or(...$tableConstraints);
|
||||
}
|
||||
}
|
||||
return $expressionBuilder->and(...$constraints);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
namespace TYPO3\CMS\Core\Database\Query\Restriction;
|
||||
|
||||
use TYPO3\CMS\Core\Context\Context;
|
||||
use TYPO3\CMS\Core\Database\Query\Expression\CompositeExpression;
|
||||
use TYPO3\CMS\Core\Database\Query\Expression\ExpressionBuilder;
|
||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||
|
||||
/**
|
||||
* A collection of restrictions to be used in frontend context.
|
||||
* This is a replacement for PageRepository::enableFields()
|
||||
*/
|
||||
class FrontendRestrictionContainer extends AbstractRestrictionContainer
|
||||
{
|
||||
/**
|
||||
* @var string[]
|
||||
*/
|
||||
protected array $defaultRestrictionTypes = [
|
||||
DeletedRestriction::class,
|
||||
WorkspaceRestriction::class,
|
||||
HiddenRestriction::class,
|
||||
StartTimeRestriction::class,
|
||||
EndTimeRestriction::class,
|
||||
FrontendGroupRestriction::class,
|
||||
];
|
||||
|
||||
protected Context $context;
|
||||
|
||||
/**
|
||||
* FrontendRestrictionContainer constructor.
|
||||
* Initializes the default restrictions for frontend requests
|
||||
*/
|
||||
public function __construct(?Context $context = null)
|
||||
{
|
||||
$this->context = $context ?? GeneralUtility::makeInstance(Context::class);
|
||||
foreach ($this->defaultRestrictionTypes as $restrictionType) {
|
||||
$this->add($this->createRestriction($restrictionType));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Main method to build expressions for given tables
|
||||
* Iterates over all registered restrictions and removes the hidden restriction if preview is requested
|
||||
*
|
||||
* @param array $queriedTables Array of tables, where array key is table alias and value is a table name
|
||||
* @param ExpressionBuilder $expressionBuilder Expression builder instance to add restrictions with
|
||||
* @return CompositeExpression The result of query builder expression(s)
|
||||
*/
|
||||
public function buildExpression(array $queriedTables, ExpressionBuilder $expressionBuilder): CompositeExpression
|
||||
{
|
||||
$constraints = [];
|
||||
foreach ($this->restrictions as $restriction) {
|
||||
foreach ($queriedTables as $tableAlias => $tableName) {
|
||||
$disableRestriction = false;
|
||||
if ($restriction instanceof HiddenRestriction || $restriction instanceof StartTimeRestriction || $restriction instanceof EndTimeRestriction) {
|
||||
$visibilityAspect = $this->context->getAspect('visibility');
|
||||
if ($restriction instanceof HiddenRestriction) {
|
||||
// If display of hidden records is requested, we must disable the hidden restriction.
|
||||
if ($tableName === 'pages') {
|
||||
$disableRestriction = $visibilityAspect->includeHiddenPages();
|
||||
} else {
|
||||
$disableRestriction = $visibilityAspect->includeHiddenContent();
|
||||
}
|
||||
}
|
||||
if ($restriction instanceof StartTimeRestriction || $restriction instanceof EndTimeRestriction) {
|
||||
$disableRestriction = $visibilityAspect->includeScheduledRecords();
|
||||
}
|
||||
}
|
||||
if (!$disableRestriction) {
|
||||
$constraints[] = $restriction->buildExpression([$tableAlias => $tableName], $expressionBuilder);
|
||||
}
|
||||
}
|
||||
}
|
||||
return $expressionBuilder->and(...$constraints);
|
||||
}
|
||||
|
||||
protected function createRestriction($restrictionClass): QueryRestrictionInterface
|
||||
{
|
||||
if ($restrictionClass === WorkspaceRestriction::class) {
|
||||
return GeneralUtility::makeInstance($restrictionClass, (int)$this->context->getPropertyFromAspect('workspace', 'id', 0));
|
||||
}
|
||||
if ($restrictionClass === FrontendGroupRestriction::class) {
|
||||
return GeneralUtility::makeInstance($restrictionClass, $this->context->getPropertyFromAspect('frontend.user', 'groupIds', []));
|
||||
}
|
||||
|
||||
return parent::createRestriction($restrictionClass);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
namespace TYPO3\CMS\Core\Database\Query\Restriction;
|
||||
|
||||
use TYPO3\CMS\Core\Database\Query\Expression\CompositeExpression;
|
||||
use TYPO3\CMS\Core\Database\Query\Expression\ExpressionBuilder;
|
||||
use TYPO3\CMS\Core\Schema\Capability\TcaSchemaCapability;
|
||||
use TYPO3\CMS\Core\Schema\TcaSchemaFactory;
|
||||
|
||||
/**
|
||||
* Restriction to filter records that have been marked as hidden
|
||||
*/
|
||||
class HiddenRestriction implements QueryRestrictionInterface
|
||||
{
|
||||
/**
|
||||
* Main method to build expressions for given tables
|
||||
* Evaluates the ctrl/enablecolumns/disabled flag of the table and adds the according restriction if set
|
||||
*
|
||||
* @param array $queriedTables Array of tables, where array key is table alias and value is a table name
|
||||
* @param ExpressionBuilder $expressionBuilder Expression builder instance to add restrictions with
|
||||
* @return CompositeExpression The result of query builder expression(s)
|
||||
*/
|
||||
public function buildExpression(array $queriedTables, ExpressionBuilder $expressionBuilder): CompositeExpression
|
||||
{
|
||||
$tcaSchemaFactory = $expressionBuilder->getContainer()->get(TcaSchemaFactory::class);
|
||||
$constraints = [];
|
||||
foreach ($queriedTables as $tableAlias => $tableName) {
|
||||
if (!$tcaSchemaFactory->has($tableName)) {
|
||||
continue;
|
||||
}
|
||||
$schema = $tcaSchemaFactory->get($tableName);
|
||||
if ($schema->hasCapability(TcaSchemaCapability::RestrictionDisabledField)) {
|
||||
$constraints[] = $expressionBuilder->eq(
|
||||
$tableAlias . '.' . $schema->getCapability(TcaSchemaCapability::RestrictionDisabledField)->getFieldName(),
|
||||
0
|
||||
);
|
||||
}
|
||||
}
|
||||
return $expressionBuilder->and(...$constraints);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
namespace TYPO3\CMS\Core\Database\Query\Restriction;
|
||||
|
||||
use TYPO3\CMS\Core\Database\Query\Expression\CompositeExpression;
|
||||
use TYPO3\CMS\Core\Database\Query\Expression\ExpressionBuilder;
|
||||
|
||||
/**
|
||||
* Restriction container that applies added restrictions only to the given table aliases.
|
||||
* Enforced restrictions are treated equally to all other restrictions.
|
||||
*/
|
||||
class LimitToTablesRestrictionContainer implements QueryRestrictionContainerInterface
|
||||
{
|
||||
/**
|
||||
* @var QueryRestrictionInterface[]
|
||||
*/
|
||||
private $restrictions = [];
|
||||
|
||||
/**
|
||||
* @var QueryRestrictionContainerInterface[]
|
||||
*/
|
||||
private $restrictionContainer = [];
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $applicableTableAliases;
|
||||
|
||||
public function removeAll(): QueryRestrictionContainerInterface
|
||||
{
|
||||
$this->applicableTableAliases = $this->restrictions = $this->restrictionContainer = [];
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function removeByType(string $restrictionType): QueryRestrictionContainerInterface
|
||||
{
|
||||
unset($this->applicableTableAliases[$restrictionType], $this->restrictions[$restrictionType]);
|
||||
foreach ($this->restrictionContainer as $restrictionContainer) {
|
||||
$restrictionContainer->removeByType($restrictionType);
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function add(QueryRestrictionInterface $restriction): QueryRestrictionContainerInterface
|
||||
{
|
||||
$this->restrictions[get_class($restriction)] = $restriction;
|
||||
if ($restriction instanceof QueryRestrictionContainerInterface) {
|
||||
$this->restrictionContainer[get_class($restriction)] = $restriction;
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the restriction, but also remembers which table aliases it should be applied to
|
||||
*
|
||||
* @param array $tableAliases flat array of table aliases, not table names
|
||||
*/
|
||||
public function addForTables(QueryRestrictionInterface $restriction, array $tableAliases): QueryRestrictionContainerInterface
|
||||
{
|
||||
$this->applicableTableAliases[get_class($restriction)] = $tableAliases;
|
||||
return $this->add($restriction);
|
||||
}
|
||||
|
||||
/**
|
||||
* Main method to build expressions for given tables, but respecting configured filters.
|
||||
*
|
||||
* @param array $queriedTables Array of tables, where array key is table alias and value is a table name
|
||||
* @param ExpressionBuilder $expressionBuilder Expression builder instance to add restrictions with
|
||||
* @return CompositeExpression The result of query builder expression(s)
|
||||
*/
|
||||
public function buildExpression(array $queriedTables, ExpressionBuilder $expressionBuilder): CompositeExpression
|
||||
{
|
||||
$constraints = [];
|
||||
foreach ($this->restrictions as $name => $restriction) {
|
||||
$constraints[] = $restriction->buildExpression(
|
||||
$this->filterApplicableTableAliases($queriedTables, $name),
|
||||
$expressionBuilder
|
||||
);
|
||||
}
|
||||
return $expressionBuilder->and(...$constraints);
|
||||
}
|
||||
|
||||
private function filterApplicableTableAliases(array $queriedTables, string $name): array
|
||||
{
|
||||
if (!isset($this->applicableTableAliases[$name])) {
|
||||
return $queriedTables;
|
||||
}
|
||||
|
||||
$filteredTables = [];
|
||||
foreach ($this->applicableTableAliases[$name] as $tableAlias) {
|
||||
if (isset($queriedTables[$tableAlias])) {
|
||||
$filteredTables[$tableAlias] = $queriedTables[$tableAlias];
|
||||
}
|
||||
}
|
||||
|
||||
return $filteredTables;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
namespace TYPO3\CMS\Core\Database\Query\Restriction;
|
||||
|
||||
use TYPO3\CMS\Core\Database\Query\Expression\CompositeExpression;
|
||||
use TYPO3\CMS\Core\Database\Query\Expression\ExpressionBuilder;
|
||||
|
||||
/**
|
||||
* Restriction to filter records that only reside on a specific list of page IDs
|
||||
*/
|
||||
final readonly class PageIdListRestriction implements QueryRestrictionInterface
|
||||
{
|
||||
public function __construct(
|
||||
private array $tableNames,
|
||||
private array $pageIds
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Main method to build expressions for given tables
|
||||
*
|
||||
* @param array $queriedTables Array of tables, where array key is table alias and value is a table name
|
||||
* @param ExpressionBuilder $expressionBuilder Expression builder instance to add restrictions with
|
||||
* @return CompositeExpression The result of query builder expression(s)
|
||||
*/
|
||||
public function buildExpression(array $queriedTables, ExpressionBuilder $expressionBuilder): CompositeExpression
|
||||
{
|
||||
$constraints = [];
|
||||
foreach ($queriedTables as $tableAlias => $tableName) {
|
||||
if (empty($this->tableNames) || in_array($tableAlias, $this->tableNames, true)) {
|
||||
$constraints[] = $expressionBuilder->in(
|
||||
$tableAlias . '.pid',
|
||||
array_map(intval(...), $this->pageIds)
|
||||
);
|
||||
}
|
||||
}
|
||||
return $expressionBuilder->and(...$constraints);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,132 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
namespace TYPO3\CMS\Core\Database\Query\Restriction;
|
||||
|
||||
use TYPO3\CMS\Core\Context\UserAspect;
|
||||
use TYPO3\CMS\Core\Database\Query\Expression\CompositeExpression;
|
||||
use TYPO3\CMS\Core\Database\Query\Expression\ExpressionBuilder;
|
||||
|
||||
/**
|
||||
* Restriction to make queries respect backend user rights for pages.
|
||||
*
|
||||
* Adds a WHERE-clause for the pages-table where user permissions according to input argument, $permissions, is validated.
|
||||
* $permissions is the "mask" used to select - see Permission Bitset.
|
||||
* E.g. if $perms is 1 then you'll get all pages that a user can actually see!
|
||||
* 2^0 = show (1)
|
||||
* 2^1 = edit (2)
|
||||
* 2^2 = delete (4)
|
||||
* 2^3 = new (8)
|
||||
* If the user is 'admin' no validation is used.
|
||||
*
|
||||
* If the user is not set at all (->user is not an array), then "AND 1=0" is returned (will cause no selection results at all)
|
||||
*
|
||||
* The 95% use of this function is "->getPagePermsClause(1)" which will
|
||||
* return WHERE clauses for *selecting* pages in backend listings - in other words this will check read permissions.
|
||||
*/
|
||||
class PagePermissionRestriction implements QueryRestrictionInterface
|
||||
{
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
protected $permissions;
|
||||
|
||||
/**
|
||||
* @var UserAspect
|
||||
*/
|
||||
protected $userAspect;
|
||||
|
||||
public function __construct(UserAspect $userAspect, int $permissions)
|
||||
{
|
||||
$this->permissions = $permissions;
|
||||
$this->userAspect = $userAspect;
|
||||
}
|
||||
|
||||
/**
|
||||
* Main method to build expressions for given tables
|
||||
*
|
||||
* @param array $queriedTables Array of tables, where array key is table alias and value is a table name
|
||||
* @param ExpressionBuilder $expressionBuilder Expression builder instance to add restrictions with
|
||||
* @return CompositeExpression The result of query builder expression(s)
|
||||
*/
|
||||
public function buildExpression(array $queriedTables, ExpressionBuilder $expressionBuilder): CompositeExpression
|
||||
{
|
||||
$constraints = [];
|
||||
|
||||
foreach ($queriedTables as $tableAlias => $tableName) {
|
||||
if ($tableName !== 'pages') {
|
||||
continue;
|
||||
}
|
||||
|
||||
$constraint = $this->buildUserConstraints($expressionBuilder, $tableAlias);
|
||||
if ($constraint) {
|
||||
$constraints[] = $expressionBuilder->and($constraint);
|
||||
}
|
||||
}
|
||||
|
||||
return $expressionBuilder->and(...$constraints);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string|CompositeExpression|null
|
||||
* @throws \TYPO3\CMS\Core\Context\Exception\AspectPropertyNotFoundException
|
||||
*/
|
||||
protected function buildUserConstraints(ExpressionBuilder $expressionBuilder, string $tableAlias)
|
||||
{
|
||||
if (!$this->userAspect->isLoggedIn()) {
|
||||
return $expressionBuilder->comparison(1, ExpressionBuilder::EQ, 0);
|
||||
}
|
||||
if ($this->userAspect->isAdmin()) {
|
||||
return null;
|
||||
}
|
||||
// User permissions
|
||||
$constraint = $expressionBuilder->or(
|
||||
$expressionBuilder->comparison(
|
||||
$expressionBuilder->bitAnd($tableAlias . '.perms_everybody', $this->permissions),
|
||||
ExpressionBuilder::EQ,
|
||||
$this->permissions
|
||||
),
|
||||
$expressionBuilder->and(
|
||||
$expressionBuilder->eq($tableAlias . '.perms_userid', $this->userAspect->get('id')),
|
||||
$expressionBuilder->comparison(
|
||||
$expressionBuilder->bitAnd($tableAlias . '.perms_user', $this->permissions),
|
||||
ExpressionBuilder::EQ,
|
||||
$this->permissions
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
// User groups (if any are set)
|
||||
$groupIds = array_map(intval(...), $this->userAspect->getGroupIds());
|
||||
if (!empty($groupIds)) {
|
||||
$constraint = $constraint->with(
|
||||
$expressionBuilder->and(
|
||||
$expressionBuilder->in(
|
||||
$tableAlias . '.perms_groupid',
|
||||
$groupIds
|
||||
),
|
||||
$expressionBuilder->comparison(
|
||||
$expressionBuilder->bitAnd($tableAlias . '.perms_group', $this->permissions),
|
||||
ExpressionBuilder::EQ,
|
||||
$this->permissions
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
return $constraint;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
namespace TYPO3\CMS\Core\Database\Query\Restriction;
|
||||
|
||||
/**
|
||||
* Interface that all restriction collections must implement.
|
||||
* It is an extension of the QueryRestrictionInterface, so collections can be treated as single restriction
|
||||
*/
|
||||
interface QueryRestrictionContainerInterface extends QueryRestrictionInterface
|
||||
{
|
||||
/**
|
||||
* Removes all restrictions stored within this container
|
||||
*
|
||||
* @return QueryRestrictionContainerInterface
|
||||
*/
|
||||
public function removeAll();
|
||||
|
||||
/**
|
||||
* Remove restriction of a given type
|
||||
*
|
||||
* @param string $restrictionType Class name of the restriction to be removed
|
||||
* @return QueryRestrictionContainerInterface
|
||||
*/
|
||||
public function removeByType(string $restrictionType);
|
||||
|
||||
/**
|
||||
* Add a new restriction instance to this collection
|
||||
*
|
||||
* @return QueryRestrictionContainerInterface
|
||||
*/
|
||||
public function add(QueryRestrictionInterface $restriction);
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
namespace TYPO3\CMS\Core\Database\Query\Restriction;
|
||||
|
||||
use TYPO3\CMS\Core\Database\Query\Expression\CompositeExpression;
|
||||
use TYPO3\CMS\Core\Database\Query\Expression\ExpressionBuilder;
|
||||
|
||||
/**
|
||||
* The main restriction interface. All restrictions (including the collections) must implement this.
|
||||
*/
|
||||
interface QueryRestrictionInterface
|
||||
{
|
||||
/**
|
||||
* Main method to build expressions for given tables
|
||||
*
|
||||
* @param array $queriedTables Array of tables, where array key is table alias and value is a table name
|
||||
* @param ExpressionBuilder $expressionBuilder Expression builder instance to add restrictions with
|
||||
* @return CompositeExpression The result of query builder expression(s)
|
||||
*/
|
||||
public function buildExpression(array $queriedTables, ExpressionBuilder $expressionBuilder): CompositeExpression;
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
namespace TYPO3\CMS\Core\Database\Query\Restriction;
|
||||
|
||||
use TYPO3\CMS\Core\Database\Query\Expression\CompositeExpression;
|
||||
use TYPO3\CMS\Core\Database\Query\Expression\ExpressionBuilder;
|
||||
|
||||
/**
|
||||
* Restriction to filter records which are not stored on the root page.
|
||||
*/
|
||||
class RootLevelRestriction implements QueryRestrictionInterface
|
||||
{
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $tableNames;
|
||||
|
||||
public function __construct(array $tableNames = [])
|
||||
{
|
||||
$this->tableNames = $tableNames;
|
||||
}
|
||||
|
||||
/**
|
||||
* Main method to build expressions for given tables
|
||||
*
|
||||
* @param array $queriedTables Array of tables, where array key is table alias and value is a table name
|
||||
* @param ExpressionBuilder $expressionBuilder Expression builder instance to add restrictions with
|
||||
* @return CompositeExpression The result of query builder expression(s)
|
||||
*/
|
||||
public function buildExpression(array $queriedTables, ExpressionBuilder $expressionBuilder): CompositeExpression
|
||||
{
|
||||
$constraints = [];
|
||||
foreach ($queriedTables as $tableAlias => $tableName) {
|
||||
if (empty($this->tableNames) || in_array($tableAlias, $this->tableNames, true)) {
|
||||
$constraints[] = $expressionBuilder->eq(
|
||||
$tableAlias . '.pid',
|
||||
0
|
||||
);
|
||||
}
|
||||
}
|
||||
return $expressionBuilder->and(...$constraints);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
namespace TYPO3\CMS\Core\Database\Query\Restriction;
|
||||
|
||||
use TYPO3\CMS\Core\Database\Query\Expression\CompositeExpression;
|
||||
use TYPO3\CMS\Core\Database\Query\Expression\ExpressionBuilder;
|
||||
use TYPO3\CMS\Core\Schema\Capability\TcaSchemaCapability;
|
||||
use TYPO3\CMS\Core\Schema\TcaSchemaFactory;
|
||||
|
||||
/**
|
||||
* Restriction to filter records, that should not be shown until the start time has been reached
|
||||
*/
|
||||
class StartTimeRestriction implements QueryRestrictionInterface
|
||||
{
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
protected $accessTimeStamp;
|
||||
|
||||
public function __construct(?int $accessTimeStamp = null)
|
||||
{
|
||||
$this->accessTimeStamp = $accessTimeStamp ?: ($GLOBALS['SIM_ACCESS_TIME'] ?? null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Main method to build expressions for given tables
|
||||
* Evaluates the ctrl/enablecolumns/starttime flag of the table and adds the according restriction if set
|
||||
*
|
||||
* @param array $queriedTables Array of tables, where array key is table alias and value is a table name
|
||||
* @param ExpressionBuilder $expressionBuilder Expression builder instance to add restrictions with
|
||||
* @return CompositeExpression The result of query builder expression(s)
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function buildExpression(array $queriedTables, ExpressionBuilder $expressionBuilder): CompositeExpression
|
||||
{
|
||||
$tcaSchemaFactory = $expressionBuilder->getContainer()->get(TcaSchemaFactory::class);
|
||||
$constraints = [];
|
||||
foreach ($queriedTables as $tableAlias => $tableName) {
|
||||
if (!$tcaSchemaFactory->has($tableName)) {
|
||||
continue;
|
||||
}
|
||||
$schema = $tcaSchemaFactory->get($tableName);
|
||||
if ($schema->hasCapability(TcaSchemaCapability::RestrictionStartTime)) {
|
||||
if (empty($this->accessTimeStamp)) {
|
||||
throw new \RuntimeException(
|
||||
'accessTimeStamp needs to be set to an integer value, but is empty! Maybe $GLOBALS[\'SIM_ACCESS_TIME\'] has been overridden somewhere?',
|
||||
1462820645
|
||||
);
|
||||
}
|
||||
$constraints[] = $expressionBuilder->lte(
|
||||
$tableAlias . '.' . $schema->getCapability(TcaSchemaCapability::RestrictionStartTime)->getFieldName(),
|
||||
(int)$this->accessTimeStamp
|
||||
);
|
||||
}
|
||||
}
|
||||
return $expressionBuilder->and(...$constraints);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
namespace TYPO3\CMS\Core\Database\Query\Restriction;
|
||||
|
||||
use TYPO3\CMS\Core\Database\Query\Expression\CompositeExpression;
|
||||
use TYPO3\CMS\Core\Database\Query\Expression\ExpressionBuilder;
|
||||
use TYPO3\CMS\Core\Schema\TcaSchemaFactory;
|
||||
use TYPO3\CMS\Core\Versioning\VersionState;
|
||||
|
||||
/**
|
||||
* Restriction to make queries workspace-aware. This restriction ALWAYS fetches the live version
|
||||
* plus in current workspace the workspace records.
|
||||
* It does not care about the state, as this should be done by overlays.
|
||||
*
|
||||
* As workspaces cannot be fully overlaid within ONE query, this query does the following:
|
||||
* - In live context, only fetch published records
|
||||
* - In a workspace, fetch all LIVE records and all workspace records which do not have "1" (= all new placeholders get fetched as well)
|
||||
*
|
||||
* This means, that all records which are fetched need to run through either
|
||||
* - BackendUtility::getRecordWSOL() (when having one or a few records)
|
||||
* - PageRepository->versionOL()
|
||||
* - PlainDataResolver (when having lots of records)
|
||||
*/
|
||||
class WorkspaceRestriction implements QueryRestrictionInterface
|
||||
{
|
||||
protected int $workspaceId;
|
||||
|
||||
/**
|
||||
* Used to also query records within a workspace, which is useful for DB queries
|
||||
* that check for a specific field (e.g. "slug") which might have changed within a workspace.
|
||||
* Please note that some duplicates might be shown and the "reduce" logic needs to be
|
||||
* added after querying. Setting this flag might also be a problem when using the DB query
|
||||
* with limit and offset settings.
|
||||
*/
|
||||
protected bool $includeAllVersionedRecords;
|
||||
|
||||
public function __construct(int $workspaceId = 0, bool $includeAllVersionedRecords = false)
|
||||
{
|
||||
$this->workspaceId = $workspaceId;
|
||||
$this->includeAllVersionedRecords = $includeAllVersionedRecords;
|
||||
}
|
||||
|
||||
/**
|
||||
* Main method to build expressions for given tables
|
||||
*
|
||||
* @param array $queriedTables Array of tables, where array key is table alias and value is a table name
|
||||
* @param ExpressionBuilder $expressionBuilder Expression builder instance to add restrictions with
|
||||
* @return CompositeExpression The result of query builder expression(s)
|
||||
*/
|
||||
public function buildExpression(array $queriedTables, ExpressionBuilder $expressionBuilder): CompositeExpression
|
||||
{
|
||||
$tcaSchemaFactory = $expressionBuilder->getContainer()->get(TcaSchemaFactory::class);
|
||||
$constraints = [];
|
||||
foreach ($queriedTables as $tableAlias => $tableName) {
|
||||
if (!$tcaSchemaFactory->has($tableName) || !$tcaSchemaFactory->get($tableName)->isWorkspaceAware()) {
|
||||
continue;
|
||||
}
|
||||
if ($this->workspaceId === 0) {
|
||||
// Only include records from live workspace
|
||||
$workspaceIdExpression = $expressionBuilder->eq($tableAlias . '.t3ver_wsid', 0);
|
||||
} else {
|
||||
// Include live records PLUS records from the given workspace
|
||||
$workspaceIdExpression = $expressionBuilder->in(
|
||||
$tableAlias . '.t3ver_wsid',
|
||||
[0, $this->workspaceId]
|
||||
);
|
||||
}
|
||||
// Always filter out versioned records that have an "offline" record
|
||||
// But include moved records AND newly created records (t3ver_oid=0)
|
||||
if ($this->includeAllVersionedRecords === false) {
|
||||
$constraints[] = $expressionBuilder->and(
|
||||
$workspaceIdExpression,
|
||||
$expressionBuilder->or(
|
||||
$expressionBuilder->eq(
|
||||
$tableAlias . '.t3ver_oid',
|
||||
0
|
||||
),
|
||||
$expressionBuilder->eq(
|
||||
$tableAlias . '.t3ver_state',
|
||||
VersionState::MOVE_POINTER->value
|
||||
)
|
||||
)
|
||||
);
|
||||
} else {
|
||||
// Include live records plus records from the given workspace
|
||||
// but never include versioned records marked as deleted
|
||||
$constraints[] = $expressionBuilder->and(
|
||||
$workspaceIdExpression,
|
||||
$expressionBuilder->neq(
|
||||
$tableAlias . '.t3ver_state',
|
||||
VersionState::DELETE_PLACEHOLDER->value
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
return $expressionBuilder->and(...$constraints);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user