104 lines
3.8 KiB
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;
|
|
}
|
|
}
|