[FEATURE] Enable queries using "root" and "-1" for pidInList 23/28623/5
authorOliver Hader <oliver@typo3.org>
Fri, 21 Mar 2014 22:13:57 +0000 (23:13 +0100)
committerOliver Hader <oliver.hader@typo3.org>
Sat, 22 Mar 2014 00:44:32 +0000 (01:44 +0100)
The version preview in the frontend rendering process basically
selects only the live versions and then overlays those records
with possible versions. Since the MM handling is changed to
directly point to the most specific version in that regard (this
is an exception to the "always live, overlay then" approach), the
versions also need to be selected directly. ContentObjectRenderer
uses the method PageRepository::enableFields() which adds an
additional SQL WHERE part, like " AND tablename.pid<>-1" to
exclude possible versions.

Besides that, elements (like sys_catagory) that are stored on the
root-level cannot be queried at all which leads to custom code in
the end just to perform these queries.

This change allows selections on the root-level and disables the
"pid<>-1" constraint if the opposite has been defined in the
pidInList property.

Example:
select.pidInList = root,-1

Resolves: #57168
Documentation: #57171
Releases: 6.2
Change-Id: I6fb91f89f70614d59c83d808f07e890833248880
Reviewed-on: https://review.typo3.org/28623
Reviewed-by: Ernesto Baschny
Reviewed-by: Oliver Hader
Tested-by: Oliver Hader
typo3/sysext/core/Tests/Functional/Fixtures/Frontend/JsonRenderer.ts
typo3/sysext/core/Tests/Functional/Framework/Frontend/UserFunction.php [deleted file]
typo3/sysext/frontend/Classes/ContentObject/ContentObjectRenderer.php
typo3/sysext/frontend/Classes/Page/PageRepository.php
typo3/sysext/frontend/Tests/Unit/ContentObject/ContentObjectRendererTest.php

index b96d82a..e89f117 100644 (file)
@@ -54,14 +54,7 @@ page {
                                watcher.parentRecordField = categories
                                table = sys_category
                                select {
-                                       pidInList = 0
-                                       uidInList.preUserFunc = TYPO3\CMS\Core\Tests\Functional\Framework\Frontend\UserFunction->getManyToManyIds
-                                       uidInList.preUserFunc {
-                                               uidForeign.data = field:_ORIG_uid // field:uid
-                                               manyToManyTableName = sys_category_record_mm
-                                               matchTableName = tt_content
-                                               matchFieldName = categories
-                                       }
+                                       pidInList = root,-1
                                        selectFields = sys_category.*
                                        join = sys_category_record_mm ON sys_category_record_mm.uid_local = sys_category.uid
                                        where.data = field:_ORIG_uid // field:uid
diff --git a/typo3/sysext/core/Tests/Functional/Framework/Frontend/UserFunction.php b/typo3/sysext/core/Tests/Functional/Framework/Frontend/UserFunction.php
deleted file mode 100644 (file)
index fecb08c..0000000
+++ /dev/null
@@ -1,116 +0,0 @@
-<?php
-namespace TYPO3\CMS\Core\Tests\Functional\Framework\Frontend;
-
-/***************************************************************
- * Copyright notice
- *
- * (c) 2014 Oliver Hader <oliver.hader@typo3.org>
- * 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!
- ***************************************************************/
-
-/**
- * Model of frontend response
- */
-class UserFunction implements \TYPO3\CMS\Core\SingletonInterface {
-
-       /**
-        * @var \TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer
-        */
-       public $cObj;
-
-       /**
-        * @param string $content
-        * @param array $configuration
-        * @return string
-        */
-       public function getManyToManyIds($content, array $configuration = NULL) {
-               $where = array();
-               $uidLocal = NULL;
-               $uidForeign = NULL;
-               $manyToManyTableName = NULL;
-
-               $uidLocal = (int)$this->getValue('uidLocal', $configuration);
-               $uidForeign = (int)$this->getValue('uidForeign', $configuration);
-               $manyToManyTableName = $this->getValue('manyToManyTableName', $configuration);
-
-               if (!($uidLocal xor $uidForeign) || empty($manyToManyTableName)) {
-                       return $content;
-               }
-
-               if (!empty($uidLocal)) {
-                       $selectField = 'uid_foreign';
-                       $sortingField = 'sorting';
-                       $where[] = 'uid_local=' . $uidLocal;
-               } else {
-                       $selectField = 'uid_local';
-                       $sortingField = 'sorting_foreign';
-                       $where[] = 'uid_foreign=' . $uidForeign;
-               }
-
-               if (!empty($configuration['matchTableName'])) {
-                       $where[] = 'tablenames=' . $this->getDatabaseConnection()->fullQuoteStr($configuration['matchTableName'], $manyToManyTableName);
-               }
-               if (!empty($configuration['matchFieldName'])) {
-                       $where[] = 'fieldname=' . $this->getDatabaseConnection()->fullQuoteStr($configuration['matchFieldName'], $manyToManyTableName);
-               }
-
-               $references = $this->getDatabaseConnection()->exec_SELECTgetRows(
-                       $selectField,
-                       $manyToManyTableName,
-                       implode(' AND ', $where),
-                       '',
-                       $sortingField,
-                       '',
-                       $selectField
-               );
-
-               if (empty($references)) {
-                       return $content;
-               }
-
-               $content = implode(',', array_keys($references));
-               return $content;
-       }
-
-       /**
-        * @param string $property
-        * @param array $configuration
-        * @return string
-        */
-       protected function getValue($property, array $configuration = NULL) {
-               $value = '';
-
-               if (!empty($configuration[$property])) {
-                       $value = $configuration[$property];
-               }
-               if (!empty($configuration[$property . '.'])) {
-                       $value = $this->cObj->stdWrap($value, $configuration[$property . '.']);
-               }
-
-               return $value;
-       }
-
-       /**
-        * @return \TYPO3\CMS\Core\Database\DatabaseConnection
-        */
-       protected function getDatabaseConnection() {
-               return $GLOBALS['TYPO3_DB'];
-       }
-
-}
index 04180b4..fddde98 100644 (file)
@@ -7221,11 +7221,12 @@ class ContentObjectRenderer {
         *
         * @param string $table The table for which to get the where clause
         * @param boolean $show_hidden If set, then you want NOT to filter out hidden records. Otherwise hidden record are filtered based on the current preview settings.
+        * @param array $ignore_array Array you can pass where keys can be "disabled", "starttime", "endtime", "fe_group" (keys from "enablefields" in TCA) and if set they will make sure that part of the clause is not added. Thus disables the specific part of the clause. For previewing etc.
         * @return string The part of the where clause on the form " AND [fieldname]=0 AND ...". Eg. " AND hidden=0 AND starttime < 123345567
-        * @todo Define visibility
         */
-       public function enableFields($table, $show_hidden = 0) {
-               return $GLOBALS['TSFE']->sys_page->enableFields($table, $show_hidden ? $show_hidden : ($table == 'pages' ? $GLOBALS['TSFE']->showHiddenPage : $GLOBALS['TSFE']->showHiddenRecords));
+       public function enableFields($table, $show_hidden = FALSE, array $ignore_array = array()) {
+               $show_hidden = $show_hidden ?: ($table === 'pages' ? $GLOBALS['TSFE']->showHiddenPage : $GLOBALS['TSFE']->showHiddenRecords);
+               return $GLOBALS['TSFE']->sys_page->enableFields($table, $show_hidden, $ignore_array);
        }
 
        /**
@@ -7666,6 +7667,7 @@ class ContentObjectRenderer {
                // Init:
                $query = '';
                $pid_uid_flag = 0;
+               $enableFieldsIgnore = array();
                $queryParts = array(
                        'SELECT' => '',
                        'FROM' => '',
@@ -7703,8 +7705,15 @@ class ContentObjectRenderer {
                        $listArr = GeneralUtility::intExplode(',', str_replace('this', $GLOBALS['TSFE']->contentPid, $conf['pidInList']));
                        // Removes all pages which are not visible for the user!
                        $listArr = $this->checkPidArray($listArr);
+                       if (GeneralUtility::inList($conf['pidInList'], 'root')) {
+                               $listArr[] = 0;
+                       }
+                       if (GeneralUtility::inList($conf['pidInList'], '-1')) {
+                               $listArr[] = -1;
+                               $enableFieldsIgnore['pid'] = TRUE;
+                       }
                        if (count($listArr)) {
-                               $query .= ' AND ' . $table . '.pid IN (' . implode(',', $GLOBALS['TYPO3_DB']->cleanIntArray($listArr)) . ')';
+                               $query .= ' AND ' . $table . '.pid IN (' . implode(',', array_map('intval', $listArr)) . ')';
                                $pid_uid_flag++;
                        } else {
                                // If not uid and not pid then uid is set to 0 - which results in nothing!!
@@ -7750,7 +7759,7 @@ class ContentObjectRenderer {
                if ($table == 'pages') {
                        $query .= ' ' . $GLOBALS['TSFE']->sys_page->where_hid_del . $GLOBALS['TSFE']->sys_page->where_groupAccess;
                } else {
-                       $query .= $this->enableFields($table);
+                       $query .= $this->enableFields($table, FALSE, $enableFieldsIgnore);
                }
                // MAKE WHERE:
                if ($query) {
index a81a1ff..768e924 100644 (file)
@@ -898,7 +898,7 @@ class PageRepository {
                                }
 
                                // Filter out versioned records
-                               if (!$noVersionPreview) {
+                               if (!$noVersionPreview && empty($ignore_array['pid'])) {
                                        $query .= ' AND ' . $table . '.pid<>-1';
                                }
                        }
index f4a4147..5284483 100644 (file)
@@ -1280,10 +1280,12 @@ class ContentObjectRendererTest extends \TYPO3\CMS\Core\Tests\UnitTestCase {
                );
                $this->cObj->expects($this->at(0))
                        ->method('getTreeList')
-                       ->with(-16, 15);
+                       ->with(-16, 15)
+                       ->will($this->returnValue('15,16'));
                $this->cObj->expects($this->at(1))
                        ->method('getTreeList')
-                       ->with(-35, 15);
+                       ->with(-35, 15)
+                       ->will($this->returnValue('15,35'));
                $this->cObj->getQuery('tt_content', $conf, TRUE);
        }
 
@@ -1316,7 +1318,8 @@ class ContentObjectRendererTest extends \TYPO3\CMS\Core\Tests\UnitTestCase {
                );
                $this->cObj->expects($this->once())
                        ->method('getTreeList')
-                       ->with(-27);
+                       ->with(-27)
+                       ->will($this->returnValue('27'));
                $this->cObj->getQuery('tt_content', $conf, TRUE);
        }