mirror of
https://github.com/Part-DB/Part-DB-server.git
synced 2025-06-25 11:18:51 +02:00
Validate bom when adding additional bom entries via addPart controller to prevent invalid BOMs
This fixes issue #302
This commit is contained in:
parent
2ebb4fef4c
commit
98e179ba06
2 changed files with 95 additions and 12 deletions
|
@ -26,21 +26,26 @@ use App\DataTables\ProjectBomEntriesDataTable;
|
||||||
use App\Entity\Parts\Part;
|
use App\Entity\Parts\Part;
|
||||||
use App\Entity\ProjectSystem\Project;
|
use App\Entity\ProjectSystem\Project;
|
||||||
use App\Entity\ProjectSystem\ProjectBOMEntry;
|
use App\Entity\ProjectSystem\ProjectBOMEntry;
|
||||||
|
use App\Form\ProjectSystem\ProjectAddPartsType;
|
||||||
use App\Form\ProjectSystem\ProjectBOMEntryCollectionType;
|
use App\Form\ProjectSystem\ProjectBOMEntryCollectionType;
|
||||||
use App\Form\ProjectSystem\ProjectBuildType;
|
use App\Form\ProjectSystem\ProjectBuildType;
|
||||||
use App\Form\Type\StructuralEntityType;
|
use App\Form\Type\StructuralEntityType;
|
||||||
use App\Helpers\Projects\ProjectBuildRequest;
|
use App\Helpers\Projects\ProjectBuildRequest;
|
||||||
use App\Services\ImportExportSystem\BOMImporter;
|
use App\Services\ImportExportSystem\BOMImporter;
|
||||||
use App\Services\ProjectSystem\ProjectBuildHelper;
|
use App\Services\ProjectSystem\ProjectBuildHelper;
|
||||||
|
use App\Validator\Constraints\UniqueObjectCollection;
|
||||||
use Doctrine\Common\Collections\ArrayCollection;
|
use Doctrine\Common\Collections\ArrayCollection;
|
||||||
use Doctrine\ORM\EntityManagerInterface;
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
use League\Csv\SyntaxError;
|
use League\Csv\SyntaxError;
|
||||||
use Omines\DataTablesBundle\DataTableFactory;
|
use Omines\DataTablesBundle\DataTableFactory;
|
||||||
|
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
|
||||||
|
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntityValidator;
|
||||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||||
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
|
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
|
||||||
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
|
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
|
||||||
use Symfony\Component\Form\Extension\Core\Type\FileType;
|
use Symfony\Component\Form\Extension\Core\Type\FileType;
|
||||||
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
|
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
|
||||||
|
use Symfony\Component\Form\FormEvents;
|
||||||
use Symfony\Component\HttpFoundation\Request;
|
use Symfony\Component\HttpFoundation\Request;
|
||||||
use Symfony\Component\HttpFoundation\Response;
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
use Symfony\Component\Routing\Annotation\Route;
|
use Symfony\Component\Routing\Annotation\Route;
|
||||||
|
@ -201,19 +206,10 @@ class ProjectController extends AbstractController
|
||||||
$this->denyAccessUnlessGranted('@projects.edit');
|
$this->denyAccessUnlessGranted('@projects.edit');
|
||||||
}
|
}
|
||||||
|
|
||||||
$builder = $this->createFormBuilder();
|
$form = $this->createForm(ProjectAddPartsType::class, null, [
|
||||||
$builder->add('project', StructuralEntityType::class, [
|
'project' => $project,
|
||||||
'class' => Project::class,
|
|
||||||
'required' => true,
|
|
||||||
'disabled' => $project instanceof Project, //If a project is given, disable the field
|
|
||||||
'data' => $project,
|
|
||||||
'constraints' => [
|
|
||||||
new NotNull()
|
|
||||||
]
|
|
||||||
]);
|
]);
|
||||||
$builder->add('bom_entries', ProjectBOMEntryCollectionType::class);
|
|
||||||
$builder->add('submit', SubmitType::class, ['label' => 'save']);
|
|
||||||
$form = $builder->getForm();
|
|
||||||
|
|
||||||
//Preset the BOM entries with the selected parts, when the form was not submitted yet
|
//Preset the BOM entries with the selected parts, when the form was not submitted yet
|
||||||
$preset_data = new ArrayCollection();
|
$preset_data = new ArrayCollection();
|
||||||
|
@ -249,8 +245,11 @@ class ProjectController extends AbstractController
|
||||||
foreach ($bom_entries as $bom_entry){
|
foreach ($bom_entries as $bom_entry){
|
||||||
$target_project->addBOMEntry($bom_entry);
|
$target_project->addBOMEntry($bom_entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
$entityManager->flush();
|
$entityManager->flush();
|
||||||
|
|
||||||
|
|
||||||
//If a redirect query parameter is set, redirect to this page
|
//If a redirect query parameter is set, redirect to this page
|
||||||
if ($request->query->get('_redirect')) {
|
if ($request->query->get('_redirect')) {
|
||||||
return $this->redirect($request->query->get('_redirect'));
|
return $this->redirect($request->query->get('_redirect'));
|
||||||
|
|
84
src/Form/ProjectSystem/ProjectAddPartsType.php
Normal file
84
src/Form/ProjectSystem/ProjectAddPartsType.php
Normal file
|
@ -0,0 +1,84 @@
|
||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* This file is part of Part-DB (https://github.com/Part-DB/Part-DB-symfony).
|
||||||
|
*
|
||||||
|
* Copyright (C) 2019 - 2023 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace App\Form\ProjectSystem;
|
||||||
|
|
||||||
|
use App\Entity\ProjectSystem\Project;
|
||||||
|
use App\Entity\ProjectSystem\ProjectBOMEntry;
|
||||||
|
use App\Form\Type\StructuralEntityType;
|
||||||
|
use App\Validator\Constraints\UniqueObjectCollection;
|
||||||
|
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
|
||||||
|
use Symfony\Component\Form\AbstractType;
|
||||||
|
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
|
||||||
|
use Symfony\Component\Form\FormBuilderInterface;
|
||||||
|
use Symfony\Component\Form\FormEvent;
|
||||||
|
use Symfony\Component\Form\FormEvents;
|
||||||
|
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||||
|
use Symfony\Component\Validator\Constraints\NotNull;
|
||||||
|
|
||||||
|
class ProjectAddPartsType extends AbstractType
|
||||||
|
{
|
||||||
|
public function buildForm(FormBuilderInterface $builder, array $options)
|
||||||
|
{
|
||||||
|
$builder->add('project', StructuralEntityType::class, [
|
||||||
|
'class' => Project::class,
|
||||||
|
'required' => true,
|
||||||
|
'disabled' => $options['project'] instanceof Project, //If a project is given, disable the field
|
||||||
|
'data' => $options['project'],
|
||||||
|
'constraints' => [
|
||||||
|
new NotNull()
|
||||||
|
]
|
||||||
|
]);
|
||||||
|
$builder->add('bom_entries', ProjectBOMEntryCollectionType::class, [
|
||||||
|
'entry_options' => [
|
||||||
|
'constraints' => [
|
||||||
|
new UniqueEntity(fields: ['part', 'project'], entityClass: ProjectBOMEntry::class, message: 'project.bom_entry.part_already_in_bom'),
|
||||||
|
new UniqueEntity(fields: ['name', 'project'], entityClass: ProjectBOMEntry::class, message: 'project.bom_entry.name_already_in_bom', ignoreNull: true),
|
||||||
|
]
|
||||||
|
],
|
||||||
|
'constraints' => [
|
||||||
|
new UniqueObjectCollection(fields: ['part'], message: 'project.bom_entry.part_already_in_bom'),
|
||||||
|
new UniqueObjectCollection(fields: ['name'], message: 'project.bom_entry.name_already_in_bom'),
|
||||||
|
]
|
||||||
|
]);
|
||||||
|
$builder->add('submit', SubmitType::class, ['label' => 'save']);
|
||||||
|
|
||||||
|
//After submit set the project for all bom entries, so that it can be validated properly
|
||||||
|
$builder->addEventListener(FormEvents::SUBMIT, function (FormEvent $event) {
|
||||||
|
$form = $event->getForm();
|
||||||
|
/** @var Project $project */
|
||||||
|
$project = $form->get('project')->getData();
|
||||||
|
$bom_entries = $form->get('bom_entries')->getData();
|
||||||
|
|
||||||
|
foreach ($bom_entries as $bom_entry) {
|
||||||
|
$bom_entry->setProject($project);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public function configureOptions(OptionsResolver $resolver)
|
||||||
|
{
|
||||||
|
$resolver->setDefaults([
|
||||||
|
'project' => null,
|
||||||
|
]);
|
||||||
|
|
||||||
|
$resolver->setAllowedTypes('project', ['null', Project::class]);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue