Modified the DigiKey Provider to works with the V4 API (#875)

* Modified the DigiKey Provider to works with the V4 API

* Correclty apply the MarketPlaceFilter option to digikey v4 API

* Show the packe type (Tape&Reel, Box, etc.) as footprint in digikey provider search

---------

Co-authored-by: Jan Böhmer <mail@jan-boehmer.de>
This commit is contained in:
Daniel Carrasco 2025-03-27 21:26:18 +01:00 committed by GitHub
parent 7275db27e7
commit d3b225771c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -108,12 +108,15 @@ class DigikeyProvider implements InfoProviderInterface
{ {
$request = [ $request = [
'Keywords' => $keyword, 'Keywords' => $keyword,
'RecordCount' => 50, 'Limit' => 50,
'RecordStartPosition' => 0, 'Offset' => 0,
'ExcludeMarketPlaceProducts' => 'true', 'FilterOptionsRequest' => [
'MarketPlaceFilter' => 'ExcludeMarketPlace',
],
]; ];
$response = $this->digikeyClient->request('POST', '/Search/v3/Products/Keyword', [ //$response = $this->digikeyClient->request('POST', '/Search/v3/Products/Keyword', [
$response = $this->digikeyClient->request('POST', '/products/v4/search/keyword', [
'json' => $request, 'json' => $request,
'auth_bearer' => $this->authTokenManager->getAlwaysValidTokenString(self::OAUTH_APP_NAME) 'auth_bearer' => $this->authTokenManager->getAlwaysValidTokenString(self::OAUTH_APP_NAME)
]); ]);
@ -124,18 +127,21 @@ class DigikeyProvider implements InfoProviderInterface
$result = []; $result = [];
$products = $response_array['Products']; $products = $response_array['Products'];
foreach ($products as $product) { foreach ($products as $product) {
$result[] = new SearchResultDTO( foreach ($product['ProductVariations'] as $variation) {
provider_key: $this->getProviderKey(), $result[] = new SearchResultDTO(
provider_id: $product['DigiKeyPartNumber'], provider_key: $this->getProviderKey(),
name: $product['ManufacturerPartNumber'], provider_id: $variation['DigiKeyProductNumber'],
description: $product['DetailedDescription'] ?? $product['ProductDescription'], name: $product['ManufacturerProductNumber'],
category: $this->getCategoryString($product), description: $product['Description']['DetailedDescription'] ?? $product['Description']['ProductDescription'],
manufacturer: $product['Manufacturer']['Value'] ?? null, category: $this->getCategoryString($product),
mpn: $product['ManufacturerPartNumber'], manufacturer: $product['Manufacturer']['Name'] ?? null,
preview_image_url: $product['PrimaryPhoto'] ?? null, mpn: $product['ManufacturerProductNumber'],
manufacturing_status: $this->productStatusToManufacturingStatus($product['ProductStatus']), preview_image_url: $product['PhotoUrl'] ?? null,
provider_url: $product['ProductUrl'], manufacturing_status: $this->productStatusToManufacturingStatus($product['ProductStatus']['Id']),
); provider_url: $product['ProductUrl'],
footprint: $variation['PackageType']['Name'], //Use the footprint field, to show the user the package type (Tape & Reel, etc., as digikey has many different package types)
);
}
} }
return $result; return $result;
@ -143,32 +149,42 @@ class DigikeyProvider implements InfoProviderInterface
public function getDetails(string $id): PartDetailDTO public function getDetails(string $id): PartDetailDTO
{ {
$response = $this->digikeyClient->request('GET', '/Search/v3/Products/' . urlencode($id), [ $response = $this->digikeyClient->request('GET', '/products/v4/search/' . urlencode($id) . '/productdetails', [
'auth_bearer' => $this->authTokenManager->getAlwaysValidTokenString(self::OAUTH_APP_NAME) 'auth_bearer' => $this->authTokenManager->getAlwaysValidTokenString(self::OAUTH_APP_NAME)
]); ]);
$product = $response->toArray(); $response_array = $response->toArray();
$product = $response_array['Product'];
$footprint = null; $footprint = null;
$parameters = $this->parametersToDTOs($product['Parameters'] ?? [], $footprint); $parameters = $this->parametersToDTOs($product['Parameters'] ?? [], $footprint);
$media = $this->mediaToDTOs($product['MediaLinks']); $media = $this->mediaToDTOs($id);
// Get the price_breaks of the selected variation
$price_breaks = [];
foreach ($product['ProductVariations'] as $variation) {
if ($variation['DigiKeyProductNumber'] == $id) {
$price_breaks = $variation['StandardPricing'] ?? [];
break;
}
}
return new PartDetailDTO( return new PartDetailDTO(
provider_key: $this->getProviderKey(), provider_key: $this->getProviderKey(),
provider_id: $product['DigiKeyPartNumber'], provider_id: $id,
name: $product['ManufacturerPartNumber'], name: $product['ManufacturerProductNumber'],
description: $product['DetailedDescription'] ?? $product['ProductDescription'], description: $product['Description']['DetailedDescription'] ?? $product['Description']['ProductDescription'],
category: $this->getCategoryString($product), category: $this->getCategoryString($product),
manufacturer: $product['Manufacturer']['Value'] ?? null, manufacturer: $product['Manufacturer']['Name'] ?? null,
mpn: $product['ManufacturerPartNumber'], mpn: $product['ManufacturerProductNumber'],
preview_image_url: $product['PrimaryPhoto'] ?? null, preview_image_url: $product['PhotoUrl'] ?? null,
manufacturing_status: $this->productStatusToManufacturingStatus($product['ProductStatus']), manufacturing_status: $this->productStatusToManufacturingStatus($product['ProductStatus']['Id']),
provider_url: $product['ProductUrl'], provider_url: $product['ProductUrl'],
footprint: $footprint, footprint: $footprint,
datasheets: $media['datasheets'], datasheets: $media['datasheets'],
images: $media['images'], images: $media['images'],
parameters: $parameters, parameters: $parameters,
vendor_infos: $this->pricingToDTOs($product['StandardPricing'] ?? [], $product['DigiKeyPartNumber'], $product['ProductUrl']), vendor_infos: $this->pricingToDTOs($price_breaks, $id, $product['ProductUrl']),
); );
} }
@ -177,28 +193,35 @@ class DigikeyProvider implements InfoProviderInterface
* @param string|null $dk_status * @param string|null $dk_status
* @return ManufacturingStatus|null * @return ManufacturingStatus|null
*/ */
private function productStatusToManufacturingStatus(?string $dk_status): ?ManufacturingStatus private function productStatusToManufacturingStatus(?int $dk_status): ?ManufacturingStatus
{ {
// The V4 can use strings to get the status, but if you have changed the PROVIDER_DIGIKEY_LANGUAGE it will not match.
// Using the Id instead which should be fixed.
//
// The API is not well documented and the ID are not there yet, so were extracted using "trial and error".
// The 'Preliminary' id was not found in several categories so I was unable to extract it. Disabled for now.
return match ($dk_status) { return match ($dk_status) {
null => null, null => null,
'Active' => ManufacturingStatus::ACTIVE, 0 => ManufacturingStatus::ACTIVE,
'Obsolete' => ManufacturingStatus::DISCONTINUED, 1 => ManufacturingStatus::DISCONTINUED,
'Discontinued at Digi-Key', 'Last Time Buy' => ManufacturingStatus::EOL, 2, 4 => ManufacturingStatus::EOL,
'Not For New Designs' => ManufacturingStatus::NRFND, 7 => ManufacturingStatus::NRFND,
'Preliminary' => ManufacturingStatus::ANNOUNCED, //'Preliminary' => ManufacturingStatus::ANNOUNCED,
default => ManufacturingStatus::NOT_SET, default => ManufacturingStatus::NOT_SET,
}; };
} }
private function getCategoryString(array $product): string private function getCategoryString(array $product): string
{ {
$category = $product['Category']['Value']; $category = $product['Category']['Name'];
$sub_category = $product['Family']['Value']; $sub_category = current($product['Category']['ChildCategories']);
//Replace the ' - ' category separator with ' -> ' if ($sub_category) {
$sub_category = str_replace(' - ', ' -> ', $sub_category); //Replace the ' - ' category separator with ' -> '
$category = $category . ' -> ' . str_replace(' - ', ' -> ', $sub_category["Name"]);
}
return $category . ' -> ' . $sub_category; return $category;
} }
/** /**
@ -215,18 +238,18 @@ class DigikeyProvider implements InfoProviderInterface
foreach ($parameters as $parameter) { foreach ($parameters as $parameter) {
if ($parameter['ParameterId'] === 1291) { //Meaning "Manufacturer given footprint" if ($parameter['ParameterId'] === 1291) { //Meaning "Manufacturer given footprint"
$footprint_name = $parameter['Value']; $footprint_name = $parameter['ValueText'];
} }
if (in_array(trim((string) $parameter['Value']), ['', '-'], true)) { if (in_array(trim((string) $parameter['ValueText']), ['', '-'], true)) {
continue; continue;
} }
//If the parameter was marked as text only, then we do not try to parse it as a numerical value //If the parameter was marked as text only, then we do not try to parse it as a numerical value
if (in_array($parameter['ParameterId'], self::TEXT_ONLY_PARAMETERS, true)) { if (in_array($parameter['ParameterId'], self::TEXT_ONLY_PARAMETERS, true)) {
$results[] = new ParameterDTO(name: $parameter['Parameter'], value_text: $parameter['Value']); $results[] = new ParameterDTO(name: $parameter['ParameterText'], value_text: $parameter['ValueText']);
} else { //Otherwise try to parse it as a numerical value } else { //Otherwise try to parse it as a numerical value
$results[] = ParameterDTO::parseValueIncludingUnit($parameter['Parameter'], $parameter['Value']); $results[] = ParameterDTO::parseValueIncludingUnit($parameter['ParameterText'], $parameter['ValueText']);
} }
} }
@ -258,12 +281,18 @@ class DigikeyProvider implements InfoProviderInterface
* @return FileDTO[][] * @return FileDTO[][]
* @phpstan-return array<string, FileDTO[]> * @phpstan-return array<string, FileDTO[]>
*/ */
private function mediaToDTOs(array $media_links): array private function mediaToDTOs(string $id): array
{ {
$datasheets = []; $datasheets = [];
$images = []; $images = [];
foreach ($media_links as $media_link) { $response = $this->digikeyClient->request('GET', '/products/v4/search/' . urlencode($id) . '/media', [
'auth_bearer' => $this->authTokenManager->getAlwaysValidTokenString(self::OAUTH_APP_NAME)
]);
$media_array = $response->toArray();
foreach ($media_array['MediaLinks'] as $media_link) {
$file = new FileDTO(url: $media_link['Url'], name: $media_link['Title']); $file = new FileDTO(url: $media_link['Url'], name: $media_link['Title']);
switch ($media_link['MediaType']) { switch ($media_link['MediaType']) {