diff --git a/app/Console/Commands/IkeaPrice.php b/app/Console/Commands/IkeaPrice.php new file mode 100644 index 0000000..0c9e0bf --- /dev/null +++ b/app/Console/Commands/IkeaPrice.php @@ -0,0 +1,40 @@ +argument('article'); + $country = $this->argument('country'); + + $responses = $countryCompareController->makeRequest($article,$country); + $prices = $countryCompareController->processResponse($responses,$article); + //dd($prices); + return 0; + } +} + diff --git a/app/Console/Commands/IkeaPrices.php b/app/Console/Commands/IkeaPrices.php new file mode 100644 index 0000000..30bcb66 --- /dev/null +++ b/app/Console/Commands/IkeaPrices.php @@ -0,0 +1,38 @@ +argument('article'); + $responses = $countryCompareController->makeRequests($article); + $prices = $countryCompareController->processResponse($responses,$article); + //dd($prices); + return 0; + } +} + diff --git a/app/Http/Controllers/.DS_Store b/app/Http/Controllers/.DS_Store new file mode 100644 index 0000000..bf62309 Binary files /dev/null and b/app/Http/Controllers/.DS_Store differ diff --git a/app/Http/Controllers/CountryCompareController.php b/app/Http/Controllers/CountryCompareController.php new file mode 100644 index 0000000..541d449 --- /dev/null +++ b/app/Http/Controllers/CountryCompareController.php @@ -0,0 +1,269 @@ +each(function ($country) use (&$countries) { + $countries[] = $country->country_name; + }); + + $this->countries = collect($countries); + } + public function search(Request $request) + { + $itemCodes = $request->input("item_codes"); + $ta_codes = explode(' ', str_replace('.', '', trim($itemCodes))); + + $requests = $this->makeRequests($ta_codes[0]); + return $this->processResponse($requests,$ta_codes[0]); + } + + public function makeRequests($ta_code) + { + $requests = Http::pool(fn (Pool $pool) => [ + CountryCode::all()->each(function ($countryCode) use ($pool, $ta_code) { + $this->countries[] = $countryCode->country_name; + return $pool->as($countryCode->country_name)->get($countryCode->search_url . $ta_code); + }) + ]); + return $requests; + } + + public function makeRequest($ta_code, $country) + { + $countryCode = CountryCode::where('country_name', $country)->first(); + return Http::pool(fn (Pool $pool) => [ + $pool->as($countryCode->country_name)->get($countryCode->search_url . $ta_code) + ]); + } + + public function processResponse($responses, $code) + { + $prices = []; + + foreach ($this->countries as $country) { + + if (isset($responses[$country]) && $responses[$country]->ok()) { + + $response = $responses[$country]->body(); + switch ($country) { + case "Bulgaria": + case "Cyprus": + case "Greece": + $prices[$country] = $this->parseJson_CY_GR_BG($code, (string) $response); + break; + case "Iceland": + $prices[$country] = $this->parseJson_IS($country, $code, (string) $response); + break; + case "Türkiye": + $prices[$country] = $this->parseJson_TR((string) $response); + break; + case "Lithuania": + case "Estonia": + case "Latvia": + $prices[$country] = $this->parseJson_EE_LT_LV($country, $code, (string) $response); + break; + default: + $prices[$country] = $this->parseJson((string) $response); + } + } + } + + return $prices; + } + public function parseJson($json_raw) + { + $json_values = array(); + + $json_decoded = json_decode($json_raw, true); + //dd($json_decoded); + $searchResultPage = $json_decoded["searchResultPage"]; + $products = $searchResultPage["products"]; + $main = $products["main"]; + $items = $main["items"]; + + foreach ($items as $item) { + $product = $item["product"]; + + $salesPrice = $product["salesPrice"]; + $numeral = $salesPrice["numeral"]; + + $json_values = array( + 'url_product' => $product['pipUrl'], + 'tag' => $product['tag'], + 'price' => $numeral, + 'price_eur' => 0 + ); + break; + } + + return $json_values; + } + + public function parseJson_TR($body) + { + //echo "country: " . $country . ", code: " . $code . "
"; + + $dochtml = new \DOMDocument(); + @$dochtml->loadHTML('' . $body); + + $xpath = new \DOMXpath($dochtml); + $price = null; + //$c = ltrim($code, "0"); + $json_values = array(); + + $url_product = $xpath->query('/html/head/meta[(@property="og:url")]/@content')[0]->nodeValue; + $price = $xpath->query('/html/head/meta[(@property="og:price:amount")]/@content')[0]->nodeValue; + + $price = floatval(trim(str_replace('.', '', $price))); + + $json_values = array( + 'url_product' => $url_product, + 'tag' => null, + 'price' => floatval($price), + 'price_eur' => 0 + ); + + return $json_values; + } + + public function parseJson_CY_GR_BG($code, $body) + { + //echo "country: " . $country . ", code: " . $code . "
"; + + $dochtml = new \DOMDocument(); + @$dochtml->loadHTML('' . $body); + + $xpath = new \DOMXpath($dochtml); + $price = null; + $c = ltrim($code, "0"); + $json_values = array(); + + try { + $price = $xpath->query('//*/div[(@class="yotpo yotpo-main-widget" and @data-product-id="' . $code . '")]/@data-price')[0]->nodeValue; + $url_product = $xpath->query('//*/div[(@class="yotpo yotpo-main-widget" and @data-product-id="' . $code . '")]/@data-url')[0]->nodeValue; + } catch (\Exception $e) { + return []; + } + $price = floatval($price); + + + $json_values = array( + 'url_product' => $url_product, + 'tag' => null, + 'price' => floatval($price), + 'price_eur' => 0 + ); + + return $json_values; + } + + public function parseJson_EE_LT_LV($country, $code, $body) + { + //echo "country: " . $country . ", code: " . $code . "
"; + + $dochtml = new \DOMDocument(); + @$dochtml->loadHTML('' . $body); + + $xpath = new \DOMXpath($dochtml); + $price = null; + $c = ltrim($code, "0"); + $json_values = array(); + + try { + $price = $xpath->query('//*/div[(@class="itemPriceBox" and @data-item="' . $c . '")]//p[@class="itemNormalPrice display-6"]/span')[0]->nodeValue; + + if (is_null($price) || empty($price)) { + $price = $xpath->query('//*/div[(@class="itemPriceBox" and @data-item="' . $c . '")]//div[@class="itemBTI display-6"]/span')[0]->nodeValue; + } + + switch ($country) { + case "Estonia": + $url_product = "https://www.ikea.ee" . $xpath->query('//*/div[(@class="card-header")]/a/@href')[0]->nodeValue; + break; + case "Lithuania": + $url_product = "https://www.ikea.lt" . $xpath->query('//*/div[(@class="card-header")]/a/@href')[0]->nodeValue; + break; + case "Latvia": + $url_product = "https://www.ikea.lv" . $xpath->query('//*/div[(@class="card-header")]/a/@href')[0]->nodeValue; + break; + default: + $url_product = null; + } + } catch (\Exception $e) { + return []; + } + + if (is_null($price) || empty($price)) { + $url_product = null; + } + + $price = floatval(trim(str_replace(' ', '', str_replace(',', '.', str_replace(array('€'), '', $price))))); + + $json_values = array( + 'url_product' => $url_product, + //$url_product, + 'tag' => null, + 'price' => $price, + 'price_eur' => 0 + ); + + return $json_values; + } + + public function parseJson_IS($country, $code, $body) + { + //echo "country: " . $country . ", code: " . $code . "
"; + + $dochtml = new \DOMDocument(); + @$dochtml->loadHTML('' . $body); + + $xpath = new \DOMXpath($dochtml); + $price = null; + $c = ltrim($code, "0"); + $json_values = array(); + + try { + $price = $xpath->query('//*/div[(@class="itemPriceBox")]//p[@class="itemNormalPrice revamp_price price"]/span/span')[0]->nodeValue; + + if (is_null($price) || empty($price)) { + $price = $xpath->query('//*/div[(@class="itemPriceBox")]//p[@class="itemBTI display-6 revamp_price price"]/span/span')[0]->nodeValue; + } + + $url_product = "https://www.ikea.is" . $xpath->query('/html/head/meta[(@property="og:url")]/@content')[0]->nodeValue; + + //echo "url_product: " . $url_product . "
"; + + if (is_null($price) || empty($price)) { + $url_product = null; + } + + } catch (\Exception $e) { + return []; + } + $price = floatval(trim(str_replace(' ', '', str_replace(',', '.', str_replace('.', '', str_replace(array('€'), '', $price)))))); + + $json_values = array( + 'url_product' => $url_product, + //$url_product, + 'tag' => null, + 'price' => $price, + 'price_eur' => 0 + ); + + return $json_values; + } +} diff --git a/composer.json b/composer.json index cf63219..16a7f7a 100644 --- a/composer.json +++ b/composer.json @@ -15,6 +15,8 @@ "laravel/jetstream": "^2.9", "laravel/sanctum": "^2.14.1", "laravel/tinker": "^2.7", + "masterminds/html5": "^2.8", + "paquettg/php-html-parser": "^2.2", "pusher/pusher-php-server": "^7.0", "spatie/laravel-permission": "^5.5", "tightenco/ziggy": "^1.0" diff --git a/composer.lock b/composer.lock index fee6ae8..6c66b43 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": "a0740cf70dd9814ae6b1c55e419dacf2", + "content-hash": "ad6ab448ac9b62b01922490669b4c2b2", "packages": [ { "name": "bacon/bacon-qr-code", @@ -3091,6 +3091,73 @@ }, "time": "2018-06-05T21:06:51+00:00" }, + { + "name": "masterminds/html5", + "version": "2.8.1", + "source": { + "type": "git", + "url": "https://github.com/Masterminds/html5-php.git", + "reference": "f47dcf3c70c584de14f21143c55d9939631bc6cf" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Masterminds/html5-php/zipball/f47dcf3c70c584de14f21143c55d9939631bc6cf", + "reference": "f47dcf3c70c584de14f21143c55d9939631bc6cf", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "php": ">=5.3.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.8.35 || ^5.7.21 || ^6 || ^7 || ^8" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.7-dev" + } + }, + "autoload": { + "psr-4": { + "Masterminds\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Matt Butcher", + "email": "technosophos@gmail.com" + }, + { + "name": "Matt Farina", + "email": "matt@mattfarina.com" + }, + { + "name": "Asmir Mustafic", + "email": "goetas@gmail.com" + } + ], + "description": "An HTML5 parser and serializer.", + "homepage": "http://masterminds.github.io/html5-php", + "keywords": [ + "HTML5", + "dom", + "html", + "parser", + "querypath", + "serializer", + "xml" + ], + "support": { + "issues": "https://github.com/Masterminds/html5-php/issues", + "source": "https://github.com/Masterminds/html5-php/tree/2.8.1" + }, + "time": "2023-05-10T11:58:31+00:00" + }, { "name": "matomo/device-detector", "version": "6.0.2", @@ -3675,6 +3742,114 @@ }, "time": "2022-05-31T20:59:12+00:00" }, + { + "name": "paquettg/php-html-parser", + "version": "2.2.1", + "source": { + "type": "git", + "url": "https://github.com/paquettg/php-html-parser.git", + "reference": "668c770fc5724ea3f15b8791435f054835be8d5e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/paquettg/php-html-parser/zipball/668c770fc5724ea3f15b8791435f054835be8d5e", + "reference": "668c770fc5724ea3f15b8791435f054835be8d5e", + "shasum": "" + }, + "require": { + "ext-curl": "*", + "ext-mbstring": "*", + "ext-zlib": "*", + "paquettg/string-encode": "~1.0.0", + "php": ">=7.1" + }, + "require-dev": { + "infection/infection": "^0.13.4", + "mockery/mockery": "^1.2", + "phan/phan": "^2.4", + "php-coveralls/php-coveralls": "^2.1", + "phpunit/phpunit": "^7.5.1" + }, + "type": "library", + "autoload": { + "psr-4": { + "PHPHtmlParser\\": "src/PHPHtmlParser" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Gilles Paquette", + "email": "paquettg@gmail.com", + "homepage": "http://gillespaquette.ca" + } + ], + "description": "An HTML DOM parser. It allows you to manipulate HTML. Find tags on an HTML page with selectors just like jQuery.", + "homepage": "https://github.com/paquettg/php-html-parser", + "keywords": [ + "dom", + "html", + "parser" + ], + "support": { + "issues": "https://github.com/paquettg/php-html-parser/issues", + "source": "https://github.com/paquettg/php-html-parser/tree/2.2.1" + }, + "time": "2020-01-20T12:59:15+00:00" + }, + { + "name": "paquettg/string-encode", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/paquettg/string-encoder.git", + "reference": "a8708e9fac9d5ddfc8fc2aac6004e2cd05d80fee" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/paquettg/string-encoder/zipball/a8708e9fac9d5ddfc8fc2aac6004e2cd05d80fee", + "reference": "a8708e9fac9d5ddfc8fc2aac6004e2cd05d80fee", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "require-dev": { + "phpunit/phpunit": "^7.5.1" + }, + "type": "library", + "autoload": { + "psr-0": { + "stringEncode": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Gilles Paquette", + "email": "paquettg@gmail.com", + "homepage": "http://gillespaquette.ca" + } + ], + "description": "Facilitating the process of altering string encoding in PHP.", + "homepage": "https://github.com/paquettg/string-encoder", + "keywords": [ + "charset", + "encoding", + "string" + ], + "support": { + "issues": "https://github.com/paquettg/string-encoder/issues", + "source": "https://github.com/paquettg/string-encoder/tree/1.0.1" + }, + "time": "2018-12-21T02:25:09+00:00" + }, { "name": "paragonie/constant_time_encoding", "version": "v2.6.3", diff --git a/out.json b/out.json new file mode 100644 index 0000000..0af560a --- /dev/null +++ b/out.json @@ -0,0 +1 @@ +"{"usergroup":"[]","testActivationTriggers":{},"searchResultPage":{"searchPhrase":"70458873","storeWindow":[],"storeCount":0,"didYouMean":[],"relatedSearches":[],"retiredProducts":[],"products":{"badge":0,"filters":[],"sortOrders":{"name":"Sort","values":[]},"main":{"items":[],"start":0,"end":0,"max":0},"shelves":[{"title":"Recommended categories","result":{"items":[{"metadata":"v1;1;CATEGORY;st001;categories_shelf;","category":{"name":"Storage \u0026 organisation","key":"st001","url":"https://www.ikea.com/au/en/cat/storage-organisation-st001/","imageUrl":"https://www.ikea.com/global/assets/range-categorisation/images/storage-organisation-st001.jpeg"},"type":"CATEGORY","label":"Category","actionTokens":[],"isBreakout":false},{"metadata":"v1;2;CATEGORY;fu001;categories_shelf;","category":{"name":"Furniture","key":"fu001","url":"https://www.ikea.com/au/en/cat/furniture-fu001/","imageUrl":"https://www.ikea.com/global/assets/range-categorisation/images/furniture-fu001.jpeg"},"type":"CATEGORY","label":"Category","actionTokens":[],"isBreakout":false},{"metadata":"v1;3;CATEGORY;kt001;categories_shelf;","category":{"name":"Kitchenware \u0026 tableware","key":"kt001","url":"https://www.ikea.com/au/en/cat/kitchenware-tableware-kt001/","imageUrl":"https://www.ikea.com/global/assets/range-categorisation/images/kitchenware-tableware-kt001.jpeg"},"type":"CATEGORY","label":"Category","actionTokens":[],"isBreakout":false},{"metadata":"v1;4;CATEGORY;de001;categories_shelf;","category":{"name":"Decoration","key":"de001","url":"https://www.ikea.com/au/en/cat/decoration-de001/","imageUrl":"https://www.ikea.com/global/assets/range-categorisation/images/decoration-de001.jpeg"},"type":"CATEGORY","label":"Category","actionTokens":[],"isBreakout":false},{"metadata":"v1;5;CATEGORY;bm001;categories_shelf;","category":{"name":"Beds \u0026 mattresses","key":"bm001","url":"https://www.ikea.com/au/en/cat/beds-mattresses-bm001/","imageUrl":"https://www.ikea.com/global/assets/range-categorisation/images/beds-mattresses-bm001.jpeg"},"type":"CATEGORY","label":"Category","actionTokens":[],"isBreakout":false},{"metadata":"v1;6;CATEGORY;ka001;categories_shelf;","category":{"name":"Kitchen \u0026 appliances","key":"ka001","url":"https://www.ikea.com/au/en/cat/kitchen-appliances-ka001/","imageUrl":"https://www.ikea.com/global/assets/range-categorisation/images/kitchen-appliances-ka001.jpeg"},"type":"CATEGORY","label":"Category","actionTokens":[],"isBreakout":false},{"metadata":"v1;7;CATEGORY;od001;categories_shelf;","category":{"name":"Outdoor products","key":"od001","url":"https://www.ikea.com/au/en/cat/outdoor-products-od001/","imageUrl":"https://www.ikea.com/global/assets/range-categorisation/images/outdoor-products-od001.jpeg"},"type":"CATEGORY","label":"Category","actionTokens":[],"isBreakout":false},{"metadata":"v1;8;CATEGORY;lc001;categories_shelf;","category":{"name":"Laundry \u0026 cleaning","key":"lc001","url":"https://www.ikea.com/au/en/cat/laundry-cleaning-lc001/","imageUrl":"https://www.ikea.com/global/assets/range-categorisation/images/laundry-cleaning-lc001.jpeg"},"type":"CATEGORY","label":"Category","actionTokens":[],"isBreakout":false},{"metadata":"v1;9;CATEGORY;ba001;categories_shelf;","category":{"name":"Bathroom products","key":"ba001","url":"https://www.ikea.com/au/en/cat/bathroom-products-ba001/","imageUrl":"https://www.ikea.com/global/assets/range-categorisation/images/bathroom-products-ba001.jpeg"},"type":"CATEGORY","label":"Category","actionTokens":[],"isBreakout":false},{"metadata":"v1;10;CATEGORY;rm001;categories_shelf;","category":{"name":"Rugs, mats \u0026 flooring","key":"rm001","url":"https://www.ikea.com/au/en/cat/rugs-mats-flooring-rm001/","imageUrl":"https://www.ikea.com/global/assets/range-categorisation/images/rugs-mats-flooring-rm001.jpeg"},"type":"CATEGORY","label":"Category","actionTokens":[],"isBreakout":false},{"metadata":"v1;11;CATEGORY;bc001;categories_shelf;","category":{"name":"Baby \u0026 children","key":"bc001","url":"https://www.ikea.com/au/en/cat/baby-children-bc001/","imageUrl":"https://www.ikea.com/global/assets/range-categorisation/images/baby-children-bc001.jpeg"},"type":"CATEGORY","label":"Category","actionTokens":[],"isBreakout":false},{"metadata":"v1;12;CATEGORY;li001;categories_shelf;","category":{"name":"Lighting","key":"li001","url":"https://www.ikea.com/au/en/cat/lighting-li001/","imageUrl":"https://www.ikea.com/global/assets/range-categorisation/images/lighting-li001.jpeg"},"type":"CATEGORY","label":"Category","actionTokens":[],"isBreakout":false}],"start":0,"end":12,"max":12}}],"pageMessages":[]},"content":{"badge":0,"filters":[],"sortOrders":{"name":"Sort","values":[]},"main":{"items":[],"start":0,"end":0,"max":0},"shelves":[],"pageMessages":[]}}}" diff --git a/resources/js/Pages/IkeaRoot.vue b/resources/js/Pages/IkeaRoot.vue index c078a64..ae84cfd 100644 --- a/resources/js/Pages/IkeaRoot.vue +++ b/resources/js/Pages/IkeaRoot.vue @@ -1,6 +1,4 @@ @@ -103,25 +113,35 @@ onMounted(fetch);
-
-
- -
-
-
- Zadaj krajiny v ktorych chces vyhadavat -
-
- - +
+
+
+
+
+ Zadaj krajiny v ktorych chces vyhadavat +
+
+ + +
+
+ Zadaj polozku +
+
+ + + +
- +
+
-