/** * Queries the database for the page record and returns it. * * @param integer $uid Page id * @throws \RuntimeException * @return array */ protected function getRecordArray($uid) { if (!isset(self::$pageRecordCache[$this->getCacheIdentifier($uid)])) { if (!is_array($GLOBALS['TCA']['pages']['columns'])) { if (isset($GLOBALS['TSFE'])) { $GLOBALS['TSFE']->includeTCA($GLOBALS['TSFE']->TCAloaded); } \TYPO3\CMS\Core\Utility\GeneralUtility::loadTCA('pages'); } $row = $GLOBALS['TYPO3_DB']->exec_SELECTgetSingleRow(implode(',', self::$rootlineFields), 'pages', 'uid = ' . intval($uid) . ' AND pages.deleted = 0 AND pages.doktype <> ' . \TYPO3\CMS\Frontend\Page\PageRepository::DOKTYPE_RECYCLER); if (empty($row)) { throw new \RuntimeException('Could not fetch page data for uid ' . $uid . '.', 1343589451); } $this->pageContext->versionOL('pages', $row, FALSE, TRUE); $this->pageContext->fixVersioningPid('pages', $row); if (is_array($row)) { $this->pageContext->getPageOverlay($row, $this->languageUid); $row = $this->enrichWithRelationFields($uid, $row); self::$pageRecordCache[$this->getCacheIdentifier($uid)] = $row; } } if (!is_array(self::$pageRecordCache[$this->getCacheIdentifier($uid)])) { throw new \RuntimeException('Broken rootline. Could not resolve page with uid ' . $uid . '.', 1343464101); } return self::$pageRecordCache[$this->getCacheIdentifier($uid)]; }
/** * Queries the database for the page record and returns it. * * @param int $uid Page id * @throws \RuntimeException * @return array */ protected function getRecordArray($uid) { $currentCacheIdentifier = $this->getCacheIdentifier($uid); if (!isset(self::$pageRecordCache[$currentCacheIdentifier])) { $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('pages'); $queryBuilder->getRestrictions()->removeAll()->add(GeneralUtility::makeInstance(DeletedRestriction::class)); $row = $queryBuilder->select(...self::$rootlineFields)->from('pages')->where($queryBuilder->expr()->eq('uid', $queryBuilder->createNamedParameter($uid, \PDO::PARAM_INT)), $queryBuilder->expr()->neq('doktype', $queryBuilder->createNamedParameter(PageRepository::DOKTYPE_RECYCLER, \PDO::PARAM_INT)))->execute()->fetch(); if (empty($row)) { throw new \RuntimeException('Could not fetch page data for uid ' . $uid . '.', 1343589451); } $this->pageContext->versionOL('pages', $row, false, true); $this->pageContext->fixVersioningPid('pages', $row); if (is_array($row)) { if ($this->languageUid > 0) { $row = $this->pageContext->getPageOverlay($row, $this->languageUid); } $row = $this->enrichWithRelationFields(isset($row['_PAGES_OVERLAY_UID']) ? $row['_PAGES_OVERLAY_UID'] : $uid, $row); self::$pageRecordCache[$currentCacheIdentifier] = $row; } } if (!is_array(self::$pageRecordCache[$currentCacheIdentifier])) { throw new \RuntimeException('Broken rootline. Could not resolve page with uid ' . $uid . '.', 1343464101); } return self::$pageRecordCache[$currentCacheIdentifier]; }
/** * Wrapper for \TYPO3\CMS\Frontend\Page\PageRepository::getPageOverlay() * * @param mixed $pageInput * @param integer $languageUid * @return array */ public function getPageOverlay($pageInput, $languageUid = -1) { $key = md5(serialize($pageInput) . $languageUid); if (FALSE === isset(self::$cachedOverlays[$key])) { self::$cachedOverlays[$key] = self::$pageSelect->getPageOverlay($pageInput, $languageUid); } return self::$cachedOverlays[$key]; }
/** * @test */ public function getPageOverlayByRowWithoutTranslation() { $orig = $this->pageRepo->getPage(4); $row = $this->pageRepo->getPageOverlay($orig, 1); $this->assertInternalType('array', $row); $this->assertEquals(4, $row['uid']); $this->assertEquals('Dummy 1-4', $row['title']); //original title }
/** * Remove page if not translated * * @param array $pages * @return array */ private function hidePagesIfNotTranslated($pages) { $language = GeneralUtility::_GET('L'); if (intval($language) !== 0 && intval($this->pluginConfig['1']['urlEntries.']['pages.']['hidePagesIfNotTranslated']) === 1) { foreach ($pages as $key => $page) { $pageOverlay = $this->pageRepository->getPageOverlay($page, $language); if (empty($pageOverlay['_PAGES_OVERLAY'])) { unset($pages[$key]); } } } return $pages; }
/** * Creates a path part of the URL. * * @return void */ protected function createPathComponentUsingRootline() { $mountPointParameter = ''; if (isset($this->urlParameters['MP'])) { $mountPointParameter = $this->urlParameters['MP']; unset($this->urlParameters['MP']); } $rootLineUtility = GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Utility\\RootlineUtility', $this->urlParameters['id'], $mountPointParameter, $this->pageRepository); /** @var \TYPO3\CMS\Core\Utility\RootlineUtility $rootLineUtility */ $rootLine = $rootLineUtility->get(); // Skip from the root of the tree to the first level of pages while (count($rootLine) !== 0) { $page = array_pop($rootLine); if ($page['uid'] == $this->rootPageId) { break; } } $enableLanguageOverlay = (int) $this->originalUrlParameters['L'] > 0; $components = array(); $reversedRootLine = array_reverse($rootLine); $rootLineMax = count($reversedRootLine) - 1; for ($current = 0; $current <= $rootLineMax; $current++) { $page = $reversedRootLine[$current]; // Skip if this page is excluded if ($page['tx_realurl_exclude'] && $current !== $rootLineMax) { continue; } if ($enableLanguageOverlay) { $overlay = $this->pageRepository->getPageOverlay($page, (int) $this->originalUrlParameters['L']); if (is_array($overlay)) { $page = $overlay; unset($overlay); } } foreach (self::$pageTitleFields as $field) { if (isset($page[$field]) && $page[$field] !== '') { $segment = $this->utility->convertToSafeString($page[$field], $this->separatorCharacter); if ($segment === '') { $segment = $this->emptySegmentValue; } $components[] = $segment; $this->appendToEncodedUrl($segment); continue 2; } } } if (count($components) > 0) { $this->addToPathCache(implode('/', $components)); } }
/** * Queries the database for the page record and returns it. * * @param int $uid Page id * @throws \RuntimeException * @return array */ protected function getRecordArray($uid) { $currentCacheIdentifier = $this->getCacheIdentifier($uid); if (!isset(self::$pageRecordCache[$currentCacheIdentifier])) { $row = $this->databaseConnection->exec_SELECTgetSingleRow(implode(',', self::$rootlineFields), 'pages', 'uid = ' . (int) $uid . ' AND pages.deleted = 0 AND pages.doktype <> ' . PageRepository::DOKTYPE_RECYCLER); if (empty($row)) { throw new \RuntimeException('Could not fetch page data for uid ' . $uid . '.', 1343589451); } $this->pageContext->versionOL('pages', $row, false, true); $this->pageContext->fixVersioningPid('pages', $row); if (is_array($row)) { if ($this->languageUid > 0) { $row = $this->pageContext->getPageOverlay($row, $this->languageUid); } $row = $this->enrichWithRelationFields(isset($row['_PAGES_OVERLAY_UID']) ? $row['_PAGES_OVERLAY_UID'] : $uid, $row); self::$pageRecordCache[$currentCacheIdentifier] = $row; } } if (!is_array(self::$pageRecordCache[$currentCacheIdentifier])) { throw new \RuntimeException('Broken rootline. Could not resolve page with uid ' . $uid . '.', 1343464101); } return self::$pageRecordCache[$currentCacheIdentifier]; }
/** * Creates a path part of the URL. * * @return void */ protected function createPathComponent() { $rooLineUtility = GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Utility\\RootlineUtility', $this->urlParameters['id']); $rootLine = $rooLineUtility->get(); array_pop($rootLine); if ((int) $this->originalUrlParameters['L'] > 0) { $enableLanguageOverlay = TRUE; $fieldList = self::$pageOverlayTitleFields; } else { $enableLanguageOverlay = FALSE; $fieldList = self::$pageTitleFields; } $components = array(); foreach (array_reverse($rootLine) as $page) { if ($enableLanguageOverlay) { $overlay = $this->pageRepository->getPageOverlay($page, (int) $this->originalUrlParameters['L']); if (is_array($overlay)) { $page = $overlay; unset($overlay); } } foreach ($fieldList as $field) { if ($page[$field]) { $segment = $this->utility->convertToSafeString($page[$field]); if ($segment === '') { $segment = $this->emptySegmentValue; } $components[] = $segment; $this->appendToEncodedUrl($segment); continue 2; } } } if (count($components) > 0) { $this->addToPathCache(implode('/', $components)); } }
/** * Creates the menu in the internal variables, ready for output. * Basically this will read the page records needed and fill in the internal $this->menuArr * Based on a hash of this array and some other variables the $this->result variable will be loaded either from cache OR by calling the generate() method of the class to create the menu for real. * * @return void * @todo Define visibility */ public function makeMenu() { if ($this->id) { $this->useCacheHash = FALSE; // Initializing showAccessRestrictedPages if ($this->mconf['showAccessRestrictedPages']) { // SAVING where_groupAccess $SAVED_where_groupAccess = $this->sys_page->where_groupAccess; // Temporarily removing fe_group checking! $this->sys_page->where_groupAccess = ''; } // Begin production of menu: $temp = array(); $altSortFieldValue = trim($this->mconf['alternativeSortingField']); $altSortField = $altSortFieldValue ?: 'sorting'; // ... only for the FIRST level of a HMENU if ($this->menuNumber == 1 && $this->conf['special']) { $value = isset($this->conf['special.']['value.']) ? $this->parent_cObj->stdWrap($this->conf['special.']['value'], $this->conf['special.']['value.']) : $this->conf['special.']['value']; switch ($this->conf['special']) { case 'userfunction': $temp = $this->parent_cObj->callUserFunction($this->conf['special.']['userFunc'], array_merge($this->conf['special.'], array('_altSortField' => $altSortField)), ''); if (!is_array($temp)) { $temp = array(); } break; case 'language': $temp = array(); // Getting current page record NOT overlaid by any translation: $currentPageWithNoOverlay = $this->sys_page->getRawRecord('pages', $GLOBALS['TSFE']->page['uid']); // Traverse languages set up: $languageItems = GeneralUtility::intExplode(',', $value); foreach ($languageItems as $sUid) { // Find overlay record: if ($sUid) { $lRecs = $this->sys_page->getPageOverlay($GLOBALS['TSFE']->page['uid'], $sUid); } else { $lRecs = array(); } // Checking if the "disabled" state should be set. if (GeneralUtility::hideIfNotTranslated($GLOBALS['TSFE']->page['l18n_cfg']) && $sUid && !count($lRecs) || $GLOBALS['TSFE']->page['l18n_cfg'] & 1 && (!$sUid || !count($lRecs)) || !$this->conf['special.']['normalWhenNoLanguage'] && $sUid && !count($lRecs)) { $iState = $GLOBALS['TSFE']->sys_language_uid == $sUid ? 'USERDEF2' : 'USERDEF1'; } else { $iState = $GLOBALS['TSFE']->sys_language_uid == $sUid ? 'ACT' : 'NO'; } if ($this->conf['addQueryString']) { $getVars = $this->parent_cObj->getQueryArguments($this->conf['addQueryString.'], array('L' => $sUid), TRUE); $this->analyzeCacheHashRequirements($getVars); } else { $getVars = '&L=' . $sUid; } // Adding menu item: $temp[] = array_merge(array_merge($currentPageWithNoOverlay, $lRecs), array('ITEM_STATE' => $iState, '_ADD_GETVARS' => $getVars, '_SAFE' => TRUE)); } break; case 'directory': if ($value == '') { $value = $GLOBALS['TSFE']->page['uid']; } $items = GeneralUtility::intExplode(',', $value); foreach ($items as $id) { $MP = $this->tmpl->getFromMPmap($id); // Checking if a page is a mount page and if so, change the ID and set the MP var properly. $mount_info = $this->sys_page->getMountPointInfo($id); if (is_array($mount_info)) { if ($mount_info['overlay']) { // Overlays should already have their full MPvars calculated: $MP = $this->tmpl->getFromMPmap($mount_info['mount_pid']); $MP = $MP ? $MP : $mount_info['MPvar']; } else { $MP = ($MP ? $MP . ',' : '') . $mount_info['MPvar']; } $id = $mount_info['mount_pid']; } // Get sub-pages: $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('uid', 'pages', 'pid=' . (int) $id . $this->sys_page->where_hid_del, '', $altSortField); while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) { $row = $this->sys_page->getPage($row['uid']); $GLOBALS['TSFE']->sys_page->versionOL('pages', $row, TRUE); if (!empty($row)) { // Keep mount point? $mount_info = $this->sys_page->getMountPointInfo($row['uid'], $row); // There is a valid mount point. if (is_array($mount_info) && $mount_info['overlay']) { // Using "getPage" is OK since we need the check for enableFields // AND for type 2 of mount pids we DO require a doktype < 200! $mp_row = $this->sys_page->getPage($mount_info['mount_pid']); if (count($mp_row)) { $row = $mp_row; $row['_MP_PARAM'] = $mount_info['MPvar']; } else { // If the mount point could not be fetched with respect // to enableFields, unset the row so it does not become a part of the menu! unset($row); } } // Add external MP params, then the row: if (!empty($row)) { if ($MP) { $row['_MP_PARAM'] = $MP . ($row['_MP_PARAM'] ? ',' . $row['_MP_PARAM'] : ''); } $temp[$row['uid']] = $row; } } } $GLOBALS['TYPO3_DB']->sql_free_result($res); } break; case 'list': if ($value == '') { $value = $this->id; } $skippedEnableFields = array(); if (!empty($this->mconf['showAccessRestrictedPages'])) { $skippedEnableFields = array('fe_group' => 1); } /** @var \TYPO3\CMS\Core\Database\RelationHandler $loadDB*/ $loadDB = GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Database\\RelationHandler'); $loadDB->setFetchAllFields(TRUE); $loadDB->start($value, 'pages'); $loadDB->additionalWhere['pages'] = $this->parent_cObj->enableFields('pages', FALSE, $skippedEnableFields); $loadDB->getFromDB(); foreach ($loadDB->itemArray as $val) { $MP = $this->tmpl->getFromMPmap($val['id']); // Keep mount point? $mount_info = $this->sys_page->getMountPointInfo($val['id']); // There is a valid mount point. if (is_array($mount_info) && $mount_info['overlay']) { // Using "getPage" is OK since we need the check for enableFields // AND for type 2 of mount pids we DO require a doktype < 200! $mp_row = $this->sys_page->getPage($mount_info['mount_pid']); if (count($mp_row)) { $row = $mp_row; $row['_MP_PARAM'] = $mount_info['MPvar']; // Overlays should already have their full MPvars calculated if ($mount_info['overlay']) { $MP = $this->tmpl->getFromMPmap($mount_info['mount_pid']); if ($MP) { unset($row['_MP_PARAM']); } } } else { // If the mount point could not be fetched with respect to // enableFields, unset the row so it does not become a part of the menu! unset($row); } } else { $row = $loadDB->results['pages'][$val['id']]; } //Add versioning overlay for current page (to respect workspaces) if (is_array($row)) { $this->sys_page->versionOL('pages', $row, TRUE); } // Add external MP params, then the row: if (is_array($row)) { if ($MP) { $row['_MP_PARAM'] = $MP . ($row['_MP_PARAM'] ? ',' . $row['_MP_PARAM'] : ''); } $temp[] = $this->sys_page->getPageOverlay($row); } } break; case 'updated': if ($value == '') { $value = $GLOBALS['TSFE']->page['uid']; } $items = GeneralUtility::intExplode(',', $value); if (MathUtility::canBeInterpretedAsInteger($this->conf['special.']['depth'])) { $depth = MathUtility::forceIntegerInRange($this->conf['special.']['depth'], 1, 20); } else { $depth = 20; } // Max number of items $limit = MathUtility::forceIntegerInRange($this->conf['special.']['limit'], 0, 100); $maxAge = (int) $this->parent_cObj->calc($this->conf['special.']['maxAge']); if (!$limit) { $limit = 10; } // *'auto', 'manual', 'tstamp' $mode = $this->conf['special.']['mode']; // Get id's $id_list_arr = array(); foreach ($items as $id) { $bA = MathUtility::forceIntegerInRange($this->conf['special.']['beginAtLevel'], 0, 100); $id_list_arr[] = $this->parent_cObj->getTreeList(-1 * $id, $depth - 1 + $bA, $bA - 1); } $id_list = implode(',', $id_list_arr); // Get sortField (mode) switch ($mode) { case 'starttime': $sortField = 'starttime'; break; case 'lastUpdated': case 'manual': $sortField = 'lastUpdated'; break; case 'tstamp': $sortField = 'tstamp'; break; case 'crdate': $sortField = 'crdate'; break; default: $sortField = 'SYS_LASTCHANGED'; } // Get $extraWhere = ($this->conf['includeNotInMenu'] ? '' : ' AND pages.nav_hide=0') . $this->getDoktypeExcludeWhere(); if ($this->conf['special.']['excludeNoSearchPages']) { $extraWhere .= ' AND pages.no_search=0'; } if ($maxAge > 0) { $extraWhere .= ' AND ' . $sortField . '>' . ($GLOBALS['SIM_ACCESS_TIME'] - $maxAge); } $res = $this->parent_cObj->exec_getQuery('pages', array('pidInList' => '0', 'uidInList' => $id_list, 'where' => $sortField . '>=0' . $extraWhere, 'orderBy' => $altSortFieldValue ? $altSortFieldValue : $sortField . ' desc', 'max' => $limit)); while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) { $GLOBALS['TSFE']->sys_page->versionOL('pages', $row, TRUE); if (is_array($row)) { $temp[$row['uid']] = $this->sys_page->getPageOverlay($row); } } break; case 'keywords': list($value) = GeneralUtility::intExplode(',', $value); if (!$value) { $value = $GLOBALS['TSFE']->page['uid']; } if ($this->conf['special.']['setKeywords'] || $this->conf['special.']['setKeywords.']) { $kw = isset($this->conf['special.']['setKeywords.']) ? $this->parent_cObj->stdWrap($this->conf['special.']['setKeywords'], $this->conf['special.']['setKeywords.']) : $this->conf['special.']['setKeywords']; } else { // The page record of the 'value'. $value_rec = $this->sys_page->getPage($value); $kfieldSrc = $this->conf['special.']['keywordsField.']['sourceField'] ? $this->conf['special.']['keywordsField.']['sourceField'] : 'keywords'; // keywords. $kw = trim($this->parent_cObj->keywords($value_rec[$kfieldSrc])); } // *'auto', 'manual', 'tstamp' $mode = $this->conf['special.']['mode']; switch ($mode) { case 'starttime': $sortField = 'starttime'; break; case 'lastUpdated': case 'manual': $sortField = 'lastUpdated'; break; case 'tstamp': $sortField = 'tstamp'; break; case 'crdate': $sortField = 'crdate'; break; default: $sortField = 'SYS_LASTCHANGED'; } // Depth, limit, extra where if (MathUtility::canBeInterpretedAsInteger($this->conf['special.']['depth'])) { $depth = MathUtility::forceIntegerInRange($this->conf['special.']['depth'], 0, 20); } else { $depth = 20; } // Max number of items $limit = MathUtility::forceIntegerInRange($this->conf['special.']['limit'], 0, 100); $extraWhere = ' AND pages.uid<>' . $value . ($this->conf['includeNotInMenu'] ? '' : ' AND pages.nav_hide=0') . $this->getDoktypeExcludeWhere(); if ($this->conf['special.']['excludeNoSearchPages']) { $extraWhere .= ' AND pages.no_search=0'; } // Start point $eLevel = $this->parent_cObj->getKey(isset($this->conf['special.']['entryLevel.']) ? $this->parent_cObj->stdWrap($this->conf['special.']['entryLevel'], $this->conf['special.']['entryLevel.']) : $this->conf['special.']['entryLevel'], $this->tmpl->rootLine); $startUid = (int) $this->tmpl->rootLine[$eLevel]['uid']; // Which field is for keywords $kfield = 'keywords'; if ($this->conf['special.']['keywordsField']) { list($kfield) = explode(' ', trim($this->conf['special.']['keywordsField'])); } // If there are keywords and the startuid is present. if ($kw && $startUid) { $bA = MathUtility::forceIntegerInRange($this->conf['special.']['beginAtLevel'], 0, 100); $id_list = $this->parent_cObj->getTreeList(-1 * $startUid, $depth - 1 + $bA, $bA - 1); $kwArr = explode(',', $kw); foreach ($kwArr as $word) { $word = trim($word); if ($word) { $keyWordsWhereArr[] = $kfield . ' LIKE \'%' . $GLOBALS['TYPO3_DB']->quoteStr($word, 'pages') . '%\''; } } $res = $this->parent_cObj->exec_getQuery('pages', array('pidInList' => '0', 'uidInList' => $id_list, 'where' => '(' . implode(' OR ', $keyWordsWhereArr) . ')' . $extraWhere, 'orderBy' => $altSortFieldValue ? $altSortFieldValue : $sortField . ' desc', 'max' => $limit)); while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) { $GLOBALS['TSFE']->sys_page->versionOL('pages', $row, TRUE); if (is_array($row)) { $temp[$row['uid']] = $this->sys_page->getPageOverlay($row); } } } break; case 'categories': /** @var \TYPO3\CMS\Frontend\ContentObject\Menu\CategoryMenuUtility $categoryMenuUtility */ $categoryMenuUtility = GeneralUtility::makeInstance('TYPO3\\CMS\\Frontend\\ContentObject\\Menu\\CategoryMenuUtility'); $temp = $categoryMenuUtility->collectPages($value, $this->conf['special.'], $this); break; case 'rootline': $range = isset($this->conf['special.']['range.']) ? $this->parent_cObj->stdWrap($this->conf['special.']['range'], $this->conf['special.']['range.']) : $this->conf['special.']['range']; $begin_end = explode('|', $range); $begin_end[0] = (int) $begin_end[0]; if (!MathUtility::canBeInterpretedAsInteger($begin_end[1])) { $begin_end[1] = -1; } $beginKey = $this->parent_cObj->getKey($begin_end[0], $this->tmpl->rootLine); $endKey = $this->parent_cObj->getKey($begin_end[1], $this->tmpl->rootLine); if ($endKey < $beginKey) { $endKey = $beginKey; } $rl_MParray = array(); foreach ($this->tmpl->rootLine as $k_rl => $v_rl) { // For overlaid mount points, set the variable right now: if ($v_rl['_MP_PARAM'] && $v_rl['_MOUNT_OL']) { $rl_MParray[] = $v_rl['_MP_PARAM']; } // Traverse rootline: if ($k_rl >= $beginKey && $k_rl <= $endKey) { $temp_key = $k_rl; $temp[$temp_key] = $this->sys_page->getPage($v_rl['uid']); if (count($temp[$temp_key])) { // If there are no specific target for the page, put the level specific target on. if (!$temp[$temp_key]['target']) { $temp[$temp_key]['target'] = $this->conf['special.']['targets.'][$k_rl]; $temp[$temp_key]['_MP_PARAM'] = implode(',', $rl_MParray); } } else { unset($temp[$temp_key]); } } // For normal mount points, set the variable for next level. if ($v_rl['_MP_PARAM'] && !$v_rl['_MOUNT_OL']) { $rl_MParray[] = $v_rl['_MP_PARAM']; } } // Reverse order of elements (e.g. "1,2,3,4" gets "4,3,2,1"): if (isset($this->conf['special.']['reverseOrder']) && $this->conf['special.']['reverseOrder']) { $temp = array_reverse($temp); $rl_MParray = array_reverse($rl_MParray); } break; case 'browse': list($value) = GeneralUtility::intExplode(',', $value); if (!$value) { $value = $GLOBALS['TSFE']->page['uid']; } // Will not work out of rootline if ($value != $this->tmpl->rootLine[0]['uid']) { $recArr = array(); // The page record of the 'value'. $value_rec = $this->sys_page->getPage($value); // 'up' page cannot be outside rootline if ($value_rec['pid']) { // The page record of 'up'. $recArr['up'] = $this->sys_page->getPage($value_rec['pid']); } // If the 'up' item was NOT level 0 in rootline... if ($recArr['up']['pid'] && $value_rec['pid'] != $this->tmpl->rootLine[0]['uid']) { // The page record of "index". $recArr['index'] = $this->sys_page->getPage($recArr['up']['pid']); } // prev / next is found $prevnext_menu = $this->removeInaccessiblePages($this->sys_page->getMenu($value_rec['pid'], '*', $altSortField)); $lastKey = 0; $nextActive = 0; foreach ($prevnext_menu as $k_b => $v_b) { if ($nextActive) { $recArr['next'] = $v_b; $nextActive = 0; } if ($v_b['uid'] == $value) { if ($lastKey) { $recArr['prev'] = $prevnext_menu[$lastKey]; } $nextActive = 1; } $lastKey = $k_b; } reset($prevnext_menu); $recArr['first'] = pos($prevnext_menu); end($prevnext_menu); $recArr['last'] = pos($prevnext_menu); // prevsection / nextsection is found // You can only do this, if there is a valid page two levels up! if (is_array($recArr['index'])) { $prevnextsection_menu = $this->removeInaccessiblePages($this->sys_page->getMenu($recArr['index']['uid'], '*', $altSortField)); $lastKey = 0; $nextActive = 0; foreach ($prevnextsection_menu as $k_b => $v_b) { if ($nextActive) { $sectionRec_temp = $this->removeInaccessiblePages($this->sys_page->getMenu($v_b['uid'], '*', $altSortField)); if (count($sectionRec_temp)) { reset($sectionRec_temp); $recArr['nextsection'] = pos($sectionRec_temp); end($sectionRec_temp); $recArr['nextsection_last'] = pos($sectionRec_temp); $nextActive = 0; } } if ($v_b['uid'] == $value_rec['pid']) { if ($lastKey) { $sectionRec_temp = $this->removeInaccessiblePages($this->sys_page->getMenu($prevnextsection_menu[$lastKey]['uid'], '*', $altSortField)); if (count($sectionRec_temp)) { reset($sectionRec_temp); $recArr['prevsection'] = pos($sectionRec_temp); end($sectionRec_temp); $recArr['prevsection_last'] = pos($sectionRec_temp); } } $nextActive = 1; } $lastKey = $k_b; } } if ($this->conf['special.']['items.']['prevnextToSection']) { if (!is_array($recArr['prev']) && is_array($recArr['prevsection_last'])) { $recArr['prev'] = $recArr['prevsection_last']; } if (!is_array($recArr['next']) && is_array($recArr['nextsection'])) { $recArr['next'] = $recArr['nextsection']; } } $items = explode('|', $this->conf['special.']['items']); $c = 0; foreach ($items as $k_b => $v_b) { $v_b = strtolower(trim($v_b)); if ((int) $this->conf['special.'][$v_b . '.']['uid']) { $recArr[$v_b] = $this->sys_page->getPage((int) $this->conf['special.'][$v_b . '.']['uid']); } if (is_array($recArr[$v_b])) { $temp[$c] = $recArr[$v_b]; if ($this->conf['special.'][$v_b . '.']['target']) { $temp[$c]['target'] = $this->conf['special.'][$v_b . '.']['target']; } $tmpSpecialFields = $this->conf['special.'][$v_b . '.']['fields.']; if (is_array($tmpSpecialFields)) { foreach ($tmpSpecialFields as $fk => $val) { $temp[$c][$fk] = $val; } } $c++; } } } break; } if ($this->mconf['sectionIndex']) { $sectionIndexes = array(); foreach ($temp as $page) { $sectionIndexes = $sectionIndexes + $this->sectionIndex($altSortField, $page['uid']); } $temp = $sectionIndexes; } } elseif (is_array($this->alternativeMenuTempArray)) { // Setting $temp array if not level 1. $temp = $this->alternativeMenuTempArray; } elseif ($this->mconf['sectionIndex']) { $temp = $this->sectionIndex($altSortField); } else { // Default: // gets the menu $temp = $this->sys_page->getMenu($this->id, '*', $altSortField); } $c = 0; $c_b = 0; $minItems = (int) ($this->mconf['minItems'] ?: $this->conf['minItems']); $maxItems = (int) ($this->mconf['maxItems'] ?: $this->conf['maxItems']); $begin = $this->parent_cObj->calc($this->mconf['begin'] ? $this->mconf['begin'] : $this->conf['begin']); $minItemsConf = isset($this->mconf['minItems.']) ? $this->mconf['minItems.'] : (isset($this->conf['minItems.']) ? $this->conf['minItems.'] : NULL); $minItems = is_array($minItemsConf) ? $this->parent_cObj->stdWrap($minItems, $minItemsConf) : $minItems; $maxItemsConf = isset($this->mconf['maxItems.']) ? $this->mconf['maxItems.'] : (isset($this->conf['maxItems.']) ? $this->conf['maxItems.'] : NULL); $maxItems = is_array($maxItemsConf) ? $this->parent_cObj->stdWrap($maxItems, $maxItemsConf) : $maxItems; $beginConf = isset($this->mconf['begin.']) ? $this->mconf['begin.'] : (isset($this->conf['begin.']) ? $this->conf['begin.'] : NULL); $begin = is_array($beginConf) ? $this->parent_cObj->stdWrap($begin, $beginConf) : $begin; $banUidArray = $this->getBannedUids(); // Fill in the menuArr with elements that should go into the menu: $this->menuArr = array(); foreach ($temp as $data) { $spacer = GeneralUtility::inList($this->spacerIDList, $data['doktype']) || $data['ITEM_STATE'] === 'SPC' ? 1 : 0; // if item is a spacer, $spacer is set if ($this->filterMenuPages($data, $banUidArray, $spacer)) { $c_b++; // If the beginning item has been reached. if ($begin <= $c_b) { $this->menuArr[$c] = $data; $this->menuArr[$c]['isSpacer'] = $spacer; $c++; if ($maxItems && $c >= $maxItems) { break; } } } } // Fill in fake items, if min-items is set. if ($minItems) { while ($c < $minItems) { $this->menuArr[$c] = array('title' => '...', 'uid' => $GLOBALS['TSFE']->id); $c++; } } // Passing the menuArr through a user defined function: if ($this->mconf['itemArrayProcFunc']) { if (!is_array($this->parentMenuArr)) { $this->parentMenuArr = array(); } $this->menuArr = $this->userProcess('itemArrayProcFunc', $this->menuArr); } // Setting number of menu items $GLOBALS['TSFE']->register['count_menuItems'] = count($this->menuArr); $this->hash = md5(serialize($this->menuArr) . serialize($this->mconf) . serialize($this->tmpl->rootLine) . serialize($this->MP_array)); // Get the cache timeout: if ($this->conf['cache_period']) { $cacheTimeout = $this->conf['cache_period']; } else { $cacheTimeout = $GLOBALS['TSFE']->get_cache_timeout(); } $cache = $this->getCache(); $cachedData = $cache->get($this->hash); if (!is_array($cachedData)) { $this->generate(); $cache->set($this->hash, $this->result, array('ident_MENUDATA'), (int) $cacheTimeout); } else { $this->result = $cachedData; } // End showAccessRestrictedPages if ($this->mconf['showAccessRestrictedPages']) { // RESTORING where_groupAccess $this->sys_page->where_groupAccess = $SAVED_where_groupAccess; } } }
/** * Fetches all menuitems if special = keywords is set * * @param string $specialValue The value from special.value * @param string $sortingField The sorting field * @return array */ protected function prepareMenuItemsForKeywordsMenu($specialValue, $sortingField) { $tsfe = $this->getTypoScriptFrontendController(); $menuItems = array(); list($specialValue) = GeneralUtility::intExplode(',', $specialValue); if (!$specialValue) { $specialValue = $tsfe->page['uid']; } if ($this->conf['special.']['setKeywords'] || $this->conf['special.']['setKeywords.']) { $kw = isset($this->conf['special.']['setKeywords.']) ? $this->parent_cObj->stdWrap($this->conf['special.']['setKeywords'], $this->conf['special.']['setKeywords.']) : $this->conf['special.']['setKeywords']; } else { // The page record of the 'value'. $value_rec = $this->sys_page->getPage($specialValue); $kfieldSrc = $this->conf['special.']['keywordsField.']['sourceField'] ? $this->conf['special.']['keywordsField.']['sourceField'] : 'keywords'; // keywords. $kw = trim($this->parent_cObj->keywords($value_rec[$kfieldSrc])); } // *'auto', 'manual', 'tstamp' $mode = $this->conf['special.']['mode']; switch ($mode) { case 'starttime': $sortField = 'starttime'; break; case 'lastUpdated': case 'manual': $sortField = 'lastUpdated'; break; case 'tstamp': $sortField = 'tstamp'; break; case 'crdate': $sortField = 'crdate'; break; default: $sortField = 'SYS_LASTCHANGED'; } // Depth, limit, extra where if (MathUtility::canBeInterpretedAsInteger($this->conf['special.']['depth'])) { $depth = MathUtility::forceIntegerInRange($this->conf['special.']['depth'], 0, 20); } else { $depth = 20; } // Max number of items $limit = MathUtility::forceIntegerInRange($this->conf['special.']['limit'], 0, 100); $extraWhere = ' AND pages.uid<>' . $specialValue . ($this->conf['includeNotInMenu'] ? '' : ' AND pages.nav_hide=0') . $this->getDoktypeExcludeWhere(); if ($this->conf['special.']['excludeNoSearchPages']) { $extraWhere .= ' AND pages.no_search=0'; } // Start point $eLevel = $this->parent_cObj->getKey(isset($this->conf['special.']['entryLevel.']) ? $this->parent_cObj->stdWrap($this->conf['special.']['entryLevel'], $this->conf['special.']['entryLevel.']) : $this->conf['special.']['entryLevel'], $this->tmpl->rootLine); $startUid = (int) $this->tmpl->rootLine[$eLevel]['uid']; // Which field is for keywords $kfield = 'keywords'; if ($this->conf['special.']['keywordsField']) { list($kfield) = explode(' ', trim($this->conf['special.']['keywordsField'])); } // If there are keywords and the startuid is present if ($kw && $startUid) { $bA = MathUtility::forceIntegerInRange($this->conf['special.']['beginAtLevel'], 0, 100); $id_list = $this->parent_cObj->getTreeList(-1 * $startUid, $depth - 1 + $bA, $bA - 1); $kwArr = explode(',', $kw); $keyWordsWhereArr = array(); foreach ($kwArr as $word) { $word = trim($word); if ($word) { $keyWordsWhereArr[] = $kfield . ' LIKE \'%' . $this->getDatabaseConnection()->quoteStr($word, 'pages') . '%\''; } } $where = empty($keyWordsWhereArr) ? '' : '(' . implode(' OR ', $keyWordsWhereArr) . ')'; $res = $this->parent_cObj->exec_getQuery('pages', array('pidInList' => '0', 'uidInList' => $id_list, 'where' => $where . $extraWhere, 'orderBy' => $sortingField ?: $sortField . ' desc', 'max' => $limit)); while ($row = $this->getDatabaseConnection()->sql_fetch_assoc($res)) { $tsfe->sys_page->versionOL('pages', $row, true); if (is_array($row)) { $menuItems[$row['uid']] = $this->sys_page->getPageOverlay($row); } } $this->getDatabaseConnection()->sql_free_result($res); } return $menuItems; }
/** * Checks whether a translated shortcut page has a different shortcut * target than the original language page. * If that is the case, things get corrected to follow that alternative * shortcut * * @return void * @author Ingo Renner <*****@*****.**> */ protected function checkTranslatedShortcut() { if (!is_null($this->originalShortcutPage)) { $originalShortcutPageOverlay = $this->sys_page->getPageOverlay($this->originalShortcutPage['uid'], $this->sys_language_uid); if (!empty($originalShortcutPageOverlay['shortcut']) && $originalShortcutPageOverlay['shortcut'] != $this->id) { // the translation of the original shortcut page has a different shortcut target! // set the correct page and id $shortcut = $this->getPageShortcut($originalShortcutPageOverlay['shortcut'], $originalShortcutPageOverlay['shortcut_mode'], $originalShortcutPageOverlay['uid']); $this->id = $this->contentPid = $shortcut['uid']; $this->page = $this->sys_page->getPage($this->id); // Fix various effects on things like menus f.e. $this->fetch_the_id(); $this->tmpl->rootLine = array_reverse($this->rootLine); } } }
/** * Creates a path part of the URL. * * @return void */ protected function createPathComponentUsingRootline() { $mountPointParameter = ''; if (isset($this->urlParameters['MP'])) { $mountPointParameter = $this->urlParameters['MP']; unset($this->urlParameters['MP']); } $rootLineUtility = GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Utility\\RootlineUtility', $this->urlParameters['id'], $mountPointParameter, $this->pageRepository); /** @var \TYPO3\CMS\Core\Utility\RootlineUtility $rootLineUtility */ $rootLine = $rootLineUtility->get(); // Skip from the root of the tree to the first level of pages while (count($rootLine) !== 0) { $page = array_pop($rootLine); if ($page['uid'] == $this->rootPageId) { break; } } $languageExceptionUids = (string) $this->configuration->get('pagePath/languageExceptionUids'); $enableLanguageOverlay = (int) $this->originalUrlParameters['L'] > 0 && (empty($languageExceptionUids) || !GeneralUtility::inList($languageExceptionUids, $this->sysLanguageUid)); $components = array(); $reversedRootLine = array_reverse($rootLine); $rootLineMax = count($reversedRootLine) - 1; for ($current = 0; $current <= $rootLineMax; $current++) { $page = $reversedRootLine[$current]; // Skip if this page is excluded if ($page['tx_realurl_exclude'] && $current !== $rootLineMax) { continue; } if ($enableLanguageOverlay) { $overlay = $this->pageRepository->getPageOverlay($page, (int) $this->originalUrlParameters['L']); if (is_array($overlay)) { $page = $overlay; unset($overlay); } } // if path override is set, use path segment also for all subpages to shorten the url and throw away all segments found so far if ($page['tx_realurl_pathoverride'] && $page['tx_realurl_pathsegment'] !== '') { $segment = trim($page['tx_realurl_pathsegment'], '/'); $segments = explode('/', $segment); array_walk($segments, function (&$segments, $key) { $segments[$key] = $this->utility->convertToSafeString($segments[$key], $this->separatorCharacter); }); // Technically we could do with `$components = $segments` but it fills better to have overriden string here $segment = implode('/', $segments); $components = array($segment); continue; } foreach (self::$pageTitleFields as $field) { if (isset($page[$field]) && $page[$field] !== '') { $segment = $this->utility->convertToSafeString($page[$field], $this->separatorCharacter); if ($segment === '') { $segment = $this->emptySegmentValue; } $components[] = $segment; continue 2; } } } if (count($components) > 0) { foreach ($components as $segment) { $this->appendToEncodedUrl($segment); } $this->addToPathCache(implode('/', $components)); } }