diff --git a/composer.json b/composer.json index a47bd12a..d3ff4d39 100644 --- a/composer.json +++ b/composer.json @@ -21,6 +21,7 @@ "doctrine/doctrine-migrations-bundle": "^3.0", "doctrine/orm": "^2.16", "dompdf/dompdf": "dev-master#87bea32efe0b0db309e1d31537201f64d5508280 as v2.0.3", + "dunglas/doctrine-json-odm": "^1.3", "erusev/parsedown": "^1.7", "florianv/swap": "^4.0", "florianv/swap-bundle": "dev-master", diff --git a/composer.lock b/composer.lock index 13a67773..01b26199 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "258be26a5e5d25abc80062849a2a948e", + "content-hash": "8a469df5900d883cd5b7ad6944ded916", "packages": [ { "name": "api-platform/core", @@ -2046,6 +2046,88 @@ }, "time": "2023-11-17T21:30:00+00:00" }, + { + "name": "dunglas/doctrine-json-odm", + "version": "v1.3.0", + "source": { + "type": "git", + "url": "https://github.com/dunglas/doctrine-json-odm.git", + "reference": "d729dc37fa7aaddb7658c52020678cc5294387f1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/dunglas/doctrine-json-odm/zipball/d729dc37fa7aaddb7658c52020678cc5294387f1", + "reference": "d729dc37fa7aaddb7658c52020678cc5294387f1", + "shasum": "" + }, + "require": { + "doctrine/orm": "^2.6.3", + "php": ">=7.1", + "symfony/property-access": "^4.4 || ^5.4 || ^6.0", + "symfony/property-info": "^4.4 || ^5.4 || ^6.0", + "symfony/serializer": "^4.4 || ^5.4 || ^6.0" + }, + "require-dev": { + "doctrine/annotations": "^1.0", + "doctrine/dbal": "^2.7 || ^3.3", + "doctrine/doctrine-bundle": "^1.12.13 || ^2.2", + "symfony/finder": "^4.4 || ^5.4 || ^6.0", + "symfony/framework-bundle": "^4.4 || ^5.4 || ^6.0", + "symfony/phpunit-bridge": "^6.0" + }, + "suggest": { + "scienta/doctrine-json-functions": "To add support for JSON functions in DQL.", + "symfony/framework-bundle": "To use the provided bundle." + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Dunglas\\DoctrineJsonOdm\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Kévin Dunglas", + "email": "kevin@dunglas.fr", + "homepage": "https://dunglas.fr" + } + ], + "description": "An object document mapper for Doctrine ORM using JSON types of modern RDBMS.", + "homepage": "https://dunglas.fr", + "keywords": [ + "database", + "json", + "mysql", + "odm", + "orm", + "postgresql", + "rdbms" + ], + "support": { + "issues": "https://github.com/dunglas/doctrine-json-odm/issues", + "source": "https://github.com/dunglas/doctrine-json-odm/tree/v1.3.0" + }, + "funding": [ + { + "url": "https://github.com/dunglas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/dunglas/doctrine-json-odm", + "type": "tidelift" + } + ], + "time": "2023-02-23T15:22:16+00:00" + }, { "name": "egulias/email-validator", "version": "4.0.2", diff --git a/config/bundles.php b/config/bundles.php index 70b10fa5..4dd085a7 100644 --- a/config/bundles.php +++ b/config/bundles.php @@ -33,4 +33,5 @@ return [ KnpU\OAuth2ClientBundle\KnpUOAuth2ClientBundle::class => ['all' => true], Nelmio\CorsBundle\NelmioCorsBundle::class => ['all' => true], ApiPlatform\Symfony\Bundle\ApiPlatformBundle::class => ['all' => true], + Dunglas\DoctrineJsonOdm\Bundle\DunglasDoctrineJsonOdmBundle::class => ['all' => true], ]; diff --git a/migrations/Version20231129231240.php b/migrations/Version20231129231240.php new file mode 100644 index 00000000..676da4fb --- /dev/null +++ b/migrations/Version20231129231240.php @@ -0,0 +1,36 @@ +addSql('ALTER TABLE categories ADD eda_info JSON NOT NULL COMMENT \'(DC2Type:json_document)\''); + $this->addSql('ALTER TABLE footprints ADD eda_info JSON NOT NULL COMMENT \'(DC2Type:json_document)\''); + $this->addSql('ALTER TABLE parts ADD eda_info JSON NOT NULL COMMENT \'(DC2Type:json_document)\''); + + } + + public function down(Schema $schema): void + { + // this down() migration is auto-generated, please modify it to your needs + $this->addSql('ALTER TABLE `categories` DROP eda_info'); + $this->addSql('ALTER TABLE `footprints` DROP eda_info'); + $this->addSql('ALTER TABLE `parts` DROP eda_info'); + } +} diff --git a/src/Entity/EDA/EDAPartInfo.php b/src/Entity/EDA/EDAPartInfo.php new file mode 100644 index 00000000..731ffcef --- /dev/null +++ b/src/Entity/EDA/EDAPartInfo.php @@ -0,0 +1,143 @@ +. + */ + +declare(strict_types=1); + + +namespace App\Entity\EDA; + +class EDAPartInfo +{ + /** + * @var string|null The reference prefix of the Part in the schematic. E.g. "R" for resistors, or "C" for capacitors. + */ + private ?string $reference_prefix = null; + /** @var string|null The value, which should be shown together with the part (e.g. 470 for a 470 Ohm resistor) */ + private ?string $value = null; + /** @var bool|null If this is true, then this part is invisible for the EDA software */ + private ?bool $invisible = null; + + /** @var bool|null If this is set to true, then this part will be excluded from the BOM */ + private ?bool $exclude_from_bom = null; + /** @var bool|null If this is set to true, then this part will be excluded from the board/the PCB */ + private ?bool $exclude_from_board = null; + /** @var bool|null If this is set to true, then this part will be excluded in the simulation */ + private ?bool $exclude_from_sim = true; + /** @var string|null The KiCAD schematic symbol, which should be used (the path to the library) */ + private ?string $kicad_symbol = null; + /** @var string|null The KiCAD footprint, which should be used (the path to the library) */ + private ?string $kicad_footprint = null; + + public function __construct( + + ) { + + } + + public function getReferencePrefix(): ?string + { + return $this->reference_prefix; + } + + public function setReferencePrefix(?string $reference_prefix): EDAPartInfo + { + $this->reference_prefix = $reference_prefix; + return $this; + } + + public function getValue(): ?string + { + return $this->value; + } + + public function setValue(?string $value): EDAPartInfo + { + $this->value = $value; + return $this; + } + + public function getInvisible(): ?bool + { + return $this->invisible; + } + + public function setInvisible(?bool $invisible): EDAPartInfo + { + $this->invisible = $invisible; + return $this; + } + + public function getExcludeFromBom(): ?bool + { + return $this->exclude_from_bom; + } + + public function setExcludeFromBom(?bool $exclude_from_bom): EDAPartInfo + { + $this->exclude_from_bom = $exclude_from_bom; + return $this; + } + + public function getExcludeFromBoard(): ?bool + { + return $this->exclude_from_board; + } + + public function setExcludeFromBoard(?bool $exclude_from_board): EDAPartInfo + { + $this->exclude_from_board = $exclude_from_board; + return $this; + } + + public function getExcludeFromSim(): ?bool + { + return $this->exclude_from_sim; + } + + public function setExcludeFromSim(?bool $exclude_from_sim): EDAPartInfo + { + $this->exclude_from_sim = $exclude_from_sim; + return $this; + } + + public function getKicadSymbol(): ?string + { + return $this->kicad_symbol; + } + + public function setKicadSymbol(?string $kicad_symbol): EDAPartInfo + { + $this->kicad_symbol = $kicad_symbol; + return $this; + } + + public function getKicadFootprint(): ?string + { + return $this->kicad_footprint; + } + + public function setKicadFootprint(?string $kicad_footprint): EDAPartInfo + { + $this->kicad_footprint = $kicad_footprint; + return $this; + } + + +} \ No newline at end of file diff --git a/src/Entity/Parts/Category.php b/src/Entity/Parts/Category.php index 95e2295c..2751db79 100644 --- a/src/Entity/Parts/Category.php +++ b/src/Entity/Parts/Category.php @@ -38,6 +38,7 @@ use ApiPlatform\OpenApi\Model\Operation; use ApiPlatform\Serializer\Filter\PropertyFilter; use App\ApiPlatform\Filter\LikeFilter; use App\Entity\Attachments\Attachment; +use App\Entity\EDA\EDAPartInfo; use App\Repository\Parts\CategoryRepository; use Doctrine\DBAL\Types\Types; use Doctrine\Common\Collections\ArrayCollection; @@ -47,6 +48,7 @@ use App\Entity\Base\AbstractStructuralDBElement; use App\Entity\Parameters\CategoryParameter; use Doctrine\Common\Collections\Collection; use Doctrine\ORM\Mapping as ORM; +use Doctrine\ORM\Mapping\Column; use Symfony\Component\Serializer\Annotation\Groups; use Symfony\Component\Validator\Constraints as Assert; @@ -185,6 +187,8 @@ class Category extends AbstractPartsContainingDBElement #[Groups(['category:read'])] protected ?\DateTimeInterface $lastModified = null; + #[Column(type: 'json_document', options: ['jsonb' => true])] + protected ?EDAPartInfo $eda_info = null; public function getPartnameHint(): string { diff --git a/src/Entity/Parts/Footprint.php b/src/Entity/Parts/Footprint.php index c3f70087..be00d162 100644 --- a/src/Entity/Parts/Footprint.php +++ b/src/Entity/Parts/Footprint.php @@ -39,6 +39,7 @@ use ApiPlatform\Serializer\Filter\PropertyFilter; use App\ApiPlatform\Filter\LikeFilter; use App\Entity\Attachments\Attachment; use App\Entity\Attachments\AttachmentTypeAttachment; +use App\Entity\EDA\EDAPartInfo; use App\Repository\Parts\FootprintRepository; use App\Entity\Base\AbstractStructuralDBElement; use Doctrine\Common\Collections\ArrayCollection; @@ -47,6 +48,7 @@ use App\Entity\Base\AbstractPartsContainingDBElement; use App\Entity\Parameters\FootprintParameter; use Doctrine\Common\Collections\Collection; use Doctrine\ORM\Mapping as ORM; +use Doctrine\ORM\Mapping\Column; use Symfony\Component\Serializer\Annotation\Groups; use Symfony\Component\Validator\Constraints as Assert; @@ -137,6 +139,8 @@ class Footprint extends AbstractPartsContainingDBElement #[Groups(['footprint:read'])] protected ?\DateTimeInterface $lastModified = null; + #[Column(type: 'json_document', options: ['jsonb' => true])] + protected ?EDAPartInfo $eda_info = null; /**************************************** * Getters diff --git a/src/Entity/Parts/Part.php b/src/Entity/Parts/Part.php index 9f7cda95..61c8d821 100644 --- a/src/Entity/Parts/Part.php +++ b/src/Entity/Parts/Part.php @@ -42,6 +42,7 @@ use App\ApiPlatform\Filter\LikeFilter; use App\ApiPlatform\Filter\PartStoragelocationFilter; use App\Entity\Attachments\AttachmentTypeAttachment; use App\Entity\Parts\PartTraits\AssociationTrait; +use App\Entity\Parts\PartTraits\EDATrait; use App\Repository\PartRepository; use Doctrine\DBAL\Types\Types; use App\Entity\Attachments\Attachment; @@ -115,6 +116,7 @@ class Part extends AttachmentContainingDBElement use ParametersTrait; use ProjectTrait; use AssociationTrait; + use EDATrait; /** @var Collection */ diff --git a/src/Entity/Parts/PartTraits/EDATrait.php b/src/Entity/Parts/PartTraits/EDATrait.php new file mode 100644 index 00000000..134d3141 --- /dev/null +++ b/src/Entity/Parts/PartTraits/EDATrait.php @@ -0,0 +1,51 @@ +. + */ + +declare(strict_types=1); + + +namespace App\Entity\Parts\PartTraits; + +use App\Entity\EDA\EDAPartInfo; +use Doctrine\ORM\Mapping\Column; +use Symfony\Component\Validator\Constraints\Valid; + +trait EDATrait +{ + #[Column(type: 'json_document', options: ['jsonb' => true])] + #[Valid] + protected ?EDAPartInfo $eda_info = null; + + public function getEdaInfo(): ?EDAPartInfo + { + return $this->eda_info; + } + + public function setEdaInfo(?EDAPartInfo $eda_info): self + { + if ($eda_info !== null) { + //Do a clone, to ensure that the property is updated in the database + $eda_info = clone $eda_info; + } + + $this->eda_info = $eda_info; + return $this; + } +} \ No newline at end of file diff --git a/src/Form/Part/EDAPartInfoType.php b/src/Form/Part/EDAPartInfoType.php new file mode 100644 index 00000000..af4732f2 --- /dev/null +++ b/src/Form/Part/EDAPartInfoType.php @@ -0,0 +1,56 @@ +. + */ + +declare(strict_types=1); + + +namespace App\Form\Part; + +use App\Entity\EDA\EDAPartInfo; +use App\Entity\Parts\PartAssociation; +use App\Form\Type\TriStateCheckboxType; +use Symfony\Component\Form\AbstractType; +use Symfony\Component\Form\Extension\Core\Type\TextType; +use Symfony\Component\Form\FormBuilderInterface; +use Symfony\Component\OptionsResolver\OptionsResolver; + +class EDAPartInfoType extends AbstractType +{ + public function buildForm(FormBuilderInterface $builder, array $options): void + { + $builder + ->add('reference_prefix', TextType::class) + ->add('value', TextType::class) + ->add('invisible', TriStateCheckboxType::class) + ->add('exclude_from_bom', TriStateCheckboxType::class) + ->add('exclude_from_board', TriStateCheckboxType::class) + ->add('exclude_from_sim', TriStateCheckboxType::class) + ->add('kicad_symbol', TextType::class) + ->add('kicad_footprint', TextType::class) + ; + } + + public function configureOptions(OptionsResolver $resolver): void + { + $resolver->setDefaults([ + 'data_class' => EDAPartInfo::class, + ]); + } +} \ No newline at end of file diff --git a/src/Form/Part/PartBaseType.php b/src/Form/Part/PartBaseType.php index f7243e64..a36c6484 100644 --- a/src/Form/Part/PartBaseType.php +++ b/src/Form/Part/PartBaseType.php @@ -22,6 +22,7 @@ declare(strict_types=1); namespace App\Form\Part; +use App\Entity\EDA\EDAPartInfo; use App\Entity\Parts\ManufacturingStatus; use App\Services\InfoProviderSystem\DTOs\PartDetailDTO; use Symfony\Bundle\SecurityBundle\Security; @@ -255,6 +256,13 @@ class PartBaseType extends AbstractType 'by_reference' => false, ]); + //EDA info + $builder->add('eda_info', EDAPartInfoType::class, [ + 'label' => false, + 'required' => false, + 'setter' => fn (Part $part, ?EDAPartInfo $x) => $part->setEdaInfo($x), + ]); + $builder->add('log_comment', TextType::class, [ 'label' => 'edit.log_comment', 'mapped' => false, diff --git a/symfony.lock b/symfony.lock index 72f5ec4d..7fe0957f 100644 --- a/symfony.lock +++ b/symfony.lock @@ -152,6 +152,15 @@ "dompdf/dompdf": { "version": "v0.8.5" }, + "dunglas/doctrine-json-odm": { + "version": "1.3", + "recipe": { + "repo": "github.com/symfony/recipes-contrib", + "branch": "main", + "version": "0.1", + "ref": "c2ab78f625df0c89af5908d50a28602ff8c4919f" + } + }, "egulias/email-validator": { "version": "2.1.11" },