/** * @param string $mass * @param bool $makeResources * @param bool $makeMountPoint * @param string $extensionKey * @param null $author * @param null $title * @param null $description * @param bool $useVhs * @param bool $useFluidcontentCore * @param bool $pages * @param bool $content * @param bool $backend * @param bool $controllers */ public function buildSiteAction($mass = EnterpriseLevelEnumeration::BY_DEFAULT, $makeResources = true, $makeMountPoint = true, $extensionKey = null, $author = null, $title = null, $description = null, $useVhs = true, $useFluidcontentCore = true, $pages = true, $content = true, $backend = false, $controllers = true) { $view = 'buildSite'; $this->view->assign('csh', BackendUtility::wrapInHelp('builder', 'modules')); $this->view->assign('view', $view); $output = $this->kickStarterService->generateFluidPoweredSite($mass, $makeResources, $makeMountPoint, $extensionKey, $author, $title, $description, $useVhs, $useFluidcontentCore, $pages, $content, $backend, $controllers); $this->view->assign('output', $output); // Note: remapping some arguments to match values that will be displayed in the receipt; display uses // template from EXT:builder $attributes = ['name' => ['value' => $extensionKey], 'author' => ['value' => $author], 'level' => ['value' => $level], 'vhs' => ['value' => $useVhs], 'pages' => ['value' => $pages], 'content' => ['value' => $content], 'backend' => ['value' => $backend], 'controllers' => ['value' => $controllers]]; $attributes['name'] = $extensionKey; $attributes['vhs'] = $useVhs; $this->view->assign('attributes', $attributes); }
/** * Render a help button wit the given title and content * * @param string $title Help title * @return mixed */ public function render($title) { $content = $this->renderChildren(); return BackendUtility::wrapInHelp('', '', '', array('title' => $title, 'description' => $content)); }
/** * Gets the filled markers that are used in the HTML template. * * @return array The filled marker array */ protected function getTemplateMarkers() { $markers = array('CSH' => \TYPO3\CMS\Backend\Utility\BackendUtility::wrapInHelp('_MOD_tools_txschedulerM1', ''), 'FUNC_MENU' => $this->getFunctionMenu(), 'CONTENT' => $this->content, 'TITLE' => $GLOBALS['LANG']->getLL('title')); return $markers; }
/** * Builds the checkboxes out of the hooks array * * @param array $brokenLinkOverView Array of broken links information * @param string $prefix * @return string code content */ protected function getCheckOptions(array $brokenLinkOverView, $prefix = '') { $markerArray = array(); if (!empty($prefix)) { $additionalAttr = ' class="' . $prefix . '"'; } else { $additionalAttr = ' class="refresh"'; } $checkOptionsTemplate = HtmlParser::getSubpart($this->doc->moduleTemplate, '###CHECKOPTIONS_SECTION###'); $hookSectionTemplate = HtmlParser::getSubpart($checkOptionsTemplate, '###HOOK_SECTION###'); $markerArray['statistics_header'] = $this->doc->sectionHeader($this->getLanguageService()->getLL('report.statistics.header')); $markerArray['total_count_label'] = BackendUtility::wrapInHelp('linkvalidator', 'checkboxes', $this->getLanguageService()->getLL('overviews.nbtotal')); $markerArray['total_count'] = $brokenLinkOverView['brokenlinkCount'] ?: '0'; $linktypes = GeneralUtility::trimExplode(',', $this->modTS['linktypes'], TRUE); $hookSectionContent = ''; if (is_array($linktypes)) { if (!empty($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['linkvalidator']['checkLinks']) && is_array($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['linkvalidator']['checkLinks'])) { foreach ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['linkvalidator']['checkLinks'] as $type => $value) { if (in_array($type, $linktypes)) { $hookSectionMarker = array('count' => $brokenLinkOverView[$type] ?: '0'); $translation = $this->getLanguageService()->getLL('hooks.' . $type) ?: $type; $hookSectionMarker['option'] = '<input type="checkbox"' . $additionalAttr . ' id="' . $prefix . 'SET_' . $type . '" name="' . $prefix . 'SET[' . $type . ']" value="1"' . ($this->pObj->MOD_SETTINGS[$type] ? ' checked="checked"' : '') . '/>' . '<label for="' . $prefix . 'SET_' . $type . '">' . htmlspecialchars($translation) . '</label>'; $hookSectionContent .= HtmlParser::substituteMarkerArray($hookSectionTemplate, $hookSectionMarker, '###|###', TRUE, TRUE); } } } } $checkOptionsTemplate = HtmlParser::substituteSubpart($checkOptionsTemplate, '###HOOK_SECTION###', $hookSectionContent); return HtmlParser::substituteMarkerArray($checkOptionsTemplate, $markerArray, '###|###', TRUE, TRUE); }
/** * Creates the listing of records from a single table * * @param string $table Table name * @param int $id Page id * @param string $rowList List of fields to show in the listing. Pseudo fields will be added including the record header. * @throws \UnexpectedValueException * @return string HTML table with the listing for the record. */ public function getTable($table, $id, $rowList = '') { $rowListArray = GeneralUtility::trimExplode(',', $rowList, true); // if no columns have been specified, show description (if configured) if (!empty($GLOBALS['TCA'][$table]['ctrl']['descriptionColumn']) && empty($rowListArray)) { array_push($rowListArray, $GLOBALS['TCA'][$table]['ctrl']['descriptionColumn']); } $backendUser = $this->getBackendUserAuthentication(); $lang = $this->getLanguageService(); $db = $this->getDatabaseConnection(); // Init $addWhere = ''; $titleCol = $GLOBALS['TCA'][$table]['ctrl']['label']; $thumbsCol = $GLOBALS['TCA'][$table]['ctrl']['thumbnail']; $l10nEnabled = $GLOBALS['TCA'][$table]['ctrl']['languageField'] && $GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField'] && !$GLOBALS['TCA'][$table]['ctrl']['transOrigPointerTable']; $tableCollapsed = (bool) $this->tablesCollapsed[$table]; // prepare space icon $this->spaceIcon = '<span class="btn btn-default disabled">' . $this->iconFactory->getIcon('empty-empty', Icon::SIZE_SMALL)->render() . '</span>'; // Cleaning rowlist for duplicates and place the $titleCol as the first column always! $this->fieldArray = array(); // title Column // Add title column $this->fieldArray[] = $titleCol; // Control-Panel if (!GeneralUtility::inList($rowList, '_CONTROL_')) { $this->fieldArray[] = '_CONTROL_'; } // Clipboard if ($this->showClipboard) { $this->fieldArray[] = '_CLIPBOARD_'; } // Ref if (!$this->dontShowClipControlPanels) { $this->fieldArray[] = '_REF_'; } // Path if ($this->searchLevels) { $this->fieldArray[] = '_PATH_'; } // Localization if ($this->localizationView && $l10nEnabled) { $this->fieldArray[] = '_LOCALIZATION_'; $this->fieldArray[] = '_LOCALIZATION_b'; $addWhere .= ' AND ( ' . $GLOBALS['TCA'][$table]['ctrl']['languageField'] . '<=0 OR ' . $GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField'] . ' = 0 )'; } // Cleaning up: $this->fieldArray = array_unique(array_merge($this->fieldArray, $rowListArray)); if ($this->noControlPanels) { $tempArray = array_flip($this->fieldArray); unset($tempArray['_CONTROL_']); unset($tempArray['_CLIPBOARD_']); $this->fieldArray = array_keys($tempArray); } // Creating the list of fields to include in the SQL query: $selectFields = $this->fieldArray; $selectFields[] = 'uid'; $selectFields[] = 'pid'; // adding column for thumbnails if ($thumbsCol) { $selectFields[] = $thumbsCol; } if ($table == 'pages') { $selectFields[] = 'module'; $selectFields[] = 'extendToSubpages'; $selectFields[] = 'nav_hide'; $selectFields[] = 'doktype'; $selectFields[] = 'shortcut'; $selectFields[] = 'shortcut_mode'; $selectFields[] = 'mount_pid'; } if (is_array($GLOBALS['TCA'][$table]['ctrl']['enablecolumns'])) { $selectFields = array_merge($selectFields, $GLOBALS['TCA'][$table]['ctrl']['enablecolumns']); } foreach (array('type', 'typeicon_column', 'editlock') as $field) { if ($GLOBALS['TCA'][$table]['ctrl'][$field]) { $selectFields[] = $GLOBALS['TCA'][$table]['ctrl'][$field]; } } if ($GLOBALS['TCA'][$table]['ctrl']['versioningWS']) { $selectFields[] = 't3ver_id'; $selectFields[] = 't3ver_state'; $selectFields[] = 't3ver_wsid'; } if ($l10nEnabled) { $selectFields[] = $GLOBALS['TCA'][$table]['ctrl']['languageField']; $selectFields[] = $GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField']; } if ($GLOBALS['TCA'][$table]['ctrl']['label_alt']) { $selectFields = array_merge($selectFields, GeneralUtility::trimExplode(',', $GLOBALS['TCA'][$table]['ctrl']['label_alt'], true)); } // Unique list! $selectFields = array_unique($selectFields); $fieldListFields = $this->makeFieldList($table, 1); if (empty($fieldListFields) && $GLOBALS['TYPO3_CONF_VARS']['BE']['debug']) { $message = sprintf($lang->sL('LLL:EXT:lang/locallang_mod_web_list.xlf:missingTcaColumnsMessage', true), $table, $table); $messageTitle = $lang->sL('LLL:EXT:lang/locallang_mod_web_list.xlf:missingTcaColumnsMessageTitle', true); /** @var FlashMessage $flashMessage */ $flashMessage = GeneralUtility::makeInstance(FlashMessage::class, $message, $messageTitle, FlashMessage::WARNING, true); /** @var $flashMessageService FlashMessageService */ $flashMessageService = GeneralUtility::makeInstance(FlashMessageService::class); /** @var $defaultFlashMessageQueue \TYPO3\CMS\Core\Messaging\FlashMessageQueue */ $defaultFlashMessageQueue = $flashMessageService->getMessageQueueByIdentifier(); $defaultFlashMessageQueue->enqueue($flashMessage); } // Making sure that the fields in the field-list ARE in the field-list from TCA! $selectFields = array_intersect($selectFields, $fieldListFields); // Implode it into a list of fields for the SQL-statement. $selFieldList = implode(',', $selectFields); $this->selFieldList = $selFieldList; if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/class.db_list_extra.inc']['getTable'])) { foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/class.db_list_extra.inc']['getTable'] as $classData) { $hookObject = GeneralUtility::getUserObj($classData); if (!$hookObject instanceof RecordListGetTableHookInterface) { throw new \UnexpectedValueException('$hookObject must implement interface ' . RecordListGetTableHookInterface::class, 1195114460); } $hookObject->getDBlistQuery($table, $id, $addWhere, $selFieldList, $this); } } // Create the SQL query for selecting the elements in the listing: // do not do paging when outputting as CSV if ($this->csvOutput) { $this->iLimit = 0; } if ($this->firstElementNumber > 2 && $this->iLimit > 0) { // Get the two previous rows for sorting if displaying page > 1 $this->firstElementNumber = $this->firstElementNumber - 2; $this->iLimit = $this->iLimit + 2; // (API function from TYPO3\CMS\Recordlist\RecordList\AbstractDatabaseRecordList) $queryParts = $this->makeQueryArray($table, $id, $addWhere, $selFieldList); $this->firstElementNumber = $this->firstElementNumber + 2; $this->iLimit = $this->iLimit - 2; } else { // (API function from TYPO3\CMS\Recordlist\RecordList\AbstractDatabaseRecordList) $queryParts = $this->makeQueryArray($table, $id, $addWhere, $selFieldList); } // Finding the total amount of records on the page // (API function from TYPO3\CMS\Recordlist\RecordList\AbstractDatabaseRecordList) $this->setTotalItems($queryParts); // Init: $dbCount = 0; $out = ''; $tableHeader = ''; $result = null; $listOnlyInSingleTableMode = $this->listOnlyInSingleTableMode && !$this->table; // If the count query returned any number of records, we perform the real query, // selecting records. if ($this->totalItems) { // Fetch records only if not in single table mode if ($listOnlyInSingleTableMode) { $dbCount = $this->totalItems; } else { // Set the showLimit to the number of records when outputting as CSV if ($this->csvOutput) { $this->showLimit = $this->totalItems; $this->iLimit = $this->totalItems; } $result = $db->exec_SELECT_queryArray($queryParts); $dbCount = $db->sql_num_rows($result); } } // If any records was selected, render the list: if ($dbCount) { $tableTitle = $lang->sL($GLOBALS['TCA'][$table]['ctrl']['title'], true); if ($tableTitle === '') { $tableTitle = $table; } // Header line is drawn $theData = array(); if ($this->disableSingleTableView) { $theData[$titleCol] = '<span class="c-table">' . BackendUtility::wrapInHelp($table, '', $tableTitle) . '</span> (<span class="t3js-table-total-items">' . $this->totalItems . '</span>)'; } else { $icon = $this->table ? '<span title="' . $lang->getLL('contractView', true) . '">' . $this->iconFactory->getIcon('actions-view-table-collapse', Icon::SIZE_SMALL)->render() . '</span>' : '<span title="' . $lang->getLL('expandView', true) . '">' . $this->iconFactory->getIcon('actions-view-table-expand', Icon::SIZE_SMALL)->render() . '</span>'; $theData[$titleCol] = $this->linkWrapTable($table, $tableTitle . ' (<span class="t3js-table-total-items">' . $this->totalItems . '</span>) ' . $icon); } if ($listOnlyInSingleTableMode) { $tableHeader .= BackendUtility::wrapInHelp($table, '', $theData[$titleCol]); } else { // Render collapse button if in multi table mode $collapseIcon = ''; if (!$this->table) { $href = htmlspecialchars($this->listURL() . '&collapse[' . $table . ']=' . ($tableCollapsed ? '0' : '1')); $title = $tableCollapsed ? $lang->sL('LLL:EXT:lang/locallang_core.xlf:labels.expandTable', true) : $lang->sL('LLL:EXT:lang/locallang_core.xlf:labels.collapseTable', true); $icon = '<span class="collapseIcon">' . $this->iconFactory->getIcon($tableCollapsed ? 'actions-view-list-expand' : 'actions-view-list-collapse', Icon::SIZE_SMALL)->render() . '</span>'; $collapseIcon = '<a href="' . $href . '" title="' . $title . '" class="pull-right t3js-toggle-recordlist" data-table="' . htmlspecialchars($table) . '" data-toggle="collapse" data-target="#recordlist-' . htmlspecialchars($table) . '">' . $icon . '</a>'; } $tableHeader .= $theData[$titleCol] . $collapseIcon; } // Render table rows only if in multi table view or if in single table view $rowOutput = ''; if (!$listOnlyInSingleTableMode || $this->table) { // Fixing an order table for sortby tables $this->currentTable = array(); $currentIdList = array(); $doSort = $GLOBALS['TCA'][$table]['ctrl']['sortby'] && !$this->sortField; $prevUid = 0; $prevPrevUid = 0; // Get first two rows and initialize prevPrevUid and prevUid if on page > 1 if ($this->firstElementNumber > 2 && $this->iLimit > 0) { $row = $db->sql_fetch_assoc($result); $prevPrevUid = -(int) $row['uid']; $row = $db->sql_fetch_assoc($result); $prevUid = $row['uid']; } $accRows = array(); // Accumulate rows here while ($row = $db->sql_fetch_assoc($result)) { if (!$this->isRowListingConditionFulfilled($table, $row)) { continue; } // In offline workspace, look for alternative record: BackendUtility::workspaceOL($table, $row, $backendUser->workspace, true); if (is_array($row)) { $accRows[] = $row; $currentIdList[] = $row['uid']; if ($doSort) { if ($prevUid) { $this->currentTable['prev'][$row['uid']] = $prevPrevUid; $this->currentTable['next'][$prevUid] = '-' . $row['uid']; $this->currentTable['prevUid'][$row['uid']] = $prevUid; } $prevPrevUid = isset($this->currentTable['prev'][$row['uid']]) ? -$prevUid : $row['pid']; $prevUid = $row['uid']; } } } $db->sql_free_result($result); $this->totalRowCount = count($accRows); // CSV initiated if ($this->csvOutput) { $this->initCSV(); } // Render items: $this->CBnames = array(); $this->duplicateStack = array(); $this->eCounter = $this->firstElementNumber; $cc = 0; foreach ($accRows as $row) { // Render item row if counter < limit if ($cc < $this->iLimit) { $cc++; $this->translations = false; $rowOutput .= $this->renderListRow($table, $row, $cc, $titleCol, $thumbsCol); // If localization view is enabled it means that the selected records are // either default or All language and here we will not select translations // which point to the main record: if ($this->localizationView && $l10nEnabled) { // For each available translation, render the record: if (is_array($this->translations)) { foreach ($this->translations as $lRow) { // $lRow isn't always what we want - if record was moved we've to work with the // placeholder records otherwise the list is messed up a bit if ($row['_MOVE_PLH_uid'] && $row['_MOVE_PLH_pid']) { $where = 't3ver_move_id="' . (int) $lRow['uid'] . '" AND pid="' . $row['_MOVE_PLH_pid'] . '" AND t3ver_wsid=' . $row['t3ver_wsid'] . BackendUtility::deleteClause($table); $tmpRow = BackendUtility::getRecordRaw($table, $where, $selFieldList); $lRow = is_array($tmpRow) ? $tmpRow : $lRow; } // In offline workspace, look for alternative record: BackendUtility::workspaceOL($table, $lRow, $backendUser->workspace, true); if (is_array($lRow) && $backendUser->checkLanguageAccess($lRow[$GLOBALS['TCA'][$table]['ctrl']['languageField']])) { $currentIdList[] = $lRow['uid']; $rowOutput .= $this->renderListRow($table, $lRow, $cc, $titleCol, $thumbsCol, 18); } } } } } // Counter of total rows incremented: $this->eCounter++; } // Record navigation is added to the beginning and end of the table if in single // table mode if ($this->table) { $rowOutput = $this->renderListNavigation('top') . $rowOutput . $this->renderListNavigation('bottom'); } else { // Show that there are more records than shown if ($this->totalItems > $this->itemsLimitPerTable) { $countOnFirstPage = $this->totalItems > $this->itemsLimitSingleTable ? $this->itemsLimitSingleTable : $this->totalItems; $hasMore = $this->totalItems > $this->itemsLimitSingleTable; $colspan = $this->showIcon ? count($this->fieldArray) + 1 : count($this->fieldArray); $rowOutput .= '<tr><td colspan="' . $colspan . '"> <a href="' . htmlspecialchars($this->listURL() . '&table=' . rawurlencode($table)) . '" class="btn btn-default">' . '<span class="t3-icon fa fa-chevron-down"></span> <i>[1 - ' . $countOnFirstPage . ($hasMore ? '+' : '') . ']</i></a> </td></tr>'; } } // The header row for the table is now created: $out .= $this->renderListHeader($table, $currentIdList); } $collapseClass = $tableCollapsed && !$this->table ? 'collapse' : 'collapse in'; $dataState = $tableCollapsed && !$this->table ? 'collapsed' : 'expanded'; // The list of records is added after the header: $out .= $rowOutput; // ... and it is all wrapped in a table: $out = ' <!-- DB listing of elements: "' . htmlspecialchars($table) . '" --> <div class="panel panel-space panel-default"> <div class="panel-heading"> ' . $tableHeader . ' </div> <div class="table-fit ' . $collapseClass . '" id="recordlist-' . htmlspecialchars($table) . '" data-state="' . $dataState . '"> <table data-table="' . htmlspecialchars($table) . '" class="table table-striped table-hover' . ($listOnlyInSingleTableMode ? ' typo3-dblist-overview' : '') . '"> ' . $out . ' </table> </div> </div> '; // Output csv if... // This ends the page with exit. if ($this->csvOutput) { $this->outputCSV($table); } } // Return content: return $out; }
/** * Main function, starting the rendering of the list. * * @return void * @todo Define visibility */ public function main() { // Start document template object: $this->doc = GeneralUtility::makeInstance('TYPO3\\CMS\\Backend\\Template\\DocumentTemplate'); $this->doc->backPath = $GLOBALS['BACK_PATH']; $this->doc->setModuleTemplate('EXT:recordlist/Resources/Private/Templates/db_list.html'); // Loading current page record and checking access: $this->pageinfo = BackendUtility::readPageAccess($this->id, $this->perms_clause); $access = is_array($this->pageinfo) ? 1 : 0; // Apply predefined values for hidden checkboxes // Set predefined value for DisplayBigControlPanel: if ($this->modTSconfig['properties']['enableDisplayBigControlPanel'] === 'activated') { $this->MOD_SETTINGS['bigControlPanel'] = TRUE; } elseif ($this->modTSconfig['properties']['enableDisplayBigControlPanel'] === 'deactivated') { $this->MOD_SETTINGS['bigControlPanel'] = FALSE; } // Set predefined value for Clipboard: if ($this->modTSconfig['properties']['enableClipBoard'] === 'activated') { $this->MOD_SETTINGS['clipBoard'] = TRUE; } elseif ($this->modTSconfig['properties']['enableClipBoard'] === 'deactivated') { $this->MOD_SETTINGS['clipBoard'] = FALSE; } // Set predefined value for LocalizationView: if ($this->modTSconfig['properties']['enableLocalizationView'] === 'activated') { $this->MOD_SETTINGS['localization'] = TRUE; } elseif ($this->modTSconfig['properties']['enableLocalizationView'] === 'deactivated') { $this->MOD_SETTINGS['localization'] = FALSE; } // Initialize the dblist object: /** @var $dblist \TYPO3\CMS\Recordlist\RecordList\DatabaseRecordList */ $dblist = GeneralUtility::makeInstance('TYPO3\\CMS\\Recordlist\\RecordList\\DatabaseRecordList'); $dblist->backPath = $GLOBALS['BACK_PATH']; $dblist->script = BackendUtility::getModuleUrl('web_list', array(), ''); $dblist->calcPerms = $GLOBALS['BE_USER']->calcPerms($this->pageinfo); $dblist->thumbs = $GLOBALS['BE_USER']->uc['thumbnailsByDefault']; $dblist->returnUrl = $this->returnUrl; $dblist->allFields = $this->MOD_SETTINGS['bigControlPanel'] || $this->table ? 1 : 0; $dblist->localizationView = $this->MOD_SETTINGS['localization']; $dblist->showClipboard = 1; $dblist->disableSingleTableView = $this->modTSconfig['properties']['disableSingleTableView']; $dblist->listOnlyInSingleTableMode = $this->modTSconfig['properties']['listOnlyInSingleTableView']; $dblist->hideTables = $this->modTSconfig['properties']['hideTables']; $dblist->hideTranslations = $this->modTSconfig['properties']['hideTranslations']; $dblist->tableTSconfigOverTCA = $this->modTSconfig['properties']['table.']; $dblist->alternateBgColors = $this->modTSconfig['properties']['alternateBgColors'] ? 1 : 0; $dblist->allowedNewTables = GeneralUtility::trimExplode(',', $this->modTSconfig['properties']['allowedNewTables'], TRUE); $dblist->deniedNewTables = GeneralUtility::trimExplode(',', $this->modTSconfig['properties']['deniedNewTables'], TRUE); $dblist->newWizards = $this->modTSconfig['properties']['newWizards'] ? 1 : 0; $dblist->pageRow = $this->pageinfo; $dblist->counter++; $dblist->MOD_MENU = array('bigControlPanel' => '', 'clipBoard' => '', 'localization' => ''); $dblist->modTSconfig = $this->modTSconfig; $clickTitleMode = trim($this->modTSconfig['properties']['clickTitleMode']); $dblist->clickTitleMode = $clickTitleMode === '' ? 'edit' : $clickTitleMode; // Clipboard is initialized: // Start clipboard $dblist->clipObj = GeneralUtility::makeInstance('TYPO3\\CMS\\Backend\\Clipboard\\Clipboard'); // Initialize - reads the clipboard content from the user session $dblist->clipObj->initializeClipboard(); // Clipboard actions are handled: // CB is the clipboard command array $CB = GeneralUtility::_GET('CB'); if ($this->cmd == 'setCB') { // CBH is all the fields selected for the clipboard, CBC is the checkbox fields which were checked. // By merging we get a full array of checked/unchecked elements // This is set to the 'el' array of the CB after being parsed so only the table in question is registered. $CB['el'] = $dblist->clipObj->cleanUpCBC(array_merge(GeneralUtility::_POST('CBH'), (array) GeneralUtility::_POST('CBC')), $this->cmd_table); } if (!$this->MOD_SETTINGS['clipBoard']) { // If the clipboard is NOT shown, set the pad to 'normal'. $CB['setP'] = 'normal'; } // Execute commands. $dblist->clipObj->setCmd($CB); // Clean up pad $dblist->clipObj->cleanCurrent(); // Save the clipboard content $dblist->clipObj->endClipboard(); // This flag will prevent the clipboard panel in being shown. // It is set, if the clickmenu-layer is active AND the extended view is not enabled. $dblist->dontShowClipControlPanels = !$this->MOD_SETTINGS['bigControlPanel'] && $dblist->clipObj->current == 'normal' && !$this->modTSconfig['properties']['showClipControlPanelsDespiteOfCMlayers']; // If there is access to the page or root page is used for searching, then render the list contents and set up the document template object: if ($access || $this->id === 0 && $this->search_levels > 0 && strlen($this->search_field) > 0) { // Deleting records...: // Has not to do with the clipboard but is simply the delete action. The clipboard object is used to clean up the submitted entries to only the selected table. if ($this->cmd == 'delete') { $items = $dblist->clipObj->cleanUpCBC(GeneralUtility::_POST('CBC'), $this->cmd_table, 1); if (count($items)) { $cmd = array(); foreach ($items as $iK => $value) { $iKParts = explode('|', $iK); $cmd[$iKParts[0]][$iKParts[1]]['delete'] = 1; } $tce = GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\DataHandling\\DataHandler'); $tce->stripslashes_values = 0; $tce->start(array(), $cmd); $tce->process_cmdmap(); if (isset($cmd['pages'])) { BackendUtility::setUpdateSignal('updatePageTree'); } $tce->printLogErrorMessages(GeneralUtility::getIndpEnv('REQUEST_URI')); } } // Initialize the listing object, dblist, for rendering the list: $this->pointer = \TYPO3\CMS\Core\Utility\MathUtility::forceIntegerInRange($this->pointer, 0, 100000); $dblist->start($this->id, $this->table, $this->pointer, $this->search_field, $this->search_levels, $this->showLimit); $dblist->setDispFields(); // Render versioning selector: if (\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::isLoaded('version')) { $dblist->HTMLcode .= $this->doc->getVersionSelector($this->id); } // Render the list of tables: $dblist->generateList(); $listUrl = substr($dblist->listURL(), strlen($GLOBALS['BACK_PATH'])); // Add JavaScript functions to the page: $this->doc->JScode = $this->doc->wrapScriptTags(' function jumpExt(URL,anchor) { // var anc = anchor?anchor:""; window.location.href = URL+(T3_THIS_LOCATION?"&returnUrl="+T3_THIS_LOCATION:"")+anc; return false; } function jumpSelf(URL) { // window.location.href = URL+(T3_RETURN_URL?"&returnUrl="+T3_RETURN_URL:""); return false; } function setHighlight(id) { // top.fsMod.recentIds["web"]=id; top.fsMod.navFrameHighlightedID["web"]="pages"+id+"_"+top.fsMod.currentBank; // For highlighting if (top.content && top.content.nav_frame && top.content.nav_frame.refresh_nav) { top.content.nav_frame.refresh_nav(); } } ' . $this->doc->redirectUrls($listUrl) . ' ' . $dblist->CBfunctions() . ' function editRecords(table,idList,addParams,CBflag) { // window.location.href="' . $GLOBALS['BACK_PATH'] . 'alt_doc.php?returnUrl=' . rawurlencode(GeneralUtility::getIndpEnv('REQUEST_URI')) . '&edit["+table+"]["+idList+"]=edit"+addParams; } function editList(table,idList) { // var list=""; // Checking how many is checked, how many is not var pointer=0; var pos = idList.indexOf(","); while (pos!=-1) { if (cbValue(table+"|"+idList.substr(pointer,pos-pointer))) { list+=idList.substr(pointer,pos-pointer)+","; } pointer=pos+1; pos = idList.indexOf(",",pointer); } if (cbValue(table+"|"+idList.substr(pointer))) { list+=idList.substr(pointer)+","; } return list ? list : idList; } if (top.fsMod) top.fsMod.recentIds["web"] = ' . (int) $this->id . '; '); // Setting up the context sensitive menu: $this->doc->getContextMenuCode(); } // access // Begin to compile the whole page, starting out with page header: $this->body = $this->doc->header($this->pageinfo['title']); $this->body .= '<form action="' . htmlspecialchars($dblist->listURL()) . '" method="post" name="dblistForm">'; $this->body .= $dblist->HTMLcode; $this->body .= '<input type="hidden" name="cmd_table" /><input type="hidden" name="cmd" /></form>'; // If a listing was produced, create the page footer with search form etc: if ($dblist->HTMLcode) { // Making field select box (when extended view for a single table is enabled): if ($dblist->table) { $this->body .= $dblist->fieldSelectBox($dblist->table); } // Adding checkbox options for extended listing and clipboard display: $this->body .= ' <!-- Listing options for extended view, clipboard and localization view --> <div id="typo3-listOptions"> <form action="" method="post">'; // Add "display bigControlPanel" checkbox: if ($this->modTSconfig['properties']['enableDisplayBigControlPanel'] === 'selectable') { $this->body .= BackendUtility::getFuncCheck($this->id, 'SET[bigControlPanel]', $this->MOD_SETTINGS['bigControlPanel'], '', $this->table ? '&table=' . $this->table : '', 'id="checkLargeControl"'); $this->body .= '<label for="checkLargeControl">' . BackendUtility::wrapInHelp('xMOD_csh_corebe', 'list_options', $GLOBALS['LANG']->getLL('largeControl', TRUE)) . '</label><br />'; } // Add "clipboard" checkbox: if ($this->modTSconfig['properties']['enableClipBoard'] === 'selectable') { if ($dblist->showClipboard) { $this->body .= BackendUtility::getFuncCheck($this->id, 'SET[clipBoard]', $this->MOD_SETTINGS['clipBoard'], '', $this->table ? '&table=' . $this->table : '', 'id="checkShowClipBoard"'); $this->body .= '<label for="checkShowClipBoard">' . BackendUtility::wrapInHelp('xMOD_csh_corebe', 'list_options', $GLOBALS['LANG']->getLL('showClipBoard', TRUE)) . '</label><br />'; } } // Add "localization view" checkbox: if ($this->modTSconfig['properties']['enableLocalizationView'] === 'selectable') { $this->body .= BackendUtility::getFuncCheck($this->id, 'SET[localization]', $this->MOD_SETTINGS['localization'], '', $this->table ? '&table=' . $this->table : '', 'id="checkLocalization"'); $this->body .= '<label for="checkLocalization">' . BackendUtility::wrapInHelp('xMOD_csh_corebe', 'list_options', $GLOBALS['LANG']->getLL('localization', TRUE)) . '</label><br />'; } $this->body .= ' </form> </div>'; } // Printing clipboard if enabled if ($this->MOD_SETTINGS['clipBoard'] && $dblist->showClipboard && ($dblist->HTMLcode || $dblist->clipObj->hasElements())) { $this->body .= '<div class="db_list-dashboard">' . $dblist->clipObj->printClipboard() . '</div>'; } // Search box: if (!$this->modTSconfig['properties']['disableSearchBox'] && ($dblist->HTMLcode || $dblist->searchString !== '')) { $sectionTitle = BackendUtility::wrapInHelp('xMOD_csh_corebe', 'list_searchbox', $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:labels.search', TRUE)); $this->body .= '<div class="db_list-searchbox">' . $this->doc->section($sectionTitle, $dblist->getSearchBox(), FALSE, TRUE, FALSE, TRUE) . '</div>'; } // Additional footer content $footerContentHook = $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['recordlist/mod1/index.php']['drawFooterHook']; if (is_array($footerContentHook)) { foreach ($footerContentHook as $hook) { $params = array(); $this->body .= GeneralUtility::callUserFunction($hook, $params, $this); } } // Setting up the buttons and markers for docheader $docHeaderButtons = $dblist->getButtons(); $markers = array('CSH' => $docHeaderButtons['csh'], 'CONTENT' => $this->body, 'EXTRACONTAINERCLASS' => $this->table ? 'singletable' : ''); // Build the <body> for the module $this->content = $this->doc->moduleBody($this->pageinfo, $docHeaderButtons, $markers); // Renders the module page $this->content = $this->doc->render('DB list', $this->content); }
/** * @param string $view * @return void */ public function buildFormAction($view = 'BuildForm') { $author = ''; if (!empty($GLOBALS['BE_USER']->user['realName']) && !empty($GLOBALS['BE_USER']->user['email'])) { $author = $GLOBALS['BE_USER']->user['realName'] . ' <' . $GLOBALS['BE_USER']->user['email'] . '>'; } $this->view->assign('csh', BackendUtility::wrapInHelp('builder', 'modules')); $this->view->assign('view', $view); $this->view->assign('author', $author); $isFluidcontentCoreInstalled = ExtensionManagementUtility::isLoaded('fluidcontent_core') ? "'checked'" : null; $this->view->assign('isFluidcontentCoreInstalled', $isFluidcontentCoreInstalled); }
/** * Returns the CSH Icon for given string * * @param string $str Locallang key * @param string $label The label to be used, that should be wrapped in help * @return string HTML output. */ protected function getCSH($str, $label) { $context = '_MOD_user_setup'; $field = $str; $strParts = explode(':', $str); if (count($strParts) > 1) { // Setting comes from another extension $context = $strParts[0]; $field = $strParts[1]; } elseif ($str !== 'language' && $str !== 'simuser' && $str !== 'reset') { $field = 'option_' . $str; } return BackendUtility::wrapInHelp($context, $field, $label); }
/** * Rendering all other listings than QuickEdit * * @return void * @todo Define visibility */ public function renderListContent() { // Initialize list object (see "class.db_layout.inc"): /** @var $dblist \TYPO3\CMS\Backend\View\PageLayoutView */ $dblist = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Backend\\View\\PageLayoutView'); $dblist->backPath = $GLOBALS['BACK_PATH']; $dblist->thumbs = $this->imagemode; $dblist->no_noWrap = 1; $dblist->descrTable = $this->descrTable; $this->pointer = \TYPO3\CMS\Core\Utility\MathUtility::forceIntegerInRange($this->pointer, 0, 100000); $dblist->script = 'db_layout.php'; $dblist->showIcon = 0; $dblist->setLMargin = 0; $dblist->doEdit = $this->EDIT_CONTENT; $dblist->ext_CALC_PERMS = $this->CALC_PERMS; $dblist->agePrefixes = $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:labels.minutesHoursDaysYears'); $dblist->id = $this->id; $dblist->nextThree = \TYPO3\CMS\Core\Utility\MathUtility::forceIntegerInRange($this->modTSconfig['properties']['editFieldsAtATime'], 0, 10); $dblist->option_showBigButtons = $this->modTSconfig['properties']['disableBigButtons'] === '0'; $dblist->option_newWizard = $this->modTSconfig['properties']['disableNewContentElementWizard'] ? 0 : 1; $dblist->defLangBinding = $this->modTSconfig['properties']['defLangBinding'] ? 1 : 0; if (!$dblist->nextThree) { $dblist->nextThree = 1; } $dblist->externalTables = $this->externalTables; // Create menu for selecting a table to jump to (this is, if more than just pages/tt_content elements are found on the page!) $h_menu = $dblist->getTableMenu($this->id); // Initialize other variables: $h_func = ''; $tableOutput = array(); $tableJSOutput = array(); $CMcounter = 0; // Traverse the list of table names which has records on this page (that array is populated // by the $dblist object during the function getTableMenu()): foreach ($dblist->activeTables as $table => $value) { // Load full table definitions: \TYPO3\CMS\Core\Utility\GeneralUtility::loadTCA($table); if (!isset($dblist->externalTables[$table])) { $q_count = $this->getNumberOfHiddenElements(); $h_func_b = \TYPO3\CMS\Backend\Utility\BackendUtility::getFuncCheck($this->id, 'SET[tt_content_showHidden]', $this->MOD_SETTINGS['tt_content_showHidden'], 'db_layout.php', '', 'id="checkTt_content_showHidden"') . '<label for="checkTt_content_showHidden">' . (!$q_count ? $GLOBALS['TBE_TEMPLATE']->dfw($GLOBALS['LANG']->getLL('hiddenCE')) : $GLOBALS['LANG']->getLL('hiddenCE') . ' (' . $q_count . ')') . '</label>'; // Boolean: Display up/down arrows and edit icons for tt_content records $dblist->tt_contentConfig['showCommands'] = 1; // Boolean: Display info-marks or not $dblist->tt_contentConfig['showInfo'] = 1; // Boolean: If set, the content of column(s) $this->tt_contentConfig['showSingleCol'] is shown // in the total width of the page $dblist->tt_contentConfig['single'] = 0; if ($this->MOD_SETTINGS['function'] == 4) { // Grid view $dblist->tt_contentConfig['showAsGrid'] = 1; } // Setting up the tt_content columns to show: if (is_array($GLOBALS['TCA']['tt_content']['columns']['colPos']['config']['items'])) { $colList = array(); $tcaItems = \TYPO3\CMS\Core\Utility\GeneralUtility::callUserFunction('EXT:cms/classes/class.tx_cms_backendlayout.php:TYPO3\\CMS\\Backend\\View\\BackendLayoutView->getColPosListItemsParsed', $this->id, $this); foreach ($tcaItems as $temp) { $colList[] = $temp[1]; } } else { // ... should be impossible that colPos has no array. But this is the fallback should it make any sense: $colList = array('1', '0', '2', '3'); } if (strcmp($this->colPosList, '')) { $colList = array_intersect(\TYPO3\CMS\Core\Utility\GeneralUtility::intExplode(',', $this->colPosList), $colList); } // If only one column found, display the single-column view. if (count($colList) === 1 && !$this->MOD_SETTINGS['function'] === 4) { // Boolean: If set, the content of column(s) $this->tt_contentConfig['showSingleCol'] // is shown in the total width of the page $dblist->tt_contentConfig['single'] = 1; // The column(s) to show if single mode (under each other) $dblist->tt_contentConfig['showSingleCol'] = current($colList); } // The order of the rows: Default is left(1), Normal(0), right(2), margin(3) $dblist->tt_contentConfig['cols'] = implode(',', $colList); $dblist->tt_contentConfig['showHidden'] = $this->MOD_SETTINGS['tt_content_showHidden']; $dblist->tt_contentConfig['sys_language_uid'] = intval($this->current_sys_language); // If the function menu is set to "Language": if ($this->MOD_SETTINGS['function'] == 2) { $dblist->tt_contentConfig['single'] = 0; $dblist->tt_contentConfig['languageMode'] = 1; $dblist->tt_contentConfig['languageCols'] = $this->MOD_MENU['language']; $dblist->tt_contentConfig['languageColsPointer'] = $this->current_sys_language; } } else { if (isset($this->MOD_SETTINGS) && isset($this->MOD_MENU)) { $h_func = \TYPO3\CMS\Backend\Utility\BackendUtility::getFuncMenu($this->id, 'SET[' . $table . ']', $this->MOD_SETTINGS[$table], $this->MOD_MENU[$table], 'db_layout.php', ''); } else { $h_func = ''; } } // Start the dblist object: $dblist->itemsLimitSingleTable = 1000; $dblist->start($this->id, $table, $this->pointer, $this->search_field, $this->search_levels, $this->showLimit); $dblist->counter = $CMcounter; $dblist->ext_function = $this->MOD_SETTINGS['function']; // Render versioning selector: $dblist->HTMLcode .= $this->doc->getVersionSelector($this->id); // Generate the list of elements here: $dblist->generateList(); // Adding the list content to the tableOutput variable: $tableOutput[$table] = ($h_func ? $h_func . '<br /><img src="clear.gif" width="1" height="4" alt="" /><br />' : '') . $dblist->HTMLcode . ($h_func_b ? '<img src="clear.gif" width="1" height="10" alt="" /><br />' . $h_func_b : ''); // ... and any accumulated JavaScript goes the same way! $tableJSOutput[$table] = $dblist->JScode; // Increase global counter: $CMcounter += $dblist->counter; // Reset variables after operation: $dblist->HTMLcode = ''; $dblist->JScode = ''; $h_func = ''; $h_func_b = ''; } // END: traverse tables // For Context Sensitive Menus: $this->doc->getContextMenuCode(); // Add the content for each table we have rendered (traversing $tableOutput variable) foreach ($tableOutput as $table => $output) { $content .= $this->doc->section('', $output, TRUE, TRUE, 0, TRUE); $content .= $this->doc->spacer(15); $content .= $this->doc->sectionEnd(); } // Making search form: if (!$this->modTSconfig['properties']['disableSearchBox'] && count($tableOutput)) { $sectionTitle = \TYPO3\CMS\Backend\Utility\BackendUtility::wrapInHelp('xMOD_csh_corebe', 'list_searchbox', $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:labels.search', TRUE)); $content .= $this->doc->section($sectionTitle, $dblist->getSearchBox(0), FALSE, TRUE, FALSE, TRUE); } // Additional footer content $footerContentHook = $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['cms/layout/db_layout.php']['drawFooterHook']; if (is_array($footerContentHook)) { foreach ($footerContentHook as $hook) { $params = array(); $content .= \TYPO3\CMS\Core\Utility\GeneralUtility::callUserFunction($hook, $params, $this); } } return $content; }
/** * Prints the clipboard * * @return string HTML output * @throws \BadFunctionCallException */ public function printClipboard() { $languageService = $this->getLanguageService(); $elementCount = count($this->elFromTable($this->fileMode ? '_FILE' : '')); // Copymode Selector menu $copymodeUrl = GeneralUtility::linkThisScript(); $this->view->assign('actionCopyModeUrl', htmlspecialchars(GeneralUtility::quoteJSvalue($copymodeUrl . '&CB[setCopyMode]='))); $this->view->assign('actionCopyModeUrl1', htmlspecialchars(GeneralUtility::quoteJSvalue($copymodeUrl . '&CB[setCopyMode]=1'))); $this->view->assign('currentMode', $this->currentMode()); $this->view->assign('elementCount', $elementCount); if ($elementCount) { $removeAllUrl = GeneralUtility::linkThisScript(['CB' => ['removeAll' => $this->current]]); $this->view->assign('removeAllUrl', $removeAllUrl); // Selector menu + clear button $optionArray = []; // Import / Export link: if (ExtensionManagementUtility::isLoaded('impexp')) { $url = BackendUtility::getModuleUrl('xMOD_tximpexp', $this->exportClipElementParameters()); $optionArray[] = ['label' => $this->clLabel('export', 'rm'), 'uri' => $url]; } // Edit: if (!$this->fileMode) { $optionArray[] = ['label' => $this->clLabel('edit', 'rm'), 'uri' => '#', 'additionalAttributes' => ['onclick' => htmlspecialchars('window.location.href=' . GeneralUtility::quoteJSvalue($this->editUrl() . '&returnUrl=') . '+top.rawurlencode(window.location.href);')]]; } // Delete referenced elements: $confirmationCheck = false; if ($this->getBackendUser()->jsConfirmation(JsConfirmation::DELETE)) { $confirmationCheck = true; } $confirmationMessage = sprintf($languageService->sL('LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:mess.deleteClip'), $elementCount); $title = $languageService->sL('LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:labels.clipboard.delete_elements'); $returnUrl = $this->deleteUrl(1, $this->fileMode ? 1 : 0); $btnOkText = $languageService->sL('LLL:EXT:lang/Resources/Private/Language/locallang_alt_doc.xlf:buttons.confirm.delete_elements.yes'); $btnCancelText = $languageService->sL('LLL:EXT:lang/Resources/Private/Language/locallang_alt_doc.xlf:buttons.confirm.delete_elements.no'); $optionArray[] = ['label' => htmlspecialchars($title), 'uri' => $returnUrl, 'additionalAttributes' => ['class' => $confirmationCheck ? 't3js-modal-trigger' : ''], 'data' => ['severity' => 'warning', 'button-close-text' => htmlspecialchars($btnCancelText), 'button-ok-text' => htmlspecialchars($btnOkText), 'content' => htmlspecialchars($confirmationMessage), 'title' => htmlspecialchars($title)]]; // Clear clipboard $optionArray[] = ['label' => $languageService->sL('LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:labels.clipboard.clear_clipboard', true), 'uri' => $removeAllUrl . '#clip_head']; $this->view->assign('optionArray', $optionArray); } // Print header and content for the NORMAL tab: $this->view->assign('current', $this->current); $tabArray = []; $tabArray['normal'] = ['id' => 'normal', 'number' => 0, 'url' => GeneralUtility::linkThisScript(['CB' => ['setP' => 'normal']]), 'description' => 'normal-description', 'label' => 'labels.normal', 'padding' => $this->padTitle('normal')]; if ($this->current == 'normal') { $tabArray['normal']['content'] = $this->getContentFromTab('normal'); } // Print header and content for the NUMERIC tabs: for ($a = 1; $a <= $this->numberTabs; $a++) { $tabArray['tab_' . $a] = ['id' => 'tab_' . $a, 'number' => $a, 'url' => GeneralUtility::linkThisScript(['CB' => ['setP' => 'tab_' . $a]]), 'description' => 'cliptabs-description', 'label' => 'labels.cliptabs-name', 'padding' => $this->padTitle('tab_' . $a)]; if ($this->current === 'tab_' . $a) { $tabArray['tab_' . $a]['content'] = $this->getContentFromTab('tab_' . $a); } } $this->view->assign('clipboardHeader', BackendUtility::wrapInHelp('xMOD_csh_corebe', 'list_clipboard', $this->clLabel('clipboard', 'buttons'))); $this->view->assign('tabArray', $tabArray); return $this->view->render(); }
/** * Entry method * * @return array As defined in initializeResultArray() of AbstractNode */ public function render() { $table = $this->globalOptions['table']; $row = $this->globalOptions['databaseRow']; $fieldName = $this->globalOptions['fieldName']; $flexFormDataStructureArray = $this->globalOptions['flexFormDataStructureArray']; $flexFormRowData = $this->globalOptions['flexFormRowData']; $flexFormCurrentLanguage = $this->globalOptions['flexFormCurrentLanguage']; $flexFormNoEditDefaultLanguage = $this->globalOptions['flexFormNoEditDefaultLanguage']; $flexFormFormPrefix = $this->globalOptions['flexFormFormPrefix']; $parameterArray = $this->globalOptions['parameterArray']; $languageService = $this->getLanguageService(); $resultArray = $this->initializeResultArray(); foreach ($flexFormDataStructureArray as $flexFormFieldName => $flexFormFieldArray) { if (!is_array($flexFormFieldArray) || !isset($flexFormFieldArray['type']) && !is_array($flexFormFieldArray['TCEforms']['config'])) { continue; } if ($flexFormFieldArray['type'] === 'array') { // Section if (empty($flexFormFieldArray['section'])) { $resultArray['html'] = LF . 'Section expected at ' . $flexFormFieldName . ' but not found'; continue; } $sectionTitle = ''; if (!empty($flexFormFieldArray['title'])) { $sectionTitle = $languageService->sL($flexFormFieldArray['title']); } $options = $this->globalOptions; $options['flexFormDataStructureArray'] = $flexFormFieldArray['el']; $options['flexFormRowData'] = is_array($flexFormRowData[$flexFormFieldName]['el']) ? $flexFormRowData[$flexFormFieldName]['el'] : array(); $options['flexFormSectionType'] = $flexFormFieldName; $options['flexFormSectionTitle'] = $sectionTitle; $options['renderType'] = 'flexFormSectionContainer'; /** @var NodeFactory $nodeFactory */ $nodeFactory = $this->globalOptions['nodeFactory']; $sectionContainerResult = $nodeFactory->create($options)->render(); $resultArray = $this->mergeChildReturnIntoExistingResult($resultArray, $sectionContainerResult); } else { // Single element $vDEFkey = 'vDEF'; $displayConditionResult = TRUE; if (!empty($flexFormFieldArray['TCEforms']['displayCond'])) { $conditionData = is_array($flexFormRowData) ? $flexFormRowData : array(); $conditionData['parentRec'] = $row; /** @var $elementConditionMatcher ElementConditionMatcher */ $elementConditionMatcher = GeneralUtility::makeInstance(ElementConditionMatcher::class); $displayConditionResult = $elementConditionMatcher->match($flexFormFieldArray['TCEforms']['displayCond'], $conditionData, $vDEFkey); } if (!$displayConditionResult) { continue; } // On-the-fly migration for flex form "TCA" // @deprecated since TYPO3 CMS 7, will be removed in TYPO3 CMS 8. This can be removed *if* no additional TCA migration is added with CMS 8, see class TcaMigration $dummyTca = array('dummyTable' => array('columns' => array('dummyField' => $flexFormFieldArray['TCEforms']))); $tcaMigration = GeneralUtility::makeInstance(TcaMigration::class); $migratedTca = $tcaMigration->migrate($dummyTca); $messages = $tcaMigration->getMessages(); if (!empty($messages)) { $context = 'FormEngine did an on-the-fly migration of a flex form data structure. This is deprecated and will be removed' . ' with TYPO3 CMS 8. Merge the following changes into the flex form definition of table ' . $table . ' in field ' . $fieldName . ':'; array_unshift($messages, $context); GeneralUtility::deprecationLog(implode(LF, $messages)); } $flexFormFieldArray['TCEforms'] = $migratedTca['dummyTable']['columns']['dummyField']; // Set up options for single element $fakeParameterArray = array('fieldConf' => array('label' => $languageService->sL(trim($flexFormFieldArray['TCEforms']['label'])), 'config' => $flexFormFieldArray['TCEforms']['config'], 'defaultExtras' => $flexFormFieldArray['TCEforms']['defaultExtras'], 'onChange' => $flexFormFieldArray['TCEforms']['onChange'])); // Force a none field if default language can not be edited if ($flexFormNoEditDefaultLanguage && $flexFormCurrentLanguage === 'lDEF') { $fakeParameterArray['fieldConf']['config'] = array('type' => 'none', 'rows' => 2); } $alertMsgOnChange = ''; if ($fakeParameterArray['fieldConf']['onChange'] === 'reload' || !empty($GLOBALS['TCA'][$table]['ctrl']['type']) && $GLOBALS['TCA'][$table]['ctrl']['type'] === $flexFormFieldName || !empty($GLOBALS['TCA'][$table]['ctrl']['requestUpdate']) && GeneralUtility::inList($GLOBALS['TCA'][$table]['ctrl']['requestUpdate'], $flexFormFieldName)) { if ($this->getBackendUserAuthentication()->jsConfirmation(JsConfirmation::TYPE_CHANGE)) { $alertMsgOnChange = 'if (confirm(TBE_EDITOR.labels.onChangeAlert) && TBE_EDITOR.checkSubmit(-1)){ TBE_EDITOR.submitForm() };'; } else { $alertMsgOnChange = 'if (TBE_EDITOR.checkSubmit(-1)){ TBE_EDITOR.submitForm();}'; } } $fakeParameterArray['fieldChangeFunc'] = $parameterArray['fieldChangeFunc']; if ($alertMsgOnChange) { $fakeParameterArray['fieldChangeFunc']['alert'] = $alertMsgOnChange; } $fakeParameterArray['onFocus'] = $parameterArray['onFocus']; $fakeParameterArray['label'] = $parameterArray['label']; $fakeParameterArray['itemFormElName'] = $parameterArray['itemFormElName'] . $flexFormFormPrefix . '[' . $flexFormFieldName . '][' . $vDEFkey . ']'; $fakeParameterArray['itemFormElID'] = $fakeParameterArray['itemFormElName']; if (isset($flexFormRowData[$flexFormFieldName][$vDEFkey])) { $fakeParameterArray['itemFormElValue'] = $flexFormRowData[$flexFormFieldName][$vDEFkey]; } else { $fakeParameterArray['itemFormElValue'] = $fakeParameterArray['fieldConf']['config']['default']; } $options = $this->globalOptions; $options['parameterArray'] = $fakeParameterArray; $options['elementBaseName'] = $this->globalOptions['elementBaseName'] . $flexFormFormPrefix . '[' . $flexFormFieldName . '][' . $vDEFkey . ']'; if (!empty($flexFormFieldArray['TCEforms']['config']['renderType'])) { $options['renderType'] = $flexFormFieldArray['TCEforms']['config']['renderType']; } else { // Fallback to type if no renderType is given $options['renderType'] = $flexFormFieldArray['TCEforms']['config']['type']; } /** @var NodeFactory $nodeFactory */ $nodeFactory = $this->globalOptions['nodeFactory']; $childResult = $nodeFactory->create($options)->render(); $theTitle = htmlspecialchars($fakeParameterArray['fieldConf']['label']); $defInfo = array(); if (!$flexFormNoEditDefaultLanguage) { $previewLanguages = $this->globalOptions['additionalPreviewLanguages']; foreach ($previewLanguages as $previewLanguage) { $defInfo[] = '<div class="t3-form-original-language">'; $defInfo[] = FormEngineUtility::getLanguageIcon($table, $row, 'v' . $previewLanguage['ISOcode']); $defInfo[] = $this->previewFieldValue($flexFormRowData[$flexFormFieldName]['v' . $previewLanguage['ISOcode']], $fakeParameterArray['fieldConf'], $fieldName); $defInfo[] = '</div>'; } } $languageIcon = ''; if ($vDEFkey !== 'vDEF') { $languageIcon = FormEngineUtility::getLanguageIcon($table, $row, $vDEFkey); } // Possible line breaks in the label through xml: \n => <br/>, usage of nl2br() not possible, so it's done through str_replace (?!) $processedTitle = str_replace('\\n', '<br />', $theTitle); // @todo: Similar to the processing within SingleElementContainer ... use it from there?! $html = array(); $html[] = '<div class="form-section">'; $html[] = '<div class="form-group t3js-formengine-palette-field t3js-formengine-validation-marker">'; $html[] = '<label class="t3js-formengine-label">'; $html[] = $languageIcon; $html[] = BackendUtility::wrapInHelp($parameterArray['_cshKey'], $flexFormFieldName, $processedTitle); $html[] = '</label>'; $html[] = '<div class="t3js-formengine-field-item">'; $html[] = $childResult['html']; $html[] = implode(LF, $defInfo); $html[] = $this->renderVDEFDiff($flexFormRowData[$flexFormFieldName], $vDEFkey); $html[] = '</div>'; $html[] = '</div>'; $html[] = '</div>'; $resultArray['html'] .= implode(LF, $html); $childResult['html'] = ''; $resultArray = $this->mergeChildReturnIntoExistingResult($resultArray, $childResult); } } return $resultArray; }
/** * Wrap a single element * * @param array $element Given element as documented above * @param array $additionalPaletteClasses Additional classes to be added to HTML * @return string Wrapped element */ protected function wrapSingleFieldContentWithLabelAndOuterDiv(array $element, array $additionalPaletteClasses = array()) { $fieldName = $element['fieldName']; $paletteFieldClasses = array('form-group', 't3js-formengine-validation-marker', 't3js-formengine-palette-field'); foreach ($additionalPaletteClasses as $class) { $paletteFieldClasses[] = $class; } $label = BackendUtility::wrapInHelp($this->data['tableName'], $fieldName, htmlspecialchars($element['fieldLabel'])); $content = array(); $content[] = '<div class="' . implode(' ', $paletteFieldClasses) . '">'; $content[] = '<label class="t3js-formengine-label">'; $content[] = $label; $content[] = '</label>'; $content[] = $element['fieldHtml']; $content[] = '</div>'; return implode(LF, $content); }
/** * Create a regular new element (pages and records) * * @return void * @todo Define visibility */ public function regularNew() { $doNotShowFullDescr = FALSE; // Initialize array for accumulating table rows: $this->tRows = array(); // tree images $halfLine = '<img' . \TYPO3\CMS\Backend\Utility\IconUtility::skinImg($this->doc->backPath, 'gfx/ol/halfline.gif', 'width="18" height="8"') . ' alt="" />'; $firstLevel = '<img' . \TYPO3\CMS\Backend\Utility\IconUtility::skinImg($this->doc->backPath, 'gfx/ol/join.gif', 'width="18" height="16"') . ' alt="" />'; $secondLevel = '<img' . \TYPO3\CMS\Backend\Utility\IconUtility::skinImg($this->doc->backPath, 'gfx/ol/line.gif', 'width="18" height="16"') . ' alt="" /> <img' . \TYPO3\CMS\Backend\Utility\IconUtility::skinImg($this->doc->backPath, 'gfx/ol/join.gif', 'width="18" height="16"') . ' alt="" />'; $secondLevelLast = '<img' . \TYPO3\CMS\Backend\Utility\IconUtility::skinImg($this->doc->backPath, 'gfx/ol/line.gif', 'width="18" height="16"') . ' alt="" /> <img' . \TYPO3\CMS\Backend\Utility\IconUtility::skinImg($this->doc->backPath, 'gfx/ol/joinbottom.gif', 'width="18" height="16"') . ' alt="" />'; // Get TSconfig for current page $pageTS = \TYPO3\CMS\Backend\Utility\BackendUtility::getPagesTSconfig($this->id); // Finish initializing new pages options with TSconfig // Each new page option may be hidden by TSconfig // Enabled option for the position of a new page $this->newPagesSelectPosition = !empty($pageTS['mod.']['wizards.']['newRecord.']['pages.']['show.']['pageSelectPosition']); // Pseudo-boolean (0/1) for backward compatibility $this->newPagesInto = !empty($pageTS['mod.']['wizards.']['newRecord.']['pages.']['show.']['pageInside']) ? 1 : 0; $this->newPagesAfter = !empty($pageTS['mod.']['wizards.']['newRecord.']['pages.']['show.']['pageAfter']) ? 1 : 0; // Slight spacer from header: $this->code .= $halfLine; // New Page $table = 'pages'; $v = $GLOBALS['TCA'][$table]; $pageIcon = \TYPO3\CMS\Backend\Utility\IconUtility::getSpriteIconForRecord($table, array()); $newPageIcon = \TYPO3\CMS\Backend\Utility\IconUtility::getSpriteIcon('actions-page-new'); $rowContent = ''; // New pages INSIDE this pages $newPageLinks = array(); if ($this->newPagesInto && $this->isTableAllowedForThisPage($this->pageinfo, 'pages') && $GLOBALS['BE_USER']->check('tables_modify', 'pages') && $GLOBALS['BE_USER']->workspaceCreateNewRecord($this->pageinfo['_ORIG_uid'] ? $this->pageinfo['_ORIG_uid'] : $this->id, 'pages')) { // Create link to new page inside: $newPageLinks[] = $this->linkWrap(\TYPO3\CMS\Backend\Utility\IconUtility::getSpriteIconForRecord($table, array()) . $GLOBALS['LANG']->sL($v['ctrl']['title'], 1) . ' (' . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:db_new.php.inside', 1) . ')', $table, $this->id); } // New pages AFTER this pages if ($this->newPagesAfter && $this->isTableAllowedForThisPage($this->pidInfo, 'pages') && $GLOBALS['BE_USER']->check('tables_modify', 'pages') && $GLOBALS['BE_USER']->workspaceCreateNewRecord($this->pidInfo['uid'], 'pages')) { $newPageLinks[] = $this->linkWrap($pageIcon . $GLOBALS['LANG']->sL($v['ctrl']['title'], 1) . ' (' . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:db_new.php.after', 1) . ')', 'pages', -$this->id); } // New pages at selection position if ($this->newPagesSelectPosition) { // Link to page-wizard: $newPageLinks[] = '<a href="' . htmlspecialchars(\TYPO3\CMS\Core\Utility\GeneralUtility::linkThisScript(array('pagesOnly' => 1))) . '">' . $pageIcon . htmlspecialchars($GLOBALS['LANG']->getLL('pageSelectPosition')) . '</a>'; } // Assemble all new page links $numPageLinks = count($newPageLinks); for ($i = 0; $i < $numPageLinks; $i++) { // For the last link, use the "branch bottom" icon if ($i == $numPageLinks - 1) { $treeComponent = $secondLevelLast; } else { $treeComponent = $secondLevel; } $rowContent .= '<br />' . $treeComponent . $newPageLinks[$i]; } // Add row header and half-line if not empty if (!empty($rowContent)) { $rowContent .= '<br />' . $halfLine; $rowContent = $firstLevel . $newPageIcon . ' <strong>' . $GLOBALS['LANG']->getLL('createNewPage') . '</strong>' . $rowContent; } // Compile table row to show the icon for "new page (select position)" $startRows = array(); if ($this->showNewRecLink('pages') && !empty($rowContent)) { $startRows[] = ' <tr> <td nowrap="nowrap">' . $rowContent . '</td> <td>' . \TYPO3\CMS\Backend\Utility\BackendUtility::wrapInHelp($table, '') . '</td> </tr> '; } // New tables (but not pages) INSIDE this pages $isAdmin = $GLOBALS['BE_USER']->isAdmin(); $newContentIcon = \TYPO3\CMS\Backend\Utility\IconUtility::getSpriteIcon('actions-document-new'); if ($this->newContentInto) { if (is_array($GLOBALS['TCA'])) { $groupName = ''; foreach ($GLOBALS['TCA'] as $table => $v) { $count = count($GLOBALS['TCA'][$table]); $counter = 1; if ($table != 'pages' && $this->showNewRecLink($table) && $this->isTableAllowedForThisPage($this->pageinfo, $table) && $GLOBALS['BE_USER']->check('tables_modify', $table) && (($v['ctrl']['rootLevel'] xor $this->id) || $v['ctrl']['rootLevel'] == -1) && $GLOBALS['BE_USER']->workspaceCreateNewRecord($this->pageinfo['_ORIG_uid'] ? $this->pageinfo['_ORIG_uid'] : $this->id, $table)) { $newRecordIcon = \TYPO3\CMS\Backend\Utility\IconUtility::getSpriteIconForRecord($table, array()); $rowContent = ''; // Create new link for record: $newLink = $this->linkWrap($newRecordIcon . $GLOBALS['LANG']->sL($v['ctrl']['title'], 1), $table, $this->id); // If the table is 'tt_content' (from "cms" extension), create link to wizard if ($table == 'tt_content') { $groupName = $GLOBALS['LANG']->getLL('createNewContent'); $rowContent = $firstLevel . $newContentIcon . ' <strong>' . $GLOBALS['LANG']->getLL('createNewContent') . '</strong>'; // If mod.web_list.newContentWiz.overrideWithExtension is set, use that extension's wizard instead: $overrideExt = $this->web_list_modTSconfig['properties']['newContentWiz.']['overrideWithExtension']; $pathToWizard = \TYPO3\CMS\Core\Extension\ExtensionManager::isLoaded($overrideExt) ? \TYPO3\CMS\Core\Extension\ExtensionManager::extRelPath($overrideExt) . 'mod1/db_new_content_el.php' : 'sysext/cms/layout/db_new_content_el.php'; $href = $pathToWizard . '?id=' . $this->id . '&returnUrl=' . rawurlencode(\TYPO3\CMS\Core\Utility\GeneralUtility::getIndpEnv('REQUEST_URI')); $rowContent .= '<br />' . $secondLevel . $newLink . '<br />' . $secondLevelLast . '<a href="' . htmlspecialchars($href) . '">' . $newContentIcon . htmlspecialchars($GLOBALS['LANG']->getLL('clickForWizard')) . '</a>'; // Half-line added: $rowContent .= '<br />' . $halfLine; } else { // Get the title if ($v['ctrl']['readOnly'] || $v['ctrl']['hideTable'] || $v['ctrl']['is_static']) { continue; } if ($v['ctrl']['adminOnly'] && !$isAdmin) { continue; } $nameParts = explode('_', $table); $thisTitle = ''; if ($nameParts[0] == 'tx' || $nameParts[0] == 'tt') { // Try to extract extension name if (substr($v['ctrl']['title'], 0, 8) == 'LLL:EXT:') { $_EXTKEY = substr($v['ctrl']['title'], 8); $_EXTKEY = substr($_EXTKEY, 0, strpos($_EXTKEY, '/')); if ($_EXTKEY != '') { // First try to get localisation of extension title $temp = explode(':', substr($v['ctrl']['title'], 9 + strlen($_EXTKEY))); $langFile = $temp[0]; $thisTitle = $GLOBALS['LANG']->sL('LLL:EXT:' . $_EXTKEY . '/' . $langFile . ':extension.title'); // If no localisation available, read title from ext_emconf.php if (!$thisTitle && is_file(\TYPO3\CMS\Core\Extension\ExtensionManager::extPath($_EXTKEY) . 'ext_emconf.php')) { include \TYPO3\CMS\Core\Extension\ExtensionManager::extPath($_EXTKEY) . 'ext_emconf.php'; $thisTitle = $EM_CONF[$_EXTKEY]['title']; } $iconFile[$_EXTKEY] = '<img ' . 'src="' . \TYPO3\CMS\Core\Extension\ExtensionManager::extRelPath($_EXTKEY) . $GLOBALS['TYPO3_LOADED_EXT'][$_EXTKEY]['ext_icon'] . '" ' . 'width="16" height="16" ' . 'alt="' . $thisTitle . '" />'; } else { $thisTitle = $nameParts[1]; $iconFile[$_EXTKEY] = ''; } } else { $thisTitle = $nameParts[1]; $iconFile[$_EXTKEY] = ''; } } else { $_EXTKEY = 'system'; $thisTitle = $GLOBALS['LANG']->getLL('system_records'); $iconFile['system'] = \TYPO3\CMS\Backend\Utility\IconUtility::getSpriteIcon('apps-pagetree-root'); } if ($groupName == '' || $groupName != $_EXTKEY) { $groupName = empty($v['ctrl']['groupName']) ? $_EXTKEY : $v['ctrl']['groupName']; } $rowContent .= $newLink; $counter++; } // Compile table row: if ($table == 'tt_content') { $startRows[] = ' <tr> <td nowrap="nowrap">' . $rowContent . '</td> <td>' . \TYPO3\CMS\Backend\Utility\BackendUtility::wrapInHelp($table, '') . '</td> </tr>'; } else { $this->tRows[$groupName]['title'] = $thisTitle; $this->tRows[$groupName]['html'][] = $rowContent; $this->tRows[$groupName]['table'][] = $table; } } } } } // User sort if (isset($pageTS['mod.']['wizards.']['newRecord.']['order'])) { $this->newRecordSortList = \TYPO3\CMS\Core\Utility\GeneralUtility::trimExplode(',', $pageTS['mod.']['wizards.']['newRecord.']['order'], TRUE); } uksort($this->tRows, array($this, 'sortNewRecordsByConfig')); // Compile table row: $finalRows = array(); $finalRows[] = implode('', $startRows); foreach ($this->tRows as $key => $value) { $row = '<tr> <td nowrap="nowrap">' . $halfLine . '<br />' . $firstLevel . '' . $iconFile[$key] . ' <strong>' . $value['title'] . '</strong>' . '</td><td> <br />' . \TYPO3\CMS\Backend\Utility\BackendUtility::wrapInHelp($key, '') . '</td> </tr>'; $count = count($value['html']) - 1; foreach ($value['html'] as $recordKey => $record) { $row .= ' <tr> <td nowrap="nowrap">' . ($recordKey < $count ? $secondLevel : $secondLevelLast) . $record . '</td> <td>' . \TYPO3\CMS\Backend\Utility\BackendUtility::wrapInHelp($value['table'][$recordKey], '') . '</td> </tr>'; } $finalRows[] = $row; } // end of tree $finalRows[] = ' <tr> <td><img' . \TYPO3\CMS\Backend\Utility\IconUtility::skinImg($this->doc->backPath, 'gfx/ol/stopper.gif', 'width="18" height="16"') . ' alt="" /></td> <td></td> </tr> '; // Make table: $this->code .= ' <table border="0" cellpadding="0" cellspacing="0" id="typo3-newRecord"> ' . implode('', $finalRows) . ' </table> '; }
/** * Render additional information fields within the scheduler backend. * * @param array $taskInfo Array information of task to return * @param ValidatorTask $task Task object * @param \TYPO3\CMS\Scheduler\Controller\SchedulerModuleController $schedulerModule Reference to the BE module of the Scheduler * @return array Additional fields * @see \TYPO3\CMS\Scheduler\AdditionalFieldProviderInterface->getAdditionalFields($taskInfo, $task, $schedulerModule) */ public function getAdditionalFields(array &$taskInfo, $task, \TYPO3\CMS\Scheduler\Controller\SchedulerModuleController $schedulerModule) { $additionalFields = array(); if (empty($taskInfo['configuration'])) { if ($schedulerModule->CMD == 'add') { $taskInfo['configuration'] = ''; } elseif ($schedulerModule->CMD == 'edit') { $taskInfo['configuration'] = $task->getConfiguration(); } else { $taskInfo['configuration'] = $task->getConfiguration(); } } if (empty($taskInfo['depth'])) { if ($schedulerModule->CMD == 'add') { $taskInfo['depth'] = array(); } elseif ($schedulerModule->CMD == 'edit') { $taskInfo['depth'] = $task->getDepth(); } else { $taskInfo['depth'] = $task->getDepth(); } } if (empty($taskInfo['page'])) { if ($schedulerModule->CMD == 'add') { $taskInfo['page'] = ''; } elseif ($schedulerModule->CMD == 'edit') { $taskInfo['page'] = $task->getPage(); } else { $taskInfo['page'] = $task->getPage(); } } if (empty($taskInfo['email'])) { if ($schedulerModule->CMD == 'add') { $taskInfo['email'] = ''; } elseif ($schedulerModule->CMD == 'edit') { $taskInfo['email'] = $task->getEmail(); } else { $taskInfo['email'] = $task->getEmail(); } } if (empty($taskInfo['emailOnBrokenLinkOnly'])) { if ($schedulerModule->CMD == 'add') { $taskInfo['emailOnBrokenLinkOnly'] = 1; } elseif ($schedulerModule->CMD == 'edit') { $taskInfo['emailOnBrokenLinkOnly'] = $task->getEmailOnBrokenLinkOnly(); } else { $taskInfo['emailOnBrokenLinkOnly'] = $task->getEmailOnBrokenLinkOnly(); } } if (empty($taskInfo['emailTemplateFile'])) { if ($schedulerModule->CMD == 'add') { $taskInfo['emailTemplateFile'] = 'EXT:linkvalidator/Resources/Private/Templates/mailtemplate.html'; } elseif ($schedulerModule->CMD == 'edit') { $taskInfo['emailTemplateFile'] = $task->getEmailTemplateFile(); } else { $taskInfo['emailTemplateFile'] = $task->getEmailTemplateFile(); } } $fieldId = 'task_page'; $fieldCode = '<input type="text" name="tx_scheduler[linkvalidator][page]" id="' . $fieldId . '" value="' . htmlspecialchars($taskInfo['page']) . '"/>'; $label = $GLOBALS['LANG']->sL('LLL:EXT:linkvalidator/Resources/Private/Language/locallang.xlf:tasks.validate.page'); $label = BackendUtility::wrapInHelp('linkvalidator', $fieldId, $label); $additionalFields[$fieldId] = array('code' => $fieldCode, 'label' => $label); // input for depth $fieldId = 'task_depth'; $fieldValueArray = array('0' => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:labels.depth_0'), '1' => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:labels.depth_1'), '2' => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:labels.depth_2'), '3' => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:labels.depth_3'), '4' => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:labels.depth_4'), '999' => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:labels.depth_infi')); $fieldCode = '<select name="tx_scheduler[linkvalidator][depth]" id="' . $fieldId . '">'; foreach ($fieldValueArray as $depth => $label) { $fieldCode .= "\t" . '<option value="' . htmlspecialchars($depth) . '"' . ($depth == $taskInfo['depth'] ? ' selected="selected"' : '') . '>' . $label . '</option>'; } $fieldCode .= '</select>'; $label = $GLOBALS['LANG']->sL('LLL:EXT:linkvalidator/Resources/Private/Language/locallang.xlf:tasks.validate.depth'); $label = BackendUtility::wrapInHelp('linkvalidator', $fieldId, $label); $additionalFields[$fieldId] = array('code' => $fieldCode, 'label' => $label); $fieldId = 'task_configuration'; $fieldCode = '<textarea name="tx_scheduler[linkvalidator][configuration]" id="' . $fieldId . '" >' . htmlspecialchars($taskInfo['configuration']) . '</textarea>'; $label = $GLOBALS['LANG']->sL('LLL:EXT:linkvalidator/Resources/Private/Language/locallang.xlf:tasks.validate.conf'); $label = BackendUtility::wrapInHelp('linkvalidator', $fieldId, $label); $additionalFields[$fieldId] = array('code' => $fieldCode, 'label' => $label); $fieldId = 'task_email'; $fieldCode = '<input type="text" name="tx_scheduler[linkvalidator][email]" id="' . $fieldId . '" value="' . htmlspecialchars($taskInfo['email']) . '" />'; $label = $GLOBALS['LANG']->sL('LLL:EXT:linkvalidator/Resources/Private/Language/locallang.xlf:tasks.validate.email'); $label = BackendUtility::wrapInHelp('linkvalidator', $fieldId, $label); $additionalFields[$fieldId] = array('code' => $fieldCode, 'label' => $label); $fieldId = 'task_emailOnBrokenLinkOnly'; $fieldCode = '<input type="checkbox" name="tx_scheduler[linkvalidator][emailOnBrokenLinkOnly]" id="' . $fieldId . '" ' . (htmlspecialchars($taskInfo['emailOnBrokenLinkOnly']) ? 'checked="checked"' : '') . ' />'; $label = $GLOBALS['LANG']->sL('LLL:EXT:linkvalidator/Resources/Private/Language/locallang.xlf:tasks.validate.emailOnBrokenLinkOnly'); $label = BackendUtility::wrapInHelp('linkvalidator', $fieldId, $label); $additionalFields[$fieldId] = array('code' => $fieldCode, 'label' => $label); $fieldId = 'task_emailTemplateFile'; $fieldCode = '<input type="text" name="tx_scheduler[linkvalidator][emailTemplateFile]" id="' . $fieldId . '" value="' . htmlspecialchars($taskInfo['emailTemplateFile']) . '" />'; $label = $GLOBALS['LANG']->sL('LLL:EXT:linkvalidator/Resources/Private/Language/locallang.xlf:tasks.validate.emailTemplateFile'); $label = BackendUtility::wrapInHelp('linkvalidator', $fieldId, $label); $additionalFields[$fieldId] = array('code' => $fieldCode, 'label' => $label); return $additionalFields; }
/** * Render check boxes * * @return array As defined in initializeResultArray() of AbstractNode */ public function render() { $html = []; // Field configuration from TCA: $parameterArray = $this->data['parameterArray']; $config = $parameterArray['fieldConf']['config']; $disabled = !empty($config['readOnly']); $selItems = $config['items']; if (!empty($selItems)) { // Get values in an array (and make unique, which is fine because there can be no duplicates anyway): $itemArray = array_flip($parameterArray['itemFormElValue']); // Traverse the Array of selector box items: $groups = array(); $currentGroup = 0; $c = 0; $sOnChange = ''; if (!$disabled) { $sOnChange = implode('', $parameterArray['fieldChangeFunc']); // Used to accumulate the JS needed to restore the original selection. foreach ($selItems as $p) { // Non-selectable element: if ($p[1] === '--div--') { $selIcon = ''; if (isset($p[2]) && $p[2] != 'empty-empty') { $selIcon = FormEngineUtility::getIconHtml($p[2]); } $currentGroup++; $groups[$currentGroup]['header'] = array('icon' => $selIcon, 'title' => htmlspecialchars($p[0])); } else { // Check if some help text is available // Since TYPO3 4.5 help text is expected to be an associative array // with two key, "title" and "description" // For the sake of backwards compatibility, we test if the help text // is a string and use it as a description (this could happen if items // are modified with an itemProcFunc) $hasHelp = false; $help = ''; $helpArray = array(); if (!empty($p[3])) { $hasHelp = true; if (is_array($p[3])) { $helpArray = $p[3]; } else { $helpArray['description'] = $p[3]; } } if ($hasHelp) { $help = BackendUtility::wrapInHelp('', '', '', $helpArray); } // Selected or not by default: $checked = 0; if (isset($itemArray[$p[1]])) { $checked = 1; unset($itemArray[$p[1]]); } // Build item array $groups[$currentGroup]['items'][] = array('id' => StringUtility::getUniqueId('select_checkbox_row_'), 'name' => $parameterArray['itemFormElName'] . '[' . $c . ']', 'value' => $p[1], 'checked' => $checked, 'disabled' => false, 'class' => '', 'icon' => !empty($p[2]) ? FormEngineUtility::getIconHtml($p[2]) : $this->iconFactory->getIcon('empty-empty', Icon::SIZE_SMALL)->render(), 'title' => htmlspecialchars($p[0], ENT_COMPAT, 'UTF-8', false), 'help' => $help); $c++; } } } // Add an empty hidden field which will send a blank value if all items are unselected. $html[] = '<input type="hidden" class="select-checkbox" name="' . htmlspecialchars($parameterArray['itemFormElName']) . '" value="">'; // Building the checkboxes foreach ($groups as $groupKey => $group) { $groupId = htmlspecialchars($parameterArray['itemFormElID']) . '-group-' . $groupKey; $html[] = '<div class="panel panel-default">'; if (is_array($group['header'])) { $html[] = '<div class="panel-heading">'; $html[] = '<a data-toggle="collapse" href="#' . $groupId . '" aria-expanded="false" aria-controls="' . $groupId . '">'; $html[] = $group['header']['icon']; $html[] = $group['header']['title']; $html[] = '</a>'; $html[] = '</div>'; } if (is_array($group['items']) && !empty($group['items'])) { $tableRows = []; $checkGroup = array(); $uncheckGroup = array(); $resetGroup = array(); // Render rows foreach ($group['items'] as $item) { $tableRows[] = '<tr class="' . $item['class'] . '">'; $tableRows[] = '<td class="col-checkbox">'; $tableRows[] = '<input type="checkbox" ' . 'id="' . $item['id'] . '" ' . 'name="' . htmlspecialchars($item['name']) . '" ' . 'value="' . htmlspecialchars($item['value']) . '" ' . 'onclick="' . htmlspecialchars($sOnChange) . '" ' . ($item['checked'] ? 'checked=checked ' : '') . ($item['disabled'] ? 'disabled=disabled ' : '') . $parameterArray['onFocus'] . '>'; $tableRows[] = '</td>'; $tableRows[] = '<td class="col-icon">'; $tableRows[] = '<label class="label-block" for="' . $item['id'] . '">' . $item['icon'] . '</label>'; $tableRows[] = '</td>'; $tableRows[] = '<td class="col-title">'; $tableRows[] = '<label class="label-block" for="' . $item['id'] . '">' . $item['title'] . '</label>'; $tableRows[] = '</td>'; $tableRows[] = '<td>' . $item['help'] . '</td>'; $tableRows[] = '</tr>'; $checkGroup[] = 'document.editform[' . GeneralUtility::quoteJSvalue($item['name']) . '].checked=1;'; $uncheckGroup[] = 'document.editform[' . GeneralUtility::quoteJSvalue($item['name']) . '].checked=0;'; $resetGroup[] = 'document.editform[' . GeneralUtility::quoteJSvalue($item['name']) . '].checked=' . $item['checked'] . ';'; } // Build toggle group checkbox $toggleGroupCheckbox = ''; if (!empty($resetGroup)) { $toggleGroupCheckbox = '<input type="checkbox" ' . 'class="checkbox" ' . 'onclick="if (checked) {' . htmlspecialchars(implode('', $checkGroup) . '} else {' . implode('', $uncheckGroup)) . '}">'; } // Build reset group button $resetGroupBtn = ''; if (!empty($resetGroup)) { $title = $this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:labels.revertSelection', true); $resetGroupBtn = '<a href="#" ' . 'class="btn btn-default" ' . 'onclick="' . implode('', $resetGroup) . ' return false;" ' . 'title="' . $title . '">' . $this->iconFactory->getIcon('actions-edit-undo', Icon::SIZE_SMALL)->render() . ' ' . $this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:labels.revertSelection') . '</a>'; } if (is_array($group['header'])) { $html[] = '<div id="' . $groupId . '" class="panel-collapse collapse" role="tabpanel">'; } $html[] = '<div class="table-fit">'; $html[] = '<table class="table table-transparent table-hover">'; $html[] = '<thead>'; $html[] = '<tr>'; $html[] = '<th class="col-checkbox">' . $toggleGroupCheckbox . '</th>'; $html[] = '<th class="col-icon"></th>'; $html[] = '<th class="text-right" colspan="2">' . $resetGroupBtn . '</th>'; $html[] = '</tr>'; $html[] = '</thead>'; $html[] = '<tbody>' . implode(LF, $tableRows) . '</tbody>'; $html[] = '</table>'; $html[] = '</div>'; if (is_array($group['header'])) { $html[] = '</div>'; } } $html[] = '</div>'; } } if (!$disabled) { $html = $this->renderWizards(array(implode(LF, $html)), $config['wizards'], $this->data['tableName'], $this->data['databaseRow'], $this->data['fieldName'], $parameterArray, $parameterArray['itemFormElName'], BackendUtility::getSpecConfParts($parameterArray['fieldConf']['defaultExtras'])); } $resultArray = $this->initializeResultArray(); $resultArray['html'] = $html; return $resultArray; }
/** * Creates a checkbox list (renderMode = "checkbox") * * @param string $table See getSingleField_typeSelect() * @param string $field See getSingleField_typeSelect() * @param array $row See getSingleField_typeSelect() * @param array $parameterArray See getSingleField_typeSelect() * @param array $config (Redundant) content of $PA['fieldConf']['config'] (for convenience) * @param array $selItems Items available for selection * @param string $noMatchingLabel Label for no-matching-value * @return string The HTML code for the item */ protected function getSingleField_typeSelect_checkbox($table, $field, $row, $parameterArray, $config, $selItems, $noMatchingLabel) { if (empty($selItems)) { return ''; } // Get values in an array (and make unique, which is fine because there can be no duplicates anyway): $itemArray = array_flip(FormEngineUtility::extractValuesOnlyFromValueLabelList($parameterArray['itemFormElValue'])); $output = ''; // Disabled $disabled = 0; if ($this->isGlobalReadonly() || $config['readOnly']) { $disabled = 1; } // Traverse the Array of selector box items: $groups = array(); $currentGroup = 0; $c = 0; $sOnChange = ''; if (!$disabled) { $sOnChange = implode('', $parameterArray['fieldChangeFunc']); // Used to accumulate the JS needed to restore the original selection. foreach ($selItems as $p) { // Non-selectable element: if ($p[1] === '--div--') { $selIcon = ''; if (isset($p[2]) && $p[2] != 'empty-empty') { $selIcon = FormEngineUtility::getIconHtml($p[2]); } $currentGroup++; $groups[$currentGroup]['header'] = array('icon' => $selIcon, 'title' => htmlspecialchars($p[0])); } else { // Check if some help text is available // Since TYPO3 4.5 help text is expected to be an associative array // with two key, "title" and "description" // For the sake of backwards compatibility, we test if the help text // is a string and use it as a description (this could happen if items // are modified with an itemProcFunc) $hasHelp = FALSE; $help = ''; $helpArray = array(); if (!empty($p[3])) { $hasHelp = TRUE; if (is_array($p[3])) { $helpArray = $p[3]; } else { $helpArray['description'] = $p[3]; } } if ($hasHelp) { $help = BackendUtility::wrapInHelp('', '', '', $helpArray); } // Selected or not by default: $checked = 0; if (isset($itemArray[$p[1]])) { $checked = 1; unset($itemArray[$p[1]]); } // Build item array $groups[$currentGroup]['items'][] = array('id' => str_replace('.', '', uniqid('select_checkbox_row_', TRUE)), 'name' => $parameterArray['itemFormElName'] . '[' . $c . ']', 'value' => $p[1], 'checked' => $checked, 'disabled' => $disabled, 'class' => '', 'icon' => !empty($p[2]) ? FormEngineUtility::getIconHtml($p[2]) : IconUtility::getSpriteIcon('empty-empty'), 'title' => htmlspecialchars($p[0], ENT_COMPAT, 'UTF-8', FALSE), 'help' => $help); $c++; } } } // Remaining values (invalid): if (!empty($itemArray) && !$parameterArray['fieldTSConfig']['disableNoMatchingValueElement'] && !$config['disableNoMatchingValueElement']) { $currentGroup++; foreach ($itemArray as $theNoMatchValue => $temp) { // Build item array $groups[$currentGroup]['items'][] = array('id' => str_replace('.', '', uniqid('select_checkbox_row_', TRUE)), 'name' => $parameterArray['itemFormElName'] . '[' . $c . ']', 'value' => $theNoMatchValue, 'checked' => 1, 'disabled' => $disabled, 'class' => 'danger', 'icon' => '', 'title' => htmlspecialchars(@sprintf($noMatchingLabel, $theNoMatchValue), ENT_COMPAT, 'UTF-8', FALSE), 'help' => ''); $c++; } } // Add an empty hidden field which will send a blank value if all items are unselected. $output .= '<input type="hidden" class="select-checkbox" name="' . htmlspecialchars($parameterArray['itemFormElName']) . '" value="" />'; // Building the checkboxes foreach ($groups as $groupKey => $group) { $groupId = htmlspecialchars($parameterArray['itemFormElID']) . '-group-' . $groupKey; $output .= '<div class="panel panel-default">'; if (is_array($group['header'])) { $output .= ' <div class="panel-heading"> <a data-toggle="collapse" href="#' . $groupId . '" aria-expanded="true" aria-controls="' . $groupId . '"> ' . $group['header']['icon'] . ' ' . $group['header']['title'] . ' </a> </div> '; } if (is_array($group['items']) && !empty($group['items'])) { $tableRows = ''; $checkGroup = array(); $uncheckGroup = array(); $resetGroup = array(); // Render rows foreach ($group['items'] as $item) { $tableRows .= ' <tr class="' . $item['class'] . '"> <td class="col-checkbox"> <input type="checkbox" id="' . $item['id'] . '" name="' . htmlspecialchars($item['name']) . '" value="' . htmlspecialchars($item['value']) . '" onclick="' . htmlspecialchars($sOnChange) . '" ' . ($item['checked'] ? ' checked=checked' : '') . ' ' . ($item['disabled'] ? ' disabled=disabled' : '') . ' ' . $parameterArray['onFocus'] . ' /> </td> <td class="col-icon"> <label class="label-block" for="' . $item['id'] . '">' . $item['icon'] . '</label> </td> <td class="col-title"> <label class="label-block" for="' . $item['id'] . '">' . $item['title'] . '</label> </td> <td>' . $item['help'] . '</td> </tr> '; $checkGroup[] = 'document.editform[' . GeneralUtility::quoteJSvalue($item['name']) . '].checked=1;'; $uncheckGroup[] = 'document.editform[' . GeneralUtility::quoteJSvalue($item['name']) . '].checked=0;'; $resetGroup[] = 'document.editform[' . GeneralUtility::quoteJSvalue($item['name']) . '].checked=' . $item['checked'] . ';'; } // Build toggle group checkbox $toggleGroupCheckbox = ''; if (!empty($resetGroup)) { $toggleGroupCheckbox = ' <input type="checkbox" class="checkbox" onclick="if (checked) {' . htmlspecialchars(implode('', $checkGroup) . '} else {' . implode('', $uncheckGroup)) . '}"> '; } // Build reset group button $resetGroupBtn = ''; if (!empty($resetGroup)) { $resetGroupBtn = ' <a href="#" class="btn btn-default" onclick="' . implode('', $resetGroup) . ' return false;' . '"> ' . IconUtility::getSpriteIcon('actions-edit-undo', array('title' => htmlspecialchars($this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:labels.revertSelection')))) . ' ' . $this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:labels.revertSelection') . ' </a> '; } $output .= ' <div id="' . $groupId . '" class="panel-collapse collapse in" role="tabpanel"> <div class="table-fit"> <table class="table table-transparent table-hover"> <thead> <tr> <th class="col-checkbox">' . $toggleGroupCheckbox . '</th> <th class="col-icon"></th> <th class="text-right" colspan="2">' . $resetGroupBtn . '</th> </tr> </thead> <tbody>' . $tableRows . '</tbody> </table> </div> </div> '; } $output .= '</div>'; } return $output; }
/** * Entry method * * @return array As defined in initializeResultArray() of AbstractNode */ public function render() { $table = $this->data['tableName']; $row = $this->data['databaseRow']; $flexFormDataStructureArray = $this->data['flexFormDataStructureArray']; $flexFormRowData = $this->data['flexFormRowData']; $flexFormFormPrefix = $this->data['flexFormFormPrefix']; $parameterArray = $this->data['parameterArray']; $metaData = $this->data['parameterArray']['fieldConf']['config']['ds']['meta']; $languageService = $this->getLanguageService(); /** @var IconFactory $iconFactory */ $iconFactory = GeneralUtility::makeInstance(IconFactory::class); $resultArray = $this->initializeResultArray(); foreach ($flexFormDataStructureArray as $flexFormFieldName => $flexFormFieldArray) { if (!is_array($flexFormFieldArray) || !isset($flexFormFieldArray['type']) && !is_array($flexFormFieldArray['config'])) { continue; } if ($flexFormFieldArray['type'] === 'array') { // Section if (empty($flexFormFieldArray['section'])) { $resultArray['html'] = LF . 'Section expected at ' . $flexFormFieldName . ' but not found'; continue; } $sectionTitle = ''; if (!empty($flexFormFieldArray['title'])) { $sectionTitle = $languageService->sL($flexFormFieldArray['title']); } $options = $this->data; $options['flexFormDataStructureArray'] = $flexFormFieldArray['el']; $options['flexFormRowData'] = is_array($flexFormRowData[$flexFormFieldName]['el']) ? $flexFormRowData[$flexFormFieldName]['el'] : array(); $options['flexFormSectionType'] = $flexFormFieldName; $options['flexFormSectionTitle'] = $sectionTitle; $options['renderType'] = 'flexFormSectionContainer'; $sectionContainerResult = $this->nodeFactory->create($options)->render(); $resultArray = $this->mergeChildReturnIntoExistingResult($resultArray, $sectionContainerResult); } else { if (is_array($metaData) && isset($metaData['langChildren']) && isset($metaData['languagesOnElement'])) { $lkeys = $metaData['languagesOnElement']; array_walk($lkeys, function (&$value) { $value = 'v' . $value; }); } else { $lkeys = array('vDEF'); } $html = array(); foreach ($lkeys as $lkey) { // Set up options for single element $fakeParameterArray = array('fieldConf' => array('label' => $languageService->sL(trim($flexFormFieldArray['label'])), 'config' => $flexFormFieldArray['config'], 'defaultExtras' => $flexFormFieldArray['defaultExtras'], 'onChange' => $flexFormFieldArray['onChange'])); $alertMsgOnChange = ''; if ($fakeParameterArray['fieldConf']['onChange'] === 'reload' || !empty($GLOBALS['TCA'][$table]['ctrl']['type']) && $GLOBALS['TCA'][$table]['ctrl']['type'] === $flexFormFieldName || !empty($GLOBALS['TCA'][$table]['ctrl']['requestUpdate']) && GeneralUtility::inList($GLOBALS['TCA'][$table]['ctrl']['requestUpdate'], $flexFormFieldName)) { if ($this->getBackendUserAuthentication()->jsConfirmation(JsConfirmation::TYPE_CHANGE)) { $alertMsgOnChange = 'top.TYPO3.Modal.confirm(TBE_EDITOR.labels.refreshRequired.title, TBE_EDITOR.labels.refreshRequired.content).on("button.clicked", function(e) { if (e.target.name == "ok" && TBE_EDITOR.checkSubmit(-1)) { TBE_EDITOR.submitForm() } top.TYPO3.Modal.dismiss(); });'; } else { $alertMsgOnChange = 'if (TBE_EDITOR.checkSubmit(-1)){ TBE_EDITOR.submitForm();}'; } } $fakeParameterArray['fieldChangeFunc'] = $parameterArray['fieldChangeFunc']; if ($alertMsgOnChange) { $fakeParameterArray['fieldChangeFunc']['alert'] = $alertMsgOnChange; } $fakeParameterArray['onFocus'] = $parameterArray['onFocus']; $fakeParameterArray['label'] = $parameterArray['label']; $fakeParameterArray['itemFormElName'] = $parameterArray['itemFormElName'] . $flexFormFormPrefix . '[' . $flexFormFieldName . '][' . $lkey . ']'; $fakeParameterArray['itemFormElID'] = $fakeParameterArray['itemFormElName']; if (isset($flexFormRowData[$flexFormFieldName][$lkey])) { $fakeParameterArray['itemFormElValue'] = $flexFormRowData[$flexFormFieldName][$lkey]; } else { $fakeParameterArray['itemFormElValue'] = $fakeParameterArray['fieldConf']['config']['default']; } $options = $this->data; $options['parameterArray'] = $fakeParameterArray; $options['elementBaseName'] = $this->data['elementBaseName'] . $flexFormFormPrefix . '[' . $flexFormFieldName . '][' . $lkey . ']'; if (!empty($flexFormFieldArray['config']['renderType'])) { $options['renderType'] = $flexFormFieldArray['config']['renderType']; } else { // Fallback to type if no renderType is given $options['renderType'] = $flexFormFieldArray['config']['type']; } $childResult = $this->nodeFactory->create($options)->render(); $theTitle = htmlspecialchars($fakeParameterArray['fieldConf']['label']); $defInfo = array(); // Possible line breaks in the label through xml: \n => <br/>, usage of nl2br() not possible, so it's done through str_replace (?!) $processedTitle = str_replace('\\n', '<br />', $theTitle); // @todo: Similar to the processing within SingleElementContainer ... use it from there?! $html[] = '<div class="form-group t3js-formengine-palette-field t3js-formengine-validation-marker">'; $html[] = '<label class="t3js-formengine-label">'; if (is_array($metaData) && isset($metaData['langChildren']) && $metaData['langChildren']) { // Find language uid of this iso code $languageUid = 0; $lKeyWithoutV = substr($lkey, 1); if ($lKeyWithoutV !== 'DEF') { foreach ($this->data['systemLanguageRows'] as $systemLanguageRow) { if ($systemLanguageRow['iso'] === $lKeyWithoutV) { $languageUid = $systemLanguageRow['uid']; break; } } } $languageIcon = $iconFactory->getIcon($this->data['systemLanguageRows'][$languageUid]['flagIconIdentifier'], Icon::SIZE_SMALL)->render(); $html[] = $languageIcon; } $html[] = BackendUtility::wrapInHelp($parameterArray['_cshKey'], $flexFormFieldName, $processedTitle); $html[] = '</label>'; $html[] = '<div class="t3js-formengine-field-item">'; $html[] = $childResult['html']; $html[] = implode(LF, $defInfo); $html[] = $this->renderVDEFDiff($flexFormRowData[$flexFormFieldName], $lkey); $html[] = '</div>'; $html[] = '</div>'; } if (!empty($html)) { $resultArray['html'] .= '<div class="form-section">' . implode(LF, $html) . '</div>'; } $childResult['html'] = ''; $resultArray = $this->mergeChildReturnIntoExistingResult($resultArray, $childResult); } } return $resultArray; }
/** * Gets the filled markers that are used in the HTML template. * * @return array The filled marker array */ protected function getTemplateMarkers() { return array('CSH' => BackendUtility::wrapInHelp('_MOD_system_txschedulerM1', ''), 'FUNC_MENU' => $this->getFunctionMenu(), 'CONTENT' => $this->content, 'TITLE' => $this->getLanguageService()->getLL('title')); }
/** * Recursive rendering of flexforms * * @param array $dataStruct (part of) Data Structure for which to render. Keys on first level is flex-form fields * @param array $editData (part of) Data array of flexform corresponding to the input DS. Keys on first level is flex-form field names * @param string $table Table name, eg. tt_content * @param string $field Field name, eg. tx_templavoila_flex * @param array $row The particular record from $table in which the field $field is found * @param array $PA Array of standard information for rendering of a form field in TCEforms, see other rendering functions too * @param string $formPrefix Form field prefix, eg. "[data][sDEF][lDEF][...][...] * @param integer $level Indicates nesting level for the function call * @param string $idPrefix Prefix for ID-values * @param boolean $toggleClosed Defines whether the next flexform level is open or closed. Comes from _TOGGLE pseudo field in FlexForm xml. * @return string HTMl code for form. * @todo Define visibility */ public function getSingleField_typeFlex_draw($dataStruct, $editData, $table, $field, $row, &$PA, $formPrefix = '', $level = 0, $idPrefix = 'ID', $toggleClosed = FALSE) { $output = ''; $mayRestructureFlexforms = $this->getBackendUserAuthentication()->checkLanguageAccess(0); // Data Structure array must be ... and array of course... if (is_array($dataStruct)) { foreach ($dataStruct as $key => $value) { // Traversing fields in structure: if (is_array($value)) { // The value of each entry must be an array. // ******************** // Making the row: // ******************** // Title of field: // <title>LLL:EXT:cms/locallang_ttc.xml:media.sources</title> $theTitle = $value['title']; // If there is a title, check for LLL label if (strlen($theTitle) > 0) { $theTitle = htmlspecialchars(GeneralUtility::fixed_lgd_cs($this->sL($theTitle), (int) $this->getBackendUserAuthentication()->uc['titleLen'])); } // If it's a "section" or "container": if ($value['type'] == 'array') { // Creating IDs for form fields: // It's important that the IDs "cascade" - otherwise we can't dynamically expand the flex form // because this relies on simple string substitution of the first parts of the id values. // This is a suffix used for forms on this level $thisId = GeneralUtility::shortMd5(uniqid('id', TRUE)); // $idPrefix is the prefix for elements on lower levels in the hierarchy and we combine this // with the thisId value to form a new ID on this level. $idTagPrefix = $idPrefix . '-' . $thisId; // If it's a "section" containing other elements: if ($value['section']) { // Load script.aculo.us if flexform sections can be moved by drag'n'drop: $this->getControllerDocumentTemplate()->getPageRenderer()->loadScriptaculous(); // Render header of section: $output .= '<div class="t3-form-field-label-flexsection"><strong>' . $theTitle . '</strong></div>'; // Render elements in data array for section: $tRows = array(); if (is_array($editData[$key]['el'])) { foreach ($editData[$key]['el'] as $k3 => $v3) { $cc = $k3; if (is_array($v3)) { $theType = key($v3); $theDat = $v3[$theType]; $newSectionEl = $value['el'][$theType]; if (is_array($newSectionEl)) { $tRows[] = $this->getSingleField_typeFlex_draw(array($theType => $newSectionEl), array($theType => $theDat), $table, $field, $row, $PA, $formPrefix . '[' . $key . '][el][' . $cc . ']', $level + 1, $idTagPrefix, $v3['_TOGGLE']); } } } } // Now, we generate "templates" for new elements that could be added to this section // by traversing all possible types of content inside the section: // We have to handle the fact that requiredElements and such may be set during this // rendering process and therefore we save and reset the state of some internal variables // ... little crude, but works... // Preserving internal variables we don't want to change: $TEMP_requiredElements = $this->requiredElements; // Traversing possible types of new content in the section: $newElementsLinks = array(); foreach ($value['el'] as $nnKey => $nCfg) { $additionalJS_post_saved = $this->additionalJS_post; $this->additionalJS_post = array(); $additionalJS_submit_saved = $this->additionalJS_submit; $this->additionalJS_submit = array(); $newElementTemplate = $this->getSingleField_typeFlex_draw(array($nnKey => $nCfg), array(), $table, $field, $row, $PA, $formPrefix . '[' . $key . '][el][' . $idTagPrefix . '-form]', $level + 1, $idTagPrefix); // Makes a "Add new" link: $var = uniqid('idvar'); $replace = 'replace(/' . $idTagPrefix . '-/g,"' . $idTagPrefix . '-"+' . $var . '+"-")'; $replace .= '.replace(/(tceforms-(datetime|date)field-)/g,"$1" + (new Date()).getTime())'; $onClickInsert = 'var ' . $var . ' = "' . 'idx"+(new Date()).getTime();' . 'new Insertion.Bottom($("' . $idTagPrefix . '"), ' . json_encode($newElementTemplate) . '.' . $replace . '); setActionStatus("' . $idTagPrefix . '");' . 'eval(unescape("' . rawurlencode(implode(';', $this->additionalJS_post)) . '").' . $replace . ');' . 'TBE_EDITOR.addActionChecks("submit", unescape("' . rawurlencode(implode(';', $this->additionalJS_submit)) . '").' . $replace . ');' . 'TYPO3.TCEFORMS.update();' . 'return false;'; // Kasper's comment (kept for history): // Maybe there is a better way to do this than store the HTML for the new element // in rawurlencoded format - maybe it even breaks with certain charsets? // But for now this works... $this->additionalJS_post = $additionalJS_post_saved; $this->additionalJS_submit = $additionalJS_submit_saved; $title = ''; if (isset($nCfg['title'])) { $title = $this->sL($nCfg['title']); } elseif (isset($nCfg['tx_templavoila']['title'])) { /* @deprecated since 4.7 will be removed two versions after 6.2 */ GeneralUtility::deprecationLog('Flexform data for table ' . $table . ', field ' . $field . 'contains the <tx_templavoila><title>... construct deprecated since TYPO3 4.7. ' . 'The <tx_templavoila> element has to be removed now. Support will be removed two versions after 6.2.'); $title = $this->sL($nCfg['tx_templavoila']['title']); } $newElementsLinks[] = '<a href="#" onclick="' . htmlspecialchars($onClickInsert) . '">' . IconUtility::getSpriteIcon('actions-document-new') . htmlspecialchars(GeneralUtility::fixed_lgd_cs($title, 30)) . '</a>'; } // Reverting internal variables we don't want to change: $this->requiredElements = $TEMP_requiredElements; // Adding the sections: $toggleAll = $this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:labels.toggleall', TRUE); $output .= ' <div class="t3-form-field-toggle-flexsection"> <a href="#" onclick="' . htmlspecialchars('flexFormToggleSubs("' . $idTagPrefix . '"); return false;') . '">' . IconUtility::getSpriteIcon('actions-move-right', array('title' => $toggleAll)) . $toggleAll . ' </a> </div> <div id="' . $idTagPrefix . '" class="t3-form-field-container-flexsection">' . implode('', $tRows) . '</div>'; $output .= $mayRestructureFlexforms ? '<div class="t3-form-field-add-flexsection"><strong>' . $this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:labels.addnew', TRUE) . ':</strong> ' . implode(' | ', $newElementsLinks) . '</div>' : ''; } else { // It is a container $toggleIcon_open = IconUtility::getSpriteIcon('actions-move-down'); $toggleIcon_close = IconUtility::getSpriteIcon('actions-move-right'); // Create on-click actions. $onClickRemove = 'if (confirm("Are you sure?")){/*###REMOVE###*/;$("' . $idTagPrefix . '").hide();setActionStatus("' . $idPrefix . '");} return false;'; $onClickToggle = 'flexFormToggle("' . $idTagPrefix . '"); return false;'; $onMove = 'flexFormSortable("' . $idPrefix . '")'; // Notice: Creating "new" elements after others seemed to be too difficult to do // and since moving new elements created in the bottom is now so easy // with drag'n'drop I didn't see the need. // Putting together header of a section. Sections can be removed, copied, opened/closed, moved up and down: // I didn't know how to make something right-aligned without a table, so I put it in a table. // can be made into <div>'s if someone like to. // Notice: The fact that I make a "Sortable.create" right onmousedown is that if we // initialize this when rendering the form in PHP new and copied elements will not // be possible to move as a sortable. But this way a new sortable is initialized every time // someone tries to move and it will always work. $ctrlHeader = ' <table class="t3-form-field-header-flexsection" onmousedown="' . ($mayRestructureFlexforms ? htmlspecialchars($onMove) : '') . '"> <tr> <td> <a href="#" onclick="' . htmlspecialchars($onClickToggle) . '" id="' . $idTagPrefix . '-toggle"> ' . ($toggleClosed ? $toggleIcon_close : $toggleIcon_open) . ' </a> <strong>' . $theTitle . '</strong> <em><span id="' . $idTagPrefix . '-preview"></span></em> </td> <td align="right">' . ($mayRestructureFlexforms ? IconUtility::getSpriteIcon('actions-move-move', array('title' => 'Drag to Move')) : '') . ($mayRestructureFlexforms ? '<a href="#" onclick="' . htmlspecialchars($onClickRemove) . '">' . IconUtility::getSpriteIcon('actions-edit-delete', array('title' => 'Delete')) : '') . '</td> </tr> </table>'; $s = GeneralUtility::revExplode('[]', $formPrefix, 2); $actionFieldName = '_ACTION_FLEX_FORM' . $PA['itemFormElName'] . $s[0] . '][_ACTION][' . $s[1]; // Push the container to DynNestedStack as it may be toggled $this->pushToDynNestedStack('flex', $idTagPrefix); // Putting together the container: $this->additionalJS_delete = array(); $singleField_typeFlex_draw = $this->getSingleField_typeFlex_draw($value['el'], $editData[$key]['el'], $table, $field, $row, $PA, $formPrefix . '[' . $key . '][el]', $level + 1, $idTagPrefix); $output .= ' <div id="' . $idTagPrefix . '" class="t3-form-field-container-flexsections"> <input id="' . $idTagPrefix . '-action" type="hidden" name="' . htmlspecialchars($actionFieldName) . '" value=""/> ' . $ctrlHeader . ' <div class="t3-form-field-record-flexsection" id="' . $idTagPrefix . '-content"' . ($toggleClosed ? ' style="display:none;"' : '') . '>' . $singleField_typeFlex_draw . ' </div> <input id="' . $idTagPrefix . '-toggleClosed" type="hidden" name="' . htmlspecialchars('data[' . $table . '][' . $row['uid'] . '][' . $field . ']' . $formPrefix . '[_TOGGLE]') . '" value="' . ($toggleClosed ? 1 : 0) . '" /> </div>'; $output = str_replace('/*###REMOVE###*/', GeneralUtility::slashJS(htmlspecialchars(implode('', $this->additionalJS_delete))), $output); // NOTICE: We are saving the toggle-state directly in the flexForm XML and "unauthorized" // according to the data structure. It means that flexform XML will report unclean and // a cleaning operation will remove the recorded togglestates. This is not a fatal problem. // Ideally we should save the toggle states in meta-data but it is much harder to do that. // And this implementation was easy to make and with no really harmful impact. // Pop the container from DynNestedStack $this->popFromDynNestedStack('flex', $idTagPrefix); } } elseif (is_array($value['TCEforms']['config'])) { // Rendering a single form element: if (is_array($PA['_valLang'])) { $rotateLang = $PA['_valLang']; } else { $rotateLang = array($PA['_valLang']); } $conditionData = is_array($editData) ? $editData : array(); // Add current $row to data processed by \TYPO3\CMS\Backend\Form\ElementConditionMatcher $conditionData['parentRec'] = $row; $tRows = array(); /** @var $elementConditionMatcher \TYPO3\CMS\Backend\Form\ElementConditionMatcher */ $elementConditionMatcher = GeneralUtility::makeInstance('TYPO3\\CMS\\Backend\\Form\\ElementConditionMatcher'); foreach ($rotateLang as $vDEFkey) { $vDEFkey = 'v' . $vDEFkey; $displayConditionResult = TRUE; if ($value['TCEforms']['displayCond']) { $displayConditionResult = $elementConditionMatcher->match($value['TCEforms']['displayCond'], $conditionData, $vDEFkey); } if ($displayConditionResult) { $fakePA = array(); $fakePA['fieldConf'] = array('label' => $this->sL(trim($value['TCEforms']['label'])), 'config' => $value['TCEforms']['config'], 'defaultExtras' => $value['TCEforms']['defaultExtras'], 'onChange' => $value['TCEforms']['onChange']); if ($PA['_noEditDEF'] && $PA['_lang'] === 'lDEF') { $fakePA['fieldConf']['config'] = array('type' => 'none', 'rows' => 2); } if ($fakePA['fieldConf']['onChange'] === 'reload' || !empty($GLOBALS['TCA'][$table]['ctrl']['type']) && (string) $key === $GLOBALS['TCA'][$table]['ctrl']['type'] || !empty($GLOBALS['TCA'][$table]['ctrl']['requestUpdate']) && GeneralUtility::inList($GLOBALS['TCA'][$table]['ctrl']['requestUpdate'], $key)) { if ($this->getBackendUserAuthentication()->jsConfirmation(1)) { $alertMsgOnChange = 'if (confirm(TBE_EDITOR.labels.onChangeAlert) && TBE_EDITOR.checkSubmit(-1)){ TBE_EDITOR.submitForm() };'; } else { $alertMsgOnChange = 'if(TBE_EDITOR.checkSubmit(-1)){ TBE_EDITOR.submitForm();}'; } } else { $alertMsgOnChange = ''; } $fakePA['fieldChangeFunc'] = $PA['fieldChangeFunc']; if (strlen($alertMsgOnChange)) { $fakePA['fieldChangeFunc']['alert'] = $alertMsgOnChange; } $fakePA['onFocus'] = $PA['onFocus']; $fakePA['label'] = $PA['label']; $fakePA['itemFormElName'] = $PA['itemFormElName'] . $formPrefix . '[' . $key . '][' . $vDEFkey . ']'; $fakePA['itemFormElName_file'] = $PA['itemFormElName_file'] . $formPrefix . '[' . $key . '][' . $vDEFkey . ']'; $fakePA['itemFormElID'] = $fakePA['itemFormElName']; if (isset($editData[$key][$vDEFkey])) { $fakePA['itemFormElValue'] = $editData[$key][$vDEFkey]; } else { $fakePA['itemFormElValue'] = $fakePA['fieldConf']['config']['default']; } $theFormEl = $this->getSingleField_SW($table, $field, $row, $fakePA); $theTitle = htmlspecialchars($fakePA['fieldConf']['label']); if (!in_array('DEF', $rotateLang)) { $defInfo = '<div class="typo3-TCEforms-originalLanguageValue">' . $this->getLanguageIcon($table, $row, 0) . $this->previewFieldValue($editData[$key]['vDEF'], $fakePA['fieldConf'], $field) . ' </div>'; } else { $defInfo = ''; } if (!$PA['_noEditDEF']) { $prLang = $this->getAdditionalPreviewLanguages(); foreach ($prLang as $prL) { $defInfo .= '<div class="typo3-TCEforms-originalLanguageValue">' . $this->getLanguageIcon($table, $row, 'v' . $prL['ISOcode']) . $this->previewFieldValue($editData[$key]['v' . $prL['ISOcode']], $fakePA['fieldConf'], $field) . ' </div>'; } } $languageIcon = ''; if ($vDEFkey != 'vDEF') { $languageIcon = $this->getLanguageIcon($table, $row, $vDEFkey); } // Put row together // possible linebreaks in the label through xml: \n => <br/>, usage of nl2br() // not possible, so it's done through str_replace $processedTitle = str_replace('\\n', '<br />', $theTitle); $tRows[] = '<div class="t3-form-field-container t3-form-field-container-flex">' . '<div class="t3-form-field-label t3-form-field-label-flex">' . $languageIcon . BackendUtility::wrapInHelp($PA['_cshKey'], $key, $processedTitle) . '</div> <div class="t3-form-field t3-form-field-flex">' . $theFormEl . $defInfo . $this->renderVDEFDiff($editData[$key], $vDEFkey) . '</div> </div>'; } } if (count($tRows)) { $output .= implode('', $tRows); } } } } } return $output; }
/** * Return a form to add a new task or edit an existing one * * @return string HTML form to add or edit a task */ protected function editTaskAction() { $this->view->setTemplatePathAndFilename($this->backendTemplatePath . 'EditTask.html'); $registeredClasses = $this->getRegisteredClasses(); $registeredTaskGroups = $this->getRegisteredTaskGroups(); $taskInfo = array(); $task = null; $process = 'edit'; if ($this->submittedData['uid'] > 0) { // If editing, retrieve data for existing task try { $taskRecord = $this->scheduler->fetchTaskRecord($this->submittedData['uid']); // If there's a registered execution, the task should not be edited if (!empty($taskRecord['serialized_executions'])) { $this->addMessage($this->getLanguageService()->getLL('msg.maynotEditRunningTask'), FlashMessage::ERROR); throw new \LogicException('Runnings tasks cannot not be edited', 1251232849); } // Get the task object /** @var $task \TYPO3\CMS\Scheduler\Task\AbstractTask */ $task = unserialize($taskRecord['serialized_task_object']); // Set some task information $taskInfo['disable'] = $taskRecord['disable']; $taskInfo['description'] = $taskRecord['description']; $taskInfo['task_group'] = $taskRecord['task_group']; // Check that the task object is valid if (isset($registeredClasses[get_class($task)]) && $this->scheduler->isValidTaskObject($task)) { // The task object is valid, process with fetching current data $taskInfo['class'] = get_class($task); // Get execution information $taskInfo['start'] = (int) $task->getExecution()->getStart(); $taskInfo['end'] = (int) $task->getExecution()->getEnd(); $taskInfo['interval'] = $task->getExecution()->getInterval(); $taskInfo['croncmd'] = $task->getExecution()->getCronCmd(); $taskInfo['multiple'] = $task->getExecution()->getMultiple(); if (!empty($taskInfo['interval']) || !empty($taskInfo['croncmd'])) { // Guess task type from the existing information // If an interval or a cron command is defined, it's a recurring task $taskInfo['type'] = AbstractTask::TYPE_RECURRING; $taskInfo['frequency'] = $taskInfo['interval'] ?: $taskInfo['croncmd']; } else { // It's not a recurring task // Make sure interval and cron command are both empty $taskInfo['type'] = AbstractTask::TYPE_SINGLE; $taskInfo['frequency'] = ''; $taskInfo['end'] = 0; } } else { // The task object is not valid // Issue error message $this->addMessage(sprintf($this->getLanguageService()->getLL('msg.invalidTaskClassEdit'), get_class($task)), FlashMessage::ERROR); // Initialize empty values $taskInfo['start'] = 0; $taskInfo['end'] = 0; $taskInfo['frequency'] = ''; $taskInfo['multiple'] = false; $taskInfo['type'] = AbstractTask::TYPE_SINGLE; } } catch (\OutOfBoundsException $e) { // Add a message and continue throwing the exception $this->addMessage(sprintf($this->getLanguageService()->getLL('msg.taskNotFound'), $this->submittedData['uid']), FlashMessage::ERROR); throw $e; } } else { // If adding a new object, set some default values $taskInfo['class'] = key($registeredClasses); $taskInfo['type'] = AbstractTask::TYPE_RECURRING; $taskInfo['start'] = $GLOBALS['EXEC_TIME']; $taskInfo['end'] = ''; $taskInfo['frequency'] = ''; $taskInfo['multiple'] = 0; $process = 'add'; } // If some data was already submitted, use it to override // existing data if (!empty($this->submittedData)) { \TYPO3\CMS\Core\Utility\ArrayUtility::mergeRecursiveWithOverrule($taskInfo, $this->submittedData); } // Get the extra fields to display for each task that needs some $allAdditionalFields = array(); if ($process === 'add') { foreach ($registeredClasses as $class => $registrationInfo) { if (!empty($registrationInfo['provider'])) { /** @var $providerObject \TYPO3\CMS\Scheduler\AdditionalFieldProviderInterface */ $providerObject = GeneralUtility::getUserObj($registrationInfo['provider']); if ($providerObject instanceof \TYPO3\CMS\Scheduler\AdditionalFieldProviderInterface) { $additionalFields = $providerObject->getAdditionalFields($taskInfo, null, $this); $allAdditionalFields = array_merge($allAdditionalFields, array($class => $additionalFields)); } } } } else { if (!empty($registeredClasses[$taskInfo['class']]['provider'])) { $providerObject = GeneralUtility::getUserObj($registeredClasses[$taskInfo['class']]['provider']); if ($providerObject instanceof \TYPO3\CMS\Scheduler\AdditionalFieldProviderInterface) { $allAdditionalFields[$taskInfo['class']] = $providerObject->getAdditionalFields($taskInfo, $task, $this); } } } // Load necessary JavaScript $this->getPageRenderer()->loadJquery(); $this->getPageRenderer()->loadRequireJsModule('TYPO3/CMS/Scheduler/Scheduler'); $this->getPageRenderer()->loadRequireJsModule('TYPO3/CMS/Backend/DateTimePicker'); // Start rendering the add/edit form $this->view->assign('uid', htmlspecialchars($this->submittedData['uid'])); $this->view->assign('cmd', htmlspecialchars($this->CMD)); $table = array(); // Disable checkbox $label = '<label for="task_disable">' . $this->getLanguageService()->sL('LLL:EXT:lang/locallang_common.xlf:disable') . '</label>'; $table[] = '<div class="form-section" id="task_disable_row"><div class="form-group">' . BackendUtility::wrapInHelp($this->cshKey, 'task_disable', $label) . '<div class="form-control-wrap">' . '<input type="hidden" name="tx_scheduler[disable]" value="0">' . '<input class="checkbox" type="checkbox" name="tx_scheduler[disable]" value="1" id="task_disable" ' . ($taskInfo['disable'] ? ' checked="checked"' : '') . '>' . '</div>' . '</div></div>'; // Task class selector $label = '<label for="task_class">' . $this->getLanguageService()->getLL('label.class') . '</label>'; // On editing, don't allow changing of the task class, unless it was not valid if ($this->submittedData['uid'] > 0 && !empty($taskInfo['class'])) { $cell = '<div>' . $registeredClasses[$taskInfo['class']]['title'] . ' (' . $registeredClasses[$taskInfo['class']]['extension'] . ')</div>'; $cell .= '<input type="hidden" name="tx_scheduler[class]" id="task_class" value="' . htmlspecialchars($taskInfo['class']) . '">'; } else { $cell = '<select name="tx_scheduler[class]" id="task_class" class="form-control">'; // Group registered classes by classname $groupedClasses = array(); foreach ($registeredClasses as $class => $classInfo) { $groupedClasses[$classInfo['extension']][$class] = $classInfo; } ksort($groupedClasses); // Loop on all grouped classes to display a selector foreach ($groupedClasses as $extension => $class) { $cell .= '<optgroup label="' . htmlspecialchars($extension) . '">'; foreach ($groupedClasses[$extension] as $class => $classInfo) { $selected = $class == $taskInfo['class'] ? ' selected="selected"' : ''; $cell .= '<option value="' . htmlspecialchars($class) . '"' . 'title="' . htmlspecialchars($classInfo['description']) . '" ' . $selected . '>' . htmlspecialchars($classInfo['title']) . '</option>'; } $cell .= '</optgroup>'; } $cell .= '</select>'; } $table[] = '<div class="form-section" id="task_class_row"><div class="form-group">' . BackendUtility::wrapInHelp($this->cshKey, 'task_class', $label) . '<div class="form-control-wrap">' . $cell . '</div>' . '</div></div>'; // Task type selector $label = '<label for="task_type">' . $this->getLanguageService()->getLL('label.type') . '</label>'; $table[] = '<div class="form-section" id="task_type_row"><div class="form-group">' . BackendUtility::wrapInHelp($this->cshKey, 'task_type', $label) . '<div class="form-control-wrap">' . '<select name="tx_scheduler[type]" id="task_type" class="form-control">' . '<option value="1" ' . ((int) $taskInfo['type'] === AbstractTask::TYPE_SINGLE ? ' selected="selected"' : '') . '>' . $this->getLanguageService()->getLL('label.type.single') . '</option>' . '<option value="2" ' . ((int) $taskInfo['type'] === AbstractTask::TYPE_RECURRING ? ' selected="selected"' : '') . '>' . $this->getLanguageService()->getLL('label.type.recurring') . '</option>' . '</select>' . '</div>' . '</div></div>'; // Task group selector $label = '<label for="task_group">' . $this->getLanguageService()->getLL('label.group') . '</label>'; $cell = '<select name="tx_scheduler[task_group]" id="task_class" class="form-control">'; // Loop on all groups to display a selector $cell .= '<option value="0" title=""></option>'; foreach ($registeredTaskGroups as $taskGroup) { $selected = $taskGroup['uid'] == $taskInfo['task_group'] ? ' selected="selected"' : ''; $cell .= '<option value="' . $taskGroup['uid'] . '"' . 'title="'; $cell .= htmlspecialchars($taskGroup['groupName']) . '"' . $selected . '>'; $cell .= htmlspecialchars($taskGroup['groupName']) . '</option>'; } $cell .= '</select>'; $table[] = '<div class="form-section" id="task_group_row"><div class="form-group">' . BackendUtility::wrapInHelp($this->cshKey, 'task_group', $label) . '<div class="form-control-wrap">' . $cell . '</div>' . '</div></div>'; $dateFormat = $GLOBALS['TYPO3_CONF_VARS']['SYS']['USdateFormat'] ? '%H:%M %m-%d-%Y' : '%H:%M %d-%m-%Y'; $label = '<label for="tceforms-datetimefield-task_start">' . BackendUtility::wrapInHelp($this->cshKey, 'task_start', $this->getLanguageService()->getLL('label.start')) . '</label>'; $value = $taskInfo['start'] > 0 ? strftime($dateFormat, $taskInfo['start']) : ''; $table[] = '<div class="form-section"><div class="row"><div class="form-group col-sm-6" id="task_start_col">' . $label . '<div class="form-control-wrap">' . '<div class="input-group" id="tceforms-datetimefield-task_start_row-wrapper">' . '<input name="tx_scheduler[start]_hr" value="' . $value . '" class="form-control t3js-datetimepicker t3js-clearable" data-date-type="datetime" data-date-offset="0" type="text" id="tceforms-datetimefield-task_start_row">' . '<input name="tx_scheduler[start]" value="' . $taskInfo['start'] . '" type="hidden">' . '<span class="input-group-btn"><label class="btn btn-default" for="tceforms-datetimefield-task_start_row"><span class="fa fa-calendar"></span></label></span>' . '</div>' . '</div>' . '</div>'; // End date/time field // NOTE: datetime fields need a special id naming scheme $value = $taskInfo['end'] > 0 ? strftime($dateFormat, $taskInfo['end']) : ''; $label = '<label for="tceforms-datetimefield-task_end">' . $this->getLanguageService()->getLL('label.end') . '</label>'; $table[] = '<div class="form-group col-sm-6" id="task_end_col">' . BackendUtility::wrapInHelp($this->cshKey, 'task_end', $label) . '<div class="form-control-wrap">' . '<div class="input-group" id="tceforms-datetimefield-task_end_row-wrapper">' . '<input name="tx_scheduler[end]_hr" value="' . $value . '" class="form-control t3js-datetimepicker t3js-clearable" data-date-type="datetime" data-date-offset="0" type="text" id="tceforms-datetimefield-task_end_row">' . '<input name="tx_scheduler[end]" value="' . $taskInfo['end'] . '" type="hidden">' . '<span class="input-group-btn"><label class="btn btn-default" for="tceforms-datetimefield-task_end_row"><span class="fa fa-calendar"></span></label></span>' . '</div>' . '</div>' . '</div></div></div>'; // Frequency input field $label = '<label for="task_frequency">' . $this->getLanguageService()->getLL('label.frequency.long') . '</label>'; $table[] = '<div class="form-section" id="task_frequency_row"><div class="form-group">' . BackendUtility::wrapInHelp($this->cshKey, 'task_frequency', $label) . '<div class="form-control-wrap">' . '<input type="text" name="tx_scheduler[frequency]" class="form-control" id="task_frequency" value="' . htmlspecialchars($taskInfo['frequency']) . '">' . '</div>' . '</div></div>'; // Multiple execution selector $label = '<label for="task_multiple">' . $this->getLanguageService()->getLL('label.parallel.long') . '</label>'; $table[] = '<div class="form-section" id="task_multiple_row"><div class="form-group">' . BackendUtility::wrapInHelp($this->cshKey, 'task_multiple', $label) . '<div class="form-control-wrap">' . '<input type="hidden" name="tx_scheduler[multiple]" value="0">' . '<input class="checkbox" type="checkbox" name="tx_scheduler[multiple]" value="1" id="task_multiple" ' . ($taskInfo['multiple'] ? 'checked="checked"' : '') . '>' . '</div>' . '</div></div>'; // Description $label = '<label for="task_description">' . $this->getLanguageService()->getLL('label.description') . '</label>'; $table[] = '<div class="form-section" id="task_description_row"><div class="form-group">' . BackendUtility::wrapInHelp($this->cshKey, 'task_description', $label) . '<div class="form-control-wrap">' . '<textarea class="form-control" name="tx_scheduler[description]">' . htmlspecialchars($taskInfo['description']) . '</textarea>' . '</div>' . '</div></div>'; // Display additional fields foreach ($allAdditionalFields as $class => $fields) { if ($class == $taskInfo['class']) { $additionalFieldsStyle = ''; } else { $additionalFieldsStyle = ' style="display: none"'; } // Add each field to the display, if there are indeed any if (isset($fields) && is_array($fields)) { foreach ($fields as $fieldID => $fieldInfo) { $label = '<label for="' . $fieldID . '">' . $this->getLanguageService()->sL($fieldInfo['label']) . '</label>'; $htmlClassName = strtolower(str_replace('\\', '-', $class)); $table[] = '<div class="form-section extraFields extra_fields_' . $htmlClassName . '" ' . $additionalFieldsStyle . ' id="' . $fieldID . '_row"><div class="form-group">' . BackendUtility::wrapInHelp($fieldInfo['cshKey'], $fieldInfo['cshLabel'], $label) . '<div class="form-control-wrap">' . $fieldInfo['code'] . '</div>' . '</div></div>'; } } } $this->view->assign('table', implode(LF, $table)); // Server date time $dateFormat = $GLOBALS['TYPO3_CONF_VARS']['SYS']['ddmmyy'] . ' ' . $GLOBALS['TYPO3_CONF_VARS']['SYS']['hhmm'] . ' T (e'; $this->view->assign('now', date($dateFormat) . ', GMT ' . date('P') . ')'); return $this->view->render(); }
/** * Main function, starting the rendering of the list. * * @return void */ public function main() { $backendUser = $this->getBackendUserAuthentication(); $lang = $this->getLanguageService(); // Loading current page record and checking access: $this->pageinfo = BackendUtility::readPageAccess($this->id, $this->perms_clause); $access = is_array($this->pageinfo) ? 1 : 0; // Start document template object: // We need to keep this due to deeply nested dependencies $this->doc = GeneralUtility::makeInstance(DocumentTemplate::class); $this->getPageRenderer()->loadRequireJsModule('TYPO3/CMS/Backend/AjaxDataHandler'); $calcPerms = $backendUser->calcPerms($this->pageinfo); $userCanEditPage = $calcPerms & Permission::PAGE_EDIT && !empty($this->id) && ($backendUser->isAdmin() || (int) $this->pageinfo['editlock'] === 0); if ($userCanEditPage) { $this->getPageRenderer()->loadRequireJsModule('TYPO3/CMS/Backend/PageActions', 'function(PageActions) { PageActions.setPageId(' . (int) $this->id . '); PageActions.initializePageTitleRenaming(); }'); } $this->getPageRenderer()->loadRequireJsModule('TYPO3/CMS/Recordlist/Tooltip'); // Apply predefined values for hidden checkboxes // Set predefined value for DisplayBigControlPanel: if ($this->modTSconfig['properties']['enableDisplayBigControlPanel'] === 'activated') { $this->MOD_SETTINGS['bigControlPanel'] = true; } elseif ($this->modTSconfig['properties']['enableDisplayBigControlPanel'] === 'deactivated') { $this->MOD_SETTINGS['bigControlPanel'] = false; } // Set predefined value for Clipboard: if ($this->modTSconfig['properties']['enableClipBoard'] === 'activated') { $this->MOD_SETTINGS['clipBoard'] = true; } elseif ($this->modTSconfig['properties']['enableClipBoard'] === 'deactivated') { $this->MOD_SETTINGS['clipBoard'] = false; } else { if ($this->MOD_SETTINGS['clipBoard'] === null) { $this->MOD_SETTINGS['clipBoard'] = true; } } // Set predefined value for LocalizationView: if ($this->modTSconfig['properties']['enableLocalizationView'] === 'activated') { $this->MOD_SETTINGS['localization'] = true; } elseif ($this->modTSconfig['properties']['enableLocalizationView'] === 'deactivated') { $this->MOD_SETTINGS['localization'] = false; } // Initialize the dblist object: /** @var $dblist RecordList\DatabaseRecordList */ $dblist = GeneralUtility::makeInstance(RecordList\DatabaseRecordList::class); $dblist->script = BackendUtility::getModuleUrl('web_list'); $dblist->calcPerms = $calcPerms; $dblist->thumbs = $backendUser->uc['thumbnailsByDefault']; $dblist->returnUrl = $this->returnUrl; $dblist->allFields = $this->MOD_SETTINGS['bigControlPanel'] || $this->table ? 1 : 0; $dblist->localizationView = $this->MOD_SETTINGS['localization']; $dblist->showClipboard = 1; $dblist->disableSingleTableView = $this->modTSconfig['properties']['disableSingleTableView']; $dblist->listOnlyInSingleTableMode = $this->modTSconfig['properties']['listOnlyInSingleTableView']; $dblist->hideTables = $this->modTSconfig['properties']['hideTables']; $dblist->hideTranslations = $this->modTSconfig['properties']['hideTranslations']; $dblist->tableTSconfigOverTCA = $this->modTSconfig['properties']['table.']; $dblist->allowedNewTables = GeneralUtility::trimExplode(',', $this->modTSconfig['properties']['allowedNewTables'], true); $dblist->deniedNewTables = GeneralUtility::trimExplode(',', $this->modTSconfig['properties']['deniedNewTables'], true); $dblist->newWizards = $this->modTSconfig['properties']['newWizards'] ? 1 : 0; $dblist->pageRow = $this->pageinfo; $dblist->counter++; $dblist->MOD_MENU = ['bigControlPanel' => '', 'clipBoard' => '', 'localization' => '']; $dblist->modTSconfig = $this->modTSconfig; $clickTitleMode = trim($this->modTSconfig['properties']['clickTitleMode']); $dblist->clickTitleMode = $clickTitleMode === '' ? 'edit' : $clickTitleMode; if (isset($this->modTSconfig['properties']['tableDisplayOrder.'])) { $typoScriptService = GeneralUtility::makeInstance(TypoScriptService::class); $dblist->setTableDisplayOrder($typoScriptService->convertTypoScriptArrayToPlainArray($this->modTSconfig['properties']['tableDisplayOrder.'])); } // Clipboard is initialized: // Start clipboard $dblist->clipObj = GeneralUtility::makeInstance(Clipboard::class); // Initialize - reads the clipboard content from the user session $dblist->clipObj->initializeClipboard(); // Clipboard actions are handled: // CB is the clipboard command array $CB = GeneralUtility::_GET('CB'); if ($this->cmd == 'setCB') { // CBH is all the fields selected for the clipboard, CBC is the checkbox fields which were checked. // By merging we get a full array of checked/unchecked elements // This is set to the 'el' array of the CB after being parsed so only the table in question is registered. $CB['el'] = $dblist->clipObj->cleanUpCBC(array_merge(GeneralUtility::_POST('CBH'), (array) GeneralUtility::_POST('CBC')), $this->cmd_table); } if (!$this->MOD_SETTINGS['clipBoard']) { // If the clipboard is NOT shown, set the pad to 'normal'. $CB['setP'] = 'normal'; } // Execute commands. $dblist->clipObj->setCmd($CB); // Clean up pad $dblist->clipObj->cleanCurrent(); // Save the clipboard content $dblist->clipObj->endClipboard(); // This flag will prevent the clipboard panel in being shown. // It is set, if the clickmenu-layer is active AND the extended view is not enabled. $dblist->dontShowClipControlPanels = $dblist->clipObj->current == 'normal' && !$this->modTSconfig['properties']['showClipControlPanelsDespiteOfCMlayers']; // If there is access to the page or root page is used for searching, then render the list contents and set up the document template object: if ($access || $this->id === 0 && $this->search_levels !== 0 && $this->search_field !== '') { // Deleting records...: // Has not to do with the clipboard but is simply the delete action. The clipboard object is used to clean up the submitted entries to only the selected table. if ($this->cmd == 'delete') { $items = $dblist->clipObj->cleanUpCBC(GeneralUtility::_POST('CBC'), $this->cmd_table, 1); if (!empty($items)) { $cmd = []; foreach ($items as $iK => $value) { $iKParts = explode('|', $iK); $cmd[$iKParts[0]][$iKParts[1]]['delete'] = 1; } $tce = GeneralUtility::makeInstance(DataHandler::class); $tce->start([], $cmd); $tce->process_cmdmap(); if (isset($cmd['pages'])) { BackendUtility::setUpdateSignal('updatePageTree'); } $tce->printLogErrorMessages(GeneralUtility::getIndpEnv('REQUEST_URI')); } } // Initialize the listing object, dblist, for rendering the list: $this->pointer = max(0, (int) $this->pointer); $dblist->start($this->id, $this->table, $this->pointer, $this->search_field, $this->search_levels, $this->showLimit); $dblist->setDispFields(); // Render versioning selector: if (ExtensionManagementUtility::isLoaded('version')) { $dblist->HTMLcode .= $this->moduleTemplate->getVersionSelector($this->id); } // Render the list of tables: $dblist->generateList(); $listUrl = $dblist->listURL(); // Add JavaScript functions to the page: $this->moduleTemplate->addJavaScriptCode('RecordListInlineJS', ' function jumpExt(URL,anchor) { // var anc = anchor?anchor:""; window.location.href = URL+(T3_THIS_LOCATION?"&returnUrl="+T3_THIS_LOCATION:"")+anc; return false; } function jumpSelf(URL) { // window.location.href = URL+(T3_RETURN_URL?"&returnUrl="+T3_RETURN_URL:""); return false; } function jumpToUrl(URL) { window.location.href = URL; return false; } function setHighlight(id) { // top.fsMod.recentIds["web"]=id; top.fsMod.navFrameHighlightedID["web"]="pages"+id+"_"+top.fsMod.currentBank; // For highlighting if (top.nav_frame && top.nav_frame.refresh_nav) { top.nav_frame.refresh_nav(); } } ' . $this->moduleTemplate->redirectUrls($listUrl) . ' ' . $dblist->CBfunctions() . ' function editRecords(table,idList,addParams,CBflag) { // window.location.href="' . BackendUtility::getModuleUrl('record_edit', ['returnUrl' => GeneralUtility::getIndpEnv('REQUEST_URI')]) . '&edit["+table+"]["+idList+"]=edit"+addParams; } function editList(table,idList) { // var list=""; // Checking how many is checked, how many is not var pointer=0; var pos = idList.indexOf(","); while (pos!=-1) { if (cbValue(table+"|"+idList.substr(pointer,pos-pointer))) { list+=idList.substr(pointer,pos-pointer)+","; } pointer=pos+1; pos = idList.indexOf(",",pointer); } if (cbValue(table+"|"+idList.substr(pointer))) { list+=idList.substr(pointer)+","; } return list ? list : idList; } if (top.fsMod) top.fsMod.recentIds["web"] = ' . (int) $this->id . '; '); // Setting up the context sensitive menu: $this->moduleTemplate->getPageRenderer()->loadRequireJsModule('TYPO3/CMS/Backend/ClickMenu'); } // access // Begin to compile the whole page, starting out with page header: if (!$this->id) { $title = $GLOBALS['TYPO3_CONF_VARS']['SYS']['sitename']; } else { $title = $this->pageinfo['title']; } $this->body = $this->moduleTemplate->header($title); $this->moduleTemplate->setTitle($title); if (!empty($dblist->HTMLcode)) { $output = $dblist->HTMLcode; } else { $output = ''; $flashMessage = GeneralUtility::makeInstance(FlashMessage::class, $lang->getLL('noRecordsOnThisPage'), '', FlashMessage::INFO); /** @var $flashMessageService \TYPO3\CMS\Core\Messaging\FlashMessageService */ $flashMessageService = GeneralUtility::makeInstance(FlashMessageService::class); /** @var $defaultFlashMessageQueue \TYPO3\CMS\Core\Messaging\FlashMessageQueue */ $defaultFlashMessageQueue = $flashMessageService->getMessageQueueByIdentifier(); $defaultFlashMessageQueue->enqueue($flashMessage); } $this->body .= '<form action="' . htmlspecialchars($dblist->listURL()) . '" method="post" name="dblistForm">'; $this->body .= $output; $this->body .= '<input type="hidden" name="cmd_table" /><input type="hidden" name="cmd" /></form>'; // If a listing was produced, create the page footer with search form etc: if ($dblist->HTMLcode) { // Making field select box (when extended view for a single table is enabled): if ($dblist->table) { $this->body .= $dblist->fieldSelectBox($dblist->table); } // Adding checkbox options for extended listing and clipboard display: $this->body .= ' <!-- Listing options for extended view, clipboard and localization view --> <div class="typo3-listOptions"> <form action="" method="post">'; // Add "display bigControlPanel" checkbox: if ($this->modTSconfig['properties']['enableDisplayBigControlPanel'] === 'selectable') { $this->body .= '<div class="checkbox">' . '<label for="checkLargeControl">' . BackendUtility::getFuncCheck($this->id, 'SET[bigControlPanel]', $this->MOD_SETTINGS['bigControlPanel'], '', $this->table ? '&table=' . $this->table : '', 'id="checkLargeControl"') . BackendUtility::wrapInHelp('xMOD_csh_corebe', 'list_options', htmlspecialchars($lang->getLL('largeControl'))) . '</label>' . '</div>'; } // Add "clipboard" checkbox: if ($this->modTSconfig['properties']['enableClipBoard'] === 'selectable') { if ($dblist->showClipboard) { $this->body .= '<div class="checkbox">' . '<label for="checkShowClipBoard">' . BackendUtility::getFuncCheck($this->id, 'SET[clipBoard]', $this->MOD_SETTINGS['clipBoard'], '', $this->table ? '&table=' . $this->table : '', 'id="checkShowClipBoard"') . BackendUtility::wrapInHelp('xMOD_csh_corebe', 'list_options', htmlspecialchars($lang->getLL('showClipBoard'))) . '</label>' . '</div>'; } } // Add "localization view" checkbox: if ($this->modTSconfig['properties']['enableLocalizationView'] === 'selectable') { $this->body .= '<div class="checkbox">' . '<label for="checkLocalization">' . BackendUtility::getFuncCheck($this->id, 'SET[localization]', $this->MOD_SETTINGS['localization'], '', $this->table ? '&table=' . $this->table : '', 'id="checkLocalization"') . BackendUtility::wrapInHelp('xMOD_csh_corebe', 'list_options', htmlspecialchars($lang->getLL('localization'))) . '</label>' . '</div>'; } $this->body .= ' </form> </div>'; } // Printing clipboard if enabled if ($this->MOD_SETTINGS['clipBoard'] && $dblist->showClipboard && ($dblist->HTMLcode || $dblist->clipObj->hasElements())) { $this->body .= '<div class="db_list-dashboard">' . $dblist->clipObj->printClipboard() . '</div>'; } // Additional footer content $footerContentHook = $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['recordlist/Modules/Recordlist/index.php']['drawFooterHook']; if (is_array($footerContentHook)) { foreach ($footerContentHook as $hook) { $params = []; $this->body .= GeneralUtility::callUserFunction($hook, $params, $this); } } // Setting up the buttons for docheader $dblist->getDocHeaderButtons($this->moduleTemplate); // searchbox toolbar if (!$this->modTSconfig['properties']['disableSearchBox'] && ($dblist->HTMLcode || !empty($dblist->searchString))) { $this->content = $dblist->getSearchBox(); $this->moduleTemplate->getPageRenderer()->loadRequireJsModule('TYPO3/CMS/Backend/ToggleSearchToolbox'); $searchButton = $this->moduleTemplate->getDocHeaderComponent()->getButtonBar()->makeLinkButton(); $searchButton->setHref('#')->setClasses('t3js-toggle-search-toolbox')->setTitle($lang->sL('LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:labels.title.searchIcon'))->setIcon($this->iconFactory->getIcon('actions-search', Icon::SIZE_SMALL)); $this->moduleTemplate->getDocHeaderComponent()->getButtonBar()->addButton($searchButton, ButtonBar::BUTTON_POSITION_LEFT, 90); } if ($this->pageinfo) { $this->moduleTemplate->getDocHeaderComponent()->setMetaInformation($this->pageinfo); } // Build the <body> for the module $this->content .= $this->body; }
/** * Create a regular new element (pages and records) * * @return void */ public function regularNew() { $lang = $this->getLanguageService(); // Initialize array for accumulating table rows: $this->tRows = array(); // Get TSconfig for current page $pageTS = BackendUtility::getPagesTSconfig($this->id); // Finish initializing new pages options with TSconfig // Each new page option may be hidden by TSconfig // Enabled option for the position of a new page $this->newPagesSelectPosition = !empty($pageTS['mod.']['wizards.']['newRecord.']['pages.']['show.']['pageSelectPosition']); // Pseudo-boolean (0/1) for backward compatibility $displayNewPagesIntoLink = $this->newPagesInto && !empty($pageTS['mod.']['wizards.']['newRecord.']['pages.']['show.']['pageInside']) ? 1 : 0; $displayNewPagesAfterLink = $this->newPagesAfter && !empty($pageTS['mod.']['wizards.']['newRecord.']['pages.']['show.']['pageAfter']) ? 1 : 0; // Slight spacer from header: $this->code .= ''; // New Page $table = 'pages'; $v = $GLOBALS['TCA'][$table]; $pageIcon = $this->moduleTemplate->getIconFactory()->getIconForRecord($table, array(), Icon::SIZE_SMALL)->render(); $newPageIcon = $this->moduleTemplate->getIconFactory()->getIcon('actions-page-new', Icon::SIZE_SMALL)->render(); $rowContent = ''; // New pages INSIDE this pages $newPageLinks = array(); if ($displayNewPagesIntoLink && $this->isTableAllowedForThisPage($this->pageinfo, 'pages') && $this->getBackendUserAuthentication()->check('tables_modify', 'pages') && $this->getBackendUserAuthentication()->workspaceCreateNewRecord($this->pageinfo['_ORIG_uid'] ?: $this->id, 'pages')) { // Create link to new page inside: $newPageLinks[] = $this->linkWrap($this->moduleTemplate->getIconFactory()->getIconForRecord($table, array(), Icon::SIZE_SMALL)->render() . $lang->sL($v['ctrl']['title'], true) . ' (' . $lang->sL('LLL:EXT:lang/locallang_core.xlf:db_new.php.inside', true) . ')', $table, $this->id); } // New pages AFTER this pages if ($displayNewPagesAfterLink && $this->isTableAllowedForThisPage($this->pidInfo, 'pages') && $this->getBackendUserAuthentication()->check('tables_modify', 'pages') && $this->getBackendUserAuthentication()->workspaceCreateNewRecord($this->pidInfo['uid'], 'pages')) { $newPageLinks[] = $this->linkWrap($pageIcon . $lang->sL($v['ctrl']['title'], true) . ' (' . $lang->sL('LLL:EXT:lang/locallang_core.xlf:db_new.php.after', true) . ')', 'pages', -$this->id); } // New pages at selection position if ($this->newPagesSelectPosition && $this->showNewRecLink('pages')) { // Link to page-wizard: $newPageLinks[] = '<a href="' . htmlspecialchars(GeneralUtility::linkThisScript(array('pagesOnly' => 1))) . '">' . $pageIcon . htmlspecialchars($lang->getLL('pageSelectPosition')) . '</a>'; } // Assemble all new page links $numPageLinks = count($newPageLinks); for ($i = 0; $i < $numPageLinks; $i++) { $rowContent .= '<li>' . $newPageLinks[$i] . '</li>'; } if ($this->showNewRecLink('pages')) { $rowContent = '<ul class="list-tree"><li>' . $newPageIcon . '<strong>' . $lang->getLL('createNewPage') . '</strong><ul>' . $rowContent . '</ul></li>'; } else { $rowContent = '<ul class="list-tree"><li><ul>' . $rowContent . '</li></ul>'; } // Compile table row $startRows = array($rowContent); $iconFile = array(); // New tables (but not pages) INSIDE this pages $isAdmin = $this->getBackendUserAuthentication()->isAdmin(); $newContentIcon = $this->moduleTemplate->getIconFactory()->getIcon('actions-document-new', Icon::SIZE_SMALL)->render(); if ($this->newContentInto) { if (is_array($GLOBALS['TCA'])) { $groupName = ''; foreach ($GLOBALS['TCA'] as $table => $v) { if ($table != 'pages' && $this->showNewRecLink($table) && $this->isTableAllowedForThisPage($this->pageinfo, $table) && $this->getBackendUserAuthentication()->check('tables_modify', $table) && (($v['ctrl']['rootLevel'] xor $this->id) || $v['ctrl']['rootLevel'] == -1) && $this->getBackendUserAuthentication()->workspaceCreateNewRecord($this->pageinfo['_ORIG_uid'] ? $this->pageinfo['_ORIG_uid'] : $this->id, $table)) { $newRecordIcon = $this->moduleTemplate->getIconFactory()->getIconForRecord($table, array(), Icon::SIZE_SMALL)->render(); $rowContent = ''; $thisTitle = ''; // Create new link for record: $newLink = $this->linkWrap($newRecordIcon . $lang->sL($v['ctrl']['title'], true), $table, $this->id); // If the table is 'tt_content', create link to wizard if ($table == 'tt_content') { $groupName = $lang->getLL('createNewContent'); $rowContent = $newContentIcon . '<strong>' . $lang->getLL('createNewContent') . '</strong><ul>'; // If mod.newContentElementWizard.override is set, use that extension's wizard instead: $tsConfig = BackendUtility::getModTSconfig($this->id, 'mod'); $moduleName = isset($tsConfig['properties']['newContentElementWizard.']['override']) ? $tsConfig['properties']['newContentElementWizard.']['override'] : 'new_content_element'; $url = BackendUtility::getModuleUrl($moduleName, ['id' => $this->id, 'returnUrl' => GeneralUtility::getIndpEnv('REQUEST_URI')]); $rowContent .= '<li>' . $newLink . ' ' . BackendUtility::wrapInHelp($table, '') . '</li><li><a href="' . htmlspecialchars($url) . '">' . $newContentIcon . htmlspecialchars($lang->getLL('clickForWizard')) . '</a></li></ul>'; } else { // Get the title if ($v['ctrl']['readOnly'] || $v['ctrl']['hideTable'] || $v['ctrl']['is_static']) { continue; } if ($v['ctrl']['adminOnly'] && !$isAdmin) { continue; } $nameParts = explode('_', $table); $thisTitle = ''; $_EXTKEY = ''; if ($nameParts[0] == 'tx' || $nameParts[0] == 'tt') { // Try to extract extension name if (substr($v['ctrl']['title'], 0, 8) == 'LLL:EXT:') { $_EXTKEY = substr($v['ctrl']['title'], 8); $_EXTKEY = substr($_EXTKEY, 0, strpos($_EXTKEY, '/')); if ($_EXTKEY != '') { // First try to get localisation of extension title $temp = explode(':', substr($v['ctrl']['title'], 9 + strlen($_EXTKEY))); $langFile = $temp[0]; $thisTitle = $lang->sL('LLL:EXT:' . $_EXTKEY . '/' . $langFile . ':extension.title'); // If no localisation available, read title from ext_emconf.php $extEmConfFile = ExtensionManagementUtility::extPath($_EXTKEY) . 'ext_emconf.php'; if (!$thisTitle && is_file($extEmConfFile)) { $EM_CONF = array(); include $extEmConfFile; $thisTitle = $EM_CONF[$_EXTKEY]['title']; } $iconFile[$_EXTKEY] = '<img ' . 'src="' . ExtensionManagementUtility::extRelPath($_EXTKEY) . $GLOBALS['TYPO3_LOADED_EXT'][$_EXTKEY]['ext_icon'] . '" ' . 'width="16" height="16" ' . 'alt="' . $thisTitle . '" />'; } } if (empty($thisTitle)) { $_EXTKEY = $nameParts[1]; $thisTitle = $nameParts[1]; $iconFile[$_EXTKEY] = ''; } } else { if ($table === 'pages_language_overlay' && !$this->checkIfLanguagesExist()) { continue; } $_EXTKEY = 'system'; $thisTitle = $lang->getLL('system_records'); $iconFile['system'] = $this->moduleTemplate->getIconFactory()->getIcon('apps-pagetree-root', Icon::SIZE_SMALL)->render(); } if ($groupName == '' || $groupName != $_EXTKEY) { $groupName = empty($v['ctrl']['groupName']) ? $_EXTKEY : $v['ctrl']['groupName']; } $rowContent .= $newLink; } // Compile table row: if ($table == 'tt_content') { $startRows[] = '<li>' . $rowContent . '</li>'; } else { $this->tRows[$groupName]['title'] = $thisTitle; $this->tRows[$groupName]['html'][] = $rowContent; $this->tRows[$groupName]['table'][] = $table; } } } } } // User sort if (isset($pageTS['mod.']['wizards.']['newRecord.']['order'])) { $this->newRecordSortList = GeneralUtility::trimExplode(',', $pageTS['mod.']['wizards.']['newRecord.']['order'], true); } uksort($this->tRows, array($this, 'sortNewRecordsByConfig')); // Compile table row: $finalRows = array(); $finalRows[] = implode('', $startRows); foreach ($this->tRows as $key => $value) { $row = '<li>' . $iconFile[$key] . ' <strong>' . $value['title'] . '</strong><ul>'; foreach ($value['html'] as $recordKey => $record) { $row .= '<li>' . $record . ' ' . BackendUtility::wrapInHelp($value['table'][$recordKey], '') . '</li>'; } $row .= '</ul></li>'; $finalRows[] = $row; } $finalRows[] = '</ul>'; // Make table: $this->code .= implode('', $finalRows); }
/** * Entry method * * @return array As defined in initializeResultArray() of AbstractNode */ public function render() { $table = $this->data['tableName']; $flexFormDataStructureArray = $this->data['flexFormDataStructureArray']; $flexFormRowData = $this->data['flexFormRowData']; $flexFormFormPrefix = $this->data['flexFormFormPrefix']; $parameterArray = $this->data['parameterArray']; $languageService = $this->getLanguageService(); $resultArray = $this->initializeResultArray(); foreach ($flexFormDataStructureArray as $flexFormFieldName => $flexFormFieldArray) { if (!is_array($flexFormFieldArray) || !isset($flexFormFieldArray['type']) && !is_array($flexFormFieldArray['config'])) { continue; } if ($flexFormFieldArray['type'] === 'array') { // Section if (empty($flexFormFieldArray['section'])) { $resultArray['html'] = LF . 'Section expected at ' . $flexFormFieldName . ' but not found'; continue; } $sectionTitle = ''; if (!empty(trim($flexFormFieldArray['title']))) { $sectionTitle = $languageService->sL(trim($flexFormFieldArray['title'])); } $options = $this->data; $options['flexFormDataStructureArray'] = $flexFormFieldArray['el']; $options['flexFormRowData'] = isset($flexFormRowData[$flexFormFieldName]['el']) ? $flexFormRowData[$flexFormFieldName]['el'] : []; $options['flexFormSectionType'] = $flexFormFieldName; $options['flexFormSectionTitle'] = $sectionTitle; $options['renderType'] = 'flexFormSectionContainer'; $sectionContainerResult = $this->nodeFactory->create($options)->render(); $resultArray = $this->mergeChildReturnIntoExistingResult($resultArray, $sectionContainerResult); } else { // Set up options for single element $fakeParameterArray = ['fieldConf' => ['label' => $languageService->sL(trim($flexFormFieldArray['label'])), 'config' => $flexFormFieldArray['config'], 'children' => $flexFormFieldArray['children'], 'defaultExtras' => $flexFormFieldArray['defaultExtras'], 'onChange' => $flexFormFieldArray['onChange']], 'fieldChangeFunc' => $parameterArray['fieldChangeFunc'], 'label' => $parameterArray['label']]; $alertMsgOnChange = ''; if ($fakeParameterArray['fieldConf']['onChange'] === 'reload' || !empty($GLOBALS['TCA'][$table]['ctrl']['type']) && $GLOBALS['TCA'][$table]['ctrl']['type'] === $flexFormFieldName || !empty($GLOBALS['TCA'][$table]['ctrl']['requestUpdate']) && GeneralUtility::inList($GLOBALS['TCA'][$table]['ctrl']['requestUpdate'], $flexFormFieldName)) { if ($this->getBackendUserAuthentication()->jsConfirmation(JsConfirmation::TYPE_CHANGE)) { $alertMsgOnChange = 'top.TYPO3.Modal.confirm(TBE_EDITOR.labels.refreshRequired.title, TBE_EDITOR.labels.refreshRequired.content).on("button.clicked", function(e) { if (e.target.name == "ok" && TBE_EDITOR.checkSubmit(-1)) { TBE_EDITOR.submitForm() } top.TYPO3.Modal.dismiss(); });'; } else { $alertMsgOnChange = 'if (TBE_EDITOR.checkSubmit(-1)){ TBE_EDITOR.submitForm();}'; } } if ($alertMsgOnChange) { $fakeParameterArray['fieldChangeFunc']['alert'] = $alertMsgOnChange; } $originalFieldName = $parameterArray['itemFormElName']; $fakeParameterArray['itemFormElName'] = $parameterArray['itemFormElName'] . $flexFormFormPrefix . '[' . $flexFormFieldName . '][vDEF]'; if ($fakeParameterArray['itemFormElName'] !== $originalFieldName) { // If calculated itemFormElName is different from originalFieldName // change the originalFieldName in TBE_EDITOR_fieldChanged. This is // especially relevant for wizards writing their content back to hidden fields if (!empty($fakeParameterArray['fieldChangeFunc']['TBE_EDITOR_fieldChanged'])) { $fakeParameterArray['fieldChangeFunc']['TBE_EDITOR_fieldChanged'] = str_replace($originalFieldName, $fakeParameterArray['itemFormElName'], $fakeParameterArray['fieldChangeFunc']['TBE_EDITOR_fieldChanged']); } } $fakeParameterArray['itemFormElID'] = $fakeParameterArray['itemFormElName']; if (isset($flexFormRowData[$flexFormFieldName]['vDEF'])) { $fakeParameterArray['itemFormElValue'] = $flexFormRowData[$flexFormFieldName]['vDEF']; } else { $fakeParameterArray['itemFormElValue'] = $fakeParameterArray['fieldConf']['config']['default']; } $options = $this->data; $options['parameterArray'] = $fakeParameterArray; $options['elementBaseName'] = $this->data['elementBaseName'] . $flexFormFormPrefix . '[' . $flexFormFieldName . '][vDEF]'; if (!empty($flexFormFieldArray['config']['renderType'])) { $options['renderType'] = $flexFormFieldArray['config']['renderType']; } else { // Fallback to type if no renderType is given $options['renderType'] = $flexFormFieldArray['config']['type']; } $childResult = $this->nodeFactory->create($options)->render(); // Possible line breaks in the label through xml: \n => <br/>, usage of nl2br() not possible, so it's done through str_replace (?!) $processedTitle = str_replace('\\n', '<br />', htmlspecialchars($fakeParameterArray['fieldConf']['label'])); $html = []; $html[] = '<div class="form-section">'; $html[] = '<div class="form-group t3js-formengine-palette-field t3js-formengine-validation-marker">'; $html[] = '<label class="t3js-formengine-label">'; $html[] = BackendUtility::wrapInHelp($parameterArray['_cshKey'], $flexFormFieldName, $processedTitle); $html[] = '</label>'; $html[] = '<div class="t3js-formengine-field-item">'; $html[] = $childResult['html']; $html[] = '</div>'; $html[] = '</div>'; $html[] = '</div>'; $resultArray['html'] .= implode(LF, $html); $childResult['html'] = ''; $resultArray = $this->mergeChildReturnIntoExistingResult($resultArray, $childResult); } } return $resultArray; }
/** * Prints the clipboard * * @return string HTML output * @todo Define visibility */ public function printClipboard() { $out = array(); $elCount = count($this->elFromTable($this->fileMode ? '_FILE' : '')); // Upper header $out[] = ' <tr class="t3-row-header"> <td colspan="3">' . \TYPO3\CMS\Backend\Utility\BackendUtility::wrapInHelp('xMOD_csh_corebe', 'list_clipboard', $this->clLabel('clipboard', 'buttons')) . '</td> </tr>'; // Button/menu header: $thumb_url = \TYPO3\CMS\Core\Utility\GeneralUtility::linkThisScript(array('CB' => array('setThumb' => $this->clipData['_setThumb'] ? 0 : 1))); $rmall_url = \TYPO3\CMS\Core\Utility\GeneralUtility::linkThisScript(array('CB' => array('removeAll' => $this->current))); // Copymode Selector menu $copymode_url = \TYPO3\CMS\Core\Utility\GeneralUtility::linkThisScript(); $moveLabel = htmlspecialchars($GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_misc.php:moveElements')); $copyLabel = htmlspecialchars($GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_misc.php:copyElements')); $opt = array(); $opt[] = '<option style="padding-left: 20px; background-image: url(\'' . \TYPO3\CMS\Backend\Utility\IconUtility::skinImg($this->backPath, 'gfx/clip_cut.gif', '', 1) . '\'); background-repeat: no-repeat;" value="" ' . ($this->currentMode() == 'copy' ? '' : 'selected="selected"') . '>' . $moveLabel . '</option>'; $opt[] = '<option style="padding-left: 20px; background-image: url(\'' . \TYPO3\CMS\Backend\Utility\IconUtility::skinImg($this->backPath, 'gfx/clip_copy.gif', '', 1) . '\'); background-repeat: no-repeat;" value="1" ' . ($this->currentMode() == 'copy' ? 'selected="selected"' : '') . '>' . $copyLabel . '</option>'; $copymode_selector = ' <select name="CB[setCopyMode]" onchange="this.form.method=\'POST\'; this.form.action=\'' . htmlspecialchars($copymode_url . '&CB[setCopyMode]=') . '\'+(this.options[this.selectedIndex].value); this.form.submit(); return true;" >' . implode('', $opt) . '</select>'; // Selector menu + clear button $opt = array(); $opt[] = '<option value="" selected="selected">' . $this->clLabel('menu', 'rm') . '</option>'; // Import / Export link: if ($elCount && \TYPO3\CMS\Core\Extension\ExtensionManager::isLoaded('impexp')) { $opt[] = '<option value="' . htmlspecialchars('window.location.href=\'' . $this->backPath . \TYPO3\CMS\Core\Extension\ExtensionManager::extRelPath('impexp') . 'app/index.php' . $this->exportClipElementParameters() . '\';') . '">' . $this->clLabel('export', 'rm') . '</option>'; } // Edit: if (!$this->fileMode && $elCount) { $opt[] = '<option value="' . htmlspecialchars('window.location.href=\'' . $this->editUrl() . '&returnUrl=\'+top.rawurlencode(window.location.href);') . '">' . $this->clLabel('edit', 'rm') . '</option>'; } // Delete: if ($elCount) { if ($GLOBALS['BE_USER']->jsConfirmation(4)) { $js = ' if (confirm(' . $GLOBALS['LANG']->JScharCode(sprintf($GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:mess.deleteClip'), $elCount)) . ')){ window.location.href=\'' . $this->deleteUrl(0, $this->fileMode ? 1 : 0) . '&redirect=\'+top.rawurlencode(window.location.href); } '; } else { $js = ' window.location.href=\'' . $this->deleteUrl(0, $this->fileMode ? 1 : 0) . '&redirect=\'+top.rawurlencode(window.location.href); '; } $opt[] = '<option value="' . htmlspecialchars($js) . '">' . $this->clLabel('delete', 'rm') . '</option>'; } $selector_menu = '<select name="_clipMenu" onchange="eval(this.options[this.selectedIndex].value);this.selectedIndex=0;">' . implode('', $opt) . '</select>'; $out[] = ' <tr class="typo3-clipboard-head"> <td nowrap="nowrap">' . '<a href="' . htmlspecialchars($thumb_url) . '#clip_head">' . '<img' . \TYPO3\CMS\Backend\Utility\IconUtility::skinImg($this->backPath, 'gfx/thumb_' . ($this->clipData['_setThumb'] ? 's' : 'n') . '.gif', 'width="21" height="16"') . ' vspace="2" border="0" title="' . $this->clLabel('thumbmode_clip') . '" alt="" />' . '</a>' . '</td> <td width="95%" nowrap="nowrap">' . $copymode_selector . ' ' . $selector_menu . '</td> <td>' . '<a href="' . htmlspecialchars($rmall_url) . '#clip_head">' . \TYPO3\CMS\Backend\Utility\IconUtility::getSpriteIcon('actions-document-close', array('title' => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:buttons.clear', TRUE))) . '</a></td> </tr>'; // Print header and content for the NORMAL tab: $out[] = ' <tr class="bgColor5"> <td colspan="3"><a href="' . htmlspecialchars(\TYPO3\CMS\Core\Utility\GeneralUtility::linkThisScript(array('CB' => array('setP' => 'normal')))) . '#clip_head">' . \TYPO3\CMS\Backend\Utility\IconUtility::getSpriteIcon('actions-view-table-' . ($this->current == 'normal' ? 'collapse' : 'expand')) . $this->padTitleWrap('Normal', 'normal') . '</a></td> </tr>'; if ($this->current == 'normal') { $out = array_merge($out, $this->printContentFromTab('normal')); } // Print header and content for the NUMERIC tabs: for ($a = 1; $a <= $this->numberTabs; $a++) { $out[] = ' <tr class="bgColor5"> <td colspan="3"><a href="' . htmlspecialchars(\TYPO3\CMS\Core\Utility\GeneralUtility::linkThisScript(array('CB' => array('setP' => 'tab_' . $a)))) . '#clip_head">' . \TYPO3\CMS\Backend\Utility\IconUtility::getSpriteIcon('actions-view-table-' . ($this->current == 'tab_' . $a ? 'collapse' : 'expand')) . $this->padTitleWrap($this->clLabel('cliptabs') . $a, 'tab_' . $a) . '</a></td> </tr>'; if ($this->current == 'tab_' . $a) { $out = array_merge($out, $this->printContentFromTab('tab_' . $a)); } } // Wrap accumulated rows in a table: $output = '<a name="clip_head"></a> <!-- TYPO3 Clipboard: --> <table cellpadding="0" cellspacing="1" border="0" width="290" id="typo3-clipboard"> ' . implode('', $out) . ' </table>'; // Wrap in form tag: $output = '<form action="">' . $output . '</form>'; // Return the accumulated content: return $output; }
/** * Prints the clipboard * * @return string HTML output */ public function printClipboard() { $out = array(); $elementCount = count($this->elFromTable($this->fileMode ? '_FILE' : '')); // Button/menu header: $removeAllUrl = GeneralUtility::linkThisScript(array('CB' => array('removeAll' => $this->current))); // Copymode Selector menu $copymodeUrl = GeneralUtility::linkThisScript(); $moveLabel = htmlspecialchars($this->getLanguageService()->sL('LLL:EXT:lang/locallang_misc.xlf:moveElements')); $copyLabel = htmlspecialchars($this->getLanguageService()->sL('LLL:EXT:lang/locallang_misc.xlf:copyElements')); $copymodeSelector = ' <div class="btn-group"> <button class="btn btn-default dropdown-toggle" type="button" id="copymodeSelector" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true"> ' . ($this->currentMode() === 'copy' ? $copyLabel : $moveLabel) . ' <span class="caret"></span> </button> <ul class="dropdown-menu" aria-labelledby="copymodeSelector"> <li><a href="#" onclick="document.getElementById(\'clipboard_form\').method=\'POST\'; document.getElementById(\'clipboard_form\').action=' . htmlspecialchars(GeneralUtility::quoteJSvalue($copymodeUrl . '&CB[setCopyMode]=')) . '; document.getElementById(\'clipboard_form\').submit(); return true;">' . $moveLabel . '</a></li> <li><a href="#" onclick="document.getElementById(\'clipboard_form\').method=\'POST\'; document.getElementById(\'clipboard_form\').action=' . htmlspecialchars(GeneralUtility::quoteJSvalue($copymodeUrl . '&CB[setCopyMode]=1')) . '; document.getElementById(\'clipboard_form\').submit(); return true;">' . $copyLabel . '</a></li> </ul> </div> '; // Selector menu + clear button $optionArray = array(); // Import / Export link: if ($elementCount && ExtensionManagementUtility::isLoaded('impexp')) { $url = BackendUtility::getModuleUrl('xMOD_tximpexp', $this->exportClipElementParameters()); $optionArray[] = '<li><a href="#" onclick="' . htmlspecialchars('window.location.href=' . GeneralUtility::quoteJSvalue($url) . ';') . '">' . $this->clLabel('export', 'rm') . '</a></li>'; } // Edit: if (!$this->fileMode && $elementCount) { $optionArray[] = '<li><a href="#" onclick="' . htmlspecialchars('window.location.href=' . GeneralUtility::quoteJSvalue($this->editUrl() . '&returnUrl=') . '+top.rawurlencode(window.location.href);') . '">' . $this->clLabel('edit', 'rm') . '</a></li>'; } $deleteLink = ''; $menuSelector = ''; if ($elementCount) { // Delete: $deleteLink = '<a class="btn btn-danger" href="' . htmlspecialchars($removeAllUrl) . '#clip_head" title="' . $this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:buttons.clear', true) . '">' . $this->iconFactory->getIcon('actions-document-close', Icon::SIZE_SMALL)->render(SvgIconProvider::MARKUP_IDENTIFIER_INLINE) . '</a>'; if ($this->getBackendUser()->jsConfirmation(JsConfirmation::DELETE)) { $js = ' if (confirm(' . GeneralUtility::quoteJSvalue(sprintf($this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:mess.deleteClip'), $elementCount)) . ')){ window.location.href=' . GeneralUtility::quoteJSvalue($this->deleteUrl(0, $this->fileMode ? 1 : 0) . '&redirect=') . '+top.rawurlencode(window.location.href); } '; } else { $js = ' window.location.href=' . GeneralUtility::quoteJSvalue($this->deleteUrl(0, $this->fileMode ? 1 : 0) . '&redirect=') . '+top.rawurlencode(window.location.href); '; } $optionArray[] = '<li><a href="#" onclick="' . htmlspecialchars($js) . '">' . $this->clLabel('delete', 'rm') . '</a></li>'; // menuSelector $menuSelector = ' <div class="btn-group"> <button class="btn btn-default dropdown-toggle" type="button" id="menuSelector" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true"> ' . $this->clLabel('menu', 'rm') . ' <span class="caret"></span> </button> <ul class="dropdown-menu" aria-labelledby="menuSelector"> ' . implode('', $optionArray) . ' </ul> </div> '; } $out[] = ' <tr> <td colspan="2" nowrap="nowrap" width="95%">' . $copymodeSelector . ' ' . $menuSelector . '</td> <td nowrap="nowrap" class="col-control">' . $deleteLink . '</td> </tr>'; // Print header and content for the NORMAL tab: // check for current item so it can be wrapped in strong tag $current = $this->current == 'normal'; $out[] = ' <tr> <td colspan="3"><a href="' . htmlspecialchars(GeneralUtility::linkThisScript(array('CB' => array('setP' => 'normal')))) . '#clip_head" title="' . $this->clLabel('normal-description') . '">' . '<span class="t3-icon fa ' . ($current ? 'fa-check-circle' : 'fa-circle-o') . '"></span>' . $this->padTitleWrap($this->clLabel('normal'), 'normal', $current) . '</a></td> </tr>'; if ($this->current == 'normal') { $out = array_merge($out, $this->printContentFromTab('normal')); } // Print header and content for the NUMERIC tabs: for ($a = 1; $a <= $this->numberTabs; $a++) { // check for current item so it can be wrapped in strong tag $current = $this->current == 'tab_' . $a; $out[] = ' <tr> <td colspan="3"><a href="' . htmlspecialchars(GeneralUtility::linkThisScript(array('CB' => array('setP' => 'tab_' . $a)))) . '#clip_head" title="' . $this->clLabel('cliptabs-description') . '">' . '<span class="t3-icon fa ' . ($current ? 'fa-check-circle' : 'fa-circle-o') . '"></span>' . $this->padTitleWrap(sprintf($this->clLabel('cliptabs-name'), $a), 'tab_' . $a, $current) . '</a></td> </tr>'; if ($this->current == 'tab_' . $a) { $out = array_merge($out, $this->printContentFromTab('tab_' . $a)); } } // Wrap accumulated rows in a table: $output = '<a name="clip_head"></a> <!-- TYPO3 Clipboard: --> <div class="row"> <div class="col-sm-12"> <div class="panel panel-default"> <div class="panel-heading">' . BackendUtility::wrapInHelp('xMOD_csh_corebe', 'list_clipboard', $this->clLabel('clipboard', 'buttons')) . '</div> <table class="table"> ' . implode('', $out) . ' </table> </div> </div> </div> '; // Wrap in form tag: $output = '<form action="" id="clipboard_form">' . $output . '</form>'; // Return the accumulated content: return $output; }
/** * Creates the listing of records from a single table * * @param string $table Table name * @param int $id Page id * @param string $rowlist List of fields to show in the listing. * Pseudo fields will be added including the record header. * * @return string HTML table with the listing for the record. * @throws UnexpectedValueException If hook was of wrong interface */ public function getTable($table, $id, $rowlist) { $database = $this->getDatabaseConnection(); $language = $this->getLanguageService(); $backendUser = $this->getBackendUser(); // Init $addWhere = ''; $titleCol = $GLOBALS['TCA'][$table]['ctrl']['label']; $thumbsCol = $GLOBALS['TCA'][$table]['ctrl']['thumbnail']; $l10nEnabled = $GLOBALS['TCA'][$table]['ctrl']['languageField'] && $GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField'] && !$GLOBALS['TCA'][$table]['ctrl']['transOrigPointerTable']; $tableCollapsed = !$this->tablesCollapsed[$table] ? FALSE : TRUE; // prepare space icon $this->spaceIcon = IconUtility::getSpriteIcon('empty-empty', array('style' => 'background-position: 0 10px;')); // Cleaning rowlist for duplicates and place the $titleCol // as the first column always! $this->fieldArray = array(); // title Column // Add title column $this->fieldArray[] = $titleCol; // Control-Panel if (!GeneralUtility::inList($rowlist, '_CONTROL_')) { $this->fieldArray[] = '_CONTROL_'; $this->fieldArray[] = '_AFTERCONTROL_'; } // Clipboard if ($this->showClipboard) { $this->fieldArray[] = '_CLIPBOARD_'; } // Ref if (!$this->dontShowClipControlPanels) { $this->fieldArray[] = '_REF_'; $this->fieldArray[] = '_AFTERREF_'; } // Path if ($this->searchLevels) { $this->fieldArray[] = '_PATH_'; } // Localization if ($this->localizationView && $l10nEnabled) { $this->fieldArray[] = '_LOCALIZATION_'; $this->fieldArray[] = '_LOCALIZATION_b'; $addWhere .= ' AND ( ' . $GLOBALS['TCA'][$table]['ctrl']['languageField'] . ' <= 0 OR ' . $GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField'] . ' = 0 )'; } // Cleaning up: $this->fieldArray = array_unique(array_merge($this->fieldArray, GeneralUtility::trimExplode(',', $rowlist, 1))); if ($this->noControlPanels) { $tempArray = array_flip($this->fieldArray); unset($tempArray['_CONTROL_']); unset($tempArray['_CLIPBOARD_']); $this->fieldArray = array_keys($tempArray); } // Creating the list of fields to include in the SQL query: $selectFields = $this->fieldArray; $selectFields[] = 'uid'; $selectFields[] = 'pid'; // adding column for thumbnails if ($thumbsCol) { $selectFields[] = $thumbsCol; } if ($table == 'pages') { if (ExtensionManagementUtility::isLoaded('cms')) { $selectFields[] = 'module'; $selectFields[] = 'extendToSubpages'; $selectFields[] = 'nav_hide'; } $selectFields[] = 'doktype'; } if (is_array($GLOBALS['TCA'][$table]['ctrl']['enablecolumns'])) { $selectFields = array_merge($selectFields, $GLOBALS['TCA'][$table]['ctrl']['enablecolumns']); } if ($GLOBALS['TCA'][$table]['ctrl']['type']) { $selectFields[] = $GLOBALS['TCA'][$table]['ctrl']['type']; } if ($GLOBALS['TCA'][$table]['ctrl']['typeicon_column']) { $selectFields[] = $GLOBALS['TCA'][$table]['ctrl']['typeicon_column']; } if ($GLOBALS['TCA'][$table]['ctrl']['versioningWS']) { $selectFields[] = 't3ver_id'; $selectFields[] = 't3ver_state'; $selectFields[] = 't3ver_wsid'; // Filtered out when tx_commerce_categories in makeFieldList() $selectFields[] = 't3ver_swapmode'; } if ($l10nEnabled) { $selectFields[] = $GLOBALS['TCA'][$table]['ctrl']['languageField']; $selectFields[] = $GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField']; } if ($GLOBALS['TCA'][$table]['ctrl']['label_alt']) { $selectFields = array_merge($selectFields, GeneralUtility::trimExplode(',', $GLOBALS['TCA'][$table]['ctrl']['label_alt'], 1)); } // Unique list! $selectFields = array_unique($selectFields); // Making sure that the fields in the field-list ARE in the field-list from TCA! $selectFields = array_intersect($selectFields, $this->makeFieldList($table, 1)); // implode it into a list of fields for the SQL-statement. $selFieldList = implode(',', $selectFields); $this->selFieldList = $selFieldList; /** * DB-List getTable * * @date 2007-11-16 * @request Malte Jansen <*****@*****.**> */ if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/class.db_list_extra.inc']['getTable'])) { foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/class.db_list_extra.inc']['getTable'] as $classData) { $hookObject = GeneralUtility::getUserObj($classData); if (!$hookObject instanceof \TYPO3\CMS\Backend\RecordList\RecordListGetTableHookInterface) { throw new UnexpectedValueException('$hookObject must implement interface \\TYPO3\\CMS\\Backend\\RecordList\\RecordListGetTableHookInterface', 1195114460); } $hookObject->getDBlistQuery($table, $id, $addWhere, $selFieldList, $this); } } // Create the SQL query for selecting the elements in the listing: // do not do paging when outputting as CSV if ($this->csvOutput) { $this->iLimit = 0; } if ($this->firstElementNumber > 2 && $this->iLimit > 0) { // Get the two previous rows for sorting if displaying page > 1 $this->firstElementNumber = $this->firstElementNumber - 2; $this->iLimit = $this->iLimit + 2; // (API function from class.db_list.inc) $queryParts = $this->makeQueryArray($table, $id, $addWhere, $selFieldList); $this->firstElementNumber = $this->firstElementNumber + 2; $this->iLimit = $this->iLimit - 2; } else { // (API function from class.db_list.inc) $queryParts = $this->makeQueryArray($table, $id, $addWhere, $selFieldList); } // Finding the total amount of records on the page $this->setTotalItems($queryParts); // Init: $dbCount = 0; $out = ''; $listOnlyInSingleTableMode = $this->listOnlyInSingleTableMode && !$this->table; $result = FALSE; // If the count query returned any number of records, // we perform the real query, selecting records. if ($this->totalItems) { // Fetch records only if not in single table mode or // if in multi table mode and not collapsed if ($listOnlyInSingleTableMode || !$this->table && $tableCollapsed) { $dbCount = $this->totalItems; } else { // set the showLimit to the number of records when outputting as CSV if ($this->csvOutput) { $this->showLimit = $this->totalItems; $this->iLimit = $this->totalItems; } $result = $database->exec_SELECT_queryArray($queryParts); $dbCount = $database->sql_num_rows($result); } } // If any records was selected, render the list: if ($dbCount) { // Half line is drawn between tables: if (!$listOnlyInSingleTableMode) { $theData = array(); if (!$this->table && !$rowlist) { $theData[$titleCol] = '<img src="/' . TYPO3_mainDir . '/clear.gif" width="' . ($GLOBALS['SOBE']->MOD_SETTINGS['bigControlPanel'] ? '230' : '350') . '" height="1" alt="" />'; if (in_array('_CONTROL_', $this->fieldArray)) { $theData['_CONTROL_'] = ''; } if (in_array('_CLIPBOARD_', $this->fieldArray)) { $theData['_CLIPBOARD_'] = ''; } } $out .= $this->addelement(0, '', $theData, 'class="c-table-row-spacer"', $this->leftMargin); } // Header line is drawn $theData = array(); if ($this->disableSingleTableView) { $theData[$titleCol] = '<span class="c-table">' . BackendUtility::wrapInHelp($table, '', $language->sL($GLOBALS['TCA'][$table]['ctrl']['title'], TRUE)) . '</span> (' . $this->totalItems . ')'; } else { $theData[$titleCol] = $this->linkWrapTable($table, '<span class="c-table">' . $language->sL($GLOBALS['TCA'][$table]['ctrl']['title'], TRUE) . '</span> (' . $this->totalItems . ') ' . ($this->table ? IconUtility::getSpriteIcon('actions-view-table-collapse', array('title' => $language->getLL('contractView', TRUE))) : IconUtility::getSpriteIcon('actions-view-table-expand', array('title' => $language->getLL('expandView', TRUE))))); } if ($listOnlyInSingleTableMode) { $out .= ' <tr> <td class="t3-row-header" style="width: 95%;">' . BackendUtility::wrapInHelp($table, '', $theData[$titleCol]) . '</td> </tr>'; } else { // Render collapse button if in multi table mode $collapseIcon = ''; if (!$this->table) { if ($tableCollapsed) { $options = array('class' => 'collapseIcon', 'title' => $language->sL('LLL:EXT:lang/locallang_core.php:labels.expandTable', TRUE)); } else { $options = array('class' => 'collapseIcon', 'title' => $language->sL('LLL:EXT:lang/locallang_core.php:labels.collapseTable', TRUE)); } $value = $tableCollapsed ? '0' : '1'; $collapseIcon = '<a href="' . htmlspecialchars($this->listURL() . '&collapse[' . $table . ']=' . $value) . '">' . ($tableCollapsed ? IconUtility::getSpriteIcon('actions-view-list-expand', $options) : IconUtility::getSpriteIcon('actions-view-list-collapse', $options)) . '</a>'; } $out .= $this->addElement(1, $collapseIcon, $theData, ' class="t3-row-header"', ''); } $iOut = ''; // Render table rows only if in multi table view // and not collapsed or if in single table view if (!$listOnlyInSingleTableMode && (!$tableCollapsed || $this->table)) { // Fixing a order table for sortby tables $this->currentTable = array(); $currentIdList = array(); $doSort = $GLOBALS['TCA'][$table]['ctrl']['sortby'] && !$this->sortField; $prevUid = 0; $prevPrevUid = 0; // Get first two rows and initialize prevPrevUid and prevUid if on page > 1 if ($this->firstElementNumber > 2 && $this->iLimit > 0) { $row = $database->sql_fetch_assoc($result); $prevPrevUid = -(int) $row['uid']; $row = $database->sql_fetch_assoc($result); $prevUid = $row['uid']; } // Accumulate rows here $accRows = array(); while ($row = $database->sql_fetch_assoc($result)) { // In offline workspace, look for alternative record: BackendUtility::workspaceOL($table, $row, $this->getBackendUser()->workspace, TRUE); if (is_array($row)) { $accRows[] = $row; $currentIdList[] = $row['uid']; if ($doSort) { if ($prevUid) { $this->currentTable['prev'][$row['uid']] = $prevPrevUid; $this->currentTable['next'][$prevUid] = '-' . $row['uid']; $this->currentTable['prevUid'][$row['uid']] = $prevUid; } $prevPrevUid = isset($this->currentTable['prev'][$row['uid']]) ? -$prevUid : $row['pid']; $prevUid = $row['uid']; } } } $database->sql_free_result($result); $this->totalRowCount = count($accRows); // CSV initiated if ($this->csvOutput) { $this->initCSV(); } // Render items: $this->CBnames = array(); $this->duplicateStack = array(); $this->eCounter = $this->firstElementNumber; $iOut = ''; $cc = 0; foreach ($accRows as $row) { // Render item row if counter < limit if ($cc < $this->iLimit) { $cc++; $this->translations = FALSE; $iOut .= $this->renderListRow($table, $row, $cc, $titleCol, $thumbsCol); // If localization view is enabled it means that the selected records are // either default or All language and here we will not select translations // which point to the main record: if ($this->localizationView && $l10nEnabled) { // For each available translation, render the record: if (is_array($this->translations)) { foreach ($this->translations as $lRow) { // $lRow isn't always what we want - if record was moved we've to work with the // placeholder records otherwise the list is messed up a bit if ($row['_MOVE_PLH_uid'] && $row['_MOVE_PLH_pid']) { $tmpRow = BackendUtility::getRecordRaw($table, 't3ver_move_id="' . (int) $lRow['uid'] . '" AND pid="' . $row['_MOVE_PLH_pid'] . '" AND t3ver_wsid=' . $row['t3ver_wsid'] . BackendUtility::deleteClause($table), $selFieldList); $lRow = is_array($tmpRow) ? $tmpRow : $lRow; } // In offline workspace, look for alternative record: BackendUtility::workspaceOL($table, $lRow, $this->getBackendUser()->workspace, TRUE); if (is_array($lRow) && $backendUser->checkLanguageAccess($lRow[$GLOBALS['TCA'][$table]['ctrl']['languageField']])) { $currentIdList[] = $lRow['uid']; $iOut .= $this->renderListRow($table, $lRow, $cc, $titleCol, $thumbsCol, 18); } } } } } // Counter of total rows incremented: $this->eCounter++; } // Record navigation is added to the beginning and // end of the table if in single table mode if ($this->table) { $iOut = $this->renderListNavigation('top') . $iOut . $this->renderListNavigation('bottom'); } else { // show that there are more records than shown if ($this->totalItems > $this->itemsLimitPerTable) { $countOnFirstPage = $this->totalItems > $this->itemsLimitSingleTable ? $this->itemsLimitSingleTable : $this->totalItems; $hasMore = $this->totalItems > $this->itemsLimitSingleTable; $iOut .= '<tr><td colspan="' . count($this->fieldArray) . '" style="padding: 5px;"> <a href="' . htmlspecialchars($this->listURL() . '&table=' . rawurlencode($table)) . '">' . '<img' . IconUtility::skinImg($this->backPath, 'gfx/pildown.gif', 'width="14" height="14"') . ' alt="" />' . ' <i>[1 - ' . $countOnFirstPage . ($hasMore ? '+' : '') . ']</i></a> </td></tr>'; } } // The header row for the table is now created: $out .= $this->renderListHeader($table, $currentIdList); } // The list of records is added after the header: $out .= $iOut; unset($iOut); // ... and it is all wrapped in a table: $out = ' <!-- DB listing of elements: "' . htmlspecialchars($table) . '" --> <table border="0" cellpadding="0" cellspacing="0" class="typo3-dblist' . ($listOnlyInSingleTableMode ? ' typo3-dblist-overview' : '') . '"> ' . $out . ' </table>'; // Output csv if... if ($this->csvOutput) { // This ends the page with exit. $this->outputCSV($table); } } // Return content: return $out; }
/** * Wrap a single element * * @param array $element Given element as documented above * @param array $additionalPaletteClasses Additional classes to be added to HTML * @return string Wrapped element */ protected function wrapSingleFieldContentWithLabelAndOuterDiv(array $element, array $additionalPaletteClasses = array()) { $fieldName = $element['fieldName']; $paletteFieldClasses = array('form-group', 't3js-formengine-validation-marker', 't3js-formengine-palette-field'); foreach ($additionalPaletteClasses as $class) { $paletteFieldClasses[] = $class; } $label = BackendUtility::wrapInHelp($this->globalOptions['table'], $fieldName, htmlspecialchars($element['fieldLabel'])); $content = array(); $content[] = '<div class="' . implode(' ', $paletteFieldClasses) . '">'; $content[] = '<label class="t3js-formengine-label">'; $content[] = $label; $content[] = '<img name="req_' . $this->globalOptions['table'] . '_' . $this->globalOptions['databaseRow']['uid'] . '_' . $fieldName . '" src="clear.gif" class="t3js-formengine-field-required" alt="" />'; $content[] = '</label>'; $content[] = $element['fieldHtml']; $content[] = '</div>'; return implode(LF, $content); }
/** * Returns the CSH Icon for given string * * @param string $str Locallang key * @param string $label The label to be used, that should be wrapped in help * @return string HTML output. */ protected function getCSH($str, $label) { $context = '_MOD_user_setup'; $field = $str; $strParts = explode(':', $str); if (count($strParts) > 1) { // Setting comes from another extension $context = $strParts[0]; $field = $strParts[1]; } elseif (!\TYPO3\CMS\Core\Utility\GeneralUtility::inList('language,simuser,reset', $str)) { $field = 'option_' . $str; } return \TYPO3\CMS\Backend\Utility\BackendUtility::wrapInHelp($context, $field, $label); }
/** * Renders the grid layout table after the HTML content for the single elements has been rendered * * @param array $layoutSetup : The setup of the layout that is selected for the grid we are going to render * @param array $row : The current data row for the container item * @param array $head : The data for the column headers of the grid we are going to render * @param array $gridContent : The content data of the grid we are going to render * * @return string */ public function renderGridLayoutTable($layoutSetup, $row, $head, $gridContent) { $specificIds = $this->helper->getSpecificIds($row); $grid = '<div class="t3-grid-container t3-grid-element-container' . ($layoutSetup['frame'] ? ' t3-grid-container-framed t3-grid-container-' . $layoutSetup['frame'] : '') . ($layoutSetup['top_level_layout'] ? ' t3-grid-tl-container' : '') . '">'; if ($layoutSetup['frame'] || $this->helper->getBackendUser()->uc['showGridInformation'] === 1) { $grid .= '<h4 class="t3-grid-container-title-' . (int) $layoutSetup['frame'] . '">' . BackendUtility::wrapInHelp('tx_gridelements_backend_layouts', 'title', $this->languageService->sL($layoutSetup['title']), array('title' => $this->languageService->sL($layoutSetup['title']), 'description' => $this->languageService->sL($layoutSetup['description']))) . '</h4>'; } $grid .= '<table border="0" cellspacing="0" cellpadding="0" width="100%" height="100%" class="t3-page-columns t3-grid-table">'; // add colgroups $colCount = 0; $rowCount = 0; if (isset($layoutSetup['config'])) { if (isset($layoutSetup['config']['colCount'])) { $colCount = (int) $layoutSetup['config']['colCount']; } if (isset($layoutSetup['config']['rowCount'])) { $rowCount = (int) $layoutSetup['config']['rowCount']; } } $grid .= '<colgroup>'; for ($i = 0; $i < $colCount; $i++) { $grid .= '<col style="width:' . 100 / $colCount . '%"></col>'; } $grid .= '</colgroup>'; // cycle through rows for ($layoutRow = 1; $layoutRow <= $rowCount; $layoutRow++) { $rowConfig = $layoutSetup['config']['rows.'][$layoutRow . '.']; if (!isset($rowConfig)) { continue; } $grid .= '<tr>'; for ($col = 1; $col <= $colCount; $col++) { $columnConfig = $rowConfig['columns.'][$col . '.']; if (!isset($columnConfig)) { continue; } // which column should be displayed inside this cell $columnKey = isset($columnConfig['colPos']) && $columnConfig['colPos'] !== '' ? (int) $columnConfig['colPos'] : 32768; // allowed CTypes $allowedContentTypes = array(); if (!empty($columnConfig['allowed'])) { $allowedContentTypes = array_flip(GeneralUtility::trimExplode(',', $columnConfig['allowed'])); if (!isset($allowedContentTypes['*'])) { foreach ($allowedContentTypes as $key => &$ctype) { $ctype = 't3-allow-' . $key; } } else { unset($allowedContentTypes); } } if (!empty($columnConfig['allowedGridTypes'])) { $allowedGridTypes = array_flip(GeneralUtility::trimExplode(',', $columnConfig['allowedGridTypes'])); if (!isset($allowedGridTypes['*']) && !empty($allowedGridTypes)) { foreach ($allowedGridTypes as $gridType => &$gridTypeClass) { $gridTypeClass = 't3-allow-gridtype t3-allow-gridtype-' . $gridType; } $allowedContentTypes['gridelements_pi1'] = 't3-allow-gridelements_pi1'; } else { if (!empty($allowedContentTypes)) { $allowedContentTypes['gridelements_pi1'] = 't3-allow-gridelements_pi1'; } unset($allowedGridTypes); } } // render the grid cell $colSpan = (int) $columnConfig['colspan']; $rowSpan = (int) $columnConfig['rowspan']; $expanded = $this->helper->getBackendUser()->uc['moduleData']['page']['gridelementsCollapsedColumns'][$row['uid'] . '_' . $columnKey] ? 'collapsed' : 'expanded'; $grid .= '<td valign="top"' . (isset($columnConfig['colspan']) ? ' colspan="' . $colSpan . '"' : '') . (isset($columnConfig['rowspan']) ? ' rowspan="' . $rowSpan . '"' : '') . 'data-colpos="' . $columnKey . '" data-columnkey="' . $specificIds['uid'] . '_' . $columnKey . '" class="t3-grid-cell t3js-page-column t3-page-column t3-page-column-' . $columnKey . (!isset($columnConfig['colPos']) || $columnConfig['colPos'] === '' ? ' t3-grid-cell-unassigned' : '') . (isset($columnConfig['colspan']) && $columnConfig['colPos'] !== '' ? ' t3-grid-cell-width' . $colSpan : '') . (isset($columnConfig['rowspan']) && $columnConfig['colPos'] !== '' ? ' t3-grid-cell-height' . $rowSpan : '') . ' ' . ($layoutSetup['horizontal'] ? ' t3-grid-cell-horizontal' : '') . (!empty($allowedContentTypes) ? ' ' . join(' ', $allowedContentTypes) : ' t3-allow-all') . (!empty($allowedGridTypes) ? ' ' . join(' ', $allowedGridTypes) : '') . ' ' . $expanded . '" data-state="' . $expanded . '">'; $grid .= ($this->helper->getBackendUser()->uc['hideColumnHeaders'] ? '' : $head[$columnKey]) . $gridContent[$columnKey]; $grid .= '</td>'; } $grid .= '</tr>'; } $grid .= '</table></div>'; return $grid; }