From 431fb197696361b2e1e043c4384d9df8f067a22a Mon Sep 17 00:00:00 2001 From: Timo Schmidt Date: Sat, 21 Jan 2017 12:24:46 +0100 Subject: [PATCH] [TASK] Introduce TCAService * Introduces a TCAService class that allows to perform TCA related checks for records * Add unit tests for TCAService * Replaces usage in RecordMonitor and GarbageCollector Fixes: #903 --- Classes/GarbageCollector.php | 157 ++--------- Classes/IndexQueue/Queue.php | 2 +- Classes/IndexQueue/RecordMonitor.php | 67 ++--- Classes/System/TCA/TCAService.php | 228 ++++++++++++++++ Tests/Unit/System/TCA/TCAServiceTest.php | 334 +++++++++++++++++++++++ 5 files changed, 610 insertions(+), 178 deletions(-) create mode 100644 Classes/System/TCA/TCAService.php create mode 100644 Tests/Unit/System/TCA/TCAServiceTest.php diff --git a/Classes/GarbageCollector.php b/Classes/GarbageCollector.php index c3e87aed51..c6a70d311d 100644 --- a/Classes/GarbageCollector.php +++ b/Classes/GarbageCollector.php @@ -26,6 +26,7 @@ use ApacheSolrForTypo3\Solr\GarbageCollectorPostProcessor; use ApacheSolrForTypo3\Solr\IndexQueue\Queue; +use ApacheSolrForTypo3\Solr\System\TCA\TCAService; use TYPO3\CMS\Backend\Utility\BackendUtility; use TYPO3\CMS\Core\DataHandling\DataHandler; use TYPO3\CMS\Core\SingletonInterface; @@ -42,8 +43,25 @@ */ class GarbageCollector extends AbstractDataHandlerListener implements SingletonInterface { + /** + * @var array + */ protected $trackedRecords = []; + /** + * @var TCAService + */ + protected $tcaService; + + /** + * GarbageCollector constructor. + * @param TCAService|null $TCAService + */ + public function __construct(TCAService $TCAService = null) + { + $this->tcaService = is_null($TCAService) ? GeneralUtility::makeInstance(TCAService::class) : $TCAService; + } + /** * Hooks into TCE main and tracks record deletion commands. * @@ -286,12 +304,10 @@ public function processDatamap_preProcessFieldArray( return; } - $visibilityAffectingFields = $this->getVisibilityAffectingFieldsByTable($table); + $hasConfiguredEnableColumnForFeGroup = $this->tcaService->isEnableColumn($table, 'fe_group'); - if (isset($GLOBALS['TCA'][$table]['ctrl']['enablecolumns']) - && array_key_exists('fe_group', - $GLOBALS['TCA'][$table]['ctrl']['enablecolumns']) - ) { + if ($hasConfiguredEnableColumnForFeGroup) { + $visibilityAffectingFields = $this->tcaService->getVisibilityAffectingFieldsByTable($table); $record = BackendUtility::getRecord( $table, $uid, @@ -299,67 +315,13 @@ public function processDatamap_preProcessFieldArray( '', false ); - $record = $this->normalizeFrontendGroupField($table, $record); + $record = $this->tcaService->normalizeFrontendGroupField($table, $record); // keep previous state of important fields for later comparison $this->trackedRecords[$table][$uid] = $record; } } - /** - * Compiles a list of visibility affecting fields of a table so that it can - * be used in SQL queries. - * - * @param string $table Table name to retrieve visibility affecting fields for - * @return string Comma separated list of field names that affect the visibility of a record on the website - */ - protected function getVisibilityAffectingFieldsByTable($table) - { - static $visibilityAffectingFields; - - if (!isset($visibilityAffectingFields[$table])) { - // we always want to get the uid and pid although they do not affect visibility - $fields = ['uid', 'pid']; - if (isset($GLOBALS['TCA'][$table]['ctrl']['enablecolumns'])) { - $fields = array_merge($fields, - $GLOBALS['TCA'][$table]['ctrl']['enablecolumns']); - } - - if (isset($GLOBALS['TCA'][$table]['ctrl']['delete'])) { - $fields[] = $GLOBALS['TCA'][$table]['ctrl']['delete']; - } - - if ($table == 'pages') { - $fields[] = 'no_search'; - $fields[] = 'doktype'; - } - - $visibilityAffectingFields[$table] = implode(', ', $fields); - } - - return $visibilityAffectingFields[$table]; - } - - /** - * Makes sure that "empty" frontend group fields are always the same value. - * - * @param string $table The record's table name. - * @param array $record the record array. - * @return array The cleaned record - */ - protected function normalizeFrontendGroupField($table, $record) - { - if (isset($GLOBALS['TCA'][$table]['ctrl']['enablecolumns']['fe_group'])) { - $frontendGroupsField = $GLOBALS['TCA'][$table]['ctrl']['enablecolumns']['fe_group']; - - if ($record[$frontendGroupsField] == '') { - $record[$frontendGroupsField] = '0'; - } - } - - return $record; - } - /** * Hooks into TCE Main and watches all record updates. If a change is * detected that would remove the record from the website, we try to find @@ -388,15 +350,14 @@ public function processDatamap_afterDatabaseOperations( return; } - $garbageCollectionRelevantFields = $this->getVisibilityAffectingFieldsByTable($table); + $garbageCollectionRelevantFields = $this->tcaService->getVisibilityAffectingFieldsByTable($table); - $record = BackendUtility::getRecord($table, $uid, - $garbageCollectionRelevantFields, '', false); - $record = $this->normalizeFrontendGroupField($table, $record); + $record = BackendUtility::getRecord($table, $uid, $garbageCollectionRelevantFields, '', false); + $record = $this->tcaService->normalizeFrontendGroupField($table, $record); - if ($this->isHidden($table, $record) - || (($this->isStartTimeInFuture($table, $record) - || $this->isEndTimeInPast($table, $record)) + if ($this->tcaService->isHidden($table, $record) + || (($this->tcaService->isStartTimeInFuture($table, $record) + || $this->tcaService->isEndTimeInPast($table, $record)) && $this->isMarkedAsIndexed($table, $record) ) || $this->hasFrontendGroupsRemoved($table, $record) @@ -411,68 +372,6 @@ public function processDatamap_afterDatabaseOperations( } } - /** - * Checks whether a hidden field exists for the current table and if so - * determines whether it is set on the current record. - * - * @param string $table The table name. - * @param array $record An array with record fields that may affect visibility. - * @return bool True if the record is hidden, FALSE otherwise. - */ - protected function isHidden($table, $record) - { - $hidden = false; - - if (isset($GLOBALS['TCA'][$table]['ctrl']['enablecolumns']['disabled'])) { - $hiddenField = $GLOBALS['TCA'][$table]['ctrl']['enablecolumns']['disabled']; - $hidden = (boolean)$record[$hiddenField]; - } - - return $hidden; - } - - /** - * Checks whether a start time field exists for the record's table and if so - * determines if a time is set and whether that time is in the future, - * making the record invisible on the website. - * - * @param string $table The table name. - * @param array $record An array with record fields that may affect visibility. - * @return bool True if the record's start time is in the future, FALSE otherwise. - */ - protected function isStartTimeInFuture($table, $record) - { - $startTimeInFuture = false; - - if (isset($GLOBALS['TCA'][$table]['ctrl']['enablecolumns']['starttime'])) { - $startTimeField = $GLOBALS['TCA'][$table]['ctrl']['enablecolumns']['starttime']; - $startTimeInFuture = $record[$startTimeField] > time(); - } - - return $startTimeInFuture; - } - - /** - * Checks whether a end time field exists for the record's table and if so - * determines if a time is set and whether that time is in the past, - * making the record invisible on the website. - * - * @param string $table The table name. - * @param array $record An array with record fields that may affect visibility. - * @return bool True if the record's end time is in the past, FALSE otherwise. - */ - protected function isEndTimeInPast($table, $record) - { - $endTimeInPast = false; - - if (isset($GLOBALS['TCA'][$table]['ctrl']['enablecolumns']['endtime'])) { - $endTimeField = $GLOBALS['TCA'][$table]['ctrl']['enablecolumns']['endtime']; - $endTimeInPast = $record[$endTimeField] < time(); - } - - return $endTimeInPast; - } - /** * Checks whether the record is in the Index Queue and whether it has been * indexed already. diff --git a/Classes/IndexQueue/Queue.php b/Classes/IndexQueue/Queue.php index 61410a81c8..ca0c178e74 100644 --- a/Classes/IndexQueue/Queue.php +++ b/Classes/IndexQueue/Queue.php @@ -708,7 +708,7 @@ public function getItem($itemId) * * @param string $itemType item type, usually the table name * @param int $itemUid item uid - * @return array An array of items matching $itemType and $itemUid + * @return Item[] An array of items matching $itemType and $itemUid */ public function getItems($itemType, $itemUid) { diff --git a/Classes/IndexQueue/RecordMonitor.php b/Classes/IndexQueue/RecordMonitor.php index fcb1b7d146..18f71ccb38 100644 --- a/Classes/IndexQueue/RecordMonitor.php +++ b/Classes/IndexQueue/RecordMonitor.php @@ -29,6 +29,7 @@ use ApacheSolrForTypo3\Solr\GarbageCollector; use ApacheSolrForTypo3\Solr\IndexQueue\Queue; use ApacheSolrForTypo3\Solr\System\Configuration\TypoScriptConfiguration; +use ApacheSolrForTypo3\Solr\System\TCA\TCAService; use ApacheSolrForTypo3\Solr\Util; use TYPO3\CMS\Backend\Utility\BackendUtility; use TYPO3\CMS\Core\DataHandling\DataHandler; @@ -64,16 +65,26 @@ class RecordMonitor extends AbstractDataHandlerListener */ protected $mountPageUpdater; + + /** + * TCA Service + * + * @var TCAService + */ + protected $tcaService; + /** * RecordMonitor constructor. * * @param Queue|null $indexQueue * @param MountPagesUpdater|null $mountPageUpdater + * @param TCAService|null $TCAService */ - public function __construct(Queue $indexQueue = null, MountPagesUpdater $mountPageUpdater = null) + public function __construct(Queue $indexQueue = null, MountPagesUpdater $mountPageUpdater = null, TCAService $TCAService = null) { $this->indexQueue = is_null($indexQueue) ? GeneralUtility::makeInstance(Queue::class) : $indexQueue; $this->mountPageUpdater = is_null($mountPageUpdater) ? GeneralUtility::makeInstance(MountPagesUpdater::class) : $mountPageUpdater; + $this->tcaService = is_null($TCAService) ? GeneralUtility::makeInstance(TCAService::class) : $TCAService; } /** @@ -158,11 +169,8 @@ public function processCmdmap_postProcess( $this->solrConfiguration = Util::getSolrConfigurationFromPageId($uid); $record = $this->getRecord($table, $uid); - if (!empty($record) && $this->isEnabledRecord($table, - $record) - ) { + if (!empty($record) && $this->tcaService->isEnabledRecord($table, $record)) { $this->mountPageUpdater->update($uid); - $this->indexQueue->updateItem($table, $uid); } else { // TODO should be moved to garbage collector @@ -179,9 +187,7 @@ public function processCmdmap_postProcess( if ($isMonitoredTable) { $record = $this->getRecord($table, $uid); - if (!empty($record) && $this->isEnabledRecord($table, - $record) - ) { + if (!empty($record) && $this->tcaService->isEnabledRecord($table, $record)) { if (Util::isLocalizedRecord($table, $record)) { // if it's a localization overlay, update the original record instead $uid = $record[$GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField']]; @@ -205,7 +211,7 @@ public function processCmdmap_postProcess( // moving pages in LIVE workspace $this->solrConfiguration = Util::getSolrConfigurationFromPageId($uid); $record = $this->getRecord('pages', $uid); - if (!empty($record) && $this->isEnabledRecord($table, $record)) { + if (!empty($record) && $this->tcaService->isEnabledRecord($table, $record)) { $this->indexQueue->updateItem('pages', $uid); } else { // check if the item should be removed from the index because it no longer matches the conditions @@ -312,7 +318,7 @@ protected function processRecord($recordTable, $recordPageId, $recordUid, $field // we have a localized record without a visible parent record. Nothing to do. return; } - if ($this->isEnabledRecord($recordTable, $record)) { + if ($this->tcaService->isEnabledRecord($recordTable, $record)) { $configurationName = $this->getIndexingConfigurationName($recordTable, $recordUid); $this->indexQueue->updateItem($recordTable, $recordUid, $configurationName); @@ -335,7 +341,7 @@ protected function getIsTranslationParentRecordEnabled($recordTable, $recordUid) { $tableEnableFields = implode(', ', $GLOBALS['TCA'][$recordTable]['ctrl']['enablecolumns']); $l10nParentRecord = BackendUtility::getRecord($recordTable, $recordUid, $tableEnableFields, '', false); - return $this->isEnabledRecord($recordTable, $l10nParentRecord); + return $this->tcaService->isEnabledRecord($recordTable, $l10nParentRecord); } /** @@ -367,14 +373,8 @@ protected function doPagesPostUpdateOperations(array $fields, $recordUid) * * @return int */ - protected function getRecordPageId( - $status, - $recordTable, - $recordUid, - $originalUid, - array $fields, - DataHandler $tceMain - ) { + protected function getRecordPageId($status, $recordTable, $recordUid, $originalUid, array $fields, DataHandler $tceMain) + { if ($status == 'update' && !isset($fields['pid'])) { $recordPageId = $this->getValidatedPid($tceMain, $recordTable, $recordUid); if ($recordTable == 'pages' && Util::isRootPage($recordUid)) { @@ -477,35 +477,6 @@ protected function getValidatedPid(DataHandler $tceMain, $table, $uid) return $pid; } - /** - * Checks if a record is "enabled" - * - * A record is considered "enabled" if - * - it is not hidden - * - it is not deleted - * - as a page it is not set to be excluded from search - * - * @param string $table The record's table name - * @param array $record The record to check - * @return bool TRUE if the record is enabled, FALSE otherwise - */ - protected function isEnabledRecord($table, $record) - { - $recordEnabled = true; - - if ( - (isset($GLOBALS['TCA'][$table]['ctrl']['enablecolumns']['disabled']) && !empty($record[$GLOBALS['TCA'][$table]['ctrl']['enablecolumns']['disabled']])) - || - (isset($GLOBALS['TCA'][$table]['ctrl']['delete']) && !empty($record[$GLOBALS['TCA'][$table]['ctrl']['delete']])) - || - ($table == 'pages' && !empty($record['no_search'])) - ) { - $recordEnabled = false; - } - - return $recordEnabled; - } - /** * Retrieves the name of the Indexing Queue Configuration for a record * diff --git a/Classes/System/TCA/TCAService.php b/Classes/System/TCA/TCAService.php new file mode 100644 index 0000000000..350248942a --- /dev/null +++ b/Classes/System/TCA/TCAService.php @@ -0,0 +1,228 @@ + + */ +class TCAService +{ + /** + * @var array + */ + protected $tca = []; + + /** + * @var array + */ + protected $visibilityAffectingFields = []; + + /** + * TCAService constructor. + * @param null $TCA + */ + public function __construct($TCA = null) + { + $this->tca = (array) (is_null($TCA) ? $GLOBALS['TCA'] : $TCA); + } + + /** + * @return integer + */ + protected function getTime() + { + return isset($GLOBALS['EXEC_TIME']) ? $GLOBALS['EXEC_TIME'] : time(); + } + + /** + * Checks if a record is "enabled" + * + * A record is considered "enabled" if + * - it is not hidden + * - it is not deleted + * - as a page it is not set to be excluded from search + * + * @param string $table The record's table name + * @param array $record The record to check + * @return bool TRUE if the record is enabled, FALSE otherwise + */ + public function isEnabledRecord($table, $record) + { + if ( + (isset($this->tca[$table]['ctrl']['enablecolumns']['disabled']) && !empty($record[$this->tca[$table]['ctrl']['enablecolumns']['disabled']])) + || + (isset($this->tca[$table]['ctrl']['delete']) && !empty($record[$this->tca[$table]['ctrl']['delete']])) + || + ($table == 'pages' && !empty($record['no_search'])) + ) { + return false; + } + + return true; + } + + /** + * Checks whether a end time field exists for the record's table and if so + * determines if a time is set and whether that time is in the past, + * making the record invisible on the website. + * + * @param string $table The table name. + * @param array $record An array with record fields that may affect visibility. + * @return bool True if the record's end time is in the past, FALSE otherwise. + */ + public function isEndTimeInPast($table, $record) + { + $endTimeInPast = false; + + if (isset($this->tca[$table]['ctrl']['enablecolumns']['endtime'])) { + $endTimeField = $this->tca[$table]['ctrl']['enablecolumns']['endtime']; + $endTimeInPast = $record[$endTimeField] < $this->getTime(); + } + + return $endTimeInPast; + } + + /** + * This method can be used to check if there is a configured key in + * + * $GLOBALS['TCA']['mytable']['ctrl']['enablecolumns'] + * + * Example: + * + * $GLOBALS['TCA']['mytable']]['ctrl']['enablecolumns']['fe_group'] = 'mygroupfield' + * + * ->isEnableColumn('mytable', 'fe_group') will return true, because 'mygroupfield' is + * configured as column. + * + * @params string $table + * @param string $columnName + * @return bool + */ + public function isEnableColumn($table, $columnName) + { + return ( + isset($GLOBALS['TCA'][$table]['ctrl']['enablecolumns']) && + array_key_exists($columnName, $GLOBALS['TCA'][$table]['ctrl']['enablecolumns']) + ); + } + + /** + * Checks whether a start time field exists for the record's table and if so + * determines if a time is set and whether that time is in the future, + * making the record invisible on the website. + * + * @param string $table The table name. + * @param array $record An array with record fields that may affect visibility. + * @return bool True if the record's start time is in the future, FALSE otherwise. + */ + public function isStartTimeInFuture($table, $record) + { + $startTimeInFuture = false; + + if (isset($this->tca[$table]['ctrl']['enablecolumns']['starttime'])) { + $startTimeField = $this->tca[$table]['ctrl']['enablecolumns']['starttime']; + $startTimeInFuture = $record[$startTimeField] > $this->getTime(); + } + + return $startTimeInFuture; + } + + + /** + * Checks whether a hidden field exists for the current table and if so + * determines whether it is set on the current record. + * + * @param string $table The table name. + * @param array $record An array with record fields that may affect visibility. + * @return bool True if the record is hidden, FALSE otherwise. + */ + public function isHidden($table, $record) + { + $hidden = false; + + if (isset($this->tca[$table]['ctrl']['enablecolumns']['disabled'])) { + $hiddenField = $this->tca[$table]['ctrl']['enablecolumns']['disabled']; + $hidden = (boolean)$record[$hiddenField]; + } + + return $hidden; + } + + /** + * Makes sure that "empty" frontend group fields are always the same value. + * + * @param string $table The record's table name. + * @param array $record the record array. + * @return array The cleaned record + */ + public function normalizeFrontendGroupField($table, $record) + { + if (isset($this->tca[$table]['ctrl']['enablecolumns']['fe_group'])) { + $frontendGroupsField = $this->tca[$table]['ctrl']['enablecolumns']['fe_group']; + + if ($record[$frontendGroupsField] == '') { + $record[$frontendGroupsField] = '0'; + } + } + + return $record; + } + + /** + * Compiles a list of visibility affecting fields of a table so that it can + * be used in SQL queries. + * + * @param string $table Table name to retrieve visibility affecting fields for + * @return string Comma separated list of field names that affect the visibility of a record on the website + */ + public function getVisibilityAffectingFieldsByTable($table) + { + if (isset($this->visibilityAffectingFields[$table])) { + return $this->visibilityAffectingFields[$table]; + } + + // we always want to get the uid and pid although they do not affect visibility + $fields = ['uid', 'pid']; + if (isset($this->tca[$table]['ctrl']['enablecolumns'])) { + $fields = array_merge($fields, $this->tca[$table]['ctrl']['enablecolumns']); + } + + if (isset($this->tca[$table]['ctrl']['delete'])) { + $fields[] = $this->tca[$table]['ctrl']['delete']; + } + + if ($table == 'pages') { + $fields[] = 'no_search'; + $fields[] = 'doktype'; + } + + $this->visibilityAffectingFields[$table] = implode(', ', $fields); + + return $this->visibilityAffectingFields[$table]; + } +} diff --git a/Tests/Unit/System/TCA/TCAServiceTest.php b/Tests/Unit/System/TCA/TCAServiceTest.php new file mode 100644 index 0000000000..c86017a5c5 --- /dev/null +++ b/Tests/Unit/System/TCA/TCAServiceTest.php @@ -0,0 +1,334 @@ + + * All rights reserved + * + * This script is part of the TYPO3 project. The TYPO3 project is + * free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * The GNU General Public License can be found at + * http://www.gnu.org/copyleft/gpl.html. + * + * This script is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * This copyright notice MUST APPEAR in all copies of the script! + ***************************************************************/ + +use ApacheSolrForTypo3\Solr\System\TCA\TCAService; +use ApacheSolrForTypo3\Solr\Tests\Unit\UnitTest; + +/** + * Testcase to test the TCAService. + * + * @author Timo Hund + */ +class TCAServiceTest extends UnitTest +{ + + /** + * When a deleted record is passed (has 1 in the TCA deleted field, this should be detected). + * + * @test + */ + public function getIsEnabledRecordDetectDeletedRecord() { + $fakeTCA = [ + 'pages' => [ + 'ctrl' => [ + 'delete' => 'deleted' + ] + ] + ]; + + $fakePageRecord = [ + 'deleted' => 1 + ]; + + $tcaService = new TCAService($fakeTCA); + $isVisible = $tcaService->isEnabledRecord('pages', $fakePageRecord); + + $this->assertFalse($isVisible); + } + + /** + * When a record is passed that is not deleted we should detect that. + * + * @test + */ + public function getIsEnabledRecordDetectNonDeletedRecord() { + $fakeTCA = [ + 'pages' => [ + 'ctrl' => [ + 'delete' => 'deleted' + ] + ] + ]; + + $fakePageRecord = [ + 'title' => 'hello world' + ]; + + $tcaService = new TCAService($fakeTCA); + $isVisible = $tcaService->isEnabledRecord('pages', $fakePageRecord); + + $this->assertTrue($isVisible); + } + + /** + * When a page record is passed with the field no_search = 1 it should be detected is invisible + * + * @test + */ + public function getIsEnabledRecordDetectsPageConfiguredWithNoSearch() { + $fakeTCA = [ + 'pages' => [ + 'ctrl' => [ + 'delete' => 'deleted' + ] + ] + ]; + + $fakePageRecord = [ + 'no_search' => 1 + ]; + + $tcaService = new TCAService($fakeTCA); + $isVisible = $tcaService->isEnabledRecord('pages', $fakePageRecord); + + $this->assertFalse($isVisible); + } + + + /** + * @test + */ + public function isEndTimeInPastCanDetectedEndtimeThatIsInPast() { + $fakeTCA = [ + 'pages' => [ + 'ctrl' => [ + 'enablecolumns' => [ + 'endtime' => 'end' + ] + ] + ] + ]; + + $GLOBALS['EXEC_TIME'] = 1000; + $fakePageRecord = [ + 'end' => 999 + ]; + $tcaService = new TCAService($fakeTCA); + $isEndTimeInPast = $tcaService->isEndTimeInPast('pages', $fakePageRecord); + + $this->assertTrue($isEndTimeInPast, 'Endtime in past was not detected as endtime in past'); + } + + + /** + * @test + */ + public function isEndTimeInPastCanDetectedEndtimeThatIsNotInPast() { + $fakeTCA = [ + 'pages' => [ + 'ctrl' => [ + 'enablecolumns' => [ + 'endtime' => 'end' + ] + ] + ] + ]; + + $GLOBALS['EXEC_TIME'] = 1000; + $fakePageRecord = [ + 'end' => 1001 + ]; + $tcaService = new TCAService($fakeTCA); + $isEndTimeInPast = $tcaService->isEndTimeInPast('pages', $fakePageRecord); + + $this->assertFalse($isEndTimeInPast, 'Endtime in future, was detected as endtime in past'); + } + + /** + * @test + */ + public function isStartTimeInFutureCanDetectedStartTimeInFuture() { + $fakeTCA = [ + 'pages' => [ + 'ctrl' => [ + 'enablecolumns' => [ + 'starttime' => 'start' + ] + ] + ] + ]; + + $GLOBALS['EXEC_TIME'] = 1000; + $fakePageRecord = [ + 'start' => 1001 + ]; + $tcaService = new TCAService($fakeTCA); + $isStartTimeInFuture = $tcaService->isStartTimeInFuture('pages', $fakePageRecord); + + $this->assertTrue($isStartTimeInFuture, 'Starttime in future was not detected as start time in future'); + } + + /** + * @test + */ + public function isStartTimeInFutureCanDetectedStartTimeNotInFuture() { + $fakeTCA = [ + 'pages' => [ + 'ctrl' => [ + 'enablecolumns' => [ + 'starttime' => 'start' + ] + ] + ] + ]; + + $GLOBALS['EXEC_TIME'] = 1000; + $fakePageRecord = [ + 'start' => 999 + ]; + $tcaService = new TCAService($fakeTCA); + $isStartTimeInFuture = $tcaService->isStartTimeInFuture('pages', $fakePageRecord); + + $this->assertFalse($isStartTimeInFuture, 'Start time in past was detected as starttime in future'); + } + + /** + * @test + */ + public function isHiddenCanDetectHiddenRecord() { + $fakeTCA = [ + 'pages' => [ + 'ctrl' => [ + 'enablecolumns' => [ + 'disabled' => 'hidden' + ] + ] + ] + ]; + + $fakePageRecord = [ + 'hidden' => 1 + ]; + $tcaService = new TCAService($fakeTCA); + $isHidden = $tcaService->isHidden('pages', $fakePageRecord); + + $this->assertTrue($isHidden, 'Page was expected to be hidden'); + } + + /** + * @test + */ + public function isHiddenCanDetectNonHiddenRecord() { + $fakeTCA = [ + 'pages' => [ + 'ctrl' => [ + 'enablecolumns' => [ + 'disabled' => 'hidden' + ] + ] + ] + ]; + + $fakePageRecord = [ + 'hidden' => 0 + ]; + $tcaService = new TCAService($fakeTCA); + $isHidden = $tcaService->isHidden('pages', $fakePageRecord); + + $this->assertFalse($isHidden, 'Page was not expected to be hidden'); + } + + /** + * @test + */ + public function canNormalizeFrontendGroupField() { + $fakeTCA = [ + 'pages' => [ + 'ctrl' => [ + 'enablecolumns' => [ + 'fe_group' => 'fe_groups' + ] + ] + ] + ]; + + $fakePageRecord = []; + $tcaService = new TCAService($fakeTCA); + $normalizedRecord = $tcaService->normalizeFrontendGroupField('pages', $fakePageRecord); + + $this->assertSame($normalizedRecord['fe_groups'], '0', 'Empty fe_group field was not normalized to 0'); + } + + /** + * @test + */ + public function getVisibilityAffectingFieldsByTableCanReturnDefaultFieldsWhenNoTCAIsConfigured() + { + $tcaService = new TCAService([]); + $visibilityFields = $tcaService->getVisibilityAffectingFieldsByTable('pages'); + + $this->assertContains('doktype', $visibilityFields, 'Expected to have doktype as visibility affecting field as default for pages'); + $this->assertContains('no_search', $visibilityFields, 'Expected to have no_search as visibility affecting field as default for pages'); + } + + /** + * @test + */ + public function getVisibilityAffectingFieldsByTableCanReturnUidAndPidForNormalRecordTable() + { + $tcaService = new TCAService([]); + $visibilityFields = $tcaService->getVisibilityAffectingFieldsByTable('tx_domain_model_faketable'); + $this->assertEquals('uid, pid', $visibilityFields, 'TCA Service should return uid and pid of visibility affecting fields for record table where no TCA is configured'); + } + + /** + * @test + */ + public function getVisibilityAffectingFieldsByTableCanReturnConfiguredDeleteField() + { + $fakeTCA = [ + 'tx_domain_model_faketable' => [ + 'ctrl' => [ + 'delete' => 'deleted' + ] + ] + ]; + + $tcaService = new TCAService($fakeTCA); + $visibilityFields = $tcaService->getVisibilityAffectingFieldsByTable('tx_domain_model_faketable'); + $this->assertContains('deleted', $visibilityFields, 'The deleted field should be retrieved as visibility affecting field'); + } + + /** + * @test + */ + public function getVisibilityAffectingFieldsByTableCanReturnConfiguredEnableConfiguredEnabledColumnFields() + { + $fakeTCA = [ + 'tx_domain_model_faketable' => [ + 'ctrl' => [ + 'enablecolumns' => [ + 'fe_group' => 'fe_groups' + ] + ] + ] + ]; + + $tcaService = new TCAService($fakeTCA); + $visibilityFields = $tcaService->getVisibilityAffectingFieldsByTable('tx_domain_model_faketable'); + $this->assertContains('fe_groups', $visibilityFields, 'The field fe_groups should be retrieved as visbility affecting field'); + } +} \ No newline at end of file