323 lines
13 KiB
PHP
323 lines
13 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace Krzysiej\RyobiCrawler\Command;
|
|
|
|
use Illuminate\Database\Capsule\Manager as Capsule;
|
|
use Illuminate\Database\Schema\Blueprint;
|
|
use Krzysiej\RyobiCrawler\Models\Country;
|
|
use Symfony\Component\Console\Attribute\AsCommand;
|
|
use Symfony\Component\Console\Command\Command;
|
|
use Symfony\Component\Console\Input\InputInterface;
|
|
use Symfony\Component\Console\Input\InputOption;
|
|
use Symfony\Component\Console\Output\OutputInterface;
|
|
use function Symfony\Component\Clock\now;
|
|
|
|
#[AsCommand(name: 'app:migrate', description: 'Create database and rum migrations')]
|
|
class Migrate extends Command
|
|
{
|
|
private const RECREATE_OPTION = 'recreate';
|
|
|
|
protected function configure(): void
|
|
{
|
|
$this->addOption(self::RECREATE_OPTION, null, InputOption::VALUE_OPTIONAL, 'Recreate database file event if exist and has data.');
|
|
}
|
|
|
|
public function execute(InputInterface $input, OutputInterface $output): int
|
|
{
|
|
if ($input->getOption(self::RECREATE_OPTION)) {
|
|
unlink(__DIR__ . '/../../database.sqlite');
|
|
touch(__DIR__ . '/../../database.sqlite');
|
|
}
|
|
$capsule = new Capsule;
|
|
$capsule->addConnection([
|
|
'driver' => 'sqlite',
|
|
'database' => __DIR__ . '/../../database.sqlite',
|
|
]);
|
|
$capsule->setAsGlobal();
|
|
$capsule->bootEloquent();
|
|
$this->createProductsTable();
|
|
$this->createPricesTable();
|
|
$this->createStocksTable();
|
|
$this->addColumns();
|
|
$this->createCountriesTable();
|
|
$this->index();
|
|
|
|
return Command::SUCCESS;
|
|
}
|
|
|
|
public function createProductsTable(): void
|
|
{
|
|
if (!Capsule::schema()->hasTable('products')) {
|
|
Capsule::schema()->create('products', function (Blueprint $table) {
|
|
$table->increments('id');
|
|
$table->string('name');
|
|
$table->integer('skuID')->unique();
|
|
$table->integer('availableQuantity');
|
|
$table->json('categories');
|
|
$table->string('image');
|
|
$table->string('subTitle');
|
|
$table->string('variantCode');
|
|
$table->string('modelCode');
|
|
$table->string('url');
|
|
$table->boolean('starred')->default(false);
|
|
$table->timestamps();
|
|
});
|
|
}
|
|
}
|
|
|
|
public function createPricesTable(): void
|
|
{
|
|
if (!Capsule::schema()->hasTable('prices')) {
|
|
Capsule::schema()->create('prices', function (Blueprint $table) {
|
|
$table->increments('id');
|
|
$table->foreignId('product_id');
|
|
$table->float('price');
|
|
$table->float('productStandardPrice');
|
|
$table->float('lowestProductPrice30Days');
|
|
$table->timestamps();
|
|
});
|
|
}
|
|
}
|
|
|
|
public function createCountriesTable(): void
|
|
{
|
|
if (!Capsule::schema()->hasTable('countries')) {
|
|
Capsule::schema()->create('countries', function (Blueprint $table) {
|
|
$table->increments('id');
|
|
$table->text('countryName');
|
|
$table->text('productsUrl');
|
|
$table->text('cultureCode');
|
|
$table->text('currency');
|
|
$table->text('locale');
|
|
$table->timestamps();
|
|
});
|
|
}
|
|
if (Capsule::schema()->hasTable('countries') && !Country::where('countryName', 'Poland')->exists()) {
|
|
$id = Capsule::table('countries')->insertGetId(
|
|
[
|
|
'countryName' => 'Poland',
|
|
'productsUrl' => 'https://pl.ryobitools.eu/api/product-listing/get-products',
|
|
'cultureCode' => 'pl-PL',
|
|
'currency' => 'PLN',
|
|
'locale' => 'pl',
|
|
'created_at' => now(),
|
|
'updated_at' => now(),
|
|
]);
|
|
}
|
|
if (Capsule::schema()->hasTable('countries') && !Country::where('countryName', 'UK')->exists()) {
|
|
Capsule::table('countries')->insert([
|
|
'countryName' => 'UK',
|
|
'productsUrl' => 'https://uk.ryobitools.eu/api/product-listing/get-products',
|
|
'cultureCode' => 'en-GB',
|
|
'currency' => 'GBP',
|
|
'locale' => 'uk',
|
|
'created_at' => now(),
|
|
'updated_at' => now(),
|
|
]
|
|
);
|
|
}
|
|
if (Capsule::schema()->hasTable('countries') && !Country::where('countryName', 'Netherlands')->exists()) {
|
|
Capsule::table('countries')->insert([
|
|
'countryName' => 'Netherlands',
|
|
'productsUrl' => 'https://nl.ryobitools.eu/api/product-listing/get-products',
|
|
'cultureCode' => 'nl-NL',
|
|
'currency' => 'EUR',
|
|
'locale' => 'nl',
|
|
'created_at' => now(),
|
|
'updated_at' => now(),
|
|
]
|
|
);
|
|
}
|
|
if (Capsule::schema()->hasTable('countries') && !Country::where('countryName', 'France')->exists()) {
|
|
Capsule::table('countries')->insert([
|
|
'countryName' => 'France',
|
|
'productsUrl' => 'https://fr.ryobitools.eu/api/product-listing/get-products',
|
|
'cultureCode' => 'fr-FR',
|
|
'currency' => 'EUR',
|
|
'locale' => 'fr',
|
|
'created_at' => now(),
|
|
'updated_at' => now(),
|
|
]
|
|
);
|
|
}
|
|
if (Capsule::schema()->hasTable('countries') && !Country::where('countryName', 'Spain')->exists()) {
|
|
Capsule::table('countries')->insert([
|
|
'countryName' => 'Spain',
|
|
'productsUrl' => 'https://es.ryobitools.eu/api/product-listing/get-products',
|
|
'cultureCode' => 'es-ES',
|
|
'currency' => 'EUR',
|
|
'locale' => 'es',
|
|
'created_at' => now(),
|
|
'updated_at' => now(),
|
|
]
|
|
);
|
|
}
|
|
if (Capsule::schema()->hasTable('countries') && !Country::where('countryName', 'Poland')->exists()) {
|
|
$id = Capsule::table('countries')->insertGetId(
|
|
[
|
|
'countryName' => 'Poland',
|
|
'productsUrl' => 'https://pl.ryobitools.eu/api/product-listing/get-products',
|
|
'cultureCode' => 'pl-PL',
|
|
'currency' => 'PLN',
|
|
'locale' => 'pl',
|
|
'created_at' => now(),
|
|
'updated_at' => now(),
|
|
]);
|
|
}
|
|
if (Capsule::schema()->hasTable('countries') && !Country::where('countryName', 'UK')->exists()) {
|
|
Capsule::table('countries')->insert([
|
|
'countryName' => 'UK',
|
|
'productsUrl' => 'https://uk.ryobitools.eu/api/product-listing/get-products',
|
|
'cultureCode' => 'en-GB',
|
|
'currency' => 'GBP',
|
|
'locale' => 'uk',
|
|
'created_at' => now(),
|
|
'updated_at' => now(),
|
|
]
|
|
);
|
|
}
|
|
|
|
if (!Capsule::schema()->hasColumn('products', 'country_id')) {
|
|
Capsule::schema()->table('products', function (Blueprint $table) use ($id) {
|
|
$table->foreignId('country_id')->default($id)->references('id')->on('countries');
|
|
});
|
|
}
|
|
}
|
|
|
|
public function createStocksTable(): void
|
|
{
|
|
if (!Capsule::schema()->hasTable('stocks')) {
|
|
Capsule::schema()->create('stocks', function (Blueprint $table) {
|
|
$table->increments('id');
|
|
$table->foreignId('product_id');
|
|
$table->integer('availableQuantity');
|
|
$table->integer('stock');
|
|
$table->boolean('isInStock');
|
|
$table->boolean('previouslyHadStock');
|
|
$table->boolean('isNew');
|
|
$table->boolean('isComingSoon');
|
|
$table->boolean('isOnSale');
|
|
$table->timestamps();
|
|
});
|
|
}
|
|
}
|
|
|
|
public function addColumns(): void
|
|
{
|
|
if (!Capsule::schema()->hasColumn('products', 'priceCurrent')) {
|
|
Capsule::schema()->table('products', function (Blueprint $table) {
|
|
$table->float('priceCurrent')->default(0);
|
|
});
|
|
}
|
|
|
|
if (!Capsule::schema()->hasColumn('products', 'priceLowest')) {
|
|
Capsule::schema()->table('products', function (Blueprint $table) {
|
|
$table->float('priceLowest')->default(0);
|
|
});
|
|
}
|
|
|
|
if (!Capsule::schema()->hasColumn('products', 'productStandardPrice')) {
|
|
Capsule::schema()->table('products', function (Blueprint $table) {
|
|
$table->float('productStandardPrice')->default(0);
|
|
});
|
|
}
|
|
|
|
if (!Capsule::schema()->hasColumn('products', 'lowestProductPrice30Days')) {
|
|
Capsule::schema()->table('products', function (Blueprint $table) {
|
|
$table->float('lowestProductPrice30Days')->default(0);
|
|
});
|
|
}
|
|
|
|
if (!Capsule::schema()->hasColumn('products', 'lastSeen')) {
|
|
Capsule::schema()->table('products', function (Blueprint $table) {
|
|
$table->date('lastSeen')->nullable();
|
|
});
|
|
}
|
|
|
|
if (!Capsule::schema()->hasColumn('products', 'stock')) {
|
|
Capsule::schema()->table('products', function (Blueprint $table) {
|
|
$table->integer('stock')->nullable();
|
|
});
|
|
}
|
|
if (!Capsule::schema()->hasColumn('products', 'promotions')) {
|
|
Capsule::schema()->table('products', function (Blueprint $table) {
|
|
$table->json('promotions')->nullable();
|
|
});
|
|
}
|
|
if (!Capsule::schema()->hasColumn('prices', 'conversionRate')) {
|
|
Capsule::schema()->table('prices', function (Blueprint $table) {
|
|
$table->float('conversionRate')->nullable();
|
|
});
|
|
}
|
|
if (!Capsule::schema()->hasColumn('products', 'conversionRate')) {
|
|
Capsule::schema()->table('products', function (Blueprint $table) {
|
|
$table->float('conversionRate')->nullable();
|
|
});
|
|
}
|
|
}
|
|
|
|
public function index(): void
|
|
{
|
|
if (!$this->hasIndex('products_skuid_country_id_unique')) {
|
|
Capsule::schema()->table('products', function (Blueprint $table) {
|
|
if ($this->hasIndex('products_skuid_unique')) {
|
|
$table->integer('skuID')->unique(false)->change();
|
|
}
|
|
$table->unique(['skuID', 'country_id']);
|
|
});
|
|
}
|
|
|
|
if (!$this->hasIndex('prices_product_id_index')) {
|
|
Capsule::schema()->table('prices', function (Blueprint $table) {
|
|
$table->index('product_id');
|
|
});
|
|
}
|
|
|
|
if (!$this->hasIndex('products_id_index')) {
|
|
Capsule::schema()->table('products', function (Blueprint $table) {
|
|
$table->index('id');
|
|
});
|
|
}
|
|
|
|
if (!$this->hasIndex('stocks_product_id_stock_index')) {
|
|
Capsule::schema()->table('stocks', function (Blueprint $table) {
|
|
$table->index(['product_id', 'stock']);
|
|
});
|
|
}
|
|
|
|
if (!$this->isFK('products', 'id', 'stocks', 'product_id')) {
|
|
Capsule::schema()->table('products', function (Blueprint $table) {
|
|
$table->foreign('id')->references('product_id')->on('stocks');
|
|
});
|
|
}
|
|
|
|
if (!$this->isFK('products', 'id', 'prices', 'product_id')) {
|
|
Capsule::schema()->table('products', function (Blueprint $table) {
|
|
$table->foreign('id')->references('product_id')->on('prices');
|
|
});
|
|
}
|
|
if (!$this->isFK('products', 'country_id', 'countries', 'id')) {
|
|
Capsule::schema()->table('products', function (Blueprint $table) {
|
|
$table->foreign('country_id')->references('id')->on('countries');
|
|
});
|
|
}
|
|
}
|
|
|
|
private function isFK(string $table, string $column, string $fTable, string $fColumn): bool
|
|
{
|
|
$fkColumns = Capsule::schema()->getForeignKeys($table);
|
|
|
|
return !empty(array_filter($fkColumns, fn($fkColumn) => ($fkColumn['foreign_table'] == $fTable &&
|
|
in_array($fColumn, $fkColumn['foreign_columns']) &&
|
|
in_array($column, $fkColumn['columns']))
|
|
));
|
|
}
|
|
|
|
private function hasIndex(string $indexName): bool
|
|
{
|
|
return !!count(Capsule::select('SELECT name FROM sqlite_master WHERE type = "index" and name = ?', [$indexName]));
|
|
}
|
|
}
|