fixed bugs introduced by the new system

This commit is contained in:
pushrbx 2023-02-11 16:32:16 +00:00
parent 9c9e592711
commit d171f29bc9
73 changed files with 339 additions and 181 deletions

View File

@ -25,7 +25,12 @@ class Anime extends JikanApiSearchableModel
* @var array * @var array
*/ */
protected $fillable = [ protected $fillable = [
'mal_id','url','title','title_english','title_japanese','title_synonyms', 'titles', 'images', 'type','source','episodes','status','airing','aired','duration','rating','score','scored_by','rank','popularity','members','favorites','synopsis','background','premiered','broadcast','related','producers','licensors','studios','genres', 'explicit_genres', 'themes', 'demographics', 'opening_themes','ending_themes' 'mal_id', 'url', 'title', 'title_english', 'title_japanese', 'title_synonyms',
'titles', 'images', 'type', 'source', 'episodes', 'status', 'airing', 'aired',
'duration', 'rating', 'score', 'scored_by', 'rank', 'popularity', 'members',
'favorites', 'synopsis', 'background', 'premiered', 'broadcast', 'related',
'producers', 'licensors', 'studios', 'genres', 'explicit_genres', 'themes',
'demographics', 'opening_themes', 'ending_themes', 'trailer', 'approved', 'createdAt', 'modifiedAt'
]; ];
/** /**
@ -59,12 +64,13 @@ class Anime extends JikanApiSearchableModel
public function setSeasonAttribute($value) public function setSeasonAttribute($value)
{ {
$this->attributes['season'] = $this->getSeasonAttribute(); // noop
// this attribute is calculated
} }
public function getSeasonAttribute() public function getSeasonAttribute()
{ {
$premiered = $this->attributes['premiered']; $premiered = array_key_exists('premiered', $this->attributes) ? $this->attributes['premiered'] : null;
if (empty($premiered) if (empty($premiered)
|| is_null($premiered) || is_null($premiered)
@ -79,12 +85,13 @@ class Anime extends JikanApiSearchableModel
public function setYearAttribute($value) public function setYearAttribute($value)
{ {
$this->attributes['year'] = $this->getYearAttribute(); // noop
// this attribute is calculated
} }
public function getYearAttribute() public function getYearAttribute()
{ {
$premiered = $this->attributes['premiered']; $premiered = array_key_exists('premiered', $this->attributes) ? $this->attributes['premiered'] : null;
if (empty($premiered) if (empty($premiered)
|| is_null($premiered) || is_null($premiered)
@ -93,36 +100,18 @@ class Anime extends JikanApiSearchableModel
return null; return null;
} }
return (int) explode(' ', $premiered)[1]; return (int)explode(' ', $premiered)[1];
} }
public function setBroadcastAttribute($value) public function setBroadcastAttribute($value)
{ {
$this->attributes['year'] = $this->getBroadcastAttribute(); $this->attributes['broadcast'] = $this->adaptBroadcastValue($value);
} }
public function getBroadcastAttribute() public function getBroadcastAttribute()
{ {
if (array_key_exists("broadcast", $this->attributes)) { if (array_key_exists("broadcast", $this->attributes)) {
$broadcastStr = $this->attributes['broadcast']; return $this->adaptBroadcastValue($this->attributes['broadcast']);
if (!preg_match('~(.*) at (.*) \(~', $broadcastStr, $matches)) {
return [
'day' => null,
'time' => null,
'timezone' => null,
'string' => $broadcastStr
];
}
if (preg_match('~(.*) at (.*) \(~', $broadcastStr, $matches)) {
return [
'day' => $matches[1],
'time' => $matches[2],
'timezone' => 'Asia/Tokyo',
'string' => $broadcastStr
];
}
} }
return [ return [
@ -220,8 +209,8 @@ class Anime extends JikanApiSearchableModel
public function toSearchableArray(): array public function toSearchableArray(): array
{ {
return [ return [
'id' => (string) $this->mal_id, 'id' => (string)$this->mal_id,
'mal_id' => (int) $this->mal_id, 'mal_id' => (int)$this->mal_id,
'start_date' => $this->convertToTimestamp($this->aired['from']), 'start_date' => $this->convertToTimestamp($this->aired['from']),
'end_date' => $this->convertToTimestamp($this->aired['to']), 'end_date' => $this->convertToTimestamp($this->aired['to']),
'title' => $this->title, 'title' => $this->title,
@ -293,6 +282,38 @@ class Anime extends JikanApiSearchableModel
]; ];
} }
private function adaptBroadcastValue(array|string $broadcast): array
{
if (is_array($broadcast)) {
return $broadcast;
}
if (!preg_match('~(.*) at (.*) \(~', $broadcast, $matches)) {
return [
'day' => null,
'time' => null,
'timezone' => null,
'string' => $broadcast
];
}
if (preg_match('~(.*) at (.*) \(~', $broadcast, $matches)) {
return [
'day' => $matches[1],
'time' => $matches[2],
'timezone' => 'Asia/Tokyo',
'string' => $broadcast
];
}
return [
'day' => null,
'time' => null,
'timezone' => null,
'string' => null
];
}
protected static function newFactory() protected static function newFactory()
{ {
return App::make(AnimeFactory::class); return App::make(AnimeFactory::class);

View File

@ -19,7 +19,9 @@ class Character extends JikanApiSearchableModel
* @var array * @var array
*/ */
protected $fillable = [ protected $fillable = [
'mal_id', 'url', 'name', 'name_kanji', 'nicknames', 'about', 'member_favorites', 'images', 'animeography', 'mangaography', 'voice_actors' 'mal_id', 'url', 'name', 'name_kanji', 'nicknames', 'about', 'member_favorites',
'images', 'animeography', 'mangaography', 'voice_actors',
'createdAt', 'modifiedAt'
]; ];
/** /**
@ -42,7 +44,7 @@ class Character extends JikanApiSearchableModel
* @var array * @var array
*/ */
protected $hidden = [ protected $hidden = [
'_id', 'trailer_url', 'premiered', 'opening_themes', 'ending_themes', 'images', 'member_favorites' '_id', 'trailer_url', 'premiered', 'opening_themes', 'ending_themes', 'member_favorites'
]; ];
public function __construct(array $attributes = []) public function __construct(array $attributes = [])
@ -57,6 +59,12 @@ class Character extends JikanApiSearchableModel
return $this->attributes['member_favorites']; return $this->attributes['member_favorites'];
} }
/** @noinspection PhpUnused */
public function getImagesAttribute()
{
return $this->attributes['images'];
}
public static function scrape(int $id) public static function scrape(int $id)
{ {
$data = app('JikanParser')->getCharacter(new CharacterRequest($id)); $data = app('JikanParser')->getCharacter(new CharacterRequest($id));

View File

@ -43,7 +43,7 @@ class Club extends JikanApiSearchableModel
* @var array * @var array
*/ */
protected $hidden = [ protected $hidden = [
'_id', 'request_hash', 'expiresAt', 'images' '_id', 'request_hash', 'expiresAt'
]; ];
public function __construct(array $attributes = []) public function __construct(array $attributes = [])
@ -64,6 +64,12 @@ class Club extends JikanApiSearchableModel
return $query->where("access", $value->label); return $query->where("access", $value->label);
} }
/** @noinspection PhpUnused */
public function getImagesAttribute()
{
return $this->attributes['images'];
}
public static function scrape(int $id) public static function scrape(int $id)
{ {
$data = app('JikanParser')->getClub(new ClubRequest($id)); $data = app('JikanParser')->getClub(new ClubRequest($id));

View File

@ -16,7 +16,8 @@ class Episode extends Model
* @var array * @var array
*/ */
protected $fillable = [ protected $fillable = [
'mal_id', 'title', 'title_japanese', 'title_romanji', 'aired', 'filler', 'recap', 'video_url', 'forum_url', 'synopsis' 'mal_id', 'title', 'title_japanese', 'title_romanji', 'aired', 'filler', 'recap', 'video_url', 'forum_url', 'synopsis',
'createdAt', 'modifiedAt'
]; ];
/** /**

View File

@ -16,9 +16,9 @@ use Jikan\Request\Anime\AnimeCharactersAndStaffRequest;
*/ */
final class AnimeCharactersLookupHandler extends RequestHandlerWithScraperCache final class AnimeCharactersLookupHandler extends RequestHandlerWithScraperCache
{ {
protected function resource(Collection $results): JsonResource protected function resource(CachedData $results): JsonResource
{ {
return new AnimeCharactersResource($results->first()); return new AnimeCharactersResource($results);
} }
/** /**

View File

@ -16,10 +16,10 @@ use Jikan\Request\Anime\AnimeEpisodeRequest;
*/ */
final class AnimeEpisodeLookupHandler extends RequestHandlerWithScraperCache final class AnimeEpisodeLookupHandler extends RequestHandlerWithScraperCache
{ {
protected function resource(Collection $results): JsonResource protected function resource(CachedData $results): JsonResource
{ {
return new AnimeEpisodeResource( return new AnimeEpisodeResource(
$results->first() $results
); );
} }

View File

@ -4,6 +4,7 @@ namespace App\Features;
use App\Dto\AnimeExternalLookupCommand; use App\Dto\AnimeExternalLookupCommand;
use App\Http\Resources\V4\ExternalLinksResource; use App\Http\Resources\V4\ExternalLinksResource;
use App\Support\CachedData;
use Illuminate\Http\JsonResponse; use Illuminate\Http\JsonResponse;
use Illuminate\Http\Resources\Json\JsonResource; use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
@ -13,10 +14,10 @@ use Illuminate\Support\Collection;
*/ */
final class AnimeExternalLookupHandler extends ItemLookupHandler final class AnimeExternalLookupHandler extends ItemLookupHandler
{ {
protected function resource(Collection $results): JsonResource protected function resource(CachedData $results): JsonResource
{ {
return new ExternalLinksResource( return new ExternalLinksResource(
$results->first() $results
); );
} }

View File

@ -17,10 +17,10 @@ use Jikan\Request\Anime\AnimeForumRequest;
*/ */
final class AnimeForumLookupHandler extends RequestHandlerWithScraperCache final class AnimeForumLookupHandler extends RequestHandlerWithScraperCache
{ {
protected function resource(Collection $results): JsonResource protected function resource(CachedData $results): JsonResource
{ {
return new ForumResource( return new ForumResource(
$results->first() $results
); );
} }

View File

@ -4,6 +4,7 @@ namespace App\Features;
use App\Dto\AnimeFullLookupCommand; use App\Dto\AnimeFullLookupCommand;
use App\Http\Resources\V4\AnimeFullResource; use App\Http\Resources\V4\AnimeFullResource;
use App\Support\CachedData;
use Illuminate\Http\JsonResponse; use Illuminate\Http\JsonResponse;
use Illuminate\Http\Resources\Json\JsonResource; use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
@ -19,8 +20,8 @@ final class AnimeFullLookupHandler extends ItemLookupHandler
return AnimeFullLookupCommand::class; return AnimeFullLookupCommand::class;
} }
protected function resource(Collection $results): JsonResource protected function resource(CachedData $results): JsonResource
{ {
return new AnimeFullResource($results->first()); return new AnimeFullResource($results);
} }
} }

View File

@ -4,6 +4,7 @@ namespace App\Features;
use App\Dto\AnimeLookupCommand; use App\Dto\AnimeLookupCommand;
use App\Http\Resources\V4\AnimeResource; use App\Http\Resources\V4\AnimeResource;
use App\Support\CachedData;
use Illuminate\Http\JsonResponse; use Illuminate\Http\JsonResponse;
use Illuminate\Http\Resources\Json\JsonResource; use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
@ -13,9 +14,9 @@ use Illuminate\Support\Collection;
*/ */
final class AnimeLookupHandler extends ItemLookupHandler final class AnimeLookupHandler extends ItemLookupHandler
{ {
protected function resource(Collection $results): JsonResource protected function resource(CachedData $results): JsonResource
{ {
return new AnimeResource($results->first()); return new AnimeResource($results);
} }
/** /**

View File

@ -16,10 +16,10 @@ use Jikan\Request\Anime\AnimeMoreInfoRequest;
*/ */
final class AnimeMoreInfoLookupHandler extends RequestHandlerWithScraperCache final class AnimeMoreInfoLookupHandler extends RequestHandlerWithScraperCache
{ {
protected function resource(Collection $results): JsonResource protected function resource(CachedData $results): JsonResource
{ {
return new MoreInfoResource( return new MoreInfoResource(
$results->first() $results
); );
} }

View File

@ -17,10 +17,10 @@ use Jikan\Request\Anime\AnimePicturesRequest;
*/ */
final class AnimePicturesLookupHandler extends RequestHandlerWithScraperCache final class AnimePicturesLookupHandler extends RequestHandlerWithScraperCache
{ {
protected function resource(Collection $results): JsonResource protected function resource(CachedData $results): JsonResource
{ {
return new PicturesResource( return new PicturesResource(
$results->first() $results
); );
} }

View File

@ -16,10 +16,10 @@ use Jikan\Request\Anime\AnimeRecommendationsRequest;
*/ */
final class AnimeRecommendationsLookupHandler extends RequestHandlerWithScraperCache final class AnimeRecommendationsLookupHandler extends RequestHandlerWithScraperCache
{ {
protected function resource(Collection $results): JsonResource protected function resource(CachedData $results): JsonResource
{ {
return new RecommendationsResource( return new RecommendationsResource(
$results->first() $results
); );
} }

View File

@ -4,6 +4,7 @@ namespace App\Features;
use App\Dto\AnimeRelationsLookupCommand; use App\Dto\AnimeRelationsLookupCommand;
use App\Http\Resources\V4\AnimeRelationsResource; use App\Http\Resources\V4\AnimeRelationsResource;
use App\Support\CachedData;
use Illuminate\Http\JsonResponse; use Illuminate\Http\JsonResponse;
use Illuminate\Http\Resources\Json\JsonResource; use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
@ -13,10 +14,10 @@ use Illuminate\Support\Collection;
*/ */
final class AnimeRelationsLookupHandler extends ItemLookupHandler final class AnimeRelationsLookupHandler extends ItemLookupHandler
{ {
protected function resource(Collection $results): JsonResource protected function resource(CachedData $results): JsonResource
{ {
return new AnimeRelationsResource( return new AnimeRelationsResource(
$results->first() $results
); );
} }

View File

@ -28,9 +28,9 @@ final class AnimeReviewsLookupHandler extends RequestHandlerWithScraperCache
return AnimeReviewsLookupCommand::class; return AnimeReviewsLookupCommand::class;
} }
protected function resource(Collection $results): JsonResource protected function resource(CachedData $results): JsonResource
{ {
return new ReviewsResource($results->first()); return new ReviewsResource($results);
} }
protected function getScraperData(string $requestFingerPrint, Collection $requestParams): CachedData protected function getScraperData(string $requestFingerPrint, Collection $requestParams): CachedData

View File

@ -16,9 +16,9 @@ use Jikan\Request\Anime\AnimeCharactersAndStaffRequest;
*/ */
final class AnimeStaffLookupHandler extends RequestHandlerWithScraperCache final class AnimeStaffLookupHandler extends RequestHandlerWithScraperCache
{ {
protected function resource(Collection $results): JsonResource protected function resource(CachedData $results): JsonResource
{ {
return new AnimeStaffResource($results->first()); return new AnimeStaffResource($results);
} }
/** /**

View File

@ -16,10 +16,10 @@ use Jikan\Request\Anime\AnimeStatsRequest;
*/ */
final class AnimeStatsLookupHandler extends RequestHandlerWithScraperCache final class AnimeStatsLookupHandler extends RequestHandlerWithScraperCache
{ {
protected function resource(Collection $results): JsonResource protected function resource(CachedData $results): JsonResource
{ {
return new AnimeStatisticsResource( return new AnimeStatisticsResource(
$results->first() $results
); );
} }

View File

@ -4,6 +4,7 @@ namespace App\Features;
use App\Dto\AnimeStreamingLookupCommand; use App\Dto\AnimeStreamingLookupCommand;
use App\Http\Resources\V4\StreamingLinksResource; use App\Http\Resources\V4\StreamingLinksResource;
use App\Support\CachedData;
use Illuminate\Http\JsonResponse; use Illuminate\Http\JsonResponse;
use Illuminate\Http\Resources\Json\JsonResource; use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
@ -13,10 +14,10 @@ use Illuminate\Support\Collection;
*/ */
final class AnimeStreamingLookupHandler extends ItemLookupHandler final class AnimeStreamingLookupHandler extends ItemLookupHandler
{ {
protected function resource(Collection $results): JsonResource protected function resource(CachedData $results): JsonResource
{ {
return new StreamingLinksResource( return new StreamingLinksResource(
$results->first() $results
); );
} }

View File

@ -4,6 +4,7 @@ namespace App\Features;
use App\Dto\AnimeThemesLookupCommand; use App\Dto\AnimeThemesLookupCommand;
use App\Http\Resources\V4\AnimeThemesResource; use App\Http\Resources\V4\AnimeThemesResource;
use App\Support\CachedData;
use Illuminate\Http\JsonResponse; use Illuminate\Http\JsonResponse;
use Illuminate\Http\Resources\Json\JsonResource; use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
@ -14,10 +15,10 @@ use Illuminate\Support\Collection;
final class AnimeThemesLookupHandler extends ItemLookupHandler final class AnimeThemesLookupHandler extends ItemLookupHandler
{ {
protected function resource(Collection $results): JsonResource protected function resource(CachedData $results): JsonResource
{ {
return new AnimeThemesResource( return new AnimeThemesResource(
$results->first() $results
); );
} }

View File

@ -17,10 +17,10 @@ use Jikan\Request\Anime\AnimeVideosEpisodesRequest;
*/ */
final class AnimeVideosEpisodesLookupHandler extends RequestHandlerWithScraperCache final class AnimeVideosEpisodesLookupHandler extends RequestHandlerWithScraperCache
{ {
protected function resource(Collection $results): JsonResource protected function resource(CachedData $results): JsonResource
{ {
return new AnimeEpisodesResource( return new AnimeEpisodesResource(
$results->first() $results
); );
} }

View File

@ -16,10 +16,10 @@ use Jikan\Request\Anime\AnimeVideosRequest;
*/ */
final class AnimeVideosLookupHandler extends RequestHandlerWithScraperCache final class AnimeVideosLookupHandler extends RequestHandlerWithScraperCache
{ {
protected function resource(Collection $results): JsonResource protected function resource(CachedData $results): JsonResource
{ {
return new AnimeVideosResource( return new AnimeVideosResource(
$results->first() $results
); );
} }

View File

@ -4,6 +4,7 @@ namespace App\Features;
use App\Dto\CharacterAnimeLookupCommand; use App\Dto\CharacterAnimeLookupCommand;
use App\Http\Resources\V4\CharacterAnimeCollection; use App\Http\Resources\V4\CharacterAnimeCollection;
use App\Support\CachedData;
use Illuminate\Http\JsonResponse; use Illuminate\Http\JsonResponse;
use Illuminate\Http\Resources\Json\JsonResource; use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
@ -13,11 +14,11 @@ use Illuminate\Support\Collection;
*/ */
final class CharacterAnimeLookupHandler extends ItemLookupHandler final class CharacterAnimeLookupHandler extends ItemLookupHandler
{ {
protected function resource(Collection $results): JsonResource protected function resource(CachedData $results): JsonResource
{ {
/** @noinspection PhpUndefinedMethodInspection */ /** @noinspection PhpUndefinedMethodInspection */
return new CharacterAnimeCollection( return new CharacterAnimeCollection(
$results->offsetGetFirst("animeography") $results->get("animeography")
); );
} }

View File

@ -4,6 +4,7 @@ namespace App\Features;
use App\Dto\CharacterFullLookupCommand; use App\Dto\CharacterFullLookupCommand;
use App\Http\Resources\V4\CharacterFullResource; use App\Http\Resources\V4\CharacterFullResource;
use App\Support\CachedData;
use Illuminate\Http\JsonResponse; use Illuminate\Http\JsonResponse;
use Illuminate\Http\Resources\Json\JsonResource; use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
@ -13,9 +14,9 @@ use Illuminate\Support\Collection;
*/ */
final class CharacterFullLookupHandler extends ItemLookupHandler final class CharacterFullLookupHandler extends ItemLookupHandler
{ {
protected function resource(Collection $results): JsonResource protected function resource(CachedData $results): JsonResource
{ {
return new CharacterFullResource($results->first()); return new CharacterFullResource($results);
} }
/** /**

View File

@ -4,6 +4,7 @@ namespace App\Features;
use App\Dto\CharacterLookupCommand; use App\Dto\CharacterLookupCommand;
use App\Http\Resources\V4\CharacterResource; use App\Http\Resources\V4\CharacterResource;
use App\Support\CachedData;
use Illuminate\Http\JsonResponse; use Illuminate\Http\JsonResponse;
use Illuminate\Http\Resources\Json\JsonResource; use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
@ -13,9 +14,9 @@ use Illuminate\Support\Collection;
*/ */
final class CharacterLookupHandler extends ItemLookupHandler final class CharacterLookupHandler extends ItemLookupHandler
{ {
protected function resource(Collection $results): JsonResource protected function resource(CachedData $results): JsonResource
{ {
return new CharacterResource($results->first()); return new CharacterResource($results);
} }
/** /**

View File

@ -4,6 +4,7 @@ namespace App\Features;
use App\Dto\CharacterMangaLookupCommand; use App\Dto\CharacterMangaLookupCommand;
use App\Http\Resources\V4\CharacterMangaCollection; use App\Http\Resources\V4\CharacterMangaCollection;
use App\Support\CachedData;
use Illuminate\Http\JsonResponse; use Illuminate\Http\JsonResponse;
use Illuminate\Http\Resources\Json\JsonResource; use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
@ -13,11 +14,11 @@ use Illuminate\Support\Collection;
*/ */
final class CharacterMangaLookupHandler extends ItemLookupHandler final class CharacterMangaLookupHandler extends ItemLookupHandler
{ {
protected function resource(Collection $results): JsonResource protected function resource(CachedData $results): JsonResource
{ {
/** @noinspection PhpUndefinedMethodInspection */ /** @noinspection PhpUndefinedMethodInspection */
return new CharacterMangaCollection( return new CharacterMangaCollection(
$results->offsetGetFirst("mangaography") $results->get("mangaography")
); );
} }

View File

@ -16,9 +16,9 @@ use Jikan\Request\Character\CharacterPicturesRequest;
*/ */
final class CharacterPicturesLookupHandler extends RequestHandlerWithScraperCache final class CharacterPicturesLookupHandler extends RequestHandlerWithScraperCache
{ {
protected function resource(Collection $results): JsonResource protected function resource(CachedData $results): JsonResource
{ {
return new PicturesResource($results->first()); return new PicturesResource($results);
} }
/** /**

View File

@ -4,6 +4,7 @@ namespace App\Features;
use App\Dto\CharacterVoicesLookupCommand; use App\Dto\CharacterVoicesLookupCommand;
use App\Http\Resources\V4\CharacterSeiyuuCollection; use App\Http\Resources\V4\CharacterSeiyuuCollection;
use App\Support\CachedData;
use Illuminate\Http\JsonResponse; use Illuminate\Http\JsonResponse;
use Illuminate\Http\Resources\Json\JsonResource; use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
@ -13,11 +14,11 @@ use Illuminate\Support\Collection;
*/ */
final class CharacterVoicesLookupHandler extends ItemLookupHandler final class CharacterVoicesLookupHandler extends ItemLookupHandler
{ {
protected function resource(Collection $results): JsonResource protected function resource(CachedData $results): JsonResource
{ {
/** @noinspection PhpUndefinedMethodInspection */ /** @noinspection PhpUndefinedMethodInspection */
return new CharacterSeiyuuCollection( return new CharacterSeiyuuCollection(
$results->offsetGetFirst("voice_actors") $results->get("voice_actors")
); );
} }

View File

@ -4,6 +4,7 @@ namespace App\Features;
use App\Dto\ClubLookupCommand; use App\Dto\ClubLookupCommand;
use App\Http\Resources\V4\ClubResource; use App\Http\Resources\V4\ClubResource;
use App\Support\CachedData;
use Illuminate\Http\JsonResponse; use Illuminate\Http\JsonResponse;
use Illuminate\Http\Resources\Json\JsonResource; use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
@ -13,9 +14,9 @@ use Illuminate\Support\Collection;
*/ */
final class ClubLookupHandler extends ItemLookupHandler final class ClubLookupHandler extends ItemLookupHandler
{ {
protected function resource(Collection $results): JsonResource protected function resource(CachedData $results): JsonResource
{ {
return new ClubResource($results->first()); return new ClubResource($results);
} }
/** /**

View File

@ -4,6 +4,7 @@ namespace App\Features;
use App\Dto\ClubRelationLookupCommand; use App\Dto\ClubRelationLookupCommand;
use App\Http\Resources\V4\ClubRelationsResource; use App\Http\Resources\V4\ClubRelationsResource;
use App\Support\CachedData;
use Illuminate\Http\JsonResponse; use Illuminate\Http\JsonResponse;
use Illuminate\Http\Resources\Json\JsonResource; use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
@ -13,9 +14,9 @@ use Illuminate\Support\Collection;
*/ */
final class ClubRelationsLookupHandler extends ItemLookupHandler final class ClubRelationsLookupHandler extends ItemLookupHandler
{ {
protected function resource(Collection $results): JsonResource protected function resource(CachedData $results): JsonResource
{ {
return new ClubRelationsResource($results->first()); return new ClubRelationsResource($results);
} }
/** /**

View File

@ -3,6 +3,7 @@
namespace App\Features; namespace App\Features;
use App\Dto\ClubStaffLookupCommand; use App\Dto\ClubStaffLookupCommand;
use App\Support\CachedData;
use Illuminate\Http\JsonResponse; use Illuminate\Http\JsonResponse;
use Illuminate\Http\Resources\Json\JsonResource; use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
@ -13,9 +14,9 @@ use App\Http\Resources\V4\ClubStaffResource;
*/ */
final class ClubStaffLookupHandler extends ItemLookupHandler final class ClubStaffLookupHandler extends ItemLookupHandler
{ {
protected function resource(Collection $results): JsonResource protected function resource(CachedData $results): JsonResource
{ {
return new ClubStaffResource($results->first()); return new ClubStaffResource($results);
} }
/** /**

View File

@ -5,6 +5,7 @@ namespace App\Features;
use App\Contracts\CachedScraperService; use App\Contracts\CachedScraperService;
use App\Dto\LookupDataCommand; use App\Dto\LookupDataCommand;
use App\Contracts\RequestHandler; use App\Contracts\RequestHandler;
use App\Support\CachedData;
use Illuminate\Http\Resources\Json\JsonResource; use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Http\Resources\Json\ResourceCollection; use Illuminate\Http\Resources\Json\ResourceCollection;
use Illuminate\Http\Response; use Illuminate\Http\Response;
@ -32,9 +33,9 @@ abstract class ItemLookupHandler implements RequestHandler
$requestFingerprint = $request->getFingerPrint(); $requestFingerprint = $request->getFingerPrint();
$results = $this->scraperService->find($request->id, $requestFingerprint); $results = $this->scraperService->find($request->id, $requestFingerprint);
$resource = $this->resource($results->collect()); $resource = $this->resource($results);
return $resource->response()->addJikanCacheFlags($requestFingerprint, $results); return $resource->response()->addJikanCacheFlags($requestFingerprint, $results);
} }
protected abstract function resource(Collection $results): JsonResource; protected abstract function resource(CachedData $results): JsonResource;
} }

View File

@ -21,9 +21,9 @@ final class MangaCharactersLookupHandler extends RequestHandlerWithScraperCache
return MangaCharactersLookupCommand::class; return MangaCharactersLookupCommand::class;
} }
protected function resource(Collection $results): JsonResource protected function resource(CachedData $results): JsonResource
{ {
return new MangaCharactersResource($results->first()); return new MangaCharactersResource($results);
} }
protected function getScraperData(string $requestFingerPrint, Collection $requestParams): CachedData protected function getScraperData(string $requestFingerPrint, Collection $requestParams): CachedData

View File

@ -4,6 +4,7 @@ namespace App\Features;
use App\Dto\MangaExternalLookupCommand; use App\Dto\MangaExternalLookupCommand;
use App\Http\Resources\V4\ExternalLinksResource; use App\Http\Resources\V4\ExternalLinksResource;
use App\Support\CachedData;
use Illuminate\Http\JsonResponse; use Illuminate\Http\JsonResponse;
use Illuminate\Http\Resources\Json\JsonResource; use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
@ -18,8 +19,8 @@ final class MangaExternalLookupHandler extends ItemLookupHandler
return MangaExternalLookupCommand::class; return MangaExternalLookupCommand::class;
} }
protected function resource(Collection $results): JsonResource protected function resource(CachedData $results): JsonResource
{ {
return new ExternalLinksResource($results->first()); return new ExternalLinksResource($results);
} }
} }

View File

@ -21,9 +21,9 @@ final class MangaForumLookupHandler extends RequestHandlerWithScraperCache
return MangaForumLookupCommand::class; return MangaForumLookupCommand::class;
} }
protected function resource(Collection $results): JsonResource protected function resource(CachedData $results): JsonResource
{ {
return new ForumResource($results->first()); return new ForumResource($results);
} }
protected function getScraperData(string $requestFingerPrint, Collection $requestParams): CachedData protected function getScraperData(string $requestFingerPrint, Collection $requestParams): CachedData

View File

@ -4,6 +4,7 @@ namespace App\Features;
use App\Dto\MangaFullLookupCommand; use App\Dto\MangaFullLookupCommand;
use App\Http\Resources\V4\MangaFullResource; use App\Http\Resources\V4\MangaFullResource;
use App\Support\CachedData;
use Illuminate\Http\JsonResponse; use Illuminate\Http\JsonResponse;
use Illuminate\Http\Resources\Json\JsonResource; use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
@ -18,8 +19,8 @@ final class MangaFullLookupHandler extends ItemLookupHandler
return MangaFullLookupCommand::class; return MangaFullLookupCommand::class;
} }
protected function resource(Collection $results): JsonResource protected function resource(CachedData $results): JsonResource
{ {
return new MangaFullResource($results->first()); return new MangaFullResource($results);
} }
} }

View File

@ -4,6 +4,7 @@ namespace App\Features;
use App\Dto\MangaLookupCommand; use App\Dto\MangaLookupCommand;
use App\Http\Resources\V4\MangaResource; use App\Http\Resources\V4\MangaResource;
use App\Support\CachedData;
use Illuminate\Http\JsonResponse; use Illuminate\Http\JsonResponse;
use Illuminate\Http\Resources\Json\JsonResource; use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
@ -18,8 +19,8 @@ final class MangaLookupHandler extends ItemLookupHandler
return MangaLookupCommand::class; return MangaLookupCommand::class;
} }
protected function resource(Collection $results): JsonResource protected function resource(CachedData $results): JsonResource
{ {
return new MangaResource($results->first()); return new MangaResource($results);
} }
} }

View File

@ -21,9 +21,9 @@ final class MangaMoreInfoLookupHandler extends RequestHandlerWithScraperCache
return MangaMoreInfoLookupCommand::class; return MangaMoreInfoLookupCommand::class;
} }
protected function resource(Collection $results): JsonResource protected function resource(CachedData $results): JsonResource
{ {
return new MoreInfoResource($results->first()); return new MoreInfoResource($results);
} }
protected function getScraperData(string $requestFingerPrint, Collection $requestParams): CachedData protected function getScraperData(string $requestFingerPrint, Collection $requestParams): CachedData

View File

@ -21,9 +21,9 @@ final class MangaPicturesLookupHandler extends RequestHandlerWithScraperCache
return MangaPicturesLookupCommand::class; return MangaPicturesLookupCommand::class;
} }
protected function resource(Collection $results): JsonResource protected function resource(CachedData $results): JsonResource
{ {
return new PicturesResource($results->first()); return new PicturesResource($results);
} }
protected function getScraperData(string $requestFingerPrint, Collection $requestParams): CachedData protected function getScraperData(string $requestFingerPrint, Collection $requestParams): CachedData

View File

@ -21,9 +21,9 @@ final class MangaRecommendationsLookupHandler extends RequestHandlerWithScraperC
return MangaRecommendationsLookupCommand::class; return MangaRecommendationsLookupCommand::class;
} }
protected function resource(Collection $results): JsonResource protected function resource(CachedData $results): JsonResource
{ {
return new RecommendationsResource($results->first()); return new RecommendationsResource($results);
} }
protected function getScraperData(string $requestFingerPrint, Collection $requestParams): CachedData protected function getScraperData(string $requestFingerPrint, Collection $requestParams): CachedData

View File

@ -4,6 +4,7 @@ namespace App\Features;
use App\Dto\MangaRelationsLookupCommand; use App\Dto\MangaRelationsLookupCommand;
use App\Http\Resources\V4\MangaRelationsResource; use App\Http\Resources\V4\MangaRelationsResource;
use App\Support\CachedData;
use Illuminate\Http\JsonResponse; use Illuminate\Http\JsonResponse;
use Illuminate\Http\Resources\Json\JsonResource; use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
@ -18,8 +19,8 @@ final class MangaRelationsLookupHandler extends ItemLookupHandler
return MangaRelationsLookupCommand::class; return MangaRelationsLookupCommand::class;
} }
protected function resource(Collection $results): JsonResource protected function resource(CachedData $results): JsonResource
{ {
return new MangaRelationsResource($results->first()); return new MangaRelationsResource($results);
} }
} }

View File

@ -24,9 +24,9 @@ final class MangaReviewsLookupHandler extends RequestHandlerWithScraperCache
return MangaReviewsLookupCommand::class; return MangaReviewsLookupCommand::class;
} }
protected function resource(Collection $results): JsonResource protected function resource(CachedData $results): JsonResource
{ {
return new ReviewsResource($results->first()); return new ReviewsResource($results);
} }
protected function getScraperData(string $requestFingerPrint, Collection $requestParams): CachedData protected function getScraperData(string $requestFingerPrint, Collection $requestParams): CachedData

View File

@ -21,9 +21,9 @@ final class MangaStatsLookupHandler extends RequestHandlerWithScraperCache
return MangaStatsLookupCommand::class; return MangaStatsLookupCommand::class;
} }
protected function resource(Collection $results): JsonResource protected function resource(CachedData $results): JsonResource
{ {
return new MangaStatisticsResource($results->first()); return new MangaStatisticsResource($results);
} }
protected function getScraperData(string $requestFingerPrint, Collection $requestParams): CachedData protected function getScraperData(string $requestFingerPrint, Collection $requestParams): CachedData

View File

@ -4,6 +4,7 @@ namespace App\Features;
use App\Dto\PersonAnimeLookupCommand; use App\Dto\PersonAnimeLookupCommand;
use App\Http\Resources\V4\PersonAnimeCollection; use App\Http\Resources\V4\PersonAnimeCollection;
use App\Support\CachedData;
use Illuminate\Http\JsonResponse; use Illuminate\Http\JsonResponse;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
@ -17,8 +18,8 @@ final class PersonAnimeLookupHandler extends ItemLookupHandler
return PersonAnimeLookupCommand::class; return PersonAnimeLookupCommand::class;
} }
protected function resource(Collection $results): PersonAnimeCollection protected function resource(CachedData $results): PersonAnimeCollection
{ {
return new PersonAnimeCollection($results->offsetGetFirst("anime_staff_positions")); return new PersonAnimeCollection($results->get("anime_staff_positions"));
} }
} }

View File

@ -4,6 +4,7 @@ namespace App\Features;
use App\Dto\PersonFullLookupCommand; use App\Dto\PersonFullLookupCommand;
use App\Http\Resources\V4\PersonFullResource; use App\Http\Resources\V4\PersonFullResource;
use App\Support\CachedData;
use Illuminate\Http\JsonResponse; use Illuminate\Http\JsonResponse;
use Illuminate\Http\Resources\Json\JsonResource; use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
@ -18,8 +19,8 @@ final class PersonFullLookupHandler extends ItemLookupHandler
return PersonFullLookupCommand::class; return PersonFullLookupCommand::class;
} }
protected function resource(Collection $results): JsonResource protected function resource(CachedData $results): JsonResource
{ {
return new PersonFullResource($results->first()); return new PersonFullResource($results);
} }
} }

View File

@ -4,6 +4,7 @@ namespace App\Features;
use App\Dto\PersonLookupCommand; use App\Dto\PersonLookupCommand;
use App\Http\Resources\V4\PersonResource; use App\Http\Resources\V4\PersonResource;
use App\Support\CachedData;
use Illuminate\Http\JsonResponse; use Illuminate\Http\JsonResponse;
use Illuminate\Http\Resources\Json\JsonResource; use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
@ -18,8 +19,8 @@ final class PersonLookupHandler extends ItemLookupHandler
return PersonLookupCommand::class; return PersonLookupCommand::class;
} }
protected function resource(Collection $results): JsonResource protected function resource(CachedData $results): JsonResource
{ {
return new PersonResource($results->first()); return new PersonResource($results);
} }
} }

View File

@ -4,6 +4,7 @@ namespace App\Features;
use App\Dto\PersonMangaLookupCommand; use App\Dto\PersonMangaLookupCommand;
use App\Http\Resources\V4\PersonMangaCollection; use App\Http\Resources\V4\PersonMangaCollection;
use App\Support\CachedData;
use Illuminate\Http\JsonResponse; use Illuminate\Http\JsonResponse;
use Illuminate\Http\Resources\Json\JsonResource; use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
@ -18,8 +19,8 @@ final class PersonMangaLookupHandler extends ItemLookupHandler
return PersonMangaLookupCommand::class; return PersonMangaLookupCommand::class;
} }
protected function resource(Collection $results): JsonResource protected function resource(CachedData $results): JsonResource
{ {
return new PersonMangaCollection($results->offsetGetFirst("published_manga")); return new PersonMangaCollection($results->get("published_manga"));
} }
} }

View File

@ -21,9 +21,9 @@ final class PersonPicturesLookupHandler extends RequestHandlerWithScraperCache
return PersonPicturesLookupCommand::class; return PersonPicturesLookupCommand::class;
} }
protected function resource(Collection $results): JsonResource protected function resource(CachedData $results): JsonResource
{ {
return new PicturesResource($results->first()); return new PicturesResource($results);
} }
protected function getScraperData(string $requestFingerPrint, Collection $requestParams): CachedData protected function getScraperData(string $requestFingerPrint, Collection $requestParams): CachedData

View File

@ -4,6 +4,7 @@ namespace App\Features;
use App\Dto\PersonVoicesLookupCommand; use App\Dto\PersonVoicesLookupCommand;
use App\Http\Resources\V4\PersonVoicesCollection; use App\Http\Resources\V4\PersonVoicesCollection;
use App\Support\CachedData;
use Illuminate\Http\JsonResponse; use Illuminate\Http\JsonResponse;
use Illuminate\Http\Resources\Json\JsonResource; use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
@ -18,8 +19,8 @@ final class PersonVoicesLookupHandler extends ItemLookupHandler
return PersonVoicesLookupCommand::class; return PersonVoicesLookupCommand::class;
} }
protected function resource(Collection $results): JsonResource protected function resource(CachedData $results): JsonResource
{ {
return new PersonVoicesCollection($results->offsetGetFirst("voice_acting_roles")); return new PersonVoicesCollection($results->get("voice_acting_roles"));
} }
} }

View File

@ -4,6 +4,7 @@ namespace App\Features;
use App\Dto\ProducerExternalLookupCommand; use App\Dto\ProducerExternalLookupCommand;
use App\Http\Resources\V4\ExternalLinksResource; use App\Http\Resources\V4\ExternalLinksResource;
use App\Support\CachedData;
use Illuminate\Http\JsonResponse; use Illuminate\Http\JsonResponse;
use Illuminate\Http\Resources\Json\JsonResource; use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
@ -18,8 +19,8 @@ final class ProducerExternalLookupHandler extends ItemLookupHandler
return ProducerExternalLookupCommand::class; return ProducerExternalLookupCommand::class;
} }
protected function resource(Collection $results): JsonResource protected function resource(CachedData $results): JsonResource
{ {
return new ExternalLinksResource($results->first()); return new ExternalLinksResource($results);
} }
} }

View File

@ -4,6 +4,7 @@ namespace App\Features;
use App\Dto\ProducerFullLookupCommand; use App\Dto\ProducerFullLookupCommand;
use App\Http\Resources\V4\ProducerFullResource; use App\Http\Resources\V4\ProducerFullResource;
use App\Support\CachedData;
use Illuminate\Http\JsonResponse; use Illuminate\Http\JsonResponse;
use Illuminate\Http\Resources\Json\JsonResource; use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
@ -18,8 +19,8 @@ final class ProducerFullLookupHandler extends ItemLookupHandler
return ProducerFullLookupCommand::class; return ProducerFullLookupCommand::class;
} }
protected function resource(Collection $results): JsonResource protected function resource(CachedData $results): JsonResource
{ {
return new ProducerFullResource($results->first()); return new ProducerFullResource($results);
} }
} }

View File

@ -4,6 +4,7 @@ namespace App\Features;
use App\Dto\ProducerLookupCommand; use App\Dto\ProducerLookupCommand;
use App\Http\Resources\V4\ProducerResource; use App\Http\Resources\V4\ProducerResource;
use App\Support\CachedData;
use Illuminate\Http\JsonResponse; use Illuminate\Http\JsonResponse;
use Illuminate\Http\Resources\Json\JsonResource; use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
@ -18,8 +19,8 @@ final class ProducerLookupHandler extends ItemLookupHandler
return ProducerLookupCommand::class; return ProducerLookupCommand::class;
} }
protected function resource(Collection $results): JsonResource protected function resource(CachedData $results): JsonResource
{ {
return new ProducerResource($results->first()); return new ProducerResource($results);
} }
} }

View File

@ -30,7 +30,7 @@ final class QueryAnimeListOfUserHandler extends RequestHandlerWithScraperCache
return $this->renderResponse($requestFingerPrint, $results); return $this->renderResponse($requestFingerPrint, $results);
} }
public function resource(Collection $results): JsonResource public function resource(CachedData $results): JsonResource
{ {
if ($results->isEmpty() || count($results->get("anime")) === 0) { if ($results->isEmpty() || count($results->get("anime")) === 0) {
return new UserProfileAnimeListCollection([]); return new UserProfileAnimeListCollection([]);

View File

@ -30,13 +30,13 @@ final class QueryMangaListOfUserHandler extends RequestHandlerWithScraperCache
return $this->renderResponse($requestFingerPrint, $results); return $this->renderResponse($requestFingerPrint, $results);
} }
public function resource(Collection $results): JsonResource public function resource(CachedData $results): JsonResource
{ {
if ($results->isEmpty()) { if ($results->isEmpty()) {
return new UserProfileAnimeListCollection([]); return new UserProfileAnimeListCollection([]);
} }
$listResults = $results->first()['manga']; $listResults = $results->get("manga");
foreach ($listResults as &$result) { foreach ($listResults as &$result) {
$result = (new UserProfileMangaListResource($result)); $result = (new UserProfileMangaListResource($result));
} }

View File

@ -21,7 +21,7 @@ final class QueryRandomPersonHandler extends QueryRandomItemHandler
protected function resource(Collection $results): JsonResource protected function resource(Collection $results): JsonResource
{ {
return new PersonResource( return new PersonResource(
$results->first() $results
); );
} }

View File

@ -37,10 +37,10 @@ abstract class RequestHandlerWithScraperCache implements RequestHandler
protected abstract function getScraperData(string $requestFingerPrint, Collection $requestParams): CachedData; protected abstract function getScraperData(string $requestFingerPrint, Collection $requestParams): CachedData;
protected function resource(Collection $results): JsonResource protected function resource(CachedData $results): JsonResource
{ {
return new ResultsResource( return new ResultsResource(
$results->first() ?? ["results" => []] $results->isEmpty() ? ["results" => []] : $results->toArray()
); );
} }
@ -51,8 +51,7 @@ abstract class RequestHandlerWithScraperCache implements RequestHandler
*/ */
protected function renderResponse(string $requestFingerPrint, CachedData $results) protected function renderResponse(string $requestFingerPrint, CachedData $results)
{ {
$finalResults = $results->collect(); $response = $this->resource($results)->response();
$response = $this->resource($finalResults)->response();
return $response->addJikanCacheFlags($requestFingerPrint, $results); return $response->addJikanCacheFlags($requestFingerPrint, $results);
} }
} }

View File

@ -4,6 +4,7 @@ namespace App\Features;
use App\Dto\UserAboutLookupCommand; use App\Dto\UserAboutLookupCommand;
use App\Http\Resources\V4\ProfileAboutResource; use App\Http\Resources\V4\ProfileAboutResource;
use App\Support\CachedData;
use Illuminate\Http\Resources\Json\JsonResource; use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
@ -17,8 +18,8 @@ final class UserAboutLookupHandler extends UserLookupHandler
return UserAboutLookupCommand::class; return UserAboutLookupCommand::class;
} }
protected function resource(Collection $results): JsonResource protected function resource(CachedData $results): JsonResource
{ {
return new ProfileAboutResource($results->first()); return new ProfileAboutResource($results);
} }
} }

View File

@ -4,6 +4,7 @@ namespace App\Features;
use App\Dto\UserExternalLookupCommand; use App\Dto\UserExternalLookupCommand;
use App\Http\Resources\V4\ExternalLinksResource; use App\Http\Resources\V4\ExternalLinksResource;
use App\Support\CachedData;
use Illuminate\Http\Resources\Json\JsonResource; use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
@ -17,8 +18,8 @@ final class UserExternalLookupHandler extends UserLookupHandler
return UserExternalLookupCommand::class; return UserExternalLookupCommand::class;
} }
protected function resource(Collection $results): JsonResource protected function resource(CachedData $results): JsonResource
{ {
return new ExternalLinksResource($results->first()); return new ExternalLinksResource($results);
} }
} }

View File

@ -4,6 +4,7 @@ namespace App\Features;
use App\Dto\UserFavoritesLookupCommand; use App\Dto\UserFavoritesLookupCommand;
use App\Http\Resources\V4\ProfileFavoritesResource; use App\Http\Resources\V4\ProfileFavoritesResource;
use App\Support\CachedData;
use Illuminate\Http\Resources\Json\JsonResource; use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
@ -17,8 +18,8 @@ final class UserFavoritesLookupHandler extends UserLookupHandler
return UserFavoritesLookupCommand::class; return UserFavoritesLookupCommand::class;
} }
protected function resource(Collection $results): JsonResource protected function resource(CachedData $results): JsonResource
{ {
return new ProfileFavoritesResource($results->first()); return new ProfileFavoritesResource($results);
} }
} }

View File

@ -4,6 +4,7 @@ namespace App\Features;
use App\Dto\UserFullLookupCommand; use App\Dto\UserFullLookupCommand;
use App\Http\Resources\V4\ProfileFullResource; use App\Http\Resources\V4\ProfileFullResource;
use App\Support\CachedData;
use Illuminate\Http\Resources\Json\JsonResource; use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
@ -17,8 +18,8 @@ final class UserFullLookupHandler extends UserLookupHandler
return UserFullLookupCommand::class; return UserFullLookupCommand::class;
} }
protected function resource(Collection $results): JsonResource protected function resource(CachedData $results): JsonResource
{ {
return new ProfileFullResource($results->first()); return new ProfileFullResource($results);
} }
} }

View File

@ -20,9 +20,9 @@ final class UserHistoryLookupHandler extends RequestHandlerWithScraperCache
return UserHistoryLookupCommand::class; return UserHistoryLookupCommand::class;
} }
protected function resource(Collection $results): JsonResource protected function resource(CachedData $results): JsonResource
{ {
return new ProfileHistoryResource($results->first()); return new ProfileHistoryResource($results);
} }
protected function getScraperData(string $requestFingerPrint, Collection $requestParams): CachedData protected function getScraperData(string $requestFingerPrint, Collection $requestParams): CachedData

View File

@ -4,6 +4,7 @@ namespace App\Features;
use App\Dto\UserProfileLookupCommand; use App\Dto\UserProfileLookupCommand;
use App\Http\Resources\V4\ProfileResource; use App\Http\Resources\V4\ProfileResource;
use App\Support\CachedData;
use Illuminate\Http\Resources\Json\JsonResource; use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
@ -17,8 +18,8 @@ final class UserProfileLookupHandler extends UserLookupHandler
return UserProfileLookupCommand::class; return UserProfileLookupCommand::class;
} }
protected function resource(Collection $results): JsonResource protected function resource(CachedData $results): JsonResource
{ {
return new ProfileResource($results->first()); return new ProfileResource($results);
} }
} }

View File

@ -4,6 +4,7 @@ namespace App\Features;
use App\Dto\UserStatisticsLookupCommand; use App\Dto\UserStatisticsLookupCommand;
use App\Http\Resources\V4\ProfileStatisticsResource; use App\Http\Resources\V4\ProfileStatisticsResource;
use App\Support\CachedData;
use Illuminate\Http\Resources\Json\JsonResource; use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
@ -17,8 +18,8 @@ final class UserStatisticsLookupHandler extends UserLookupHandler
return UserStatisticsLookupCommand::class; return UserStatisticsLookupCommand::class;
} }
protected function resource(Collection $results): JsonResource protected function resource(CachedData $results): JsonResource
{ {
return new ProfileStatisticsResource($results->first()); return new ProfileStatisticsResource($results);
} }
} }

View File

@ -4,6 +4,7 @@ namespace App\Features;
use App\Dto\UserUpdatesLookupCommand; use App\Dto\UserUpdatesLookupCommand;
use App\Http\Resources\V4\ProfileLastUpdatesResource; use App\Http\Resources\V4\ProfileLastUpdatesResource;
use App\Support\CachedData;
use Illuminate\Http\Resources\Json\JsonResource; use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
@ -17,8 +18,8 @@ final class UserUpdatesLookupHandler extends UserLookupHandler
return UserUpdatesLookupCommand::class; return UserUpdatesLookupCommand::class;
} }
protected function resource(Collection $results): JsonResource protected function resource(CachedData $results): JsonResource
{ {
return new ProfileLastUpdatesResource($results->first()); return new ProfileLastUpdatesResource($results);
} }
} }

View File

@ -22,7 +22,8 @@ class GenreAnime extends JikanApiSearchableModel
* @var array * @var array
*/ */
protected $fillable = [ protected $fillable = [
'mal_id', 'name', 'url', 'count' 'mal_id', 'name', 'url', 'count',
'createdAt', 'modifiedAt'
]; ];
/** /**

View File

@ -22,7 +22,8 @@ class GenreManga extends JikanApiSearchableModel
* @var array * @var array
*/ */
protected $fillable = [ protected $fillable = [
'mal_id', 'name', 'url', 'count' 'mal_id', 'name', 'url', 'count',
'createdAt', 'modifiedAt'
]; ];
/** /**

View File

@ -22,7 +22,8 @@ class Magazine extends JikanApiSearchableModel
* @var array * @var array
*/ */
protected $fillable = [ protected $fillable = [
'mal_id', 'name', 'url', 'count' 'mal_id', 'name', 'url', 'count',
'createdAt', 'modifiedAt'
]; ];
/** /**

View File

@ -24,8 +24,11 @@ class Manga extends JikanApiSearchableModel
* @var array * @var array
*/ */
protected $fillable = [ protected $fillable = [
'mal_id', 'url', 'title', 'title_english', 'title_japanese', 'title_synonyms', 'titles', 'images', 'status', 'type', 'volumes', 'chapters', 'publishing', 'published', 'rank', 'score', 'mal_id', 'url', 'title', 'title_english', 'title_japanese', 'title_synonyms', 'titles',
'scored_by', 'popularity', 'members', 'favorites', 'synopsis', 'background', 'related', 'genres', 'explicit_genres', 'themes', 'demographics', 'authors', 'serializations', 'images', 'status', 'type', 'volumes', 'chapters', 'publishing', 'published', 'rank', 'score',
'scored_by', 'popularity', 'members', 'favorites', 'synopsis', 'background', 'related',
'genres', 'explicit_genres', 'themes', 'demographics', 'authors', 'serializations',
'createdAt', 'modifiedAt'
]; ];
/** /**
@ -33,7 +36,7 @@ class Manga extends JikanApiSearchableModel
* *
* @var array * @var array
*/ */
protected $appends = []; protected $appends = ['themes'];
/** /**
* The table associated with the model. * The table associated with the model.
@ -149,9 +152,15 @@ class Manga extends JikanApiSearchableModel
]; ];
} }
public function getThemesAttribute(): array /** @noinspection PhpUnused */
public function getThemesAttribute()
{ {
return []; $result = [];
if (array_key_exists("themes", $this->attributes)) {
$result = $this->attributes["themes"];
}
return $result;
} }
public function typesenseQueryBy(): array public function typesenseQueryBy(): array

View File

@ -19,7 +19,10 @@ class Person extends JikanApiSearchableModel
* @var array * @var array
*/ */
protected $fillable = [ protected $fillable = [
'mal_id', 'url', 'images', 'website_url', 'name', 'given_name', 'family_name', 'alternative_names', 'birthday', 'member_favorites', 'about', 'voice_acting_roles', 'anime_staff_positions', 'published_manga' 'mal_id', 'url', 'images', 'website_url', 'name', 'given_name', 'family_name',
'alternative_names', 'birthday', 'member_favorites', 'about', 'voice_acting_roles',
'anime_staff_positions', 'published_manga',
'createdAt', 'modifiedAt'
]; ];
/** /**
@ -42,7 +45,7 @@ class Person extends JikanApiSearchableModel
* @var array * @var array
*/ */
protected $hidden = [ protected $hidden = [
'_id', 'images', 'member_favorites' '_id', 'member_favorites'
]; ];
public function __construct(array $attributes = []) public function __construct(array $attributes = [])
@ -51,11 +54,17 @@ class Person extends JikanApiSearchableModel
$this->displayNameFieldName = "name"; $this->displayNameFieldName = "name";
} }
/** @noinspection PhpUnused */
public function getFavoritesAttribute() public function getFavoritesAttribute()
{ {
return $this->attributes['member_favorites']; return $this->attributes['member_favorites'];
} }
/** @noinspection PhpUnused */
public function getImagesAttribute()
{
return $this->attributes['images'];
}
public static function scrape(int $id) public static function scrape(int $id)
{ {

View File

@ -17,7 +17,8 @@ class Producers extends JikanApiSearchableModel
* @var array * @var array
*/ */
protected $fillable = [ protected $fillable = [
'mal_id', 'url', 'images', 'titles', 'established', 'favorites', 'about', 'external', 'count' 'mal_id', 'url', 'images', 'titles', 'established', 'favorites', 'about', 'external', 'count',
'createdAt', 'modifiedAt'
]; ];
/** /**

View File

@ -17,7 +17,9 @@ class Profile extends JikanApiSearchableModel
* @var array * @var array
*/ */
protected $fillable = [ protected $fillable = [
'mal_id', 'username', 'url', 'images', 'last_online', 'gender', 'birthday', 'location', 'joined', 'anime_stats', 'manga_stats', 'favorites', 'about' 'mal_id', 'username', 'url', 'images', 'last_online', 'gender', 'birthday', 'location',
'joined', 'anime_stats', 'manga_stats', 'favorites', 'about',
'createdAt', 'modifiedAt'
]; ];
/** /**

View File

@ -83,7 +83,7 @@ final class DefaultCachedScraperService implements CachedScraperService
$results = $this->dbResultSetToCachedData($dbResults); $results = $this->dbResultSetToCachedData($dbResults);
if ($results->isEmpty() || $results->isExpired()) { if ($results->isEmpty() || $results->isExpired()) {
$scraperResponse = $this->repository->scrape($key); $scraperResponse = $this->repository->scrape($val);
$this->raiseNotFoundIfErrors($scraperResponse); $this->raiseNotFoundIfErrors($scraperResponse);
@ -93,8 +93,7 @@ final class DefaultCachedScraperService implements CachedScraperService
if ($results->isEmpty()) { if ($results->isEmpty()) {
$this->repository->insert($response); $this->repository->insert($response);
} }
else if ($results->isExpired()) {
if ($results->isExpired()) {
$this->repository->where($key, $val)->update($response); $this->repository->where($key, $val)->update($response);
} }
@ -156,8 +155,7 @@ final class DefaultCachedScraperService implements CachedScraperService
if ($results->isEmpty()) { if ($results->isEmpty()) {
$this->repository->insert($response); $this->repository->insert($response);
} }
else if ($results->isExpired()) {
if ($results->isExpired()) {
$this->repository->queryByMalId($id)->update($response); $this->repository->queryByMalId($id)->update($response);
} }

View File

@ -2,15 +2,24 @@
namespace App\Support; namespace App\Support;
use App\Concerns\ScraperCacheTtl;
use App\JikanApiModel; use App\JikanApiModel;
use ArrayAccess;
use Illuminate\Support\Carbon; use Illuminate\Support\Carbon;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
use Illuminate\Support\Env; use Illuminate\Support\Traits\ForwardsCalls;
use Illuminate\Support\Traits\Macroable;
use MongoDB\BSON\UTCDateTime; use MongoDB\BSON\UTCDateTime;
final class CachedData /**
* A class to represent cached scraper results. This is just a fancy collection which knows about
* cache ttl and whether the data is expired in the cache or not.
*/
final class CachedData implements ArrayAccess
{ {
use ForwardsCalls, Macroable {
__call as macroCall;
}
private int $cacheTimeToLive; private int $cacheTimeToLive;
private function __construct( private function __construct(
@ -21,6 +30,11 @@ final class CachedData
$this->cacheTimeToLive = $cacheTtl; $this->cacheTimeToLive = $cacheTtl;
} }
/**
* @param Collection $scraperResult Always a collection which has the result from the scraper wrapped under a key
* or a document from the db.
* @return static
*/
public static function from(Collection $scraperResult): self public static function from(Collection $scraperResult): self
{ {
return new self($scraperResult, app(CacheOptions::class)->ttl()); return new self($scraperResult, app(CacheOptions::class)->ttl());
@ -41,16 +55,6 @@ final class CachedData
return $this->scraperResult; return $this->scraperResult;
} }
public function offsetGet(string $key): mixed
{
return $this->scraperResult->offsetGet($key);
}
public function offsetSet(string $key, mixed $value): void
{
$this->scraperResult->offsetSet($key, $value);
}
public function isEmpty(): bool public function isEmpty(): bool
{ {
return $this->scraperResult->isEmpty(); return $this->scraperResult->isEmpty();
@ -98,9 +102,52 @@ final class CachedData
return $this->mixedToTimestamp($modifiedAt); return $this->mixedToTimestamp($modifiedAt);
} }
if (null !== $modifiedAt = $result->get("updated_at")) {
return $this->mixedToTimestamp($modifiedAt);
}
return null; return null;
} }
/**
* Dynamically get elements by key from the underlying scraper result collection.
* Additionally, this will add support for DelegatesToResource trait which is used by JsonResource class,
* making the instances of this class passable as ctor arg for laravel resources.
* @param string|int $key
* @return \Closure|null
*/
public function __get(string|int $key)
{
return $this->scraperResult->get($key);
}
/**
* Determine if an element with the specified key exists in the underlying scraper result collection.
* Additionally, this will add support for DelegatesToResource trait which is used by JsonResource class,
* making the instance of this class passable as ctor arg for laravel resources.
* @param string|int $key
* @return bool
*/
public function __isset(string|int $key)
{
return $this->scraperResult->has($key);
}
/**
* Dynamically pass method calls to the underlying scraper result collection.
* @param $method
* @param $parameters
* @return mixed
*/
public function __call($method, $parameters)
{
if (self::hasMacro($method)) {
return $this->macroCall($method, $parameters);
}
return $this->forwardCallTo($this->scraperResult, $method, $parameters);
}
private function mixedToTimestamp(mixed $modifiedAt): ?int private function mixedToTimestamp(mixed $modifiedAt): ?int
{ {
if ($modifiedAt instanceof UTCDateTime) { if ($modifiedAt instanceof UTCDateTime) {
@ -115,4 +162,24 @@ final class CachedData
return null; return null;
} }
public function offsetExists(mixed $offset): bool
{
return $this->scraperResult->offsetExists($offset);
}
public function offsetGet(mixed $offset): mixed
{
return $this->scraperResult->offsetGet($offset);
}
public function offsetSet(mixed $offset, mixed $value): void
{
// noop, readonly
}
public function offsetUnset(mixed $offset): void
{
// noop, readonly
}
} }

View File

@ -45,7 +45,7 @@ class AnimeSearchEndpointTest extends TestCase
{ {
return [ return [
"query string = `?limit=5`" => [ "query string = `?limit=5`" => [
[5, []] 5, []
], ],
"query string = `?limit=5&type=tv`" => [5, ["type" => "tv"]], "query string = `?limit=5&type=tv`" => [5, ["type" => "tv"]],
"query string = `?limit=5&type=tv&min_score=7`" => [ "query string = `?limit=5&type=tv&min_score=7`" => [