*/ /** * Child class for the Web > Page module * * @author Kasper Skårhøj * @package TYPO3 * @subpackage core */ class tx_cms_layout extends recordList { // External, static: For page statistics: var $stat_select_field = 'page_id'; // fieldname from sys_stat to select on. var $stat_codes = array(); // eg. "HITS_days:-1" // External, static: Flags of various kinds: var $pI_showUser = 0; // If TRUE, users/groups are shown in the page info box. var $pI_showStat = 1; // If TRUE, hit statistics are shown in the page info box. var $nextThree = 3; // The number of successive records to edit when showing content elements. var $pages_noEditColumns = 0; // If TRUE, disables the edit-column icon for tt_content elements var $option_showBigButtons = 1; // If TRUE, shows big buttons for editing page properties, moving, creating elements etc. in the columns view. var $option_newWizard = 1; // If TRUE, new-wizards are linked to rather than the regular new-element list. var $ext_function = 0; // If set to "1", will link a big button to content element wizard. var $doEdit = 1; // If TRUE, elements will have edit icons (probably this is whethere the user has permission to edit the page content). Set externally. var $agePrefixes = ' min| hrs| days| yrs| min| hour| day| year'; // Age prefixes for displaying times. May be set externally to localized values. var $externalTables = array(); // Array of tables to be listed by the Web > Page module in addition to the default tables. var $descrTable; // "Pseudo" Description -table name var $defLangBinding = FALSE; // If set TRUE, the language mode of tt_content elements will be rendered with hard binding between default language content elements and their translations! // External, static: Configuration of tt_content element display: var $tt_contentConfig = Array( 'showInfo' => 1, // Boolean: Display info-marks or not 'showCommands' => 1, // Boolean: Display up/down arrows and edit icons for tt_content records 'single' => 1, // Boolean: If set, the content of column(s) $this->tt_contentConfig['showSingleCol'] is shown in the total width of the page 'showAsGrid' => 0, // Boolean: If set, the content of columns is shown in grid 'showSingleCol' => 0, // The column(s) to show if single mode (under each other) 'languageCols' => 0, 'languageMode' => 0, 'languageColsPointer' => 0, 'showHidden' => 1, // Displays hidden records as well 'sys_language_uid' => 0, // Which language 'cols' => '1,0,2,3' // The order of the rows: Default is left(1), Normal(0), right(2), margin(3) ); // Internal, dynamic: var $allowedTableNames = array(); // Will contain a list of tables which can be listed by the user. var $activeTables = array(); // Contains icon/title of pages which are listed in the tables menu (see getTableMenu() function ) var $tt_contentData = Array( 'nextThree' => Array(), 'prev' => Array(), 'next' => Array() ); var $CType_labels = array(); // Used to store labels for CTypes for tt_content elements var $itemLabels = array(); // Used to store labels for the various fields in tt_content elements /***************************************** * * Renderings * *****************************************/ /** * Adds the code of a single table * * @param string Table name * @param integer Current page id * @return string HTML for listing. */ function getTable($table, $id) { // Load full table definition: t3lib_div::loadTCA($table); if (isset($this->externalTables[$table])) { return $this->getExternalTables($id, $table); } else { // Branch out based on table name: switch ($table) { case 'pages': return $this->getTable_pages($id); break; case 'tt_content': return $this->getTable_tt_content($id); break; } } } /** * Renders an external table from page id * * @param integer Page id * @param string name of the table * @return string HTML for the listing */ function getExternalTables($id, $table) { $type = $GLOBALS['SOBE']->MOD_SETTINGS[$table]; if (!isset($type)) { $type = 0; } $fList = $this->externalTables[$table][$type]['fList']; // eg. "name;title;email;company,image" // The columns are separeted by comma ','. // Values separated by semicolon ';' are shown in the same column. $icon = $this->externalTables[$table][$type]['icon']; $addWhere = $this->externalTables[$table][$type]['addWhere']; // Create listing $out = $this->makeOrdinaryList($table, $id, $fList, $icon, $addWhere); return $out; } /** * Renders records from the pages table from page id * (Used to get information about the page tree content by "Web>Info"!) * * @param integer Page id * @return string HTML for the listing */ function getTable_pages($id) { // Initializing: $out = ''; $delClause = t3lib_BEfunc::deleteClause('pages') . ' AND ' . $GLOBALS['BE_USER']->getPagePermsClause(1); // Select clause for pages: // Select current page: if (!$id) { $row = $GLOBALS['SOBE']->pageinfo; // The root has a pseudo record in pageinfo... } else { $result = $GLOBALS['TYPO3_DB']->exec_SELECTquery('*', 'pages', 'uid=' . intval($id) . $delClause); $row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($result); t3lib_BEfunc::workspaceOL('pages', $row); } // If there was found a page: if (is_array($row)) { // Select which fields to show: $pKey = $GLOBALS['SOBE']->MOD_SETTINGS['function'] == 'tx_cms_webinfo_hits' ? 'hits' : $GLOBALS['SOBE']->MOD_SETTINGS['pages']; switch ($pKey) { case 'hits': $this->fieldArray = explode(',', 'title,' . implode(',', $this->stat_codes)); break; case 1: $this->cleanTableNames(); $tableNames = $this->allowedTableNames; $this->fieldArray = explode(',', 'title,uid,' . implode(',', array_keys($tableNames))); break; case 2: $this->fieldArray = explode(',', 'title,uid,lastUpdated,newUntil,no_cache,cache_timeout,php_tree_stop,TSconfig,storage_pid,is_siteroot,fe_login_mode'); break; default: $this->fieldArray = explode(',', 'title,uid,alias,starttime,endtime,fe_group,target,url,shortcut,shortcut_mode'); break; } // Getting select-depth: $depth = intval($GLOBALS['SOBE']->MOD_SETTINGS['pages_levels']); // Half line is drawn $theData = Array(); $theData['subject'] = $this->widthGif; $out .= $this->addelement(0, '', $theData); // Overriding a few things: $this->no_noWrap = 0; $this->oddColumnsCssClass = 'bgColor3-20'; // Items $this->eCounter = $this->firstElementNumber; // Creating elements: list($flag, $code) = $this->fwd_rwd_nav(); $out .= $code; $editUids = array(); if ($flag) { // Getting children: $theRows = Array(); $theRows = $this->pages_getTree($theRows, $row['uid'], $delClause . t3lib_BEfunc::versioningPlaceholderClause('pages'), '', $depth); if ($GLOBALS['BE_USER']->doesUserHaveAccess($row, 2)) { $editUids[] = $row['uid']; } $out .= $this->pages_drawItem($row, $this->fieldArray); // Traverse all pages selected: foreach ($theRows as $n => $sRow) { if ($GLOBALS['BE_USER']->doesUserHaveAccess($sRow, 2)) { $editUids[] = $sRow['uid']; } $out .= $this->pages_drawItem($sRow, $this->fieldArray); } $this->eCounter++; } // Header line is drawn $theData = Array(); $editIdList = implode(',', $editUids); // Traverse fields (as set above) in order to create header values: foreach ($this->fieldArray as $field) { if ($editIdList && isset($GLOBALS['TCA']['pages']['columns'][$field]) && $field != 'uid' && !$this->pages_noEditColumns) { $params = '&edit[pages][' . $editIdList . ']=edit&columnsOnly=' . $field . '&disHelp=1'; $iTitle = sprintf($GLOBALS['LANG']->getLL('editThisColumn'), rtrim(trim($GLOBALS['LANG']->sL(t3lib_BEfunc::getItemLabel('pages', $field))), ':')); $eI = '' . t3lib_iconWorks::getSpriteIcon('actions-document-open') . ''; } else { $eI = ''; } switch ($field) { case 'title': $theData[$field] = ' ' . $GLOBALS['LANG']->sL($GLOBALS['TCA']['pages']['columns'][$field]['label']) . '' . $eI; break; case 'uid': $theData[$field] = ' ID:'; break; default: if (substr($field, 0, 6) == 'table_') { $f2 = substr($field, 6); if ($GLOBALS['TCA'][$f2]) { $theData[$field] = ' ' . t3lib_iconWorks::getSpriteIconForRecord( $f2, array(), array('title' => $GLOBALS['LANG']->sL($GLOBALS['TCA'][$f2]['ctrl']['title'], 1)) ); } } elseif (substr($field, 0, 5) == 'HITS_') { $fParts = explode(':', substr($field, 5)); switch ($fParts[0]) { case 'days': $timespan = mktime(0, 0, 0) + intval($fParts[1]) * 3600 * 24; $theData[$field] = ' ' . date('d', $timespan); break; default: $theData[$field] = ''; break; } } else { $theData[$field] = '  ' . $GLOBALS['LANG']->sL($GLOBALS['TCA']['pages']['columns'][$field]['label'], 1) . '' . $eI; } break; } } // Start table: $this->oddColumnsCssClass = ''; // CSH: $out = t3lib_BEfunc::cshItem($this->descrTable, 'func_' . $pKey, $GLOBALS['BACK_PATH']) . ' ' . $this->addelement(1, '', $theData, ' class="t3-row-header"', 20) . $out . '
'; } $this->oddColumnsCssClass = ''; return $out; } /** * Returns the backend layout which should be used for this page. * * @param integer $id: Uid of the current page * @return mixed Uid of the backend layout record or NULL if no layout should be used */ function getSelectedBackendLayoutUid($id) { // uid, pid, t3ver_swapmode needed for workspaceOL() $page = $GLOBALS['TYPO3_DB']->exec_SELECTgetSingleRow('uid, pid, t3ver_swapmode, backend_layout', 'pages', 'uid=' . $id); t3lib_BEfunc::workspaceOL('pages', $page); $backendLayoutUid = intval($page['backend_layout']); if ($backendLayoutUid == -1) { // if it is set to "none" - don't use any $backendLayoutUid = NULL; } elseif ($backendLayoutUid == 0) { // if it not set check the rootline for a layout on next level and use this $rootline = t3lib_BEfunc::BEgetRootLine($id); for ($i = count($rootline) - 2; $i > 0; $i--) { $backendLayoutUid = intval($rootline[$i]['backend_layout_next_level']); if ($backendLayoutUid > 0) { // stop searching if a layout for "next level" is set break; } elseif ($backendLayoutUid == -1){ // if layout for "next level" is set to "none" - don't use any and stop searching $backendLayoutUid = NULL; break; } } } // if it is set to a positive value use this return $backendLayoutUid; } /** * Renders Content Elements from the tt_content table from page id * * @param integer Page id * @return string HTML for the listing */ function getTable_tt_content($id) { $this->initializeLanguages(); // Initialize: $RTE = $GLOBALS['BE_USER']->isRTE(); $lMarg = 1; $showHidden = $this->tt_contentConfig['showHidden'] ? '' : t3lib_BEfunc::BEenableFields('tt_content'); $pageTitleParamForAltDoc = '&recTitle=' . rawurlencode(t3lib_BEfunc::getRecordTitle('pages', t3lib_BEfunc::getRecordWSOL('pages', $id), TRUE)); $GLOBALS['SOBE']->doc->getPageRenderer()->loadExtJs(); $GLOBALS['SOBE']->doc->getPageRenderer()->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]] = $GLOBALS['LANG']->sL($val[0]); } $this->itemLabels = array(); foreach ($GLOBALS['TCA']['tt_content']['columns'] as $name => $val) { $this->itemLabels[$name] = $GLOBALS['LANG']->sL($val['label']); } // Select display mode: if (!$this->tt_contentConfig['single']) { // MULTIPLE column display mode, side by side: // 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 = explode(',', $langList); $defLanguageCount = array(); $defLangBinding = array(); // For EACH languages... : foreach ($langListArr as $lP) { // If NOT languageMode, then we'll only be through this once. $showLanguage = $this->defLangBinding && $lP == 0 ? ' AND sys_language_uid IN (0,-1)' : ' AND sys_language_uid=' . $lP; $cList = explode(',', $this->tt_contentConfig['cols']); $content = array(); $head = array(); // For EACH column, render the content into a variable: foreach ($cList as $key) { if (!$lP) { $defLanguageCount[$key] = array(); } // Select content elements from this column/language: $queryParts = $this->makeQueryArray('tt_content', $id, 'AND colPos=' . intval($key) . $showHidden . $showLanguage); $result = $GLOBALS['TYPO3_DB']->exec_SELECT_queryArray($queryParts); // 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 && !intval($key) && !$GLOBALS['TYPO3_DB']->sql_num_rows($result)) { $onClick = "window.location.href='db_new_content_el.php?id=" . $id . '&colPos=' . intval($key) . '&sys_language_uid=' . $lP . '&uid_pid=' . $id . '&returnUrl=' . rawurlencode(t3lib_div::getIndpEnv('REQUEST_URI')) . "';"; $theNewButton = $GLOBALS['SOBE']->doc->t3Button($onClick, $GLOBALS['LANG']->getLL('newPageContent')); $content[$key] .= '
' . $theNewButton; } // Traverse any selected elements and render their display code: $rowArr = $this->getResult($result); foreach ($rowArr as $rKey => $row) { if (is_array($row) && (int) $row['t3ver_state'] != 2) { $singleElementHTML = ''; if (!$lP) { $defLanguageCount[$key][] = $row['uid']; } $editUidList .= $row['uid'] . ','; $disableMoveAndNewButtons = ($this->defLangBinding && $lP > 0); $singleElementHTML .= $this->tt_content_drawHeader($row, $this->tt_contentConfig['showInfo'] ? 15 : 5, $disableMoveAndNewButtons, TRUE); $isRTE = $RTE && $this->isRTEforField('tt_content', $row, 'bodytext'); $innerContent = '
' . $this->tt_content_drawItem($row, $isRTE) . '
'; $singleElementHTML .= '
' . $innerContent . '
' . $this->tt_content_drawFooter($row); // NOTE: this is the end tag for
// because of bad (historic) conception, starting tag has to be placed inside tt_content_drawHeader() $singleElementHTML .= '
'; $statusHidden = ($this->isDisabled('tt_content', $row) ? ' t3-page-ce-hidden' : ''); $singleElementHTML = '
' . $singleElementHTML . '
'; // 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(t3lib_div::getIndpEnv('REQUEST_URI')) . "';"; } else { $params = '&edit[tt_content][' . (-$row['uid']) . ']=new'; $onClick = t3lib_BEfunc::editOnClick($params, $this->backPath); } $singleElementHTML .= '
' . t3lib_iconWorks::getSpriteIcon('actions-document-new') . '
'; } if ($this->defLangBinding && $this->tt_contentConfig['languageMode']) { $defLangBinding[$key][$lP][$row[($lP ? 'l18n_parent' : 'uid')]] = $singleElementHTML; } else { $content[$key] .= $singleElementHTML; } } else { unset($rowArr[$rKey]); } } // Add new-icon link, header: $newP = $this->newContentElementOnClick($id, $key, $lP); $colTitle = t3lib_BEfunc::getProcessedValue('tt_content', 'colPos', $key); $tcaItems = t3lib_div::callUserFunction('EXT:cms/classes/class.tx_cms_backendlayout.php:tx_cms_BackendLayout->getColPosListItemsParsed', $id, $this); foreach ($tcaItems as $item) { if ($item[1] == $key) { $colTitle = $GLOBALS['LANG']->sL($item[0]); } } $head[$key] .= $this->tt_content_drawColHeader($colTitle, ($this->doEdit && count($rowArr) ? '&edit[tt_content][' . $editUidList . ']=edit' . $pageTitleParamForAltDoc : ''), $newP); $editUidList = ''; } // For EACH column, fit the rendered content into a table cell: $out = ''; $backendLayoutUid = $this->getSelectedBackendLayoutUid($id); $backendLayoutRecord = t3lib_BEfunc::getRecord('backend_layout', intval($backendLayoutUid)); $this->tt_contentConfig['showAsGrid'] = !empty($backendLayoutRecord['config']) && !$this->tt_contentConfig['languageMode']; if (!$this->tt_contentConfig['showAsGrid']) { foreach ($cList as $k => $key) { if (!$k) { $out .= ' '; } else { $out .= ' '; } $out .= ' ' . $head[$key] . $content[$key] . ''; // Storing content for use if languageMode is set: 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); } } } // Wrap the cells into a table row: $out = ' ' . $out . '
'; } else { // GRID VIEW: // initialize TS parser to parse config to array $parser = t3lib_div::makeInstance('t3lib_TSparser'); $parser->parse($backendLayoutRecord['config']); $grid .= '
'; // add colgroups $colCount = intval($parser->setup['backend_layout.']['colCount']); $rowCount = intval($parser->setup['backend_layout.']['rowCount']); $grid .= ''; for ($i = 0; $i < $colCount; $i++) { $grid .= ''; } $grid .= ''; // cycle through rows for ($row = 1; $row <= $rowCount; $row++) { $rowConfig = $parser->setup['backend_layout.']['rows.'][$row . '.']; if (!isset($rowConfig)) { continue; } $grid .= ''; 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 = intval($columnConfig['colPos']); // render the grid cell $colSpan = intval($columnConfig['colspan']); $rowSpan = intval($columnConfig['rowspan']); $grid .= ''; } $grid .= ''; } $out .= $grid . '
0 ? ' colspan="' . $colSpan . '"' : '') . ($rowSpan > 0 ? ' rowspan="' . $rowSpan . '"' : '') . ' class="t3-gridCell t3-page-column t3-page-column-' . $columnKey . (!isset($columnConfig['colPos']) ? ' t3-gridCell-unassigned' : '') . ((isset($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']) && $head[$columnKey]) { $grid .= $head[$columnKey] . $content[$columnKey]; } elseif ($columnConfig['colPos']) { $grid .= $this->tt_content_drawColHeader($GLOBALS['LANG']->getLL('noAccess'), '', ''); } else { $grid .= $this->tt_content_drawColHeader($GLOBALS['LANG']->getLL('notAssigned'), '', ''); } $grid .= '
'; } // CSH: $out .= t3lib_BEfunc::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 = ''; // Separator between language columns (black thin line) $midSep = ' '; // 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: $cCont[$lP] = ' ' . htmlspecialchars($this->tt_contentConfig['languageCols'][$lP]) . ''; // "View page" icon is added: $viewLink = '' . t3lib_iconWorks::getSpriteIcon('actions-document-view') . ''; // Language overlay page header: if ($lP) { list($lpRecord) = t3lib_BEfunc::getRecordsByField('pages_language_overlay', 'pid', $id, 'AND sys_language_uid=' . intval($lP)); t3lib_BEfunc::workspaceOL('pages_language_overlay', $lpRecord); $params = '&edit[pages_language_overlay][' . $lpRecord['uid'] . ']=edit&overrideVals[pages_language_overlay][sys_language_uid]=' . $lP; $lPLabel = $GLOBALS['SOBE']->doc->wrapClickMenuOnIcon(t3lib_iconWorks::getSpriteIconForRecord('pages_language_overlay', $lpRecord), 'pages_language_overlay', $lpRecord['uid']) . $viewLink . ($GLOBALS['BE_USER']->check('tables_modify', 'pages_language_overlay') ? '' . t3lib_iconWorks::getSpriteIcon('actions-document-open') . '' : '') . htmlspecialchars(t3lib_div::fixed_lgd_cs($lpRecord['title'], 20)); } else { $lPLabel = $viewLink; } $sCont[$lP] = ' ' . $lPLabel . ''; } // Add headers: $out .= '' . implode($midSep, $cCont) . ''; $out .= '' . implode($midSep, $sCont) . ''; // Traverse previously built content for the columns: foreach ($languageColumn as $cKey => $cCont) { $out .= ' ' . implode('' . $midSep . ' ', $cCont) . ' '; 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 .= ' ' . implode('' . $midSep . ' ', $cCont) . ' '; } // Create spacer: $cCont = array(); foreach ($langListArr as $lP) { $cCont[] = ' '; } $out .= ' ' . implode('' . $midSep . ' ', $cCont) . ' '; } } // Finally, wrap it all in a table and add the language selector on top of it: $out = $languageSelector . ' ' . $out . '
'; // CSH: $out .= t3lib_BEfunc::cshItem($this->descrTable, 'language_list', $GLOBALS['BACK_PATH']); } } else { // SINGLE column mode (columns shown beneath each other): #debug('single column'); 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']); $content = array(); $out = ''; // Expand the table to some preset dimensions: $out .= ' '; // Traverse columns to display top-on-top foreach ($cList as $counter => $key) { // Select content elements: $queryParts = $this->makeQueryArray('tt_content', $id, 'AND colPos=' . intval($key) . $showHidden . $showLanguage); $result = $GLOBALS['TYPO3_DB']->exec_SELECT_queryArray($queryParts); $c = 0; $rowArr = $this->getResult($result); $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 && !intval($key) && !$GLOBALS['TYPO3_DB']->sql_num_rows($result)) { $onClick = "window.location.href='db_new_content_el.php?id=" . $id . '&colPos=' . intval($key) . '&sys_language_uid=' . $lP . '&uid_pid=' . $id . '&returnUrl=' . rawurlencode(t3lib_div::getIndpEnv('REQUEST_URI')) . "';"; $theNewButton = $GLOBALS['SOBE']->doc->t3Button($onClick, $GLOBALS['LANG']->getLL('newPageContent')); $theNewButton = '
' . $theNewButton; } else { $theNewButton = ''; } // Traverse any selected elements: foreach ($rowArr as $rKey => $row) { if (is_array($row) && (int) $row['t3ver_state'] != 2) { $c++; $editUidList .= $row['uid'] . ','; $isRTE = $RTE && $this->isRTEforField('tt_content', $row, 'bodytext'); // Create row output: $rowOut .= ' ' . $this->tt_content_drawHeader($row) . '   ' . $this->tt_content_drawItem($row, $isRTE) . ' '; // If the element was not the last element, add a divider line: if ($c != $GLOBALS['TYPO3_DB']->sql_num_rows($result)) { $rowOut .= ' backPath, 'gfx/stiblet_medium2.gif', 'width="468" height="1"') . ' class="c-divider" alt="" /> '; } } else { unset($rowArr[$rKey]); } } // Add spacer between sections in the vertical list if ($counter) { $out .= '



'; } // Add section header: $newP = $this->newContentElementOnClick($id, $key, $this->tt_contentConfig['sys_language_uid']); $out .= ' ' . $this->tt_content_drawColHeader(t3lib_BEfunc::getProcessedValue('tt_content', 'colPos', $key), ($this->doEdit && count($rowArr) ? '&edit[tt_content][' . $editUidList . ']=edit' . $pageTitleParamForAltDoc : ''), $newP) . $theNewButton . '
'; // Finally, add the content from the records in this column: $out .= $rowOut; } // Finally, wrap all table rows in one, big table: $out = ' ' . $out . '
'; // CSH: $out .= t3lib_BEfunc::cshItem($this->descrTable, 'columns_single', $GLOBALS['BACK_PATH']); } else { $out = '

' . $GLOBALS['SOBE']->doc->icons(1) . 'Sorry, you cannot view a single language in this localization mode (Default Language Binding is enabled)

'; } } // Add the big buttons to page: if ($this->option_showBigButtons) { $bArray = array(); if (!$GLOBALS['SOBE']->current_sys_language) { if ($this->ext_CALC_PERMS & 2) { $bArray[0] = $GLOBALS['SOBE']->doc->t3Button(t3lib_BEfunc::editOnClick('&edit[pages][' . $id . "]=edit", $this->backPath, ''), $GLOBALS['LANG']->getLL('editPageProperties')); } } else { if ($this->doEdit && $GLOBALS['BE_USER']->check('tables_modify', 'pages_language_overlay')) { list($languageOverlayRecord) = t3lib_BEfunc::getRecordsByField('pages_language_overlay', 'pid', $id, 'AND sys_language_uid=' . intval($GLOBALS['SOBE']->current_sys_language)); $bArray[0] = $GLOBALS['SOBE']->doc->t3Button(t3lib_BEfunc::editOnClick('&edit[pages_language_overlay][' . $languageOverlayRecord['uid'] . "]=edit", $this->backPath, ''), $GLOBALS['LANG']->getLL('editPageProperties_curLang')); } } if ($this->ext_CALC_PERMS & 4 || $this->ext_CALC_PERMS & 2) { $bArray[1] = $GLOBALS['SOBE']->doc->t3Button("window.location.href='" . $this->backPath . "move_el.php?table=pages&uid=" . $id . '&returnUrl=' . rawurlencode(t3lib_div::getIndpEnv('REQUEST_URI')) . "';", $GLOBALS['LANG']->getLL('move_page')); } if ($this->ext_CALC_PERMS & 8) { $bArray[2] = $GLOBALS['SOBE']->doc->t3Button("window.location.href='" . $this->backPath . "db_new.php?id=" . $id . '&pagesOnly=1&returnUrl=' . rawurlencode(t3lib_div::getIndpEnv('REQUEST_URI')) . "';", $GLOBALS['LANG']->getLL('newPage2')); } if ($this->doEdit && $this->ext_function == 1) { $bArray[3] = $GLOBALS['SOBE']->doc->t3Button("window.location.href='db_new_content_el.php?id=" . $id . '&sys_language_uid=' . $GLOBALS['SOBE']->current_sys_language . '&returnUrl=' . rawurlencode(t3lib_div::getIndpEnv('REQUEST_URI')) . "';", $GLOBALS['LANG']->getLL('newPageContent2')); } $out = '
' . implode(' ', $bArray) . ' ' . t3lib_BEfunc::cshItem($this->descrTable, 'button_panel', $GLOBALS['BACK_PATH']) . '

' . $out; } // Return content: return $out; } /********************************** * * Generic listing of items * **********************************/ /** * Creates a standard list of elements from a table. * * @param string Table name * @param integer Page id. * @param string Comma list of fields to display * @param boolean If TRUE, icon is shown * @param string Additional WHERE-clauses. * @return string HTML table */ function makeOrdinaryList($table, $id, $fList, $icon = 0, $addWhere = '') { // Initialize: $out = ''; $queryParts = $this->makeQueryArray($table, $id, $addWhere); $this->setTotalItems($queryParts); $dbCount = 0; // Make query for records if there were any records found in the count operation: if ($this->totalItems) { $result = $GLOBALS['TYPO3_DB']->exec_SELECT_queryArray($queryParts); $dbCount = $GLOBALS['TYPO3_DB']->sql_num_rows($result); } // If records were found, render the list: $out = ''; if ($dbCount) { // Set fields $this->fieldArray = t3lib_div::trimExplode(',', '__cmds__,' . $fList, TRUE); // Header line is drawn $theData = array(); $theData = $this->headerFields($this->fieldArray, $table, $theData); if ($this->doEdit) { $theData['__cmds__'] = '' . t3lib_iconWorks::getSpriteIcon('actions-document-new') . ''; } $out .= $this->addelement(1, '', $theData, ' class="c-headLine"', 15); // Render Items $this->eCounter = $this->firstElementNumber; while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($result)) { t3lib_BEfunc::workspaceOL($table, $row); if (is_array($row)) { list($flag, $code) = $this->fwd_rwd_nav(); $out .= $code; if ($flag) { $params = '&edit[' . $table . '][' . $row['uid'] . ']=edit'; $Nrow = array(); // Setting icons/edit links: if ($icon) { $Nrow['__cmds__'] = $this->getIcon($table, $row); } if ($this->doEdit) { $Nrow['__cmds__'] .= '' . t3lib_iconWorks::getSpriteIcon('actions-document-open') . ''; } else { $Nrow['__cmds__'] .= $this->noEditIcon(); } // Get values: $Nrow = $this->dataFields($this->fieldArray, $table, $row, $Nrow); $tdparams = $this->eCounter % 2 ? ' class="bgColor4"' : ' class="bgColor4-20"'; $out .= $this->addelement(1, '', $Nrow, $tdparams); } $this->eCounter++; } } // Wrap it all in a table: $out = ' ' . $out . '
'; } return $out; } /** * Adds content to all data fields in $out array * * @param array Array of fields to display. Each field name has a special feature which is that the field name can be specified as more field names. Eg. "field1,field2;field3". Field 2 and 3 will be shown in the same cell of the table separated by
while field1 will have its own cell. * @param string Table name * @param array Record array * @param array Array to which the data is added * @return array $out array returned after processing. * @see makeOrdinaryList() */ function dataFields($fieldArr, $table, $row, $out = array()) { // Check table validity: if ($GLOBALS['TCA'][$table]) { t3lib_div::loadTCA($table); $thumbsCol = $GLOBALS['TCA'][$table]['ctrl']['thumbnail']; // Traverse fields: foreach ($fieldArr as $fieldName) { if ($GLOBALS['TCA'][$table]['columns'][$fieldName]) { // Each field has its own cell (if configured in TCA) if ($fieldName == $thumbsCol) { // If the column is a thumbnail column: $out[$fieldName] = $this->thumbCode($row, $table, $fieldName); } else { // ... otherwise just render the output: $out[$fieldName] = nl2br(htmlspecialchars(trim(t3lib_div::fixed_lgd_cs(t3lib_BEfunc::getProcessedValue($table, $fieldName, $row[$fieldName], 0, 0, 0, $row['uid']), 250)))); } } else { // Each field is separated by
and shown in the same cell (If not a TCA field, then explode the field name with ";" and check each value there as a TCA configured field) $theFields = explode(';', $fieldName); // Traverse fields, separated by ";" (displayed in a single cell). foreach ($theFields as $fName2) { if ($GLOBALS['TCA'][$table]['columns'][$fName2]) { $out[$fieldName] .= '' . $GLOBALS['LANG']->sL($GLOBALS['TCA'][$table]['columns'][$fName2]['label'], 1) . '' . '  ' . htmlspecialchars(t3lib_div::fixed_lgd_cs(t3lib_BEfunc::getProcessedValue($table, $fName2, $row[$fName2], 0, 0, 0, $row['uid']), 25)) . '
'; } } } // If no value, add a nbsp. if (!$out[$fieldName]) { $out[$fieldName] = ' '; } // Wrap in dimmed-span tags if record is "disabled" if ($this->isDisabled($table, $row)) { $out[$fieldName] = $GLOBALS['TBE_TEMPLATE']->dfw($out[$fieldName]); } } } return $out; } /** * Header fields made for the listing of records * * @param array Field names * @param string The table name * @param array Array to which the headers are added. * @return array $out returned after addition of the header fields. * @see makeOrdinaryList() */ function headerFields($fieldArr, $table, $out = array()) { t3lib_div::loadTCA($table); foreach ($fieldArr as $fieldName) { $ll = $GLOBALS['LANG']->sL($GLOBALS['TCA'][$table]['columns'][$fieldName]['label'], 1); $out[$fieldName] = '' . ($ll ? $ll : ' ') . ''; } return $out; } /********************************** * * Additional functions; Pages * **********************************/ /** * Adds pages-rows to an array, selecting recursively in the page tree. * * @param array Array which will accumulate page rows * @param integer Pid to select from * @param string Query-where clause * @param string Prefixed icon code. * @param integer Depth (decreasing) * @return array $theRows, but with added rows. */ function pages_getTree($theRows, $pid, $qWhere, $treeIcons, $depth) { $depth--; if ($depth >= 0) { $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('*', 'pages', 'pid=' . intval($pid) . $qWhere, '', 'sorting'); $c = 0; $rc = $GLOBALS['TYPO3_DB']->sql_num_rows($res); while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) { t3lib_BEfunc::workspaceOL('pages', $row); if (is_array($row)) { $c++; $row['treeIcons'] = $treeIcons . 'backPath, 'gfx/ol/join' . ($rc == $c ? 'bottom' : '') . '.gif', 'width="18" height="16"') . ' alt="" />'; $theRows[] = $row; // Get the branch $spaceOutIcons = 'backPath, 'gfx/ol/' . ($rc == $c ? 'blank.gif' : 'line.gif'), 'width="18" height="16"') . ' alt="" />'; $theRows = $this->pages_getTree($theRows, $row['uid'], $qWhere, $treeIcons . $spaceOutIcons, $row['php_tree_stop'] ? 0 : $depth); } } } else { $count = $GLOBALS['TYPO3_DB']->exec_SELECTcountRows('uid', 'pages', 'pid=' . intval($pid) . $qWhere); if ($count) { $this->plusPages[$pid] = $count; } } return $theRows; } /** * Adds a list item for the pages-rendering * * @param array Record array * @param array Field list * @return string HTML for the item */ function pages_drawItem($row, $fieldArr) { // Initialization $theIcon = $this->getIcon('pages', $row); // Preparing and getting the data-array $theData = Array(); foreach ($fieldArr as $field) { switch ($field) { case 'title': $red = $this->plusPages[$row['uid']] ? '' : ''; $pTitle = htmlspecialchars(t3lib_BEfunc::getProcessedValue('pages', $field, $row[$field], 20)); if ($red) { $pTitle = '' . $pTitle . ''; } $theData[$field] = $row['treeIcons'] . $theIcon . $red . $pTitle . '  '; break; case 'php_tree_stop': case 'TSconfig': $theData[$field] = $row[$field] ? ' x' : ' '; break; case 'uid': if ($GLOBALS['BE_USER']->doesUserHaveAccess($row, 2)) { $params = '&edit[pages][' . $row['uid'] . ']=edit'; $eI = '' . t3lib_iconWorks::getSpriteIcon('actions-document-open') . ''; } else { $eI = ''; } $theData[$field] = '' . $row['uid'] . $eI . ''; break; default: if (substr($field, 0, 6) == 'table_') { $f2 = substr($field, 6); if ($GLOBALS['TCA'][$f2]) { $c = $this->numberOfRecords($f2, $row['uid']); $theData[$field] = '  ' . ($c ? $c : ''); } } elseif (substr($field, 0, 5) == 'HITS_') { if (t3lib_extMgm::isLoaded('sys_stat')) { $fParts = explode(':', substr($field, 5)); switch ($fParts[0]) { case 'days': $timespan = mktime(0, 0, 0) + intval($fParts[1]) * 3600 * 24; // Page hits $number = $GLOBALS['TYPO3_DB']->exec_SELECTcountRows( '*', 'sys_stat', $this->stat_select_field . '=' . intval($row['uid']) . ' AND tstamp >=' . intval($timespan) . ' AND tstamp <' . intval($timespan + 3600 * 24) ); if ($number) { // Sessions $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery( 'count(*)', 'sys_stat', $this->stat_select_field . '=' . intval($row['uid']) . ' AND tstamp>=' . intval($timespan) . ' AND tstamp<' . intval($timespan + 3600 * 24) . ' AND surecookie<>\'\'', 'surecookie' ); $scnumber = $GLOBALS['TYPO3_DB']->sql_num_rows($res); $number .= '/' . $scnumber; } else { $number = ''; } break; } $theData[$field] = ' ' . $number; } else { $theData[$field] = ' '; } } else { $theData[$field] = '  ' . htmlspecialchars(t3lib_BEfunc::getProcessedValue('pages', $field, $row[$field])); } break; } } $this->addElement_tdParams['title'] = ($row['_CSSCLASS'] ? ' class="' . $row['_CSSCLASS'] . '"' : ''); return $this->addelement(1, '', $theData); } /********************************** * * Additional functions; Content Elements * **********************************/ /** * Draw header for a content element column: * * @param string Column name * @param string Edit params (Syntax: &edit[...] for alt_doc.php) * @param string New element params (Syntax: &edit[...] for alt_doc.php) * @return string HTML table */ function tt_content_drawColHeader($colName, $editParams, $newParams) { $icons = ''; // Create command links: if ($this->tt_contentConfig['showCommands']) { // New record: if ($newParams) { $icons .= '' . t3lib_iconWorks::getSpriteIcon('actions-document-new') . ''; } // Edit whole of column: if ($editParams) { $icons .= '' . t3lib_iconWorks::getSpriteIcon('actions-document-open') . ''; } } if (strlen($icons)) { $icons = '
' . $icons . '
'; } // Create header row: $out = '
' . $icons . '
' . htmlspecialchars($colName) . '
'; return $out; } /** * Draw the footer for a single tt_content element * * @param array Record array * @return string HTML of the footer */ protected function tt_content_drawFooter(array $row) { $content = ''; // Get processed values: $info = array(); $this->getProcessedValue('tt_content', 'hidden,starttime,endtime,fe_group,spaceBefore,spaceAfter', $row, $info); // Display info from records fields: if (count($info)) { $content = '
' . implode('
', $info) . '
'; } // Wrap it if (!empty($content)) { $content = ''; } return $content; } /** * Draw the header for a single tt_content element * * @param array Record array * @param integer Amount of pixel space above the header. * @param boolean If set the buttons for creating new elements and moving up and down are not shown. * @param boolean If set, we are in language mode and flags will be shown for languages * @return string HTML table with the record header. */ function tt_content_drawHeader($row, $space = 0, $disableMoveAndNewButtons = FALSE, $langMode = FALSE) { // Load full table description: t3lib_div::loadTCA('tt_content'); // If show info is set...; if ($this->tt_contentConfig['showInfo']) { // Render control panel for the element: if ($this->tt_contentConfig['showCommands'] && $this->doEdit) { // Edit content element: $params = '&edit[tt_content][' . $this->tt_contentData['nextThree'][$row['uid']] . ']=edit'; $out .= '' . t3lib_iconWorks::getSpriteIcon('actions-document-open') . ''; // Hide element: $hiddenField = $GLOBALS['TCA']['tt_content']['ctrl']['enablecolumns']['disabled']; if ($hiddenField && $GLOBALS['TCA']['tt_content']['columns'][$hiddenField] && (!$GLOBALS['TCA']['tt_content']['columns'][$hiddenField]['exclude'] || $GLOBALS['BE_USER']->check('non_exclude_fields', 'tt_content:' . $hiddenField))) { if ($row[$hiddenField]) { $params = '&data[tt_content][' . ($row['_ORIG_uid'] ? $row['_ORIG_uid'] : $row['uid']) . '][' . $hiddenField . ']=0'; $out .= '' . t3lib_iconWorks::getSpriteIcon('actions-edit-unhide') . ''; } else { $params = '&data[tt_content][' . ($row['_ORIG_uid'] ? $row['_ORIG_uid'] : $row['uid']) . '][' . $hiddenField . ']=1'; $out .= '' . t3lib_iconWorks::getSpriteIcon('actions-edit-hide') . ''; } } // Delete $params = '&cmd[tt_content][' . $row['uid'] . '][delete]=1'; $confirm = $GLOBALS['LANG']->JScharCode($GLOBALS['LANG']->getLL('deleteWarning') . t3lib_BEfunc::translationCount('tt_content', $row['uid'], ' ' . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xml:labels.translationsOfRecord'))); $out .= '' . t3lib_iconWorks::getSpriteIcon('actions-edit-delete') . ''; if (!$disableMoveAndNewButtons) { $moveButtonContent = ''; $displayMoveButtons = FALSE; // Move element up: if ($this->tt_contentData['prev'][$row['uid']]) { $params = '&cmd[tt_content][' . $row['uid'] . '][move]=' . $this->tt_contentData['prev'][$row['uid']]; $moveButtonContent .= '' . t3lib_iconWorks::getSpriteIcon('actions-move-up') . ''; $displayMoveButtons = TRUE; } else { $moveButtonContent .= t3lib_iconWorks::getSpriteIcon('empty-empty'); } // Move element down: if ($this->tt_contentData['next'][$row['uid']]) { $params = '&cmd[tt_content][' . $row['uid'] . '][move]= ' . $this->tt_contentData['next'][$row['uid']]; $moveButtonContent .= '' . t3lib_iconWorks::getSpriteIcon('actions-move-down') . ''; $displayMoveButtons = TRUE; } else { $moveButtonContent .= t3lib_iconWorks::getSpriteIcon('empty-empty'); } if ($displayMoveButtons) { $out .= '' . $moveButtonContent . ''; } } } } $additionalIcons = array(); $additionalIcons[] = $this->getIcon('tt_content', $row) . ' '; $additionalIcons[] = ($langMode ? $this->languageFlag($row['sys_language_uid'], FALSE) : ''); // Get record locking status: if ($lockInfo = t3lib_BEfunc::isRecordLocked('tt_content', $row['uid'])) { $additionalIcons[] = '' . t3lib_iconWorks::getSpriteIcon('status-warning-in-use') . ''; } // Call stats information hook if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['GLOBAL']['recStatInfoHooks'])) { $_params = array('tt_content', $row['uid'], &$row); foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['GLOBAL']['recStatInfoHooks'] as $_funcRef) { $additionalIcons[] = t3lib_div::callUserFunction($_funcRef, $_params, $this); } } // Wrap the whole header // NOTE: end-tag for
is in getTable_tt_content() return '

' . implode('', $additionalIcons) . ' ' . $out . '

'; } /** * Draws the preview content for a content element * * @param string Content element * @param boolean Set if the RTE link can be created. * @return string HTML */ function tt_content_drawItem($row, $isRTE = FALSE) { $out = ''; $outHeader = ''; // Make header: if ($row['header']) { $infoArr = Array(); $this->getProcessedValue('tt_content', 'header_position,header_layout,header_link', $row, $infoArr); // If header layout is set to 'hidden', display an accordant note: if ($row['header_layout'] == 100) { $hiddenHeaderNote = ' [' . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xml:labels.hidden', TRUE) . ']'; } $outHeader = ($row['date'] ? htmlspecialchars($this->itemLabels['date'] . ' ' . t3lib_BEfunc::date($row['date'])) . '
' : '') . '' . $this->linkEditContent($this->renderText($row['header']), $row) . $hiddenHeaderNote . '
'; } // 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 = t3lib_div::getUserObj($hookClass); if (!($hookObject instanceof tx_cms_layout_tt_content_drawItemHook)) { throw new UnexpectedValueException('$hookObject must implement interface tx_cms_layout_tt_content_drawItemHook', 1218547409); } $hookObject->preProcess($this, $drawItem, $outHeader, $out, $row); } } // 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) . '
'; } break; case 'text': case 'textpic': case 'image': if ($row['CType'] == 'text' || $row['CType'] == 'textpic') { if ($row['bodytext']) { $this->getProcessedValue('tt_content', 'text_align,text_face,text_size,text_color,text_properties', $row, $infoArr); $out .= $this->linkEditContent($this->renderText($row['bodytext']), $row) . '
'; } } if ($row['CType'] == 'textpic' || $row['CType'] == 'image') { if ($row['image']) { $out .= $this->thumbCode($row, 'tt_content', 'image') . '
'; if ($row['imagecaption']) { $out .= $this->linkEditContent($this->renderText($row['imagecaption']), $row) . '
'; } } } break; case 'bullets': case 'table': case 'mailform': if ($row['bodytext']) { $out .= $this->linkEditContent($this->renderText($row['bodytext']), $row) . '
'; } break; case 'uploads': if ($row['media']) { $out .= $this->linkEditContent($this->renderText($row['bodytext']), $row) . '
'; } break; case 'multimedia': if ($row['multimedia']) { $out .= $this->renderText($row['multimedia']) . '
'; $out .= $this->renderText($row['parameters']) . '
'; } break; case 'splash': if ($row['bodytext']) { $out .= $this->linkEditContent($this->renderText($row['bodytext']), $row) . '
'; } if ($row['image']) { $out .= $this->thumbCode($row, 'tt_content', 'image') . '
'; } break; case 'menu': if ($row['pages']) { $out .= $this->linkEditContent($row['pages'], $row) . '
'; } break; case 'shortcut': if ($row['records']) { $out .= $this->linkEditContent($row['shortcut'], $row) . '
'; } 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 (count($hookArr) > 0) { $_params = array('pObj' => &$this, 'row' => $row, 'infoArr' => $infoArr); foreach ($hookArr as $_funcRef) { $hookOut .= t3lib_div::callUserFunction($_funcRef, $_params, $this); } } if (strcmp($hookOut, '')) { $out .= $hookOut; } elseif (!empty($row['select_key'])) { $out .= $GLOBALS['LANG']->sL(t3lib_BEfunc::getItemLabel('tt_content', 'select_key'), 1) . ' ' . $row['select_key'] . '
'; } $out .= $GLOBALS['LANG']->sL(t3lib_BEfunc::getLabelFromItemlist('tt_content', 'pages', $row['pages']), 1) . '
'; break; case 'script': $out .= $GLOBALS['LANG']->sL(t3lib_BEfunc::getItemLabel('tt_content', 'select_key'), 1) . ' ' . $row['select_key'] . '
'; $out .= '
' . $this->linkEditContent($this->renderText($row['bodytext']), $row) . '
'; $out .= '
' . $this->linkEditContent($this->renderText($row['imagecaption']), $row) . '
'; break; default: if ($row['bodytext']) { $out .= $this->linkEditContent($this->renderText($row['bodytext']), $row) . '
'; } break; } } // Wrap span-tags: $out = ' ' . $out . ''; // Add header: $out = $outHeader . $out; // Add RTE button: if ($isRTE) { $out .= $this->linkRTEbutton($row); } // Return values: if ($this->isDisabled('tt_content', $row)) { return $GLOBALS['TBE_TEMPLATE']->dfw($out); } else { return $out; } } /** * Filters out all tt_content uids which are already translated so only non-translated uids is left. * Selects across columns, but within in the same PID. Columns are expect to be the same for translations and original but this may be a conceptual error (?) * * @param array Numeric array with uids of tt_content elements in the default language * @param integer Page pid * @param integer Sys language UID * @return array Modified $defLanguageCount */ function getNonTranslatedTTcontentUids($defLanguageCount, $id, $lP) { if ($lP && count($defLanguageCount)) { // Select all translations here: $queryParts = $this->makeQueryArray('tt_content', $id, 'AND sys_language_uid=' . intval($lP) . ' AND l18n_parent IN (' . implode(',', $defLanguageCount) . ')'); $result = $GLOBALS['TYPO3_DB']->exec_SELECT_queryArray($queryParts); // Flip uids: $defLanguageCount = array_flip($defLanguageCount); // Traverse any selected elements and unset original UID if any: $rowArr = $this->getResult($result); foreach ($rowArr as $row) { unset($defLanguageCount[$row['l18n_parent']]); } // Flip again: $defLanguageCount = array_keys($defLanguageCount); } return $defLanguageCount; } /** * Creates button which is used to create copies of records.. * * @param array Numeric array with uids of tt_content elements in the default language * @param integer Sys language UID * @return string "Copy languages" button, if available. */ function newLanguageButton($defLanguageCount, $lP) { if ($this->doEdit && count($defLanguageCount) && $lP) { $params = ''; foreach ($defLanguageCount as $uidVal) { $params .= '&cmd[tt_content][' . $uidVal . '][localize]=' . $lP; } // Copy for language: $onClick = "window.location.href='" . $GLOBALS['SOBE']->doc->issueCommand($params) . "'; return false;"; $theNewButton = $GLOBALS['SOBE']->doc->t3Button($onClick, $GLOBALS['LANG']->getLL('newPageContent_copyForLang') . ' [' . count($defLanguageCount) . ']'); return $theNewButton; } } /** * Creates onclick-attribute content for a new content element * * @param integer Page id where to create the element. * @param integer Preset: Column position value * @param integer Preset: Sys langauge value * @return string String for onclick attribute. * @see getTable_tt_content() */ function newContentElementOnClick($id, $colPos, $sys_language) { if ($this->option_newWizard) { $onClick = "window.location.href='db_new_content_el.php?id=" . $id . '&colPos=' . $colPos . '&sys_language_uid=' . $sys_language . '&uid_pid=' . $id . '&returnUrl=' . rawurlencode(t3lib_div::getIndpEnv('REQUEST_URI')) . "';"; } else { $onClick = t3lib_BEfunc::editOnClick('&edit[tt_content][' . $id . ']=new&defVals[tt_content][colPos]=' . $colPos . '&defVals[tt_content][sys_language_uid]=' . $sys_language, $this->backPath); } return $onClick; } /** * Will create a link on the input string and possible a big button after the string which links to editing in the RTE * Used for content element content displayed so the user can click the content / "Edit in Rich Text Editor" button * * @param string String to link. Must be prepared for HTML output. * @param array The row. * @return string If the whole thing was editable ($this->doEdit) $str is return with link around. Otherwise just $str. * @see getTable_tt_content() */ function linkEditContent($str, $row) { $addButton = ''; $onClick = ''; if ($this->doEdit) { // Setting onclick action for content link: $onClick = t3lib_BEfunc::editOnClick('&edit[tt_content][' . $row['uid'] . ']=edit', $this->backPath); } // Return link return $onClick ? '' . $str . '' . $addButton : $str; } /** * Adds a button to edit the row in RTE wizard * * @param array The row of tt_content element * @return string Button to click if you want to edit in RTE wizard. */ function linkRTEbutton($row) { $params = array(); $params['table'] = 'tt_content'; $params['uid'] = $row['uid']; $params['pid'] = $row['pid']; $params['field'] = 'bodytext'; $params['returnUrl'] = t3lib_div::linkThisScript(); $RTEonClick = "window.location.href='" . $this->backPath . "wizard_rte.php?" . t3lib_div::implodeArrayForUrl('', array('P' => $params)) . "';return false;"; $addButton = $this->option_showBigButtons && $this->doEdit ? $GLOBALS['SOBE']->doc->t3Button($RTEonClick, $GLOBALS['LANG']->getLL('editInRTE')) : ''; return $addButton; } /** * Make selector box for creating new translation in a language * Displays only languages which are not yet present for the current page and * that are not disabled with page TS. * * @param integer Page id for which to create a new language (pages_language_overlay record) * @return string ' . implode('', $langSelItems) . '

'; } } } /** * Traverse the result pointer given, adding each record to array and setting some internal values at the same time. * * @param pointer SQL result pointer for select query. * @param string Table name defaulting to tt_content * @return array The selected rows returned in this array. */ function getResult($result, $table = 'tt_content') { // Initialize: $editUidList = ''; $recs = Array(); $nextTree = $this->nextThree; $c = 0; $output = Array(); // Traverse the result: while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($result)) { t3lib_BEfunc::workspaceOL($table, $row, -99, TRUE); if ($row) { // Add the row to the array: $output[] = $row; // Set an internal register: $recs[$c] = $row['uid']; // Create the list of the next three ids (for editing links...) for ($a = 0; $a < $nextTree; $a++) { if (isset($recs[$c - $a])) { $this->tt_contentData['nextThree'][$recs[$c - $a]] .= $row['uid'] . ','; } } // Set next/previous ids: if (isset($recs[$c - 1])) { if (isset($recs[$c - 2])) { $this->tt_contentData['prev'][$row['uid']] = -$recs[$c - 2]; } else { $this->tt_contentData['prev'][$row['uid']] = $row['pid']; } $this->tt_contentData['next'][$recs[$c - 1]] = -$row['uid']; } $c++; } } // Return selected records return $output; } /******************************** * * Various helper functions * ********************************/ /** * Counts and returns the number of records on the page with $pid * * @param string Table name * @param integer Page id * @return integer Number of records. */ function numberOfRecords($table, $pid) { if ($GLOBALS['TCA'][$table]) { $count = $GLOBALS['TYPO3_DB']->exec_SELECTcountRows( 'uid', $table, 'pid=' . intval($pid) . t3lib_BEfunc::deleteClause($table) . t3lib_BEfunc::versioningPlaceholderClause($table) ); } return intval($count); } /** * Processing of larger amounts of text (usually from RTE/bodytext fields) with word wrapping etc. * * @param string Input string * @return string Output string */ function renderText($input) { $input = strip_tags($input); $input = t3lib_div::fixed_lgd_cs($input, 1500); return nl2br(htmlspecialchars(trim($this->wordWrapper($input)))); } /** * Creates the icon image tag for record from table and wraps it in a link which will trigger the click menu. * * @param string Table name * @param array Record array * @param string Record title (NOT USED) * @return string HTML for the icon */ function getIcon($table, $row) { // Initialization $alttext = t3lib_BEfunc::getRecordIconAltText($row, $table); $iconImg = t3lib_iconWorks::getSpriteIconForRecord($table, $row, array('title' => $alttext)); $this->counter++; // The icon with link $theIcon = $GLOBALS['SOBE']->doc->wrapClickMenuOnIcon($iconImg, $table, $row['uid']); return $theIcon; } /** * Creates processed values for all fieldnames in $fieldList based on values from $row array. * The result is 'returned' through $info which is passed as a reference * * @param string Table name * @param string Commalist of fields. * @param array Record from which to take values for processing. * @param array Array to which the processed values are added. * @return void */ function getProcessedValue($table, $fieldList, array $row, array &$info) { // Splitting values from $fieldList $fieldArr = explode(',', $fieldList); // Traverse fields from $fieldList foreach ($fieldArr as $field) { if ($row[$field]) { $info[] = '' . htmlspecialchars($this->itemLabels[$field]) . ' ' . htmlspecialchars(t3lib_BEfunc::getProcessedValue($table, $field, $row[$field])); } } } /** * Returns TRUE, if the record given as parameters is NOT visible based on hidden/starttime/endtime (if available) * * @param string Tablename of table to test * @param array Record row. * @return boolean Returns TRUE, if disabled. */ function isDisabled($table, $row) { if ( ($GLOBALS['TCA'][$table]['ctrl']['enablecolumns']['disabled'] && $row[$GLOBALS['TCA'][$table]['ctrl']['enablecolumns']['disabled']]) || ($GLOBALS['TCA'][$table]['ctrl']['enablecolumns']['starttime'] && $row[$GLOBALS['TCA'][$table]['ctrl']['enablecolumns']['starttime']] > $GLOBALS['EXEC_TIME']) || ($GLOBALS['TCA'][$table]['ctrl']['enablecolumns']['endtime'] && $row[$GLOBALS['TCA'][$table]['ctrl']['enablecolumns']['endtime']] && $row[$GLOBALS['TCA'][$table]['ctrl']['enablecolumns']['endtime']] < $GLOBALS['EXEC_TIME']) ) { return TRUE; } } /** * Will perform "word-wrapping" on the input string. What it does is to split by space or linebreak, then find any word longer than $max and if found, a hyphen is inserted. * Works well on normal texts, little less well when HTML is involved (since much HTML will have long strings that will be broken). * * @param string Content to word-wrap. * @param integer Max number of chars in a word before it will be wrapped. * @param string Character to insert when wrapping. * @return string Processed output. */ function wordWrapper($content, $max = 50, $char = ' -') { $array = preg_split('/[ ' . LF . ']/', $content); foreach ($array as $val) { if (strlen($val) > $max) { $content = str_replace($val, substr(chunk_split($val, $max, $char), 0, -1), $content); } } return $content; } /** * Returns icon for "no-edit" of a record. * Basically, the point is to signal that this record could have had an edit link if the circumstances were right. A placeholder for the regular edit icon... * * @param string Label key from LOCAL_LANG * @return string IMG tag for icon. */ function noEditIcon($label = 'noEditItems') { return t3lib_iconWorks::getSpriteIcon('status-edit-read-only', array('title' => $GLOBALS['LANG']->getLL($label, TRUE))); } /** * Function, which fills in the internal array, $this->allowedTableNames with all tables to which the user has access. Also a set of standard tables (pages, static_template, sys_filemounts, etc...) are filtered out. So what is left is basically all tables which makes sense to list content from. * * @return void */ function cleanTableNames() { // Get all table names: $tableNames = array_flip(array_keys($GLOBALS['TCA'])); // Unset common names: unset($tableNames['pages']); unset($tableNames['static_template']); unset($tableNames['sys_filemounts']); unset($tableNames['sys_action']); unset($tableNames['sys_workflows']); unset($tableNames['be_users']); unset($tableNames['be_groups']); $this->allowedTableNames = array(); // Traverse table names and set them in allowedTableNames array IF they can be read-accessed by the user. if (is_array($tableNames)) { foreach ($tableNames as $k => $v) { if ($GLOBALS['BE_USER']->check('tables_select', $k)) { $this->allowedTableNames['table_' . $k] = $k; } } } } /** * Checking if the RTE is available/enabled for a certain table/field and if so, it returns TRUE. * Used to determine if the RTE button should be displayed. * * @param string Table name * @param array Record row (needed, if there are RTE dependencies based on other fields in the record) * @param string Field name * @return boolean Returns TRUE if the rich text editor would be enabled/available for the field name specified. */ function isRTEforField($table, $row, $field) { $specConf = $this->getSpecConfForField($table, $row, $field); $p = t3lib_BEfunc::getSpecConfParametersFromArray($specConf['rte_transform']['parameters']); if (isset($specConf['richtext']) && (!$p['flag'] || !$row[$p['flag']])) { t3lib_BEfunc::fixVersioningPid($table, $row); list($tscPID, $thePidValue) = t3lib_BEfunc::getTSCpid($table, $row['uid'], $row['pid']); if ($thePidValue >= 0) { // If the pid-value is not negative (that is, a pid could NOT be fetched) $RTEsetup = $GLOBALS['BE_USER']->getTSConfig('RTE', t3lib_BEfunc::getPagesTSconfig($tscPID)); $RTEtypeVal = t3lib_BEfunc::getTCAtypeValue($table, $row); $thisConfig = t3lib_BEfunc::RTEsetup($RTEsetup['properties'], $table, $field, $RTEtypeVal); if (!$thisConfig['disabled']) { return TRUE; } } } return FALSE; } /** * Returns "special" configuration from the "types" configuration in TCA for the record given by tablename/fieldname. * Used by isRTEforField() in the process of finding whether a field has RTE enabled or not. * * @param string Table name * @param array Record array * @param string Field name * @return array Spec. conf (if available) * @access private * @see isRTEforField() */ function getSpecConfForField($table, $row, $field) { // Get types-configuration for the record: $types_fieldConfig = t3lib_BEfunc::getTCAtypes($table, $row); // Find the given field and return the spec key value if found: if (is_array($types_fieldConfig)) { foreach ($types_fieldConfig as $vconf) { if ($vconf['field'] == $field) { return $vconf['spec']; } } } } /***************************************** * * External renderings * *****************************************/ /** * Creates an info-box for the current page (identified by input record). * * @param array Page record * @param boolean If set, there will be shown an edit icon, linking to editing of the page properties. * @return string HTML for the box. */ function getPageInfoBox($rec, $edit = 0) { // If editing of the page properties is allowed: if ($edit) { $params = '&edit[pages][' . $rec['uid'] . ']=edit'; $editIcon = '' . t3lib_iconWorks::getSpriteIcon('actions-document-open') . ''; } else { $editIcon = $this->noEditIcon('noEditPage'); } // Setting page icon, link, title: $outPutContent = t3lib_iconWorks::getSpriteIconForRecord('pages', $rec, array('title' => t3lib_BEfunc::titleAttribForPages($rec))) . $editIcon . ' ' . htmlspecialchars($rec['title']); // Init array where infomation is accumulated as label/value pairs. $lines = array(); // Owner user/group: if ($this->pI_showUser) { // User: $users = t3lib_BEfunc::getUserNames('username,usergroup,usergroup_cached_list,uid,realName'); $groupArray = explode(',', $GLOBALS['BE_USER']->user['usergroup_cached_list']); $users = t3lib_BEfunc::blindUserNames($users, $groupArray); $lines[] = array($GLOBALS['LANG']->getLL('pI_crUser') . ':', htmlspecialchars($users[$rec['cruser_id']]['username']) . ' (' . $users[$rec['cruser_id']]['realName'] . ')'); } // Created: $lines[] = array( $GLOBALS['LANG']->getLL('pI_crDate') . ':', t3lib_BEfunc::datetime($rec['crdate']) . ' (' . t3lib_BEfunc::calcAge($GLOBALS['EXEC_TIME'] - $rec['crdate'], $this->agePrefixes) . ')', ); // Last change: $lines[] = array( $GLOBALS['LANG']->getLL('pI_lastChange') . ':', t3lib_BEfunc::datetime($rec['tstamp']) . ' (' . t3lib_BEfunc::calcAge($GLOBALS['EXEC_TIME'] - $rec['tstamp'], $this->agePrefixes) . ')', ); // Last change of content: if ($rec['SYS_LASTCHANGED']) { $lines[] = array( $GLOBALS['LANG']->getLL('pI_lastChangeContent') . ':', t3lib_BEfunc::datetime($rec['SYS_LASTCHANGED']) . ' (' . t3lib_BEfunc::calcAge($GLOBALS['EXEC_TIME'] - $rec['SYS_LASTCHANGED'], $this->agePrefixes) . ')', ); } // Spacer: $lines[] = ''; // Display contents of certain page fields, if any value: $dfields = explode(',', 'alias,target,hidden,starttime,endtime,fe_group,no_cache,cache_timeout,newUntil,lastUpdated,subtitle,keywords,description,abstract,author,author_email'); foreach ($dfields as $fV) { if ($rec[$fV]) { $lines[] = array($GLOBALS['LANG']->sL(t3lib_BEfunc::getItemLabel('pages', $fV)), t3lib_BEfunc::getProcessedValue('pages', $fV, $rec[$fV])); } } // Page hits (depends on "sys_stat" extension) if ($this->pI_showStat && t3lib_extMgm::isLoaded('sys_stat')) { // Counting total hits: $count = $GLOBALS['TYPO3_DB']->exec_SELECTcountRows('*', 'sys_stat', 'page_id=' . intval($rec['uid'])); if ($count) { // Get min/max $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('min(tstamp) AS min,max(tstamp) AS max', 'sys_stat', 'page_id=' . intval($rec['uid'])); $rrow2 = $GLOBALS['TYPO3_DB']->sql_fetch_row($res); $lines[] = ''; $lines[] = array($GLOBALS['LANG']->getLL('pI_hitsPeriod') . ':', t3lib_BEfunc::date($rrow2[0]) . ' - ' . t3lib_BEfunc::date($rrow2[1]) . ' (' . t3lib_BEfunc::calcAge($rrow2[1] - $rrow2[0], $this->agePrefixes) . ')'); $lines[] = array($GLOBALS['LANG']->getLL('pI_hitsTotal') . ':', $rrow2[0]); // Last 10 days $nextMidNight = mktime(0, 0, 0) + 1 * 3600 * 24; $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('count(*), FLOOR((' . $nextMidNight . '-tstamp)/(24*3600)) AS day', 'sys_stat', 'page_id=' . intval($rec['uid']) . ' AND tstamp>' . ($nextMidNight - 10 * 24 * 3600), 'day'); $days = array(); while ($rrow = $GLOBALS['TYPO3_DB']->sql_fetch_row($res)) { $days[$rrow[1]] = $rrow[0]; } $headerH = array(); $contentH = array(); for ($a = 9; $a >= 0; $a--) { $headerH[] = '  ' . date('d', $nextMidNight - ($a + 1) * 24 * 3600) . ' '; $contentH[] = ' ' . ($days[$a] ? intval($days[$a]) : '-') . ''; } // Compile first hit-table (last 10 days) $hitTable = ' ' . implode('', $headerH) . '' . implode('', $contentH) . '
'; $lines[] = array($GLOBALS['LANG']->getLL('pI_hits10days') . ':', $hitTable, 1); // Last 24 hours $nextHour = mktime(date('H'), 0, 0) + 3600; $hours = 16; $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('count(*), FLOOR((' . $nextHour . '-tstamp)/3600) AS hours', 'sys_stat', 'page_id=' . intval($rec['uid']) . ' AND tstamp>' . ($nextHour - $hours * 3600), 'hours'); $days = array(); while ($rrow = $GLOBALS['TYPO3_DB']->sql_fetch_row($res)) { $days[$rrow[1]] = $rrow[0]; } $headerH = array(); $contentH = array(); for ($a = ($hours - 1); $a >= 0; $a--) { $headerH[] = '  ' . intval(date('H', $nextHour - ($a + 1) * 3600)) . ' '; $contentH[] = ' ' . ($days[$a] ? intval($days[$a]) : '-') . ''; } // Compile second hit-table (last 24 hours) $hitTable = ' ' . implode('', $headerH) . '' . implode('', $contentH) . '
'; $lines[] = array($GLOBALS['LANG']->getLL('pI_hits24hours') . ':', $hitTable, 1); } } // Finally, wrap the elements in the $lines array in table cells/rows foreach ($lines as $fV) { if (is_array($fV)) { if (!$fV[2]) { $fV[1] = htmlspecialchars($fV[1]); } $out .= ' ' . htmlspecialchars($fV[0]) . '   ' . $fV[1] . ' '; } else { $out .= ' '; } } // Wrap table tags around... $outPutContent .= ' ' . $out . '
'; // ... and return it. return $outPutContent; } /** * Creates a menu of the tables that can be listed by this function * Only tables which has records on the page will be included. * Notice: The function also fills in the internal variable $this->activeTables with icon/titles. * * @param integer Page id from which we are listing records (the function will look up if there are records on the page) * @return string HTML output. */ function getTableMenu($id) { // Initialize: $this->activeTables = array(); $theTables = array('tt_content'); // External tables: if (is_array($this->externalTables)) { $theTables = array_unique(array_merge($theTables, array_keys($this->externalTables))); } // Traverse tables to check: foreach ($theTables as $tName) { // Check access and whether the proper extensions are loaded: if ($GLOBALS['BE_USER']->check('tables_select', $tName) && (t3lib_extMgm::isLoaded($tName) || t3lib_div::inList('fe_users,tt_content', $tName) || isset($this->externalTables[$tName]))) { // Make query to count records from page: $c = $GLOBALS['TYPO3_DB']->exec_SELECTcountRows( 'uid', $tName, 'pid=' . intval($id) . t3lib_BEfunc::deleteClause($tName) . t3lib_BEfunc::versioningPlaceholderClause($tName) ); // If records were found (or if "tt_content" is the table...): if ($c || t3lib_div::inList('tt_content', $tName)) { // Add row to menu: $out .= ' ' . t3lib_iconWorks::getSpriteIconForRecord( $tName, array(), array('title' => $GLOBALS['LANG']->sL($GLOBALS['TCA'][$tName]['ctrl']['title'], 1)) ) . ''; // ... and to the internal array, activeTables we also add table icon and title (for use elsewhere) $this->activeTables[$tName] = t3lib_iconWorks::getSpriteIconForRecord( $tName, array(), array('title' => $GLOBALS['LANG']->sL($GLOBALS['TCA'][$tName]['ctrl']['title'], 1) . ': ' . $c . ' ' . $GLOBALS['LANG']->getLL('records', 1)) ) . ' ' . $GLOBALS['LANG']->sL($GLOBALS['TCA'][$tName]['ctrl']['title'], 1); } } } // Wrap cells in table tags: $out = ' ' . $out . '
'; // Return the content: return $out; } /** * Enhancement for the strip_tags function that provides the feature to fill in empty tags. * Example is accepted by TYPO3 but would not displayed in the Backend otherwise. * * @param string Input string * @param boolean If TRUE, empty tags will be filled with the first attribute of the tag before. * @return string Input string with all HTML and PHP tags stripped * @deprecated since TYPO3 4.6, will be removed in 4.8 - using php-function strip_tags now */ function strip_tags($content, $fillEmptyContent = FALSE) { if ($fillEmptyContent && strstr($content, '><')) { $content = preg_replace('/(<[^ >]* )([^ >]*)([^>]*>)(<\/[^>]*>)/', '$1$2$3$2$4', $content); } $content = preg_replace('//', LF, $content); return strip_tags($content); } } if (defined('TYPO3_MODE') && isset($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['ext/cms/layout/class.tx_cms_layout.php'])) { include_once($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['ext/cms/layout/class.tx_cms_layout.php']); } ?>