public function edit($intId=null, $ajaxId=null)
	{
		if ($GLOBALS['TL_DCA'][$this->strTable]['config']['notEditable'])
		{
			throw new InternalServerErrorException('Table "' . $this->strTable . '" is not editable.');
		}

		if ($intId != '')
		{
			$this->intId = $intId;
		}

		// Get the current record
		$objRow = $this->Database->prepare("SELECT * FROM " . $this->strTable . " WHERE id=?")
								 ->limit(1)
								 ->execute($this->intId);

		// Redirect if there is no record with the given ID
		if ($objRow->numRows < 1)
		{
			throw new AccessDeniedException('Cannot load record "' . $this->strTable . '.id=' . $this->intId . '".');
		}

		$this->objActiveRecord = $objRow;

		$return = '';
		$this->values[] = $this->intId;
		$this->procedure[] = 'id=?';

		$this->blnCreateNewVersion = false;
		$objVersions = new Versions($this->strTable, $this->intId);

		if (!$GLOBALS['TL_DCA'][$this->strTable]['config']['hideVersionMenu'])
		{
			// Compare versions
			if (Input::get('versions'))
			{
				$objVersions->compare();
			}

			// Restore a version
			if (Input::post('FORM_SUBMIT') == 'tl_version' && Input::post('version') != '')
			{
				$objVersions->restore(Input::post('version'));
				$this->reload();
			}
		}

		$objVersions->initialize();

		// Build an array from boxes and rows
		$this->strPalette = $this->getPalette();
		$boxes = StringUtil::trimsplit(';', $this->strPalette);
		$legends = array();

		if (!empty($boxes))
		{
			foreach ($boxes as $k=>$v)
			{
				$eCount = 1;
				$boxes[$k] = StringUtil::trimsplit(',', $v);

				foreach ($boxes[$k] as $kk=>$vv)
				{
					if (preg_match('/^\[.*\]$/', $vv))
					{
						++$eCount;
						continue;
					}

					if (preg_match('/^\{.*\}$/', $vv))
					{
						$legends[$k] = substr($vv, 1, -1);
						unset($boxes[$k][$kk]);
					}
					elseif ($GLOBALS['TL_DCA'][$this->strTable]['fields'][$vv]['exclude'] || !\is_array($GLOBALS['TL_DCA'][$this->strTable]['fields'][$vv]))
					{
						unset($boxes[$k][$kk]);
					}
				}

				// Unset a box if it does not contain any fields
				if (\count($boxes[$k]) < $eCount)
				{
					unset($boxes[$k]);
				}
			}

			/** @var Session $objSessionBag */
			$objSessionBag = System::getContainer()->get('session')->getBag('contao_backend');

			$class = 'tl_tbox';
			$fs = $objSessionBag->get('fieldset_states');

			// Render boxes
			foreach ($boxes as $k=>$v)
			{
				$arrAjax = array();
				$blnAjax = false;
				$key = '';
				$cls = '';
				$legend = '';

				if (isset($legends[$k]))
				{
					list($key, $cls) = explode(':', $legends[$k]);
					$legend = "\n" . '<legend onclick="AjaxRequest.toggleFieldset(this,\'' . $key . '\',\'' . $this->strTable . '\')">' . ($GLOBALS['TL_LANG'][$this->strTable][$key] ?? $key) . '</legend>';
				}

				if (isset($fs[$this->strTable][$key]))
				{
					$class .= ($fs[$this->strTable][$key] ? '' : ' collapsed');
				}
				else
				{
					$class .= (($cls && $legend) ? ' ' . $cls : '');
				}

				$return .= "\n\n" . '<fieldset' . ($key ? ' id="pal_'.$key.'"' : '') . ' class="' . $class . ($legend ? '' : ' nolegend') . '">' . $legend;
				$thisId = '';

				// Build rows of the current box
				foreach ($v as $vv)
				{
					if ($vv == '[EOF]')
					{
						if ($blnAjax && Environment::get('isAjaxRequest'))
						{
							if ($ajaxId == $thisId)
							{
								return $arrAjax[$thisId] . '<input type="hidden" name="FORM_FIELDS[]" value="'.StringUtil::specialchars($this->strPalette).'">';
							}

							if (\count($arrAjax) > 1)
							{
								$current = "\n" . '<div id="'.$thisId.'" class="subpal cf">' . $arrAjax[$thisId] . '</div>';
								unset($arrAjax[$thisId]);
								end($arrAjax);
								$thisId = key($arrAjax);
								$arrAjax[$thisId] .= $current;
							}
						}

						$return .= "\n" . '</div>';

						continue;
					}

					if (preg_match('/^\[.*\]$/', $vv))
					{
						$thisId = 'sub_' . substr($vv, 1, -1);
						$arrAjax[$thisId] = '';
						$blnAjax = ($ajaxId == $thisId && Environment::get('isAjaxRequest')) ? true : $blnAjax;
						$return .= "\n" . '<div id="'.$thisId.'" class="subpal cf">';

						continue;
					}

					$this->strField = $vv;
					$this->strInputName = $vv;
					$this->varValue = $objRow->$vv;

					// Convert CSV fields (see #2890)
					if ($GLOBALS['TL_DCA'][$this->strTable]['fields'][$this->strField]['eval']['multiple'] && isset($GLOBALS['TL_DCA'][$this->strTable]['fields'][$this->strField]['eval']['csv']))
					{
						$this->varValue = StringUtil::trimsplit($GLOBALS['TL_DCA'][$this->strTable]['fields'][$this->strField]['eval']['csv'], $this->varValue);
					}

					// Call load_callback
					if (\is_array($GLOBALS['TL_DCA'][$this->strTable]['fields'][$this->strField]['load_callback']))
					{
						foreach ($GLOBALS['TL_DCA'][$this->strTable]['fields'][$this->strField]['load_callback'] as $callback)
						{
							if (\is_array($callback))
							{
								$this->import($callback[0]);
								$this->varValue = $this->{$callback[0]}->{$callback[1]}($this->varValue, $this);
							}
							elseif (\is_callable($callback))
							{
								$this->varValue = $callback($this->varValue, $this);
							}
						}
					}

					// Re-set the current value
					$this->objActiveRecord->{$this->strField} = $this->varValue;

					// Build the row and pass the current palette string (thanks to Tristan Lins)
					$blnAjax ? $arrAjax[$thisId] .= $this->row($this->strPalette) : $return .= $this->row($this->strPalette);
				}

				$class = 'tl_box';
				$return .= "\n" . '</fieldset>';
			}
		}

		// Versions overview
		if ($GLOBALS['TL_DCA'][$this->strTable]['config']['enableVersioning'] && !$GLOBALS['TL_DCA'][$this->strTable]['config']['hideVersionMenu'])
		{
			$version = $objVersions->renderDropdown();
		}
		else
		{
			$version = '';
		}

		// Submit buttons
		$arrButtons = array();
		$arrButtons['save'] = '<button type="submit" name="save" id="save" class="tl_submit" accesskey="s">'.$GLOBALS['TL_LANG']['MSC']['save'].'</button>';

		if (!Input::get('nb'))
		{
			$arrButtons['saveNclose'] = '<button type="submit" name="saveNclose" id="saveNclose" class="tl_submit" accesskey="c">'.$GLOBALS['TL_LANG']['MSC']['saveNclose'].'</button>';

			if (!Input::get('nc'))
			{
				if (!$GLOBALS['TL_DCA'][$this->strTable]['config']['closed'] && !$GLOBALS['TL_DCA'][$this->strTable]['config']['notCreatable'])
				{
					$arrButtons['saveNcreate'] = '<button type="submit" name="saveNcreate" id="saveNcreate" class="tl_submit" accesskey="n">'.$GLOBALS['TL_LANG']['MSC']['saveNcreate'].'</button>';

					if (!$GLOBALS['TL_DCA'][$this->strTable]['config']['notCopyable'])
					{
						$arrButtons['saveNduplicate'] = '<button type="submit" name="saveNduplicate" id="saveNduplicate" class="tl_submit" accesskey="d">'.$GLOBALS['TL_LANG']['MSC']['saveNduplicate'].'</button>';
					}
				}

				if ($GLOBALS['TL_DCA'][$this->strTable]['config']['switchToEdit'])
				{
					$arrButtons['saveNedit'] = '<button type="submit" name="saveNedit" id="saveNedit" class="tl_submit" accesskey="e">'.$GLOBALS['TL_LANG']['MSC']['saveNedit'].'</button>';
				}

				if ($GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['mode'] == 4 || \strlen($this->ptable) || $GLOBALS['TL_DCA'][$this->strTable]['config']['switchToEdit'])
				{
					$arrButtons['saveNback'] = '<button type="submit" name="saveNback" id="saveNback" class="tl_submit" accesskey="g">'.$GLOBALS['TL_LANG']['MSC']['saveNback'].'</button>';
				}
			}
		}

		// Call the buttons_callback (see #4691)
		if (\is_array($GLOBALS['TL_DCA'][$this->strTable]['edit']['buttons_callback']))
		{
			foreach ($GLOBALS['TL_DCA'][$this->strTable]['edit']['buttons_callback'] as $callback)
			{
				if (\is_array($callback))
				{
					$this->import($callback[0]);
					$arrButtons = $this->{$callback[0]}->{$callback[1]}($arrButtons, $this);
				}
				elseif (\is_callable($callback))
				{
					$arrButtons = $callback($arrButtons, $this);
				}
			}
		}

		if (\count($arrButtons) < 3)
		{
			$strButtons = implode(' ', $arrButtons);
		}
		else
		{
			$strButtons = array_shift($arrButtons) . ' ';
			$strButtons .= '<div class="split-button">';
			$strButtons .= array_shift($arrButtons) . '<button type="button" id="sbtog">' . Image::getHtml('navcol.svg') . '</button> <ul class="invisible">';

			foreach ($arrButtons as $strButton)
			{
				$strButtons .= '<li>' . $strButton . '</li>';
			}

			$strButtons .= '</ul></div>';
		}

		// Add the buttons and end the form
		$return .= '
</div>
<div class="tl_formbody_submit">
<div class="tl_submit_container">
  ' . $strButtons . '
</div>
</div>
</form>';

		$strVersionField = '';

		// Store the current version number (see #8412)
		if (($intLatestVersion = $objVersions->getLatestVersion()) !== null)
		{
			$strVersionField = '
<input type="hidden" name="VERSION_NUMBER" value="'.$intLatestVersion.'">';
		}

		// Begin the form (-> DO NOT CHANGE THIS ORDER -> this way the onsubmit attribute of the form can be changed by a field)
		$return = $version . Message::generate() . ($this->noReload ? '
<p class="tl_error">'.$GLOBALS['TL_LANG']['ERR']['general'].'</p>' : '') . '
<div id="tl_buttons">' . (Input::get('nb') ? '&nbsp;' : '
<a href="'.$this->getReferer(true).'" class="header_back" title="'.StringUtil::specialchars($GLOBALS['TL_LANG']['MSC']['backBTTitle']).'" accesskey="b" onclick="Backend.getScrollOffset()">'.$GLOBALS['TL_LANG']['MSC']['backBT'].'</a>') . '
</div>
<form action="'.ampersand(Environment::get('request'), true).'" id="'.$this->strTable.'" class="tl_form tl_edit_form" method="post" enctype="' . ($this->blnUploadable ? 'multipart/form-data' : 'application/x-www-form-urlencoded') . '"'.(!empty($this->onsubmit) ? ' onsubmit="'.implode(' ', $this->onsubmit).'"' : '').'>
<div class="tl_formbody_edit">
<input type="hidden" name="FORM_SUBMIT" value="'.$this->strTable.'">
<input type="hidden" name="REQUEST_TOKEN" value="'.REQUEST_TOKEN.'">'.$strVersionField.'
<input type="hidden" name="FORM_FIELDS[]" value="'.StringUtil::specialchars($this->strPalette).'">' . $return;

		// Reload the page to prevent _POST variables from being sent twice
		if (Input::post('FORM_SUBMIT') == $this->strTable && !$this->noReload)
		{
			$arrValues = $this->values;
			array_unshift($arrValues, time());

			// Trigger the onsubmit_callback
			if (\is_array($GLOBALS['TL_DCA'][$this->strTable]['config']['onsubmit_callback']))
			{
				foreach ($GLOBALS['TL_DCA'][$this->strTable]['config']['onsubmit_callback'] as $callback)
				{
					if (\is_array($callback))
					{
						$this->import($callback[0]);
						$this->{$callback[0]}->{$callback[1]}($this);
					}
					elseif (\is_callable($callback))
					{
						$callback($this);
					}
				}
			}

			// Save the current version
			if ($this->blnCreateNewVersion)
			{
				$objVersions->create();

				// Call the onversion_callback
				if (\is_array($GLOBALS['TL_DCA'][$this->strTable]['config']['onversion_callback']))
				{
					@trigger_error('Using the onversion_callback has been deprecated and will no longer work in Contao 5.0. Use the oncreate_version_callback instead.', E_USER_DEPRECATED);

					foreach ($GLOBALS['TL_DCA'][$this->strTable]['config']['onversion_callback'] as $callback)
					{
						if (\is_array($callback))
						{
							$this->import($callback[0]);
							$this->{$callback[0]}->{$callback[1]}($this->strTable, $this->intId, $this);
						}
						elseif (\is_callable($callback))
						{
							$callback($this->strTable, $this->intId, $this);
						}
					}
				}
			}

			// Set the current timestamp (-> DO NOT CHANGE THE ORDER version - timestamp)
			if ($GLOBALS['TL_DCA'][$this->strTable]['config']['dynamicPtable'])
			{
				$this->Database->prepare("UPDATE " . $this->strTable . " SET ptable=?, tstamp=? WHERE id=?")
							   ->execute($this->ptable, time(), $this->intId);
			}
			else
			{
				$this->Database->prepare("UPDATE " . $this->strTable . " SET tstamp=? WHERE id=?")
							   ->execute(time(), $this->intId);
			}

			// Show a warning if the record has been saved by another user (see #8412)
			if ($intLatestVersion !== null && isset($_POST['VERSION_NUMBER']) && $intLatestVersion > Input::post('VERSION_NUMBER'))
			{
				$objTemplate = new BackendTemplate('be_conflict');
				$objTemplate->language = $GLOBALS['TL_LANGUAGE'];
				$objTemplate->title = StringUtil::specialchars($GLOBALS['TL_LANG']['MSC']['versionConflict']);
				$objTemplate->theme = Backend::getTheme();
				$objTemplate->charset = Config::get('characterSet');
				$objTemplate->base = Environment::get('base');
				$objTemplate->h1 = $GLOBALS['TL_LANG']['MSC']['versionConflict'];
				$objTemplate->explain1 = sprintf($GLOBALS['TL_LANG']['MSC']['versionConflict1'], $intLatestVersion, Input::post('VERSION_NUMBER'));
				$objTemplate->explain2 = sprintf($GLOBALS['TL_LANG']['MSC']['versionConflict2'], $intLatestVersion + 1, $intLatestVersion);
				$objTemplate->diff = $objVersions->compare(true);
				$objTemplate->href = Environment::get('request');
				$objTemplate->button = $GLOBALS['TL_LANG']['MSC']['continue'];

				throw new ResponseException($objTemplate->getResponse());
			}

			// Invalidate cache tags
			$this->invalidateCacheTags($this);

			// Redirect
			if (isset($_POST['saveNclose']))
			{
				Message::reset();
				System::setCookie('BE_PAGE_OFFSET', 0, 0);

				$this->redirect($this->getReferer());
			}
			elseif (isset($_POST['saveNedit']))
			{
				Message::reset();
				System::setCookie('BE_PAGE_OFFSET', 0, 0);

				$this->redirect($this->addToUrl($GLOBALS['TL_DCA'][$this->strTable]['list']['operations']['edit']['href'], false, array('s2e', 'act', 'mode', 'pid')));
			}
			elseif (isset($_POST['saveNback']))
			{
				Message::reset();
				System::setCookie('BE_PAGE_OFFSET', 0, 0);

				if ($this->ptable == '')
				{
					$this->redirect(TL_SCRIPT . '?do=' . Input::get('do'));
				}
				// TODO: try to abstract this
				elseif (($this->ptable == 'tl_theme' && $this->strTable == 'tl_style_sheet') || ($this->ptable == 'tl_page' && $this->strTable == 'tl_article'))
				{
					$this->redirect($this->getReferer(false, $this->strTable));
				}
				else
				{
					$this->redirect($this->getReferer(false, $this->ptable));
				}
			}
			elseif (isset($_POST['saveNcreate']))
			{
				Message::reset();
				System::setCookie('BE_PAGE_OFFSET', 0, 0);

				$strUrl = TL_SCRIPT . '?do=' . Input::get('do');

				if (isset($_GET['table']))
				{
					$strUrl .= '&amp;table=' . Input::get('table');
				}

				// Tree view
				if ($this->treeView)
				{
					$strUrl .= '&amp;act=create&amp;mode=1&amp;pid=' . $this->intId;
				}

				// Parent view
				elseif ($GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['mode'] == 4)
				{
					$strUrl .= $this->Database->fieldExists('sorting', $this->strTable) ? '&amp;act=create&amp;mode=1&amp;pid=' . $this->intId : '&amp;act=create&amp;mode=2&amp;pid=' . $this->activeRecord->pid;
				}

				// List view
				else
				{
					$strUrl .= ($this->ptable != '') ? '&amp;act=create&amp;mode=2&amp;pid=' . CURRENT_ID : '&amp;act=create';
				}

				$this->redirect($strUrl . '&amp;rt=' . REQUEST_TOKEN);
			}
			elseif (isset($_POST['saveNduplicate']))
			{
				Message::reset();
				System::setCookie('BE_PAGE_OFFSET', 0, 0);

				$strUrl = TL_SCRIPT . '?do=' . Input::get('do');

				if (isset($_GET['table']))
				{
					$strUrl .= '&amp;table=' . Input::get('table');
				}

				// Tree view
				if ($this->treeView)
				{
					$strUrl .= '&amp;act=copy&amp;mode=1&amp;id=' . $this->intId . '&amp;pid=' . $this->intId;
				}

				// Parent view
				elseif ($GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['mode'] == 4)
				{
					$strUrl .= $this->Database->fieldExists('sorting', $this->strTable) ? '&amp;act=copy&amp;mode=1&amp;pid=' . $this->intId . '&amp;id=' . $this->intId : '&amp;act=copy&amp;mode=2&amp;pid=' . CURRENT_ID . '&amp;id=' . $this->intId;
				}

				// List view
				else
				{
					$strUrl .= ($this->ptable != '') ? '&amp;act=copy&amp;mode=2&amp;pid=' . CURRENT_ID . '&amp;id=' . CURRENT_ID : '&amp;act=copy&amp;id=' . CURRENT_ID;
				}

				$this->redirect($strUrl . '&amp;rt=' . REQUEST_TOKEN);
			}

			$this->reload();
		}

		// Set the focus if there is an error
		if ($this->noReload)
		{
			$return .= '
<script>
  window.addEvent(\'domready\', function() {
    Backend.vScrollTo(($(\'' . $this->strTable . '\').getElement(\'label.error\').getPosition().y - 20));
  });
</script>';
		}

		return $return;
	}
public function edit($intId=null, $ajaxId=null)
	{
		if ($GLOBALS['TL_DCA'][$this->strTable]['config']['notEditable'])
		{
			throw new InternalServerErrorException('Table "' . $this->strTable . '" is not editable.');
		}

		if ($intId != '')
		{
			$this->intId = $intId;
		}

		
		$objRow = $this->Database->prepare("SELECT * FROM " . $this->strTable . " WHERE id=?")
								 ->limit(1)
								 ->execute($this->intId);

		
		if ($objRow->numRows < 1)
		{
			throw new AccessDeniedException('Cannot load record "' . $this->strTable . '.id=' . $this->intId . '".');
		}

		$this->objActiveRecord = $objRow;

		$return = '';
		$this->values[] = $this->intId;
		$this->procedure[] = 'id=?';

		$this->blnCreateNewVersion = false;
		$objVersions = new Versions($this->strTable, $this->intId);

		if (!$GLOBALS['TL_DCA'][$this->strTable]['config']['hideVersionMenu'])
		{
			
			if (Input::get('versions'))
			{
				$objVersions->compare();
			}

			
			if (Input::post('FORM_SUBMIT') == 'tl_version' && Input::post('version') != '')
			{
				$objVersions->restore(Input::post('version'));
				$this->reload();
			}
		}

		$objVersions->initialize();

		
		$this->strPalette = $this->getPalette();
		$boxes = StringUtil::trimsplit(';', $this->strPalette);
		$legends = array();

		if (!empty($boxes))
		{
			foreach ($boxes as $k=>$v)
			{
				$eCount = 1;
				$boxes[$k] = StringUtil::trimsplit(',', $v);

				foreach ($boxes[$k] as $kk=>$vv)
				{
					if (preg_match('/^\[.*\]$/', $vv))
					{
						++$eCount;
						continue;
					}

					if (preg_match('/^\{.*\}$/', $vv))
					{
						$legends[$k] = substr($vv, 1, -1);
						unset($boxes[$k][$kk]);
					}
					elseif ($GLOBALS['TL_DCA'][$this->strTable]['fields'][$vv]['exclude'] || !\is_array($GLOBALS['TL_DCA'][$this->strTable]['fields'][$vv]))
					{
						unset($boxes[$k][$kk]);
					}
				}

				
				if (\count($boxes[$k]) < $eCount)
				{
					unset($boxes[$k]);
				}
			}

			
			$objSessionBag = System::getContainer()->get('session')->getBag('contao_backend');

			$class = 'tl_tbox';
			$fs = $objSessionBag->get('fieldset_states');

			
			foreach ($boxes as $k=>$v)
			{
				$arrAjax = array();
				$blnAjax = false;
				$key = '';
				$cls = '';
				$legend = '';

				if (isset($legends[$k]))
				{
					list($key, $cls) = explode(':', $legends[$k]);
					$legend = "\n" . '<legend onclick="AjaxRequest.toggleFieldset(this,\'' . $key . '\',\'' . $this->strTable . '\')">' . ($GLOBALS['TL_LANG'][$this->strTable][$key] ?? $key) . '</legend>';
				}

				if (isset($fs[$this->strTable][$key]))
				{
					$class .= ($fs[$this->strTable][$key] ? '' : ' collapsed');
				}
				else
				{
					$class .= (($cls && $legend) ? ' ' . $cls : '');
				}

				$return .= "\n\n" . '<fieldset' . ($key ? ' id="pal_'.$key.'"' : '') . ' class="' . $class . ($legend ? '' : ' nolegend') . '">' . $legend;
				$thisId = '';

				
				foreach ($v as $vv)
				{
					if ($vv == '[EOF]')
					{
						if ($blnAjax && Environment::get('isAjaxRequest'))
						{
							if ($ajaxId == $thisId)
							{
								return $arrAjax[$thisId] . '<input type="hidden" name="FORM_FIELDS[]" value="'.StringUtil::specialchars($this->strPalette).'">';
							}

							if (\count($arrAjax) > 1)
							{
								$current = "\n" . '<div id="'.$thisId.'" class="subpal cf">' . $arrAjax[$thisId] . '</div>';
								unset($arrAjax[$thisId]);
								end($arrAjax);
								$thisId = key($arrAjax);
								$arrAjax[$thisId] .= $current;
							}
						}

						$return .= "\n" . '</div>';

						continue;
					}

					if (preg_match('/^\[.*\]$/', $vv))
					{
						$thisId = 'sub_' . substr($vv, 1, -1);
						$arrAjax[$thisId] = '';
						$blnAjax = ($ajaxId == $thisId && Environment::get('isAjaxRequest')) ? true : $blnAjax;
						$return .= "\n" . '<div id="'.$thisId.'" class="subpal cf">';

						continue;
					}

					$this->strField = $vv;
					$this->strInputName = $vv;
					$this->varValue = $objRow->$vv;

					
					if ($GLOBALS['TL_DCA'][$this->strTable]['fields'][$this->strField]['eval']['multiple'] && isset($GLOBALS['TL_DCA'][$this->strTable]['fields'][$this->strField]['eval']['csv']))
					{
						$this->varValue = StringUtil::trimsplit($GLOBALS['TL_DCA'][$this->strTable]['fields'][$this->strField]['eval']['csv'], $this->varValue);
					}

					
					if (\is_array($GLOBALS['TL_DCA'][$this->strTable]['fields'][$this->strField]['load_callback']))
					{
						foreach ($GLOBALS['TL_DCA'][$this->strTable]['fields'][$this->strField]['load_callback'] as $callback)
						{
							if (\is_array($callback))
							{
								$this->import($callback[0]);
								$this->varValue = $this->{$callback[0]}->{$callback[1]}($this->varValue, $this);
							}
							elseif (\is_callable($callback))
							{
								$this->varValue = $callback($this->varValue, $this);
							}
						}
					}

					
					$this->objActiveRecord->{$this->strField} = $this->varValue;

					
					$blnAjax ? $arrAjax[$thisId] .= $this->row($this->strPalette) : $return .= $this->row($this->strPalette);
				}

				$class = 'tl_box';
				$return .= "\n" . '</fieldset>';
			}
		}

		
		if ($GLOBALS['TL_DCA'][$this->strTable]['config']['enableVersioning'] && !$GLOBALS['TL_DCA'][$this->strTable]['config']['hideVersionMenu'])
		{
			$version = $objVersions->renderDropdown();
		}
		else
		{
			$version = '';
		}

		
		$arrButtons = array();
		$arrButtons['save'] = '<button type="submit" name="save" id="save" class="tl_submit" accesskey="s">'.$GLOBALS['TL_LANG']['MSC']['save'].'</button>';

		if (!Input::get('nb'))
		{
			$arrButtons['saveNclose'] = '<button type="submit" name="saveNclose" id="saveNclose" class="tl_submit" accesskey="c">'.$GLOBALS['TL_LANG']['MSC']['saveNclose'].'</button>';

			if (!Input::get('nc'))
			{
				if (!$GLOBALS['TL_DCA'][$this->strTable]['config']['closed'] && !$GLOBALS['TL_DCA'][$this->strTable]['config']['notCreatable'])
				{
					$arrButtons['saveNcreate'] = '<button type="submit" name="saveNcreate" id="saveNcreate" class="tl_submit" accesskey="n">'.$GLOBALS['TL_LANG']['MSC']['saveNcreate'].'</button>';

					if (!$GLOBALS['TL_DCA'][$this->strTable]['config']['notCopyable'])
					{
						$arrButtons['saveNduplicate'] = '<button type="submit" name="saveNduplicate" id="saveNduplicate" class="tl_submit" accesskey="d">'.$GLOBALS['TL_LANG']['MSC']['saveNduplicate'].'</button>';
					}
				}

				if ($GLOBALS['TL_DCA'][$this->strTable]['config']['switchToEdit'])
				{
					$arrButtons['saveNedit'] = '<button type="submit" name="saveNedit" id="saveNedit" class="tl_submit" accesskey="e">'.$GLOBALS['TL_LANG']['MSC']['saveNedit'].'</button>';
				}

				if ($GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['mode'] == 4 || \strlen($this->ptable) || $GLOBALS['TL_DCA'][$this->strTable]['config']['switchToEdit'])
				{
					$arrButtons['saveNback'] = '<button type="submit" name="saveNback" id="saveNback" class="tl_submit" accesskey="g">'.$GLOBALS['TL_LANG']['MSC']['saveNback'].'</button>';
				}
			}
		}

		
		if (\is_array($GLOBALS['TL_DCA'][$this->strTable]['edit']['buttons_callback']))
		{
			foreach ($GLOBALS['TL_DCA'][$this->strTable]['edit']['buttons_callback'] as $callback)
			{
				if (\is_array($callback))
				{
					$this->import($callback[0]);
					$arrButtons = $this->{$callback[0]}->{$callback[1]}($arrButtons, $this);
				}
				elseif (\is_callable($callback))
				{
					$arrButtons = $callback($arrButtons, $this);
				}
			}
		}

		if (\count($arrButtons) < 3)
		{
			$strButtons = implode(' ', $arrButtons);
		}
		else
		{
			$strButtons = array_shift($arrButtons) . ' ';
			$strButtons .= '<div class="split-button">';
			$strButtons .= array_shift($arrButtons) . '<button type="button" id="sbtog">' . Image::getHtml('navcol.svg') . '</button> <ul class="invisible">';

			foreach ($arrButtons as $strButton)
			{
				$strButtons .= '<li>' . $strButton . '</li>';
			}

			$strButtons .= '</ul></div>';
		}

		
		$return .= '
</div>
<div class="tl_formbody_submit">
<div class="tl_submit_container">
  ' . $strButtons . '
</div>
</div>
</form>';

		$strVersionField = '';

		
		if (($intLatestVersion = $objVersions->getLatestVersion()) !== null)
		{
			$strVersionField = '
<input type="hidden" name="VERSION_NUMBER" value="'.$intLatestVersion.'">';
		}

		
		$return = $version . Message::generate() . ($this->noReload ? '
<p class="tl_error">'.$GLOBALS['TL_LANG']['ERR']['general'].'</p>' : '') . '
<div id="tl_buttons">' . (Input::get('nb') ? '&nbsp;' : '
<a href="'.$this->getReferer(true).'" class="header_back" title="'.StringUtil::specialchars($GLOBALS['TL_LANG']['MSC']['backBTTitle']).'" accesskey="b" onclick="Backend.getScrollOffset()">'.$GLOBALS['TL_LANG']['MSC']['backBT'].'</a>') . '
</div>
<form action="'.ampersand(Environment::get('request'), true).'" id="'.$this->strTable.'" class="tl_form tl_edit_form" method="post" enctype="' . ($this->blnUploadable ? 'multipart/form-data' : 'application/x-www-form-urlencoded') . '"'.(!empty($this->onsubmit) ? ' onsubmit="'.implode(' ', $this->onsubmit).'"' : '').'>
<div class="tl_formbody_edit">
<input type="hidden" name="FORM_SUBMIT" value="'.$this->strTable.'">
<input type="hidden" name="REQUEST_TOKEN" value="'.REQUEST_TOKEN.'">'.$strVersionField.'
<input type="hidden" name="FORM_FIELDS[]" value="'.StringUtil::specialchars($this->strPalette).'">' . $return;

		
		if (Input::post('FORM_SUBMIT') == $this->strTable && !$this->noReload)
		{
			$arrValues = $this->values;
			array_unshift($arrValues, time());

			
			if (\is_array($GLOBALS['TL_DCA'][$this->strTable]['config']['onsubmit_callback']))
			{
				foreach ($GLOBALS['TL_DCA'][$this->strTable]['config']['onsubmit_callback'] as $callback)
				{
					if (\is_array($callback))
					{
						$this->import($callback[0]);
						$this->{$callback[0]}->{$callback[1]}($this);
					}
					elseif (\is_callable($callback))
					{
						$callback($this);
					}
				}
			}

			
			if ($this->blnCreateNewVersion)
			{
				$objVersions->create();

				
				if (\is_array($GLOBALS['TL_DCA'][$this->strTable]['config']['onversion_callback']))
				{
					@trigger_error('Using the onversion_callback has been deprecated and will no longer work in Contao 5.0. Use the oncreate_version_callback instead.', E_USER_DEPRECATED);

					foreach ($GLOBALS['TL_DCA'][$this->strTable]['config']['onversion_callback'] as $callback)
					{
						if (\is_array($callback))
						{
							$this->import($callback[0]);
							$this->{$callback[0]}->{$callback[1]}($this->strTable, $this->intId, $this);
						}
						elseif (\is_callable($callback))
						{
							$callback($this->strTable, $this->intId, $this);
						}
					}
				}
			}

			
			if ($GLOBALS['TL_DCA'][$this->strTable]['config']['dynamicPtable'])
			{
				$this->Database->prepare("UPDATE " . $this->strTable . " SET ptable=?, tstamp=? WHERE id=?")
							   ->execute($this->ptable, time(), $this->intId);
			}
			else
			{
				$this->Database->prepare("UPDATE " . $this->strTable . " SET tstamp=? WHERE id=?")
							   ->execute(time(), $this->intId);
			}

			
			if ($intLatestVersion !== null && isset($_POST['VERSION_NUMBER']) && $intLatestVersion > Input::post('VERSION_NUMBER'))
			{
				$objTemplate = new BackendTemplate('be_conflict');
				$objTemplate->language = $GLOBALS['TL_LANGUAGE'];
				$objTemplate->title = StringUtil::specialchars($GLOBALS['TL_LANG']['MSC']['versionConflict']);
				$objTemplate->theme = Backend::getTheme();
				$objTemplate->charset = Config::get('characterSet');
				$objTemplate->base = Environment::get('base');
				$objTemplate->h1 = $GLOBALS['TL_LANG']['MSC']['versionConflict'];
				$objTemplate->explain1 = sprintf($GLOBALS['TL_LANG']['MSC']['versionConflict1'], $intLatestVersion, Input::post('VERSION_NUMBER'));
				$objTemplate->explain2 = sprintf($GLOBALS['TL_LANG']['MSC']['versionConflict2'], $intLatestVersion + 1, $intLatestVersion);
				$objTemplate->diff = $objVersions->compare(true);
				$objTemplate->href = Environment::get('request');
				$objTemplate->button = $GLOBALS['TL_LANG']['MSC']['continue'];

				throw new ResponseException($objTemplate->getResponse());
			}

			
			$this->invalidateCacheTags($this);

			
			if (isset($_POST['saveNclose']))
			{
				Message::reset();
				System::setCookie('BE_PAGE_OFFSET', 0, 0);

				$this->redirect($this->getReferer());
			}
			elseif (isset($_POST['saveNedit']))
			{
				Message::reset();
				System::setCookie('BE_PAGE_OFFSET', 0, 0);

				$this->redirect($this->addToUrl($GLOBALS['TL_DCA'][$this->strTable]['list']['operations']['edit']['href'], false, array('s2e', 'act', 'mode', 'pid')));
			}
			elseif (isset($_POST['saveNback']))
			{
				Message::reset();
				System::setCookie('BE_PAGE_OFFSET', 0, 0);

				if ($this->ptable == '')
				{
					$this->redirect(TL_SCRIPT . '?do=' . Input::get('do'));
				}
				
				elseif (($this->ptable == 'tl_theme' && $this->strTable == 'tl_style_sheet') || ($this->ptable == 'tl_page' && $this->strTable == 'tl_article'))
				{
					$this->redirect($this->getReferer(false, $this->strTable));
				}
				else
				{
					$this->redirect($this->getReferer(false, $this->ptable));
				}
			}
			elseif (isset($_POST['saveNcreate']))
			{
				Message::reset();
				System::setCookie('BE_PAGE_OFFSET', 0, 0);

				$strUrl = TL_SCRIPT . '?do=' . Input::get('do');

				if (isset($_GET['table']))
				{
					$strUrl .= '&amp;table=' . Input::get('table');
				}

				
				if ($this->treeView)
				{
					$strUrl .= '&amp;act=create&amp;mode=1&amp;pid=' . $this->intId;
				}

				
				elseif ($GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['mode'] == 4)
				{
					$strUrl .= $this->Database->fieldExists('sorting', $this->strTable) ? '&amp;act=create&amp;mode=1&amp;pid=' . $this->intId : '&amp;act=create&amp;mode=2&amp;pid=' . $this->activeRecord->pid;
				}

				
				else
				{
					$strUrl .= ($this->ptable != '') ? '&amp;act=create&amp;mode=2&amp;pid=' . CURRENT_ID : '&amp;act=create';
				}

				$this->redirect($strUrl . '&amp;rt=' . REQUEST_TOKEN);
			}
			elseif (isset($_POST['saveNduplicate']))
			{
				Message::reset();
				System::setCookie('BE_PAGE_OFFSET', 0, 0);

				$strUrl = TL_SCRIPT . '?do=' . Input::get('do');

				if (isset($_GET['table']))
				{
					$strUrl .= '&amp;table=' . Input::get('table');
				}

				
				if ($this->treeView)
				{
					$strUrl .= '&amp;act=copy&amp;mode=1&amp;id=' . $this->intId . '&amp;pid=' . $this->intId;
				}

				
				elseif ($GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['mode'] == 4)
				{
					$strUrl .= $this->Database->fieldExists('sorting', $this->strTable) ? '&amp;act=copy&amp;mode=1&amp;pid=' . $this->intId . '&amp;id=' . $this->intId : '&amp;act=copy&amp;mode=2&amp;pid=' . CURRENT_ID . '&amp;id=' . $this->intId;
				}

				
				else
				{
					$strUrl .= ($this->ptable != '') ? '&amp;act=copy&amp;mode=2&amp;pid=' . CURRENT_ID . '&amp;id=' . CURRENT_ID : '&amp;act=copy&amp;id=' . CURRENT_ID;
				}

				$this->redirect($strUrl . '&amp;rt=' . REQUEST_TOKEN);
			}

			$this->reload();
		}

		
		if ($this->noReload)
		{
			$return .= '
<script>
  window.addEvent(\'domready\', function() {
    Backend.vScrollTo(($(\'' . $this->strTable . '\').getElement(\'label.error\').getPosition().y - 20));
  });
</script>';
		}

		return $return;
	}
public function edit ( $ intId = null , $ ajaxId = null ) { if ( $ GLOBALS [ 'TL_DCA' ] [ $ this -> strTable ] [ 'config' ] [ 'notEditable' ] ) { throw new InternalServerErrorException ( 'Table "' . $ this -> strTable . '" is not editable.' ) ; } if ( $ intId != '' ) { $ this -> intId = $ intId ; } // Get the current record $ objRow = $ this -> Database -> prepare ( "SELECT * FROM " . $ this -> strTable . " WHERE id=?" ) -> limit ( 1 ) -> execute ( $ this -> intId ) ; // Redirect if there is no record with the given ID if ( $ objRow -> numRows < 1 ) { throw new AccessDeniedException ( 'Cannot load record "' . $ this -> strTable . '.id=' . $ this -> intId . '".' ) ; } $ this -> objActiveRecord = $ objRow ; $ return = '' ; $ this -> values [ ] = $ this -> intId ; $ this -> procedure [ ] = 'id=?' ; $ this -> blnCreateNewVersion = false ; $ objVersions = new Versions ( $ this -> strTable , $ this -> intId ) ; if ( ! $ GLOBALS [ 'TL_DCA' ] [ $ this -> strTable ] [ 'config' ] [ 'hideVersionMenu' ] ) { // Compare versions if ( Input :: get ( 'versions' ) ) { $ objVersions -> compare ( ) ; } // Restore a version if ( Input :: post ( 'FORM_SUBMIT' ) == 'tl_version' && Input :: post ( 'version' ) != '' ) { $ objVersions -> restore ( Input :: post ( 'version' ) ) ; $ this -> reload ( ) ; } } $ objVersions -> initialize ( ) ; // Build an array from boxes and rows $ this -> strPalette = $ this -> getPalette ( ) ; $ boxes = StringUtil :: trimsplit ( ';' , $ this -> strPalette ) ; $ legends = array ( ) ; if ( ! empty ( $ boxes ) ) { foreach ( $ boxes as $ k => $ v ) { $ eCount = 1 ; $ boxes [ $ k ] = StringUtil :: trimsplit ( ',' , $ v ) ; foreach ( $ boxes [ $ k ] as $ kk => $ vv ) { if ( preg_match ( '/^\[.*\]$/' , $ vv ) ) { ++ $ eCount ; continue ; } if ( preg_match ( '/^\{.*\}$/' , $ vv ) ) { $ legends [ $ k ] = substr ( $ vv , 1 , - 1 ) ; unset ( $ boxes [ $ k ] [ $ kk ] ) ; } elseif ( $ GLOBALS [ 'TL_DCA' ] [ $ this -> strTable ] [ 'fields' ] [ $ vv ] [ 'exclude' ] || ! \ is_array ( $ GLOBALS [ 'TL_DCA' ] [ $ this -> strTable ] [ 'fields' ] [ $ vv ] ) ) { unset ( $ boxes [ $ k ] [ $ kk ] ) ; } } // Unset a box if it does not contain any fields if ( \ count ( $ boxes [ $ k ] ) < $ eCount ) { unset ( $ boxes [ $ k ] ) ; } } /** @var Session $objSessionBag */ $ objSessionBag = System :: getContainer ( ) -> get ( 'session' ) -> getBag ( 'contao_backend' ) ; $ class = 'tl_tbox' ; $ fs = $ objSessionBag -> get ( 'fieldset_states' ) ; // Render boxes foreach ( $ boxes as $ k => $ v ) { $ arrAjax = array ( ) ; $ blnAjax = false ; $ key = '' ; $ cls = '' ; $ legend = '' ; if ( isset ( $ legends [ $ k ] ) ) { list ( $ key , $ cls ) = explode ( ':' , $ legends [ $ k ] ) ; $ legend = "\n" . '<legend onclick="AjaxRequest.toggleFieldset(this,\'' . $ key . '\',\'' . $ this -> strTable . '\')">' . ( $ GLOBALS [ 'TL_LANG' ] [ $ this -> strTable ] [ $ key ] ?? $ key ) . '</legend>' ; } if ( isset ( $ fs [ $ this -> strTable ] [ $ key ] ) ) { $ class .= ( $ fs [ $ this -> strTable ] [ $ key ] ? '' : ' collapsed' ) ; } else { $ class .= ( ( $ cls && $ legend ) ? ' ' . $ cls : '' ) ; } $ return .= "\n\n" . '<fieldset' . ( $ key ? ' id="pal_' . $ key . '"' : '' ) . ' class="' . $ class . ( $ legend ? '' : ' nolegend' ) . '">' . $ legend ; $ thisId = '' ; // Build rows of the current box foreach ( $ v as $ vv ) { if ( $ vv == '[EOF]' ) { if ( $ blnAjax && Environment :: get ( 'isAjaxRequest' ) ) { if ( $ ajaxId == $ thisId ) { return $ arrAjax [ $ thisId ] . '<input type="hidden" name="FORM_FIELDS[]" value="' . StringUtil :: specialchars ( $ this -> strPalette ) . '">' ; } if ( \ count ( $ arrAjax ) > 1 ) { $ current = "\n" . '<div id="' . $ thisId . '" class="subpal cf">' . $ arrAjax [ $ thisId ] . '</div>' ; unset ( $ arrAjax [ $ thisId ] ) ; end ( $ arrAjax ) ; $ thisId = key ( $ arrAjax ) ; $ arrAjax [ $ thisId ] .= $ current ; } } $ return .= "\n" . '</div>' ; continue ; } if ( preg_match ( '/^\[.*\]$/' , $ vv ) ) { $ thisId = 'sub_' . substr ( $ vv , 1 , - 1 ) ; $ arrAjax [ $ thisId ] = '' ; $ blnAjax = ( $ ajaxId == $ thisId && Environment :: get ( 'isAjaxRequest' ) ) ? true : $ blnAjax ; $ return .= "\n" . '<div id="' . $ thisId . '" class="subpal cf">' ; continue ; } $ this -> strField = $ vv ; $ this -> strInputName = $ vv ; $ this -> varValue = $ objRow -> $ vv ; // Convert CSV fields (see #2890) if ( $ GLOBALS [ 'TL_DCA' ] [ $ this -> strTable ] [ 'fields' ] [ $ this -> strField ] [ 'eval' ] [ 'multiple' ] && isset ( $ GLOBALS [ 'TL_DCA' ] [ $ this -> strTable ] [ 'fields' ] [ $ this -> strField ] [ 'eval' ] [ 'csv' ] ) ) { $ this -> varValue = StringUtil :: trimsplit ( $ GLOBALS [ 'TL_DCA' ] [ $ this -> strTable ] [ 'fields' ] [ $ this -> strField ] [ 'eval' ] [ 'csv' ] , $ this -> varValue ) ; } // Call load_callback if ( \ is_array ( $ GLOBALS [ 'TL_DCA' ] [ $ this -> strTable ] [ 'fields' ] [ $ this -> strField ] [ 'load_callback' ] ) ) { foreach ( $ GLOBALS [ 'TL_DCA' ] [ $ this -> strTable ] [ 'fields' ] [ $ this -> strField ] [ 'load_callback' ] as $ callback ) { if ( \ is_array ( $ callback ) ) { $ this -> import ( $ callback [ 0 ] ) ; $ this -> varValue = $ this -> { $ callback [ 0 ] } -> { $ callback [ 1 ] } ( $ this -> varValue , $ this ) ; } elseif ( \ is_callable ( $ callback ) ) { $ this -> varValue = $ callback ( $ this -> varValue , $ this ) ; } } } // Re-set the current value $ this -> objActiveRecord -> { $ this -> strField } = $ this -> varValue ; // Build the row and pass the current palette string (thanks to Tristan Lins) $ blnAjax ? $ arrAjax [ $ thisId ] .= $ this -> row ( $ this -> strPalette ) : $ return .= $ this -> row ( $ this -> strPalette ) ; } $ class = 'tl_box' ; $ return .= "\n" . '</fieldset>' ; } } // Versions overview if ( $ GLOBALS [ 'TL_DCA' ] [ $ this -> strTable ] [ 'config' ] [ 'enableVersioning' ] && ! $ GLOBALS [ 'TL_DCA' ] [ $ this -> strTable ] [ 'config' ] [ 'hideVersionMenu' ] ) { $ version = $ objVersions -> renderDropdown ( ) ; } else { $ version = '' ; } // Submit buttons $ arrButtons = array ( ) ; $ arrButtons [ 'save' ] = '<button type="submit" name="save" id="save" class="tl_submit" accesskey="s">' . $ GLOBALS [ 'TL_LANG' ] [ 'MSC' ] [ 'save' ] . '</button>' ; if ( ! Input :: get ( 'nb' ) ) { $ arrButtons [ 'saveNclose' ] = '<button type="submit" name="saveNclose" id="saveNclose" class="tl_submit" accesskey="c">' . $ GLOBALS [ 'TL_LANG' ] [ 'MSC' ] [ 'saveNclose' ] . '</button>' ; if ( ! Input :: get ( 'nc' ) ) { if ( ! $ GLOBALS [ 'TL_DCA' ] [ $ this -> strTable ] [ 'config' ] [ 'closed' ] && ! $ GLOBALS [ 'TL_DCA' ] [ $ this -> strTable ] [ 'config' ] [ 'notCreatable' ] ) { $ arrButtons [ 'saveNcreate' ] = '<button type="submit" name="saveNcreate" id="saveNcreate" class="tl_submit" accesskey="n">' . $ GLOBALS [ 'TL_LANG' ] [ 'MSC' ] [ 'saveNcreate' ] . '</button>' ; if ( ! $ GLOBALS [ 'TL_DCA' ] [ $ this -> strTable ] [ 'config' ] [ 'notCopyable' ] ) { $ arrButtons [ 'saveNduplicate' ] = '<button type="submit" name="saveNduplicate" id="saveNduplicate" class="tl_submit" accesskey="d">' . $ GLOBALS [ 'TL_LANG' ] [ 'MSC' ] [ 'saveNduplicate' ] . '</button>' ; } } if ( $ GLOBALS [ 'TL_DCA' ] [ $ this -> strTable ] [ 'config' ] [ 'switchToEdit' ] ) { $ arrButtons [ 'saveNedit' ] = '<button type="submit" name="saveNedit" id="saveNedit" class="tl_submit" accesskey="e">' . $ GLOBALS [ 'TL_LANG' ] [ 'MSC' ] [ 'saveNedit' ] . '</button>' ; } if ( $ GLOBALS [ 'TL_DCA' ] [ $ this -> strTable ] [ 'list' ] [ 'sorting' ] [ 'mode' ] == 4 || \ strlen ( $ this -> ptable ) || $ GLOBALS [ 'TL_DCA' ] [ $ this -> strTable ] [ 'config' ] [ 'switchToEdit' ] ) { $ arrButtons [ 'saveNback' ] = '<button type="submit" name="saveNback" id="saveNback" class="tl_submit" accesskey="g">' . $ GLOBALS [ 'TL_LANG' ] [ 'MSC' ] [ 'saveNback' ] . '</button>' ; } } } // Call the buttons_callback (see #4691) if ( \ is_array ( $ GLOBALS [ 'TL_DCA' ] [ $ this -> strTable ] [ 'edit' ] [ 'buttons_callback' ] ) ) { foreach ( $ GLOBALS [ 'TL_DCA' ] [ $ this -> strTable ] [ 'edit' ] [ 'buttons_callback' ] as $ callback ) { if ( \ is_array ( $ callback ) ) { $ this -> import ( $ callback [ 0 ] ) ; $ arrButtons = $ this -> { $ callback [ 0 ] } -> { $ callback [ 1 ] } ( $ arrButtons , $ this ) ; } elseif ( \ is_callable ( $ callback ) ) { $ arrButtons = $ callback ( $ arrButtons , $ this ) ; } } } if ( \ count ( $ arrButtons ) < 3 ) { $ strButtons = implode ( ' ' , $ arrButtons ) ; } else { $ strButtons = array_shift ( $ arrButtons ) . ' ' ; $ strButtons .= '<div class="split-button">' ; $ strButtons .= array_shift ( $ arrButtons ) . '<button type="button" id="sbtog">' . Image :: getHtml ( 'navcol.svg' ) . '</button> <ul class="invisible">' ; foreach ( $ arrButtons as $ strButton ) { $ strButtons .= '<li>' . $ strButton . '</li>' ; } $ strButtons .= '</ul></div>' ; } // Add the buttons and end the form $ return .= '
</div>
<div class="tl_formbody_submit">
<div class="tl_submit_container">
  ' . $ strButtons . '
</div>
</div>
</form>' ; $ strVersionField = '' ; // Store the current version number (see #8412) if ( ( $ intLatestVersion = $ objVersions -> getLatestVersion ( ) ) !== null ) { $ strVersionField = '
<input type="hidden" name="VERSION_NUMBER" value="' . $ intLatestVersion . '">' ; } // Begin the form (-> DO NOT CHANGE THIS ORDER -> this way the onsubmit attribute of the form can be changed by a field) $ return = $ version . Message :: generate ( ) . ( $ this -> noReload ? '
<p class="tl_error">' . $ GLOBALS [ 'TL_LANG' ] [ 'ERR' ] [ 'general' ] . '</p>' : '' ) . '
<div id="tl_buttons">' . ( Input :: get ( 'nb' ) ? '&nbsp;' : '
<a href="' . $ this -> getReferer ( true ) . '" class="header_back" title="' . StringUtil :: specialchars ( $ GLOBALS [ 'TL_LANG' ] [ 'MSC' ] [ 'backBTTitle' ] ) . '" accesskey="b" onclick="Backend.getScrollOffset()">' . $ GLOBALS [ 'TL_LANG' ] [ 'MSC' ] [ 'backBT' ] . '</a>' ) . '
</div>
<form action="' . ampersand ( Environment :: get ( 'request' ) , true ) . '" id="' . $ this -> strTable . '" class="tl_form tl_edit_form" method="post" enctype="' . ( $ this -> blnUploadable ? 'multipart/form-data' : 'application/x-www-form-urlencoded' ) . '"' . ( ! empty ( $ this -> onsubmit ) ? ' onsubmit="' . implode ( ' ' , $ this -> onsubmit ) . '"' : '' ) . '>
<div class="tl_formbody_edit">
<input type="hidden" name="FORM_SUBMIT" value="' . $ this -> strTable . '">
<input type="hidden" name="REQUEST_TOKEN" value="' . REQUEST_TOKEN . '">' . $ strVersionField . '
<input type="hidden" name="FORM_FIELDS[]" value="' . StringUtil :: specialchars ( $ this -> strPalette ) . '">' . $ return ; // Reload the page to prevent _POST variables from being sent twice if ( Input :: post ( 'FORM_SUBMIT' ) == $ this -> strTable && ! $ this -> noReload ) { $ arrValues = $ this -> values ; array_unshift ( $ arrValues , time ( ) ) ; // Trigger the onsubmit_callback if ( \ is_array ( $ GLOBALS [ 'TL_DCA' ] [ $ this -> strTable ] [ 'config' ] [ 'onsubmit_callback' ] ) ) { foreach ( $ GLOBALS [ 'TL_DCA' ] [ $ this -> strTable ] [ 'config' ] [ 'onsubmit_callback' ] as $ callback ) { if ( \ is_array ( $ callback ) ) { $ this -> import ( $ callback [ 0 ] ) ; $ this -> { $ callback [ 0 ] } -> { $ callback [ 1 ] } ( $ this ) ; } elseif ( \ is_callable ( $ callback ) ) { $ callback ( $ this ) ; } } } // Save the current version if ( $ this -> blnCreateNewVersion ) { $ objVersions -> create ( ) ; // Call the onversion_callback if ( \ is_array ( $ GLOBALS [ 'TL_DCA' ] [ $ this -> strTable ] [ 'config' ] [ 'onversion_callback' ] ) ) { @ trigger_error ( 'Using the onversion_callback has been deprecated and will no longer work in Contao 5.0. Use the oncreate_version_callback instead.' , E_USER_DEPRECATED ) ; foreach ( $ GLOBALS [ 'TL_DCA' ] [ $ this -> strTable ] [ 'config' ] [ 'onversion_callback' ] as $ callback ) { if ( \ is_array ( $ callback ) ) { $ this -> import ( $ callback [ 0 ] ) ; $ this -> { $ callback [ 0 ] } -> { $ callback [ 1 ] } ( $ this -> strTable , $ this -> intId , $ this ) ; } elseif ( \ is_callable ( $ callback ) ) { $ callback ( $ this -> strTable , $ this -> intId , $ this ) ; } } } } // Set the current timestamp (-> DO NOT CHANGE THE ORDER version - timestamp) if ( $ GLOBALS [ 'TL_DCA' ] [ $ this -> strTable ] [ 'config' ] [ 'dynamicPtable' ] ) { $ this -> Database -> prepare ( "UPDATE " . $ this -> strTable . " SET ptable=?, tstamp=? WHERE id=?" ) -> execute ( $ this -> ptable , time ( ) , $ this -> intId ) ; } else { $ this -> Database -> prepare ( "UPDATE " . $ this -> strTable . " SET tstamp=? WHERE id=?" ) -> execute ( time ( ) , $ this -> intId ) ; } // Show a warning if the record has been saved by another user (see #8412) if ( $ intLatestVersion !== null && isset ( $ _POST [ 'VERSION_NUMBER' ] ) && $ intLatestVersion > Input :: post ( 'VERSION_NUMBER' ) ) { $ objTemplate = new BackendTemplate ( 'be_conflict' ) ; $ objTemplate -> language = $ GLOBALS [ 'TL_LANGUAGE' ] ; $ objTemplate -> title = StringUtil :: specialchars ( $ GLOBALS [ 'TL_LANG' ] [ 'MSC' ] [ 'versionConflict' ] ) ; $ objTemplate -> theme = Backend :: getTheme ( ) ; $ objTemplate -> charset = Config :: get ( 'characterSet' ) ; $ objTemplate -> base = Environment :: get ( 'base' ) ; $ objTemplate -> h1 = $ GLOBALS [ 'TL_LANG' ] [ 'MSC' ] [ 'versionConflict' ] ; $ objTemplate -> explain1 = sprintf ( $ GLOBALS [ 'TL_LANG' ] [ 'MSC' ] [ 'versionConflict1' ] , $ intLatestVersion , Input :: post ( 'VERSION_NUMBER' ) ) ; $ objTemplate -> explain2 = sprintf ( $ GLOBALS [ 'TL_LANG' ] [ 'MSC' ] [ 'versionConflict2' ] , $ intLatestVersion + 1 , $ intLatestVersion ) ; $ objTemplate -> diff = $ objVersions -> compare ( true ) ; $ objTemplate -> href = Environment :: get ( 'request' ) ; $ objTemplate -> button = $ GLOBALS [ 'TL_LANG' ] [ 'MSC' ] [ 'continue' ] ; throw new ResponseException ( $ objTemplate -> getResponse ( ) ) ; } // Invalidate cache tags $ this -> invalidateCacheTags ( $ this ) ; // Redirect if ( isset ( $ _POST [ 'saveNclose' ] ) ) { Message :: reset ( ) ; System :: setCookie ( 'BE_PAGE_OFFSET' , 0 , 0 ) ; $ this -> redirect ( $ this -> getReferer ( ) ) ; } elseif ( isset ( $ _POST [ 'saveNedit' ] ) ) { Message :: reset ( ) ; System :: setCookie ( 'BE_PAGE_OFFSET' , 0 , 0 ) ; $ this -> redirect ( $ this -> addToUrl ( $ GLOBALS [ 'TL_DCA' ] [ $ this -> strTable ] [ 'list' ] [ 'operations' ] [ 'edit' ] [ 'href' ] , false , array ( 's2e' , 'act' , 'mode' , 'pid' ) ) ) ; } elseif ( isset ( $ _POST [ 'saveNback' ] ) ) { Message :: reset ( ) ; System :: setCookie ( 'BE_PAGE_OFFSET' , 0 , 0 ) ; if ( $ this -> ptable == '' ) { $ this -> redirect ( TL_SCRIPT . '?do=' . Input :: get ( 'do' ) ) ; } // TODO: try to abstract this elseif ( ( $ this -> ptable == 'tl_theme' && $ this -> strTable == 'tl_style_sheet' ) || ( $ this -> ptable == 'tl_page' && $ this -> strTable == 'tl_article' ) ) { $ this -> redirect ( $ this -> getReferer ( false , $ this -> strTable ) ) ; } else { $ this -> redirect ( $ this -> getReferer ( false , $ this -> ptable ) ) ; } } elseif ( isset ( $ _POST [ 'saveNcreate' ] ) ) { Message :: reset ( ) ; System :: setCookie ( 'BE_PAGE_OFFSET' , 0 , 0 ) ; $ strUrl = TL_SCRIPT . '?do=' . Input :: get ( 'do' ) ; if ( isset ( $ _GET [ 'table' ] ) ) { $ strUrl .= '&amp;table=' . Input :: get ( 'table' ) ; } // Tree view if ( $ this -> treeView ) { $ strUrl .= '&amp;act=create&amp;mode=1&amp;pid=' . $ this -> intId ; } // Parent view elseif ( $ GLOBALS [ 'TL_DCA' ] [ $ this -> strTable ] [ 'list' ] [ 'sorting' ] [ 'mode' ] == 4 ) { $ strUrl .= $ this -> Database -> fieldExists ( 'sorting' , $ this -> strTable ) ? '&amp;act=create&amp;mode=1&amp;pid=' . $ this -> intId : '&amp;act=create&amp;mode=2&amp;pid=' . $ this -> activeRecord -> pid ; } // List view else { $ strUrl .= ( $ this -> ptable != '' ) ? '&amp;act=create&amp;mode=2&amp;pid=' . CURRENT_ID : '&amp;act=create' ; } $ this -> redirect ( $ strUrl . '&amp;rt=' . REQUEST_TOKEN ) ; } elseif ( isset ( $ _POST [ 'saveNduplicate' ] ) ) { Message :: reset ( ) ; System :: setCookie ( 'BE_PAGE_OFFSET' , 0 , 0 ) ; $ strUrl = TL_SCRIPT . '?do=' . Input :: get ( 'do' ) ; if ( isset ( $ _GET [ 'table' ] ) ) { $ strUrl .= '&amp;table=' . Input :: get ( 'table' ) ; } // Tree view if ( $ this -> treeView ) { $ strUrl .= '&amp;act=copy&amp;mode=1&amp;id=' . $ this -> intId . '&amp;pid=' . $ this -> intId ; } // Parent view elseif ( $ GLOBALS [ 'TL_DCA' ] [ $ this -> strTable ] [ 'list' ] [ 'sorting' ] [ 'mode' ] == 4 ) { $ strUrl .= $ this -> Database -> fieldExists ( 'sorting' , $ this -> strTable ) ? '&amp;act=copy&amp;mode=1&amp;pid=' . $ this -> intId . '&amp;id=' . $ this -> intId : '&amp;act=copy&amp;mode=2&amp;pid=' . CURRENT_ID . '&amp;id=' . $ this -> intId ; } // List view else { $ strUrl .= ( $ this -> ptable != '' ) ? '&amp;act=copy&amp;mode=2&amp;pid=' . CURRENT_ID . '&amp;id=' . CURRENT_ID : '&amp;act=copy&amp;id=' . CURRENT_ID ; } $ this -> redirect ( $ strUrl . '&amp;rt=' . REQUEST_TOKEN ) ; } $ this -> reload ( ) ; } // Set the focus if there is an error if ( $ this -> noReload ) { $ return .= '
<script>
  window.addEvent(\'domready\', function() {
    Backend.vScrollTo(($(\'' . $ this -> strTable . '\').getElement(\'label.error\').getPosition().y - 20));
  });
</script>' ; } return $ return ; }
Auto-generate a form to edit the current database record

@param integer $intId
@param integer $ajaxId

@return string

@throws AccessDeniedException
@throws InternalServerErrorException
Auto - generate a form to edit the current database record