protected function treeView()
{
$table = $this->strTable;
$treeClass = 'tl_tree';
if ($GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['mode'] == 6) {
$table = $this->ptable;
$treeClass = 'tl_tree_xtnd';
\System::loadLanguageFile($table);
$this->loadDataContainer($table);
}
/** @var SessionInterface $objSession */
$objSession = \System::getContainer()->get('session');
/** @var AttributeBagInterface $objSessionBag */
$objSessionBag = $objSession->getBag('contao_backend');
$session = $objSessionBag->all();
// Toggle the nodes
if (\Input::get('ptg') == 'all') {
$node = $GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['mode'] == 6 ? $this->strTable . '_' . $table . '_tree' : $this->strTable . '_tree';
// Expand tree
if (!is_array($session[$node]) || empty($session[$node]) || current($session[$node]) != 1) {
$session[$node] = array();
$objNodes = $this->Database->execute("SELECT DISTINCT pid FROM " . $table . " WHERE pid>0");
while ($objNodes->next()) {
$session[$node][$objNodes->pid] = 1;
}
} else {
$session[$node] = array();
}
$objSessionBag->replace($session);
$this->redirect(preg_replace('/(&(amp;)?|\\?)ptg=[^& ]*/i', '', \Environment::get('request')));
}
// Return if a mandatory field (id, pid, sorting) is missing
if ($GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['mode'] == 5 && (!$this->Database->fieldExists('id', $table) || !$this->Database->fieldExists('pid', $table) || !$this->Database->fieldExists('sorting', $table))) {
return '
<p class="tl_empty">Table "' . $table . '" can not be shown as tree, because the "id", "pid" or "sorting" field is missing!</p>';
}
// Return if there is no parent table
if ($GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['mode'] == 6 && !strlen($this->ptable)) {
return '
<p class="tl_empty">Table "' . $table . '" can not be shown as extended tree, because there is no parent table!</p>';
}
$blnClipboard = false;
$arrClipboard = $objSession->get('CLIPBOARD');
// Check the clipboard
if (!empty($arrClipboard[$this->strTable])) {
$blnClipboard = true;
$arrClipboard = $arrClipboard[$this->strTable];
}
$label = $GLOBALS['TL_DCA'][$table]['config']['label'];
$icon = $GLOBALS['TL_DCA'][$table]['list']['sorting']['icon'] ?: 'pagemounts.svg';
$label = \Image::getHtml($icon) . ' <label>' . $label . '</label>';
// Begin buttons container
$return = '
<div id="tl_buttons">' . (\Input::get('act') == 'select' ? '
<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> ' : (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('act=paste&mode=create') . '" 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>' . \Message::generate();
$tree = '';
$blnHasSorting = $this->Database->fieldExists('sorting', $table);
$arrFound = array();
if (!empty($this->procedure)) {
$fld = $GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['mode'] == 6 ? 'pid' : 'id';
$objRoot = $this->Database->prepare("SELECT {$fld} FROM {$this->strTable} WHERE " . implode(' AND ', $this->procedure))->execute($this->values);
if ($objRoot->numRows < 1) {
$this->root = array();
} else {
// Respect existing limitations (root IDs)
if (!empty($this->root)) {
$arrRoot = array();
while ($objRoot->next()) {
if (count(array_intersect($this->root, $this->Database->getParentRecords($objRoot->{$fld}, $table))) > 0) {
$arrRoot[] = $objRoot->{$fld};
}
}
$arrFound = $arrRoot;
$this->root = $this->eliminateNestedPages($arrFound);
} else {
$arrFound = $objRoot->fetchEach($fld);
$this->root = $this->eliminateNestedPages($arrFound);
}
}
}
// Call a recursive function that builds the tree
for ($i = 0, $c = count($this->root); $i < $c; $i++) {
$tree .= $this->generateTree($table, $this->root[$i], array('p' => $this->root[$i - 1], 'n' => $this->root[$i + 1]), $blnHasSorting, -20, $blnClipboard ? $arrClipboard : false, $GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['mode'] == 5 && $blnClipboard && $this->root[$i] == $arrClipboard['id'], false, false, $arrFound);
}
// Return if there are no records
if ($tree == '' && \Input::get('act') != 'paste') {
return $return . '
<p class="tl_empty">' . $GLOBALS['TL_LANG']['MSC']['noResult'] . '</p>';
}
$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">
<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 tree_view" id="tl_listing">' . (isset($GLOBALS['TL_DCA'][$table]['list']['sorting']['breadcrumb']) ? $GLOBALS['TL_DCA'][$table]['list']['sorting']['breadcrumb'] : '') . (\Input::get('act') == 'select' ? '
<div class="tl_select_trigger">
<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">
</div>' : '') . '
<ul class="tl_listing ' . $treeClass . '">
<li class="tl_folder_top cf"><div class="tl_left">' . $label . '</div> <div class="tl_right">';
$_buttons = ' ';
// Show paste button only if there are no root records specified
if (\Input::get('act') != 'select' && $GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['mode'] == 5 && $blnClipboard && (!count($GLOBALS['TL_DCA'][$table]['list']['sorting']['root']) && $GLOBALS['TL_DCA'][$table]['list']['sorting']['root'] !== false || $GLOBALS['TL_DCA'][$table]['list']['sorting']['rootPaste'])) {
// Call paste_button_callback (&$dc, $row, $table, $cr, $childs, $previous, $next)
if (is_array($GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['paste_button_callback'])) {
$strClass = $GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['paste_button_callback'][0];
$strMethod = $GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['paste_button_callback'][1];
$this->import($strClass);
$_buttons = $this->{$strClass}->{$strMethod}($this, array('id' => 0), $table, false, $arrClipboard);
} elseif (is_callable($GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['paste_button_callback'])) {
$_buttons = $GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['paste_button_callback']($this, array('id' => 0), $table, false, $arrClipboard);
} else {
$imagePasteInto = \Image::getHtml('pasteinto.svg', $GLOBALS['TL_LANG'][$this->strTable]['pasteinto'][0]);
$_buttons = '<a href="' . $this->addToUrl('act=' . $arrClipboard['mode'] . '&mode=2&pid=0' . (!is_array($arrClipboard['id']) ? '&id=' . $arrClipboard['id'] : '')) . '" title="' . \StringUtil::specialchars($GLOBALS['TL_LANG'][$this->strTable]['pasteinto'][0]) . '" onclick="Backend.getScrollOffset()">' . $imagePasteInto . '</a> ';
}
}
// End table
$return .= $_buttons . '</div></li>' . $tree . '
</ul>
</div>';
// Close the 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>';
$arrButtons['override'] = '<button type="submit" name="override" id="override" class="tl_submit" accesskey="v">' . $GLOBALS['TL_LANG']['MSC']['overrideSelected'] . '</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']['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>';
}
// 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 class="tl_formbody_submit" style="text-align:right">
<div class="tl_submit_container">
' . $strButtons . '
</div>
</div>
</div>
</form>';
}
return $return;
}