Пример #1
0
    /**
     * List all records of the current table and return them as HTML string
     *
     * @return string
     */
    protected function listView()
    {
        $return = '';
        $table = $GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['mode'] == 6 ? $this->ptable : $this->strTable;
        $orderBy = $GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['fields'];
        $firstOrderBy = preg_replace('/\\s+.*$/', '', $orderBy[0]);
        if (is_array($this->orderBy) && $this->orderBy[0] != '') {
            $orderBy = $this->orderBy;
            $firstOrderBy = $this->firstOrderBy;
        }
        $query = "SELECT * FROM " . $this->strTable;
        if (!empty($this->procedure)) {
            $query .= " WHERE " . implode(' AND ', $this->procedure);
        }
        if (!empty($this->root) && is_array($this->root)) {
            $query .= (!empty($this->procedure) ? " AND " : " WHERE ") . "id IN(" . implode(',', array_map('intval', $this->root)) . ")";
        }
        if (is_array($orderBy) && $orderBy[0] != '') {
            foreach ($orderBy as $k => $v) {
                list($key, $direction) = explode(' ', $v, 2);
                if ($GLOBALS['TL_DCA'][$this->strTable]['fields'][$key]['eval']['findInSet']) {
                    if (is_array($GLOBALS['TL_DCA'][$this->strTable]['fields'][$key]['options_callback'])) {
                        $strClass = $GLOBALS['TL_DCA'][$this->strTable]['fields'][$key]['options_callback'][0];
                        $strMethod = $GLOBALS['TL_DCA'][$this->strTable]['fields'][$key]['options_callback'][1];
                        $this->import($strClass);
                        $keys = $this->{$strClass}->{$strMethod}($this);
                    } elseif (is_callable($GLOBALS['TL_DCA'][$this->strTable]['fields'][$key]['options_callback'])) {
                        $keys = $GLOBALS['TL_DCA'][$this->strTable]['fields'][$key]['options_callback']($this);
                    } else {
                        $keys = $GLOBALS['TL_DCA'][$this->strTable]['fields'][$key]['options'];
                    }
                    if ($GLOBALS['TL_DCA'][$this->strTable]['fields'][$key]['eval']['isAssociative'] || array_is_assoc($keys)) {
                        $keys = array_keys($keys);
                    }
                    $orderBy[$k] = $this->Database->findInSet($v, $keys);
                } elseif (in_array($GLOBALS['TL_DCA'][$this->strTable]['fields'][$key]['flag'], array(5, 6, 7, 8, 9, 10))) {
                    $orderBy[$k] = "CAST({$key} AS SIGNED)" . ($direction ? " {$direction}" : "");
                    // see #5503
                }
            }
            if ($GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['mode'] == 3) {
                $firstOrderBy = 'pid';
                $showFields = $GLOBALS['TL_DCA'][$table]['list']['label']['fields'];
                $query .= " ORDER BY (SELECT " . $showFields[0] . " FROM " . $this->ptable . " WHERE " . $this->ptable . ".id=" . $this->strTable . ".pid), " . implode(', ', $orderBy);
                // Set the foreignKey so that the label is translated (also for backwards compatibility)
                if ($GLOBALS['TL_DCA'][$table]['fields']['pid']['foreignKey'] == '') {
                    $GLOBALS['TL_DCA'][$table]['fields']['pid']['foreignKey'] = $this->ptable . '.' . $showFields[0];
                }
                // Remove the parent field from label fields
                array_shift($showFields);
                $GLOBALS['TL_DCA'][$table]['list']['label']['fields'] = $showFields;
            } else {
                $query .= " ORDER BY " . implode(', ', $orderBy);
            }
        }
        if ($GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['mode'] == 1 && $GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['flag'] % 2 == 0) {
            $query .= " DESC";
        }
        $objRowStmt = $this->Database->prepare($query);
        if ($this->limit != '') {
            $arrLimit = explode(',', $this->limit);
            $objRowStmt->limit($arrLimit[1], $arrLimit[0]);
        }
        $objRow = $objRowStmt->execute($this->values);
        $this->bid = $return != '' ? $this->bid : 'tl_buttons';
        // Display buttos
        if (!$GLOBALS['TL_DCA'][$this->strTable]['config']['closed'] || !empty($GLOBALS['TL_DCA'][$this->strTable]['list']['global_operations'])) {
            $return .= '

<div id="' . $this->bid . '">' . (\Input::get('act') == 'select' || $this->ptable ? '
<a href="' . $this->getReferer(true, $this->ptable) . '" class="header_back" title="' . 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="' . specialchars($GLOBALS['TL_LANG']['MSC']['backBTTitle']) . '" accesskey="b" onclick="Backend.getScrollOffset()">' . $GLOBALS['TL_LANG']['MSC']['backBT'] . '</a> ' : '')) . (\Input::get('act') != 'select' && !$GLOBALS['TL_DCA'][$this->strTable]['config']['closed'] && !$GLOBALS['TL_DCA'][$this->strTable]['config']['notCreatable'] ? '
<a href="' . ($this->ptable != '' ? $this->addToUrl('act=create' . ($GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['mode'] < 4 ? '&amp;mode=2' : '') . '&amp;pid=' . $this->intId) : $this->addToUrl('act=create')) . '" class="header_new" title="' . specialchars($GLOBALS['TL_LANG'][$this->strTable]['new'][1]) . '" accesskey="n" onclick="Backend.getScrollOffset()">' . $GLOBALS['TL_LANG'][$this->strTable]['new'][0] . '</a> ' : '') . $this->generateGlobalButtons() . '
</div>' . \Message::generate(true);
        }
        // Return "no records found" message
        if ($objRow->numRows < 1) {
            $return .= '
<p class="tl_empty">' . $GLOBALS['TL_LANG']['MSC']['noResult'] . '</p>';
        } else {
            $result = $objRow->fetchAllAssoc();
            $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 . '">' : '') . '

<div class="tl_listing_container list_view">' . (\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>' : '') . '

<table class="tl_listing' . ($GLOBALS['TL_DCA'][$this->strTable]['list']['label']['showColumns'] ? ' showColumns' : '') . '">';
            // Automatically add the "order by" field as last column if we do not have group headers
            if ($GLOBALS['TL_DCA'][$this->strTable]['list']['label']['showColumns']) {
                $blnFound = false;
                // Extract the real key and compare it to $firstOrderBy
                foreach ($GLOBALS['TL_DCA'][$this->strTable]['list']['label']['fields'] as $f) {
                    if (strpos($f, ':') !== false) {
                        list($f) = explode(':', $f, 2);
                    }
                    if ($firstOrderBy == $f) {
                        $blnFound = true;
                        break;
                    }
                }
                if (!$blnFound) {
                    $GLOBALS['TL_DCA'][$this->strTable]['list']['label']['fields'][] = $firstOrderBy;
                }
            }
            // Generate the table header if the "show columns" option is active
            if ($GLOBALS['TL_DCA'][$this->strTable]['list']['label']['showColumns']) {
                $return .= '
  <tr>';
                foreach ($GLOBALS['TL_DCA'][$this->strTable]['list']['label']['fields'] as $f) {
                    if (strpos($f, ':') !== false) {
                        list($f) = explode(':', $f, 2);
                    }
                    $return .= '
    <th class="tl_folder_tlist col_' . $f . ($f == $firstOrderBy ? ' ordered_by' : '') . '">' . (is_array($GLOBALS['TL_DCA'][$this->strTable]['fields'][$f]['label']) ? $GLOBALS['TL_DCA'][$this->strTable]['fields'][$f]['label'][0] : $GLOBALS['TL_DCA'][$this->strTable]['fields'][$f]['label']) . '</th>';
                }
                $return .= '
    <th class="tl_folder_tlist tl_right_nowrap">&nbsp;</th>
  </tr>';
            }
            // Process result and add label and buttons
            $remoteCur = false;
            $groupclass = 'tl_folder_tlist';
            $eoCount = -1;
            foreach ($result as $row) {
                $args = array();
                $this->current[] = $row['id'];
                $showFields = $GLOBALS['TL_DCA'][$table]['list']['label']['fields'];
                // Label
                foreach ($showFields as $k => $v) {
                    // Decrypt the value
                    if ($GLOBALS['TL_DCA'][$this->strTable]['fields'][$v]['eval']['encrypt']) {
                        $row[$v] = \Encryption::decrypt(deserialize($row[$v]));
                    }
                    if (strpos($v, ':') !== false) {
                        list($strKey, $strTable) = explode(':', $v);
                        list($strTable, $strField) = explode('.', $strTable);
                        $objRef = $this->Database->prepare("SELECT " . $strField . " FROM " . $strTable . " WHERE id=?")->limit(1)->execute($row[$strKey]);
                        $args[$k] = $objRef->numRows ? $objRef->{$strField} : '';
                    } elseif (in_array($GLOBALS['TL_DCA'][$this->strTable]['fields'][$v]['flag'], array(5, 6, 7, 8, 9, 10))) {
                        if ($GLOBALS['TL_DCA'][$this->strTable]['fields'][$v]['eval']['rgxp'] == 'date') {
                            $args[$k] = $row[$v] ? \Date::parse(\Config::get('dateFormat'), $row[$v]) : '-';
                        } elseif ($GLOBALS['TL_DCA'][$this->strTable]['fields'][$v]['eval']['rgxp'] == 'time') {
                            $args[$k] = $row[$v] ? \Date::parse(\Config::get('timeFormat'), $row[$v]) : '-';
                        } else {
                            $args[$k] = $row[$v] ? \Date::parse(\Config::get('datimFormat'), $row[$v]) : '-';
                        }
                    } elseif ($GLOBALS['TL_DCA'][$this->strTable]['fields'][$v]['inputType'] == 'checkbox' && !$GLOBALS['TL_DCA'][$this->strTable]['fields'][$v]['eval']['multiple']) {
                        $args[$k] = $row[$v] != '' ? $GLOBALS['TL_LANG']['MSC']['yes'] : $GLOBALS['TL_LANG']['MSC']['no'];
                    } else {
                        $row_v = deserialize($row[$v]);
                        if (is_array($row_v)) {
                            $args_k = array();
                            foreach ($row_v as $option) {
                                $args_k[] = $GLOBALS['TL_DCA'][$table]['fields'][$v]['reference'][$option] ?: $option;
                            }
                            $args[$k] = implode(', ', $args_k);
                        } elseif (isset($GLOBALS['TL_DCA'][$table]['fields'][$v]['reference'][$row[$v]])) {
                            $args[$k] = is_array($GLOBALS['TL_DCA'][$table]['fields'][$v]['reference'][$row[$v]]) ? $GLOBALS['TL_DCA'][$table]['fields'][$v]['reference'][$row[$v]][0] : $GLOBALS['TL_DCA'][$table]['fields'][$v]['reference'][$row[$v]];
                        } elseif (($GLOBALS['TL_DCA'][$table]['fields'][$v]['eval']['isAssociative'] || array_is_assoc($GLOBALS['TL_DCA'][$table]['fields'][$v]['options'])) && isset($GLOBALS['TL_DCA'][$table]['fields'][$v]['options'][$row[$v]])) {
                            $args[$k] = $GLOBALS['TL_DCA'][$table]['fields'][$v]['options'][$row[$v]];
                        } else {
                            $args[$k] = $row[$v];
                        }
                    }
                }
                // Shorten the label it if it is too long
                $label = vsprintf($GLOBALS['TL_DCA'][$this->strTable]['list']['label']['format'] ?: '%s', $args);
                if ($GLOBALS['TL_DCA'][$this->strTable]['list']['label']['maxCharacters'] > 0 && $GLOBALS['TL_DCA'][$this->strTable]['list']['label']['maxCharacters'] < strlen(strip_tags($label))) {
                    $label = trim(\StringUtil::substrHtml($label, $GLOBALS['TL_DCA'][$this->strTable]['list']['label']['maxCharacters'])) . ' …';
                }
                // Remove empty brackets (), [], {}, <> and empty tags from the label
                $label = preg_replace('/\\( *\\) ?|\\[ *\\] ?|\\{ *\\} ?|< *> ?/', '', $label);
                $label = preg_replace('/<[^>]+>\\s*<\\/[^>]+>/', '', $label);
                // Build the sorting groups
                if ($GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['mode'] > 0) {
                    $current = $row[$firstOrderBy];
                    $orderBy = $GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['fields'];
                    $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, $current, $sortingMode);
                    // Add the group header
                    if (!$GLOBALS['TL_DCA'][$this->strTable]['list']['label']['showColumns'] && !$GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['disableGrouping'] && ($remoteNew != $remoteCur || $remoteCur === false)) {
                        $eoCount = -1;
                        $group = $this->formatGroupHeader($firstOrderBy, $remoteNew, $sortingMode, $row);
                        $remoteCur = $remoteNew;
                        $return .= '
  <tr>
    <td colspan="2" class="' . $groupclass . '">' . $group . '</td>
  </tr>';
                        $groupclass = 'tl_folder_list';
                    }
                }
                $return .= '
  <tr class="' . (++$eoCount % 2 == 0 ? 'even' : 'odd') . ' click2edit toggle_select" onmouseover="Theme.hoverRow(this,1)" onmouseout="Theme.hoverRow(this,0)">
    ';
                $colspan = 1;
                // Call the label_callback ($row, $label, $this)
                if (is_array($GLOBALS['TL_DCA'][$this->strTable]['list']['label']['label_callback']) || is_callable($GLOBALS['TL_DCA'][$this->strTable]['list']['label']['label_callback'])) {
                    if (is_array($GLOBALS['TL_DCA'][$this->strTable]['list']['label']['label_callback'])) {
                        $strClass = $GLOBALS['TL_DCA'][$this->strTable]['list']['label']['label_callback'][0];
                        $strMethod = $GLOBALS['TL_DCA'][$this->strTable]['list']['label']['label_callback'][1];
                        $this->import($strClass);
                        $args = $this->{$strClass}->{$strMethod}($row, $label, $this, $args);
                    } elseif (is_callable($GLOBALS['TL_DCA'][$this->strTable]['list']['label']['label_callback'])) {
                        $args = $GLOBALS['TL_DCA'][$this->strTable]['list']['label']['label_callback']($row, $label, $this, $args);
                    }
                    // Handle strings and arrays (backwards compatibility)
                    if (!$GLOBALS['TL_DCA'][$this->strTable]['list']['label']['showColumns']) {
                        $label = is_array($args) ? implode(' ', $args) : $args;
                    } elseif (!is_array($args)) {
                        $args = array($args);
                        $colspan = count($GLOBALS['TL_DCA'][$this->strTable]['list']['label']['fields']);
                    }
                }
                // Show columns
                if ($GLOBALS['TL_DCA'][$this->strTable]['list']['label']['showColumns']) {
                    foreach ($args as $j => $arg) {
                        $return .= '<td colspan="' . $colspan . '" class="tl_file_list col_' . $GLOBALS['TL_DCA'][$this->strTable]['list']['label']['fields'][$j] . ($GLOBALS['TL_DCA'][$this->strTable]['list']['label']['fields'][$j] == $firstOrderBy ? ' ordered_by' : '') . '">' . ($arg ?: '-') . '</td>';
                    }
                } else {
                    $return .= '<td class="tl_file_list">' . $label . '</td>';
                }
                // Buttons ($row, $table, $root, $blnCircularReference, $childs, $previous, $next)
                $return .= (\Input::get('act') == 'select' ? '
    <td class="tl_file_list tl_right_nowrap"><input type="checkbox" name="IDS[]" id="ids_' . $row['id'] . '" class="tl_tree_checkbox" value="' . $row['id'] . '"></td>' : '
    <td class="tl_file_list tl_right_nowrap">' . $this->generateButtons($row, $this->strTable, $this->root) . '</td>') . '
  </tr>';
            }
            // Close the table
            $return .= '
</table>

</div>';
            // Close the form
            if (\Input::get('act') == 'select') {
                // Submit buttons
                $arrButtons = array();
                if (!$GLOBALS['TL_DCA'][$this->strTable]['config']['notDeletable']) {
                    $arrButtons['delete'] = '<input type="submit" name="delete" id="delete" class="tl_submit" accesskey="d" onclick="return confirm(\'' . $GLOBALS['TL_LANG']['MSC']['delAllConfirm'] . '\')" value="' . specialchars($GLOBALS['TL_LANG']['MSC']['deleteSelected']) . '">';
                }
                if (!$GLOBALS['TL_DCA'][$this->strTable]['config']['notCopyable']) {
                    $arrButtons['copy'] = '<input type="submit" name="copy" id="copy" class="tl_submit" accesskey="c" value="' . specialchars($GLOBALS['TL_LANG']['MSC']['copySelected']) . '">';
                }
                if (!$GLOBALS['TL_DCA'][$this->strTable]['config']['notEditable']) {
                    $arrButtons['override'] = '<input type="submit" name="override" id="override" class="tl_submit" accesskey="v" value="' . specialchars($GLOBALS['TL_LANG']['MSC']['overrideSelected']) . '">';
                    $arrButtons['edit'] = '<input type="submit" name="edit" id="edit" class="tl_submit" accesskey="s" value="' . specialchars($GLOBALS['TL_LANG']['MSC']['editSelected']) . '">';
                }
                // 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);
                        }
                    }
                }
                $return .= '

<div class="tl_formbody_submit" style="text-align:right">

<div class="tl_submit_container">
  ' . implode(' ', $arrButtons) . '
</div>

</div>
</div>
</form>';
            }
        }
        return $return;
    }
Пример #2
0
    /**
     * Show header of the parent table and list all records of the current table
     * @return string
     */
    protected function parentView()
    {
        $blnClipboard = false;
        $arrClipboard = $this->Session->get('CLIPBOARD');
        $blnHasSorting = false;
        $blnMultiboard = false;
        // Check clipboard
        if (!empty($arrClipboard[$this->strTable])) {
            $blnClipboard = true;
            $arrClipboard = $arrClipboard[$this->strTable];
            if (is_array($arrClipboard['id'])) {
                $blnMultiboard = true;
            }
        }
        // Load the fonts to display the paste hint
        $GLOBALS['TL_CONFIG']['loadGoogleFonts'] = $blnClipboard;
        $strBackUrl = \Input::get('id') ? 'contao/main.php?do=iso_products' : \System::getReferer(true, $this->ptable);
        $return = '
<div id="tl_buttons">' . (\Input::get('nb') ? '&nbsp;' : '
<a href="' . $strBackUrl . '" class="header_back" title="' . specialchars($GLOBALS['TL_LANG']['MSC']['backBTTitle']) . '" accesskey="b" onclick="Backend.getScrollOffset()">' . $GLOBALS['TL_LANG']['MSC']['backBT'] . '</a>') . ' ' . (!$blnClipboard ? \Input::get('act') != 'select' ? (!$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="' . specialchars($GLOBALS['TL_LANG'][$this->strTable]['new'][1]) . '" accesskey="n" onclick="Backend.getScrollOffset()">' . $GLOBALS['TL_LANG'][$this->strTable]['new'][0] . '</a> ' : '') . $this->generateGlobalButtons() : '' : '<a href="' . $this->addToUrl('clipboard=1') . '" class="header_clipboard" title="' . specialchars($GLOBALS['TL_LANG']['MSC']['clearClipboard']) . '" accesskey="x">' . $GLOBALS['TL_LANG']['MSC']['clearClipboard'] . '</a> ') . '
</div>' . \Message::generate(true);
        // Get all details of the parent record
        $objParent = $this->Database->prepare("SELECT * FROM {$this->strTable} 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" method="post">
<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 iso_listing_container parent_view">

<div class="tl_header click2edit" onmouseover="Theme.hoverDiv(this,1)" onmouseout="Theme.hoverDiv(this,0)">';
        // List all records of the child table
        if (!\Input::get('act') || \Input::get('act') == 'paste' || \Input::get('act') == 'select') {
            $imagePasteAfter = \Image::getHtml('pasteafter.gif', $GLOBALS['TL_LANG'][$this->strTable]['pasteafter'][0]);
            $imageEditHeader = \Image::getHtml('edit.gif', $GLOBALS['TL_LANG'][$this->strTable]['edit'][0]);
            $strEditHeader = $GLOBALS['TL_LANG'][$this->strTable]['edit'][0];
            $return .= '
<div class="tl_content_right">' . (\Input::get('act') == 'select' ? '
<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">' : (!$GLOBALS['TL_DCA'][$this->ptable]['config']['notEditable'] ? '
<a href="' . preg_replace('/&(amp;)?table=[^& ]*/i', $this->ptable != '' ? '&amp;table=' . $this->ptable : '', $this->addToUrl('act=edit')) . '" class="edit" title="' . specialchars($strEditHeader) . '">' . $imageEditHeader . '</a>' : '') . ($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="' . specialchars($GLOBALS['TL_LANG'][$this->strTable]['pastenew'][0]) . '">' . $imagePasteNew . '</a>' : '') . ($blnClipboard ? ' <a href="' . $this->addToUrl('act=' . $arrClipboard['mode'] . '&amp;mode=2&amp;pid=' . $objParent->id . (!$blnMultiboard ? '&amp;id=' . $arrClipboard['id'] : '')) . '" title="' . specialchars($GLOBALS['TL_LANG'][$this->strTable]['pasteafter'][0]) . '" onclick="Backend.getScrollOffset()">' . $imagePasteAfter . '</a>' : '')) . '
</div>';
            // Format header fields
            $add = array();
            $headerFields = $GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['headerFields'];
            foreach ($headerFields as $v) {
                $_v = deserialize($objParent->{$v});
                if (is_array($_v)) {
                    $_v = implode(', ', $_v);
                } elseif ($GLOBALS['TL_DCA'][$this->strTable]['fields'][$v]['inputType'] == 'checkbox' && !$GLOBALS['TL_DCA'][$this->strTable]['fields'][$v]['eval']['multiple']) {
                    $_v = $_v != '' ? $GLOBALS['TL_LANG']['MSC']['yes'] : $GLOBALS['TL_LANG']['MSC']['no'];
                } elseif ($GLOBALS['TL_DCA'][$this->strTable]['fields'][$v]['eval']['rgxp'] == 'date') {
                    $_v = $_v ? \Date::parse($GLOBALS['TL_CONFIG']['dateFormat'], $_v) : '-';
                } elseif ($GLOBALS['TL_DCA'][$this->strTable]['fields'][$v]['eval']['rgxp'] == 'time') {
                    $_v = $_v ? \Date::parse($GLOBALS['TL_CONFIG']['timeFormat'], $_v) : '-';
                } elseif ($GLOBALS['TL_DCA'][$this->strTable]['fields'][$v]['eval']['rgxp'] == 'datim') {
                    $_v = $_v ? \Date::parse($GLOBALS['TL_CONFIG']['datimFormat'], $_v) : '-';
                } elseif ($v == 'tstamp') {
                    $objMaxTstamp = $this->Database->prepare("SELECT MAX(tstamp) AS tstamp FROM {$this->strTable} WHERE pid=?")->execute($objParent->id);
                    if (!$objMaxTstamp->tstamp) {
                        $objMaxTstamp->tstamp = $objParent->tstamp;
                    }
                    $_v = \Date::parse($GLOBALS['TL_CONFIG']['datimFormat'], max($objParent->tstamp, $objMaxTstamp->tstamp));
                } elseif (isset($GLOBALS['TL_DCA'][$this->strTable]['fields'][$v]['foreignKey'])) {
                    $arrForeignKey = explode('.', $GLOBALS['TL_DCA'][$this->strTable]['fields'][$v]['foreignKey'], 2);
                    $objLabel = $this->Database->prepare("SELECT " . $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->strTable]['fields'][$v]['reference'][$_v])) {
                    $_v = $GLOBALS['TL_DCA'][$this->strTable]['fields'][$v]['reference'][$_v][0];
                } elseif (isset($GLOBALS['TL_DCA'][$this->strTable]['fields'][$v]['reference'][$_v])) {
                    $_v = $GLOBALS['TL_DCA'][$this->strTable]['fields'][$v]['reference'][$_v];
                } elseif ($GLOBALS['TL_DCA'][$this->strTable]['fields'][$v]['eval']['isAssociative'] || array_is_assoc($GLOBALS['TL_DCA'][$this->strTable]['fields'][$v]['options'])) {
                    $_v = $GLOBALS['TL_DCA'][$this->strTable]['fields'][$v]['options'][$_v];
                }
                // Add the sorting field
                if ($_v != '') {
                    $key = isset($GLOBALS['TL_LANG'][$this->strTable][$v][0]) ? $GLOBALS['TL_LANG'][$this->strTable][$v][0] : $v;
                    $add[$key] = $_v;
                }
            }
            // Trigger the header_callback (see #3417)
            if (is_array($GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['header_callback'])) {
                $strClass = $GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['header_callback'][0];
                $strMethod = $GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['header_callback'][1];
                $this->import($strClass);
                $add = $this->{$strClass}->{$strMethod}($add, $this);
            } elseif (is_callable($GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['header_callback'])) {
                $add = call_user_func($GLOBALS['TL_DCA'][$this->strTable]['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 " . $key[1] . " FROM " . $key[0] . " WHERE " . $this->strTable . "." . $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]);
            }
            $this->procedure[] = "pid=?";
            $this->values[] = CURRENT_ID;
            // Support empty ptable fields (backwards compatibility)
            if ($GLOBALS['TL_DCA'][$this->strTable]['config']['dynamicPtable']) {
                $this->procedure[] = "ptable=?";
                $this->values[] = $this->strTable;
            }
            // WHERE
            if (!empty($this->procedure)) {
                $query .= " WHERE " . implode(' AND ', $this->procedure);
            }
            if (!empty($this->root) && is_array($this->root)) {
                $query .= (!empty($this->procedure) ? " 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($this->values);
            if ($objOrderBy->numRows < 1) {
                return $return . '
<p class="tl_empty_parent_view">' . $GLOBALS['TL_LANG']['MSC']['noResult'] . '</p>

</div>';
            }
            $result = $objOrderBy->fetchAllAssoc();
            $return .= '

<table class="tl_listing' . ($GLOBALS['TL_DCA'][$this->strTable]['list']['label']['showColumns'] ? ' showColumns' : '') . '">';
            // Automatically add the "order by" field as last column if we do not have group headers
            if ($GLOBALS['TL_DCA'][$this->strTable]['list']['label']['showColumns']) {
                $blnFound = false;
                // Extract the real key and compare it to $firstOrderBy
                foreach ($GLOBALS['TL_DCA'][$this->strTable]['list']['label']['fields'] as $f) {
                    if (strpos($f, ':') !== false) {
                        list($f, ) = explode(':', $f, 2);
                    }
                    if ($firstOrderBy == $f) {
                        $blnFound = true;
                        break;
                    }
                }
                if (!$blnFound) {
                    $GLOBALS['TL_DCA'][$this->strTable]['list']['label']['fields'][] = $firstOrderBy;
                }
            }
            // Generate the table header if the "show columns" option is active
            if ($GLOBALS['TL_DCA'][$this->strTable]['list']['label']['showColumns']) {
                $return .= '
  <tr>';
                foreach ($GLOBALS['TL_DCA'][$this->strTable]['list']['label']['fields'] as $f) {
                    if (strpos($f, ':') !== false) {
                        list($f, ) = explode(':', $f, 2);
                    }
                    $return .= '
    <th class="tl_folder_tlist col_' . $f . ($f == $firstOrderBy ? ' ordered_by' : '') . '">' . (is_array($GLOBALS['TL_DCA'][$this->strTable]['fields'][$f]['label']) ? $GLOBALS['TL_DCA'][$this->strTable]['fields'][$f]['label'][0] : $GLOBALS['TL_DCA'][$this->strTable]['fields'][$f]['label']) . '</th>';
                }
                $return .= '
    <th class="tl_folder_tlist tl_right_nowrap iso_operations">&nbsp;</th>
  </tr>';
            }
            // Process result and add label and buttons
            $remoteCur = false;
            $groupclass = 'tl_folder_tlist';
            $eoCount = -1;
            foreach ($result as $row) {
                $args = array();
                $this->current[] = $row['id'];
                $showFields = $GLOBALS['TL_DCA'][$this->strTable]['list']['label']['fields'];
                // Label
                foreach ($showFields as $k => $v) {
                    // Decrypt the value
                    if ($GLOBALS['TL_DCA'][$this->strTable]['fields'][$v]['eval']['encrypt']) {
                        $row[$v] = \Encryption::decrypt(deserialize($row[$v]));
                    }
                    if (strpos($v, ':') !== false) {
                        list($strKey, $strTable) = explode(':', $v);
                        list($strTable, $strField) = explode('.', $strTable);
                        $objRef = $this->Database->prepare("SELECT " . $strField . " FROM " . $strTable . " WHERE id=?")->limit(1)->execute($row[$strKey]);
                        $args[$k] = $objRef->numRows ? $objRef->{$strField} : '';
                    } elseif (in_array($GLOBALS['TL_DCA'][$this->strTable]['fields'][$v]['flag'], array(5, 6, 7, 8, 9, 10))) {
                        if ($GLOBALS['TL_DCA'][$this->strTable]['fields'][$v]['eval']['rgxp'] == 'date') {
                            $args[$k] = $row[$v] ? \Date::parse($GLOBALS['TL_CONFIG']['dateFormat'], $row[$v]) : '-';
                        } elseif ($GLOBALS['TL_DCA'][$this->strTable]['fields'][$v]['eval']['rgxp'] == 'time') {
                            $args[$k] = $row[$v] ? \Date::parse($GLOBALS['TL_CONFIG']['timeFormat'], $row[$v]) : '-';
                        } else {
                            $args[$k] = $row[$v] ? \Date::parse($GLOBALS['TL_CONFIG']['datimFormat'], $row[$v]) : '-';
                        }
                    } elseif ($GLOBALS['TL_DCA'][$this->strTable]['fields'][$v]['inputType'] == 'checkbox' && !$GLOBALS['TL_DCA'][$this->strTable]['fields'][$v]['eval']['multiple']) {
                        $args[$k] = $row[$v] != '' ? $GLOBALS['TL_DCA'][$this->strTable]['fields'][$v]['label'][0] : '';
                    } else {
                        $row_v = deserialize($row[$v]);
                        if (is_array($row_v)) {
                            $args_k = array();
                            foreach ($row_v as $option) {
                                $args_k[] = $GLOBALS['TL_DCA'][$this->strTable]['fields'][$v]['reference'][$option] ?: $option;
                            }
                            $args[$k] = implode(', ', $args_k);
                        } elseif (isset($GLOBALS['TL_DCA'][$this->strTable]['fields'][$v]['reference'][$row[$v]])) {
                            $args[$k] = is_array($GLOBALS['TL_DCA'][$this->strTable]['fields'][$v]['reference'][$row[$v]]) ? $GLOBALS['TL_DCA'][$this->strTable]['fields'][$v]['reference'][$row[$v]][0] : $GLOBALS['TL_DCA'][$this->strTable]['fields'][$v]['reference'][$row[$v]];
                        } elseif (($GLOBALS['TL_DCA'][$this->strTable]['fields'][$v]['eval']['isAssociative'] || array_is_assoc($GLOBALS['TL_DCA'][$this->strTable]['fields'][$v]['options'])) && isset($GLOBALS['TL_DCA'][$this->strTable]['fields'][$v]['options'][$row[$v]])) {
                            $args[$k] = $GLOBALS['TL_DCA'][$this->strTable]['fields'][$v]['options'][$row[$v]];
                        } else {
                            $args[$k] = $row[$v];
                        }
                    }
                }
                // Shorten the label it if it is too long
                $label = vsprintf($GLOBALS['TL_DCA'][$this->strTable]['list']['label']['format'] ?: '%s', $args);
                if ($GLOBALS['TL_DCA'][$this->strTable]['list']['label']['maxCharacters'] > 0 && $GLOBALS['TL_DCA'][$this->strTable]['list']['label']['maxCharacters'] < strlen(strip_tags($label))) {
                    $label = trim(\StringUtil::substrHtml($label, $GLOBALS['TL_DCA'][$this->strTable]['list']['label']['maxCharacters'])) . ' …';
                }
                // Remove empty brackets (), [], {}, <> and empty tags from the label
                $label = preg_replace('/\\( *\\) ?|\\[ *\\] ?|\\{ *\\} ?|< *> ?/', '', $label);
                $label = preg_replace('/<[^>]+>\\s*<\\/[^>]+>/', '', $label);
                // Build the sorting groups
                if ($GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['mode'] > 0) {
                    $current = $row[$firstOrderBy];
                    $orderBy = $GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['fields'];
                    $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, $current, $sortingMode);
                    // Add the group header
                    if (!$GLOBALS['TL_DCA'][$this->strTable]['list']['label']['showColumns'] && !$GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['disableGrouping'] && ($remoteNew != $remoteCur || $remoteCur === false)) {
                        $eoCount = -1;
                        $group = $this->formatGroupHeader($firstOrderBy, $remoteNew, $sortingMode, $row);
                        $remoteCur = $remoteNew;
                        $return .= '
  <tr>
    <td colspan="2" class="' . $groupclass . '">' . $group . '</td>
  </tr>';
                        $groupclass = 'tl_folder_list';
                    }
                }
                $return .= '
  <tr class="' . (++$eoCount % 2 == 0 ? 'even' : 'odd') . ' click2edit" onmouseover="Theme.hoverRow(this,1)" onmouseout="Theme.hoverRow(this,0)" onclick="Theme.toggleSelect(this)">
    ';
                $colspan = 1;
                // Call the label callback ($row, $label, $this)
                if (is_array($GLOBALS['TL_DCA'][$this->strTable]['list']['label']['label_callback']) || is_callable($GLOBALS['TL_DCA'][$this->strTable]['list']['label']['label_callback'])) {
                    if (is_array($GLOBALS['TL_DCA'][$this->strTable]['list']['label']['label_callback'])) {
                        $strClass = $GLOBALS['TL_DCA'][$this->strTable]['list']['label']['label_callback'][0];
                        $strMethod = $GLOBALS['TL_DCA'][$this->strTable]['list']['label']['label_callback'][1];
                        $this->import($strClass);
                        $args = $this->{$strClass}->{$strMethod}($row, $label, $this, $args);
                    } else {
                        $args = call_user_func($GLOBALS['TL_DCA'][$this->strTable]['list']['label']['label_callback'], $row, $label, $this, $args);
                    }
                    // Handle strings and arrays (backwards compatibility)
                    if (!$GLOBALS['TL_DCA'][$this->strTable]['list']['label']['showColumns']) {
                        $label = is_array($args) ? implode(' ', $args) : $args;
                    } elseif (!is_array($args)) {
                        $args = array($args);
                        $colspan = count($GLOBALS['TL_DCA'][$this->strTable]['list']['label']['fields']);
                    }
                }
                // Show columns
                if ($GLOBALS['TL_DCA'][$this->strTable]['list']['label']['showColumns']) {
                    foreach ($args as $j => $arg) {
                        $return .= '<td colspan="' . $colspan . '" class="tl_file_list col_' . $GLOBALS['TL_DCA'][$this->strTable]['list']['label']['fields'][$j] . ($GLOBALS['TL_DCA'][$this->strTable]['list']['label']['fields'][$j] == $firstOrderBy ? ' ordered_by' : '') . '">' . ($arg ?: '-') . '</td>';
                    }
                } else {
                    $return .= '<td class="tl_file_list">' . $label . '</td>';
                }
                // Buttons ($row, $table, $root, $blnCircularReference, $childs, $previous, $next)
                $return .= (\Input::get('act') == 'select' ? '
    <td class="tl_file_list tl_right_nowrap iso_operations"><input type="checkbox" name="IDS[]" id="ids_' . $row['id'] . '" class="tl_tree_checkbox" value="' . $row['id'] . '"></td>' : '
    <td class="tl_file_list tl_right_nowrap iso_operations">' . $this->generateButtons($row, $this->strTable, $this->root) . '</td>') . '
  </tr>';
            }
            // Close the table
            $return .= '
</table>

</div>';
        }
        // Close form
        if (\Input::get('act') == 'select') {
            // Submit buttons
            $arrButtons = array();
            if (!$GLOBALS['TL_DCA'][$this->strTable]['config']['notDeletable']) {
                $arrButtons['delete'] = '<input type="submit" name="delete" id="delete" class="tl_submit" accesskey="d" onclick="return confirm(\'' . $GLOBALS['TL_LANG']['MSC']['delAllConfirm'] . '\')" value="' . specialchars($GLOBALS['TL_LANG']['MSC']['deleteSelected']) . '">';
            }
            if (!$GLOBALS['TL_DCA'][$this->strTable]['config']['notSortable']) {
                $arrButtons['cut'] = '<input type="submit" name="cut" id="cut" class="tl_submit" accesskey="x" value="' . specialchars($GLOBALS['TL_LANG']['MSC']['moveSelected']) . '">';
            }
            if (!$GLOBALS['TL_DCA'][$this->strTable]['config']['notCopyable']) {
                $arrButtons['copy'] = '<input type="submit" name="copy" id="copy" class="tl_submit" accesskey="c" value="' . specialchars($GLOBALS['TL_LANG']['MSC']['copySelected']) . '">';
            }
            if (!$GLOBALS['TL_DCA'][$this->strTable]['config']['notEditable']) {
                $arrButtons['override'] = '<input type="submit" name="override" id="override" class="tl_submit" accesskey="v" value="' . specialchars($GLOBALS['TL_LANG']['MSC']['overrideSelected']) . '">';
                $arrButtons['edit'] = '<input type="submit" name="edit" id="edit" class="tl_submit" accesskey="s" value="' . specialchars($GLOBALS['TL_LANG']['MSC']['editSelected']) . '">';
            }
            // 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);
                    }
                }
            }
            $return .= '

<div class="tl_formbody_submit" style="text-align:right">

<div class="tl_submit_container">
  ' . implode(' ', $arrButtons) . '
</div>

</div>
</div>
</form>';
        }
        return $return;
    }
 /**
  * Generate the module
  */
 protected function compile()
 {
     /** @var \PageModel $objPage */
     global $objPage;
     // Mark the x and y parameter as used (see #4277)
     if (isset($_GET['x'])) {
         \Input::get('x');
         \Input::get('y');
     }
     // Trigger the search module from a custom form
     if (!isset($_GET['keywords']) && \Input::post('FORM_SUBMIT') == 'tl_search') {
         $_GET['keywords'] = \Input::post('keywords');
         $_GET['query_type'] = \Input::post('query_type');
         $_GET['per_page'] = \Input::post('per_page');
     }
     $blnFuzzy = $this->fuzzy;
     $strQueryType = \Input::get('query_type') ?: $this->queryType;
     $strKeywords = trim(\Input::get('keywords'));
     /** @var \FrontendTemplate|object $objFormTemplate */
     $objFormTemplate = new \FrontendTemplate($this->searchType == 'advanced' ? 'mod_search_advanced' : 'mod_search_simple');
     $objFormTemplate->uniqueId = $this->id;
     $objFormTemplate->queryType = $strQueryType;
     $objFormTemplate->keyword = specialchars($strKeywords);
     $objFormTemplate->keywordLabel = $GLOBALS['TL_LANG']['MSC']['keywords'];
     $objFormTemplate->optionsLabel = $GLOBALS['TL_LANG']['MSC']['options'];
     $objFormTemplate->search = specialchars($GLOBALS['TL_LANG']['MSC']['searchLabel']);
     $objFormTemplate->matchAll = specialchars($GLOBALS['TL_LANG']['MSC']['matchAll']);
     $objFormTemplate->matchAny = specialchars($GLOBALS['TL_LANG']['MSC']['matchAny']);
     $objFormTemplate->id = \Config::get('disableAlias') && \Input::get('id') ? \Input::get('id') : false;
     $objFormTemplate->action = ampersand(\Environment::get('indexFreeRequest'));
     // Redirect page
     if ($this->jumpTo && ($objTarget = $this->objModel->getRelated('jumpTo')) !== null) {
         $objFormTemplate->action = $this->generateFrontendUrl($objTarget->row());
     }
     $this->Template->form = $objFormTemplate->parse();
     $this->Template->pagination = '';
     $this->Template->results = '';
     // Execute the search if there are keywords
     if ($strKeywords != '' && $strKeywords != '*' && !$this->jumpTo) {
         // Reference page
         if ($this->rootPage > 0) {
             $intRootId = $this->rootPage;
             $arrPages = $this->Database->getChildRecords($this->rootPage, 'tl_page');
             array_unshift($arrPages, $this->rootPage);
         } else {
             $intRootId = $objPage->rootId;
             $arrPages = $this->Database->getChildRecords($objPage->rootId, 'tl_page');
         }
         // HOOK: add custom logic (see #5223)
         if (isset($GLOBALS['TL_HOOKS']['customizeSearch']) && is_array($GLOBALS['TL_HOOKS']['customizeSearch'])) {
             foreach ($GLOBALS['TL_HOOKS']['customizeSearch'] as $callback) {
                 $this->import($callback[0]);
                 $this->{$callback[0]}->{$callback[1]}($arrPages, $strKeywords, $strQueryType, $blnFuzzy);
             }
         }
         // Return if there are no pages
         if (!is_array($arrPages) || empty($arrPages)) {
             $this->log('No searchable pages found', __METHOD__, TL_ERROR);
             return;
         }
         $arrResult = null;
         $strChecksum = md5($strKeywords . $strQueryType . $intRootId . $blnFuzzy);
         $query_starttime = microtime(true);
         $strCacheFile = 'system/cache/search/' . $strChecksum . '.json';
         // Load the cached result
         if (file_exists(TL_ROOT . '/' . $strCacheFile)) {
             $objFile = new \File($strCacheFile, true);
             if ($objFile->mtime > time() - 1800) {
                 $arrResult = json_decode($objFile->getContent(), true);
             } else {
                 $objFile->delete();
             }
         }
         // Cache the result
         if ($arrResult === null) {
             try {
                 $objSearch = \Search::searchFor($strKeywords, $strQueryType == 'or', $arrPages, 0, 0, $blnFuzzy);
                 $arrResult = $objSearch->fetchAllAssoc();
             } catch (\Exception $e) {
                 $this->log('Website search failed: ' . $e->getMessage(), __METHOD__, TL_ERROR);
                 $arrResult = array();
             }
             \File::putContent($strCacheFile, json_encode($arrResult));
         }
         $query_endtime = microtime(true);
         // Sort out protected pages
         if (\Config::get('indexProtected') && !BE_USER_LOGGED_IN) {
             $this->import('FrontendUser', 'User');
             foreach ($arrResult as $k => $v) {
                 if ($v['protected']) {
                     if (!FE_USER_LOGGED_IN) {
                         unset($arrResult[$k]);
                     } else {
                         $groups = deserialize($v['groups']);
                         if (!is_array($groups) || empty($groups) || !count(array_intersect($groups, $this->User->groups))) {
                             unset($arrResult[$k]);
                         }
                     }
                 }
             }
             $arrResult = array_values($arrResult);
         }
         $count = count($arrResult);
         $this->Template->count = $count;
         $this->Template->page = null;
         $this->Template->keywords = $strKeywords;
         // No results
         if ($count < 1) {
             $this->Template->header = sprintf($GLOBALS['TL_LANG']['MSC']['sEmpty'], $strKeywords);
             $this->Template->duration = substr($query_endtime - $query_starttime, 0, 6) . ' ' . $GLOBALS['TL_LANG']['MSC']['seconds'];
             return;
         }
         $from = 1;
         $to = $count;
         // Pagination
         if ($this->perPage > 0) {
             $id = 'page_s' . $this->id;
             $page = \Input::get($id) !== null ? \Input::get($id) : 1;
             $per_page = \Input::get('per_page') ?: $this->perPage;
             // Do not index or cache the page if the page number is outside the range
             if ($page < 1 || $page > max(ceil($count / $per_page), 1)) {
                 /** @var \PageError404 $objHandler */
                 $objHandler = new $GLOBALS['TL_PTY']['error_404']();
                 $objHandler->generate($objPage->id);
             }
             $from = ($page - 1) * $per_page + 1;
             $to = $from + $per_page > $count ? $count : $from + $per_page - 1;
             // Pagination menu
             if ($to < $count || $from > 1) {
                 $objPagination = new \Pagination($count, $per_page, \Config::get('maxPaginationLinks'), $id);
                 $this->Template->pagination = $objPagination->generate("\n  ");
             }
             $this->Template->page = $page;
         }
         // Get the results
         for ($i = $from - 1; $i < $to && $i < $count; $i++) {
             /** @var \FrontendTemplate|object $objTemplate */
             $objTemplate = new \FrontendTemplate($this->searchTpl ?: 'search_default');
             $objTemplate->url = $arrResult[$i]['url'];
             $objTemplate->link = $arrResult[$i]['title'];
             $objTemplate->href = $arrResult[$i]['url'];
             $objTemplate->title = specialchars($arrResult[$i]['title']);
             $objTemplate->class = ($i == $from - 1 ? 'first ' : '') . ($i == $to - 1 || $i == $count - 1 ? 'last ' : '') . ($i % 2 == 0 ? 'even' : 'odd');
             $objTemplate->relevance = sprintf($GLOBALS['TL_LANG']['MSC']['relevance'], number_format($arrResult[$i]['relevance'] / $arrResult[0]['relevance'] * 100, 2) . '%');
             $objTemplate->filesize = $arrResult[$i]['filesize'];
             $objTemplate->matches = $arrResult[$i]['matches'];
             $arrContext = array();
             $arrMatches = trimsplit(',', $arrResult[$i]['matches']);
             // Get the context
             foreach ($arrMatches as $strWord) {
                 $arrChunks = array();
                 preg_match_all('/(^|\\b.{0,' . $this->contextLength . '}\\PL)' . str_replace('+', '\\+', $strWord) . '(\\PL.{0,' . $this->contextLength . '}\\b|$)/ui', $arrResult[$i]['text'], $arrChunks);
                 foreach ($arrChunks[0] as $strContext) {
                     $arrContext[] = ' ' . $strContext . ' ';
                 }
             }
             // Shorten the context and highlight all keywords
             if (!empty($arrContext)) {
                 $objTemplate->context = trim(\StringUtil::substrHtml(implode('…', $arrContext), $this->totalLength));
                 $objTemplate->context = preg_replace('/(\\PL)(' . implode('|', $arrMatches) . ')(\\PL)/ui', '$1<span class="highlight">$2</span>$3', $objTemplate->context);
                 $objTemplate->hasContext = true;
             }
             $this->Template->results .= $objTemplate->parse();
         }
         $this->Template->header = vsprintf($GLOBALS['TL_LANG']['MSC']['sResults'], array($from, $to, $count, $strKeywords));
         $this->Template->duration = substr($query_endtime - $query_starttime, 0, 6) . ' ' . $GLOBALS['TL_LANG']['MSC']['seconds'];
     }
 }
 /**
  * @param \File $objCsvFile
  * @param $strTable
  * @param $strImportMode
  * @param null $arrSelectedFields
  * @param string $strFieldseparator
  * @param string $strFieldenclosure
  * @param string $strPrimaryKey
  * @param string $arrDelim
  */
 public function importCsv(\File $objCsvFile, $strTable, $strImportMode, $arrSelectedFields = null, $strFieldseparator = ';', $strFieldenclosure = '', $strPrimaryKey = 'id', $arrDelim = '||', $blnTestMode = false)
 {
     // store sucess or failure message in the session
     $_SESSION['import_from_csv']['report'] = array();
     // load language file
     \System::loadLanguageFile($strTable);
     // load dca
     $this->loadDataContainer($strTable);
     // store the options in $this->arrData
     $this->arrData = array('tablename' => $strTable, 'primaryKey' => $strPrimaryKey, 'importMode' => $strImportMode, 'selectedFields' => is_array($arrSelectedFields) ? $arrSelectedFields : array(), 'fieldSeparator' => $strFieldseparator, 'fieldEnclosure' => $strFieldenclosure);
     // truncate table
     if ($this->arrData['importMode'] == 'truncate_table') {
         $this->Database->execute('TRUNCATE TABLE `' . $strTable . '`');
     }
     if (count($this->arrData['selectedFields']) < 1) {
         return;
     }
     // get content as array
     $arrFileContent = $objCsvFile->getContentAsArray();
     $arrFieldnames = explode($this->arrData['fieldSeparator'], $arrFileContent[0]);
     // trim quotes in the first line and get the fieldnames
     $arrFieldnames = array_map(array($this, 'myTrim'), $arrFieldnames);
     // count rows
     $rows = 0;
     // count errors
     $insertError = 0;
     // store each line as an entry in the db
     foreach ($arrFileContent as $line => $lineContent) {
         $doNotSave = false;
         // line 0 contains the fieldnames
         if ($line == 0) {
             continue;
         }
         // count rows
         $rows++;
         // separate the line into the different fields
         $arrLine = explode($this->arrData['fieldSeparator'], $lineContent);
         // Set the associative Array with the line content
         $assocArrayLine = array();
         foreach ($arrFieldnames as $k => $fieldname) {
             $assocArrayLine[$fieldname] = $arrLine[$k];
         }
         $set = array();
         foreach ($arrFieldnames as $k => $fieldname) {
             $blnCustomValidation = false;
             // continue if field is excluded from import
             if (!in_array($fieldname, $this->arrData['selectedFields'])) {
                 continue;
             }
             // if entries are appended autoincrement id
             if ($this->arrData['importMode'] == 'append_entries' && strtolower($fieldname) == $this->arrData['primaryKey']) {
                 continue;
             }
             // get the field content
             $fieldValue = $arrLine[$k];
             // trim quotes
             $fieldValue = $this->myTrim($fieldValue);
             // convert variable to a string (see #2)
             $fieldValue = strval($fieldValue);
             // get the DCA of the current field
             $arrDCA =& $GLOBALS['TL_DCA'][$strTable]['fields'][$fieldname];
             $arrDCA = is_array($arrDCA) ? $arrDCA : array();
             // Prepare FormWidget object !set inputType to "text" if there is no definition
             $inputType = $arrDCA['inputType'] != '' ? $arrDCA['inputType'] : 'text';
             // Map checkboxWizards to regular checkbox widgets
             if ($inputType == 'checkboxWizard') {
                 $inputType = 'checkbox';
             }
             $strClass =& $GLOBALS['TL_FFL'][$inputType];
             // HOOK: add custom validation
             if (isset($GLOBALS['TL_HOOKS']['importFromCsv']) && is_array($GLOBALS['TL_HOOKS']['importFromCsv'])) {
                 $arrCustomValidation = array('strTable' => $strTable, 'arrDCA' => $arrDCA, 'fieldname' => $fieldname, 'value' => $fieldValue, 'arrayLine' => $assocArrayLine, 'line' => $line, 'objCsvFile' => $objCsvFile, 'skipWidgetValidation' => false, 'hasErrors' => false, 'errorMsg' => null, 'doNotSave' => false, 'blnTestMode' => $blnTestMode);
                 $blnCustomValidation = false;
                 foreach ($GLOBALS['TL_HOOKS']['importFromCsv'] as $callback) {
                     $this->import($callback[0]);
                     $arrCustomValidation = $this->{$callback[0]}->{$callback[1]}($arrCustomValidation, $this);
                     if (!is_array($arrCustomValidation)) {
                         die('Als Rückgabewert wird ein Array erwartet. Fehler in ' . __FILE__ . ' in Zeile ' . __LINE__ . '.');
                     }
                     $fieldValue = $arrCustomValidation['value'];
                     // Check if widget-validation should be skipped
                     if ($blnCustomValidation['skipWidgetValidation'] === true) {
                         $blnCustomValidation = true;
                     }
                 }
                 if ($arrCustomValidation['errorMsg'] != '') {
                     $fieldValue = sprintf('<span class="errMsg">%s</span>', $arrCustomValidation['errorMsg']);
                 }
                 if ($arrCustomValidation['doNotSave']) {
                     $doNotSave = true;
                 }
             }
             // Continue if the class does not exist
             // Use form widgets for input validation
             if (class_exists($strClass) && $blnCustomValidation === false) {
                 $objWidget = new $strClass($strClass::getAttributesFromDca($arrDCA, $fieldname, $fieldValue, '', '', $this));
                 $objWidget->storeValues = false;
                 // Set post var, so the content can be validated
                 \Input::setPost($fieldname, $fieldValue);
                 if ($fieldname == 'password') {
                     \Input::setPost('password_confirm', $fieldValue);
                 }
                 // add option values in the csv like this: value1||value2||value3
                 if ($inputType == 'radio' || $inputType == 'checkbox' || $inputType == 'select') {
                     if ($arrDCA['eval']['multiple'] === true) {
                         // Security issues in Contao #6695
                         if (version_compare(VERSION . BUILD, '3.2.5', '>=')) {
                             $fieldValue = $fieldValue != '' ? explode($arrDelim, $fieldValue) : null;
                         }
                         \Input::setPost($fieldname, $fieldValue);
                         $objWidget->value = $fieldValue;
                     }
                 }
                 // validate input
                 $objWidget->validate();
                 $fieldValue = $objWidget->value;
                 // Convert date formats into timestamps
                 $rgxp = $arrDCA['eval']['rgxp'];
                 if (($rgxp == 'date' || $rgxp == 'time' || $rgxp == 'datim') && $fieldValue != '' && !$objWidget->hasErrors()) {
                     try {
                         $strTimeFormat = $GLOBALS['TL_CONFIG'][$rgxp . 'Format'];
                         $objDate = new \Date($fieldValue, $strTimeFormat);
                         $fieldValue = $objDate->tstamp;
                     } catch (\OutOfBoundsException $e) {
                         $objWidget->addError(sprintf($GLOBALS['TL_LANG']['ERR']['invalidDate'], $fieldValue));
                     }
                 }
                 // Make sure that unique fields are unique
                 if ($arrDCA['eval']['unique'] && $fieldValue != '' && !$this->Database->isUniqueValue($strTable, $fieldname, $fieldValue, null)) {
                     $objWidget->addError(sprintf($GLOBALS['TL_LANG']['ERR']['unique'], $arrDCA['label'][0] ?: $fieldname));
                 }
                 // Do not save the field if there are errors
                 if ($objWidget->hasErrors()) {
                     $doNotSave = true;
                     $fieldValue = sprintf('"%s" => <span class="errMsg">%s</span>', $fieldValue, $objWidget->getErrorsAsString());
                 } else {
                     // Set the correct empty value
                     if ($fieldValue === '') {
                         $fieldValue = $objWidget->getEmptyValue();
                     }
                 }
             }
             $set[$fieldname] = is_array($fieldValue) ? serialize($fieldValue) : $fieldValue;
         }
         // insert data record
         if (!$doNotSave) {
             // insert tstamp
             if ($this->Database->fieldExists('tstamp', $strTable)) {
                 if (!$set['tstamp'] > 0) {
                     $set['tstamp'] = time();
                 }
             }
             // insert dateAdded (tl_member)
             if ($this->Database->fieldExists('dateAdded', $strTable)) {
                 if (!$set['dateAdded'] > 0) {
                     $set['dateAdded'] = time();
                 }
             }
             // add new member to newsletter recipient list
             if ($strTable == 'tl_member' && $set['email'] != '' && $set['newsletter'] != '') {
                 foreach (deserialize($set['newsletter'], true) as $newsletterId) {
                     // check for unique email-address
                     $objRecipient = $this->Database->prepare("SELECT * FROM tl_newsletter_recipients WHERE email=? AND pid=(SELECT pid FROM tl_newsletter_recipients WHERE id=?) AND id!=?")->execute($set['email'], $newsletterId, $newsletterId);
                     if (!$objRecipient->numRows) {
                         $arrRecipient = array();
                         $arrRecipient['tstamp'] = time();
                         $arrRecipient['pid'] = $newsletterId;
                         $arrRecipient['email'] = $set['email'];
                         $arrRecipient['active'] = '1';
                         if ($blnTestMode !== true) {
                             $this->Database->prepare('INSERT INTO tl_newsletter_recipients %s')->set($arrRecipient)->execute();
                         }
                     }
                 }
             }
             try {
                 if ($blnTestMode !== true) {
                     // insert entry into database
                     $this->Database->prepare('INSERT INTO ' . $strTable . ' %s')->set($set)->execute();
                 }
             } catch (\Exception $e) {
                 $set['insertError'] = $e->getMessage();
                 $doNotSave = true;
             }
         }
         // generate html markup for the import report table
         $htmlReport = '';
         $cssClass = 'allOk';
         if ($doNotSave) {
             $cssClass = 'error';
             $htmlReport .= sprintf('<tr class="%s"><td class="tdTitle" colspan="2">#%s Datensatz konnte nicht angelegt werden!</td></tr>', $cssClass, $line);
             // increment error counter if necessary
             $insertError++;
         } else {
             $htmlReport .= sprintf('<tr class="%s"><td class="tdTitle" colspan="2">#%s Datensatz erfolgreich angelegt!</td></tr>', $cssClass, $line);
         }
         foreach ($set as $k => $v) {
             if (is_array($v)) {
                 $v = serialize($v);
             }
             $htmlReport .= sprintf('<tr class="%s"><td>%s</td><td>%s</td></tr>', $cssClass, \StringUtil::substr($k, 30), \StringUtil::substrHtml($v, 90));
         }
         $htmlReport .= '<tr class="delim"><td>&nbsp;</td><td>&nbsp;</td></tr>';
         $_SESSION['import_from_csv']['report'][] = $htmlReport;
     }
     $_SESSION['import_from_csv']['status'] = array('blnTestMode' => $blnTestMode, 'rows' => $rows, 'success' => $rows - $insertError, 'errors' => $insertError);
 }
 protected function generateItemLabel($objRow, $folderAttribute)
 {
     $blnProtected = false;
     $showFields = $this->arrDca['list']['label']['fields'];
     $dc = new DC_Table(\Config::get('fieldpalette_table'));
     $dc->id = $this->currentRecord;
     $dc->activeRecord = $objRow;
     foreach ($showFields as $k => $v) {
         $args[$k] = FormSubmission::prepareSpecialValueForPrint($objRow->{$v}, $this->arrDca['fields'][$v], $this->strTable, $dc);
     }
     $label = vsprintf(strlen($this->arrDca['list']['label']['format']) ? $this->arrDca['list']['label']['format'] : '%s', $args);
     // Shorten the label if it is too long
     if ($this->arrDca['list']['label']['maxCharacters'] > 0 && $this->arrDca['list']['label']['maxCharacters'] < utf8_strlen(strip_tags($label))) {
         $label = trim(\StringUtil::substrHtml($label, $this->arrDca['list']['label']['maxCharacters'])) . ' …';
     }
     // Call the label_callback ($row, $label, $this)
     if (is_array($this->arrDca['list']['label']['label_callback'])) {
         $strClass = $this->arrDca['list']['label']['label_callback'][0];
         $strMethod = $this->arrDca['list']['label']['label_callback'][1];
         $this->import($strClass);
         return $this->{$strClass}->{$strMethod}($objRow->row(), $label, $this, $folderAttribute, false, $blnProtected);
     } elseif (is_callable($this->arrDca['list']['label']['label_callback'])) {
         return $this->arrDca['list']['label']['label_callback']($objRow->row(), $label, $this, $folderAttribute, false, $blnProtected);
     } else {
         return $label;
     }
     return $label;
 }