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])); } }