Skip to content

Commit

Permalink
Merge pull request #88 from b13/bugfix/issue-83
Browse files Browse the repository at this point in the history
[BUGFIX] moved records in Workspace
  • Loading branch information
bmack committed Sep 23, 2020
2 parents adcfde2 + 515f492 commit fa39597
Show file tree
Hide file tree
Showing 11 changed files with 726 additions and 49 deletions.
6 changes: 1 addition & 5 deletions Classes/DataProcessing/ContainerProcessor.php
Original file line number Diff line number Diff line change
Expand Up @@ -110,11 +110,7 @@ protected function processColPos(
'tables' => 'tt_content'
];
foreach ($children as &$child) {
if ($child['t3ver_oid'] > 0) {
$conf['source'] = $child['t3ver_oid'];
} else {
$conf['source'] = $child['uid'];
}
$conf['source'] = $child['uid'];
$child['renderedContent'] = $cObj->render($contentRecordRenderer, $conf);
}
$processedData[$as] = $children;
Expand Down
49 changes: 28 additions & 21 deletions Classes/Domain/Factory/ContainerFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,14 +32,18 @@ class ContainerFactory implements SingletonInterface
protected $tcaRegistry;

/**
* ContainerFactory constructor.
* @param Database|null $database
* @param Registry|null $tcaRegistry
* @var int
*/
public function __construct(Database $database = null, Registry $tcaRegistry = null)
protected $workspaceId = 0;

public function __construct(Database $database = null, Registry $tcaRegistry = null, Context $context = null)
{
$this->database = $database ?? GeneralUtility::makeInstance(Database::class);
$this->tcaRegistry = $tcaRegistry ?? GeneralUtility::makeInstance(Registry::class);
if ($context === null) {
$context = GeneralUtility::makeInstance(Context::class);
}
$this->workspaceId = (int)$context->getPropertyFromAspect('workspace', 'id');
}

/**
Expand Down Expand Up @@ -77,6 +81,7 @@ public function buildContainer(int $uid): Container
} else {
// connected mode
$defaultRecords = $this->database->fetchRecordsByParentAndLanguage($defaultRecord['uid'], 0);
$defaultRecords = $this->doWorkspaceOverlay($defaultRecords);
$localizedRecords = $this->database->fetchOverlayRecords($defaultRecords, $language);
$childRecords = $this->sortLocalizedRecordsByDefaultRecords($defaultRecords, $localizedRecords);
}
Expand All @@ -100,24 +105,20 @@ public function buildContainer(int $uid): Container
*/
protected function doWorkspaceOverlay(array $defaultRecords): array
{
$workspaceId = GeneralUtility::makeInstance(Context::class)->getPropertyFromAspect('workspace', 'id');
if ($workspaceId > 0) {
$workspaceRecords = $this->database->fetchWorkspaceRecords($defaultRecords, $workspaceId);
$overlayed = [];
if (empty($defaultRecords)) {
return [];
}
if ($this->workspaceId > 0) {
$filtered = [];
$uidsHavingWorkspaceVersion = $this->database->fetchUidsHavingWorkspaceVersion($defaultRecords, $this->workspaceId);
foreach ($defaultRecords as $defaultRecord) {
$foundOverlay = null;
foreach ($workspaceRecords as $workspaceRecord) {
if ($workspaceRecord['t3ver_oid'] === $defaultRecord['uid']) {
$foundOverlay = $workspaceRecord;
}
}
if ($foundOverlay !== null) {
$overlayed[] = $foundOverlay;
} else {
$overlayed[] = $defaultRecord;
if ($defaultRecord['t3ver_wsid'] === $this->workspaceId) {
$filtered[] = $defaultRecord;
} elseif (in_array($defaultRecord['uid'], $uidsHavingWorkspaceVersion, true) === false) {
$filtered[] = $defaultRecord;
}
}
return $overlayed;
return $filtered;
}
// filter workspace placeholders
$filtered = [];
Expand Down Expand Up @@ -164,13 +165,15 @@ protected function buildContainerWithOverlay(int $uid, LanguageAspect $languageA
// connected mode
$childRecords = $this->database->fetchRecordsByParentAndLanguage($defaultRecord['uid'], 0);
if ($languageAspect->doOverlays()) {
$childRecords = $this->doWorkspaceOverlay($childRecords);
$childRecordsOverlays = $this->database->fetchOverlayRecords($childRecords, $language);
$childRecords = $this->doOverlay($childRecords, $childRecordsOverlays);
}
}
} else {
$childRecords = $this->database->fetchRecordsByParentAndLanguage($record['uid'], 0);
if ($languageAspect->doOverlays()) {
$childRecords = $this->doWorkspaceOverlay($childRecords);
$childRecordsOverlays = $this->database->fetchOverlayRecords($childRecords, $language);
$childRecords = $this->doOverlay($childRecords, $childRecordsOverlays);
}
Expand All @@ -196,7 +199,9 @@ protected function sortLocalizedRecordsByDefaultRecords(array $defaultRecords, a
$sorted = [];
foreach ($defaultRecords as $defaultRecord) {
foreach ($localizedRecords as $localizedRecord) {
if ($localizedRecord['l18n_parent'] === $defaultRecord['uid']) {
if ($localizedRecord['l18n_parent'] === $defaultRecord['uid'] ||
$localizedRecord['l18n_parent'] === $defaultRecord['t3ver_oid']
) {
$sorted[] = $localizedRecord;
}
}
Expand All @@ -215,7 +220,9 @@ protected function doOverlay(array $defaultRecords, array $localizedRecords): ar
foreach ($defaultRecords as $defaultRecord) {
$foundOverlay = null;
foreach ($localizedRecords as $localizedRecord) {
if ($localizedRecord['l18n_parent'] === $defaultRecord['uid']) {
if ($localizedRecord['l18n_parent'] === $defaultRecord['uid'] ||
$localizedRecord['l18n_parent'] === $defaultRecord['t3ver_oid']
) {
$foundOverlay = $localizedRecord;
}
}
Expand Down
75 changes: 56 additions & 19 deletions Classes/Domain/Factory/Database.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,37 @@
* of the License, or any later version.
*/

use TYPO3\CMS\Core\Context\Context;
use TYPO3\CMS\Core\Database\Connection;
use TYPO3\CMS\Core\Database\ConnectionPool;
use TYPO3\CMS\Core\Database\Query\QueryBuilder;
use TYPO3\CMS\Core\Database\Query\Restriction\DeletedRestriction;
use TYPO3\CMS\Core\Database\Query\Restriction\FrontendRestrictionContainer;
use TYPO3\CMS\Core\Database\Query\Restriction\FrontendWorkspaceRestriction;
use TYPO3\CMS\Core\SingletonInterface;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Core\Versioning\VersionState;

class Database implements SingletonInterface
{
/**
* @var int
*/
protected $backendUserId = 0;

/**
* @var int
*/
protected $workspaceId = 0;

public function __construct(Context $context = null)
{
if ($context === null) {
$context = GeneralUtility::makeInstance(Context::class);
}
$this->backendUserId = (int)$context->getPropertyFromAspect('backend.user', 'id', 0);
$this->workspaceId = (int)$context->getPropertyFromAspect('workspace', 'id');
}

/**
* @return QueryBuilder
Expand All @@ -31,8 +52,11 @@ protected function getQueryBuilder(): QueryBuilder
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('tt_content');
if (TYPO3_MODE === 'BE') {
$queryBuilder->getRestrictions()->removeAll()->add(GeneralUtility::makeInstance(DeletedRestriction::class));
} else {
} elseif (TYPO3_MODE === 'FE') {
$queryBuilder->setRestrictions(GeneralUtility::makeInstance(FrontendRestrictionContainer::class));
if ($this->backendUserId > 0) {
$queryBuilder->getRestrictions()->removeByType(FrontendWorkspaceRestriction::class);
}
}
return $queryBuilder;
}
Expand Down Expand Up @@ -91,7 +115,8 @@ public function fetchOneDefaultRecord(array $record): ?array
public function fetchRecordsByParentAndLanguage(int $parent, int $language): array
{
$queryBuilder = $this->getQueryBuilder();
$records = (array)$queryBuilder->select('*')

return (array)$queryBuilder->select('*')
->from('tt_content')
->where(
$queryBuilder->expr()->eq(
Expand All @@ -102,15 +127,21 @@ public function fetchRecordsByParentAndLanguage(int $parent, int $language): arr
'sys_language_uid',
$queryBuilder->createNamedParameter($language, \PDO::PARAM_INT)
),
$queryBuilder->expr()->eq(
't3ver_oid',
$queryBuilder->createNamedParameter(0, \PDO::PARAM_INT)
$queryBuilder->expr()->notIn(
't3ver_state',
$queryBuilder->createNamedParameter(
[VersionState::NEW_PLACEHOLDER, VersionState::MOVE_PLACEHOLDER],
Connection::PARAM_INT_ARRAY
)
),
$queryBuilder->expr()->in(
't3ver_wsid',
$queryBuilder->createNamedParameter([0, $this->workspaceId], Connection::PARAM_INT_ARRAY)
)
)
->orderBy('sorting', 'ASC')
->execute()
->fetchAll();
return $records;
}

/**
Expand All @@ -123,6 +154,9 @@ public function fetchOverlayRecords(array $records, int $language): array
$uids = [];
foreach ($records as $record) {
$uids[] = $record['uid'];
if ($record['t3ver_oid'] > 0) {
$uids[] = $record['t3ver_oid'];
}
}
$queryBuilder = $this->getQueryBuilder();
$records = (array)$queryBuilder->select('*')
Expand All @@ -136,30 +170,34 @@ public function fetchOverlayRecords(array $records, int $language): array
'sys_language_uid',
$queryBuilder->createNamedParameter($language, \PDO::PARAM_INT)
),
$queryBuilder->expr()->eq(
't3ver_oid',
$queryBuilder->createNamedParameter(0, \PDO::PARAM_INT)
$queryBuilder->expr()->notIn(
't3ver_state',
$queryBuilder->createNamedParameter(
[VersionState::NEW_PLACEHOLDER, VersionState::MOVE_PLACEHOLDER],
Connection::PARAM_INT_ARRAY
)
),
$queryBuilder->expr()->in(
't3ver_wsid',
$queryBuilder->createNamedParameter([0, $this->workspaceId], Connection::PARAM_INT_ARRAY)
)
)
->execute()
->fetchAll();

return $records;
}

/**
* @param array $records
* @param int $workspaceId
* @return array
*/
public function fetchWorkspaceRecords(array $records, int $workspaceId): array
public function fetchUidsHavingWorkspaceVersion(array $records, int $workspaceId): array
{
if (empty($records)) {
return [];
}
$uids = [];
foreach ($records as $record) {
$uids[] = $record['uid'];
}
$queryBuilder = $this->getQueryBuilder();
$records = (array)$queryBuilder->select('*')
return (array)$queryBuilder->select('t3ver_oid')
->from('tt_content')
->where(
$queryBuilder->expr()->in(
Expand All @@ -172,8 +210,7 @@ public function fetchWorkspaceRecords(array $records, int $workspaceId): array
)
)
->execute()
->fetchAll();
return $records;
->fetchAll(\PDO::FETCH_COLUMN);
}

/**
Expand Down
23 changes: 23 additions & 0 deletions Classes/Hooks/Datahandler/Database.php
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,29 @@ public function fetchOneRecord(int $uid): ?array
return $record;
}

/**
* @param int $uid
* @return array|null
*/
public function fetchOneMovedRecord(int $uid): ?array
{
$queryBuilder = $this->getQueryBuilder();
$record = $queryBuilder->select('*')
->from('tt_content')
->where(
$queryBuilder->expr()->eq(
't3ver_move_id',
$queryBuilder->createNamedParameter($uid, \PDO::PARAM_INT)
)
)
->execute()
->fetch();
if ($record === false) {
return null;
}
return $record;
}

/**
* @param array $record
* @return array
Expand Down
35 changes: 31 additions & 4 deletions Classes/Hooks/Datahandler/DatamapAfterDatabaseOperationHook.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,24 @@
* of the License, or any later version.
*/

use TYPO3\CMS\Backend\Utility\BackendUtility;
use TYPO3\CMS\Core\DataHandling\DataHandler;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Core\Utility\MathUtility;

class DatamapAfterDatabaseOperationHook
{
/**
* @var Database
*/
protected $database;

/**
* @param Database|null $database
*/
public function __construct(Database $database = null)
{
$this->database = $database ?? GeneralUtility::makeInstance(Database::class);
}

/**
* @param string $status
Expand All @@ -33,19 +44,35 @@ public function processDatamap_afterDatabaseOperations(string $status, string $t
if (
$table === 'tt_content' &&
$status === 'update' &&
$dataHandler->BE_USER->workspace > 0 &&
MathUtility::canBeInterpretedAsInteger($id) &&
is_array($dataHandler->datamap['tt_content'])
) {
$datamapForPlaceHolders = ['tt_content' => []];
foreach ($dataHandler->datamap['tt_content'] as $origId => $data) {
if (!empty($data['tx_container_parent']) && $data['tx_container_parent'] > 0) {
$workspaceVersion = BackendUtility::getWorkspaceVersionOfRecord($dataHandler->BE_USER->workspace, $table, $origId, 'uid,t3ver_oid');
if ((int)$workspaceVersion['uid'] === (int)$id && (int)$workspaceVersion['uid'] !== (int)$origId) {
$origRecord = $this->database->fetchOneRecord((int)$origId);
// origRecord is copied placeholder
if (
(int)$origRecord['t3ver_oid'] === 0 &&
(int)$origRecord['tx_container_parent'] !== (int)$data['tx_container_parent'] &&
(int)$origRecord['t3ver_wsid'] === (int)$dataHandler->BE_USER->workspace
) {
$datamapForPlaceHolders['tt_content'][$origId] = ['tx_container_parent' => $data['tx_container_parent']];
} else {
// origRecord is moved placehoder
$origRecord = $this->database->fetchOneMovedRecord((int)$origId);
if (
(int)$origRecord['t3ver_oid'] === 0 &&
(int)$origRecord['tx_container_parent'] !== (int)$data['tx_container_parent'] &&
(int)$origRecord['t3ver_wsid'] === (int)$dataHandler->BE_USER->workspace
) {
$datamapForPlaceHolders['tt_content'][$origRecord['uid']] = ['tx_container_parent' => $data['tx_container_parent']];
}
}
}
}
if (count($datamapForPlaceHolders['tt_content']) > 0) {
if (!empty($datamapForPlaceHolders['tt_content'])) {
$localDataHandler = GeneralUtility::makeInstance(DataHandler::class);
$localDataHandler->bypassWorkspaceRestrictions = true;
$localDataHandler->start($datamapForPlaceHolders, [], $dataHandler->BE_USER);
Expand Down
Loading

0 comments on commit fa39597

Please sign in to comment.