2020-04-14 11:07:07 +02:00
< ? php
2022-11-29 21:21:26 +01:00
/*
* This file is part of Part - DB ( https :// github . com / Part - DB / Part - DB - symfony ) .
*
* Copyright ( C ) 2019 - 2022 Jan Böhmer ( https :// github . com / jbtronics )
*
* This program is free software : you can redistribute it and / or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation , either version 3 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU Affero General Public License for more details .
*
* You should have received a copy of the GNU Affero General Public License
* along with this program . If not , see < https :// www . gnu . org / licenses />.
*/
2020-05-10 21:39:31 +02:00
declare ( strict_types = 1 );
2020-04-14 11:07:07 +02:00
/**
* This file is part of Part - DB ( https :// github . com / Part - DB / Part - DB - symfony ) .
*
2022-11-29 22:28:53 +01:00
* Copyright ( C ) 2019 - 2022 Jan Böhmer ( https :// github . com / jbtronics )
2020-04-14 11:07:07 +02:00
*
* This program is free software : you can redistribute it and / or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation , either version 3 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU Affero General Public License for more details .
*
* You should have received a copy of the GNU Affero General Public License
* along with this program . If not , see < https :// www . gnu . org / licenses />.
*/
namespace App\Controller ;
2020-04-16 19:56:30 +02:00
use App\Entity\Base\AbstractDBElement ;
use App\Entity\LabelSystem\LabelOptions ;
2023-06-13 20:24:54 +02:00
use App\Entity\LabelSystem\LabelProcessMode ;
2020-04-14 11:07:07 +02:00
use App\Entity\LabelSystem\LabelProfile ;
2023-06-12 23:39:30 +02:00
use App\Entity\LabelSystem\LabelSupportedElement ;
2020-05-06 22:44:21 +02:00
use App\Exceptions\TwigModeException ;
2020-04-16 19:56:30 +02:00
use App\Form\LabelSystem\LabelDialogType ;
2020-04-21 00:00:29 +02:00
use App\Repository\DBElementRepository ;
2020-04-16 19:56:30 +02:00
use App\Services\ElementTypeNameGenerator ;
2020-04-14 11:07:07 +02:00
use App\Services\LabelSystem\LabelGenerator ;
2020-04-21 00:00:29 +02:00
use App\Services\Misc\RangeParser ;
2020-04-16 19:56:30 +02:00
use Doctrine\ORM\EntityManagerInterface ;
2020-04-14 11:07:07 +02:00
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController ;
2020-05-06 22:44:21 +02:00
use Symfony\Component\Form\FormError ;
2020-04-16 19:56:30 +02:00
use Symfony\Component\HttpFoundation\Request ;
2020-08-21 22:43:37 +02:00
use Symfony\Component\HttpFoundation\Response ;
2024-03-03 20:37:33 +01:00
use Symfony\Component\Routing\Attribute\Route ;
2025-09-06 23:49:14 +02:00
use Symfony\Component\Validator\Validator\ValidatorInterface ;
2020-05-07 13:31:19 +02:00
use Symfony\Contracts\Translation\TranslatorInterface ;
2020-04-14 11:07:07 +02:00
2023-05-28 01:21:05 +02:00
#[Route(path: '/label')]
2020-04-14 11:07:07 +02:00
class LabelController extends AbstractController
{
2025-09-06 23:49:14 +02:00
public function __construct ( protected LabelGenerator $labelGenerator , protected EntityManagerInterface $em , protected ElementTypeNameGenerator $elementTypeNameGenerator , protected RangeParser $rangeParser , protected TranslatorInterface $translator ,
private readonly ValidatorInterface $validator
)
2020-04-14 11:07:07 +02:00
{
}
2023-05-28 01:21:05 +02:00
#[Route(path: '/dialog', name: 'label_dialog')]
#[Route(path: '/{profile}/dialog', name: 'label_dialog_profile')]
2020-08-21 22:43:37 +02:00
public function generator ( Request $request , ? LabelProfile $profile = null ) : Response
2020-04-16 19:56:30 +02:00
{
2020-05-04 23:21:58 +02:00
$this -> denyAccessUnlessGranted ( '@labels.create_labels' );
//If we inherit a LabelProfile, the user need to have access to it...
2023-06-11 14:55:06 +02:00
if ( $profile instanceof LabelProfile ) {
2020-05-04 23:21:58 +02:00
$this -> denyAccessUnlessGranted ( 'read' , $profile );
}
2023-06-11 14:55:06 +02:00
$label_options = $profile instanceof LabelProfile ? $profile -> getOptions () : new LabelOptions ();
2020-04-16 19:56:30 +02:00
2020-05-07 22:29:45 +02:00
//We have to disable the options, if twig mode is selected and user is not allowed to use it.
2023-06-13 20:24:54 +02:00
$disable_options = ( LabelProcessMode :: TWIG === $label_options -> getProcessMode ()) && ! $this -> isGranted ( '@labels.use_twig' );
2020-05-07 22:29:45 +02:00
$form = $this -> createForm ( LabelDialogType :: class , null , [
'disable_options' => $disable_options ,
2025-09-06 23:56:51 +02:00
'profile' => $profile
2020-05-07 22:29:45 +02:00
]);
2020-04-16 19:56:30 +02:00
//Try to parse given target_type and target_id
2023-06-12 23:39:30 +02:00
$target_type = $request -> query -> getEnum ( 'target_type' , LabelSupportedElement :: class , null );
2020-04-16 19:56:30 +02:00
$target_id = $request -> query -> get ( 'target_id' , null );
2020-05-01 20:29:18 +02:00
$generate = $request -> query -> getBoolean ( 'generate' , false );
2023-06-12 23:39:30 +02:00
if ( ! $profile instanceof LabelProfile && $target_type instanceof LabelSupportedElement ) {
2020-04-16 19:56:30 +02:00
$label_options -> setSupportedElement ( $target_type );
}
2020-04-21 00:00:29 +02:00
if ( is_string ( $target_id )) {
$form [ 'target_id' ] -> setData ( $target_id );
2020-04-16 19:56:30 +02:00
}
$form [ 'options' ] -> setData ( $label_options );
$form -> handleRequest ( $request );
/** @var LabelOptions $form_options */
$form_options = $form [ 'options' ] -> getData ();
$pdf_data = null ;
$filename = 'invalid.pdf' ;
2023-06-11 14:55:06 +02:00
if (( $form -> isSubmitted () && $form -> isValid ()) || ( $generate && ! $form -> isSubmitted () && $profile instanceof LabelProfile )) {
2025-01-05 22:00:07 +01:00
//Check if the label should be saved as profile
2025-01-06 00:21:04 +01:00
if ( $form -> get ( 'save_profile' ) -> isClicked () && $this -> isGranted ( '@labels.create_profiles' )) { //@phpstan-ignore-line Phpstan does not recognize the isClicked method
2025-01-05 22:00:07 +01:00
//Retrieve the profile name from the form
$new_name = $form -> get ( 'save_profile_name' ) -> getData ();
//ensure that the name is not empty
if ( $new_name === '' || $new_name === null ) {
$form -> get ( 'save_profile_name' ) -> addError ( new FormError ( $this -> translator -> trans ( 'label_generator.profile_name_empty' )));
goto render ;
}
2025-09-06 23:49:14 +02:00
$new_profile = new LabelProfile ();
$new_profile -> setName ( $form -> get ( 'save_profile_name' ) -> getData ());
$new_profile -> setOptions ( $form_options );
//Validate the profile name
$errors = $this -> validator -> validate ( $new_profile );
if ( count ( $errors ) > 0 ) {
foreach ( $errors as $error ) {
$form -> get ( 'save_profile_name' ) -> addError ( new FormError ( $error -> getMessage ()));
}
goto render ;
}
$this -> em -> persist ( $new_profile );
2025-01-05 22:00:07 +01:00
$this -> em -> flush ();
$this -> addFlash ( 'success' , 'label_generator.profile_saved' );
return $this -> redirectToRoute ( 'label_dialog_profile' , [
2025-09-06 23:49:14 +02:00
'profile' => $new_profile -> getID (),
2025-01-05 22:00:07 +01:00
'target_id' => ( string ) $form -> get ( 'target_id' ) -> getData ()
2025-09-06 23:56:51 +02:00
]);
}
2025-09-07 00:26:24 +02:00
//Check if the current profile should be updated
if ( $form -> has ( 'update_profile' )
&& $form -> get ( 'update_profile' ) -> isClicked () //@phpstan-ignore-line Phpstan does not recognize the isClicked method
&& $profile instanceof LabelProfile
&& $this -> isGranted ( 'edit' , $profile )) {
2025-09-06 23:56:51 +02:00
//Update the profile options
$profile -> setOptions ( $form_options );
//Validate the profile name
$errors = $this -> validator -> validate ( $profile );
if ( count ( $errors ) > 0 ) {
foreach ( $errors as $error ) {
$this -> addFlash ( 'error' , $error -> getMessage ());
}
goto render ;
}
$this -> em -> persist ( $profile );
$this -> em -> flush ();
$this -> addFlash ( 'success' , 'label_generator.profile_updated' );
return $this -> redirectToRoute ( 'label_dialog_profile' , [
'profile' => $profile -> getID (),
'target_id' => ( string ) $form -> get ( 'target_id' ) -> getData ()
2025-01-05 22:00:07 +01:00
]);
}
2020-04-21 00:00:29 +02:00
$target_id = ( string ) $form -> get ( 'target_id' ) -> getData ();
$targets = $this -> findObjects ( $form_options -> getSupportedElement (), $target_id );
2023-06-11 14:15:46 +02:00
if ( $targets !== []) {
2020-05-06 22:44:21 +02:00
try {
$pdf_data = $this -> labelGenerator -> generateLabel ( $form_options , $targets );
$filename = $this -> getLabelName ( $targets [ 0 ], $profile );
} catch ( TwigModeException $exception ) {
2024-08-23 22:28:29 +02:00
$form -> get ( 'options' ) -> get ( 'lines' ) -> addError ( new FormError ( $exception -> getSafeMessage ()));
2020-05-06 22:44:21 +02:00
}
2020-05-05 19:55:31 +02:00
} else {
2020-05-07 13:31:19 +02:00
//$this->addFlash('warning', 'label_generator.no_entities_found');
$form -> get ( 'target_id' ) -> addError (
new FormError ( $this -> translator -> trans ( 'label_generator.no_entities_found' ))
);
2020-05-05 19:55:31 +02:00
}
2023-06-27 00:18:47 +02:00
//When the profile lines are empty, show a notice flash
if ( trim ( $form_options -> getLines ()) === '' ) {
$this -> addFlash ( 'notice' , 'label_generator.no_lines_given' );
}
2020-04-16 19:56:30 +02:00
}
2025-01-05 22:00:07 +01:00
render :
2023-05-28 01:21:05 +02:00
return $this -> render ( 'label_system/dialog.html.twig' , [
2022-03-04 21:20:18 +01:00
'form' => $form ,
2020-04-16 19:56:30 +02:00
'pdf_data' => $pdf_data ,
'filename' => $filename ,
2020-05-08 12:43:04 +02:00
'profile' => $profile ,
2020-04-16 19:56:30 +02:00
]);
}
protected function getLabelName ( AbstractDBElement $element , ? LabelProfile $profile = null ) : string
{
2020-05-10 21:39:31 +02:00
$ret = 'label_' . $this -> elementTypeNameGenerator -> getLocalizedTypeLabel ( $element );
2020-04-16 19:56:30 +02:00
$ret .= $element -> getID ();
2020-05-10 21:39:31 +02:00
return $ret . '.pdf' ;
2020-04-16 19:56:30 +02:00
}
2023-06-12 23:39:30 +02:00
protected function findObjects ( LabelSupportedElement $type , string $ids ) : array
2020-04-16 19:56:30 +02:00
{
2020-04-21 00:00:29 +02:00
$id_array = $this -> rangeParser -> parse ( $ids );
2024-12-28 22:31:04 +01:00
/** @var DBElementRepository<AbstractDBElement> $repo */
2023-06-12 23:39:30 +02:00
$repo = $this -> em -> getRepository ( $type -> getEntityClass ());
2020-05-10 21:39:31 +02:00
2020-04-21 00:00:29 +02:00
return $repo -> getElementsFromIDArray ( $id_array );
2020-04-16 19:56:30 +02:00
}
2020-05-10 21:39:31 +02:00
}