resolvePackages(); if ($packages->isEmpty()) { $this->warn('No packages matched the given filters.'); return self::FAILURE; } $dryRun = (bool) $this->option('dry-run'); $pull = (bool) $this->option('pull'); $queue = (bool) $this->option('queue'); $allowUnmapped = (bool) $this->option('allow-unmapped'); if (! $pull && ! $allowUnmapped && ! $this->hasPackageFilter()) { if (! $this->guardUnmappedPackages($packages)) { return self::FAILURE; } } $packages->each(function (Package $package) use ($dryRun, $pull, $queue) { if ($pull) { $this->dispatchPullJob($package, $queue); return; } $this->dispatchSyncJob($package, $dryRun, $queue); }); $this->info(sprintf( 'Queued %d package %s for Paddle %s.', $packages->count(), Str::plural('entry', $packages->count()), $pull ? 'pull' : 'sync' )); return self::SUCCESS; } protected function resolvePackages(): Collection { $keys = collect((array) $this->option('package'))->filter(); $query = Package::query(); if ($keys->isNotEmpty()) { $ids = $keys ->filter(fn ($value) => is_numeric($value)) ->map(fn ($value) => (int) $value); $slugs = $keys ->reject(fn ($value) => is_numeric($value)) ->values(); $query->where(function ($builder) use ($ids, $slugs) { if ($ids->isNotEmpty()) { $builder->orWhereIn('id', $ids); } if ($slugs->isNotEmpty()) { $builder->orWhereIn('slug', $slugs); } }); } return $query->orderByDesc('id')->get(); } protected function hasPackageFilter(): bool { return collect((array) $this->option('package'))->filter()->isNotEmpty(); } protected function guardUnmappedPackages(Collection $packages): bool { $unmapped = $packages->filter(fn (Package $package) => blank($package->paddle_product_id) || blank($package->paddle_price_id)); if ($unmapped->isEmpty()) { return true; } $this->error('Unmapped Paddle package IDs detected. Resolve legacy mappings or pass --allow-unmapped.'); $this->table( ['ID', 'Slug', 'Missing'], $unmapped->map(function (Package $package): array { $missing = []; if (blank($package->paddle_product_id)) { $missing[] = 'product_id'; } if (blank($package->paddle_price_id)) { $missing[] = 'price_id'; } return [ $package->id, $package->slug, implode(', ', $missing), ]; })->values()->all() ); return false; } protected function dispatchSyncJob(Package $package, bool $dryRun, bool $queue): void { $context = [ 'dry_run' => $dryRun, ]; if ($queue) { SyncPackageToPaddle::dispatch($package->id, $context); $this->line(sprintf('> queued sync for package #%d (%s)', $package->id, $package->slug)); return; } SyncPackageToPaddle::dispatchSync($package->id, $context); $this->line(sprintf('> synced package #%d (%s)', $package->id, $package->slug)); } protected function dispatchPullJob(Package $package, bool $queue): void { if ($queue) { PullPackageFromPaddle::dispatch($package->id); $this->line(sprintf('> queued pull for package #%d (%s)', $package->id, $package->slug)); return; } PullPackageFromPaddle::dispatchSync($package->id); $this->line(sprintf('> pulled package #%d (%s)', $package->id, $package->slug)); } }