public function copy($source = null, $destination = null)
{
if ($GLOBALS['TL_DCA'][$this->strTable]['config']['notCopyable']) {
throw new InternalServerErrorException('Table "' . $this->strTable . '" is not copyable.');
}
$strFolder = \Input::get('pid', true);
$blnDoNotRedirect = $source !== null;
if ($source === null) {
$source = $this->intId;
}
if ($destination === null) {
$destination = str_replace(dirname($source), $strFolder, $source);
}
$this->isValid($source);
$this->isValid($destination);
if (!file_exists(TL_ROOT . '/' . $source) || !$this->isMounted($source)) {
throw new AccessDeniedException('File or folder "' . $source . '" is not mounted or cannot be found.');
}
if (!file_exists(TL_ROOT . '/' . $strFolder) || !$this->isMounted($strFolder)) {
throw new AccessDeniedException('Parent folder "' . $strFolder . '" is not mounted or is not a directory.');
}
// Avoid a circular reference
if (preg_match('/^' . preg_quote($source, '/') . '/i', $strFolder)) {
throw new InternalServerErrorException('Attempt to copy the folder "' . $source . '" to "' . $strFolder . '" (circular reference).');
}
/** @var SessionInterface $objSession */
$objSession = \System::getContainer()->get('session');
// Empty clipboard
$arrClipboard = $objSession->get('CLIPBOARD');
$arrClipboard[$this->strTable] = array();
$objSession->set('CLIPBOARD', $arrClipboard);
$this->import('Files');
// Copy folders
if (is_dir(TL_ROOT . '/' . $source)) {
$count = 1;
$new = $destination;
// Add a suffix if the folder exists
while (is_dir(TL_ROOT . '/' . $new) && $count < 12) {
$new = $destination . '_' . $count++;
}
$destination = $new;
$this->Files->rcopy($source, $destination);
} else {
$count = 1;
$new = $destination;
$ext = strtolower(substr($destination, strrpos($destination, '.') + 1));
// Add a suffix if the file exists
while (file_exists(TL_ROOT . '/' . $new) && $count < 12) {
$new = str_replace('.' . $ext, '_' . $count++ . '.' . $ext, $destination);
}
$destination = $new;
$this->Files->copy($source, $destination);
}
// Update the database AFTER the file has been copied
if ($this->blnIsDbAssisted) {
$syncSource = \Dbafs::shouldBeSynchronized($source);
$syncTarget = \Dbafs::shouldBeSynchronized($destination);
if ($syncSource && $syncTarget) {
\Dbafs::copyResource($source, $destination);
} elseif ($syncTarget) {
\Dbafs::addResource($destination);
}
}
// Call the oncopy_callback
if (is_array($GLOBALS['TL_DCA'][$this->strTable]['config']['oncopy_callback'])) {
foreach ($GLOBALS['TL_DCA'][$this->strTable]['config']['oncopy_callback'] as $callback) {
if (is_array($callback)) {
$this->import($callback[0]);
$this->{$callback[0]}->{$callback[1]}($source, $destination, $this);
} elseif (is_callable($callback)) {
$callback($source, $destination, $this);
}
}
}
// Add a log entry
$this->log('File or folder "' . $source . '" has been copied to "' . $destination . '"', __METHOD__, TL_FILES);
// Redirect
if (!$blnDoNotRedirect) {
// Switch to edit mode
if (is_file(TL_ROOT . '/' . $destination)) {
$this->redirect($this->switchToEdit($destination));
}
$this->redirect($this->getReferer());
}
}