apiService = $apiService; parent::__construct(); } /** * Execute the console command. */ public function handle(): int { $page = 1; $stored = 0; $updated = 0; $this->info('Fetching exercises from ExerciseDB...'); while (true) { $results = $this->apiService->fetch($page); $results = $results['data']; $count = count($results); if ($count === 0) { break; } [$s, $u] = $this->process($results); $stored += $s; $updated += $u; $this->info("Processed page {$page} with {$count} items."); if ($count < ApiService::PER_PAGE) { break; } $page++; sleep(5); } $this->info("Done. Created {$stored}, updated {$updated} exercises."); return self::SUCCESS; } /** * @param array> $results * @return array{int,int} [created, updated] */ private function process(array $results): array { $created = 0; $updated = 0; foreach ($results as $item) { $exerciseDbId = (string)($item['exerciseId'] ?? ''); if ($exerciseDbId === '') { continue; } $name = (string)($item['name'] ?? ''); $gifUrl = (string)($item['gifUrl'] ?? ''); $instructions = $item['instructions'] ?? []; if (is_array($instructions)) { $instructionsText = implode("\n", array_filter(array_map('strval', $instructions))); } else { $instructionsText = (string)$instructions; } $slug = Str::slug($name) ?: $exerciseDbId; $values = [ 'name' => $name, 'slug' => $slug, 'gif_url' => $gifUrl, 'instructions' => $instructionsText, ]; $existing = Exercise::where('exercise_db_id', $exerciseDbId)->first(); $exercise = Exercise::updateOrCreate( ['exercise_db_id' => $exerciseDbId], $values, ); if ($existing) { $updated++; } else { $created++; } // Relations // Body part (string) $bodyPartVal = $item['bodyPart'] ?? null; $bodyPartIds = []; if ($bodyPartVal) { $bodyParts = is_array($bodyPartVal) ? $bodyPartVal : [$bodyPartVal]; foreach ($bodyParts as $bp) { $bpName = (string)$bp; $bpSlug = Str::slug($bpName); $bpModel = BodyPart::firstOrCreate(['slug' => $bpSlug], ['name' => $bpName]); $bodyPartIds[] = $bpModel->id; } } if ($bodyPartIds) { $exercise->bodyParts()->sync($bodyPartIds); } // Target muscle (string) $targetVal = $item['target'] ?? null; $targetIds = []; if ($targetVal) { $targets = is_array($targetVal) ? $targetVal : [$targetVal]; foreach ($targets as $tm) { $mName = (string)$tm; $mSlug = Str::slug($mName); $mModel = Muscle::firstOrCreate(['slug' => $mSlug], ['name' => $mName]); $targetIds[] = $mModel->id; } } if ($targetIds) { $exercise->targetMuscles()->sync($targetIds); } // Secondary muscles (array) $secVal = $item['secondaryMuscles'] ?? []; $secondaryIds = []; if (!is_array($secVal)) { $secVal = [$secVal]; } foreach ($secVal as $sm) { $smName = (string)$sm; if ($smName === '') { continue; } $smSlug = Str::slug($smName); $mModel = Muscle::firstOrCreate(['slug' => $smSlug], ['name' => $smName]); $secondaryIds[] = $mModel->id; } if ($secondaryIds) { $exercise->secondaryMuscles()->sync($secondaryIds); } // Equipment (string or array depending on source variant) $equipVal = $item['equipment'] ?? null; $equipmentIds = []; if ($equipVal) { $equipments = is_array($equipVal) ? $equipVal : [$equipVal]; foreach ($equipments as $eq) { $eqName = (string)$eq; $eqSlug = Str::slug($eqName); $eqModel = Equipment::firstOrCreate(['slug' => $eqSlug], ['name' => $eqName]); $equipmentIds[] = $eqModel->id; } } if ($equipmentIds) { $exercise->equipments()->sync($equipmentIds); } } return [$created, $updated]; } }