Feature: Add Shopify product importer and table-rate shipping; bump to 0.2.0 #1

Merged
arvanitakis merged 5 commits from 1811058982446433859-creating-product-importer into master 2026-07-08 21:40:16 +00:00
7 changed files with 147 additions and 1 deletions
Showing only changes of commit cd9632a6bf - Show all commits
+61
View File
@@ -0,0 +1,61 @@
<?php
namespace Modules\Core\Command;
use Illuminate\Console\Command;
use Modules\Core\MigrateImport\ImportSpec;
use Modules\Core\MigrateImport\RunMigrateImportJob;
class MigrateImportCommand extends Command
{
protected $signature = "boboko:migrate:import
{--source= : The source platform to import from}
{--type= : The import mechanism for the chosen source}
{--file= : Path to the export file (when type is export)}";
protected $description = "Migrate data (products, customers, etc.) from an external source";
// Supported sources. Only "shopify" is wired up for now.
private const SOURCES = [
"shopify",
// "woocommerce",
];
// Supported import types per source. Only "export" is wired up for now.
private const TYPES = [
"export",
// "api",
];
public function handle(): void
{
$source = $this->option("source")
?? $this->choice("Select a source:", self::SOURCES, 0);
$type = $this->option("type")
?? $this->choice("Select an import type:", self::TYPES, 0);
if ($type === "api") {
$credentials = [
"api_key" => $this->secret("API key:"),
"api_secret" => $this->secret("API secret:"),
];
$filePath = null;
} else {
$filePath = $this->option("file")
?? $this->ask("Path to the export file:");
$credentials = null;
}
$spec = new ImportSpec(
source: $source,
type: $type,
filePath: $filePath,
credentials: $credentials,
);
RunMigrateImportJob::dispatch($spec);
$this->info("Import queued.");
}
}
+14
View File
@@ -0,0 +1,14 @@
<?php
namespace Modules\Core\MigrateImport;
class ImportSpec
{
public function __construct(
public readonly string $source,
public readonly string $type,
public readonly ?string $filePath = null,
public readonly ?array $credentials = null,
) {
}
}
+8
View File
@@ -0,0 +1,8 @@
<?php
namespace Modules\Core\MigrateImport;
interface Importer
{
public function import(ImportSpec $spec): void;
}
+21
View File
@@ -0,0 +1,21 @@
<?php
namespace Modules\Core\MigrateImport;
use Modules\Core\MigrateImport\Shopify\ShopifyExportImporter;
class ImporterFactory
{
public static function make(ImportSpec $spec): Importer
{
return match ([$spec->source, $spec->type]) {
["shopify", "export"] => new ShopifyExportImporter(),
// ["shopify", "api"] => new ShopifyApiImporter(),
// ["woocommerce", "export"] => new WooCommerceExportImporter(),
// ["woocommerce", "api"] => new WooCommerceApiImporter(),
default => throw new \InvalidArgumentException(
"No importer available for source \"{$spec->source}\" with type \"{$spec->type}\".",
),
};
}
}
+28
View File
@@ -0,0 +1,28 @@
<?php
namespace Modules\Core\MigrateImport;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
class RunMigrateImportJob implements ShouldQueue
{
use Dispatchable;
use InteractsWithQueue;
use Queueable;
use SerializesModels;
public function __construct(
public readonly ImportSpec $spec,
) {
}
public function handle(): void
{
$importer = ImporterFactory::make($this->spec);
$importer->import($this->spec);
}
}
@@ -0,0 +1,13 @@
<?php
namespace Modules\Core\MigrateImport\Shopify;
use Modules\Core\MigrateImport\ImportSpec;
use Modules\Core\MigrateImport\Importer;
class ShopifyExportImporter implements Importer
{
public function import(ImportSpec $spec): void
{
}
}
+2 -1
View File
@@ -8,6 +8,7 @@ use Modules\Core\Command\AnonymizeCommand;
use Modules\Core\Command\ExportCleanupCommand;
use Modules\Core\Command\ExportCommand;
use Modules\Core\Command\ImportCommand;
use Modules\Core\Command\MigrateImportCommand;
class CoreServiceProvider extends ServiceProvider
{
@@ -32,7 +33,7 @@ class CoreServiceProvider extends ServiceProvider
], 'core-assets');
if ($this->app->runningInConsole()) {
$this->commands([AnonymizeCommand::class, ExportCommand::class, ExportCleanupCommand::class, ImportCommand::class]);
$this->commands([AnonymizeCommand::class, ExportCommand::class, ExportCleanupCommand::class, ImportCommand::class, MigrateImportCommand::class]);
}
}
}