/** * @param $row * @param $href * @param $label * @param $title * @param $icon * @param $attributes * @return string */ public function toggleIcon($row, $href, $label, $title, $icon, $attributes) { if (strlen(Input::get('tid'))) { $this->toggleVisibility(Input::get('tid'), Input::get('state') == 1, @func_get_arg(12) ?: null); $this->redirect($this->getReferer()); } // Check permissions AFTER checking the tid, so hacking attempts are logged if (!$this->User->hasAccess('tl_api_client::disable', 'alexf')) { return ''; } $href .= '&tid=' . $row['id'] . '&state=' . $row['disable']; if ($row['disable']) { $icon = 'invisible.gif'; } return '<a href="' . $this->addToUrl($href) . '" title="' . specialchars($title) . '"' . $attributes . '>' . Image::getHtml($icon, $label, 'data-state="' . ($row['disable'] ? 0 : 1) . '"') . '</a> '; }
/** * Generate the widget and return it as string * * @return string */ public function generate() { if (!is_array($this->varValue)) { $this->varValue = []; } $options = []; // Generate the options foreach ((array) $this->options as $option) { $linkId = sprintf('ctrl_%s_%s_%s_%s_link', $this->objDca->field, $this->objDca->id, $this->strId, $option['value']); $reference = $GLOBALS['TL_DCA'][$this->objDca->table]['fields'][$this->objDca->field]['reference'][$option['value']]; $options[] = ['type' => ['label' => $option['label'], 'hint' => is_array($reference) ? $reference[1] : ''], 'picker' => ['tag' => $linkId, 'url' => sprintf('contao/page.php?do=%s&table=%s&field=%s&value=%s', Input::get('do'), $this->objDca->table, $this->objDca->field, str_replace(['{{link_url::', '}}'], '', $this->varValue[$option['value']]['link']))], 'link' => ['id' => $linkId, 'name' => sprintf('%s[%s][link]', $this->strId, $option['value']), 'value' => $this->varValue[$option['value']]['link']], 'title' => ['name' => sprintf('%s[%s][title]', $this->strId, $option['value']), 'value' => $this->varValue[$option['value']]['title']]]; } $template = new BackendTemplate('be_cfg_link_registry_widget'); $template->options = $options; $template->field = $this->objDca->field; $template->picker = ['id' => $this->objDca->field, 'title' => str_replace("'", "\\'", $GLOBALS['TL_LANG']['MOD']['page'][0]), 'image' => Image::getHtml('pickpage.gif', $GLOBALS['TL_LANG']['MSC']['pagepicker'], 'style="vertical-align:top;cursor:pointer"')]; return $template->parse(); }
/** * return a icon tag instead of an Image * * @param string $src * @param string $alt * @param string $attributes * * @return string */ public static function getHtml($src, $alt = '', $attributes = '') { // Only do this in the Backend if (TL_MODE == "FE" || \Backend::getTheme() != "sb-admin") { return parent::getHtml($src, $alt, $attributes); } $arrImage = array('article.gif' => 'share', 'article_.gif' => 'share icon-disabled', 'copychilds.gif' => 'files-o', 'copychilds_.gif' => 'files-o icon-disabled', 'apply.gif' => 'check-circle', 'copy.gif' => 'plus', 'cut.gif' => 'sort', 'delete.gif' => 'trash-o', 'edit.gif' => 'pencil', 'edit_.gif' => 'pencil icon-disabled', 'editor.gif' => 'file-code-o', 'editor_.gif' => 'file-code-o icon-disabled', 'featured_.gif' => 'star-o', 'featured.gif' => 'star', 'header.gif' => 'cogs', 'invisible.gif' => 'eye-slash', 'new.gif' => 'plus-circle', 'pasteafter.gif' => 'caret-down', 'pasteafter_.gif' => 'caret-down icon-disabled', 'pasteinto.gif' => 'caret-right', 'pasteinto_.gif' => 'caret-right icon-disabled', 'protect.gif' => 'unlock', 'protect_.gif' => 'lock', 'show.gif' => 'info', 'undo.gif' => 'undo', 'visible.gif' => 'eye', 'modules.gif' => 'cogs', 'pagemounts.gif' => 'globe', 'root.gif' => 'globe', 'root_1.gif' => 'globe icon-disabled', 'diff.gif' => 'tasks', 'diffTemplate.gif' => 'tasks', 'diff_.gif' => 'tasks icon-disabled', 'diffTemplate_.gif' => 'tasks icon-disabled', 'drag.gif' => 'sort', 'up.gif' => 'arrow-up', 'down.gif' => 'arrow-down', 'folMinus.gif' => 'minus-square-o', 'folPlus.gif' => 'plus-square-o', 'mgroup.gif' => 'users', 'member.gif' => 'user', 'member_.gif' => 'user icon-disabled', 'su.gif' => 'qq'); if (array_key_exists($src, $arrImage)) { preg_match('/class=\\"([^\\"]*)\\"/', $attributes, $matches); $cssClass = isset($matches[1]) ? " " . $matches[1] : ""; preg_match('/style=\\"([^\\"]*)\\"/', $attributes, $matches); $style = isset($matches[1]) ? ' style="' . $matches[1] . '"' : ""; preg_match('/title=\\"([^\\"]*)\\"/', $attributes, $matches); $title = isset($matches[1]) ? ' title="' . $matches[1] . '"' : ""; return sprintf('<i class="fa fa-%s%s action-icon"%s%s></i>', $arrImage[$src], $cssClass, $style, $title); } return parent::getHtml($src, $alt, $attributes); }
/** * Generate the icons by the given conditions. * * @param array $row The current record. * * @return string */ public function generateDeviceConditionConfiguration($row) { if (!Input::get('do') == 'article' || !Input::get('do') == 'postmanager' || Input::get('task') == 'indexmanager') { return; } $conditions = deserialize($row['device_condition']); $allConditions = array('desktop', 'mobile'); $return = ''; Controller::loadLanguageFile('default'); if (!$conditions) { foreach ($allConditions as $condition) { $return .= Image::getHtml('/system/modules/z_device-condition/assets/icons/' . $condition . '.png', $this->getTranslationForCondition($condition)); } } else { foreach ($allConditions as $condition) { if (in_array($condition, $conditions)) { $return .= Image::getHtml('/system/modules/z_device-condition/assets/icons/' . $condition . '.png', $this->getTranslationForCondition($condition)); } else { $return .= Image::getHtml('/system/modules/z_device-condition/assets/icons/disabled/' . $condition . '.png', $this->getTranslationForCondition($condition)); } } } return $return; }
/** * @param $row * @param $href * @param $label * @param $title * @param $icon * @param $attributes * @return string */ public function toggleIcon($row, $href, $label, $title, $icon, $attributes) { if (strlen(Input::get('tid'))) { $this->toggleVisibility(Input::get('tid'), Input::get('state') == 1, @func_get_arg(12) ?: null); $this->redirect($this->getReferer()); } $href .= '&tid=' . $row['id'] . '&state=' . ($row['published'] ? '' : 1); if (!$row['published']) { $icon = 'invisible.gif'; } return '<a href="' . $this->addToUrl($href) . '" title="' . specialchars($title) . '"' . $attributes . '>' . Image::getHtml($icon, $label, 'data-state="' . ($row['published'] ? 1 : 0) . '"') . '</a> '; }
/** * Recursively render the pagetree * * @param integer $id * @param integer $intMargin * @param boolean $protectedPage * @param boolean $blnNoRecursion * @param array $arrFound * * @return string */ protected function renderPagetree($id, $intMargin, $protectedPage = false, $blnNoRecursion = false, $arrFound = array()) { static $session; /** @var AttributeBagInterface $objSessionBag */ $objSessionBag = \System::getContainer()->get('session')->getBag('contao_backend'); $session = $objSessionBag->all(); $flag = substr($this->strField, 0, 2); $node = 'tree_' . $this->strTable . '_' . $this->strField; $xtnode = 'tree_' . $this->strTable . '_' . $this->strName; // Get the session data and toggle the nodes if (\Input::get($flag . 'tg')) { $session[$node][\Input::get($flag . 'tg')] = isset($session[$node][\Input::get($flag . 'tg')]) && $session[$node][\Input::get($flag . 'tg')] == 1 ? 0 : 1; $objSessionBag->replace($session); $this->redirect(preg_replace('/(&(amp;)?|\\?)' . $flag . 'tg=[^& ]*/i', '', \Environment::get('request'))); } $objPage = $this->Database->prepare("SELECT id, alias, type, protected, published, start, stop, hide, title FROM tl_page WHERE id=?")->limit(1)->execute($id); // Return if there is no result if ($objPage->numRows < 1) { return ''; } $return = ''; $intSpacing = 20; $childs = array(); // Check whether there are child records if (!$blnNoRecursion) { $objNodes = $this->Database->prepare("SELECT id FROM tl_page WHERE pid=?" . (!empty($arrFound) ? " AND id IN(" . implode(',', array_map('intval', $arrFound)) . ")" : '') . " ORDER BY sorting")->execute($id); if ($objNodes->numRows) { $childs = $objNodes->fetchEach('id'); } } $return .= "\n " . '<li class="' . ($objPage->type == 'root' ? 'tl_folder' : 'tl_file') . ' toggle_select hover-div"><div class="tl_left" style="padding-left:' . ($intMargin + $intSpacing) . 'px">'; $folderAttribute = 'style="margin-left:20px"'; $session[$node][$id] = is_numeric($session[$node][$id]) ? $session[$node][$id] : 0; $level = $intMargin / $intSpacing + 1; $blnIsOpen = !empty($arrFound) || $session[$node][$id] == 1 || in_array($id, $this->arrNodes); if (!empty($childs)) { $folderAttribute = ''; $img = $blnIsOpen ? 'folMinus.svg' : 'folPlus.svg'; $alt = $blnIsOpen ? $GLOBALS['TL_LANG']['MSC']['collapseNode'] : $GLOBALS['TL_LANG']['MSC']['expandNode']; $return .= '<a href="' . \Backend::addToUrl($flag . 'tg=' . $id) . '" title="' . \StringUtil::specialchars($alt) . '" onclick="return AjaxRequest.togglePagetree(this,\'' . $xtnode . '_' . $id . '\',\'' . $this->strField . '\',\'' . $this->strName . '\',' . $level . ')">' . \Image::getHtml($img, '', 'style="margin-right:2px"') . '</a>'; } // Set the protection status $objPage->protected = $objPage->protected || $protectedPage; // Add the current page if (!empty($childs)) { $return .= \Image::getHtml($this->getPageStatusIcon($objPage), '', $folderAttribute) . ' <a href="' . \Backend::addToUrl('pn=' . $objPage->id) . '" title="' . \StringUtil::specialchars($objPage->title . ' (' . $objPage->alias . \Config::get('urlSuffix') . ')') . '">' . ($objPage->type == 'root' ? '<strong>' : '') . $objPage->title . ($objPage->type == 'root' ? '</strong>' : '') . '</a></div> <div class="tl_right">'; } else { $return .= \Image::getHtml($this->getPageStatusIcon($objPage), '', $folderAttribute) . ' ' . ($objPage->type == 'root' ? '<strong>' : '') . $objPage->title . ($objPage->type == 'root' ? '</strong>' : '') . '</div> <div class="tl_right">'; } // Add checkbox or radio button switch ($this->fieldType) { case 'checkbox': $return .= '<input type="checkbox" name="' . $this->strName . '[]" id="' . $this->strName . '_' . $id . '" class="tl_tree_checkbox" value="' . \StringUtil::specialchars($id) . '" onfocus="Backend.getScrollOffset()"' . static::optionChecked($id, $this->varValue) . '>'; break; default: case 'radio': $return .= '<input type="radio" name="' . $this->strName . '" id="' . $this->strName . '_' . $id . '" class="tl_tree_radio" value="' . \StringUtil::specialchars($id) . '" onfocus="Backend.getScrollOffset()"' . static::optionChecked($id, $this->varValue) . '>'; break; } $return .= '</div><div style="clear:both"></div></li>'; // Begin a new submenu if ($blnIsOpen || !empty($childs) && $objSessionBag->get('page_selector_search') != '') { $return .= '<li class="parent" id="' . $node . '_' . $id . '"><ul class="level_' . $level . '">'; for ($k = 0, $c = count($childs); $k < $c; $k++) { $return .= $this->renderPagetree($childs[$k], $intMargin + $intSpacing, $objPage->protected, $blnNoRecursion, $arrFound); } $return .= '</ul></li>'; } return $return; }
/** * @param $doTable * @return string */ public function getIcon($doTable) { $icon = ''; $path = 'system/modules/prosearch/assets/images/'; if (version_compare(VERSION, '4.0', '>=') && !$GLOBALS['PS_NO_COMPOSER'] && $GLOBALS['PS_NO_COMPOSER'] != true) { $path = 'bundles/prosearch/images/'; } if (!in_array($doTable, $this->notCoreModules)) { $path = ''; } if ($this->modules[$doTable] && $this->modules[$doTable]['icon']) { $icon = Image::getHtml($path . $this->modules[$doTable]['icon']); } return $icon; }
/** * @param $state * @param $label * @param $fieldID * @param bool $noHTML * @return string */ public function getToggleIcon($state, $label, $fieldID, $noHTML = false) { $src = $state ? 'files/fmodule/assets/' . $fieldID . '.' : 'files/fmodule/assets/' . $fieldID . '_.'; $temp = $state ? 'files/fmodule/assets/' . $fieldID . '_.' : 'files/fmodule/assets/' . $fieldID . '.'; $allowedFormat = array('gif', 'png', 'svg'); foreach ($allowedFormat as $format) { if (is_file(TL_ROOT . '/' . $src . $format) && !$noHTML) { return Image::getHtml($src . $format, $label, 'data-src="' . $temp . $format . '" data-state="' . ($state ? 1 : 0) . '"'); } if (is_file(TL_ROOT . '/' . $src . $format) && $noHTML) { return $src . $format; } } $icon = $state ? 'featured.gif' : 'featured_.gif'; $nIcon = $state ? 'featured_.gif' : 'featured.gif'; $temp = 'system/themes/' . Backend::getTheme() . '/images/' . $nIcon; $src = 'system/themes/' . Backend::getTheme() . '/images/' . $icon; if ($noHTML) { return $src; } return Image::getHtml($src, $label, 'data-src="' . $temp . '" data-state="' . ($state ? 1 : 0) . '"'); }
/** * Show header of the parent table and list all records of the current table * * @return string */ protected function parentView() { /** @var SessionInterface $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 fonts to display the paste hint \Config::set('loadGoogleFonts', $blnClipboard); // Load the language file and data container array of the parent table \System::loadLanguageFile($this->ptable); $this->loadDataContainer($this->ptable); $return = ' <div id="tl_buttons">' . (\Input::get('nb') ? ' ' : ($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' && !$blnClipboard && !$GLOBALS['TL_DCA'][$this->strTable]['config']['closed'] && !$GLOBALS['TL_DCA'][$this->strTable]['config']['notCreatable'] ? ' <a href="' . $this->addToUrl($blnHasSorting ? 'act=paste&mode=create' : 'act=create&mode=2&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> ' : '') . ($blnClipboard ? ' <a href="' . $this->addToUrl('clipboard=1') . '" class="header_clipboard" title="' . specialchars($GLOBALS['TL_LANG']['MSC']['clearClipboard']) . '" accesskey="x">' . $GLOBALS['TL_LANG']['MSC']['clearClipboard'] . '</a> ' : $this->generateGlobalButtons()) . ' </div>' . \Message::generate(true); // 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"> <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"> <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', 'User'); // Header $imagePasteNew = \Image::getHtml('new.gif', $GLOBALS['TL_LANG'][$this->strTable]['pastenew'][0]); $imagePasteAfter = \Image::getHtml('pasteafter.gif', $GLOBALS['TL_LANG'][$this->strTable]['pasteafter'][0]); $imageEditHeader = \Image::getHtml('header.gif', $GLOBALS['TL_LANG'][$this->strTable]['editheader'][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">' : ($blnClipboard ? ' <a href="' . $this->addToUrl('act=' . $arrClipboard['mode'] . '&mode=2&pid=' . $objParent->id . (!$blnMultiboard ? '&id=' . $arrClipboard['id'] : '')) . '" title="' . 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 != '' ? '&table=' . $this->ptable : '', $this->addToUrl('act=edit')) . '" class="edit" title="' . specialchars(isset($GLOBALS['TL_LANG'][$this->ptable]['editmeta'][1]) ? $GLOBALS['TL_LANG'][$this->ptable]['editmeta'][1] : $GLOBALS['TL_LANG'][$this->strTable]['editheader'][1]) . '">' . $imageEditHeader . '</a>' : '') . ($blnHasSorting && !$GLOBALS['TL_DCA'][$this->strTable]['config']['closed'] && !$GLOBALS['TL_DCA'][$this->strTable]['config']['notCreatable'] ? ' <a href="' . $this->addToUrl('act=create&mode=2&pid=' . $objParent->id . '&id=' . $this->intId) . '" title="' . 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 = 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]['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') { if ($GLOBALS['TL_DCA'][$this->strTable]['config']['dynamicPtable']) { $ptable = $GLOBALS['TL_DCA'][$this->strTable]['config']['ptable']; $cond = $ptable == 'tl_article' ? "(ptable=? OR ptable='')" : "ptable=?"; $objMaxTstamp = $this->Database->prepare("SELECT MAX(tstamp) AS tstamp FROM " . $this->strTable . " WHERE pid=? AND {$cond}")->execute($objParent->id, $ptable); } else { $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(\Config::get('datimFormat'), max($objParent->tstamp, $objMaxTstamp->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 " . $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 = isset($GLOBALS['TL_LANG'][$this->ptable][$v][0]) ? $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 " . $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]); } $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.gif', sprintf($GLOBALS['TL_LANG'][$this->strTable]['pasteafter'][1], $row[$i]['id'])); $imagePasteNew = \Image::getHtml('new.gif', 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(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); 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']); // 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 : '') . ($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'] . '">'; } 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&mode=1&pid=' . $row[$i]['id'] . '&id=' . $objParent->id) . '" title="' . 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_.gif'); } elseif ($blnMultiboard) { $return .= ' <a href="' . $this->addToUrl('act=' . $arrClipboard['mode'] . '&mode=1&pid=' . $row[$i]['id']) . '" title="' . 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'] . '&mode=1&pid=' . $row[$i]['id'] . '&id=' . $arrClipboard['id']) . '" title="' . 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 .= ' ' . \Image::getHtml('drag.gif', '', 'class="drag-handle" title="' . sprintf($GLOBALS['TL_LANG'][$this->strTable]['cut'][1], $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 .= ' </div>'; // Close form if (\Input::get('act') == 'select') { // Submit buttons $arrButtons = array(); 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']['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']['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']['notEditable']) { $arrButtons['override'] = '<button type="submit" name="override" id="override" class="tl_submit" accesskey="v">' . $GLOBALS['TL_LANG']['MSC']['overrideSelected'] . '</button>'; $arrButtons['edit'] = '<button type="submit" name="edit" id="edit" class="tl_submit" accesskey="s">' . $GLOBALS['TL_LANG']['MSC']['editSelected'] . '</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); } } } $return .= ' <div class="tl_formbody_submit" style="text-align:right"> <div class="tl_submit_container"> ' . implode(' ', $arrButtons) . ' </div> </div> </div> </form>'; } return $return; }
/** * Render the versions dropdown menu * * @return string */ public function renderDropdown() { $objVersion = $this->Database->prepare("SELECT tstamp, version, username, active FROM tl_version WHERE fromTable=? AND pid=? ORDER BY version DESC")->execute($this->strTable, $this->intPid); if ($objVersion->numRows < 2) { return ''; } $versions = ''; while ($objVersion->next()) { $versions .= ' <option value="' . $objVersion->version . '"' . ($objVersion->active ? ' selected="selected"' : '') . '>' . $GLOBALS['TL_LANG']['MSC']['version'] . ' ' . $objVersion->version . ' (' . \Date::parse(\Config::get('datimFormat'), $objVersion->tstamp) . ') ' . $objVersion->username . '</option>'; } return ' <div class="tl_version_panel"> <form action="' . ampersand(\Environment::get('request'), true) . '" id="tl_version" class="tl_form" method="post"> <div class="tl_formbody"> <input type="hidden" name="FORM_SUBMIT" value="tl_version"> <input type="hidden" name="REQUEST_TOKEN" value="' . REQUEST_TOKEN . '"> <select name="version" class="tl_select">' . $versions . ' </select> <button type="submit" name="showVersion" id="showVersion" class="tl_submit">' . $GLOBALS['TL_LANG']['MSC']['restore'] . '</button> <a href="' . \Backend::addToUrl('versions=1&popup=1') . '" title="' . \StringUtil::specialchars($GLOBALS['TL_LANG']['MSC']['showDifferences']) . '" onclick="Backend.openModalIframe({\'width\':768,\'title\':\'' . \StringUtil::specialchars(str_replace("'", "\\'", sprintf($GLOBALS['TL_LANG']['MSC']['recordOfTable'], $this->intPid, $this->strTable))) . '\',\'url\':this.href});return false">' . \Image::getHtml('diff.svg') . '</a> </div> </form> </div> '; }
/** * Compile buttons from the table configuration array and return them as HTML * * @param array $arrRow * @param string $strTable * @param array $arrRootIds * @param boolean $blnCircularReference * @param array $arrChildRecordIds * @param string $strPrevious * @param string $strNext * * @return string */ protected function generateButtons($arrRow, $strTable, $arrRootIds = array(), $blnCircularReference = false, $arrChildRecordIds = null, $strPrevious = null, $strNext = null) { if (empty($GLOBALS['TL_DCA'][$strTable]['list']['operations'])) { return ''; } $return = ''; foreach ($GLOBALS['TL_DCA'][$strTable]['list']['operations'] as $k => $v) { $v = is_array($v) ? $v : array($v); $id = \StringUtil::specialchars(rawurldecode($arrRow['id'])); $label = $v['label'][0] ?: $k; $title = sprintf($v['label'][1] ?: $k, $id); $attributes = $v['attributes'] != '' ? ' ' . ltrim(sprintf($v['attributes'], $id, $id)) : ''; // Add the key as CSS class if (strpos($attributes, 'class="') !== false) { $attributes = str_replace('class="', 'class="' . $k . ' ', $attributes); } else { $attributes = ' class="' . $k . '"' . $attributes; } // Call a custom function instead of using the default button if (is_array($v['button_callback'])) { $this->import($v['button_callback'][0]); $return .= $this->{$v['button_callback'][0]}->{$v['button_callback'][1]}($arrRow, $v['href'], $label, $title, $v['icon'], $attributes, $strTable, $arrRootIds, $arrChildRecordIds, $blnCircularReference, $strPrevious, $strNext, $this); continue; } elseif (is_callable($v['button_callback'])) { $return .= $v['button_callback']($arrRow, $v['href'], $label, $title, $v['icon'], $attributes, $strTable, $arrRootIds, $arrChildRecordIds, $blnCircularReference, $strPrevious, $strNext, $this); continue; } // Generate all buttons except "move up" and "move down" buttons if ($k != 'move' && $v != 'move') { if ($k == 'show') { $return .= '<a href="' . $this->addToUrl($v['href'] . '&id=' . $arrRow['id'] . '&popup=1') . '" title="' . \StringUtil::specialchars($title) . '" onclick="Backend.openModalIframe({\'width\':768,\'title\':\'' . \StringUtil::specialchars(str_replace("'", "\\'", sprintf($GLOBALS['TL_LANG'][$strTable]['show'][1], $arrRow['id']))) . '\',\'url\':this.href});return false"' . $attributes . '>' . \Image::getHtml($v['icon'], $label) . '</a> '; } else { $return .= '<a href="' . $this->addToUrl($v['href'] . '&id=' . $arrRow['id']) . '" title="' . \StringUtil::specialchars($title) . '"' . $attributes . '>' . \Image::getHtml($v['icon'], $label) . '</a> '; } continue; } $arrDirections = array('up', 'down'); $arrRootIds = is_array($arrRootIds) ? $arrRootIds : array($arrRootIds); foreach ($arrDirections as $dir) { $label = $GLOBALS['TL_LANG'][$strTable][$dir][0] ?: $dir; $title = $GLOBALS['TL_LANG'][$strTable][$dir][1] ?: $dir; $label = \Image::getHtml($dir . '.svg', $label); $href = $v['href'] ?: '&act=move'; if ($dir == 'up') { $return .= (is_numeric($strPrevious) && (!in_array($arrRow['id'], $arrRootIds) || empty($GLOBALS['TL_DCA'][$strTable]['list']['sorting']['root'])) ? '<a href="' . $this->addToUrl($href . '&id=' . $arrRow['id']) . '&sid=' . intval($strPrevious) . '" title="' . \StringUtil::specialchars($title) . '"' . $attributes . '>' . $label . '</a> ' : \Image::getHtml('up_.svg')) . ' '; continue; } $return .= (is_numeric($strNext) && (!in_array($arrRow['id'], $arrRootIds) || empty($GLOBALS['TL_DCA'][$strTable]['list']['sorting']['root'])) ? '<a href="' . $this->addToUrl($href . '&id=' . $arrRow['id']) . '&sid=' . intval($strNext) . '" title="' . \StringUtil::specialchars($title) . '"' . $attributes . '>' . $label . '</a> ' : \Image::getHtml('down_.svg')) . ' '; } } return trim($return); }
/** * Generate an image tag and return it as string * * @param string $src The image path * @param string $alt An optional alt attribute * @param string $attributes A string of other attributes * * @return string The image HTML tag * * @deprecated Deprecated since Contao 4.0, to be removed in Contao 5.0. * Use Image::getHtml() instead. */ public static function generateImage($src, $alt = '', $attributes = '') { trigger_error('Using Controller::generateImage() has been deprecated and will no longer work in Contao 5.0. Use Image::getHtml() instead.', E_USER_DEPRECATED); return \Image::getHtml($src, $alt, $attributes); }
/** * Handle a get html for image event. * * @param GenerateHtmlEvent $event The event. * * @return void */ public function handleGenerateHtml(GenerateHtmlEvent $event) { $event->setHtml(Image::getHtml($event->getSrc(), $event->getAlt(), $event->getAttributes())); }
/** * Add an image to each page in the tree * * @param array $row * @param string $label * @param \DataContainer $dc * @param string $imageAttribute * @param boolean $blnReturnImage * @param boolean $blnProtected * * @return string */ public static function addPageIcon($row, $label, \DataContainer $dc = null, $imageAttribute = '', $blnReturnImage = false, $blnProtected = false) { if ($blnProtected) { $row['protected'] = true; } $image = \Controller::getPageStatusIcon((object) $row); // Return the image only if ($blnReturnImage) { return \Image::getHtml($image, '', $imageAttribute); } // Mark root pages if ($row['type'] == 'root' || \Input::get('do') == 'article') { $label = '<strong>' . $label . '</strong>'; } // Add the breadcrumb link $label = '<a href="' . \Controller::addToUrl('node=' . $row['id']) . '" title="' . specialchars($GLOBALS['TL_LANG']['MSC']['selectNode']) . '">' . $label . '</a>'; // Return the image return '<a href="contao/main.php?do=feRedirect&page=' . $row['id'] . '" title="' . specialchars($GLOBALS['TL_LANG']['MSC']['view']) . '"' . ($dc->table != 'tl_page' ? ' class="tl_gray"' : '') . ' target="_blank">' . \Image::getHtml($image, '', $imageAttribute) . '</a> ' . $label; }
/** * Recursively render the filetree * * @param string $path * @param integer $intMargin * @param boolean $mount * @param boolean $blnProtected * * @return string */ protected function renderFiletree($path, $intMargin, $mount = false, $blnProtected = true) { // Invalid path if (!is_dir($path)) { return ''; } // Make sure that $this->varValue is an array (see #3369) if (!is_array($this->varValue)) { $this->varValue = array($this->varValue); } static $session; /** @var AttributeBagInterface $objSessionBag */ $objSessionBag = \System::getContainer()->get('session')->getBag('contao_backend'); $session = $objSessionBag->all(); $flag = substr($this->strField, 0, 2); $node = 'tree_' . $this->strTable . '_' . $this->strField; $xtnode = 'tree_' . $this->strTable . '_' . $this->strName; // Get session data and toggle nodes if (\Input::get($flag . 'tg')) { $session[$node][\Input::get($flag . 'tg')] = isset($session[$node][\Input::get($flag . 'tg')]) && $session[$node][\Input::get($flag . 'tg')] == 1 ? 0 : 1; $objSessionBag->replace($session); $this->redirect(preg_replace('/(&(amp;)?|\\?)' . $flag . 'tg=[^& ]*/i', '', \Environment::get('request'))); } $return = ''; $intSpacing = 20; $files = array(); $folders = array(); $level = $intMargin / $intSpacing + 1; // Mount folder if ($mount) { $folders = array($path); } else { foreach (scan($path) as $v) { if (strncmp($v, '.', 1) === 0) { continue; } if (is_dir($path . '/' . $v)) { $folders[] = $path . '/' . $v; } else { $files[] = $path . '/' . $v; } } } natcasesort($folders); $folders = array_values($folders); natcasesort($files); $files = array_values($files); // Sort descending (see #4072) if ($this->sort == 'desc') { $folders = array_reverse($folders); $files = array_reverse($files); } $folderClass = $this->files || $this->filesOnly ? 'tl_folder' : 'tl_file'; // Process folders for ($f = 0, $c = count($folders); $f < $c; $f++) { $countFiles = 0; $content = scan($folders[$f]); $return .= "\n " . '<li class="' . $folderClass . ' toggle_select" onmouseover="Theme.hoverDiv(this, 1)" onmouseout="Theme.hoverDiv(this, 0)"><div class="tl_left" style="padding-left:' . $intMargin . 'px">'; // Check whether there are subfolders or files foreach ($content as $v) { if (is_dir($folders[$f] . '/' . $v) || $this->files || $this->filesOnly) { $countFiles++; } } $tid = md5($folders[$f]); $folderAttribute = 'style="margin-left:20px"'; $session[$node][$tid] = is_numeric($session[$node][$tid]) ? $session[$node][$tid] : 0; $currentFolder = str_replace(TL_ROOT . '/', '', $folders[$f]); $blnIsOpen = $session[$node][$tid] == 1 || count(preg_grep('/^' . preg_quote($currentFolder, '/') . '\\//', $this->varValue)) > 0; // Add a toggle button if there are childs if ($countFiles > 0) { $folderAttribute = ''; $img = $blnIsOpen ? 'folMinus.gif' : 'folPlus.gif'; $alt = $blnIsOpen ? $GLOBALS['TL_LANG']['MSC']['collapseNode'] : $GLOBALS['TL_LANG']['MSC']['expandNode']; $return .= '<a href="' . $this->addToUrl($flag . 'tg=' . $tid) . '" title="' . specialchars($alt) . '" onclick="return AjaxRequest.toggleFiletree(this,\'' . $xtnode . '_' . $tid . '\',\'' . $currentFolder . '\',\'' . $this->strField . '\',\'' . $this->strName . '\',' . $level . ')">' . \Image::getHtml($img, '', 'style="margin-right:2px"') . '</a>'; } $protected = $blnProtected; // Check whether the folder is public if ($protected === true && array_search('.public', $content) !== false) { $protected = false; } $folderImg = $blnIsOpen && $countFiles > 0 ? $protected ? 'folderOP.gif' : 'folderO.gif' : ($protected ? 'folderCP.gif' : 'folderC.gif'); $folderLabel = $this->files || $this->filesOnly ? '<strong>' . specialchars(basename($currentFolder)) . '</strong>' : specialchars(basename($currentFolder)); // Add the current folder $return .= \Image::getHtml($folderImg, '', $folderAttribute) . ' <a href="' . $this->addToUrl('node=' . $this->urlEncode($currentFolder)) . '" title="' . specialchars($GLOBALS['TL_LANG']['MSC']['selectNode']) . '">' . $folderLabel . '</a></div> <div class="tl_right">'; // Add a checkbox or radio button if (!$this->filesOnly) { switch ($this->fieldType) { case 'checkbox': $return .= '<input type="checkbox" name="' . $this->strName . '[]" id="' . $this->strName . '_' . md5($currentFolder) . '" class="tl_tree_checkbox" value="' . specialchars($currentFolder) . '" onfocus="Backend.getScrollOffset()"' . $this->optionChecked($currentFolder, $this->varValue) . '>'; break; case 'radio': $return .= '<input type="radio" name="' . $this->strName . '" id="' . $this->strName . '_' . md5($currentFolder) . '" class="tl_tree_radio" value="' . specialchars($currentFolder) . '" onfocus="Backend.getScrollOffset()"' . $this->optionChecked($currentFolder, $this->varValue) . '>'; break; } } $return .= '</div><div style="clear:both"></div></li>'; // Call the next node if ($countFiles > 0 && $blnIsOpen) { $return .= '<li class="parent" id="' . $xtnode . '_' . $tid . '"><ul class="level_' . $level . '">'; $return .= $this->renderFiletree($folders[$f], $intMargin + $intSpacing, false, $protected); $return .= '</ul></li>'; } } // Process files if ($this->files || $this->filesOnly) { $allowedExtensions = null; if ($this->extensions != '') { $allowedExtensions = trimsplit(',', $this->extensions); } for ($h = 0, $c = count($files); $h < $c; $h++) { $thumbnail = ''; $currentFile = str_replace(TL_ROOT . '/', '', $files[$h]); $currentEncoded = $this->urlEncode($currentFile); $objFile = new \File($currentFile); // Check file extension if (is_array($allowedExtensions) && !in_array($objFile->extension, $allowedExtensions)) { continue; } $return .= "\n " . '<li class="tl_file toggle_select" onmouseover="Theme.hoverDiv(this, 1)" onmouseout="Theme.hoverDiv(this, 0)"><div class="tl_left" style="padding-left:' . ($intMargin + $intSpacing) . 'px">'; // Generate thumbnail if ($objFile->isImage && $objFile->height > 0) { $thumbnail .= ' <span class="tl_gray">(' . $objFile->width . 'x' . $objFile->height . ')</span>'; if (\Config::get('thumbnails') && ($objFile->isSvgImage || $objFile->height <= \Config::get('gdMaxImgHeight') && $objFile->width <= \Config::get('gdMaxImgWidth'))) { $_height = $objFile->height < 50 ? $objFile->height : 50; $_width = $objFile->width * $_height / $objFile->height > 400 ? 90 : ''; $thumbnail .= '<br><img src="' . TL_FILES_URL . \Image::get($currentEncoded, $_width, $_height) . '" alt="" style="margin:0 0 2px -19px">'; } } $return .= \Image::getHtml($objFile->icon, $objFile->mime) . ' ' . utf8_convert_encoding(specialchars(basename($currentFile)), \Config::get('characterSet')) . $thumbnail . '</div> <div class="tl_right">'; // Add checkbox or radio button switch ($this->fieldType) { case 'checkbox': $return .= '<input type="checkbox" name="' . $this->strName . '[]" id="' . $this->strName . '_' . md5($currentFile) . '" class="tl_tree_checkbox" value="' . specialchars($currentFile) . '" onfocus="Backend.getScrollOffset()"' . $this->optionChecked($currentFile, $this->varValue) . '>'; break; case 'radio': $return .= '<input type="radio" name="' . $this->strName . '" id="' . $this->strName . '_' . md5($currentFile) . '" class="tl_tree_radio" value="' . specialchars($currentFile) . '" onfocus="Backend.getScrollOffset()"' . $this->optionChecked($currentFile, $this->varValue) . '>'; break; } $return .= '</div><div style="clear:both"></div></li>'; } } return $return; }
/** * Generate the widget and return it as string * * @return string */ public function generate() { $arrOptions = array(); if (!$this->multiple && count($this->arrOptions) > 1) { $this->arrOptions = array($this->arrOptions[0]); } // The "required" attribute only makes sense for single checkboxes if ($this->mandatory && !$this->multiple) { $this->arrAttributes['required'] = 'required'; } /** @var AttributeBagInterface $objSessionBag */ $objSessionBag = \System::getContainer()->get('session')->getBag('contao_backend'); $state = $objSessionBag->get('checkbox_groups'); // Toggle the checkbox group if (\Input::get('cbc')) { $state[\Input::get('cbc')] = isset($state[\Input::get('cbc')]) && $state[\Input::get('cbc')] == 1 ? 0 : 1; $objSessionBag->set('checkbox_groups', $state); $this->redirect(preg_replace('/(&(amp;)?|\\?)cbc=[^& ]*/i', '', \Environment::get('request'))); } $blnFirst = true; $blnCheckAll = true; foreach ($this->arrOptions as $i => $arrOption) { // Single dimension array if (is_numeric($i)) { $arrOptions[] = $this->generateCheckbox($arrOption, $i); continue; } $id = 'cbc_' . $this->strId . '_' . \StringUtil::standardize($i); $img = 'folPlus.svg'; $display = 'none'; if (!isset($state[$id]) || !empty($state[$id])) { $img = 'folMinus.svg'; $display = 'block'; } $arrOptions[] = '<div class="checkbox_toggler' . ($blnFirst ? '_first' : '') . '"><a href="' . $this->addToUrl('cbc=' . $id) . '" onclick="AjaxRequest.toggleCheckboxGroup(this,\'' . $id . '\');Backend.getScrollOffset();return false">' . \Image::getHtml($img) . '</a>' . $i . '</div><fieldset id="' . $id . '" class="tl_checkbox_container checkbox_options" style="display:' . $display . '"><input type="checkbox" id="check_all_' . $id . '" class="tl_checkbox" onclick="Backend.toggleCheckboxGroup(this, \'' . $id . '\')"> <label for="check_all_' . $id . '" style="color:#a6a6a6"><em>' . $GLOBALS['TL_LANG']['MSC']['selectAll'] . '</em></label>'; // Multidimensional array foreach ($arrOption as $k => $v) { $arrOptions[] = $this->generateCheckbox($v, standardize($i) . '_' . $k); } $arrOptions[] = '</fieldset>'; $blnFirst = false; $blnCheckAll = false; } // Add a "no entries found" message if there are no options if (empty($arrOptions)) { $arrOptions[] = '<p class="tl_noopt">' . $GLOBALS['TL_LANG']['MSC']['noResult'] . '</p>'; $blnCheckAll = false; } if ($this->multiple) { return sprintf('<fieldset id="ctrl_%s" class="tl_checkbox_container%s"><legend>%s%s%s%s</legend><input type="hidden" name="%s" value="">%s%s</fieldset>%s', $this->strId, $this->strClass != '' ? ' ' . $this->strClass : '', $this->mandatory ? '<span class="invisible">' . $GLOBALS['TL_LANG']['MSC']['mandatory'] . ' </span>' : '', $this->strLabel, $this->mandatory ? '<span class="mandatory">*</span>' : '', $this->xlabel, $this->strName, $blnCheckAll ? '<input type="checkbox" id="check_all_' . $this->strId . '" class="tl_checkbox" onclick="Backend.toggleCheckboxGroup(this,\'ctrl_' . $this->strId . '\')' . ($this->onclick ? ';' . $this->onclick : '') . '"> <label for="check_all_' . $this->strId . '" style="color:#a6a6a6"><em>' . $GLOBALS['TL_LANG']['MSC']['selectAll'] . '</em></label><br>' : '', str_replace('<br></fieldset><br>', '</fieldset>', implode('<br>', $arrOptions)), $this->wizard); } else { return sprintf('<div id="ctrl_%s" class="tl_checkbox_single_container%s"><input type="hidden" name="%s" value="">%s</div>%s', $this->strId, $this->strClass != '' ? ' ' . $this->strClass : '', $this->strName, str_replace('<br></div><br>', '</div>', implode('<br>', $arrOptions)), $this->wizard); } }
/** * Add a breadcrumb menu to the file tree * * @param string $strKey * * @throws AccessDeniedException * @throws \RuntimeException */ public static function addFilesBreadcrumb($strKey = 'tl_files_node') { /** @var AttributeBagInterface $objSession */ $objSession = \System::getContainer()->get('session')->getBag('contao_backend'); // Set a new node if (isset($_GET['fn'])) { // Check the path (thanks to Arnaud Buchoux) if (\Validator::isInsecurePath(\Input::get('fn', true))) { throw new \RuntimeException('Insecure path ' . \Input::get('fn', true)); } $objSession->set($strKey, \Input::get('fn', true)); \Controller::redirect(preg_replace('/(&|\\?)fn=[^&]*/', '', \Environment::get('request'))); } $strNode = $objSession->get($strKey); if ($strNode == '') { return; } // Check the path (thanks to Arnaud Buchoux) if (\Validator::isInsecurePath($strNode)) { throw new \RuntimeException('Insecure path ' . $strNode); } // Currently selected folder does not exist if (!is_dir(TL_ROOT . '/' . $strNode)) { $objSession->set($strKey, ''); return; } $objUser = \BackendUser::getInstance(); $strPath = \Config::get('uploadPath'); $arrNodes = explode('/', preg_replace('/^' . preg_quote(\Config::get('uploadPath'), '/') . '\\//', '', $strNode)); $arrLinks = array(); // Add root link $arrLinks[] = \Image::getHtml('filemounts.svg') . ' <a href="' . \Backend::addToUrl('fn=') . '" title="' . \StringUtil::specialchars($GLOBALS['TL_LANG']['MSC']['selectAllNodes']) . '">' . $GLOBALS['TL_LANG']['MSC']['filterAll'] . '</a>'; // Generate breadcrumb trail foreach ($arrNodes as $strFolder) { $strPath .= '/' . $strFolder; // Do not show pages which are not mounted if (!$objUser->hasAccess($strPath, 'filemounts')) { continue; } // No link for the active folder if ($strPath == $strNode) { $arrLinks[] = \Image::getHtml('folderC.svg') . ' ' . $strFolder; } else { $arrLinks[] = \Image::getHtml('folderC.svg') . ' <a href="' . \Backend::addToUrl('fn=' . $strPath) . '" title="' . \StringUtil::specialchars($GLOBALS['TL_LANG']['MSC']['selectNode']) . '">' . $strFolder . '</a>'; } } // Check whether the node is mounted if (!$objUser->hasAccess($strNode, 'filemounts')) { $objSession->set($strKey, ''); throw new AccessDeniedException('Folder ID "' . $strNode . '" is not mounted'); } // Limit tree $GLOBALS['TL_DCA']['tl_files']['list']['sorting']['root'] = array($strNode); // Insert breadcrumb menu $GLOBALS['TL_DCA']['tl_files']['list']['sorting']['breadcrumb'] .= ' <ul id="tl_breadcrumb"> <li>' . implode(' > </li><li>', $arrLinks) . '</li> </ul>'; }
/** * Render the file tree and return it as HTML string * * @param string $path * @param integer $intMargin * @param boolean $mount * @param boolean $blnProtected * @param array $arrClipboard * @param array $arrFound * * @return string */ protected function generateTree($path, $intMargin, $mount = false, $blnProtected = true, $arrClipboard = null, $arrFound = array()) { static $session; /** @var AttributeBagInterface $objSessionBag */ $objSessionBag = \System::getContainer()->get('session')->getBag('contao_backend'); $session = $objSessionBag->all(); // Get the session data and toggle the nodes if (\Input::get('tg')) { $session['filetree'][\Input::get('tg')] = isset($session['filetree'][\Input::get('tg')]) && $session['filetree'][\Input::get('tg')] == 1 ? 0 : 1; $objSessionBag->replace($session); $this->redirect(preg_replace('/(&(amp;)?|\\?)tg=[^& ]*/i', '', \Environment::get('request'))); } $return = ''; $files = array(); $folders = array(); $intSpacing = 20; $level = $intMargin / $intSpacing + 1; // Mount folder if ($mount) { $folders = array($path); } else { foreach (scan($path) as $v) { if (strncmp($v, '.', 1) === 0) { continue; } if (is_file($path . '/' . $v)) { $files[] = $path . '/' . $v; } else { if ($v == '__new__') { $this->Files->rmdir(str_replace(TL_ROOT . '/', '', $path) . '/' . $v); } else { $folders[] = $path . '/' . $v; } } } natcasesort($folders); $folders = array_values($folders); natcasesort($files); $files = array_values($files); } // Folders for ($f = 0, $c = count($folders); $f < $c; $f++) { $md5 = substr(md5($folders[$f]), 0, 8); $content = scan($folders[$f]); $currentFolder = str_replace(TL_ROOT . '/', '', $folders[$f]); $session['filetree'][$md5] = is_numeric($session['filetree'][$md5]) ? $session['filetree'][$md5] : 0; $currentEncoded = $this->urlEncode($currentFolder); $countFiles = count($content); // Subtract files that will not be shown foreach ($content as $file) { if (strncmp($file, '.', 1) === 0) { --$countFiles; } elseif (!empty($arrFound) && !in_array($currentFolder . '/' . $file, $arrFound) && !preg_grep('/^' . preg_quote($currentFolder . '/' . $file, '/') . '\\//', $arrFound)) { --$countFiles; } } if (!empty($arrFound) && $countFiles < 1 && !in_array($currentFolder, $arrFound)) { continue; } $return .= "\n " . '<li class="tl_folder click2edit toggle_select hover-div"><div class="tl_left" style="padding-left:' . ($intMargin + ($countFiles < 1 ? 20 : 0)) . 'px">'; // Add a toggle button if there are childs if ($countFiles > 0) { $img = !empty($arrFound) || $session['filetree'][$md5] == 1 ? 'folMinus.gif' : 'folPlus.gif'; $alt = !empty($arrFound) || $session['filetree'][$md5] == 1 ? $GLOBALS['TL_LANG']['MSC']['collapseNode'] : $GLOBALS['TL_LANG']['MSC']['expandNode']; $return .= '<a href="' . $this->addToUrl('tg=' . $md5) . '" title="' . specialchars($alt) . '" onclick="Backend.getScrollOffset(); return AjaxRequest.toggleFileManager(this, \'filetree_' . $md5 . '\', \'' . $currentFolder . '\', ' . $level . ')">' . \Image::getHtml($img, '', 'style="margin-right:2px"') . '</a>'; } $protected = $blnProtected; // Check whether the folder is public if ($protected === true && array_search('.public', $content) !== false) { $protected = false; } $folderImg = $protected ? 'folderCP.gif' : 'folderC.gif'; // Add the current folder $strFolderNameEncoded = \StringUtil::convertEncoding(specialchars(basename($currentFolder)), \Config::get('characterSet')); $return .= \Image::getHtml($folderImg, '') . ' <a href="' . $this->addToUrl('node=' . $currentEncoded) . '" title="' . specialchars($GLOBALS['TL_LANG']['MSC']['selectNode']) . '"><strong>' . $strFolderNameEncoded . '</strong></a></div> <div class="tl_right">'; // Paste buttons if ($arrClipboard !== false && \Input::get('act') != 'select') { $imagePasteInto = \Image::getHtml('pasteinto.gif', $GLOBALS['TL_LANG'][$this->strTable]['pasteinto'][0]); $return .= ($arrClipboard['mode'] == 'cut' || $arrClipboard['mode'] == 'copy') && preg_match('/^' . preg_quote($arrClipboard['id'], '/') . '/i', $currentFolder) ? \Image::getHtml('pasteinto_.gif') : '<a href="' . $this->addToUrl('act=' . $arrClipboard['mode'] . '&mode=2&pid=' . $currentEncoded . (!is_array($arrClipboard['id']) ? '&id=' . $arrClipboard['id'] : '')) . '" title="' . specialchars($GLOBALS['TL_LANG'][$this->strTable]['pasteinto'][1]) . '" onclick="Backend.getScrollOffset()">' . $imagePasteInto . '</a> '; } else { // Do not display buttons for mounted folders if ($this->User->isAdmin || !in_array($currentFolder, $this->User->filemounts)) { $return .= \Input::get('act') == 'select' ? '<input type="checkbox" name="IDS[]" id="ids_' . md5($currentEncoded) . '" class="tl_tree_checkbox" value="' . $currentEncoded . '">' : $this->generateButtons(array('id' => $currentEncoded, 'popupWidth' => 600, 'popupHeight' => 123, 'fileNameEncoded' => $strFolderNameEncoded), $this->strTable); } // Upload button if (!$GLOBALS['TL_DCA'][$this->strTable]['config']['closed'] && !$GLOBALS['TL_DCA'][$this->strTable]['config']['notCreatable'] && \Input::get('act') != 'select') { $return .= ' <a href="' . $this->addToUrl('&act=move&mode=2&pid=' . $currentEncoded) . '" title="' . specialchars(sprintf($GLOBALS['TL_LANG']['tl_files']['uploadFF'], $currentEncoded)) . '">' . \Image::getHtml('new.gif', $GLOBALS['TL_LANG'][$this->strTable]['move'][0]) . '</a>'; } } $return .= '</div><div style="clear:both"></div></li>'; // Call the next node if (!empty($content) && (!empty($arrFound) || $session['filetree'][$md5] == 1)) { $return .= '<li class="parent" id="filetree_' . $md5 . '"><ul class="level_' . $level . '">'; $return .= $this->generateTree($folders[$f], $intMargin + $intSpacing, false, $protected, $arrClipboard, $arrFound); $return .= '</ul></li>'; } } // Process files for ($h = 0, $c = count($files); $h < $c; $h++) { $thumbnail = ''; $popupWidth = 600; $popupHeight = 161; $currentFile = str_replace(TL_ROOT . '/', '', $files[$h]); $objFile = new \File($currentFile); if (!empty($this->arrValidFileTypes) && !in_array($objFile->extension, $this->arrValidFileTypes)) { continue; } // Ignore files not matching the search criteria if (!empty($arrFound) && !in_array($currentFile, $arrFound)) { continue; } $currentEncoded = $this->urlEncode($currentFile); $return .= "\n " . '<li class="tl_file click2edit toggle_select hover-div"><div class="tl_left" style="padding-left:' . ($intMargin + $intSpacing) . 'px">'; // Generate the thumbnail if ($objFile->isImage) { if ($objFile->viewHeight > 0) { if ($objFile->width && $objFile->height) { $popupWidth = $objFile->width > 600 ? $objFile->width + 61 : 661; $popupHeight = $objFile->height + 210; } else { $popupWidth = 661; $popupHeight = 625 / $objFile->viewWidth * $objFile->viewHeight + 210; } $thumbnail .= ' <span class="tl_gray">(' . $this->getReadableSize($objFile->filesize); if ($objFile->width && $objFile->height) { $thumbnail .= ', ' . $objFile->width . 'x' . $objFile->height . ' px'; } $thumbnail .= ')</span>'; if (\Config::get('thumbnails') && ($objFile->isSvgImage || $objFile->height <= \Config::get('gdMaxImgHeight') && $objFile->width <= \Config::get('gdMaxImgWidth'))) { $imageObj = \Image::create($currentEncoded, array(400, $objFile->height && $objFile->height < 50 ? $objFile->height : 50, 'box')); $importantPart = $imageObj->getImportantPart(); $thumbnail .= '<br><img src="' . TL_FILES_URL . $imageObj->executeResize()->getResizedPath() . '" alt="" style="margin:0 0 2px -19px">'; if ($importantPart['x'] > 0 || $importantPart['y'] > 0 || $importantPart['width'] < $objFile->width || $importantPart['height'] < $objFile->height) { $thumbnail .= ' <img src="' . TL_FILES_URL . $imageObj->setZoomLevel(100)->setTargetWidth(320)->setTargetHeight($objFile->height && $objFile->height < 40 ? $objFile->height : 40)->executeResize()->getResizedPath() . '" alt="" style="margin:0 0 2px 0">'; } } } else { $popupHeight = 360; // dimensionless SVGs are rendered at 300x150px, so the popup needs to be 150px + 210px high } } else { $thumbnail .= ' <span class="tl_gray">(' . $this->getReadableSize($objFile->filesize) . ')</span>'; } $strFileNameEncoded = \StringUtil::convertEncoding(specialchars(basename($currentFile)), \Config::get('characterSet')); // No popup links for templates and in the popup file manager if ($this->strTable == 'tl_templates' || \Input::get('popup')) { $return .= \Image::getHtml($objFile->icon) . ' ' . $strFileNameEncoded . $thumbnail . '</div> <div class="tl_right">'; } else { $return .= '<a href="' . $currentEncoded . '" title="' . specialchars($GLOBALS['TL_LANG']['MSC']['view']) . '" target="_blank">' . \Image::getHtml($objFile->icon, $objFile->mime) . '</a> ' . $strFileNameEncoded . $thumbnail . '</div> <div class="tl_right">'; } // Buttons if ($arrClipboard !== false && \Input::get('act') != 'select') { $_buttons = ' '; } else { $_buttons = \Input::get('act') == 'select' ? '<input type="checkbox" name="IDS[]" id="ids_' . md5($currentEncoded) . '" class="tl_tree_checkbox" value="' . $currentEncoded . '">' : $this->generateButtons(array('id' => $currentEncoded, 'popupWidth' => $popupWidth, 'popupHeight' => $popupHeight, 'fileNameEncoded' => $strFileNameEncoded), $this->strTable); } $return .= $_buttons . '</div><div style="clear:both"></div></li>'; } return $return; }
/** * Recursively render the filetree * * @param string $path * @param integer $intMargin * @param boolean $mount * @param boolean $blnProtected * @param array $arrFound * * @return string */ protected function renderFiletree($path, $intMargin, $mount = false, $blnProtected = true, $arrFound = array()) { // Invalid path if (!is_dir($path)) { return ''; } // Make sure that $this->varValue is an array (see #3369) if (!is_array($this->varValue)) { $this->varValue = array($this->varValue); } static $session; /** @var AttributeBagInterface $objSessionBag */ $objSessionBag = \System::getContainer()->get('session')->getBag('contao_backend'); $session = $objSessionBag->all(); $flag = substr($this->strField, 0, 2); $node = 'tree_' . $this->strTable . '_' . $this->strField; $xtnode = 'tree_' . $this->strTable . '_' . $this->strName; // Get session data and toggle nodes if (\Input::get($flag . 'tg')) { $session[$node][\Input::get($flag . 'tg')] = isset($session[$node][\Input::get($flag . 'tg')]) && $session[$node][\Input::get($flag . 'tg')] == 1 ? 0 : 1; $objSessionBag->replace($session); $this->redirect(preg_replace('/(&(amp;)?|\\?)' . $flag . 'tg=[^& ]*/i', '', \Environment::get('request'))); } $return = ''; $intSpacing = 20; $files = array(); $folders = array(); $level = $intMargin / $intSpacing + 1; // Mount folder if ($mount) { $folders = array($path); } else { foreach (scan($path) as $v) { if (strncmp($v, '.', 1) === 0) { continue; } if (is_dir($path . '/' . $v)) { $folders[] = $path . '/' . $v; } else { $files[] = $path . '/' . $v; } } } natcasesort($folders); $folders = array_values($folders); natcasesort($files); $files = array_values($files); // Sort descending (see #4072) if ($this->sort == 'desc') { $folders = array_reverse($folders); $files = array_reverse($files); } $folderClass = $this->files || $this->filesOnly ? 'tl_folder' : 'tl_file'; // Process folders for ($f = 0, $c = count($folders); $f < $c; $f++) { $content = scan($folders[$f]); $currentFolder = str_replace(TL_ROOT . '/', '', $folders[$f]); $countFiles = count($content); // Check whether there are subfolders or files foreach ($content as $file) { if (strncmp($file, '.', 1) === 0) { --$countFiles; } elseif (!$this->files && !$this->filesOnly && is_file($folders[$f] . '/' . $file)) { --$countFiles; } elseif (!empty($arrFound) && !in_array($currentFolder . '/' . $file, $arrFound) && !preg_grep('/^' . preg_quote($currentFolder . '/' . $file, '/') . '\\//', $arrFound)) { --$countFiles; } } if (!empty($arrFound) && $countFiles < 1 && !in_array($currentFolder, $arrFound)) { continue; } $tid = md5($folders[$f]); $folderAttribute = 'style="margin-left:20px"'; $session[$node][$tid] = is_numeric($session[$node][$tid]) ? $session[$node][$tid] : 0; $currentFolder = str_replace(TL_ROOT . '/', '', $folders[$f]); $blnIsOpen = !empty($arrFound) || $session[$node][$tid] == 1 || count(preg_grep('/^' . preg_quote($currentFolder, '/') . '\\//', $this->varValue)) > 0; $return .= "\n " . '<li class="' . $folderClass . ' toggle_select hover-div"><div class="tl_left" style="padding-left:' . $intMargin . 'px">'; // Add a toggle button if there are childs if ($countFiles > 0) { $folderAttribute = ''; $img = $blnIsOpen ? 'folMinus.svg' : 'folPlus.svg'; $alt = $blnIsOpen ? $GLOBALS['TL_LANG']['MSC']['collapseNode'] : $GLOBALS['TL_LANG']['MSC']['expandNode']; $return .= '<a href="' . \Backend::addToUrl($flag . 'tg=' . $tid) . '" title="' . \StringUtil::specialchars($alt) . '" onclick="return AjaxRequest.toggleFiletree(this,\'' . $xtnode . '_' . $tid . '\',\'' . $currentFolder . '\',\'' . $this->strField . '\',\'' . $this->strName . '\',' . $level . ')">' . \Image::getHtml($img, '', 'style="margin-right:2px"') . '</a>'; } $protected = $blnProtected; // Check whether the folder is public if ($protected === true && array_search('.public', $content) !== false) { $protected = false; } $folderImg = $protected ? 'folderCP.svg' : 'folderC.svg'; $folderLabel = $this->files || $this->filesOnly ? '<strong>' . \StringUtil::specialchars(basename($currentFolder)) . '</strong>' : \StringUtil::specialchars(basename($currentFolder)); // Add the current folder $return .= \Image::getHtml($folderImg, '', $folderAttribute) . ' <a href="' . \Backend::addToUrl('fn=' . $this->urlEncode($currentFolder)) . '" title="' . \StringUtil::specialchars($GLOBALS['TL_LANG']['MSC']['selectNode']) . '">' . $folderLabel . '</a></div> <div class="tl_right">'; // Add a checkbox or radio button if (!$this->filesOnly) { switch ($this->fieldType) { case 'checkbox': $return .= '<input type="checkbox" name="' . $this->strName . '[]" id="' . $this->strName . '_' . md5($currentFolder) . '" class="tl_tree_checkbox" value="' . \StringUtil::specialchars($currentFolder) . '" onfocus="Backend.getScrollOffset()"' . $this->optionChecked($currentFolder, $this->varValue) . '>'; break; case 'radio': $return .= '<input type="radio" name="' . $this->strName . '" id="' . $this->strName . '_' . md5($currentFolder) . '" class="tl_tree_radio" value="' . \StringUtil::specialchars($currentFolder) . '" onfocus="Backend.getScrollOffset()"' . $this->optionChecked($currentFolder, $this->varValue) . '>'; break; } } $return .= '</div><div style="clear:both"></div></li>'; // Call the next node if ($blnIsOpen) { $return .= '<li class="parent" id="' . $xtnode . '_' . $tid . '"><ul class="level_' . $level . '">'; $return .= $this->renderFiletree($folders[$f], $intMargin + $intSpacing, false, $protected, $arrFound); $return .= '</ul></li>'; } } // Process files if ($this->files || $this->filesOnly) { for ($h = 0, $c = count($files); $h < $c; $h++) { $thumbnail = ''; $currentFile = str_replace(TL_ROOT . '/', '', $files[$h]); $currentEncoded = $this->urlEncode($currentFile); $objFile = new \File($currentFile); if (!empty($this->arrValidFileTypes) && !in_array($objFile->extension, $this->arrValidFileTypes)) { continue; } // Ignore files not matching the search criteria if (!empty($arrFound) && !in_array($currentFile, $arrFound)) { continue; } $return .= "\n " . '<li class="tl_file toggle_select hover-div"><div class="tl_left" style="padding-left:' . ($intMargin + $intSpacing) . 'px">'; $thumbnail .= ' <span class="tl_gray">(' . $this->getReadableSize($objFile->filesize); if ($objFile->width && $objFile->height) { $thumbnail .= ', ' . $objFile->width . 'x' . $objFile->height . ' px'; } $thumbnail .= ')</span>'; // Generate thumbnail if ($objFile->isImage && $objFile->viewHeight > 0 && \Config::get('thumbnails') && ($objFile->isSvgImage || $objFile->height <= \Config::get('gdMaxImgHeight') && $objFile->width <= \Config::get('gdMaxImgWidth'))) { $imageObj = \Image::create($currentEncoded, array(400, $objFile->height && $objFile->height < 50 ? $objFile->height : 50, 'box')); $importantPart = $imageObj->getImportantPart(); $thumbnail .= '<br>' . \Image::getHtml($imageObj->executeResize()->getResizedPath(), '', 'style="margin:0 0 2px -19px"'); if ($importantPart['x'] > 0 || $importantPart['y'] > 0 || $importantPart['width'] < $objFile->width || $importantPart['height'] < $objFile->height) { $thumbnail .= ' ' . \Image::getHtml($imageObj->setZoomLevel(100)->setTargetWidth(320)->setTargetHeight($objFile->height && $objFile->height < 40 ? $objFile->height : 40)->executeResize()->getResizedPath(), '', 'style="margin:0 0 2px 0;vertical-align:bottom"'); } } $return .= \Image::getHtml($objFile->icon, $objFile->mime) . ' ' . \StringUtil::convertEncoding(\StringUtil::specialchars(basename($currentFile)), \Config::get('characterSet')) . $thumbnail . '</div> <div class="tl_right">'; // Add checkbox or radio button switch ($this->fieldType) { case 'checkbox': $return .= '<input type="checkbox" name="' . $this->strName . '[]" id="' . $this->strName . '_' . md5($currentFile) . '" class="tl_tree_checkbox" value="' . \StringUtil::specialchars($currentFile) . '" onfocus="Backend.getScrollOffset()"' . $this->optionChecked($currentFile, $this->varValue) . '>'; break; case 'radio': $return .= '<input type="radio" name="' . $this->strName . '" id="' . $this->strName . '_' . md5($currentFile) . '" class="tl_tree_radio" value="' . \StringUtil::specialchars($currentFile) . '" onfocus="Backend.getScrollOffset()"' . $this->optionChecked($currentFile, $this->varValue) . '>'; break; } $return .= '</div><div style="clear:both"></div></li>'; } } return $return; }
/** * 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 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="' . \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' && !$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 ? '&mode=2' : '') . '&pid=' . $this->intId) : $this->addToUrl('act=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> ' : '') . $this->generateGlobalButtons() . ' </div>' . \Message::generate(); } // 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"></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(\StringUtil::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 = \StringUtil::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 hover-row"> '; $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 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']['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']['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; }
/** * Get modal show button. * * @param $newsId * * @return string */ protected function getModalShowButton($newsId, $translator) { $urlParams = array(array('name' => 'act', 'value' => 'show'), array('name' => 'table', 'value' => 'tl_news'), array('name' => 'id', 'value' => $newsId), array('name' => 'popup', 'value' => 1)); $label = $translator->translate('show.1', 'tl_news'); return '<a ' . 'href="' . self::getBackendUrl($urlParams) . '" ' . 'title="' . self::getTitle($label, $newsId) . '" ' . 'onclick="' . self::getOnClickModal($label, $newsId) . '" ' . 'class="edit">' . Image::getHtml('show.gif', $translator->translate('show.0', 'tl_news')) . '</a> '; }
/** * @param $arrRow * @param $admin * @param $permArr * @return string */ public function createButtons($arrRow) { $strTable = $arrRow['dca']; $this->loadDataContainer($strTable); if (empty($GLOBALS['TL_DCA'][$strTable]['list']['operations'])) { return ''; } $return = ''; $operations = $GLOBALS['TL_DCA'][$strTable]['list']['operations']; $mode = $GLOBALS['TL_DCA'][$strTable]['list']['sorting']['mode']; $id = specialchars(rawurldecode($arrRow['docId'])); $id = $id ? '&id=' . $id : ''; $fmTable = substr($arrRow['dca'], 0, 2); //$pid = $arrRow['pid'] ? '&pid='.$arrRow['pid'] : ''; $table = $arrRow['dca'] ? '&table=' . $arrRow['dca'] : ''; if ($operations['editheader'] || $operations['edit']) { $href = 'act=edit'; $queryStr = $href . $id . $table; $tagsStr = ''; if ($arrRow['dca'] != 'tl_files') { $tagsStr = '[' . $arrRow['docId'] . ']'; } if ($arrRow['tags']) { $tags = explode(',', $arrRow['tags']); foreach ($tags as $tag) { $tagsStr .= '<span class="ps_tag">' . $tag . '</span>'; } } $title = strlen($arrRow['title']) > 100 ? substr($arrRow['title'], 0, 100) . '…' : $arrRow['title']; $arrRow['dynTable'] = null; // reset dyntable if not needed $return .= '<div class="title"><span class="icon">' . $arrRow['icon'] . '</span><a href="' . $this->addToSearchUrl($arrRow, $queryStr) . '" class="search-result" tabindex="1" onclick="Backend.openModalIframe({\'width\':960,\'title\':\'' . $arrRow['title'] . '\',\'url\':this.href});return false"><span>' . mb_convert_encoding($title, 'UTF-8') . '</span> <span class="info">' . $tagsStr . '</span></a></div>'; } $return .= '<div class="operations">'; // if has childs go to overview $ctableArr = deserialize($arrRow['ctable']); $mode = $mode ? $mode : 5; if (is_array($ctableArr) && !empty($ctableArr) && $mode != 5 && $fmTable != 'fm') { $href = ''; $icon = ''; $ptable = ''; $arrRow['dynTable'] = null; foreach ($ctableArr as $ctable) { $href = '&table=' . $ctable . ''; $icon = 'edit.gif'; $ptable = ''; } $queryStr = $href . $id . $ptable; $return .= '<a href="' . $this->addToSearchUrl($arrRow, $queryStr) . '" tabindex="1">' . Image::getHtml($icon, $arrRow['title']) . '</a>'; } // go to ietm if ($operations['editheader'] || $operations['edit']) { $href = 'act=edit'; $icon = 'header.gif'; $ptable = $table; $arrRow['dynTable'] = null; // reset dyntable if not needed $queryStr = $href . $id . $ptable; $return .= '<a href="' . $this->addToSearchUrl($arrRow, $queryStr) . '" tabindex="1">' . Image::getHtml($icon, $arrRow['title']) . '</a>'; } if ($fmTable == 'fm') { // list view $href = '&table=tl_content'; $fmType = '&view=list'; $icon = $GLOBALS['PS_PUBLIC_PATH'] . 'images/page.png'; $queryStr = $href . $fmType . $id; $arrRow['dynTable'] = null; $return .= '<a href="' . $this->addToSearchUrl($arrRow, $queryStr) . '" tabindex="1">' . Image::getHtml($icon, $arrRow['title']) . '</a>'; //detailview $icon = $GLOBALS['PS_PUBLIC_PATH'] . 'images/detail.png'; $fmType = '&view=detail'; $queryStr = $href . $fmType . $id; $return .= '<a href="' . $this->addToSearchUrl($arrRow, $queryStr) . '" tabindex="1">' . Image::getHtml($icon, $arrRow['title']) . '</a>'; } if ($arrRow['doTable'] == 'page') { $pageID = $arrRow['docId']; // page node $pageNodeQueryStr = 'node=' . $pageID; $dca['dynTable'] = null; // reset dyntable if not needed $icon = $arrRow['icon']; $return .= '<a href="' . $this->addToSearchUrl($arrRow, $pageNodeQueryStr) . '" tabindex="1">' . $icon . '</a>'; // article node $articleNodeQueryStr = 'node=' . $pageID; $arrRow['dynTable'] = 'article'; $icon = 'article.gif'; $return .= '<a href="' . $this->addToSearchUrl($arrRow, $articleNodeQueryStr) . '" tabindex="1">' . Image::getHtml($icon, $arrRow['title']) . '</a>'; // Open Frontend Page if ($arrRow['type'] == 'regular') { $feQueryStr = 'page=' . $pageID; $arrRow['dynTable'] = 'feRedirect'; $icon = 'preview.gif'; $return .= '<a href="' . $this->addToSearchUrl($arrRow, $feQueryStr) . '" target="_blank" tabindex="1">' . Image::getHtml($icon, $arrRow['title']) . '</a>'; } } if ($arrRow['dca'] == 'tl_files' && in_array($arrRow['extension'], $GLOBALS['PS_EDITABLE_FILES'])) { $href = 'act=source'; $queryStr = $href . $id; $icon = 'editor.gif'; $return .= '<a href="' . $this->addToSearchUrl($arrRow, $queryStr) . '" tabindex="1">' . Image::getHtml($icon, $arrRow['title']) . '</a>'; } // show if ($operations['show'] && $arrRow['dca'] != 'tl_files') { $href = 'act=show'; $icon = 'show.gif'; $arrRow['dynTable'] = null; // reset dyntable if not needed $attributes = $operations['show']['attributes'] != '' ? ' ' . ltrim(sprintf($operations['show']['attributes'], $id, $id)) : ''; $queryStr = $href . $id . $table . '&popup=1'; $return .= '<a href="' . $this->addToSearchUrl($arrRow, $queryStr) . '" tabindex="1" onclick="Backend.openModalIframe({\'width\':768,\'title\':\'' . specialchars(str_replace("'", "\\'", sprintf($arrRow['title'], $arrRow['docId']))) . '\',\'url\':this.href});return false"' . $attributes . '>' . Image::getHtml($icon) . '</a> '; } if ($operations['show'] && $arrRow['dca'] == 'tl_files') { $href = 'contao/popup.php?src=' . base64_encode($arrRow['docId']) . ''; $icon = 'show.gif'; $arrRow['dynTable'] = null; // reset dyntable if not needed //$attributes = ($operations['show']['attributes'] != '') ? ' ' . ltrim(sprintf($operations['show']['attributes'], $id, $id)) : ''; $return .= '<a href="' . $href . '" tabindex="1" onclick="Backend.openModalIframe({\'width\':768,\'title\':\'' . str_replace("'", "\\'", specialchars($arrRow['title'], false, true)) . '\',\'url\':this.href,\'height\':500});return false" >' . Image::getHtml($icon) . '</a>'; } $return .= '</div>'; return trim($return); }