@@ -108,12 +108,15 @@ public function searchByKeyword(string $keyword): array
108108 {
109109 $ request = [
110110 'Keywords ' => $ keyword ,
111- 'RecordCount ' => 50 ,
112- 'RecordStartPosition ' => 0 ,
113- 'ExcludeMarketPlaceProducts ' => 'true ' ,
111+ 'Limit ' => 50 ,
112+ 'Offset ' => 0 ,
113+ 'FilterOptionsRequest ' => [
114+ 'MarketPlaceFilter ' => 'ExcludeMarketPlace ' ,
115+ ],
114116 ];
115117
116- $ response = $ this ->digikeyClient ->request ('POST ' , '/Search/v3/Products/Keyword ' , [
118+ //$response = $this->digikeyClient->request('POST', '/Search/v3/Products/Keyword', [
119+ $ response = $ this ->digikeyClient ->request ('POST ' , '/products/v4/search/keyword ' , [
117120 'json ' => $ request ,
118121 'auth_bearer ' => $ this ->authTokenManager ->getAlwaysValidTokenString (self ::OAUTH_APP_NAME )
119122 ]);
@@ -124,51 +127,64 @@ public function searchByKeyword(string $keyword): array
124127 $ result = [];
125128 $ products = $ response_array ['Products ' ];
126129 foreach ($ products as $ product ) {
127- $ result [] = new SearchResultDTO (
128- provider_key: $ this ->getProviderKey (),
129- provider_id: $ product ['DigiKeyPartNumber ' ],
130- name: $ product ['ManufacturerPartNumber ' ],
131- description: $ product ['DetailedDescription ' ] ?? $ product ['ProductDescription ' ],
132- category: $ this ->getCategoryString ($ product ),
133- manufacturer: $ product ['Manufacturer ' ]['Value ' ] ?? null ,
134- mpn: $ product ['ManufacturerPartNumber ' ],
135- preview_image_url: $ product ['PrimaryPhoto ' ] ?? null ,
136- manufacturing_status: $ this ->productStatusToManufacturingStatus ($ product ['ProductStatus ' ]),
137- provider_url: $ product ['ProductUrl ' ],
138- );
130+ foreach ($ product ['ProductVariations ' ] as $ variation ) {
131+ $ result [] = new SearchResultDTO (
132+ provider_key: $ this ->getProviderKey (),
133+ provider_id: $ variation ['DigiKeyProductNumber ' ],
134+ name: $ product ['ManufacturerProductNumber ' ],
135+ description: $ product ['Description ' ]['DetailedDescription ' ] ?? $ product ['Description ' ]['ProductDescription ' ],
136+ category: $ this ->getCategoryString ($ product ),
137+ manufacturer: $ product ['Manufacturer ' ]['Name ' ] ?? null ,
138+ mpn: $ product ['ManufacturerProductNumber ' ],
139+ preview_image_url: $ product ['PhotoUrl ' ] ?? null ,
140+ manufacturing_status: $ this ->productStatusToManufacturingStatus ($ product ['ProductStatus ' ]['Id ' ]),
141+ provider_url: $ product ['ProductUrl ' ],
142+ 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)
143+ );
144+ }
139145 }
140146
141147 return $ result ;
142148 }
143149
144150 public function getDetails (string $ id ): PartDetailDTO
145151 {
146- $ response = $ this ->digikeyClient ->request ('GET ' , '/Search/v3/Products / ' . urlencode ($ id ), [
152+ $ response = $ this ->digikeyClient ->request ('GET ' , '/products/v4/search / ' . urlencode ($ id ) . ' /productdetails ' , [
147153 'auth_bearer ' => $ this ->authTokenManager ->getAlwaysValidTokenString (self ::OAUTH_APP_NAME )
148154 ]);
149155
150- $ product = $ response ->toArray ();
156+ $ response_array = $ response ->toArray ();
157+ $ product = $ response_array ['Product ' ];
151158
152159 $ footprint = null ;
153160 $ parameters = $ this ->parametersToDTOs ($ product ['Parameters ' ] ?? [], $ footprint );
154- $ media = $ this ->mediaToDTOs ($ product ['MediaLinks ' ]);
161+ $ media = $ this ->mediaToDTOs ($ id );
162+
163+ // Get the price_breaks of the selected variation
164+ $ price_breaks = [];
165+ foreach ($ product ['ProductVariations ' ] as $ variation ) {
166+ if ($ variation ['DigiKeyProductNumber ' ] == $ id ) {
167+ $ price_breaks = $ variation ['StandardPricing ' ] ?? [];
168+ break ;
169+ }
170+ }
155171
156172 return new PartDetailDTO (
157173 provider_key: $ this ->getProviderKey (),
158- provider_id: $ product [ ' DigiKeyPartNumber ' ] ,
159- name: $ product ['ManufacturerPartNumber ' ],
160- description: $ product ['DetailedDescription ' ] ?? $ product ['ProductDescription ' ],
174+ provider_id: $ id ,
175+ name: $ product ['ManufacturerProductNumber ' ],
176+ description: $ product ['Description ' ][ ' DetailedDescription ' ] ?? $ product[ ' Description ' ] ['ProductDescription ' ],
161177 category: $ this ->getCategoryString ($ product ),
162- manufacturer: $ product ['Manufacturer ' ]['Value ' ] ?? null ,
163- mpn: $ product ['ManufacturerPartNumber ' ],
164- preview_image_url: $ product ['PrimaryPhoto ' ] ?? null ,
165- manufacturing_status: $ this ->productStatusToManufacturingStatus ($ product ['ProductStatus ' ]),
178+ manufacturer: $ product ['Manufacturer ' ]['Name ' ] ?? null ,
179+ mpn: $ product ['ManufacturerProductNumber ' ],
180+ preview_image_url: $ product ['PhotoUrl ' ] ?? null ,
181+ manufacturing_status: $ this ->productStatusToManufacturingStatus ($ product ['ProductStatus ' ][ ' Id ' ] ),
166182 provider_url: $ product ['ProductUrl ' ],
167183 footprint: $ footprint ,
168184 datasheets: $ media ['datasheets ' ],
169185 images: $ media ['images ' ],
170186 parameters: $ parameters ,
171- vendor_infos: $ this ->pricingToDTOs ($ product [ ' StandardPricing ' ] ?? [] , $ product [ ' DigiKeyPartNumber ' ] , $ product ['ProductUrl ' ]),
187+ vendor_infos: $ this ->pricingToDTOs ($ price_breaks , $ id , $ product ['ProductUrl ' ]),
172188 );
173189 }
174190
@@ -177,28 +193,35 @@ public function getDetails(string $id): PartDetailDTO
177193 * @param string|null $dk_status
178194 * @return ManufacturingStatus|null
179195 */
180- private function productStatusToManufacturingStatus (?string $ dk_status ): ?ManufacturingStatus
196+ private function productStatusToManufacturingStatus (?int $ dk_status ): ?ManufacturingStatus
181197 {
198+ // The V4 can use strings to get the status, but if you have changed the PROVIDER_DIGIKEY_LANGUAGE it will not match.
199+ // Using the Id instead which should be fixed.
200+ //
201+ // The API is not well documented and the ID are not there yet, so were extracted using "trial and error".
202+ // The 'Preliminary' id was not found in several categories so I was unable to extract it. Disabled for now.
182203 return match ($ dk_status ) {
183204 null => null ,
184- ' Active ' => ManufacturingStatus::ACTIVE ,
185- ' Obsolete ' => ManufacturingStatus::DISCONTINUED ,
186- ' Discontinued at Digi-Key ' , ' Last Time Buy ' => ManufacturingStatus::EOL ,
187- ' Not For New Designs ' => ManufacturingStatus::NRFND ,
188- 'Preliminary ' => ManufacturingStatus::ANNOUNCED ,
205+ 0 => ManufacturingStatus::ACTIVE ,
206+ 1 => ManufacturingStatus::DISCONTINUED ,
207+ 2 , 4 => ManufacturingStatus::EOL ,
208+ 7 => ManufacturingStatus::NRFND ,
209+ // 'Preliminary' => ManufacturingStatus::ANNOUNCED,
189210 default => ManufacturingStatus::NOT_SET ,
190211 };
191212 }
192213
193214 private function getCategoryString (array $ product ): string
194215 {
195- $ category = $ product ['Category ' ]['Value ' ];
196- $ sub_category = $ product ['Family ' ]['Value ' ] ;
216+ $ category = $ product ['Category ' ]['Name ' ];
217+ $ sub_category = current ( $ product ['Category ' ]['ChildCategories ' ]) ;
197218
198- //Replace the ' - ' category separator with ' -> '
199- $ sub_category = str_replace (' - ' , ' -> ' , $ sub_category );
219+ if ($ sub_category ) {
220+ //Replace the ' - ' category separator with ' -> '
221+ $ category = $ category . ' -> ' . str_replace (' - ' , ' -> ' , $ sub_category ["Name " ]);
222+ }
200223
201- return $ category . ' -> ' . $ sub_category ;
224+ return $ category ;
202225 }
203226
204227 /**
@@ -215,18 +238,18 @@ private function parametersToDTOs(array $parameters, string|null &$footprint_nam
215238
216239 foreach ($ parameters as $ parameter ) {
217240 if ($ parameter ['ParameterId ' ] === 1291 ) { //Meaning "Manufacturer given footprint"
218- $ footprint_name = $ parameter ['Value ' ];
241+ $ footprint_name = $ parameter ['ValueText ' ];
219242 }
220243
221- if (in_array (trim ((string ) $ parameter ['Value ' ]), ['' , '- ' ], true )) {
244+ if (in_array (trim ((string ) $ parameter ['ValueText ' ]), ['' , '- ' ], true )) {
222245 continue ;
223246 }
224247
225248 //If the parameter was marked as text only, then we do not try to parse it as a numerical value
226249 if (in_array ($ parameter ['ParameterId ' ], self ::TEXT_ONLY_PARAMETERS , true )) {
227- $ results [] = new ParameterDTO (name: $ parameter ['Parameter ' ], value_text: $ parameter ['Value ' ]);
250+ $ results [] = new ParameterDTO (name: $ parameter ['ParameterText ' ], value_text: $ parameter ['ValueText ' ]);
228251 } else { //Otherwise try to parse it as a numerical value
229- $ results [] = ParameterDTO::parseValueIncludingUnit ($ parameter ['Parameter ' ], $ parameter ['Value ' ]);
252+ $ results [] = ParameterDTO::parseValueIncludingUnit ($ parameter ['ParameterText ' ], $ parameter ['ValueText ' ]);
230253 }
231254 }
232255
@@ -258,12 +281,18 @@ private function pricingToDTOs(array $price_breaks, string $order_number, string
258281 * @return FileDTO[][]
259282 * @phpstan-return array<string, FileDTO[]>
260283 */
261- private function mediaToDTOs (array $ media_links ): array
284+ private function mediaToDTOs (string $ id ): array
262285 {
263286 $ datasheets = [];
264287 $ images = [];
265288
266- foreach ($ media_links as $ media_link ) {
289+ $ response = $ this ->digikeyClient ->request ('GET ' , '/products/v4/search/ ' . urlencode ($ id ) . '/media ' , [
290+ 'auth_bearer ' => $ this ->authTokenManager ->getAlwaysValidTokenString (self ::OAUTH_APP_NAME )
291+ ]);
292+
293+ $ media_array = $ response ->toArray ();
294+
295+ foreach ($ media_array ['MediaLinks ' ] as $ media_link ) {
267296 $ file = new FileDTO (url: $ media_link ['Url ' ], name: $ media_link ['Title ' ]);
268297
269298 switch ($ media_link ['MediaType ' ]) {
0 commit comments