diff --git a/composer.json b/composer.json index 11026fa2..3b2904d6 100644 --- a/composer.json +++ b/composer.json @@ -54,6 +54,8 @@ "symfony/apache-pack": "^1.0", "symfony/asset": "6.4.*", "symfony/console": "6.4.*", + "symfony/css-selector": "6.4.*", + "symfony/dom-crawler": "6.4.*", "symfony/dotenv": "6.4.*", "symfony/expression-language": "6.4.*", "symfony/flex": "^v2.3.1", @@ -104,7 +106,6 @@ "rector/rector": "^2.0.4", "roave/security-advisories": "dev-latest", "symfony/browser-kit": "6.4.*", - "symfony/css-selector": "6.4.*", "symfony/debug-bundle": "6.4.*", "symfony/maker-bundle": "^1.13", "symfony/phpunit-bridge": "6.4.*", diff --git a/composer.lock b/composer.lock index 892ae0c7..498132b2 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "ca8701d95e24bae5d28ccdcfe242e8e4", + "content-hash": "75643d42e05fce4684644d375bff2d0a", "packages": [ { "name": "amphp/amp", @@ -8984,6 +8984,73 @@ ], "time": "2025-01-25T08:04:58+00:00" }, + { + "name": "symfony/dom-crawler", + "version": "v6.4.18", + "source": { + "type": "git", + "url": "https://github.com/symfony/dom-crawler.git", + "reference": "fd07959d3e8992795029bdab3605c2e8e895034e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/fd07959d3e8992795029bdab3605c2e8e895034e", + "reference": "fd07959d3e8992795029bdab3605c2e8e895034e", + "shasum": "" + }, + "require": { + "masterminds/html5": "^2.6", + "php": ">=8.1", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-mbstring": "~1.0" + }, + "require-dev": { + "symfony/css-selector": "^5.4|^6.0|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\DomCrawler\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Eases DOM navigation for HTML and XML documents", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/dom-crawler/tree/v6.4.18" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-01-09T15:35:00+00:00" + }, { "name": "symfony/dotenv", "version": "v6.4.16", @@ -18497,73 +18564,6 @@ ], "time": "2024-09-25T14:18:03+00:00" }, - { - "name": "symfony/dom-crawler", - "version": "v6.4.18", - "source": { - "type": "git", - "url": "https://github.com/symfony/dom-crawler.git", - "reference": "fd07959d3e8992795029bdab3605c2e8e895034e" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/fd07959d3e8992795029bdab3605c2e8e895034e", - "reference": "fd07959d3e8992795029bdab3605c2e8e895034e", - "shasum": "" - }, - "require": { - "masterminds/html5": "^2.6", - "php": ">=8.1", - "symfony/polyfill-ctype": "~1.8", - "symfony/polyfill-mbstring": "~1.0" - }, - "require-dev": { - "symfony/css-selector": "^5.4|^6.0|^7.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\DomCrawler\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Eases DOM navigation for HTML and XML documents", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/dom-crawler/tree/v6.4.18" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2025-01-09T15:35:00+00:00" - }, { "name": "symfony/maker-bundle", "version": "v1.62.1", diff --git a/src/Services/InfoProviderSystem/Providers/LCSCProvider.php b/src/Services/InfoProviderSystem/Providers/LCSCProvider.php index d903a8dd..375c6f4d 100755 --- a/src/Services/InfoProviderSystem/Providers/LCSCProvider.php +++ b/src/Services/InfoProviderSystem/Providers/LCSCProvider.php @@ -76,7 +76,7 @@ class LCSCProvider implements InfoProviderInterface 'Cookie' => new Cookie('currencyCode', $this->currency) ], 'query' => [ - 'productCode' => $id, + 'prductCode' => $id, ], ]); diff --git a/src/Services/InfoProviderSystem/Providers/ReicheltProvider.php b/src/Services/InfoProviderSystem/Providers/ReicheltProvider.php new file mode 100644 index 00000000..19c52b2a --- /dev/null +++ b/src/Services/InfoProviderSystem/Providers/ReicheltProvider.php @@ -0,0 +1,109 @@ +. + */ + +declare(strict_types=1); + + +namespace App\Services\InfoProviderSystem\Providers; + +use App\Services\InfoProviderSystem\DTOs\PartDetailDTO; +use App\Services\InfoProviderSystem\DTOs\SearchResultDTO; +use Symfony\Component\DomCrawler\Crawler; +use Symfony\Contracts\HttpClient\HttpClientInterface; + +class ReicheltProvider implements InfoProviderInterface +{ + + private const SEARCH_ENDPOINT = "https://www.reichelt.com/index.html?ACTION=446&LA=0&nbc=1&q=%s"; + + public function __construct(private readonly HttpClientInterface $client) + { + } + + public function getProviderInfo(): array + { + return [ + 'name' => 'Reichelt', + 'description' => 'TODO', + 'url' => 'https://www.reichelt.de/', + 'disabled_help' => 'TODO' + ]; + } + + public function getProviderKey(): string + { + return 'reichelt'; + } + + public function isActive(): bool + { + return true; + } + + public function searchByKeyword(string $keyword): array + { + //Lowercase the keyword and urlencode it + $keyword = urlencode($keyword); + $response = $this->client->request('GET', sprintf(self::SEARCH_ENDPOINT, $keyword)); + $html = $response->getContent(); + + //Parse the HTML and return the results + $dom = new Crawler($html); + //Iterate over all div.al_gallery_article elements + $results = []; + $dom->filter('div.al_gallery_article')->each(function (Crawler $element) use (&$results) { + + $productID = $element->filter('meta[itemprop="productID"]')->attr('content'); + $name = $element->filter('meta[itemprop="name"]')->attr('content'); + $sku = $element->filter('meta[itemprop="sku"]')->attr('content'); + + //Try to extract a picture URL: + $pictureURL = $element->filter("div.al_artlogo img")->attr('src'); + + $results[] = new SearchResultDTO( + provider_key: $this->getProviderKey(), + provider_id: $productID, + name: $productID, + description: $name, + category: null, + manufacturer: $sku, + preview_image_url: $pictureURL, + provider_url: $element->filter('a.al_artinfo_link')->attr('href') + ); + }); + + return $results; + } + + public function getDetails(string $id): PartDetailDTO + { + // TODO: Implement getDetails() method. + } + + public function getCapabilities(): array + { + return [ + ProviderCapabilities::BASIC, + ProviderCapabilities::PICTURE, + ProviderCapabilities::DATASHEET, + ProviderCapabilities::PRICE, + ]; + } +} \ No newline at end of file