From f6c8b21f2cf3770e40723a7d6b7cd6d934ccdb41 Mon Sep 17 00:00:00 2001 From: Kevin Meijer Date: Mon, 28 Nov 2022 11:50:15 +0100 Subject: [PATCH 1/2] Prefixed category url path with slash --- src/Actions/Categories/CreateCategories.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Actions/Categories/CreateCategories.php b/src/Actions/Categories/CreateCategories.php index 57dae2b..b0191ae 100644 --- a/src/Actions/Categories/CreateCategories.php +++ b/src/Actions/Categories/CreateCategories.php @@ -19,7 +19,7 @@ public function create(Collection $categories, string $storeCode): \Illuminate\S 'magento_parent_id' => $category->parent_id ?? '', 'title' => $category->name, 'slug' => Str::replace('/', '-', $category->url_path), - 'url_path' => $category->url_path ?? '', + 'url_path' => $category->url_path ? '/' . $category->url_path : '', ])->each(fn ($category) => Entry::updateOrCreate($category, 'categories', 'slug', $storeCode)); } } From bb095e7c03100e3b095c386c62a84b5e79d2f9ef Mon Sep 17 00:00:00 2001 From: Kevin Meijer Date: Fri, 27 Jan 2023 11:52:03 +0100 Subject: [PATCH 2/2] Refactored Product import and added separate delete job --- src/Actions/Products/CreateProducts.php | 14 ++- src/Actions/Products/ImportProducts.php | 85 +++++++++++++++---- src/Commands/DeleteProductsCommand.php | 24 ++++++ src/Commands/SyncProductsCommand.php | 15 +++- .../Controllers/StatamicRewriteController.php | 30 +++++++ .../ViewComposers/StatamicDataComposer.php | 1 + src/Jobs/CreateProductsJob.php | 35 ++++++++ src/Jobs/DeleteProductsJob.php | 28 ++++++ src/Jobs/ImportProductsJob.php | 6 +- src/RapidezStatamicServiceProvider.php | 6 +- 10 files changed, 214 insertions(+), 30 deletions(-) create mode 100644 src/Commands/DeleteProductsCommand.php create mode 100644 src/Http/Controllers/StatamicRewriteController.php create mode 100644 src/Jobs/CreateProductsJob.php create mode 100644 src/Jobs/DeleteProductsJob.php diff --git a/src/Actions/Products/CreateProducts.php b/src/Actions/Products/CreateProducts.php index 995e9c6..556cb11 100644 --- a/src/Actions/Products/CreateProducts.php +++ b/src/Actions/Products/CreateProducts.php @@ -2,20 +2,16 @@ namespace Rapidez\Statamic\Actions\Products; -use Illuminate\Database\Eloquent\Collection; +use Illuminate\Support\Enumerable; use Statamic\Facades\Entry; class CreateProducts { - public function create(Collection $products, string $storeCode): \Illuminate\Support\Collection + public function create(Enumerable $products, string $storeCode): Enumerable { - if ($products->isEmpty()) { - return new Collection(); - } - - return $products->map(fn ($product) => [ + return $products->map(fn ($product): array => [ 'sku' => $product->sku, - 'title' => $product->name - ])->each(fn ($product) => Entry::updateOrCreate($product, 'products', 'sku', $storeCode)); + 'title' => $product->name, + ])->each(fn (array $product) => Entry::updateOrCreate($product, 'products', 'sku', $storeCode)); } } diff --git a/src/Actions/Products/ImportProducts.php b/src/Actions/Products/ImportProducts.php index a7addbd..52f509d 100644 --- a/src/Actions/Products/ImportProducts.php +++ b/src/Actions/Products/ImportProducts.php @@ -2,8 +2,13 @@ namespace Rapidez\Statamic\Actions\Products; +use Illuminate\Database\Eloquent\Builder; +use Illuminate\Support\Carbon; +use Illuminate\Support\Enumerable; use Illuminate\Support\Facades\DB; +use Rapidez\Core\Models\Model; use Rapidez\Statamic\Events\ProductsImportedEvent; +use Rapidez\Statamic\Jobs\CreateProductsJob; use Statamic\Facades\Site; class ImportProducts @@ -11,41 +16,89 @@ class ImportProducts public function __construct( public CreateProducts $createProducts, public DeleteProducts $deleteProducts, - protected int $chunkSize = 200 + protected int $chunkSize = 500 ) { } - public function import( - ?string $store = null - ): void + public function import(?Carbon $updatedAt = null, ?string $store = null): void { $productModel = config('rapidez.models.product'); - foreach(Site::all() as $site) { + $sites = Site::all(); + + if ($store !== null) { + $sites = collect([$store => Site::get($store)]); + } + + $sites->each(function ($site) use ($productModel, $updatedAt) { $siteAttributes = $site->attributes(); if (!isset($siteAttributes['magento_store_id'])) { - continue; + return; } config()->set('rapidez.store', $siteAttributes['magento_store_id']); - $productSkus = collect(); - $childIds = DB::table('catalog_product_super_link')->select(['product_id'])->get()->pluck('product_id'); - $flat = (new $productModel())->getTable(); + $childIds = DB::table('catalog_product_super_link')->pluck('product_id'); + + /** @var Model $flat */ + $flat = new $productModel(); + $productQuery = $productModel::selectOnlyIndexable() - ->where($flat . '.type_id', 'configurable') - ->orWhereNotIn($flat . '.entity_id', $childIds->toArray()) + ->when($updatedAt !== null, function (Builder $builder) use ($updatedAt): void { + $builder->where($builder->qualifyColumn('updated_at'), '>=', $updatedAt); + }) + ->where(function (Builder $builder) use ($childIds): void { + $builder + ->where($builder->qualifyColumn('type_id'), 'configurable') + ->orWhereNotIn($builder->qualifyColumn('entity_id'), $childIds->toArray()); + }) ->withEventyGlobalScopes('statamic.product.scopes'); - $productQuery->chunk($this->chunkSize, function ($products) use ($site, &$productSkus) { - $products = $this->createProducts->create($products, $site->handle()); - $productSkus = $productSkus->merge($products->map(fn ($product) => $product['sku'])); + $productQuery->chunk($this->chunkSize, function (Enumerable $products) use ($site): void { + CreateProductsJob::dispatch($products, $site->handle()); }); + }); - $this->deleteProducts->deleteOldProducts($productSkus, $site->handle()); + ProductsImportedEvent::dispatch(); + } + + public function delete(?string $store = null): void + { + $productModel = config('rapidez.models.product'); + + $sites = Site::all(); + + if ($store !== null) { + $sites = collect([$store => Site::get($store)]); } - ProductsImportedEvent::dispatch(); + $sites->each(function ($site) use ($productModel) { + $siteAttributes = $site->attributes(); + + if (!isset($siteAttributes['magento_store_id'])) { + return; + } + + config()->set('rapidez.store', $siteAttributes['magento_store_id']); + + $childIds = DB::table('catalog_product_super_link')->pluck('product_id'); + + /** @var Model $flat */ + $flat = new $productModel(); + + $productSkus = collect(); + + $productQuery = $productModel::selectOnlyIndexable() + ->where($flat->qualifyColumn('type_id'), 'configurable') + ->orWhereNotIn($flat->qualifyColumn('entity_id'), $childIds->toArray()) + ->withEventyGlobalScopes('statamic.product.scopes'); + + $productQuery->chunk($this->chunkSize, function (Enumerable $products) use ($site, &$productSkus): void { + $productSkus = $productSkus->merge($products->map(fn($product) => $product['sku'])); + }); + + $this->deleteProducts->deleteOldProducts($productSkus, $site->handle()); + }); } } diff --git a/src/Commands/DeleteProductsCommand.php b/src/Commands/DeleteProductsCommand.php new file mode 100644 index 0000000..5170939 --- /dev/null +++ b/src/Commands/DeleteProductsCommand.php @@ -0,0 +1,24 @@ +argument('store'); + + DeleteProductsJob::dispatch($store); + + return static::SUCCESS; + } +} diff --git a/src/Commands/SyncProductsCommand.php b/src/Commands/SyncProductsCommand.php index 9697118..93e1988 100644 --- a/src/Commands/SyncProductsCommand.php +++ b/src/Commands/SyncProductsCommand.php @@ -3,17 +3,28 @@ namespace Rapidez\Statamic\Commands; use Illuminate\Console\Command; +use Illuminate\Support\Carbon; use Rapidez\Statamic\Jobs\ImportProductsJob; class SyncProductsCommand extends Command { - protected $signature = 'rapidez:statamic:sync:products {store?}'; + protected $signature = 'rapidez:statamic:sync:products {store?} {--updated-at=}'; protected $description = 'Sync the Magento products to Statamic.'; public function handle(): int { - ImportProductsJob::dispatch($this->argument('store')); + /** @var ?string $store */ + $store = $this->argument('store'); + + /** @var ?string $updatedAt */ + $updatedAt = $this->option('updated-at'); + + if($updatedAt !== null) { + $updatedAt = Carbon::parse($updatedAt); + } + + ImportProductsJob::dispatch($updatedAt, $store); return static::SUCCESS; } diff --git a/src/Http/Controllers/StatamicRewriteController.php b/src/Http/Controllers/StatamicRewriteController.php new file mode 100644 index 0000000..c9a7465 --- /dev/null +++ b/src/Http/Controllers/StatamicRewriteController.php @@ -0,0 +1,30 @@ +get('rapidez.store_code'); + + $entry = Entry::query() + ->where('collection', 'pages') + ->where('locale', $storeCode) + ->where('slug', $request->path() == '/' ? 'home' : $request->path()) + ->first(); + + if (!$entry) { + throw new NotFoundHttpException(); + } + + $template = View::exists($entry->template()) ? $entry->template() : $entry->blueprint->handle(); + + echo view($template, ['entry' => $entry]); + } +} diff --git a/src/Http/ViewComposers/StatamicDataComposer.php b/src/Http/ViewComposers/StatamicDataComposer.php index f4eaa66..52273c0 100644 --- a/src/Http/ViewComposers/StatamicDataComposer.php +++ b/src/Http/ViewComposers/StatamicDataComposer.php @@ -30,6 +30,7 @@ public function compose(View $view) : View if(!isset($view->globals)) { $view->with('globals', (object)$this->globals); } + return $view; } } \ No newline at end of file diff --git a/src/Jobs/CreateProductsJob.php b/src/Jobs/CreateProductsJob.php new file mode 100644 index 0000000..cca9d5b --- /dev/null +++ b/src/Jobs/CreateProductsJob.php @@ -0,0 +1,35 @@ +products || !$this->siteHandle) { + return; + } + + $createProducts->create($this->products, $this->siteHandle); + } +} diff --git a/src/Jobs/DeleteProductsJob.php b/src/Jobs/DeleteProductsJob.php new file mode 100644 index 0000000..46a0c3d --- /dev/null +++ b/src/Jobs/DeleteProductsJob.php @@ -0,0 +1,28 @@ +delete($this->store); + } +} diff --git a/src/Jobs/ImportProductsJob.php b/src/Jobs/ImportProductsJob.php index ce93aef..504dc02 100644 --- a/src/Jobs/ImportProductsJob.php +++ b/src/Jobs/ImportProductsJob.php @@ -7,6 +7,7 @@ use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Foundation\Bus\Dispatchable; use Illuminate\Queue\InteractsWithQueue; +use Illuminate\Support\Carbon; use Rapidez\Statamic\Actions\Products\ImportProducts; class ImportProductsJob implements ShouldQueue, ShouldBeUnique @@ -16,12 +17,13 @@ class ImportProductsJob implements ShouldQueue, ShouldBeUnique use Queueable; public function __construct( - public ?string $store = null + public ?Carbon $updatedAt = null, + public ?string $store = null, ){ } public function handle(ImportProducts $importProducts): void { - $importProducts->import($this->store); + $importProducts->import($this->updatedAt, $this->store); } } diff --git a/src/RapidezStatamicServiceProvider.php b/src/RapidezStatamicServiceProvider.php index e3d986b..6293c4d 100644 --- a/src/RapidezStatamicServiceProvider.php +++ b/src/RapidezStatamicServiceProvider.php @@ -3,9 +3,11 @@ namespace Rapidez\Statamic; use Illuminate\Support\ServiceProvider; +use Rapidez\Statamic\Http\Controllers\StatamicRewriteController; use Statamic\Http\Controllers\FrontendController; use Illuminate\Support\Facades\Cache; use Illuminate\Support\Facades\Event; +use Rapidez\Statamic\Commands\DeleteProductsCommand; use Rapidez\Statamic\Commands\SyncProductsCommand; use Rapidez\Statamic\Commands\SyncCategoriesCommand; use Statamic\Facades\Entry; @@ -20,6 +22,7 @@ use Validator; use Statamic\Events\GlobalSetSaved; use Statamic\Events\GlobalSetDeleted; +use TorMorten\Eventy\Facades\Eventy; class RapidezStatamicServiceProvider extends ServiceProvider { @@ -39,7 +42,7 @@ public function boot() public function bootRoutes() : self { if (!$this->app->routesAreCached()) { - Rapidez::addFallbackRoute([FrontendController::class, 'index'], 100); + Rapidez::addFallbackRoute(StatamicRewriteController::class, 100); } return $this; @@ -56,6 +59,7 @@ public function bootCommands() : self { $this->commands([ SyncProductsCommand::class, + DeleteProductsCommand::class, SyncCategoriesCommand::class ]);