118 lines
4.3 KiB
PHP
118 lines
4.3 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace Krzysiej\RyobiCrawler\Command;
|
|
|
|
use GuzzleHttp\Client;
|
|
use GuzzleHttp\Exception\GuzzleException;
|
|
use Illuminate\Database\Capsule\Manager as Capsule;
|
|
use Krzysiej\RyobiCrawler\Models\Price;
|
|
use Krzysiej\RyobiCrawler\Models\Product;
|
|
use Krzysiej\RyobiCrawler\Models\Stock;
|
|
use Symfony\Component\Console\Attribute\AsCommand;
|
|
use Symfony\Component\Console\Command\Command;
|
|
use Symfony\Component\Console\Helper\ProgressBar;
|
|
use Symfony\Component\Console\Input\InputInterface;
|
|
use Symfony\Component\Console\Output\OutputInterface;
|
|
|
|
#[AsCommand(name: 'app:scrape', description: 'Scrape all products from Ryobi website')]
|
|
class ScrapeWebsite extends Command
|
|
{
|
|
private Client $client;
|
|
|
|
protected function configure(): void
|
|
{
|
|
$capsule = new Capsule;
|
|
$capsule->addConnection([
|
|
'driver' => 'sqlite',
|
|
'database' => __DIR__ . '/../../database.sqlite',
|
|
]);
|
|
$capsule->setAsGlobal();
|
|
$capsule->bootEloquent();
|
|
$this->client = new Client();
|
|
}
|
|
|
|
public function execute(InputInterface $input, OutputInterface $output): int
|
|
{
|
|
$progress = new ProgressBar($output);
|
|
$progress->start();
|
|
$products = $this->getProducts();
|
|
$progress->setMaxSteps(count($products));
|
|
foreach ($products as $product) {
|
|
$this->saveProduct($product);
|
|
$progress->advance();
|
|
}
|
|
$progress->finish();
|
|
$output->writeln('');
|
|
$output->writeln('DONE');
|
|
|
|
return Command::SUCCESS;
|
|
}
|
|
|
|
private function getProducts(): array
|
|
{
|
|
$products = [];
|
|
$page = 0;
|
|
do {
|
|
try {
|
|
$res = $this->client->request('POST', 'https://pl.ryobitools.eu/api/product-listing/get-products', [
|
|
'form_params' => [
|
|
"includePreviousPages" => false,
|
|
"pageIndex" => $page,
|
|
"pageSize" => 100,
|
|
"cultureCode" => "pl-PL",
|
|
]
|
|
]);
|
|
$responseObject = json_decode($res->getBody()->getContents());
|
|
$products = array_merge($products, $responseObject->products);
|
|
$page++;
|
|
$canLoadMore = $responseObject->canLoadMore;
|
|
} catch (GuzzleException) {
|
|
return $products;
|
|
}
|
|
} while ($canLoadMore);
|
|
|
|
return $products;
|
|
}
|
|
|
|
private function saveProduct(\stdClass $product): void
|
|
{
|
|
/** @var Product $productModel */
|
|
$productModel = Product::firstOrNew(['skuID' => $product->skuID]);
|
|
|
|
$productModel->skuID = $product->skuID;
|
|
$productModel->name = $product->name;
|
|
$productModel->availableQuantity = $product->availableQuantity;
|
|
$productModel->categories = $product->categories;
|
|
$productModel->image = $product->image;
|
|
$productModel->subTitle = $product->subTitle;
|
|
$productModel->variantCode = $product->variantCode;
|
|
$productModel->modelCode = $product->modelCode;
|
|
$productModel->url = $product->url;
|
|
$productModel->touch('updated_at');
|
|
$productModel->save();
|
|
$priceExists = $productModel->price()->whereRaw("strftime('%Y-%m-%d', created_at) = ?", [date('Y-m-d')])->exists();
|
|
|
|
if (false === $priceExists) {
|
|
$price = new Price();
|
|
$price->price = $product->productPrice;
|
|
$price->productStandardPrice = $product->productStandardPrice;
|
|
$price->lowestProductPrice30Days = $product->lowestProductPrice30Days;
|
|
$productModel->price()->save($price);
|
|
}
|
|
$stockExist = $productModel->stock()->whereRaw("strftime('%Y-%m-%d', created_at) = ?", [date('Y-m-d')])->exists();
|
|
if (false === $stockExist) {
|
|
$stock = new Stock();
|
|
$stock->availableQuantity = $product->availableQuantity;
|
|
$stock->stock = $product->stock;
|
|
$stock->isInStock = $product->isInStock;
|
|
$stock->previouslyHadStock = $product->previouslyHadStock;
|
|
$stock->isNew = $product->isNew;
|
|
$stock->isComingSoon = $product->isComingSoon;
|
|
$stock->isOnSale = $product->isOnSale;
|
|
$productModel->stock()->save($stock);
|
|
}
|
|
}
|
|
}
|