core-bundle/src/Resources/contao/drivers/DC_Folder.php
public function move($blnIsAjax=false)
	{
		$strFolder = Input::get('pid', true);

		if (!file_exists($this->strRootDir . '/' . $strFolder) || !$this->isMounted($strFolder))
		{
			throw new AccessDeniedException('Folder "' . $strFolder . '" is not mounted or is not a directory.');
		}

		if (!preg_match('/^'.preg_quote(Config::get('uploadPath'), '/').'/i', $strFolder))
		{
			throw new AccessDeniedException('Parent folder "' . $strFolder . '" is not within the files directory.');
		}

		// Empty clipboard
		if (!$blnIsAjax)
		{
			/** @var Session $objSession */
			$objSession = System::getContainer()->get('session');

			$arrClipboard = $objSession->get('CLIPBOARD');
			$arrClipboard[$this->strTable] = array();
			$objSession->set('CLIPBOARD', $arrClipboard);
		}

		// Instantiate the uploader
		$this->import(BackendUser::class, 'User');
		$class = $this->User->uploader;

		// See #4086
		if (!class_exists($class))
		{
			$class = 'DropZone';
		}

		/** @var FileUpload $objUploader */
		$objUploader = new $class();

		// Process the uploaded files
		if (Input::post('FORM_SUBMIT') == 'tl_upload')
		{
			// Generate the DB entries
			if ($this->blnIsDbAssisted && Dbafs::shouldBeSynchronized($strFolder))
			{
				// Upload the files
				$arrUploaded = $objUploader->uploadTo($strFolder);

				if (empty($arrUploaded) && !$objUploader->hasError())
				{
					if ($blnIsAjax)
					{
						throw new ResponseException(new Response($GLOBALS['TL_LANG']['ERR']['emptyUpload'], 400));
					}

					Message::addError($GLOBALS['TL_LANG']['ERR']['emptyUpload']);
					$this->reload();
				}

				foreach ($arrUploaded as $strFile)
				{
					Dbafs::addResource($strFile);
				}
			}
			else
			{
				// Not DB-assisted, so just upload the file
				$arrUploaded = $objUploader->uploadTo($strFolder);
			}

			// HOOK: post upload callback
			if (isset($GLOBALS['TL_HOOKS']['postUpload']) && \is_array($GLOBALS['TL_HOOKS']['postUpload']))
			{
				foreach ($GLOBALS['TL_HOOKS']['postUpload'] as $callback)
				{
					if (\is_array($callback))
					{
						$this->import($callback[0]);
						$this->{$callback[0]}->{$callback[1]}($arrUploaded);
					}
					elseif (\is_callable($callback))
					{
						$callback($arrUploaded);
					}
				}
			}

			// Update the hash of the target folder
			if ($this->blnIsDbAssisted && Dbafs::shouldBeSynchronized($strFolder))
			{
				Dbafs::updateFolderHashes($strFolder);
			}

			// Redirect or reload
			if (!$objUploader->hasError())
			{
				if ($blnIsAjax)
				{
					/** @var Session $objSession */
					$objSession = System::getContainer()->get('session');

					if ($objSession->isStarted())
					{
						// Get the info messages only
						$arrMessages = $objSession->getFlashBag()->get('contao.' . TL_MODE . '.info');
						Message::reset();

						if (!empty($arrMessages))
						{
							throw new ResponseException(new Response('<p class="tl_info">' . implode('</p><p class="tl_info">', $arrMessages) . '</p>', 201));
						}
					}

					throw new ResponseException(new Response('', 201));
				}

				// Do not purge the html folder (see #2898)
				if (isset($_POST['uploadNback']) && !$objUploader->hasResized())
				{
					Message::reset();
					$this->redirect($this->getReferer());
				}

				$this->reload();
			}
			elseif ($blnIsAjax)
			{
				throw new ResponseException(new Response(Message::generateUnwrapped(TL_MODE, true), 500));
			}
		}

		// Submit buttons
		$arrButtons = array();
		$arrButtons['upload'] = '<button type="submit" name="upload" class="tl_submit" accesskey="s">'.$GLOBALS['TL_LANG'][$this->strTable]['upload'][0].'</button>';
		$arrButtons['uploadNback'] = '<button type="submit" name="uploadNback" class="tl_submit" accesskey="c">'.$GLOBALS['TL_LANG'][$this->strTable]['uploadNback'].'</button>';

		// Call the buttons_callback (see #4691)
		if (\is_array($GLOBALS['TL_DCA'][$this->strTable]['edit']['buttons_callback']))
		{
			foreach ($GLOBALS['TL_DCA'][$this->strTable]['edit']['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>';
		}

		// Display the upload form
		return Message::generate() . '
<div id="tl_buttons">
<a href="'.$this->getReferer(true).'" class="header_back" title="'.StringUtil::specialchars($GLOBALS['TL_LANG']['MSC']['backBTTitle']).'" accesskey="b" onclick="Backend.getScrollOffset()">'.$GLOBALS['TL_LANG']['MSC']['backBT'].'</a>
</div>
<form action="'.ampersand(Environment::get('request'), true).'" id="'.$this->strTable.'" class="tl_form tl_edit_form" method="post"'.(!empty($this->onsubmit) ? ' onsubmit="'.implode(' ', $this->onsubmit).'"' : '').' enctype="multipart/form-data">
<div class="tl_formbody_edit">
<input type="hidden" name="FORM_SUBMIT" value="tl_upload">
<input type="hidden" name="REQUEST_TOKEN" value="'.REQUEST_TOKEN.'">
<input type="hidden" name="MAX_FILE_SIZE" value="'.Config::get('maxFileSize').'">
<div class="tl_tbox">
<div class="widget">
  <h3>'.$GLOBALS['TL_LANG'][$this->strTable]['fileupload'][0].'</h3>'.$objUploader->generateMarkup().'
</div>
</div>
</div>
<div class="tl_formbody_submit">
<div class="tl_submit_container">
  ' . $strButtons . '
</div>
</div>
</form>';
	}
public function move($blnIsAjax=false)
	{
		$strFolder = Input::get('pid', true);

		if (!file_exists($this->strRootDir . '/' . $strFolder) || !$this->isMounted($strFolder))
		{
			throw new AccessDeniedException('Folder "' . $strFolder . '" is not mounted or is not a directory.');
		}

		if (!preg_match('/^'.preg_quote(Config::get('uploadPath'), '/').'/i', $strFolder))
		{
			throw new AccessDeniedException('Parent folder "' . $strFolder . '" is not within the files directory.');
		}

		// Empty clipboard
		if (!$blnIsAjax)
		{
			/** @var Session $objSession */
			$objSession = System::getContainer()->get('session');

			$arrClipboard = $objSession->get('CLIPBOARD');
			$arrClipboard[$this->strTable] = array();
			$objSession->set('CLIPBOARD', $arrClipboard);
		}

		// Instantiate the uploader
		$this->import(BackendUser::class, 'User');
		$class = $this->User->uploader;

		// See #4086
		if (!class_exists($class))
		{
			$class = 'DropZone';
		}

		/** @var FileUpload $objUploader */
		$objUploader = new $class();

		// Process the uploaded files
		if (Input::post('FORM_SUBMIT') == 'tl_upload')
		{
			// Generate the DB entries
			if ($this->blnIsDbAssisted && Dbafs::shouldBeSynchronized($strFolder))
			{
				// Upload the files
				$arrUploaded = $objUploader->uploadTo($strFolder);

				if (empty($arrUploaded) && !$objUploader->hasError())
				{
					if ($blnIsAjax)
					{
						throw new ResponseException(new Response($GLOBALS['TL_LANG']['ERR']['emptyUpload'], 400));
					}

					Message::addError($GLOBALS['TL_LANG']['ERR']['emptyUpload']);
					$this->reload();
				}

				foreach ($arrUploaded as $strFile)
				{
					Dbafs::addResource($strFile);
				}
			}
			else
			{
				// Not DB-assisted, so just upload the file
				$arrUploaded = $objUploader->uploadTo($strFolder);
			}

			// HOOK: post upload callback
			if (isset($GLOBALS['TL_HOOKS']['postUpload']) && \is_array($GLOBALS['TL_HOOKS']['postUpload']))
			{
				foreach ($GLOBALS['TL_HOOKS']['postUpload'] as $callback)
				{
					if (\is_array($callback))
					{
						$this->import($callback[0]);
						$this->{$callback[0]}->{$callback[1]}($arrUploaded);
					}
					elseif (\is_callable($callback))
					{
						$callback($arrUploaded);
					}
				}
			}

			// Update the hash of the target folder
			if ($this->blnIsDbAssisted && Dbafs::shouldBeSynchronized($strFolder))
			{
				Dbafs::updateFolderHashes($strFolder);
			}

			// Redirect or reload
			if (!$objUploader->hasError())
			{
				if ($blnIsAjax)
				{
					/** @var Session $objSession */
					$objSession = System::getContainer()->get('session');

					if ($objSession->isStarted())
					{
						// Get the info messages only
						$arrMessages = $objSession->getFlashBag()->get('contao.' . TL_MODE . '.info');
						Message::reset();

						if (!empty($arrMessages))
						{
							throw new ResponseException(new Response('<p class="tl_info">' . implode('</p><p class="tl_info">', $arrMessages) . '</p>', 201));
						}
					}

					throw new ResponseException(new Response('', 201));
				}

				// Do not purge the html folder (see #2898)
				if (isset($_POST['uploadNback']) && !$objUploader->hasResized())
				{
					Message::reset();
					$this->redirect($this->getReferer());
				}

				$this->reload();
			}
			elseif ($blnIsAjax)
			{
				throw new ResponseException(new Response(Message::generateUnwrapped(TL_MODE, true), 500));
			}
		}

		// Submit buttons
		$arrButtons = array();
		$arrButtons['upload'] = '<button type="submit" name="upload" class="tl_submit" accesskey="s">'.$GLOBALS['TL_LANG'][$this->strTable]['upload'][0].'</button>';
		$arrButtons['uploadNback'] = '<button type="submit" name="uploadNback" class="tl_submit" accesskey="c">'.$GLOBALS['TL_LANG'][$this->strTable]['uploadNback'].'</button>';

		// Call the buttons_callback (see #4691)
		if (\is_array($GLOBALS['TL_DCA'][$this->strTable]['edit']['buttons_callback']))
		{
			foreach ($GLOBALS['TL_DCA'][$this->strTable]['edit']['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>';
		}

		// Display the upload form
		return Message::generate() . '
<div id="tl_buttons">
<a href="'.$this->getReferer(true).'" class="header_back" title="'.StringUtil::specialchars($GLOBALS['TL_LANG']['MSC']['backBTTitle']).'" accesskey="b" onclick="Backend.getScrollOffset()">'.$GLOBALS['TL_LANG']['MSC']['backBT'].'</a>
</div>
<form action="'.ampersand(Environment::get('request'), true).'" id="'.$this->strTable.'" class="tl_form tl_edit_form" method="post"'.(!empty($this->onsubmit) ? ' onsubmit="'.implode(' ', $this->onsubmit).'"' : '').' enctype="multipart/form-data">
<div class="tl_formbody_edit">
<input type="hidden" name="FORM_SUBMIT" value="tl_upload">
<input type="hidden" name="REQUEST_TOKEN" value="'.REQUEST_TOKEN.'">
<input type="hidden" name="MAX_FILE_SIZE" value="'.Config::get('maxFileSize').'">
<div class="tl_tbox">
<div class="widget">
  <h3>'.$GLOBALS['TL_LANG'][$this->strTable]['fileupload'][0].'</h3>'.$objUploader->generateMarkup().'
</div>
</div>
</div>
<div class="tl_formbody_submit">
<div class="tl_submit_container">
  ' . $strButtons . '
</div>
</div>
</form>';
	}
Move one or more local files to the server

@param boolean $blnIsAjax

@return string

@throws AccessDeniedException