diff --git a/config/packages/security.yaml b/config/packages/security.yaml index c2241f08..dab2b5dd 100644 --- a/config/packages/security.yaml +++ b/config/packages/security.yaml @@ -71,3 +71,5 @@ security: - { path: "^/\\w{2}/tree", role: PUBLIC_ACCESS } # Restrict access to API to users, which has the API access permission - { path: "^/api", allow_if: 'is_granted("@api.access_api") and is_authenticated()' } + # Restrict access to KICAD to users, which has API access permission + - { path: "^/kicad-api", allow_if: 'is_granted("@api.access_api") and is_authenticated()' } diff --git a/src/Controller/KiCADAPIController.php b/src/Controller/KiCADAPIController.php new file mode 100644 index 00000000..46d05c47 --- /dev/null +++ b/src/Controller/KiCADAPIController.php @@ -0,0 +1,121 @@ +. + */ + +declare(strict_types=1); + + +namespace App\Controller; + +use App\Entity\Parts\Category; +use App\Entity\Parts\Part; +use App\Services\Trees\NodesListBuilder; +use Doctrine\ORM\EntityManagerInterface; +use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; +use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Routing\Annotation\Route; + +#[Route('/kicad-api/v1')] +class KiCADAPIController extends AbstractController +{ + public function __construct(private readonly EntityManagerInterface $em) + { + + } + + #[Route('/', name: 'kicad_api_root')] + public function root(): Response + { + //The API documentation says this can be either blank or the URL to the endpoints + return $this->json([ + 'categories' => '', + 'parts' => '', + ]); + } + + #[Route('/categories.json', name: 'kicad_api_categories')] + public function categories(NodesListBuilder $nodesListBuilder): Response + { + $categories = $nodesListBuilder->typeToNodesList(Category::class); + $result = []; + foreach ($categories as $category) { + $result[] = [ + 'id' => (string) $category->getId(), + 'name' => $category->getFullPath('/'), + ]; + } + + return $this->json($result); + } + + #[Route('/parts/category/{category}.json', name: 'kicad_api_category')] + public function categoryParts(Category $category): Response + { + $category_repo = $this->em->getRepository(Category::class); + $parts = $category_repo->getParts($category); + + $result = []; + foreach ($parts as $part) { + $result[] = [ + 'id' => (string) $part->getId(), + 'name' => $part->getName(), + 'description' => $part->getDescription(), + ]; + } + + return $this->json($result); + } + + #[Route('/parts/{part}.json', name: 'kicad_api_part')] + public function partDetails(Part $part): Response + { + return $this->json($this->partToKiCADPart($part)); + } + + private function partToKiCADPart(Part $part): array + { + $result = [ + 'id' => (string) $part->getId(), + 'name' => $part->getName(), + "symbolIdStr" => "Device:R", + "exclude_from_bom" => "False", + "exclude_from_board" => "False", + "exclude_from_sim" => "True", + "fields" => [] + ]; + + //Add misc fields + $result["fields"]["description"] = $this->createValue($part->getDescription()); + $result["fields"]["value"] = $this->createValue($part->getName(), true); + $result["fields"]["keywords"] = $this->createValue($part->getTags()); + if ($part->getManufacturer()) { + $result["fields"]["manufacturer"] = $this->createValue($part->getManufacturer()->getName()); + } + + return $result; + } + + private function createValue(string|int|float $value, bool $visible = false): array + { + return [ + 'value' => (string) $value, + 'visible' => $visible ? 'True' : 'False', + ]; + } +} \ No newline at end of file