[TASK] Streamline PageRepository->getRawRecord
[Packages/TYPO3.CMS.git] / typo3 / sysext / frontend / Classes / Page / PageRepository.php
index 462ec0c..748297b 100644 (file)
@@ -14,7 +14,12 @@ namespace TYPO3\CMS\Frontend\Page;
  * The TYPO3 project - inspiring people to share!
  */
 
  * The TYPO3 project - inspiring people to share!
  */
 
-use TYPO3\CMS\Core\Cache\CacheManager;
+use TYPO3\CMS\Core\Database\Connection;
+use TYPO3\CMS\Core\Database\ConnectionPool;
+use TYPO3\CMS\Core\Database\Query\QueryHelper;
+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\Resource\Exception\FileDoesNotExistException;
 use TYPO3\CMS\Core\Resource\FileRepository;
 use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
 use TYPO3\CMS\Core\Resource\Exception\FileDoesNotExistException;
 use TYPO3\CMS\Core\Resource\FileRepository;
 use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
@@ -36,7 +41,7 @@ class PageRepository
     /**
      * @var array
      */
     /**
      * @var array
      */
-    public $urltypes = array('', 'http://', 'ftp://', 'mailto:', 'https://');
+    public $urltypes = ['', 'http://', 'ftp://', 'mailto:', 'https://'];
 
     /**
      * This is not the final clauses. There will normally be conditions for the
 
     /**
      * This is not the final clauses. There will normally be conditions for the
@@ -61,7 +66,7 @@ class PageRepository
 
     /**
      * If TRUE, versioning preview of other record versions is allowed. THIS MUST
 
     /**
      * If TRUE, versioning preview of other record versions is allowed. THIS MUST
-     * ONLY BE SET IF the page is not cached and truely previewed by a backend
+     * ONLY BE SET IF the page is not cached and truly previewed by a backend
      * user!!!
      *
      * @var bool
      * user!!!
      *
      * @var bool
@@ -69,11 +74,6 @@ class PageRepository
     public $versioningPreview = false;
 
     /**
     public $versioningPreview = false;
 
     /**
-     * @var string
-     */
-    public $versioningPreview_where_hid_del = '';
-
-    /**
      * Workspace ID for preview
      *
      * @var int
      * Workspace ID for preview
      *
      * @var int
@@ -83,7 +83,7 @@ class PageRepository
     /**
      * @var array
      */
     /**
      * @var array
      */
-    public $workspaceCache = array();
+    public $workspaceCache = [];
 
     /**
      * Error string set by getRootLine()
 
     /**
      * Error string set by getRootLine()
@@ -102,42 +102,42 @@ class PageRepository
     /**
      * @var array
      */
     /**
      * @var array
      */
-    protected $cache_getRootLine = array();
+    protected $cache_getRootLine = [];
 
     /**
      * @var array
      */
 
     /**
      * @var array
      */
-    protected $cache_getPage = array();
+    protected $cache_getPage = [];
 
     /**
      * @var array
      */
 
     /**
      * @var array
      */
-    protected $cache_getPage_noCheck = array();
+    protected $cache_getPage_noCheck = [];
 
     /**
      * @var array
      */
 
     /**
      * @var array
      */
-    protected $cache_getPageIdFromAlias = array();
+    protected $cache_getPageIdFromAlias = [];
 
     /**
      * @var array
      */
 
     /**
      * @var array
      */
-    protected $cache_getMountPointInfo = array();
+    protected $cache_getMountPointInfo = [];
 
     /**
      * @var array
      */
 
     /**
      * @var array
      */
-    protected $tableNamesAllowedOnRootLevel = array(
+    protected $tableNamesAllowedOnRootLevel = [
         'sys_file_metadata',
         'sys_category',
         'sys_file_metadata',
         'sys_category',
-    );
+    ];
 
     /**
      * Computed properties that are added to database rows.
      *
      * @var array
      */
 
     /**
      * Computed properties that are added to database rows.
      *
      * @var array
      */
-    protected $computedPropertyNames = array(
+    protected $computedPropertyNames = [
         '_LOCALIZED_UID',
         '_MP_PARAM',
         '_ORIG_uid',
         '_LOCALIZED_UID',
         '_MP_PARAM',
         '_ORIG_uid',
@@ -145,7 +145,7 @@ class PageRepository
         '_PAGES_OVERLAY',
         '_PAGES_OVERLAY_UID',
         '_PAGES_OVERLAY_LANGUAGE',
         '_PAGES_OVERLAY',
         '_PAGES_OVERLAY_UID',
         '_PAGES_OVERLAY_LANGUAGE',
-    );
+    ];
 
     /**
      * Named constants for "magic numbers" of the field doktype
 
     /**
      * Named constants for "magic numbers" of the field doktype
@@ -174,7 +174,6 @@ class PageRepository
      * into account
      *
      * @param bool $show_hidden If $show_hidden is TRUE, the hidden-field is ignored!! Normally this should be FALSE. Is used for previewing.
      * into account
      *
      * @param bool $show_hidden If $show_hidden is TRUE, the hidden-field is ignored!! Normally this should be FALSE. Is used for previewing.
-     * @return void
      * @see \TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController::fetch_the_id(), \TYPO3\CMS\Tstemplate\Controller\TemplateAnalyzerModuleFunctionController::initialize_editor()
      */
     public function init($show_hidden)
      * @see \TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController::fetch_the_id(), \TYPO3\CMS\Tstemplate\Controller\TemplateAnalyzerModuleFunctionController::initialize_editor()
      */
     public function init($show_hidden)
@@ -186,18 +185,27 @@ class PageRepository
             // de-selecting hidden pages - we need versionOL() to unset them only
             // if the overlay record instructs us to.
             // Clear where_hid_del and restrict to live and current workspaces
             // de-selecting hidden pages - we need versionOL() to unset them only
             // if the overlay record instructs us to.
             // Clear where_hid_del and restrict to live and current workspaces
-            $this->where_hid_del = ' AND pages.deleted=0 AND (pages.t3ver_wsid=0 OR pages.t3ver_wsid=' . (int)$this->versioningWorkspaceId . ')';
+            $expressionBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
+                ->getQueryBuilderForTable('pages')
+                ->expr();
+            $this->where_hid_del = ' AND ' . $expressionBuilder->andX(
+                $expressionBuilder->eq('pages.deleted', 0),
+                $expressionBuilder->orX(
+                    $expressionBuilder->eq('pages.t3ver_wsid', 0),
+                    $expressionBuilder->eq('pages.t3ver_wsid', (int)$this->versioningWorkspaceId)
+                )
+            );
         } else {
             // add starttime / endtime, and check for hidden/deleted
             // Filter out new/deleted place-holder pages in case we are NOT in a
             // versioning preview (that means we are online!)
         } else {
             // add starttime / endtime, and check for hidden/deleted
             // Filter out new/deleted place-holder pages in case we are NOT in a
             // versioning preview (that means we are online!)
-            $this->where_hid_del = $this->enableFields('pages', $show_hidden, array('fe_group' => true), true);
+            $this->where_hid_del = $this->enableFields('pages', $show_hidden, ['fe_group' => true], true);
         }
         }
-        if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS'][PageRepository::class]['init'])) {
-            foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS'][PageRepository::class]['init'] as $classRef) {
+        if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS'][self::class]['init'])) {
+            foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS'][self::class]['init'] as $classRef) {
                 $hookObject = GeneralUtility::makeInstance($classRef);
                 if (!$hookObject instanceof PageRepositoryInitHookInterface) {
                 $hookObject = GeneralUtility::makeInstance($classRef);
                 if (!$hookObject instanceof PageRepositoryInitHookInterface) {
-                    throw new \UnexpectedValueException($hookObject . ' must implement interface TYPO3\\CMS\\Frontend\\Page\\PageRepositoryInitHookInterface', 1379579812);
+                    throw new \UnexpectedValueException($hookObject . ' must implement interface ' . PageRepositoryInitHookInterface::class, 1379579812);
                 }
                 $hookObject->init_postProcess($this);
             }
                 }
                 $hookObject->init_postProcess($this);
             }
@@ -218,28 +226,49 @@ class PageRepository
      * @param int $uid The page id to look up.
      * @param bool $disableGroupAccessCheck If set, the check for group access is disabled. VERY rarely used
      * @throws \UnexpectedValueException
      * @param int $uid The page id to look up.
      * @param bool $disableGroupAccessCheck If set, the check for group access is disabled. VERY rarely used
      * @throws \UnexpectedValueException
-     * @return array The page row with overlayed localized fields. Empty it no page.
+     * @return array The page row with overlaid localized fields. Empty it no page.
      * @see getPage_noCheck()
      */
     public function getPage($uid, $disableGroupAccessCheck = false)
     {
         // Hook to manipulate the page uid for special overlay handling
         if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_page.php']['getPage'])) {
      * @see getPage_noCheck()
      */
     public function getPage($uid, $disableGroupAccessCheck = false)
     {
         // Hook to manipulate the page uid for special overlay handling
         if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_page.php']['getPage'])) {
-            foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_page.php']['getPage'] as $classRef) {
-                $hookObject = GeneralUtility::getUserObj($classRef);
+            foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_page.php']['getPage'] as $className) {
+                $hookObject = GeneralUtility::makeInstance($className);
                 if (!$hookObject instanceof PageRepositoryGetPageHookInterface) {
                 if (!$hookObject instanceof PageRepositoryGetPageHookInterface) {
-                    throw new \UnexpectedValueException('$hookObject must implement interface ' . PageRepositoryGetPageHookInterface::class, 1251476766);
+                    throw new \UnexpectedValueException($className . ' must implement interface ' . PageRepositoryGetPageHookInterface::class, 1251476766);
                 }
                 $hookObject->getPage_preProcess($uid, $disableGroupAccessCheck, $this);
             }
         }
                 }
                 $hookObject->getPage_preProcess($uid, $disableGroupAccessCheck, $this);
             }
         }
-        $accessCheck = $disableGroupAccessCheck ? '' : $this->where_groupAccess;
-        $cacheKey = md5($accessCheck . '-' . $this->where_hid_del . '-' . $this->sys_language_uid);
+        $cacheKey = md5(
+            implode(
+                '-',
+                [
+                    ($disableGroupAccessCheck ? '' : $this->where_groupAccess),
+                    $this->where_hid_del,
+                    $this->sys_language_uid
+                ]
+            )
+        );
         if (is_array($this->cache_getPage[$uid][$cacheKey])) {
             return $this->cache_getPage[$uid][$cacheKey];
         }
         if (is_array($this->cache_getPage[$uid][$cacheKey])) {
             return $this->cache_getPage[$uid][$cacheKey];
         }
-        $result = array();
-        $row = $this->getDatabaseConnection()->exec_SELECTgetSingleRow('*', 'pages', 'uid=' . (int)$uid . $this->where_hid_del . $accessCheck);
+        $result = [];
+        $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('pages');
+        $queryBuilder->getRestrictions()->removeAll();
+        $queryBuilder->select('*')
+            ->from('pages')
+            ->where(
+                $queryBuilder->expr()->eq('uid', (int)$uid),
+                QueryHelper::stripLogicalOperatorPrefix($this->where_hid_del)
+            );
+
+        if (!$disableGroupAccessCheck) {
+            $queryBuilder->andWhere(QueryHelper::stripLogicalOperatorPrefix($this->where_groupAccess));
+        }
+
+        $row = $queryBuilder->execute()->fetch();
         if ($row) {
             $this->versionOL('pages', $row);
             if (is_array($row)) {
         if ($row) {
             $this->versionOL('pages', $row);
             if (is_array($row)) {
@@ -255,7 +284,7 @@ class PageRepository
      * ->where_hid_del (start- and endtime or hidden). Only "deleted" is checked!
      *
      * @param int $uid The page id to look up
      * ->where_hid_del (start- and endtime or hidden). Only "deleted" is checked!
      *
      * @param int $uid The page id to look up
-     * @return array The page row with overlayed localized fields. Empty array if no page.
+     * @return array The page row with overlaid localized fields. Empty array if no page.
      * @see getPage()
      */
     public function getPage_noCheck($uid)
      * @see getPage()
      */
     public function getPage_noCheck($uid)
@@ -263,10 +292,18 @@ class PageRepository
         if ($this->cache_getPage_noCheck[$uid]) {
             return $this->cache_getPage_noCheck[$uid];
         }
         if ($this->cache_getPage_noCheck[$uid]) {
             return $this->cache_getPage_noCheck[$uid];
         }
-        $res = $this->getDatabaseConnection()->exec_SELECTquery('*', 'pages', 'uid=' . (int)$uid . $this->deleteClause('pages'));
-        $row = $this->getDatabaseConnection()->sql_fetch_assoc($res);
-        $this->getDatabaseConnection()->sql_free_result($res);
-        $result = array();
+
+        $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('pages');
+        $queryBuilder->getRestrictions()
+            ->removeAll()
+            ->add(GeneralUtility::makeInstance(DeletedRestriction::class));
+        $row = $queryBuilder->select('*')
+            ->from('pages')
+            ->where($queryBuilder->expr()->eq('uid', (int)$uid))
+            ->execute()
+            ->fetch();
+
+        $result = [];
         if ($row) {
             $this->versionOL('pages', $row);
             if (is_array($row)) {
         if ($row) {
             $this->versionOL('pages', $row);
             if (is_array($row)) {
@@ -281,15 +318,26 @@ class PageRepository
      * Returns the $row of the first web-page in the tree (for the default menu...)
      *
      * @param int $uid The page id for which to fetch first subpages (PID)
      * Returns the $row of the first web-page in the tree (for the default menu...)
      *
      * @param int $uid The page id for which to fetch first subpages (PID)
-     * @return mixed If found: The page record (with overlayed localized fields, if any). If NOT found: blank value (not array!)
+     * @return mixed If found: The page record (with overlaid localized fields, if any). If NOT found: blank value (not array!)
      * @see \TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController::fetch_the_id()
      */
     public function getFirstWebPage($uid)
     {
         $output = '';
      * @see \TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController::fetch_the_id()
      */
     public function getFirstWebPage($uid)
     {
         $output = '';
-        $res = $this->getDatabaseConnection()->exec_SELECTquery('*', 'pages', 'pid=' . (int)$uid . $this->where_hid_del . $this->where_groupAccess, '', 'sorting', '1');
-        $row = $this->getDatabaseConnection()->sql_fetch_assoc($res);
-        $this->getDatabaseConnection()->sql_free_result($res);
+        $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('pages');
+        $queryBuilder->getRestrictions()->removeAll();
+        $row = $queryBuilder->select('*')
+            ->from('pages')
+            ->where(
+                $queryBuilder->expr()->eq('pid', $queryBuilder->createNamedParameter($uid, \PDO::PARAM_INT)),
+                QueryHelper::stripLogicalOperatorPrefix($this->where_hid_del),
+                QueryHelper::stripLogicalOperatorPrefix($this->where_groupAccess)
+            )
+            ->orderBy('sorting')
+            ->setMaxResults(1)
+            ->execute()
+            ->fetch();
+
         if ($row) {
             $this->versionOL('pages', $row);
             if (is_array($row)) {
         if ($row) {
             $this->versionOL('pages', $row);
             if (is_array($row)) {
@@ -312,9 +360,22 @@ class PageRepository
         if ($this->cache_getPageIdFromAlias[$alias]) {
             return $this->cache_getPageIdFromAlias[$alias];
         }
         if ($this->cache_getPageIdFromAlias[$alias]) {
             return $this->cache_getPageIdFromAlias[$alias];
         }
-        $db = $this->getDatabaseConnection();
-        $row = $db->exec_SELECTgetSingleRow('uid', 'pages', 'alias=' . $db->fullQuoteStr($alias, 'pages') . ' AND pid>=0 AND pages.deleted=0');
-        // "AND pid>=0" because of versioning (means that aliases sent MUST be online!)
+        $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('pages');
+        $queryBuilder->getRestrictions()
+            ->removeAll()
+            ->add(GeneralUtility::makeInstance(DeletedRestriction::class));
+
+        $row = $queryBuilder->select('uid')
+            ->from('pages')
+            ->where(
+                $queryBuilder->expr()->eq('alias', $queryBuilder->createNamedParameter($alias, \PDO::PARAM_STR)),
+                // "AND pid>=0" because of versioning (means that aliases sent MUST be online!)
+                $queryBuilder->expr()->gte('pid', $queryBuilder->createNamedParameter(0, \PDO::PARAM_INT))
+            )
+            ->setMaxResults(1)
+            ->execute()
+            ->fetch();
+
         if ($row) {
             $this->cache_getPageIdFromAlias[$alias] = $row['uid'];
             return $row['uid'];
         if ($row) {
             $this->cache_getPageIdFromAlias[$alias] = $row['uid'];
             return $row['uid'];
@@ -326,25 +387,25 @@ class PageRepository
     /**
      * Returns the relevant page overlay record fields
      *
     /**
      * Returns the relevant page overlay record fields
      *
-     * @param mixed $pageInput If $pageInput is an integer, it's the pid of the pageOverlay record and thus the page overlay record is returned. If $pageInput is an array, it's a page-record and based on this page record the language record is found and OVERLAYED before the page record is returned.
+     * @param mixed $pageInput If $pageInput is an integer, it's the pid of the pageOverlay record and thus the page overlay record is returned. If $pageInput is an array, it's a page-record and based on this page record the language record is found and OVERLAID before the page record is returned.
      * @param int $lUid Language UID if you want to set an alternative value to $this->sys_language_uid which is default. Should be >=0
      * @throws \UnexpectedValueException
      * @param int $lUid Language UID if you want to set an alternative value to $this->sys_language_uid which is default. Should be >=0
      * @throws \UnexpectedValueException
-     * @return array Page row which is overlayed with language_overlay record (or the overlay record alone)
+     * @return array Page row which is overlaid with language_overlay record (or the overlay record alone)
      */
     public function getPageOverlay($pageInput, $lUid = -1)
     {
      */
     public function getPageOverlay($pageInput, $lUid = -1)
     {
-        $rows = $this->getPagesOverlay(array($pageInput), $lUid);
+        $rows = $this->getPagesOverlay([$pageInput], $lUid);
         // Always an array in return
         // Always an array in return
-        return isset($rows[0]) ? $rows[0] : array();
+        return isset($rows[0]) ? $rows[0] : [];
     }
 
     /**
      * Returns the relevant page overlay record fields
      *
     }
 
     /**
      * Returns the relevant page overlay record fields
      *
-     * @param array $pagesInput Array of integers or array of arrays. If each value is an integer, it's the pids of the pageOverlay records and thus the page overlay records are returned. If each value is an array, it's page-records and based on this page records the language records are found and OVERLAYED before the page records are returned.
+     * @param array $pagesInput Array of integers or array of arrays. If each value is an integer, it's the pids of the pageOverlay records and thus the page overlay records are returned. If each value is an array, it's page-records and based on this page records the language records are found and OVERLAID before the page records are returned.
      * @param int $lUid Language UID if you want to set an alternative value to $this->sys_language_uid which is default. Should be >=0
      * @throws \UnexpectedValueException
      * @param int $lUid Language UID if you want to set an alternative value to $this->sys_language_uid which is default. Should be >=0
      * @throws \UnexpectedValueException
-     * @return array Page rows which are overlayed with language_overlay record.
+     * @return array Page rows which are overlaid with language_overlay record.
      *               If the input was an array of integers, missing records are not
      *               included. If the input were page rows, untranslated pages
      *               are returned.
      *               If the input was an array of integers, missing records are not
      *               included. If the input were page rows, untranslated pages
      *               are returned.
@@ -352,7 +413,7 @@ class PageRepository
     public function getPagesOverlay(array $pagesInput, $lUid = -1)
     {
         if (empty($pagesInput)) {
     public function getPagesOverlay(array $pagesInput, $lUid = -1)
     {
         if (empty($pagesInput)) {
-            return array();
+            return [];
         }
         // Initialize:
         if ($lUid < 0) {
         }
         // Initialize:
         if ($lUid < 0) {
@@ -360,26 +421,22 @@ class PageRepository
         }
         $row = null;
         if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_page.php']['getPageOverlay'])) {
         }
         $row = null;
         if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_page.php']['getPageOverlay'])) {
-            foreach ($pagesInput as $origPage) {
-                foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_page.php']['getPageOverlay'] as $classRef) {
-                    $hookObject = GeneralUtility::getUserObj($classRef);
+            foreach ($pagesInput as &$origPage) {
+                foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_page.php']['getPageOverlay'] as $className) {
+                    $hookObject = GeneralUtility::makeInstance($className);
                     if (!$hookObject instanceof PageRepositoryGetPageOverlayHookInterface) {
                     if (!$hookObject instanceof PageRepositoryGetPageOverlayHookInterface) {
-                        throw new \UnexpectedValueException('$hookObject must implement interface ' . PageRepositoryGetPageOverlayHookInterface::class, 1269878881);
+                        throw new \UnexpectedValueException($className . ' must implement interface ' . PageRepositoryGetPageOverlayHookInterface::class, 1269878881);
                     }
                     $hookObject->getPageOverlay_preProcess($origPage, $lUid, $this);
                 }
             }
                     }
                     $hookObject->getPageOverlay_preProcess($origPage, $lUid, $this);
                 }
             }
+            unset($origPage);
         }
         // If language UID is different from zero, do overlay:
         if ($lUid) {
         }
         // If language UID is different from zero, do overlay:
         if ($lUid) {
-            $fieldArr = GeneralUtility::trimExplode(',', $GLOBALS['TYPO3_CONF_VARS']['FE']['pageOverlayFields'], true);
-            $page_ids = array();
+            $page_ids = [];
 
             $origPage = reset($pagesInput);
 
             $origPage = reset($pagesInput);
-            if (is_array($origPage)) {
-                // Make sure that only fields which exist in the first incoming record are overlaid!
-                $fieldArr = array_intersect($fieldArr, array_keys($origPage));
-            }
             foreach ($pagesInput as $origPage) {
                 if (is_array($origPage)) {
                     // Was the whole record
             foreach ($pagesInput as $origPage) {
                 if (is_array($origPage)) {
                     // Was the whole record
@@ -389,43 +446,47 @@ class PageRepository
                     $page_ids[] = $origPage;
                 }
             }
                     $page_ids[] = $origPage;
                 }
             }
-            if (!empty($fieldArr)) {
-                if (!in_array('pid', $fieldArr, true)) {
-                    $fieldArr[] = 'pid';
-                }
-                // NOTE to enabledFields('pages_language_overlay'):
-                // Currently the showHiddenRecords of TSFE set will allow
-                // pages_language_overlay records to be selected as they are
-                // child-records of a page.
-                // However you may argue that the showHiddenField flag should
-                // determine this. But that's not how it's done right now.
-                // Selecting overlay record:
-                $db = $this->getDatabaseConnection();
-                $res = $db->exec_SELECTquery(
-                    implode(',', $fieldArr),
-                    'pages_language_overlay',
-                    'pid IN(' . implode(',', $db->cleanIntArray($page_ids)) . ')'
-                    . ' AND sys_language_uid=' . (int)$lUid . $this->enableFields('pages_language_overlay')
-                );
-                $overlays = array();
-                while ($row = $db->sql_fetch_assoc($res)) {
-                    $this->versionOL('pages_language_overlay', $row);
-                    if (is_array($row)) {
-                        $row['_PAGES_OVERLAY'] = true;
-                        $row['_PAGES_OVERLAY_UID'] = $row['uid'];
-                        $row['_PAGES_OVERLAY_LANGUAGE'] = $lUid;
-                        $origUid = $row['pid'];
-                        // Unset vital fields that are NOT allowed to be overlaid:
-                        unset($row['uid']);
-                        unset($row['pid']);
-                        $overlays[$origUid] = $row;
-                    }
+            // NOTE regarding the query restrictions
+            // Currently the showHiddenRecords of TSFE set will allow
+            // pages_language_overlay records to be selected as they are
+            // child-records of a page.
+            // However you may argue that the showHiddenField flag should
+            // determine this. But that's not how it's done right now.
+            // Selecting overlay record:
+            $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
+                ->getQueryBuilderForTable('pages_language_overlay');
+            $queryBuilder->setRestrictions(GeneralUtility::makeInstance(FrontendRestrictionContainer::class));
+            $result = $queryBuilder->select('*')
+                ->from('pages_language_overlay')
+                ->where(
+                    $queryBuilder->expr()->in(
+                        'pid',
+                        $queryBuilder->createNamedParameter($page_ids, Connection::PARAM_INT_ARRAY)
+                    ),
+                    $queryBuilder->expr()->eq(
+                        'sys_language_uid',
+                        $queryBuilder->createNamedParameter($lUid, \PDO::PARAM_INT)
+                    )
+                )
+                ->execute();
+
+            $overlays = [];
+            while ($row = $result->fetch()) {
+                $this->versionOL('pages_language_overlay', $row);
+                if (is_array($row)) {
+                    $row['_PAGES_OVERLAY'] = true;
+                    $row['_PAGES_OVERLAY_UID'] = $row['uid'];
+                    $row['_PAGES_OVERLAY_LANGUAGE'] = $lUid;
+                    $origUid = $row['pid'];
+                    // Unset vital fields that are NOT allowed to be overlaid:
+                    unset($row['uid']);
+                    unset($row['pid']);
+                    $overlays[$origUid] = $row;
                 }
                 }
-                $db->sql_free_result($res);
             }
         }
         // Create output:
             }
         }
         // Create output:
-        $pagesOutput = array();
+        $pagesOutput = [];
         foreach ($pagesInput as $key => $origPage) {
             if (is_array($origPage)) {
                 $pagesOutput[$key] = $origPage;
         foreach ($pagesInput as $key => $origPage) {
             if (is_array($origPage)) {
                 $pagesOutput[$key] = $origPage;
@@ -433,9 +494,7 @@ class PageRepository
                     // Overwrite the original field with the overlay
                     foreach ($overlays[$origPage['uid']] as $fieldName => $fieldValue) {
                         if ($fieldName !== 'uid' && $fieldName !== 'pid') {
                     // Overwrite the original field with the overlay
                     foreach ($overlays[$origPage['uid']] as $fieldName => $fieldValue) {
                         if ($fieldName !== 'uid' && $fieldName !== 'pid') {
-                            if ($this->shouldFieldBeOverlaid('pages_language_overlay', $fieldName, $fieldValue)) {
-                                $pagesOutput[$key][$fieldName] = $fieldValue;
-                            }
+                            $pagesOutput[$key][$fieldName] = $fieldValue;
                         }
                     }
                 }
                         }
                     }
                 }
@@ -453,7 +512,7 @@ class PageRepository
      * in records from the same table)
      *
      * @param string $table Table name
      * in records from the same table)
      *
      * @param string $table Table name
-     * @param array $row Record to overlay. Must containt uid, pid and $table]['ctrl']['languageField']
+     * @param array $row Record to overlay. Must contain uid, pid and $table]['ctrl']['languageField']
      * @param int $sys_language_content Pointer to the sys_language uid for content on the site.
      * @param string $OLmode Overlay mode. If "hideNonTranslated" then records without translation will not be returned  un-translated but unset (and return value is FALSE)
      * @throws \UnexpectedValueException
      * @param int $sys_language_content Pointer to the sys_language uid for content on the site.
      * @param string $OLmode Overlay mode. If "hideNonTranslated" then records without translation will not be returned  un-translated but unset (and return value is FALSE)
      * @throws \UnexpectedValueException
@@ -462,17 +521,19 @@ class PageRepository
     public function getRecordOverlay($table, $row, $sys_language_content, $OLmode = '')
     {
         if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_page.php']['getRecordOverlay'])) {
     public function getRecordOverlay($table, $row, $sys_language_content, $OLmode = '')
     {
         if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_page.php']['getRecordOverlay'])) {
-            foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_page.php']['getRecordOverlay'] as $classRef) {
-                $hookObject = GeneralUtility::getUserObj($classRef);
+            foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_page.php']['getRecordOverlay'] as $className) {
+                $hookObject = GeneralUtility::makeInstance($className);
                 if (!$hookObject instanceof PageRepositoryGetRecordOverlayHookInterface) {
                 if (!$hookObject instanceof PageRepositoryGetRecordOverlayHookInterface) {
-                    throw new \UnexpectedValueException('$hookObject must implement interface ' . PageRepositoryGetRecordOverlayHookInterface::class, 1269881658);
+                    throw new \UnexpectedValueException($className . ' must implement interface ' . PageRepositoryGetRecordOverlayHookInterface::class, 1269881658);
                 }
                 $hookObject->getRecordOverlay_preProcess($table, $row, $sys_language_content, $OLmode, $this);
             }
         }
         if ($row['uid'] > 0 && ($row['pid'] > 0 || in_array($table, $this->tableNamesAllowedOnRootLevel, true))) {
             if ($GLOBALS['TCA'][$table] && $GLOBALS['TCA'][$table]['ctrl']['languageField'] && $GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField']) {
                 }
                 $hookObject->getRecordOverlay_preProcess($table, $row, $sys_language_content, $OLmode, $this);
             }
         }
         if ($row['uid'] > 0 && ($row['pid'] > 0 || in_array($table, $this->tableNamesAllowedOnRootLevel, true))) {
             if ($GLOBALS['TCA'][$table] && $GLOBALS['TCA'][$table]['ctrl']['languageField'] && $GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField']) {
-                if (!$GLOBALS['TCA'][$table]['ctrl']['transOrigPointerTable']) {
+                // Return record for ALL languages untouched
+                // TODO: Fix call stack to prevent this situation in the first place
+                if ($table !== 'pages_language_overlay' && (int)$row[$GLOBALS['TCA'][$table]['ctrl']['languageField']] !== -1) {
                     // Will not be able to work with other tables (Just didn't implement it yet;
                     // Requires a scan over all tables [ctrl] part for first FIND the table that
                     // carries localization information for this table (which could even be more
                     // Will not be able to work with other tables (Just didn't implement it yet;
                     // Requires a scan over all tables [ctrl] part for first FIND the table that
                     // carries localization information for this table (which could even be more
@@ -480,12 +541,34 @@ class PageRepository
                     // takes a little more....) Will try to overlay a record only if the
                     // sys_language_content value is larger than zero.
                     if ($sys_language_content > 0) {
                     // takes a little more....) Will try to overlay a record only if the
                     // sys_language_content value is larger than zero.
                     if ($sys_language_content > 0) {
-                        // Must be default language or [All], otherwise no overlaying:
+                        // Must be default language, otherwise no overlaying
                         if ((int)$row[$GLOBALS['TCA'][$table]['ctrl']['languageField']] === 0) {
                             // Select overlay record:
                         if ((int)$row[$GLOBALS['TCA'][$table]['ctrl']['languageField']] === 0) {
                             // Select overlay record:
-                            $res = $this->getDatabaseConnection()->exec_SELECTquery('*', $table, 'pid=' . (int)$row['pid'] . ' AND ' . $GLOBALS['TCA'][$table]['ctrl']['languageField'] . '=' . (int)$sys_language_content . ' AND ' . $GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField'] . '=' . (int)$row['uid'] . $this->enableFields($table), '', '', '1');
-                            $olrow = $this->getDatabaseConnection()->sql_fetch_assoc($res);
-                            $this->getDatabaseConnection()->sql_free_result($res);
+                            $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
+                                ->getQueryBuilderForTable($table);
+                            $queryBuilder->setRestrictions(
+                                GeneralUtility::makeInstance(FrontendRestrictionContainer::class)
+                            );
+                            $olrow = $queryBuilder->select('*')
+                                ->from($table)
+                                ->where(
+                                    $queryBuilder->expr()->eq(
+                                        'pid',
+                                        $queryBuilder->createNamedParameter($row['pid'], \PDO::PARAM_INT)
+                                    ),
+                                    $queryBuilder->expr()->eq(
+                                        $GLOBALS['TCA'][$table]['ctrl']['languageField'],
+                                        $queryBuilder->createNamedParameter($sys_language_content, \PDO::PARAM_INT)
+                                    ),
+                                    $queryBuilder->expr()->eq(
+                                        $GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField'],
+                                        $queryBuilder->createNamedParameter($row['uid'], \PDO::PARAM_INT)
+                                    )
+                                )
+                                ->setMaxResults(1)
+                                ->execute()
+                                ->fetch();
+
                             $this->versionOL($table, $olrow);
                             // Merge record content by traversing all fields:
                             if (is_array($olrow)) {
                             $this->versionOL($table, $olrow);
                             // Merge record content by traversing all fields:
                             if (is_array($olrow)) {
@@ -497,9 +580,7 @@ class PageRepository
                                 }
                                 foreach ($row as $fN => $fV) {
                                     if ($fN !== 'uid' && $fN !== 'pid' && isset($olrow[$fN])) {
                                 }
                                 foreach ($row as $fN => $fV) {
                                     if ($fN !== 'uid' && $fN !== 'pid' && isset($olrow[$fN])) {
-                                        if ($this->shouldFieldBeOverlaid($table, $fN, $olrow[$fN])) {
-                                            $row[$fN] = $olrow[$fN];
-                                        }
+                                        $row[$fN] = $olrow[$fN];
                                     } elseif ($fN === 'uid') {
                                         $row['_LOCALIZED_UID'] = $olrow['uid'];
                                     }
                                     } elseif ($fN === 'uid') {
                                         $row['_LOCALIZED_UID'] = $olrow['uid'];
                                     }
@@ -523,10 +604,10 @@ class PageRepository
             }
         }
         if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_page.php']['getRecordOverlay'])) {
             }
         }
         if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_page.php']['getRecordOverlay'])) {
-            foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_page.php']['getRecordOverlay'] as $classRef) {
-                $hookObject = GeneralUtility::getUserObj($classRef);
+            foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_page.php']['getRecordOverlay'] as $className) {
+                $hookObject = GeneralUtility::makeInstance($className);
                 if (!$hookObject instanceof PageRepositoryGetRecordOverlayHookInterface) {
                 if (!$hookObject instanceof PageRepositoryGetRecordOverlayHookInterface) {
-                    throw new \UnexpectedValueException('$hookObject must implement interface ' . PageRepositoryGetRecordOverlayHookInterface::class, 1269881659);
+                    throw new \UnexpectedValueException($className . ' must implement interface ' . PageRepositoryGetRecordOverlayHookInterface::class, 1269881659);
                 }
                 $hookObject->getRecordOverlay_postProcess($table, $row, $sys_language_content, $OLmode, $this);
             }
                 }
                 $hookObject->getRecordOverlay_postProcess($table, $row, $sys_language_content, $OLmode, $this);
             }
@@ -542,7 +623,7 @@ class PageRepository
 
     /**
      * Returns an array with page rows for subpages of a certain page ID. This is used for menus in the frontend.
 
     /**
      * Returns an array with page rows for subpages of a certain page ID. This is used for menus in the frontend.
-     * If there are mount points in overlay mode the _MP_PARAM field is set to the corret MPvar.
+     * If there are mount points in overlay mode the _MP_PARAM field is set to the correct MPvar.
      *
      * If the $pageId being input does in itself require MPvars to define a correct
      * rootline these must be handled externally to this function.
      *
      * If the $pageId being input does in itself require MPvars to define a correct
      * rootline these must be handled externally to this function.
@@ -552,7 +633,7 @@ class PageRepository
      * @param string $sortField The field to sort by. Default is "sorting
      * @param string $additionalWhereClause Optional additional where clauses. Like "AND title like '%blabla%'" for instance.
      * @param bool $checkShortcuts Check if shortcuts exist, checks by default
      * @param string $sortField The field to sort by. Default is "sorting
      * @param string $additionalWhereClause Optional additional where clauses. Like "AND title like '%blabla%'" for instance.
      * @param bool $checkShortcuts Check if shortcuts exist, checks by default
-     * @return array Array with key/value pairs; keys are page-uid numbers. values are the corresponding page records (with overlayed localized fields, if any)
+     * @return array Array with key/value pairs; keys are page-uid numbers. values are the corresponding page records (with overlaid localized fields, if any)
      * @see \TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController::getPageShortcut(), \TYPO3\CMS\Frontend\ContentObject\Menu\AbstractMenuContentObject::makeMenu()
      * @see \TYPO3\CMS\WizardCrpages\Controller\CreatePagesWizardModuleFunctionController, \TYPO3\CMS\WizardSortpages\View\SortPagesWizardModuleFunction
      */
      * @see \TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController::getPageShortcut(), \TYPO3\CMS\Frontend\ContentObject\Menu\AbstractMenuContentObject::makeMenu()
      * @see \TYPO3\CMS\WizardCrpages\Controller\CreatePagesWizardModuleFunctionController, \TYPO3\CMS\WizardSortpages\View\SortPagesWizardModuleFunction
      */
@@ -572,7 +653,7 @@ class PageRepository
      * @param string $sortField The field to sort by. Default is "sorting"
      * @param string $additionalWhereClause Optional additional where clauses. Like "AND title like '%blabla%'" for instance.
      * @param bool $checkShortcuts Check if shortcuts exist, checks by default
      * @param string $sortField The field to sort by. Default is "sorting"
      * @param string $additionalWhereClause Optional additional where clauses. Like "AND title like '%blabla%'" for instance.
      * @param bool $checkShortcuts Check if shortcuts exist, checks by default
-     * @return array Array with key/value pairs; keys are page-uid numbers. values are the corresponding page records (with overlayed localized fields, if any)
+     * @return array Array with key/value pairs; keys are page-uid numbers. values are the corresponding page records (with overlaid localized fields, if any)
      */
     public function getMenuForPages(array $pageIds, $fields = '*', $sortField = 'sorting', $additionalWhereClause = '', $checkShortcuts = true)
     {
      */
     public function getMenuForPages(array $pageIds, $fields = '*', $sortField = 'sorting', $additionalWhereClause = '', $checkShortcuts = true)
     {
@@ -583,7 +664,7 @@ class PageRepository
      * Internal method used by getMenu() and getMenuForPages()
      * Returns an array with page rows for subpages with pid is in $pageIds or uid is in $pageIds, depending on $parentPages
      * This is used for menus. If there are mount points in overlay mode
      * Internal method used by getMenu() and getMenuForPages()
      * Returns an array with page rows for subpages with pid is in $pageIds or uid is in $pageIds, depending on $parentPages
      * This is used for menus. If there are mount points in overlay mode
-     * the _MP_PARAM field is set to the corret MPvar.
+     * the _MP_PARAM field is set to the correct MPvar.
      *
      * If the $pageIds being input does in itself require MPvars to define a correct
      * rootline these must be handled externally to this function.
      *
      * If the $pageIds being input does in itself require MPvars to define a correct
      * rootline these must be handled externally to this function.
@@ -593,8 +674,8 @@ class PageRepository
      * @param string $sortField The field to sort by. Default is "sorting
      * @param string $additionalWhereClause Optional additional where clauses. Like "AND title like '%blabla%'" for instance.
      * @param bool $checkShortcuts Check if shortcuts exist, checks by default
      * @param string $sortField The field to sort by. Default is "sorting
      * @param string $additionalWhereClause Optional additional where clauses. Like "AND title like '%blabla%'" for instance.
      * @param bool $checkShortcuts Check if shortcuts exist, checks by default
-     * @param bool $parentPages Whether the uid list is meant as list of parent pages or the page itself TRUE means id list is checked agains pid field
-     * @return array Array with key/value pairs; keys are page-uid numbers. values are the corresponding page records (with overlayed localized fields, if any)
+     * @param bool $parentPages Whether the uid list is meant as list of parent pages or the page itself TRUE means id list is checked against pid field
+     * @return array Array with key/value pairs; keys are page-uid numbers. values are the corresponding page records (with overlaid localized fields, if any)
      * @see \TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController::getPageShortcut(), \TYPO3\CMS\Frontend\ContentObject\Menu\AbstractMenuContentObject::makeMenu()
      * @see \TYPO3\CMS\WizardCrpages\Controller\CreatePagesWizardModuleFunctionController, \TYPO3\CMS\WizardSortpages\View\SortPagesWizardModuleFunction
      */
      * @see \TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController::getPageShortcut(), \TYPO3\CMS\Frontend\ContentObject\Menu\AbstractMenuContentObject::makeMenu()
      * @see \TYPO3\CMS\WizardCrpages\Controller\CreatePagesWizardModuleFunctionController, \TYPO3\CMS\WizardSortpages\View\SortPagesWizardModuleFunction
      */
@@ -602,24 +683,30 @@ class PageRepository
     {
         $pages = [];
         $relationField = $parentPages ? 'pid' : 'uid';
     {
         $pages = [];
         $relationField = $parentPages ? 'pid' : 'uid';
-        $db = $this->getDatabaseConnection();
-
-        $whereStatement = $relationField . ' IN ('
-            . implode(',', $db->cleanIntArray($pageIds)) . ')'
-            . $this->where_hid_del
-            . $this->where_groupAccess
-            . ' '
-            . $additionalWhereClause;
-
-        $databaseResource = $db->exec_SELECTquery(
-            $fields,
-            'pages',
-            $whereStatement,
-            '',
-            $sortField
-        );
+        $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('pages');
+        $queryBuilder->getRestrictions()->removeAll();
+
+        $res = $queryBuilder->select(...GeneralUtility::trimExplode(',', $fields, true))
+            ->from('pages')
+            ->where(
+                $queryBuilder->expr()->in(
+                    $relationField,
+                    $queryBuilder->createNamedParameter($pageIds, Connection::PARAM_INT_ARRAY)
+                ),
+                QueryHelper::stripLogicalOperatorPrefix($this->where_hid_del),
+                QueryHelper::stripLogicalOperatorPrefix($this->where_groupAccess),
+                QueryHelper::stripLogicalOperatorPrefix($additionalWhereClause)
+            );
 
 
-        while (($page = $db->sql_fetch_assoc($databaseResource))) {
+        if (!empty($sortField)) {
+            $orderBy = QueryHelper::parseOrderBy($sortField);
+            foreach ($orderBy as $order) {
+                $res->orderBy(...$order);
+            }
+        }
+        $result = $res->execute();
+
+        while ($page = $result->fetch()) {
             $originalUid = $page['uid'];
 
             // Versioning Preview Overlay
             $originalUid = $page['uid'];
 
             // Versioning Preview Overlay
@@ -644,8 +731,6 @@ class PageRepository
             }
         }
 
             }
         }
 
-        $db->sql_free_result($databaseResource);
-
         // Finally load language overlays
         return $this->getPagesOverlay($pages);
     }
         // Finally load language overlays
         return $this->getPagesOverlay($pages);
     }
@@ -718,16 +803,21 @@ class PageRepository
                 $searchUid = 0;
             }
 
                 $searchUid = 0;
             }
 
-            $whereStatement = $searchField . '=' . $searchUid
-                . $this->where_hid_del
-                . $this->where_groupAccess
-                . ' ' . $additionalWhereClause;
-
-            $count = $this->getDatabaseConnection()->exec_SELECTcountRows(
-                'uid',
-                'pages',
-                $whereStatement
-            );
+            $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('pages');
+            $queryBuilder->getRestrictions()->removeAll();
+            $count = $queryBuilder->count('uid')
+                ->from('pages')
+                ->where(
+                    $queryBuilder->expr()->eq(
+                        $searchField,
+                        $queryBuilder->createNamedParameter($searchUid, \PDO::PARAM_INT)
+                    ),
+                    QueryHelper::stripLogicalOperatorPrefix($this->where_hid_del),
+                    QueryHelper::stripLogicalOperatorPrefix($this->where_groupAccess),
+                    QueryHelper::stripLogicalOperatorPrefix($additionalWhereClause)
+                )
+                ->execute()
+                ->fetchColumn();
 
             if (!$count) {
                 $page = [];
 
             if (!$count) {
                 $page = [];
@@ -758,31 +848,61 @@ class PageRepository
         // Appending to domain string
         $domain .= $path;
         $domain = preg_replace('/\\/*$/', '', $domain);
         // Appending to domain string
         $domain .= $path;
         $domain = preg_replace('/\\/*$/', '', $domain);
-        $res = $this->getDatabaseConnection()->exec_SELECTquery('pages.uid,sys_domain.redirectTo,sys_domain.redirectHttpStatusCode,sys_domain.prepend_params', 'pages,sys_domain', 'pages.uid=sys_domain.pid
-                                               AND sys_domain.hidden=0
-                                               AND (sys_domain.domainName=' . $this->getDatabaseConnection()->fullQuoteStr($domain, 'sys_domain') . ' OR sys_domain.domainName=' . $this->getDatabaseConnection()->fullQuoteStr(($domain . '/'), 'sys_domain') . ') ' . $this->where_hid_del . $this->where_groupAccess, '', '', 1);
-        $row = $this->getDatabaseConnection()->sql_fetch_assoc($res);
-        $this->getDatabaseConnection()->sql_free_result($res);
-        if ($row) {
-            if ($row['redirectTo']) {
-                $redirectUrl = $row['redirectTo'];
-                if ($row['prepend_params']) {
-                    $redirectUrl = rtrim($redirectUrl, '/');
-                    $prependStr = ltrim(substr($request_uri, strlen($path)), '/');
-                    $redirectUrl .= '/' . $prependStr;
-                }
-                $statusCode = (int)$row['redirectHttpStatusCode'];
-                if ($statusCode && defined(HttpUtility::class . '::HTTP_STATUS_' . $statusCode)) {
-                    HttpUtility::redirect($redirectUrl, constant(HttpUtility::class . '::HTTP_STATUS_' . $statusCode));
-                } else {
-                    HttpUtility::redirect($redirectUrl, HttpUtility::HTTP_STATUS_301);
-                }
-                die;
+        $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('pages');
+        $queryBuilder->getRestrictions()->removeAll();
+        $row = $queryBuilder
+            ->select(
+                'pages.uid',
+                'sys_domain.redirectTo',
+                'sys_domain.redirectHttpStatusCode',
+                'sys_domain.prepend_params'
+            )
+            ->from('pages')
+            ->from('sys_domain')
+            ->where(
+                $queryBuilder->expr()->eq('pages.uid', $queryBuilder->quoteIdentifier('sys_domain.pid')),
+                $queryBuilder->expr()->eq(
+                    'sys_domain.hidden',
+                    $queryBuilder->createNamedParameter(0, \PDO::PARAM_INT)
+                ),
+                $queryBuilder->expr()->orX(
+                    $queryBuilder->expr()->eq(
+                        'sys_domain.domainName',
+                        $queryBuilder->createNamedParameter($domain, \PDO::PARAM_STR)
+                    ),
+                    $queryBuilder->expr()->eq(
+                        'sys_domain.domainName',
+                        $queryBuilder->createNamedParameter($domain . '/', \PDO::PARAM_STR)
+                    )
+                ),
+                QueryHelper::stripLogicalOperatorPrefix($this->where_hid_del),
+                QueryHelper::stripLogicalOperatorPrefix($this->where_groupAccess)
+            )
+            ->setMaxResults(1)
+            ->execute()
+            ->fetch();
+
+        if (!$row) {
+            return '';
+        }
+
+        if ($row['redirectTo']) {
+            $redirectUrl = $row['redirectTo'];
+            if ($row['prepend_params']) {
+                $redirectUrl = rtrim($redirectUrl, '/');
+                $prependStr = ltrim(substr($request_uri, strlen($path)), '/');
+                $redirectUrl .= '/' . $prependStr;
+            }
+            $statusCode = (int)$row['redirectHttpStatusCode'];
+            if ($statusCode && defined(HttpUtility::class . '::HTTP_STATUS_' . $statusCode)) {
+                HttpUtility::redirect($redirectUrl, constant(HttpUtility::class . '::HTTP_STATUS_' . $statusCode));
             } else {
             } else {
-                return $row['uid'];
+                HttpUtility::redirect($redirectUrl, HttpUtility::HTTP_STATUS_301);
             }
             }
+            die;
+        } else {
+            return $row['uid'];
         }
         }
-        return '';
     }
 
     /**
     }
 
     /**
@@ -816,53 +936,24 @@ class PageRepository
                 if (substr($this->error_getRootLine, -7) === 'uid -1.') {
                     $this->error_getRootLine_failPid = -1;
                 }
                 if (substr($this->error_getRootLine, -7) === 'uid -1.') {
                     $this->error_getRootLine_failPid = -1;
                 }
-                return array();
+                return [];
             /** @see \TYPO3\CMS\Core\Utility\RootlineUtility::getRecordArray */
             } elseif ($ex->getCode() === 1343589451) {
             /** @see \TYPO3\CMS\Core\Utility\RootlineUtility::getRecordArray */
             } elseif ($ex->getCode() === 1343589451) {
-                return array();
+                return [];
             }
             throw $ex;
         }
     }
 
     /**
             }
             throw $ex;
         }
     }
 
     /**
-     * Creates a "path" string for the input root line array titles.
-     * Used for writing statistics.
-     *
-     * @param array $rl A rootline array!
-     * @param int $len The max length of each title from the rootline.
-     * @return string The path in the form "/page title/This is another pageti.../Another page
-     * @see \TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController::getConfigArray()
-     */
-    public function getPathFromRootline($rl, $len = 20)
-    {
-        $path = '';
-        if (is_array($rl)) {
-            $c = count($rl);
-            for ($a = 0; $a < $c; $a++) {
-                if ($rl[$a]['uid']) {
-                    $path .= '/' . GeneralUtility::fixed_lgd_cs(strip_tags($rl[$a]['title']), $len);
-                }
-            }
-        }
-        return $path;
-    }
-
-    /**
-     * Returns the URL type for the input page row IF the doktype is 3 and not
-     * disabled.
+     * Returns the URL type for the input page row IF the doktype is set to 3.
      *
      * @param array $pagerow The page row to return URL type for
      *
      * @param array $pagerow The page row to return URL type for
-     * @param bool $disable A flag to simply disable any output from here. - deprecated - don't use anymore.
-     * @return string|bool The URL type from $this->urltypes array. False if not found or disabled.
-     * @see \TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController::setExternalJumpUrl()
+     * @return string|bool The URL from based on the data from "urltype" and "url". False if not found.
+     * @see \TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController::initializeRedirectUrlHandlers()
      */
      */
-    public function getExtURL($pagerow, $disable = false)
+    public function getExtURL($pagerow)
     {
     {
-        if ($disable !== false) {
-            GeneralUtility::deprecationLog('The disable option of PageRepository::getExtUrl() is deprecated since TYPO3 CMS 7, will be removed with TYPO3 CMS 8.');
-            return false;
-        }
         if ((int)$pagerow['doktype'] === self::DOKTYPE_LINK) {
             $redirectTo = $this->urltypes[$pagerow['urltype']] . $pagerow['url'];
             // If relative path, prefix Site URL:
         if ((int)$pagerow['doktype'] === self::DOKTYPE_LINK) {
             $redirectTo = $this->urltypes[$pagerow['urltype']] . $pagerow['url'];
             // If relative path, prefix Site URL:
@@ -889,7 +980,7 @@ class PageRepository
      * @return mixed Returns FALSE if no mount point was found, "-1" if there should have been one, but no connection to it, otherwise an array with information about mount pid and modes.
      * @see \TYPO3\CMS\Frontend\ContentObject\Menu\AbstractMenuContentObject
      */
      * @return mixed Returns FALSE if no mount point was found, "-1" if there should have been one, but no connection to it, otherwise an array with information about mount pid and modes.
      * @see \TYPO3\CMS\Frontend\ContentObject\Menu\AbstractMenuContentObject
      */
-    public function getMountPointInfo($pageId, $pageRec = false, $prevMountPids = array(), $firstPageUid = 0)
+    public function getMountPointInfo($pageId, $pageRec = false, $prevMountPids = [], $firstPageUid = 0)
     {
         $result = false;
         if ($GLOBALS['TYPO3_CONF_VARS']['FE']['enable_mount_pids']) {
     {
         $result = false;
         if ($GLOBALS['TYPO3_CONF_VARS']['FE']['enable_mount_pids']) {
@@ -898,9 +989,26 @@ class PageRepository
             }
             // Get pageRec if not supplied:
             if (!is_array($pageRec)) {
             }
             // Get pageRec if not supplied:
             if (!is_array($pageRec)) {
-                $res = $this->getDatabaseConnection()->exec_SELECTquery('uid,pid,doktype,mount_pid,mount_pid_ol,t3ver_state', 'pages', 'uid=' . (int)$pageId . ' AND pages.deleted=0 AND pages.doktype<>255');
-                $pageRec = $this->getDatabaseConnection()->sql_fetch_assoc($res);
-                $this->getDatabaseConnection()->sql_free_result($res);
+                $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('pages');
+                $queryBuilder->getRestrictions()
+                    ->removeAll()
+                    ->add(GeneralUtility::makeInstance(DeletedRestriction::class));
+
+                $pageRec = $queryBuilder->select('uid', 'pid', 'doktype', 'mount_pid', 'mount_pid_ol', 't3ver_state')
+                    ->from('pages')
+                    ->where(
+                        $queryBuilder->expr()->eq(
+                            'uid',
+                            $queryBuilder->createNamedParameter($pageId, \PDO::PARAM_INT)
+                        ),
+                        $queryBuilder->expr()->neq(
+                            'doktype',
+                            $queryBuilder->createNamedParameter(255, \PDO::PARAM_INT)
+                        )
+                    )
+                    ->execute()
+                    ->fetch();
+
                 // Only look for version overlay if page record is not supplied; This assumes
                 // that the input record is overlaid with preview version, if any!
                 $this->versionOL('pages', $pageRec);
                 // Only look for version overlay if page record is not supplied; This assumes
                 // that the input record is overlaid with preview version, if any!
                 $this->versionOL('pages', $pageRec);
@@ -913,22 +1021,39 @@ class PageRepository
             $mount_pid = (int)$pageRec['mount_pid'];
             if (is_array($pageRec) && (int)$pageRec['doktype'] === self::DOKTYPE_MOUNTPOINT && $mount_pid > 0 && !in_array($mount_pid, $prevMountPids, true)) {
                 // Get the mount point record (to verify its general existence):
             $mount_pid = (int)$pageRec['mount_pid'];
             if (is_array($pageRec) && (int)$pageRec['doktype'] === self::DOKTYPE_MOUNTPOINT && $mount_pid > 0 && !in_array($mount_pid, $prevMountPids, true)) {
                 // Get the mount point record (to verify its general existence):
-                $res = $this->getDatabaseConnection()->exec_SELECTquery('uid,pid,doktype,mount_pid,mount_pid_ol,t3ver_state', 'pages', 'uid=' . $mount_pid . ' AND pages.deleted=0 AND pages.doktype<>255');
-                $mountRec = $this->getDatabaseConnection()->sql_fetch_assoc($res);
-                $this->getDatabaseConnection()->sql_free_result($res);
+                $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('pages');
+                $queryBuilder->getRestrictions()
+                    ->removeAll()
+                    ->add(GeneralUtility::makeInstance(DeletedRestriction::class));
+
+                $mountRec = $queryBuilder->select('uid', 'pid', 'doktype', 'mount_pid', 'mount_pid_ol', 't3ver_state')
+                    ->from('pages')
+                    ->where(
+                        $queryBuilder->expr()->eq(
+                            'uid',
+                            $queryBuilder->createNamedParameter($mount_pid, \PDO::PARAM_INT)
+                        ),
+                        $queryBuilder->expr()->neq(
+                            'doktype',
+                            $queryBuilder->createNamedParameter(255, \PDO::PARAM_INT)
+                        )
+                    )
+                    ->execute()
+                    ->fetch();
+
                 $this->versionOL('pages', $mountRec);
                 if (is_array($mountRec)) {
                     // Look for recursive mount point:
                     $prevMountPids[] = $mount_pid;
                     $recursiveMountPid = $this->getMountPointInfo($mount_pid, $mountRec, $prevMountPids, $firstPageUid);
                     // Return mount point information:
                 $this->versionOL('pages', $mountRec);
                 if (is_array($mountRec)) {
                     // Look for recursive mount point:
                     $prevMountPids[] = $mount_pid;
                     $recursiveMountPid = $this->getMountPointInfo($mount_pid, $mountRec, $prevMountPids, $firstPageUid);
                     // Return mount point information:
-                    $result = $recursiveMountPid ?: array(
+                    $result = $recursiveMountPid ?: [
                         'mount_pid' => $mount_pid,
                         'overlay' => $pageRec['mount_pid_ol'],
                         'MPvar' => $mount_pid . '-' . $firstPageUid,
                         'mount_point_rec' => $pageRec,
                         'mount_pid_rec' => $mountRec
                         'mount_pid' => $mount_pid,
                         'overlay' => $pageRec['mount_pid_ol'],
                         'MPvar' => $mount_pid . '-' . $firstPageUid,
                         'mount_point_rec' => $pageRec,
                         'mount_pid_rec' => $mountRec
-                    );
+                    ];
                 } else {
                     // Means, there SHOULD have been a mount point, but there was none!
                     $result = -1;
                 } else {
                     // Means, there SHOULD have been a mount point, but there was none!
                     $result = -1;
@@ -958,16 +1083,31 @@ class PageRepository
     {
         $uid = (int)$uid;
         if (is_array($GLOBALS['TCA'][$table]) && $uid > 0) {
     {
         $uid = (int)$uid;
         if (is_array($GLOBALS['TCA'][$table]) && $uid > 0) {
-            $res = $this->getDatabaseConnection()->exec_SELECTquery('*', $table, 'uid = ' . $uid . $this->enableFields($table));
-            $row = $this->getDatabaseConnection()->sql_fetch_assoc($res);
-            $this->getDatabaseConnection()->sql_free_result($res);
+            $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($table);
+            $queryBuilder->setRestrictions(GeneralUtility::makeInstance(FrontendRestrictionContainer::class));
+            $row = $queryBuilder->select('*')
+                ->from($table)
+                ->where($queryBuilder->expr()->eq('uid', $queryBuilder->createNamedParameter($uid, \PDO::PARAM_INT)))
+                ->execute()
+                ->fetch();
+
             if ($row) {
                 $this->versionOL($table, $row);
                 if (is_array($row)) {
                     if ($checkPage) {
             if ($row) {
                 $this->versionOL($table, $row);
                 if (is_array($row)) {
                     if ($checkPage) {
-                        $res = $this->getDatabaseConnection()->exec_SELECTquery('uid', 'pages', 'uid=' . (int)$row['pid'] . $this->enableFields('pages'));
-                        $numRows = $this->getDatabaseConnection()->sql_num_rows($res);
-                        $this->getDatabaseConnection()->sql_free_result($res);
+                        $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
+                            ->getQueryBuilderForTable('pages');
+                        $queryBuilder->setRestrictions(GeneralUtility::makeInstance(FrontendRestrictionContainer::class));
+                        $numRows = (int)$queryBuilder->count('*')
+                            ->from('pages')
+                            ->where(
+                                $queryBuilder->expr()->eq(
+                                    'uid',
+                                    $queryBuilder->createNamedParameter($row['pid'], \PDO::PARAM_INT)
+                                )
+                            )
+                            ->execute()
+                            ->fetchColumn();
                         if ($numRows > 0) {
                             return $row;
                         } else {
                         if ($numRows > 0) {
                             return $row;
                         } else {
@@ -996,9 +1136,16 @@ class PageRepository
     {
         $uid = (int)$uid;
         if (isset($GLOBALS['TCA'][$table]) && is_array($GLOBALS['TCA'][$table]) && $uid > 0) {
     {
         $uid = (int)$uid;
         if (isset($GLOBALS['TCA'][$table]) && is_array($GLOBALS['TCA'][$table]) && $uid > 0) {
-            $res = $this->getDatabaseConnection()->exec_SELECTquery($fields, $table, 'uid = ' . $uid . $this->deleteClause($table));
-            $row = $this->getDatabaseConnection()->sql_fetch_assoc($res);
-            $this->getDatabaseConnection()->sql_free_result($res);
+            $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($table);
+            $queryBuilder->getRestrictions()
+                ->removeAll()
+                ->add(GeneralUtility::makeInstance(DeletedRestriction::class));
+            $row = $queryBuilder->select(...GeneralUtility::trimExplode(',', $fields, true))
+                ->from($table)
+                ->where($queryBuilder->expr()->eq('uid', $queryBuilder->createNamedParameter($uid, \PDO::PARAM_INT)))
+                ->execute()
+                ->fetch();
+
             if ($row) {
                 if (!$noWSOL) {
                     $this->versionOL($table, $row);
             if ($row) {
                 if (!$noWSOL) {
                     $this->versionOL($table, $row);
@@ -1026,14 +1173,42 @@ class PageRepository
     public function getRecordsByField($theTable, $theField, $theValue, $whereClause = '', $groupBy = '', $orderBy = '', $limit = '')
     {
         if (is_array($GLOBALS['TCA'][$theTable])) {
     public function getRecordsByField($theTable, $theField, $theValue, $whereClause = '', $groupBy = '', $orderBy = '', $limit = '')
     {
         if (is_array($GLOBALS['TCA'][$theTable])) {
-            $res = $this->getDatabaseConnection()->exec_SELECTquery('*', $theTable, $theField . '=' . $this->getDatabaseConnection()->fullQuoteStr($theValue, $theTable) . $this->deleteClause($theTable) . ' ' . $whereClause, $groupBy, $orderBy, $limit);
-            $rows = array();
-            while ($row = $this->getDatabaseConnection()->sql_fetch_assoc($res)) {
-                if (is_array($row)) {
-                    $rows[] = $row;
+            $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($theTable);
+            $queryBuilder->getRestrictions()
+                ->removeAll()
+                ->add(GeneralUtility::makeInstance(DeletedRestriction::class));
+
+            $queryBuilder->select('*')
+                ->from($theTable)
+                ->where($queryBuilder->expr()->eq($theField, $queryBuilder->createNamedParameter($theValue)));
+
+            if ($whereClause !== '') {
+                $queryBuilder->andWhere(QueryHelper::stripLogicalOperatorPrefix($whereClause));
+            }
+
+            if ($groupBy !== '') {
+                $queryBuilder->groupBy(QueryHelper::parseGroupBy($groupBy));
+            }
+
+            if ($orderBy !== '') {
+                foreach (QueryHelper::parseOrderBy($orderBy) as $orderPair) {
+                    list($fieldName, $order) = $orderPair;
+                    $queryBuilder->addOrderBy($fieldName, $order);
                 }
             }
                 }
             }
-            $this->getDatabaseConnection()->sql_free_result($res);
+
+            if ($limit !== '') {
+                if (strpos($limit, ',')) {
+                    $limitOffsetAndMax = GeneralUtility::intExplode(',', $limit);
+                    $queryBuilder->setFirstResult((int)$limitOffsetAndMax[0]);
+                    $queryBuilder->setMaxResults((int)$limitOffsetAndMax[1]);
+                } else {
+                    $queryBuilder->setMaxResults((int)$limit);
+                }
+            }
+
+            $rows = $queryBuilder->execute()->fetchAll();
+
             if (!empty($rows)) {
                 return $rows;
             }
             if (!empty($rows)) {
                 return $rows;
             }
@@ -1043,53 +1218,11 @@ class PageRepository
 
     /********************************
      *
 
     /********************************
      *
-     * Caching and standard clauses
+     * Standard clauses
      *
      ********************************/
 
     /**
      *
      ********************************/
 
     /**
-     * Returns data stored for the hash string in the cache "cache_hash"
-     * Can be used to retrieved a cached value, array or object
-     * Can be used from your frontend plugins if you like. It is also used to
-     * store the parsed TypoScript template structures. You can call it directly
-     * like PageRepository::getHash()
-     *
-     * @param string $hash The hash-string which was used to store the data value
-     * @return mixed The "data" from the cache
-     * @see tslib_TStemplate::start(), storeHash()
-     */
-    public static function getHash($hash)
-    {
-        $hashContent = null;
-        /** @var \TYPO3\CMS\Core\Cache\Frontend\FrontendInterface $contentHashCache */
-        $contentHashCache = GeneralUtility::makeInstance(CacheManager::class)->getCache('cache_hash');
-        $cacheEntry = $contentHashCache->get($hash);
-        if ($cacheEntry) {
-            $hashContent = $cacheEntry;
-        }
-        return $hashContent;
-    }
-
-    /**
-     * Stores $data in the 'cache_hash' cache with the hash key, $hash
-     * and visual/symbolic identification, $ident
-     *
-     * Can be used from your frontend plugins if you like. You can call it
-     * directly like PageRepository::storeHash()
-     *
-     * @param string $hash 32 bit hash string (eg. a md5 hash of a serialized array identifying the data being stored)
-     * @param mixed $data The data to store
-     * @param string $ident Is just a textual identification in order to inform about the content!
-     * @param int $lifetime The lifetime for the cache entry in seconds
-     * @return void
-     * @see tslib_TStemplate::start(), getHash()
-     */
-    public static function storeHash($hash, $data, $ident, $lifetime = 0)
-    {
-        GeneralUtility::makeInstance(CacheManager::class)->getCache('cache_hash')->set($hash, $data, array('ident_' . $ident), (int)$lifetime);
-    }
-
-    /**
      * Returns the "AND NOT deleted" clause for the tablename given IF
      * $GLOBALS['TCA'] configuration points to such a field.
      *
      * Returns the "AND NOT deleted" clause for the tablename given IF
      * $GLOBALS['TCA'] configuration points to such a field.
      *
@@ -1119,41 +1252,49 @@ class PageRepository
      * @return string The clause starting like " AND ...=... AND ...=...
      * @see \TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer::enableFields(), deleteClause()
      */
      * @return string The clause starting like " AND ...=... AND ...=...
      * @see \TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer::enableFields(), deleteClause()
      */
-    public function enableFields($table, $show_hidden = -1, $ignore_array = array(), $noVersionPreview = false)
+    public function enableFields($table, $show_hidden = -1, $ignore_array = [], $noVersionPreview = false)
     {
         if ($show_hidden === -1 && is_object($this->getTypoScriptFrontendController())) {
             // If show_hidden was not set from outside and if TSFE is an object, set it
             // based on showHiddenPage and showHiddenRecords from TSFE
     {
         if ($show_hidden === -1 && is_object($this->getTypoScriptFrontendController())) {
             // If show_hidden was not set from outside and if TSFE is an object, set it
             // based on showHiddenPage and showHiddenRecords from TSFE
-            $show_hidden = $table === 'pages' ? $this->getTypoScriptFrontendController()->showHiddenPage : $this->getTypoScriptFrontendController()->showHiddenRecords;
+            $show_hidden = $table === 'pages' || $table === 'pages_language_overlay'
+                ? $this->getTypoScriptFrontendController()->showHiddenPage
+                : $this->getTypoScriptFrontendController()->showHiddenRecords;
         }
         if ($show_hidden === -1) {
             $show_hidden = 0;
         }
         // If show_hidden was not changed during the previous evaluation, do it here.
         $ctrl = $GLOBALS['TCA'][$table]['ctrl'];
         }
         if ($show_hidden === -1) {
             $show_hidden = 0;
         }
         // If show_hidden was not changed during the previous evaluation, do it here.
         $ctrl = $GLOBALS['TCA'][$table]['ctrl'];
-        $query = '';
+        $expressionBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
+            ->getQueryBuilderForTable($table)
+            ->expr();
+        $constraints = [];
         if (is_array($ctrl)) {
             // Delete field check:
             if ($ctrl['delete']) {
         if (is_array($ctrl)) {
             // Delete field check:
             if ($ctrl['delete']) {
-                $query .= ' AND ' . $table . '.' . $ctrl['delete'] . '=0';
+                $constraints[] = $expressionBuilder->eq($table . '.' . $ctrl['delete'], 0);
             }
             if ($ctrl['versioningWS']) {
                 if (!$this->versioningPreview) {
                     // Filter out placeholder records (new/moved/deleted items)
                     // in case we are NOT in a versioning preview (that means we are online!)
             }
             if ($ctrl['versioningWS']) {
                 if (!$this->versioningPreview) {
                     // Filter out placeholder records (new/moved/deleted items)
                     // in case we are NOT in a versioning preview (that means we are online!)
-                    $query .= ' AND ' . $table . '.t3ver_state<=' . new VersionState(VersionState::DEFAULT_STATE);
+                    $constraints[] = $expressionBuilder->lte(
+                        $table . '.t3ver_state',
+                        new VersionState(VersionState::DEFAULT_STATE)
+                    );
                 } elseif ($table !== 'pages') {
                     // show only records of live and of the current workspace
                     // in case we are in a versioning preview
                 } elseif ($table !== 'pages') {
                     // show only records of live and of the current workspace
                     // in case we are in a versioning preview
-                    $query .= ' AND (' .
-                                $table . '.t3ver_wsid=0 OR ' .
-                                $table . '.t3ver_wsid=' . (int)$this->versioningWorkspaceId .
-                                ')';
+                    $constraints[] = $expressionBuilder->orX(
+                        $expressionBuilder->eq($table . '.t3ver_wsid', 0),
+                        $expressionBuilder->eq($table . '.t3ver_wsid', (int)$this->versioningWorkspaceId)
+                    );
                 }
 
                 // Filter out versioned records
                 if (!$noVersionPreview && empty($ignore_array['pid'])) {
                 }
 
                 // Filter out versioned records
                 if (!$noVersionPreview && empty($ignore_array['pid'])) {
-                    $query .= ' AND ' . $table . '.pid<>-1';
+                    $constraints[] = $expressionBuilder->neq($table . '.pid', -1);
                 }
             }
 
                 }
             }
 
@@ -1164,32 +1305,39 @@ class PageRepository
                 if (!$this->versioningPreview || !$ctrl['versioningWS'] || $noVersionPreview) {
                     if ($ctrl['enablecolumns']['disabled'] && !$show_hidden && !$ignore_array['disabled']) {
                         $field = $table . '.' . $ctrl['enablecolumns']['disabled'];
                 if (!$this->versioningPreview || !$ctrl['versioningWS'] || $noVersionPreview) {
                     if ($ctrl['enablecolumns']['disabled'] && !$show_hidden && !$ignore_array['disabled']) {
                         $field = $table . '.' . $ctrl['enablecolumns']['disabled'];
-                        $query .= ' AND ' . $field . '=0';
+                        $constraints[] = $expressionBuilder->eq($field, 0);
                     }
                     if ($ctrl['enablecolumns']['starttime'] && !$ignore_array['starttime']) {
                         $field = $table . '.' . $ctrl['enablecolumns']['starttime'];
                     }
                     if ($ctrl['enablecolumns']['starttime'] && !$ignore_array['starttime']) {
                         $field = $table . '.' . $ctrl['enablecolumns']['starttime'];
-                        $query .= ' AND ' . $field . '<=' . $GLOBALS['SIM_ACCESS_TIME'];
+                        $constraints[] = $expressionBuilder->lte($field, (int)$GLOBALS['SIM_ACCESS_TIME']);
                     }
                     if ($ctrl['enablecolumns']['endtime'] && !$ignore_array['endtime']) {
                         $field = $table . '.' . $ctrl['enablecolumns']['endtime'];
                     }
                     if ($ctrl['enablecolumns']['endtime'] && !$ignore_array['endtime']) {
                         $field = $table . '.' . $ctrl['enablecolumns']['endtime'];
-                        $query .= ' AND (' . $field . '=0 OR ' . $field . '>' . $GLOBALS['SIM_ACCESS_TIME'] . ')';
+                        $constraints[] = $expressionBuilder->orX(
+                            $expressionBuilder->eq($field, 0),
+                            $expressionBuilder->gt($field, (int)$GLOBALS['SIM_ACCESS_TIME'])
+                        );
                     }
                     if ($ctrl['enablecolumns']['fe_group'] && !$ignore_array['fe_group']) {
                         $field = $table . '.' . $ctrl['enablecolumns']['fe_group'];
                     }
                     if ($ctrl['enablecolumns']['fe_group'] && !$ignore_array['fe_group']) {
                         $field = $table . '.' . $ctrl['enablecolumns']['fe_group'];
-                        $query .= $this->getMultipleGroupsWhereClause($field, $table);
+                        $constraints[] = QueryHelper::stripLogicalOperatorPrefix(
+                            $this->getMultipleGroupsWhereClause($field, $table)
+                        );
                     }
                     // Call hook functions for additional enableColumns
                     // It is used by the extension ingmar_accessctrl which enables assigning more
                     // than one usergroup to content and page records
                     if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_page.php']['addEnableColumns'])) {
                     }
                     // Call hook functions for additional enableColumns
                     // It is used by the extension ingmar_accessctrl which enables assigning more
                     // than one usergroup to content and page records
                     if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_page.php']['addEnableColumns'])) {
-                        $_params = array(
+                        $_params = [
                             'table' => $table,
                             'show_hidden' => $show_hidden,
                             'ignore_array' => $ignore_array,
                             'ctrl' => $ctrl
                             'table' => $table,
                             'show_hidden' => $show_hidden,
                             'ignore_array' => $ignore_array,
                             'ctrl' => $ctrl
-                        );
+                        ];
                         foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_page.php']['addEnableColumns'] as $_funcRef) {
                         foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_page.php']['addEnableColumns'] as $_funcRef) {
-                            $query .= GeneralUtility::callUserFunction($_funcRef, $_params, $this);
+                            $constraints[] = QueryHelper::stripLogicalOperatorPrefix(
+                                GeneralUtility::callUserFunction($_funcRef, $_params, $this)
+                            );
                         }
                     }
                 }
                         }
                     }
                 }
@@ -1197,7 +1345,8 @@ class PageRepository
         } else {
             throw new \InvalidArgumentException('There is no entry in the $TCA array for the table "' . $table . '". This means that the function enableFields() is ' . 'called with an invalid table name as argument.', 1283790586);
         }
         } else {
             throw new \InvalidArgumentException('There is no entry in the $TCA array for the table "' . $table . '". This means that the function enableFields() is ' . 'called with an invalid table name as argument.', 1283790586);
         }
-        return $query;
+
+        return empty($constraints) ? '' : ' AND ' . $expressionBuilder->andX(...$constraints);
     }
 
     /**
     }
 
     /**
@@ -1211,18 +1360,22 @@ class PageRepository
      */
     public function getMultipleGroupsWhereClause($field, $table)
     {
      */
     public function getMultipleGroupsWhereClause($field, $table)
     {
+        $expressionBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
+            ->getQueryBuilderForTable($table)
+            ->expr();
         $memberGroups = GeneralUtility::intExplode(',', $this->getTypoScriptFrontendController()->gr_list);
         $memberGroups = GeneralUtility::intExplode(',', $this->getTypoScriptFrontendController()->gr_list);
-        $orChecks = array();
+        $orChecks = [];
         // If the field is empty, then OK
         // If the field is empty, then OK
-        $orChecks[] = $field . '=\'\'';
+        $orChecks[] = $expressionBuilder->eq($field, $expressionBuilder->literal(''));
         // If the field is NULL, then OK
         // If the field is NULL, then OK
-        $orChecks[] = $field . ' IS NULL';
-        // If the field contsains zero, then OK
-        $orChecks[] = $field . '=\'0\'';
+        $orChecks[] = $expressionBuilder->isNull($field);
+        // If the field contains zero, then OK
+        $orChecks[] = $expressionBuilder->eq($field, $expressionBuilder->literal('0'));
         foreach ($memberGroups as $value) {
         foreach ($memberGroups as $value) {
-            $orChecks[] = $this->getDatabaseConnection()->listQuery($field, $value, $table);
+            $orChecks[] = $expressionBuilder->inSet($field, $expressionBuilder->literal($value));
         }
         }
-        return ' AND (' . implode(' OR ', $orChecks) . ')';
+
+        return' AND (' . $expressionBuilder->orX(...$orChecks) . ')';
     }
 
     /**********************
     }
 
     /**********************
@@ -1247,7 +1400,6 @@ class PageRepository
      *
      * @param string $table Table name
      * @param array $rr Record array passed by reference. As minimum, "pid" and "uid" fields must exist! "t3ver_oid" and "t3ver_wsid" is nice and will save you a DB query.
      *
      * @param string $table Table name
      * @param array $rr Record array passed by reference. As minimum, "pid" and "uid" fields must exist! "t3ver_oid" and "t3ver_wsid" is nice and will save you a DB query.
-     * @return void (Passed by ref).
      * @see BackendUtility::fixVersioningPid(), versionOL(), getRootLine()
      */
     public function fixVersioningPid($table, &$rr)
      * @see BackendUtility::fixVersioningPid(), versionOL(), getRootLine()
      */
     public function fixVersioningPid($table, &$rr)
@@ -1255,7 +1407,6 @@ class PageRepository
         if ($this->versioningPreview && is_array($rr) && (int)$rr['pid'] === -1 && $GLOBALS['TCA'][$table]['ctrl']['versioningWS']) {
             $oid = 0;
             $wsid = 0;
         if ($this->versioningPreview && is_array($rr) && (int)$rr['pid'] === -1 && $GLOBALS['TCA'][$table]['ctrl']['versioningWS']) {
             $oid = 0;
             $wsid = 0;
-            // Have to hardcode it for "pages" table since TCA is not loaded at this moment!
             // Check values for t3ver_oid and t3ver_wsid:
             if (isset($rr['t3ver_oid']) && isset($rr['t3ver_wsid'])) {
                 // If "t3ver_oid" is already a field, just set this:
             // Check values for t3ver_oid and t3ver_wsid:
             if (isset($rr['t3ver_oid']) && isset($rr['t3ver_wsid'])) {
                 // If "t3ver_oid" is already a field, just set this:
@@ -1308,7 +1459,6 @@ class PageRepository
      * @param array $row Record array passed by reference. As minimum, the "uid", "pid" and "t3ver_state" fields must exist! The record MAY be set to FALSE in which case the calling function should act as if the record is forbidden to access!
      * @param bool $unsetMovePointers If set, the $row is cleared in case it is a move-pointer. This is only for preview of moved records (to remove the record from the original location so it appears only in the new location)
      * @param bool $bypassEnableFieldsCheck Unless this option is TRUE, the $row is unset if enablefields for BOTH the version AND the online record deselects it. This is because when versionOL() is called it is assumed that the online record is already selected with no regards to it's enablefields. However, after looking for a new version the online record enablefields must ALSO be evaluated of course. This is done all by this function!
      * @param array $row Record array passed by reference. As minimum, the "uid", "pid" and "t3ver_state" fields must exist! The record MAY be set to FALSE in which case the calling function should act as if the record is forbidden to access!
      * @param bool $unsetMovePointers If set, the $row is cleared in case it is a move-pointer. This is only for preview of moved records (to remove the record from the original location so it appears only in the new location)
      * @param bool $bypassEnableFieldsCheck Unless this option is TRUE, the $row is unset if enablefields for BOTH the version AND the online record deselects it. This is because when versionOL() is called it is assumed that the online record is already selected with no regards to it's enablefields. However, after looking for a new version the online record enablefields must ALSO be evaluated of course. This is done all by this function!
-     * @return void (Passed by ref).
      * @see fixVersioningPid(), BackendUtility::workspaceOL()
      */
     public function versionOL($table, &$row, $unsetMovePointers = false, $bypassEnableFieldsCheck = false)
      * @see fixVersioningPid(), BackendUtility::workspaceOL()
      */
     public function versionOL($table, &$row, $unsetMovePointers = false, $bypassEnableFieldsCheck = false)
@@ -1331,8 +1481,7 @@ class PageRepository
                     $wsAlt['pid'] = $row['pid'];
                     // For versions of single elements or page+content, preserve online UID and PID
                     // (this will produce true "overlay" of element _content_, not any references)
                     $wsAlt['pid'] = $row['pid'];
                     // For versions of single elements or page+content, preserve online UID and PID
                     // (this will produce true "overlay" of element _content_, not any references)
-                    // For page+content the "_ORIG_uid" should actually be used as PID for selection
-                    // of tables with "versioning_followPages" enabled.
+                    // For page+content the "_ORIG_uid" should actually be used as PID for selection.
                     $wsAlt['_ORIG_uid'] = $wsAlt['uid'];
                     $wsAlt['uid'] = $row['uid'];
                     // Translate page alias as well so links are pointing to the _online_ page:
                     $wsAlt['_ORIG_uid'] = $wsAlt['uid'];
                     $wsAlt['uid'] = $row['uid'];
                     // Translate page alias as well so links are pointing to the _online_ page:
@@ -1394,7 +1543,6 @@ class PageRepository
         if (!empty($GLOBALS['TCA'][$table]['ctrl']['versioningWS'])
             && (int)VersionState::cast($row['t3ver_state'])->equals(VersionState::MOVE_PLACEHOLDER)
         ) {
         if (!empty($GLOBALS['TCA'][$table]['ctrl']['versioningWS'])
             && (int)VersionState::cast($row['t3ver_state'])->equals(VersionState::MOVE_PLACEHOLDER)
         ) {
-            // Only for WS ver 2... (moving) - enabled by default with CMS7
             // If t3ver_move_id is not found, then find it (but we like best if it is here)
             if (!isset($row['t3ver_move_id'])) {
                 $moveIDRec = $this->getRawRecord($table, $row['uid'], 't3ver_move_id', true);
             // If t3ver_move_id is not found, then find it (but we like best if it is here)
             if (!isset($row['t3ver_move_id'])) {
                 $moveIDRec = $this->getRawRecord($table, $row['uid'], 't3ver_move_id', true);
@@ -1404,9 +1552,20 @@ class PageRepository
             }
             // Find pointed-to record.
             if ($moveID) {
             }
             // Find pointed-to record.
             if ($moveID) {
-                $res = $this->getDatabaseConnection()->exec_SELECTquery(implode(',', array_keys($row)), $table, 'uid=' . (int)$moveID . $this->enableFields($table));
-                $origRow = $this->getDatabaseConnection()->sql_fetch_assoc($res);
-                $this->getDatabaseConnection()->sql_free_result($res);
+                $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($table);
+                $queryBuilder->setRestrictions(GeneralUtility::makeInstance(FrontendRestrictionContainer::class));
+                $origRow = $queryBuilder->select(...array_keys($this->purgeComputedProperties($row)))
+                    ->from($table)
+                    ->where(
+                        $queryBuilder->expr()->eq(
+                            'uid',
+                            $queryBuilder->createNamedParameter($moveID, \PDO::PARAM_INT)
+                        )
+                    )
+                    ->setMaxResults(1)
+                    ->execute()
+                    ->fetch();
+
                 if ($origRow) {
                     $row = $origRow;
                     return true;
                 if ($origRow) {
                     $row = $origRow;
                     return true;
@@ -1431,10 +1590,35 @@ class PageRepository
             $workspace = (int)$this->versioningWorkspaceId;
             if (!empty($GLOBALS['TCA'][$table]['ctrl']['versioningWS']) && $workspace !== 0) {
                 // Select workspace version of record:
             $workspace = (int)$this->versioningWorkspaceId;
             if (!empty($GLOBALS['TCA'][$table]['ctrl']['versioningWS']) && $workspace !== 0) {
                 // Select workspace version of record:
-                $row = $this->getDatabaseConnection()->exec_SELECTgetSingleRow($fields, $table, 'pid<>-1 AND
-                                               t3ver_state=' . new VersionState(VersionState::MOVE_PLACEHOLDER) . ' AND
-                                               t3ver_move_id=' . (int)$uid . ' AND
-                                               t3ver_wsid=' . (int)$workspace . $this->deleteClause($table));
+                $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($table);
+                $queryBuilder->getRestrictions()
+                    ->removeAll()
+                    ->add(GeneralUtility::makeInstance(DeletedRestriction::class));
+
+                $row = $queryBuilder->select(...GeneralUtility::trimExplode(',', $fields, true))
+                    ->from($table)
+                    ->where(
+                        $queryBuilder->expr()->neq('pid', $queryBuilder->createNamedParameter(-1, \PDO::PARAM_INT)),
+                        $queryBuilder->expr()->eq(
+                            't3ver_state',
+                            $queryBuilder->createNamedParameter(
+                                new VersionState(VersionState::MOVE_PLACEHOLDER),
+                                \PDO::PARAM_INT
+                            )
+                        ),
+                        $queryBuilder->expr()->eq(
+                            't3ver_move_id',
+                            $queryBuilder->createNamedParameter($uid, \PDO::PARAM_INT)
+                        ),
+                        $queryBuilder->expr()->eq(
+                            't3ver_wsid',
+                            $queryBuilder->createNamedParameter($workspace, \PDO::PARAM_INT)
+                        )
+                    )
+                    ->setMaxResults(1)
+                    ->execute()
+                    ->fetch();
+
                 if (is_array($row)) {
                     return $row;
                 }
                 if (is_array($row)) {
                     return $row;
                 }
@@ -1459,18 +1643,52 @@ class PageRepository
         if ($workspace !== 0 && !empty($GLOBALS['TCA'][$table]['ctrl']['versioningWS'])) {
             $workspace = (int)$workspace;
             $uid = (int)$uid;
         if ($workspace !== 0 && !empty($GLOBALS['TCA'][$table]['ctrl']['versioningWS'])) {
             $workspace = (int)$workspace;
             $uid = (int)$uid;
-            // Setting up enableFields for version record
-            $enFields = $this->enableFields($table, -1, array(), true);
             // Select workspace version of record, only testing for deleted.
             // Select workspace version of record, only testing for deleted.
-            $newrow = $this->getDatabaseConnection()->exec_SELECTgetSingleRow($fields, $table, 'pid=-1 AND
-                                       t3ver_oid=' . $uid . ' AND
-                                       t3ver_wsid=' . $workspace . $this->deleteClause($table));
+            $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($table);
+            $queryBuilder->getRestrictions()
+                ->removeAll()
+                ->add(GeneralUtility::makeInstance(DeletedRestriction::class));
+
+            $newrow = $queryBuilder->select(...GeneralUtility::trimExplode(',', $fields, true))
+                ->from($table)
+                ->where(
+                    $queryBuilder->expr()->eq('pid', $queryBuilder->createNamedParameter(-1, \PDO::PARAM_INT)),
+                    $queryBuilder->expr()->eq(
+                        't3ver_oid',
+                        $queryBuilder->createNamedParameter($uid, \PDO::PARAM_INT)
+                    ),
+                    $queryBuilder->expr()->eq(
+                        't3ver_wsid',
+                        $queryBuilder->createNamedParameter($workspace, \PDO::PARAM_INT)
+                    )
+                )
+                ->setMaxResults(1)
+                ->execute()
+                ->fetch();
+
             // If version found, check if it could have been selected with enableFields on
             // as well:
             // If version found, check if it could have been selected with enableFields on
             // as well:
+            $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($table);
+            $queryBuilder->setRestrictions(GeneralUtility::makeInstance(FrontendRestrictionContainer::class));
+            // Remove the frontend workspace restriction because we are testing a version record
+            $queryBuilder->getRestrictions()->removeByType(FrontendWorkspaceRestriction::class);
+            $queryBuilder->select('uid')
+                ->from($table)
+                ->setMaxResults(1);
+
             if (is_array($newrow)) {
             if (is_array($newrow)) {
-                if ($bypassEnableFieldsCheck || $this->getDatabaseConnection()->exec_SELECTgetSingleRow('uid', $table, 'pid=-1 AND
-                                               t3ver_oid=' . $uid . ' AND
-                                               t3ver_wsid=' . $workspace . $enFields)) {
+                $queryBuilder->where(
+                    $queryBuilder->expr()->eq('pid', $queryBuilder->createNamedParameter(-1, \PDO::PARAM_INT)),
+                    $queryBuilder->expr()->eq(
+                        't3ver_oid',
+                        $queryBuilder->createNamedParameter($uid, \PDO::PARAM_INT)
+                    ),
+                    $queryBuilder->expr()->eq(
+                        't3ver_wsid',
+                        $queryBuilder->createNamedParameter($workspace, \PDO::PARAM_INT)
+                    )
+                );
+                if ($bypassEnableFieldsCheck || $queryBuilder->execute()->fetchColumn()) {
                     // Return offline version, tested for its enableFields.
                     return $newrow;
                 } else {
                     // Return offline version, tested for its enableFields.
                     return $newrow;
                 } else {
@@ -1480,7 +1698,10 @@ class PageRepository
             } else {
                 // OK, so no workspace version was found. Then check if online version can be
                 // selected with full enable fields and if so, return 1:
             } else {
                 // OK, so no workspace version was found. Then check if online version can be
                 // selected with full enable fields and if so, return 1:
-                if ($bypassEnableFieldsCheck || $this->getDatabaseConnection()->exec_SELECTgetSingleRow('uid', $table, 'uid=' . $uid . $enFields)) {
+                $queryBuilder->where(
+                    $queryBuilder->expr()->eq('uid', $queryBuilder->createNamedParameter($uid, \PDO::PARAM_INT))
+                );
+                if ($bypassEnableFieldsCheck || $queryBuilder->execute()->fetchColumn()) {
                     // Means search was done, but no version found.
                     return 1;
                 } else {
                     // Means search was done, but no version found.
                     return 1;
                 } else {
@@ -1509,8 +1730,17 @@ class PageRepository
             $ws = $this->workspaceCache[$wsid];
         } else {
             if ($wsid > 0) {
             $ws = $this->workspaceCache[$wsid];
         } else {
             if ($wsid > 0) {
-                // No $GLOBALS['TCA'] yet!
-                $ws = $this->getDatabaseConnection()->exec_SELECTgetSingleRow('*', 'sys_workspace', 'uid=' . (int)$wsid . ' AND deleted=0');
+                $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
+                    ->getQueryBuilderForTable('sys_workspace');
+                $queryBuilder->getRestrictions()->removeAll();
+                $ws = $queryBuilder->select('*')
+                    ->from('sys_workspace')
+                    ->where(
+                        $queryBuilder->expr()->eq('uid', $queryBuilder->createNamedParameter($wsid, \PDO::PARAM_INT)),
+                        $queryBuilder->expr()->eq('deleted', $queryBuilder->createNamedParameter(0, \PDO::PARAM_INT))
+                    )
+                    ->execute()
+                    ->fetch();
                 if (!is_array($ws)) {
                     return false;
                 }
                 if (!is_array($ws)) {
                     return false;
                 }
@@ -1545,7 +1775,7 @@ class PageRepository
              * We just catch the exception here
              * Reasoning: There is nothing an editor or even admin could do
              */
              * We just catch the exception here
              * Reasoning: There is nothing an editor or even admin could do
              */
-            return array();
+            return [];
         } catch (\InvalidArgumentException $e) {
             /**
              * The storage does not exist anymore
         } catch (\InvalidArgumentException $e) {
             /**
              * The storage does not exist anymore
@@ -1553,7 +1783,7 @@ class PageRepository
              */
             $logMessage = $e->getMessage() . ' (table: "' . $tableName . '", fieldName: "' . $fieldName . '", currentId: ' . $currentId . ')';
             GeneralUtility::sysLog($logMessage, 'core', GeneralUtility::SYSLOG_SEVERITY_ERROR);
              */
             $logMessage = $e->getMessage() . ' (table: "' . $tableName . '", fieldName: "' . $fieldName . '", currentId: ' . $currentId . ')';
             GeneralUtility::sysLog($logMessage, 'core', GeneralUtility::SYSLOG_SEVERITY_ERROR);
-            return array();
+            return [];
         }
 
         $localizedId = null;
         }
 
         $localizedId = null;
@@ -1563,8 +1793,8 @@ class PageRepository
             $localizedId = $element['_PAGES_OVERLAY_UID'];
         }
 
             $localizedId = $element['_PAGES_OVERLAY_UID'];
         }
 
-        if (!empty($GLOBALS['TCA'][$tableName]['ctrl']['transForeignTable'])) {
-            $tableName = $GLOBALS['TCA'][$tableName]['ctrl']['transForeignTable'];
+        if ($tableName === 'pages') {
+            $tableName = 'pages_language_overlay';
         }
 
         $isTableLocalizable = (
         }
 
         $isTableLocalizable = (
@@ -1573,10 +1803,7 @@ class PageRepository
         );
         if ($isTableLocalizable && $localizedId !== null) {
             $localizedReferences = $fileRepository->findByRelation($tableName, $fieldName, $localizedId);
         );
         if ($isTableLocalizable && $localizedId !== null) {
             $localizedReferences = $fileRepository->findByRelation($tableName, $fieldName, $localizedId);
-            $localizedReferencesValue = $localizedReferences ?: '';
-            if ($this->shouldFieldBeOverlaid($tableName, $fieldName, $localizedReferencesValue)) {
-                $references = $localizedReferences;
-            }
+            $references = $localizedReferences;
         }
 
         return $references;
         }
 
         return $references;
@@ -1600,50 +1827,6 @@ class PageRepository
     }
 
     /**
     }
 
     /**
-     * Determine if a field needs an overlay
-     *
-     * @param string $table TCA tablename
-     * @param string $field TCA fieldname
-     * @param mixed $value Current value of the field
-     * @return bool Returns TRUE if a given record field needs to be overlaid
-     */
-    protected function shouldFieldBeOverlaid($table, $field, $value)
-    {
-        $l10n_mode = isset($GLOBALS['TCA'][$table]['columns'][$field]['l10n_mode'])
-            ? $GLOBALS['TCA'][$table]['columns'][$field]['l10n_mode']
-            : '';
-
-        $shouldFieldBeOverlaid = true;
-
-        if ($l10n_mode === 'exclude') {
-            $shouldFieldBeOverlaid = false;
-        } elseif ($l10n_mode === 'mergeIfNotBlank') {
-            $checkValue = $value;
-
-            // 0 values are considered blank when coming from a group field
-            if (empty($value) && $GLOBALS['TCA'][$table]['columns'][$field]['config']['type'] === 'group') {
-                $checkValue = '';
-            }
-
-            if ($checkValue === array() || !is_array($checkValue) && trim($checkValue) === '') {
-                $shouldFieldBeOverlaid = false;
-            }
-        }
-
-        return $shouldFieldBeOverlaid;
-    }
-
-    /**
-     * Returns the database connection
-     *
-     * @return \TYPO3\CMS\Core\Database\DatabaseConnection
-     */
-    protected function getDatabaseConnection()
-    {
-        return $GLOBALS['TYPO3_DB'];
-    }
-
-    /**
      * @return \TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController
      */
     protected function getTypoScriptFrontendController()
      * @return \TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController
      */
     protected function getTypoScriptFrontendController()