Release 1.30.4 (#3770)

* prevent empty invoice number
* prevent broken invoice filename
* fix recent timesheets for user
* allow to upload twig invoice template
This commit is contained in:
Kevin Papst
2023-01-19 15:13:44 +01:00
committed by GitHub
parent 559868fede
commit 7ea3eb1e3c
37 changed files with 191 additions and 50 deletions

View File

@@ -44,6 +44,7 @@ use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Security\Csrf\CsrfToken;
use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface;
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
use Twig\Environment;
/**
* Controller used to create invoices and manage invoice templates.
@@ -409,7 +410,7 @@ final class InvoiceController extends AbstractController
* @Route(path="/document_upload", name="admin_invoice_document_upload", methods={"GET", "POST"})
* @Security("is_granted('upload_invoice_template')")
*/
public function uploadDocumentAction(Request $request, string $projectDirectory, InvoiceDocumentRepository $documentRepository)
public function uploadDocumentAction(Request $request, string $projectDirectory, InvoiceDocumentRepository $documentRepository, Environment $twig, SystemConfiguration $systemConfiguration)
{
$dir = $documentRepository->getUploadDirectory();
$invoiceDir = $dir;
@@ -418,6 +419,7 @@ final class InvoiceController extends AbstractController
if ($invoiceDir[0] !== '/') {
$invoiceDir = $projectDirectory . DIRECTORY_SEPARATOR . $dir;
}
$invoiceDir = rtrim($invoiceDir, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR;
$used = [];
foreach ($this->templateRepository->findAll() as $template) {
@@ -473,23 +475,56 @@ final class InvoiceController extends AbstractController
/** @var UploadedFile $uploadedFile */
$uploadedFile = $form->get('document')->getData();
$originalFilename = pathinfo($uploadedFile->getClientOriginalName(), PATHINFO_FILENAME);
$safeFilename = transliterator_transliterate(
'Any-Latin; Latin-ASCII; [^A-Za-z0-9_] remove; Lower()',
$originalFilename
);
$originalName = $uploadedFile->getClientOriginalName();
$safeFilename = null;
$extension = null;
$success = true;
$extension = $uploadedFile->guessExtension();
$allowed = InvoiceDocumentUploadForm::EXTENSIONS_NO_TWIG;
if ((bool) $systemConfiguration->find('invoice.upload_twig') === true) {
$allowed = InvoiceDocumentUploadForm::EXTENSIONS;
}
$newFilename = substr($safeFilename, 0, 20) . '.' . $extension;
foreach ($allowed as $ext) {
$len = \strlen($ext);
if (substr_compare($originalName, $ext, -$len) === 0) {
$extension = $ext;
$withoutExtension = str_replace($ext, '', $originalName);
$safeFilename = transliterator_transliterate(InvoiceDocumentUploadForm::FILENAME_RULE, $withoutExtension);
break;
}
}
try {
$uploadedFile->move($invoiceDir, $newFilename);
if ($safeFilename === null || $extension === null) {
$success = false;
$this->flashError('Invalid file given');
} else {
$newFilename = substr($safeFilename, 0, 20) . $extension;
try {
$uploadedFile->move($invoiceDir, $newFilename);
// if this is a twig file, we directly try to compile the template
if (stripos($newFilename, '.twig') !== false) {
try {
$twig->enableAutoReload();
$twig->load('@invoice/' . $newFilename);
$twig->disableAutoReload();
} catch (Exception $ex) {
unlink($invoiceDir . $newFilename);
$success = false;
$this->flashException($ex, 'File was deleted, as Twig template is broken: ' . $ex->getMessage());
}
}
} catch (Exception $ex) {
$this->flashException($ex, 'action.upload.error');
}
}
if ($success) {
$this->flashSuccess('action.update.success');
return $this->redirectToRoute('admin_invoice_document_upload');
} catch (Exception $ex) {
$this->flashException($ex, 'action.upload.error');
}
}
}