beta 3 (#3780)
* 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:
@@ -9,6 +9,7 @@
|
||||
|
||||
namespace App\Form;
|
||||
|
||||
use App\Configuration\SystemConfiguration;
|
||||
use App\Repository\InvoiceDocumentRepository;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\FileType;
|
||||
@@ -21,28 +22,45 @@ use Symfony\Component\Validator\Context\ExecutionContextInterface;
|
||||
|
||||
final class InvoiceDocumentUploadForm extends AbstractType
|
||||
{
|
||||
public function __construct(private InvoiceDocumentRepository $repository)
|
||||
public const EXTENSIONS = ['.html.twig', '.pdf.twig', '.docx', '.xlsx', '.ods'];
|
||||
public const EXTENSIONS_NO_TWIG = ['.docx', '.xlsx', '.ods'];
|
||||
public const FILENAME_RULE = 'Any-Latin; Latin-ASCII; [^A-Za-z0-9_\-] remove; Lower()';
|
||||
|
||||
/** @var array<string> */
|
||||
private array $extensions = [];
|
||||
|
||||
public function __construct(private InvoiceDocumentRepository $repository, private SystemConfiguration $systemConfiguration)
|
||||
{
|
||||
}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder, array $options): void
|
||||
{
|
||||
$this->extensions = self::EXTENSIONS_NO_TWIG;
|
||||
$extensions = 'DOCX, ODS, XLSX';
|
||||
$mimetypes = [
|
||||
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
||||
'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
|
||||
'application/vnd.oasis.opendocument.spreadsheet',
|
||||
];
|
||||
|
||||
if ((bool) $this->systemConfiguration->find('invoice.upload_twig') === true) {
|
||||
$this->extensions = self::EXTENSIONS;
|
||||
$extensions = 'DOCX, ODS, XLSX, TWIG (PDF & HTML)';
|
||||
$mimetypes = array_merge($mimetypes, [
|
||||
'application/octet-stream', // needed for twig templates
|
||||
'text/html', // needed for twig templates
|
||||
'text/plain', // needed for twig templates
|
||||
]);
|
||||
}
|
||||
|
||||
$builder
|
||||
->add('document', FileType::class, [
|
||||
'label' => 'invoice_renderer',
|
||||
'translation_domain' => 'invoice-renderer',
|
||||
'help' => 'help.upload',
|
||||
'help_translation_parameters' => ['%extensions%' => $extensions],
|
||||
'mapped' => false,
|
||||
'required' => true,
|
||||
'attr' => [
|
||||
'accept' => implode(',', $mimetypes)
|
||||
],
|
||||
'constraints' => [
|
||||
new File([
|
||||
'mimeTypes' => $mimetypes,
|
||||
@@ -54,7 +72,7 @@ final class InvoiceDocumentUploadForm extends AbstractType
|
||||
;
|
||||
}
|
||||
|
||||
public function validateDocument($value, ExecutionContextInterface $context)
|
||||
public function validateDocument($value, ExecutionContextInterface $context): void
|
||||
{
|
||||
if (!($value instanceof UploadedFile)) {
|
||||
return;
|
||||
@@ -71,6 +89,48 @@ final class InvoiceDocumentUploadForm extends AbstractType
|
||||
->setTranslationDomain('validators')
|
||||
->setCode('kimai-invoice-document-upload-01')
|
||||
->addViolation();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$extension = null;
|
||||
$nameWithoutExtension = null;
|
||||
|
||||
foreach ($this->extensions as $ext) {
|
||||
$len = \strlen($ext);
|
||||
if (substr_compare($name, $ext, -$len) === 0) {
|
||||
$extension = $ext;
|
||||
$nameWithoutExtension = str_replace($ext, '', $name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ($extension === null || $nameWithoutExtension === null) {
|
||||
$context->buildViolation('This invoice document cannot be used, allowed file extensions are: %extensions%')
|
||||
->setParameters(['%extensions%' => implode(', ', $this->extensions)])
|
||||
->setTranslationDomain('validators')
|
||||
->setCode('kimai-invoice-document-upload-02')
|
||||
->addViolation();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$safeFilename = transliterator_transliterate(self::FILENAME_RULE, $nameWithoutExtension);
|
||||
|
||||
if ($safeFilename !== $nameWithoutExtension) {
|
||||
$context->buildViolation('This invoice document cannot be used, filename may only contain the following ascii character: %character%')
|
||||
->setParameters(['%character%' => 'A-Z a-z 0-9 _ -'])
|
||||
->setTranslationDomain('validators')
|
||||
->setCode('kimai-invoice-document-upload-03')
|
||||
->addViolation();
|
||||
}
|
||||
|
||||
if (mb_strlen($nameWithoutExtension) > 20) {
|
||||
$context->buildViolation('This invoice document cannot be used, allowed filename length without extension is %character% character.')
|
||||
->setParameters(['%character%' => 20])
|
||||
->setTranslationDomain('validators')
|
||||
->setCode('kimai-invoice-document-upload-04')
|
||||
->addViolation();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user