diff --git a/app/Http/Controllers/MovieController.php b/app/Http/Controllers/MovieController.php index 27f5f32..3dbab2e 100644 --- a/app/Http/Controllers/MovieController.php +++ b/app/Http/Controllers/MovieController.php @@ -6,19 +6,14 @@ use App\Http\Requests\MoreMoviesRequest; use App\Http\Resources\MoreTitles; use DipeshSukhia\LaravelHtmlMinify\LaravelHtmlMinifyFacade; -use DipeshSukhia\LaravelHtmlMinify\Middleware\LaravelMinifyHtml; -use Illuminate\Http\Request; use App\Services\ApiClient; use App\Services\TmdbClient; use App\Supports\Traits\CleanItems; -use Illuminate\Support\Facades\Cache; use App\Supports\SchemaBuilder; -use Illuminate\Support\Facades\View; use App\Supports\Traits\Helpers; use App\Supports\Traits\TopContent; use Illuminate\Support\Facades\Route; use Illuminate\Support\Str; -use Illuminate\Support\Facades\Vite; class MovieController extends Controller { diff --git a/app/Http/Controllers/PeopleController.php b/app/Http/Controllers/PeopleController.php new file mode 100644 index 0000000..a2a3abc --- /dev/null +++ b/app/Http/Controllers/PeopleController.php @@ -0,0 +1,60 @@ +getPerson($id); + $page = request()->query('page', 1); + ['data' => $data, 'pagination' => $pagination, 'name' => $name] = $this->formatTmdbPersonResponse($results, $page); + $page_text = ($page > 1) + ? sprintf(' - Page %s', $page) + : ''; + // dd($pagination); + $data = $pagination->items(); + + $meta = []; + $meta['title'] = str(config('site.people.cast.title'))->replace(['{NAME}'], $name)->replace(['{PAGE}'], $page_text)->apa(); + $meta['page_title'] = str(config('site.people.cast.page_title'))->replace(['{NAME}'], $name)->replace(['{PAGE}'], $page_text)->apa(); + $meta['description'] = str(config('site.people.cast.description'))->replace(['{NAME}'], $name)->replace(['{PAGE}'], $page_text); + $meta['keywords'] = config('site.people.cast.keywords', false); + $meta['image'] = asset('images/cover.jpg'); + $meta['route'] = Route::current(); + // dd($meta['route']); + + // $query = str($query)->apa(); + + // sleep(2); + return view('list', compact('data', 'pagination', 'meta', 'id')); + + } + public function more(TmdbClient $tmdbClient, MorePersonCastRequest $request):JsonResponse { + $results = $tmdbClient->getPerson($request->validated()['person_id']); + $page = request()->query('page', 1); + ['data' => $data, 'pagination' => $pagination, 'name' => $name] = $this->formatTmdbPersonResponse($results, $request->validated()['page']); + + $items = $pagination->items(); + + + $has_more_pages = $pagination->hasMorePages(); + $current_page = $pagination->currentPage(); + $html = LaravelHtmlMinifyFacade::htmlMinify(view('components.more_titles', compact('items'))->render()); + + return response()->json(compact('current_page', 'has_more_pages', 'html')); + } +} diff --git a/app/Http/Requests/MorePersonCastRequest.php b/app/Http/Requests/MorePersonCastRequest.php new file mode 100644 index 0000000..6d12b2f --- /dev/null +++ b/app/Http/Requests/MorePersonCastRequest.php @@ -0,0 +1,29 @@ +|string> + */ + public function rules(): array + { + return [ + 'person_id' => 'integer|required', + 'page' => 'integer|required' + ]; + } +} diff --git a/app/Services/TmdbClient.php b/app/Services/TmdbClient.php index 95803f4..9266bf7 100644 --- a/app/Services/TmdbClient.php +++ b/app/Services/TmdbClient.php @@ -5,6 +5,7 @@ use App\Http\Resources\MovieDetail; use App\Services\TmdbClient as ServicesTmdbClient; use App\Supports\Traits\CleanItems; +use App\Supports\Traits\Helpers; use Carbon\Carbon; use Illuminate\Support\Facades\Cache; use Symfony\Component\Cache\Adapter\RedisAdapter; @@ -24,7 +25,7 @@ class TmdbClient { - use CleanItems; + use CleanItems, Helpers; private static $instance; private $ttl = 3600*24; private $use_cache = true; @@ -272,4 +273,14 @@ public function getSearch(string $query, int $page = 1) return $call(); } + public function getPerson($id) + { + $call = fn() => self::filterTmdbPersonData($this->client->getPeopleApi()->getPerson($id, ['language' => 'en-US', 'append_to_response' => 'movie_credits,tv_credits'])); + if ($this->use_cache) + return Cache::remember('person_movie_credits_'.$id, $this->ttl, $call); + + return $call(); + + } + } diff --git a/app/Supports/Traits/CleanItems.php b/app/Supports/Traits/CleanItems.php index 45e5fc0..81c85ea 100644 --- a/app/Supports/Traits/CleanItems.php +++ b/app/Supports/Traits/CleanItems.php @@ -361,10 +361,38 @@ public function formatTmdbResponse(array $data, $with_pagination = false, $route ]; } } + $response['pagination']['links'] = $links; } // dd($response); return $response; } + + public function formatTmdbPersonResponse(array $data, $page = 1, $limit = false):array + { + $response = []; + $results = collect([]); + $response['name'] = $data['name']; + + $results = collect($data['titles'])->map(function($item) { + $item = (Object)$item; + return [ + 'id' => self::encodeId($item->id), + 'title' => $item->title, + 'image' => self::getImageUrl($item->poster_path, 'w300', null, null), + 'slug' => Str::slug($item->title) === '' ? sprintf('f%sl', $item->id) : Str::slug($item->title), + 'year' => Carbon::parse($item->date)->format('Y'), + 'date' => $item->date ?? $item->first_air_date ?? Carbon::now()->format('Y-m-d'), + 'type' => $item->type, + 'route' => $item->type, + ]; + })->when($limit, fn($collection) => $collection->take($limit));//->sortByDesc('popularity'); + $response['data'] = $results; + + $response['pagination'] = new LengthAwarePaginator($results->forPage($page, 20), count($results), 20, $page, [ + 'path' => request()->url() + ]); + return $response; + } } diff --git a/app/Supports/Traits/Helpers.php b/app/Supports/Traits/Helpers.php index 910111b..c3a4ca1 100644 --- a/app/Supports/Traits/Helpers.php +++ b/app/Supports/Traits/Helpers.php @@ -85,6 +85,7 @@ public static function getCast(array $actors, int $limit = 5): array return collect($actors)->map(fn ($actor) => [ 'id' => $actor['id'], 'name' => $actor['name'], + 'slug' => str()->slug($actor['name']) !== '' ? str()->slug($actor['name']) : sprintf('a%sn', $actor['name']), 'as' => $actor['character'], 'image' => self::getImageUrl($actor['profile_path'], 'w500', 200, 300), ])->take($limit)->all(); @@ -256,4 +257,33 @@ public static function getShareLinks(string $url, string $title, string $descrip ]; } + public static function filterTmdbPersonData(array $data):array + { + $movies = collect($data['movie_credits']['cast'] ?? [])->where('adult', false)->map(function($movie){ + return [ + 'id' => $movie['id'], + 'title' => $movie['title'], + 'poster_path' => $movie['poster_path'], + 'date' => $movie['release_date'], + 'type' => 'movie' + ]; + }); + $shows = collect($data['tv_credits']['cast'] ?? [])->where('adult', false)->map(function($show){ + return [ + 'id' => $show['id'], + 'title' => $show['name'], + 'poster_path' => $show['poster_path'], + 'date' => $show['first_air_date'], + 'type' => 'show' + ]; + }); + + return [ + 'id' => $data['id'], + 'name' => $data['name'], + 'titles' => $movies->merge($shows)->whereNotNull('poster_path')->sortByDesc('date')->values()->all(), + ]; + + } + } diff --git a/config/site.php b/config/site.php index ab39ba2..327679a 100644 --- a/config/site.php +++ b/config/site.php @@ -114,17 +114,20 @@ 'page_title' => 'Browse %s Movies', 'description' => 'Movies List Page Description for genre %s', ], - 'cast' => [ - 'title' => 'Watch %s Movies Online{PAGE} - ' . config('app.name'), - 'page_title' => 'Browse %s Movies', - 'description' => '%s Movies{PAGE}: viewing or downloading the greatest films and TV series for free in all languages, in high definition, on safe and legal websites......', - ], + 'top_imdb' => [ 'title' => 'IMDb Top 250', 'page_title' => 'IMDb Top 250', 'description' => 'Top IMDb Titles Description', ], ], + 'people' => [ + 'cast' => [ + 'title' => 'Watch {NAME} Movies & Series Online{PAGE} - ' . config('app.name'), + 'page_title' => 'Browse {NAME} Titles', + 'description' => '%s Movies{PAGE}: viewing or downloading the greatest films and TV series for free in all languages, in high definition, on safe and legal websites......', + ], + ], ]; diff --git a/public/build/assets/load-more-BlXjt7JF.js b/public/build/assets/load-more-BlXjt7JF.js deleted file mode 100644 index 6a2abfc..0000000 --- a/public/build/assets/load-more-BlXjt7JF.js +++ /dev/null @@ -1 +0,0 @@ -window.lazyFunctions={more:function(a){const n=a,e=JSON.parse(atob(a.dataset.params)),r=new Headers;r.append("Content-Type","application/json"),r.append("Accept","application/json");const o={page:e.page,route:e.route};"genre"in e.route_parameters&&(o.genre=e.route_parameters.genre),"search"in e&&(o.search=e.search);const s={method:"POST",headers:r,body:JSON.stringify(o)};fetch(e.route,s).then(t=>t.json()).then(t=>{const i=a.parentNode;i.innerHTML+=t.html,window.lLoad.update(),a.remove(),document.getElementById(a.getAttribute("id")).remove(),t.has_more_pages&&(e.page=t.current_page+1,n.setAttribute("href",n.getAttribute("href").replace(new RegExp(t.current_page+"$"),t.current_page+1)),n.setAttribute("data-params",btoa(JSON.stringify(e))),n.removeAttribute("data-ll-status"),n.classList.remove("entered"),i.appendChild(n),window.lMore.update())}).catch(t=>console.error(t))}};function c(a){var n=a.getAttribute("data-lazy-function"),e=window.lazyFunctions[n];e&&e(a)}window.lMore=new window.LazyLoad({elements_selector:"#next-page",unobserve_entered:!0,callback_enter:c}); diff --git a/public/build/assets/load-more-Ck2SWgku.js b/public/build/assets/load-more-Ck2SWgku.js new file mode 100644 index 0000000..fe365a3 --- /dev/null +++ b/public/build/assets/load-more-Ck2SWgku.js @@ -0,0 +1 @@ +window.lazyFunctions={more:function(a){const r=a,e=JSON.parse(atob(a.dataset.params)),o=new Headers;o.append("Content-Type","application/json"),o.append("Accept","application/json");const n={page:e.page,route:e.route};"genre"in e.route_parameters&&(n.genre=e.route_parameters.genre),"person_id"in e.route_parameters&&(n.person_id=e.route_parameters.person_id),"search"in e&&(n.search=e.search);const s={method:"POST",headers:o,body:JSON.stringify(n)};fetch(e.route,s).then(t=>t.json()).then(t=>{const i=a.parentNode;i.innerHTML+=t.html,window.lLoad.update(),a.remove(),document.getElementById(a.getAttribute("id")).remove(),t.has_more_pages&&(e.page=t.current_page+1,r.setAttribute("href",r.getAttribute("href").replace(new RegExp(t.current_page+"$"),t.current_page+1)),r.setAttribute("data-params",btoa(JSON.stringify(e))),r.removeAttribute("data-ll-status"),r.classList.remove("entered"),i.appendChild(r),window.lMore.update())}).catch(t=>console.error(t))}};function p(a){var r=a.getAttribute("data-lazy-function"),e=window.lazyFunctions[r];e&&e(a)}window.lMore=new window.LazyLoad({elements_selector:"#next-page",unobserve_entered:!0,callback_enter:p}); diff --git a/public/build/manifest.json b/public/build/manifest.json index c71ecc8..9dfcf40 100644 --- a/public/build/manifest.json +++ b/public/build/manifest.json @@ -24,7 +24,7 @@ "isEntry": true }, "resources/js/load-more.js": { - "file": "assets/load-more-BlXjt7JF.js", + "file": "assets/load-more-Ck2SWgku.js", "name": "load-more", "src": "resources/js/load-more.js", "isEntry": true diff --git a/resources/js/load-more.js b/resources/js/load-more.js index 840bdf1..a3bf721 100644 --- a/resources/js/load-more.js +++ b/resources/js/load-more.js @@ -18,6 +18,9 @@ window.lazyFunctions = { if ('genre' in params.route_parameters) { postBody.genre = params.route_parameters.genre; } + if ('person_id' in params.route_parameters) { + postBody.person_id = params.route_parameters.person_id; + } if ('search' in params) { postBody.search = params.search; } diff --git a/resources/views/movie.blade.php b/resources/views/movie.blade.php index ee9fe09..02eea39 100644 --- a/resources/views/movie.blade.php +++ b/resources/views/movie.blade.php @@ -123,7 +123,7 @@ Cast: @foreach($movie['cast'] as $actor) - {{ $actor['name'] }}@if(!$loop->last), @endif + {{ $actor['name'] }} @if(!$loop->last), @endif @endforeach
  • diff --git a/resources/views/show.blade.php b/resources/views/show.blade.php index 6a76825..a1fee00 100644 --- a/resources/views/show.blade.php +++ b/resources/views/show.blade.php @@ -119,7 +119,7 @@ Cast: @foreach($show['cast'] as $actor) - {{ $actor['name'] }}@if(!$loop->last), @endif + {{ $actor['name'] }} @if(!$loop->last), @endif @endforeach
  • diff --git a/routes/api.php b/routes/api.php index 9a5eb08..377f7d3 100644 --- a/routes/api.php +++ b/routes/api.php @@ -3,6 +3,7 @@ use App\Http\Controllers\HomeController; use App\Http\Controllers\MovieController; use App\Http\Controllers\ShowController; +use App\Http\Controllers\PeopleController; use Illuminate\Http\Request; use Illuminate\Support\Facades\Route; @@ -23,4 +24,5 @@ Route::post('/movies', [MovieController::class, 'movies_more'])->name('api.movies'); Route::post('/movies/genre', [MovieController::class, 'movies_genre_more'])->name('api.movies.genre'); Route::post('/tv-shows', [ShowController::class, 'shows_more'])->name('api.shows'); +Route::post('/person', [PeopleController::class, 'more'])->name('api.person'); Route::post('/search', [HomeController::class, 'search_more'])->name('api.search'); diff --git a/routes/web.php b/routes/web.php index 95659b3..5f49c84 100644 --- a/routes/web.php +++ b/routes/web.php @@ -6,6 +6,7 @@ use App\Http\Controllers\ShowController; use Illuminate\Foundation\Application; use Illuminate\Support\Facades\Route; +use App\Http\Controllers\PeopleController; /* @@ -22,6 +23,7 @@ Route::pattern('page', '\d+'); Route::pattern('season', '\d+'); Route::pattern('id', '[0-9]+'); +Route::pattern('person_id', '[0-9]+'); Route::pattern('p', 'page'); Route::pattern('country', '[a-z]{2}'); @@ -34,6 +36,7 @@ Route::get('/movie/{id}/{slug}', [MovieController::class, 'index'])->name('movie'); Route::get('/series/{id}/{slug}', [ShowController::class, 'index'])->name('show'); Route::get('/series/{id}/{slug}/season/{season}', [ShowController::class, 'season'])->name('show.season'); +Route::get('/person/{person_id}/{slug}', [PeopleController::class, 'index'])->name('person'); Route::get('/search', [HomeController::class, 'search'])->name('search');