Skip to content

Commit

Permalink
[FEATURE] Adds Support for MM-Records to excluded Tables
Browse files Browse the repository at this point in the history
  • Loading branch information
dhoffmann1979 committed Aug 14, 2024
1 parent feaff09 commit 8486183
Show file tree
Hide file tree
Showing 8 changed files with 231 additions and 5 deletions.
40 changes: 40 additions & 0 deletions Classes/Component/Core/Demand/Type/MmDemand.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<?php

declare(strict_types=1);

namespace In2code\In2publishCore\Component\Core\Demand\Type;

use In2code\In2publishCore\Component\Core\Record\Model\Node;

class MmDemand implements Demand
{
use UniqueRecordKeyGenerator;

protected string $from;
protected string $property;
/** @var mixed */
protected $value;
protected Node $record;

/**
* @param mixed $value
*/
public function __construct(string $from, string $property, $value, Node $record)
{
$this->from = $from;
$this->property = $property;
$this->value = $value;
$this->record = $record;
}

public function addToDemandsArray(array &$demands): void
{
$uniqueRecordKey = $this->createUniqueRecordKey($this->record);
$demands[$this->from][$this->property][$this->value][$uniqueRecordKey] = $this->record;
}

public function addToMetaArray(array &$meta, array $frame): void
{
$meta[$this->from][$this->property][] = $frame;
}
}
65 changes: 65 additions & 0 deletions Classes/Component/Core/DemandResolver/Mm/MmDemandResolver.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
<?php

namespace In2code\In2publishCore\Component\Core\DemandResolver\Mm;

use Doctrine\DBAL\Exception;
use In2code\In2publishCore\Component\Core\Demand\CallerAwareDemandsCollection;
use In2code\In2publishCore\Component\Core\Demand\Demands;
use In2code\In2publishCore\Component\Core\Demand\Type\MmDemand;
use In2code\In2publishCore\Component\Core\Demand\Type\SelectDemand;
use In2code\In2publishCore\Component\Core\DemandResolver\DemandResolver;
use In2code\In2publishCore\Component\Core\DemandResolver\Exception\InvalidDemandException;
use In2code\In2publishCore\Component\Core\Record\Factory\RecordFactoryInjection;
use In2code\In2publishCore\Component\Core\RecordCollection;
use In2code\In2publishCore\Component\Core\RecordIndexInjection;
use In2code\In2publishCore\Component\Core\Repository\DualDatabaseRepositoryInjection;
use In2code\In2publishCore\Component\Core\Repository\ForeignSingleDatabaseRepositoryInjection;
use In2code\In2publishCore\Component\Core\Repository\LocalSingleDatabaseRepositoryInjection;

class MmDemandResolver implements DemandResolver
{
use RecordFactoryInjection;
use RecordIndexInjection;
use DualDatabaseRepositoryInjection;
use LocalSingleDatabaseRepositoryInjection;
use ForeignSingleDatabaseRepositoryInjection;

public function resolveDemand(Demands $demands, RecordCollection $recordCollection): void
{
foreach ($demands->getDemandsByType(MmDemand::class) as $mmTable => $fields) {
foreach ($fields as $field => $valueMaps) {
try {
$rows = $this->dualDatabaseRepository->findMmByProperty(
$mmTable,
$field,
array_keys($valueMaps)
);
} catch (Exception $exception) {
if ($demands instanceof CallerAwareDemandsCollection) {
$callers = $demands->getMeta(MmDemand::class, $mmTable, $field);
$exception = new InvalidDemandException($callers, $exception);
}
throw $exception;
}
foreach ($rows as $mmId => $recordInfo) {
$mmRecord = $this->recordIndex->getRecord($mmTable, $mmId);
if (null === $mmRecord) {
$mmRecord = $this->recordFactory->createMmRecord(
$mmTable,
$mmId,
$recordInfo['local'] ?? [],
$recordInfo['foreign'] ?? [],
);
if (null === $mmRecord) {
continue;
}
}
$mapValue = $mmRecord->getProp($field);
foreach ($valueMaps[$mapValue] as $parent) {
$parent->addChild($mmRecord);
}
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
use In2code\In2publishCore\Component\Core\Resolver\GroupMultiTableResolver;
use In2code\In2publishCore\Component\Core\Resolver\GroupSingleTableResolver;
use In2code\In2publishCore\Component\Core\Resolver\Resolver;
use In2code\In2publishCore\Component\Core\Resolver\SelectStandaloneMmResolver;
use In2code\In2publishCore\Component\Core\Resolver\StaticJoinResolver;
use In2code\In2publishCore\Utility\DatabaseUtility;
use TYPO3\CMS\Core\Utility\GeneralUtility;
Expand Down Expand Up @@ -57,12 +58,12 @@ protected function additionalPreProcess(string $table, string $column, array $tc
}

$allowedTables = GeneralUtility::trimExplode(',', $allowed);
if (['pages'] === $allowedTables) {
if (empty($tca['MM']) && ['pages'] === $allowedTables) {
return ['TCA relations to pages are not resolved.'];
}

$allowedTables = $this->excludedTablesService->removeExcludedTables($allowedTables);
if (empty($allowedTables)) {
if (empty($tca['MM']) && empty($allowedTables)) {
return ['All tables of this relation (' . $allowed . ') are excluded.'];
}

Expand Down Expand Up @@ -109,6 +110,12 @@ protected function buildResolver(string $table, string $column, array $processed
$additionalWhere = $matches['where'];
}

if ('pages' === $foreignTable || $this->excludedTablesService->isExcludedTable($foreignTable)) {
$resolver = $this->container->get(SelectStandaloneMmResolver::class);
$resolver->configure($mmTable, $selectField);
return $resolver;
}

if (!$isSingleTable) {
$resolver = $this->container->get(GroupMmMultiTableResolver::class);
$resolver->configure($tables, $mmTable, $column, $selectField, $additionalWhere);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use In2code\In2publishCore\Component\Core\Resolver\InlineMultiValueResolver;
use In2code\In2publishCore\Component\Core\Resolver\InlineSelectResolver;
use In2code\In2publishCore\Component\Core\Resolver\Resolver;
use In2code\In2publishCore\Component\Core\Resolver\SelectStandaloneMmResolver;
use In2code\In2publishCore\Component\Core\Resolver\StaticJoinResolver;
use In2code\In2publishCore\Utility\DatabaseUtility;

Expand Down Expand Up @@ -37,7 +38,7 @@ class InlineProcessor extends AbstractProcessor
protected function additionalPreProcess(string $table, string $column, array $tca): array
{
$foreignTable = $tca['foreign_table'] ?? null;
if (null !== $foreignTable && $this->excludedTablesService->isExcludedTable($foreignTable)) {
if (empty($tca['MM']) && null !== $foreignTable && $this->excludedTablesService->isExcludedTable($foreignTable)) {
return ['The table ' . $foreignTable . ' is excluded from publishing'];
}
return [];
Expand All @@ -55,6 +56,12 @@ protected function buildResolver(string $table, string $column, array $processed

$additionalWhere = $this->processMmMatchFields($processedTca);

if ('pages' === $foreignTable || $this->excludedTablesService->isExcludedTable($foreignTable)) {
$resolver = $this->container->get(SelectStandaloneMmResolver::class);
$resolver->configure($mmTable, $selectField);
return $resolver;
}

/** @var StaticJoinResolver $resolver */
$resolver = $this->container->get(StaticJoinResolver::class);
$resolver->configure($mmTable, $foreignTable, $additionalWhere, $selectField);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use In2code\In2publishCore\Component\Core\Resolver\Resolver;
use In2code\In2publishCore\Component\Core\Resolver\SelectMmResolver;
use In2code\In2publishCore\Component\Core\Resolver\SelectResolver;
use In2code\In2publishCore\Component\Core\Resolver\SelectStandaloneMmResolver;
use In2code\In2publishCore\Utility\DatabaseUtility;

use function array_filter;
Expand Down Expand Up @@ -58,11 +59,11 @@ protected function additionalPreProcess(string $table, string $column, array $tc
// Skip relations to table "pages", except if it's the page's transOrigPointerField
$foreignTable = $tca['foreign_table'] ?? null;
$transOrigPointerField = $GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField'] ?? null;
if ('pages' === $foreignTable && ('pages' !== $table || $column !== $transOrigPointerField)) {
if (empty($tca['MM']) && 'pages' === $foreignTable && ('pages' !== $table || $column !== $transOrigPointerField)) {
return ['TCA relations to pages are not resolved.'];
}

if (null !== $foreignTable && $this->excludedTablesService->isExcludedTable($foreignTable)) {
if (empty($tca['MM']) && null !== $foreignTable && $this->excludedTablesService->isExcludedTable($foreignTable)) {
return ['The table ' . $foreignTable . ' is excluded from publishing'];
}

Expand Down Expand Up @@ -91,6 +92,12 @@ protected function buildResolver(string $table, string $column, array $processed
$foreignTableWhere = DatabaseUtility::stripLogicalOperatorPrefix($foreignTableWhere);
$foreignTableWhere = $this->tcaEscapingMarkerService->escapeMarkedIdentifier($foreignTableWhere);

if ('pages' === $foreignTable || $this->excludedTablesService->isExcludedTable($foreignTable)) {
$resolver = $this->container->get(SelectStandaloneMmResolver::class);
$resolver->configure($mmTable, $selectField);
return $resolver;
}

/** @var SelectMmResolver $resolver */
$resolver = $this->container->get(SelectMmResolver::class);
$resolver->configure($foreignTableWhere, $column, $mmTable, $foreignTable, $selectField);
Expand Down
9 changes: 9 additions & 0 deletions Classes/Component/Core/Repository/DualDatabaseRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -76,4 +76,13 @@ public function findByWhere(string $table, string $andWhere): array

return $this->mergeRowsByIdentifier($localRows, $foreignRows);
}

public function findMmByProperty(string $table, string $property, array $values): array
{
$localRows = $this->localRepository->findMmByProperty($table, $property, $values);
$foreignRows = $this->foreignRepository->findMmByProperty($table, $property, $values);

return $this->mergeRowsByIdentifier($localRows, $foreignRows);
}

}
25 changes: 25 additions & 0 deletions Classes/Component/Core/Repository/SingleDatabaseRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -210,4 +210,29 @@ public function findByWhere($table, string $andWhere): array
$result = $query->executeQuery();
return array_column($result->fetchAllAssociative(), null, 'uid');
}

public function findMmByProperty(string $table, string $property, array $values): array
{
$query = $this->connection->createQueryBuilder();
$query->getRestrictions()->removeAll();
$query->select('*')
->from($table)
->where(
$query->expr()->in(
$property,
$query->createNamedParameter($values, DbalConnection::PARAM_STR_ARRAY),
),
);

$result = $query->executeQuery();
$rows = [];
foreach ($result->fetchAllAssociative() as $row) {
$mmIdentityProperties = [
$row['uid_local'],
$row['uid_foreign'],
];
$rows[hash('sha1', json_encode($mmIdentityProperties, JSON_THROW_ON_ERROR))] = $row;
}
return $rows;
}
}
66 changes: 66 additions & 0 deletions Classes/Component/Core/Resolver/SelectStandaloneMmResolver.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
<?php

declare(strict_types=1);

namespace In2code\In2publishCore\Component\Core\Resolver;

use In2code\In2publishCore\Component\Core\Demand\Demands;
use In2code\In2publishCore\Component\Core\Demand\Type\JoinDemand;
use In2code\In2publishCore\Component\Core\Demand\Type\MmDemand;
use In2code\In2publishCore\Component\Core\Demand\Type\StandaloneMmDemand;
use In2code\In2publishCore\Component\Core\PreProcessing\PreProcessor\AbstractProcessor;
use In2code\In2publishCore\Component\Core\Record\Model\Record;
use In2code\In2publishCore\Service\ReplaceMarkersService;
use In2code\In2publishCore\Service\ReplaceMarkersServiceInject;
use TYPO3\CMS\Core\Utility\GeneralUtility;

use function preg_match;

class SelectStandaloneMmResolver extends AbstractResolver
{
use ReplaceMarkersServiceInject;

protected string $mmTable;
protected string $selectField;

public function configure(
string $mmTable,
string $selectField
): void {
$this->mmTable = $mmTable;
$this->selectField = $selectField;
}

public function getTargetTables(): array
{
return [$this->mmTable];
}

public function resolve(Demands $demands, Record $record): void
{
$value = $record->getId();

$demand = new MmDemand($this->mmTable, $this->selectField, $value, $record);

$demands->addDemand($demand);
}

public function __serialize(): array
{
return [
'metaInfo' => $this->metaInfo,
'mmTable' => $this->mmTable,
'selectField' => $this->selectField,
];
}

public function __unserialize(array $data): void
{
$this->metaInfo = $data['metaInfo'];
$this->configure(
$data['mmTable'],
$data['selectField'],
);
$this->injectReplaceMarkersService(GeneralUtility::makeInstance(ReplaceMarkersService::class));
}
}

0 comments on commit 8486183

Please sign in to comment.