Allow to pass options to info providers
Some checks failed
Build assets artifact / Build assets artifact (push) Has been cancelled
Docker Image Build / build (linux/amd64, amd64, ubuntu-latest) (push) Has been cancelled
Docker Image Build / build (linux/arm/v7, armv7, ubuntu-24.04-arm) (push) Has been cancelled
Docker Image Build / build (linux/arm64, arm64, ubuntu-24.04-arm) (push) Has been cancelled
Docker Image Build (FrankenPHP) / build (linux/amd64, amd64, ubuntu-latest) (push) Has been cancelled
Docker Image Build (FrankenPHP) / build (linux/arm/v7, armv7, ubuntu-24.04-arm) (push) Has been cancelled
Docker Image Build (FrankenPHP) / build (linux/arm64, arm64, ubuntu-24.04-arm) (push) Has been cancelled
Static analysis / Static analysis (push) Has been cancelled
PHPUnit Tests / PHPUnit and coverage Test (PHP 8.2, mysql) (push) Has been cancelled
PHPUnit Tests / PHPUnit and coverage Test (PHP 8.3, mysql) (push) Has been cancelled
PHPUnit Tests / PHPUnit and coverage Test (PHP 8.4, mysql) (push) Has been cancelled
PHPUnit Tests / PHPUnit and coverage Test (PHP 8.5, mysql) (push) Has been cancelled
PHPUnit Tests / PHPUnit and coverage Test (PHP 8.2, postgres) (push) Has been cancelled
PHPUnit Tests / PHPUnit and coverage Test (PHP 8.3, postgres) (push) Has been cancelled
PHPUnit Tests / PHPUnit and coverage Test (PHP 8.4, postgres) (push) Has been cancelled
PHPUnit Tests / PHPUnit and coverage Test (PHP 8.5, postgres) (push) Has been cancelled
PHPUnit Tests / PHPUnit and coverage Test (PHP 8.2, sqlite) (push) Has been cancelled
PHPUnit Tests / PHPUnit and coverage Test (PHP 8.3, sqlite) (push) Has been cancelled
PHPUnit Tests / PHPUnit and coverage Test (PHP 8.4, sqlite) (push) Has been cancelled
PHPUnit Tests / PHPUnit and coverage Test (PHP 8.5, sqlite) (push) Has been cancelled
Docker Image Build / merge (push) Has been cancelled
Docker Image Build (FrankenPHP) / merge (push) Has been cancelled

This commit is contained in:
Jan Böhmer 2026-04-27 22:37:05 +02:00
parent cf34de6772
commit 4f67f21b33
17 changed files with 55 additions and 46 deletions

View file

@ -86,7 +86,7 @@ final class AIInfoExtractor implements InfoProviderInterface
return $this->settings->platform !== null && $this->settings->model !== null && $this->settings->model !== '';
}
public function searchByKeyword(string $keyword): array
public function searchByKeyword(string $keyword, array $options = []): array
{
try {
return [
@ -96,7 +96,7 @@ final class AIInfoExtractor implements InfoProviderInterface
}
}
public function getDetails(string $id): PartDetailDTO
public function getDetails(string $id, array $options = []): PartDetailDTO
{
$url = $this->fixAndValidateURL($id);

View file

@ -34,7 +34,8 @@ interface BatchInfoProviderInterface extends InfoProviderInterface
* Search for multiple keywords in a single batch operation and return the results, ordered by the keywords.
* This allows for a more efficient search compared to running multiple single searches.
* @param string[] $keywords
* @param array<string, mixed> $options An associative array of options which can be used to modify the search behavior. The supported options depend on the provider and should be documented in the provider's documentation.
* @return array<string, SearchResultDTO[]> An associative array where the key is the keyword and the value is the search results for that keyword
*/
public function searchByKeywordsBatch(array $keywords): array;
public function searchByKeywordsBatch(array $keywords, array $options = []): array;
}

View file

@ -461,9 +461,11 @@ class BuerklinProvider implements BatchInfoProviderInterface, URLHandlerInfoProv
}
/**
* @param string $keyword
* @param array $options
* @return PartDetailDTO[]
*/
public function searchByKeyword(string $keyword): array
public function searchByKeyword(string $keyword, array $options = []): array
{
$keyword = strtoupper(trim($keyword));
if ($keyword === '') {
@ -493,7 +495,7 @@ class BuerklinProvider implements BatchInfoProviderInterface, URLHandlerInfoProv
}
}
public function getDetails(string $id): PartDetailDTO
public function getDetails(string $id, array $options = []): PartDetailDTO
{
// Detail endpoint is /products/{code}/
$response = $this->getProduct($id);
@ -588,10 +590,11 @@ class BuerklinProvider implements BatchInfoProviderInterface, URLHandlerInfoProv
}
/**
* @param string[] $keywords
* @param array $keywords
* @param array $options
* @return array<string, SearchResultDTO[]>
*/
public function searchByKeywordsBatch(array $keywords): array
public function searchByKeywordsBatch(array $keywords, array $options = []): array
{
/** @var array<string, SearchResultDTO[]> $results */
$results = [];
@ -643,27 +646,27 @@ class BuerklinProvider implements BatchInfoProviderInterface, URLHandlerInfoProv
public function getIDFromURL(string $url): ?string
{
//Inputs:
//https://www.buerklin.com/de/p/bkl-electronic/niedervoltsteckverbinder/072341-l/40F1332/
//Inputs:
//https://www.buerklin.com/de/p/bkl-electronic/niedervoltsteckverbinder/072341-l/40F1332/
//https://www.buerklin.com/de/p/40F1332/
//https://www.buerklin.com/en/p/bkl-electronic/dc-connectors/072341-l/40F1332/
//https://www.buerklin.com/en/p/40F1332/
//The ID is the last part after the manufacturer/category/mpn segment and before the final slash
//https://www.buerklin.com/de/p/bkl-electronic/niedervoltsteckverbinder/072341-l/40F1332/#download should also work
$path = parse_url($url, PHP_URL_PATH);
if (!$path) {
return null;
}
// Ensure it's actually a product URL
if (strpos($path, '/p/') === false) {
return null;
}
$id = basename(rtrim($path, '/'));
return $id !== '' && $id !== 'p' ? $id : null;
}

View file

@ -111,7 +111,7 @@ class CanopyProvider implements InfoProviderInterface
return null;
}
public function searchByKeyword(string $keyword): array
public function searchByKeyword(string $keyword, array $options = []): array
{
$response = $this->httpClient->request('GET', self::SEARCH_API_URL, [
'query' => [
@ -177,7 +177,7 @@ class CanopyProvider implements InfoProviderInterface
return new PurchaseInfoDTO(self::DISTRIBUTOR_NAME, order_number: $asin, prices: $priceDtos, product_url: $this->productPageFromASIN($asin));
}
public function getDetails(string $id): PartDetailDTO
public function getDetails(string $id, array $options = []): PartDetailDTO
{
//Check that the id is a valid ASIN (10 characters, letters and numbers)
if (!preg_match('/^[A-Z0-9]{10}$/', $id)) {

View file

@ -88,7 +88,7 @@ readonly class ConradProvider implements InfoProviderInterface, URLHandlerInfoPr
return null;
}
public function searchByKeyword(string $keyword): array
public function searchByKeyword(string $keyword, array $options = []): array
{
$url = $this->settings->shopID->getAPIRoot() . self::SEARCH_ENDPOINT . '/'
. $this->settings->shopID->getDomainEnd() . '/' . $this->settings->shopID->getLanguage()
@ -279,7 +279,7 @@ readonly class ConradProvider implements InfoProviderInterface, URLHandlerInfoPr
);
}
public function getDetails(string $id): PartDetailDTO
public function getDetails(string $id, array $options = []): PartDetailDTO
{
$productInfoURL = $this->settings->shopID->getAPIRoot() . '/product/1/service/' . $this->settings->shopID->getShopID()
. '/product/' . $id;

View file

@ -106,7 +106,7 @@ class DigikeyProvider implements InfoProviderInterface
return $this->settings->clientId !== null && $this->settings->clientId !== '' && $this->authTokenManager->hasToken(self::OAUTH_APP_NAME);
}
public function searchByKeyword(string $keyword): array
public function searchByKeyword(string $keyword, array $options = []): array
{
$request = [
'Keywords' => $keyword,
@ -159,7 +159,7 @@ class DigikeyProvider implements InfoProviderInterface
return $result;
}
public function getDetails(string $id): PartDetailDTO
public function getDetails(string $id, array $options = []): PartDetailDTO
{
try {
$response = $this->digikeyClient->request('GET', '/products/v4/search/' . urlencode($id) . '/productdetails', [

View file

@ -282,12 +282,12 @@ class Element14Provider implements InfoProviderInterface, URLHandlerInfoProvider
};
}
public function searchByKeyword(string $keyword): array
public function searchByKeyword(string $keyword, array $options = []): array
{
return $this->queryByTerm('any:' . $keyword);
}
public function getDetails(string $id): PartDetailDTO
public function getDetails(string $id, array $options = []): PartDetailDTO
{
$tmp = $this->queryByTerm('id:' . $id);
if (count($tmp) === 0) {

View file

@ -54,7 +54,7 @@ class EmptyProvider implements InfoProviderInterface
return true;
}
public function searchByKeyword(string $keyword): array
public function searchByKeyword(string $keyword, array $options = []): array
{
return [
@ -69,7 +69,7 @@ class EmptyProvider implements InfoProviderInterface
];
}
public function getDetails(string $id): PartDetailDTO
public function getDetails(string $id, array $options = []): PartDetailDTO
{
throw new \RuntimeException('No part details available');
}

View file

@ -87,7 +87,7 @@ class GenericWebProvider implements InfoProviderInterface
return $this->settings->enabled;
}
public function searchByKeyword(string $keyword): array
public function searchByKeyword(string $keyword, array $options = []): array
{
$url = $this->fixAndValidateURL($keyword);

View file

@ -61,16 +61,18 @@ interface InfoProviderInterface
/**
* Searches for a keyword and returns a list of search results
* @param string $keyword The keyword to search for
* @param array $options An associative array of options for the search, which can be used to pass additional parameters to the provider (e.g. filters, pagination, etc.). The content of this array is provider specific and not defined by the interface
* @return SearchResultDTO[] A list of search results
*/
public function searchByKeyword(string $keyword): array;
public function searchByKeyword(string $keyword, array $options = []): array;
/**
* Returns detailed information about the part with the given id
* @param string $id
* @param array $options An associative array of options for the search, which can be used to pass additional parameters to the provider (e.g. filters, pagination, etc.). The content of this array is provider specific and not defined by the interface
* @return PartDetailDTO
*/
public function getDetails(string $id): PartDetailDTO;
public function getDetails(string $id, array $options = []): PartDetailDTO;
/**
* A list of capabilities this provider supports (which kind of data it can provide).

View file

@ -349,17 +349,18 @@ class LCSCProvider implements BatchInfoProviderInterface, URLHandlerInfoProvider
return $result;
}
public function searchByKeyword(string $keyword): array
public function searchByKeyword(string $keyword, array $options = []): array
{
return $this->queryByTerm($keyword, true); // Use lightweight mode for search
}
/**
* Batch search multiple keywords asynchronously (like JavaScript Promise.all)
* @param array $keywords Array of keywords to search
* @param array $keywords
* @param array $options
* @return array Results indexed by keyword
*/
public function searchByKeywordsBatch(array $keywords): array
public function searchByKeywordsBatch(array $keywords, array $options = []): array
{
if (empty($keywords)) {
return [];
@ -428,7 +429,7 @@ class LCSCProvider implements BatchInfoProviderInterface, URLHandlerInfoProvider
return $result;
}
public function getDetails(string $id): PartDetailDTO
public function getDetails(string $id, array $options = []): PartDetailDTO
{
$tmp = $this->queryByTerm($id, false);
if (count($tmp) === 0) {

View file

@ -278,12 +278,13 @@ class OEMSecretsProvider implements InfoProviderInterface
* and debugging with local JSON files. The results are processed, cached, and then sorted based
* on the keyword and specified criteria.
*
* @param string $keyword The part number to search for
* @param string $keyword
* @param array $options
* @return array An array of processed product details, sorted by relevance and additional criteria.
*
* @throws \Exception If the JSON file used for debugging is not found or contains errors.
*/
public function searchByKeyword(string $keyword): array
public function searchByKeyword(string $keyword, array $options = []): array
{
/*
oemsecrets Part Search API 3.0.1
@ -414,12 +415,13 @@ class OEMSecretsProvider implements InfoProviderInterface
* found in the cache, they are returned. If not, an exception is thrown indicating that
* the details could not be found.
*
* @param string $id The unique identifier of the provider or part.
* @param string $id
* @param array $options
* @return PartDetailDTO The detailed information about the part.
*
* @throws \Exception If no details are found for the given provider ID.
*/
public function getDetails(string $id): PartDetailDTO
public function getDetails(string $id, array $options = []): PartDetailDTO
{
$cacheKey = $this->getCacheKey($id);
$cacheItem = $this->partInfoCache->getItem($cacheKey);

View file

@ -326,7 +326,7 @@ class OctopartProvider implements InfoProviderInterface
);
}
public function searchByKeyword(string $keyword): array
public function searchByKeyword(string $keyword, array $options = []): array
{
$graphQL = sprintf(<<<'GRAPHQL'
query partSearch($keyword: String, $limit: Int, $currency: String!, $country: String!, $authorizedOnly: Boolean!) {
@ -367,7 +367,7 @@ class OctopartProvider implements InfoProviderInterface
return $tmp;
}
public function getDetails(string $id): PartDetailDTO
public function getDetails(string $id, array $options = []): PartDetailDTO
{
//Check if we have the part cached
$cached = $this->getFromCache($id);

View file

@ -66,7 +66,7 @@ class PollinProvider implements InfoProviderInterface, URLHandlerInfoProviderInt
return $this->settings->enabled;
}
public function searchByKeyword(string $keyword): array
public function searchByKeyword(string $keyword, array $options = []): array
{
$response = $this->client->request('GET', 'https://www.pollin.de/search', [
'query' => [
@ -110,7 +110,7 @@ class PollinProvider implements InfoProviderInterface, URLHandlerInfoProviderInt
};
}
public function getDetails(string $id): PartDetailDTO
public function getDetails(string $id, array $options = []): PartDetailDTO
{
//Ensure that $id is numeric
if (!is_numeric($id)) {

View file

@ -69,7 +69,7 @@ class ReicheltProvider implements InfoProviderInterface
return $this->settings->enabled;
}
public function searchByKeyword(string $keyword): array
public function searchByKeyword(string $keyword, array $options = []): array
{
$response = $this->client->request('GET', sprintf($this->getBaseURL() . '/shop/search/%s', $keyword));
$html = $response->getContent();
@ -108,7 +108,7 @@ class ReicheltProvider implements InfoProviderInterface
return $results;
}
public function getDetails(string $id): PartDetailDTO
public function getDetails(string $id, array $options = []): PartDetailDTO
{
//Check that the ID is a number
if (!is_numeric($id)) {

View file

@ -69,7 +69,7 @@ class TMEProvider implements InfoProviderInterface, URLHandlerInfoProviderInterf
return $this->tmeClient->isUsable();
}
public function searchByKeyword(string $keyword): array
public function searchByKeyword(string $keyword, array $options = []): array
{
$response = $this->tmeClient->makeRequest('Products/Search', [
'Country' => $this->settings->country,
@ -99,7 +99,7 @@ class TMEProvider implements InfoProviderInterface, URLHandlerInfoProviderInterf
return $result;
}
public function getDetails(string $id): PartDetailDTO
public function getDetails(string $id, array $options = []): PartDetailDTO
{
$response = $this->tmeClient->makeRequest('Products/GetProducts', [
'Country' => $this->settings->country,

View file

@ -55,7 +55,7 @@ class TestProvider implements InfoProviderInterface
return true;
}
public function searchByKeyword(string $keyword): array
public function searchByKeyword(string $keyword, array $options = []): array
{
return [
new SearchResultDTO(provider_key: $this->getProviderKey(), provider_id: 'element1', name: 'Element 1', description: 'fd'),
@ -72,7 +72,7 @@ class TestProvider implements InfoProviderInterface
];
}
public function getDetails(string $id): PartDetailDTO
public function getDetails(string $id, array $options = []): PartDetailDTO
{
return new PartDetailDTO(
provider_key: $this->getProviderKey(),
@ -92,4 +92,4 @@ class TestProvider implements InfoProviderInterface
]
);
}
}
}