protected function parentView()
	{
		/** @var Session $objSession */
		$objSession = System::getContainer()->get('session');

		$blnClipboard = false;
		$arrClipboard = $objSession->get('CLIPBOARD');
		$table = ($GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['mode'] == 6) ? $this->ptable : $this->strTable;
		$blnHasSorting = $GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['fields'][0] == 'sorting';
		$blnMultiboard = false;

		// Check clipboard
		if (!empty($arrClipboard[$table]))
		{
			$blnClipboard = true;
			$arrClipboard = $arrClipboard[$table];

			if (\is_array($arrClipboard['id']))
			{
				$blnMultiboard = true;
			}
		}

		// Load the language file and data container array of the parent table
		System::loadLanguageFile($this->ptable);
		$this->loadDataContainer($this->ptable);

		$return = Message::generate() . '
<div id="tl_buttons">' . (Input::get('nb') ? '&nbsp;' : ($this->ptable ? '
<a href="'.$this->getReferer(true, $this->ptable).'" class="header_back" title="'.StringUtil::specialchars($GLOBALS['TL_LANG']['MSC']['backBTTitle']).'" accesskey="b" onclick="Backend.getScrollOffset()">'.$GLOBALS['TL_LANG']['MSC']['backBT'].'</a>' : (isset($GLOBALS['TL_DCA'][$this->strTable]['config']['backlink']) ? '
<a href="contao/main.php?'.$GLOBALS['TL_DCA'][$this->strTable]['config']['backlink'].'" class="header_back" title="'.StringUtil::specialchars($GLOBALS['TL_LANG']['MSC']['backBTTitle']).'" accesskey="b" onclick="Backend.getScrollOffset()">'.$GLOBALS['TL_LANG']['MSC']['backBT'].'</a>' : ''))) . ' ' . ((Input::get('act') != 'select' && !$blnClipboard && !$GLOBALS['TL_DCA'][$this->strTable]['config']['closed'] && !$GLOBALS['TL_DCA'][$this->strTable]['config']['notCreatable']) ? '
<a href="'.$this->addToUrl(($blnHasSorting ? 'act=paste&amp;mode=create' : 'act=create&amp;mode=2&amp;pid='.$this->intId)).'" class="header_new" title="'.StringUtil::specialchars($GLOBALS['TL_LANG'][$this->strTable]['new'][1]).'" accesskey="n" onclick="Backend.getScrollOffset()">'.$GLOBALS['TL_LANG'][$this->strTable]['new'][0].'</a> ' : '') . ($blnClipboard ? '
<a href="'.$this->addToUrl('clipboard=1').'" class="header_clipboard" title="'.StringUtil::specialchars($GLOBALS['TL_LANG']['MSC']['clearClipboard']).'" accesskey="x">'.$GLOBALS['TL_LANG']['MSC']['clearClipboard'].'</a> ' : $this->generateGlobalButtons()) . '
</div>';

		// Get all details of the parent record
		$objParent = $this->Database->prepare("SELECT * FROM " . $this->ptable . " WHERE id=?")
									->limit(1)
									->execute(CURRENT_ID);

		if ($objParent->numRows < 1)
		{
			return $return;
		}

		$return .= ((Input::get('act') == 'select') ? '

<form action="'.ampersand(Environment::get('request'), true).'" id="tl_select" class="tl_form'.((Input::get('act') == 'select') ? ' unselectable' : '').'" method="post" novalidate>
<div class="tl_formbody_edit">
<input type="hidden" name="FORM_SUBMIT" value="tl_select">
<input type="hidden" name="REQUEST_TOKEN" value="'.REQUEST_TOKEN.'">' : '').($blnClipboard ? '
<div id="paste_hint">
  <p>'.$GLOBALS['TL_LANG']['MSC']['selectNewPosition'].'</p>
</div>' : '').'
<div class="tl_listing_container parent_view'.($this->strPickerFieldType ? ' picker unselectable' : '').'" id="tl_listing">
<div class="tl_header click2edit toggle_select hover-div">';

		// List all records of the child table
		if (!Input::get('act') || Input::get('act') == 'paste' || Input::get('act') == 'select')
		{
			$this->import(BackendUser::class, 'User');

			// Header
			$imagePasteNew = Image::getHtml('new.svg', $GLOBALS['TL_LANG'][$this->strTable]['pastenew'][0]);
			$imagePasteAfter = Image::getHtml('pasteafter.svg', $GLOBALS['TL_LANG'][$this->strTable]['pasteafter'][0]);
			$imageEditHeader = Image::getHtml('header.svg', $GLOBALS['TL_LANG'][$this->strTable]['editheader'][0]);

			$return .= '
<div class="tl_content_right">'.((Input::get('act') == 'select' || $this->strPickerFieldType == 'checkbox') ? '
<label for="tl_select_trigger" class="tl_select_label">'.$GLOBALS['TL_LANG']['MSC']['selectAll'].'</label> <input type="checkbox" id="tl_select_trigger" onclick="Backend.toggleCheckboxes(this)" class="tl_tree_checkbox">' : ($blnClipboard ? '
<a href="'.$this->addToUrl('act='.$arrClipboard['mode'].'&amp;mode=2&amp;pid='.$objParent->id . (!$blnMultiboard ? '&amp;id='.$arrClipboard['id'] : '')).'" title="'.StringUtil::specialchars($GLOBALS['TL_LANG'][$this->strTable]['pasteafter'][0]).'" onclick="Backend.getScrollOffset()">'.$imagePasteAfter.'</a>' : ((!$GLOBALS['TL_DCA'][$this->ptable]['config']['notEditable'] && $this->User->canEditFieldsOf($this->ptable)) ? '
<a href="'.preg_replace('/&(amp;)?table=[^& ]*/i', (($this->ptable != '') ? '&amp;table='.$this->ptable : ''), $this->addToUrl('act=edit'.(Input::get('nb') ? '&amp;nc=1' : ''))).'" class="edit" title="'.StringUtil::specialchars($GLOBALS['TL_LANG'][$this->ptable]['editmeta'][1] ?? $GLOBALS['TL_LANG'][$this->strTable]['editheader'][1]).'">'.$imageEditHeader.'</a> ' . $this->generateHeaderButtons($objParent->row(), $this->ptable) : '') . (($blnHasSorting && !$GLOBALS['TL_DCA'][$this->strTable]['config']['closed'] && !$GLOBALS['TL_DCA'][$this->strTable]['config']['notCreatable']) ? '
<a href="'.$this->addToUrl('act=create&amp;mode=2&amp;pid='.$objParent->id.'&amp;id='.$this->intId).'" title="'.StringUtil::specialchars($GLOBALS['TL_LANG'][$this->strTable]['pastenew'][0]).'">'.$imagePasteNew.'</a>' : ''))) . '
</div>';

			// Format header fields
			$add = array();
			$headerFields = $GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['headerFields'];

			foreach ($headerFields as $v)
			{
				$_v = StringUtil::deserialize($objParent->$v);

				// Translate UUIDs to paths
				if ($GLOBALS['TL_DCA'][$this->ptable]['fields'][$v]['inputType'] == 'fileTree')
				{
					$objFiles = FilesModel::findMultipleByUuids((array) $_v);

					if ($objFiles !== null)
					{
						$_v = $objFiles->fetchEach('path');
					}
				}

				if (\is_array($_v))
				{
					$_v = implode(', ', $_v);
				}
				elseif ($GLOBALS['TL_DCA'][$this->ptable]['fields'][$v]['eval']['isBoolean'] || ($GLOBALS['TL_DCA'][$this->ptable]['fields'][$v]['inputType'] == 'checkbox' && !$GLOBALS['TL_DCA'][$this->ptable]['fields'][$v]['eval']['multiple']))
				{
					$_v = $_v ? $GLOBALS['TL_LANG']['MSC']['yes'] : $GLOBALS['TL_LANG']['MSC']['no'];
				}
				elseif ($GLOBALS['TL_DCA'][$this->ptable]['fields'][$v]['eval']['rgxp'] == 'date')
				{
					$_v = $_v ? Date::parse(Config::get('dateFormat'), $_v) : '-';
				}
				elseif ($GLOBALS['TL_DCA'][$this->ptable]['fields'][$v]['eval']['rgxp'] == 'time')
				{
					$_v = $_v ? Date::parse(Config::get('timeFormat'), $_v) : '-';
				}
				elseif ($GLOBALS['TL_DCA'][$this->ptable]['fields'][$v]['eval']['rgxp'] == 'datim')
				{
					$_v = $_v ? Date::parse(Config::get('datimFormat'), $_v) : '-';
				}
				elseif ($v == 'tstamp')
				{
					$_v = Date::parse(Config::get('datimFormat'), $objParent->tstamp);
				}
				elseif (isset($GLOBALS['TL_DCA'][$this->ptable]['fields'][$v]['foreignKey']))
				{
					$arrForeignKey = explode('.', $GLOBALS['TL_DCA'][$this->ptable]['fields'][$v]['foreignKey'], 2);

					$objLabel = $this->Database->prepare("SELECT " . Database::quoteIdentifier($arrForeignKey[1]) . " AS value FROM " . $arrForeignKey[0] . " WHERE id=?")
											   ->limit(1)
											   ->execute($_v);

					if ($objLabel->numRows)
					{
						$_v = $objLabel->value;
					}
				}
				elseif (\is_array($GLOBALS['TL_DCA'][$this->ptable]['fields'][$v]['reference'][$_v]))
				{
					$_v = $GLOBALS['TL_DCA'][$this->ptable]['fields'][$v]['reference'][$_v][0];
				}
				elseif (isset($GLOBALS['TL_DCA'][$this->ptable]['fields'][$v]['reference'][$_v]))
				{
					$_v = $GLOBALS['TL_DCA'][$this->ptable]['fields'][$v]['reference'][$_v];
				}
				elseif ($GLOBALS['TL_DCA'][$this->ptable]['fields'][$v]['eval']['isAssociative'] || array_is_assoc($GLOBALS['TL_DCA'][$this->ptable]['fields'][$v]['options']))
				{
					$_v = $GLOBALS['TL_DCA'][$this->ptable]['fields'][$v]['options'][$_v];
				}
				elseif (\is_array($GLOBALS['TL_DCA'][$this->ptable]['fields'][$v]['options_callback']))
				{
					$strClass = $GLOBALS['TL_DCA'][$this->ptable]['fields'][$v]['options_callback'][0];
					$strMethod = $GLOBALS['TL_DCA'][$this->ptable]['fields'][$v]['options_callback'][1];

					$this->import($strClass);
					$options_callback = $this->$strClass->$strMethod($this);

					$_v = $options_callback[$_v];
				}
				elseif (\is_callable($GLOBALS['TL_DCA'][$this->ptable]['fields'][$v]['options_callback']))
				{
					$options_callback = $GLOBALS['TL_DCA'][$this->ptable]['fields'][$v]['options_callback']($this);

					$_v = $options_callback[$_v];
				}

				// Add the sorting field
				if ($_v != '')
				{
					if (isset($GLOBALS['TL_DCA'][$this->ptable]['fields'][$v]['label']))
					{
						$key = \is_array($GLOBALS['TL_DCA'][$this->ptable]['fields'][$v]['label']) ? $GLOBALS['TL_DCA'][$this->ptable]['fields'][$v]['label'][0] : $GLOBALS['TL_DCA'][$this->ptable]['fields'][$v]['label'];
					}
					else
					{
						$key = $GLOBALS['TL_LANG'][$this->ptable][$v][0] ?? $v;
					}

					$add[$key] = $_v;
				}
			}

			// Trigger the header_callback (see #3417)
			if (\is_array($GLOBALS['TL_DCA'][$table]['list']['sorting']['header_callback']))
			{
				$strClass = $GLOBALS['TL_DCA'][$table]['list']['sorting']['header_callback'][0];
				$strMethod = $GLOBALS['TL_DCA'][$table]['list']['sorting']['header_callback'][1];

				$this->import($strClass);
				$add = $this->$strClass->$strMethod($add, $this);
			}
			elseif (\is_callable($GLOBALS['TL_DCA'][$table]['list']['sorting']['header_callback']))
			{
				$add = $GLOBALS['TL_DCA'][$table]['list']['sorting']['header_callback']($add, $this);
			}

			// Output the header data
			$return .= '

<table class="tl_header_table">';

			foreach ($add as $k=>$v)
			{
				if (\is_array($v))
				{
					$v = $v[0];
				}

				$return .= '
  <tr>
    <td><span class="tl_label">'.$k.':</span> </td>
    <td>'.$v.'</td>
  </tr>';
			}

			$return .= '
</table>
</div>';

			$orderBy = array();
			$firstOrderBy = array();

			// Add all records of the current table
			$query = "SELECT * FROM " . $this->strTable;

			if (\is_array($this->orderBy) && \strlen($this->orderBy[0]))
			{
				$orderBy = $this->orderBy;
				$firstOrderBy = preg_replace('/\s+.*$/', '', $orderBy[0]);

				// Order by the foreign key
				if (isset($GLOBALS['TL_DCA'][$this->strTable]['fields'][$firstOrderBy]['foreignKey']))
				{
					$key = explode('.', $GLOBALS['TL_DCA'][$this->strTable]['fields'][$firstOrderBy]['foreignKey'], 2);
					$query = "SELECT *, (SELECT ". Database::quoteIdentifier($key[1]) ." FROM ". $key[0] ." WHERE ". $this->strTable .".". Database::quoteIdentifier($firstOrderBy) ."=". $key[0] .".id) AS foreignKey FROM " . $this->strTable;
					$orderBy[0] = 'foreignKey';
				}
			}
			elseif (\is_array($GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['fields']))
			{
				$orderBy = $GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['fields'];
				$firstOrderBy = preg_replace('/\s+.*$/', '', $orderBy[0]);
			}

			$arrProcedure = $this->procedure;
			$arrValues = $this->values;

			// Support empty ptable fields
			if ($GLOBALS['TL_DCA'][$this->strTable]['config']['dynamicPtable'])
			{
				$arrProcedure[] = ($this->ptable == 'tl_article') ? "(ptable=? OR ptable='')" : "ptable=?";
				$arrValues[] = $this->ptable;
			}

			// WHERE
			if (!empty($arrProcedure))
			{
				$query .= " WHERE " . implode(' AND ', $arrProcedure);
			}
			if (!empty($this->root) && \is_array($this->root))
			{
				$query .= (!empty($arrProcedure) ? " AND " : " WHERE ") . "id IN(" . implode(',', array_map('\intval', $this->root)) . ")";
			}

			// ORDER BY
			if (!empty($orderBy) && \is_array($orderBy))
			{
				$query .= " ORDER BY " . implode(', ', $orderBy);
			}

			$objOrderByStmt = $this->Database->prepare($query);

			// LIMIT
			if (\strlen($this->limit))
			{
				$arrLimit = explode(',', $this->limit);
				$objOrderByStmt->limit($arrLimit[1], $arrLimit[0]);
			}

			$objOrderBy = $objOrderByStmt->execute($arrValues);

			if ($objOrderBy->numRows < 1)
			{
				return $return . '
<p class="tl_empty_parent_view">'.$GLOBALS['TL_LANG']['MSC']['noResult'].'</p>
</div>';
			}

			// Call the child_record_callback
			if (\is_array($GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['child_record_callback']) || \is_callable($GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['child_record_callback']))
			{
				$strGroup = '';
				$blnIndent = false;
				$intWrapLevel = 0;
				$row = $objOrderBy->fetchAllAssoc();

				// Make items sortable
				if ($blnHasSorting)
				{
					$return .= '

<ul id="ul_' . CURRENT_ID . '">';
				}

				for ($i=0, $c=\count($row); $i<$c; $i++)
				{
					$this->current[] = $row[$i]['id'];
					$imagePasteAfter = Image::getHtml('pasteafter.svg', sprintf($GLOBALS['TL_LANG'][$this->strTable]['pasteafter'][1], $row[$i]['id']));
					$imagePasteNew = Image::getHtml('new.svg', sprintf($GLOBALS['TL_LANG'][$this->strTable]['pastenew'][1], $row[$i]['id']));

					// Decrypt encrypted value
					foreach ($row[$i] as $k=>$v)
					{
						if ($GLOBALS['TL_DCA'][$table]['fields'][$k]['eval']['encrypt'])
						{
							$row[$i][$k] = Encryption::decrypt(StringUtil::deserialize($v));
						}
					}

					// Make items sortable
					if ($blnHasSorting)
					{
						$return .= '
<li id="li_' . $row[$i]['id'] . '">';
					}

					// Add the group header
					if (!$GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['disableGrouping'] && $firstOrderBy != 'sorting')
					{
						$sortingMode = (\count($orderBy) == 1 && $firstOrderBy == $orderBy[0] && $GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['flag'] != '' && $GLOBALS['TL_DCA'][$this->strTable]['fields'][$firstOrderBy]['flag'] == '') ? $GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['flag'] : $GLOBALS['TL_DCA'][$this->strTable]['fields'][$firstOrderBy]['flag'];
						$remoteNew = $this->formatCurrentValue($firstOrderBy, $row[$i][$firstOrderBy], $sortingMode);
						$group = $this->formatGroupHeader($firstOrderBy, $remoteNew, $sortingMode, $row[$i]);

						if ($group != $strGroup)
						{
							$return .= "\n\n" . '<div class="tl_content_header">'.$group.'</div>';
							$strGroup = $group;
						}
					}

					$blnWrapperStart = \in_array($row[$i]['type'], $GLOBALS['TL_WRAPPERS']['start']);
					$blnWrapperSeparator = \in_array($row[$i]['type'], $GLOBALS['TL_WRAPPERS']['separator']);
					$blnWrapperStop = \in_array($row[$i]['type'], $GLOBALS['TL_WRAPPERS']['stop']);
					$blnIndentFirst = isset($row[$i - 1]['type']) && \in_array($row[$i - 1]['type'], $GLOBALS['TL_WRAPPERS']['start']);
					$blnIndentLast = isset($row[$i + 1]['type']) && \in_array($row[$i + 1]['type'], $GLOBALS['TL_WRAPPERS']['stop']);

					// Closing wrappers
					if ($blnWrapperStop)
					{
						if (--$intWrapLevel < 1)
						{
							$blnIndent = false;
						}
					}

					$return .= '
<div class="tl_content'.($blnWrapperStart ? ' wrapper_start' : '').($blnWrapperSeparator ? ' wrapper_separator' : '').($blnWrapperStop ? ' wrapper_stop' : '').($blnIndent ? ' indent indent_'.$intWrapLevel : '').($blnIndentFirst ? ' indent_first' : '').($blnIndentLast ? ' indent_last' : '').(($GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['child_record_class'] != '') ? ' ' . $GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['child_record_class'] : '').(($i%2 == 0) ? ' even' : ' odd').' click2edit toggle_select hover-div">
<div class="tl_content_right">';

					// Opening wrappers
					if ($blnWrapperStart)
					{
						if (++$intWrapLevel > 0)
						{
							$blnIndent = true;
						}
					}

					// Edit multiple
					if (Input::get('act') == 'select')
					{
						$return .= '<input type="checkbox" name="IDS[]" id="ids_'.$row[$i]['id'].'" class="tl_tree_checkbox" value="'.$row[$i]['id'].'">';
					}

					// Regular buttons
					else
					{
						$return .= $this->generateButtons($row[$i], $this->strTable, $this->root, false, null, $row[($i-1)]['id'], $row[($i+1)]['id']);

						// Sortable table
						if ($blnHasSorting)
						{
							// Create new button
							if (!$GLOBALS['TL_DCA'][$this->strTable]['config']['closed'] && !$GLOBALS['TL_DCA'][$this->strTable]['config']['notCreatable'])
							{
								$return .= ' <a href="'.$this->addToUrl('act=create&amp;mode=1&amp;pid='.$row[$i]['id'].'&amp;id='.$objParent->id.(Input::get('nb') ? '&amp;nc=1' : '')).'" title="'.StringUtil::specialchars(sprintf($GLOBALS['TL_LANG'][$this->strTable]['pastenew'][1], $row[$i]['id'])).'">'.$imagePasteNew.'</a>';
							}

							// Prevent circular references
							if (($blnClipboard && $arrClipboard['mode'] == 'cut' && $row[$i]['id'] == $arrClipboard['id']) || ($blnMultiboard && $arrClipboard['mode'] == 'cutAll' && \in_array($row[$i]['id'], $arrClipboard['id'])))
							{
								$return .= ' ' . Image::getHtml('pasteafter_.svg');
							}

							// Copy/move multiple
							elseif ($blnMultiboard)
							{
								$return .= ' <a href="'.$this->addToUrl('act='.$arrClipboard['mode'].'&amp;mode=1&amp;pid='.$row[$i]['id']).'" title="'.StringUtil::specialchars(sprintf($GLOBALS['TL_LANG'][$this->strTable]['pasteafter'][1], $row[$i]['id'])).'" onclick="Backend.getScrollOffset()">'.$imagePasteAfter.'</a>';
							}

							// Paste buttons
							elseif ($blnClipboard)
							{
								$return .= ' <a href="'.$this->addToUrl('act='.$arrClipboard['mode'].'&amp;mode=1&amp;pid='.$row[$i]['id'].'&amp;id='.$arrClipboard['id']).'" title="'.StringUtil::specialchars(sprintf($GLOBALS['TL_LANG'][$this->strTable]['pasteafter'][1], $row[$i]['id'])).'" onclick="Backend.getScrollOffset()">'.$imagePasteAfter.'</a>';
							}

							// Drag handle
							if (!$GLOBALS['TL_DCA'][$this->strTable]['config']['notSortable'])
							{
								$return .= ' <button type="button" class="drag-handle" title="' . StringUtil::specialchars(sprintf($GLOBALS['TL_LANG'][$this->strTable]['cut'][1], $row[$i]['id'])) . '" aria-hidden="true">' . Image::getHtml('drag.svg') . '</button>';
							}
						}

						// Picker
						if ($this->strPickerFieldType)
						{
							$return .= $this->getPickerInputField($row[$i]['id']);
						}
					}

					if (\is_array($GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['child_record_callback']))
					{
						$strClass = $GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['child_record_callback'][0];
						$strMethod = $GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['child_record_callback'][1];

						$this->import($strClass);
						$return .= '</div>'.$this->$strClass->$strMethod($row[$i]).'</div>';
					}
					elseif (\is_callable($GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['child_record_callback']))
					{
						$return .= '</div>'.$GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['child_record_callback']($row[$i]).'</div>';
					}

					// Make items sortable
					if ($blnHasSorting)
					{
						$return .= '
</li>';
					}
				}
			}
		}

		// Make items sortable
		if ($blnHasSorting && !$GLOBALS['TL_DCA'][$this->strTable]['config']['notSortable'] && Input::get('act') != 'select')
		{
			$return .= '
</ul>
<script>
  Backend.makeParentViewSortable("ul_' . CURRENT_ID . '");
</script>';
		}

		$return .= ($this->strPickerFieldType == 'radio' ? '
<div class="tl_radio_reset">
<label for="tl_radio_reset" class="tl_radio_label">'.$GLOBALS['TL_LANG']['MSC']['resetSelected'].'</label> <input type="radio" name="picker" id="tl_radio_reset" value="" class="tl_tree_radio">
</div>' : '').'
</div>';

		// Close form
		if (Input::get('act') == 'select')
		{
			// Submit buttons
			$arrButtons = array();

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

			if (!$GLOBALS['TL_DCA'][$this->strTable]['config']['notDeletable'])
			{
				$arrButtons['delete'] = '<button type="submit" name="delete" id="delete" class="tl_submit" accesskey="d" onclick="return confirm(\''.$GLOBALS['TL_LANG']['MSC']['delAllConfirm'].'\')">'.$GLOBALS['TL_LANG']['MSC']['deleteSelected'].'</button>';
			}

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

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

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

			// Call the buttons_callback (see #4691)
			if (\is_array($GLOBALS['TL_DCA'][$this->strTable]['select']['buttons_callback']))
			{
				foreach ($GLOBALS['TL_DCA'][$this->strTable]['select']['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" style="text-align:right">
<div class="tl_submit_container">
  ' . $strButtons . '
</div>
</div>
</form>';
		}

		return $return;
	}
protected function parentView()
	{
		
		$objSession = System::getContainer()->get('session');

		$blnClipboard = false;
		$arrClipboard = $objSession->get('CLIPBOARD');
		$table = ($GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['mode'] == 6) ? $this->ptable : $this->strTable;
		$blnHasSorting = $GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['fields'][0] == 'sorting';
		$blnMultiboard = false;

		
		if (!empty($arrClipboard[$table]))
		{
			$blnClipboard = true;
			$arrClipboard = $arrClipboard[$table];

			if (\is_array($arrClipboard['id']))
			{
				$blnMultiboard = true;
			}
		}

		
		System::loadLanguageFile($this->ptable);
		$this->loadDataContainer($this->ptable);

		$return = Message::generate() . '
<div id="tl_buttons">' . (Input::get('nb') ? '&nbsp;' : ($this->ptable ? '
<a href="'.$this->getReferer(true, $this->ptable).'" class="header_back" title="'.StringUtil::specialchars($GLOBALS['TL_LANG']['MSC']['backBTTitle']).'" accesskey="b" onclick="Backend.getScrollOffset()">'.$GLOBALS['TL_LANG']['MSC']['backBT'].'</a>' : (isset($GLOBALS['TL_DCA'][$this->strTable]['config']['backlink']) ? '
<a href="contao/main.php?'.$GLOBALS['TL_DCA'][$this->strTable]['config']['backlink'].'" class="header_back" title="'.StringUtil::specialchars($GLOBALS['TL_LANG']['MSC']['backBTTitle']).'" accesskey="b" onclick="Backend.getScrollOffset()">'.$GLOBALS['TL_LANG']['MSC']['backBT'].'</a>' : ''))) . ' ' . ((Input::get('act') != 'select' && !$blnClipboard && !$GLOBALS['TL_DCA'][$this->strTable]['config']['closed'] && !$GLOBALS['TL_DCA'][$this->strTable]['config']['notCreatable']) ? '
<a href="'.$this->addToUrl(($blnHasSorting ? 'act=paste&amp;mode=create' : 'act=create&amp;mode=2&amp;pid='.$this->intId)).'" class="header_new" title="'.StringUtil::specialchars($GLOBALS['TL_LANG'][$this->strTable]['new'][1]).'" accesskey="n" onclick="Backend.getScrollOffset()">'.$GLOBALS['TL_LANG'][$this->strTable]['new'][0].'</a> ' : '') . ($blnClipboard ? '
<a href="'.$this->addToUrl('clipboard=1').'" class="header_clipboard" title="'.StringUtil::specialchars($GLOBALS['TL_LANG']['MSC']['clearClipboard']).'" accesskey="x">'.$GLOBALS['TL_LANG']['MSC']['clearClipboard'].'</a> ' : $this->generateGlobalButtons()) . '
</div>';

		
		$objParent = $this->Database->prepare("SELECT * FROM " . $this->ptable . " WHERE id=?")
									->limit(1)
									->execute(CURRENT_ID);

		if ($objParent->numRows < 1)
		{
			return $return;
		}

		$return .= ((Input::get('act') == 'select') ? '

<form action="'.ampersand(Environment::get('request'), true).'" id="tl_select" class="tl_form'.((Input::get('act') == 'select') ? ' unselectable' : '').'" method="post" novalidate>
<div class="tl_formbody_edit">
<input type="hidden" name="FORM_SUBMIT" value="tl_select">
<input type="hidden" name="REQUEST_TOKEN" value="'.REQUEST_TOKEN.'">' : '').($blnClipboard ? '
<div id="paste_hint">
  <p>'.$GLOBALS['TL_LANG']['MSC']['selectNewPosition'].'</p>
</div>' : '').'
<div class="tl_listing_container parent_view'.($this->strPickerFieldType ? ' picker unselectable' : '').'" id="tl_listing">
<div class="tl_header click2edit toggle_select hover-div">';

		
		if (!Input::get('act') || Input::get('act') == 'paste' || Input::get('act') == 'select')
		{
			$this->import(BackendUser::class, 'User');

			
			$imagePasteNew = Image::getHtml('new.svg', $GLOBALS['TL_LANG'][$this->strTable]['pastenew'][0]);
			$imagePasteAfter = Image::getHtml('pasteafter.svg', $GLOBALS['TL_LANG'][$this->strTable]['pasteafter'][0]);
			$imageEditHeader = Image::getHtml('header.svg', $GLOBALS['TL_LANG'][$this->strTable]['editheader'][0]);

			$return .= '
<div class="tl_content_right">'.((Input::get('act') == 'select' || $this->strPickerFieldType == 'checkbox') ? '
<label for="tl_select_trigger" class="tl_select_label">'.$GLOBALS['TL_LANG']['MSC']['selectAll'].'</label> <input type="checkbox" id="tl_select_trigger" onclick="Backend.toggleCheckboxes(this)" class="tl_tree_checkbox">' : ($blnClipboard ? '
<a href="'.$this->addToUrl('act='.$arrClipboard['mode'].'&amp;mode=2&amp;pid='.$objParent->id . (!$blnMultiboard ? '&amp;id='.$arrClipboard['id'] : '')).'" title="'.StringUtil::specialchars($GLOBALS['TL_LANG'][$this->strTable]['pasteafter'][0]).'" onclick="Backend.getScrollOffset()">'.$imagePasteAfter.'</a>' : ((!$GLOBALS['TL_DCA'][$this->ptable]['config']['notEditable'] && $this->User->canEditFieldsOf($this->ptable)) ? '
<a href="'.preg_replace('/&(amp;)?table=[^& ]*/i', (($this->ptable != '') ? '&amp;table='.$this->ptable : ''), $this->addToUrl('act=edit'.(Input::get('nb') ? '&amp;nc=1' : ''))).'" class="edit" title="'.StringUtil::specialchars($GLOBALS['TL_LANG'][$this->ptable]['editmeta'][1] ?? $GLOBALS['TL_LANG'][$this->strTable]['editheader'][1]).'">'.$imageEditHeader.'</a> ' . $this->generateHeaderButtons($objParent->row(), $this->ptable) : '') . (($blnHasSorting && !$GLOBALS['TL_DCA'][$this->strTable]['config']['closed'] && !$GLOBALS['TL_DCA'][$this->strTable]['config']['notCreatable']) ? '
<a href="'.$this->addToUrl('act=create&amp;mode=2&amp;pid='.$objParent->id.'&amp;id='.$this->intId).'" title="'.StringUtil::specialchars($GLOBALS['TL_LANG'][$this->strTable]['pastenew'][0]).'">'.$imagePasteNew.'</a>' : ''))) . '
</div>';

			
			$add = array();
			$headerFields = $GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['headerFields'];

			foreach ($headerFields as $v)
			{
				$_v = StringUtil::deserialize($objParent->$v);

				
				if ($GLOBALS['TL_DCA'][$this->ptable]['fields'][$v]['inputType'] == 'fileTree')
				{
					$objFiles = FilesModel::findMultipleByUuids((array) $_v);

					if ($objFiles !== null)
					{
						$_v = $objFiles->fetchEach('path');
					}
				}

				if (\is_array($_v))
				{
					$_v = implode(', ', $_v);
				}
				elseif ($GLOBALS['TL_DCA'][$this->ptable]['fields'][$v]['eval']['isBoolean'] || ($GLOBALS['TL_DCA'][$this->ptable]['fields'][$v]['inputType'] == 'checkbox' && !$GLOBALS['TL_DCA'][$this->ptable]['fields'][$v]['eval']['multiple']))
				{
					$_v = $_v ? $GLOBALS['TL_LANG']['MSC']['yes'] : $GLOBALS['TL_LANG']['MSC']['no'];
				}
				elseif ($GLOBALS['TL_DCA'][$this->ptable]['fields'][$v]['eval']['rgxp'] == 'date')
				{
					$_v = $_v ? Date::parse(Config::get('dateFormat'), $_v) : '-';
				}
				elseif ($GLOBALS['TL_DCA'][$this->ptable]['fields'][$v]['eval']['rgxp'] == 'time')
				{
					$_v = $_v ? Date::parse(Config::get('timeFormat'), $_v) : '-';
				}
				elseif ($GLOBALS['TL_DCA'][$this->ptable]['fields'][$v]['eval']['rgxp'] == 'datim')
				{
					$_v = $_v ? Date::parse(Config::get('datimFormat'), $_v) : '-';
				}
				elseif ($v == 'tstamp')
				{
					$_v = Date::parse(Config::get('datimFormat'), $objParent->tstamp);
				}
				elseif (isset($GLOBALS['TL_DCA'][$this->ptable]['fields'][$v]['foreignKey']))
				{
					$arrForeignKey = explode('.', $GLOBALS['TL_DCA'][$this->ptable]['fields'][$v]['foreignKey'], 2);

					$objLabel = $this->Database->prepare("SELECT " . Database::quoteIdentifier($arrForeignKey[1]) . " AS value FROM " . $arrForeignKey[0] . " WHERE id=?")
											   ->limit(1)
											   ->execute($_v);

					if ($objLabel->numRows)
					{
						$_v = $objLabel->value;
					}
				}
				elseif (\is_array($GLOBALS['TL_DCA'][$this->ptable]['fields'][$v]['reference'][$_v]))
				{
					$_v = $GLOBALS['TL_DCA'][$this->ptable]['fields'][$v]['reference'][$_v][0];
				}
				elseif (isset($GLOBALS['TL_DCA'][$this->ptable]['fields'][$v]['reference'][$_v]))
				{
					$_v = $GLOBALS['TL_DCA'][$this->ptable]['fields'][$v]['reference'][$_v];
				}
				elseif ($GLOBALS['TL_DCA'][$this->ptable]['fields'][$v]['eval']['isAssociative'] || array_is_assoc($GLOBALS['TL_DCA'][$this->ptable]['fields'][$v]['options']))
				{
					$_v = $GLOBALS['TL_DCA'][$this->ptable]['fields'][$v]['options'][$_v];
				}
				elseif (\is_array($GLOBALS['TL_DCA'][$this->ptable]['fields'][$v]['options_callback']))
				{
					$strClass = $GLOBALS['TL_DCA'][$this->ptable]['fields'][$v]['options_callback'][0];
					$strMethod = $GLOBALS['TL_DCA'][$this->ptable]['fields'][$v]['options_callback'][1];

					$this->import($strClass);
					$options_callback = $this->$strClass->$strMethod($this);

					$_v = $options_callback[$_v];
				}
				elseif (\is_callable($GLOBALS['TL_DCA'][$this->ptable]['fields'][$v]['options_callback']))
				{
					$options_callback = $GLOBALS['TL_DCA'][$this->ptable]['fields'][$v]['options_callback']($this);

					$_v = $options_callback[$_v];
				}

				
				if ($_v != '')
				{
					if (isset($GLOBALS['TL_DCA'][$this->ptable]['fields'][$v]['label']))
					{
						$key = \is_array($GLOBALS['TL_DCA'][$this->ptable]['fields'][$v]['label']) ? $GLOBALS['TL_DCA'][$this->ptable]['fields'][$v]['label'][0] : $GLOBALS['TL_DCA'][$this->ptable]['fields'][$v]['label'];
					}
					else
					{
						$key = $GLOBALS['TL_LANG'][$this->ptable][$v][0] ?? $v;
					}

					$add[$key] = $_v;
				}
			}

			
			if (\is_array($GLOBALS['TL_DCA'][$table]['list']['sorting']['header_callback']))
			{
				$strClass = $GLOBALS['TL_DCA'][$table]['list']['sorting']['header_callback'][0];
				$strMethod = $GLOBALS['TL_DCA'][$table]['list']['sorting']['header_callback'][1];

				$this->import($strClass);
				$add = $this->$strClass->$strMethod($add, $this);
			}
			elseif (\is_callable($GLOBALS['TL_DCA'][$table]['list']['sorting']['header_callback']))
			{
				$add = $GLOBALS['TL_DCA'][$table]['list']['sorting']['header_callback']($add, $this);
			}

			
			$return .= '

<table class="tl_header_table">';

			foreach ($add as $k=>$v)
			{
				if (\is_array($v))
				{
					$v = $v[0];
				}

				$return .= '
  <tr>
    <td><span class="tl_label">'.$k.':</span> </td>
    <td>'.$v.'</td>
  </tr>';
			}

			$return .= '
</table>
</div>';

			$orderBy = array();
			$firstOrderBy = array();

			
			$query = "SELECT * FROM " . $this->strTable;

			if (\is_array($this->orderBy) && \strlen($this->orderBy[0]))
			{
				$orderBy = $this->orderBy;
				$firstOrderBy = preg_replace('/\s+.*$/', '', $orderBy[0]);

				
				if (isset($GLOBALS['TL_DCA'][$this->strTable]['fields'][$firstOrderBy]['foreignKey']))
				{
					$key = explode('.', $GLOBALS['TL_DCA'][$this->strTable]['fields'][$firstOrderBy]['foreignKey'], 2);
					$query = "SELECT *, (SELECT ". Database::quoteIdentifier($key[1]) ." FROM ". $key[0] ." WHERE ". $this->strTable .".". Database::quoteIdentifier($firstOrderBy) ."=". $key[0] .".id) AS foreignKey FROM " . $this->strTable;
					$orderBy[0] = 'foreignKey';
				}
			}
			elseif (\is_array($GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['fields']))
			{
				$orderBy = $GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['fields'];
				$firstOrderBy = preg_replace('/\s+.*$/', '', $orderBy[0]);
			}

			$arrProcedure = $this->procedure;
			$arrValues = $this->values;

			
			if ($GLOBALS['TL_DCA'][$this->strTable]['config']['dynamicPtable'])
			{
				$arrProcedure[] = ($this->ptable == 'tl_article') ? "(ptable=? OR ptable='')" : "ptable=?";
				$arrValues[] = $this->ptable;
			}

			
			if (!empty($arrProcedure))
			{
				$query .= " WHERE " . implode(' AND ', $arrProcedure);
			}
			if (!empty($this->root) && \is_array($this->root))
			{
				$query .= (!empty($arrProcedure) ? " AND " : " WHERE ") . "id IN(" . implode(',', array_map('\intval', $this->root)) . ")";
			}

			
			if (!empty($orderBy) && \is_array($orderBy))
			{
				$query .= " ORDER BY " . implode(', ', $orderBy);
			}

			$objOrderByStmt = $this->Database->prepare($query);

			
			if (\strlen($this->limit))
			{
				$arrLimit = explode(',', $this->limit);
				$objOrderByStmt->limit($arrLimit[1], $arrLimit[0]);
			}

			$objOrderBy = $objOrderByStmt->execute($arrValues);

			if ($objOrderBy->numRows < 1)
			{
				return $return . '
<p class="tl_empty_parent_view">'.$GLOBALS['TL_LANG']['MSC']['noResult'].'</p>
</div>';
			}

			
			if (\is_array($GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['child_record_callback']) || \is_callable($GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['child_record_callback']))
			{
				$strGroup = '';
				$blnIndent = false;
				$intWrapLevel = 0;
				$row = $objOrderBy->fetchAllAssoc();

				
				if ($blnHasSorting)
				{
					$return .= '

<ul id="ul_' . CURRENT_ID . '">';
				}

				for ($i=0, $c=\count($row); $i<$c; $i++)
				{
					$this->current[] = $row[$i]['id'];
					$imagePasteAfter = Image::getHtml('pasteafter.svg', sprintf($GLOBALS['TL_LANG'][$this->strTable]['pasteafter'][1], $row[$i]['id']));
					$imagePasteNew = Image::getHtml('new.svg', sprintf($GLOBALS['TL_LANG'][$this->strTable]['pastenew'][1], $row[$i]['id']));

					
					foreach ($row[$i] as $k=>$v)
					{
						if ($GLOBALS['TL_DCA'][$table]['fields'][$k]['eval']['encrypt'])
						{
							$row[$i][$k] = Encryption::decrypt(StringUtil::deserialize($v));
						}
					}

					
					if ($blnHasSorting)
					{
						$return .= '
<li id="li_' . $row[$i]['id'] . '">';
					}

					
					if (!$GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['disableGrouping'] && $firstOrderBy != 'sorting')
					{
						$sortingMode = (\count($orderBy) == 1 && $firstOrderBy == $orderBy[0] && $GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['flag'] != '' && $GLOBALS['TL_DCA'][$this->strTable]['fields'][$firstOrderBy]['flag'] == '') ? $GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['flag'] : $GLOBALS['TL_DCA'][$this->strTable]['fields'][$firstOrderBy]['flag'];
						$remoteNew = $this->formatCurrentValue($firstOrderBy, $row[$i][$firstOrderBy], $sortingMode);
						$group = $this->formatGroupHeader($firstOrderBy, $remoteNew, $sortingMode, $row[$i]);

						if ($group != $strGroup)
						{
							$return .= "\n\n" . '<div class="tl_content_header">'.$group.'</div>';
							$strGroup = $group;
						}
					}

					$blnWrapperStart = \in_array($row[$i]['type'], $GLOBALS['TL_WRAPPERS']['start']);
					$blnWrapperSeparator = \in_array($row[$i]['type'], $GLOBALS['TL_WRAPPERS']['separator']);
					$blnWrapperStop = \in_array($row[$i]['type'], $GLOBALS['TL_WRAPPERS']['stop']);
					$blnIndentFirst = isset($row[$i - 1]['type']) && \in_array($row[$i - 1]['type'], $GLOBALS['TL_WRAPPERS']['start']);
					$blnIndentLast = isset($row[$i + 1]['type']) && \in_array($row[$i + 1]['type'], $GLOBALS['TL_WRAPPERS']['stop']);

					
					if ($blnWrapperStop)
					{
						if (--$intWrapLevel < 1)
						{
							$blnIndent = false;
						}
					}

					$return .= '
<div class="tl_content'.($blnWrapperStart ? ' wrapper_start' : '').($blnWrapperSeparator ? ' wrapper_separator' : '').($blnWrapperStop ? ' wrapper_stop' : '').($blnIndent ? ' indent indent_'.$intWrapLevel : '').($blnIndentFirst ? ' indent_first' : '').($blnIndentLast ? ' indent_last' : '').(($GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['child_record_class'] != '') ? ' ' . $GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['child_record_class'] : '').(($i%2 == 0) ? ' even' : ' odd').' click2edit toggle_select hover-div">
<div class="tl_content_right">';

					
					if ($blnWrapperStart)
					{
						if (++$intWrapLevel > 0)
						{
							$blnIndent = true;
						}
					}

					
					if (Input::get('act') == 'select')
					{
						$return .= '<input type="checkbox" name="IDS[]" id="ids_'.$row[$i]['id'].'" class="tl_tree_checkbox" value="'.$row[$i]['id'].'">';
					}

					
					else
					{
						$return .= $this->generateButtons($row[$i], $this->strTable, $this->root, false, null, $row[($i-1)]['id'], $row[($i+1)]['id']);

						
						if ($blnHasSorting)
						{
							
							if (!$GLOBALS['TL_DCA'][$this->strTable]['config']['closed'] && !$GLOBALS['TL_DCA'][$this->strTable]['config']['notCreatable'])
							{
								$return .= ' <a href="'.$this->addToUrl('act=create&amp;mode=1&amp;pid='.$row[$i]['id'].'&amp;id='.$objParent->id.(Input::get('nb') ? '&amp;nc=1' : '')).'" title="'.StringUtil::specialchars(sprintf($GLOBALS['TL_LANG'][$this->strTable]['pastenew'][1], $row[$i]['id'])).'">'.$imagePasteNew.'</a>';
							}

							
							if (($blnClipboard && $arrClipboard['mode'] == 'cut' && $row[$i]['id'] == $arrClipboard['id']) || ($blnMultiboard && $arrClipboard['mode'] == 'cutAll' && \in_array($row[$i]['id'], $arrClipboard['id'])))
							{
								$return .= ' ' . Image::getHtml('pasteafter_.svg');
							}

							
							elseif ($blnMultiboard)
							{
								$return .= ' <a href="'.$this->addToUrl('act='.$arrClipboard['mode'].'&amp;mode=1&amp;pid='.$row[$i]['id']).'" title="'.StringUtil::specialchars(sprintf($GLOBALS['TL_LANG'][$this->strTable]['pasteafter'][1], $row[$i]['id'])).'" onclick="Backend.getScrollOffset()">'.$imagePasteAfter.'</a>';
							}

							
							elseif ($blnClipboard)
							{
								$return .= ' <a href="'.$this->addToUrl('act='.$arrClipboard['mode'].'&amp;mode=1&amp;pid='.$row[$i]['id'].'&amp;id='.$arrClipboard['id']).'" title="'.StringUtil::specialchars(sprintf($GLOBALS['TL_LANG'][$this->strTable]['pasteafter'][1], $row[$i]['id'])).'" onclick="Backend.getScrollOffset()">'.$imagePasteAfter.'</a>';
							}

							
							if (!$GLOBALS['TL_DCA'][$this->strTable]['config']['notSortable'])
							{
								$return .= ' <button type="button" class="drag-handle" title="' . StringUtil::specialchars(sprintf($GLOBALS['TL_LANG'][$this->strTable]['cut'][1], $row[$i]['id'])) . '" aria-hidden="true">' . Image::getHtml('drag.svg') . '</button>';
							}
						}

						
						if ($this->strPickerFieldType)
						{
							$return .= $this->getPickerInputField($row[$i]['id']);
						}
					}

					if (\is_array($GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['child_record_callback']))
					{
						$strClass = $GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['child_record_callback'][0];
						$strMethod = $GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['child_record_callback'][1];

						$this->import($strClass);
						$return .= '</div>'.$this->$strClass->$strMethod($row[$i]).'</div>';
					}
					elseif (\is_callable($GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['child_record_callback']))
					{
						$return .= '</div>'.$GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['child_record_callback']($row[$i]).'</div>';
					}

					
					if ($blnHasSorting)
					{
						$return .= '
</li>';
					}
				}
			}
		}

		
		if ($blnHasSorting && !$GLOBALS['TL_DCA'][$this->strTable]['config']['notSortable'] && Input::get('act') != 'select')
		{
			$return .= '
</ul>
<script>
  Backend.makeParentViewSortable("ul_' . CURRENT_ID . '");
</script>';
		}

		$return .= ($this->strPickerFieldType == 'radio' ? '
<div class="tl_radio_reset">
<label for="tl_radio_reset" class="tl_radio_label">'.$GLOBALS['TL_LANG']['MSC']['resetSelected'].'</label> <input type="radio" name="picker" id="tl_radio_reset" value="" class="tl_tree_radio">
</div>' : '').'
</div>';

		
		if (Input::get('act') == 'select')
		{
			
			$arrButtons = array();

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

			if (!$GLOBALS['TL_DCA'][$this->strTable]['config']['notDeletable'])
			{
				$arrButtons['delete'] = '<button type="submit" name="delete" id="delete" class="tl_submit" accesskey="d" onclick="return confirm(\''.$GLOBALS['TL_LANG']['MSC']['delAllConfirm'].'\')">'.$GLOBALS['TL_LANG']['MSC']['deleteSelected'].'</button>';
			}

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

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

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

			
			if (\is_array($GLOBALS['TL_DCA'][$this->strTable]['select']['buttons_callback']))
			{
				foreach ($GLOBALS['TL_DCA'][$this->strTable]['select']['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" style="text-align:right">
<div class="tl_submit_container">
  ' . $strButtons . '
</div>
</div>
</form>';
		}

		return $return;
	}
protected function parentView ( ) { /** @var Session $objSession */ $ objSession = System :: getContainer ( ) -> get ( 'session' ) ; $ blnClipboard = false ; $ arrClipboard = $ objSession -> get ( 'CLIPBOARD' ) ; $ table = ( $ GLOBALS [ 'TL_DCA' ] [ $ this -> strTable ] [ 'list' ] [ 'sorting' ] [ 'mode' ] == 6 ) ? $ this -> ptable : $ this -> strTable ; $ blnHasSorting = $ GLOBALS [ 'TL_DCA' ] [ $ this -> strTable ] [ 'list' ] [ 'sorting' ] [ 'fields' ] [ 0 ] == 'sorting' ; $ blnMultiboard = false ; // Check clipboard if ( ! empty ( $ arrClipboard [ $ table ] ) ) { $ blnClipboard = true ; $ arrClipboard = $ arrClipboard [ $ table ] ; if ( \ is_array ( $ arrClipboard [ 'id' ] ) ) { $ blnMultiboard = true ; } } // Load the language file and data container array of the parent table System :: loadLanguageFile ( $ this -> ptable ) ; $ this -> loadDataContainer ( $ this -> ptable ) ; $ return = Message :: generate ( ) . '
<div id="tl_buttons">' . ( Input :: get ( 'nb' ) ? '&nbsp;' : ( $ this -> ptable ? '
<a href="' . $ this -> getReferer ( true , $ this -> ptable ) . '" class="header_back" title="' . StringUtil :: specialchars ( $ GLOBALS [ 'TL_LANG' ] [ 'MSC' ] [ 'backBTTitle' ] ) . '" accesskey="b" onclick="Backend.getScrollOffset()">' . $ GLOBALS [ 'TL_LANG' ] [ 'MSC' ] [ 'backBT' ] . '</a>' : ( isset ( $ GLOBALS [ 'TL_DCA' ] [ $ this -> strTable ] [ 'config' ] [ 'backlink' ] ) ? '
<a href="contao/main.php?' . $ GLOBALS [ 'TL_DCA' ] [ $ this -> strTable ] [ 'config' ] [ 'backlink' ] . '" class="header_back" title="' . StringUtil :: specialchars ( $ GLOBALS [ 'TL_LANG' ] [ 'MSC' ] [ 'backBTTitle' ] ) . '" accesskey="b" onclick="Backend.getScrollOffset()">' . $ GLOBALS [ 'TL_LANG' ] [ 'MSC' ] [ 'backBT' ] . '</a>' : '' ) ) ) . ' ' . ( ( Input :: get ( 'act' ) != 'select' && ! $ blnClipboard && ! $ GLOBALS [ 'TL_DCA' ] [ $ this -> strTable ] [ 'config' ] [ 'closed' ] && ! $ GLOBALS [ 'TL_DCA' ] [ $ this -> strTable ] [ 'config' ] [ 'notCreatable' ] ) ? '
<a href="' . $ this -> addToUrl ( ( $ blnHasSorting ? 'act=paste&amp;mode=create' : 'act=create&amp;mode=2&amp;pid=' . $ this -> intId ) ) . '" class="header_new" title="' . StringUtil :: specialchars ( $ GLOBALS [ 'TL_LANG' ] [ $ this -> strTable ] [ 'new' ] [ 1 ] ) . '" accesskey="n" onclick="Backend.getScrollOffset()">' . $ GLOBALS [ 'TL_LANG' ] [ $ this -> strTable ] [ 'new' ] [ 0 ] . '</a> ' : '' ) . ( $ blnClipboard ? '
<a href="' . $ this -> addToUrl ( 'clipboard=1' ) . '" class="header_clipboard" title="' . StringUtil :: specialchars ( $ GLOBALS [ 'TL_LANG' ] [ 'MSC' ] [ 'clearClipboard' ] ) . '" accesskey="x">' . $ GLOBALS [ 'TL_LANG' ] [ 'MSC' ] [ 'clearClipboard' ] . '</a> ' : $ this -> generateGlobalButtons ( ) ) . '
</div>' ; // Get all details of the parent record $ objParent = $ this -> Database -> prepare ( "SELECT * FROM " . $ this -> ptable . " WHERE id=?" ) -> limit ( 1 ) -> execute ( CURRENT_ID ) ; if ( $ objParent -> numRows < 1 ) { return $ return ; } $ return .= ( ( Input :: get ( 'act' ) == 'select' ) ? '

<form action="' . ampersand ( Environment :: get ( 'request' ) , true ) . '" id="tl_select" class="tl_form' . ( ( Input :: get ( 'act' ) == 'select' ) ? ' unselectable' : '' ) . '" method="post" novalidate>
<div class="tl_formbody_edit">
<input type="hidden" name="FORM_SUBMIT" value="tl_select">
<input type="hidden" name="REQUEST_TOKEN" value="' . REQUEST_TOKEN . '">' : '' ) . ( $ blnClipboard ? '
<div id="paste_hint">
  <p>' . $ GLOBALS [ 'TL_LANG' ] [ 'MSC' ] [ 'selectNewPosition' ] . '</p>
</div>' : '' ) . '
<div class="tl_listing_container parent_view' . ( $ this -> strPickerFieldType ? ' picker unselectable' : '' ) . '" id="tl_listing">
<div class="tl_header click2edit toggle_select hover-div">' ; // List all records of the child table if ( ! Input :: get ( 'act' ) || Input :: get ( 'act' ) == 'paste' || Input :: get ( 'act' ) == 'select' ) { $ this -> import ( BackendUser :: class , 'User' ) ; // Header $ imagePasteNew = Image :: getHtml ( 'new.svg' , $ GLOBALS [ 'TL_LANG' ] [ $ this -> strTable ] [ 'pastenew' ] [ 0 ] ) ; $ imagePasteAfter = Image :: getHtml ( 'pasteafter.svg' , $ GLOBALS [ 'TL_LANG' ] [ $ this -> strTable ] [ 'pasteafter' ] [ 0 ] ) ; $ imageEditHeader = Image :: getHtml ( 'header.svg' , $ GLOBALS [ 'TL_LANG' ] [ $ this -> strTable ] [ 'editheader' ] [ 0 ] ) ; $ return .= '
<div class="tl_content_right">' . ( ( Input :: get ( 'act' ) == 'select' || $ this -> strPickerFieldType == 'checkbox' ) ? '
<label for="tl_select_trigger" class="tl_select_label">' . $ GLOBALS [ 'TL_LANG' ] [ 'MSC' ] [ 'selectAll' ] . '</label> <input type="checkbox" id="tl_select_trigger" onclick="Backend.toggleCheckboxes(this)" class="tl_tree_checkbox">' : ( $ blnClipboard ? '
<a href="' . $ this -> addToUrl ( 'act=' . $ arrClipboard [ 'mode' ] . '&amp;mode=2&amp;pid=' . $ objParent -> id . ( ! $ blnMultiboard ? '&amp;id=' . $ arrClipboard [ 'id' ] : '' ) ) . '" title="' . StringUtil :: specialchars ( $ GLOBALS [ 'TL_LANG' ] [ $ this -> strTable ] [ 'pasteafter' ] [ 0 ] ) . '" onclick="Backend.getScrollOffset()">' . $ imagePasteAfter . '</a>' : ( ( ! $ GLOBALS [ 'TL_DCA' ] [ $ this -> ptable ] [ 'config' ] [ 'notEditable' ] && $ this -> User -> canEditFieldsOf ( $ this -> ptable ) ) ? '
<a href="' . preg_replace ( '/&(amp;)?table=[^& ]*/i' , ( ( $ this -> ptable != '' ) ? '&amp;table=' . $ this -> ptable : '' ) , $ this -> addToUrl ( 'act=edit' . ( Input :: get ( 'nb' ) ? '&amp;nc=1' : '' ) ) ) . '" class="edit" title="' . StringUtil :: specialchars ( $ GLOBALS [ 'TL_LANG' ] [ $ this -> ptable ] [ 'editmeta' ] [ 1 ] ?? $ GLOBALS [ 'TL_LANG' ] [ $ this -> strTable ] [ 'editheader' ] [ 1 ] ) . '">' . $ imageEditHeader . '</a> ' . $ this -> generateHeaderButtons ( $ objParent -> row ( ) , $ this -> ptable ) : '' ) . ( ( $ blnHasSorting && ! $ GLOBALS [ 'TL_DCA' ] [ $ this -> strTable ] [ 'config' ] [ 'closed' ] && ! $ GLOBALS [ 'TL_DCA' ] [ $ this -> strTable ] [ 'config' ] [ 'notCreatable' ] ) ? '
<a href="' . $ this -> addToUrl ( 'act=create&amp;mode=2&amp;pid=' . $ objParent -> id . '&amp;id=' . $ this -> intId ) . '" title="' . StringUtil :: specialchars ( $ GLOBALS [ 'TL_LANG' ] [ $ this -> strTable ] [ 'pastenew' ] [ 0 ] ) . '">' . $ imagePasteNew . '</a>' : '' ) ) ) . '
</div>' ; // Format header fields $ add = array ( ) ; $ headerFields = $ GLOBALS [ 'TL_DCA' ] [ $ this -> strTable ] [ 'list' ] [ 'sorting' ] [ 'headerFields' ] ; foreach ( $ headerFields as $ v ) { $ _v = StringUtil :: deserialize ( $ objParent -> $ v ) ; // Translate UUIDs to paths if ( $ GLOBALS [ 'TL_DCA' ] [ $ this -> ptable ] [ 'fields' ] [ $ v ] [ 'inputType' ] == 'fileTree' ) { $ objFiles = FilesModel :: findMultipleByUuids ( ( array ) $ _v ) ; if ( $ objFiles !== null ) { $ _v = $ objFiles -> fetchEach ( 'path' ) ; } } if ( \ is_array ( $ _v ) ) { $ _v = implode ( ', ' , $ _v ) ; } elseif ( $ GLOBALS [ 'TL_DCA' ] [ $ this -> ptable ] [ 'fields' ] [ $ v ] [ 'eval' ] [ 'isBoolean' ] || ( $ GLOBALS [ 'TL_DCA' ] [ $ this -> ptable ] [ 'fields' ] [ $ v ] [ 'inputType' ] == 'checkbox' && ! $ GLOBALS [ 'TL_DCA' ] [ $ this -> ptable ] [ 'fields' ] [ $ v ] [ 'eval' ] [ 'multiple' ] ) ) { $ _v = $ _v ? $ GLOBALS [ 'TL_LANG' ] [ 'MSC' ] [ 'yes' ] : $ GLOBALS [ 'TL_LANG' ] [ 'MSC' ] [ 'no' ] ; } elseif ( $ GLOBALS [ 'TL_DCA' ] [ $ this -> ptable ] [ 'fields' ] [ $ v ] [ 'eval' ] [ 'rgxp' ] == 'date' ) { $ _v = $ _v ? Date :: parse ( Config :: get ( 'dateFormat' ) , $ _v ) : '-' ; } elseif ( $ GLOBALS [ 'TL_DCA' ] [ $ this -> ptable ] [ 'fields' ] [ $ v ] [ 'eval' ] [ 'rgxp' ] == 'time' ) { $ _v = $ _v ? Date :: parse ( Config :: get ( 'timeFormat' ) , $ _v ) : '-' ; } elseif ( $ GLOBALS [ 'TL_DCA' ] [ $ this -> ptable ] [ 'fields' ] [ $ v ] [ 'eval' ] [ 'rgxp' ] == 'datim' ) { $ _v = $ _v ? Date :: parse ( Config :: get ( 'datimFormat' ) , $ _v ) : '-' ; } elseif ( $ v == 'tstamp' ) { $ _v = Date :: parse ( Config :: get ( 'datimFormat' ) , $ objParent -> tstamp ) ; } elseif ( isset ( $ GLOBALS [ 'TL_DCA' ] [ $ this -> ptable ] [ 'fields' ] [ $ v ] [ 'foreignKey' ] ) ) { $ arrForeignKey = explode ( '.' , $ GLOBALS [ 'TL_DCA' ] [ $ this -> ptable ] [ 'fields' ] [ $ v ] [ 'foreignKey' ] , 2 ) ; $ objLabel = $ this -> Database -> prepare ( "SELECT " . Database :: quoteIdentifier ( $ arrForeignKey [ 1 ] ) . " AS value FROM " . $ arrForeignKey [ 0 ] . " WHERE id=?" ) -> limit ( 1 ) -> execute ( $ _v ) ; if ( $ objLabel -> numRows ) { $ _v = $ objLabel -> value ; } } elseif ( \ is_array ( $ GLOBALS [ 'TL_DCA' ] [ $ this -> ptable ] [ 'fields' ] [ $ v ] [ 'reference' ] [ $ _v ] ) ) { $ _v = $ GLOBALS [ 'TL_DCA' ] [ $ this -> ptable ] [ 'fields' ] [ $ v ] [ 'reference' ] [ $ _v ] [ 0 ] ; } elseif ( isset ( $ GLOBALS [ 'TL_DCA' ] [ $ this -> ptable ] [ 'fields' ] [ $ v ] [ 'reference' ] [ $ _v ] ) ) { $ _v = $ GLOBALS [ 'TL_DCA' ] [ $ this -> ptable ] [ 'fields' ] [ $ v ] [ 'reference' ] [ $ _v ] ; } elseif ( $ GLOBALS [ 'TL_DCA' ] [ $ this -> ptable ] [ 'fields' ] [ $ v ] [ 'eval' ] [ 'isAssociative' ] || array_is_assoc ( $ GLOBALS [ 'TL_DCA' ] [ $ this -> ptable ] [ 'fields' ] [ $ v ] [ 'options' ] ) ) { $ _v = $ GLOBALS [ 'TL_DCA' ] [ $ this -> ptable ] [ 'fields' ] [ $ v ] [ 'options' ] [ $ _v ] ; } elseif ( \ is_array ( $ GLOBALS [ 'TL_DCA' ] [ $ this -> ptable ] [ 'fields' ] [ $ v ] [ 'options_callback' ] ) ) { $ strClass = $ GLOBALS [ 'TL_DCA' ] [ $ this -> ptable ] [ 'fields' ] [ $ v ] [ 'options_callback' ] [ 0 ] ; $ strMethod = $ GLOBALS [ 'TL_DCA' ] [ $ this -> ptable ] [ 'fields' ] [ $ v ] [ 'options_callback' ] [ 1 ] ; $ this -> import ( $ strClass ) ; $ options_callback = $ this -> $ strClass -> $ strMethod ( $ this ) ; $ _v = $ options_callback [ $ _v ] ; } elseif ( \ is_callable ( $ GLOBALS [ 'TL_DCA' ] [ $ this -> ptable ] [ 'fields' ] [ $ v ] [ 'options_callback' ] ) ) { $ options_callback = $ GLOBALS [ 'TL_DCA' ] [ $ this -> ptable ] [ 'fields' ] [ $ v ] [ 'options_callback' ] ( $ this ) ; $ _v = $ options_callback [ $ _v ] ; } // Add the sorting field if ( $ _v != '' ) { if ( isset ( $ GLOBALS [ 'TL_DCA' ] [ $ this -> ptable ] [ 'fields' ] [ $ v ] [ 'label' ] ) ) { $ key = \ is_array ( $ GLOBALS [ 'TL_DCA' ] [ $ this -> ptable ] [ 'fields' ] [ $ v ] [ 'label' ] ) ? $ GLOBALS [ 'TL_DCA' ] [ $ this -> ptable ] [ 'fields' ] [ $ v ] [ 'label' ] [ 0 ] : $ GLOBALS [ 'TL_DCA' ] [ $ this -> ptable ] [ 'fields' ] [ $ v ] [ 'label' ] ; } else { $ key = $ GLOBALS [ 'TL_LANG' ] [ $ this -> ptable ] [ $ v ] [ 0 ] ?? $ v ; } $ add [ $ key ] = $ _v ; } } // Trigger the header_callback (see #3417) if ( \ is_array ( $ GLOBALS [ 'TL_DCA' ] [ $ table ] [ 'list' ] [ 'sorting' ] [ 'header_callback' ] ) ) { $ strClass = $ GLOBALS [ 'TL_DCA' ] [ $ table ] [ 'list' ] [ 'sorting' ] [ 'header_callback' ] [ 0 ] ; $ strMethod = $ GLOBALS [ 'TL_DCA' ] [ $ table ] [ 'list' ] [ 'sorting' ] [ 'header_callback' ] [ 1 ] ; $ this -> import ( $ strClass ) ; $ add = $ this -> $ strClass -> $ strMethod ( $ add , $ this ) ; } elseif ( \ is_callable ( $ GLOBALS [ 'TL_DCA' ] [ $ table ] [ 'list' ] [ 'sorting' ] [ 'header_callback' ] ) ) { $ add = $ GLOBALS [ 'TL_DCA' ] [ $ table ] [ 'list' ] [ 'sorting' ] [ 'header_callback' ] ( $ add , $ this ) ; } // Output the header data $ return .= '

<table class="tl_header_table">' ; foreach ( $ add as $ k => $ v ) { if ( \ is_array ( $ v ) ) { $ v = $ v [ 0 ] ; } $ return .= '
  <tr>
    <td><span class="tl_label">' . $ k . ':</span> </td>
    <td>' . $ v . '</td>
  </tr>' ; } $ return .= '
</table>
</div>' ; $ orderBy = array ( ) ; $ firstOrderBy = array ( ) ; // Add all records of the current table $ query = "SELECT * FROM " . $ this -> strTable ; if ( \ is_array ( $ this -> orderBy ) && \ strlen ( $ this -> orderBy [ 0 ] ) ) { $ orderBy = $ this -> orderBy ; $ firstOrderBy = preg_replace ( '/\s+.*$/' , '' , $ orderBy [ 0 ] ) ; // Order by the foreign key if ( isset ( $ GLOBALS [ 'TL_DCA' ] [ $ this -> strTable ] [ 'fields' ] [ $ firstOrderBy ] [ 'foreignKey' ] ) ) { $ key = explode ( '.' , $ GLOBALS [ 'TL_DCA' ] [ $ this -> strTable ] [ 'fields' ] [ $ firstOrderBy ] [ 'foreignKey' ] , 2 ) ; $ query = "SELECT *, (SELECT " . Database :: quoteIdentifier ( $ key [ 1 ] ) . " FROM " . $ key [ 0 ] . " WHERE " . $ this -> strTable . "." . Database :: quoteIdentifier ( $ firstOrderBy ) . "=" . $ key [ 0 ] . ".id) AS foreignKey FROM " . $ this -> strTable ; $ orderBy [ 0 ] = 'foreignKey' ; } } elseif ( \ is_array ( $ GLOBALS [ 'TL_DCA' ] [ $ this -> strTable ] [ 'list' ] [ 'sorting' ] [ 'fields' ] ) ) { $ orderBy = $ GLOBALS [ 'TL_DCA' ] [ $ this -> strTable ] [ 'list' ] [ 'sorting' ] [ 'fields' ] ; $ firstOrderBy = preg_replace ( '/\s+.*$/' , '' , $ orderBy [ 0 ] ) ; } $ arrProcedure = $ this -> procedure ; $ arrValues = $ this -> values ; // Support empty ptable fields if ( $ GLOBALS [ 'TL_DCA' ] [ $ this -> strTable ] [ 'config' ] [ 'dynamicPtable' ] ) { $ arrProcedure [ ] = ( $ this -> ptable == 'tl_article' ) ? "(ptable=? OR ptable='')" : "ptable=?" ; $ arrValues [ ] = $ this -> ptable ; } // WHERE if ( ! empty ( $ arrProcedure ) ) { $ query .= " WHERE " . implode ( ' AND ' , $ arrProcedure ) ; } if ( ! empty ( $ this -> root ) && \ is_array ( $ this -> root ) ) { $ query .= ( ! empty ( $ arrProcedure ) ? " AND " : " WHERE " ) . "id IN(" . implode ( ',' , array_map ( '\intval' , $ this -> root ) ) . ")" ; } // ORDER BY if ( ! empty ( $ orderBy ) && \ is_array ( $ orderBy ) ) { $ query .= " ORDER BY " . implode ( ', ' , $ orderBy ) ; } $ objOrderByStmt = $ this -> Database -> prepare ( $ query ) ; // LIMIT if ( \ strlen ( $ this -> limit ) ) { $ arrLimit = explode ( ',' , $ this -> limit ) ; $ objOrderByStmt -> limit ( $ arrLimit [ 1 ] , $ arrLimit [ 0 ] ) ; } $ objOrderBy = $ objOrderByStmt -> execute ( $ arrValues ) ; if ( $ objOrderBy -> numRows < 1 ) { return $ return . '
<p class="tl_empty_parent_view">' . $ GLOBALS [ 'TL_LANG' ] [ 'MSC' ] [ 'noResult' ] . '</p>
</div>' ; } // Call the child_record_callback if ( \ is_array ( $ GLOBALS [ 'TL_DCA' ] [ $ this -> strTable ] [ 'list' ] [ 'sorting' ] [ 'child_record_callback' ] ) || \ is_callable ( $ GLOBALS [ 'TL_DCA' ] [ $ this -> strTable ] [ 'list' ] [ 'sorting' ] [ 'child_record_callback' ] ) ) { $ strGroup = '' ; $ blnIndent = false ; $ intWrapLevel = 0 ; $ row = $ objOrderBy -> fetchAllAssoc ( ) ; // Make items sortable if ( $ blnHasSorting ) { $ return .= '

<ul id="ul_' . CURRENT_ID . '">' ; } for ( $ i = 0 , $ c = \ count ( $ row ) ; $ i < $ c ; $ i ++ ) { $ this -> current [ ] = $ row [ $ i ] [ 'id' ] ; $ imagePasteAfter = Image :: getHtml ( 'pasteafter.svg' , sprintf ( $ GLOBALS [ 'TL_LANG' ] [ $ this -> strTable ] [ 'pasteafter' ] [ 1 ] , $ row [ $ i ] [ 'id' ] ) ) ; $ imagePasteNew = Image :: getHtml ( 'new.svg' , sprintf ( $ GLOBALS [ 'TL_LANG' ] [ $ this -> strTable ] [ 'pastenew' ] [ 1 ] , $ row [ $ i ] [ 'id' ] ) ) ; // Decrypt encrypted value foreach ( $ row [ $ i ] as $ k => $ v ) { if ( $ GLOBALS [ 'TL_DCA' ] [ $ table ] [ 'fields' ] [ $ k ] [ 'eval' ] [ 'encrypt' ] ) { $ row [ $ i ] [ $ k ] = Encryption :: decrypt ( StringUtil :: deserialize ( $ v ) ) ; } } // Make items sortable if ( $ blnHasSorting ) { $ return .= '
<li id="li_' . $ row [ $ i ] [ 'id' ] . '">' ; } // Add the group header if ( ! $ GLOBALS [ 'TL_DCA' ] [ $ this -> strTable ] [ 'list' ] [ 'sorting' ] [ 'disableGrouping' ] && $ firstOrderBy != 'sorting' ) { $ sortingMode = ( \ count ( $ orderBy ) == 1 && $ firstOrderBy == $ orderBy [ 0 ] && $ GLOBALS [ 'TL_DCA' ] [ $ this -> strTable ] [ 'list' ] [ 'sorting' ] [ 'flag' ] != '' && $ GLOBALS [ 'TL_DCA' ] [ $ this -> strTable ] [ 'fields' ] [ $ firstOrderBy ] [ 'flag' ] == '' ) ? $ GLOBALS [ 'TL_DCA' ] [ $ this -> strTable ] [ 'list' ] [ 'sorting' ] [ 'flag' ] : $ GLOBALS [ 'TL_DCA' ] [ $ this -> strTable ] [ 'fields' ] [ $ firstOrderBy ] [ 'flag' ] ; $ remoteNew = $ this -> formatCurrentValue ( $ firstOrderBy , $ row [ $ i ] [ $ firstOrderBy ] , $ sortingMode ) ; $ group = $ this -> formatGroupHeader ( $ firstOrderBy , $ remoteNew , $ sortingMode , $ row [ $ i ] ) ; if ( $ group != $ strGroup ) { $ return .= "\n\n" . '<div class="tl_content_header">' . $ group . '</div>' ; $ strGroup = $ group ; } } $ blnWrapperStart = \ in_array ( $ row [ $ i ] [ 'type' ] , $ GLOBALS [ 'TL_WRAPPERS' ] [ 'start' ] ) ; $ blnWrapperSeparator = \ in_array ( $ row [ $ i ] [ 'type' ] , $ GLOBALS [ 'TL_WRAPPERS' ] [ 'separator' ] ) ; $ blnWrapperStop = \ in_array ( $ row [ $ i ] [ 'type' ] , $ GLOBALS [ 'TL_WRAPPERS' ] [ 'stop' ] ) ; $ blnIndentFirst = isset ( $ row [ $ i - 1 ] [ 'type' ] ) && \ in_array ( $ row [ $ i - 1 ] [ 'type' ] , $ GLOBALS [ 'TL_WRAPPERS' ] [ 'start' ] ) ; $ blnIndentLast = isset ( $ row [ $ i + 1 ] [ 'type' ] ) && \ in_array ( $ row [ $ i + 1 ] [ 'type' ] , $ GLOBALS [ 'TL_WRAPPERS' ] [ 'stop' ] ) ; // Closing wrappers if ( $ blnWrapperStop ) { if ( -- $ intWrapLevel < 1 ) { $ blnIndent = false ; } } $ return .= '
<div class="tl_content' . ( $ blnWrapperStart ? ' wrapper_start' : '' ) . ( $ blnWrapperSeparator ? ' wrapper_separator' : '' ) . ( $ blnWrapperStop ? ' wrapper_stop' : '' ) . ( $ blnIndent ? ' indent indent_' . $ intWrapLevel : '' ) . ( $ blnIndentFirst ? ' indent_first' : '' ) . ( $ blnIndentLast ? ' indent_last' : '' ) . ( ( $ GLOBALS [ 'TL_DCA' ] [ $ this -> strTable ] [ 'list' ] [ 'sorting' ] [ 'child_record_class' ] != '' ) ? ' ' . $ GLOBALS [ 'TL_DCA' ] [ $ this -> strTable ] [ 'list' ] [ 'sorting' ] [ 'child_record_class' ] : '' ) . ( ( $ i % 2 == 0 ) ? ' even' : ' odd' ) . ' click2edit toggle_select hover-div">
<div class="tl_content_right">' ; // Opening wrappers if ( $ blnWrapperStart ) { if ( ++ $ intWrapLevel > 0 ) { $ blnIndent = true ; } } // Edit multiple if ( Input :: get ( 'act' ) == 'select' ) { $ return .= '<input type="checkbox" name="IDS[]" id="ids_' . $ row [ $ i ] [ 'id' ] . '" class="tl_tree_checkbox" value="' . $ row [ $ i ] [ 'id' ] . '">' ; } // Regular buttons else { $ return .= $ this -> generateButtons ( $ row [ $ i ] , $ this -> strTable , $ this -> root , false , null , $ row [ ( $ i - 1 ) ] [ 'id' ] , $ row [ ( $ i + 1 ) ] [ 'id' ] ) ; // Sortable table if ( $ blnHasSorting ) { // Create new button if ( ! $ GLOBALS [ 'TL_DCA' ] [ $ this -> strTable ] [ 'config' ] [ 'closed' ] && ! $ GLOBALS [ 'TL_DCA' ] [ $ this -> strTable ] [ 'config' ] [ 'notCreatable' ] ) { $ return .= ' <a href="' . $ this -> addToUrl ( 'act=create&amp;mode=1&amp;pid=' . $ row [ $ i ] [ 'id' ] . '&amp;id=' . $ objParent -> id . ( Input :: get ( 'nb' ) ? '&amp;nc=1' : '' ) ) . '" title="' . StringUtil :: specialchars ( sprintf ( $ GLOBALS [ 'TL_LANG' ] [ $ this -> strTable ] [ 'pastenew' ] [ 1 ] , $ row [ $ i ] [ 'id' ] ) ) . '">' . $ imagePasteNew . '</a>' ; } // Prevent circular references if ( ( $ blnClipboard && $ arrClipboard [ 'mode' ] == 'cut' && $ row [ $ i ] [ 'id' ] == $ arrClipboard [ 'id' ] ) || ( $ blnMultiboard && $ arrClipboard [ 'mode' ] == 'cutAll' && \ in_array ( $ row [ $ i ] [ 'id' ] , $ arrClipboard [ 'id' ] ) ) ) { $ return .= ' ' . Image :: getHtml ( 'pasteafter_.svg' ) ; } // Copy/move multiple elseif ( $ blnMultiboard ) { $ return .= ' <a href="' . $ this -> addToUrl ( 'act=' . $ arrClipboard [ 'mode' ] . '&amp;mode=1&amp;pid=' . $ row [ $ i ] [ 'id' ] ) . '" title="' . StringUtil :: specialchars ( sprintf ( $ GLOBALS [ 'TL_LANG' ] [ $ this -> strTable ] [ 'pasteafter' ] [ 1 ] , $ row [ $ i ] [ 'id' ] ) ) . '" onclick="Backend.getScrollOffset()">' . $ imagePasteAfter . '</a>' ; } // Paste buttons elseif ( $ blnClipboard ) { $ return .= ' <a href="' . $ this -> addToUrl ( 'act=' . $ arrClipboard [ 'mode' ] . '&amp;mode=1&amp;pid=' . $ row [ $ i ] [ 'id' ] . '&amp;id=' . $ arrClipboard [ 'id' ] ) . '" title="' . StringUtil :: specialchars ( sprintf ( $ GLOBALS [ 'TL_LANG' ] [ $ this -> strTable ] [ 'pasteafter' ] [ 1 ] , $ row [ $ i ] [ 'id' ] ) ) . '" onclick="Backend.getScrollOffset()">' . $ imagePasteAfter . '</a>' ; } // Drag handle if ( ! $ GLOBALS [ 'TL_DCA' ] [ $ this -> strTable ] [ 'config' ] [ 'notSortable' ] ) { $ return .= ' <button type="button" class="drag-handle" title="' . StringUtil :: specialchars ( sprintf ( $ GLOBALS [ 'TL_LANG' ] [ $ this -> strTable ] [ 'cut' ] [ 1 ] , $ row [ $ i ] [ 'id' ] ) ) . '" aria-hidden="true">' . Image :: getHtml ( 'drag.svg' ) . '</button>' ; } } // Picker if ( $ this -> strPickerFieldType ) { $ return .= $ this -> getPickerInputField ( $ row [ $ i ] [ 'id' ] ) ; } } if ( \ is_array ( $ GLOBALS [ 'TL_DCA' ] [ $ this -> strTable ] [ 'list' ] [ 'sorting' ] [ 'child_record_callback' ] ) ) { $ strClass = $ GLOBALS [ 'TL_DCA' ] [ $ this -> strTable ] [ 'list' ] [ 'sorting' ] [ 'child_record_callback' ] [ 0 ] ; $ strMethod = $ GLOBALS [ 'TL_DCA' ] [ $ this -> strTable ] [ 'list' ] [ 'sorting' ] [ 'child_record_callback' ] [ 1 ] ; $ this -> import ( $ strClass ) ; $ return .= '</div>' . $ this -> $ strClass -> $ strMethod ( $ row [ $ i ] ) . '</div>' ; } elseif ( \ is_callable ( $ GLOBALS [ 'TL_DCA' ] [ $ this -> strTable ] [ 'list' ] [ 'sorting' ] [ 'child_record_callback' ] ) ) { $ return .= '</div>' . $ GLOBALS [ 'TL_DCA' ] [ $ this -> strTable ] [ 'list' ] [ 'sorting' ] [ 'child_record_callback' ] ( $ row [ $ i ] ) . '</div>' ; } // Make items sortable if ( $ blnHasSorting ) { $ return .= '
</li>' ; } } } } // Make items sortable if ( $ blnHasSorting && ! $ GLOBALS [ 'TL_DCA' ] [ $ this -> strTable ] [ 'config' ] [ 'notSortable' ] && Input :: get ( 'act' ) != 'select' ) { $ return .= '
</ul>
<script>
  Backend.makeParentViewSortable("ul_' . CURRENT_ID . '");
</script>' ; } $ return .= ( $ this -> strPickerFieldType == 'radio' ? '
<div class="tl_radio_reset">
<label for="tl_radio_reset" class="tl_radio_label">' . $ GLOBALS [ 'TL_LANG' ] [ 'MSC' ] [ 'resetSelected' ] . '</label> <input type="radio" name="picker" id="tl_radio_reset" value="" class="tl_tree_radio">
</div>' : '' ) . '
</div>' ; // Close form if ( Input :: get ( 'act' ) == 'select' ) { // Submit buttons $ arrButtons = array ( ) ; if ( ! $ GLOBALS [ 'TL_DCA' ] [ $ this -> strTable ] [ 'config' ] [ 'notEditable' ] ) { $ arrButtons [ 'edit' ] = '<button type="submit" name="edit" id="edit" class="tl_submit" accesskey="s">' . $ GLOBALS [ 'TL_LANG' ] [ 'MSC' ] [ 'editSelected' ] . '</button>' ; } if ( ! $ GLOBALS [ 'TL_DCA' ] [ $ this -> strTable ] [ 'config' ] [ 'notDeletable' ] ) { $ arrButtons [ 'delete' ] = '<button type="submit" name="delete" id="delete" class="tl_submit" accesskey="d" onclick="return confirm(\'' . $ GLOBALS [ 'TL_LANG' ] [ 'MSC' ] [ 'delAllConfirm' ] . '\')">' . $ GLOBALS [ 'TL_LANG' ] [ 'MSC' ] [ 'deleteSelected' ] . '</button>' ; } if ( ! $ GLOBALS [ 'TL_DCA' ] [ $ this -> strTable ] [ 'config' ] [ 'notCopyable' ] ) { $ arrButtons [ 'copy' ] = '<button type="submit" name="copy" id="copy" class="tl_submit" accesskey="c">' . $ GLOBALS [ 'TL_LANG' ] [ 'MSC' ] [ 'copySelected' ] . '</button>' ; } if ( ! $ GLOBALS [ 'TL_DCA' ] [ $ this -> strTable ] [ 'config' ] [ 'notSortable' ] ) { $ arrButtons [ 'cut' ] = '<button type="submit" name="cut" id="cut" class="tl_submit" accesskey="x">' . $ GLOBALS [ 'TL_LANG' ] [ 'MSC' ] [ 'moveSelected' ] . '</button>' ; } if ( ! $ GLOBALS [ 'TL_DCA' ] [ $ this -> strTable ] [ 'config' ] [ 'notEditable' ] ) { $ arrButtons [ 'override' ] = '<button type="submit" name="override" id="override" class="tl_submit" accesskey="v">' . $ GLOBALS [ 'TL_LANG' ] [ 'MSC' ] [ 'overrideSelected' ] . '</button>' ; } // Call the buttons_callback (see #4691) if ( \ is_array ( $ GLOBALS [ 'TL_DCA' ] [ $ this -> strTable ] [ 'select' ] [ 'buttons_callback' ] ) ) { foreach ( $ GLOBALS [ 'TL_DCA' ] [ $ this -> strTable ] [ 'select' ] [ '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" style="text-align:right">
<div class="tl_submit_container">
  ' . $ strButtons . '
</div>
</div>
</form>' ; } return $ return ; }
Show header of the parent table and list all records of the current table

@return string
Show header of the parent table and list all records of the current table