* For the full copyright and license information, please read the * LICENSE.txt file that was distributed with this source code. * * The TYPO3 project - inspiring people to share! */ /** * Main form rendering script * By sending certain parameters to this script you can bring up a form * which allows the user to edit the content of one or more database records. * * @author Kasper Skårhøj <*****@*****.**> */ call_user_func(function () { $classLoader = (require __DIR__ . '/contrib/vendor/autoload.php'); (new \TYPO3\CMS\Backend\Http\Application($classLoader))->run(function () { \TYPO3\CMS\Backend\Utility\BackendUtility::lockRecords(); \TYPO3\CMS\Core\Utility\GeneralUtility::deprecationLog('The entry point to FormEngine was moved to an own module. Please use BackendUtility::getModuleUrl(\'record_edit\') to link to alt_doc.php. This script will be removed in TYPO3 CMS 8.'); /* @var $editDocumentController \TYPO3\CMS\Backend\Controller\EditDocumentController */ $editDocumentController = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Backend\Controller\EditDocumentController::class); // Preprocessing, storing data if submitted to $editDocumentController->preInit(); // Checks, if a save button has been clicked (or the doSave variable is sent) if ($editDocumentController->doProcessData()) { $formprotection = \TYPO3\CMS\Core\FormProtection\FormProtectionFactory::get(); if ($formprotection->validateToken(\TYPO3\CMS\Core\Utility\GeneralUtility::_GP('formToken'), 'editRecord')) { $editDocumentController->processData(); } } $editDocumentController->init(); $editDocumentController->main(); $editDocumentController->printContent();
/** * Rendering the quick-edit view. * * @return string */ public function renderQuickEdit() { $databaseConnection = $this->getDatabaseConnection(); $beUser = $this->getBackendUser(); $lang = $this->getLanguageService(); // Set the edit_record value for internal use in this function: $edit_record = $this->edit_record; // If a command to edit all records in a column is issue, then select all those elements, and redirect to FormEngine if (substr($edit_record, 0, 9) == '_EDIT_COL') { $res = $databaseConnection->exec_SELECTquery('*', 'tt_content', 'pid=' . (int) $this->id . ' AND colPos=' . (int) substr($edit_record, 10) . ' AND sys_language_uid=' . (int) $this->current_sys_language . ($this->MOD_SETTINGS['tt_content_showHidden'] ? '' : BackendUtility::BEenableFields('tt_content')) . BackendUtility::deleteClause('tt_content') . BackendUtility::versioningPlaceholderClause('tt_content'), '', 'sorting'); $idListA = array(); while ($cRow = $databaseConnection->sql_fetch_assoc($res)) { $idListA[] = $cRow['uid']; } $url = BackendUtility::getModuleUrl('record_edit', array('edit[tt_content][' . implode(',', $idListA) . ']' => 'edit', 'returnUrl' => $this->local_linkThisScript(array('edit_record' => '')))); HttpUtility::redirect($url); } // If the former record edited was the creation of a NEW record, this will look up the created records uid: if ($this->new_unique_uid) { $res = $databaseConnection->exec_SELECTquery('*', 'sys_log', 'userid=' . (int) $beUser->user['uid'] . ' AND NEWid=' . $databaseConnection->fullQuoteStr($this->new_unique_uid, 'sys_log')); $sys_log_row = $databaseConnection->sql_fetch_assoc($res); if (is_array($sys_log_row)) { $edit_record = $sys_log_row['tablename'] . ':' . $sys_log_row['recuid']; } } $edit_record = $this->makeQuickEditMenu($edit_record); // Splitting the edit-record cmd value into table/uid: $this->eRParts = explode(':', $edit_record); $tableName = $this->eRParts[0]; // Delete-button flag? $this->deleteButton = MathUtility::canBeInterpretedAsInteger($this->eRParts[1]) && $edit_record && ($tableName !== 'pages' && $this->EDIT_CONTENT || $tableName === 'pages' && $this->CALC_PERMS & Permission::PAGE_DELETE); // If undo-button should be rendered (depends on available items in sys_history) $this->undoButton = false; $undoRes = $databaseConnection->exec_SELECTquery('tstamp', 'sys_history', 'tablename=' . $databaseConnection->fullQuoteStr($tableName, 'sys_history') . ' AND recuid=' . (int) $this->eRParts[1], '', 'tstamp DESC', '1'); if ($this->undoButtonR = $databaseConnection->sql_fetch_assoc($undoRes)) { $this->undoButton = true; } // Setting up the Return URL for coming back to THIS script (if links take the user to another script) $R_URL_parts = parse_url(GeneralUtility::getIndpEnv('REQUEST_URI')); $R_URL_getvars = GeneralUtility::_GET(); unset($R_URL_getvars['popView']); unset($R_URL_getvars['new_unique_uid']); $R_URL_getvars['edit_record'] = $edit_record; $this->R_URI = $R_URL_parts['path'] . '?' . GeneralUtility::implodeArrayForUrl('', $R_URL_getvars); // Creating editing form: if ($edit_record) { // Splitting uid parts for special features, if new: list($uidVal, $neighborRecordUid, $ex_colPos) = explode('/', $this->eRParts[1]); if ($uidVal === 'new') { $command = 'new'; // Page id of this new record $theUid = $this->id; if ($neighborRecordUid) { $theUid = $neighborRecordUid; } } else { $command = 'edit'; $theUid = $uidVal; // Convert $uidVal to workspace version if any: $draftRecord = BackendUtility::getWorkspaceVersionOfRecord($beUser->workspace, $tableName, $theUid, 'uid'); if ($draftRecord) { $theUid = $draftRecord['uid']; } } // @todo: Hack because DatabaseInitializeNewRow reads from _GP directly $GLOBALS['_GET']['defVals'][$tableName] = array('colPos' => (int) $ex_colPos, 'sys_language_uid' => (int) $this->current_sys_language); /** @var TcaDatabaseRecord $formDataGroup */ $formDataGroup = GeneralUtility::makeInstance(TcaDatabaseRecord::class); /** @var FormDataCompiler $formDataCompiler */ $formDataCompiler = GeneralUtility::makeInstance(FormDataCompiler::class, $formDataGroup); /** @var NodeFactory $nodeFactory */ $nodeFactory = GeneralUtility::makeInstance(NodeFactory::class); try { $formDataCompilerInput = ['tableName' => $tableName, 'vanillaUid' => (int) $theUid, 'command' => $command]; $formData = $formDataCompiler->compile($formDataCompilerInput); if ($command !== 'new') { BackendUtility::lockRecords($tableName, $formData['databaseRow']['uid'], $tableName === 'tt_content' ? $formData['databaseRow']['pid'] : 0); } $formData['renderType'] = 'outerWrapContainer'; $formResult = $nodeFactory->create($formData)->render(); $panel = $formResult['html']; $formResult['html'] = ''; /** @var FormResultCompiler $formResultCompiler */ $formResultCompiler = GeneralUtility::makeInstance(FormResultCompiler::class); $formResultCompiler->mergeResult($formResult); $row = $formData['databaseRow']; $new_unique_uid = ''; if ($command === 'new') { $new_unique_uid = $row['uid']; } // Add hidden fields: if ($uidVal == 'new') { $panel .= '<input type="hidden" name="data[' . $tableName . '][' . $row['uid'] . '][pid]" value="' . $row['pid'] . '" />'; } $redirect = $uidVal == 'new' ? BackendUtility::getModuleUrl($this->moduleName, ['id' => $this->id, 'new_unique_uid' => $new_unique_uid, 'returnUrl' => $this->returnUrl]) : $this->R_URI; $panel .= ' <input type="hidden" name="_serialNumber" value="' . md5(microtime()) . '" /> <input type="hidden" name="edit_record" value="' . $edit_record . '" /> <input type="hidden" name="redirect" value="' . htmlspecialchars($redirect) . '" /> '; // Add JavaScript as needed around the form: $content = $formResultCompiler->JStop() . $panel . $formResultCompiler->printNeededJSFunctions(); // Display "is-locked" message: if ($command === 'edit') { $lockInfo = BackendUtility::isRecordLocked($tableName, $formData['databaseRow']['uid']); if ($lockInfo) { /** @var \TYPO3\CMS\Core\Messaging\FlashMessage $flashMessage */ $flashMessage = GeneralUtility::makeInstance(FlashMessage::class, htmlspecialchars($lockInfo['msg']), '', FlashMessage::WARNING); /** @var $flashMessageService \TYPO3\CMS\Core\Messaging\FlashMessageService */ $flashMessageService = GeneralUtility::makeInstance(FlashMessageService::class); /** @var $defaultFlashMessageQueue \TYPO3\CMS\Core\Messaging\FlashMessageQueue */ $defaultFlashMessageQueue = $flashMessageService->getMessageQueueByIdentifier(); $defaultFlashMessageQueue->enqueue($flashMessage); } } } catch (AccessDeniedException $e) { // If no edit access, print error message: $content = '<h2>' . $lang->getLL('noAccess', true) . '</h2>'; $content .= '<div>' . $lang->getLL('noAccess_msg') . '<br /><br />' . ($beUser->errorMsg ? 'Reason: ' . $beUser->errorMsg . '<br /><br />' : '') . '</div>'; } } else { // If no edit access, print error message: $content = '<h2>' . $lang->getLL('noAccess') . '</h2>'; $content .= '<div>' . $lang->getLL('noAccess_msg') . '</div>'; } // Element selection matrix: if ($tableName === 'tt_content' && MathUtility::canBeInterpretedAsInteger($this->eRParts[1])) { $content .= '<h2>' . $lang->getLL('CEonThisPage') . '</h2>'; // PositionMap $posMap = GeneralUtility::makeInstance(ContentLayoutPagePositionMap::class); $posMap->cur_sys_language = $this->current_sys_language; $content .= $posMap->printContentElementColumns($this->id, $this->eRParts[1], $this->colPosList, $this->MOD_SETTINGS['tt_content_showHidden'], $this->R_URI); // Toggle hidden ContentElements $numberOfHiddenElements = $this->getNumberOfHiddenElements(); if ($numberOfHiddenElements) { $content .= '<div class="checkbox">'; $content .= '<label for="checkTt_content_showHidden">'; $content .= BackendUtility::getFuncCheck($this->id, 'SET[tt_content_showHidden]', $this->MOD_SETTINGS['tt_content_showHidden'], '', '', 'id="checkTt_content_showHidden"'); $content .= !$numberOfHiddenElements ? '<span class="text-muted">' . $lang->getLL('hiddenCE', true) . '</span>' : $lang->getLL('hiddenCE', true) . ' (' . $numberOfHiddenElements . ')'; $content .= '</label>'; $content .= '</div>'; } // CSH $content .= BackendUtility::cshItem($this->descrTable, 'quickEdit_selElement'); } return $content; }
/** * Log out current user! * Removes the current session record, sets the internal ->user array to a blank string; * Thereby the current user (if any) is effectively logged out! * * @return void * @todo Define visibility */ public function logoff() { if ($this->writeDevLog) { GeneralUtility::devLog('logoff: ses_id = ' . $this->id, 'TYPO3\\CMS\\Core\\Authentication\\AbstractUserAuthentication'); } // Release the locked records \TYPO3\CMS\Backend\Utility\BackendUtility::lockRecords(); // Hook for pre-processing the logoff() method, requested and implemented by andreas.otto@dkd.de: if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_userauth.php']['logoff_pre_processing'])) { $_params = array(); foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_userauth.php']['logoff_pre_processing'] as $_funcRef) { if ($_funcRef) { GeneralUtility::callUserFunction($_funcRef, $_params, $this); } } } $this->db->exec_DELETEquery($this->session_table, 'ses_id = ' . $this->db->fullQuoteStr($this->id, $this->session_table) . ' AND ses_name = ' . $this->db->fullQuoteStr($this->name, $this->session_table)); $this->user = NULL; // Hook for post-processing the logoff() method, requested and implemented by andreas.otto@dkd.de: if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_userauth.php']['logoff_post_processing'])) { $_params = array(); foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_userauth.php']['logoff_post_processing'] as $_funcRef) { if ($_funcRef) { GeneralUtility::callUserFunction($_funcRef, $_params, $this); } } } }
/** * Injects the request object for the current request or subrequest * Simply calls main() and init() and outputs the content * * @param ServerRequestInterface $request the current request * @param ResponseInterface $response * @return ResponseInterface the response with the content */ public function mainAction(ServerRequestInterface $request, ResponseInterface $response) { BackendUtility::lockRecords(); $GLOBALS['SOBE'] = $this; $this->init(); $this->clearCache(); $this->main(); $this->moduleTemplate->setContent($this->content); $response->getBody()->write($this->moduleTemplate->renderContent()); return $response; }
/** * Injects the request object for the current request or subrequest * * @param ServerRequestInterface $request the current request * @param ResponseInterface $response * @return ResponseInterface the response with the content */ public function mainAction(ServerRequestInterface $request, ResponseInterface $response) { BackendUtility::lockRecords(); // Preprocessing, storing data if submitted to $this->preInit(); // Checks, if a save button has been clicked (or the doSave variable is sent) if ($this->doProcessData()) { $this->processData(); } $this->init(); $this->main(); $response->getBody()->write($this->moduleTemplate->renderContent()); return $response; }
/** * Log out current user! * Removes the current session record, sets the internal ->user array to a blank string; * Thereby the current user (if any) is effectively logged out! * * @return void */ public function logoff() { if ($this->writeDevLog) { GeneralUtility::devLog('logoff: ses_id = ' . $this->id, AbstractUserAuthentication::class); } // Release the locked records BackendUtility::lockRecords(); // Hook for pre-processing the logoff() method, requested and implemented by andreas.otto@dkd.de: if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_userauth.php']['logoff_pre_processing'])) { $_params = array(); foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_userauth.php']['logoff_pre_processing'] as $_funcRef) { if ($_funcRef) { GeneralUtility::callUserFunction($_funcRef, $_params, $this); } } } GeneralUtility::makeInstance(ConnectionPool::class)->getConnectionForTable($this->session_table)->delete($this->session_table, ['ses_id' => $this->id, 'ses_name' => $this->name]); $this->user = null; // Hook for post-processing the logoff() method, requested and implemented by andreas.otto@dkd.de: if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_userauth.php']['logoff_post_processing'])) { $_params = array(); foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_userauth.php']['logoff_post_processing'] as $_funcRef) { if ($_funcRef) { GeneralUtility::callUserFunction($_funcRef, $_params, $this); } } } }
/** * Sets the lock for a record from table/id, IF $this->lockRecords is set! * * @param string $table The table name * @param int $id The id of the record * @param int $pid The pid of the record * @return void */ public function lockRecord($table, $id, $pid = 0) { if ($this->lockRecords) { BackendUtility::lockRecords($table, $id, $pid); } }
/** * Sets the lock for a record from table/id, IF $this->lockRecords is set! * * @param string $table The table name * @param integer $id The id of the record * @param integer $pid The pid of the record * @return void * @todo Define visibility */ public function lockRecord($table, $id, $pid = 0) { if ($this->lockRecords) { \TYPO3\CMS\Backend\Utility\BackendUtility::lockRecords($table, $id, $pid); } }