* merge master - allow to upload twig invoice templates via UI
* support adding existing teams with same name
* permissions cannot be set right after role was created - fixes #3777
* allow to deactivate unique customer number validation - fixes #3762 
* invalid message when trying to edit locked or exported timesheets in calendar - fixes #3766
* updated icons and manifest - fixes #3761
This commit is contained in:
Kevin Papst
2023-01-21 14:49:55 +01:00
committed by GitHub
parent b62253e1f3
commit a230be77dd
79 changed files with 428 additions and 358 deletions

View File

@@ -9,6 +9,7 @@
namespace App\Controller;
use App\Configuration\SystemConfiguration;
use App\Entity\Customer;
use App\Entity\Invoice;
use App\Entity\InvoiceTemplate;
@@ -48,6 +49,7 @@ use Symfony\Component\Security\Csrf\CsrfToken;
use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface;
use Symfony\Component\Security\Http\Attribute\IsGranted;
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
use Twig\Environment;
/**
* Controller used to create invoices and manage invoice templates.
@@ -447,7 +449,7 @@ final class InvoiceController extends AbstractController
#[Route(path: '/document_upload', name: 'admin_invoice_document_upload', methods: ['GET', 'POST'])]
#[IsGranted('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): Response
{
$dir = $documentRepository->getUploadDirectory();
$invoiceDir = $dir;
@@ -456,6 +458,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) {
@@ -511,23 +514,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');
}
}
}