add person page
This commit is contained in:
parent
5759606bca
commit
a17082eea6
15 changed files with 179 additions and 15 deletions
|
@ -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
|
||||
{
|
||||
|
|
60
app/Http/Controllers/PeopleController.php
Normal file
60
app/Http/Controllers/PeopleController.php
Normal file
|
@ -0,0 +1,60 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Http\Requests\MorePersonCastRequest;
|
||||
use DipeshSukhia\LaravelHtmlMinify\LaravelHtmlMinifyFacade;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use App\Services\ApiClient;
|
||||
use App\Services\TmdbClient;
|
||||
use App\Supports\Traits\CleanItems;
|
||||
use App\Supports\SchemaBuilder;
|
||||
use App\Supports\Traits\Helpers;
|
||||
use App\Supports\Traits\TopContent;
|
||||
use Route;
|
||||
|
||||
class PeopleController extends Controller
|
||||
{
|
||||
use CleanItems;
|
||||
|
||||
public function index(TmdbClient $tmdbClient, int $id, string $slug) {
|
||||
$results = $tmdbClient->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'));
|
||||
}
|
||||
}
|
29
app/Http/Requests/MorePersonCastRequest.php
Normal file
29
app/Http/Requests/MorePersonCastRequest.php
Normal file
|
@ -0,0 +1,29 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Requests;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
|
||||
class MorePersonCastRequest extends FormRequest
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*/
|
||||
public function authorize(): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string>
|
||||
*/
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
'person_id' => 'integer|required',
|
||||
'page' => 'integer|required'
|
||||
];
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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(),
|
||||
];
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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......',
|
||||
],
|
||||
],
|
||||
|
||||
|
||||
];
|
||||
|
|
|
@ -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});
|
1
public/build/assets/load-more-Ck2SWgku.js
Normal file
1
public/build/assets/load-more-Ck2SWgku.js
Normal file
|
@ -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});
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -123,7 +123,7 @@
|
|||
<span class="caption">Cast:</span>
|
||||
<span class="value">
|
||||
@foreach($movie['cast'] as $actor)
|
||||
{{ $actor['name'] }}@if(!$loop->last), @endif
|
||||
<a href="{{ route('person', ['person_id' => $actor['id'], 'slug' => $actor['slug']]) }}">{{ $actor['name'] }}</a> @if(!$loop->last), @endif
|
||||
@endforeach</span>
|
||||
</li>
|
||||
<li>
|
||||
|
|
|
@ -119,7 +119,7 @@
|
|||
<span class="caption">Cast:</span>
|
||||
<span class="value">
|
||||
@foreach($show['cast'] as $actor)
|
||||
{{ $actor['name'] }}@if(!$loop->last), @endif
|
||||
<a href="{{ route('person', ['person_id' => $actor['id'], 'slug' => $actor['slug']]) }}">{{ $actor['name'] }}</a> @if(!$loop->last), @endif
|
||||
@endforeach</span>
|
||||
</li>
|
||||
<li>
|
||||
|
|
|
@ -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');
|
||||
|
|
|
@ -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');
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue