From 214caa263b3a47f4e560bba63b3b0c46b8d8000b Mon Sep 17 00:00:00 2001 From: Richard Dern Date: Thu, 18 Apr 2024 01:52:40 +0200 Subject: [PATCH] Added basic Rebrickable service --- app/Providers/RebrickableServiceProvider.php | 29 ++++++++++ .../CollectibleCreators/LegoBundleCreator.php | 58 +++++++++++++++++-- .../Rebrickable/RebrickableClient.php | 58 +++++++++++++++++++ bootstrap/providers.php | 1 + config/services.php | 5 ++ 5 files changed, 147 insertions(+), 4 deletions(-) create mode 100644 app/Providers/RebrickableServiceProvider.php create mode 100644 app/Services/Rebrickable/RebrickableClient.php diff --git a/app/Providers/RebrickableServiceProvider.php b/app/Providers/RebrickableServiceProvider.php new file mode 100644 index 0000000..69a2105 --- /dev/null +++ b/app/Providers/RebrickableServiceProvider.php @@ -0,0 +1,29 @@ +app->singleton(RebrickableClient::class, function ($app) { + $config = $app['config']->get('services.rebrickable'); + + return new RebrickableClient($config); + }); + } + + /** + * Bootstrap services. + */ + public function boot(): void + { + // + } +} diff --git a/app/Services/BundleCreator/Creators/CollectibleCreators/LegoBundleCreator.php b/app/Services/BundleCreator/Creators/CollectibleCreators/LegoBundleCreator.php index 8cb4d93..b1d4df0 100644 --- a/app/Services/BundleCreator/Creators/CollectibleCreators/LegoBundleCreator.php +++ b/app/Services/BundleCreator/Creators/CollectibleCreators/LegoBundleCreator.php @@ -2,25 +2,68 @@ namespace App\Services\BundleCreator\Creators\CollectibleCreators; +use App\Classes\Bundle; +use App\Exceptions\BundleAlreadyExists; use App\Services\BundleCreator\Creators\BaseBundleCreator; +use App\Services\Rebrickable\RebrickableClient; use Illuminate\Filesystem\FilesystemAdapter; +use Illuminate\Support\Str; +use function Laravel\Prompts\select; use function Laravel\Prompts\text; class LegoBundleCreator extends BaseBundleCreator { + private static string $section = 'collections'; + + private static string $brand = 'lego'; + public function __construct(protected ?array $data, protected FilesystemAdapter $disk) { } + /** + * Create a bundle + */ + public function createBundle(): string + { + $rebrickable = app()->make(RebrickableClient::class); + $setData = $rebrickable->getSet($this->data['rebrickable_id']); + $theme = $rebrickable->getTheme($setData['theme_id']); + $themeSlug = Str::slug($theme['name']); + $path = sprintf('%s/%s/%s/%s', static::$section, static::$brand, $themeSlug, $this->data['product_id']); + + $bundle = new Bundle($path, $this->disk); + + if ($bundle->exists()) { + throw new BundleAlreadyExists( + sprintf('A bundle already exists in %s', $path) + ); + } + + $bundle->markdown()->set(''); + $bundle->metadata()->setMany([ + 'title' => $setData['name'], + 'date' => now()->toIso8601String(), + ]); + $bundle->metadata('metadata')->set('details.Identifiant', $this->data['product_id']); + $bundle->metadata('rebrickable')->setMany([ + 'set' => $setData, + ]); + + $bundle->save(); + + return $path; + } + /** * Return a boolean value indicating if the creator can actually make the * bundle using known data. */ public function canCreateBundle(): bool { - return !empty($this->data['productId']); + return !empty($this->data['product_id']) && !empty($this->data['rebrickable_id']); } /** @@ -31,8 +74,15 @@ public function formSpecs(): ?array { $specs = []; - if (empty($this->data['productId'])) { - $specs['productId'] = fn () => text('Product ID', '', '', true); + if (empty($this->data['product_id'])) { + $specs['product_id'] = fn () => text('Product ID', '', '', true); + } else { + if (empty($this->data['rebrickable_id'])) { + $specs['rebrickable_id'] = fn () => select( + 'Rebrickable Set ID', + app()->make(RebrickableClient::class)->searchSet($this->data['product_id']) + ); + } } return $specs; @@ -44,6 +94,6 @@ public function formSpecs(): ?array */ public static function handles(string $section, ?array $data = []): bool { - return $section === 'collections' && !empty($data['brand']) && $data['brand'] === 'lego'; + return $section === static::$section && !empty($data['brand']) && $data['brand'] === static::$brand; } } diff --git a/app/Services/Rebrickable/RebrickableClient.php b/app/Services/Rebrickable/RebrickableClient.php new file mode 100644 index 0000000..6627d6e --- /dev/null +++ b/app/Services/Rebrickable/RebrickableClient.php @@ -0,0 +1,58 @@ +get(sprintf('sets/?search=%s', $setId)); + $options = []; + + foreach ($response['results'] as $result) { + $options[$result['set_num']] = $result['name']; + } + + return $options; + } + + /** + * Get a specific set from its rebrickable ID + */ + public function getSet(string $setId) + { + $response = $this->get(sprintf('sets/%s/', $setId)); + + return $response; + } + + /** + * Get a specific theme from its rebrickable ID + */ + public function getTheme(string $themeId) + { + $response = $this->get(sprintf('themes/%s/', $themeId)); + + return $response; + } + + private function get(string $url) + { + $key = $this->config['key']; + $baseUrl = $this->config['baseUrl']; + + return Http::throw() + ->withHeader('Authorization', sprintf('key %s', $key)) + ->get(sprintf('%s/%s', $baseUrl, $url))->json(); + } +} diff --git a/bootstrap/providers.php b/bootstrap/providers.php index 73bde76..fb8f1af 100644 --- a/bootstrap/providers.php +++ b/bootstrap/providers.php @@ -3,4 +3,5 @@ return [ App\Providers\AppServiceProvider::class, App\Providers\BundleCreatorServiceProvider::class, + App\Providers\RebrickableServiceProvider::class, ]; diff --git a/config/services.php b/config/services.php index 0a245e1..c0037e8 100644 --- a/config/services.php +++ b/config/services.php @@ -14,6 +14,11 @@ | */ + 'rebrickable' => [ + 'baseUrl' => 'https://rebrickable.com/api/v3/lego', + 'key' => env('REBRICKABLE_API_KEY'), + ], + 'postmark' => [ 'token' => env('POSTMARK_TOKEN'), ],