From 35d9b1ffd427a9c0784c856ddf9b0bb1d86d4f95 Mon Sep 17 00:00:00 2001
From: Benjamin Mack <benni@typo3.org>
Date: Tue, 24 Mar 2015 16:29:38 +0100
Subject: [PATCH] [TASK] Make alt_doc.php dispatched

Resolves: #65292
Releases: master
Change-Id: Ib94e59bf5d9896186aa6923eab50a2236308bd6a
Reviewed-on: http://review.typo3.org/38113
Reviewed-by: Wouter Wolters <typo3@wouterwolters.nl>
Tested-by: Wouter Wolters <typo3@wouterwolters.nl>
Reviewed-by: Anja Leichsenring <aleichsenring@ab-softlab.de>
Tested-by: Anja Leichsenring <aleichsenring@ab-softlab.de>
---
 typo3/alt_doc.php                             |  4 ++
 typo3/close.html                              |  4 +-
 .../backend/Classes/ClickMenu/ClickMenu.php   | 23 +++++++---
 .../backend/Classes/Clipboard/Clipboard.php   | 11 ++---
 .../Classes/Controller/BackendController.php  |  1 +
 .../Controller/EditDocumentController.php     | 39 +++++++++-------
 .../Controller/PageLayoutController.php       |  7 ++-
 .../SimpleDataHandlerController.php           |  4 +-
 .../Controller/Wizard/AddController.php       | 16 ++++---
 .../Controller/Wizard/EditController.php      | 25 ++++++----
 .../Controller/Wizard/ListController.php      |  2 +-
 .../Classes/Form/Element/InlineElement.php    | 11 +++--
 .../backend/Classes/Form/FormEngine.php       | 14 ++++--
 .../Classes/Form/FrontendFormEngine.php       |  2 +-
 .../Classes/Search/LiveSearch/LiveSearch.php  |  8 ++--
 .../Classes/Utility/BackendUtility.php        | 10 ++--
 .../backend/Classes/View/PageLayoutView.php   | 14 +++---
 .../backend/Modules/FormEngine/conf.php       |  4 ++
 .../backend/Modules/FormEngine/index.php      | 41 +++++++++++++++++
 .../Modules/NewContentElement/index.php       |  9 +++-
 .../components/pagetree/javascript/actions.js |  2 +-
 typo3/sysext/backend/ext_tables.php           |  6 +++
 .../ViewHelpers/EditRecordViewHelper.php      | 41 +++++++++++++++++
 .../Partials/BackendUser/IndexListRow.html    |  4 +-
 .../BackendUserGroup/IndexListRow.html        |  7 +--
 .../Private/Templates/BackendUser/Index.html  |  2 +-
 .../Templates/BackendUserGroup/Index.html     |  2 +-
 typo3/sysext/cms/layout/db_new_content_el.php |  8 +++-
 .../core/Classes/Database/QueryView.php       | 12 +++--
 .../FrontendEditingController.php             |  6 +--
 .../feedit/Classes/FrontendEditPanel.php      | 14 +++---
 typo3/sysext/filelist/Classes/FileList.php    |  3 +-
 .../ContentObject/ContentObjectRenderer.php   |  6 +--
 .../frontend/Classes/View/AdminPanelView.php  | 16 +++++--
 .../ToolbarItems/OpendocsToolbarItem.php      |  8 ++--
 .../sysext/recordlist/Classes/RecordList.php  |  2 +-
 .../RecordList/AbstractDatabaseRecordList.php | 14 ++++--
 .../Classes/Utility/RecyclerUtility.php       |  2 +-
 .../Classes/Report/Status/SecurityStatus.php  | 11 +++--
 .../sysext/sys_action/Classes/ActionTask.php  | 46 +++++++++++++++----
 .../ViewHelpers/EditLinkViewHelper.php        |  9 +++-
 typo3/sysext/t3editor/res/tsref/tsref.xml     |  2 +-
 .../Classes/Controller/PreviewController.php  |  1 +
 .../Public/JavaScript/configuration.js        |  2 +-
 44 files changed, 337 insertions(+), 138 deletions(-)
 create mode 100644 typo3/sysext/backend/Modules/FormEngine/conf.php
 create mode 100644 typo3/sysext/backend/Modules/FormEngine/index.php
 create mode 100644 typo3/sysext/beuser/Classes/ViewHelpers/EditRecordViewHelper.php

diff --git a/typo3/alt_doc.php b/typo3/alt_doc.php
index 3f007cbe85fc..72a71a73a7ee 100644
--- a/typo3/alt_doc.php
+++ b/typo3/alt_doc.php
@@ -22,6 +22,10 @@
 require_once 'init.php';
 \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);
 
diff --git a/typo3/close.html b/typo3/close.html
index fac2d38368d0..eb6ab3f35749 100644
--- a/typo3/close.html
+++ b/typo3/close.html
@@ -6,7 +6,7 @@
 <html>
 <head>
 
-	<!-- Close script, used in particular by the alt_doc.php script to close the current edit window -->
+	<!-- Close script, used in particular by FormEngine to close the current edit window -->
 
 	<!-- TYPO3 Script ID: typo3/close.html -->
 	<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
@@ -20,4 +20,4 @@
 </head>
 <body>
 </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/typo3/sysext/backend/Classes/ClickMenu/ClickMenu.php b/typo3/sysext/backend/Classes/ClickMenu/ClickMenu.php
index 3f859b42475b..9e586f70b812 100644
--- a/typo3/sysext/backend/Classes/ClickMenu/ClickMenu.php
+++ b/typo3/sysext/backend/Classes/ClickMenu/ClickMenu.php
@@ -652,8 +652,10 @@ class ClickMenu {
 	 * @internal
 	 */
 	public function DB_editAccess($table, $uid) {
-		$addParam = '&columnsOnly=' . rawurlencode((implode(',', $GLOBALS['TCA'][$table]['ctrl']['enablecolumns']) . ($table === 'pages' ? ',extendToSubpages' : '')));
-		$url = 'alt_doc.php?edit[' . $table . '][' . $uid . ']=edit' . $addParam;
+		$url = BackendUtility::getModuleUrl('record_edit', array(
+			'columnsOnly' => rawurlencode((implode(',', $GLOBALS['TCA'][$table]['ctrl']['enablecolumns']) . ($table === 'pages' ? ',extendToSubpages' : ''))),
+			'edit[' . $table . '][' . $uid . ']' => 'edit'
+		));
 		return $this->linkItem($this->languageService->makeEntities($this->languageService->getLL('CM_editAccess')), IconUtility::getSpriteIcon('actions-document-edit-access'), $this->urlRefForCM($url, 'returnUrl'), 1);
 	}
 
@@ -665,7 +667,9 @@ class ClickMenu {
 	 * @internal
 	 */
 	public function DB_editPageProperties($uid) {
-		$url = 'alt_doc.php?edit[pages][' . $uid . ']=edit';
+		$url = BackendUtility::getModuleUrl('record_edit', array(
+			'edit[pages][' . $uid . ']' => 'edit'
+		));
 		return $this->linkItem($this->languageService->makeEntities($this->languageService->getLL('CM_editPageProperties')), IconUtility::getSpriteIcon('actions-page-open'), $this->urlRefForCM($url, 'returnUrl'), 1);
 	}
 
@@ -685,16 +689,21 @@ class ClickMenu {
 		$loc = 'top.content.list_frame';
 		$addParam = '';
 		$theIcon = 'actions-document-open';
+
+		$link = BackendUtility::getModuleUrl('record_edit', array(
+			'edit[' . $table . '][' . $uid . ']' => 'edit'
+		));
+
 		if ($this->iParts[0] === 'pages' && $this->iParts[1] && $this->backendUser->check('modules', $pageModule)) {
 			$this->editPageIconSet = TRUE;
 			if ($this->backendUser->uc['classicPageEditMode']) {
 				$addParam = '&editRegularContentFromId=' . (int)$this->iParts[1];
 			} else {
-				$editOnClick = 'if(' . $loc . '){' . $loc . '.location.href=top.TS.PATH_typo3+\'alt_doc.php?returnUrl=\'+top.rawurlencode(' . $this->frameLocation(($loc . '.document')) . '.pathname+' . $this->frameLocation(($loc . '.document')) . '.search)+\'&edit[' . $table . '][' . $uid . ']=edit' . $addParam . '\';}';
+				$editOnClick = 'if(' . $loc . '){' . $loc . '.location.href=top.TS.PATH_typo3+\'' . $link . '&returnUrl=\'+top.rawurlencode(' . $this->frameLocation(($loc . '.document')) . '.pathname+' . $this->frameLocation(($loc . '.document')) . '.search)+\'' . $addParam . '\';}';
 			}
 		}
 		if (!$editOnClick) {
-			$editOnClick = 'if(' . $loc . '){' . $loc . '.location.href=top.TS.PATH_typo3+\'alt_doc.php?returnUrl=\'+top.rawurlencode(' . $this->frameLocation(($loc . '.document')) . '.pathname+' . $this->frameLocation(($loc . '.document')) . '.search)+\'&edit[' . $table . '][' . $uid . ']=edit' . $addParam . '\';}';
+			$editOnClick = 'if(' . $loc . '){' . $loc . '.location.href=top.TS.PATH_typo3+\'' . $link . '&returnUrl=\'+top.rawurlencode(' . $this->frameLocation(($loc . '.document')) . '.pathname+' . $this->frameLocation(($loc . '.document')) . '.search)+\'' . $addParam . '\';}';
 		}
 		return $this->linkItem($this->label('edit'), IconUtility::getSpriteIcon($theIcon), $editOnClick . ';');
 	}
@@ -711,8 +720,8 @@ class ClickMenu {
 		$frame = 'top.content.list_frame';
 		$location = $this->frameLocation($frame . '.document');
 		$module = $this->listFrame
-			? GeneralUtility::quoteJSvalue('alt_doc.php?edit[' . $table . '][-' . $uid . ']=new&returnUrl=') . '+top.rawurlencode(' . $location . '.pathname+' . $location . '.search)'
-			: GeneralUtility::quoteJSvalue(BackendUtility::getModuleUrl('db_new', ['id' => (int)$uid]));
+			? GeneralUtility::quoteJSvalue(BackendUtility::getModuleUrl('record_edit', array('edit[' . $table . '][-' . $uid . ']' => 'new')) . '&returnUrl=') . '+top.rawurlencode(' . $location . '.pathname+' . $location . '.search)'
+			: GeneralUtility::quoteJSvalue(BackendUtility::getModuleUrl('db_new', array('id' => (int)$uid)));
 		$editOnClick = 'if(' . $frame . '){' . $frame . '.location.href=top.TS.PATH_typo3+' . $module . ';}';
 		$icon = IconUtility::getSpriteIcon('actions-' . ($table === 'pages' ? 'page' : 'document') . '-new');
 		return $this->linkItem($this->label('new'), $icon, $editOnClick);
diff --git a/typo3/sysext/backend/Classes/Clipboard/Clipboard.php b/typo3/sysext/backend/Classes/Clipboard/Clipboard.php
index 6fe3fd461c1a..fce53f6561a5 100644
--- a/typo3/sysext/backend/Classes/Clipboard/Clipboard.php
+++ b/typo3/sysext/backend/Classes/Clipboard/Clipboard.php
@@ -592,20 +592,19 @@ class Clipboard {
 	/**
 	 * editUrl of all current elements
 	 * ONLY database
-	 * Links to alt_doc.php
+	 * Links to FormEngine
 	 *
-	 * @return string The URL to alt_doc.php with parameters.
+	 * @return string The URL to FormEngine with parameters.
 	 */
 	public function editUrl() {
+		$parameters = array();
 		// All records
 		$elements = $this->elFromTable('');
-		$editCMDArray = array();
 		foreach ($elements as $tP => $value) {
 			list($table, $uid) = explode('|', $tP);
-			$editCMDArray[] = '&edit[' . $table . '][' . $uid . ']=edit';
+			$parameters['edit[' . $table . '][' . $uid . ']'] = 'edit';
 		}
-		$rU = $this->backPath . 'alt_doc.php?' . implode('', $editCMDArray);
-		return $rU;
+		return BackendUtility::getModuleUrl('record_edit', $parameters);
 	}
 
 	/**
diff --git a/typo3/sysext/backend/Classes/Controller/BackendController.php b/typo3/sysext/backend/Classes/Controller/BackendController.php
index 4476de79868c..34f5724683ab 100644
--- a/typo3/sysext/backend/Classes/Controller/BackendController.php
+++ b/typo3/sysext/backend/Classes/Controller/BackendController.php
@@ -305,6 +305,7 @@ class BackendController {
 			}
 			$this->pageRenderer->addInlineSetting('RecordHistory', 'moduleUrl', BackendUtility::getModuleUrl('record_history'));
 			$this->pageRenderer->addInlineSetting('NewRecord', 'moduleUrl', BackendUtility::getModuleUrl('db_new'));
+			$this->pageRenderer->addInlineSetting('FormEngine', 'moduleUrl', BackendUtility::getModuleUrl('record_edit'));
 		}
 	}
 
diff --git a/typo3/sysext/backend/Classes/Controller/EditDocumentController.php b/typo3/sysext/backend/Classes/Controller/EditDocumentController.php
index f211589c9473..ec0751d46886 100644
--- a/typo3/sysext/backend/Classes/Controller/EditDocumentController.php
+++ b/typo3/sysext/backend/Classes/Controller/EditDocumentController.php
@@ -232,7 +232,7 @@ class EditDocumentController {
 
 	/**
 	 * Return URL script, processed. This contains the script (if any) that we should
-	 * RETURN TO from the alt_doc.php script IF we press the close button. Thus this
+	 * RETURN TO from the FormEngine script IF we press the close button. Thus this
 	 * variable is normally passed along from the calling script so we can properly return if needed.
 	 *
 	 * @var string
@@ -454,7 +454,7 @@ class EditDocumentController {
 		$this->dontStoreDocumentRef = 0;
 		$this->storeTitle = '';
 		// Get session data for the module:
-		$this->docDat = $GLOBALS['BE_USER']->getModuleData('alt_doc.php', 'ses');
+		$this->docDat = $GLOBALS['BE_USER']->getModuleData('FormEngine', 'ses');
 		$this->docHandler = $this->docDat[0];
 		// If a request for closing the document has been sent, act accordingly:
 		if ($this->closeDoc > 0) {
@@ -739,7 +739,7 @@ class EditDocumentController {
 				// Checking if the currently open document is stored in the list of "open documents" - if not, then add it:
 				if (($this->docDat[1] !== $this->storeUrlMd5 || !isset($this->docHandler[$this->storeUrlMd5])) && !$this->dontStoreDocumentRef) {
 					$this->docHandler[$this->storeUrlMd5] = array($this->storeTitle, $this->storeArray, $this->storeUrl, $this->firstEl);
-					$GLOBALS['BE_USER']->pushModuleData('alt_doc.php', array($this->docHandler, $this->storeUrlMd5));
+					$GLOBALS['BE_USER']->pushModuleData('FormEngine', array($this->docHandler, $this->storeUrlMd5));
 					BackendUtility::setUpdateSignal('OpendocsController::updateNumber', count($this->docHandler));
 				}
 				// Module configuration
@@ -1124,11 +1124,11 @@ class EditDocumentController {
 	 */
 	public function functionMenus() {
 		if ($GLOBALS['BE_USER']->getTSConfigVal('options.enableShowPalettes')) {
-			// Show palettes:
+			// Show palettes
 
 			return '<div class="checkbox">' .
 				'<label for="checkShowPalettes">' .
-					BackendUtility::getFuncCheck('', 'SET[showPalettes]', $this->MOD_SETTINGS['showPalettes'], 'alt_doc.php', (GeneralUtility::implodeArrayForUrl('', array_merge($this->R_URL_getvars, array('SET' => ''))) . BackendUtility::getUrlToken('editRecord')), 'id="checkShowPalettes"') .
+					BackendUtility::getFuncCheck('', 'SET[showPalettes]', $this->MOD_SETTINGS['showPalettes'], BackendUtility::getModuleUrl('record_edit'), (GeneralUtility::implodeArrayForUrl('', array_merge($this->R_URL_getvars, array('SET' => ''))) . BackendUtility::getUrlToken('editRecord')), 'id="checkShowPalettes"') .
 					$GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:labels.showPalettes', TRUE) .
 				'</label>'.
 			'</div>';
@@ -1233,11 +1233,16 @@ class EditDocumentController {
 							$newTranslation = isset($rowsByLang[$lang['uid']]) ? '' : ' [' . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:labels.new', TRUE) . ']';
 							// Create url for creating a localized record
 							if ($newTranslation) {
-								$href = $this->doc->issueCommand('&cmd[' . $table . '][' . $rowsByLang[0]['uid'] . '][localize]=' . $lang['uid'], $this->backPath . 'alt_doc.php?justLocalized=' . rawurlencode(($table . ':' . $rowsByLang[0]['uid'] . ':' . $lang['uid'])) . '&returnUrl=' . rawurlencode($this->retUrl) . BackendUtility::getUrlToken('editRecord'));
+								$redirectUrl = BackendUtility::getModuleUrl('record_edit', array(
+									'justLocalized' => rawurlencode(($table . ':' . $rowsByLang[0]['uid'] . ':' . $lang['uid'])),
+									'returnUrl' => rawurlencode($this->retUrl) . BackendUtility::getUrlToken('editRecord')
+								));
+								$href = $this->doc->issueCommand('&cmd[' . $table . '][' . $rowsByLang[0]['uid'] . '][localize]=' . $lang['uid'], $redirectUrl);
 							} else {
-								$href = $this->backPath . 'alt_doc.php?';
-								$href .= '&edit[' . $table . '][' . $rowsByLang[$lang['uid']]['uid'] . ']=edit';
-								$href .= '&returnUrl=' . rawurlencode($this->retUrl) . BackendUtility::getUrlToken('editRecord');
+								$href = BackendUtility::getModuleUrl('record_edit', array(
+									'edit[' . $table . '][' . $rowsByLang[$lang['uid']]['uid'] . ']' => 'edit',
+									'returnUrl' => rawurlencode($this->retUrl) . BackendUtility::getUrlToken('editRecord')
+								));
 							}
 							$langSelItems[$lang['uid']] = '
 								<option value="' . htmlspecialchars($href) . '"' . ($currentLanguage == $lang['uid'] ? ' selected="selected"' : '') . '>' . htmlspecialchars(($lang['title'] . $newTranslation)) . '</option>';
@@ -1257,7 +1262,7 @@ class EditDocumentController {
 	}
 
 	/**
-	 * Redirects to alt_doc with new parameters to edit a just created localized record
+	 * Redirects to FormEngine with new parameters to edit a just created localized record
 	 *
 	 * @param string $justLocalized String passed by GET &justLocalized=
 	 * @return void
@@ -1268,10 +1273,11 @@ class EditDocumentController {
 			$localizedRecord = $GLOBALS['TYPO3_DB']->exec_SELECTgetSingleRow('uid', $table, $GLOBALS['TCA'][$table]['ctrl']['languageField'] . '=' . (int)$language . ' AND ' . $GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField'] . '=' . (int)$orig_uid . BackendUtility::deleteClause($table) . BackendUtility::versioningPlaceholderClause($table));
 			if (is_array($localizedRecord)) {
 				// Create parameters and finally run the classic page module for creating a new page translation
-				$params = '&edit[' . $table . '][' . $localizedRecord['uid'] . ']=edit';
-				$returnUrl = '&returnUrl=' . rawurlencode(GeneralUtility::sanitizeLocalUrl(GeneralUtility::_GP('returnUrl')));
-				$location = $GLOBALS['BACK_PATH'] . 'alt_doc.php?' . $params . $returnUrl . BackendUtility::getUrlToken('editRecord');
-				HttpUtility::redirect($location);
+				$location = BackendUtility::getModuleUrl('record_edit', array(
+					'edit[' . $table . '][' . $localizedRecord['uid'] . ']' => 'edit',
+					'returnUrl' => rawurlencode(GeneralUtility::sanitizeLocalUrl(GeneralUtility::_GP('returnUrl')))
+				));
+				HttpUtility::redirect($location . BackendUtility::getUrlToken('editRecord'));
 			}
 		}
 	}
@@ -1471,7 +1477,7 @@ class EditDocumentController {
 				$this->docHandler = array();
 			}
 			$GLOBALS['BE_USER']->pushModuleData('opendocs::recent', $recentDocs);
-			$GLOBALS['BE_USER']->pushModuleData('alt_doc.php', array($this->docHandler, $this->docDat[1]));
+			$GLOBALS['BE_USER']->pushModuleData('FormEngine', array($this->docHandler, $this->docDat[1]));
 			BackendUtility::setUpdateSignal('OpendocsController::updateNumber', count($this->docHandler));
 		}
 		// If ->returnEditConf is set, then add the current content of editconf to the ->retUrl variable: (used by other scripts, like wizard_add, to know which records was created or so...)
@@ -1480,7 +1486,8 @@ class EditDocumentController {
 		}
 		// If code is NOT set OR set to 1, then make a header location redirect to $this->retUrl
 		if (!$code || $code == 1) {
-			HttpUtility::redirect($this->retUrl);
+			// @todo: find out why we need rawurldecode here!
+			HttpUtility::redirect(rawurldecode($this->retUrl));
 		} else {
 			$this->setDocument('', $this->retUrl);
 		}
diff --git a/typo3/sysext/backend/Classes/Controller/PageLayoutController.php b/typo3/sysext/backend/Classes/Controller/PageLayoutController.php
index 22449342ae8d..b0c26c5f13fa 100644
--- a/typo3/sysext/backend/Classes/Controller/PageLayoutController.php
+++ b/typo3/sysext/backend/Classes/Controller/PageLayoutController.php
@@ -656,14 +656,17 @@ class PageLayoutController {
 		$this->doc->getContextMenuCode();
 		// Set the edit_record value for internal use in this function:
 		$edit_record = $this->edit_record;
-		// If a command to edit all records in a column is issue, then select all those elements, and redirect to alt_doc.php:
+		// If 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 = $GLOBALS['TYPO3_DB']->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 = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
 				$idListA[] = $cRow['uid'];
 			}
-			$url = $GLOBALS['BACK_PATH'] . 'alt_doc.php?edit[tt_content][' . implode(',', $idListA) . ']=edit&returnUrl=' . rawurlencode($this->local_linkThisScript(array('edit_record' => '')));
+			$url = BackendUtility::getModuleUrl('record_edit', array(
+				'edit[tt_content][' . implode(',', $idListA) . ']' => 'edit',
+				'returnUrl' => rawurlencode($this->local_linkThisScript(array('edit_record' => '')))
+			));
 			\TYPO3\CMS\Core\Utility\HttpUtility::redirect($url);
 		}
 		// If the former record edited was the creation of a NEW record, this will look up the created records uid:
diff --git a/typo3/sysext/backend/Classes/Controller/SimpleDataHandlerController.php b/typo3/sysext/backend/Classes/Controller/SimpleDataHandlerController.php
index f136ae469fe7..a04d7d1312b8 100644
--- a/typo3/sysext/backend/Classes/Controller/SimpleDataHandlerController.php
+++ b/typo3/sysext/backend/Classes/Controller/SimpleDataHandlerController.php
@@ -22,8 +22,8 @@ use TYPO3\CMS\Core\Utility\GeneralUtility;
  * sending the posted data to the object.
  *
  * Used by many smaller forms/links in TYPO3, including the QuickEdit module.
- * Is not used by alt_doc.php though (main form rendering script) - that uses the same class (TCEmain) but makes its own initialization (to save the redirect request).
- * For all other cases than alt_doc.php it is recommended to use this script for submitting your editing forms - but the best solution in any case would probably be to link your application to alt_doc.php, that will give you easy form-rendering as well.
+ * Is not used by FormEngine though (main form rendering script) - that uses the same class (TCEmain) but makes its own initialization (to save the redirect request).
+ * For all other cases than FormEngine it is recommended to use this script for submitting your editing forms - but the best solution in any case would probably be to link your application to FormEngine, that will give you easy form-rendering as well.
  *
  * @author Kasper Skårhøj <kasperYYYY@typo3.com>
  */
diff --git a/typo3/sysext/backend/Classes/Controller/Wizard/AddController.php b/typo3/sysext/backend/Classes/Controller/Wizard/AddController.php
index 144a93f093c2..b648951d943f 100644
--- a/typo3/sysext/backend/Classes/Controller/Wizard/AddController.php
+++ b/typo3/sysext/backend/Classes/Controller/Wizard/AddController.php
@@ -54,7 +54,7 @@ class AddController extends AbstractWizardController {
 	public $table;
 
 	/**
-	 * Loaded with the created id of a record when TCEforms (alt_doc.php) returns ...
+	 * Loaded with the created id of a record FormEngine returns ...
 	 *
 	 * @var int
 	 */
@@ -68,7 +68,7 @@ class AddController extends AbstractWizardController {
 	public $P;
 
 	/**
-	 * Information coming back from alt_doc.php script, telling what the table/id was of the newly created record.
+	 * Information coming back from the FormEngine script, telling what the table/id was of the newly created record.
 	 *
 	 * @var array
 	 */
@@ -136,7 +136,7 @@ class AddController extends AbstractWizardController {
 
 	/**
 	 * Main function
-	 * Will issue a location-header, redirecting either BACK or to a new alt_doc.php instance...
+	 * Will issue a location-header, redirecting either BACK or to a new FormEngine instance...
 	 *
 	 * @return void
 	 */
@@ -195,12 +195,16 @@ class AddController extends AbstractWizardController {
 					$tce->process_datamap();
 				}
 			}
-			// Return to the parent alt_doc.php record editing session:
+			// Return to the parent FormEngine record editing session:
 			HttpUtility::redirect(GeneralUtility::sanitizeLocalUrl($this->P['returnUrl']));
 		} else {
-			// Redirecting to alt_doc.php with instructions to create a new record
+			// Redirecting to FormEngine with instructions to create a new record
 			// AND when closing to return back with information about that records ID etc.
-			$redirectUrl = 'alt_doc.php?returnUrl=' . rawurlencode(GeneralUtility::getIndpEnv('REQUEST_URI')) . '&returnEditConf=1&edit[' . $this->P['params']['table'] . '][' . $this->pid . ']=new';
+			$redirectUrl = BackendUtility::getModuleUrl('record_edit', array(
+				'returnEditConf' => 1,
+				'edit[' . $this->P['params']['table'] . '][' . $this->pid . ']' => 'new',
+				'returnUrl' => rawurlencode(GeneralUtility::getIndpEnv('REQUEST_URI'))
+			));
 			HttpUtility::redirect($redirectUrl);
 		}
 	}
diff --git a/typo3/sysext/backend/Classes/Controller/Wizard/EditController.php b/typo3/sysext/backend/Classes/Controller/Wizard/EditController.php
index 44baa931a800..ac2a7a58b085 100644
--- a/typo3/sysext/backend/Classes/Controller/Wizard/EditController.php
+++ b/typo3/sysext/backend/Classes/Controller/Wizard/EditController.php
@@ -56,7 +56,7 @@ class EditController extends AbstractWizardController {
 	 */
 	protected function init() {
 		$this->P = GeneralUtility::_GP('P');
-		// Used for the return URL to alt_doc.php so that we can close the window.
+		// Used for the return URL to FormEngine so that we can close the window.
 		$this->doClose = GeneralUtility::_GP('doClose');
 	}
 
@@ -75,28 +75,35 @@ class EditController extends AbstractWizardController {
 			$field = $this->P['field'];
 			$config = $GLOBALS['TCA'][$table]['columns'][$field]['config'];
 			$fTable = $this->P['currentValue'] < 0 ? $config['neg_foreign_table'] : $config['foreign_table'];
+
+			$urlParameters = array(
+				'returnUrl' => rawurlencode(BackendUtility::getModuleUrl('wizard_edit', array('doClose' => 1)))
+			);
+
 			// Detecting the various allowed field type setups and acting accordingly.
 			if (is_array($config) && $config['type'] == 'select' && !$config['MM'] && $config['maxitems'] <= 1 && \TYPO3\CMS\Core\Utility\MathUtility::canBeInterpretedAsInteger($this->P['currentValue']) && $this->P['currentValue'] && $fTable) {
-				// SINGLE value:
-				$redirectUrl = 'alt_doc.php?returnUrl=' . rawurlencode(BackendUtility::getModuleUrl('wizard_edit', array('doClose' => 1))) . '&edit[' . $fTable . '][' . $this->P['currentValue'] . ']=edit';
-				HttpUtility::redirect($redirectUrl);
+				// SINGLE value
+				$urlParameters['edit[' . $fTable . '][' . $this->P['currentValue'] . ']'] = 'edit';
+				// Redirect to FormEngine
+				$url = BackendUtility::getModuleUrl('record_edit', $urlParameters);
+				HttpUtility::redirect($url);
 			} elseif (is_array($config) && $this->P['currentSelectedValues'] && ($config['type'] == 'select' && $config['foreign_table'] || $config['type'] == 'group' && $config['internal_type'] == 'db')) {
 				// MULTIPLE VALUES:
 				// Init settings:
 				$allowedTables = $config['type'] == 'group' ? $config['allowed'] : $config['foreign_table'] . ',' . $config['neg_foreign_table'];
 				$prependName = 1;
-				$params = '';
 				// Selecting selected values into an array:
 				$dbAnalysis = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Database\RelationHandler::class);
 				$dbAnalysis->start($this->P['currentSelectedValues'], $allowedTables);
 				$value = $dbAnalysis->getValueArray($prependName);
-				// Traverse that array and make parameters for alt_doc.php:
+				// Traverse that array and make parameters for FormEngine
 				foreach ($value as $rec) {
 					$recTableUidParts = GeneralUtility::revExplode('_', $rec, 2);
-					$params .= '&edit[' . $recTableUidParts[0] . '][' . $recTableUidParts[1] . ']=edit';
+					$urlParameters['edit[' . $recTableUidParts[0] . '][' . $recTableUidParts[1] . ']'] = 'edit';
 				}
-				// Redirect to alt_doc.php:
-				HttpUtility::redirect('alt_doc.php?returnUrl=' . rawurlencode(BackendUtility::getModuleUrl('wizard_edit', array('doClose' => 1))) . $params);
+				// Redirect to FormEngine
+				$url = BackendUtility::getModuleUrl('record_edit', $urlParameters);
+				HttpUtility::redirect($url);
 			} else {
 				$this->closeWindow();
 			}
diff --git a/typo3/sysext/backend/Classes/Controller/Wizard/ListController.php b/typo3/sysext/backend/Classes/Controller/Wizard/ListController.php
index f9d8a6b54dff..494570912f86 100644
--- a/typo3/sysext/backend/Classes/Controller/Wizard/ListController.php
+++ b/typo3/sysext/backend/Classes/Controller/Wizard/ListController.php
@@ -63,7 +63,7 @@ class ListController extends AbstractWizardController {
 
 	/**
 	 * Main function
-	 * Will issue a location-header, redirecting either BACK or to a new alt_doc.php instance...
+	 * Will issue a location-header, redirecting either BACK or to a new FormEngine instance...
 	 *
 	 * @return void
 	 */
diff --git a/typo3/sysext/backend/Classes/Form/Element/InlineElement.php b/typo3/sysext/backend/Classes/Form/Element/InlineElement.php
index a475e12911a5..a58d9947275f 100644
--- a/typo3/sysext/backend/Classes/Form/Element/InlineElement.php
+++ b/typo3/sysext/backend/Classes/Form/Element/InlineElement.php
@@ -737,11 +737,12 @@ class InlineElement {
 					'sys_file_metadata',
 					'file = ' . (int)substr($rec['uid_local'], 9) . ' AND sys_language_uid = ' . $rec['sys_language_uid']
 				);
-				$editUid = $recordInDatabase['uid'];
 				if ($GLOBALS['BE_USER']->check('tables_modify', 'sys_file_metadata')) {
-					$editOnClick = 'if(top.content.list_frame){top.content.list_frame.location.href=top.TS.PATH_typo3+\'alt_doc.php?returnUrl=\'+top.rawurlencode('
-						. 'top.content.list_frame.document.location' . '.pathname+top.content.list_frame.document.location' . '.search)+'
-						. '\'&edit[sys_file_metadata][' . (int)$editUid . ']=edit\';}';
+					$url = BackendUtility::getModuleUrl('record_edit', array(
+						'edit[sys_file_metadata][' . (int)$recordInDatabase['uid'] . ']' => 'edit'
+					));
+					$editOnClick = 'if(top.content.list_frame){top.content.list_frame.location.href=top.TS.PATH_typo3+\'' . $url . '&returnUrl=\'+top.rawurlencode('
+						. 'top.content.list_frame.document.location' . '.pathname+top.content.list_frame.document.location' . '.search);}';
 					$title = $languageService->sL('LLL:EXT:lang/locallang_core.xlf:cm.editMetadata');
 					$cells['editmetadata'] = '
 						<a class="btn btn-default" href="#" class="btn" onclick="' . htmlspecialchars($editOnClick) . '" title="' . htmlspecialchars($title) . '">
@@ -2176,7 +2177,7 @@ class InlineElement {
 	}
 
 	/**
-	 * Checks the page access rights (Code for access check mostly taken from alt_doc.php)
+	 * Checks the page access rights (Code for access check mostly taken from EditDocumentController)
 	 * as well as the table access rights of the user.
 	 *
 	 * @param string $cmd The command that should be performed ('new' or 'edit')
diff --git a/typo3/sysext/backend/Classes/Form/FormEngine.php b/typo3/sysext/backend/Classes/Form/FormEngine.php
index 63fd52fef611..62b13fb9ab3c 100644
--- a/typo3/sysext/backend/Classes/Form/FormEngine.php
+++ b/typo3/sysext/backend/Classes/Form/FormEngine.php
@@ -372,7 +372,7 @@ class FormEngine {
 	public $hookObjectsSingleField = array();
 
 	/**
-	 * Rows getting inserted into the alt_doc headers (when called from alt_doc.php)
+	 * Rows getting inserted into the headers (when called from the EditDocumentController)
 	 *
 	 * @var array
 	 */
@@ -920,10 +920,14 @@ class FormEngine {
 						$item = $this->renderDefaultLanguageContent($table, $field, $row, $item);
 						$item = $this->renderDefaultLanguageDiff($table, $field, $row, $item);
 					}
-					// If the record has been saved and the "linkTitleToSelf" is set, we make the field name into a link, which will load ONLY this field in alt_doc.php
+					// If the record has been saved and the "linkTitleToSelf" is set, we make the field name into a link, which will load ONLY this field in the EditDocumentController
 					$label = htmlspecialchars($PA['label'], ENT_COMPAT, 'UTF-8', FALSE);
 					if (MathUtility::canBeInterpretedAsInteger($row['uid']) && $PA['fieldTSConfig']['linkTitleToSelf'] && !GeneralUtility::_GP('columnsOnly')) {
-						$lTTS_url = 'alt_doc.php?edit[' . $table . '][' . $row['uid'] . ']=edit&columnsOnly=' . $field . '&returnUrl=' . rawurlencode($this->thisReturnUrl());
+						$lTTS_url = BackendUtility::getModuleUrl('record_edit', array(
+							'edit[' . $table . '][' . $row['uid'] . ']' => 'edit',
+							'columnsOnly' => $field,
+							'returnUrl' => rawurlencode($this->thisReturnUrl())
+						));
 						$label = '<a href="' . htmlspecialchars($lTTS_url) . '">' . $label . '</a>';
 					}
 
@@ -1366,7 +1370,7 @@ class FormEngine {
 	 * Will register data from original language records if the current record is a translation of another.
 	 * The original data is shown with the edited record in the form.
 	 * The information also includes possibly diff-views of what changed in the original record.
-	 * Function called from outside (see alt_doc.php + quick edit) before rendering a form for a record
+	 * Function called from outside (see EditDocumentController + quick edit) before rendering a form for a record
 	 *
 	 * @param string $table Table name of the record being edited
 	 * @param array $rec Record array of the record being edited
@@ -1664,7 +1668,7 @@ class FormEngine {
 
 	/**
 	 * Wraps all the table rows into a single table.
-	 * Used externally from scripts like alt_doc.php and db_layout.php (which uses TCEforms...)
+	 * Used externally from scripts like EditDocumentController and PageLayoutController (which uses FormEngine)
 	 *
 	 * @param string $c Code to output between table-parts; table rows
 	 * @param array $rec The record
diff --git a/typo3/sysext/backend/Classes/Form/FrontendFormEngine.php b/typo3/sysext/backend/Classes/Form/FrontendFormEngine.php
index 433994761f69..038c8d14930a 100644
--- a/typo3/sysext/backend/Classes/Form/FrontendFormEngine.php
+++ b/typo3/sysext/backend/Classes/Form/FrontendFormEngine.php
@@ -117,7 +117,7 @@ class FrontendFormEngine extends \TYPO3\CMS\Backend\Form\FormEngine {
 
 	/**
 	 * Initializes an anonymous template container.
-	 * The created container can be compared to alt_doc.php in backend-only disposal.
+	 * The created container can be compared to "record_edit" module in backend-only disposal.
 	 *
 	 * @return void
 	 */
diff --git a/typo3/sysext/backend/Classes/Search/LiveSearch/LiveSearch.php b/typo3/sysext/backend/Classes/Search/LiveSearch/LiveSearch.php
index 63b4d07bace4..277e009698ed 100644
--- a/typo3/sysext/backend/Classes/Search/LiveSearch/LiveSearch.php
+++ b/typo3/sysext/backend/Classes/Search/LiveSearch/LiveSearch.php
@@ -244,11 +244,13 @@ class LiveSearch {
 		} else {
 			$permsEdit = $calcPerms & Permission::CONTENT_EDIT;
 		}
-		// "Edit" link: ( Only if permissions to edit the page-record of the content of the parent page ($this->id)
-		// @todo Is there an existing function to generate this link?
+		// "Edit" link - Only if permissions to edit the page-record of the content of the parent page ($this->id)
 		if ($permsEdit) {
 			$returnUrl = BackendUtility::getModuleUrl('web_list', array('id' => $row['pid']));
-			$editLink = 'alt_doc.php?' . '&edit[' . $tableName . '][' . $row['uid'] . ']=edit&returnUrl=' . rawurlencode($returnUrl);
+			$editLink = BackendUtility::getModuleUrl('record_edit', array(
+				'edit[' . $tableName . '][' . $row['uid'] . ']' => 'edit',
+				'returnUrl' => rawurlencode($returnUrl)
+			));
 		}
 		return $editLink;
 	}
diff --git a/typo3/sysext/backend/Classes/Utility/BackendUtility.php b/typo3/sysext/backend/Classes/Utility/BackendUtility.php
index 20d592129f04..94640defe95b 100644
--- a/typo3/sysext/backend/Classes/Utility/BackendUtility.php
+++ b/typo3/sysext/backend/Classes/Utility/BackendUtility.php
@@ -2668,11 +2668,11 @@ class BackendUtility {
 	}
 
 	/**
-	 * Returns a JavaScript string (for an onClick handler) which will load the alt_doc.php script that shows the form for editing of the record(s) you have send as params.
+	 * Returns a JavaScript string (for an onClick handler) which will load the EditDocumentController script that shows the form for editing of the record(s) you have send as params.
 	 * REMEMBER to always htmlspecialchar() content in href-properties to ampersands get converted to entities (XHTML requirement and XSS precaution)
 	 *
-	 * @param string $params Parameters sent along to alt_doc.php. This requires a much more details description which you must seek in Inside TYPO3s documentation of the alt_doc.php API. And example could be '&edit[pages][123] = edit' which will show edit form for page record 123.
-	 * @param string $backPath Must point back to the TYPO3_mainDir directory (where alt_doc.php is)
+	 * @param string $params Parameters sent along to EditDocumentController. This requires a much more details description which you must seek in Inside TYPO3s documentation of the FormEngine API. And example could be '&edit[pages][123] = edit' which will show edit form for page record 123.
+	 * @param string $backPath Must point back to the TYPO3_mainDir directory (where the main entry point is)
 	 * @param string $requestUri An optional returnUrl you can set - automatically set to REQUEST_URI.
 	 *
 	 * @return string
@@ -2683,7 +2683,7 @@ class BackendUtility {
 			? '\'+T3_THIS_LOCATION+\''
 			: rawurlencode($requestUri ?: GeneralUtility::getIndpEnv('REQUEST_URI'));
 		$retUrlParam = 'returnUrl=' . $returnUrl;
-		return 'window.location.href=\'' . $backPath . 'alt_doc.php?' . $retUrlParam . $params . '\'; return false;';
+		return 'window.location.href=\'' . self::getModuleUrl('record_edit', array(), $backPath) . '&' . $retUrlParam . $params . '\'; return false;';
 	}
 
 	/**
@@ -3266,7 +3266,7 @@ class BackendUtility {
 	 * @param int $uid Record uid
 	 * @return array
 	 * @internal
-	 * @see class.db_layout.inc, alt_db_navframe.php, alt_doc.php, db_layout.php
+	 * @see class.db_layout.inc, alt_db_navframe.php, EditDocumentController, db_layout.php
 	 */
 	static public function isRecordLocked($table, $uid) {
 		if (!is_array($GLOBALS['LOCKED_RECORDS'])) {
diff --git a/typo3/sysext/backend/Classes/View/PageLayoutView.php b/typo3/sysext/backend/Classes/View/PageLayoutView.php
index 6cf15cdbb398..06daea517e34 100644
--- a/typo3/sysext/backend/Classes/View/PageLayoutView.php
+++ b/typo3/sysext/backend/Classes/View/PageLayoutView.php
@@ -1228,8 +1228,8 @@ class PageLayoutView extends \TYPO3\CMS\Recordlist\RecordList\AbstractDatabaseRe
 	 * Draw header for a content element column:
 	 *
 	 * @param string $colName Column name
-	 * @param string $editParams Edit params (Syntax: &edit[...] for alt_doc.php)
-	 * @param string $newParams New element params (Syntax: &edit[...] for alt_doc.php) OBSOLETE
+	 * @param string $editParams Edit params (Syntax: &edit[...] for FormEngine)
+	 * @param string $newParams New element params (Syntax: &edit[...] for FormEngine) OBSOLETE
 	 * @param array|NULL $pasteParams Paste element params (i.e. array(colPos => 1, sys_language_uid => 2))
 	 * @return string HTML table
 	 */
@@ -1832,10 +1832,12 @@ class PageLayoutView extends \TYPO3\CMS\Recordlist\RecordList\AbstractDatabaseRe
 			}
 			// If any languages are left, make selector:
 			if (count($langSelItems) > 1) {
-				$onChangeContent = 'window.location.href=\'' . $this->backPath . 'alt_doc.php?&edit[pages_language_overlay]['
-					. $id . ']=new&overrideVals[pages_language_overlay][doktype]=' . (int)$this->pageRecord['doktype']
-					. '&overrideVals[pages_language_overlay][sys_language_uid]=\'+this.options[this.selectedIndex].value+\'&returnUrl='
-					. rawurlencode(GeneralUtility::getIndpEnv('REQUEST_URI')) . '\'';
+				$url = BackendUtility::getModuleUrl('record_edit', array(
+					'edit[pages_language_overlay]['. $id . ']' => 'new',
+					'overrideVals[pages_language_overlay][doktype]' => (int)$this->pageRecord['doktype'],
+					'returnUrl' => rawurlencode(GeneralUtility::getIndpEnv('REQUEST_URI'))
+				), $this->backPath);
+				$onChangeContent = 'window.location.href=\'' . $url . '&overrideVals[pages_language_overlay][sys_language_uid]=\'+this.options[this.selectedIndex].value';
 				return '<div class="form-inline form-inline-spaced">'
 					. '<div class="form-group">'
 					. '<label for="createNewLanguage">'
diff --git a/typo3/sysext/backend/Modules/FormEngine/conf.php b/typo3/sysext/backend/Modules/FormEngine/conf.php
new file mode 100644
index 000000000000..11d101d897f9
--- /dev/null
+++ b/typo3/sysext/backend/Modules/FormEngine/conf.php
@@ -0,0 +1,4 @@
+<?php
+// Required for mod.php
+$MCONF['name'] = 'record_edit';
+$MCONF['script'] = '_DISPATCH';
diff --git a/typo3/sysext/backend/Modules/FormEngine/index.php b/typo3/sysext/backend/Modules/FormEngine/index.php
new file mode 100644
index 000000000000..5aa840930716
--- /dev/null
+++ b/typo3/sysext/backend/Modules/FormEngine/index.php
@@ -0,0 +1,41 @@
+<?php
+/*
+ * This file is part of the TYPO3 CMS project.
+ *
+ * It is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, either version 2
+ * of the License, or any later version.
+ *
+ * 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 <kasperYYYY@typo3.com>
+ */
+
+\TYPO3\CMS\Backend\Utility\BackendUtility::lockRecords();
+
+/* @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();
diff --git a/typo3/sysext/backend/Modules/NewContentElement/index.php b/typo3/sysext/backend/Modules/NewContentElement/index.php
index 626251cf019c..a7368cf6d2f6 100644
--- a/typo3/sysext/backend/Modules/NewContentElement/index.php
+++ b/typo3/sysext/backend/Modules/NewContentElement/index.php
@@ -46,7 +46,12 @@ class ext_posMap extends \TYPO3\CMS\Backend\Tree\View\PagePositionMap {
 	 * @return string
 	 */
 	public function onClickInsertRecord($row, $vv, $moveUid, $pid, $sys_lang = 0) {
-		$location = $this->backPath . 'alt_doc.php?edit[tt_content][' . (is_array($row) ? -$row['uid'] : $pid) . ']=new&defVals[tt_content][colPos]=' . $vv . '&defVals[tt_content][sys_language_uid]=' . $sys_lang . '&returnUrl=' . rawurlencode($GLOBALS['SOBE']->R_URI);
+		$location = \TYPO3\CMS\Backend\Utility\BackendUtility::getModuleUrl('record_edit', array(
+			'edit[tt_content][' . (is_array($row) ? -$row['uid'] : $pid) . ']' => 'new',
+			'defVals[tt_content][colPos]' => $vv,
+			'defVals[tt_content][sys_language_uid]' => $sys_lang,
+			'returnUrl' => rawurlencode($GLOBALS['SOBE']->R_URI)
+		));
 		return 'window.location.href=' . \TYPO3\CMS\Core\Utility\GeneralUtility::quoteJSvalue($location) . '+document.editForm.defValues.value; return false;';
 	}
 
@@ -55,4 +60,4 @@ class ext_posMap extends \TYPO3\CMS\Backend\Tree\View\PagePositionMap {
 $GLOBALS['SOBE'] = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Backend\Controller\ContentElement\NewContentElementController::class);
 $GLOBALS['SOBE']->init();
 $GLOBALS['SOBE']->main();
-$GLOBALS['SOBE']->printContent();
\ No newline at end of file
+$GLOBALS['SOBE']->printContent();
diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/extjs/components/pagetree/javascript/actions.js b/typo3/sysext/backend/Resources/Public/JavaScript/extjs/components/pagetree/javascript/actions.js
index 3e49a9f18eea..743acaaad107 100644
--- a/typo3/sysext/backend/Resources/Public/JavaScript/extjs/components/pagetree/javascript/actions.js
+++ b/typo3/sysext/backend/Resources/Public/JavaScript/extjs/components/pagetree/javascript/actions.js
@@ -323,7 +323,7 @@ TYPO3.Components.PageTree.Actions = {
 		}
 
 		TYPO3.Backend.ContentContainer.setUrl(
-			'alt_doc.php?edit[pages][' + node.attributes.nodeData.id + ']=edit&returnUrl=' + returnUrl
+			TYPO3.settings.FormEngine.moduleUrl + '&edit[pages][' + node.attributes.nodeData.id + ']=edit&returnUrl=' + returnUrl
 		);
 	},
 
diff --git a/typo3/sysext/backend/ext_tables.php b/typo3/sysext/backend/ext_tables.php
index 8f4b40362d95..738697687b09 100644
--- a/typo3/sysext/backend/ext_tables.php
+++ b/typo3/sysext/backend/ext_tables.php
@@ -2,6 +2,12 @@
 defined('TYPO3_MODE') or die();
 
 if (TYPO3_MODE === 'BE') {
+	// Register record edit module
+	\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addModulePath(
+		'record_edit',
+		\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::extPath($_EXTKEY) . 'Modules/FormEngine/'
+	);
+
 	// Register record history module
 	\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addModulePath(
 		'record_history',
diff --git a/typo3/sysext/beuser/Classes/ViewHelpers/EditRecordViewHelper.php b/typo3/sysext/beuser/Classes/ViewHelpers/EditRecordViewHelper.php
new file mode 100644
index 000000000000..594a47edf2df
--- /dev/null
+++ b/typo3/sysext/beuser/Classes/ViewHelpers/EditRecordViewHelper.php
@@ -0,0 +1,41 @@
+<?php
+namespace TYPO3\CMS\Beuser\ViewHelpers;
+
+/*
+ * This file is part of the TYPO3 CMS project.
+ *
+ * It is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, either version 2
+ * of the License, or any later version.
+ *
+ * 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!
+ */
+
+use TYPO3\CMS\Backend\Utility\BackendUtility;
+
+/**
+ * Edit Record ViewHelper, see FormEngine logic
+ *
+ * @internal
+ */
+class EditRecordViewHelper extends \TYPO3\CMS\Fluid\Core\ViewHelper\AbstractViewHelper {
+
+	/**
+	 * Returns a URL to link to FormEngine
+	 *
+	 * @param string $parameters Is a set of GET params to send to FormEngine
+	 * @return string URL to FormEngine module + parameters
+	 * @see \TYPO3\CMS\Backend\Utility\BackendUtility::getModuleUrl()
+	 */
+	public function render($parameters) {
+		$parameters = \TYPO3\CMS\Core\Utility\GeneralUtility::explodeUrl2Array($parameters);
+		if (isset($parameters['returnUrl'])) {
+			$parameters['returnUrl'] = rawurlencode($parameters['returnUrl']);
+		}
+		return BackendUtility::getModuleUrl('record_edit', $parameters);
+	}
+
+}
diff --git a/typo3/sysext/beuser/Resources/Private/Partials/BackendUser/IndexListRow.html b/typo3/sysext/beuser/Resources/Private/Partials/BackendUser/IndexListRow.html
index af0d70826d10..a181ff9dda07 100644
--- a/typo3/sysext/beuser/Resources/Private/Partials/BackendUser/IndexListRow.html
+++ b/typo3/sysext/beuser/Resources/Private/Partials/BackendUser/IndexListRow.html
@@ -8,7 +8,7 @@
 		</a>
 	</td>
 	<td class="col-title">
-		<a href="alt_doc.php?edit[be_users][{backendUser.uid}]=edit&amp;returnUrl={returnUrl}">
+		<a href="{bu:editRecord(parameters: 'edit[be_users][{backendUser.uid}]=edit&returnUrl={returnUrl}')}">
 			<b>{backendUser.userName}</b><br />
 			{backendUser.realName}
 		</a>
@@ -27,7 +27,7 @@
 		<f:link.action action="addToCompareList" arguments="{uid: backendUser.uid}" class="btn btn-default"><be:spriteManagerIcon iconName="actions-edit-add"/> <f:translate key="compare" /></f:link.action>
 		<div class="btn-group" role="group">
 			<a class="btn btn-default" href="#" onclick="top.launchView('be_users', '{backendUser.uid}'); return false;"><be:spriteManagerIcon iconName="actions-document-info" /></a>
-			<a class="btn btn-default" href="alt_doc.php?edit[be_users][{backendUser.uid}]=edit&amp;returnUrl={returnUrl}"><be:spriteManagerIcon iconName="actions-document-open" /></a>
+			<a class="btn btn-default" href="{bu:editRecord(parameters: 'edit[be_users][{backendUser.uid}]=edit&returnUrl={returnUrl}')}"><be:spriteManagerIcon iconName="actions-document-open" /></a>
 			<f:if condition="{backendUser.currentlyLoggedIn} == 1">
 				<f:then>
 					<span class="btn btn-default disabled"><be:spriteManagerIcon iconName="empty-empty" /></span>
diff --git a/typo3/sysext/beuser/Resources/Private/Partials/BackendUserGroup/IndexListRow.html b/typo3/sysext/beuser/Resources/Private/Partials/BackendUserGroup/IndexListRow.html
index 6db26e7fcc25..d139fef726ad 100644
--- a/typo3/sysext/beuser/Resources/Private/Partials/BackendUserGroup/IndexListRow.html
+++ b/typo3/sysext/beuser/Resources/Private/Partials/BackendUserGroup/IndexListRow.html
@@ -8,14 +8,15 @@
 		</a>
 	</td>
 	<td class="col-title">
-		<a href="alt_doc.php?edit[be_groups][{backendUserGroup.uid}]=edit&amp;returnUrl={returnUrl}">
+
+		<a href="{bu:editRecord(parameters: 'edit[be_groups][{backendUserGroup.uid}]=edit&returnUrl={returnUrl}')}">
 			<b>{backendUserGroup.title}</b><br />
 			{backendUser.realName}
 		</a>
 	</td>
 	<td>
 		<f:for each="{backendUserGroup.subgroups}" as="subgroup" iteration="subGroupIterator">
-			<a href="alt_doc.php?edit[be_groups][{subgroup.uid}]=edit&amp;returnUrl={returnUrl}">
+			<a href="{bu:editRecord(parameters: 'edit[be_groups][{backendUserGroup.uid}]=edit&returnUrl={returnUrl}')}">
 				{subgroup.title}
 			</a>
 			<f:if condition="{subGroupIterator.isLast}"><f:else>, </f:else></f:if>
@@ -24,7 +25,7 @@
 	<td class="col-control">
 		<div class="btn-group" role="group">
 			<a class="btn btn-default" href="#" onclick="top.launchView('be_groups', '{backendUserGroup.uid}'); return false;"><be:spriteManagerIcon iconName="actions-document-info" /></a>
-			<a class="btn btn-default" href="alt_doc.php?edit[be_groups][{backendUserGroup.uid}]=edit&amp;returnUrl={returnUrl}"><be:spriteManagerIcon iconName="actions-document-open" /></a>
+			<a class="btn btn-default" href="{bu:editRecord(parameters: 'edit[be_groups][{backendUserGroup.uid}]=edit&returnUrl={returnUrl}')}"><be:spriteManagerIcon iconName="actions-document-open" /></a>
 			<f:if condition="{backendUserGroup.hidden}">
 				<f:then>
 					<a class="btn btn-default" href="{bu:issueCommand(parameters: 'data[be_groups][{backendUserGroup.uid}][hidden]=0', redirectUrl: redirectUrl)}"><be:spriteManagerIcon iconName="actions-edit-unhide" options="{title: 'unhide'}" /></a>
diff --git a/typo3/sysext/beuser/Resources/Private/Templates/BackendUser/Index.html b/typo3/sysext/beuser/Resources/Private/Templates/BackendUser/Index.html
index 0915ced4c0e4..b9ea4c0904d7 100644
--- a/typo3/sysext/beuser/Resources/Private/Templates/BackendUser/Index.html
+++ b/typo3/sysext/beuser/Resources/Private/Templates/BackendUser/Index.html
@@ -4,7 +4,7 @@
 <f:layout name="Default" />
 
 <f:section name="iconButtons">
-	<a href="#" onclick="window.location.href='alt_doc.php?returnUrl='+T3_THIS_LOCATION+'&amp;edit[be_users][0]=new'; return false;"><be:spriteManagerIcon iconName="actions-document-new" /></a>
+	<a href="{bu:editRecord:(parameters: 'edit[be_users][0]=new&returnUrl={returnUrl}')}"><be:spriteManagerIcon iconName="actions-document-new" /></a>
 </f:section>
 
 <f:section name="headline">
diff --git a/typo3/sysext/beuser/Resources/Private/Templates/BackendUserGroup/Index.html b/typo3/sysext/beuser/Resources/Private/Templates/BackendUserGroup/Index.html
index f3096da1d945..40e1e1798e28 100644
--- a/typo3/sysext/beuser/Resources/Private/Templates/BackendUserGroup/Index.html
+++ b/typo3/sysext/beuser/Resources/Private/Templates/BackendUserGroup/Index.html
@@ -4,7 +4,7 @@
 <f:layout name="Default" />
 
 <f:section name="iconButtons">
-	<a href="#" onclick="window.location.href='alt_doc.php?returnUrl=' + T3_THIS_LOCATION + '&amp;edit[be_groups][0]=new'; return false;"><be:spriteManagerIcon iconName="actions-document-new" /></a>
+	<a href="{bu:editRecord:(parameters: 'edit[be_groups][0]=new&returnUrl={returnUrl}')}"><be:spriteManagerIcon iconName="actions-document-new" /></a>
 </f:section>
 
 <f:section name="headline">
diff --git a/typo3/sysext/cms/layout/db_new_content_el.php b/typo3/sysext/cms/layout/db_new_content_el.php
index 0b70614f39d5..f75479693e63 100644
--- a/typo3/sysext/cms/layout/db_new_content_el.php
+++ b/typo3/sysext/cms/layout/db_new_content_el.php
@@ -64,8 +64,12 @@ class ext_posMap extends \TYPO3\CMS\Backend\Tree\View\PagePositionMap {
 	 * @return string
 	 */
 	public function onClickInsertRecord($row, $vv, $moveUid, $pid, $sys_lang = 0) {
-		$table = 'tt_content';
-		$location = $this->backPath . 'alt_doc.php?edit[tt_content][' . (is_array($row) ? -$row['uid'] : $pid) . ']=new&defVals[tt_content][colPos]=' . $vv . '&defVals[tt_content][sys_language_uid]=' . $sys_lang . '&returnUrl=' . rawurlencode($GLOBALS['SOBE']->R_URI);
+		$location = \TYPO3\CMS\Backend\Utility\BackendUtility::getModuleUrl('record_edit', array(
+			'edit[tt_content][' . (is_array($row) ? -$row['uid'] : $pid) . ']' => 'new',
+			'defVals[tt_content][colPos]' => $vv,
+			'defVals[tt_content][sys_language_uid]' => $sys_lang,
+			'returnUrl' => rawurlencode($GLOBALS['SOBE']->R_URI)
+		));
 		return 'window.location.href=\'' . $location . '\'+document.editForm.defValues.value; return false;';
 	}
 
diff --git a/typo3/sysext/core/Classes/Database/QueryView.php b/typo3/sysext/core/Classes/Database/QueryView.php
index 288d9cd3b107..bb89246479a4 100644
--- a/typo3/sysext/core/Classes/Database/QueryView.php
+++ b/typo3/sysext/core/Classes/Database/QueryView.php
@@ -545,17 +545,19 @@ class QueryView {
 			$out .= '<a class="btn btn-default" href="#" onClick="top.launchView(\'' . $table . '\',' . $row['uid'] . ',\'' . $GLOBALS['BACK_PATH'] . '\');return false;">' . \TYPO3\CMS\Backend\Utility\IconUtility::getSpriteIcon('status-dialog-information') . '</a>';
 			$out .= '<a class="btn btn-default" href="#" onClick="' . BackendUtility::editOnClick($params, $GLOBALS['BACK_PATH'], (GeneralUtility::getIndpEnv('REQUEST_URI') . GeneralUtility::implodeArrayForUrl('SET', (array)GeneralUtility::_POST('SET')))) . '">' . \TYPO3\CMS\Backend\Utility\IconUtility::getSpriteIcon('actions-document-open') . '</a>';
 		} else {
-			$out .= '<a class="btn btn-default" href="' . GeneralUtility::linkThisUrl(BackendUtility::getModuleUrl('tce_db', arary(), $GLOBALS['BACK_PATH']), array(
+			$out .= '<a class="btn btn-default" href="' . GeneralUtility::linkThisUrl(BackendUtility::getModuleUrl('tce_db', array(), $GLOBALS['BACK_PATH']), array(
 					('cmd[' . $table . '][' . $row['uid'] . '][undelete]') => '1',
 					'redirect' => GeneralUtility::linkThisScript(array())
 				)) . BackendUtility::getUrlToken('tceAction') . '">';
 			$out .= \TYPO3\CMS\Backend\Utility\IconUtility::getSpriteIcon('actions-edit-restore', array('title' => 'undelete only')) . '</a>';
+			$formEngineParameters = array(
+				'edit[' . $table . '][' . $row['uid'] . ']' => 'edit',
+				'returnUrl' => GeneralUtility::linkThisScript(array())
+			);
+			$redirectUrl = BackendUtility::getModuleUrl('record_edit', $formEngineParameters);
 			$out .= '<a class="btn btn-default" href="' . GeneralUtility::linkThisUrl(BackendUtility::getModuleUrl('tce_db', array(), $GLOBALS['BACK_PATH']), array(
 					('cmd[' . $table . '][' . $row['uid'] . '][undelete]') => '1',
-					'redirect' => GeneralUtility::linkThisUrl('alt_doc.php', array(
-						('edit[' . $table . '][' . $row['uid'] . ']') => 'edit',
-						'returnUrl' => GeneralUtility::linkThisScript(array())
-					))
+					'redirect' => $redirectUrl
 				)) . BackendUtility::getUrlToken('tceAction') . '">';
 			$out .= \TYPO3\CMS\Backend\Utility\IconUtility::getSpriteIcon('actions-edit-restore-edit', array('title' => 'undelete and edit')) . '</a>';
 		}
diff --git a/typo3/sysext/core/Classes/FrontendEditing/FrontendEditingController.php b/typo3/sysext/core/Classes/FrontendEditing/FrontendEditingController.php
index 0842f1f048d2..fcf3af60e799 100644
--- a/typo3/sysext/core/Classes/FrontendEditing/FrontendEditingController.php
+++ b/typo3/sysext/core/Classes/FrontendEditing/FrontendEditingController.php
@@ -103,15 +103,15 @@ class FrontendEditingController {
 	}
 
 	/**
-	 * Adds an edit icon to the content string. The edit icon links to alt_doc.php with proper parameters for editing the table/fields of the context.
+	 * Adds an edit icon to the content string. The edit icon links to FormEngine with proper parameters for editing the table/fields of the context.
 	 * This implements TYPO3 context sensitive editing facilities. Only backend users will have access (if properly configured as well).
 	 *
 	 * @param string $content The content to which the edit icons should be appended
-	 * @param string $params The parameters defining which table and fields to edit. Syntax is [tablename]:[fieldname],[fieldname],[fieldname],... OR [fieldname],[fieldname],[fieldname],... (basically "[tablename]:" is optional, default table is the one of the "current record" used in the function). The fieldlist is sent as "&columnsOnly=" parameter to alt_doc.php
+	 * @param string $params The parameters defining which table and fields to edit. Syntax is [tablename]:[fieldname],[fieldname],[fieldname],... OR [fieldname],[fieldname],[fieldname],... (basically "[tablename]:" is optional, default table is the one of the "current record" used in the function). The fieldlist is sent as "&columnsOnly=" parameter to FormEngine
 	 * @param array $conf TypoScript properties for configuring the edit icons.
 	 * @param string $currentRecord The "table:uid" of the record being shown. If empty string then $this->currentRecord is used. For new records (set by $conf['newRecordFromTable']) it's auto-generated to "[tablename]:NEW
 	 * @param array $dataArray Alternative data array to use. Default is $this->data
-	 * @param string $addUrlParamStr Additional URL parameters for the link pointing to alt_doc.php
+	 * @param string $addUrlParamStr Additional URL parameters for the link pointing to FormEngine
 	 * @return string The input content string, possibly with edit icons added (not necessarily in the end but just after the last string of normal content.
 	 */
 	public function displayEditIcons($content, $params, array $conf = array(), $currentRecord = '', array $dataArray = array(), $addUrlParamStr = '') {
diff --git a/typo3/sysext/feedit/Classes/FrontendEditPanel.php b/typo3/sysext/feedit/Classes/FrontendEditPanel.php
index 1be54e75936e..876992b9cbb0 100644
--- a/typo3/sysext/feedit/Classes/FrontendEditPanel.php
+++ b/typo3/sysext/feedit/Classes/FrontendEditPanel.php
@@ -185,15 +185,15 @@ class FrontendEditPanel {
 	}
 
 	/**
-	 * Adds an edit icon to the content string. The edit icon links to alt_doc.php with proper parameters for editing the table/fields of the context.
+	 * Adds an edit icon to the content string. The edit icon links to EditDocumentController with proper parameters for editing the table/fields of the context.
 	 * This implements TYPO3 context sensitive editing facilities. Only backend users will have access (if properly configured as well).
 	 *
 	 * @param string $content The content to which the edit icons should be appended
-	 * @param string $params The parameters defining which table and fields to edit. Syntax is [tablename]:[fieldname],[fieldname],[fieldname],... OR [fieldname],[fieldname],[fieldname],... (basically "[tablename]:" is optional, default table is the one of the "current record" used in the function). The fieldlist is sent as "&columnsOnly=" parameter to alt_doc.php
+	 * @param string $params The parameters defining which table and fields to edit. Syntax is [tablename]:[fieldname],[fieldname],[fieldname],... OR [fieldname],[fieldname],[fieldname],... (basically "[tablename]:" is optional, default table is the one of the "current record" used in the function). The fieldlist is sent as "&columnsOnly=" parameter to EditDocumentController
 	 * @param array $conf TypoScript properties for configuring the edit icons.
 	 * @param string $currentRecord The "table:uid" of the record being shown. If empty string then $this->currentRecord is used. For new records (set by $conf['newRecordFromTable']) it's auto-generated to "[tablename]:NEW
 	 * @param array $dataArr Alternative data array to use. Default is $this->data
-	 * @param string $addUrlParamStr Additional URL parameters for the link pointing to alt_doc.php
+	 * @param string $addUrlParamStr Additional URL parameters for the link pointing to EditDocumentController
 	 * @param string $table
 	 * @param int $editUid
 	 * @param string $fieldList
@@ -207,7 +207,7 @@ class FrontendEditPanel {
 		$iconImg = $conf['iconImg'] ? $conf['iconImg'] : '<img  ' . IconUtility::skinImg(TYPO3_mainDir, 'gfx/edit_fe.gif', 'width="11" height="12" border="0" align="top" ') . ' title="' . htmlspecialchars($iconTitle, ENT_COMPAT, 'UTF-8', FALSE) . '"' . $style . ' class="frontEndEditIcons" alt="" />';
 		$nV = GeneralUtility::_GP('ADMCMD_view') ? 1 : 0;
 		$adminURL = GeneralUtility::getIndpEnv('TYPO3_SITE_URL') . TYPO3_mainDir;
-		$icon = $this->editPanelLinkWrap_doWrap($iconImg, $adminURL . 'alt_doc.php?edit[' . $table . '][' . $editUid . ']=edit&columnsOnly=' . rawurlencode($fieldList) . '&noView=' . $nV . $addUrlParamStr);
+		$icon = $this->editPanelLinkWrap_doWrap($iconImg, $adminURL . BackendUtility::getModuleUrl('record_edit', array('edit[' . $table . '][' . $editUid . ']' => 'edit', 'columnsOnly' => rawurlencode($fieldList), 'noView' => $nV)) . $addUrlParamStr);
 		if ($conf['beforeLastTag'] < 0) {
 			$content = $icon . $content;
 		} elseif ($conf['beforeLastTag'] > 0) {
@@ -241,7 +241,7 @@ class FrontendEditPanel {
 		$adminURL = GeneralUtility::getIndpEnv('TYPO3_SITE_URL') . TYPO3_mainDir;
 		if ($cmd == 'edit') {
 			$rParts = explode(':', $currentRecord);
-			$out = $this->editPanelLinkWrap_doWrap($string, $adminURL . 'alt_doc.php?edit[' . $rParts[0] . '][' . $rParts[1] . ']=edit&noView=' . $nV, $currentRecord);
+			$out = $this->editPanelLinkWrap_doWrap($string, $adminURL . BackendUtility::getModuleUrl('record_edit', array('edit[' . $rParts[0] . '][' . $rParts[1] . ']' => 'edit', 'noView=' . $nV)), $currentRecord);
 		} elseif ($cmd == 'new') {
 			$rParts = explode(':', $currentRecord);
 			if ($rParts[0] == 'pages') {
@@ -250,7 +250,7 @@ class FrontendEditPanel {
 				if (!(int)$nPid) {
 					$nPid = MathUtility::canBeInterpretedAsInteger($rParts[1]) ? -$rParts[1] : $this->frontendController->id;
 				}
-				$out = $this->editPanelLinkWrap_doWrap($string, $adminURL . 'alt_doc.php?edit[' . $rParts[0] . '][' . $nPid . ']=new&noView=' . $nV, $currentRecord);
+				$out = $this->editPanelLinkWrap_doWrap($string, $adminURL . BackendUtility::getModuleUrl('record_edit', array('edit[' . $rParts[0] . '][' . $nPid . ']' => 'new', 'noView' => $nV)), $currentRecord);
 			}
 		} else {
 			if ($confirm && $this->backendUser->jsConfirmation(JsConfirmation::FE_EDIT)) {
@@ -266,7 +266,7 @@ class FrontendEditPanel {
 	}
 
 	/**
-	 * Creates a link to a script (eg. typo3/alt_doc.php or NewRecordController) which either opens in the current frame OR in a pop-up window.
+	 * Creates a link to a script (eg. EditDocumentController or NewRecordController) which either opens in the current frame OR in a pop-up window.
 	 *
 	 * @param string $string The string to wrap in a link, typ. and image used as button in the edit panel.
 	 * @param string $url The URL of the link. Should be absolute if supposed to work with <base> path set.
diff --git a/typo3/sysext/filelist/Classes/FileList.php b/typo3/sysext/filelist/Classes/FileList.php
index d81ca05cbc57..b1617b28de27 100644
--- a/typo3/sysext/filelist/Classes/FileList.php
+++ b/typo3/sysext/filelist/Classes/FileList.php
@@ -696,8 +696,7 @@ class FileList extends AbstractRecordList {
 									} else {
 										$href = $GLOBALS['SOBE']->doc->issueCommand(
 											'&cmd[sys_file_metadata][' . $metaDataRecord['uid'] . '][localize]=' . $languageId,
-											$this->backPath . 'alt_doc.php?justLocalized=' . rawurlencode(('sys_file_metadata:' . $metaDataRecord['uid'] . ':' . $languageId)) .
-											'&returnUrl=' . rawurlencode($this->listURL()) . BackendUtility::getUrlToken('editRecord')
+											BackendUtility::getModuleUrl('record_edit', array('justLocalized' => rawurlencode('sys_file_metadata:' . $metaDataRecord['uid'] . ':' . $languageId), 'returnUrl' => rawurlencode($this->listURL())), $this->backPath) . BackendUtility::getUrlToken('editRecord')
 										);
 										$flagButtonIcon = IconUtility::getSpriteIcon(
 											$flagIcon,
diff --git a/typo3/sysext/frontend/Classes/ContentObject/ContentObjectRenderer.php b/typo3/sysext/frontend/Classes/ContentObject/ContentObjectRenderer.php
index 9bb317a165ea..ef3ebc2190d8 100644
--- a/typo3/sysext/frontend/Classes/ContentObject/ContentObjectRenderer.php
+++ b/typo3/sysext/frontend/Classes/ContentObject/ContentObjectRenderer.php
@@ -8277,15 +8277,15 @@ class ContentObjectRenderer {
 	}
 
 	/**
-	 * Adds an edit icon to the content string. The edit icon links to alt_doc.php with proper parameters for editing the table/fields of the context.
+	 * Adds an edit icon to the content string. The edit icon links to FormEngine with proper parameters for editing the table/fields of the context.
 	 * This implements TYPO3 context sensitive editing facilities. Only backend users will have access (if properly configured as well).
 	 *
 	 * @param string $content The content to which the edit icons should be appended
-	 * @param string $params The parameters defining which table and fields to edit. Syntax is [tablename]:[fieldname],[fieldname],[fieldname],... OR [fieldname],[fieldname],[fieldname],... (basically "[tablename]:" is optional, default table is the one of the "current record" used in the function). The fieldlist is sent as "&columnsOnly=" parameter to alt_doc.php
+	 * @param string $params The parameters defining which table and fields to edit. Syntax is [tablename]:[fieldname],[fieldname],[fieldname],... OR [fieldname],[fieldname],[fieldname],... (basically "[tablename]:" is optional, default table is the one of the "current record" used in the function). The fieldlist is sent as "&columnsOnly=" parameter to FormEngine
 	 * @param array $conf TypoScript properties for configuring the edit icons.
 	 * @param string $currentRecord The "table:uid" of the record being shown. If empty string then $this->currentRecord is used. For new records (set by $conf['newRecordFromTable']) it's auto-generated to "[tablename]:NEW
 	 * @param array $dataArr Alternative data array to use. Default is $this->data
-	 * @param string $addUrlParamStr Additional URL parameters for the link pointing to alt_doc.php
+	 * @param string $addUrlParamStr Additional URL parameters for the link pointing to FormEngine
 	 * @return string The input content string, possibly with edit icons added (not necessarily in the end but just after the last string of normal content.
 	 */
 	public function editIcons($content, $params, array $conf = array(), $currentRecord = '', $dataArr = array(), $addUrlParamStr = '') {
diff --git a/typo3/sysext/frontend/Classes/View/AdminPanelView.php b/typo3/sysext/frontend/Classes/View/AdminPanelView.php
index 687793b64640..a6fad3c296b6 100644
--- a/typo3/sysext/frontend/Classes/View/AdminPanelView.php
+++ b/typo3/sysext/frontend/Classes/View/AdminPanelView.php
@@ -623,9 +623,13 @@ class AdminPanelView {
 			$toolBar .= '<a href="' . htmlspecialchars(TYPO3_mainDir . BackendUtility::getModuleUrl('db_new', ['id' => $id, 'pagesOnly' => 1, 'returnUrl' => $returnUrl])) . '">' . $icon . '</a>';
 		}
 		if ($perms & Permission::PAGE_EDIT) {
-			$params = '&edit[pages][' . $id . ']=edit';
 			$icon = IconUtility::getSpriteIcon('actions-document-open', array('title' => $this->extGetLL('edit_editPageProperties', FALSE)));
-			$toolBar .= '<a href="' . htmlspecialchars(TYPO3_mainDir . 'alt_doc.php?' . $params . '&noView=1&returnUrl=' . rawurlencode($returnUrl)) . '">' . $icon . '</a>';
+			$url = BackendUtility::getModuleUrl('record_edit', array(
+				'edit[pages][' . $id . ']' => 'edit',
+				'noView' => 1,
+				'returnUrl' => rawurlencode($returnUrl)
+			), FALSE, TRUE);
+			$toolBar .= '<a href="' . htmlspecialchars($url) . '">' . $icon . '</a>';
 			if ($GLOBALS['TSFE']->sys_language_uid && $langAllowed) {
 				$row = $GLOBALS['TYPO3_DB']->exec_SELECTgetSingleRow(
 					'uid,pid,t3ver_state',
@@ -636,9 +640,13 @@ class AdminPanelView {
 				);
 				$GLOBALS['TSFE']->sys_page->versionOL('pages_language_overlay', $row);
 				if (is_array($row)) {
-					$params = '&edit[pages_language_overlay][' . $row['uid'] . ']=edit';
 					$icon = IconUtility::getSpriteIcon('mimetypes-x-content-page-language-overlay', array('title' => $this->extGetLL('edit_editPageOverlay', FALSE)));
-					$toolBar .= '<a href="' . htmlspecialchars(TYPO3_mainDir . 'alt_doc.php?' . $params . '&noView=1&returnUrl=' . rawurlencode($returnUrl)) . '">' . $icon . '</a>';
+					$url = BackendUtility::getModuleUrl('record_edit', array(
+						'edit[pages_language_overlay][' . $row['uid'] . ']' => 'edit',
+						'noView' => 1,
+						'returnUrl' => rawurlencode($returnUrl)
+					), FALSE, TRUE);
+					$toolBar .= '<a href="' . htmlspecialchars($url) . '">' . $icon . '</a>';
 				}
 			}
 		}
diff --git a/typo3/sysext/opendocs/Classes/Backend/ToolbarItems/OpendocsToolbarItem.php b/typo3/sysext/opendocs/Classes/Backend/ToolbarItems/OpendocsToolbarItem.php
index b6ad26ecf4c5..166de8a31d54 100644
--- a/typo3/sysext/opendocs/Classes/Backend/ToolbarItems/OpendocsToolbarItem.php
+++ b/typo3/sysext/opendocs/Classes/Backend/ToolbarItems/OpendocsToolbarItem.php
@@ -63,7 +63,7 @@ class OpendocsToolbarItem implements ToolbarItemInterface {
 	 */
 	public function loadDocsFromUserSession() {
 		$backendUser = $this->getBackendUser();
-		list($this->openDocs, ) = $backendUser->getModuleData('alt_doc.php', 'ses');
+		list($this->openDocs, ) = $backendUser->getModuleData('FormEngine', 'ses');
 		$this->recentDocs = $backendUser->getModuleData('opendocs::recent');
 	}
 
@@ -138,7 +138,7 @@ class OpendocsToolbarItem implements ToolbarItemInterface {
 		}
 		$label = htmlspecialchars(strip_tags(htmlspecialchars_decode($document[0])));
 		$icon = \TYPO3\CMS\Backend\Utility\IconUtility::getSpriteIconForRecord($table, $record);
-		$link = $GLOBALS['BACK_PATH'] . 'alt_doc.php?' . $document[2];
+		$link = \TYPO3\CMS\Backend\Utility\BackendUtility::getModuleUrl('record_edit') . '&' . $document[2];
 		$pageId = (int)$document[3]['uid'];
 		if ($document[3]['table'] !== 'pages') {
 			$pageId = (int)$document[3]['pid'];
@@ -223,8 +223,8 @@ class OpendocsToolbarItem implements ToolbarItemInterface {
 			}
 			// Remove it from the list of the open documents, and store the status
 			unset($this->openDocs[$md5sum]);
-			list(, $docDat) = $backendUser->getModuleData('alt_doc.php', 'ses');
-			$backendUser->pushModuleData('alt_doc.php', array($this->openDocs, $docDat));
+			list(, $docDat) = $backendUser->getModuleData('FormEngine', 'ses');
+			$backendUser->pushModuleData('FormEngine', array($this->openDocs, $docDat));
 			$backendUser->pushModuleData('opendocs::recent', $this->recentDocs);
 		}
 		$this->renderAjax($params, $ajaxObj);
diff --git a/typo3/sysext/recordlist/Classes/RecordList.php b/typo3/sysext/recordlist/Classes/RecordList.php
index 03e5eff56bbb..bc3b622f61e4 100644
--- a/typo3/sysext/recordlist/Classes/RecordList.php
+++ b/typo3/sysext/recordlist/Classes/RecordList.php
@@ -405,7 +405,7 @@ class RecordList {
 				' . $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;
+					window.location.href="' . BackendUtility::getModuleUrl('record_edit', array('returnUrl' => rawurlencode(GeneralUtility::getIndpEnv('REQUEST_URI')))) . '&edit["+table+"]["+idList+"]=edit"+addParams;
 				}
 				function editList(table,idList) {	//
 					var list="";
diff --git a/typo3/sysext/recordlist/Classes/RecordList/AbstractDatabaseRecordList.php b/typo3/sysext/recordlist/Classes/RecordList/AbstractDatabaseRecordList.php
index e9e3ea9f0c8f..cec501b002da 100644
--- a/typo3/sysext/recordlist/Classes/RecordList/AbstractDatabaseRecordList.php
+++ b/typo3/sysext/recordlist/Classes/RecordList/AbstractDatabaseRecordList.php
@@ -998,7 +998,7 @@ class AbstractDatabaseRecordList extends AbstractRecordList {
 	}
 
 	/**
-	 * Redirects to TCEforms (alt_doc) if a record is just localized.
+	 * Redirects to FormEngine if a record is just localized.
 	 *
 	 * @param string $justLocalized String with table, orig uid and language separated by ":
 	 * @return void
@@ -1010,10 +1010,14 @@ class AbstractDatabaseRecordList extends AbstractRecordList {
 			if (is_array($localizedRecord)) {
 				// Create parameters and finally run the classic page module for creating a new page translation
 				$url = substr($this->listURL(), strlen($this->backPath));
-				$params = '&edit[' . $table . '][' . $localizedRecord['uid'] . ']=edit';
-				$returnUrl = '&returnUrl=' . rawurlencode($url);
-				$location = $GLOBALS['BACK_PATH'] . 'alt_doc.php?' . $params . $returnUrl;
-				HttpUtility::redirect($location);
+				$editUserAccountUrl = BackendUtility::getModuleUrl(
+					'record_edit',
+					array(
+						'edit[' . $table . '][' . $localizedRecord['uid'] . ']' => 'edit',
+						'returnUrl' => rawurlencode($url)
+					)
+				);
+				HttpUtility::redirect($editUserAccountUrl);
 			}
 		}
 	}
diff --git a/typo3/sysext/recycler/Classes/Utility/RecyclerUtility.php b/typo3/sysext/recycler/Classes/Utility/RecyclerUtility.php
index 0b96c3cbca13..16139dac299c 100644
--- a/typo3/sysext/recycler/Classes/Utility/RecyclerUtility.php
+++ b/typo3/sysext/recycler/Classes/Utility/RecyclerUtility.php
@@ -31,7 +31,7 @@ class RecyclerUtility {
 	 *
 	 ************************************************************/
 	/**
-	 * Checks the page access rights (Code for access check mostly taken from alt_doc.php)
+	 * Checks the page access rights (Code for access check mostly taken from FormEngine)
 	 * as well as the table access rights of the user.
 	 *
 	 * @param string $table The table to check access for
diff --git a/typo3/sysext/reports/Classes/Report/Status/SecurityStatus.php b/typo3/sysext/reports/Classes/Report/Status/SecurityStatus.php
index 515c2d7086ab..b63adbe25eae 100644
--- a/typo3/sysext/reports/Classes/Report/Status/SecurityStatus.php
+++ b/typo3/sysext/reports/Classes/Report/Status/SecurityStatus.php
@@ -71,8 +71,13 @@ class SecurityStatus implements \TYPO3\CMS\Reports\StatusProviderInterface {
 			if (!$secure) {
 				$value = $GLOBALS['LANG']->getLL('status_insecure');
 				$severity = \TYPO3\CMS\Reports\Status::ERROR;
-				$editUserAccountUrl = 'alt_doc.php?returnUrl=' .
-					rawurlencode(BackendUtility::getModuleUrl('system_ReportsTxreportsm1')) . '&edit[be_users][' . $row['uid'] . ']=edit';
+				$editUserAccountUrl = BackendUtility::getModuleUrl(
+					'record_edit',
+					array(
+						'edit[be_users][' . $row['uid'] . ']' => 'edit',
+						'returnUrl' => rawurlencode(BackendUtility::getModuleUrl('system_ReportsTxreportsm1'))
+					)
+				);
 				$message = sprintf($GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:warning.backend_admin'),
 					'<a href="' . htmlspecialchars($editUserAccountUrl) . '">', '</a>');
 			}
@@ -205,4 +210,4 @@ class SecurityStatus implements \TYPO3\CMS\Reports\StatusProviderInterface {
 			$GLOBALS['LANG']->getLL('status_saltedPasswords'), $value, $message, $severity);
 	}
 
-}
\ No newline at end of file
+}
diff --git a/typo3/sysext/sys_action/Classes/ActionTask.php b/typo3/sysext/sys_action/Classes/ActionTask.php
index e63698fbdc94..f4a465710235 100644
--- a/typo3/sysext/sys_action/Classes/ActionTask.php
+++ b/typo3/sysext/sys_action/Classes/ActionTask.php
@@ -158,8 +158,15 @@ class ActionTask implements \TYPO3\CMS\Taskcenter\TaskInterface {
 			$editActionLink = '';
 			// Admins are allowed to edit sys_action records
 			if ($this->getBackendUser()->isAdmin()) {
-				$returnUrl = rawurlencode(GeneralUtility::getIndpEnv('REQUEST_URI'));
-				$link = GeneralUtility::getIndpEnv('TYPO3_REQUEST_DIR') . $GLOBALS['BACK_PATH'] . 'alt_doc.php?returnUrl=' . $returnUrl . '&edit[sys_action][' . $actionRow['uid'] . ']=edit';
+				$link = BackendUtility::getModuleUrl(
+					'record_edit',
+					array(
+						'edit[sys_action][' . $actionRow['uid'] . ']' => 'edit',
+						'returnUrl' => rawurlencode(GeneralUtility::getIndpEnv('REQUEST_URI'))
+					),
+					FALSE,
+					TRUE
+				);
 				$editActionLink = '<a class="edit" href="' . $link . '">' . '<img class="icon"' . \TYPO3\CMS\Backend\Utility\IconUtility::skinImg($GLOBALS['BACK_PATH'], 'gfx/edit2.gif') . ' title="' . $this->getLanguageService()->getLL('edit-sys_action') . '" alt="" />' . $this->getLanguageService()->getLL('edit-sys_action') . '</a>';
 			}
 			$actionList[] = array(
@@ -193,8 +200,15 @@ class ActionTask implements \TYPO3\CMS\Taskcenter\TaskInterface {
 		}
 		// Admin users can create a new action
 		if ($this->getBackendUser()->isAdmin()) {
-			$returnUrl = rawurlencode($this->moduleUrl);
-			$link = GeneralUtility::getIndpEnv('TYPO3_REQUEST_DIR') . $GLOBALS['BACK_PATH'] . 'alt_doc.php?returnUrl=' . $returnUrl . '&edit[sys_action][0]=new';
+			$link = BackendUtility::getModuleUrl(
+				'record_edit',
+				array(
+					'edit[sys_action][0]' => 'new',
+					'returnUrl' => rawurlencode($this->moduleUrl)
+				),
+				FALSE,
+				TRUE
+			);
 			$content .= '<p>' .
 				'<a href="' . $link . '" title="' . $this->getLanguageService()->getLL('new-sys_action') . '">' .
 				\TYPO3\CMS\Backend\Utility\IconUtility::getSpriteIcon('actions-document-new', array('class' => 'icon', 'title' => $this->getLanguageService()->getLL('new-sys_action'))) .
@@ -609,8 +623,15 @@ class ActionTask implements \TYPO3\CMS\Taskcenter\TaskInterface {
 	 * @return void Redirect to form to create a record
 	 */
 	protected function viewNewRecord($record) {
-		$returnUrl = rawurlencode($this->moduleUrl);
-		$link = GeneralUtility::getIndpEnv('TYPO3_REQUEST_DIR') . $GLOBALS['BACK_PATH'] . 'alt_doc.php?returnUrl=' . $returnUrl . '&edit[' . $record['t3_tables'] . '][' . (int)$record['t3_listPid'] . ']=new';
+		$link = BackendUtility::getModuleUrl(
+			'record_edit',
+			array(
+				'edit[' . $record['t3_tables'] . '][' . (int)$record['t3_listPid'] . ']' => 'new',
+				'returnUrl' => rawurlencode($this->moduleUrl)
+			),
+			FALSE,
+			TRUE
+		);
 		\TYPO3\CMS\Core\Utility\HttpUtility::redirect($link);
 	}
 
@@ -637,11 +658,20 @@ class ActionTask implements \TYPO3\CMS\Taskcenter\TaskInterface {
 			if (isset($record['crdate'])) {
 				$description .= ' - ' . BackendUtility::dateTimeAge($record['crdate']);
 			}
+			$link = BackendUtility::getModuleUrl(
+				'record_edit',
+				array(
+					'edit[' . $el['table'] . '][' . $el['id'] . ']' => 'edit',
+					'returnUrl' => rawurlencode($this->moduleUrl)
+				),
+				FALSE,
+				TRUE
+			);
 			$actionList[$el['id']] = array(
 				'title' => $title,
 				'description' => BackendUtility::getRecordTitle($el['table'], $dbAnalysis->results[$el['table']][$el['id']]),
 				'descriptionHtml' => $description,
-				'link' => $GLOBALS['BACK_PATH'] . 'alt_doc.php?returnUrl=' . rawurlencode(GeneralUtility::getIndpEnv('REQUEST_URI')) . '&edit[' . $el['table'] . '][' . $el['id'] . ']=edit',
+				'link' => $link,
 				'icon' => \TYPO3\CMS\Backend\Utility\IconUtility::getSpriteIconForRecord($el['table'], $dbAnalysis->results[$el['table']][$el['id']], array('title' => htmlspecialchars($path)))
 			);
 		}
@@ -787,7 +817,7 @@ class ActionTask implements \TYPO3\CMS\Taskcenter\TaskInterface {
 
 				' . $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;
+					window.location.href="' . BackendUtility::getModuleUrl('record_edit', array('returnUrl' => rawurlencode(GeneralUtility::getIndpEnv('REQUEST_URI')))) . '&edit["+table+"]["+idList+"]=edit"+addParams;
 				}
 				function editList(table,idList) {
 					var list="";
diff --git a/typo3/sysext/sys_note/Classes/ViewHelpers/EditLinkViewHelper.php b/typo3/sysext/sys_note/Classes/ViewHelpers/EditLinkViewHelper.php
index 6f4981237152..4b6909686e4e 100644
--- a/typo3/sysext/sys_note/Classes/ViewHelpers/EditLinkViewHelper.php
+++ b/typo3/sysext/sys_note/Classes/ViewHelpers/EditLinkViewHelper.php
@@ -27,8 +27,13 @@ class EditLinkViewHelper extends \TYPO3\CMS\Fluid\Core\ViewHelper\AbstractViewHe
 	 * @return string
 	 */
 	public function render($id) {
-		$returnUrl = \TYPO3\CMS\Core\Utility\GeneralUtility::getIndpEnv('REQUEST_URI');
-		return $GLOBALS['BACK_PATH'] . 'alt_doc.php?&edit[sys_note][' . $id . ']=edit&returnUrl=' . rawurlencode($returnUrl);
+		return \TYPO3\CMS\Backend\Utility\BackendUtility::getModuleUrl(
+			'record_edit',
+			array(
+				'edit[sys_note][' . $id . ']' => 'edit',
+				'returnUrl' => rawurlencode(\TYPO3\CMS\Core\Utility\GeneralUtility::getIndpEnv('REQUEST_URI'))
+			)
+		);
 	}
 
 }
diff --git a/typo3/sysext/t3editor/res/tsref/tsref.xml b/typo3/sysext/t3editor/res/tsref/tsref.xml
index 426a85c12411..5c5bd8b14147 100644
--- a/typo3/sysext/t3editor/res/tsref/tsref.xml
+++ b/typo3/sysext/t3editor/res/tsref/tsref.xml
@@ -7235,7 +7235,7 @@ Set to value "2" the content will be printed in a table - looks nicer.]]></descr
 ]]></default>
 		</property>
 		<property name="editIcons" type="string">
-			<description><![CDATA[If not empty, then insert an icon linking to the typo3/alt_doc.php with some parameters to build and backend user edit form for certain fields.
+			<description><![CDATA[If not empty, then insert an icon linking to the FormEngine with some parameters to build and backend user edit form for certain fields.
 The value of this property is a list of fields from a table to edit. It's assumed that the current record of the cObj is the record to be edited.
 Syntax: optional tablename : comma list of fieldnames[list of pallette-field names separated by | ]
 
diff --git a/typo3/sysext/workspaces/Classes/Controller/PreviewController.php b/typo3/sysext/workspaces/Classes/Controller/PreviewController.php
index c886bbbc8b2d..c7f93e52d9c9 100644
--- a/typo3/sysext/workspaces/Classes/Controller/PreviewController.php
+++ b/typo3/sysext/workspaces/Classes/Controller/PreviewController.php
@@ -68,6 +68,7 @@ class PreviewController extends AbstractController {
 		foreach ($jsFiles as $jsFile) {
 			$this->pageRenderer->addJsFile($resourcePathJavaScript . $jsFile);
 		}
+		$this->pageRenderer->addInlineSetting('FormEngine', 'moduleUrl', BackendUtility::getModuleUrl('record_edit'));
 		$this->pageRenderer->addInlineSetting('RecordHistory', 'moduleUrl', BackendUtility::getModuleUrl('record_history'));
 		// @todo this part should be done with inlineLocallanglabels
 		$this->pageRenderer->addJsInlineCode('workspace-inline-code', $this->generateJavascript());
diff --git a/typo3/sysext/workspaces/Resources/Public/JavaScript/configuration.js b/typo3/sysext/workspaces/Resources/Public/JavaScript/configuration.js
index 3384ece78f35..48d502721643 100644
--- a/typo3/sysext/workspaces/Resources/Public/JavaScript/configuration.js
+++ b/typo3/sysext/workspaces/Resources/Public/JavaScript/configuration.js
@@ -277,7 +277,7 @@ TYPO3.Workspaces.Configuration.RowButtons = {
 			tooltip: TYPO3.l10n.localize('tooltip.editElementAction'),
 			handler: function(grid, rowIndex, colIndex) {
 				var record = TYPO3.Workspaces.MainStore.getAt(rowIndex);
-				var newUrl = 'alt_doc.php?returnUrl=' + encodeURIComponent(document.location.href) + '&id=' + TYPO3.settings.Workspaces.id + '&edit[' + record.json.table + '][' + record.json.uid + ']=edit';
+				var newUrl = TYPO3.settings.FormEngine.moduleUrl + '&returnUrl=' + encodeURIComponent(document.location.href) + '&id=' + TYPO3.settings.Workspaces.id + '&edit[' + record.json.table + '][' + record.json.uid + ']=edit';
 				// Append workspace of record in all-workspaces view
 				if (TYPO3.settings.Workspaces.allView) {
 					newUrl += '&workspace=' + record.json.t3ver_wsid;
-- 
GitLab