├── .editorconfig ├── .gitattributes ├── .github ├── FUNDING.yml ├── ISSUE_TEMPLATE │ └── bug.yml └── workflows │ ├── archive.yaml │ ├── code-quality-pr.yaml │ ├── code-quality-push.yaml │ ├── comment-run.yaml │ ├── tests.yaml │ └── utilities │ ├── lint-pr │ └── lint-push ├── .gitignore ├── .php-cs-fixer.dist.php ├── LICENSE ├── composer.json ├── grumphp.yml ├── phpunit.xml ├── phpunit.xml.dist ├── readme.md ├── src ├── Exception │ ├── BadResponseException.php │ └── ParserException.php ├── Goutte │ └── GoutteWrapper.php ├── Helper │ ├── Constants.php │ ├── JString.php │ ├── MalUrlExtractor.php │ ├── Media.php │ └── Parser.php ├── Model │ ├── Anime │ │ ├── Anime.php │ │ ├── AnimeCharactersAndStaff.php │ │ ├── AnimeEpisode.php │ │ ├── AnimeMoreInfo.php │ │ ├── AnimeRecentlyUpdatedByUser.php │ │ ├── AnimeReview.php │ │ ├── AnimeReviewScores.php │ │ ├── AnimeReviews.php │ │ ├── AnimeStats.php │ │ ├── AnimeStatsScore.php │ │ ├── AnimeUserUpdates.php │ │ ├── AnimeVideos.php │ │ ├── AnimeVideosEpisodes.php │ │ ├── EpisodeListItem.php │ │ ├── Episodes.php │ │ ├── MusicVideoListItem.php │ │ ├── PromoListItem.php │ │ ├── StaffListItem.php │ │ └── StreamEpisodeListItem.php │ ├── Character │ │ ├── Animeography.php │ │ ├── Character.php │ │ ├── CharacterListItem.php │ │ ├── Mangaography.php │ │ └── VoiceActor.php │ ├── Club │ │ ├── Club.php │ │ ├── UserList.php │ │ └── UserProfile.php │ ├── Common │ │ ├── AnimeCard.php │ │ ├── AnimeMeta.php │ │ ├── CharacterMeta.php │ │ ├── ClubMeta.php │ │ ├── Collection │ │ │ ├── Pagination.php │ │ │ └── Results.php │ │ ├── CommonMeta.php │ │ ├── DateProp.php │ │ ├── DateRange.php │ │ ├── DefaultPicture.php │ │ ├── ItemBasicMeta.php │ │ ├── ItemMeta.php │ │ ├── MagazineMeta.php │ │ ├── MalUrl.php │ │ ├── MangaCard.php │ │ ├── MangaMeta.php │ │ ├── MusicMeta.php │ │ ├── Ography.php │ │ ├── PersonMeta.php │ │ ├── Picture.php │ │ ├── Recommendation.php │ │ ├── Title.php │ │ ├── Url.php │ │ ├── User.php │ │ ├── UserMeta.php │ │ ├── UserMetaBasic.php │ │ └── YoutubeMeta.php │ ├── Forum │ │ ├── ForumPost.php │ │ └── ForumTopic.php │ ├── Genre │ │ ├── AnimeGenre.php │ │ ├── AnimeGenreList.php │ │ ├── AnimeGenreListItem.php │ │ ├── MangaGenre.php │ │ ├── MangaGenreList.php │ │ └── MangaGenreListItem.php │ ├── Magazine │ │ ├── Magazine.php │ │ ├── MagazineList.php │ │ ├── MagazineListItem.php │ │ └── MagazineManga.php │ ├── Manga │ │ ├── CharacterListItem.php │ │ ├── Manga.php │ │ ├── MangaMoreInfo.php │ │ ├── MangaRecentlyUpdatedByUser.php │ │ ├── MangaReview.php │ │ ├── MangaReviewScores.php │ │ ├── MangaReviewer.php │ │ ├── MangaReviews.php │ │ ├── MangaStats.php │ │ ├── MangaStatsScore.php │ │ └── MangaUserUpdates.php │ ├── News │ │ ├── NewsList.php │ │ └── NewsListItem.php │ ├── Person │ │ ├── AnimeStaffPosition.php │ │ ├── Person.php │ │ ├── PublishedManga.php │ │ └── VoiceActingRole.php │ ├── Producer │ │ ├── Producer.php │ │ ├── ProducerAnime.php │ │ ├── ProducerList.php │ │ └── ProducerListItem.php │ ├── Recommendations │ │ ├── RecentRecommendations.php │ │ ├── RecommendationListItem.php │ │ ├── Recommender.php │ │ └── UserRecommendations.php │ ├── Resource │ │ ├── AnimeImageResource │ │ │ ├── AnimeImageResource.php │ │ │ ├── Jpg.php │ │ │ └── Webp.php │ │ ├── CharacterImageResource │ │ │ ├── CharacterImageResource.php │ │ │ ├── Jpg.php │ │ │ └── Webp.php │ │ ├── ClubImageResource │ │ │ ├── ClubImageResource.php │ │ │ └── Jpg.php │ │ ├── CommonImageResource │ │ │ ├── CommonImageResource.php │ │ │ ├── Jpg.php │ │ │ └── Webp.php │ │ ├── PersonImageResource │ │ │ ├── Jpg.php │ │ │ └── PersonImageResource.php │ │ ├── UserImageResource │ │ │ ├── Jpg.php │ │ │ ├── UserImageResource.php │ │ │ └── Webp.php │ │ ├── WrapImageResource │ │ │ ├── Jpg.php │ │ │ └── WrapImageResource.php │ │ └── YoutubeImageResource.php │ ├── Reviews │ │ ├── AnimeReview.php │ │ ├── FullAnimeReview.php │ │ ├── FullMangaReview.php │ │ ├── MangaReview.php │ │ ├── Reactions.php │ │ ├── Review.php │ │ ├── Reviewer.php │ │ └── Reviews.php │ ├── Schedule │ │ └── Schedule.php │ ├── Search │ │ ├── AnimeSearch.php │ │ ├── AnimeSearchListItem.php │ │ ├── CharacterSearch.php │ │ ├── CharacterSearchListItem.php │ │ ├── MangaSearch.php │ │ ├── MangaSearchListItem.php │ │ ├── PersonSearch.php │ │ ├── PersonSearchListItem.php │ │ ├── Search.php │ │ ├── UserSearch.php │ │ └── UserSearchListItem.php │ ├── SeasonList │ │ ├── SeasonArchive.php │ │ └── SeasonListItem.php │ ├── Seasonal │ │ ├── Seasonal.php │ │ └── SeasonalAnime.php │ ├── Top │ │ ├── TopAnime.php │ │ ├── TopAnimeListItem.php │ │ ├── TopCharacterListItem.php │ │ ├── TopCharacters.php │ │ ├── TopManga.php │ │ ├── TopMangaListItem.php │ │ ├── TopPeople.php │ │ └── TopPersonListItem.php │ ├── User │ │ ├── AnimeListItem.php │ │ ├── AnimeStats.php │ │ ├── BaseLastUpdate.php │ │ ├── FavoriteAnime.php │ │ ├── FavoriteCharacter.php │ │ ├── FavoriteCharacterRelatedEntry.php │ │ ├── FavoriteListEntry.php │ │ ├── FavoriteManga.php │ │ ├── Favorites.php │ │ ├── Friend.php │ │ ├── Friends.php │ │ ├── History.php │ │ ├── LastAnimeUpdate.php │ │ ├── LastMangaUpdate.php │ │ ├── LastUpdates.php │ │ ├── MangaListItem.php │ │ ├── MangaStats.php │ │ ├── Profile.php │ │ └── Reviews │ │ │ ├── UserAnimeReview.php │ │ │ ├── UserMangaReview.php │ │ │ └── UserReviews.php │ └── Watch │ │ ├── EpisodeListItem.php │ │ ├── Episodes.php │ │ ├── PromotionalVideoListItem.php │ │ ├── PromotionalVideos.php │ │ └── RecentEpisodeListItem.php ├── MyAnimeList │ └── MalClient.php ├── Parser │ ├── Anime │ │ ├── AnimeEpisodeParser.php │ │ ├── AnimeParser.php │ │ ├── AnimeRecentlyUpdatedByUsersListParser.php │ │ ├── AnimeRecentlyUpdatedByUsersParser.php │ │ ├── AnimeReviewsParser.php │ │ ├── AnimeStatsParser.php │ │ ├── CharactersAndStaffParser.php │ │ ├── EpisodeListItemParser.php │ │ ├── EpisodesParser.php │ │ ├── MoreInfoParser.php │ │ ├── MusicVideoListItemParser.php │ │ ├── PromoListItemParser.php │ │ ├── StaffListItemParser.php │ │ ├── StreamEpisodeListItemParser.php │ │ └── VideosParser.php │ ├── Character │ │ ├── AnimeographyParser.php │ │ ├── CharacterListItemParser.php │ │ ├── CharacterParser.php │ │ ├── MangaographyParser.php │ │ ├── OgraphyParser.php │ │ └── VoiceActorParser.php │ ├── Club │ │ ├── ClubParser.php │ │ ├── UserListParser.php │ │ └── UserProfileParser.php │ ├── Common │ │ ├── AlternativeTitleParser.php │ │ ├── AnimeCardParser.php │ │ ├── DefaultPicturesPageParser.php │ │ ├── ItemMetaParser.php │ │ ├── MalUrlParser.php │ │ ├── MangaCardParser.php │ │ ├── PictureParser.php │ │ ├── PicturesPageParser.php │ │ ├── Recommendation.php │ │ ├── Recommendations.php │ │ └── UrlParser.php │ ├── Forum │ │ ├── ForumPageParser.php │ │ └── ForumTopicParser.php │ ├── Genre │ │ ├── AnimeGenreListItemParser.php │ │ ├── AnimeGenreListParser.php │ │ ├── AnimeGenreParser.php │ │ ├── MangaGenreListItemParser.php │ │ ├── MangaGenreListParser.php │ │ └── MangaGenreParser.php │ ├── Magazine │ │ ├── MagazineListItemParser.php │ │ ├── MagazineListParser.php │ │ └── MagazineParser.php │ ├── Manga │ │ ├── CharactersParser.php │ │ ├── MangaParser.php │ │ ├── MangaRecentlyUpdatedByUsersListParser.php │ │ ├── MangaRecentlyUpdatedByUsersParser.php │ │ ├── MangaReviewScoresParser.php │ │ ├── MangaReviewerParser.php │ │ ├── MangaReviewsParser.php │ │ ├── MangaStatsParser.php │ │ └── MoreInfoParser.php │ ├── News │ │ ├── NewsListItemParser.php │ │ └── NewsListParser.php │ ├── ParserInterface.php │ ├── Person │ │ ├── AnimeStaffPositionParser.php │ │ ├── PersonParser.php │ │ ├── PublishedMangaParser.php │ │ └── VoiceActingRoleParser.php │ ├── Producer │ │ ├── ProducerListItemParser.php │ │ ├── ProducerListParser.php │ │ └── ProducerParser.php │ ├── Recommendations │ │ ├── RecentRecommendationsParser.php │ │ ├── RecommendationListItemParser.php │ │ └── UserRecommendationsParser.php │ ├── Reviews │ │ ├── AnimeReviewParser.php │ │ ├── MangaReviewParser.php │ │ ├── ReactionsParser.php │ │ ├── ReviewerParser.php │ │ └── ReviewsParser.php │ ├── Schedule │ │ └── ScheduleParser.php │ ├── Search │ │ ├── AnimeSearchListItemParser.php │ │ ├── AnimeSearchParser.php │ │ ├── CharacterSearchListItemParser.php │ │ ├── CharacterSearchParser.php │ │ ├── MangaSearchListItemParser.php │ │ ├── MangaSearchParser.php │ │ ├── PersonSearchListItemParser.php │ │ ├── PersonSearchParser.php │ │ ├── UserSearchListItemParser.php │ │ └── UserSearchParser.php │ ├── SeasonList │ │ ├── SeasonListItemParser.php │ │ └── SeasonListParser.php │ ├── Seasonal │ │ └── SeasonalParser.php │ ├── Top │ │ ├── TopAnimeParser.php │ │ ├── TopCharactersParser.php │ │ ├── TopListItemParser.php │ │ ├── TopMangaParser.php │ │ └── TopPeopleParser.php │ ├── User │ │ ├── ClubParser.php │ │ ├── Friends │ │ │ ├── FriendParser.php │ │ │ └── FriendsParser.php │ │ ├── History │ │ │ ├── HistoryItemParser.php │ │ │ └── HistoryParser.php │ │ ├── Profile │ │ │ ├── AnimeStatsParser.php │ │ │ ├── FavoritesParser.php │ │ │ ├── LastUpdatesParser.php │ │ │ ├── MangaStatsParser.php │ │ │ └── UserProfileParser.php │ │ ├── Reviews │ │ │ └── UserReviewsParser.php │ │ └── UsernameByIdParser.php │ └── Watch │ │ ├── EpisodeListItemParser.php │ │ ├── PromotionalVideoListItemParser.php │ │ ├── WatchEpisodesParser.php │ │ └── WatchPromotionalVideosParser.php └── Request │ ├── Anime │ ├── AnimeCharactersAndStaffRequest.php │ ├── AnimeEpisodeRequest.php │ ├── AnimeEpisodesRequest.php │ ├── AnimeForumRequest.php │ ├── AnimeMoreInfoRequest.php │ ├── AnimeNewsRequest.php │ ├── AnimePicturesRequest.php │ ├── AnimeRecentlyUpdatedByUsersRequest.php │ ├── AnimeRecommendationsRequest.php │ ├── AnimeRequest.php │ ├── AnimeReviewsRequest.php │ ├── AnimeStatsRequest.php │ ├── AnimeVideosEpisodesRequest.php │ └── AnimeVideosRequest.php │ ├── Character │ ├── CharacterPicturesRequest.php │ └── CharacterRequest.php │ ├── Club │ ├── ClubRequest.php │ └── UserListRequest.php │ ├── Genre │ ├── AnimeGenreRequest.php │ ├── AnimeGenresRequest.php │ ├── MangaGenreRequest.php │ └── MangaGenresRequest.php │ ├── Magazine │ ├── MagazineRequest.php │ └── MagazinesRequest.php │ ├── Manga │ ├── MangaCharactersRequest.php │ ├── MangaForumRequest.php │ ├── MangaMoreInfoRequest.php │ ├── MangaNewsRequest.php │ ├── MangaPicturesRequest.php │ ├── MangaRecentlyUpdatedByUsersRequest.php │ ├── MangaRecommendationsRequest.php │ ├── MangaRequest.php │ ├── MangaReviewsRequest.php │ └── MangaStatsRequest.php │ ├── Person │ ├── PersonPicturesRequest.php │ └── PersonRequest.php │ ├── Producer │ ├── ProducerRequest.php │ └── ProducersRequest.php │ ├── Recommendations │ └── RecentRecommendationsRequest.php │ ├── RequestInterface.php │ ├── Reviews │ └── ReviewsRequest.php │ ├── Schedule │ └── ScheduleRequest.php │ ├── Search │ ├── AnimeSearchRequest.php │ ├── CharacterSearchRequest.php │ ├── MangaSearchRequest.php │ ├── PersonSearchRequest.php │ └── UserSearchRequest.php │ ├── SeasonList │ └── SeasonListRequest.php │ ├── Seasonal │ └── SeasonalRequest.php │ ├── Top │ ├── TopAnimeRequest.php │ ├── TopCharactersRequest.php │ ├── TopMangaRequest.php │ └── TopPeopleRequest.php │ ├── User │ ├── RecentlyOnlineUsersRequest.php │ ├── UserAnimeListRequest.php │ ├── UserClubsRequest.php │ ├── UserFriendsRequest.php │ ├── UserHistoryRequest.php │ ├── UserMangaListRequest.php │ ├── UserProfileRequest.php │ ├── UserRecommendationsRequest.php │ ├── UserReviewsRequest.php │ └── UsernameByIdRequest.php │ └── Watch │ ├── PopularEpisodesRequest.php │ ├── PopularPromotionalVideosRequest.php │ ├── RecentEpisodesRequest.php │ └── RecentPromotionalVideosRequest.php └── test └── JikanTest ├── Helper ├── JStringTest.php ├── MediaTest.php └── ParserTest.php ├── HttpFilesystemCacheClientCallback.php ├── Model └── Common │ ├── DatePropTest.php │ └── DateRangeTest.php ├── Parser ├── Anime │ ├── AnimeEpisodeParserTest.php │ ├── AnimeEpisodesParserTest.php │ ├── AnimeMoreInfoParserTest.php │ ├── AnimeParserTest.php │ ├── AnimeRecentlyUpdatedByUsersParserTest.php │ ├── AnimeRecommendationParserTest.php │ ├── AnimeReviewsParserTest.php │ └── AnimeStatsParserTest.php ├── Character │ ├── AnimeographyParserTest.php │ ├── CharacterListItemParserTest.php │ ├── CharacterParserTest.php │ ├── StaffListItemParserTest.php │ └── VoiceActorParserTest.php ├── Club │ ├── ClubParserTest.php │ └── UserListParserTest.php ├── Common │ └── MalUrlParserTest.php ├── Forum │ └── ForumTopicParserTest.php ├── Genre │ ├── AnimeGenreParserTest.php │ └── MangaGenreParserTest.php ├── Magazine │ └── MagazineParserTest.php ├── Manga │ ├── CharactersParserTest.php │ ├── MangaParserTest.php │ ├── MangaRecentlyUpdatedByUsersParserTest.php │ ├── MangaRecommendationParserTest.php │ ├── MangaReviewsParserTest.php │ └── MangaStatsParserTest.php ├── News │ └── NewsListItemParserTest.php ├── Person │ └── PersonParserTest.php ├── Pictures │ └── PicturesPageParserTest.php ├── Producer │ └── ProducerParserTest.php ├── Schedule │ └── ScheduleParserTest.php ├── Search │ ├── AnimeSearchAiringTest.php │ ├── AnimeSearchEpisodeTest.php │ ├── AnimeSearchTest.php │ ├── CharacterSearchTest.php │ ├── MangaSearchTest.php │ └── PersonSearchTest.php ├── SeasonList │ ├── SeasonListItemParserTest.php │ └── SeasonListParserTest.php ├── Seasonal │ ├── SeasonalAnimeParserTest.php │ └── SeasonalParserTest.php ├── Top │ ├── TopAnimeParserTest.php │ ├── TopCharacterParserTest.php │ ├── TopMangaParserTest.php │ └── TopPeopleParserTest.php ├── UserFriend │ └── FriendParserTest.php ├── UserHistory │ └── UserHistoryParserTest.php ├── UserProfile │ └── UserProfileParserTest.php └── Video │ └── AnimeVideoParserTest.php └── TestCase.php /.editorconfig: -------------------------------------------------------------------------------- 1 | # Editor configuration, see http://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | indent_style = space 7 | indent_size = 2 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | end_of_line = lf 11 | 12 | [*.md] 13 | max_line_length = off 14 | trim_trailing_whitespace = false 15 | 16 | [*.php] 17 | indent_size = 4 18 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | 7 | # Standard to msysgit 8 | *.doc diff=astextplain 9 | *.DOC diff=astextplain 10 | *.docx diff=astextplain 11 | *.DOCX diff=astextplain 12 | *.dot diff=astextplain 13 | *.DOT diff=astextplain 14 | *.pdf diff=astextplain 15 | *.PDF diff=astextplain 16 | *.rtf diff=astextplain 17 | *.RTF diff=astextplain 18 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | #github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] 4 | patreon: jikan # Replace with a single Patreon username 5 | #open_collective: # Replace with a single Open Collective username 6 | #ko_fi: # Replace with a single Ko-fi username 7 | #tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | #community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | #custom: # Replace with a single custom sponsorship URL 10 | -------------------------------------------------------------------------------- /.github/workflows/archive.yaml: -------------------------------------------------------------------------------- 1 | name: Archive 2 | 3 | on: 4 | schedule: 5 | - cron: "0 0 * * *" 6 | 7 | jobs: 8 | archive: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: actions/stale@v5.0.0 12 | with: 13 | repo-token: ${{ secrets.GITHUB_TOKEN }} 14 | days-before-stale: 60 15 | days-before-close: 18 16 | stale-issue-message: > 17 | This issue will be closed and archived in 18 days, as there has been no activity in the last 60 days. 18 | If this issue is still relevant or you would like to see it actioned, please respond and we will re-open this issue. 19 | stale-pr-message: > 20 | This pull request will be closed and archived in 18 days, as there has been no activity in the last 60 days. 21 | If this is still being worked on, please respond and we will re-open this pull request. 22 | stale-issue-label: 'archived' 23 | stale-pr-label: 'archived' 24 | exempt-issue-labels: 'in progress,feature request,bug,enhancement,no-archive' 25 | exempt-pr-labels: 'in progress' 26 | -------------------------------------------------------------------------------- /.github/workflows/code-quality-pr.yaml: -------------------------------------------------------------------------------- 1 | name: Code Quality 2 | 3 | on: 4 | pull_request: 5 | 6 | jobs: 7 | codeQuality: 8 | runs-on: ubuntu-20.04 9 | name: PHP 10 | steps: 11 | - name: Checkout changes 12 | uses: actions/checkout@v2 13 | with: 14 | fetch-depth: 0 15 | - name: Setup PHP and linter 16 | uses: shivammathur/setup-php@v2 17 | with: 18 | php-version: '8.0' 19 | tools: parallel-lint, phpunit, php-cs-fixer 20 | - name: Run code quality checks 21 | run: ./.github/workflows/utilities/lint-pr ${{ github.base_ref }} 22 | -------------------------------------------------------------------------------- /.github/workflows/code-quality-push.yaml: -------------------------------------------------------------------------------- 1 | name: Code Quality 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | 8 | jobs: 9 | codeQuality: 10 | runs-on: ubuntu-20.04 11 | name: PHP 12 | steps: 13 | - name: Checkout changes 14 | uses: actions/checkout@v2 15 | with: 16 | fetch-depth: 0 17 | - name: Setup PHP and linter 18 | uses: shivammathur/setup-php@v2 19 | with: 20 | php-version: '8.0' 21 | tools: parallel-lint, phpunit, php-cs-fixer 22 | - name: Run code quality checks 23 | run: ./.github/workflows/utilities/lint-push 24 | -------------------------------------------------------------------------------- /.github/workflows/comment-run.yaml: -------------------------------------------------------------------------------- 1 | name: "Comment run" 2 | on: 3 | issue_comment: 4 | types: [created] 5 | 6 | jobs: 7 | comment-run: 8 | runs-on: ubuntu-18.04 9 | steps: 10 | - uses: actions/checkout@v2 11 | with: 12 | # 0 indicates all history 13 | fetch-depth: 0 14 | - uses: nwtgck/actions-comment-run@v1.1 15 | with: 16 | github-token: ${{ secrets.GITHUB_TOKEN }} 17 | allowed-associations: '["OWNER", "COLLABORATOR"]' 18 | -------------------------------------------------------------------------------- /.github/workflows/utilities/lint-push: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env php 2 | $elem["file"] === $file); 31 | 32 | foreach ($errors_in_file as $error) { 33 | echo "\e[2m" . str_pad(' L' . $error['line'], 7) . " | \e[0m"; 34 | echo "\e[0;31mERR:\e[0m "; 35 | echo $error['message']; 36 | echo "\n"; 37 | } 38 | } 39 | 40 | exit(1); 41 | } 42 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /vendor/ 2 | /.idea/ 3 | /composer.lock 4 | /test.php 5 | /jikan-fixtures 6 | /.php-cs-fixer.cache 7 | composer.phar 8 | .phpunit.result.cache 9 | /.phpdoc 10 | -------------------------------------------------------------------------------- /.php-cs-fixer.dist.php: -------------------------------------------------------------------------------- 1 | in(__DIR__.'/src') 5 | ; 6 | 7 | return (new PhpCsFixer\Config()) 8 | ->setRules([ 9 | '@PSR2' => true, 10 | 'array_syntax' => ['syntax' => 'short'], 11 | ]) 12 | ->setFinder($finder) 13 | ; 14 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Jikan API 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /grumphp.yml: -------------------------------------------------------------------------------- 1 | grumphp: 2 | process_timeout: 180 3 | tasks: 4 | phpcsfixer: 5 | config: .php-cs-fixer.dist.php 6 | git_blacklist: 7 | keywords: 8 | - 'var_dump' 9 | - 'exit' 10 | - 'else' 11 | - 'ini_set' 12 | - 'error_reporting' 13 | - 'die' 14 | paratest: 15 | always_execute: true 16 | phplint: ~ -------------------------------------------------------------------------------- /phpunit.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | src 6 | 7 | 8 | 9 | 10 | ./test/JikanTest 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /phpunit.xml.dist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | ./test/JikanTest 5 | 6 | 7 | 8 | 9 | src 10 | 11 | 12 | -------------------------------------------------------------------------------- /src/Exception/BadResponseException.php: -------------------------------------------------------------------------------- 1 | getPath()); 23 | 24 | return new self($message, $previous->getCode(), $previous); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/Goutte/GoutteWrapper.php: -------------------------------------------------------------------------------- 1 | getInternalResponse(); 48 | if ($internalResponse->getStatusCode() >= 400) { 49 | throw new BadResponseException( 50 | $internalResponse->getStatusCode().' on '.$response->getUri(), 51 | $internalResponse->getStatusCode() 52 | ); 53 | } 54 | 55 | return $response; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/Helper/Media.php: -------------------------------------------------------------------------------- 1 | ]{11})/", 30 | $url, 31 | $matches 32 | ); 33 | 34 | return $matches[1] ?? null; 35 | } 36 | 37 | /** 38 | * @param string $id 39 | * @return string 40 | */ 41 | public static function generateYoutubeUrlFromId(?string $id) : ?string 42 | { 43 | if ($id === null) { 44 | return null; 45 | } 46 | 47 | return sprintf('https://www.youtube.com/watch?v=%s', $id); 48 | } 49 | 50 | /** 51 | * @param string $id 52 | * @return YoutubeImageResource 53 | */ 54 | public static function generateYoutubeImageResource(?string $id) : YoutubeImageResource 55 | { 56 | return YoutubeImageResource::factory($id); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/Model/Anime/AnimeCharactersAndStaff.php: -------------------------------------------------------------------------------- 1 | characters = $parser->getCharacters(); 36 | $instance->staff = $parser->getStaff(); 37 | 38 | return $instance; 39 | } 40 | 41 | /** 42 | * @return \Jikan\Model\Character\CharacterListItem[] 43 | */ 44 | public function getCharacters(): array 45 | { 46 | return $this->characters; 47 | } 48 | 49 | /** 50 | * @return StaffListItem[] 51 | */ 52 | public function getStaff(): array 53 | { 54 | return $this->staff; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/Model/Anime/AnimeMoreInfo.php: -------------------------------------------------------------------------------- 1 | moreInfo = $parser->getMoreInfo(); 30 | 31 | return $instance; 32 | } 33 | 34 | /** 35 | * @return string|null 36 | */ 37 | public function getMoreInfo(): ?string 38 | { 39 | return $this->moreInfo; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/Model/Anime/AnimeReview.php: -------------------------------------------------------------------------------- 1 | malId = $parser->getId(); 31 | $instance->url = $parser->getUrl(); 32 | $instance->type = $parser->getType() ?? 'anime'; 33 | $instance->reactions = $parser->getReactions(); 34 | $instance->date = $parser->getDate(); 35 | $instance->user = $parser->getReviewer(); 36 | $instance->score = $parser->getReviewerScore(); 37 | $instance->review = $parser->getContent(); 38 | $instance->tags = $parser->getReviewTag(); 39 | $instance->isPreliminary = $parser->isPreliminary(); 40 | $instance->episodesWatched = $parser->getEpisodesWatched(); 41 | $instance->isSpoiler = $parser->isSpoiler(); 42 | 43 | return $instance; 44 | } 45 | 46 | /** 47 | * @return Reviewer 48 | */ 49 | public function getUser(): Reviewer 50 | { 51 | return $this->user; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/Model/Anime/AnimeReviews.php: -------------------------------------------------------------------------------- 1 | results = $parser->getResults(); 31 | $instance->hasNextPage = $parser->hasNextPage(); 32 | 33 | return $instance; 34 | } 35 | 36 | /** 37 | * @return static 38 | */ 39 | public static function mock() : self 40 | { 41 | return new self(); 42 | } 43 | 44 | /** 45 | * @return array 46 | */ 47 | public function getResults(): array 48 | { 49 | return $this->results; 50 | } 51 | 52 | /** 53 | * @return bool 54 | */ 55 | public function hasNextPage(): bool 56 | { 57 | return $this->hasNextPage; 58 | } 59 | 60 | /** 61 | * @return int 62 | */ 63 | public function getLastVisiblePage(): int 64 | { 65 | return $this->lastVisiblePage; 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/Model/Anime/AnimeStatsScore.php: -------------------------------------------------------------------------------- 1 | score = $score; 38 | $instance->votes = $votes; 39 | $instance->percentage = $percentage; 40 | 41 | return $instance; 42 | } 43 | 44 | /** 45 | * @return mixed 46 | */ 47 | public function getScore() 48 | { 49 | return $this->score; 50 | } 51 | 52 | /** 53 | * @return int 54 | */ 55 | public function getVotes(): int 56 | { 57 | return $this->votes; 58 | } 59 | 60 | /** 61 | * @return float 62 | */ 63 | public function getPercentage(): float 64 | { 65 | return $this->percentage; 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/Model/Anime/AnimeVideos.php: -------------------------------------------------------------------------------- 1 | episodes = $parser->getEpisodes(); 39 | $instance->promo = $parser->getPromos(); 40 | $instance->musicVideos = $parser->getMusic(); 41 | 42 | return $instance; 43 | } 44 | 45 | /** 46 | * @return PromoListItem[] 47 | */ 48 | public function getPromos(): array 49 | { 50 | return $this->promo; 51 | } 52 | 53 | /** 54 | * @return StreamEpisodeListItem[] 55 | */ 56 | public function getEpisodes(): array 57 | { 58 | return $this->episodes; 59 | } 60 | 61 | /** 62 | * @return MusicVideoListItem[] 63 | */ 64 | public function getMusicVideos() 65 | { 66 | return $this->musicVideos; 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/Model/Anime/MusicVideoListItem.php: -------------------------------------------------------------------------------- 1 | title = $parser->getTitle(); 40 | $instance->video = YoutubeMeta::factory($parser->getVideoUrl()); 41 | $instance->meta = $parser->getMusic(); 42 | 43 | return $instance; 44 | } 45 | 46 | /** 47 | * @return string 48 | */ 49 | public function getTitle(): string 50 | { 51 | return $this->title; 52 | } 53 | 54 | /** 55 | * @return YoutubeMeta 56 | */ 57 | public function getVideo(): YoutubeMeta 58 | { 59 | return $this->video; 60 | } 61 | 62 | /** 63 | * @return MusicMeta 64 | */ 65 | public function getMeta(): MusicMeta 66 | { 67 | return $this->meta; 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/Model/Anime/PromoListItem.php: -------------------------------------------------------------------------------- 1 | title = $parser->getTitle(); 35 | $instance->trailer = YoutubeMeta::factory($parser->getVideoUrl()); 36 | 37 | return $instance; 38 | } 39 | 40 | /** 41 | * @return string 42 | */ 43 | public function getTitle(): string 44 | { 45 | return $this->title; 46 | } 47 | 48 | /** 49 | * @return YoutubeMeta 50 | */ 51 | public function getTrailer(): YoutubeMeta 52 | { 53 | return $this->trailer; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/Model/Anime/StaffListItem.php: -------------------------------------------------------------------------------- 1 | positions = $parser->getPositions(); 36 | $instance->person = $parser->getPersonMeta(); 37 | 38 | return $instance; 39 | } 40 | 41 | /** 42 | * @return PersonMeta 43 | */ 44 | public function getPerson(): PersonMeta 45 | { 46 | return $this->person; 47 | } 48 | 49 | /** 50 | * @return string[] 51 | */ 52 | public function getPositions(): array 53 | { 54 | return $this->positions; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/Model/Character/Animeography.php: -------------------------------------------------------------------------------- 1 | anime = $parser->getAnimeMeta(); 32 | $instance->role = $parser->getRole(); 33 | 34 | return $instance; 35 | } 36 | 37 | /** 38 | * @return AnimeMeta 39 | */ 40 | public function getAnime(): AnimeMeta 41 | { 42 | return $this->anime; 43 | } 44 | 45 | /** 46 | * @return string 47 | */ 48 | public function getRole(): string 49 | { 50 | return $this->role; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/Model/Character/Mangaography.php: -------------------------------------------------------------------------------- 1 | manga = $parser->getMangaMeta(); 32 | $instance->role = $parser->getRole(); 33 | 34 | return $instance; 35 | } 36 | 37 | /** 38 | * @return MangaMeta 39 | */ 40 | public function getManga(): MangaMeta 41 | { 42 | return $this->manga; 43 | } 44 | 45 | /** 46 | * @return string 47 | */ 48 | public function getRole(): string 49 | { 50 | return $this->role; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/Model/Character/VoiceActor.php: -------------------------------------------------------------------------------- 1 | person = $parser->getPersonMeta(); 36 | $instance->language = $parser->getLanguage(); 37 | 38 | return $instance; 39 | } 40 | 41 | /** 42 | * @return PersonMeta 43 | */ 44 | public function getPerson(): PersonMeta 45 | { 46 | return $this->person; 47 | } 48 | 49 | /** 50 | * @return string 51 | */ 52 | public function getLanguage(): string 53 | { 54 | return $this->language; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/Model/Club/UserProfile.php: -------------------------------------------------------------------------------- 1 | username = $parser->getUsername(); 39 | $instance->images = UserImageResource::factory($parser->getImage()); 40 | $instance->url = $parser->getUrl(); 41 | 42 | return $instance; 43 | } 44 | 45 | /** 46 | * @return string 47 | */ 48 | public function getUsername(): string 49 | { 50 | return $this->username; 51 | } 52 | 53 | /** 54 | * @return string 55 | */ 56 | public function getUrl(): string 57 | { 58 | return $this->url; 59 | } 60 | 61 | /** 62 | * @return UserImageResource 63 | */ 64 | public function getImages(): UserImageResource 65 | { 66 | return $this->images; 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/Model/Common/ClubMeta.php: -------------------------------------------------------------------------------- 1 | malId = $malId; 37 | $instance->name = $name; 38 | $instance->url = $url; 39 | 40 | return $instance; 41 | } 42 | 43 | /** 44 | * @return int 45 | */ 46 | public function getMalId(): int 47 | { 48 | return $this->malId; 49 | } 50 | 51 | /** 52 | * @return string 53 | */ 54 | public function getName(): string 55 | { 56 | return $this->name; 57 | } 58 | 59 | /** 60 | * @return string 61 | */ 62 | public function getUrl(): string 63 | { 64 | return $this->url; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/Model/Common/Collection/Pagination.php: -------------------------------------------------------------------------------- 1 | results; 23 | } 24 | 25 | /** 26 | * @param array $results 27 | * @return Results 28 | */ 29 | public function setResults(array $results): Results 30 | { 31 | $this->results = $results; 32 | return $this; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/Model/Common/DefaultPicture.php: -------------------------------------------------------------------------------- 1 | imageUrl = $parser->getSmall(); 29 | 30 | return $instance; 31 | } 32 | 33 | /** 34 | * @return string 35 | */ 36 | public function getImageUrl(): string 37 | { 38 | return $this->imageUrl; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/Model/Common/ItemBasicMeta.php: -------------------------------------------------------------------------------- 1 | malId = (int) $malId; 31 | $this->name = $name; 32 | } 33 | 34 | /** 35 | * @return int 36 | */ 37 | public function getMalId(): int 38 | { 39 | return $this->malId; 40 | } 41 | 42 | /** 43 | * @return string 44 | */ 45 | public function getTitle(): string 46 | { 47 | return $this->name; 48 | } 49 | 50 | /** 51 | * @return string 52 | */ 53 | public function getName(): string 54 | { 55 | return $this->name; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/Model/Common/MagazineMeta.php: -------------------------------------------------------------------------------- 1 | name = $name; 33 | $this->url = $url; 34 | } 35 | 36 | /** 37 | * @return string 38 | */ 39 | public function __toString() 40 | { 41 | return $this->name; 42 | } 43 | 44 | /** 45 | * @return int 46 | */ 47 | public function getMalId(): int 48 | { 49 | return MalUrlParser::parseId($this->url); 50 | } 51 | 52 | /** 53 | * @return string 54 | */ 55 | public function getType(): string 56 | { 57 | return preg_replace('#https://myanimelist.net/(\w+)/.*#', '$1', $this->url); 58 | } 59 | 60 | /** 61 | * @return string 62 | */ 63 | public function getName(): string 64 | { 65 | return $this->name; 66 | } 67 | 68 | /** 69 | * @return string 70 | */ 71 | public function getTitle(): string 72 | { 73 | return $this->name; 74 | } 75 | 76 | /** 77 | * @return string 78 | */ 79 | public function getUrl(): string 80 | { 81 | return $this->url; 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /src/Model/Common/MusicMeta.php: -------------------------------------------------------------------------------- 1 | title = $title; 30 | $this->author = $author; 31 | } 32 | 33 | /** 34 | * @return string 35 | */ 36 | public function __toString() 37 | { 38 | return "$this->title by $this->author"; 39 | } 40 | 41 | /** 42 | * @return string|null 43 | */ 44 | public function getTitle(): ?string 45 | { 46 | return $this->title; 47 | } 48 | 49 | /** 50 | * @return string|null 51 | */ 52 | public function getAuthor(): ?string 53 | { 54 | return $this->author; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/Model/Common/Ography.php: -------------------------------------------------------------------------------- 1 | role; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/Model/Common/Picture.php: -------------------------------------------------------------------------------- 1 | largeImageUrl = $parser->getLarge(); 34 | $instance->imageUrl = $parser->getSmall(); 35 | 36 | return $instance; 37 | } 38 | 39 | /** 40 | * @return string 41 | */ 42 | public function getImageUrl(): string 43 | { 44 | return $this->imageUrl; 45 | } 46 | 47 | /** 48 | * @return string 49 | */ 50 | public function getLargeImageUrl(): string 51 | { 52 | return $this->largeImageUrl; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/Model/Common/Recommendation.php: -------------------------------------------------------------------------------- 1 | entry = $parser->getEntryMeta(); 43 | $instance->url = $parser->getRecommendationurl(); 44 | $instance->votes = $parser->getRecommendationCount(); 45 | 46 | return $instance; 47 | } 48 | 49 | /** 50 | * @return CommonMeta 51 | */ 52 | public function getEntry(): CommonMeta 53 | { 54 | return $this->entry; 55 | } 56 | 57 | /** 58 | * @return string 59 | */ 60 | public function getUrl(): string 61 | { 62 | return $this->url; 63 | } 64 | 65 | /** 66 | * @return int 67 | */ 68 | public function getVotes(): int 69 | { 70 | return $this->votes; 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/Model/Common/Title.php: -------------------------------------------------------------------------------- 1 | type = $type; 33 | $this->title = $title; 34 | } 35 | 36 | /** 37 | * @return string 38 | */ 39 | public function getType(): string 40 | { 41 | return $this->type; 42 | } 43 | 44 | /** 45 | * @return string|null 46 | */ 47 | public function getTitle(): ?string 48 | { 49 | return $this->title; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/Model/Common/Url.php: -------------------------------------------------------------------------------- 1 | name = $name; 31 | $this->url = $url; 32 | } 33 | 34 | /** 35 | * @return string 36 | */ 37 | public function __toString() 38 | { 39 | return $this->name; 40 | } 41 | 42 | /** 43 | * @return string 44 | */ 45 | public function getName(): string 46 | { 47 | return $this->name; 48 | } 49 | 50 | /** 51 | * @return string 52 | */ 53 | public function getTitle(): string 54 | { 55 | return $this->name; 56 | } 57 | 58 | /** 59 | * @return string 60 | */ 61 | public function getUrl(): string 62 | { 63 | return $this->url; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/Model/Common/User.php: -------------------------------------------------------------------------------- 1 | url; 28 | } 29 | 30 | /** 31 | * @return string 32 | */ 33 | public function getUsername(): string 34 | { 35 | return $this->username; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/Model/Common/UserMetaBasic.php: -------------------------------------------------------------------------------- 1 | username = $username; 17 | $instance->url = $url; 18 | 19 | return $instance; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/Model/Magazine/MagazineList.php: -------------------------------------------------------------------------------- 1 | magazines = $parser->getMagazines(); 32 | 33 | return $instance; 34 | } 35 | 36 | /** 37 | * @return array|MagazineListItem[] 38 | */ 39 | public function getMagazines() 40 | { 41 | return $this->magazines; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/Model/Magazine/MagazineManga.php: -------------------------------------------------------------------------------- 1 | role = $parser->getRole(); 36 | $instance->character = $parser->getCharacterMeta(); 37 | 38 | return $instance; 39 | } 40 | 41 | /** 42 | * @return CharacterMeta 43 | */ 44 | public function getCharacter(): CharacterMeta 45 | { 46 | return $this->character; 47 | } 48 | 49 | /** 50 | * @return string 51 | */ 52 | public function getRole(): string 53 | { 54 | return $this->role; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/Model/Manga/MangaMoreInfo.php: -------------------------------------------------------------------------------- 1 | moreInfo = $parser->getMoreInfo(); 30 | 31 | return $instance; 32 | } 33 | 34 | /** 35 | * @return string 36 | */ 37 | public function getMoreInfo(): ?string 38 | { 39 | return $this->moreInfo; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/Model/Manga/MangaReview.php: -------------------------------------------------------------------------------- 1 | malId = $parser->getId(); 32 | $instance->url = $parser->getUrl(); 33 | $instance->type = $parser->getType() ?? 'manga'; 34 | $instance->reactions = $parser->getReactions(); 35 | $instance->date = $parser->getDate(); 36 | $instance->user = $parser->getReviewer(); 37 | $instance->score = $parser->getReviewerScore(); 38 | $instance->review = $parser->getContent(); 39 | $instance->tags = $parser->getReviewTag(); 40 | $instance->isPreliminary = $parser->isPreliminary(); 41 | $instance->chaptersRead = $parser->getChaptersRead(); 42 | $instance->isSpoiler = $parser->isSpoiler(); 43 | 44 | return $instance; 45 | } 46 | 47 | /** 48 | * @return Reviewer 49 | */ 50 | public function getUser(): Reviewer 51 | { 52 | return $this->user; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/Model/Manga/MangaReviews.php: -------------------------------------------------------------------------------- 1 | results = $parser->getResults(); 31 | $instance->hasNextPage = $parser->hasNextPage(); 32 | 33 | return $instance; 34 | } 35 | 36 | /** 37 | * @return static 38 | */ 39 | public static function mock() : self 40 | { 41 | return new self(); 42 | } 43 | 44 | /** 45 | * @return array 46 | */ 47 | public function getResults(): array 48 | { 49 | return $this->results; 50 | } 51 | 52 | /** 53 | * @return bool 54 | */ 55 | public function hasNextPage(): bool 56 | { 57 | return $this->hasNextPage; 58 | } 59 | 60 | /** 61 | * @return int 62 | */ 63 | public function getLastVisiblePage(): int 64 | { 65 | return $this->lastVisiblePage; 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/Model/Manga/MangaStatsScore.php: -------------------------------------------------------------------------------- 1 | score = $score; 38 | $instance->votes = $votes; 39 | $instance->percentage = $percentage; 40 | 41 | return $instance; 42 | } 43 | 44 | /** 45 | * @return int 46 | */ 47 | public function getScore(): int 48 | { 49 | return $this->score; 50 | } 51 | 52 | /** 53 | * @return int 54 | */ 55 | public function getVotes(): int 56 | { 57 | return $this->votes; 58 | } 59 | 60 | /** 61 | * @return float 62 | */ 63 | public function getPercentage(): float 64 | { 65 | return $this->percentage; 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/Model/News/NewsList.php: -------------------------------------------------------------------------------- 1 | results = $parser->getResults(); 39 | $instance->hasNextPage = $parser->getHasNextPage(); 40 | 41 | return $instance; 42 | } 43 | 44 | public static function mock() : self 45 | { 46 | return new self(); 47 | } 48 | 49 | /** 50 | * @return bool 51 | */ 52 | public function hasNextPage(): bool 53 | { 54 | return $this->hasNextPage; 55 | } 56 | 57 | /** 58 | * @return int 59 | */ 60 | public function getLastVisiblePage(): int 61 | { 62 | return $this->lastVisiblePage; 63 | } 64 | 65 | /** 66 | * @return array 67 | */ 68 | public function getResults(): array 69 | { 70 | return $this->results; 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/Model/Person/AnimeStaffPosition.php: -------------------------------------------------------------------------------- 1 | position = $parser->getPosition(); 36 | $instance->anime = $parser->getAnimeMeta(); 37 | 38 | return $instance; 39 | } 40 | 41 | /** 42 | * @return string 43 | */ 44 | public function getPosition(): string 45 | { 46 | return $this->position; 47 | } 48 | 49 | /** 50 | * @return AnimeMeta 51 | */ 52 | public function getAnimeMeta(): AnimeMeta 53 | { 54 | return $this->anime; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/Model/Person/PublishedManga.php: -------------------------------------------------------------------------------- 1 | position = $parser->getPosition(); 37 | $instance->mangaMeta = $parser->getMangaMeta(); 38 | 39 | return $instance; 40 | } 41 | 42 | /** 43 | * @return string 44 | */ 45 | public function getPosition(): string 46 | { 47 | return $this->position; 48 | } 49 | 50 | /** 51 | * @return mangaMeta 52 | */ 53 | public function getMangaMeta(): MangaMeta 54 | { 55 | return $this->mangaMeta; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/Model/Person/VoiceActingRole.php: -------------------------------------------------------------------------------- 1 | role = $parser->getRole(); 42 | $instance->anime = $parser->getAnimeMeta(); 43 | $instance->character = $parser->getCharacterMeta(); 44 | 45 | return $instance; 46 | } 47 | 48 | /** 49 | * @return string 50 | */ 51 | public function getRole(): string 52 | { 53 | return $this->role; 54 | } 55 | 56 | /** 57 | * @return AnimeMeta 58 | */ 59 | public function getAnimeMeta(): AnimeMeta 60 | { 61 | return $this->anime; 62 | } 63 | 64 | /** 65 | * @return CharacterMeta 66 | */ 67 | public function getCharacterMeta(): CharacterMeta 68 | { 69 | return $this->character; 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/Model/Producer/ProducerAnime.php: -------------------------------------------------------------------------------- 1 | producers = $parser->getProducers(); 31 | 32 | return $instance; 33 | } 34 | 35 | /** 36 | * @return array|ProducerListItem[] 37 | */ 38 | public function getProducers() 39 | { 40 | return $this->producers; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/Model/Recommendations/Recommender.php: -------------------------------------------------------------------------------- 1 | url = $url; 19 | $instance->username = $username; 20 | 21 | return $instance; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/Model/Resource/AnimeImageResource/AnimeImageResource.php: -------------------------------------------------------------------------------- 1 | jpg = Jpg::factory($imageUrl); 30 | $instance->webp = Webp::factory($imageUrl); 31 | 32 | return $instance; 33 | } 34 | 35 | /** 36 | * @return string 37 | */ 38 | public function __toString() : string 39 | { 40 | return $this->getJpg()->getImageUrl(); 41 | } 42 | 43 | /** 44 | * @return Jpg 45 | */ 46 | public function getJpg(): Jpg 47 | { 48 | return $this->jpg; 49 | } 50 | 51 | /** 52 | * @return Webp 53 | */ 54 | public function getWebp(): Webp 55 | { 56 | return $this->webp; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/Model/Resource/AnimeImageResource/Jpg.php: -------------------------------------------------------------------------------- 1 | imageUrl = $imageUrl; 36 | 37 | if ($instance->imageUrl === null) { 38 | return $instance; 39 | } 40 | 41 | $instance->smallImageUrl = str_replace('.jpg', 't.jpg', $imageUrl); 42 | $instance->largeImageUrl = str_replace('.jpg', 'l.jpg', $imageUrl); 43 | 44 | return $instance; 45 | } 46 | 47 | /** 48 | * @return string|null 49 | */ 50 | public function getImageUrl(): ?string 51 | { 52 | return $this->imageUrl; 53 | } 54 | 55 | /** 56 | * @return string|null 57 | */ 58 | public function getSmallImageUrl(): ?string 59 | { 60 | return $this->smallImageUrl; 61 | } 62 | 63 | /** 64 | * @return string|null 65 | */ 66 | public function getLargeImageUrl(): ?string 67 | { 68 | return $this->largeImageUrl; 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/Model/Resource/AnimeImageResource/Webp.php: -------------------------------------------------------------------------------- 1 | imageUrl = str_replace('.jpg', '.webp', $imageUrl); 36 | 37 | if ($instance->imageUrl === null) { 38 | return $instance; 39 | } 40 | 41 | $instance->smallImageUrl = str_replace('.jpg', 't.webp', $imageUrl); 42 | $instance->largeImageUrl = str_replace('.jpg', 'l.webp', $imageUrl); 43 | 44 | return $instance; 45 | } 46 | 47 | /** 48 | * @return string|null 49 | */ 50 | public function getImageUrl(): ?string 51 | { 52 | return $this->imageUrl; 53 | } 54 | 55 | /** 56 | * @return string|null 57 | */ 58 | public function getSmallImageUrl(): ?string 59 | { 60 | return $this->smallImageUrl; 61 | } 62 | 63 | /** 64 | * @return string|null 65 | */ 66 | public function getLargeImageUrl(): ?string 67 | { 68 | return $this->largeImageUrl; 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/Model/Resource/CharacterImageResource/CharacterImageResource.php: -------------------------------------------------------------------------------- 1 | jpg = Jpg::factory($imageUrl); 31 | $instance->webp = Webp::factory($imageUrl); 32 | 33 | return $instance; 34 | } 35 | 36 | /** 37 | * @return string 38 | */ 39 | public function __toString() : string 40 | { 41 | return $this->getJpg()->getImageUrl(); 42 | } 43 | 44 | /** 45 | * @return Webp 46 | */ 47 | public function getWebp(): Webp 48 | { 49 | return $this->webp; 50 | } 51 | 52 | /** 53 | * @return Jpg 54 | */ 55 | public function getJpg(): Jpg 56 | { 57 | return $this->jpg; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/Model/Resource/CharacterImageResource/Jpg.php: -------------------------------------------------------------------------------- 1 | imageUrl = $imageUrl; 25 | 26 | if ($instance->imageUrl === null) { 27 | return $instance; 28 | } 29 | 30 | return $instance; 31 | } 32 | 33 | /** 34 | * @return string|null 35 | */ 36 | public function getImageUrl(): ?string 37 | { 38 | return $this->imageUrl; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/Model/Resource/CharacterImageResource/Webp.php: -------------------------------------------------------------------------------- 1 | imageUrl = str_replace('.jpg', '.webp', $imageUrl); 30 | 31 | if ($instance->imageUrl === null) { 32 | return $instance; 33 | } 34 | 35 | $instance->smallImageUrl = str_replace('.jpg', 't.webp', $imageUrl); 36 | 37 | return $instance; 38 | } 39 | 40 | /** 41 | * @return string|null 42 | */ 43 | public function getImageUrl(): ?string 44 | { 45 | return $this->imageUrl; 46 | } 47 | 48 | /** 49 | * @return string|null 50 | */ 51 | public function getSmallImageUrl(): ?string 52 | { 53 | return $this->smallImageUrl; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/Model/Resource/ClubImageResource/ClubImageResource.php: -------------------------------------------------------------------------------- 1 | jpg = Jpg::factory($imageUrl); 25 | 26 | return $instance; 27 | } 28 | 29 | /** 30 | * @return string 31 | */ 32 | public function __toString() : string 33 | { 34 | return $this->getJpg()->getImageUrl(); 35 | } 36 | 37 | /** 38 | * @return Jpg 39 | */ 40 | public function getJpg(): Jpg 41 | { 42 | return $this->jpg; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/Model/Resource/ClubImageResource/Jpg.php: -------------------------------------------------------------------------------- 1 | imageUrl = $imageUrl; 25 | 26 | if ($instance->imageUrl === null) { 27 | return $instance; 28 | } 29 | 30 | return $instance; 31 | } 32 | 33 | /** 34 | * @return string|null 35 | */ 36 | public function getImageUrl(): ?string 37 | { 38 | return $this->imageUrl; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/Model/Resource/CommonImageResource/CommonImageResource.php: -------------------------------------------------------------------------------- 1 | jpg = Jpg::factory($imageUrl); 30 | $instance->webp = Webp::factory($imageUrl); 31 | 32 | return $instance; 33 | } 34 | 35 | /** 36 | * @return string 37 | */ 38 | public function __toString() : string 39 | { 40 | return $this->getJpg()->getImageUrl(); 41 | } 42 | 43 | /** 44 | * @return Jpg 45 | */ 46 | public function getJpg(): Jpg 47 | { 48 | return $this->jpg; 49 | } 50 | 51 | /** 52 | * @return Webp 53 | */ 54 | public function getWebp(): Webp 55 | { 56 | return $this->webp; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/Model/Resource/CommonImageResource/Jpg.php: -------------------------------------------------------------------------------- 1 | imageUrl = $imageUrl; 36 | 37 | if ($instance->imageUrl === null) { 38 | return $instance; 39 | } 40 | 41 | $instance->smallImageUrl = str_replace('.jpg', 't.jpg', $imageUrl); 42 | $instance->largeImageUrl = str_replace('.jpg', 'l.jpg', $imageUrl); 43 | 44 | return $instance; 45 | } 46 | 47 | /** 48 | * @return string|null 49 | */ 50 | public function getImageUrl(): ?string 51 | { 52 | return $this->imageUrl; 53 | } 54 | 55 | /** 56 | * @return string|null 57 | */ 58 | public function getSmallImageUrl(): ?string 59 | { 60 | return $this->smallImageUrl; 61 | } 62 | 63 | /** 64 | * @return string|null 65 | */ 66 | public function getLargeImageUrl(): ?string 67 | { 68 | return $this->largeImageUrl; 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/Model/Resource/CommonImageResource/Webp.php: -------------------------------------------------------------------------------- 1 | imageUrl = str_replace('.jpg', '.webp', $imageUrl); 36 | 37 | if ($instance->imageUrl === null) { 38 | return $instance; 39 | } 40 | 41 | $instance->smallImageUrl = str_replace('.jpg', 't.webp', $imageUrl); 42 | $instance->largeImageUrl = str_replace('.jpg', 'l.webp', $imageUrl); 43 | 44 | return $instance; 45 | } 46 | 47 | /** 48 | * @return string|null 49 | */ 50 | public function getImageUrl(): ?string 51 | { 52 | return $this->imageUrl; 53 | } 54 | 55 | /** 56 | * @return string|null 57 | */ 58 | public function getSmallImageUrl(): ?string 59 | { 60 | return $this->smallImageUrl; 61 | } 62 | 63 | /** 64 | * @return string|null 65 | */ 66 | public function getLargeImageUrl(): ?string 67 | { 68 | return $this->largeImageUrl; 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/Model/Resource/PersonImageResource/Jpg.php: -------------------------------------------------------------------------------- 1 | imageUrl = $imageUrl; 25 | 26 | if ($instance->imageUrl === null) { 27 | return $instance; 28 | } 29 | 30 | return $instance; 31 | } 32 | 33 | /** 34 | * @return string 35 | */ 36 | public function __toString() : string 37 | { 38 | return $this->getJpg()->getImageUrl(); 39 | } 40 | 41 | /** 42 | * @return string|null 43 | */ 44 | public function getImageUrl(): ?string 45 | { 46 | return $this->imageUrl; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/Model/Resource/PersonImageResource/PersonImageResource.php: -------------------------------------------------------------------------------- 1 | jpg = Jpg::factory($imageUrl); 26 | 27 | return $instance; 28 | } 29 | 30 | /** 31 | * @return Jpg 32 | */ 33 | public function getJpg(): Jpg 34 | { 35 | return $this->jpg; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/Model/Resource/UserImageResource/Jpg.php: -------------------------------------------------------------------------------- 1 | imageUrl = $imageUrl; 25 | 26 | return $instance; 27 | } 28 | 29 | /** 30 | * @return string 31 | */ 32 | public function __toString() : string 33 | { 34 | return $this->getJpg()->getImageUrl(); 35 | } 36 | 37 | /** 38 | * @return string|null 39 | */ 40 | public function getImageUrl(): ?string 41 | { 42 | return $this->imageUrl; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/Model/Resource/UserImageResource/UserImageResource.php: -------------------------------------------------------------------------------- 1 | jpg = Jpg::factory($imageUrl); 30 | $instance->webp = Webp::factory($imageUrl); 31 | 32 | return $instance; 33 | } 34 | 35 | /** 36 | * @return Jpg 37 | */ 38 | public function getJpg(): Jpg 39 | { 40 | return $this->jpg; 41 | } 42 | 43 | /** 44 | * @return Webp 45 | */ 46 | public function getWebp(): Webp 47 | { 48 | return $this->webp; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/Model/Resource/UserImageResource/Webp.php: -------------------------------------------------------------------------------- 1 | imageUrl = str_replace('.jpg', '.webp', $imageUrl); 25 | 26 | return $instance; 27 | } 28 | 29 | /** 30 | * @return string|null 31 | */ 32 | public function getImageUrl(): ?string 33 | { 34 | return $this->imageUrl; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/Model/Resource/WrapImageResource/Jpg.php: -------------------------------------------------------------------------------- 1 | imageUrl = $imageUrl; 25 | 26 | return $instance; 27 | } 28 | 29 | /** 30 | * @return string|null 31 | */ 32 | public function getImageUrl(): ?string 33 | { 34 | return $this->imageUrl; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/Model/Resource/WrapImageResource/WrapImageResource.php: -------------------------------------------------------------------------------- 1 | jpg = Jpg::factory($imageUrl); 25 | 26 | return $instance; 27 | } 28 | 29 | /** 30 | * @return string 31 | */ 32 | public function __toString() : string 33 | { 34 | return $this->getJpg()->getImageUrl(); 35 | } 36 | 37 | /** 38 | * @return Jpg 39 | */ 40 | public function getJpg(): Jpg 41 | { 42 | return $this->jpg; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/Model/Reviews/AnimeReview.php: -------------------------------------------------------------------------------- 1 | episodesWatched; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/Model/Reviews/MangaReview.php: -------------------------------------------------------------------------------- 1 | chaptersRead; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/Model/Reviews/Reviewer.php: -------------------------------------------------------------------------------- 1 | url = $parser->getUrl(); 27 | $instance->images = UserImageResource::factory($parser->getImageUrl()); 28 | $instance->username = $parser->getUsername(); 29 | 30 | return $instance; 31 | } 32 | 33 | /** 34 | * @return UserImageResource 35 | */ 36 | public function getImages(): UserImageResource 37 | { 38 | return $this->images; 39 | } 40 | 41 | /** 42 | * @return string 43 | */ 44 | public function getUrl(): string 45 | { 46 | return $this->url; 47 | } 48 | 49 | /** 50 | * @return string 51 | */ 52 | public function getUsername(): string 53 | { 54 | return $this->username; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/Model/Search/Search.php: -------------------------------------------------------------------------------- 1 | results = $parser->getResults(); 22 | 23 | return $instance; 24 | } 25 | 26 | /** 27 | * @return array 28 | */ 29 | public function getResults(): array 30 | { 31 | return $this->results; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/Model/SeasonList/SeasonListItem.php: -------------------------------------------------------------------------------- 1 | year = $parser->getYear(); 34 | $instance->seasons = $parser->getSeasons(); 35 | 36 | return $instance; 37 | } 38 | 39 | /** 40 | * @return int 41 | */ 42 | public function getYear(): int 43 | { 44 | return $this->year; 45 | } 46 | 47 | /** 48 | * @return string[] 49 | */ 50 | public function getSeasons(): array 51 | { 52 | return $this->seasons; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/Model/Seasonal/Seasonal.php: -------------------------------------------------------------------------------- 1 | seasonName = $parser->getSeasonName(); 40 | $instance->seasonYear = $parser->getSeasonYear(); 41 | $instance->anime = $parser->getSeasonalAnime(); 42 | 43 | return $instance; 44 | } 45 | 46 | /** 47 | * @return string|null 48 | */ 49 | public function getSeasonName(): ?string 50 | { 51 | return $this->seasonName; 52 | } 53 | 54 | /** 55 | * @return int|null 56 | */ 57 | public function getSeasonYear(): ?int 58 | { 59 | return $this->seasonYear; 60 | } 61 | 62 | /** 63 | * @return array|SeasonalAnime[] 64 | */ 65 | public function getAnime() 66 | { 67 | return $this->anime; 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/Model/Seasonal/SeasonalAnime.php: -------------------------------------------------------------------------------- 1 | continuing = $parser->isContinuing(); 32 | 33 | return $instance; 34 | } 35 | 36 | /** 37 | * @return bool 38 | */ 39 | public function isContinuing(): bool 40 | { 41 | return $this->continuing; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/Model/User/FavoriteAnime.php: -------------------------------------------------------------------------------- 1 | entry = new FavoriteCharacterRelatedEntry($malUrl); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/Model/User/FavoriteCharacterRelatedEntry.php: -------------------------------------------------------------------------------- 1 | malId = $malUrl->getMalId(); 44 | $this->title = $malUrl->getTitle(); 45 | $this->type = $malUrl->getType(); 46 | $this->url = $malUrl->getUrl(); 47 | } 48 | 49 | /** 50 | * @return int 51 | */ 52 | public function getMalId(): int 53 | { 54 | return $this->malId; 55 | } 56 | 57 | /** 58 | * @return string 59 | */ 60 | public function getTitle(): string 61 | { 62 | return $this->title; 63 | } 64 | 65 | /** 66 | * @return string 67 | */ 68 | public function getType(): string 69 | { 70 | return $this->type; 71 | } 72 | 73 | /** 74 | * @return string 75 | */ 76 | public function getUrl(): string 77 | { 78 | return $this->url; 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/Model/User/FavoriteListEntry.php: -------------------------------------------------------------------------------- 1 | type = trim($typeAndYearArr[0]); 37 | $this->startYear = (int) trim($typeAndYearArr[1]); 38 | } 39 | 40 | /** 41 | * @return string 42 | */ 43 | public function getEntityType(): string 44 | { 45 | return $this->type; 46 | } 47 | 48 | /** 49 | * @return int 50 | */ 51 | public function getStartYear(): int 52 | { 53 | return $this->startYear; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/Model/User/FavoriteManga.php: -------------------------------------------------------------------------------- 1 | user = $parser->getUserMeta(); 41 | $instance->friendsSince = $parser->getFriendsSince(); 42 | $instance->lastOnline = $parser->getLastOnline(); 43 | 44 | return $instance; 45 | } 46 | 47 | /** 48 | * @return UserMeta 49 | */ 50 | public function getUser(): UserMeta 51 | { 52 | return $this->user; 53 | } 54 | 55 | /** 56 | * @return \DateTimeImmutable 57 | */ 58 | public function getLastOnline(): \DateTimeImmutable 59 | { 60 | return $this->lastOnline; 61 | } 62 | 63 | /** 64 | * @return \DateTimeImmutable 65 | */ 66 | public function getFriendsSince(): \DateTimeImmutable 67 | { 68 | return $this->friendsSince; 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/Model/User/Friends.php: -------------------------------------------------------------------------------- 1 | results = $parser->getResults(); 36 | $instance->hasNextPage = $parser->getHasNextPage(); 37 | $instance->lastVisiblePage = $parser->getLastPage(); 38 | 39 | return $instance; 40 | } 41 | 42 | /** 43 | * @return static 44 | */ 45 | public static function mock() : self 46 | { 47 | return new self(); 48 | } 49 | 50 | /** 51 | * @return bool 52 | */ 53 | public function hasNextPage(): bool 54 | { 55 | return $this->hasNextPage; 56 | } 57 | 58 | /** 59 | * @return int 60 | */ 61 | public function getLastVisiblePage(): int 62 | { 63 | return $this->lastVisiblePage; 64 | } 65 | 66 | /** 67 | * @return array 68 | */ 69 | public function getResults(): array 70 | { 71 | return $this->results; 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/Model/User/History.php: -------------------------------------------------------------------------------- 1 | malUrl = $parser->getUrl(); 42 | $instance->increment = $parser->getIncrement(); 43 | $instance->date = $parser->getDate(); 44 | 45 | return $instance; 46 | } 47 | 48 | 49 | /** 50 | * @return MalUrl 51 | */ 52 | public function getMalUrl(): MalUrl 53 | { 54 | return $this->malUrl; 55 | } 56 | 57 | /** 58 | * @return int 59 | */ 60 | public function getIncrement(): int 61 | { 62 | return $this->increment; 63 | } 64 | 65 | /** 66 | * @return \DateTimeImmutable 67 | */ 68 | public function getDate(): \DateTimeImmutable 69 | { 70 | return $this->date; 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/Model/User/LastUpdates.php: -------------------------------------------------------------------------------- 1 | anime = $parser->getLastAnimeUpdates(); 23 | $instance->manga = $parser->getLastMangaUpdates(); 24 | return $instance; 25 | } 26 | 27 | /** 28 | * @return array 29 | */ 30 | public function getAnime(): array 31 | { 32 | return $this->anime; 33 | } 34 | 35 | /** 36 | * @return array 37 | */ 38 | public function getManga(): array 39 | { 40 | return $this->manga; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/Model/User/Reviews/UserMangaReview.php: -------------------------------------------------------------------------------- 1 | entry = $parser->getManga('user'); 32 | $instance->malId = $parser->getId(); 33 | $instance->url = $parser->getUrl(); 34 | $instance->type = $parser->getType(); 35 | $instance->reactions = $parser->getReactions(); 36 | $instance->date = $parser->getDate(); 37 | $instance->score = $parser->getReviewerScore(); 38 | $instance->review = $parser->getContent(); 39 | $instance->tags = $parser->getReviewTag(); 40 | $instance->isPreliminary = $parser->isPreliminary(); 41 | $instance->chaptersRead = $parser->getChaptersRead(); 42 | $instance->isSpoiler = $parser->isSpoiler(); 43 | 44 | return $instance; 45 | } 46 | 47 | /** 48 | * @return MangaMeta 49 | */ 50 | public function getEntry(): MangaMeta 51 | { 52 | return $this->entry; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/Model/Watch/EpisodeListItem.php: -------------------------------------------------------------------------------- 1 | entry = $parser->getAnimeMeta(); 41 | $instance->episodes = $parser->getEpisodes(); 42 | $instance->regionLocked = $parser->getRegionLocked(); 43 | 44 | return $instance; 45 | } 46 | 47 | /** 48 | * @return AnimeMeta 49 | */ 50 | public function getEntry(): AnimeMeta 51 | { 52 | return $this->entry; 53 | } 54 | 55 | /** 56 | * @return RecentEpisodeListItem 57 | */ 58 | public function getEpisodes(): RecentEpisodeListItem 59 | { 60 | return $this->episodes; 61 | } 62 | 63 | /** 64 | * @return bool 65 | */ 66 | public function isRegionLocked(): bool 67 | { 68 | return $this->regionLocked; 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/Model/Watch/Episodes.php: -------------------------------------------------------------------------------- 1 | results = $parser->getResults(); 36 | 37 | return $instance; 38 | } 39 | 40 | /** 41 | * @return bool 42 | */ 43 | public function hasNextPage(): bool 44 | { 45 | return $this->hasNextPage; 46 | } 47 | 48 | /** 49 | * @return int 50 | */ 51 | public function getLastVisiblePage(): int 52 | { 53 | return $this->lastVisiblePage; 54 | } 55 | 56 | /** 57 | * @return array 58 | */ 59 | public function getResults(): array 60 | { 61 | return $this->results; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/Model/Watch/PromotionalVideos.php: -------------------------------------------------------------------------------- 1 | results = $parser->getResults(); 36 | $instance->hasNextPage = $parser->getHasNextPage(); 37 | $instance->lastVisiblePage = $parser->getLastVisiblePage(); 38 | 39 | return $instance; 40 | } 41 | 42 | /** 43 | * @return bool 44 | */ 45 | public function hasNextPage(): bool 46 | { 47 | return $this->hasNextPage; 48 | } 49 | 50 | /** 51 | * @return int|null 52 | */ 53 | public function getLastVisiblePage(): ?int 54 | { 55 | return $this->lastVisiblePage; 56 | } 57 | 58 | /** 59 | * @return array 60 | */ 61 | public function getResults(): array 62 | { 63 | return $this->results; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/Parser/Anime/MoreInfoParser.php: -------------------------------------------------------------------------------- 1 | crawler = $crawler; 31 | } 32 | 33 | /** 34 | * Return the model 35 | * 36 | * @throws \RuntimeException 37 | * @throws \InvalidArgumentException 38 | */ 39 | public function getModel(): AnimeMoreInfo 40 | { 41 | return AnimeMoreInfo::fromParser($this); 42 | } 43 | 44 | /** 45 | * @return string 46 | * @throws \InvalidArgumentException 47 | */ 48 | public function getMoreInfo(): ?string 49 | { 50 | $moreinfo = JString::cleanse( 51 | Parser::removeChildNodes( 52 | $this->crawler->filterXPath('//div[contains(@class, "rightside")]') 53 | )->text() 54 | ); 55 | 56 | if (empty($moreinfo)) { 57 | return null; 58 | } 59 | 60 | return $moreinfo; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/Parser/Anime/PromoListItemParser.php: -------------------------------------------------------------------------------- 1 | crawler = $crawler; 29 | } 30 | 31 | /** 32 | * @return \Jikan\Model\Anime\PromoListItem 33 | * @throws \InvalidArgumentException 34 | */ 35 | public function getModel(): PromoListItem 36 | { 37 | return PromoListItem::fromParser($this); 38 | } 39 | 40 | 41 | /** 42 | * @return string 43 | * @throws \InvalidArgumentException 44 | */ 45 | public function getTitle(): string 46 | { 47 | return $this->crawler->filterXPath('//a/div/span')->text(); 48 | } 49 | 50 | /** 51 | * @return string 52 | * @throws \InvalidArgumentException 53 | */ 54 | public function getImageUrl(): string 55 | { 56 | return $this->crawler->filterXPath('//a/img')->attr('data-src'); 57 | } 58 | 59 | /** 60 | * @return string 61 | * @throws \InvalidArgumentException 62 | */ 63 | public function getVideoUrl(): string 64 | { 65 | return $this->crawler->filterXPath('//a')->attr('href'); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/Parser/Character/AnimeographyParser.php: -------------------------------------------------------------------------------- 1 | crawler = $crawler; 29 | parent::__construct($this->crawler); 30 | } 31 | 32 | /** 33 | * Return the model 34 | * 35 | * @return \Jikan\Model\Character\Animeography 36 | * @throws \InvalidArgumentException 37 | */ 38 | public function getModel(): Model\Character\Animeography 39 | { 40 | return Model\Character\Animeography::fromParser($this); 41 | } 42 | 43 | /** 44 | * @return \Jikan\Model\Common\AnimeMeta 45 | * @throws \InvalidArgumentException 46 | */ 47 | public function getAnimeMeta(): Model\Common\AnimeMeta 48 | { 49 | return new Model\Common\AnimeMeta( 50 | $this->getName(), 51 | $this->getUrl(), 52 | $this->getImage() 53 | ); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/Parser/Character/MangaographyParser.php: -------------------------------------------------------------------------------- 1 | crawler = $crawler; 29 | parent::__construct($this->crawler); 30 | } 31 | 32 | /** 33 | * Return the model 34 | * 35 | * @return \Jikan\Model\Character\Mangaography 36 | * @throws \InvalidArgumentException 37 | */ 38 | public function getModel(): Model\Character\Mangaography 39 | { 40 | return Model\Character\Mangaography::fromParser($this); 41 | } 42 | 43 | /** 44 | * @return \Jikan\Model\Common\MangaMeta 45 | * @throws \InvalidArgumentException 46 | */ 47 | public function getMangaMeta(): Model\Common\MangaMeta 48 | { 49 | return new Model\Common\MangaMeta( 50 | $this->getName(), 51 | $this->getUrl(), 52 | $this->getImage() 53 | ); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/Parser/Common/AlternativeTitleParser.php: -------------------------------------------------------------------------------- 1 | crawler = $crawler; 30 | } 31 | 32 | /** 33 | * @return \Jikan\Model\Common\Title[] 34 | * @throws \Exception 35 | */ 36 | public function getModel(): array 37 | { 38 | [$type, $title] = explode(':', $this->crawler->text(), 2); 39 | 40 | if ($type !== 'Synonyms') { 41 | return [new Title($type, JString::cleanse($title))]; 42 | } 43 | 44 | $titles = explode(', ', $title); 45 | 46 | foreach ($titles as &$title) { 47 | $title = new Title(Title::TYPE_SYNONYM, JString::cleanse($title)); 48 | } 49 | 50 | return $titles; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/Parser/Common/DefaultPicturesPageParser.php: -------------------------------------------------------------------------------- 1 | crawler = $crawler; 34 | } 35 | 36 | /** 37 | * @return \Jikan\Model\Common\DefaultPicture[] 38 | * @throws \InvalidArgumentException 39 | */ 40 | public function getModel(): array 41 | { 42 | return $this->crawler 43 | ->filterXPath('//a[@class="js-picture-gallery"]') 44 | ->each( 45 | function (Crawler $crawler) { 46 | return PersonImageResource::factory( 47 | DefaultPicture::fromParser(new PictureParser($crawler)) 48 | ->getImageUrl() 49 | ); 50 | } 51 | ); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/Parser/Common/ItemMetaParser.php: -------------------------------------------------------------------------------- 1 | crawler = $crawler; 28 | } 29 | 30 | /** 31 | * @return int|null 32 | * @throws \InvalidArgumentException 33 | */ 34 | public function getMalId(): ?int 35 | { 36 | return (int)preg_replace('#https://myanimelist.net/\w+/(\d+).*#', '$1', $this->getUrl()); 37 | } 38 | 39 | /** 40 | * @return string|null 41 | * @throws \InvalidArgumentException 42 | */ 43 | public function getUrl(): ?string 44 | { 45 | return $this->crawler->filterXPath('//a')->attr('href'); 46 | } 47 | 48 | /** 49 | * @return string|null 50 | * @throws \InvalidArgumentException 51 | */ 52 | public function getName(): ?string 53 | { 54 | return $this->crawler->filterXPath('//a')->text(); 55 | } 56 | 57 | /** 58 | * @return string|null 59 | * @throws \InvalidArgumentException 60 | */ 61 | public function getImage(): ?string 62 | { 63 | return Parser::parseImageQuality( 64 | $this->crawler->filterXPath('//img')->attr('data-src') 65 | ); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/Parser/Common/MalUrlParser.php: -------------------------------------------------------------------------------- 1 | crawler = $crawler; 29 | } 30 | 31 | /** 32 | * @param string $url 33 | * 34 | * @return int 35 | */ 36 | public static function parseId(string $url): int 37 | { 38 | if (!preg_match_all('#/(\d+)#', $url, $matches)) { 39 | return 0; 40 | // throw new \RuntimeException(sprintf('Unable to parse id from mal url: %s', $url ?? 'null')); 41 | } 42 | 43 | return (int) $matches[1][0]; 44 | } 45 | 46 | /** 47 | * @return MalUrl 48 | * @throws \InvalidArgumentException 49 | */ 50 | public function getModel(): MalUrl 51 | { 52 | $href = $this->crawler->attr('href'); 53 | $href = str_replace('https://myanimelist.net', '', $href); 54 | 55 | return new MalUrl( 56 | JString::cleanse($this->crawler->text()), 57 | 'https://myanimelist.net'.$href 58 | ); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/Parser/Common/PictureParser.php: -------------------------------------------------------------------------------- 1 | crawler = $crawler; 29 | } 30 | 31 | /** 32 | * @return string 33 | * @throws \InvalidArgumentException 34 | */ 35 | public function getLarge(): string 36 | { 37 | return $this->crawler->filterXPath('//a')->attr('href'); 38 | } 39 | 40 | /** 41 | * @return string 42 | * @throws \InvalidArgumentException 43 | */ 44 | public function getSmall(): string 45 | { 46 | return $this->crawler->filterXPath('//img')->attr('data-src'); 47 | } 48 | 49 | /** 50 | * @return Picture 51 | * @throws \InvalidArgumentException 52 | */ 53 | public function getModel(): Picture 54 | { 55 | return Picture::fromParser($this); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/Parser/Common/PicturesPageParser.php: -------------------------------------------------------------------------------- 1 | crawler = $crawler; 31 | } 32 | 33 | /** 34 | * @return \Jikan\Model\Common\Picture[] 35 | * @throws \InvalidArgumentException 36 | */ 37 | public function getModel(): array 38 | { 39 | return $this->crawler 40 | ->filterXPath('//a[@class="js-picture-gallery"]') 41 | ->each( 42 | function (Crawler $crawler) { 43 | return CommonImageResource::factory( 44 | Picture::fromParser(new PictureParser($crawler)) 45 | ->getImageUrl() 46 | ); 47 | } 48 | ); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/Parser/Common/Recommendations.php: -------------------------------------------------------------------------------- 1 | crawler = $crawler; 28 | } 29 | 30 | /** 31 | * @return array 32 | * @throws \InvalidArgumentException 33 | */ 34 | public function getModel(): array 35 | { 36 | return $this->crawler 37 | ->filterXPath('//div[@class="borderClass"]') 38 | ->each( 39 | function ($c) { 40 | return (new Recommendation($c))->getModel(); 41 | } 42 | ); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/Parser/Common/UrlParser.php: -------------------------------------------------------------------------------- 1 | crawler = $crawler; 29 | } 30 | 31 | /** 32 | * @return Url 33 | * @throws \InvalidArgumentException 34 | */ 35 | public function getModel(): Url 36 | { 37 | return new Url( 38 | JString::cleanse($this->crawler->text()), 39 | JString::cleanse($this->crawler->attr('href')) 40 | ); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/Parser/Forum/ForumPageParser.php: -------------------------------------------------------------------------------- 1 | crawler = $crawler; 28 | } 29 | 30 | /** 31 | * @return ForumTopic[] 32 | * @throws \InvalidArgumentException 33 | */ 34 | public function getTopics(): array 35 | { 36 | return $this->crawler 37 | ->filterXPath('//tr[contains(@id, "topicRow")]') 38 | ->each( 39 | function (Crawler $crawler) { 40 | return ForumTopic::fromParser(new ForumTopicParser($crawler)); 41 | } 42 | ); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/Parser/Magazine/MagazineListParser.php: -------------------------------------------------------------------------------- 1 | crawler = $crawler; 29 | } 30 | 31 | /** 32 | * @return \Jikan\Model\Magazine\Magazine 33 | * @throws \RuntimeException 34 | * @throws \InvalidArgumentException 35 | */ 36 | public function getModel(): Model\Magazine\MagazineList 37 | { 38 | return Model\Magazine\MagazineList::fromParser($this); 39 | } 40 | 41 | /** 42 | * @return array|\Jikan\Model\Magazine\MagazineAnime[] 43 | * @throws \InvalidArgumentException 44 | * @throws \RuntimeException 45 | */ 46 | public function getMagazines(): array 47 | { 48 | return $this->crawler 49 | ->filter('a.genre-name-link') 50 | ->each( 51 | function (Crawler $crawler) { 52 | return (new MagazineListItemParser($crawler))->getModel(); 53 | } 54 | ); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/Parser/Manga/CharactersParser.php: -------------------------------------------------------------------------------- 1 | crawler = $crawler; 29 | } 30 | 31 | /** 32 | * @return CharacterListItem[] 33 | * @throws \InvalidArgumentException 34 | */ 35 | public function getCharacters(): array 36 | { 37 | return $this->crawler 38 | ->filterXPath('//div[contains(@class, "manga-character-container")]/table') 39 | ->each( 40 | function (Crawler $crawler) { 41 | return CharacterListItem::fromParser(new CharacterListItemParser($crawler)); 42 | } 43 | ); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/Parser/Manga/MangaReviewerParser.php: -------------------------------------------------------------------------------- 1 | crawler = $crawler; 31 | } 32 | 33 | /** 34 | * Return the model 35 | * 36 | * @throws \RuntimeException 37 | * @throws \InvalidArgumentException 38 | */ 39 | public function getModel(): MangaMoreInfo 40 | { 41 | return MangaMoreInfo::fromParser($this); 42 | } 43 | 44 | /** 45 | * @return string|null 46 | * @throws \InvalidArgumentException 47 | */ 48 | public function getMoreInfo(): ?string 49 | { 50 | $moreinfo = JString::cleanse( 51 | Parser::removeChildNodes( 52 | $this->crawler->filterXPath('//div[contains(@class, "rightside")]') 53 | )->text() 54 | ); 55 | 56 | if (empty($moreinfo)) { 57 | return null; 58 | } 59 | 60 | return $moreinfo; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/Parser/ParserInterface.php: -------------------------------------------------------------------------------- 1 | crawler = $crawler; 32 | } 33 | 34 | /** 35 | * @return \Jikan\Model\Producer\Producer 36 | * @throws \RuntimeException 37 | * @throws \InvalidArgumentException 38 | */ 39 | public function getModel(): Model\Producer\ProducerList 40 | { 41 | return Model\Producer\ProducerList::fromParser($this); 42 | } 43 | 44 | /** 45 | * @return array|\Jikan\Model\Producer\ProducerAnime[] 46 | * @throws \InvalidArgumentException 47 | * @throws \RuntimeException 48 | */ 49 | public function getProducers(): array 50 | { 51 | return $this->crawler 52 | ->filter('a.genre-name-link') 53 | ->each( 54 | function (Crawler $crawler) { 55 | return (new ProducerListItemParser($crawler))->getModel(); 56 | } 57 | ); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/Parser/SeasonList/SeasonListParser.php: -------------------------------------------------------------------------------- 1 | crawler = $crawler; 31 | } 32 | 33 | /** 34 | * @return SeasonArchive 35 | */ 36 | public function getModel() : SeasonArchive 37 | { 38 | return SeasonArchive::fromParser($this); 39 | } 40 | 41 | /** 42 | * @return SeasonListItem[] 43 | * @throws \RuntimeException 44 | * @throws \InvalidArgumentException 45 | */ 46 | public function getResults(): array 47 | { 48 | return $this->crawler 49 | ->filterXPath('//table[contains(@class, "anime-seasonal-byseason")]//tr') 50 | ->each( 51 | function (Crawler $crawler) { 52 | return (new SeasonListItemParser($crawler))->getModel(); 53 | } 54 | ); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/Parser/User/ClubParser.php: -------------------------------------------------------------------------------- 1 | crawler = $crawler; 30 | } 31 | 32 | /** 33 | * @return array 34 | * @throws \InvalidArgumentException 35 | */ 36 | public function getClubs(): array 37 | { 38 | $node = $this->crawler 39 | ->filterXPath('//*[@id="content"]/table/tr/td[2]/ol/li'); 40 | 41 | return $node->each(function (Crawler $crawler) { 42 | return Model\Common\ClubMeta::factory( 43 | Parser::clubIdFromUrl( 44 | $crawler->filterXPath('//a')->attr('href') 45 | ), 46 | $crawler->filterXPath('//a')->text(), 47 | Constants::BASE_URL . $crawler->filterXPath('//a')->attr('href') 48 | ); 49 | }); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/Parser/User/History/HistoryParser.php: -------------------------------------------------------------------------------- 1 | crawler = $crawler; 29 | } 30 | 31 | /** 32 | * @return History[] 33 | * @throws \Exception 34 | * @throws \InvalidArgumentException 35 | */ 36 | public function getModel(): array 37 | { 38 | $node = $this->crawler->filterXPath('//div[@id="content"]/div/table/tr'); 39 | 40 | return $node 41 | ->reduce( 42 | function (Crawler $c) { 43 | return (bool)$c->filterXPath('//td[contains(@class, "borderClass")]')->count(); 44 | } 45 | ) 46 | ->each( 47 | function (Crawler $c) { 48 | return (new HistoryItemParser($c))->getModel(); 49 | } 50 | ); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/Parser/User/UsernameByIdParser.php: -------------------------------------------------------------------------------- 1 | crawler = $crawler; 32 | } 33 | 34 | public function getUser() : Model\Common\UserMetaBasic 35 | { 36 | $node = $this->crawler->filterXPath("//*[@id=\"content\"]/div[1]/div[1]/a"); 37 | 38 | preg_match('~(.*?)\'s Profile~', $node->text(), $username); 39 | 40 | return Model\Common\UserMetaBasic::fromMeta( 41 | $username[1], 42 | Constants::BASE_URL . $node->attr('href') 43 | ); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/Parser/Watch/WatchEpisodesParser.php: -------------------------------------------------------------------------------- 1 | crawler = $crawler; 28 | } 29 | 30 | public function getModel(): Model\Watch\Episodes 31 | { 32 | return Model\Watch\Episodes::fromParser($this); 33 | } 34 | 35 | public function getResults() : array 36 | { 37 | $node = $this->crawler->filterXPath( 38 | '//*[@id="content"]/div[3]/div/div[contains(@class, "video-list-outer-vertical")] 39 | ' 40 | ); 41 | 42 | if (!$node->count()) { 43 | return []; 44 | } 45 | 46 | return $node->each(function (Crawler $crawler) { 47 | return Model\Watch\EpisodeListItem::fromParser(new EpisodeListItemParser($crawler)); 48 | }); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/Request/Anime/AnimeCharactersAndStaffRequest.php: -------------------------------------------------------------------------------- 1 | id = $id; 27 | } 28 | 29 | /** 30 | * @return string 31 | */ 32 | public function getPath(): string 33 | { 34 | return sprintf('https://myanimelist.net/anime/%s/_/characters', $this->id); 35 | } 36 | 37 | /** 38 | * @return int 39 | */ 40 | public function getId(): int 41 | { 42 | return $this->id; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/Request/Anime/AnimeEpisodeRequest.php: -------------------------------------------------------------------------------- 1 | id = $id; 33 | $this->episodeId = $episodeId; 34 | } 35 | 36 | /** 37 | * @return string 38 | */ 39 | public function getPath(): string 40 | { 41 | return sprintf('https://myanimelist.net/anime/%s/_/episode/%s', $this->id, $this->episodeId); 42 | } 43 | 44 | /** 45 | * @return int 46 | */ 47 | public function getId(): int 48 | { 49 | return $this->id; 50 | } 51 | 52 | /** 53 | * @return int 54 | */ 55 | public function getEpisodeId(): int 56 | { 57 | return $this->episodeId; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/Request/Anime/AnimeEpisodesRequest.php: -------------------------------------------------------------------------------- 1 | id = $id; 33 | $this->page = ($page - 1) * 100; 34 | } 35 | 36 | /** 37 | * @return string 38 | */ 39 | public function getPath(): string 40 | { 41 | return sprintf('https://myanimelist.net/anime/%s/_/episode?offset=%s', $this->id, $this->page); 42 | } 43 | 44 | /** 45 | * @return int 46 | */ 47 | public function getId(): int 48 | { 49 | return $this->id; 50 | } 51 | 52 | /** 53 | * @return int 54 | */ 55 | public function getPage() 56 | { 57 | return $this->page; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/Request/Anime/AnimeMoreInfoRequest.php: -------------------------------------------------------------------------------- 1 | id = $id; 27 | } 28 | 29 | /** 30 | * return string 31 | */ 32 | public function getPath(): string 33 | { 34 | return sprintf('https://myanimelist.net/anime/%d/_/moreinfo', $this->id); 35 | } 36 | 37 | /** 38 | * @return int 39 | */ 40 | public function getId(): int 41 | { 42 | return $this->id; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/Request/Anime/AnimeNewsRequest.php: -------------------------------------------------------------------------------- 1 | id = $id; 32 | $this->page = $page; 33 | } 34 | 35 | /** 36 | * @return string 37 | */ 38 | public function getPath(): string 39 | { 40 | return sprintf('https://myanimelist.net/anime/%d/_/news?p=%d', $this->id, $this->page); 41 | } 42 | 43 | /** 44 | * @return int 45 | */ 46 | public function getId(): int 47 | { 48 | return $this->id; 49 | } 50 | 51 | /** 52 | * @return int 53 | */ 54 | public function getPage(): ?int 55 | { 56 | return $this->page; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/Request/Anime/AnimePicturesRequest.php: -------------------------------------------------------------------------------- 1 | id = $id; 27 | } 28 | 29 | /** 30 | * @return string 31 | */ 32 | public function getPath(): string 33 | { 34 | // MyAnimeList wants after //... it happily accepts jikan as a valid parameter though 35 | return sprintf('https://myanimelist.net/anime/%d/jikan/pics', $this->id); 36 | } 37 | 38 | /** 39 | * @return int 40 | */ 41 | public function getId(): int 42 | { 43 | return $this->id; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/Request/Anime/AnimeRecentlyUpdatedByUsersRequest.php: -------------------------------------------------------------------------------- 1 | id = $id; 33 | $this->page = ($page - 1) * 75; 34 | } 35 | 36 | /** 37 | * @return string 38 | */ 39 | public function getPath(): string 40 | { 41 | return sprintf('https://myanimelist.net/anime/%d/jikan/stats?show=%d', $this->id, $this->page); 42 | } 43 | 44 | /** 45 | * @return int 46 | */ 47 | public function getId(): int 48 | { 49 | return $this->id; 50 | } 51 | 52 | /** 53 | * @return int 54 | */ 55 | public function getPage() 56 | { 57 | return $this->page; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/Request/Anime/AnimeRecommendationsRequest.php: -------------------------------------------------------------------------------- 1 | id = $id; 27 | } 28 | 29 | /** 30 | * @return string 31 | */ 32 | public function getPath(): string 33 | { 34 | return sprintf('https://myanimelist.net/anime/%d/jikan/userrecs', $this->id); 35 | } 36 | 37 | /** 38 | * @return int 39 | */ 40 | public function getId(): int 41 | { 42 | return $this->id; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/Request/Anime/AnimeRequest.php: -------------------------------------------------------------------------------- 1 | id = $id; 27 | } 28 | 29 | /** 30 | * @return string 31 | */ 32 | public function getPath(): string 33 | { 34 | return sprintf('https://myanimelist.net/anime/%s/', $this->id); 35 | } 36 | 37 | /** 38 | * @return int 39 | */ 40 | public function getId(): int 41 | { 42 | return $this->id; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/Request/Anime/AnimeStatsRequest.php: -------------------------------------------------------------------------------- 1 | id = $id; 27 | } 28 | 29 | /** 30 | * @return string 31 | */ 32 | public function getPath(): string 33 | { 34 | // MyAnimeList wants after //... it happily accepts jikan as a valid parameter though 35 | return sprintf('https://myanimelist.net/anime/%d/jikan/stats', $this->id); 36 | } 37 | 38 | /** 39 | * @return int 40 | */ 41 | public function getId(): int 42 | { 43 | return $this->id; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/Request/Anime/AnimeVideosEpisodesRequest.php: -------------------------------------------------------------------------------- 1 | id = $id; 32 | $this->page = $page; 33 | } 34 | 35 | /** 36 | * @return string 37 | */ 38 | public function getPath(): string 39 | { 40 | return sprintf('https://myanimelist.net/anime/%d/_/video?p=%d', $this->id, $this->page); 41 | } 42 | 43 | /** 44 | * @return int 45 | */ 46 | public function getId(): int 47 | { 48 | return $this->id; 49 | } 50 | 51 | /** 52 | * @return int 53 | */ 54 | public function getPage(): int 55 | { 56 | return $this->page; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/Request/Anime/AnimeVideosRequest.php: -------------------------------------------------------------------------------- 1 | id = $id; 27 | } 28 | 29 | /** 30 | * @return string 31 | */ 32 | public function getPath(): string 33 | { 34 | return sprintf('https://myanimelist.net/anime/%d/_/video', $this->id); 35 | } 36 | 37 | /** 38 | * @return int 39 | */ 40 | public function getId(): int 41 | { 42 | return $this->id; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/Request/Character/CharacterPicturesRequest.php: -------------------------------------------------------------------------------- 1 | id = $id; 27 | } 28 | 29 | /** 30 | * @return string 31 | */ 32 | public function getPath(): string 33 | { 34 | // MyAnimeList wants after //... it happily accepts jikan as a valid parameter though 35 | return sprintf('https://myanimelist.net/character/%d/jikan/pics', $this->id); 36 | } 37 | 38 | /** 39 | * @return int 40 | */ 41 | public function getId(): int 42 | { 43 | return $this->id; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/Request/Character/CharacterRequest.php: -------------------------------------------------------------------------------- 1 | id = $id; 27 | } 28 | 29 | /** 30 | * Get the path to request 31 | * 32 | * @return string 33 | */ 34 | public function getPath(): string 35 | { 36 | return sprintf('https://myanimelist.net/character/%s', $this->id); 37 | } 38 | 39 | /** 40 | * @return int 41 | */ 42 | public function getId(): int 43 | { 44 | return $this->id; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/Request/Club/ClubRequest.php: -------------------------------------------------------------------------------- 1 | clubId = $clubId; 27 | } 28 | 29 | /** 30 | * Get the path to request 31 | * 32 | * @return string 33 | */ 34 | public function getPath(): string 35 | { 36 | return sprintf( 37 | 'https://myanimelist.net/clubs.php?cid=%s', 38 | $this->clubId 39 | ); 40 | } 41 | 42 | /** 43 | * @return int 44 | */ 45 | public function getClubId(): int 46 | { 47 | return $this->clubId; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/Request/Club/UserListRequest.php: -------------------------------------------------------------------------------- 1 | clubId = $clubId; 33 | $this->page = ($page - 1) * 36; 34 | } 35 | 36 | /** 37 | * Get the path to request 38 | * 39 | * @return string 40 | */ 41 | public function getPath(): string 42 | { 43 | return sprintf( 44 | 'https://myanimelist.net/clubs.php?action=view&t=members&id=%s&show=%s', 45 | $this->clubId, 46 | $this->page 47 | ); 48 | } 49 | 50 | /** 51 | * @return int 52 | */ 53 | public function getClubId(): int 54 | { 55 | return $this->clubId; 56 | } 57 | 58 | /** 59 | * @return int 60 | */ 61 | public function getPage() 62 | { 63 | return $this->page; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/Request/Genre/AnimeGenreRequest.php: -------------------------------------------------------------------------------- 1 | id = $id; 33 | $this->page = $page; 34 | } 35 | 36 | /** 37 | * @return string 38 | */ 39 | public function getPath(): string 40 | { 41 | return sprintf('https://myanimelist.net/anime/genre/%s?page=%s', $this->id, $this->page); 42 | } 43 | 44 | /** 45 | * @return int 46 | */ 47 | public function getId(): int 48 | { 49 | return $this->id; 50 | } 51 | 52 | /** 53 | * @return int 54 | */ 55 | public function getPage(): int 56 | { 57 | return $this->page; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/Request/Genre/AnimeGenresRequest.php: -------------------------------------------------------------------------------- 1 | id = $id; 33 | $this->page = $page; 34 | } 35 | 36 | /** 37 | * @return string 38 | */ 39 | public function getPath(): string 40 | { 41 | return sprintf('https://myanimelist.net/manga/genre/%s?page=%s', $this->id, $this->page); 42 | } 43 | 44 | /** 45 | * @return int 46 | */ 47 | public function getId(): int 48 | { 49 | return $this->id; 50 | } 51 | 52 | /** 53 | * @return int 54 | */ 55 | public function getPage(): int 56 | { 57 | return $this->page; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/Request/Genre/MangaGenresRequest.php: -------------------------------------------------------------------------------- 1 | id = $id; 33 | $this->page = $page; 34 | } 35 | 36 | /** 37 | * @return string 38 | */ 39 | public function getPath(): string 40 | { 41 | return sprintf('https://myanimelist.net/manga/magazine/%s?page=%s', $this->id, $this->page); 42 | } 43 | 44 | /** 45 | * @return int 46 | */ 47 | public function getId(): int 48 | { 49 | return $this->id; 50 | } 51 | 52 | /** 53 | * @return int 54 | */ 55 | public function getPage(): int 56 | { 57 | return $this->page; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/Request/Magazine/MagazinesRequest.php: -------------------------------------------------------------------------------- 1 | id = $id; 27 | } 28 | 29 | /** 30 | * @return string 31 | */ 32 | public function getPath(): string 33 | { 34 | return sprintf('https://myanimelist.net/manga/%s/_/characters', $this->id); 35 | } 36 | 37 | /** 38 | * @return int 39 | */ 40 | public function getId(): int 41 | { 42 | return $this->id; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/Request/Manga/MangaMoreInfoRequest.php: -------------------------------------------------------------------------------- 1 | id = $id; 27 | } 28 | 29 | /** 30 | * return string 31 | */ 32 | public function getPath(): string 33 | { 34 | return sprintf('https://myanimelist.net/manga/%d/_/moreinfo', $this->id); 35 | } 36 | 37 | /** 38 | * @return int 39 | */ 40 | public function getId(): int 41 | { 42 | return $this->id; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/Request/Manga/MangaNewsRequest.php: -------------------------------------------------------------------------------- 1 | id = $id; 32 | $this->page = $page; 33 | } 34 | 35 | /** 36 | * @return string 37 | */ 38 | public function getPath(): string 39 | { 40 | return sprintf('https://myanimelist.net/manga/%s/_/news?p=%d', $this->id, $this->page); 41 | } 42 | 43 | /** 44 | * @return int 45 | */ 46 | public function getId(): int 47 | { 48 | return $this->id; 49 | } 50 | 51 | /** 52 | * @return int 53 | */ 54 | public function getPage(): ?int 55 | { 56 | return $this->page; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/Request/Manga/MangaPicturesRequest.php: -------------------------------------------------------------------------------- 1 | id = $id; 27 | } 28 | 29 | /** 30 | * @return string 31 | */ 32 | public function getPath(): string 33 | { 34 | // MyAnimeList wants after //... it happily accepts jikan as a valid parameter though 35 | return sprintf('https://myanimelist.net/manga/%d/jikan/pics', $this->id); 36 | } 37 | 38 | /** 39 | * @return int 40 | */ 41 | public function getId(): int 42 | { 43 | return $this->id; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/Request/Manga/MangaRecentlyUpdatedByUsersRequest.php: -------------------------------------------------------------------------------- 1 | id = $id; 33 | $this->page = ($page - 1) * 75; 34 | } 35 | 36 | /** 37 | * @return string 38 | */ 39 | public function getPath(): string 40 | { 41 | return sprintf('https://myanimelist.net/manga/%d/jikan/stats?show=%d', $this->id, $this->page); 42 | } 43 | 44 | /** 45 | * @return int 46 | */ 47 | public function getId(): int 48 | { 49 | return $this->id; 50 | } 51 | 52 | /** 53 | * @return int 54 | */ 55 | public function getPage() 56 | { 57 | return $this->page; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/Request/Manga/MangaRecommendationsRequest.php: -------------------------------------------------------------------------------- 1 | id = $id; 27 | } 28 | 29 | /** 30 | * @return string 31 | */ 32 | public function getPath(): string 33 | { 34 | return sprintf('https://myanimelist.net/manga/%d/jikan/userrecs', $this->id); 35 | } 36 | 37 | /** 38 | * @return int 39 | */ 40 | public function getId(): int 41 | { 42 | return $this->id; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/Request/Manga/MangaRequest.php: -------------------------------------------------------------------------------- 1 | id = $id; 27 | } 28 | 29 | /** 30 | * @return string 31 | */ 32 | public function getPath(): string 33 | { 34 | return sprintf('https://myanimelist.net/manga/%s/', $this->id); 35 | } 36 | 37 | /** 38 | * @return int 39 | */ 40 | public function getId(): int 41 | { 42 | return $this->id; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/Request/Manga/MangaStatsRequest.php: -------------------------------------------------------------------------------- 1 | id = $id; 27 | } 28 | 29 | /** 30 | * @return string 31 | */ 32 | public function getPath(): string 33 | { 34 | // MyAnimeList wants after //... it happily accepts jikan as a valid parameter though 35 | return sprintf('https://myanimelist.net/manga/%d/jikan/stats', $this->id); 36 | } 37 | 38 | /** 39 | * @return int 40 | */ 41 | public function getId(): int 42 | { 43 | return $this->id; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/Request/Person/PersonPicturesRequest.php: -------------------------------------------------------------------------------- 1 | id = $id; 27 | } 28 | 29 | /** 30 | * @return string 31 | */ 32 | public function getPath(): string 33 | { 34 | // MyAnimeList wants after //... it happily accepts jikan as a valid parameter though 35 | return sprintf('https://myanimelist.net/people/%d/jikan/pics', $this->id); 36 | } 37 | 38 | /** 39 | * @return int 40 | */ 41 | public function getId(): int 42 | { 43 | return $this->id; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/Request/Person/PersonRequest.php: -------------------------------------------------------------------------------- 1 | id = $id; 27 | } 28 | 29 | /** 30 | * Get the path to request 31 | * 32 | * @return string 33 | */ 34 | public function getPath(): string 35 | { 36 | return sprintf('https://myanimelist.net/people/%s', $this->id); 37 | } 38 | 39 | /** 40 | * @return int 41 | */ 42 | public function getId(): int 43 | { 44 | return $this->id; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/Request/Producer/ProducerRequest.php: -------------------------------------------------------------------------------- 1 | id = $id; 33 | $this->page = $page; 34 | } 35 | 36 | /** 37 | * @return string 38 | */ 39 | public function getPath(): string 40 | { 41 | return sprintf('https://myanimelist.net/anime/producer/%s?page=%s', $this->id, $this->page); 42 | } 43 | 44 | /** 45 | * @return int 46 | */ 47 | public function getId(): int 48 | { 49 | return $this->id; 50 | } 51 | 52 | /** 53 | * @return int 54 | */ 55 | public function getPage(): int 56 | { 57 | return $this->page; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/Request/Producer/ProducersRequest.php: -------------------------------------------------------------------------------- 1 | page = $page; 27 | } 28 | 29 | /** 30 | * Get the path to request 31 | * 32 | * @return string 33 | */ 34 | public function getPath(): string 35 | { 36 | return 'https://myanimelist.net/character.php?'.http_build_query(['limit' => 50 * ($this->page-1)]); 37 | } 38 | 39 | /** 40 | * @return int 41 | */ 42 | public function getPage(): int 43 | { 44 | return $this->page; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/Request/Top/TopPeopleRequest.php: -------------------------------------------------------------------------------- 1 | page = $page; 27 | } 28 | 29 | /** 30 | * Get the path to request 31 | * 32 | * @return string 33 | */ 34 | public function getPath(): string 35 | { 36 | return 'https://myanimelist.net/people.php?'.http_build_query(['limit' => 50 * ($this->page-1)]); 37 | } 38 | 39 | /** 40 | * @return int 41 | */ 42 | public function getPage(): int 43 | { 44 | return $this->page; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/Request/User/RecentlyOnlineUsersRequest.php: -------------------------------------------------------------------------------- 1 | username = $username; 26 | } 27 | 28 | /** 29 | * @return string 30 | */ 31 | public function getPath(): string 32 | { 33 | return sprintf('https://myanimelist.net/profile/%s/clubs', $this->username); 34 | } 35 | 36 | /** 37 | * @return string 38 | */ 39 | public function getUsername(): string 40 | { 41 | return $this->username; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/Request/User/UserFriendsRequest.php: -------------------------------------------------------------------------------- 1 | username = $username; 32 | $this->page = $page; 33 | } 34 | 35 | /** 36 | * @return string 37 | */ 38 | public function getPath(): string 39 | { 40 | $query = ''; 41 | if ($this->page) { 42 | $query = '?'.http_build_query(['p' => $this->page]); 43 | } 44 | 45 | return sprintf('https://myanimelist.net/profile/%s/friends%s', $this->username, $query); 46 | } 47 | 48 | /** 49 | * @return string 50 | */ 51 | public function getUsername(): string 52 | { 53 | return $this->username; 54 | } 55 | 56 | /** 57 | * @return int 58 | */ 59 | public function getPage(): int 60 | { 61 | return $this->page; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/Request/User/UserHistoryRequest.php: -------------------------------------------------------------------------------- 1 | username = $username; 35 | 36 | 37 | if (null !== $type) { 38 | if (!\in_array($type, ['anime', 'manga'])) { 39 | throw new \InvalidArgumentException(sprintf('Type %s is not valid', $type)); 40 | } 41 | 42 | $this->type = $type; 43 | } 44 | } 45 | 46 | /** 47 | * @return string 48 | */ 49 | public function getPath(): string 50 | { 51 | return sprintf('https://myanimelist.net/history/%s/%s', $this->username, $this->type); 52 | } 53 | 54 | /** 55 | * @return string 56 | */ 57 | public function getUsername(): string 58 | { 59 | return $this->username; 60 | } 61 | 62 | /** 63 | * @return string|null 64 | */ 65 | public function getType(): ?string 66 | { 67 | return $this->type; 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/Request/User/UserProfileRequest.php: -------------------------------------------------------------------------------- 1 | username = $username; 27 | } 28 | 29 | /** 30 | * @return string 31 | */ 32 | public function getPath(): string 33 | { 34 | return sprintf('https://myanimelist.net/profile/%s/', $this->username); 35 | } 36 | 37 | /** 38 | * @return string 39 | */ 40 | public function getUsername(): string 41 | { 42 | return $this->username; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/Request/User/UserRecommendationsRequest.php: -------------------------------------------------------------------------------- 1 | username = $username; 32 | $this->page = $page; 33 | } 34 | 35 | /** 36 | * @return string 37 | */ 38 | public function getPath(): string 39 | { 40 | return sprintf('https://myanimelist.net/profile/%s/recommendations?p=%d', $this->username, $this->page); 41 | } 42 | 43 | /** 44 | * @return string 45 | */ 46 | public function getUsername(): string 47 | { 48 | return $this->username; 49 | } 50 | 51 | /** 52 | * @return int 53 | */ 54 | public function getPage(): ?int 55 | { 56 | return $this->page; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/Request/User/UserReviewsRequest.php: -------------------------------------------------------------------------------- 1 | username = $username; 32 | $this->page = $page; 33 | } 34 | 35 | /** 36 | * @return string 37 | */ 38 | public function getPath(): string 39 | { 40 | return sprintf('https://myanimelist.net/profile/%s/reviews?p=%d', $this->username, $this->page); 41 | } 42 | 43 | /** 44 | * @return string 45 | */ 46 | public function getUsername(): string 47 | { 48 | return $this->username; 49 | } 50 | 51 | /** 52 | * @return int 53 | */ 54 | public function getPage(): ?int 55 | { 56 | return $this->page; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/Request/User/UsernameByIdRequest.php: -------------------------------------------------------------------------------- 1 | id = $id; 27 | } 28 | 29 | /** 30 | * @return string 31 | */ 32 | public function getPath(): string 33 | { 34 | return sprintf('https://myanimelist.net/comments.php?id=%d', $this->id); 35 | } 36 | 37 | /** 38 | * @return int 39 | */ 40 | public function getId(): int 41 | { 42 | return $this->id; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/Request/Watch/PopularEpisodesRequest.php: -------------------------------------------------------------------------------- 1 | page = $page; 27 | } 28 | 29 | /** 30 | * @return string 31 | */ 32 | public function getPath(): string 33 | { 34 | return sprintf('https://myanimelist.net/watch/promotion?p=%d', $this->page); 35 | } 36 | 37 | /** 38 | * @return int 39 | */ 40 | public function getPage(): int 41 | { 42 | return $this->page; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /test/JikanTest/Helper/MediaTest.php: -------------------------------------------------------------------------------- 1 | getDay()); 21 | 22 | $date = new DateProp('Dec 1, 2004'); 23 | self::assertInstanceOf(DateProp::class, $date); 24 | self::assertEquals(1, $date->getDay()); 25 | self::assertEquals(12, $date->getMonth()); 26 | self::assertEquals(2004, $date->getYear()); 27 | 28 | $date = new DateProp('Dec, 2004'); 29 | self::assertInstanceOf(DateProp::class, $date); 30 | self::assertEquals(null, $date->getDay()); 31 | self::assertEquals(12, $date->getMonth()); 32 | self::assertEquals(2004, $date->getYear()); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /test/JikanTest/Parser/Anime/AnimeMoreInfoParserTest.php: -------------------------------------------------------------------------------- 1 | httpClient); 20 | $crawler = $client->request('GET', $request->getPath()); 21 | $this->parser = new \Jikan\Parser\Anime\MoreInfoParser($crawler); 22 | } 23 | 24 | /** 25 | * @test 26 | * @covers \Jikan\Parser\Anime\MoreInfoParser 27 | */ 28 | public function it_gets_more_info(): void 29 | { 30 | self::assertStringContainsString( 31 | 'Episode 492 is the second part of a two part special called Toriko x One Piece Collabo Special', 32 | $this->parser->getMoreInfo() 33 | ); 34 | } 35 | } -------------------------------------------------------------------------------- /test/JikanTest/Parser/Anime/AnimeStatsParserTest.php: -------------------------------------------------------------------------------- 1 | httpClient); 24 | $crawler = $client->request('GET', $request->getPath()); 25 | $this->animeStatsParser = new \Jikan\Parser\Anime\AnimeStatsParser($crawler); 26 | } 27 | 28 | /** 29 | * @test 30 | */ 31 | public function it_gets_numeric_statistics() 32 | { 33 | self::assertGreaterThan(0, $this->animeStatsParser->getWatching()); 34 | self::assertGreaterThan(0, $this->animeStatsParser->getCompleted()); 35 | self::assertGreaterThan(0, $this->animeStatsParser->getOnHold()); 36 | self::assertGreaterThan(0, $this->animeStatsParser->getDropped()); 37 | self::assertGreaterThan(0, $this->animeStatsParser->getTotal()); 38 | self::assertGreaterThan(0, $this->animeStatsParser->getPlanToWatch()); 39 | } 40 | 41 | /** 42 | * @test 43 | */ 44 | public function it_gets_score_attributes() 45 | { 46 | self::assertEquals( 47 | 1062, 48 | $this->animeStatsParser->getScores()[10]->getVotes() 49 | ); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /test/JikanTest/Parser/Club/UserListParserTest.php: -------------------------------------------------------------------------------- 1 | httpClient); 20 | $crawler = $client->request('GET', $request->getPath()); 21 | $this->parser = new \Jikan\Parser\Club\UserListParser($crawler); 22 | } 23 | 24 | /** 25 | * @test 26 | * @covers \Jikan\Parser\Club\UserListParser 27 | */ 28 | public function it_gets_users(): void 29 | { 30 | $results = $this->parser->getResults(); 31 | self::assertCount( 32 | 36, 33 | $results 34 | ); 35 | } 36 | } -------------------------------------------------------------------------------- /test/JikanTest/Parser/Common/MalUrlParserTest.php: -------------------------------------------------------------------------------- 1 | assertEquals(12345, MalUrlParser::parseId($url)); 23 | } 24 | 25 | 26 | public function testMalIdParserException() 27 | { 28 | // $this->expectException(\RuntimeException::class); 29 | // MalUrlParser::parseId('https://myanimelist.net/anime/bla'); 30 | $this->assertEquals(0, MalUrlParser::parseId('https://myanimelist.net/anime/blah')); 31 | } 32 | 33 | /** 34 | * @return array 35 | */ 36 | public function urlProvider(): array 37 | { 38 | return [ 39 | ['https://myanimelist.net/anime/12345'], 40 | ['https://myanimelist.net/anime/12345/Cowboy_Bebop'], 41 | ['https://myanimelist.net/anime/producer/12345/Funimation'], 42 | ['https://myanimelist.net/anime/12345/Cowboy_Bebop/episode/26'], 43 | ]; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /test/JikanTest/Parser/Magazine/MagazineParserTest.php: -------------------------------------------------------------------------------- 1 | httpClient); 24 | $crawler = $client->request('GET', 'https://myanimelist.net/manga/magazine/1'); 25 | $this->parser = new MagazineParser($crawler); 26 | } 27 | 28 | /** 29 | * @test 30 | */ 31 | public function it_gets_url() 32 | { 33 | $url = $this->parser->getUrl(); 34 | self::assertInstanceOf(\Jikan\Model\Common\MalUrl::class, $url); 35 | } 36 | 37 | /** 38 | * @test 39 | */ 40 | public function it_gets_manga() 41 | { 42 | $manga = $this->parser->getResults(); 43 | self::assertCount(68, $manga); 44 | self::assertContainsOnlyInstancesOf(\Jikan\Model\Common\MangaCard::class, $manga); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /test/JikanTest/Parser/Manga/CharactersParserTest.php: -------------------------------------------------------------------------------- 1 | httpClient); 23 | $crawler = $client->request('GET', 'https://myanimelist.net/manga/2/Berserk/characters'); 24 | $this->parser = new CharactersParser($crawler); 25 | } 26 | 27 | /** 28 | * @test 29 | */ 30 | public function it_gets_the_manga_characters() 31 | { 32 | $characters = $this->parser->getCharacters(); 33 | self::assertCount(75, $characters); 34 | $names = array_map(function ($item) { 35 | return $item->getCharacter()->getName(); 36 | }, $characters); 37 | self::assertContains('Wyald', $names); 38 | self::assertContains('Casca', $names); 39 | self::assertEquals('Main', $characters[0]->getRole()); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /test/JikanTest/Parser/Manga/MangaStatsParserTest.php: -------------------------------------------------------------------------------- 1 | httpClient); 25 | $crawler = $client->request('GET', $request->getPath()); 26 | $this->mangaStatsParser = new MangaStatsParser($crawler); 27 | } 28 | 29 | /** 30 | * @test 31 | */ 32 | public function it_gets_numeric_statistics() 33 | { 34 | self::assertGreaterThan(0, $this->mangaStatsParser->getReading()); 35 | self::assertGreaterThan(0, $this->mangaStatsParser->getCompleted()); 36 | self::assertGreaterThan(0, $this->mangaStatsParser->getOnHold()); 37 | self::assertGreaterThan(0, $this->mangaStatsParser->getDropped()); 38 | self::assertGreaterThan(0, $this->mangaStatsParser->getTotal()); 39 | self::assertGreaterThan(0, $this->mangaStatsParser->getPlanToRead()); 40 | } 41 | 42 | /** 43 | * @test 44 | */ 45 | public function it_gets_score_attributes() 46 | { 47 | self::assertEquals( 48 | 8404, $this->mangaStatsParser->getScores()[10]->getVotes() 49 | ); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /test/JikanTest/Parser/Search/AnimeSearchAiringTest.php: -------------------------------------------------------------------------------- 1 | httpClient); 20 | $this->search = $jikan->getAnimeSearch(new AnimeSearchRequest('Kaguya')); 21 | $anime = $this->search->getResults()[0]; 22 | self::assertEquals('Kaguya-sama wa Kokurasetai: Tensai-tachi no Renai Zunousen', $anime->getTitle()); 23 | 24 | // @Todo: Merge with TimeProvider branch to resolve the issue 25 | //self::assertTrue($anime->isAiring()); 26 | } 27 | 28 | /** 29 | * @test 30 | */ 31 | public function it_gets_airing_null() 32 | { 33 | $jikan = new MalClient($this->httpClient); 34 | $this->search = $jikan->getAnimeSearch(new AnimeSearchRequest('Aikatsu Friends')); 35 | $anime = $this->search->getResults()[0]; 36 | self::assertEquals('Aikatsu Friends!: Kagayaki no Jewel', $anime->getTitle()); 37 | self::assertFalse($anime->isAiring()); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /test/JikanTest/Parser/Search/AnimeSearchEpisodeTest.php: -------------------------------------------------------------------------------- 1 | httpClient); 20 | $this->search = $jikan->getAnimeSearch(new AnimeSearchRequest('Ijimekko Ookami to Nana-chan')); 21 | $anime = $this->search->getResults()[0]; 22 | self::assertEquals('Ijimekko Ookami to Nana-chan', $anime->getTitle()); 23 | self::assertFalse($anime->isAiring()); 24 | } 25 | 26 | /** 27 | * @test 28 | */ 29 | public function it_gets_multiple_episodes_airing_true() 30 | { 31 | $jikan = new MalClient($this->httpClient); 32 | $this->search = $jikan->getAnimeSearch(new AnimeSearchRequest('Bloody Bunny')); 33 | $anime = $this->search->getResults()[0]; 34 | self::assertEquals('Bloody Bunny', $anime->getTitle()); 35 | self::assertTrue($anime->isAiring()); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /test/JikanTest/Parser/Search/PersonSearchTest.php: -------------------------------------------------------------------------------- 1 | httpClient); 22 | $this->search = $jikan->getPersonSearch( 23 | new \Jikan\Request\Search\PersonSearchRequest('Ara') 24 | ); 25 | $this->person = $this->search->getResults()[0]; 26 | } 27 | 28 | /** 29 | * @test 30 | */ 31 | public function it_gets_the_name() 32 | { 33 | self::assertEquals("Araizumi, Rui", $this->person->getName()); 34 | } 35 | 36 | /** 37 | * @test 38 | */ 39 | public function it_gets_the_image_url() 40 | { 41 | self::assertEquals( 42 | "https://cdn.myanimelist.net/images/voiceactors/2/42926.jpg?s=bf7e47ee3e4a1eb93e7ef86afed1c68b", 43 | $this->person->getImages()->getJpg()->getImageUrl() 44 | ); 45 | } 46 | 47 | /** 48 | * @test 49 | */ 50 | public function it_gets_the_url() 51 | { 52 | self::assertEquals("https://myanimelist.net/people/5159/Rui_Araizumi", $this->person->getUrl()); 53 | } 54 | 55 | /** 56 | * @test 57 | */ 58 | public function it_gets_the_alternative_names() 59 | { 60 | self::assertContains('あらいず☆みるい', $this->person->getAlternativeNames()); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /test/JikanTest/Parser/SeasonList/SeasonListItemParserTest.php: -------------------------------------------------------------------------------- 1 | httpClient); 19 | $crawler = $client->request('GET', 'https://myanimelist.net/anime/season/archive'); 20 | $this->parser = new SeasonListItemParser( 21 | $crawler->filterXPath('//table[contains(@class, "anime-seasonal-byseason")]/tr')->first() 22 | ); 23 | } 24 | 25 | /** 26 | * @test 27 | * @covers \Jikan\Parser\SeasonList\SeasonListItemParser::getYear 28 | */ 29 | public function it_gets_the_year(): void 30 | { 31 | self::assertEquals(2023, $this->parser->getYear()); 32 | } 33 | 34 | /** 35 | * @test 36 | * @covers \Jikan\Parser\SeasonList\SeasonListItemParser::getSeasons 37 | */ 38 | public function it_gets_the_seasons(): void 39 | { 40 | self::assertContains('winter', $this->parser->getSeasons()); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /test/JikanTest/Parser/SeasonList/SeasonListParserTest.php: -------------------------------------------------------------------------------- 1 | httpClient); 26 | $crawler = $client->request('GET', $request->getPath()); 27 | $this->parser = new SeasonListParser($crawler); 28 | } 29 | 30 | /** 31 | * @test 32 | * @covers \Jikan\Parser\SeasonList\SeasonListParser::getModel 33 | */ 34 | public function it_contains_season_items(): void 35 | { 36 | self::assertContainsOnlyInstancesOf( 37 | SeasonListItem::class, 38 | $this->parser->getModel()->getResults() 39 | ); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /test/JikanTest/Parser/Seasonal/SeasonalParserTest.php: -------------------------------------------------------------------------------- 1 | httpClient); 22 | $request = new \Jikan\Request\Seasonal\SeasonalRequest(2018, 'spring'); 23 | $crawler = $client->request('GET', $request->getPath()); 24 | $this->springParser = new \Jikan\Parser\Seasonal\SeasonalParser($crawler); 25 | } 26 | 27 | /** 28 | * @test 29 | */ 30 | public function it_gets_the_season() 31 | { 32 | self::assertEquals('Spring 2018', $this->springParser->getSeasonName() . " " . $this->springParser->getSeasonYear()); 33 | } 34 | 35 | /** 36 | * @test 37 | */ 38 | public function it_gets_the_anime() 39 | { 40 | $anime = $this->springParser->getSeasonalAnime(); 41 | self::assertCount(290, $anime); 42 | self::assertContainsOnlyInstancesOf(\Jikan\Model\Seasonal\SeasonalAnime::class, $anime); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /test/JikanTest/Parser/UserHistory/UserHistoryParserTest.php: -------------------------------------------------------------------------------- 1 | httpClient); 25 | $crawler = $client->request('GET', 'https://myanimelist.net/history/morshuwarrior/'); 26 | $this->parser = (new \Jikan\Parser\User\History\HistoryParser($crawler))->getModel(); 27 | } 28 | 29 | /** 30 | * @test 31 | */ 32 | public function it_gets_the_url() 33 | { 34 | self::assertInstanceOf(\Jikan\Model\Common\MalUrl::class, $this->parser[0]->getMalUrl()); 35 | self::assertIsString($this->parser[0]->getMalUrl()->getTitle()); 36 | } 37 | 38 | /** 39 | * @test 40 | */ 41 | public function it_gets_the_increment() 42 | { 43 | self::assertIsInt($this->parser[0]->getIncrement()); 44 | } 45 | 46 | /** 47 | * @test 48 | */ 49 | public function it_gets_the_date() 50 | { 51 | self::assertInstanceOf(\DateTimeImmutable::class, $this->parser[0]->getDate()); 52 | } 53 | 54 | } -------------------------------------------------------------------------------- /test/JikanTest/Parser/Video/AnimeVideoParserTest.php: -------------------------------------------------------------------------------- 1 | httpClient); 26 | $crawler = $client->request('GET', 'https://myanimelist.net/anime/1/_/video'); 27 | $this->parser = new VideosParser($crawler); 28 | } 29 | 30 | 31 | /** 32 | * @test 33 | */ 34 | public function it_gets_promos() 35 | { 36 | $videos = $this->parser->getPromos(); 37 | self::assertContainsOnlyInstancesOf(PromoListItem::class, $videos); 38 | } 39 | 40 | /** 41 | * @test 42 | */ 43 | public function it_gets_episodes() 44 | { 45 | $videos = $this->parser->getEpisodes(); 46 | self::assertContainsOnlyInstancesOf(StreamEpisodeListItem::class, $videos); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /test/JikanTest/TestCase.php: -------------------------------------------------------------------------------- 1 | httpClient = new MockHttpClient(new HttpFilesystemCacheClientCallback($cachePath)); 26 | } 27 | } 28 | --------------------------------------------------------------------------------