Files
fitness/app/Console/Commands/FetchYogaDataCommand.php

104 lines
3.8 KiB
PHP

<?php
namespace App\Console\Commands;
use App\Models\YogaCategory;
use App\Models\YogaPose;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Str;
class FetchYogaDataCommand extends Command
{
protected $signature = 'yoga:fetch {--force : Recreate slugs}';
protected $description = 'Fetch yoga categories and poses from public API and upsert into local DB';
public function handle(): int
{
$url = 'https://yoga-api-nzy4.onrender.com/v1/categories';
$this->info('Fetching: ' . $url);
$response = Http::timeout(30)->acceptJson()->get($url);
if (!$response->ok()) {
$this->error('Failed to fetch data: ' . $response->status());
return self::FAILURE;
}
$data = $response->json();
if (!is_array($data)) {
$this->error('Unexpected response format');
return self::FAILURE;
}
$countCategories = 0; $countPoses = 0;
foreach ($data as $cat) {
$extId = (int) ($cat['id'] ?? 0);
if ($extId <= 0) { continue; }
$category = YogaCategory::updateOrCreate(
['external_id' => $extId],
[
'name' => (string) ($cat['category_name'] ?? 'Category ' . $extId),
'description' => (string) ($cat['category_description'] ?? ''),
]
);
$countCategories++;
$poses = $cat['poses'] ?? [];
if (!is_array($poses)) { $poses = []; }
foreach ($poses as $pose) {
$pExt = (int) ($pose['id'] ?? 0);
if ($pExt <= 0) { continue; }
$payload = [
'category_id' => $category->id,
'english_name' => (string) ($pose['english_name'] ?? ''),
'sanskrit_name_adapted' => (string) ($pose['sanskrit_name_adapted'] ?? ''),
'sanskrit_name' => (string) ($pose['sanskrit_name'] ?? ''),
'translation_name' => (string) ($pose['translation_name'] ?? ''),
'description' => (string) ($pose['pose_description'] ?? ''),
'benefits' => (string) ($pose['pose_benefits'] ?? ''),
'url_svg' => (string) ($pose['url_svg'] ?? ''),
'url_png' => (string) ($pose['url_png'] ?? ''),
'url_svg_alt' => (string) ($pose['url_svg_alt'] ?? ''),
];
$model = YogaPose::updateOrCreate(
['external_id' => $pExt],
$payload + [
// slug may be regenerated with --force
'slug' => $this->makeSlug($payload['english_name'], $pExt, $category->name),
]
);
if ($this->option('force')) {
$model->slug = $this->makeSlug($payload['english_name'], $pExt, $category->name, true);
$model->save();
}
$countPoses++;
}
}
$this->info("Imported {$countCategories} categories, {$countPoses} poses.");
return self::SUCCESS;
}
protected function makeSlug(string $englishName, int $externalId, string $categoryName = '', bool $force = false): string
{
$base = Str::slug($englishName !== '' ? $englishName : ('pose-' . $externalId));
if ($base === '') { $base = 'pose-' . $externalId; }
$slug = $base;
$i = 1;
while (YogaPose::where('slug', $slug)->exists()) {
// If force-regenerating we allow different category-based suffix to reduce collisions
$suffix = $force && $categoryName ? '-' . Str::slug($categoryName) : '';
$slug = $base . $suffix . '-' . (++$i);
}
return $slug;
}
}