[BUGFIX] Query Generation creates invalid query in BE scope
authorAnja Leichsenring <aleichsenring@ab-softlab.de>
Fri, 12 Oct 2012 07:15:31 +0000 (09:15 +0200)
committerHelmut Hummel <helmut.hummel@typo3.org>
Sat, 13 Oct 2012 12:09:32 +0000 (14:09 +0200)
While in Backend scope, no $GLOBALS['TSFE'] is available and there
is no check in place nor a fallback to prevent extbase from generating
incomplete or empty query contraints.

This patch adds the missing check and fallback to the sys_language_uid
constraint.

Change-Id: I2ed9eb01ba83ce0763c3e692a1e9ff05147a49e1
Fixes: #41904
Releases: 6.0
Reviewed-on: http://review.typo3.org/15517
Tested-by: Wouter Wolters
Reviewed-by: Markus Günther
Tested-by: Markus Günther
Reviewed-by: Helmut Hummel
Tested-by: Helmut Hummel
typo3/sysext/extbase/Classes/Persistence/Generic/Storage/Typo3DbBackend.php
typo3/sysext/extbase/Tests/Unit/Persistence/Storage/Typo3DbBackendTest.php

index 3744cbe..11d7947 100644 (file)
@@ -923,18 +923,27 @@ class Typo3DbBackend implements \TYPO3\CMS\Extbase\Persistence\Generic\Storage\B
         */
        protected function addSysLanguageStatement($tableName, array &$sql) {
                if (is_array($GLOBALS['TCA'][$tableName]['ctrl'])) {
-                       if (isset($GLOBALS['TCA'][$tableName]['ctrl']['languageField']) && $GLOBALS['TCA'][$tableName]['ctrl']['languageField'] !== NULL) {
+                       if (!empty($GLOBALS['TCA'][$tableName]['ctrl']['languageField'])) {
                                // Select all entries for the current language
-                               $additionalWhereClause = $tableName . '.' . $GLOBALS['TCA'][$tableName]['ctrl']['languageField'] . ' IN (' . $GLOBALS['TSFE']->sys_language_uid . ',-1)';
-                               // If any language is set -> get those entries which are not translated yet
-                               // They will be removed by t3lib_page::getRecordOverlay if not matching overlay mode
-                               if ($GLOBALS['TSFE']->sys_language_uid && isset($GLOBALS['TCA'][$tableName]['ctrl']['transOrigPointerField'])) {
-                                       $additionalWhereClause .= ' OR (' . $tableName . '.' . $GLOBALS['TCA'][$tableName]['ctrl']['languageField'] . '=0 AND ' . $tableName . '.uid NOT IN (' . 'SELECT ' . $tableName . '.' . $GLOBALS['TCA'][$tableName]['ctrl']['transOrigPointerField'] . ' FROM ' . $tableName . ' WHERE ' . $tableName . '.' . $GLOBALS['TCA'][$tableName]['ctrl']['transOrigPointerField'] . '>0 AND ' . $tableName . '.' . $GLOBALS['TCA'][$tableName]['ctrl']['languageField'] . '>0';
-                                       // Add delete clause to ensure all entries are loaded
-                                       if (isset($GLOBALS['TCA'][$tableName]['ctrl']['delete'])) {
-                                               $additionalWhereClause .= ' AND ' . $tableName . '.' . $GLOBALS['TCA'][$tableName]['ctrl']['delete'] . '=0';
+                               if (isset($GLOBALS['TSFE']) && is_object($GLOBALS['TSFE'])) {
+                                       $additionalWhereClause = $tableName . '.' . $GLOBALS['TCA'][$tableName]['ctrl']['languageField'] . ' IN (' . $GLOBALS['TSFE']->sys_language_uid . ',-1)';
+                                       // If any language is set -> get those entries which are not translated yet
+                                       // They will be removed by t3lib_page::getRecordOverlay if not matching overlay mode
+                                       if ($GLOBALS['TSFE']->sys_language_uid && isset($GLOBALS['TCA'][$tableName]['ctrl']['transOrigPointerField'])) {
+                                               $additionalWhereClause .= ' OR (' . $tableName . '.' . $GLOBALS['TCA'][$tableName]['ctrl']['languageField'] . '=0' .
+                                                       ' AND ' . $tableName . '.uid NOT IN (' . 'SELECT ' . $tableName . '.' . $GLOBALS['TCA'][$tableName]['ctrl']['transOrigPointerField'] .
+                                                       ' FROM ' . $tableName .
+                                                       ' WHERE ' . $tableName . '.' . $GLOBALS['TCA'][$tableName]['ctrl']['transOrigPointerField'] . '>0' .
+                                                       ' AND ' . $tableName . '.' . $GLOBALS['TCA'][$tableName]['ctrl']['languageField'] . '>0';
+
+                                               // Add delete clause to ensure all entries are loaded
+                                               if (isset($GLOBALS['TCA'][$tableName]['ctrl']['delete'])) {
+                                                       $additionalWhereClause .= ' AND ' . $tableName . '.' . $GLOBALS['TCA'][$tableName]['ctrl']['delete'] . '=0';
+                                               }
+                                               $additionalWhereClause .= '))';
                                        }
-                                       $additionalWhereClause .= '))';
+                               } else {
+                                       $additionalWhereClause = $tableName . '.' . $GLOBALS['TCA'][$tableName]['ctrl']['languageField'] . ' IN (0,-1)';
                                }
                                $sql['additionalWhereClause'][] = '(' . $additionalWhereClause . ')';
                        }
index 79f05c2..5534701 100644 (file)
@@ -115,6 +115,21 @@ class Typo3DbBackendTest extends \TYPO3\CMS\Extbase\Tests\Unit\BaseTestCase {
        /**
         * @test
         */
+       public function addSysLanguageStatementWorksInBackendContextWithNoGlobalTypoScriptFrontendControllerAvailable() {
+               $table = uniqid('tx_coretest_table');
+               $GLOBALS['TCA'][$table]['ctrl'] = array(
+                       'languageField' => 'sys_language_uid'
+               );
+               $sql = array();
+               $mockTypo3DbBackend = $this->getMock($this->buildAccessibleProxy('TYPO3\\CMS\\Extbase\\Persistence\\Generic\\Storage\\Typo3DbBackend'), array('dummy'), array(), '', false);
+               $mockTypo3DbBackend->_callRef('addSysLanguageStatement', $table, $sql);
+               $expectedSql = array('additionalWhereClause' => array('(' . $table . '.sys_language_uid IN (0,-1))'));
+               $this->assertSame($expectedSql, $sql);
+       }
+
+       /**
+        * @test
+        */
        public function addSysLanguageStatementWorksForDefaultLanguageWithoutDeleteStatementReturned() {
                $table = uniqid('tx_coretest_table');
                $GLOBALS['TCA'][$table]['ctrl'] = array(
@@ -156,7 +171,27 @@ class Typo3DbBackendTest extends \TYPO3\CMS\Extbase\Tests\Unit\BaseTestCase {
                $table = uniqid('tx_coretest_table');
                $GLOBALS['TCA'][$table]['ctrl'] = array(
                        'languageField' => 'sys_language_uid',
-                       'transOrigPointerField' => 'l18n_parent'
+                       'transOrigPointerField' => 'l10n_parent'
+               );
+               $tsfe = $this->getMock('TYPO3\\CMS\\Frontend\\Controller\\TypoScriptFrontendController', array(), array(), '', false);
+               $tsfe->sys_language_uid = 2;
+               $GLOBALS['TSFE'] = $tsfe;
+               $sql = array();
+               $mockTypo3DbBackend = $this->getMock($this->buildAccessibleProxy('TYPO3\\CMS\\Extbase\\Persistence\\Generic\\Storage\\Typo3DbBackend'), array('dummy'), array(), '', false);
+               $mockTypo3DbBackend->_callRef('addSysLanguageStatement', $table, $sql);
+               $expectedSql = array('additionalWhereClause' => array('(' . $table . '.sys_language_uid IN (2,-1) OR (' . $table . '.sys_language_uid=0 AND ' . $table . '.uid NOT IN (SELECT ' . $table . '.l10n_parent FROM ' . $table . ' WHERE ' . $table . '.l10n_parent>0 AND ' . $table . '.sys_language_uid>0)))'));
+               $this->assertSame($expectedSql, $sql);
+       }
+
+       /**
+        * @test
+        */
+       public function addSysLanguageStatementWorksForForeignLanguageWithSubselectionTakesDeleteStatementIntoAccountIfNecessary() {
+               $table = uniqid('tx_coretest_table');
+               $GLOBALS['TCA'][$table]['ctrl'] = array(
+                       'languageField' => 'sys_language_uid',
+                       'transOrigPointerField' => 'l10n_parent',
+                       'delete' => 'deleted'
                );
                $tsfe = $this->getMock('TYPO3\\CMS\\Frontend\\Controller\\TypoScriptFrontendController', array(), array(), '', false);
                $tsfe->sys_language_uid = 2;
@@ -164,7 +199,14 @@ class Typo3DbBackendTest extends \TYPO3\CMS\Extbase\Tests\Unit\BaseTestCase {
                $sql = array();
                $mockTypo3DbBackend = $this->getMock($this->buildAccessibleProxy('TYPO3\\CMS\\Extbase\\Persistence\\Generic\\Storage\\Typo3DbBackend'), array('dummy'), array(), '', false);
                $mockTypo3DbBackend->_callRef('addSysLanguageStatement', $table, $sql);
-               $expectedSql = array('additionalWhereClause' => array('(' . $table . '.sys_language_uid IN (2,-1) OR (' . $table . '.sys_language_uid=0 AND ' . $table . '.uid NOT IN (SELECT ' . $table . '.l18n_parent FROM ' . $table . ' WHERE ' . $table . '.l18n_parent>0 AND ' . $table . '.sys_language_uid>0)))'));
+               $expectedSql = array('additionalWhereClause' => array(
+                       '(' . $table . '.sys_language_uid IN (2,-1)' .
+                                       ' OR (' . $table . '.sys_language_uid=0 AND ' . $table . '.uid NOT IN (' .
+                                               'SELECT ' . $table . '.l10n_parent FROM ' . $table .
+                                               ' WHERE ' . $table . '.l10n_parent>0 AND ' .
+                                                       $table . '.sys_language_uid>0 AND ' .
+                                                       $table . '.deleted=0)))')
+               );
                $this->assertSame($expectedSql, $sql);
        }