/** * Checks if this is the handler for the given link * * The handler may store this information locally for later usage. * * @param array $linkParts Link parts as returned from TypoLinkCodecService * * @return bool */ public function canHandleLink(array $linkParts) { if (!$linkParts['url']) { return false; } $id = $linkParts['url']; $parts = explode('#', $id); if (count($parts) > 1) { $id = $parts[0]; $anchor = $parts[1]; } else { $anchor = ''; } // Checking if the id-parameter is an alias. if (!MathUtility::canBeInterpretedAsInteger($id)) { $records = BackendUtility::getRecordsByField('pages', 'alias', $id); if (empty($records)) { return false; } $id = (int) $records[0]['uid']; } $pageRow = BackendUtility::getRecordWSOL('pages', $id); if (!$pageRow) { return false; } $this->linkParts = $linkParts; $this->linkParts['pageid'] = $id; $this->linkParts['anchor'] = $anchor; return true; }
/** * Checks if this is the handler for the given link * * The handler may store this information locally for later usage. * * @param array $linkParts Link parts as returned from TypoLinkCodecService * * @return bool */ public function canHandleLink(array $linkParts) { if (!$linkParts['url']) { return false; } $data = $linkParts['url']; // Checking if the id-parameter is an alias. if (isset($data['pagealias'])) { $records = BackendUtility::getRecordsByField('pages', 'alias', $data['pagealias']); if (empty($records)) { return false; } $data['pageuid'] = (int) $records[0]['uid']; } // Check if the page still exists if ((int) $data['pageuid'] > 0) { $pageRow = BackendUtility::getRecordWSOL('pages', $data['pageuid']); if (!$pageRow) { return false; } } elseif ($data['pageuid'] !== 'current') { return false; } $this->linkParts = $linkParts; return true; }
/** * Get all domains from database just once.. * If already retrieved, just return element * * @return array */ public function getDomains() { static $results; if (!isset($results)) { $results = BackendUtility::getRecordsByField('sys_domain', 'redirectTo', ''); } return $results; }
/** * Gets an ordered list of the pages with the "Model site" flag set. * * @return array The model sites in an array. Empty array if no model was found. */ public static function getModelSitesList() { $modelSitesPid = Core::getExtensionConfiguration('modelSitesPid'); $aModelSites = BackendUtility::getRecordsByField('pages', 'pid', $modelSitesPid); $orderedModelSites = array(); if (is_array($aModelSites)) { foreach ($aModelSites as $modelSite) { $orderedModelSites[$modelSite['uid']] = $modelSite['title'] . ' (' . $modelSite['uid'] . ')'; } } return $orderedModelSites; }
/** * This method is used to define new fields for adding or editing a task * In this case, it adds an email field * * @param array $taskInfo reference to the array containing the info used in the add/edit form * @param object $task when editing, reference to the current task object. Null when adding. * @param \TYPO3\CMS\Scheduler\Controller\SchedulerModuleController $parentObject reference to the calling object (Scheduler's BE module) * * @return array Array containg all the information pertaining to the additional fields * The array is multidimensional, keyed to the task class name and each field's id * For each field it provides an associative sub-array with the following: * ['code'] => The HTML code for the field * ['label'] => The label of the field (possibly localized) * ['cshKey'] => The CSH key for the field * ['cshLabel'] => The code of the CSH label */ public function getAdditionalFields(array &$taskInfo, $task, SchedulerModuleController $parentObject) { // Initialize extra field value if (empty($taskInfo['selecteddraft'])) { if ($parentObject->CMD == 'edit') { // In case of edit, and editing a test task, set to internal value if not data was submitted already $taskInfo['selecteddraft'] = $task->draftUid; } else { // Otherwise set an empty value, as it will not be used anyway $taskInfo['selecteddraft'] = ''; } } // fetch all available drafts $drafts = array(); $draftsInternal = BackendUtility::getRecordsByField('sys_dmail', 'type', 2); $draftsExternal = BackendUtility::getRecordsByField('sys_dmail', 'type', 3); if (is_array($draftsInternal)) { $drafts = array_merge($drafts, $draftsInternal); } if (is_array($draftsExternal)) { $drafts = array_merge($drafts, $draftsExternal); } // Create the input field $fieldID = 'task_selecteddraft'; $fieldHtml = ''; if (count($drafts) === 0) { // TODO: localization $fieldHtml .= '<option>' . 'No drafts found. Please add one first through the direct mail process' . '</option>'; } else { foreach ($drafts as $draft) { // see #44577 $selected = $task->draftUid == $draft['uid'] ? ' selected="selected"' : ''; $fieldHtml .= '<option value="' . $draft['uid'] . '"' . $selected . '>' . $draft['subject'] . ' [' . $draft['uid'] . ']</option>'; } } $fieldHtml = '<select name="tx_scheduler[selecteddraft]" id="' . $fieldID . '">' . $fieldHtml . '</select>'; $additionalFields = array(); $additionalFields[$fieldID] = array('code' => $fieldHtml, 'label' => 'Choose Draft to create DirectMail from', 'cshKey' => '', 'cshLabel' => $fieldID); return $additionalFields; }
/** * Generate a different preview link * * * @param string $status status * @param string $table table name * @param integer $recordUid id of the record * @param array $fields fieldArray * @param DataHandling\DataHandler $parentObject parent Object * * @return void */ public function processDatamap_afterDatabaseOperations($status, $table, $recordUid, array $fields, DataHandling\DataHandler $parentObject) { if (in_array($status, array('new', 'update')) && !in_array($table, array('tt_content', 'pages', 'sys_file_reference'))) { $record = BackendUtility::getRecord($table, $recordUid); if ((int) $record['sys_language_uid'] > 0) { // Ref Parent depend of context $uidForeign = $table === 'pages_language_overlay' ? (int) $record['pid'] : (int) $record['l10n_parent']; $rows = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows('fieldname', 'sys_file_reference', "tablenames='{$table}' AND uid_foreign=" . $uidForeign . BackendUtility::deleteClause('sys_file_reference'), 'fieldname', 'fieldname'); $fieldnames = array(); foreach ($rows as $row) { $fieldnames[] = $row['fieldname']; } foreach ($fieldnames as $fieldname) { $references = BackendUtility::getRecordsByField('sys_file_reference', 'tablenames', $table, 'AND uid_foreign=' . $recordUid . " AND fieldname='{$fieldname}'", '', 'sorting ASC'); $l10nParents = BackendUtility::getRecordsByField('sys_file_reference', 'uid_foreign', $uidForeign, " AND fieldname='{$fieldname}'", '', 'sorting ASC'); if ($references) { for ($i = 0; count($references) > $i; $i++) { $GLOBALS['TYPO3_DB']->exec_UPDATEquery('sys_file_reference', 'uid=' . $references[$i]['uid'], array('sys_language_uid' => $record['sys_language_uid'], 'l10n_parent' => isset($l10nParents[$i]) && isset($l10nParents[$i]['uid']) ? $l10nParents[$i]['uid'] : 0)); } } } } } }
/** * Find l10n-overlay records and perform the requested delete action for these records. * * @param string $table Record Table * @param string $uid Record UID * @return void */ public function deleteL10nOverlayRecords($table, $uid) { // Check whether table can be localized or has a different table defined to store localizations: if (!BackendUtility::isTableLocalizable($table) || !empty($GLOBALS['TCA'][$table]['ctrl']['transForeignTable']) || !empty($GLOBALS['TCA'][$table]['ctrl']['transOrigPointerTable'])) { return; } $where = ''; if (isset($GLOBALS['TCA'][$table]['ctrl']['versioningWS']) && $GLOBALS['TCA'][$table]['ctrl']['versioningWS']) { $where = ' AND t3ver_oid=0'; } $l10nRecords = BackendUtility::getRecordsByField($table, $GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField'], $uid, $where); if (is_array($l10nRecords)) { foreach ($l10nRecords as $record) { // Ignore workspace delete placeholders. Those records have been marked for // deletion before - deleting them again in a workspace would revert that state. if ($this->BE_USER->workspace > 0 && BackendUtility::isTableWorkspaceEnabled($table)) { BackendUtility::workspaceOL($table, $record); if (VersionState::cast($record['t3ver_state'])->equals(VersionState::DELETE_PLACEHOLDER)) { continue; } } $this->deleteAction($table, (int) $record['t3ver_oid'] > 0 ? (int) $record['t3ver_oid'] : (int) $record['uid']); } } }
/** * If "editPage" value is sent to script and it points to an accessible page, the internal var $this->theEditRec is set to the page record which should be loaded. * Returns void * * @return void * @todo Define visibility */ public function editPageIdFunc() { if (!\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::isLoaded('cms')) { return; } // EDIT page: $this->editPage = trim($GLOBALS['LANG']->csConvObj->conv_case($GLOBALS['LANG']->charSet, $this->editPage, 'toLower')); $this->editError = ''; $this->theEditRec = ''; $this->searchFor = ''; if ($this->editPage) { // First, test alternative value consisting of [table]:[uid] and if not found, proceed with traditional page ID resolve: $this->alternativeTableUid = explode(':', $this->editPage); // We restrict it to admins only just because I'm not really sure if alt_doc.php properly // checks permissions of passed records for editing. If alt_doc.php does that, then we can remove this. if (!(count($this->alternativeTableUid) == 2 && $GLOBALS['BE_USER']->isAdmin())) { $where = ' AND (' . $GLOBALS['BE_USER']->getPagePermsClause(2) . ' OR ' . $GLOBALS['BE_USER']->getPagePermsClause(16) . ')'; if (\TYPO3\CMS\Core\Utility\MathUtility::canBeInterpretedAsInteger($this->editPage)) { $this->theEditRec = \TYPO3\CMS\Backend\Utility\BackendUtility::getRecordWSOL('pages', $this->editPage, '*', $where); } else { $records = \TYPO3\CMS\Backend\Utility\BackendUtility::getRecordsByField('pages', 'alias', $this->editPage, $where); if (is_array($records)) { $this->theEditRec = reset($records); \TYPO3\CMS\Backend\Utility\BackendUtility::workspaceOL('pages', $this->theEditRec); } } if (!is_array($this->theEditRec)) { unset($this->theEditRec); $this->searchFor = $this->editPage; } elseif (!$GLOBALS['BE_USER']->isInWebMount($this->theEditRec['uid'])) { unset($this->theEditRec); $this->editError = $GLOBALS['LANG']->getLL('bookmark_notEditable'); } else { // Visual path set: $perms_clause = $GLOBALS['BE_USER']->getPagePermsClause(1); $this->editPath = \TYPO3\CMS\Backend\Utility\BackendUtility::getRecordPath($this->theEditRec['pid'], $perms_clause, 30); if (!$GLOBALS['BE_USER']->getTSConfigVal('options.bookmark_onEditId_dontSetPageTree')) { $bookmarkKeepExpanded = $GLOBALS['BE_USER']->getTSConfigVal('options.bookmark_onEditId_keepExistingExpanded'); // Expanding page tree: \TYPO3\CMS\Backend\Utility\BackendUtility::openPageTree($this->theEditRec['pid'], !$bookmarkKeepExpanded); } } } } }
/** * Transformation handler: 'ts_links' / direction: "rte" * Converting <link tags> to <A>-tags * * @param string $value Content input * @return string Content output * @see TS_links_rte() * @todo Define visibility */ public function TS_links_rte($value) { $conf = array(); $value = $this->TS_AtagToAbs($value); // Split content by the TYPO3 pseudo tag "<link>": $blockSplit = $this->splitIntoBlock('link', $value, 1); $siteUrl = $this->siteUrl(); foreach ($blockSplit as $k => $v) { $error = ''; $external = FALSE; // Block if ($k % 2) { $tagCode = \TYPO3\CMS\Core\Utility\GeneralUtility::unQuoteFilenames(trim(substr($this->getFirstTag($v), 0, -1)), TRUE); $link_param = $tagCode[1]; $href = ''; // Parsing the typolink data. This parsing is roughly done like in tslib_content->typolink() if (strstr($link_param, '@')) { // mailadr $href = 'mailto:' . preg_replace('/^mailto:/i', '', $link_param); } elseif (substr($link_param, 0, 1) == '#') { // check if anchor $href = $siteUrl . $link_param; } else { // Check for FAL link-handler keyword: list($linkHandlerKeyword, $linkHandlerValue) = explode(':', trim($link_param), 2); if ($linkHandlerKeyword === 'file') { $href = $siteUrl . '?' . $linkHandlerKeyword . ':' . rawurlencode($linkHandlerValue); } else { $fileChar = intval(strpos($link_param, '/')); $urlChar = intval(strpos($link_param, '.')); // Parse URL: $pU = parse_url($link_param); // Detects if a file is found in site-root. list($rootFileDat) = explode('?', $link_param); $rFD_fI = pathinfo($rootFileDat); if (trim($rootFileDat) && !strstr($link_param, '/') && (@is_file(PATH_site . $rootFileDat) || \TYPO3\CMS\Core\Utility\GeneralUtility::inList('php,html,htm', strtolower($rFD_fI['extension'])))) { $href = $siteUrl . $link_param; } elseif ($pU['scheme'] || $urlChar && (!$fileChar || $urlChar < $fileChar)) { // url (external): if has scheme or if a '.' comes before a '/'. $href = $link_param; if (!$pU['scheme']) { $href = 'http://' . $href; } $external = TRUE; } elseif ($fileChar) { // file (internal) $href = $siteUrl . $link_param; } else { // integer or alias (alias is without slashes or periods or commas, that is 'nospace,alphanum_x,lower,unique' according to tables.php!!) // Splitting the parameter by ',' and if the array counts more than 1 element it's a id/type/parameters triplet $pairParts = \TYPO3\CMS\Core\Utility\GeneralUtility::trimExplode(',', $link_param, TRUE); $idPart = $pairParts[0]; $link_params_parts = explode('#', $idPart); $idPart = trim($link_params_parts[0]); $sectionMark = trim($link_params_parts[1]); if (!strcmp($idPart, '')) { $idPart = $this->recPid; } // If no id or alias is given, set it to class record pid // Checking if the id-parameter is an alias. if (!\TYPO3\CMS\Core\Utility\MathUtility::canBeInterpretedAsInteger($idPart)) { list($idPartR) = \TYPO3\CMS\Backend\Utility\BackendUtility::getRecordsByField('pages', 'alias', $idPart); $idPart = intval($idPartR['uid']); } $page = \TYPO3\CMS\Backend\Utility\BackendUtility::getRecord('pages', $idPart); if (is_array($page)) { // Page must exist... $href = $siteUrl . '?id=' . $idPart . ($pairParts[2] ? $pairParts[2] : '') . ($sectionMark ? '#' . $sectionMark : ''); } elseif (isset($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['typolinkLinkHandler'][array_shift(explode(':', $link_param))])) { $href = $link_param; } else { $href = $siteUrl . '?id=' . $link_param; $error = 'No page found: ' . $idPart; } } } } // Setting the A-tag: $bTag = '<a href="' . htmlspecialchars($href) . '"' . ($tagCode[2] && $tagCode[2] != '-' ? ' target="' . htmlspecialchars($tagCode[2]) . '"' : '') . ($tagCode[3] && $tagCode[3] != '-' ? ' class="' . htmlspecialchars($tagCode[3]) . '"' : '') . ($tagCode[4] ? ' title="' . htmlspecialchars($tagCode[4]) . '"' : '') . ($external ? ' data-htmlarea-external="1"' : '') . ($error ? ' rteerror="' . htmlspecialchars($error) . '" style="background-color: yellow; border:2px red solid; color: black;"' : '') . '>'; $eTag = '</a>'; // Modify parameters if (isset($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_parsehtml_proc.php']['modifyParams_LinksRte_PostProc']) && is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_parsehtml_proc.php']['modifyParams_LinksRte_PostProc'])) { $parameters = array('conf' => &$conf, 'currentBlock' => $v, 'url' => $href, 'tagCode' => $tagCode, 'external' => $external, 'error' => $error); foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_parsehtml_proc.php']['modifyParams_LinksRte_PostProc'] as $objRef) { $processor = \TYPO3\CMS\Core\Utility\GeneralUtility::getUserObj($objRef); $blockSplit[$k] = $processor->modifyParamsLinksRte($parameters, $this); } } else { $blockSplit[$k] = $bTag . $this->TS_links_rte($this->removeFirstAndLastTag($blockSplit[$k])) . $eTag; } } } // Return content: return implode('', $blockSplit); }
/** * Look up and return page uid for alias * * @param integer $link_param Page alias string value * @return integer Page uid corresponding to alias value. * @todo Define visibility */ public function getPageIdFromAlias($link_param) { $pRec = \TYPO3\CMS\Backend\Utility\BackendUtility::getRecordsByField('pages', 'alias', $link_param); return $pRec[0]['uid']; }
/** * For RTE/link: Parses the incoming URL and determines if it's a page, file, external or mail address. * * @param string $href HREF value tp analyse * @param string $siteUrl The URL of the current website (frontend) * @return array Array with URL information stored in assoc. keys: value, act (page, file, spec, mail), pageid, cElement, info * @todo Define visibility */ public function parseCurUrl($href, $siteUrl) { $href = trim($href); if ($href) { $info = array(); // Default is "url": $info['value'] = $href; $info['act'] = 'url'; $specialParts = explode('#_SPECIAL', $href); // Special kind (Something RTE specific: User configurable links through: "userLinks." from ->thisConfig) if (count($specialParts) == 2) { $info['value'] = '#_SPECIAL' . $specialParts[1]; $info['act'] = 'spec'; } elseif (strpos($href, 'file:') !== FALSE) { $rel = substr($href, strpos($href, 'file:') + 5); $rel = rawurldecode($rel); // resolve FAL-api "file:UID-of-sys_file-record" and "file:combined-identifier" $fileOrFolderObject = \TYPO3\CMS\Core\Resource\ResourceFactory::getInstance()->retrieveFileOrFolderObject($rel); if ($fileOrFolderObject instanceof Folder) { $info['act'] = 'folder'; $info['value'] = $fileOrFolderObject->getCombinedIdentifier(); } elseif ($fileOrFolderObject instanceof File) { $info['act'] = 'file'; $info['value'] = $fileOrFolderObject->getUid(); } else { $info['value'] = $rel; } } elseif (GeneralUtility::isFirstPartOfStr($href, $siteUrl)) { // If URL is on the current frontend website: // URL is a file, which exists: if (file_exists(PATH_site . rawurldecode($href))) { $info['value'] = rawurldecode($href); if (@is_dir(PATH_site . $info['value'])) { $info['act'] = 'folder'; } else { $info['act'] = 'file'; } } else { // URL is a page (id parameter) $uP = parse_url($href); $pp = preg_split('/^id=/', $uP['query']); $pp[1] = preg_replace('/&id=[^&]*/', '', $pp[1]); $parameters = explode('&', $pp[1]); $id = array_shift($parameters); if ($id) { // Checking if the id-parameter is an alias. if (!\TYPO3\CMS\Core\Utility\MathUtility::canBeInterpretedAsInteger($id)) { list($idPartR) = BackendUtility::getRecordsByField('pages', 'alias', $id); $id = (int) $idPartR['uid']; } $pageRow = BackendUtility::getRecordWSOL('pages', $id); $titleLen = (int) $GLOBALS['BE_USER']->uc['titleLen']; $info['value'] = $GLOBALS['LANG']->getLL('page', TRUE) . ' \'' . htmlspecialchars(GeneralUtility::fixed_lgd_cs($pageRow['title'], $titleLen)) . '\' (ID:' . $id . ($uP['fragment'] ? ', #' . $uP['fragment'] : '') . ')'; $info['pageid'] = $id; $info['cElement'] = $uP['fragment']; $info['act'] = 'page'; $info['query'] = $parameters[0] ? '&' . implode('&', $parameters) : ''; } } } else { // Email link: if (strtolower(substr($href, 0, 7)) == 'mailto:') { $info['value'] = trim(substr($href, 7)); $info['act'] = 'mail'; } } $info['info'] = $info['value']; } else { // NO value inputted: $info = array(); $info['info'] = $GLOBALS['LANG']->getLL('none'); $info['value'] = ''; $info['act'] = 'page'; } // let the hook have a look foreach ($this->hookObjects as $hookObject) { $info = $hookObject->parseCurrentUrl($href, $siteUrl, $info); } return $info; }
/** * Set all deleted rows * * @param integer $id: UID from record * @param string $table: Tablename from record * @param integer $depth: How many levels recursive * @param array $ctrl: TCA CTRL Array * @param string $filter: Filter text * @return void */ protected function setData($id = 0, $table, $depth, $tcaCtrl, $filter) { $id = intval($id); if (array_key_exists('delete', $tcaCtrl)) { // find the 'deleted' field for this table $deletedField = \TYPO3\CMS\Recycler\Utility\RecyclerUtility::getDeletedField($table); // create the filter WHERE-clause if (trim($filter) != '') { $filterWhere = ' AND (' . (\TYPO3\CMS\Core\Utility\MathUtility::canBeInterpretedAsInteger($filter) ? 'uid = ' . $filter . ' OR pid = ' . $filter . ' OR ' : '') . $tcaCtrl['label'] . ' LIKE "%' . $this->escapeValueForLike($filter, $table) . '%"' . ')'; } // get the limit if ($this->limit != '') { // count the number of deleted records for this pid $deletedCount = $GLOBALS['TYPO3_DB']->exec_SELECTcountRows('uid', $table, $deletedField . '<>0 AND pid = ' . $id . $filterWhere); // split the limit $parts = \TYPO3\CMS\Core\Utility\GeneralUtility::trimExplode(',', $this->limit); $offset = $parts[0]; $rowCount = $parts[1]; // subtract the number of deleted records from the limit's offset $result = $offset - $deletedCount; // if the result is >= 0 if ($result >= 0) { // store the new offset in the limit and go into the next depth $offset = $result; $this->limit = implode(',', array($offset, $rowCount)); // do NOT query this depth; limit also does not need to be set, we set it anyways $allowQuery = FALSE; $allowDepth = TRUE; $limit = ''; } else { // the offset for the temporary limit has to remain like the original offset // in case the original offset was just crossed by the amount of deleted records if ($offset != 0) { $tempOffset = $offset; } else { $tempOffset = 0; } // set the offset in the limit to 0 $newOffset = 0; // convert to negative result to the positive equivalent $absResult = abs($result); // if the result now is > limit's row count if ($absResult > $rowCount) { // use the limit's row count as the temporary limit $limit = implode(',', array($tempOffset, $rowCount)); // set the limit's row count to 0 $this->limit = implode(',', array($newOffset, 0)); // do not go into new depth $allowDepth = FALSE; } else { // if the result now is <= limit's row count // use the result as the temporary limit $limit = implode(',', array($tempOffset, $absResult)); // subtract the result from the row count $newCount = $rowCount - $absResult; // store the new result in the limit's row count $this->limit = implode(',', array($newOffset, $newCount)); // if the new row count is > 0 if ($newCount > 0) { // go into new depth $allowDepth = TRUE; } else { // if the new row count is <= 0 (only =0 makes sense though) // do not go into new depth $allowDepth = FALSE; } } // allow query for this depth $allowQuery = TRUE; } } else { $limit = ''; $allowDepth = TRUE; $allowQuery = TRUE; } // query for actual deleted records if ($allowQuery) { $recordsToCheck = \TYPO3\CMS\Backend\Utility\BackendUtility::getRecordsByField($table, $deletedField, '1', ' AND pid = ' . $id . $filterWhere, '', '', $limit, FALSE); if ($recordsToCheck) { $this->checkRecordAccess($table, $recordsToCheck); } } // go into depth if ($allowDepth && $depth >= 1) { // check recursively for elements beneath this page $resPages = $GLOBALS['TYPO3_DB']->exec_SELECTquery('uid', 'pages', 'pid=' . $id, '', 'sorting'); if (is_resource($resPages)) { while ($rowPages = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($resPages)) { $this->setData($rowPages['uid'], $table, $depth - 1, $tcaCtrl, $filter); // some records might have been added, check if we still have the limit for further queries if ('' != $this->limit) { $parts = \TYPO3\CMS\Core\Utility\GeneralUtility::trimExplode(',', $this->limit); // abort loop if LIMIT 0,0 if ($parts[0] == 0 && $parts[1] == 0) { break; } } } $GLOBALS['TYPO3_DB']->sql_free_result($resPages); } } $this->label[$table] = $tcaCtrl['label']; $this->title[$table] = $tcaCtrl['title']; } }
/** * @param $edit_record array * * @return array */ protected function makeQuickEditMenu($edit_record) { $lang = $this->getLanguageService(); $databaseConnection = $this->getDatabaseConnection(); $beUser = $this->getBackendUser(); $quickEditMenu = $this->moduleTemplate->getDocHeaderComponent()->getMenuRegistry()->makeMenu(); $quickEditMenu->setIdentifier('quickEditMenu'); $quickEditMenu->setLabel(''); // Setting close url/return url for exiting this script: // Goes to 'Columns' view if close is pressed (default) $this->closeUrl = $this->local_linkThisScript(array('SET' => array('function' => 1))); if ($this->returnUrl) { $this->closeUrl = $this->returnUrl; } $retUrlStr = $this->returnUrl ? '&returnUrl=' . rawurlencode($this->returnUrl) : ''; // Creating the selector box, allowing the user to select which element to edit: $isSelected = 0; $languageOverlayRecord = ''; if ($this->current_sys_language) { list($languageOverlayRecord) = BackendUtility::getRecordsByField('pages_language_overlay', 'pid', $this->id, 'AND sys_language_uid=' . (int) $this->current_sys_language); } if (is_array($languageOverlayRecord)) { $inValue = 'pages_language_overlay:' . $languageOverlayRecord['uid']; $isSelected += (int) $edit_record == $inValue; $menuItem = $quickEditMenu->makeMenuItem()->setTitle('[ ' . $lang->getLL('editLanguageHeader', true) . ' ]')->setHref(BackendUtility::getModuleUrl($this->moduleName) . '&id=' . $this->id . '&edit_record=' . $inValue . $retUrlStr)->setActive($edit_record == $inValue); $quickEditMenu->addMenuItem($menuItem); } else { $inValue = 'pages:' . $this->id; $isSelected += (int) $edit_record == $inValue; $menuItem = $quickEditMenu->makeMenuItem()->setTitle('[ ' . $lang->getLL('editPageProperties', true) . ' ]')->setHref(BackendUtility::getModuleUrl($this->moduleName) . '&id=' . $this->id . '&edit_record=' . $inValue . $retUrlStr)->setActive($edit_record == $inValue); $quickEditMenu->addMenuItem($menuItem); } // Selecting all content elements from this language and allowed colPos: $whereClause = 'pid=' . (int) $this->id . ' AND sys_language_uid=' . (int) $this->current_sys_language . ' AND colPos IN (' . $this->colPosList . ')' . ($this->MOD_SETTINGS['tt_content_showHidden'] ? '' : BackendUtility::BEenableFields('tt_content')) . BackendUtility::deleteClause('tt_content') . BackendUtility::versioningPlaceholderClause('tt_content'); if (!$this->getBackendUser()->user['admin']) { $whereClause .= ' AND editlock = 0'; } $res = $databaseConnection->exec_SELECTquery('*', 'tt_content', $whereClause, '', 'colPos,sorting'); $colPos = null; $first = 1; // Page is the pid if no record to put this after. $prev = $this->id; while ($cRow = $databaseConnection->sql_fetch_assoc($res)) { BackendUtility::workspaceOL('tt_content', $cRow); if (is_array($cRow)) { if ($first) { if (!$edit_record) { $edit_record = 'tt_content:' . $cRow['uid']; } $first = 0; } if (!isset($colPos) || $cRow['colPos'] !== $colPos) { $colPos = $cRow['colPos']; $menuItem = $quickEditMenu->makeMenuItem()->setTitle(' ')->setHref('#'); $quickEditMenu->addMenuItem($menuItem); $menuItem = $quickEditMenu->makeMenuItem()->setTitle('__' . $lang->sL(BackendUtility::getLabelFromItemlist('tt_content', 'colPos', $colPos), true) . ':__')->setHref(BackendUtility::getModuleUrl($this->moduleName) . '&id=' . $this->id . '&edit_record=_EDIT_COL:' . $colPos . $retUrlStr); $quickEditMenu->addMenuItem($menuItem); } $inValue = 'tt_content:' . $cRow['uid']; $isSelected += (int) $edit_record == $inValue; $menuItem = $quickEditMenu->makeMenuItem()->setTitle(htmlspecialchars(GeneralUtility::fixed_lgd_cs($cRow['header'] ? $cRow['header'] : '[' . $lang->sL('LLL:EXT:lang/locallang_core.xlf:labels.no_title') . '] ' . strip_tags($cRow['bodytext']), $beUser->uc['titleLen'])))->setHref(BackendUtility::getModuleUrl($this->moduleName) . '&id=' . $this->id . '&edit_record=' . $inValue . $retUrlStr)->setActive($edit_record == $inValue); $quickEditMenu->addMenuItem($menuItem); $prev = -$cRow['uid']; } } // If edit_record is not set (meaning, no content elements was found for this language) we simply set it to create a new element: if (!$edit_record) { $edit_record = 'tt_content:new/' . $prev . '/' . $colPos; $inValue = 'tt_content:new/' . $prev . '/' . $colPos; $isSelected += (int) $edit_record == $inValue; $menuItem = $quickEditMenu->makeMenuItem()->setTitle('[ ' . $lang->getLL('newLabel', 1) . ' ]')->setHref(BackendUtility::getModuleUrl($this->moduleName) . '&id=' . $this->id . '&edit_record=' . $inValue . $retUrlStr)->setActive($edit_record == $inValue); $quickEditMenu->addMenuItem($menuItem); } // If none is yet selected... if (!$isSelected) { $menuItem = $quickEditMenu->makeMenuItem()->setTitle('__________')->setHref('#'); $quickEditMenu->addMenuItem($menuItem); $menuItem = $quickEditMenu->makeMenuItem()->setTitle('[ ' . $lang->getLL('newLabel', true) . ' ]')->setHref(BackendUtility::getModuleUrl($this->moduleName) . '&id=' . $this->id . '&edit_record=' . $edit_record . $retUrlStr)->setActive($edit_record == $inValue); $quickEditMenu->addMenuItem($menuItem); } $this->moduleTemplate->getDocHeaderComponent()->getMenuRegistry()->addMenu($quickEditMenu); return $edit_record; }
/** * Check if user has access to all existing localizations for a certain record * * @param string $table The table * @param array $record The current record * @return boolean * @todo Define visibility */ public function checkFullLanguagesAccess($table, $record) { $recordLocalizationAccess = $this->checkLanguageAccess(0); if ($recordLocalizationAccess && (BackendUtility::isTableLocalizable($table) || isset($GLOBALS['TCA'][$table]['ctrl']['transForeignTable']))) { if (isset($GLOBALS['TCA'][$table]['ctrl']['transForeignTable'])) { $l10nTable = $GLOBALS['TCA'][$table]['ctrl']['transForeignTable']; $pointerField = $GLOBALS['TCA'][$l10nTable]['ctrl']['transOrigPointerField']; $pointerValue = $record['uid']; } else { $l10nTable = $table; $pointerField = $GLOBALS['TCA'][$l10nTable]['ctrl']['transOrigPointerField']; $pointerValue = $record[$pointerField] > 0 ? $record[$pointerField] : $record['uid']; } $recordLocalizations = BackendUtility::getRecordsByField($l10nTable, $pointerField, $pointerValue, '', '', '', '1'); if (is_array($recordLocalizations)) { foreach ($recordLocalizations as $localization) { $recordLocalizationAccess = $recordLocalizationAccess && $this->checkLanguageAccess($localization[$GLOBALS['TCA'][$l10nTable]['ctrl']['languageField']]); if (!$recordLocalizationAccess) { break; } } } } return $recordLocalizationAccess; }
/** * Rendering the quick-edit view. * * @return void * @todo Define visibility */ public function renderQuickEdit() { // Alternative template $this->doc->setModuleTemplate('templates/db_layout_quickedit.html'); // Alternative form tag; Quick Edit submits its content to tce_db.php. $this->doc->form = '<form action="' . htmlspecialchars($GLOBALS['BACK_PATH'] . 'tce_db.php?&prErr=1&uPT=1') . '" method="post" enctype="' . $GLOBALS['TYPO3_CONF_VARS']['SYS']['form_enctype'] . '" name="editform" onsubmit="return TBE_EDITOR.checkSubmit(1);">'; // Setting up the context sensitive menu: $this->doc->getContextMenuCode(); // Set the edit_record value for internal use in this function: $edit_record = $this->edit_record; // If a command to edit all records in a column is issue, then select all those elements, and redirect to alt_doc.php: if (substr($edit_record, 0, 9) == '_EDIT_COL') { $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('*', 'tt_content', 'pid=' . intval($this->id) . ' AND colPos=' . intval(substr($edit_record, 10)) . ' AND sys_language_uid=' . intval($this->current_sys_language) . ($this->MOD_SETTINGS['tt_content_showHidden'] ? '' : \TYPO3\CMS\Backend\Utility\BackendUtility::BEenableFields('tt_content')) . \TYPO3\CMS\Backend\Utility\BackendUtility::deleteClause('tt_content') . \TYPO3\CMS\Backend\Utility\BackendUtility::versioningPlaceholderClause('tt_content'), '', 'sorting'); $idListA = array(); while ($cRow = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) { $idListA[] = $cRow['uid']; } $url = $GLOBALS['BACK_PATH'] . 'alt_doc.php?edit[tt_content][' . implode(',', $idListA) . ']=edit&returnUrl=' . rawurlencode($this->local_linkThisScript(array('edit_record' => ''))); \TYPO3\CMS\Core\Utility\HttpUtility::redirect($url); } // If the former record edited was the creation of a NEW record, this will look up the created records uid: if ($this->new_unique_uid) { $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('*', 'sys_log', 'userid=' . intval($GLOBALS['BE_USER']->user['uid']) . ' AND NEWid=' . $GLOBALS['TYPO3_DB']->fullQuoteStr($this->new_unique_uid, 'sys_log')); $sys_log_row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res); if (is_array($sys_log_row)) { $edit_record = $sys_log_row['tablename'] . ':' . $sys_log_row['recuid']; } } // Creating the selector box, allowing the user to select which element to edit: $opt = array(); $is_selected = 0; $languageOverlayRecord = ''; if ($this->current_sys_language) { list($languageOverlayRecord) = \TYPO3\CMS\Backend\Utility\BackendUtility::getRecordsByField('pages_language_overlay', 'pid', $this->id, 'AND sys_language_uid=' . intval($this->current_sys_language)); } if (is_array($languageOverlayRecord)) { $inValue = 'pages_language_overlay:' . $languageOverlayRecord['uid']; $is_selected += intval($edit_record == $inValue); $opt[] = '<option value="' . $inValue . '"' . ($edit_record == $inValue ? ' selected="selected"' : '') . '>[ ' . $GLOBALS['LANG']->getLL('editLanguageHeader', 1) . ' ]</option>'; } else { $inValue = 'pages:' . $this->id; $is_selected += intval($edit_record == $inValue); $opt[] = '<option value="' . $inValue . '"' . ($edit_record == $inValue ? ' selected="selected"' : '') . '>[ ' . $GLOBALS['LANG']->getLL('editPageProperties', 1) . ' ]</option>'; } // Selecting all content elements from this language and allowed colPos: $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('*', 'tt_content', 'pid=' . intval($this->id) . ' AND sys_language_uid=' . intval($this->current_sys_language) . ' AND colPos IN (' . $this->colPosList . ')' . ($this->MOD_SETTINGS['tt_content_showHidden'] ? '' : \TYPO3\CMS\Backend\Utility\BackendUtility::BEenableFields('tt_content')) . \TYPO3\CMS\Backend\Utility\BackendUtility::deleteClause('tt_content') . \TYPO3\CMS\Backend\Utility\BackendUtility::versioningPlaceholderClause('tt_content'), '', 'colPos,sorting'); $colPos = ''; $first = 1; // Page is the pid if no record to put this after. $prev = $this->id; while ($cRow = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) { \TYPO3\CMS\Backend\Utility\BackendUtility::workspaceOL('tt_content', $cRow); if (is_array($cRow)) { if ($first) { if (!$edit_record) { $edit_record = 'tt_content:' . $cRow['uid']; } $first = 0; } if (strcmp($cRow['colPos'], $colPos)) { $colPos = $cRow['colPos']; $opt[] = '<option value=""></option>'; $opt[] = '<option value="_EDIT_COL:' . $colPos . '">__' . $GLOBALS['LANG']->sL(\TYPO3\CMS\Backend\Utility\BackendUtility::getLabelFromItemlist('tt_content', 'colPos', $colPos), 1) . ':__</option>'; } $inValue = 'tt_content:' . $cRow['uid']; $is_selected += intval($edit_record == $inValue); $opt[] = '<option value="' . $inValue . '"' . ($edit_record == $inValue ? ' selected="selected"' : '') . '>' . htmlspecialchars(\TYPO3\CMS\Core\Utility\GeneralUtility::fixed_lgd_cs($cRow['header'] ? $cRow['header'] : '[' . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:labels.no_title') . '] ' . strip_tags($cRow['bodytext']), $GLOBALS['BE_USER']->uc['titleLen'])) . '</option>'; $prev = -$cRow['uid']; } } // If edit_record is not set (meaning, no content elements was found for this language) we simply set it to create a new element: if (!$edit_record) { $edit_record = 'tt_content:new/' . $prev . '/' . $colPos; $inValue = 'tt_content:new/' . $prev . '/' . $colPos; $is_selected += intval($edit_record == $inValue); $opt[] = '<option value="' . $inValue . '"' . ($edit_record == $inValue ? ' selected="selected"' : '') . '>[ ' . $GLOBALS['LANG']->getLL('newLabel', 1) . ' ]</option>'; } // If none is yet selected... if (!$is_selected) { $opt[] = '<option value=""></option>'; $opt[] = '<option value="' . $edit_record . '" selected="selected">[ ' . $GLOBALS['LANG']->getLL('newLabel', 1) . ' ]</option>'; } // Splitting the edit-record cmd value into table/uid: $this->eRParts = explode(':', $edit_record); // Delete-button flag? $this->deleteButton = \TYPO3\CMS\Core\Utility\MathUtility::canBeInterpretedAsInteger($this->eRParts[1]) && $edit_record && ($this->eRParts[0] != 'pages' && $this->EDIT_CONTENT || $this->eRParts[0] == 'pages' && $this->CALC_PERMS & 4); // If undo-button should be rendered (depends on available items in sys_history) $this->undoButton = 0; $undoRes = $GLOBALS['TYPO3_DB']->exec_SELECTquery('tstamp', 'sys_history', 'tablename=' . $GLOBALS['TYPO3_DB']->fullQuoteStr($this->eRParts[0], 'sys_history') . ' AND recuid=' . intval($this->eRParts[1]), '', 'tstamp DESC', '1'); if ($this->undoButtonR = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($undoRes)) { $this->undoButton = 1; } // Setting up the Return URL for coming back to THIS script (if links take the user to another script) $R_URL_parts = parse_url(\TYPO3\CMS\Core\Utility\GeneralUtility::getIndpEnv('REQUEST_URI')); $R_URL_getvars = \TYPO3\CMS\Core\Utility\GeneralUtility::_GET(); unset($R_URL_getvars['popView']); unset($R_URL_getvars['new_unique_uid']); $R_URL_getvars['edit_record'] = $edit_record; $this->R_URI = $R_URL_parts['path'] . '?' . \TYPO3\CMS\Core\Utility\GeneralUtility::implodeArrayForUrl('', $R_URL_getvars); // Setting close url/return url for exiting this script: // Goes to 'Columns' view if close is pressed (default) $this->closeUrl = $this->local_linkThisScript(array('SET' => array('function' => 1))); if ($GLOBALS['BE_USER']->uc['condensedMode']) { $this->closeUrl = $GLOBALS['BACK_PATH'] . 'alt_db_navframe.php'; } if ($this->returnUrl) { $this->closeUrl = $this->returnUrl; } // Return-url for JavaScript: $retUrlStr = $this->returnUrl ? '+\'&returnUrl=\'+\'' . rawurlencode($this->returnUrl) . '\'' : ''; // Drawing the edit record selectbox $this->editSelect = '<select name="edit_record" onchange="' . htmlspecialchars('jumpToUrl(\'db_layout.php?id=' . $this->id . '&edit_record=\'+escape(this.options[this.selectedIndex].value)' . $retUrlStr . ',this);') . '">' . implode('', $opt) . '</select>'; // Creating editing form: if ($GLOBALS['BE_USER']->check('tables_modify', $this->eRParts[0]) && $edit_record && ($this->eRParts[0] !== 'pages' && $this->EDIT_CONTENT || $this->eRParts[0] === 'pages' && $this->CALC_PERMS & 1)) { // Splitting uid parts for special features, if new: list($uidVal, $ex_pid, $ex_colPos) = explode('/', $this->eRParts[1]); // Convert $uidVal to workspace version if any: if ($uidVal != 'new') { if ($draftRecord = \TYPO3\CMS\Backend\Utility\BackendUtility::getWorkspaceVersionOfRecord($GLOBALS['BE_USER']->workspace, $this->eRParts[0], $uidVal, 'uid')) { $uidVal = $draftRecord['uid']; } } // Initializing transfer-data object: $trData = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Backend\\Form\\DataPreprocessor'); $trData->addRawData = TRUE; $trData->defVals[$this->eRParts[0]] = array('colPos' => intval($ex_colPos), 'sys_language_uid' => intval($this->current_sys_language)); $trData->disableRTE = $this->MOD_SETTINGS['disableRTE']; $trData->lockRecords = 1; // 'new' $trData->fetchRecord($this->eRParts[0], $uidVal == 'new' ? $this->id : $uidVal, $uidVal); // Getting/Making the record: reset($trData->regTableItems_data); $rec = current($trData->regTableItems_data); if ($uidVal == 'new') { $new_unique_uid = uniqid('NEW'); $rec['uid'] = $new_unique_uid; $rec['pid'] = intval($ex_pid) ? intval($ex_pid) : $this->id; $recordAccess = TRUE; } else { $rec['uid'] = $uidVal; // Checking internals access: $recordAccess = $GLOBALS['BE_USER']->recordEditAccessInternals($this->eRParts[0], $uidVal); } if (!$recordAccess) { // If no edit access, print error message: $content .= $this->doc->section($GLOBALS['LANG']->getLL('noAccess'), $GLOBALS['LANG']->getLL('noAccess_msg') . '<br /><br />' . ($GLOBALS['BE_USER']->errorMsg ? 'Reason: ' . $GLOBALS['BE_USER']->errorMsg . '<br /><br />' : ''), 0, 1); } elseif (is_array($rec)) { // If the record is an array (which it will always be... :-) // Create instance of TCEforms, setting defaults: $tceforms = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Backend\\Form\\FormEngine'); $tceforms->backPath = $GLOBALS['BACK_PATH']; $tceforms->initDefaultBEMode(); $tceforms->fieldOrder = $this->modTSconfig['properties']['tt_content.']['fieldOrder']; $tceforms->palettesCollapsed = !$this->MOD_SETTINGS['showPalettes']; $tceforms->disableRTE = $this->MOD_SETTINGS['disableRTE']; $tceforms->enableClickMenu = TRUE; // Clipboard is initialized: // Start clipboard $tceforms->clipObj = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Backend\\Clipboard\\Clipboard'); // Initialize - reads the clipboard content from the user session $tceforms->clipObj->initializeClipboard(); // Render form, wrap it: $panel = ''; $panel .= $tceforms->getMainFields($this->eRParts[0], $rec); $panel = $tceforms->wrapTotal($panel, $rec, $this->eRParts[0]); // Add hidden fields: $theCode = $panel; if ($uidVal == 'new') { $theCode .= '<input type="hidden" name="data[' . $this->eRParts[0] . '][' . $rec['uid'] . '][pid]" value="' . $rec['pid'] . '" />'; } $theCode .= ' <input type="hidden" name="_serialNumber" value="' . md5(microtime()) . '" /> <input type="hidden" name="_disableRTE" value="' . $tceforms->disableRTE . '" /> <input type="hidden" name="edit_record" value="' . $edit_record . '" /> <input type="hidden" name="redirect" value="' . htmlspecialchars($uidVal == 'new' ? \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::extRelPath('cms') . 'layout/db_layout.php?id=' . $this->id . '&new_unique_uid=' . $new_unique_uid . '&returnUrl=' . rawurlencode($this->returnUrl) : $this->R_URI) . '" /> ' . \TYPO3\CMS\Backend\Form\FormEngine::getHiddenTokenField('tceAction'); // Add JavaScript as needed around the form: $theCode = $tceforms->printNeededJSFunctions_top() . $theCode . $tceforms->printNeededJSFunctions(); // Add warning sign if record was "locked": if ($lockInfo = \TYPO3\CMS\Backend\Utility\BackendUtility::isRecordLocked($this->eRParts[0], $rec['uid'])) { $lockedMessage = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Messaging\\FlashMessage', htmlspecialchars($lockInfo['msg']), '', \TYPO3\CMS\Core\Messaging\FlashMessage::WARNING); \TYPO3\CMS\Core\Messaging\FlashMessageQueue::addMessage($lockedMessage); } // Add whole form as a document section: $content .= $this->doc->section('', $theCode); } } else { // If no edit access, print error message: $content .= $this->doc->section($GLOBALS['LANG']->getLL('noAccess'), $GLOBALS['LANG']->getLL('noAccess_msg') . '<br /><br />', 0, 1); } // Bottom controls (function menus): $q_count = $this->getNumberOfHiddenElements(); $h_func_b = \TYPO3\CMS\Backend\Utility\BackendUtility::getFuncCheck($this->id, 'SET[tt_content_showHidden]', $this->MOD_SETTINGS['tt_content_showHidden'], 'db_layout.php', '', 'id="checkTt_content_showHidden"') . '<label for="checkTt_content_showHidden">' . (!$q_count ? $GLOBALS['TBE_TEMPLATE']->dfw($GLOBALS['LANG']->getLL('hiddenCE', 1)) : $GLOBALS['LANG']->getLL('hiddenCE', 1) . ' (' . $q_count . ')') . '</label>'; $h_func_b .= '<br />' . \TYPO3\CMS\Backend\Utility\BackendUtility::getFuncCheck($this->id, 'SET[showPalettes]', $this->MOD_SETTINGS['showPalettes'], 'db_layout.php', '', 'id="checkShowPalettes"') . '<label for="checkShowPalettes">' . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:labels.showPalettes', 1) . '</label>'; if (\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::isLoaded('context_help')) { $h_func_b .= '<br />' . \TYPO3\CMS\Backend\Utility\BackendUtility::getFuncCheck($this->id, 'SET[showDescriptions]', $this->MOD_SETTINGS['showDescriptions'], 'db_layout.php', '', 'id="checkShowDescriptions"') . '<label for="checkShowDescriptions">' . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:labels.showDescriptions', 1) . '</label>'; } if ($GLOBALS['BE_USER']->isRTE()) { $h_func_b .= '<br />' . \TYPO3\CMS\Backend\Utility\BackendUtility::getFuncCheck($this->id, 'SET[disableRTE]', $this->MOD_SETTINGS['disableRTE'], 'db_layout.php', '', 'id="checkDisableRTE"') . '<label for="checkDisableRTE">' . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:labels.disableRTE', 1) . '</label>'; } // Add the function menus to bottom: $content .= $this->doc->section('', $h_func_b, 0, 0); $content .= $this->doc->spacer(10); // Select element matrix: if ($this->eRParts[0] == 'tt_content' && \TYPO3\CMS\Core\Utility\MathUtility::canBeInterpretedAsInteger($this->eRParts[1])) { $posMap = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('ext_posMap'); $posMap->backPath = $GLOBALS['BACK_PATH']; $posMap->cur_sys_language = $this->current_sys_language; $HTMLcode = ''; // CSH: $HTMLcode .= \TYPO3\CMS\Backend\Utility\BackendUtility::cshItem($this->descrTable, 'quickEdit_selElement', $GLOBALS['BACK_PATH'], '|<br />'); $HTMLcode .= $posMap->printContentElementColumns($this->id, $this->eRParts[1], $this->colPosList, $this->MOD_SETTINGS['tt_content_showHidden'], $this->R_URI); $content .= $this->doc->spacer(20); $content .= $this->doc->section($GLOBALS['LANG']->getLL('CEonThisPage'), $HTMLcode, 0, 1); $content .= $this->doc->spacer(20); } // Finally, if comments were generated in TCEforms object, print these as a HTML comment: if (count($tceforms->commentMessages)) { $content .= ' <!-- TCEFORM messages ' . htmlspecialchars(implode(LF, $tceforms->commentMessages)) . ' --> '; } return $content; }
/** * Checking if the "&edit" variable was sent so we can open it for editing the page. * Code based on code from "alt_shortcut.php" * * @return void */ protected function handlePageEditing() { if (!\TYPO3\CMS\Core\Extension\ExtensionManager::isLoaded('cms')) { return; } // EDIT page: $editId = preg_replace('/[^[:alnum:]_]/', '', \TYPO3\CMS\Core\Utility\GeneralUtility::_GET('edit')); $editRecord = ''; if ($editId) { // Looking up the page to edit, checking permissions: $where = ' AND (' . $GLOBALS['BE_USER']->getPagePermsClause(2) . ' OR ' . $GLOBALS['BE_USER']->getPagePermsClause(16) . ')'; if (\TYPO3\CMS\Core\Utility\MathUtility::canBeInterpretedAsInteger($editId)) { $editRecord = \TYPO3\CMS\Backend\Utility\BackendUtility::getRecordWSOL('pages', $editId, '*', $where); } else { $records = \TYPO3\CMS\Backend\Utility\BackendUtility::getRecordsByField('pages', 'alias', $editId, $where); if (is_array($records)) { $editRecord = reset($records); \TYPO3\CMS\Backend\Utility\BackendUtility::workspaceOL('pages', $editRecord); } } // If the page was accessible, then let the user edit it. if (is_array($editRecord) && $GLOBALS['BE_USER']->isInWebMount($editRecord['uid'])) { // Setting JS code to open editing: $this->js .= ' // Load page to edit: window.setTimeout("top.loadEditId(' . intval($editRecord['uid']) . ');", 500); '; // Checking page edit parameter: if (!$GLOBALS['BE_USER']->getTSConfigVal('options.bookmark_onEditId_dontSetPageTree')) { $bookmarkKeepExpanded = $GLOBALS['BE_USER']->getTSConfigVal('options.bookmark_onEditId_keepExistingExpanded'); // Expanding page tree: \TYPO3\CMS\Backend\Utility\BackendUtility::openPageTree(intval($editRecord['pid']), !$bookmarkKeepExpanded); } } else { $this->js .= ' // Warning about page editing: alert(' . $GLOBALS['LANG']->JScharCode(sprintf($GLOBALS['LANG']->getLL('noEditPage'), $editId)) . '); '; } } }
/** * This methods returns an array of configurations. * And no urls! * * @param integer $id Page ID * @return array Configurations from pages and configuration records */ protected function getUrlsForPageId($id) { /** * Get configuration from tsConfig */ // Get page TSconfig for page ID: $pageTSconfig = $this->getPageTSconfigForId($id); $res = array(); if (is_array($pageTSconfig) && is_array($pageTSconfig['tx_crawler.']['crawlerCfg.'])) { $crawlerCfg = $pageTSconfig['tx_crawler.']['crawlerCfg.']; if (is_array($crawlerCfg['paramSets.'])) { foreach ($crawlerCfg['paramSets.'] as $key => $values) { if (!is_array($values)) { // Sub configuration for a single configuration string: $subCfg = (array) $crawlerCfg['paramSets.'][$key . '.']; $subCfg['key'] = $key; if (strcmp($subCfg['procInstrFilter'], '')) { $subCfg['procInstrFilter'] = implode(',', \TYPO3\CMS\Core\Utility\GeneralUtility::trimExplode(',', $subCfg['procInstrFilter'])); } $pidOnlyList = implode(',', \TYPO3\CMS\Core\Utility\GeneralUtility::trimExplode(',', $subCfg['pidsOnly'], 1)); // process configuration if it is not page-specific or if the specific page is the current page: if (!strcmp($subCfg['pidsOnly'], '') || \TYPO3\CMS\Core\Utility\GeneralUtility::inList($pidOnlyList, $id)) { // add trailing slash if not present if (!empty($subCfg['baseUrl']) && substr($subCfg['baseUrl'], -1) != '/') { $subCfg['baseUrl'] .= '/'; } // Explode, process etc.: $res[$key] = array(); $res[$key]['subCfg'] = $subCfg; $res[$key]['paramParsed'] = $this->parseParams($values); $res[$key]['paramExpanded'] = $this->expandParameters($res[$key]['paramParsed'], $id); $res[$key]['origin'] = 'pagets'; // recognize MP value if (!$this->MP) { $res[$key]['URLs'] = $this->compileUrls($res[$key]['paramExpanded'], array('?id=' . $id)); } else { $res[$key]['URLs'] = $this->compileUrls($res[$key]['paramExpanded'], array('?id=' . $id . '&MP=' . $this->MP)); } } } } } } /** * Get configuration from tx_crawler_configuration records */ // get records along the rootline $rootLine = \TYPO3\CMS\Backend\Utility\BackendUtility::BEgetRootLine($id); foreach ($rootLine as $page) { $configurationRecordsForCurrentPage = \TYPO3\CMS\Backend\Utility\BackendUtility::getRecordsByField('tx_crawler_configuration', 'pid', intval($page['uid']), \TYPO3\CMS\Backend\Utility\BackendUtility::BEenableFields('tx_crawler_configuration') . \TYPO3\CMS\Backend\Utility\BackendUtility::deleteClause('tx_crawler_configuration')); if (is_array($configurationRecordsForCurrentPage)) { foreach ($configurationRecordsForCurrentPage as $configurationRecord) { // check access to the configuration record if (empty($configurationRecord['begroups']) || $GLOBALS['BE_USER']->isAdmin() || $this->hasGroupAccess($GLOBALS['BE_USER']->user['usergroup_cached_list'], $configurationRecord['begroups'])) { $pidOnlyList = implode(',', \TYPO3\CMS\Core\Utility\GeneralUtility::trimExplode(',', $configurationRecord['pidsonly'], 1)); // process configuration if it is not page-specific or if the specific page is the current page: if (!strcmp($configurationRecord['pidsonly'], '') || \TYPO3\CMS\Core\Utility\GeneralUtility::inList($pidOnlyList, $id)) { $key = $configurationRecord['name']; // don't overwrite previously defined paramSets if (!isset($res[$key])) { /* @var $TSparserObject \TYPO3\CMS\Core\TypoScript\Parser\TypoScriptParser */ $TSparserObject = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\TypoScript\\Parser\\TypoScriptParser'); $TSparserObject->parse($configurationRecord['processing_instruction_parameters_ts']); $subCfg = array('procInstrFilter' => $configurationRecord['processing_instruction_filter'], 'procInstrParams.' => $TSparserObject->setup, 'baseUrl' => $this->getBaseUrlForConfigurationRecord($configurationRecord['base_url'], $configurationRecord['sys_domain_base_url']), 'realurl' => $configurationRecord['realurl'], 'cHash' => $configurationRecord['chash'], 'userGroups' => $configurationRecord['fegroups'], 'exclude' => $configurationRecord['exclude'], 'key' => $key); // add trailing slash if not present if (!empty($subCfg['baseUrl']) && substr($subCfg['baseUrl'], -1) != '/') { $subCfg['baseUrl'] .= '/'; } if (!in_array($id, $this->expandExcludeString($subCfg['exclude']))) { $res[$key] = array(); $res[$key]['subCfg'] = $subCfg; $res[$key]['paramParsed'] = $this->parseParams($configurationRecord['configuration']); $res[$key]['paramExpanded'] = $this->expandParameters($res[$key]['paramParsed'], $id); $res[$key]['URLs'] = $this->compileUrls($res[$key]['paramExpanded'], array('?id=' . $id)); $res[$key]['origin'] = 'tx_crawler_configuration_' . $configurationRecord['uid']; } } } } } } } if (is_array($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['crawler']['processUrls'])) { foreach ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['crawler']['processUrls'] as $func) { $params = array('res' => &$res); \TYPO3\CMS\Core\Utility\GeneralUtility::callUserFunction($func, $params, $this); } } return $res; }
/** * Find l10n-overlay records and perform the requested delete action for these records. * * @param string $table Record Table * @param string $uid Record UID * @return void * @todo Define visibility */ public function deleteL10nOverlayRecords($table, $uid) { // Check whether table can be localized or has a different table defined to store localizations: if (!\TYPO3\CMS\Backend\Utility\BackendUtility::isTableLocalizable($table) || !empty($GLOBALS['TCA'][$table]['ctrl']['transForeignTable']) || !empty($GLOBALS['TCA'][$table]['ctrl']['transOrigPointerTable'])) { return; } $where = ''; if (isset($GLOBALS['TCA'][$table]['ctrl']['versioningWS']) && $GLOBALS['TCA'][$table]['ctrl']['versioningWS']) { $where = ' AND t3ver_oid=0'; } $l10nRecords = \TYPO3\CMS\Backend\Utility\BackendUtility::getRecordsByField($table, $GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField'], $uid, $where); if (is_array($l10nRecords)) { foreach ($l10nRecords as $record) { $this->deleteAction($table, intval($record['t3ver_oid']) > 0 ? intval($record['t3ver_oid']) : intval($record['uid'])); } } }
/** * First initialization of global variables * * @return void */ public function init() { parent::init(); // initialize IconFactory $this->iconFactory = GeneralUtility::makeInstance(IconFactory::class); // get the config from pageTS $temp = BackendUtility::getModTSconfig($this->id, 'mod.web_modules.dmail'); if (!is_array($temp['properties'])) { $temp['properties'] = array(); } $this->params = $temp['properties']; $this->implodedParams = DirectMailUtility::implodeTSParams($this->params); if ($this->params['userTable'] && is_array($GLOBALS['TCA'][$this->params['userTable']])) { $this->userTable = $this->params['userTable']; $this->allowedTables[] = $this->userTable; } // check if the right domain shoud be set if (!$this->params['use_domain']) { $rootLine = BackendUtility::BEgetRootLine($this->id); if ($rootLine) { $parts = parse_url(GeneralUtility::getIndpEnv('TYPO3_SITE_URL')); if (BackendUtility::getDomainStartPage($parts['host'], $parts['path'])) { $temporaryPreUrl = BackendUtility::firstDomainRecord($rootLine); $domain = BackendUtility::getRecordsByField('sys_domain', 'domainName', $temporaryPreUrl, ' AND hidden=0', '', 'sorting'); if (is_array($domain)) { reset($domain); $dom = current($domain); $this->params['use_domain'] = $dom['uid']; } } } } $this->MOD_MENU['dmail_mode'] = BackendUtility::unsetMenuItems($this->params, $this->MOD_MENU['dmail_mode'], 'menu.dmail_mode'); // initialize backend user language if ($this->getLanguageService()->lang && ExtensionManagementUtility::isLoaded('static_info_tables')) { $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('sys_language.uid', 'sys_language LEFT JOIN static_languages ON sys_language.static_lang_isocode=static_languages.uid', 'static_languages.lg_typo3=' . $GLOBALS['TYPO3_DB']->fullQuoteStr($this->getLanguageService()->lang, 'static_languages') . BackendUtility::BEenableFields('sys_language') . BackendUtility::deleteClause('sys_language') . BackendUtility::deleteClause('static_languages')); while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) { $this->sys_language_uid = $row['uid']; } $GLOBALS['TYPO3_DB']->sql_free_result($res); } // load contextual help $this->cshTable = '_MOD_' . $this->MCONF['name']; if ($GLOBALS['BE_USER']->uc['edit_showFieldHelp']) { $this->getLanguageService()->loadSingleTableDescription($this->cshTable); } }
/** * Obtains system languages. * * @return array */ protected function getSystemLanguages() { $languages = (array) \TYPO3\CMS\Backend\Utility\BackendUtility::getRecordsByField('sys_language', 'pid', 0, '', '', 'title'); $defaultLanguageLabel = $this->getDefaultLanguageName(); array_unshift($languages, array('uid' => 0, 'title' => $defaultLanguageLabel)); array_unshift($languages, array('uid' => '', 'title' => $GLOBALS['LANG']->getLL('all_languages'))); return $languages; }
/** * Checking if the "&edit" variable was sent so we can open it for editing the page. * * @return void */ protected function handlePageEditing() { $beUser = $this->getBackendUser(); // EDIT page: $editId = preg_replace('/[^[:alnum:]_]/', '', GeneralUtility::_GET('edit')); $editRecord = ''; if ($editId) { // Looking up the page to edit, checking permissions: $where = ' AND (' . $beUser->getPagePermsClause(2) . ' OR ' . $beUser->getPagePermsClause(16) . ')'; if (MathUtility::canBeInterpretedAsInteger($editId)) { $editRecord = BackendUtility::getRecordWSOL('pages', $editId, '*', $where); } else { $records = BackendUtility::getRecordsByField('pages', 'alias', $editId, $where); if (is_array($records)) { $editRecord = reset($records); BackendUtility::workspaceOL('pages', $editRecord); } } // If the page was accessible, then let the user edit it. if (is_array($editRecord) && $beUser->isInWebMount($editRecord['uid'])) { // Setting JS code to open editing: $this->js .= ' // Load page to edit: window.setTimeout("top.loadEditId(' . (int) $editRecord['uid'] . ');", 500); '; // Checking page edit parameter: if (!$beUser->getTSConfigVal('options.bookmark_onEditId_dontSetPageTree')) { $bookmarkKeepExpanded = $beUser->getTSConfigVal('options.bookmark_onEditId_keepExistingExpanded'); // Expanding page tree: BackendUtility::openPageTree((int) $editRecord['pid'], !$bookmarkKeepExpanded); } } else { $this->js .= ' // Warning about page editing: alert(' . GeneralUtility::quoteJSvalue(sprintf($this->getLanguageService()->getLL('noEditPage'), $editId)) . '); '; } } }
/** * Get the available languages of a certain page * * @param int $pageId * @return array */ public function getAvailableLanguages($pageId) { $languageOptions = array(); /** @var \TYPO3\CMS\Backend\Configuration\TranslationConfigurationProvider $translationConfigurationProvider */ $translationConfigurationProvider = GeneralUtility::makeInstance(\TYPO3\CMS\Backend\Configuration\TranslationConfigurationProvider::class); $systemLanguages = $translationConfigurationProvider->getSystemLanguages($pageId); if ($GLOBALS['BE_USER']->checkLanguageAccess(0)) { // Use configured label for default language $languageOptions[0] = $systemLanguages[0]['title']; } $pages = BackendUtility::getRecordsByField('pages_language_overlay', 'pid', $pageId); if (!is_array($pages)) { return $languageOptions; } foreach ($pages as $page) { $languageId = (int) $page['sys_language_uid']; // Only add links to active languages the user has access to if (isset($systemLanguages[$languageId]) && $GLOBALS['BE_USER']->checkLanguageAccess($languageId)) { $languageOptions[$page['sys_language_uid']] = $systemLanguages[$languageId]['title']; } } return $languageOptions; }
/** * add localized page records to a cache/globalArray * This is much faster than requesting the DB for each tt_content-record * * @param array $pageRow * @return void */ public function addLocalizedPagesToCache($pageRow) { // create entry in cachedPageRecods for default language $this->cachedPageRecords[0][$pageRow['uid']] = $pageRow; // create entry in cachedPageRecods for additional languages, skip default language 0 foreach ($this->sysLanguages as $sysLang) { if ($sysLang[1] > 0) { list($pageOverlay) = \TYPO3\CMS\Backend\Utility\BackendUtility::getRecordsByField('pages_language_overlay', 'pid', $pageRow['uid'], 'AND sys_language_uid=' . intval($sysLang[1])); if ($pageOverlay) { $this->cachedPageRecords[$sysLang[1]][$pageRow['uid']] = \TYPO3\CMS\Core\Utility\GeneralUtility::array_merge($pageRow, $pageOverlay); } } } }
/** * @param $edit_record array * * @return array */ protected function makeQuickEditMenu($edit_record) { $lang = $this->getLanguageService(); $beUser = $this->getBackendUser(); $quickEditMenu = $this->moduleTemplate->getDocHeaderComponent()->getMenuRegistry()->makeMenu(); $quickEditMenu->setIdentifier('quickEditMenu'); $quickEditMenu->setLabel(''); // Setting close url/return url for exiting this script: // Goes to 'Columns' view if close is pressed (default) $this->closeUrl = $this->local_linkThisScript(['SET' => ['function' => 1]]); if ($this->returnUrl) { $this->closeUrl = $this->returnUrl; } $retUrlStr = $this->returnUrl ? '&returnUrl=' . rawurlencode($this->returnUrl) : ''; // Creating the selector box, allowing the user to select which element to edit: $isSelected = 0; $languageOverlayRecord = ''; if ($this->current_sys_language) { list($languageOverlayRecord) = BackendUtility::getRecordsByField('pages_language_overlay', 'pid', $this->id, 'AND sys_language_uid=' . (int) $this->current_sys_language); } if (is_array($languageOverlayRecord)) { $inValue = 'pages_language_overlay:' . $languageOverlayRecord['uid']; $isSelected += (int) $edit_record == $inValue; $menuItem = $quickEditMenu->makeMenuItem()->setTitle('[ ' . $lang->getLL('editLanguageHeader') . ' ]')->setHref(BackendUtility::getModuleUrl($this->moduleName) . '&id=' . $this->id . '&edit_record=' . $inValue . $retUrlStr)->setActive($edit_record == $inValue); $quickEditMenu->addMenuItem($menuItem); } else { $inValue = 'pages:' . $this->id; $isSelected += (int) $edit_record == $inValue; $menuItem = $quickEditMenu->makeMenuItem()->setTitle('[ ' . $lang->getLL('editPageProperties') . ' ]')->setHref(BackendUtility::getModuleUrl($this->moduleName) . '&id=' . $this->id . '&edit_record=' . $inValue . $retUrlStr)->setActive($edit_record == $inValue); $quickEditMenu->addMenuItem($menuItem); } $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('tt_content'); if ($this->MOD_SETTINGS['tt_content_showHidden']) { $queryBuilder->getRestrictions()->removeAll()->add(GeneralUtility::makeInstance(DeletedRestriction::class)); } $queryBuilder->select('*')->from('tt_content')->where($queryBuilder->expr()->eq('pid', $queryBuilder->createNamedParameter($this->id, \PDO::PARAM_INT)), $queryBuilder->expr()->eq('sys_language_uid', $queryBuilder->createNamedParameter($this->current_sys_language, \PDO::PARAM_INT)), $queryBuilder->expr()->in('colPos', $queryBuilder->createNamedParameter(GeneralUtility::intExplode(',', $this->colPosList, true), Connection::PARAM_INT_ARRAY)), $queryBuilder->expr()->orX($queryBuilder->expr()->gte('t3ver_state', $queryBuilder->createNamedParameter((string) new VersionState(VersionState::DEFAULT_STATE), \PDO::PARAM_INT)), $queryBuilder->expr()->eq('t3ver_wsid', $queryBuilder->createNamedParameter((string) new VersionState(VersionState::DEFAULT_STATE), \PDO::PARAM_INT))))->orderBy('colPos')->addOrderBy('sorting'); if (!$beUser->user['admin']) { $queryBuilder->andWhere($queryBuilder->expr()->eq('editlock', $queryBuilder->createNamedParameter(0, \PDO::PARAM_INT))); } $statement = $queryBuilder->execute(); $colPos = null; $first = 1; // Page is the pid if no record to put this after. $prev = $this->id; while ($cRow = $statement->fetch()) { BackendUtility::workspaceOL('tt_content', $cRow); if (is_array($cRow)) { if ($first) { if (!$edit_record) { $edit_record = 'tt_content:' . $cRow['uid']; } $first = 0; } if (!isset($colPos) || $cRow['colPos'] !== $colPos) { $colPos = $cRow['colPos']; $menuItem = $quickEditMenu->makeMenuItem()->setTitle(' ')->setHref('#'); $quickEditMenu->addMenuItem($menuItem); $menuItem = $quickEditMenu->makeMenuItem()->setTitle('__' . $lang->sL(BackendUtility::getLabelFromItemlist('tt_content', 'colPos', $colPos)) . ':__')->setHref(BackendUtility::getModuleUrl($this->moduleName) . '&id=' . $this->id . '&edit_record=_EDIT_COL:' . $colPos . $retUrlStr); $quickEditMenu->addMenuItem($menuItem); } $inValue = 'tt_content:' . $cRow['uid']; $isSelected += (int) $edit_record == $inValue; $menuItem = $quickEditMenu->makeMenuItem()->setTitle(GeneralUtility::fixed_lgd_cs($cRow['header'] ? $cRow['header'] : '[' . $lang->sL('LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:labels.no_title') . '] ' . strip_tags($cRow['bodytext']), $beUser->uc['titleLen']))->setHref(BackendUtility::getModuleUrl($this->moduleName) . '&id=' . $this->id . '&edit_record=' . $inValue . $retUrlStr)->setActive($edit_record == $inValue); $quickEditMenu->addMenuItem($menuItem); $prev = -$cRow['uid']; } } // If edit_record is not set (meaning, no content elements was found for this language) we simply set it to create a new element: if (!$edit_record) { $edit_record = 'tt_content:new/' . $prev . '/' . $colPos; $inValue = 'tt_content:new/' . $prev . '/' . $colPos; $isSelected += (int) $edit_record == $inValue; $menuItem = $quickEditMenu->makeMenuItem()->setTitle('[ ' . $lang->getLL('newLabel') . ' ]')->setHref(BackendUtility::getModuleUrl($this->moduleName) . '&id=' . $this->id . '&edit_record=' . $inValue . $retUrlStr)->setActive($edit_record == $inValue); $quickEditMenu->addMenuItem($menuItem); } // If none is yet selected... if (!$isSelected) { $menuItem = $quickEditMenu->makeMenuItem()->setTitle('__________')->setHref('#'); $quickEditMenu->addMenuItem($menuItem); $menuItem = $quickEditMenu->makeMenuItem()->setTitle('[ ' . $lang->getLL('newLabel') . ' ]')->setHref(BackendUtility::getModuleUrl($this->moduleName) . '&id=' . $this->id . '&edit_record=' . $edit_record . $retUrlStr)->setActive($edit_record == $inValue); $quickEditMenu->addMenuItem($menuItem); } $this->moduleTemplate->getDocHeaderComponent()->getMenuRegistry()->addMenu($quickEditMenu); return $edit_record; }
/** * Transformation handler: 'ts_links' / direction: "rte" * Converting <link tags> to <A>-tags * * @param string $value Content input * @return string Content output * @see TS_links_rte() */ public function TS_links_rte($value) { $conf = array(); $value = $this->TS_AtagToAbs($value); // Split content by the TYPO3 pseudo tag "<link>": $blockSplit = $this->splitIntoBlock('link', $value, 1); $siteUrl = $this->siteUrl(); foreach ($blockSplit as $k => $v) { $error = ''; $external = false; // Block if ($k % 2) { // split away the first "<link" part $typolink = explode(' ', substr($this->getFirstTag($v), 0, -1), 2)[1]; $tagCode = GeneralUtility::makeInstance(TypoLinkCodecService::class)->decode($typolink); $link_param = $tagCode['url']; // Parsing the typolink data. This parsing is roughly done like in \TYPO3\CMS\Frontend\ContentObject->typoLink() // Parse URL: $pU = parse_url($link_param); if (strstr($link_param, '@') && (!$pU['scheme'] || $pU['scheme'] == 'mailto')) { // mailadr $href = 'mailto:' . preg_replace('/^mailto:/i', '', $link_param); } elseif ($link_param[0] === '#') { // check if anchor $href = $siteUrl . $link_param; } else { // Check for FAL link-handler keyword: list($linkHandlerKeyword, $linkHandlerValue) = explode(':', trim($link_param), 2); if ($linkHandlerKeyword === 'file' && !StringUtility::beginsWith($link_param, 'file://')) { $href = $siteUrl . '?' . $linkHandlerKeyword . ':' . rawurlencode($linkHandlerValue); } else { $fileChar = (int) strpos($link_param, '/'); $urlChar = (int) strpos($link_param, '.'); // Detects if a file is found in site-root. list($rootFileDat) = explode('?', $link_param); $rFD_fI = pathinfo($rootFileDat); if (trim($rootFileDat) && !strstr($link_param, '/') && (@is_file(PATH_site . $rootFileDat) || GeneralUtility::inList('php,html,htm', strtolower($rFD_fI['extension'])))) { $href = $siteUrl . $link_param; } elseif ($pU['scheme'] && !isset($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['typolinkLinkHandler'][$pU['scheme']]) || $urlChar && (!$fileChar || $urlChar < $fileChar)) { // url (external): if has scheme or if a '.' comes before a '/'. $href = $link_param; if (!$pU['scheme']) { $href = 'http://' . $href; } $external = true; } elseif ($fileChar) { // It is an internal file or folder // Try to transform the href into a FAL reference try { $fileOrFolderObject = \TYPO3\CMS\Core\Resource\ResourceFactory::getInstance()->retrieveFileOrFolderObject($link_param); } catch (\TYPO3\CMS\Core\Resource\Exception $exception) { // Nothing to be done if file/folder not found or path invalid $fileOrFolderObject = null; } if ($fileOrFolderObject instanceof \TYPO3\CMS\Core\Resource\Folder) { // It's a folder $folderIdentifier = $fileOrFolderObject->getIdentifier(); $href = $siteUrl . '?file:' . rawurlencode($folderIdentifier); } elseif ($fileOrFolderObject instanceof \TYPO3\CMS\Core\Resource\FileInterface) { // It's a file $fileIdentifier = $fileOrFolderObject->getIdentifier(); $fileObject = $fileOrFolderObject->getStorage()->getFile($fileIdentifier); $href = $siteUrl . '?file:' . $fileObject->getUid(); } else { $href = $siteUrl . $link_param; } } else { // integer or alias (alias is without slashes or periods or commas, that is 'nospace,alphanum_x,lower,unique' according to tables.php!!) // Splitting the parameter by ',' and if the array counts more than 1 element it's an id/type/parameters triplet $pairParts = GeneralUtility::trimExplode(',', $link_param, true); $idPart = $pairParts[0]; $link_params_parts = explode('#', $idPart); $idPart = trim($link_params_parts[0]); $sectionMark = trim($link_params_parts[1]); if ((string) $idPart === '') { $idPart = $this->recPid; } // If no id or alias is given, set it to class record pid // Checking if the id-parameter is an alias. if (!\TYPO3\CMS\Core\Utility\MathUtility::canBeInterpretedAsInteger($idPart)) { list($idPartR) = BackendUtility::getRecordsByField('pages', 'alias', $idPart); $idPart = (int) $idPartR['uid']; } $page = BackendUtility::getRecord('pages', $idPart); if (is_array($page)) { // Page must exist... $href = $siteUrl . '?id=' . $idPart . ($pairParts[2] ? $pairParts[2] : '') . ($sectionMark ? '#' . $sectionMark : ''); } elseif (isset($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['typolinkLinkHandler'][array_shift(explode(':', $link_param))])) { $href = $link_param; } else { $href = $siteUrl . '?id=' . $link_param; $error = 'No page found: ' . $idPart; } } } } // Setting the A-tag: $bTag = '<a href="' . htmlspecialchars($href) . '"' . ($tagCode['target'] ? ' target="' . htmlspecialchars($tagCode['target']) . '"' : '') . ($tagCode['class'] ? ' class="' . htmlspecialchars($tagCode['class']) . '"' : '') . ($tagCode['title'] ? ' title="' . htmlspecialchars($tagCode['title']) . '"' : '') . ($external ? ' data-htmlarea-external="1"' : '') . ($error ? ' rteerror="' . htmlspecialchars($error) . '" style="background-color: yellow; border:2px red solid; color: black;"' : '') . '>'; $eTag = '</a>'; // Modify parameters if (isset($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_parsehtml_proc.php']['modifyParams_LinksRte_PostProc']) && is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_parsehtml_proc.php']['modifyParams_LinksRte_PostProc'])) { $parameters = array('conf' => &$conf, 'currentBlock' => $v, 'url' => $href, 'tagCode' => $tagCode, 'external' => $external, 'error' => $error); foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_parsehtml_proc.php']['modifyParams_LinksRte_PostProc'] as $objRef) { $processor = GeneralUtility::getUserObj($objRef); $blockSplit[$k] = $processor->modifyParamsLinksRte($parameters, $this); } } else { $blockSplit[$k] = $bTag . $this->TS_links_rte($this->removeFirstAndLastTag($blockSplit[$k])) . $eTag; } } } // Return content: return implode('', $blockSplit); }
/** * @param string $theTable Table name present in $GLOBALS['TCA'] * @param string $theField Field to select on * @param string $theValue Value that $theField must match * @param string $whereClause Optional additional WHERE clauses put in the end of the query. DO NOT PUT IN GROUP BY, ORDER BY or LIMIT! * @param string $groupBy Optional GROUP BY field(s), if none, supply blank string. * @param string $orderBy Optional ORDER BY field(s), if none, supply blank string. * @param string $limit Optional LIMIT value ([begin,]max), if none, supply blank string. * @param bool $useDeleteClause Use the deleteClause to check if a record is deleted (default TRUE) * @return mixed Multidimensional array with selected records (if any is selected) */ public function getRecordsByField($theTable, $theField, $theValue, $whereClause = '', $groupBy = '', $orderBy = '', $limit = '', $useDeleteClause = TRUE) { return BackendUtility::getRecordsByField($theTable, $theField, $theValue, $whereClause, $groupBy, $orderBy, $limit, $useDeleteClause); }
/** * Renders Content Elements from the tt_content table from page id * * @param int $id Page id * @return string HTML for the listing */ public function getTable_tt_content($id) { $backendUser = $this->getBackendUser(); $this->pageinfo = BackendUtility::readPageAccess($this->id, $backendUser->getPagePermsClause($this->ext_CALC_PERMS)); $this->initializeLanguages(); $this->initializeClipboard(); $pageTitleParamForAltDoc = '&recTitle=' . rawurlencode(BackendUtility::getRecordTitle('pages', BackendUtility::getRecordWSOL('pages', $id), true)); /** @var $pageRenderer PageRenderer */ $pageRenderer = GeneralUtility::makeInstance(PageRenderer::class); $pageRenderer->loadRequireJsModule('TYPO3/CMS/Backend/LayoutModule/DragDrop'); $pageRenderer->loadRequireJsModule('TYPO3/CMS/Backend/Modal'); $userCanEditPage = $this->ext_CALC_PERMS & Permission::PAGE_EDIT && !empty($this->id) && ($backendUser->isAdmin() || (int) $this->pageinfo['editlock'] === 0); if ($this->tt_contentConfig['languageColsPointer'] > 0) { $userCanEditPage = $this->getBackendUser()->check('tables_modify', 'pages_language_overlay'); } if ($userCanEditPage) { $pageRenderer->loadRequireJsModule('TYPO3/CMS/Backend/PageActions', 'function(PageActions) { PageActions.setPageId(' . (int) $this->id . '); PageActions.setLanguageOverlayId(' . $this->tt_contentConfig['languageColsPointer'] . '); PageActions.initializePageTitleRenaming(); }'); } // Get labels for CTypes and tt_content element fields in general: $this->CType_labels = array(); foreach ($GLOBALS['TCA']['tt_content']['columns']['CType']['config']['items'] as $val) { $this->CType_labels[$val[1]] = $this->getLanguageService()->sL($val[0]); } $this->itemLabels = array(); foreach ($GLOBALS['TCA']['tt_content']['columns'] as $name => $val) { $this->itemLabels[$name] = $this->getLanguageService()->sL($val['label']); } $languageColumn = array(); $out = ''; // Setting language list: $langList = $this->tt_contentConfig['sys_language_uid']; if ($this->tt_contentConfig['languageMode']) { if ($this->tt_contentConfig['languageColsPointer']) { $langList = '0,' . $this->tt_contentConfig['languageColsPointer']; } else { $langList = implode(',', array_keys($this->tt_contentConfig['languageCols'])); } $languageColumn = array(); } $langListArr = GeneralUtility::intExplode(',', $langList); $defLanguageCount = array(); $defLangBinding = array(); // For each languages... : // If not languageMode, then we'll only be through this once. foreach ($langListArr as $lP) { $lP = (int) $lP; if (!isset($this->contentElementCache[$lP])) { $this->contentElementCache[$lP] = array(); } if (count($langListArr) === 1 || $lP === 0) { $showLanguage = ' AND sys_language_uid IN (' . $lP . ',-1)'; } else { $showLanguage = ' AND sys_language_uid=' . $lP; } $cList = explode(',', $this->tt_contentConfig['cols']); $content = array(); $head = array(); // Select content records per column $contentRecordsPerColumn = $this->getContentRecordsPerColumn('table', $id, array_values($cList), $showLanguage); // For each column, render the content into a variable: foreach ($cList as $key) { if (!isset($this->contentElementCache[$lP][$key])) { $this->contentElementCache[$lP][$key] = array(); } if (!$lP) { $defLanguageCount[$key] = array(); } // Start wrapping div $content[$key] .= '<div data-colpos="' . $key . '" data-language-uid="' . $lP . '" class="t3js-sortable t3js-sortable-lang t3js-sortable-lang-' . $lP . ' t3-page-ce-wrapper'; if (empty($contentRecordsPerColumn[$key])) { $content[$key] .= ' t3-page-ce-empty'; } $content[$key] .= '">'; // Add new content at the top most position $link = ''; if ($this->getPageLayoutController()->pageIsNotLockedForEditors() && $this->getBackendUser()->doesUserHaveAccess($this->pageinfo, Permission::CONTENT_EDIT)) { $link = '<a href="#" onclick="' . htmlspecialchars($this->newContentElementOnClick($id, $key, $lP)) . '" title="' . $this->getLanguageService()->getLL('newContentElement', true) . '" class="btn btn-default btn-sm">' . $this->iconFactory->getIcon('actions-document-new', Icon::SIZE_SMALL)->render() . ' ' . $this->getLanguageService()->getLL('content', true) . '</a>'; } $content[$key] .= ' <div class="t3-page-ce t3js-page-ce" data-page="' . (int) $id . '" id="' . StringUtility::getUniqueId() . '"> <div class="t3js-page-new-ce t3-page-ce-wrapper-new-ce" id="colpos-' . $key . '-' . 'page-' . $id . '-' . StringUtility::getUniqueId() . '">' . $link . '</div> <div class="t3-page-ce-dropzone-available t3js-page-ce-dropzone-available"></div> </div> '; $editUidList = ''; $rowArr = $contentRecordsPerColumn[$key]; $this->generateTtContentDataArray($rowArr); foreach ((array) $rowArr as $rKey => $row) { $this->contentElementCache[$lP][$key][$row['uid']] = $row; if ($this->tt_contentConfig['languageMode']) { $languageColumn[$key][$lP] = $head[$key] . $content[$key]; if (!$this->defLangBinding) { $languageColumn[$key][$lP] .= $this->newLanguageButton($this->getNonTranslatedTTcontentUids($defLanguageCount[$key], $id, $lP), $lP, $key); } } if (is_array($row) && !VersionState::cast($row['t3ver_state'])->equals(VersionState::DELETE_PLACEHOLDER)) { $singleElementHTML = ''; if (!$lP && ($this->defLangBinding || $row['sys_language_uid'] != -1)) { $defLanguageCount[$key][] = isset($row['_ORIG_uid']) ? $row['_ORIG_uid'] : $row['uid']; } $editUidList .= $row['uid'] . ','; $disableMoveAndNewButtons = $this->defLangBinding && $lP > 0; if (!$this->tt_contentConfig['languageMode']) { $singleElementHTML .= '<div class="t3-page-ce-dragitem" id="' . StringUtility::getUniqueId() . '">'; } $singleElementHTML .= $this->tt_content_drawHeader($row, $this->tt_contentConfig['showInfo'] ? 15 : 5, $disableMoveAndNewButtons, !$this->tt_contentConfig['languageMode'], $this->getBackendUser()->doesUserHaveAccess($this->pageinfo, Permission::CONTENT_EDIT)); $innerContent = '<div ' . ($row['_ORIG_uid'] ? ' class="ver-element"' : '') . '>' . $this->tt_content_drawItem($row) . '</div>'; $singleElementHTML .= '<div class="t3-page-ce-body-inner">' . $innerContent . '</div>' . $this->tt_content_drawFooter($row); $isDisabled = $this->isDisabled('tt_content', $row); $statusHidden = $isDisabled ? ' t3-page-ce-hidden t3js-hidden-record' : ''; $displayNone = !$this->tt_contentConfig['showHidden'] && $isDisabled ? ' style="display: none;"' : ''; $singleElementHTML = '<div class="t3-page-ce t3js-page-ce t3js-page-ce-sortable ' . $statusHidden . '" id="element-tt_content-' . $row['uid'] . '" data-table="tt_content" data-uid="' . $row['uid'] . '"' . $displayNone . '>' . $singleElementHTML . '</div>'; if ($this->tt_contentConfig['languageMode']) { $singleElementHTML .= '<div class="t3-page-ce t3js-page-ce">'; } $singleElementHTML .= '<div class="t3js-page-new-ce t3-page-ce-wrapper-new-ce" id="colpos-' . $key . '-' . 'page-' . $id . '-' . StringUtility::getUniqueId() . '">'; // Add icon "new content element below" if (!$disableMoveAndNewButtons && $this->getPageLayoutController()->pageIsNotLockedForEditors() && $this->getBackendUser()->doesUserHaveAccess($this->pageinfo, Permission::CONTENT_EDIT)) { // New content element: if ($this->option_newWizard) { $onClick = 'window.location.href=' . GeneralUtility::quoteJSvalue(BackendUtility::getModuleUrl('new_content_element') . '&id=' . $row['pid'] . '&sys_language_uid=' . $row['sys_language_uid'] . '&colPos=' . $row['colPos'] . '&uid_pid=' . -$row['uid'] . '&returnUrl=' . rawurlencode(GeneralUtility::getIndpEnv('REQUEST_URI'))) . ';'; } else { $params = '&edit[tt_content][' . -$row['uid'] . ']=new'; $onClick = BackendUtility::editOnClick($params); } $singleElementHTML .= ' <a href="#" onclick="' . htmlspecialchars($onClick) . '" title="' . $this->getLanguageService()->getLL('newContentElement', true) . '" class="btn btn-default btn-sm">' . $this->iconFactory->getIcon('actions-document-new', Icon::SIZE_SMALL)->render() . ' ' . $this->getLanguageService()->getLL('content', true) . '</a> '; } $singleElementHTML .= '</div></div><div class="t3-page-ce-dropzone-available t3js-page-ce-dropzone-available"></div></div>'; if ($this->defLangBinding && $this->tt_contentConfig['languageMode']) { $defLangBinding[$key][$lP][$row[$lP ? 'l18n_parent' : 'uid']] = $singleElementHTML; } else { $content[$key] .= $singleElementHTML; } } else { unset($rowArr[$rKey]); } } $content[$key] .= '</div>'; // Add new-icon link, header: $newP = $this->newContentElementOnClick($id, $key, $lP); $colTitle = BackendUtility::getProcessedValue('tt_content', 'colPos', $key); $tcaItems = GeneralUtility::callUserFunction(\TYPO3\CMS\Backend\View\BackendLayoutView::class . '->getColPosListItemsParsed', $id, $this); foreach ($tcaItems as $item) { if ($item[1] == $key) { $colTitle = $this->getLanguageService()->sL($item[0]); } } $pasteP = array('colPos' => $key, 'sys_language_uid' => $lP); $editParam = $this->doEdit && !empty($rowArr) ? '&edit[tt_content][' . $editUidList . ']=edit' . $pageTitleParamForAltDoc : ''; $head[$key] .= $this->tt_content_drawColHeader($colTitle, $editParam, $newP, $pasteP); } // For each column, fit the rendered content into a table cell: $out = ''; if ($this->tt_contentConfig['languageMode']) { // in language mode process the content elements, but only fill $languageColumn. output will be generated later $sortedLanguageColumn = array(); foreach ($cList as $key) { $languageColumn[$key][$lP] = $head[$key] . $content[$key]; if (!$this->defLangBinding) { $languageColumn[$key][$lP] .= $this->newLanguageButton($this->getNonTranslatedTTcontentUids($defLanguageCount[$key], $id, $lP), $lP, $key); } // We sort $languageColumn again according to $cList as it may contain data already from above. $sortedLanguageColumn[$key] = $languageColumn[$key]; } $languageColumn = $sortedLanguageColumn; } else { $backendLayout = $this->getBackendLayoutView()->getSelectedBackendLayout($this->id); // GRID VIEW: $grid = '<div class="t3-grid-container"><table border="0" cellspacing="0" cellpadding="0" width="100%" class="t3-page-columns t3-grid-table t3js-page-columns">'; // Add colgroups $colCount = (int) $backendLayout['__config']['backend_layout.']['colCount']; $rowCount = (int) $backendLayout['__config']['backend_layout.']['rowCount']; $grid .= '<colgroup>'; for ($i = 0; $i < $colCount; $i++) { $grid .= '<col style="width:' . 100 / $colCount . '%"></col>'; } $grid .= '</colgroup>'; // Cycle through rows for ($row = 1; $row <= $rowCount; $row++) { $rowConfig = $backendLayout['__config']['backend_layout.']['rows.'][$row . '.']; if (!isset($rowConfig)) { continue; } $grid .= '<tr>'; for ($col = 1; $col <= $colCount; $col++) { $columnConfig = $rowConfig['columns.'][$col . '.']; if (!isset($columnConfig)) { continue; } // Which tt_content colPos should be displayed inside this cell $columnKey = (int) $columnConfig['colPos']; // Render the grid cell $colSpan = (int) $columnConfig['colspan']; $rowSpan = (int) $columnConfig['rowspan']; $grid .= '<td valign="top"' . ($colSpan > 0 ? ' colspan="' . $colSpan . '"' : '') . ($rowSpan > 0 ? ' rowspan="' . $rowSpan . '"' : '') . ' data-colpos="' . (int) $columnConfig['colPos'] . '" data-language-uid="' . $lP . '" class="t3js-page-lang-column-' . $lP . ' t3js-page-column t3-grid-cell t3-page-column t3-page-column-' . $columnKey . (!isset($columnConfig['colPos']) || $columnConfig['colPos'] === '' ? ' t3-grid-cell-unassigned' : '') . (isset($columnConfig['colPos']) && $columnConfig['colPos'] !== '' && !$head[$columnKey] || !GeneralUtility::inList($this->tt_contentConfig['activeCols'], $columnConfig['colPos']) ? ' t3-grid-cell-restricted' : '') . ($colSpan > 0 ? ' t3-gridCell-width' . $colSpan : '') . ($rowSpan > 0 ? ' t3-gridCell-height' . $rowSpan : '') . '">'; // Draw the pre-generated header with edit and new buttons if a colPos is assigned. // If not, a new header without any buttons will be generated. if (isset($columnConfig['colPos']) && $columnConfig['colPos'] !== '' && $head[$columnKey] && GeneralUtility::inList($this->tt_contentConfig['activeCols'], $columnConfig['colPos'])) { $grid .= $head[$columnKey] . $content[$columnKey]; } elseif (isset($columnConfig['colPos']) && $columnConfig['colPos'] !== '' && GeneralUtility::inList($this->tt_contentConfig['activeCols'], $columnConfig['colPos'])) { $grid .= $this->tt_content_drawColHeader($this->getLanguageService()->getLL('noAccess'), '', ''); } elseif (isset($columnConfig['colPos']) && $columnConfig['colPos'] !== '' && !GeneralUtility::inList($this->tt_contentConfig['activeCols'], $columnConfig['colPos'])) { $grid .= $this->tt_content_drawColHeader($this->getLanguageService()->sL($columnConfig['name']) . ' (' . $this->getLanguageService()->getLL('noAccess') . ')', '', ''); } elseif (isset($columnConfig['name']) && $columnConfig['name'] !== '') { $grid .= $this->tt_content_drawColHeader($this->getLanguageService()->sL($columnConfig['name']) . ' (' . $this->getLanguageService()->getLL('notAssigned') . ')', '', ''); } else { $grid .= $this->tt_content_drawColHeader($this->getLanguageService()->getLL('notAssigned'), '', ''); } $grid .= '</td>'; } $grid .= '</tr>'; } $out .= $grid . '</table></div>'; } // CSH: $out .= BackendUtility::cshItem($this->descrTable, 'columns_multi'); } // If language mode, then make another presentation: // Notice that THIS presentation will override the value of $out! // But it needs the code above to execute since $languageColumn is filled with content we need! if ($this->tt_contentConfig['languageMode']) { // Get language selector: $languageSelector = $this->languageSelector($id); // Reset out - we will make new content here: $out = ''; // Traverse languages found on the page and build up the table displaying them side by side: $cCont = array(); $sCont = array(); foreach ($langListArr as $lP) { // Header: $lP = (int) $lP; $cCont[$lP] = ' <td valign="top" class="t3-page-column" data-language-uid="' . $lP . '"> <h2>' . htmlspecialchars($this->tt_contentConfig['languageCols'][$lP]) . '</h2> </td>'; // "View page" icon is added: $viewLink = ''; if (!VersionState::cast($this->getPageLayoutController()->pageinfo['t3ver_state'])->equals(VersionState::DELETE_PLACEHOLDER)) { $onClick = BackendUtility::viewOnClick($this->id, '', BackendUtility::BEgetRootLine($this->id), '', '', '&L=' . $lP); $viewLink = '<a href="#" class="btn btn-default btn-sm" onclick="' . htmlspecialchars($onClick) . '" title="' . $this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:labels.showPage', true) . '">' . $this->iconFactory->getIcon('actions-view', Icon::SIZE_SMALL)->render() . '</a>'; } // Language overlay page header: if ($lP) { list($lpRecord) = BackendUtility::getRecordsByField('pages_language_overlay', 'pid', $id, 'AND sys_language_uid=' . $lP); BackendUtility::workspaceOL('pages_language_overlay', $lpRecord); $params = '&edit[pages_language_overlay][' . $lpRecord['uid'] . ']=edit&overrideVals[pages_language_overlay][sys_language_uid]=' . $lP; $recordIcon = BackendUtility::wrapClickMenuOnIcon($this->iconFactory->getIconForRecord('pages_language_overlay', $lpRecord, Icon::SIZE_SMALL)->render(), 'pages_language_overlay', $lpRecord['uid']); $editLink = $this->getBackendUser()->check('tables_modify', 'pages_language_overlay') ? '<a href="#" class="btn btn-default btn-sm" onclick="' . htmlspecialchars(BackendUtility::editOnClick($params)) . '" title="' . $this->getLanguageService()->getLL('edit', true) . '">' . $this->iconFactory->getIcon('actions-open', Icon::SIZE_SMALL)->render() . '</a>' : ''; $lPLabel = '<div class="btn-group">' . $viewLink . $editLink . '</div>' . ' ' . $recordIcon . ' ' . htmlspecialchars(GeneralUtility::fixed_lgd_cs($lpRecord['title'], 20)); } else { $params = '&edit[pages][' . $this->id . ']=edit'; $recordIcon = BackendUtility::wrapClickMenuOnIcon($this->iconFactory->getIconForRecord('pages', $this->pageRecord, Icon::SIZE_SMALL)->render(), 'pages', $this->id); $editLink = $this->getBackendUser()->check('tables_modify', 'pages_language_overlay') ? '<a href="#" class="btn btn-default btn-sm" onclick="' . htmlspecialchars(BackendUtility::editOnClick($params)) . '" title="' . $this->getLanguageService()->getLL('edit', true) . '">' . $this->iconFactory->getIcon('actions-open', Icon::SIZE_SMALL)->render() . '</a>' : ''; $lPLabel = '<div class="btn-group">' . $viewLink . $editLink . '</div>' . ' ' . $recordIcon . ' ' . htmlspecialchars(GeneralUtility::fixed_lgd_cs($this->pageRecord['title'], 20)); } $sCont[$lP] = ' <td nowrap="nowrap" class="t3-page-column t3-page-lang-label">' . $lPLabel . '</td>'; } // Add headers: $out .= '<tr>' . implode($cCont) . '</tr>'; $out .= '<tr>' . implode($sCont) . '</tr>'; unset($cCont, $sCont); // Traverse previously built content for the columns: foreach ($languageColumn as $cKey => $cCont) { $out .= '<tr>'; foreach ($cCont as $languageId => $columnContent) { $out .= '<td valign="top" class="t3-grid-cell t3-page-column t3js-page-column t3js-page-lang-column t3js-page-lang-column-' . $languageId . '">' . $columnContent . '</td>'; } $out .= '</tr>'; if ($this->defLangBinding) { // "defLangBinding" mode foreach ($defLanguageCount[$cKey] as $defUid) { $cCont = array(); foreach ($langListArr as $lP) { $cCont[] = $defLangBinding[$cKey][$lP][$defUid] . $this->newLanguageButton($this->getNonTranslatedTTcontentUids(array($defUid), $id, $lP), $lP, $cKey); } $out .= ' <tr> <td valign="top" class="t3-grid-cell">' . implode('</td>' . ' <td valign="top" class="t3-grid-cell">', $cCont) . '</td> </tr>'; } } } // Finally, wrap it all in a table and add the language selector on top of it: $out = $languageSelector . ' <div class="t3-grid-container"> <table cellpadding="0" cellspacing="0" class="t3-page-columns t3-grid-table t3js-page-columns"> ' . $out . ' </table> </div>'; // CSH: $out .= BackendUtility::cshItem($this->descrTable, 'language_list'); } return $out; }
/** * Rendering the quick-edit view. * * @return string */ public function renderQuickEdit() { $databaseConnection = $this->getDatabaseConnection(); $beUser = $this->getBackendUser(); $lang = $this->getLanguageService(); // Alternative template $this->doc->setModuleTemplate('EXT:backend/Resources/Private/Templates/db_layout_quickedit.html'); // Alternative form tag; Quick Edit submits its content to tce_db.php. $this->doc->form = '<form action="' . htmlspecialchars(BackendUtility::getModuleUrl('tce_db', ['prErr' => 1, 'uPT' => 1])) . '" method="post" enctype="' . $GLOBALS['TYPO3_CONF_VARS']['SYS']['form_enctype'] . '" name="editform" onsubmit="return TBE_EDITOR.checkSubmit(1);">'; // Setting up the context sensitive menu: $this->doc->getContextMenuCode(); // Set the edit_record value for internal use in this function: $edit_record = $this->edit_record; // If a command to edit all records in a column is issue, then select all those elements, and redirect to FormEngine if (substr($edit_record, 0, 9) == '_EDIT_COL') { $res = $databaseConnection->exec_SELECTquery('*', 'tt_content', 'pid=' . (int) $this->id . ' AND colPos=' . (int) substr($edit_record, 10) . ' AND sys_language_uid=' . (int) $this->current_sys_language . ($this->MOD_SETTINGS['tt_content_showHidden'] ? '' : BackendUtility::BEenableFields('tt_content')) . BackendUtility::deleteClause('tt_content') . BackendUtility::versioningPlaceholderClause('tt_content'), '', 'sorting'); $idListA = array(); while ($cRow = $databaseConnection->sql_fetch_assoc($res)) { $idListA[] = $cRow['uid']; } $url = BackendUtility::getModuleUrl('record_edit', array('edit[tt_content][' . implode(',', $idListA) . ']' => 'edit', 'returnUrl' => $this->local_linkThisScript(array('edit_record' => '')))); HttpUtility::redirect($url); } // If the former record edited was the creation of a NEW record, this will look up the created records uid: if ($this->new_unique_uid) { $res = $databaseConnection->exec_SELECTquery('*', 'sys_log', 'userid=' . (int) $beUser->user['uid'] . ' AND NEWid=' . $databaseConnection->fullQuoteStr($this->new_unique_uid, 'sys_log')); $sys_log_row = $databaseConnection->sql_fetch_assoc($res); if (is_array($sys_log_row)) { $edit_record = $sys_log_row['tablename'] . ':' . $sys_log_row['recuid']; } } // Creating the selector box, allowing the user to select which element to edit: $opt = array(); $is_selected = 0; $languageOverlayRecord = ''; if ($this->current_sys_language) { list($languageOverlayRecord) = BackendUtility::getRecordsByField('pages_language_overlay', 'pid', $this->id, 'AND sys_language_uid=' . (int) $this->current_sys_language); } if (is_array($languageOverlayRecord)) { $inValue = 'pages_language_overlay:' . $languageOverlayRecord['uid']; $is_selected += (int) $edit_record == $inValue; $opt[] = '<option value="' . $inValue . '"' . ($edit_record == $inValue ? ' selected="selected"' : '') . '>[ ' . $lang->getLL('editLanguageHeader', TRUE) . ' ]</option>'; } else { $inValue = 'pages:' . $this->id; $is_selected += (int) $edit_record == $inValue; $opt[] = '<option value="' . $inValue . '"' . ($edit_record == $inValue ? ' selected="selected"' : '') . '>[ ' . $lang->getLL('editPageProperties', TRUE) . ' ]</option>'; } // Selecting all content elements from this language and allowed colPos: $res = $databaseConnection->exec_SELECTquery('*', 'tt_content', 'pid=' . (int) $this->id . ' AND sys_language_uid=' . (int) $this->current_sys_language . ' AND colPos IN (' . $this->colPosList . ')' . ($this->MOD_SETTINGS['tt_content_showHidden'] ? '' : BackendUtility::BEenableFields('tt_content')) . BackendUtility::deleteClause('tt_content') . BackendUtility::versioningPlaceholderClause('tt_content'), '', 'colPos,sorting'); $colPos = NULL; $first = 1; // Page is the pid if no record to put this after. $prev = $this->id; while ($cRow = $databaseConnection->sql_fetch_assoc($res)) { BackendUtility::workspaceOL('tt_content', $cRow); if (is_array($cRow)) { if ($first) { if (!$edit_record) { $edit_record = 'tt_content:' . $cRow['uid']; } $first = 0; } if (!isset($colPos) || $cRow['colPos'] !== $colPos) { $colPos = $cRow['colPos']; $opt[] = '<option value=""></option>'; $opt[] = '<option value="_EDIT_COL:' . $colPos . '">__' . $lang->sL(BackendUtility::getLabelFromItemlist('tt_content', 'colPos', $colPos), TRUE) . ':__</option>'; } $inValue = 'tt_content:' . $cRow['uid']; $is_selected += (int) $edit_record == $inValue; $opt[] = '<option value="' . $inValue . '"' . ($edit_record == $inValue ? ' selected="selected"' : '') . '>' . htmlspecialchars(GeneralUtility::fixed_lgd_cs($cRow['header'] ? $cRow['header'] : '[' . $lang->sL('LLL:EXT:lang/locallang_core.xlf:labels.no_title') . '] ' . strip_tags($cRow['bodytext']), $beUser->uc['titleLen'])) . '</option>'; $prev = -$cRow['uid']; } } // If edit_record is not set (meaning, no content elements was found for this language) we simply set it to create a new element: if (!$edit_record) { $edit_record = 'tt_content:new/' . $prev . '/' . $colPos; $inValue = 'tt_content:new/' . $prev . '/' . $colPos; $is_selected += (int) $edit_record == $inValue; $opt[] = '<option value="' . $inValue . '"' . ($edit_record == $inValue ? ' selected="selected"' : '') . '>[ ' . $lang->getLL('newLabel', 1) . ' ]</option>'; } // If none is yet selected... if (!$is_selected) { $opt[] = '<option value=""></option>'; $opt[] = '<option value="' . $edit_record . '" selected="selected">[ ' . $lang->getLL('newLabel', TRUE) . ' ]</option>'; } // Splitting the edit-record cmd value into table/uid: $this->eRParts = explode(':', $edit_record); // Delete-button flag? $this->deleteButton = MathUtility::canBeInterpretedAsInteger($this->eRParts[1]) && $edit_record && ($this->eRParts[0] != 'pages' && $this->EDIT_CONTENT || $this->eRParts[0] == 'pages' && $this->CALC_PERMS & Permission::PAGE_DELETE); // If undo-button should be rendered (depends on available items in sys_history) $this->undoButton = FALSE; $undoRes = $databaseConnection->exec_SELECTquery('tstamp', 'sys_history', 'tablename=' . $databaseConnection->fullQuoteStr($this->eRParts[0], 'sys_history') . ' AND recuid=' . (int) $this->eRParts[1], '', 'tstamp DESC', '1'); if ($this->undoButtonR = $databaseConnection->sql_fetch_assoc($undoRes)) { $this->undoButton = TRUE; } // Setting up the Return URL for coming back to THIS script (if links take the user to another script) $R_URL_parts = parse_url(GeneralUtility::getIndpEnv('REQUEST_URI')); $R_URL_getvars = GeneralUtility::_GET(); unset($R_URL_getvars['popView']); unset($R_URL_getvars['new_unique_uid']); $R_URL_getvars['edit_record'] = $edit_record; $this->R_URI = $R_URL_parts['path'] . '?' . GeneralUtility::implodeArrayForUrl('', $R_URL_getvars); // Setting close url/return url for exiting this script: // Goes to 'Columns' view if close is pressed (default) $this->closeUrl = $this->local_linkThisScript(array('SET' => array('function' => 1))); if ($this->returnUrl) { $this->closeUrl = $this->returnUrl; } // Return-url for JavaScript: $retUrlStr = $this->returnUrl ? '+\'&returnUrl=\'+' . GeneralUtility::quoteJSvalue(rawurlencode($this->returnUrl)) : ''; // Drawing the edit record selectbox $this->editSelect = '<select name="edit_record" onchange="' . htmlspecialchars('jumpToUrl(' . GeneralUtility::quoteJSvalue(BackendUtility::getModuleUrl('web_layout') . '&id=' . $this->id . '&edit_record=') . '+escape(this.options[this.selectedIndex].value)' . $retUrlStr . ',this);') . '">' . implode('', $opt) . '</select>'; $content = ''; // Creating editing form: if ($beUser->check('tables_modify', $this->eRParts[0]) && $edit_record && ($this->eRParts[0] !== 'pages' && $this->EDIT_CONTENT || $this->eRParts[0] === 'pages' && $this->CALC_PERMS & Permission::PAGE_SHOW)) { // Splitting uid parts for special features, if new: list($uidVal, $ex_pid, $ex_colPos) = explode('/', $this->eRParts[1]); // Convert $uidVal to workspace version if any: if ($uidVal != 'new') { if ($draftRecord = BackendUtility::getWorkspaceVersionOfRecord($beUser->workspace, $this->eRParts[0], $uidVal, 'uid')) { $uidVal = $draftRecord['uid']; } } // Initializing transfer-data object: $trData = GeneralUtility::makeInstance(DataPreprocessor::class); $trData->addRawData = TRUE; $trData->defVals[$this->eRParts[0]] = array('colPos' => (int) $ex_colPos, 'sys_language_uid' => (int) $this->current_sys_language); $trData->lockRecords = 1; // 'new' $trData->fetchRecord($this->eRParts[0], $uidVal == 'new' ? $this->id : $uidVal, $uidVal); $new_unique_uid = ''; // Getting/Making the record: reset($trData->regTableItems_data); $rec = current($trData->regTableItems_data); if ($uidVal == 'new') { $new_unique_uid = uniqid('NEW', TRUE); $rec['uid'] = $new_unique_uid; $rec['pid'] = (int) $ex_pid ?: $this->id; $recordAccess = TRUE; } else { $rec['uid'] = $uidVal; // Checking internals access: $recordAccess = $beUser->recordEditAccessInternals($this->eRParts[0], $uidVal); } if (!$recordAccess) { // If no edit access, print error message: $content = $this->doc->section($lang->getLL('noAccess'), $lang->getLL('noAccess_msg') . '<br /><br />' . ($beUser->errorMsg ? 'Reason: ' . $beUser->errorMsg . '<br /><br />' : ''), 0, 1); } elseif (is_array($rec)) { // If the record is an array (which it will always be... :-) // Create instance of TCEforms, setting defaults: $tceForms = GeneralUtility::makeInstance(FormEngine::class); // Render form, wrap it: $panel = ''; $panel .= $tceForms->getMainFields($this->eRParts[0], $rec); $panel = $tceForms->wrapTotal($panel, $rec, $this->eRParts[0]); // Add hidden fields: $theCode = $panel; if ($uidVal == 'new') { $theCode .= '<input type="hidden" name="data[' . $this->eRParts[0] . '][' . $rec['uid'] . '][pid]" value="' . $rec['pid'] . '" />'; } $theCode .= ' <input type="hidden" name="_serialNumber" value="' . md5(microtime()) . '" /> <input type="hidden" name="edit_record" value="' . $edit_record . '" /> <input type="hidden" name="redirect" value="' . htmlspecialchars($uidVal == 'new' ? BackendUtility::getModuleUrl('web_layout', array('id' => $this->id, 'new_unique_uid' => $new_unique_uid, 'returnUrl' => $this->returnUrl)) : $this->R_URI) . '" /> ' . FormEngine::getHiddenTokenField('tceAction'); // Add JavaScript as needed around the form: $theCode = $tceForms->printNeededJSFunctions_top() . $theCode . $tceForms->printNeededJSFunctions(); // Add warning sign if record was "locked": if ($lockInfo = BackendUtility::isRecordLocked($this->eRParts[0], $rec['uid'])) { /** @var \TYPO3\CMS\Core\Messaging\FlashMessage $flashMessage */ $flashMessage = GeneralUtility::makeInstance(FlashMessage::class, htmlspecialchars($lockInfo['msg']), '', FlashMessage::WARNING); /** @var $flashMessageService \TYPO3\CMS\Core\Messaging\FlashMessageService */ $flashMessageService = GeneralUtility::makeInstance(FlashMessageService::class); /** @var $defaultFlashMessageQueue \TYPO3\CMS\Core\Messaging\FlashMessageQueue */ $defaultFlashMessageQueue = $flashMessageService->getMessageQueueByIdentifier(); $defaultFlashMessageQueue->enqueue($flashMessage); } // Add whole form as a document section: $content = $this->doc->section('', $theCode); } } else { // If no edit access, print error message: $content = $this->doc->section($lang->getLL('noAccess'), $lang->getLL('noAccess_msg') . '<br /><br />', 0, 1); } // Bottom controls (function menus): $q_count = $this->getNumberOfHiddenElements(); if ($q_count) { $h_func_b = '<div class="checkbox">' . '<label for="checkTt_content_showHidden">' . BackendUtility::getFuncCheck($this->id, 'SET[tt_content_showHidden]', $this->MOD_SETTINGS['tt_content_showHidden'], '', '', 'id="checkTt_content_showHidden"') . (!$q_count ? '<span class="text-muted">' . $lang->getLL('hiddenCE', TRUE) . '</span>' : $lang->getLL('hiddenCE', TRUE) . ' (' . $q_count . ')') . '</label>' . '</div>'; $content .= $this->doc->section('', $h_func_b, 0, 0); $content .= $this->doc->spacer(10); } // Select element matrix: if ($this->eRParts[0] == 'tt_content' && MathUtility::canBeInterpretedAsInteger($this->eRParts[1])) { $posMap = GeneralUtility::makeInstance(ContentLayoutPagePositionMap::class); $posMap->backPath = $GLOBALS['BACK_PATH']; $posMap->cur_sys_language = $this->current_sys_language; $HTMLcode = ''; // CSH: $HTMLcode .= BackendUtility::cshItem($this->descrTable, 'quickEdit_selElement', NULL, '|<br />'); $HTMLcode .= $posMap->printContentElementColumns($this->id, $this->eRParts[1], $this->colPosList, $this->MOD_SETTINGS['tt_content_showHidden'], $this->R_URI); $content .= $this->doc->spacer(20); $content .= $this->doc->section($lang->getLL('CEonThisPage'), $HTMLcode, 0, 1); $content .= $this->doc->spacer(20); } return $content; }
/** * Renders Content Elements from the tt_content table from page id * * @param integer $id Page id * @return string HTML for the listing * @todo Define visibility */ public function getTable_tt_content($id) { $this->initializeLanguages(); $this->initializeClipboard(); // Initialize: $RTE = $this->getBackendUser()->isRTE(); $lMarg = 1; $showHidden = $this->tt_contentConfig['showHidden'] ? '' : BackendUtility::BEenableFields('tt_content'); $pageTitleParamForAltDoc = '&recTitle=' . rawurlencode(BackendUtility::getRecordTitle('pages', BackendUtility::getRecordWSOL('pages', $id), TRUE)); /** @var $pageRenderer \TYPO3\CMS\Core\Page\PageRenderer */ $pageRenderer = $this->getPageLayoutController()->doc->getPageRenderer(); $pageRenderer->loadExtJs(); $pageRenderer->addJsFile($GLOBALS['BACK_PATH'] . 'sysext/cms/layout/js/typo3pageModule.js'); // Get labels for CTypes and tt_content element fields in general: $this->CType_labels = array(); foreach ($GLOBALS['TCA']['tt_content']['columns']['CType']['config']['items'] as $val) { $this->CType_labels[$val[1]] = $this->getLanguageService()->sL($val[0]); } $this->itemLabels = array(); foreach ($GLOBALS['TCA']['tt_content']['columns'] as $name => $val) { $this->itemLabels[$name] = $this->getLanguageService()->sL($val['label']); } $languageColumn = array(); $out = ''; // Select display mode: // MULTIPLE column display mode, side by side: if (!$this->tt_contentConfig['single']) { // Setting language list: $langList = $this->tt_contentConfig['sys_language_uid']; if ($this->tt_contentConfig['languageMode']) { if ($this->tt_contentConfig['languageColsPointer']) { $langList = '0,' . $this->tt_contentConfig['languageColsPointer']; } else { $langList = implode(',', array_keys($this->tt_contentConfig['languageCols'])); } $languageColumn = array(); } $langListArr = GeneralUtility::intExplode(',', $langList); $defLanguageCount = array(); $defLangBinding = array(); // For each languages... : // If not languageMode, then we'll only be through this once. foreach ($langListArr as $lP) { $lP = (int) $lP; if (count($langListArr) === 1 || $lP === 0) { $showLanguage = ' AND sys_language_uid IN (' . $lP . ',-1)'; } else { $showLanguage = ' AND sys_language_uid=' . $lP; } $cList = explode(',', $this->tt_contentConfig['cols']); $content = array(); $head = array(); // Select content records per column $contentRecordsPerColumn = $this->getContentRecordsPerColumn('table', $id, array_values($cList), $showHidden . $showLanguage); // For each column, render the content into a variable: foreach ($cList as $key) { if (!$lP) { $defLanguageCount[$key] = array(); } // Start wrapping div $content[$key] .= '<div class="t3-page-ce-wrapper'; if (count($contentRecordsPerColumn[$key]) === 0) { $content[$key] .= ' t3-page-ce-empty'; } $content[$key] .= '">'; // Add new content at the top most position $content[$key] .= ' <div class="t3-page-ce" id="' . uniqid() . '"> <div class="t3-page-ce-dropzone" id="colpos-' . $key . '-' . 'page-' . $id . '-' . uniqid() . '"> <div class="t3-page-ce-wrapper-new-ce"> <a href="#" onclick="' . htmlspecialchars($this->newContentElementOnClick($id, $key, $lP)) . '" title="' . $this->getLanguageService()->getLL('newRecordHere', TRUE) . '">' . IconUtility::getSpriteIcon('actions-document-new') . '</a> </div> </div> </div> '; $editUidList = ''; $rowArr = $contentRecordsPerColumn[$key]; $this->generateTtContentDataArray($rowArr); foreach ((array) $rowArr as $rKey => $row) { if ($this->tt_contentConfig['languageMode']) { $languageColumn[$key][$lP] = $head[$key] . $content[$key]; if (!$this->defLangBinding) { $languageColumn[$key][$lP] .= $this->newLanguageButton($this->getNonTranslatedTTcontentUids($defLanguageCount[$key], $id, $lP), $lP); } } if (is_array($row) && !VersionState::cast($row['t3ver_state'])->equals(VersionState::DELETE_PLACEHOLDER)) { $singleElementHTML = ''; if (!$lP && ($this->defLangBinding || $row['sys_language_uid'] != -1)) { $defLanguageCount[$key][] = $row['uid']; } $editUidList .= $row['uid'] . ','; $disableMoveAndNewButtons = $this->defLangBinding && $lP > 0; if (!$this->tt_contentConfig['languageMode']) { $singleElementHTML .= '<div class="t3-page-ce-dragitem" id="' . uniqid() . '">'; } $singleElementHTML .= $this->tt_content_drawHeader($row, $this->tt_contentConfig['showInfo'] ? 15 : 5, $disableMoveAndNewButtons, TRUE, !$this->tt_contentConfig['languageMode']); $isRTE = $RTE && $this->isRTEforField('tt_content', $row, 'bodytext'); $innerContent = '<div ' . ($row['_ORIG_uid'] ? ' class="ver-element"' : '') . '>' . $this->tt_content_drawItem($row, $isRTE) . '</div>'; $singleElementHTML .= '<div class="t3-page-ce-body-inner">' . $innerContent . '</div>' . $this->tt_content_drawFooter($row); // NOTE: this is the end tag for <div class="t3-page-ce-body"> // because of bad (historic) conception, starting tag has to be placed inside tt_content_drawHeader() $singleElementHTML .= '</div>'; $statusHidden = $this->isDisabled('tt_content', $row) ? ' t3-page-ce-hidden' : ''; $singleElementHTML = '<div class="t3-page-ce' . $statusHidden . '" id="element-tt_content-' . $row['uid'] . '">' . $singleElementHTML . '</div>'; if ($this->tt_contentConfig['languageMode']) { $singleElementHTML .= '<div class="t3-page-ce">'; } $singleElementHTML .= '<div class="t3-page-ce-dropzone" id="colpos-' . $key . '-' . 'page-' . $id . '-' . uniqid() . '">'; // Add icon "new content element below" if (!$disableMoveAndNewButtons) { // New content element: if ($this->option_newWizard) { $onClick = 'window.location.href=\'db_new_content_el.php?id=' . $row['pid'] . '&sys_language_uid=' . $row['sys_language_uid'] . '&colPos=' . $row['colPos'] . '&uid_pid=' . -$row['uid'] . '&returnUrl=' . rawurlencode(GeneralUtility::getIndpEnv('REQUEST_URI')) . '\';'; } else { $params = '&edit[tt_content][' . -$row['uid'] . ']=new'; $onClick = BackendUtility::editOnClick($params, $this->backPath); } $singleElementHTML .= ' <div class="t3-page-ce-wrapper-new-ce"> <a href="#" onclick="' . htmlspecialchars($onClick) . '" title="' . $this->getLanguageService()->getLL('newRecordHere', TRUE) . '">' . IconUtility::getSpriteIcon('actions-document-new') . '</a> </div> '; } $singleElementHTML .= '</div></div>'; if ($this->defLangBinding && $this->tt_contentConfig['languageMode']) { $defLangBinding[$key][$lP][$row[$lP ? 'l18n_parent' : 'uid']] = $singleElementHTML; } else { $content[$key] .= $singleElementHTML; } } else { unset($rowArr[$rKey]); } } $content[$key] .= '</div>'; // Add new-icon link, header: $newP = $this->newContentElementOnClick($id, $key, $lP); $colTitle = BackendUtility::getProcessedValue('tt_content', 'colPos', $key); $tcaItems = GeneralUtility::callUserFunction('TYPO3\\CMS\\Backend\\View\\BackendLayoutView->getColPosListItemsParsed', $id, $this); foreach ($tcaItems as $item) { if ($item[1] == $key) { $colTitle = $this->getLanguageService()->sL($item[0]); } } $pasteP = array('colPos' => $key, 'sys_language_uid' => $lP); $editParam = $this->doEdit && count($rowArr) ? '&edit[tt_content][' . $editUidList . ']=edit' . $pageTitleParamForAltDoc : ''; $head[$key] .= $this->tt_content_drawColHeader($colTitle, $editParam, $newP, $pasteP); } // For each column, fit the rendered content into a table cell: $out = ''; if ($this->tt_contentConfig['languageMode']) { // in language mode process the content elements, but only fill $languageColumn. output will be generated later foreach ($cList as $key) { $languageColumn[$key][$lP] = $head[$key] . $content[$key]; if (!$this->defLangBinding) { $languageColumn[$key][$lP] .= $this->newLanguageButton($this->getNonTranslatedTTcontentUids($defLanguageCount[$key], $id, $lP), $lP); } } } else { $backendLayout = $this->getBackendLayoutView()->getSelectedBackendLayout($this->id); // GRID VIEW: $grid = '<div class="t3-gridContainer"><table border="0" cellspacing="0" cellpadding="0" width="100%" height="100%" class="t3-page-columns t3-gridTable">'; // Add colgroups $colCount = (int) $backendLayout['__config']['backend_layout.']['colCount']; $rowCount = (int) $backendLayout['__config']['backend_layout.']['rowCount']; $grid .= '<colgroup>'; for ($i = 0; $i < $colCount; $i++) { $grid .= '<col style="width:' . 100 / $colCount . '%"></col>'; } $grid .= '</colgroup>'; // Cycle through rows for ($row = 1; $row <= $rowCount; $row++) { $rowConfig = $backendLayout['__config']['backend_layout.']['rows.'][$row . '.']; if (!isset($rowConfig)) { continue; } $grid .= '<tr>'; for ($col = 1; $col <= $colCount; $col++) { $columnConfig = $rowConfig['columns.'][$col . '.']; if (!isset($columnConfig)) { continue; } // Which tt_content colPos should be displayed inside this cell $columnKey = (int) $columnConfig['colPos']; // Render the grid cell $colSpan = (int) $columnConfig['colspan']; $rowSpan = (int) $columnConfig['rowspan']; $grid .= '<td valign="top"' . ($colSpan > 0 ? ' colspan="' . $colSpan . '"' : '') . ($rowSpan > 0 ? ' rowspan="' . $rowSpan . '"' : '') . ' class="t3-gridCell t3-page-column t3-page-column-' . $columnKey . (!isset($columnConfig['colPos']) || $columnConfig['colPos'] === '' ? ' t3-gridCell-unassigned' : '') . (isset($columnConfig['colPos']) && $columnConfig['colPos'] !== '' && !$head[$columnKey] ? ' t3-gridCell-restricted' : '') . ($colSpan > 0 ? ' t3-gridCell-width' . $colSpan : '') . ($rowSpan > 0 ? ' t3-gridCell-height' . $rowSpan : '') . '">'; // Draw the pre-generated header with edit and new buttons if a colPos is assigned. // If not, a new header without any buttons will be generated. if (isset($columnConfig['colPos']) && $columnConfig['colPos'] !== '' && $head[$columnKey]) { $grid .= $head[$columnKey] . $content[$columnKey]; } elseif (isset($columnConfig['colPos']) && $columnConfig['colPos'] !== '') { $grid .= $this->tt_content_drawColHeader($this->getLanguageService()->getLL('noAccess'), '', ''); } elseif (isset($columnConfig['name']) && strlen($columnConfig['name']) > 0) { $grid .= $this->tt_content_drawColHeader($this->getLanguageService()->sL($columnConfig['name']) . ' (' . $this->getLanguageService()->getLL('notAssigned') . ')', '', ''); } else { $grid .= $this->tt_content_drawColHeader($this->getLanguageService()->getLL('notAssigned'), '', ''); } $grid .= '</td>'; } $grid .= '</tr>'; } $out .= $grid . '</table></div>'; } // CSH: $out .= BackendUtility::cshItem($this->descrTable, 'columns_multi', $GLOBALS['BACK_PATH']); } // If language mode, then make another presentation: // Notice that THIS presentation will override the value of $out! // But it needs the code above to execute since $languageColumn is filled with content we need! if ($this->tt_contentConfig['languageMode']) { // Get language selector: $languageSelector = $this->languageSelector($id); // Reset out - we will make new content here: $out = ''; // Traverse languages found on the page and build up the table displaying them side by side: $cCont = array(); $sCont = array(); foreach ($langListArr as $lP) { // Header: $lP = (int) $lP; $cCont[$lP] = ' <td valign="top" class="t3-page-lang-column"> <h3>' . htmlspecialchars($this->tt_contentConfig['languageCols'][$lP]) . '</h3> </td>'; // "View page" icon is added: $onClick = BackendUtility::viewOnClick($this->id, $this->backPath, BackendUtility::BEgetRootLine($this->id), '', '', '&L=' . $lP); $viewLink = '<a href="#" onclick="' . htmlspecialchars($onClick) . '">' . IconUtility::getSpriteIcon('actions-document-view') . '</a>'; // Language overlay page header: if ($lP) { list($lpRecord) = BackendUtility::getRecordsByField('pages_language_overlay', 'pid', $id, 'AND sys_language_uid=' . $lP); BackendUtility::workspaceOL('pages_language_overlay', $lpRecord); $params = '&edit[pages_language_overlay][' . $lpRecord['uid'] . ']=edit&overrideVals[pages_language_overlay][sys_language_uid]=' . $lP; $lPLabel = $this->getPageLayoutController()->doc->wrapClickMenuOnIcon(IconUtility::getSpriteIconForRecord('pages_language_overlay', $lpRecord), 'pages_language_overlay', $lpRecord['uid']) . $viewLink . ($this->getBackendUser()->check('tables_modify', 'pages_language_overlay') ? '<a href="#" onclick="' . htmlspecialchars(BackendUtility::editOnClick($params, $this->backPath)) . '" title="' . $this->getLanguageService()->getLL('edit', TRUE) . '">' . IconUtility::getSpriteIcon('actions-document-open') . '</a>' : '') . htmlspecialchars(GeneralUtility::fixed_lgd_cs($lpRecord['title'], 20)); } else { $lPLabel = $viewLink; } $sCont[$lP] = ' <td nowrap="nowrap" class="t3-page-lang-column t3-page-lang-label">' . $lPLabel . '</td>'; } // Add headers: $out .= '<tr>' . implode($cCont) . '</tr>'; $out .= '<tr>' . implode($sCont) . '</tr>'; // Traverse previously built content for the columns: foreach ($languageColumn as $cKey => $cCont) { $out .= ' <tr> <td valign="top" class="t3-gridCell t3-page-column t3-page-lang-column">' . implode('</td>' . ' <td valign="top" class="t3-gridCell t3-page-column t3-page-lang-column">', $cCont) . '</td> </tr>'; if ($this->defLangBinding) { // "defLangBinding" mode foreach ($defLanguageCount[$cKey] as $defUid) { $cCont = array(); foreach ($langListArr as $lP) { $cCont[] = $defLangBinding[$cKey][$lP][$defUid] . $this->newLanguageButton($this->getNonTranslatedTTcontentUids(array($defUid), $id, $lP), $lP); } $out .= ' <tr> <td valign="top" class="t3-page-lang-column">' . implode('</td>' . ' <td valign="top" class="t3-page-lang-column">', $cCont) . '</td> </tr>'; } // Create spacer: $cCont = array_fill(0, count($langListArr), ' '); $out .= ' <tr> <td valign="top" class="t3-page-lang-column">' . implode('</td>' . ' <td valign="top" class="t3-page-lang-column">', $cCont) . '</td> </tr>'; } } // Finally, wrap it all in a table and add the language selector on top of it: $out = $languageSelector . ' <div class="t3-lang-gridContainer"> <table cellpadding="0" cellspacing="0" class="t3-page-langMode"> ' . $out . ' </table> </div>'; // CSH: $out .= BackendUtility::cshItem($this->descrTable, 'language_list', $GLOBALS['BACK_PATH']); } } else { // SINGLE column mode (columns shown beneath each other): if ($this->tt_contentConfig['sys_language_uid'] == 0 || !$this->defLangBinding) { // Initialize: if ($this->defLangBinding && $this->tt_contentConfig['sys_language_uid'] == 0) { $showLanguage = ' AND sys_language_uid IN (0,-1)'; $lP = 0; } else { $showLanguage = ' AND sys_language_uid=' . $this->tt_contentConfig['sys_language_uid']; $lP = $this->tt_contentConfig['sys_language_uid']; } $cList = explode(',', $this->tt_contentConfig['showSingleCol']); $out = ''; // Expand the table to some preset dimensions: $out .= ' <tr> <td><img src="clear.gif" width="' . $lMarg . '" height="1" alt="" /></td> <td valign="top"><img src="clear.gif" width="150" height="1" alt="" /></td> <td><img src="clear.gif" width="10" height="1" alt="" /></td> <td valign="top"><img src="clear.gif" width="300" height="1" alt="" /></td> </tr>'; // Select content records per column $contentRecordsPerColumn = $this->getContentRecordsPerColumn('tt_content', $id, array_values($cList), $showHidden . $showLanguage); // Traverse columns to display top-on-top foreach ($cList as $counter => $key) { $c = 0; $rowArr = $contentRecordsPerColumn[$key]; $this->generateTtContentDataArray($rowArr); $numberOfContentElementsInColumn = count($rowArr); $rowOut = ''; // If it turns out that there are not content elements in the column, then display a big button which links directly to the wizard script: if ($this->doEdit && $this->option_showBigButtons && !(int) $key && $numberOfContentElementsInColumn == 0) { $onClick = 'window.location.href=\'db_new_content_el.php?id=' . $id . '&colPos=' . (int) $key . '&sys_language_uid=' . $lP . '&uid_pid=' . $id . '&returnUrl=' . rawurlencode(GeneralUtility::getIndpEnv('REQUEST_URI')) . '\';'; $theNewButton = $this->getPageLayoutController()->doc->t3Button($onClick, $this->getLanguageService()->getLL('newPageContent')); $theNewButton = '<img src="clear.gif" width="1" height="5" alt="" /><br />' . $theNewButton; } else { $theNewButton = ''; } $editUidList = ''; // Traverse any selected elements: foreach ($rowArr as $rKey => $row) { if (is_array($row) && !VersionState::cast($row['t3ver_state'])->equals(VersionState::DELETE_PLACEHOLDER)) { $c++; $editUidList .= $row['uid'] . ','; $isRTE = $RTE && $this->isRTEforField('tt_content', $row, 'bodytext'); // Create row output: $rowOut .= ' <tr> <td></td> <td valign="top">' . $this->tt_content_drawHeader($row) . '</td> <td> </td> <td' . ($row['_ORIG_uid'] ? ' class="ver-element"' : '') . ' valign="top">' . $this->tt_content_drawItem($row, $isRTE) . '</td> </tr>'; // If the element was not the last element, add a divider line: if ($c != $numberOfContentElementsInColumn) { $rowOut .= ' <tr> <td></td> <td colspan="3"><img' . IconUtility::skinImg($this->backPath, 'gfx/stiblet_medium2.gif', 'width="468" height="1"') . ' class="c-divider" alt="" /></td> </tr>'; } } else { unset($rowArr[$rKey]); } } // Add spacer between sections in the vertical list if ($counter) { $out .= ' <tr> <td></td> <td colspan="3"><br /><br /><br /><br /></td> </tr>'; } // Add section header: $newP = $this->newContentElementOnClick($id, $key, $this->tt_contentConfig['sys_language_uid']); $pasteP = array('colPos' => $key, 'sys_language_uid' => $this->tt_contentConfig['sys_language_uid']); $out .= ' <!-- Column header: --> <tr> <td></td> <td valign="top" colspan="3">' . $this->tt_content_drawColHeader(BackendUtility::getProcessedValue('tt_content', 'colPos', $key), $this->doEdit && count($rowArr) ? '&edit[tt_content][' . $editUidList . ']=edit' . $pageTitleParamForAltDoc : '', $newP, $pasteP) . $theNewButton . '<br /></td> </tr>'; // Finally, add the content from the records in this column: $out .= $rowOut; } // Finally, wrap all table rows in one, big table: $out = ' <table border="0" cellpadding="0" cellspacing="0" width="400" class="typo3-page-columnsMode"> ' . $out . ' </table>'; // CSH: $out .= BackendUtility::cshItem($this->descrTable, 'columns_single', $GLOBALS['BACK_PATH']); } else { $out = '<br/><br/>' . $this->getPageLayoutController()->doc->icons(1) . 'Sorry, you cannot view a single language in this localization mode (Default Language Binding is enabled)<br/><br/>'; } } // Add the big buttons to page: if ($this->option_showBigButtons) { $bArray = array(); if (!$this->getPageLayoutController()->current_sys_language) { if ($this->ext_CALC_PERMS & 2) { $bArray[0] = $this->getPageLayoutController()->doc->t3Button(BackendUtility::editOnClick('&edit[pages][' . $id . ']=edit', $this->backPath, ''), $this->getLanguageService()->getLL('editPageProperties')); } } else { if ($this->doEdit && $this->getBackendUser()->check('tables_modify', 'pages_language_overlay')) { list($languageOverlayRecord) = BackendUtility::getRecordsByField('pages_language_overlay', 'pid', $id, 'AND sys_language_uid=' . (int) $this->getPageLayoutController()->current_sys_language); $bArray[0] = $this->getPageLayoutController()->doc->t3Button(BackendUtility::editOnClick('&edit[pages_language_overlay][' . $languageOverlayRecord['uid'] . ']=edit', $this->backPath, ''), $this->getLanguageService()->getLL('editPageProperties_curLang')); } } if ($this->ext_CALC_PERMS & 4 || $this->ext_CALC_PERMS & 2) { $bArray[1] = $this->getPageLayoutController()->doc->t3Button('window.location.href=\'' . $this->backPath . 'move_el.php?table=pages&uid=' . $id . '&returnUrl=' . rawurlencode(GeneralUtility::getIndpEnv('REQUEST_URI')) . '\';', $this->getLanguageService()->getLL('move_page')); } if ($this->ext_CALC_PERMS & 8) { $bArray[2] = $this->getPageLayoutController()->doc->t3Button('window.location.href=\'' . $this->backPath . 'db_new.php?id=' . $id . '&pagesOnly=1&returnUrl=' . rawurlencode(GeneralUtility::getIndpEnv('REQUEST_URI')) . '\';', $this->getLanguageService()->getLL('newPage2')); } if ($this->doEdit && $this->ext_function == 1) { $bArray[3] = $this->getPageLayoutController()->doc->t3Button('window.location.href=\'db_new_content_el.php?id=' . $id . '&sys_language_uid=' . $this->getPageLayoutController()->current_sys_language . '&returnUrl=' . rawurlencode(GeneralUtility::getIndpEnv('REQUEST_URI')) . '\';', $this->getLanguageService()->getLL('newPageContent2')); } $out = ' <table border="0" cellpadding="4" cellspacing="0" class="typo3-page-buttons"> <tr> <td>' . implode('</td> <td>', $bArray) . '</td> <td>' . BackendUtility::cshItem($this->descrTable, 'button_panel', $GLOBALS['BACK_PATH']) . '</td> </tr> </table> <br /> ' . $out; } // Return content: return $out; }
/** * Indicate that the required be_user "_cli_crawler" is * has no admin rights. * * @access protected * @return boolean * * @author Michael Klapper <*****@*****.**> */ protected function isCrawlerUserNotAdmin() { $isAvailable = false; $userArray = \TYPO3\CMS\Backend\Utility\BackendUtility::getRecordsByField('be_users', 'username', '_cli_crawler'); if (is_array($userArray) && $userArray[0]['admin'] == 0) { $isAvailable = true; } return $isAvailable; }