/** * Renders the review module user dependent with all workspaces. * The module will show all records of one workspace. * * @return void */ public function indexAction() { /** @var WorkspaceService $wsService */ $wsService = GeneralUtility::makeInstance(WorkspaceService::class); $this->view->assign('showGrid', !($GLOBALS['BE_USER']->workspace === 0 && !$GLOBALS['BE_USER']->isAdmin())); $this->view->assign('showAllWorkspaceTab', true); $this->view->assign('pageUid', GeneralUtility::_GP('id')); if (GeneralUtility::_GP('id')) { $pageRecord = BackendUtility::getRecord('pages', GeneralUtility::_GP('id')); $this->view->getModuleTemplate()->getDocHeaderComponent()->setMetaInformation($pageRecord); $this->view->assign('pageTitle', BackendUtility::getRecordTitle('pages', $pageRecord)); } $this->view->assign('showLegend', !($GLOBALS['BE_USER']->workspace === 0 && !$GLOBALS['BE_USER']->isAdmin())); $wsList = $wsService->getAvailableWorkspaces(); $activeWorkspace = $GLOBALS['BE_USER']->workspace; $performWorkspaceSwitch = false; // Only admins see multiple tabs, we decided to use it this // way for usability reasons. Regular users might be confused // by switching workspaces with the tabs in a module. if (!$GLOBALS['BE_USER']->isAdmin()) { $wsCur = array($activeWorkspace => true); $wsList = array_intersect_key($wsList, $wsCur); } else { if ((string) GeneralUtility::_GP('workspace') !== '') { $switchWs = (int) GeneralUtility::_GP('workspace'); if (in_array($switchWs, array_keys($wsList)) && $activeWorkspace != $switchWs) { $activeWorkspace = $switchWs; $GLOBALS['BE_USER']->setWorkspace($activeWorkspace); $performWorkspaceSwitch = true; BackendUtility::setUpdateSignal('updatePageTree'); } elseif ($switchWs == WorkspaceService::SELECT_ALL_WORKSPACES) { $this->redirect('fullIndex'); } } } $this->pageRenderer->addInlineSetting('Workspaces', 'isLiveWorkspace', (int) $GLOBALS['BE_USER']->workspace === 0); $this->pageRenderer->addInlineSetting('Workspaces', 'workspaceTabs', $this->prepareWorkspaceTabs($wsList, $activeWorkspace)); $this->pageRenderer->addInlineSetting('Workspaces', 'activeWorkspaceId', $activeWorkspace); $this->pageRenderer->addInlineSetting('FormEngine', 'moduleUrl', BackendUtility::getModuleUrl('record_edit')); $this->view->assign('performWorkspaceSwitch', $performWorkspaceSwitch); $this->view->assign('workspaceList', $wsList); $this->view->assign('activeWorkspaceUid', $activeWorkspace); $this->view->assign('activeWorkspaceTitle', WorkspaceService::getWorkspaceTitle($activeWorkspace)); if ($wsService->canCreatePreviewLink(GeneralUtility::_GP('id'), $activeWorkspace)) { $buttonBar = $this->view->getModuleTemplate()->getDocHeaderComponent()->getButtonBar(); $iconFactory = $this->view->getModuleTemplate()->getIconFactory(); $showButton = $buttonBar->makeLinkButton()->setHref('#')->setOnClick('TYPO3.Workspaces.Actions.generateWorkspacePreviewLinksForAllLanguages();return false;')->setTitle($this->getLanguageService()->sL('LLL:EXT:workspaces/Resources/Private/Language/locallang.xlf:tooltip.generatePagePreview'))->setIcon($iconFactory->getIcon('module-workspaces-action-preview-link', Icon::SIZE_SMALL)); $buttonBar->addButton($showButton); } $this->view->assign('showPreviewLink', $wsService->canCreatePreviewLink(GeneralUtility::_GP('id'), $activeWorkspace)); $GLOBALS['BE_USER']->setAndSaveSessionData('tx_workspace_activeWorkspace', $activeWorkspace); }
/** * Iterates through elements of $each and renders child nodes * * @param array $record The tt_content record * @param boolean $oncludeTitle If title should be included in output, * @return string */ public function render($record) { $shortcutContent = ''; $tableName = 'tt_content'; if (is_array($record)) { $altText = BackendUtility::getRecordIconAltText($record, $tableName); $iconImg = IconUtility::getSpriteIconForRecord($tableName, $record, array('title' => $altText)); if ($this->getBackendUser()->recordEditAccessInternals($tableName, $record)) { $iconImg = BackendUtility::wrapClickMenuOnIcon($iconImg, $tableName, $record['uid'], 1, '', '+copy,info,edit,view'); } $link = $this->linkEditContent(htmlspecialchars(BackendUtility::getRecordTitle($tableName, $record)), $record); $shortcutContent = $iconImg . $link; } return $shortcutContent; }
/** * Transforms the rows for the deleted Records into the Array View necessary for ExtJS Ext.data.ArrayReader * * @param array $rows Array with table as key and array with all deleted rows * @param integer $totalDeleted: Number of deleted records in total, for PagingToolbar * @return string JSON Array */ public function transform($deletedRowsArray, $totalDeleted) { $total = 0; $jsonArray = array('rows' => array()); // iterate if (is_array($deletedRowsArray) && count($deletedRowsArray) > 0) { foreach ($deletedRowsArray as $table => $rows) { $total += count($deletedRowsArray[$table]); foreach ($rows as $row) { $backendUser = \TYPO3\CMS\Backend\Utility\BackendUtility::getRecord('be_users', $row[$GLOBALS['TCA'][$table]['ctrl']['cruser_id']], 'username', '', FALSE); $jsonArray['rows'][] = array('uid' => $row['uid'], 'pid' => $row['pid'], 'table' => $table, 'crdate' => \TYPO3\CMS\Backend\Utility\BackendUtility::datetime($row[$GLOBALS['TCA'][$table]['ctrl']['crdate']]), 'tstamp' => \TYPO3\CMS\Backend\Utility\BackendUtility::datetime($row[$GLOBALS['TCA'][$table]['ctrl']['tstamp']]), 'owner' => htmlspecialchars($backendUser['username']), 'owner_uid' => $row[$GLOBALS['TCA'][$table]['ctrl']['cruser_id']], 'tableTitle' => \TYPO3\CMS\Recycler\Utility\RecyclerUtility::getUtf8String($GLOBALS['LANG']->sL($GLOBALS['TCA'][$table]['ctrl']['title'])), 'title' => htmlspecialchars(\TYPO3\CMS\Recycler\Utility\RecyclerUtility::getUtf8String(\TYPO3\CMS\Backend\Utility\BackendUtility::getRecordTitle($table, $row))), 'path' => \TYPO3\CMS\Recycler\Utility\RecyclerUtility::getRecordPath($row['pid'])); } } } $jsonArray['total'] = $totalDeleted; return json_encode($jsonArray); }
/** * Returns the title (based on $code) of a record (from table $table) with the proper link around (that is for "pages"-records a link to the level of that record...) * * @param string $table Table name * @param int $uid UID (not used here) * @param string $code Title string * @param array $row Records array (from table name) * @return string */ public function linkWrapItems($table, $uid, $code, $row) { if (!$code) { $code = '<i>[' . htmlspecialchars($this->getLanguageService()->sL('LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:labels.no_title')) . ']</i>'; } else { $code = BackendUtility::getRecordTitlePrep($code, $this->fixedL); } $title = BackendUtility::getRecordTitle($table, $row, false, true); $ficon = $this->iconFactory->getIconForRecord($table, $row, Icon::SIZE_SMALL)->render(); $ATag = '<a href="#" data-close="0" title="' . htmlspecialchars($this->getLanguageService()->getLL('addToList')) . '">'; $ATag_alt = '<a href="#" data-close="1" title="' . htmlspecialchars($this->getLanguageService()->getLL('addToList')) . '">'; $ATag_e = '</a>'; $out = '<span data-uid="' . htmlspecialchars($row['uid']) . '" data-table="' . htmlspecialchars($table) . '" data-title="' . htmlspecialchars($title) . '" data-icon="' . htmlspecialchars($ficon) . '">'; $out .= $ATag . $this->iconFactory->getIcon('actions-edit-add', Icon::SIZE_SMALL)->render() . $ATag_e . $ATag_alt . $code . $ATag_e; $out .= '</span>'; return $out; }
/** * Prepares the list of frontend users. * * @param array $params * @param object $pObj */ public function users(array &$params, $pObj) { if (GeneralUtility::inList('be_groups,fe_groups', $params['table'])) { $databaseConnection = $this->getDatabaseConnection(); $userTable = $params['table'] === 'be_groups' ? 'be_users' : 'fe_users'; /** @var \TYPO3\CMS\Recordlist\RecordList\AbstractDatabaseRecordList $recordList */ $recordList = GeneralUtility::makeInstance('TYPO3\\CMS\\Recordlist\\RecordList\\AbstractDatabaseRecordList'); $recordList->start(0, $userTable, 0); $queryParts = $recordList->makeQueryArray($userTable, 0); $queryParts['WHERE'] = '1=1' . BackendUtility::deleteClause($userTable); $result = $databaseConnection->exec_SELECT_queryArray($queryParts); while (($row = $databaseConnection->sql_fetch_assoc($result)) !== FALSE) { $label = BackendUtility::getRecordTitle($userTable, $row); $params['items'][] = array($label, $row['uid']); } $databaseConnection->sql_free_result($result); } }
/** * Renders the review module user dependent with all workspaces. * The module will show all records of one workspace. * * @return void */ public function indexAction() { $wsService = GeneralUtility::makeInstance(\TYPO3\CMS\Workspaces\Service\WorkspaceService::class); $this->view->assign('showGrid', !($GLOBALS['BE_USER']->workspace === 0 && !$GLOBALS['BE_USER']->isAdmin())); $this->view->assign('showAllWorkspaceTab', TRUE); $this->view->assign('pageUid', GeneralUtility::_GP('id')); if (GeneralUtility::_GP('id')) { $pageRecord = BackendUtility::getRecord('pages', GeneralUtility::_GP('id')); $this->view->assign('pageTitle', BackendUtility::getRecordTitle('pages', $pageRecord)); } $this->view->assign('showLegend', !($GLOBALS['BE_USER']->workspace === 0 && !$GLOBALS['BE_USER']->isAdmin())); $wsList = $wsService->getAvailableWorkspaces(); $activeWorkspace = $GLOBALS['BE_USER']->workspace; $performWorkspaceSwitch = FALSE; // Only admins see multiple tabs, we decided to use it this // way for usability reasons. Regular users might be confused // by switching workspaces with the tabs in a module. if (!$GLOBALS['BE_USER']->isAdmin()) { $wsCur = array($activeWorkspace => TRUE); $wsList = array_intersect_key($wsList, $wsCur); } else { if ((string) GeneralUtility::_GP('workspace') !== '') { $switchWs = (int) GeneralUtility::_GP('workspace'); if (in_array($switchWs, array_keys($wsList)) && $activeWorkspace != $switchWs) { $activeWorkspace = $switchWs; $GLOBALS['BE_USER']->setWorkspace($activeWorkspace); $performWorkspaceSwitch = TRUE; BackendUtility::setUpdateSignal('updatePageTree'); } elseif ($switchWs == WorkspaceService::SELECT_ALL_WORKSPACES) { $this->redirect('fullIndex'); } } } $this->pageRenderer->addInlineSetting('Workspaces', 'isLiveWorkspace', (int) $GLOBALS['BE_USER']->workspace === 0 ? TRUE : FALSE); $this->pageRenderer->addInlineSetting('Workspaces', 'workspaceTabs', $this->prepareWorkspaceTabs($wsList, $activeWorkspace)); $this->pageRenderer->addInlineSetting('Workspaces', 'activeWorkspaceId', $activeWorkspace); $this->pageRenderer->addInlineSetting('FormEngine', 'moduleUrl', BackendUtility::getModuleUrl('record_edit')); $this->view->assign('performWorkspaceSwitch', $performWorkspaceSwitch); $this->view->assign('workspaceList', $wsList); $this->view->assign('activeWorkspaceUid', $activeWorkspace); $this->view->assign('activeWorkspaceTitle', WorkspaceService::getWorkspaceTitle($activeWorkspace)); $this->view->assign('showPreviewLink', $wsService->canCreatePreviewLink(GeneralUtility::_GP('id'), $activeWorkspace)); $GLOBALS['BE_USER']->setAndSaveSessionData('tx_workspace_activeWorkspace', $activeWorkspace); }
/** * Transforms the rows for the deleted records * * @param array $deletedRowsArray Array with table as key and array with all deleted rows * @param int $totalDeleted Number of deleted records in total * @return string JSON array */ public function transform($deletedRowsArray, $totalDeleted) { $total = 0; $jsonArray = array('rows' => array()); if (is_array($deletedRowsArray)) { $lang = $this->getLanguageService(); $iconFactory = GeneralUtility::makeInstance(IconFactory::class); foreach ($deletedRowsArray as $table => $rows) { $total += count($deletedRowsArray[$table]); foreach ($rows as $row) { $pageTitle = $this->getPageTitle((int) $row['pid']); $backendUser = BackendUtility::getRecord('be_users', $row[$GLOBALS['TCA'][$table]['ctrl']['cruser_id']], 'username', '', false); $jsonArray['rows'][] = array('uid' => $row['uid'], 'pid' => $row['pid'], 'icon' => $iconFactory->getIconForRecord($table, $row, Icon::SIZE_SMALL)->render(), 'pageTitle' => $pageTitle, 'table' => $table, 'crdate' => BackendUtility::datetime($row[$GLOBALS['TCA'][$table]['ctrl']['crdate']]), 'tstamp' => BackendUtility::datetime($row[$GLOBALS['TCA'][$table]['ctrl']['tstamp']]), 'owner' => htmlspecialchars($backendUser['username']), 'owner_uid' => $row[$GLOBALS['TCA'][$table]['ctrl']['cruser_id']], 'tableTitle' => $lang->sL($GLOBALS['TCA'][$table]['ctrl']['title']), 'title' => htmlspecialchars(BackendUtility::getRecordTitle($table, $row)), 'path' => RecyclerUtility::getRecordPath($row['pid'])); } } } $jsonArray['total'] = $totalDeleted; return $jsonArray; }
/** * Transforms the rows for the deleted records * * @param array $deletedRowsArray Array with table as key and array with all deleted rows * @param int $totalDeleted Number of deleted records in total * @return string JSON array */ public function transform($deletedRowsArray, $totalDeleted) { $total = 0; $jsonArray = array('rows' => array()); if (is_array($deletedRowsArray)) { $lang = $this->getLanguageService(); $backendUser = $this->getBackendUser(); foreach ($deletedRowsArray as $table => $rows) { $total += count($deletedRowsArray[$table]); foreach ($rows as $row) { $pageTitle = $this->getPageTitle((int) $row['pid']); $backendUser = BackendUtility::getRecord('be_users', $row[$GLOBALS['TCA'][$table]['ctrl']['cruser_id']], 'username', '', FALSE); $jsonArray['rows'][] = array('uid' => $row['uid'], 'pid' => $row['pid'], 'icon' => IconUtility::getSpriteIconForRecord($table, $row), 'pageTitle' => RecyclerUtility::getUtf8String($pageTitle), 'table' => $table, 'crdate' => BackendUtility::datetime($row[$GLOBALS['TCA'][$table]['ctrl']['crdate']]), 'tstamp' => BackendUtility::datetime($row[$GLOBALS['TCA'][$table]['ctrl']['tstamp']]), 'owner' => htmlspecialchars($backendUser['username']), 'owner_uid' => $row[$GLOBALS['TCA'][$table]['ctrl']['cruser_id']], 'tableTitle' => RecyclerUtility::getUtf8String($lang->sL($GLOBALS['TCA'][$table]['ctrl']['title'])), 'title' => htmlspecialchars(RecyclerUtility::getUtf8String(BackendUtility::getRecordTitle($table, $row))), 'path' => RecyclerUtility::getRecordPath($row['pid'])); } } } $jsonArray['total'] = $totalDeleted; return $jsonArray; }
/** * Main method * * @param CLickMenu $backRef * @param array $menuItems * @param string $table * @param int $uid * * @return array */ public function main($backRef, array $menuItems, $table = '', $uid = 0) { if ($table === 'tt_content') { $this->setLanguageService($GLOBALS['LANG']); // add "paste reference after" if user is allowed to use CType shortcut if ($this->getBackendUser()->checkAuthMode('tt_content', 'CType', 'shortcut', 'explicitAllow')) { if ($menuItems['pasteafter']) { unset($menuItems['pasteafter']); $selItem = $backRef->clipObj->getSelectedRecord(); $targetItem = BackendUtility::getRecordRaw('tt_content', 'uid = ' . $uid, 'colPos,tx_gridelements_container,tx_gridelements_columns'); $elInfo = array(GeneralUtility::fixed_lgd_cs($selItem['_RECORD_TITLE'], $this->getBackendUser()->uc['titleLen']), $backRef->root ? $GLOBALS['TYPO3_CONF_VARS']['SYS']['sitename'] : GeneralUtility::fixed_lgd_cs(BackendUtility::getRecordTitle($table, $backRef->rec), $this->getBackendUser()->uc['titleLen']), $backRef->clipObj->currentMode()); $menuItems['pasteafter'] = $this->DB_paste($backRef, $table, -$uid, 'after', $elInfo, $targetItem, false); if ($backRef->clipObj->currentMode() === 'copy') { $menuItems['pastereference'] = $this->DB_paste($backRef, $table, -$uid, 'after', $elInfo, $targetItem, true); } } } } return $menuItems; }
/** * Returns the title of a record (from table $table) with the proper link around (that is for "pages"-records a link to the level of that record) * * @param string $table Table name * @param integer $uid UID * @param string $title Title string * @param array $row Records array (from table name) * @return string */ public function linkWrapItems($table, $uid, $title, $row) { // if we handle translation records, make sure that we refer to the localisation parent with their uid if (is_array($GLOBALS['TCA'][$table]['ctrl']) && array_key_exists('transOrigPointerField', $GLOBALS['TCA'][$table]['ctrl'])) { $transOrigPointerField = $GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField']; if (\TYPO3\CMS\Core\Utility\MathUtility::convertToPositiveInteger($row[$transOrigPointerField]) > 0) { $uid = $row[$transOrigPointerField]; } } $currentImage = ''; if ($this->browselistObj->curUrlInfo['recordTable'] === $table && $this->browselistObj->curUrlInfo['recordUid'] === $uid) { $currentImage = '<img' . \TYPO3\CMS\Backend\Utility\IconUtility::skinImg($GLOBALS['BACK_PATH'], 'gfx/blinkarrow_right.gif', 'width="5" height="9"') . ' class="c-blinkArrowL" alt="" />'; } $title = \TYPO3\CMS\Backend\Utility\BackendUtility::getRecordTitle($table, $row, FALSE, TRUE); if (@$this->browselistObj->mode === 'rte') { //used in RTE mode: $aOnClick = 'return link_spec(\'' . $this->linkHandler . ':' . $table . ':' . $uid . '\');'; } else { //used in wizard mode $aOnClick = 'return link_folder(\'' . $this->linkHandler . ':' . $table . ':' . $uid . '\');'; } return '<a href="#" onclick="' . $aOnClick . '">' . $title . $currentImage . '</a>'; }
/** * Rendering the information * * @param BrowseTreeView $tree The Page tree data * * @return string HTML for the information table. */ protected function renderModule(BrowseTreeView $tree) { $rows = []; $cache = CacheUtility::getCache(); foreach ($tree->tree as $row) { $cacheEntries = $cache->getByTag('sfc_pageId_' . $row['row']['uid']); if ($cacheEntries) { $isFirst = true; foreach ($cacheEntries as $identifier => $info) { $cell = ['uid' => $row['row']['uid'], 'title' => $isFirst ? $row['HTML'] . BackendUtility::getRecordTitle('pages', $row['row'], true) : $row['HTML_depthData'], 'identifier' => $identifier, 'info' => $info, 'depthData' => $row['depthData']]; $isFirst = false; $rows[] = $cell; } } else { $cell = ['uid' => $row['row']['uid'], 'title' => $row['HTML'] . BackendUtility::getRecordTitle('pages', $row['row'], true), 'depthData' => $row['depthData']]; $rows[] = $cell; } } /** @var StandaloneView $renderer */ $renderer = GeneralUtility::makeInstance(StandaloneView::class); $renderer->setTemplatePathAndFilename(GeneralUtility::getFileAbsFileName('EXT:nc_staticfilecache/Resources/Private/Templates/Module.html')); $renderer->assignMultiple(['requestUri' => GeneralUtility::getIndpEnv('REQUEST_URI'), 'rows' => $rows, 'pageId' => $this->pageId]); return $renderer->render(); }
/** * For RTE: This displays all content elements on a page and lets you create a link to the element. * * @return string HTML output. Returns content only if the ->expandPage value is set (pointing to a page uid to show tt_content records from ...) * @todo Define visibility */ public function expandPage() { $out = ''; // Set page id (if any) to expand $expPageId = $this->expandPage; // If there is an anchor value (content element reference) in the element reference, then force an ID to expand: if (!$this->expandPage && $this->curUrlInfo['cElement']) { // Set to the current link page id. $expPageId = $this->curUrlInfo['pageid']; } // Draw the record list IF there is a page id to expand: if ($expPageId && \TYPO3\CMS\Core\Utility\MathUtility::canBeInterpretedAsInteger($expPageId) && $GLOBALS['BE_USER']->isInWebMount($expPageId)) { // Set header: $out .= $this->barheader($GLOBALS['LANG']->getLL('contentElements') . ':'); // Create header for listing, showing the page title/icon: $mainPageRec = BackendUtility::getRecordWSOL('pages', $expPageId); $picon = IconUtility::getSpriteIconForRecord('pages', $mainPageRec); $picon .= BackendUtility::getRecordTitle('pages', $mainPageRec, TRUE); $out .= $picon . '<br />'; // Look up tt_content elements from the expanded page: $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('uid,header,hidden,starttime,endtime,fe_group,CType,colPos,bodytext', 'tt_content', 'pid=' . (int) $expPageId . BackendUtility::deleteClause('tt_content') . BackendUtility::versioningPlaceholderClause('tt_content'), '', 'colPos,sorting'); $cc = $GLOBALS['TYPO3_DB']->sql_num_rows($res); // Traverse list of records: $c = 0; while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) { $c++; $icon = IconUtility::getSpriteIconForRecord('tt_content', $row); if ($this->curUrlInfo['act'] == 'page' && $this->curUrlInfo['cElement'] == $row['uid']) { $arrCol = '<img' . IconUtility::skinImg($GLOBALS['BACK_PATH'], 'gfx/blinkarrow_left.gif', 'width="5" height="9"') . ' class="c-blinkArrowL" alt="" />'; } else { $arrCol = ''; } // Putting list element HTML together: $out .= '<img' . IconUtility::skinImg($GLOBALS['BACK_PATH'], 'gfx/ol/join' . ($c == $cc ? 'bottom' : '') . '.gif', 'width="18" height="16"') . ' alt="" />' . $arrCol . '<a href="#" onclick="return link_typo3Page(\'' . $expPageId . '\',\'#' . $row['uid'] . '\');">' . $icon . BackendUtility::getRecordTitle('tt_content', $row, TRUE) . '</a><br />'; // Finding internal anchor points: if (GeneralUtility::inList('text,textpic', $row['CType'])) { $split = preg_split('/(<a[^>]+name=[\'"]?([^"\'>[:space:]]+)[\'"]?[^>]*>)/i', $row['bodytext'], -1, PREG_SPLIT_DELIM_CAPTURE); foreach ($split as $skey => $sval) { if ($skey % 3 == 2) { // Putting list element HTML together: $sval = substr($sval, 0, 100); $out .= '<img' . IconUtility::skinImg($GLOBALS['BACK_PATH'], 'gfx/ol/line.gif', 'width="18" height="16"') . ' alt="" />' . '<img' . IconUtility::skinImg($GLOBALS['BACK_PATH'], 'gfx/ol/join' . ($skey + 3 > count($split) ? 'bottom' : '') . '.gif', 'width="18" height="16"') . ' alt="" />' . '<a href="#" onclick="return link_typo3Page(' . GeneralUtility::quoteJSvalue($expPageId) . ',' . GeneralUtility::quoteJSvalue('#' . $sval) . ';">' . htmlspecialchars(' <A> ' . $sval) . '</a><br />'; } } } } } return $out; }
/** * Adds the record $row from $table. * No checking for relations done here. Pure data. * * @param string $table Table name * @param array $row Record row. * @param integer $relationLevel (Internal) if the record is added as a relation, this is set to the "level" it was on. * @return void * @todo Define visibility */ public function export_addRecord($table, $row, $relationLevel = 0) { \TYPO3\CMS\Backend\Utility\BackendUtility::workspaceOL($table, $row); if (strcmp($table, '') && is_array($row) && $row['uid'] > 0 && !$this->excludeMap[$table . ':' . $row['uid']]) { if ($this->checkPID($table === 'pages' ? $row['uid'] : $row['pid'])) { if (!isset($this->dat['records'][$table . ':' . $row['uid']])) { // Prepare header info: $headerInfo = array(); $headerInfo['uid'] = $row['uid']; $headerInfo['pid'] = $row['pid']; $headerInfo['title'] = \TYPO3\CMS\Core\Utility\GeneralUtility::fixed_lgd_cs(\TYPO3\CMS\Backend\Utility\BackendUtility::getRecordTitle($table, $row), 40); $headerInfo['size'] = strlen(serialize($row)); if ($relationLevel) { $headerInfo['relationLevel'] = $relationLevel; } // If record content is not too large in size, set the header content and add the rest: if ($headerInfo['size'] < $this->maxRecordSize) { // Set the header summary: $this->dat['header']['records'][$table][$row['uid']] = $headerInfo; // Create entry in the PID lookup: $this->dat['header']['pid_lookup'][$row['pid']][$table][$row['uid']] = 1; // Initialize reference index object: $refIndexObj = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Database\\ReferenceIndex'); // Yes to workspace overlays for exporting.... $refIndexObj->WSOL = TRUE; // Data: $this->dat['records'][$table . ':' . $row['uid']] = array(); $this->dat['records'][$table . ':' . $row['uid']]['data'] = $row; $this->dat['records'][$table . ':' . $row['uid']]['rels'] = $refIndexObj->getRelations($table, $row); $this->errorLog = array_merge($this->errorLog, $refIndexObj->errorLog); // Merge error logs. // Add information about the relations in the record in the header: $this->dat['header']['records'][$table][$row['uid']]['rels'] = $this->flatDBrels($this->dat['records'][$table . ':' . $row['uid']]['rels']); // Add information about the softrefs to header: $this->dat['header']['records'][$table][$row['uid']]['softrefs'] = $this->flatSoftRefs($this->dat['records'][$table . ':' . $row['uid']]['rels']); } else { $this->error('Record ' . $table . ':' . $row['uid'] . ' was larger than maxRecordSize (' . \TYPO3\CMS\Core\Utility\GeneralUtility::formatSize($this->maxRecordSize) . ')'); } } else { $this->error('Record ' . $table . ':' . $row['uid'] . ' already added.'); } } else { $this->error('Record ' . $table . ':' . $row['uid'] . ' was outside your DB mounts!'); } } }
/** * Send an email notification to users in workspace * * @param array $stat Workspace access array from \TYPO3\CMS\Core\Authentication\BackendUserAuthentication::checkWorkspace() * @param int $stageId New Stage number: 0 = editing, 1= just ready for review, 10 = ready for publication, -1 = rejected! * @param string $table Table name of element (or list of element names if $id is zero) * @param int $id Record uid of element (if zero, then $table is used as reference to element(s) alone) * @param string $comment User comment sent along with action * @param DataHandler $tcemainObj TCEmain object * @param array $notificationAlternativeRecipients List of recipients to notify instead of be_users selected by sys_workspace, list is generated by workspace extension module * @return void */ protected function notifyStageChange(array $stat, $stageId, $table, $id, $comment, DataHandler $tcemainObj, array $notificationAlternativeRecipients = array()) { $workspaceRec = BackendUtility::getRecord('sys_workspace', $stat['uid']); // So, if $id is not set, then $table is taken to be the complete element name! $elementName = $id ? $table . ':' . $id : $table; if (!is_array($workspaceRec)) { return; } // Get the new stage title from workspaces library, if workspaces extension is installed if (\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::isLoaded('workspaces')) { $stageService = GeneralUtility::makeInstance(\TYPO3\CMS\Workspaces\Service\StagesService::class); $newStage = $stageService->getStageTitle((int) $stageId); } else { // @todo CONSTANTS SHOULD BE USED - tx_service_workspace_workspaces // @todo use localized labels // Compile label: switch ((int) $stageId) { case 1: $newStage = 'Ready for review'; break; case 10: $newStage = 'Ready for publishing'; break; case -1: $newStage = 'Element was rejected!'; break; case 0: $newStage = 'Rejected element was noticed and edited'; break; default: $newStage = 'Unknown state change!?'; } } if (count($notificationAlternativeRecipients) == 0) { // Compile list of recipients: $emails = array(); switch ((int) $stat['stagechg_notification']) { case 1: switch ((int) $stageId) { case 1: $emails = $this->getEmailsForStageChangeNotification($workspaceRec['reviewers']); break; case 10: $emails = $this->getEmailsForStageChangeNotification($workspaceRec['adminusers'], TRUE); break; case -1: // List of elements to reject: $allElements = explode(',', $elementName); // Traverse them, and find the history of each foreach ($allElements as $elRef) { list($eTable, $eUid) = explode(':', $elRef); $rows = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows('log_data,tstamp,userid', 'sys_log', 'action=6 and details_nr=30 AND tablename=' . $GLOBALS['TYPO3_DB']->fullQuoteStr($eTable, 'sys_log') . ' AND recuid=' . (int) $eUid, '', 'uid DESC'); // Find all implicated since the last stage-raise from editing to review: foreach ($rows as $dat) { $data = unserialize($dat['log_data']); $emails = $this->getEmailsForStageChangeNotification($dat['userid'], TRUE) + $emails; if ($data['stage'] == 1) { break; } } } break; case 0: $emails = $this->getEmailsForStageChangeNotification($workspaceRec['members']); break; default: $emails = $this->getEmailsForStageChangeNotification($workspaceRec['adminusers'], TRUE); } break; case 10: $emails = $this->getEmailsForStageChangeNotification($workspaceRec['adminusers'], TRUE); $emails = $this->getEmailsForStageChangeNotification($workspaceRec['reviewers']) + $emails; $emails = $this->getEmailsForStageChangeNotification($workspaceRec['members']) + $emails; break; default: // Do nothing } } else { $emails = $notificationAlternativeRecipients; } // prepare and then send the emails if (count($emails)) { // Path to record is found: list($elementTable, $elementUid) = explode(':', $elementName); $elementUid = (int) $elementUid; $elementRecord = BackendUtility::getRecord($elementTable, $elementUid); $recordTitle = BackendUtility::getRecordTitle($elementTable, $elementRecord); if ($elementTable == 'pages') { $pageUid = $elementUid; } else { BackendUtility::fixVersioningPid($elementTable, $elementRecord); $pageUid = $elementUid = $elementRecord['pid']; } // fetch the TSconfig settings for the email // old way, options are TCEMAIN.notificationEmail_body/subject $TCEmainTSConfig = $tcemainObj->getTCEMAIN_TSconfig($pageUid); // new way, options are // pageTSconfig: tx_version.workspaces.stageNotificationEmail.subject // userTSconfig: page.tx_version.workspaces.stageNotificationEmail.subject $pageTsConfig = BackendUtility::getPagesTSconfig($pageUid); $emailConfig = $pageTsConfig['tx_version.']['workspaces.']['stageNotificationEmail.']; $markers = array('###RECORD_TITLE###' => $recordTitle, '###RECORD_PATH###' => BackendUtility::getRecordPath($elementUid, '', 20), '###SITE_NAME###' => $GLOBALS['TYPO3_CONF_VARS']['SYS']['sitename'], '###SITE_URL###' => GeneralUtility::getIndpEnv('TYPO3_SITE_URL') . TYPO3_mainDir, '###WORKSPACE_TITLE###' => $workspaceRec['title'], '###WORKSPACE_UID###' => $workspaceRec['uid'], '###ELEMENT_NAME###' => $elementName, '###NEXT_STAGE###' => $newStage, '###COMMENT###' => $comment, '###USER_REALNAME###' => $tcemainObj->BE_USER->user['realName'], '###USER_FULLNAME###' => $tcemainObj->BE_USER->user['realName'], '###USER_USERNAME###' => $tcemainObj->BE_USER->user['username']); // add marker for preview links if workspace extension is loaded if (\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::isLoaded('workspaces')) { $this->workspaceService = GeneralUtility::makeInstance(\TYPO3\CMS\Workspaces\Service\WorkspaceService::class); // only generate the link if the marker is in the template - prevents database from getting to much entries if (GeneralUtility::isFirstPartOfStr($emailConfig['message'], 'LLL:')) { $tempEmailMessage = $GLOBALS['LANG']->sL($emailConfig['message']); } else { $tempEmailMessage = $emailConfig['message']; } if (strpos($tempEmailMessage, '###PREVIEW_LINK###') !== FALSE) { $markers['###PREVIEW_LINK###'] = $this->workspaceService->generateWorkspacePreviewLink($elementUid); } unset($tempEmailMessage); $markers['###SPLITTED_PREVIEW_LINK###'] = $this->workspaceService->generateWorkspaceSplittedPreviewLink($elementUid, TRUE); } // Hook for preprocessing of the content for formmails: if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/version/class.tx_version_tcemain.php']['notifyStageChange-postModifyMarkers'])) { foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/version/class.tx_version_tcemain.php']['notifyStageChange-postModifyMarkers'] as $_classRef) { $_procObj =& GeneralUtility::getUserObj($_classRef); $markers = $_procObj->postModifyMarkers($markers, $this); } } // send an email to each individual user, to ensure the // multilanguage version of the email $emailRecipients = array(); // an array of language objects that are needed // for emails with different languages $languageObjects = array($GLOBALS['LANG']->lang => $GLOBALS['LANG']); // loop through each recipient and send the email foreach ($emails as $recipientData) { // don't send an email twice if (isset($emailRecipients[$recipientData['email']])) { continue; } $emailSubject = $emailConfig['subject']; $emailMessage = $emailConfig['message']; $emailRecipients[$recipientData['email']] = $recipientData['email']; // check if the email needs to be localized // in the users' language if (GeneralUtility::isFirstPartOfStr($emailSubject, 'LLL:') || GeneralUtility::isFirstPartOfStr($emailMessage, 'LLL:')) { $recipientLanguage = $recipientData['lang'] ? $recipientData['lang'] : 'default'; if (!isset($languageObjects[$recipientLanguage])) { // a LANG object in this language hasn't been // instantiated yet, so this is done here /** @var $languageObject \TYPO3\CMS\Lang\LanguageService */ $languageObject = GeneralUtility::makeInstance(\TYPO3\CMS\Lang\LanguageService::class); $languageObject->init($recipientLanguage); $languageObjects[$recipientLanguage] = $languageObject; } else { $languageObject = $languageObjects[$recipientLanguage]; } if (GeneralUtility::isFirstPartOfStr($emailSubject, 'LLL:')) { $emailSubject = $languageObject->sL($emailSubject); } if (GeneralUtility::isFirstPartOfStr($emailMessage, 'LLL:')) { $emailMessage = $languageObject->sL($emailMessage); } } $emailSubject = \TYPO3\CMS\Core\Html\HtmlParser::substituteMarkerArray($emailSubject, $markers, '', TRUE, TRUE); $emailMessage = \TYPO3\CMS\Core\Html\HtmlParser::substituteMarkerArray($emailMessage, $markers, '', TRUE, TRUE); // Send an email to the recipient /** @var $mail \TYPO3\CMS\Core\Mail\MailMessage */ $mail = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Mail\MailMessage::class); if (!empty($recipientData['realName'])) { $recipient = array($recipientData['email'] => $recipientData['realName']); } else { $recipient = $recipientData['email']; } $mail->setTo($recipient)->setSubject($emailSubject)->setFrom(\TYPO3\CMS\Core\Utility\MailUtility::getSystemFrom())->setBody($emailMessage); $mail->send(); } $emailRecipients = implode(',', $emailRecipients); $tcemainObj->newlog2('Notification email for stage change was sent to "' . $emailRecipients . '"', $table, $id); } }
/** * Returns the title (based on $code) of a record (from table $table) with * the proper link around (that is for 'tx_commerce_categories'-records * a link to the level of that record...) * * @param string $table Table name * @param int $uid Item uid * @param string $code Item title (not htmlspecialchars()'ed yet) * @param array $row Item row * * @return string The item title. Ready for HTML output */ public function linkWrapItems($table, $uid, $code, array $row) { $language = $this->getLanguageService(); $backendUser = $this->getBackendUser(); // If the title is blank, make a "no title" label: if (!strcmp($code, '')) { $code = '<i>[' . $language->sL('LLL:EXT:lang/locallang_core.php:labels.no_title', 1) . ']</i> - ' . htmlspecialchars(GeneralUtility::fixed_lgd_cs(BackendUtility::getRecordTitle($table, $row), $backendUser->uc['titleLen'])); } else { $code = htmlspecialchars(GeneralUtility::fixed_lgd_cs($code, $this->fixedL)); } switch ((string) $this->clickTitleMode) { case 'edit': // If the listed table is 'tx_commerce_categories' we have to // request the permission settings for each page: if ($table == 'tx_commerce_categories') { $localCalcPerms = $backendUser->calcPerms(BackendUtility::getRecord('tx_commerce_categories', $row['uid'])); $permsEdit = $localCalcPerms & 2; } else { $permsEdit = $this->calcPerms & 16; } // "Edit" link: ( Only if permissions to edit the page-record // of the content of the parent page ($this->id) if ($permsEdit) { $params = '&edit[' . $table . '][' . $row['uid'] . ']=edit'; $code = '<a href="#" onclick="' . htmlspecialchars(BackendUtility::editOnClick($params, $this->backPath, -1)) . '" title="' . $language->getLL('edit', 1) . '">' . $code . '</a>'; } break; case 'show': // "Show" link (only tx_commerce_categories and tx_commerce_products elements) if ($table == 'tx_commerce_categories' || $table == 'tx_commerce_products') { $code = '<a href="#" onclick="' . htmlspecialchars(BackendUtility::viewOnClick($table == 'tx_commerce_products' ? $this->id . '#' . $row['uid'] : $row['uid'])) . '" title="' . $language->sL('LLL:EXT:lang/locallang_core.php:labels.showPage', 1) . '">' . $code . '</a>'; } break; case 'info': // "Info": (All records) $code = '<a href="#" onclick="' . htmlspecialchars('top.launchView(\'' . $table . '\', \'' . $row['uid'] . '\'); return false;') . '" title="' . $language->getLL('showInfo', 1) . '">' . $code . '</a>'; break; default: // Output the label now: if ($table == 'tx_commerce_categories') { $code = '<a href="' . htmlspecialchars($this->listURL($uid, '')) . '">' . $code . '</a>'; } } return $code; }
/** * For RTE: This displays all content elements on a page and lets you create a link to the element. * * @return string HTML output. Returns content only if the ->expandPage value is set (pointing to a page uid to show tt_content records from ...) */ function expandPage() { $out = ''; $expPageId = $this->browseLinks->expandPage; // Set page id (if any) to expand // If there is an anchor value (content element reference) in the element reference, then force an ID to expand: if (!$this->browseLinks->expandPage && $this->browseLinks->curUrlInfo['cElement']) { $expPageId = $this->browseLinks->curUrlInfo['pageid']; // Set to the current link page id. } // Draw the record list IF there is a page id to expand: if ($expPageId && t3lib_utility_Math::canBeInterpretedAsInteger($expPageId) && $GLOBALS['BE_USER']->isInWebMount($expPageId)) { // Set header: $out .= $this->browseLinks->barheader($GLOBALS['LANG']->getLL('contentElements') . ':'); // Create header for listing, showing the page title/icon: $titleLen = intval($GLOBALS['BE_USER']->uc['titleLen']); $mainPageRec = \TYPO3\CMS\Backend\Utility\BackendUtility::getRecordWSOL('pages', $expPageId); $picon = t3lib_iconWorks::getSpriteIconForRecord('pages', $mainPageRec); $picon .= \TYPO3\CMS\Backend\Utility\BackendUtility::getRecordTitle('pages', $mainPageRec, TRUE); $out .= $picon . '<br />'; // Look up tt_content elements from the expanded page: $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('uid,header,hidden,starttime,endtime,fe_group,CType,colPos,bodytext,tx_jfmulticontent_view,tx_jfmulticontent_pages,tx_jfmulticontent_contents', 'tt_content', 'pid=' . intval($expPageId) . \TYPO3\CMS\Backend\Utility\BackendUtility::deleteClause('tt_content') . \TYPO3\CMS\Backend\Utility\BackendUtility::versioningPlaceholderClause('tt_content'), '', 'colPos,sorting'); $cc = $GLOBALS['TYPO3_DB']->sql_num_rows($res); // Traverse list of records: $c = 0; while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) { $c++; $icon = t3lib_iconWorks::getSpriteIconForRecord('tt_content', $row); if ($this->browseLinks->curUrlInfo['act'] == 'page' && $this->browseLinks->curUrlInfo['cElement'] == $row['uid']) { $arrCol = '<img' . t3lib_iconWorks::skinImg($GLOBALS['BACK_PATH'], 'gfx/blinkarrow_left.gif', 'width="5" height="9"') . ' class="c-blinkArrowL" alt="" />'; } else { $arrCol = ''; } // Putting list element HTML together: $out .= '<img' . t3lib_iconWorks::skinImg($GLOBALS['BACK_PATH'], 'gfx/ol/join' . ($c == $cc ? 'bottom' : '') . '.gif', 'width="18" height="16"') . ' alt="" />' . $arrCol . '<a href="#" onclick="return link_typo3Page(\'' . $expPageId . '\',\'#' . $row['uid'] . '\');">' . $icon . \TYPO3\CMS\Backend\Utility\BackendUtility::getRecordTitle('tt_content', $row, TRUE) . '</a><br />'; $contents = array(); // get all contents switch ($row['tx_jfmulticontent_view']) { case "page": $contents = \TYPO3\CMS\Core\Utility\GeneralUtility::trimExplode(",", $row['tx_jfmulticontent_pages']); break; case "content": $contents = \TYPO3\CMS\Core\Utility\GeneralUtility::trimExplode(",", $row['tx_jfmulticontent_contents']); break; case "irre": $resIrre = $GLOBALS['TYPO3_DB']->exec_SELECTquery('*', 'tt_content', 'tx_jfmulticontent_irre_parentid=' . intval($row['uid']) . ' AND deleted = 0 AND hidden = 0', '', ''); while ($rowIrre = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($resIrre)) { $contents[] = $rowIrre['uid']; } break; } if (count($contents) > 0) { $out .= '<img' . t3lib_iconWorks::skinImg($GLOBALS['BACK_PATH'], 'gfx/ol/line.gif', 'width="18" height="16"') . ' alt="" />' . '<img' . t3lib_iconWorks::skinImg($GLOBALS['BACK_PATH'], 'gfx/ol/blank.gif', 'width="18" height="16"') . ' alt="" />'; foreach ($contents as $key => $content) { $out .= '<a href="#" onclick="return link_typo3Page(\'' . $expPageId . '\',\'#jfmulticontent_c' . $row['uid'] . '-' . ($key + 1) . '\');">' . ' ' . ($key + 1) . ' ' . '</a>'; } $out .= '<br/>'; } } } return $out; }
/** * Main method of modfuncreport * * @return string Module content */ public function main() { $this->getLanguageService()->includeLLFile('EXT:linkvalidator/Resources/Private/Language/Module/locallang.xlf'); $this->searchLevel = GeneralUtility::_GP('search_levels'); if (isset($this->pObj->id)) { $this->modTS = BackendUtility::getModTSconfig($this->pObj->id, 'mod.linkvalidator'); $this->modTS = $this->modTS['properties']; } $update = GeneralUtility::_GP('updateLinkList'); $prefix = ''; if (!empty($update)) { $prefix = 'check'; } $set = GeneralUtility::_GP($prefix . 'SET'); $this->pObj->handleExternalFunctionValue(); if (isset($this->searchLevel)) { $this->pObj->MOD_SETTINGS['searchlevel'] = $this->searchLevel; } else { $this->searchLevel = $this->pObj->MOD_SETTINGS['searchlevel']; } if (is_array($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['linkvalidator']['checkLinks'])) { foreach ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['linkvalidator']['checkLinks'] as $linkType => $value) { // Compile list of all available types. Used for checking with button "Check Links". if (strpos($this->modTS['linktypes'], $linkType) !== FALSE) { $this->availableOptions[$linkType] = 1; } // Compile list of types currently selected by the checkboxes if ($this->pObj->MOD_SETTINGS[$linkType] && empty($set) || $set[$linkType]) { $this->checkOpt[$linkType] = 1; $this->pObj->MOD_SETTINGS[$linkType] = 1; } else { $this->pObj->MOD_SETTINGS[$linkType] = 0; unset($this->checkOpt[$linkType]); } } } $this->getBackendUser()->pushModuleData('web_info', $this->pObj->MOD_SETTINGS); $this->initialize(); // Localization $this->doc->getPageRenderer()->addInlineLanguageLabelFile(ExtensionManagementUtility::extPath('linkvalidator', 'Resources/Private/Language/Module/locallang.xlf')); if ($this->modTS['showCheckLinkTab'] == 1) { $this->updateListHtml = '<input class="btn btn-default" type="submit" name="updateLinkList" id="updateLinkList" value="' . $this->getLanguageService()->getLL('label_update') . '"/>'; } $this->refreshListHtml = '<input class="btn btn-default" type="submit" name="refreshLinkList" id="refreshLinkList" value="' . $this->getLanguageService()->getLL('label_refresh') . '"/>'; $this->linkAnalyzer = GeneralUtility::makeInstance(LinkAnalyzer::class); $this->updateBrokenLinks(); $brokenLinkOverView = $this->linkAnalyzer->getLinkCounts($this->pObj->id); $this->checkOptionsHtml = $this->getCheckOptions($brokenLinkOverView); $this->checkOptionsHtmlCheck = $this->getCheckOptions($brokenLinkOverView, 'check'); $this->render(); $pageTile = ''; if ($this->pObj->id) { $pageRecord = BackendUtility::getRecord('pages', $this->pObj->id); $pageTile = '<h1>' . htmlspecialchars(BackendUtility::getRecordTitle('pages', $pageRecord)) . '</h1>'; } return '<div id="linkvalidator-modfuncreport">' . $pageTile . $this->createTabs() . '</div>'; }
/** * Make 1st level clickmenu: * * @param string $table The absolute path * @param integer $srcId UID for the current record. * @param integer $dstId Destination ID * @return string HTML content * @todo Define visibility */ public function printDragDropClickMenu($table, $srcId, $dstId) { $menuItems = array(); // If the drag and drop menu should apply to PAGES use this set of menu items if ($table == 'pages') { // Move Into: $menuItems['movePage_into'] = $this->dragDrop_copymovepage($srcId, $dstId, 'move', 'into'); // Move After: $menuItems['movePage_after'] = $this->dragDrop_copymovepage($srcId, $dstId, 'move', 'after'); // Copy Into: $menuItems['copyPage_into'] = $this->dragDrop_copymovepage($srcId, $dstId, 'copy', 'into'); // Copy After: $menuItems['copyPage_after'] = $this->dragDrop_copymovepage($srcId, $dstId, 'copy', 'after'); } // If the drag and drop menu should apply to FOLDERS use this set of menu items if ($table == 'folders') { // Move Into: $menuItems['moveFolder_into'] = $this->dragDrop_copymovefolder($srcId, $dstId, 'move'); // Copy Into: $menuItems['copyFolder_into'] = $this->dragDrop_copymovefolder($srcId, $dstId, 'copy'); } // Adding external elements to the menuItems array $menuItems = $this->processingByExtClassArray($menuItems, 'dragDrop_' . $table, $srcId); // to extend this, you need to apply a Context Menu to a "virtual" table called "dragDrop_pages" or similar // Processing by external functions? $menuItems = $this->externalProcessingOfDBMenuItems($menuItems); // Return the printed elements: return $this->printItems($menuItems, \TYPO3\CMS\Backend\Utility\IconUtility::getSpriteIconForRecord($table, $this->rec, array('title' => \TYPO3\CMS\Backend\Utility\BackendUtility::getRecordTitle($table, $this->rec, TRUE)))); }
/** * Generates grid list array from given versions. * * @param array $versions All available version records * @param string $filterTxt Text to be used to filter record result * @return void */ protected function generateDataArray(array $versions, $filterTxt) { $workspaceAccess = $GLOBALS['BE_USER']->checkWorkspace($GLOBALS['BE_USER']->workspace); $swapStage = $workspaceAccess['publish_access'] & 1 ? \TYPO3\CMS\Workspaces\Service\StagesService::STAGE_PUBLISH_ID : 0; $swapAccess = $GLOBALS['BE_USER']->workspacePublishAccess($GLOBALS['BE_USER']->workspace) && $GLOBALS['BE_USER']->workspaceSwapAccess(); $this->initializeWorkspacesCachingFramework(); // check for dataArray in cache if ($this->getDataArrayFromCache($versions, $filterTxt) === FALSE) { /** @var $stagesObj \TYPO3\CMS\Workspaces\Service\StagesService */ $stagesObj = GeneralUtility::makeInstance('TYPO3\\CMS\\Workspaces\\Service\\StagesService'); $defaultGridColumns = array(self::GridColumn_Collection => 0, self::GridColumn_CollectionLevel => 0, self::GridColumn_CollectionParent => '', self::GridColumn_CollectionCurrent => '', self::GridColumn_CollectionChildren => 0); foreach ($versions as $table => $records) { $hiddenField = $this->getTcaEnableColumnsFieldName($table, 'disabled'); $isRecordTypeAllowedToModify = $GLOBALS['BE_USER']->check('tables_modify', $table); foreach ($records as $record) { $origRecord = BackendUtility::getRecord($table, $record['t3ver_oid']); $versionRecord = BackendUtility::getRecord($table, $record['uid']); $combinedRecord = \TYPO3\CMS\Workspaces\Domain\Model\CombinedRecord::createFromArrays($table, $origRecord, $versionRecord); $this->getIntegrityService()->checkElement($combinedRecord); if ($hiddenField !== NULL) { $recordState = $this->workspaceState($versionRecord['t3ver_state'], $origRecord[$hiddenField], $versionRecord[$hiddenField]); } else { $recordState = $this->workspaceState($versionRecord['t3ver_state']); } $isDeletedPage = $table == 'pages' && $recordState == 'deleted'; $viewUrl = \TYPO3\CMS\Workspaces\Service\WorkspaceService::viewSingleRecord($table, $record['uid'], $origRecord, $versionRecord); $versionArray = array(); $versionArray['table'] = $table; $versionArray['id'] = $table . ':' . $record['uid']; $versionArray['uid'] = $record['uid']; $versionArray['workspace'] = $versionRecord['t3ver_id']; $versionArray = array_merge($versionArray, $defaultGridColumns); $versionArray['label_Workspace'] = htmlspecialchars(BackendUtility::getRecordTitle($table, $versionRecord)); $versionArray['label_Live'] = htmlspecialchars(BackendUtility::getRecordTitle($table, $origRecord)); $versionArray['label_Stage'] = htmlspecialchars($stagesObj->getStageTitle($versionRecord['t3ver_stage'])); $tempStage = $stagesObj->getNextStage($versionRecord['t3ver_stage']); $versionArray['label_nextStage'] = htmlspecialchars($stagesObj->getStageTitle($tempStage['uid'])); $tempStage = $stagesObj->getPrevStage($versionRecord['t3ver_stage']); $versionArray['label_prevStage'] = htmlspecialchars($stagesObj->getStageTitle($tempStage['uid'])); $versionArray['path_Live'] = htmlspecialchars(BackendUtility::getRecordPath($record['livepid'], '', 999)); $versionArray['path_Workspace'] = htmlspecialchars(BackendUtility::getRecordPath($record['wspid'], '', 999)); $versionArray['workspace_Title'] = htmlspecialchars(\TYPO3\CMS\Workspaces\Service\WorkspaceService::getWorkspaceTitle($versionRecord['t3ver_wsid'])); $versionArray['workspace_Tstamp'] = $versionRecord['tstamp']; $versionArray['workspace_Formated_Tstamp'] = BackendUtility::datetime($versionRecord['tstamp']); $versionArray['t3ver_wsid'] = $versionRecord['t3ver_wsid']; $versionArray['t3ver_oid'] = $record['t3ver_oid']; $versionArray['livepid'] = $record['livepid']; $versionArray['stage'] = $versionRecord['t3ver_stage']; $versionArray['icon_Live'] = \TYPO3\CMS\Backend\Utility\IconUtility::mapRecordTypeToSpriteIconClass($table, $origRecord); $versionArray['icon_Workspace'] = \TYPO3\CMS\Backend\Utility\IconUtility::mapRecordTypeToSpriteIconClass($table, $versionRecord); $languageValue = $this->getLanguageValue($table, $versionRecord); $versionArray['languageValue'] = $languageValue; $versionArray['language'] = array('cls' => \TYPO3\CMS\Backend\Utility\IconUtility::getSpriteIconClasses($this->getSystemLanguageValue($languageValue, 'flagIcon')), 'title' => htmlspecialchars($this->getSystemLanguageValue($languageValue, 'title'))); $versionArray['allowedAction_nextStage'] = $isRecordTypeAllowedToModify && $stagesObj->isNextStageAllowedForUser($versionRecord['t3ver_stage']); $versionArray['allowedAction_prevStage'] = $isRecordTypeAllowedToModify && $stagesObj->isPrevStageAllowedForUser($versionRecord['t3ver_stage']); if ($swapAccess && $swapStage != 0 && $versionRecord['t3ver_stage'] == $swapStage) { $versionArray['allowedAction_swap'] = $isRecordTypeAllowedToModify && $stagesObj->isNextStageAllowedForUser($swapStage); } elseif ($swapAccess && $swapStage == 0) { $versionArray['allowedAction_swap'] = $isRecordTypeAllowedToModify; } else { $versionArray['allowedAction_swap'] = FALSE; } $versionArray['allowedAction_delete'] = $isRecordTypeAllowedToModify; // preview and editing of a deleted page won't work ;) $versionArray['allowedAction_view'] = !$isDeletedPage && $viewUrl; $versionArray['allowedAction_edit'] = $isRecordTypeAllowedToModify && !$isDeletedPage; $versionArray['allowedAction_editVersionedPage'] = $isRecordTypeAllowedToModify && !$isDeletedPage; $versionArray['state_Workspace'] = $recordState; $versionArray = array_merge($versionArray, $this->getAdditionalColumnService()->getData($combinedRecord)); if ($filterTxt == '' || $this->isFilterTextInVisibleColumns($filterTxt, $versionArray)) { $versionIdentifier = $versionArray['id']; $this->dataArray[$versionIdentifier] = $versionArray; } } } // Suggested slot method: // methodName(\TYPO3\CMS\Workspaces\Service\GridDataService $gridData, array &$dataArray, array $versions) $this->emitSignal(self::SIGNAL_GenerateDataArray_BeforeCaching, $this->dataArray, $versions); // Enrich elements after everything has been processed: foreach ($this->dataArray as &$element) { $identifier = $element['table'] . ':' . $element['t3ver_oid']; $element['integrity'] = array('status' => $this->getIntegrityService()->getStatusRepresentation($identifier), 'messages' => htmlspecialchars($this->getIntegrityService()->getIssueMessages($identifier, TRUE))); } $this->setDataArrayIntoCache($versions, $filterTxt); } // Suggested slot method: // methodName(\TYPO3\CMS\Workspaces\Service\GridDataService $gridData, array &$dataArray, array $versions) $this->emitSignal(self::SIGNAL_GenerateDataArray_PostProcesss, $this->dataArray, $versions); $this->sortDataArray(); $this->resolveDataArrayDependencies(); }
/** * Builds a complete node including childs * * @param \TYPO3\CMS\Backend\Tree\TreeNode $basicNode * @param NULL|\TYPO3\CMS\Core\Tree\TableConfiguration\DatabaseTreeNode $parent * @param int $level * @return \TYPO3\CMS\Core\Tree\TableConfiguration\DatabaseTreeNode Node object */ protected function buildRepresentationForNode(\TYPO3\CMS\Backend\Tree\TreeNode $basicNode, DatabaseTreeNode $parent = NULL, $level = 0) { /** @var $node \TYPO3\CMS\Core\Tree\TableConfiguration\DatabaseTreeNode */ $node = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Tree\TableConfiguration\DatabaseTreeNode::class); $row = array(); if ($basicNode->getId() == 0) { $node->setSelected(FALSE); $node->setExpanded(TRUE); $node->setLabel($GLOBALS['LANG']->sL($GLOBALS['TCA'][$this->tableName]['ctrl']['title'])); } else { $row = BackendUtility::getRecordWSOL($this->tableName, $basicNode->getId(), '*', '', FALSE); $node->setLabel(BackendUtility::getRecordTitle($this->tableName, $row) ?: $basicNode->getId()); $node->setSelected(GeneralUtility::inList($this->getSelectedList(), $basicNode->getId())); $node->setExpanded($this->isExpanded($basicNode)); } $node->setId($basicNode->getId()); $node->setSelectable(!GeneralUtility::inList($this->getNonSelectableLevelList(), $level) && !in_array($basicNode->getId(), $this->getItemUnselectableList())); $node->setSortValue($this->nodeSortValues[$basicNode->getId()]); $node->setIcon(\TYPO3\CMS\Backend\Utility\IconUtility::mapRecordTypeToSpriteIconClass($this->tableName, $row)); $node->setParentNode($parent); if ($basicNode->hasChildNodes()) { $node->setHasChildren(TRUE); /** @var $childNodes \TYPO3\CMS\Backend\Tree\SortedTreeNodeCollection */ $childNodes = GeneralUtility::makeInstance(\TYPO3\CMS\Backend\Tree\SortedTreeNodeCollection::class); foreach ($basicNode->getChildNodes() as $child) { $childNodes->append($this->buildRepresentationForNode($child, $node, $level + 1)); } $node->setChildNodes($childNodes); } return $node; }
/** * Returns the most important properties of the link validator task as a * comma separated string that will be displayed in the scheduler module. * * @return string */ public function getAdditionalInformation() { $additionalInformation = array(); $page = (int) $this->getPage(); $pageLabel = $page; if ($page !== 0) { $pageData = BackendUtility::getRecord('pages', $page); if (!empty($pageData)) { $pageTitle = BackendUtility::getRecordTitle('pages', $pageData); $pageLabel = $pageTitle . ' (' . $page . ')'; } } $lang = $this->getLanguageService(); $additionalInformation[] = $lang->sL('LLL:EXT:linkvalidator/Resources/Private/Language/locallang.xlf:tasks.validate.page') . ': ' . $pageLabel; $depth = (int) $this->getDepth(); $additionalInformation[] = $lang->sL('LLL:EXT:linkvalidator/Resources/Private/Language/locallang.xlf:tasks.validate.depth') . ': ' . $lang->sL('LLL:EXT:lang/locallang_core.xlf:labels.depth_' . ($depth === 999 ? 'infi' : $depth)); $additionalInformation[] = $lang->sL('LLL:EXT:linkvalidator/Resources/Private/Language/locallang.xlf:tasks.validate.email') . ': ' . $this->getEmail(); return implode(', ', $additionalInformation); }
/** * Make reference display (what this elements points to) * * @param string $table Table name * @param string $ref Filename or uid * @return string HTML */ protected function makeRefFrom($table, $ref) { $lang = $this->getLanguageService(); $rows = $this->getDatabaseConnection()->exec_SELECTgetRows('*', 'sys_refindex', 'tablename=' . $this->getDatabaseConnection()->fullQuoteStr($table, 'sys_refindex') . ' AND recuid=' . (int) $ref); // Compile information for title tag: $infoData = array(); $infoDataHeader = ''; if (!empty($rows)) { $infoDataHeader = ' <tr> <th class="col-icon"></th> <th class="col-title">' . $lang->sL('LLL:EXT:lang/locallang_core.xlf:show_item.php.title') . '</th> <th>' . $lang->sL('LLL:EXT:lang/locallang_core.xlf:show_item.php.table') . '</th> <th>' . $lang->sL('LLL:EXT:lang/locallang_core.xlf:show_item.php.uid') . '</th> <th>' . $lang->sL('LLL:EXT:lang/locallang_core.xlf:show_item.php.field') . '</th> <th>' . $lang->sL('LLL:EXT:lang/locallang_core.xlf:show_item.php.flexpointer') . '</th> <th>' . $lang->sL('LLL:EXT:lang/locallang_core.xlf:show_item.php.softrefKey') . '</th> <th>' . $lang->sL('LLL:EXT:lang/locallang_core.xlf:show_item.php.sorting') . '</th> <th>' . $lang->sL('LLL:EXT:lang/locallang_core.xlf:show_item.php.refString') . '</th> <th class="col-control"></th> </tr>'; } foreach ($rows as $row) { $record = BackendUtility::getRecord($row['ref_table'], $row['ref_uid']); if ($record) { $icon = $this->iconFactory->getIconForRecord($row['tablename'], $record, Icon::SIZE_SMALL)->render(); $actions = $this->getRecordActions($row['ref_table'], $row['ref_uid']); $urlParameters = ['edit' => [$row['ref_table'] => [$row['ref_uid'] => 'edit']], 'returnUrl' => GeneralUtility::getIndpEnv('REQUEST_URI')]; $url = BackendUtility::getModuleUrl('record_edit', $urlParameters); $infoData[] = ' <tr> <td class="col-icon"> <a href="' . htmlspecialchars($url) . '" title="id=' . $record['uid'] . '"> ' . $icon . ' </a> </td> <td class="col-title"> <a href="' . htmlspecialchars($url) . '" title="id=' . $record['uid'] . '" > ' . BackendUtility::getRecordTitle($row['ref_table'], $record, true) . ' </a> </td> <td>' . $lang->sL($GLOBALS['TCA'][$row['ref_table']]['ctrl']['title'], true) . '</td> <td>' . htmlspecialchars($row['ref_uid']) . '</td> <td>' . htmlspecialchars($this->getLabelForTableColumn($table, $row['field'])) . '</td> <td>' . htmlspecialchars($row['flexpointer']) . '</td> <td>' . htmlspecialchars($row['softref_key']) . '</td> <td>' . htmlspecialchars($row['sorting']) . '</td> <td>' . htmlspecialchars($row['ref_string']) . '</td> <td class="col-control">' . $actions . '</td> </tr>'; } else { $infoData[] = ' <tr> <td class="col-icon"></td> <td class="col-title">' . $lang->sL('LLL:EXT:lang/locallang_core.xlf:show_item.php.missing_record') . ' (uid=' . (int) $row['recuid'] . ')</td> <td>' . $lang->sL($GLOBALS['TCA'][$row['ref_table']]['ctrl']['title'], true) . '</td> <td></td> <td>' . htmlspecialchars($this->getLabelForTableColumn($table, $row['field'])) . '</td> <td>' . htmlspecialchars($row['flexpointer']) . '</td> <td>' . htmlspecialchars($row['softref_key']) . '</td> <td>' . htmlspecialchars($row['sorting']) . '</td> <td>' . htmlspecialchars($row['ref_string']) . '</td> <td class="col-control"></td> </tr>'; } } if (empty($infoData)) { return ''; } return ' <div class="table-fit"> <table class="table table-striped table-hover"> <thead>' . $infoDataHeader . '</thead> <tbody>' . implode('', $infoData) . '</tbody> </table> </div>'; }
/** * Adds the record $row from $table. * No checking for relations done here. Pure data. * * @param string $table Table name * @param array $row Record row. * @param int $relationLevel (Internal) if the record is added as a relation, this is set to the "level" it was on. * @return void */ public function export_addRecord($table, $row, $relationLevel = 0) { BackendUtility::workspaceOL($table, $row); if ((string) $table !== '' && is_array($row) && $row['uid'] > 0 && !$this->excludeMap[$table . ':' . $row['uid']]) { if ($this->checkPID($table === 'pages' ? $row['uid'] : $row['pid'])) { if (!isset($this->dat['records'][$table . ':' . $row['uid']])) { // Prepare header info: $row = $this->filterRecordFields($table, $row); $headerInfo = array(); $headerInfo['uid'] = $row['uid']; $headerInfo['pid'] = $row['pid']; $headerInfo['title'] = GeneralUtility::fixed_lgd_cs(BackendUtility::getRecordTitle($table, $row), 40); $headerInfo['size'] = strlen(serialize($row)); if ($relationLevel) { $headerInfo['relationLevel'] = $relationLevel; } // If record content is not too large in size, set the header content and add the rest: if ($headerInfo['size'] < $this->maxRecordSize) { // Set the header summary: $this->dat['header']['records'][$table][$row['uid']] = $headerInfo; // Create entry in the PID lookup: $this->dat['header']['pid_lookup'][$row['pid']][$table][$row['uid']] = 1; // Initialize reference index object: $refIndexObj = GeneralUtility::makeInstance(ReferenceIndex::class); // Yes to workspace overlays for exporting.... $refIndexObj->WSOL = true; $relations = $refIndexObj->getRelations($table, $row); $relations = $this->fixFileIDsInRelations($relations); $relations = $this->removeSoftrefsHavingTheSameDatabaseRelation($relations); // Data: $this->dat['records'][$table . ':' . $row['uid']] = array(); $this->dat['records'][$table . ':' . $row['uid']]['data'] = $row; $this->dat['records'][$table . ':' . $row['uid']]['rels'] = $relations; // Add information about the relations in the record in the header: $this->dat['header']['records'][$table][$row['uid']]['rels'] = $this->flatDBrels($this->dat['records'][$table . ':' . $row['uid']]['rels']); // Add information about the softrefs to header: $this->dat['header']['records'][$table][$row['uid']]['softrefs'] = $this->flatSoftRefs($this->dat['records'][$table . ':' . $row['uid']]['rels']); } else { $this->error('Record ' . $table . ':' . $row['uid'] . ' was larger than maxRecordSize (' . GeneralUtility::formatSize($this->maxRecordSize) . ')'); } } else { $this->error('Record ' . $table . ':' . $row['uid'] . ' already added.'); } } else { $this->error('Record ' . $table . ':' . $row['uid'] . ' was outside your DB mounts!'); } } }
/** * Creating the module output. * * @return void */ public function main() { $lang = $this->getLanguageService(); if ($this->page_id) { $backendUser = $this->getBackendUser(); $this->moduleTemplate->getPageRenderer()->loadRequireJsModule('TYPO3/CMS/Backend/Tooltip'); // Get record for element: $elRow = BackendUtility::getRecordWSOL($this->table, $this->moveUid); // Headerline: Icon, record title: $headerLine = '<span ' . BackendUtility::getRecordToolTip($elRow, $this->table) . '>' . $this->moduleTemplate->getIconFactory()->getIconForRecord($this->table, $elRow, Icon::SIZE_SMALL)->render() . '</span>'; $headerLine .= BackendUtility::getRecordTitle($this->table, $elRow, true); // Make-copy checkbox (clicking this will reload the page with the GET var makeCopy set differently): $onClick = 'window.location.href=' . GeneralUtility::quoteJSvalue(GeneralUtility::linkThisScript(array('makeCopy' => !$this->makeCopy))) . ';'; $headerLine .= '<div><input type="hidden" name="makeCopy" value="0" />' . '<input type="checkbox" name="makeCopy" id="makeCopy" value="1"' . ($this->makeCopy ? ' checked="checked"' : '') . ' onclick="' . htmlspecialchars($onClick) . '" /> <label for="makeCopy" class="t3-label-valign-top">' . $lang->getLL('makeCopy', 1) . '</label></div>'; // Add the header-content to the module content: $this->content .= '<div>' . $headerLine . '</div>'; // Reset variable to pick up the module content in: $code = ''; // IF the table is "pages": if ((string) $this->table == 'pages') { // Get page record (if accessible): $pageInfo = BackendUtility::readPageAccess($this->page_id, $this->perms_clause); if (is_array($pageInfo) && $backendUser->isInWebMount($pageInfo['pid'], $this->perms_clause)) { // Initialize the position map: $posMap = GeneralUtility::makeInstance(PageMovingPagePositionMap::class); $posMap->moveOrCopy = $this->makeCopy ? 'copy' : 'move'; // Print a "go-up" link IF there is a real parent page (and if the user has read-access to that page). if ($pageInfo['pid']) { $pidPageInfo = BackendUtility::readPageAccess($pageInfo['pid'], $this->perms_clause); if (is_array($pidPageInfo)) { if ($backendUser->isInWebMount($pidPageInfo['pid'], $this->perms_clause)) { $code .= '<a href="' . htmlspecialchars(GeneralUtility::linkThisScript(array('uid' => (int) $pageInfo['pid'], 'moveUid' => $this->moveUid))) . '">' . $this->moduleTemplate->getIconFactory()->getIcon('actions-view-go-up', Icon::SIZE_SMALL)->render() . BackendUtility::getRecordTitle('pages', $pidPageInfo, true) . '</a><br />'; } else { $code .= $this->moduleTemplate->getIconFactory()->getIconForRecord('pages', $pidPageInfo, Icon::SIZE_SMALL)->render() . BackendUtility::getRecordTitle('pages', $pidPageInfo, true) . '<br />'; } } } // Create the position tree: $code .= $posMap->positionTree($this->page_id, $pageInfo, $this->perms_clause, $this->R_URI); } } // IF the table is "tt_content": if ((string) $this->table == 'tt_content') { // First, get the record: $tt_content_rec = BackendUtility::getRecord('tt_content', $this->moveUid); // ? if (!$this->input_moveUid) { $this->page_id = $tt_content_rec['pid']; } // Checking if the parent page is readable: $pageInfo = BackendUtility::readPageAccess($this->page_id, $this->perms_clause); if (is_array($pageInfo) && $backendUser->isInWebMount($pageInfo['pid'], $this->perms_clause)) { // Initialize the position map: $posMap = GeneralUtility::makeInstance(ContentMovingPagePositionMap::class); $posMap->moveOrCopy = $this->makeCopy ? 'copy' : 'move'; $posMap->cur_sys_language = $this->sys_language; // Headerline for the parent page: Icon, record title: $headerLine = '<span ' . BackendUtility::getRecordToolTip($pageInfo, 'pages') . '>' . $this->moduleTemplate->getIconFactory()->getIconForRecord('pages', $pageInfo, Icon::SIZE_SMALL)->render() . '</span>'; $headerLine .= BackendUtility::getRecordTitle('pages', $pageInfo, true); // Load SHARED page-TSconfig settings and retrieve column list from there, if applicable: // SHARED page-TSconfig settings. // $modTSconfig_SHARED = BackendUtility::getModTSconfig($this->pageId, 'mod.SHARED'); $colPosArray = GeneralUtility::callUserFunction(\TYPO3\CMS\Backend\View\BackendLayoutView::class . '->getColPosListItemsParsed', $this->page_id, $this); $colPosIds = array(); foreach ($colPosArray as $colPos) { $colPosIds[] = $colPos[1]; } // Removing duplicates, if any $colPosList = implode(',', array_unique($colPosIds)); // Adding parent page-header and the content element columns from position-map: $code = $headerLine . '<br />'; $code .= $posMap->printContentElementColumns($this->page_id, $this->moveUid, $colPosList, 1, $this->R_URI); // Print a "go-up" link IF there is a real parent page (and if the user has read-access to that page). $code .= '<br /><br />'; if ($pageInfo['pid']) { $pidPageInfo = BackendUtility::readPageAccess($pageInfo['pid'], $this->perms_clause); if (is_array($pidPageInfo)) { if ($backendUser->isInWebMount($pidPageInfo['pid'], $this->perms_clause)) { $code .= '<a href="' . htmlspecialchars(GeneralUtility::linkThisScript(array('uid' => (int) $pageInfo['pid'], 'moveUid' => $this->moveUid))) . '">' . $this->moduleTemplate->getIconFactory()->getIcon('actions-view-go-up', Icon::SIZE_SMALL)->render() . BackendUtility::getRecordTitle('pages', $pidPageInfo, true) . '</a><br />'; } else { $code .= $this->moduleTemplate->getIconFactory()->getIconForRecord('pages', $pidPageInfo, Icon::SIZE_SMALL)->render() . BackendUtility::getRecordTitle('pages', $pidPageInfo, true) . '<br />'; } } } // Create the position tree (for pages): $code .= $posMap->positionTree($this->page_id, $pageInfo, $this->perms_clause, $this->R_URI); } } // Add the $code content as a new section to the module: $this->content .= '<h2>' . $lang->getLL('selectPositionOfElement') . '</h2>'; $this->content .= '<div>' . $code . '</div>'; } // Setting up the buttons and markers for docheader $this->getButtons(); // Build the <body> for the module $this->moduleTemplate->setTitle($lang->getLL('movingElement')); }
/** * Recursively look for children for page version with $pid * * @param int $pid UID of page record for which to look up sub-elements following that version * @param int $c Counter, do not set (limits to 100 levels) * @return string Table with content if any */ public function pageSubContent($pid, $c = 0) { $tableNames = ArrayUtility::removeArrayEntryByValue(array_keys($GLOBALS['TCA']), 'pages'); $tableNames[] = 'pages'; $content = ''; foreach ($tableNames as $table) { // Basically list ALL tables - not only those being copied might be found! $mres = $GLOBALS['TYPO3_DB']->exec_SELECTquery('*', $table, 'pid=' . (int) $pid . BackendUtility::deleteClause($table), '', $GLOBALS['TCA'][$table]['ctrl']['sortby'] ? $GLOBALS['TCA'][$table]['ctrl']['sortby'] : ''); if ($GLOBALS['TYPO3_DB']->sql_num_rows($mres)) { $content .= ' <table class="table"> <tr> <th class="col-icon">' . $this->moduleTemplate->getIconFactory()->getIconForRecord($table, array(), Icon::SIZE_SMALL)->render() . '</th> <th class="col-title">' . $GLOBALS['LANG']->sL($GLOBALS['TCA'][$table]['ctrl']['title'], true) . '</th> <th></th> <th></th> </tr>'; while ($subrow = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($mres)) { $ownVer = $this->lookForOwnVersions($table, $subrow['uid']); $content .= ' <tr> <td class="col-icon">' . $this->moduleTemplate->getIconFactory()->getIconForRecord($table, $subrow, Icon::SIZE_SMALL)->render() . '</td> <td class="col-title">' . htmlspecialchars(BackendUtility::getRecordTitle($table, $subrow, true)) . '</td> <td>' . ($ownVer > 1 ? '<a href="' . htmlspecialchars(BackendUtility::getModuleUrl('web_txversionM1', array('table' => $table, 'uid' => $subrow['uid']))) . '">' . ($ownVer - 1) . '</a>' : '') . '</td> <td class="col-control">' . $this->adminLinks($table, $subrow) . '</td> </tr>'; if ($table == 'pages' && $c < 100) { $sub = $this->pageSubContent($subrow['uid'], $c + 1); if ($sub) { $content .= ' <tr> <td></td> <td></td> <td></td> <td width="98%">' . $sub . '</td> </tr>'; } } } $content .= '</table>'; } $GLOBALS['TYPO3_DB']->sql_free_result($mres); } return $content; }
/** * Draws the preview content for a content element * * @param array $row Content element * @return string HTML * @throws \UnexpectedValueException */ public function tt_content_drawItem($row) { $out = ''; $outHeader = ''; // Make header: if ($row['header']) { $infoArr = array(); $this->getProcessedValue('tt_content', 'header_position,header_layout,header_link', $row, $infoArr); $hiddenHeaderNote = ''; // If header layout is set to 'hidden', display an accordant note: if ($row['header_layout'] == 100) { $hiddenHeaderNote = ' <em>[' . $this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:labels.hidden', true) . ']</em>'; } $outHeader = $row['date'] ? htmlspecialchars($this->itemLabels['date'] . ' ' . BackendUtility::date($row['date'])) . '<br />' : ''; $outHeader .= '<strong>' . $this->linkEditContent($this->renderText($row['header']), $row) . $hiddenHeaderNote . '</strong><br />'; } // Make content: $infoArr = array(); $drawItem = true; // Hook: Render an own preview of a record $drawItemHooks =& $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['cms/layout/class.tx_cms_layout.php']['tt_content_drawItem']; if (is_array($drawItemHooks)) { foreach ($drawItemHooks as $hookClass) { $hookObject = GeneralUtility::getUserObj($hookClass); if (!$hookObject instanceof PageLayoutViewDrawItemHookInterface) { throw new \UnexpectedValueException('$hookObject must implement interface ' . \TYPO3\CMS\Backend\View\PageLayoutViewDrawItemHookInterface::class, 1218547409); } $hookObject->preProcess($this, $drawItem, $outHeader, $out, $row); } } // If the previous hook did not render something, // then check if a Fluid-based preview template was defined for this CType // and render it via Fluid. Possible option: // mod.web_layout.tt_content.preview.media = EXT:site_mysite/Resources/Private/Templates/Preview/Media.html if ($drawItem) { $tsConfig = BackendUtility::getModTSconfig($row['pid'], 'mod.web_layout.tt_content.preview'); if (!empty($tsConfig['properties'][$row['CType']])) { $fluidTemplateFile = $tsConfig['properties'][$row['CType']]; $fluidTemplateFile = GeneralUtility::getFileAbsFileName($fluidTemplateFile); if ($fluidTemplateFile) { try { /** @var StandaloneView $view */ $view = GeneralUtility::makeInstance(StandaloneView::class); $view->setTemplatePathAndFilename($fluidTemplateFile); $view->assignMultiple($row); if (!empty($row['pi_flexform'])) { /** @var FlexFormService $flexFormService */ $flexFormService = GeneralUtility::makeInstance(FlexFormService::class); $view->assign('pi_flexform_transformed', $flexFormService->convertFlexFormContentToArray($row['pi_flexform'])); } $out = $view->render(); $drawItem = false; } catch (\Exception $e) { // Catch any exception to avoid breaking the view } } } } // Draw preview of the item depending on its CType (if not disabled by previous hook): if ($drawItem) { switch ($row['CType']) { case 'header': if ($row['subheader']) { $out .= $this->linkEditContent($this->renderText($row['subheader']), $row) . '<br />'; } break; case 'bullets': case 'table': if ($row['bodytext']) { $out .= $this->linkEditContent($this->renderText($row['bodytext']), $row) . '<br />'; } break; case 'uploads': if ($row['media']) { $out .= $this->linkEditContent($this->getThumbCodeUnlinked($row, 'tt_content', 'media'), $row) . '<br />'; } break; case 'menu': $contentType = $this->CType_labels[$row['CType']]; $out .= $this->linkEditContent('<strong>' . htmlspecialchars($contentType) . '</strong>', $row) . '<br />'; // Add Menu Type $menuTypeLabel = $this->getLanguageService()->sL(BackendUtility::getLabelFromItemListMerged($row['pid'], 'tt_content', 'menu_type', $row['menu_type'])); $menuTypeLabel = $menuTypeLabel ?: 'invalid menu type'; $out .= $this->linkEditContent($menuTypeLabel, $row); if ($row['menu_type'] !== '2' && ($row['pages'] || $row['selected_categories'])) { // Show pages if menu type is not "Sitemap" $out .= ':' . $this->linkEditContent($this->generateListForCTypeMenu($row), $row) . '<br />'; } break; case 'shortcut': if (!empty($row['records'])) { $shortcutContent = array(); $recordList = explode(',', $row['records']); foreach ($recordList as $recordIdentifier) { $split = BackendUtility::splitTable_Uid($recordIdentifier); $tableName = empty($split[0]) ? 'tt_content' : $split[0]; $shortcutRecord = BackendUtility::getRecord($tableName, $split[1]); if (is_array($shortcutRecord)) { $icon = $this->iconFactory->getIconForRecord($tableName, $shortcutRecord, Icon::SIZE_SMALL)->render(); $icon = BackendUtility::wrapClickMenuOnIcon($icon, $tableName, $shortcutRecord['uid'], 1, '', '+copy,info,edit,view'); $shortcutContent[] = $icon . htmlspecialchars(BackendUtility::getRecordTitle($tableName, $shortcutRecord)); } } $out .= implode('<br />', $shortcutContent) . '<br />'; } break; case 'list': $hookArr = array(); $hookOut = ''; if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['cms/layout/class.tx_cms_layout.php']['list_type_Info'][$row['list_type']])) { $hookArr = $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['cms/layout/class.tx_cms_layout.php']['list_type_Info'][$row['list_type']]; } elseif (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['cms/layout/class.tx_cms_layout.php']['list_type_Info']['_DEFAULT'])) { $hookArr = $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['cms/layout/class.tx_cms_layout.php']['list_type_Info']['_DEFAULT']; } if (!empty($hookArr)) { $_params = array('pObj' => &$this, 'row' => $row, 'infoArr' => $infoArr); foreach ($hookArr as $_funcRef) { $hookOut .= GeneralUtility::callUserFunction($_funcRef, $_params, $this); } } if ((string) $hookOut !== '') { $out .= $hookOut; } elseif (!empty($row['list_type'])) { $label = BackendUtility::getLabelFromItemListMerged($row['pid'], 'tt_content', 'list_type', $row['list_type']); if (!empty($label)) { $out .= $this->linkEditContent('<strong>' . $this->getLanguageService()->sL($label, true) . '</strong>', $row) . '<br />'; } else { $message = sprintf($this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:labels.noMatchingValue'), $row['list_type']); $out .= GeneralUtility::makeInstance(FlashMessage::class, htmlspecialchars($message), '', FlashMessage::WARNING)->render(); } } elseif (!empty($row['select_key'])) { $out .= $this->getLanguageService()->sL(BackendUtility::getItemLabel('tt_content', 'select_key'), true) . ' ' . $row['select_key'] . '<br />'; } else { $out .= '<strong>' . $this->getLanguageService()->getLL('noPluginSelected') . '</strong>'; } $out .= $this->getLanguageService()->sL(BackendUtility::getLabelFromItemlist('tt_content', 'pages', $row['pages']), true) . '<br />'; break; default: $contentType = $this->CType_labels[$row['CType']]; if (isset($contentType)) { $out .= $this->linkEditContent('<strong>' . htmlspecialchars($contentType) . '</strong>', $row) . '<br />'; if ($row['bodytext']) { $out .= $this->linkEditContent($this->renderText($row['bodytext']), $row) . '<br />'; } if ($row['image']) { $out .= $this->linkEditContent($this->getThumbCodeUnlinked($row, 'tt_content', 'image'), $row) . '<br />'; } } else { $message = sprintf($this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:labels.noMatchingValue'), $row['CType']); $out .= GeneralUtility::makeInstance(FlashMessage::class, htmlspecialchars($message), '', FlashMessage::WARNING)->render(); } } } // Wrap span-tags: $out = ' <span class="exampleContent">' . $out . '</span>'; // Add header: $out = $outHeader . $out; // Return values: if ($this->isDisabled('tt_content', $row)) { return '<span class="text-muted">' . $out . '</span>'; } else { return $out; } }
/** * Prepare items from itemArray to be transferred to the TCEforms interface (as a comma list) * * @return string */ public function readyForInterface() { if (!is_array($this->itemArray)) { return false; } $output = array(); $titleLen = (int) $GLOBALS['BE_USER']->uc['titleLen']; foreach ($this->itemArray as $val) { $theRow = $this->results[$val['table']][$val['id']]; if ($theRow && is_array($GLOBALS['TCA'][$val['table']])) { $label = GeneralUtility::fixed_lgd_cs(strip_tags(BackendUtility::getRecordTitle($val['table'], $theRow)), $titleLen); $label = $label ? $label : '[...]'; $output[] = str_replace(',', '', $val['table'] . '_' . $val['id'] . '|' . rawurlencode($label)); } } return implode(',', $output); }
/** * TCA config "foreign_table" evaluation. Add them to $items * * Used by TcaSelectItems and TcaSelectTreeItems data providers * * @param array $result Result array * @param string $fieldName Current handle field name * @param array $items Incoming items * @return array Modified item array */ protected function addItemsFromForeignTable(array $result, $fieldName, array $items) { // Guard if (empty($result['processedTca']['columns'][$fieldName]['config']['foreign_table']) || !is_string($result['processedTca']['columns'][$fieldName]['config']['foreign_table'])) { return $items; } $languageService = $this->getLanguageService(); $database = $this->getDatabaseConnection(); $foreignTable = $result['processedTca']['columns'][$fieldName]['config']['foreign_table']; $foreignTableQueryArray = $this->buildForeignTableQuery($result, $fieldName); $queryResource = $database->exec_SELECT_queryArray($foreignTableQueryArray); // Early return on error with flash message $databaseError = $database->sql_error(); if (!empty($databaseError)) { $msg = htmlspecialchars($databaseError) . '<br />' . LF; $msg .= $languageService->sL('LLL:EXT:lang/locallang_core.xlf:error.database_schema_mismatch'); $msgTitle = $languageService->sL('LLL:EXT:lang/locallang_core.xlf:error.database_schema_mismatch_title'); /** @var $flashMessage FlashMessage */ $flashMessage = GeneralUtility::makeInstance(FlashMessage::class, $msg, $msgTitle, FlashMessage::ERROR, true); /** @var $flashMessageService FlashMessageService */ $flashMessageService = GeneralUtility::makeInstance(FlashMessageService::class); /** @var $defaultFlashMessageQueue FlashMessageQueue */ $defaultFlashMessageQueue = $flashMessageService->getMessageQueueByIdentifier(); $defaultFlashMessageQueue->enqueue($flashMessage); $database->sql_free_result($queryResource); return $items; } $labelPrefix = ''; if (!empty($result['processedTca']['columns'][$fieldName]['config']['foreign_table_prefix'])) { $labelPrefix = $result['processedTca']['columns'][$fieldName]['config']['foreign_table_prefix']; $labelPrefix = $languageService->sL($labelPrefix); } $iconFieldName = ''; if (!empty($result['processedTca']['ctrl']['selicon_field'])) { $iconFieldName = $result['processedTca']['ctrl']['selicon_field']; } $iconPath = ''; if (!empty($result['processedTca']['ctrl']['selicon_field_path'])) { $iconPath = $result['processedTca']['ctrl']['selicon_field_path']; } $iconFactory = GeneralUtility::makeInstance(IconFactory::class); while ($foreignRow = $database->sql_fetch_assoc($queryResource)) { BackendUtility::workspaceOL($foreignTable, $foreignRow); if (is_array($foreignRow)) { // Prepare the icon if available: if ($iconFieldName && $iconPath && $foreignRow[$iconFieldName]) { $iParts = GeneralUtility::trimExplode(',', $foreignRow[$iconFieldName], true); $icon = '../' . $iconPath . '/' . trim($iParts[0]); } else { $icon = $iconFactory->mapRecordTypeToIconIdentifier($foreignTable, $foreignRow); } // Add the item $items[] = [$labelPrefix . htmlspecialchars(BackendUtility::getRecordTitle($foreignTable, $foreignRow)), $foreignRow['uid'], $icon]; } } $database->sql_free_result($queryResource); return $items; }
/** * Renders the HTML header for a foreign record, such as the title, toggle-function, drag'n'drop, etc. * Later on the command-icons are inserted here. * * @param string $parentUid The uid of the parent (embedding) record (uid or NEW...) * @param string $foreign_table The foreign_table we create a header for * @param array $rec The current record of that foreign_table * @param array $config content of $PA['fieldConf']['config'] * @param boolean $isVirtualRecord * @return string The HTML code of the header * @todo Define visibility */ public function renderForeignRecordHeader($parentUid, $foreign_table, $rec, $config, $isVirtualRecord = FALSE) { // Init: $objectId = $this->inlineNames['object'] . self::Structure_Separator . $foreign_table . self::Structure_Separator . $rec['uid']; // We need the returnUrl of the main script when loading the fields via AJAX-call (to correct wizard code, so include it as 3rd parameter) // Pre-Processing: $isOnSymmetricSide = RelationHandler::isOnSymmetricSide($parentUid, $config, $rec); $hasForeignLabel = !$isOnSymmetricSide && $config['foreign_label'] ? TRUE : FALSE; $hasSymmetricLabel = $isOnSymmetricSide && $config['symmetric_label'] ? TRUE : FALSE; // Get the record title/label for a record: // Try using a self-defined user function only for formatted labels if (isset($GLOBALS['TCA'][$foreign_table]['ctrl']['formattedLabel_userFunc'])) { $params = array('table' => $foreign_table, 'row' => $rec, 'title' => '', 'isOnSymmetricSide' => $isOnSymmetricSide, 'options' => isset($GLOBALS['TCA'][$foreign_table]['ctrl']['formattedLabel_userFunc_options']) ? $GLOBALS['TCA'][$foreign_table]['ctrl']['formattedLabel_userFunc_options'] : array(), 'parent' => array('uid' => $parentUid, 'config' => $config)); // callUserFunction requires a third parameter, but we don't want to give $this as reference! $null = NULL; GeneralUtility::callUserFunction($GLOBALS['TCA'][$foreign_table]['ctrl']['formattedLabel_userFunc'], $params, $null); $recTitle = $params['title']; // Try using a normal self-defined user function } elseif (isset($GLOBALS['TCA'][$foreign_table]['ctrl']['label_userFunc'])) { $params = array('table' => $foreign_table, 'row' => $rec, 'title' => '', 'isOnSymmetricSide' => $isOnSymmetricSide, 'parent' => array('uid' => $parentUid, 'config' => $config)); // callUserFunction requires a third parameter, but we don't want to give $this as reference! $null = NULL; GeneralUtility::callUserFunction($GLOBALS['TCA'][$foreign_table]['ctrl']['label_userFunc'], $params, $null); $recTitle = $params['title']; } elseif ($hasForeignLabel || $hasSymmetricLabel) { $titleCol = $hasForeignLabel ? $config['foreign_label'] : $config['symmetric_label']; $foreignConfig = $this->getPossibleRecordsSelectorConfig($config, $titleCol); // Render title for everything else than group/db: if ($foreignConfig['type'] != 'groupdb') { $recTitle = BackendUtility::getProcessedValueExtra($foreign_table, $titleCol, $rec[$titleCol], 0, 0, FALSE); } else { // $recTitle could be something like: "tx_table_123|...", $valueParts = GeneralUtility::trimExplode('|', $rec[$titleCol]); $itemParts = GeneralUtility::revExplode('_', $valueParts[0], 2); $recTemp = BackendUtility::getRecordWSOL($itemParts[0], $itemParts[1]); $recTitle = BackendUtility::getRecordTitle($itemParts[0], $recTemp, FALSE); } $recTitle = BackendUtility::getRecordTitlePrep($recTitle); if (trim($recTitle) === '') { $recTitle = BackendUtility::getNoRecordTitle(TRUE); } } else { $recTitle = BackendUtility::getRecordTitle($foreign_table, $rec, TRUE); } $altText = BackendUtility::getRecordIconAltText($rec, $foreign_table); $iconImg = IconUtility::getSpriteIconForRecord($foreign_table, $rec, array('title' => htmlspecialchars($altText), 'id' => $objectId . '_icon')); $label = '<span id="' . $objectId . '_label">' . $recTitle . '</span>'; $ctrl = $this->renderForeignRecordHeaderControl($parentUid, $foreign_table, $rec, $config, $isVirtualRecord); $thumbnail = FALSE; // Renders a thumbnail for the header if (!empty($config['appearance']['headerThumbnail']['field'])) { $fieldValue = $rec[$config['appearance']['headerThumbnail']['field']]; $firstElement = array_shift(GeneralUtility::trimExplode(',', $fieldValue)); $fileUid = array_pop(BackendUtility::splitTable_Uid($firstElement)); if (!empty($fileUid)) { $fileObject = \TYPO3\CMS\Core\Resource\ResourceFactory::getInstance()->getFileObject($fileUid); if ($fileObject && $fileObject->isMissing()) { $flashMessage = \TYPO3\CMS\Core\Resource\Utility\BackendUtility::getFlashMessageForMissingFile($fileObject); $thumbnail = $flashMessage->render(); } elseif ($fileObject) { $imageSetup = $config['appearance']['headerThumbnail']; unset($imageSetup['field']); $imageSetup = array_merge(array('width' => '45', 'height' => '45c'), $imageSetup); $processedImage = $fileObject->process(\TYPO3\CMS\Core\Resource\ProcessedFile::CONTEXT_IMAGECROPSCALEMASK, $imageSetup); // Only use a thumbnail if the processing was successful. if (!$processedImage->usesOriginalFile()) { $imageUrl = $processedImage->getPublicUrl(TRUE); $thumbnail = '<img class="t3-form-field-header-inline-thumbnail-image" src="' . $imageUrl . '" alt="' . htmlspecialchars($altText) . '" title="' . htmlspecialchars($altText) . '">'; } } } } if (!empty($config['appearance']['headerThumbnail']['field']) && $thumbnail) { $headerClasses = ' t3-form-field-header-inline-has-thumbnail'; $mediaContainer = '<div class="t3-form-field-header-inline-thumbnail" id="' . $objectId . '_thumbnailcontainer">' . $thumbnail . '</div>'; } else { $headerClasses = ' t3-form-field-header-inline-has-icon'; $mediaContainer = '<div class="t3-form-field-header-inline-icon" id="' . $objectId . '_iconcontainer">' . $iconImg . '</div>'; } $header = '<div class="t3-form-field-header-inline-wrap' . $headerClasses . '">' . '<div class="t3-form-field-header-inline-ctrl">' . $ctrl . '</div>' . '<div class="t3-form-field-header-inline-body">' . $mediaContainer . '<div class="t3-form-field-header-inline-summary">' . $label . '</div>' . '</div>' . '</div>'; return $header; }
function main(&$backRef, $menuItems, $tableID, $srcId) { $this->backRef = $backRef; $this->beUser = $GLOBALS['BE_USER']; $this->LANG = $GLOBALS['LANG']; $this->includeLocalLang(); if (($tableID == 'dragDrop_tt_news_cat' || $tableID == 'tt_news_cat_CM') && $srcId) { $table = 'tt_news_cat'; $rec = BackendUtility::getRecordWSOL($table, $srcId); // fetch page record to get editing permissions $lCP = $this->beUser->calcPerms(BackendUtility::getRecord('pages', $rec['pid'])); $doEdit = $lCP & 16; // if ($doEdit && $tableID == 'dragDrop_tt_news_cat') { // $dstId = intval(GeneralUtility::_GP('dstId')); // $menuItems['moveinto'] = $this->dragDrop_moveCategory($srcId,$dstId); // $menuItems['copyinto'] = $this->dragDrop_copyCategory($srcId,$dstId); // } if ($tableID == 'tt_news_cat_CM') { $menuItems = array(); if ($doEdit) { $menuItems['edit'] = $this->DB_edit($table, $srcId); $menuItems['new'] = $this->DB_new($table, $rec); $menuItems['newsub'] = $this->DB_new($table, $rec, true); } $menuItems['info'] = $this->backRef->DB_info($table, $srcId); if ($doEdit) { $menuItems['hide'] = $this->DB_hideUnhide($table, $rec, 'hidden'); $elInfo = array(GeneralUtility::fixed_lgd_cs(BackendUtility::getRecordTitle('tt_news_cat', $rec), $this->beUser->uc['titleLen'])); $menuItems['spacer2'] = 'spacer'; $menuItems['delete'] = $this->DB_delete($table, $srcId, $elInfo); } } } return $menuItems; }