[FEATURE] Improved translation handling for statement generation
[Packages/TYPO3.CMS.git] / typo3 / sysext / extbase / Classes / Persistence / Generic / Storage / Typo3DbBackend.php
index e9bef50..e008c34 100644 (file)
@@ -63,13 +63,6 @@ class Tx_Extbase_Persistence_Storage_Typo3DbBackend implements Tx_Extbase_Persis
         */
        protected $pageTSConfigCache = array();
 
-       /**
-        * Caches information about tables (esp. the existing column names)
-        *
-        * @var array
-        */
-       protected $tableInformationCache = array();
-
        /**
         * @var Tx_Extbase_Configuration_ConfigurationManagerInterface
         */
@@ -80,6 +73,16 @@ class Tx_Extbase_Persistence_Storage_Typo3DbBackend implements Tx_Extbase_Persis
         */
        protected $cacheService;
 
+       /**
+        * @var t3lib_cache_Manager
+        */
+       protected $cacheManager;
+
+       /**
+        * @var t3lib_cache_frontend_VariableFrontend
+        */
+       protected $tableColumnCache;
+
        /**
         * Constructor. takes the database handle from $GLOBALS['TYPO3_DB']
         */
@@ -95,6 +98,22 @@ class Tx_Extbase_Persistence_Storage_Typo3DbBackend implements Tx_Extbase_Persis
                $this->configurationManager = $configurationManager;
        }
 
+       /**
+        * @param t3lib_cache_Manager $cacheManager
+        */
+       public function injectCacheManager(t3lib_cache_Manager $cacheManager) {
+               $this->cacheManager = $cacheManager;
+       }
+
+       /**
+        * Lifecycle method
+        *
+        * @return void
+        */
+       public function initializeObject() {
+               $this->tableColumnCache = $this->cacheManager->getCache('extbase_typo3dbbackend_tablecolumns');
+       }
+
        /**
         * Injects the DataMapper to map nodes to objects
         *
@@ -238,7 +257,7 @@ class Tx_Extbase_Persistence_Storage_Typo3DbBackend implements Tx_Extbase_Persis
                $parameters = array();
 
                $statement = $query->getStatement();
-               if($statement instanceof Tx_Extbase_Persistence_QOM_Statement) {
+               if ($statement instanceof Tx_Extbase_Persistence_QOM_Statement) {
                        $sql = $statement->getStatement();
                        $parameters = $statement->getBoundVariables();
                } else {
@@ -265,7 +284,7 @@ class Tx_Extbase_Persistence_Storage_Typo3DbBackend implements Tx_Extbase_Persis
         */
        public function getObjectCountByQuery(Tx_Extbase_Persistence_QueryInterface $query) {
                $constraint = $query->getConstraint();
-               if($constraint instanceof Tx_Extbase_Persistence_QOM_StatementInterface) {
+               if ($constraint instanceof Tx_Extbase_Persistence_QOM_StatementInterface) {
                        throw new Tx_Extbase_Persistence_Storage_Exception_BadConstraint('Could not execute count on queries with a constraint of type Tx_Extbase_Persistence_QOM_StatementInterface', 1256661045);
                }
                $parameters = array();
@@ -811,7 +830,7 @@ class Tx_Extbase_Persistence_Storage_Typo3DbBackend implements Tx_Extbase_Persis
                                $statement = t3lib_BEfunc::deleteClause($tableName);
                                $statement .= t3lib_BEfunc::BEenableFields($tableName);
                        }
-                       if(!empty($statement)) {
+                       if (!empty($statement)) {
                                $statement = substr($statement, 5);
                                $sql['additionalWhereClause'][] = $statement;
                        }
@@ -828,7 +847,30 @@ class Tx_Extbase_Persistence_Storage_Typo3DbBackend implements Tx_Extbase_Persis
        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) {
-                               $sql['additionalWhereClause'][] = $tableName . '.' . $GLOBALS['TCA'][$tableName]['ctrl']['languageField'] . ' IN (0,-1)';
+
+                                       // 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';
+                                       }
+
+                                       $additionalWhereClause .= '))';
+                               }
+
+                               $sql['additionalWhereClause'][] = '(' . $additionalWhereClause . ')';
                        }
                }
        }
@@ -842,10 +884,12 @@ class Tx_Extbase_Persistence_Storage_Typo3DbBackend implements Tx_Extbase_Persis
         * @return void
         */
        protected function addPageIdStatement($tableName, array &$sql, array $storagePageIds) {
-               if (empty($this->tableInformationCache[$tableName]['columnNames'])) {
-                       $this->tableInformationCache[$tableName]['columnNames'] = $this->databaseHandle->admin_get_fields($tableName);
+               $tableColumns = $this->tableColumnCache->get($tableName);
+               if ($tableColumns === FALSE) {
+                       $tableColumns = $this->databaseHandle->admin_get_fields($tableName);
+                       $this->tableColumnCache->set($tableName, $tableColumns);
                }
-               if (is_array($GLOBALS['TCA'][$tableName]['ctrl']) && array_key_exists('pid', $this->tableInformationCache[$tableName]['columnNames'])) {
+               if (is_array($GLOBALS['TCA'][$tableName]['ctrl']) && array_key_exists('pid', $tableColumns)) {
                        $sql['additionalWhereClause'][] = $tableName . '.pid IN (' . implode(', ', $storagePageIds) . ')';
                }
        }
@@ -872,6 +916,8 @@ class Tx_Extbase_Persistence_Storage_Typo3DbBackend implements Tx_Extbase_Persis
                                default:
                                        throw new Tx_Extbase_Persistence_Exception_UnsupportedOrder('Unsupported order encountered.', 1242816074);
                        }
+                       $className = '';
+                       $tableName = '';
                        if ($source instanceof Tx_Extbase_Persistence_QOM_SelectorInterface) {
                                $className = $source->getNodeTypeName();
                                $tableName = $this->dataMapper->convertClassNameToTableName($className);
@@ -973,13 +1019,30 @@ class Tx_Extbase_Persistence_Storage_Typo3DbBackend implements Tx_Extbase_Persis
                        } elseif ($source instanceof Tx_Extbase_Persistence_QOM_JoinInterface) {
                                $tableName = $source->getRight()->getSelectorName();
                        }
+
+                               // If current row is a translation select its parent
+                       if (isset($GLOBALS['TCA'][$tableName]) && isset($GLOBALS['TCA'][$tableName]['ctrl']['languageField']) &&
+                               isset($GLOBALS['TCA'][$tableName]['ctrl']['transOrigPointerField'])) {
+
+                               if (isset($row[$GLOBALS['TCA'][$tableName]['ctrl']['transOrigPointerField']]) &&
+                                       $row[$GLOBALS['TCA'][$tableName]['ctrl']['transOrigPointerField']] > 0) {
+
+                                       $row = $this->databaseHandle->exec_SELECTgetSingleRow(
+                                               $tableName . '.*',
+                                               $tableName,
+                                               $tableName . '.uid=' . $row[$GLOBALS['TCA'][$tableName]['ctrl']['transOrigPointerField']] . ' AND ' .
+                                                       $tableName . '.' . $GLOBALS['TCA'][$tableName]['ctrl']['languageField'] . '=0'
+                                       );
+                               }
+                       }
+
                        $this->pageSelectObject->versionOL($tableName, $row, TRUE);
                        if ($this->pageSelectObject->versioningPreview && isset($row['_ORIG_uid'])) {
                                $row['uid'] = $row['_ORIG_uid'];
                        }
-                       if($tableName == 'pages') {
+                       if ($tableName == 'pages') {
                                $row = $this->pageSelectObject->getPageOverlay($row, $languageUid);
-                       } elseif(isset($GLOBALS['TCA'][$tableName]['ctrl']['languageField']) && $GLOBALS['TCA'][$tableName]['ctrl']['languageField'] !== '') {
+                       } elseif (isset($GLOBALS['TCA'][$tableName]['ctrl']['languageField']) && $GLOBALS['TCA'][$tableName]['ctrl']['languageField'] !== '') {
                                if (in_array($row[$GLOBALS['TCA'][$tableName]['ctrl']['languageField']], array(-1,0))) {
                                        $overlayMode = ($languageMode === 'strict') ? 'hideNonTranslated' : '';
                                        $row = $this->pageSelectObject->getRecordOverlay($tableName, $row, $languageUid, $overlayMode);