Merge pull request #343 from shikorism/feature/integrate-metadata-resolve
メタデータの解決と保存の処理を統一
This commit is contained in:
		| @@ -2,55 +2,18 @@ | |||||||
|  |  | ||||||
| namespace App\Http\Controllers\Api; | namespace App\Http\Controllers\Api; | ||||||
|  |  | ||||||
| use App\Metadata; | use App\Services\MetadataResolveService; | ||||||
| use App\MetadataResolver\MetadataResolver; |  | ||||||
| use App\Tag; |  | ||||||
| use App\Utilities\Formatter; |  | ||||||
| use Illuminate\Http\Request; | use Illuminate\Http\Request; | ||||||
|  |  | ||||||
| class CardController | class CardController | ||||||
| { | { | ||||||
|     /** |     public function show(Request $request, MetadataResolveService $service) | ||||||
|      * @var MetadataResolver |  | ||||||
|      */ |  | ||||||
|     private $resolver; |  | ||||||
|     /** |  | ||||||
|      * @var Formatter |  | ||||||
|      */ |  | ||||||
|     private $formatter; |  | ||||||
|  |  | ||||||
|     public function __construct(MetadataResolver $resolver, Formatter $formatter) |  | ||||||
|     { |  | ||||||
|         $this->resolver = $resolver; |  | ||||||
|         $this->formatter = $formatter; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     public function show(Request $request) |  | ||||||
|     { |     { | ||||||
|         $request->validate([ |         $request->validate([ | ||||||
|             'url:required|url' |             'url:required|url' | ||||||
|         ]); |         ]); | ||||||
|  |  | ||||||
|         $url = $this->formatter->normalizeUrl($request->input('url')); |         $metadata = $service->execute($request->input('url')); | ||||||
|  |  | ||||||
|         $metadata = Metadata::find($url); |  | ||||||
|         if ($metadata === null || ($metadata->expires_at !== null && $metadata->expires_at < now())) { |  | ||||||
|             $resolved = $this->resolver->resolve($url); |  | ||||||
|             $metadata = Metadata::updateOrCreate(['url' => $url], [ |  | ||||||
|                 'title' => $resolved->title, |  | ||||||
|                 'description' => $resolved->description, |  | ||||||
|                 'image' => $resolved->image, |  | ||||||
|                 'expires_at' => $resolved->expires_at |  | ||||||
|             ]); |  | ||||||
|  |  | ||||||
|             $tagIds = []; |  | ||||||
|             foreach ($resolved->normalizedTags() as $tagName) { |  | ||||||
|                 $tag = Tag::firstOrCreate(['name' => $tagName]); |  | ||||||
|                 $tagIds[] = $tag->id; |  | ||||||
|             } |  | ||||||
|             $metadata->tags()->sync($tagIds); |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         $metadata->load('tags'); |         $metadata->load('tags'); | ||||||
|  |  | ||||||
|         $response = response($metadata); |         $response = response($metadata); | ||||||
|   | |||||||
| @@ -3,32 +3,23 @@ | |||||||
| namespace App\Listeners; | namespace App\Listeners; | ||||||
|  |  | ||||||
| use App\Events\LinkDiscovered; | use App\Events\LinkDiscovered; | ||||||
| use App\Metadata; | use App\Services\MetadataResolveService; | ||||||
| use App\MetadataResolver\MetadataResolver; |  | ||||||
| use App\Tag; |  | ||||||
| use App\Utilities\Formatter; |  | ||||||
| use GuzzleHttp\Exception\TransferException; |  | ||||||
| use Illuminate\Contracts\Queue\ShouldQueue; | use Illuminate\Contracts\Queue\ShouldQueue; | ||||||
| use Illuminate\Queue\InteractsWithQueue; | use Illuminate\Queue\InteractsWithQueue; | ||||||
| use Illuminate\Support\Facades\Log; |  | ||||||
|  |  | ||||||
| class LinkCollector | class LinkCollector | ||||||
| { | { | ||||||
|     /** @var Formatter */ |     /** @var MetadataResolveService */ | ||||||
|     private $formatter; |     private $metadataResolveService; | ||||||
|     /** @var MetadataResolver */ |  | ||||||
|     private $metadataResolver; |  | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * Create the event listener. |      * Create the event listener. | ||||||
|      * |      * | ||||||
|      * @param Formatter $formatter |      * @param MetadataResolveService $metadataResolveService | ||||||
|      * @param MetadataResolver $metadataResolver |  | ||||||
|      */ |      */ | ||||||
|     public function __construct(Formatter $formatter, MetadataResolver $metadataResolver) |     public function __construct(MetadataResolveService $metadataResolveService) | ||||||
|     { |     { | ||||||
|         $this->formatter = $formatter; |         $this->metadataResolveService = $metadataResolveService; | ||||||
|         $this->metadataResolver = $metadataResolver; |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
| @@ -39,33 +30,11 @@ class LinkCollector | |||||||
|      */ |      */ | ||||||
|     public function handle(LinkDiscovered $event) |     public function handle(LinkDiscovered $event) | ||||||
|     { |     { | ||||||
|         // URLの正規化 |         try { | ||||||
|         $url = $this->formatter->normalizeUrl($event->url); |             $this->metadataResolveService->execute($event->url); | ||||||
|  |         } catch (\Exception $e) { | ||||||
|         // 無かったら取得 |             // 今のところこのイベントは同期実行されるので、上流をクラッシュさせないために雑catchする | ||||||
|         // TODO: ある程度古かったら再取得とかありだと思う |             report($e); | ||||||
|         $metadata = Metadata::find($url); |  | ||||||
|         if ($metadata == null || ($metadata->expires_at !== null && $metadata->expires_at < now())) { |  | ||||||
|             try { |  | ||||||
|                 $resolved = $this->metadataResolver->resolve($url); |  | ||||||
|                 $metadata = Metadata::updateOrCreate(['url' => $url], [ |  | ||||||
|                     'title' => $resolved->title, |  | ||||||
|                     'description' => $resolved->description, |  | ||||||
|                     'image' => $resolved->image, |  | ||||||
|                     'expires_at' => $resolved->expires_at |  | ||||||
|                 ]); |  | ||||||
|  |  | ||||||
|                 $tagIds = []; |  | ||||||
|                 foreach ($resolved->normalizedTags() as $tagName) { |  | ||||||
|                     $tag = Tag::firstOrCreate(['name' => $tagName]); |  | ||||||
|                     $tagIds[] = $tag->id; |  | ||||||
|                 } |  | ||||||
|                 $metadata->tags()->sync($tagIds); |  | ||||||
|             } catch (TransferException $e) { |  | ||||||
|                 // 何らかの通信エラーによってメタデータの取得に失敗した時、とりあえずエラーログにURLを残す |  | ||||||
|                 Log::error(self::class . ': メタデータの取得に失敗 URL=' . $url); |  | ||||||
|                 report($e); |  | ||||||
|             } |  | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										58
									
								
								app/Services/MetadataResolveService.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								app/Services/MetadataResolveService.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,58 @@ | |||||||
|  | <?php | ||||||
|  |  | ||||||
|  | namespace App\Services; | ||||||
|  |  | ||||||
|  | use App\Metadata; | ||||||
|  | use App\MetadataResolver\MetadataResolver; | ||||||
|  | use App\Tag; | ||||||
|  | use App\Utilities\Formatter; | ||||||
|  | use GuzzleHttp\Exception\TransferException; | ||||||
|  | use Illuminate\Support\Facades\Log; | ||||||
|  |  | ||||||
|  | class MetadataResolveService | ||||||
|  | { | ||||||
|  |     /** @var MetadataResolver */ | ||||||
|  |     private $resolver; | ||||||
|  |     /** @var Formatter */ | ||||||
|  |     private $formatter; | ||||||
|  |  | ||||||
|  |     public function __construct(MetadataResolver $resolver, Formatter $formatter) | ||||||
|  |     { | ||||||
|  |         $this->resolver = $resolver; | ||||||
|  |         $this->formatter = $formatter; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public function execute(string $url): Metadata | ||||||
|  |     { | ||||||
|  |         // URLの正規化 | ||||||
|  |         $url = $this->formatter->normalizeUrl($url); | ||||||
|  |  | ||||||
|  |         // 無かったら取得 | ||||||
|  |         // TODO: ある程度古かったら再取得とかありだと思う | ||||||
|  |         $metadata = Metadata::find($url); | ||||||
|  |         if ($metadata == null || ($metadata->expires_at !== null && $metadata->expires_at < now())) { | ||||||
|  |             try { | ||||||
|  |                 $resolved = $this->resolver->resolve($url); | ||||||
|  |                 $metadata = Metadata::updateOrCreate(['url' => $url], [ | ||||||
|  |                     'title' => $resolved->title, | ||||||
|  |                     'description' => $resolved->description, | ||||||
|  |                     'image' => $resolved->image, | ||||||
|  |                     'expires_at' => $resolved->expires_at | ||||||
|  |                 ]); | ||||||
|  |  | ||||||
|  |                 $tagIds = []; | ||||||
|  |                 foreach ($resolved->normalizedTags() as $tagName) { | ||||||
|  |                     $tag = Tag::firstOrCreate(['name' => $tagName]); | ||||||
|  |                     $tagIds[] = $tag->id; | ||||||
|  |                 } | ||||||
|  |                 $metadata->tags()->sync($tagIds); | ||||||
|  |             } catch (TransferException $e) { | ||||||
|  |                 // 何らかの通信エラーによってメタデータの取得に失敗した時、とりあえずエラーログにURLを残す | ||||||
|  |                 Log::error(self::class . ': メタデータの取得に失敗 URL=' . $url); | ||||||
|  |                 throw $e; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         return $metadata; | ||||||
|  |     } | ||||||
|  | } | ||||||
		Reference in New Issue
	
	Block a user
	 shibafu
					shibafu