* @see tslib_fe::getPageAndRootline()
*/
function getRootLine($uid, $MP = '', $ignoreMPerrors = FALSE) {
- $cacheUid = $uid = intval($uid);
- $cacheIgnoreMPerrors = ($ignoreMPerrors ? 1 : 0);
-
- if (is_array($this->cache_getRootLine[$cacheUid][$this->sys_language_uid][$MP][$cacheIgnoreMPerrors])) {
- return $this->cache_getRootLine[$cacheUid][$this->sys_language_uid][$MP][$cacheIgnoreMPerrors];
- }
-
- // Initialize:
- $selFields = t3lib_div::uniqueList('pid,uid,t3ver_oid,t3ver_wsid,t3ver_state,title,alias,nav_title,media,layout,hidden,starttime,endtime,fe_group,extendToSubpages,doktype,TSconfig,storage_pid,is_siteroot,mount_pid,mount_pid_ol,fe_login_mode,backend_layout_next_level,' . $GLOBALS['TYPO3_CONF_VARS']['FE']['addRootLineFields']);
- $this->error_getRootLine = '';
- $this->error_getRootLine_failPid = 0;
-
- // Splitting the $MP parameters if present
- $MPA = array();
- if ($MP) {
- $MPA = explode(',', $MP);
- foreach ($MPA as $MPAk => $v) {
- $MPA[$MPAk] = explode('-', $MPA[$MPAk]);
- }
- }
-
- $loopCheck = 0;
- $theRowArray = array();
-
- // Max 99 levels in the page tree.
- while ($uid != 0 && $loopCheck < 99) {
- $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery($selFields, 'pages', 'uid=' . intval($uid) . ' AND pages.deleted=0 AND pages.doktype<>255');
- $row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res);
- $GLOBALS['TYPO3_DB']->sql_free_result($res);
- if ($row) {
- $this->versionOL('pages', $row, FALSE, TRUE);
- $this->fixVersioningPid('pages', $row);
-
- if (is_array($row)) {
- // Mount Point page types are allowed ONLY a) if they are the outermost record in rootline and b) if the overlay flag is not set:
- if ($GLOBALS['TYPO3_CONF_VARS']['FE']['enable_mount_pids'] && $row['doktype'] == self::DOKTYPE_MOUNTPOINT && !$ignoreMPerrors) {
- $mount_info = $this->getMountPointInfo($row['uid'], $row);
- if ($loopCheck > 0 || $mount_info['overlay']) {
- $this->error_getRootLine = 'Illegal Mount Point found in rootline';
- return array();
- }
- }
-
- // Next uid
- $uid = $row['pid'];
-
- if (count($MPA) && $GLOBALS['TYPO3_CONF_VARS']['FE']['enable_mount_pids']) {
- $curMP = end($MPA);
- if (!strcmp($row['uid'], $curMP[0])) {
-
- array_pop($MPA);
- $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery($selFields, 'pages', 'uid=' . intval($curMP[1]) . ' AND pages.deleted=0 AND pages.doktype<>255');
- $mp_row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res);
- $GLOBALS['TYPO3_DB']->sql_free_result($res);
-
- $this->versionOL('pages', $mp_row, FALSE, TRUE);
- $this->fixVersioningPid('pages', $mp_row);
-
- if (is_array($mp_row)) {
- $mount_info = $this->getMountPointInfo($mp_row['uid'], $mp_row);
- if (is_array($mount_info) && $mount_info['mount_pid'] == $curMP[0]) {
- // Setting next uid
- $uid = $mp_row['pid'];
-
- // Symlink style: Keep mount point (current row).
- if ($mount_info['overlay']) {
- // Set overlay mode:
- $row['_MOUNT_OL'] = TRUE;
- $row['_MOUNT_PAGE'] = array(
- 'uid' => $mp_row['uid'],
- 'pid' => $mp_row['pid'],
- 'title' => $mp_row['title'],
- );
- } else { // Normal operation: Insert the mount page row in rootline instead mount point.
- if ($loopCheck > 0) {
- $row = $mp_row;
- } else {
- $this->error_getRootLine = 'Current Page Id is a mounted page of the overlay type and cannot be accessed directly!';
- // Matching the page id (first run, $loopCheck = 0) with the MPvar is ONLY allowed if the mount point is the "overlay" type (otherwise it could be forged!)
- return array();
- }
- }
-
- $row['_MOUNTED_FROM'] = $curMP[0];
- $row['_MP_PARAM'] = $mount_info['MPvar'];
- } else {
- $this->error_getRootLine = 'MP var was corrupted';
- // The MP variables did NOT connect proper mount points:
- return array();
- }
- } else {
- $this->error_getRootLine = 'No moint point record found according to PID in MP var';
- // The second PID in MP var was NOT a valid page.
- return array();
- }
- }
- }
+ $rootline = t3lib_div::makeInstance('t3lib_rootline', $uid, $MP, $this);
+ if ($ignoreMPerrors) {
+ try {
+ return $rootline->get();
+ } catch (Exception $e) {
+ $this->error_getRootLine = $e->getMessage();
+ if (substr($e->getMessage(), -7) == 'uid -1.') {
+ $this->error_getRootLine_failPid = -1;
}
- // Add row to rootline with language overlaid:
- $theRowArray[] = $this->getPageOverlay($row);
- } else {
- $this->error_getRootLine = 'Broken rootline (failed on page with uid ' . $uid . ')';
- $this->error_getRootLine_failPid = $uid;
- // Broken rootline.
return array();
}
-
- $loopCheck++;
- }
-
- // If the MPA array is NOT empty, we have to return an error; All MP elements were not resolved!
- if (count($MPA)) {
- $this->error_getRootLine = 'MP value remain!';
- return array();
- }
-
- // Create output array (with reversed order of numeric keys):
- $output = Array();
- $c = count($theRowArray);
- foreach ($theRowArray as $key => $val) {
- $c--;
- $output[$c] = $val;
+ } else {
+ return $rootline->get();
}
-
- // Note: rootline errors are not cached
- $this->cache_getRootLine[$cacheUid][$this->sys_language_uid][$MP][$cacheIgnoreMPerrors] = $output;
- return $output;
}
/**
--- /dev/null
+<?php
+/***************************************************************
+ * Copyright notice
+ *
+ * (c) 2012 Steffen Ritter <steffen.ritter@typo3.org>
+ * All rights reserved
+ *
+ * This script is part of the TYPO3 project. The TYPO3 project is
+ * free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * The GNU General Public License can be found at
+ * http://www.gnu.org/copyleft/gpl.html.
+ *
+ * This script is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+/**
+ * A utility resolving and Caching the Rootline generation
+ *
+ * @author Steffen Ritter <steffen.ritter@typo3.org>
+ *
+ * @package TYPO3
+ * @subpackage t3lib
+ */
+class t3lib_rootline {
+
+ /**
+ * @var integer
+ */
+ protected $pageUid;
+
+ /**
+ * @var string
+ */
+ protected $mountPointParameter;
+
+ /**
+ * @var array
+ */
+ protected $parsedMountPointParameters = array();
+
+ /**
+ * @var integer
+ */
+ protected $languageUid = 0;
+
+ /**
+ * @var integer
+ */
+ protected $workspaceUid = 0;
+
+ /**
+ * @var boolean
+ */
+ protected $versionPreview = FALSE;
+
+ /**
+ * @var t3lib_cache_frontend_Frontend
+ */
+ protected static $cache = NULL;
+
+ /**
+ * @var array
+ */
+ protected static $localCache = array();
+
+ /**
+ * Fields to fetch when populating rootline data
+ *
+ * @var array
+ */
+ protected static $rootlineFields = array(
+ 'pid',
+ 'uid',
+ 't3ver_oid',
+ 't3ver_wsid',
+ 't3ver_state',
+ 'title',
+ 'alias',
+ 'nav_title',
+ 'media',
+ 'layout',
+ 'hidden',
+ 'starttime',
+ 'endtime',
+ 'fe_group',
+ 'extendToSubpages',
+ 'doktype',
+ 'TSconfig',
+ 'storage_pid',
+ 'is_siteroot',
+ 'mount_pid',
+ 'mount_pid_ol',
+ 'fe_login_mode',
+ 'backend_layout_next_level'
+ );
+
+ /**
+ * Rootline Context
+ *
+ * @var t3lib_pageSelect
+ */
+ protected $pageContext;
+
+ /**
+ * @var array
+ */
+ protected static $pageRecordCache = array();
+
+ /**
+ * @param int $uid
+ * @param string $mountPointParameter
+ * @param t3lib_pageSelect $context
+ * @throws RuntimeException
+ */
+ public function __construct($uid, $mountPointParameter = '', t3lib_pageSelect $context = NULL) {
+ $this->pageUid = intval($uid);
+ $this->mountPointParameter = trim($mountPointParameter);
+
+ if ($context === NULL) {
+ if ($GLOBALS['TSFE']->sys_page !== NULL) {
+ $this->pageContext = $GLOBALS['TSFE']->sys_page;
+ } else {
+ $this->pageContext = t3lib_div::makeInstance('t3lib_pageSelect');
+ }
+ } else {
+ $this->pageContext = $context;
+ }
+ $this->initializeObject();
+ }
+
+ /**
+ * Initialize a state to work with
+ *
+ * @throws RuntimeException
+ * @return void
+ */
+ protected function initializeObject() {
+
+ $this->languageUid = intval($this->pageContext->sys_language_uid);
+ $this->workspaceUid = intval($this->pageContext->versioningWorkspaceId);
+ $this->versionPreview = $this->pageContext->versioningPreview;
+
+ if ($this->mountPointParameter !== '') {
+ if (!$GLOBALS['TYPO3_CONF_VARS']['FE']['enable_mount_pids']) {
+ throw new RuntimeException('Mount-Point Pages are disabled for this installation. Cannot resolve a Rootline for a page with Mount-Points', 1343462896);
+ } else {
+ $this->parseMountPointParameter();
+ }
+ }
+
+ if (self::$cache === NULL) {
+ self::$cache = $GLOBALS['typo3CacheManager']->getCache('cache_rootline');
+ }
+
+ self::$rootlineFields = array_merge(
+ self::$rootlineFields,
+ t3lib_div::trimExplode(',', $GLOBALS['TYPO3_CONF_VARS']['FE']['addRootLineFields'], TRUE)
+ );
+ array_unique(self::$rootlineFields);
+ }
+
+ /**
+ * Constructs the cache Identifier
+ *
+ * @param integer $otherUid
+ * @return string
+ */
+ public function getCacheIdentifier($otherUid = NULL) {
+ return implode('_', array(
+ $otherUid !== NULL ? intval($otherUid) : $this->pageUid,
+ $this->mountPointParameter,
+ $this->languageUid,
+ $this->workspaceUid,
+ $this->versionPreview ? 1 : 0
+ ));
+ }
+
+ /**
+ * Returns the actual rootline
+ * @return array
+ */
+ public function get() {
+ $cacheIdentifier = $this->getCacheIdentifier();
+ if (!isset(self::$localCache[$cacheIdentifier])) {
+ if (!self::$cache->has($cacheIdentifier)) {
+ $this->generateRootlineCache();
+ } else {
+ self::$localCache[$cacheIdentifier] = self::$cache->get($cacheIdentifier);
+ }
+ }
+ return self::$localCache[$cacheIdentifier];
+ }
+
+ /**
+ * 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);
+ }
+ t3lib_div::loadTCA('pages');
+ }
+
+ $row = $GLOBALS['TYPO3_DB']->exec_SELECTgetSingleRow(
+ implode(',', self::$rootlineFields),
+ 'pages',
+ 'uid = ' . intval($uid) . ' AND pages.deleted = 0 AND pages.doktype <> ' . t3lib_pageSelect::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)) {
+ $row = $this->enrichWithRelationFields($uid, $row);
+ $this->pageContext->getPageOverlay($row, $this->languageUid);
+ 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)];
+ }
+
+ /**
+ * Resolve relations as defined in TCA and add them to the provided $pageRecord array.
+ *
+ * @param integer $uid Page id
+ * @param array $pageRecord Array with page data to add relation data to.
+ * @throws RuntimeException
+ * @return array $pageRecord with additional relations
+ */
+ protected function enrichWithRelationFields($uid, array $pageRecord) {
+ foreach ($GLOBALS['TCA']['pages']['columns'] as $column => $configuration) {
+ if ($this->columnHasRelationToResolve($configuration)) {
+ $configuration = $configuration['config'];
+ if ($configuration['MM']) {
+ /** @var $loadDBGroup t3lib_loadDBGroup */
+ $loadDBGroup = t3lib_div::makeInstance('t3lib_loadDBGroup');
+ $loadDBGroup->start(
+ $pageRecord[$column],
+ $configuration['foreign_table'],
+ $configuration['MM'],
+ $uid,
+ 'pages',
+ $configuration
+ );
+ $relatedUids = $loadDBGroup->tableArray[$configuration['foreign_table']];
+ } elseif ($configuration['foreign_field']) {
+ $table = $configuration['foreign_table'];
+ $field = $configuration['foreign_field'];
+ $whereClauseParts = array('`' . $field . '` = ' . intval($uid));
+ if (isset($configuration['foreign_match_fields']) && is_array($configuration['foreign_match_fields'])) {
+ foreach ($configuration['foreign_match_fields'] as $field => $value) {
+ $whereClauseParts[] = '`' . $field . '` = ' . $GLOBALS['TYPO3_DB']->fullQuoteStr($value);
+ }
+
+ }
+ if (isset($configuration['foreign_table_field'])) {
+ $whereClauseParts[] = '`' . trim($configuration['foreign_table_field']) . '` = \'pages\'';
+ }
+ $whereClause = implode(' AND ', $whereClauseParts);
+ $rows = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows('uid', $table, $whereClause);
+ if (!is_array($rows)) {
+ throw new RuntimeException('Could to resolve related records for page ' . $uid . ' and foreign_table ' . htmlspecialchars($configuration['foreign_table']), 1343589452);
+ }
+ $relatedUids = array();
+ foreach ($rows as $row) {
+ $relatedUids[] = $row['uid'];
+ }
+ }
+
+ $pageRecord[$column] = implode(',', $relatedUids);
+ }
+ }
+ return $pageRecord;
+ }
+
+ /**
+ * Checks whether the TCA Configuration array of a column
+ * describes a relation which is not stored as CSV in the record
+ *
+ * @param array $configuration TCA configuration to check
+ * @return boolean TRUE, if it describes a non-CSV relation
+ */
+ protected function columnHasRelationToResolve(array $configuration) {
+ $configuration = $configuration['config'];
+ if (isset($configuration['MM']) && isset($configuration['type']) && in_array($configuration['type'], array('select', 'inline', 'group'))) {
+ return TRUE;
+ }
+ if (isset($configuration['foreign_field']) && isset($configuration['type']) && in_array($configuration['type'], array('select', 'inline'))) {
+ return TRUE;
+ }
+ return FALSE;
+ }
+
+ /**
+ * Actual function to generate the rootline and cache it
+ *
+ * @throws RuntimeException
+ * @return void
+ */
+ protected function generateRootlineCache() {
+ $page = $this->getRecordArray($this->pageUid);
+
+ // If the current page is a mounted (according to the MP parameter) handle the mount-point
+ if ($this->isMountedPage()) {
+ $mountPoint = $this->getRecordArray($this->parsedMountPointParameters[$this->pageUid]);
+
+ $page = $this->processMountedPage($page, $mountPoint);
+ $parentUid = $mountPoint['pid'];
+ // Anyhow after reaching the mount-point, we have to go up that rootline
+ unset($this->parsedMountPointParameters[$this->pageUid]);
+ } else {
+ $parentUid = $page['pid'];
+ }
+
+ $cacheTags = array('pageId_' . $page['uid']);
+
+ if ($parentUid > 0) {
+ // Get rootline of (and including) parent page
+ $mountPointParameter = count($this->parsedMountPointParameters) > 0 ? $this->mountPointParameter : '';
+ /** @var $rootline t3lib_rootline */
+ $rootline = t3lib_div::makeInstance('t3lib_rootline', $parentUid, $mountPointParameter, $this->pageContext);
+ $rootline = $rootline->get();
+
+ // retrieve cache tags of parent rootline
+ foreach ($rootline as $entry) {
+ $cacheTags[] = 'pageId_' . $entry['uid'];
+ if ($entry['uid'] == $this->pageUid) {
+ throw new RuntimeException('Circular connection in rootline for page with uid ' . $this->pageUid . ' found. Check your mountpoint configuration.', 1343464103);
+ }
+ }
+ } else {
+ $rootline = array();
+ }
+
+ array_push($rootline, $page);
+
+ krsort($rootline);
+ self::$cache->set(
+ $this->getCacheIdentifier(),
+ $rootline,
+ $cacheTags
+ );
+ self::$localCache[$this->getCacheIdentifier()] = $rootline;
+ }
+
+ /**
+ * Checks whether the current Page is a Mounted Page
+ * (according to the MP-URL-Parameter)
+ *
+ * @return boolean
+ */
+ protected function isMountedPage() {
+ return in_array($this->pageUid, array_keys($this->parsedMountPointParameters));
+ }
+
+ /**
+ * Enhances with mount point information or replaces the node if needed
+ *
+ * @param array $mountedPageData page record array of mounted page
+ * @param array $mountPointPageData page record array of mount point page
+ * @throws RuntimeException
+ * @return array
+ */
+ protected function processMountedPage(array $mountedPageData, array $mountPointPageData) {
+ if ($mountPointPageData['mount_pid'] != $mountedPageData['uid']) {
+ throw new RuntimeException(
+ 'Broken rootline. Mountpoint parameter does not match the actual rootline. mount_pid (' . $mountPointPageData['mount_pid'] . ') does not match page uid (' . $mountedPageData['uid'] . ').',
+ 1343464100);
+ }
+
+ // Current page replaces the original mount-page
+ if ($mountPointPageData['mount_pid_ol']) {
+ $mountedPageData['_MOUNT_OL'] = TRUE;
+ $mountedPageData['_MOUNT_PAGE'] = array(
+ 'uid' => $mountPointPageData['uid'],
+ 'pid' => $mountPointPageData['pid'],
+ 'title' => $mountPointPageData['title']
+ );
+ } else {
+ // The mount-page is not replaced, the mount-page itself has to be used
+ $mountedPageData = $mountPointPageData;
+ }
+
+ $mountedPageData['_MOUNTED_FROM'] = $this->pageUid;
+ $mountedPageData['_MP_PARAM'] = $this->pageUid . '-' . $mountPointPageData['uid'];
+ return $mountedPageData;
+ }
+
+ /**
+ * Parse the MountPoint Parameters
+ * Splits the MP-Param via "," for several nested mountpoints
+ * and afterwords registers the mountpoint configurations
+ *
+ * @return void
+ */
+ protected function parseMountPointParameter() {
+ $mountPoints = t3lib_div::trimExplode(',', $this->mountPointParameter);
+
+ foreach ($mountPoints as $mP) {
+ list($mountedPageUid, $mountPageUid) = t3lib_div::intExplode('-', $mP);
+ $this->parsedMountPointParameters[$mountedPageUid] = $mountPageUid;
+ }
+ }
+
+}
+
+?>
\ No newline at end of file
// Delete cache for selected pages:
if (is_array($list_cache)) {
- $pageCache = $GLOBALS['typo3CacheManager']->getCache('cache_pages');
- $pageSectionCache = $GLOBALS['typo3CacheManager']->getCache('cache_pagesection');
$pageIds = $GLOBALS['TYPO3_DB']->cleanIntArray($list_cache);
foreach ($pageIds as $pageId) {
- $pageCache->flushByTag('pageId_' . $pageId);
- $pageSectionCache->flushByTag('pageId_' . $pageId);
+ $GLOBALS['typo3CacheManager']->flushCachesByTag('pageId_' . $pageId);
}
}
}
't3lib_recordlist' => PATH_t3lib . 'class.t3lib_recordlist.php',
't3lib_refindex' => PATH_t3lib . 'class.t3lib_refindex.php',
't3lib_registry' => PATH_t3lib . 'class.t3lib_registry.php',
+ 't3lib_rootline' => PATH_t3lib . 'class.t3lib_rootline.php',
't3lib_rteapi' => PATH_t3lib . 'class.t3lib_rteapi.php',
't3lib_scbase' => PATH_t3lib . 'class.t3lib_scbase.php',
't3lib_search_livesearch' => PATH_t3lib . 'search/class.t3lib_search_livesearch.php',
$tslibClasses = require(PATH_typo3 . 'sysext/cms/ext_autoload.php');
return array_merge($t3libClasses, $typo3Classes, $tslibClasses);
-?>
\ No newline at end of file
+?>
'backend' => 't3lib_cache_backend_TransientMemoryBackend',
'options' => array(),
),
+ 'cache_rootline' => array(
+ 'frontend' => 't3lib_cache_frontend_VariableFrontend',
+ 'backend' => 't3lib_cache_backend_DbBackend',
+ 'options' => array(),
+ )
),
),
'displayErrors' => -1, // <p>Integer (-1, 0, 1, 2). Configures whether PHP errors should be displayed.</p><dl><dt>0</dt><dd>Do not display any PHP error messages. Overrides the value of "exceptionalErrors" and sets it to 0 (= no errors are turned into exceptions), the configured "productionExceptionHandler" is used as exception handler</dd><dt>1</dt><dd>Display error messages with the registered errorhandler. The configured "debugExceptionHandler" is used as exception handler</dd><dt>2</dt><dd>Display errors only if client matches <a href="#SYS-devIPmask">[SYS][devIPmask]</a>. If devIPmask matches the users IP address the configured "debugExceptionHandler" is used for exceptions, if not "productionExceptionHandler" will be used</dd><dt>-1</dt><dd>Default setting. With this option, you can override the PHP setting "display_errors". If devIPmask matches the users IP address the configured "debugExceptionHandler" is used for exceptions, if not "productionExceptionHandler" will be used.</dd></dl>
--- /dev/null
+<?php
+/***************************************************************
+ * Copyright notice
+ *
+ * (c) 2012 Steffen Ritter <steffen.ritter@typo3.org>
+ * All rights reserved
+ *
+ * This script is part of the TYPO3 project. The TYPO3 project is
+ * free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * The GNU General Public License can be found at
+ * http://www.gnu.org/copyleft/gpl.html.
+ *
+ * This script is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+require_once(__DIR__ . '/fixtures/AccessibleRootline.php');
+/**
+ * Testcase for class t3lib_rootline
+ *
+ * @author Steffen Ritter <steffen.ritter@typo3.org>
+ *
+ * @package TYPO3
+ * @subpackage t3lib
+ */
+class t3lib_rootlineTest extends tx_phpunit_testcase {
+
+ /***
+ *
+ * UTILITY FUNCTIONS
+ *
+ */
+
+
+ /**
+ * Tests that $subsetCandidate is completely part of $superset
+ * and keys match.
+ *
+ * @see (A ^ B) = A <=> A c B
+ *
+ * @param array $subsetCandidate
+ * @param array $superset
+ */
+ protected function assertIsSubset(array $subsetCandidate, array $superset) {
+ $this->assertSame(
+ $subsetCandidate,
+ array_intersect_assoc($subsetCandidate, $superset)
+ );
+ }
+
+
+
+
+ /***
+ *
+ * >TEST CASES
+ *
+ */
+
+ /**
+ * @test
+ */
+ public function isMountedPageWithoutMountPointsReturnsFalse() {
+ $fixture = new Tests_unit_t3lib_AccessibleRootline(1);
+
+ $this->assertFalse(
+ $fixture->isMountedPage()
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function isMountedPageWithMatchingMountPointParameterReturnsTrue() {
+ $fixture = new Tests_unit_t3lib_AccessibleRootline(1, '1-99');
+
+ $this->assertTrue(
+ $fixture->isMountedPage()
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function isMountedPageWithNonMatchingMountPointParameterReturnsFalse() {
+ $fixture = new Tests_unit_t3lib_AccessibleRootline(1, '99-99');
+
+ $this->assertFalse(
+ $fixture->isMountedPage()
+ );
+ }
+
+ /**
+ * @test
+ * @expectedException RuntimeException
+ */
+ public function processMountedPageWithNonMountedPageThrowsException() {
+ $fixture = new Tests_unit_t3lib_AccessibleRootline(1, '1-99');
+ $fixture->processMountedPage(
+ array('uid' => 1),
+ array('uid' => 99, 'doktype' => t3lib_pageSelect::DOKTYPE_DEFAULT)
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function processMountedPageWithMountedPageNotThrowsException() {
+ $fixture = new Tests_unit_t3lib_AccessibleRootline(1, '1-99');
+ $fixture->processMountedPage(
+ array('uid' => 1),
+ array('uid' => 99, 'doktype' => t3lib_pageSelect::DOKTYPE_MOUNTPOINT, 'mount_pid' => 1)
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function processMountedPageWithMountedPageAddsMountedFromParameter() {
+ $fixture = new Tests_unit_t3lib_AccessibleRootline(1, '1-99');
+ $result = $fixture->processMountedPage(
+ array('uid' => 1),
+ array('uid' => 99, 'doktype' => t3lib_pageSelect::DOKTYPE_MOUNTPOINT, 'mount_pid' => 1)
+ );
+
+ $this->assertTrue(isset($result['_MOUNTED_FROM']));
+ $this->assertSame(1, $result['_MOUNTED_FROM']);
+ }
+
+ /**
+ * @test
+ */
+ public function processMountedPageWithMountedPageAddsMountPointParameterToReturnValue() {
+ $fixture = new Tests_unit_t3lib_AccessibleRootline(1, '1-99');
+ $result = $fixture->processMountedPage(
+ array('uid' => 1),
+ array('uid' => 99, 'doktype' => t3lib_pageSelect::DOKTYPE_MOUNTPOINT, 'mount_pid' => 1)
+ );
+
+ $this->assertTrue(isset($result['_MP_PARAM']));
+ $this->assertSame(
+ '1-99',
+ $result['_MP_PARAM']
+ );
+ }
+
+
+
+ /**
+ * @test
+ */
+ public function processMountedPageForMountPageIsOverlayAddsMountOLParameter() {
+ $fixture = new Tests_unit_t3lib_AccessibleRootline(1, '1-99');
+ $result = $fixture->processMountedPage(
+ array('uid' => 1),
+ array('uid' => 99, 'doktype' => t3lib_pageSelect::DOKTYPE_MOUNTPOINT, 'mount_pid' => 1, 'mount_pid_ol' => 1)
+ );
+
+ $this->assertTrue(isset($result['_MOUNT_OL']));
+ $this->assertSame(TRUE, $result['_MOUNT_OL']);
+ }
+
+ /**
+ * @test
+ */
+ public function processMountedPageForMountPageIsOverlayAddsDataInformationAboutMountPage() {
+ $fixture = new Tests_unit_t3lib_AccessibleRootline(1, '1-99');
+ $result = $fixture->processMountedPage(
+ array('uid' => 1),
+ array('uid' => 99, 'doktype' => t3lib_pageSelect::DOKTYPE_MOUNTPOINT, 'mount_pid' => 1, 'mount_pid_ol' => 1, 'pid' => 5, 'title' => 'TestCase')
+ );
+
+ $this->assertTrue(isset($result['_MOUNT_PAGE']));
+ $this->assertSame(
+ array('uid' => 99, 'pid' => 5, 'title' => 'TestCase'),
+ $result['_MOUNT_PAGE']
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function processMountedPageForMountPageWithoutOverlayReplacesMountedPageWithMountPage() {
+ $a = array('uid' => 99, 'doktype' => t3lib_pageSelect::DOKTYPE_MOUNTPOINT, 'mount_pid' => 1, 'mount_pid_ol' => 0);
+ $fixture = new Tests_unit_t3lib_AccessibleRootline(1, '1-99');
+ $result = $fixture->processMountedPage(
+ array('uid' => 1),
+ $a
+ );
+
+ $this->assertIsSubset($a, $result);
+ }
+
+ /**
+ * @test
+ */
+ public function columnHasRelationToResolveDetectsGroupFieldAsLocal() {
+ $fixture = new Tests_unit_t3lib_AccessibleRootline(1);
+ $this->assertFalse($fixture->columnHasRelationToResolve(array(
+ 'type' => 'group'
+ )));
+ }
+
+ /**
+ * @test
+ */
+ public function columnHasRelationToResolveDetectsGroupFieldWithMMAsRemote() {
+ $fixture = new Tests_unit_t3lib_AccessibleRootline(1);
+ $this->assertTrue($fixture->columnHasRelationToResolve(array('config' => array(
+ 'type' => 'group',
+ 'MM' => 'tx_xyz'
+ ))));
+ }
+
+ /**
+ * @test
+ */
+ public function columnHasRelationToResolveDetectsInlineFieldAsLocal() {
+ $fixture = new Tests_unit_t3lib_AccessibleRootline(1);
+ $this->assertFalse($fixture->columnHasRelationToResolve(array('config' => array(
+ 'type' => 'inline'
+ ))));
+ }
+
+ /**
+ * @test
+ */
+ public function columnHasRelationToResolveDetectsInlineFieldWithForeignKeyAsRemote() {
+ $fixture = new Tests_unit_t3lib_AccessibleRootline(1);
+ $this->assertTrue($fixture->columnHasRelationToResolve(array('config' => array(
+ 'type' => 'inline',
+ 'foreign_field' => 'xyz'
+ ))));
+ }
+
+ /**
+ * @test
+ */
+ public function columnHasRelationToResolveDetectsInlineFieldWithFMMAsRemote() {
+ $fixture = new Tests_unit_t3lib_AccessibleRootline(1);
+ $this->assertTrue($fixture->columnHasRelationToResolve(array('config' => array(
+ 'type' => 'inline',
+ 'MM' => 'xyz'
+ ))));
+ }
+
+ /**
+ * @test
+ */
+ public function columnHasRelationToResolveDetectsSelectFieldAsLocal() {
+ $fixture = new Tests_unit_t3lib_AccessibleRootline(1);
+ $this->assertFalse($fixture->columnHasRelationToResolve(array('config' => array(
+ 'type' => 'select'
+ ))));
+ }
+
+ /**
+ * @test
+ */
+ public function columnHasRelationToResolveDetectsSelectFieldWithMMAsRemote() {
+ $fixture = new Tests_unit_t3lib_AccessibleRootline(1);
+ $this->assertTrue($fixture->columnHasRelationToResolve(array('config' => array(
+ 'type' => 'select',
+ 'MM' => 'xyz'
+ ))));
+ }
+
+ /**
+ * @test
+ */
+ public function getCacheIdentifierContainsAllContextParameters() {
+ $pageContext = t3lib_div::makeInstance('t3lib_pageSelect');
+ $pageContext->sys_language_uid = 8;
+ $pageContext->versioningWorkspaceId = 15;
+ $pageContext->versioningPreview = TRUE;
+ $fixture = new Tests_unit_t3lib_AccessibleRootline(42, '47-11', $pageContext);
+ $this->assertSame(
+ '42_47-11_8_15_1',
+ $fixture->getCacheIdentifier()
+ );
+
+ $pageContext->versioningPreview = FALSE;
+ $fixture = new Tests_unit_t3lib_AccessibleRootline(42, '47-11', $pageContext);
+ $this->assertSame(
+ '42_47-11_8_15_0',
+ $fixture->getCacheIdentifier()
+ );
+
+ $pageContext->versioningWorkspaceId = 0;
+ $fixture = new Tests_unit_t3lib_AccessibleRootline(42, '47-11', $pageContext);
+ $this->assertSame(
+ '42_47-11_8_0_0',
+ $fixture->getCacheIdentifier()
+ );
+ }
+
+}
--- /dev/null
+<?php
+/***************************************************************
+ * Copyright notice
+ *
+ * (c) 2012 Steffen Ritter <steffen.ritter@typo3.org>
+ * All rights reserved
+ *
+ * This script is part of the TYPO3 project. The TYPO3 project is
+ * free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * The GNU General Public License can be found at
+ * http://www.gnu.org/copyleft/gpl.html.
+ *
+ * This script is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+/**
+ * Make method public
+ *
+ * @author Steffen Ritter <steffen.ritter@typo3.org>
+ *
+ * @package TYPO3
+ * @subpackage test
+ */
+class Tests_unit_t3lib_AccessibleRootline extends t3lib_rootline {
+
+ public function isMountedPage() {
+ return parent::isMountedPage();
+ }
+
+ public function processMountedPage($mountedPageData, $mountPointPageData) {
+ return parent::processMountedPage($mountedPageData, $mountPointPageData);
+ }
+
+ public function columnHasRelationToResolve($configuration) {
+ return parent::columnHasRelationToResolve($configuration);
+ }
+
+
+}
\ No newline at end of file