Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 16 additions & 6 deletions src/Services/EDA/KiCadHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ public function getCategoryParts(?Category $category, bool $minimal = false): ar
{
$cacheKey = 'kicad_category_parts_'.($category?->getID() ?? 0) . '_' . $this->category_depth . ($minimal ? '_min' : '');
return $this->kicadCache->get($cacheKey,
function (ItemInterface $item) use ($category) {
function (ItemInterface $item) use ($category, $minimal) {
$item->tag([
$this->tagGenerator->getElementTypeCacheTag(Category::class),
$this->tagGenerator->getElementTypeCacheTag(Part::class),
Expand Down Expand Up @@ -182,11 +182,21 @@ function (ItemInterface $item) use ($category) {
continue;
}

$result[] = [
'id' => (string)$part->getId(),
'name' => $part->getName(),
'description' => $part->getDescription(),
];
//A minimal listing carries just enough to populate the chooser's
//name column. Otherwise inline the same record the per-part
//endpoint returns: KiCad skips its follow-up request for every
//part whose listing entry already carries a "fields" object
//(see HTTP_LIB_CONNECTION::SelectAll), which turns a cold library
//open from one request per part into one request per category.
if ($minimal) {
$result[] = [
'id' => (string)$part->getId(),
'name' => $part->getName(),
'description' => $part->getDescription(),
];
} else {
$result[] = $this->getKiCADPart($part);
}
}

return $result;
Expand Down
53 changes: 53 additions & 0 deletions tests/Services/EDA/KiCadHelperTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -632,4 +632,57 @@ public function testParameterWithEmptyNameIsSkipped(): void
// Empty-named parameter should not appear
self::assertArrayNotHasKey('', $result['fields']);
}

/**
* Category 1 (from fixtures) has a KiCad symbol set, so its parts are visible to the EDA.
* The listing must carry the fields, so KiCad does not have to request each part separately.
*/
public function testCategoryPartsListingContainsFields(): void
{
$category = $this->em->find(Category::class, 1);

$result = $this->helper->getCategoryParts($category);

self::assertNotEmpty($result);
foreach ($result as $part) {
self::assertArrayHasKey('fields', $part);
self::assertIsArray($part['fields']);
//Every part gets at least these, either from itself or from its category
self::assertArrayHasKey('reference', $part['fields']);
self::assertArrayHasKey('value', $part['fields']);
self::assertArrayHasKey('footprint', $part['fields']);
self::assertArrayHasKey('symbolIdStr', $part);
}
}

/**
* The minimal listing stays minimal: id, name and description only.
*/
public function testMinimalCategoryPartsListingContainsNoFields(): void
{
$category = $this->em->find(Category::class, 1);

$result = $this->helper->getCategoryParts($category, true);

self::assertNotEmpty($result);
foreach ($result as $part) {
self::assertSame(['id', 'name', 'description'], array_keys($part));
}
}

/**
* The minimal and the full listing must describe the same parts, in the same order.
*/
public function testMinimalAndFullCategoryPartsListingsAgreeOnParts(): void
{
$category = $this->em->find(Category::class, 1);

$minimal = $this->helper->getCategoryParts($category, true);
$full = $this->helper->getCategoryParts($category);

self::assertSame(
array_column($minimal, 'id'),
array_column($full, 'id')
);
}
}