core-bundle/src/Resources/contao/widgets/FileSelector.php
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);
		}

		/** @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);
		}

		// Scan directory and sort the result
		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 = StringUtil::stripRootDir($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 = StringUtil::stripRootDir($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 && \in_array('.public', $content))
			{
				$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;

					default:
					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 = StringUtil::stripRootDir($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'))))
				{
					$rootDir = System::getContainer()->getParameter('kernel.project_dir');
					$thumbnail .= '<br>' . Image::getHtml(System::getContainer()->get('contao.image.image_factory')->create($rootDir . '/' . rawurldecode($currentEncoded), array(100, 75, ResizeConfiguration::MODE_BOX))->getUrl($rootDir), '', 'style="margin:0 0 2px -18px"');
					$importantPart = System::getContainer()->get('contao.image.image_factory')->create($rootDir . '/' . rawurldecode($currentEncoded))->getImportantPart();

					if ($importantPart->getPosition()->getX() > 0 || $importantPart->getPosition()->getY() > 0 || $importantPart->getSize()->getWidth() < $objFile->width || $importantPart->getSize()->getHeight() < $objFile->height)
					{
						$thumbnail .= ' ' . Image::getHtml(System::getContainer()->get('contao.image.image_factory')->create($rootDir . '/' . rawurldecode($currentEncoded), (new ResizeConfiguration())->setWidth(80)->setHeight(60)->setMode(ResizeConfiguration::MODE_BOX)->setZoomLevel(100))->getUrl($rootDir), '', '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;

					default:
					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;
	}
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);
		}

		/** @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);
		}

		// Scan directory and sort the result
		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 = StringUtil::stripRootDir($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 = StringUtil::stripRootDir($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 && \in_array('.public', $content))
			{
				$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;

					default:
					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 = StringUtil::stripRootDir($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'))))
				{
					$rootDir = System::getContainer()->getParameter('kernel.project_dir');
					$thumbnail .= '<br>' . Image::getHtml(System::getContainer()->get('contao.image.image_factory')->create($rootDir . '/' . rawurldecode($currentEncoded), array(100, 75, ResizeConfiguration::MODE_BOX))->getUrl($rootDir), '', 'style="margin:0 0 2px -18px"');
					$importantPart = System::getContainer()->get('contao.image.image_factory')->create($rootDir . '/' . rawurldecode($currentEncoded))->getImportantPart();

					if ($importantPart->getPosition()->getX() > 0 || $importantPart->getPosition()->getY() > 0 || $importantPart->getSize()->getWidth() < $objFile->width || $importantPart->getSize()->getHeight() < $objFile->height)
					{
						$thumbnail .= ' ' . Image::getHtml(System::getContainer()->get('contao.image.image_factory')->create($rootDir . '/' . rawurldecode($currentEncoded), (new ResizeConfiguration())->setWidth(80)->setHeight(60)->setMode(ResizeConfiguration::MODE_BOX)->setZoomLevel(100))->getUrl($rootDir), '', '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;

					default:
					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;
	}
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 ) ; } /** @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 ) ; } // Scan directory and sort the result 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 = StringUtil :: stripRootDir ( $ 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 = StringUtil :: stripRootDir ( $ 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 && \ in_array ( '.public' , $ content ) ) { $ 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 ; default : 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 = StringUtil :: stripRootDir ( $ 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' ) ) ) ) { $ rootDir = System :: getContainer ( ) -> getParameter ( 'kernel.project_dir' ) ; $ thumbnail .= '<br>' . Image :: getHtml ( System :: getContainer ( ) -> get ( 'contao.image.image_factory' ) -> create ( $ rootDir . '/' . rawurldecode ( $ currentEncoded ) , array ( 100 , 75 , ResizeConfiguration :: MODE_BOX ) ) -> getUrl ( $ rootDir ) , '' , 'style="margin:0 0 2px -18px"' ) ; $ importantPart = System :: getContainer ( ) -> get ( 'contao.image.image_factory' ) -> create ( $ rootDir . '/' . rawurldecode ( $ currentEncoded ) ) -> getImportantPart ( ) ; if ( $ importantPart -> getPosition ( ) -> getX ( ) > 0 || $ importantPart -> getPosition ( ) -> getY ( ) > 0 || $ importantPart -> getSize ( ) -> getWidth ( ) < $ objFile -> width || $ importantPart -> getSize ( ) -> getHeight ( ) < $ objFile -> height ) { $ thumbnail .= ' ' . Image :: getHtml ( System :: getContainer ( ) -> get ( 'contao.image.image_factory' ) -> create ( $ rootDir . '/' . rawurldecode ( $ currentEncoded ) , ( new ResizeConfiguration ( ) ) -> setWidth ( 80 ) -> setHeight ( 60 ) -> setMode ( ResizeConfiguration :: MODE_BOX ) -> setZoomLevel ( 100 ) ) -> getUrl ( $ rootDir ) , '' , '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 ; default : 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 ; }
Recursively render the filetree

@param string  $path
@param integer $intMargin
@param boolean $mount
@param boolean $blnProtected
@param array   $arrFound

@return string
Recursively render the filetree