diff --git a/app/Events/LinkDiscovered.php b/app/Events/LinkDiscovered.php new file mode 100644 index 0000000..0163dc6 --- /dev/null +++ b/app/Events/LinkDiscovered.php @@ -0,0 +1,24 @@ +url = $url; + } +} diff --git a/app/Http/Controllers/EjaculationController.php b/app/Http/Controllers/EjaculationController.php index 1509443..43b3d13 100644 --- a/app/Http/Controllers/EjaculationController.php +++ b/app/Http/Controllers/EjaculationController.php @@ -2,6 +2,7 @@ namespace App\Http\Controllers; +use App\Events\LinkDiscovered; use App\Tag; use App\User; use Carbon\Carbon; @@ -71,6 +72,10 @@ class EjaculationController extends Controller } $ejaculation->tags()->sync($tagIds); + if (!empty($ejaculation->link)) { + event(new LinkDiscovered($ejaculation->link)); + } + return redirect()->route('checkin.show', ['id' => $ejaculation->id])->with('status', 'チェックインしました!'); } @@ -148,6 +153,10 @@ class EjaculationController extends Controller } $ejaculation->tags()->sync($tagIds); + if (!empty($ejaculation->link)) { + event(new LinkDiscovered($ejaculation->link)); + } + return redirect()->route('checkin.show', ['id' => $ejaculation->id])->with('status', 'チェックインを修正しました!'); } diff --git a/app/Listeners/LinkCollector.php b/app/Listeners/LinkCollector.php new file mode 100644 index 0000000..6bd41ad --- /dev/null +++ b/app/Listeners/LinkCollector.php @@ -0,0 +1,54 @@ +formatter = $formatter; + $this->metadataResolver = $metadataResolver; + } + + /** + * Handle the event. + * + * @param LinkDiscovered $event + * @return void + */ + public function handle(LinkDiscovered $event) + { + // URLの正規化 + $url = $this->formatter->normalizeUrl($event->url); + + // 無かったら取得 + // TODO: ある程度古かったら再取得とかありだと思う + $metadata = Metadata::find($url); + if ($metadata == null) { + $resolved = $this->metadataResolver->resolve($url); + Metadata::create([ + 'url' => $url, + 'title' => $resolved->title, + 'description' => $resolved->description, + 'image' => $resolved->image + ]); + } + } +} diff --git a/app/Metadata.php b/app/Metadata.php new file mode 100644 index 0000000..98badb6 --- /dev/null +++ b/app/Metadata.php @@ -0,0 +1,15 @@ + [ - 'App\Listeners\EventListener', - ], + 'App\Events\LinkDiscovered' => [ + 'App\Listeners\LinkCollector' + ] ]; /** diff --git a/app/Utilities/Formatter.php b/app/Utilities/Formatter.php index fd7da98..c19e6f2 100644 --- a/app/Utilities/Formatter.php +++ b/app/Utilities/Formatter.php @@ -36,4 +36,29 @@ class Formatter { return $this->linkify->processUrls($text); } + + /** + * URLを正規化します。 + * @param string $url URL + * @return string 正規化されたURL + */ + public function normalizeUrl($url) + { + // Decode + $url = urldecode($url); + + // Remove Hashbang + $url = preg_replace('~/#!/~u', '/', $url); + + // Sort query parameters + $query = parse_url($url, PHP_URL_QUERY); + if (!empty($query)) { + $url = str_replace_last('?' . $query, '', $url); + parse_str($query, $params); + ksort($params); + $url = $url . '?' . http_build_query($params); + } + + return $url; + } } \ No newline at end of file diff --git a/database/migrations/2018_06_07_225520_create_metadata_table.php b/database/migrations/2018_06_07_225520_create_metadata_table.php new file mode 100644 index 0000000..3cb78f6 --- /dev/null +++ b/database/migrations/2018_06_07_225520_create_metadata_table.php @@ -0,0 +1,36 @@ +string('url'); + $table->string('title'); + $table->string('description'); + $table->string('image'); + $table->timestamps(); + + $table->index('url'); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('metadata'); + } +} diff --git a/routes/api.php b/routes/api.php index 083a21b..4ef841a 100644 --- a/routes/api.php +++ b/routes/api.php @@ -1,6 +1,7 @@ get('/user', function (Request $request) { return $request->user(); }); -Route::get('/checkin/card', function (Request $request, MetadataResolver $resolver) { +Route::get('/checkin/card', function (Request $request, MetadataResolver $resolver, Formatter $formatter) { $request->validate([ 'url:required|url' ]); - $url = $request->input('url'); + $url = $formatter->normalizeUrl($request->input('url')); + + $metadata = App\Metadata::find($url); + if ($metadata == null) { + $resolved = $resolver->resolve($url); + $metadata = App\Metadata::create([ + 'url' => $url, + 'title' => $resolved->title, + 'description' => $resolved->description, + 'image' => $resolved->image + ]); + } - $metadata = $resolver->resolve($url); $response = response()->json($metadata); if (!config('app.debug')) { $response = $response->setCache(['public' => true, 'max_age' => 86400]);