diff --git a/app/Http/Controllers/MovieController.php b/app/Http/Controllers/MovieController.php index be00c0184..cdb3d0d5b 100644 --- a/app/Http/Controllers/MovieController.php +++ b/app/Http/Controllers/MovieController.php @@ -47,16 +47,16 @@ class MovieController extends BasePageController } $rslt = $this->movieBrowseService->getMovieRange($page, $catarray, $offset, config('nntmux.items_per_cover_page'), $orderby, -1, (array) $this->userdata->categoryexclusions); - $results = $this->paginate($rslt ?? [], $rslt[0]->_totalcount ?? 0, config('nntmux.items_per_cover_page'), $page, $request->url(), $request->query()); + $totalCount = $rslt->isNotEmpty() ? ($rslt[0]->_totalcount ?? 0) : 0; + $results = $this->paginate($rslt ?? [], $totalCount, config('nntmux.items_per_cover_page'), $page, $request->url(), $request->query()); $movies = $results->map(function ($result) { - $result['genre'] = makeFieldLinks($result, 'genre', 'movies'); - $result['actors'] = makeFieldLinks($result, 'actors', 'movies'); - $result['director'] = makeFieldLinks($result, 'director', 'movies'); - $result['languages'] = explode(', ', $result['language']); + $result->genre = makeFieldLinks($result, 'genre', 'movies'); + $result->actors = makeFieldLinks($result, 'actors', 'movies'); + $result->director = makeFieldLinks($result, 'director', 'movies'); // Add cover image URL using helper function - $result['cover'] = getReleaseCover($result); + $result->cover = getReleaseCover($result); return $result; }); @@ -111,17 +111,6 @@ class MovieController extends BasePageController return redirect()->route('Movies')->with('error', 'Movie not found'); } - // Get all releases for this movie - $rslt = $this->movieBrowseService->getMovieRange(1, [], 0, 1000, '', -1, (array) $this->userdata->categoryexclusions); - - // Filter to only this movie's IMDB ID - /** @phpstan-ignore argument.templateType */ - $movieData = collect($rslt)->firstWhere('imdbid', $imdbid); - - if (! $movieData) { - return redirect()->route('Movies')->with('error', 'No releases found for this movie'); - } - // Convert Eloquent model to array $movieArray = $movieInfo->toArray(); @@ -147,25 +136,8 @@ class MovieController extends BasePageController // Add cover image URL using helper function $movieArray['cover'] = getReleaseCover($movieArray); - // Process all releases - $releaseNames = isset($movieData->grp_release_name) ? explode('#', $movieData->grp_release_name) : []; - $releaseSizes = isset($movieData->grp_release_size) ? explode(',', $movieData->grp_release_size) : []; - $releaseGuids = isset($movieData->grp_release_guid) ? explode(',', $movieData->grp_release_guid) : []; - $releasePostDates = isset($movieData->grp_release_postdate) ? explode(',', $movieData->grp_release_postdate) : []; - $releaseAddDates = isset($movieData->grp_release_adddate) ? explode(',', $movieData->grp_release_adddate) : []; - - $releases = []; - foreach ($releaseNames as $index => $releaseName) { - if ($releaseName && isset($releaseGuids[$index])) { - $releases[] = [ - 'name' => $releaseName, - 'guid' => $releaseGuids[$index], - 'size' => $releaseSizes[$index] ?? 0, - 'postdate' => $releasePostDates[$index] ?? null, - 'adddate' => $releaseAddDates[$index] ?? null, - ]; - } - } + // Get all releases for this movie directly (no limit) + $releases = $this->movieBrowseService->getMovieReleases($imdbid, (array) $this->userdata->categoryexclusions); $this->viewData = array_merge($this->viewData, [ 'movie' => $movieArray, diff --git a/app/Models/MovieInfo.php b/app/Models/MovieInfo.php index 10af76092..5c5072baf 100644 --- a/app/Models/MovieInfo.php +++ b/app/Models/MovieInfo.php @@ -3,6 +3,7 @@ namespace App\Models; use Illuminate\Database\Eloquent\Model; +use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Support\Facades\Cache; /** @@ -71,6 +72,14 @@ class MovieInfo extends Model */ protected $guarded = ['id']; + /** + * Get the releases associated with this movie. + */ + public function releases(): HasMany // @phpstan-ignore missingType.generics + { + return $this->hasMany(Release::class, 'imdbid', 'imdbid'); + } + public static function getAll(string $search = ''): mixed { $expiresAt = now()->addMinutes(config('nntmux.cache_expiry_medium')); diff --git a/app/Services/MovieBrowseService.php b/app/Services/MovieBrowseService.php index 1dbe98c84..3fef55bc2 100644 --- a/app/Services/MovieBrowseService.php +++ b/app/Services/MovieBrowseService.php @@ -4,7 +4,6 @@ namespace App\Services; use App\Models\Category; use App\Models\MovieInfo; -use App\Models\Release; use Illuminate\Support\Facades\Cache; use Illuminate\Support\Facades\DB; @@ -23,6 +22,11 @@ class MovieBrowseService /** * Get movie releases with covers for movie browse page. * + * Uses three separate queries instead of GROUP_CONCAT: + * 1. COUNT query for total results (replaces SQL_CALC_FOUND_ROWS) + * 2. Paginated movie list with only needed columns + * 3. Top 2 releases per movie using ROW_NUMBER() window function + * * @param array $cat * @param array $excludedCats */ @@ -30,81 +34,128 @@ class MovieBrowseService { $page = max(1, $page); $start = max(0, $start); + $catsrch = ''; if (count($cat) > 0 && $cat[0] !== -1) { // @phpstan-ignore offsetAccess.notFound $catsrch = Category::getCategorySearch($cat); } + $order = $this->getMovieOrder($orderBy); $expiresAt = now()->addMinutes(config('nntmux.cache_expiry_medium')); + $whereAge = $maxAge > 0 ? 'AND r.postdate > NOW() - INTERVAL '.$maxAge.' DAY ' : ''; $whereExcluded = count($excludedCats) > 0 ? ' AND r.categories_id NOT IN ('.implode(',', $excludedCats).')' : ''; - $limitClause = $start === false ? '' : ' LIMIT '.$num.' OFFSET '.$start; - $moviesSql = "SELECT SQL_CALC_FOUND_ROWS m.imdbid, GROUP_CONCAT(r.id ORDER BY r.postdate DESC SEPARATOR ',' ) AS grp_release_id " - ."FROM movieinfo m LEFT JOIN releases r USING (imdbid) WHERE m.title != '' AND m.imdbid != '0000000' " - ."AND r.passwordstatus {$this->showPasswords} " - .$this->getBrowseBy().' ' - .(! empty($catsrch) ? $catsrch.' ' : '') - .$whereAge - .$whereExcluded.' ' - ."GROUP BY m.imdbid ORDER BY {$order[0]} {$order[1]} {$limitClause}"; // @phpstan-ignore offsetAccess.notFound - $movieCache = Cache::get(md5($moviesSql.$page)); - if ($movieCache !== null) { - $movies = $movieCache; - } else { - $data = MovieInfo::fromQuery($moviesSql); - $movies = ['total' => DB::select('SELECT FOUND_ROWS() AS total'), 'result' => $data]; - Cache::put(md5($moviesSql.$page), $movies, $expiresAt); - } - $movieIDs = $releaseIDs = []; - if (! empty($movies['result'])) { - foreach ($movies['result'] as $id) { - $movieIDs[] = $id->imdbid; - $releaseIDs[] = $id->grp_release_id; - } - } - $inMovieIds = ! empty($movieIDs) ? implode(',', $movieIDs) : -1; - $inReleaseIds = ! empty($releaseIDs) ? implode(',', $releaseIDs) : -1; - $sql = 'SELECT ' - ."GROUP_CONCAT(r.id ORDER BY r.postdate DESC SEPARATOR ',' ) AS grp_release_id, " - ."GROUP_CONCAT(r.rarinnerfilecount ORDER BY r.postdate DESC SEPARATOR ',' ) AS grp_rarinnerfilecount, " - ."GROUP_CONCAT(r.haspreview ORDER BY r.postdate DESC SEPARATOR ',' ) AS grp_haspreview, " - ."GROUP_CONCAT(r.passwordstatus ORDER BY r.postdate DESC SEPARATOR ',' ) AS grp_release_password, " - ."GROUP_CONCAT(r.guid ORDER BY r.postdate DESC SEPARATOR ',' ) AS grp_release_guid, " - ."GROUP_CONCAT(rn.releases_id ORDER BY r.postdate DESC SEPARATOR ',' ) AS grp_release_nfoid, " - ."GROUP_CONCAT(g.name ORDER BY r.postdate DESC SEPARATOR ',' ) AS grp_release_grpname, " - ."GROUP_CONCAT(r.searchname ORDER BY r.postdate DESC SEPARATOR '#') AS grp_release_name, " - ."GROUP_CONCAT(r.postdate ORDER BY r.postdate DESC SEPARATOR ',' ) AS grp_release_postdate, " - ."GROUP_CONCAT(r.adddate ORDER BY r.postdate DESC SEPARATOR ',' ) AS grp_release_adddate, " - ."GROUP_CONCAT(r.size ORDER BY r.postdate DESC SEPARATOR ',' ) AS grp_release_size, " - ."GROUP_CONCAT(r.totalpart ORDER BY r.postdate DESC SEPARATOR ',' ) AS grp_release_totalparts, " - ."GROUP_CONCAT(r.comments ORDER BY r.postdate DESC SEPARATOR ',' ) AS grp_release_comments, " - ."GROUP_CONCAT(r.grabs ORDER BY r.postdate DESC SEPARATOR ',' ) AS grp_release_grabs, " - ."GROUP_CONCAT(df.failed ORDER BY r.postdate DESC SEPARATOR ',' ) AS grp_release_failed, " - ."GROUP_CONCAT(rr.report_count ORDER BY r.postdate DESC SEPARATOR ',' ) AS grp_release_reports, " - ."GROUP_CONCAT(rr.report_reasons ORDER BY r.postdate DESC SEPARATOR '|' ) AS grp_release_report_reasons, " - ."GROUP_CONCAT(cp.title, ' > ', c.title ORDER BY r.postdate DESC SEPARATOR ',' ) AS grp_release_catname, " - .'m.*, g.name AS group_name, rn.releases_id AS nfoid FROM releases r ' - .'LEFT OUTER JOIN usenet_groups g ON g.id = r.groups_id ' - .'LEFT OUTER JOIN release_nfos rn ON rn.releases_id = r.id ' - .'LEFT OUTER JOIN dnzb_failures df ON df.release_id = r.id ' - .'LEFT OUTER JOIN (SELECT releases_id, COUNT(*) AS report_count, GROUP_CONCAT(DISTINCT reason SEPARATOR \', \') AS report_reasons FROM release_reports WHERE status IN (\'pending\', \'reviewed\', \'resolved\') GROUP BY releases_id) rr ON rr.releases_id = r.id ' - .'LEFT OUTER JOIN categories c ON c.id = r.categories_id ' - .'LEFT OUTER JOIN root_categories cp ON cp.id = c.root_categories_id ' - .'INNER JOIN movieinfo m ON m.imdbid = r.imdbid ' - ."WHERE m.imdbid IN ($inMovieIds) AND r.id IN ($inReleaseIds) " - .(! empty($catsrch) ? $catsrch.' ' : '') - ."GROUP BY m.imdbid ORDER BY {$order[0]} {$order[1]}"; // @phpstan-ignore offsetAccess.notFound - $return = Cache::get(md5($sql.$page)); - if ($return !== null) { - return $return; - } - $return = Release::fromQuery($sql); - if (count($return) > 0) { - $return[0]->_totalcount = $movies['total'][0]->total ?? 0; - } - Cache::put(md5($sql.$page), $return, $expiresAt); + $browseBy = $this->getBrowseBy(); + $catFilter = ! empty($catsrch) ? $catsrch.' ' : ''; - return $return; + $baseWhere = "m.title != '' AND m.imdbid != '0000000' " + ."AND r.passwordstatus {$this->showPasswords} " + .$browseBy.' ' + .$catFilter + .$whereAge + .$whereExcluded; + + // Build a cache key from all the query parameters + $cacheKey = md5('movie_range_'.$baseWhere.$order[0].$order[1].$start.$num.$page); // @phpstan-ignore offsetAccess.notFound + + $cached = Cache::get($cacheKey); + if ($cached !== null) { + return $cached; + } + + // Step 1: Count total distinct movies matching filters + $countSql = 'SELECT COUNT(DISTINCT m.imdbid) AS total ' + .'FROM movieinfo m ' + .'INNER JOIN releases r ON r.imdbid = m.imdbid ' + .'WHERE '.$baseWhere; + + $totalResult = DB::select($countSql); + $totalCount = $totalResult[0]->total ?? 0; + + if ($totalCount === 0) { + return collect(); + } + + // Step 2: Get paginated movie list with only needed columns + $moviesSql = 'SELECT m.imdbid, m.tmdbid, m.traktid, m.title, m.year, m.rating, ' + .'m.plot, m.genre, m.director, m.actors, m.cover, ' + .'MAX(r.postdate) AS latest_postdate, ' + .'COUNT(r.id) AS total_releases ' + .'FROM movieinfo m ' + .'INNER JOIN releases r ON r.imdbid = m.imdbid ' + .'WHERE '.$baseWhere.' ' + .'GROUP BY m.imdbid, m.tmdbid, m.traktid, m.title, m.year, m.rating, ' + .'m.plot, m.genre, m.director, m.actors, m.cover ' + ."ORDER BY {$order[0]} {$order[1]} " // @phpstan-ignore offsetAccess.notFound + ."LIMIT {$num} OFFSET {$start}"; + + $movies = MovieInfo::fromQuery($moviesSql); + + if ($movies->isEmpty()) { + return collect(); + } + + // Build list of movie IMDB IDs for release query + $movieImdbIds = $movies->pluck('imdbid')->toArray(); + $inMovieIds = implode(',', array_map('intval', $movieImdbIds)); + + // Step 3: Get top 2 releases per movie using ROW_NUMBER() window function + $releasesSql = 'SELECT ranked.id, ranked.imdbid, ranked.guid, ranked.searchname, ' + .'ranked.size, ranked.postdate, ranked.adddate, ranked.haspreview ' + .'FROM ( ' + .'SELECT r.id, r.imdbid, r.guid, r.searchname, r.size, r.postdate, r.adddate, r.haspreview, ' + .'ROW_NUMBER() OVER (PARTITION BY r.imdbid ORDER BY r.postdate DESC) AS rn ' + .'FROM releases r ' + ."WHERE r.imdbid IN ({$inMovieIds}) " + ."AND r.passwordstatus {$this->showPasswords} " + .$catFilter + .$whereAge + .$whereExcluded + .') ranked ' + .'WHERE ranked.rn <= 2 ' + .'ORDER BY ranked.imdbid, ranked.postdate DESC'; + + $releases = DB::select($releasesSql); + + // Group releases by imdbid for fast lookup + $releasesByMovie = []; + foreach ($releases as $release) { + $releasesByMovie[$release->imdbid][] = $release; + } + + // Attach releases to each movie object + foreach ($movies as $movie) { + $movie->releases = $releasesByMovie[$movie->imdbid] ?? []; // @phpstan-ignore assign.propertyReadOnly + } + + // Set total count on first item (matches existing pattern used by controllers) + if ($movies->isNotEmpty()) { + $movies[0]->_totalcount = $totalCount; // @phpstan-ignore property.notFound + } + + Cache::put($cacheKey, $movies, $expiresAt); + + return $movies; + } + + /** + * Get all releases for a single movie by IMDB ID. + * + * @param array $excludedCats + * @return array + */ + public function getMovieReleases(string $imdbid, array $excludedCats = []): array + { + $whereExcluded = count($excludedCats) > 0 ? ' AND r.categories_id NOT IN ('.implode(',', $excludedCats).')' : ''; + + $sql = 'SELECT r.id, r.guid, r.searchname, r.size, r.postdate, r.adddate, r.haspreview ' + .'FROM releases r ' + .'WHERE r.imdbid = '.intval($imdbid).' ' + ."AND r.passwordstatus {$this->showPasswords} " + .$whereExcluded.' ' + .'ORDER BY r.postdate DESC'; + + return DB::select($sql); } /** diff --git a/resources/views/movies/partials/movie-card.blade.php b/resources/views/movies/partials/movie-card.blade.php index 881f0fa16..cb19fd57f 100644 --- a/resources/views/movies/partials/movie-card.blade.php +++ b/resources/views/movies/partials/movie-card.blade.php @@ -1,5 +1,5 @@ {{-- Movie Card Partial --}} -{{-- Props: $result (movie object), $layout (1 or 2), $site (site configuration) --}} +{{-- Props: $result (movie object with ->releases array), $layout (1 or 2), $site (site configuration) --}} @props([ 'result', @@ -8,34 +8,13 @@ ]) @php - // Get the first GUID from the comma-separated list - $guid = isset($result->grp_release_guid) ? explode(',', $result->grp_release_guid)[0] : null; - - // Parse release data - $releaseNames = isset($result->grp_release_name) ? explode('#', $result->grp_release_name) : []; - $releaseSizes = isset($result->grp_release_size) ? explode(',', $result->grp_release_size) : []; - $releaseGuids = isset($result->grp_release_guid) ? explode(',', $result->grp_release_guid) : []; - $releaseIds = isset($result->grp_release_id) ? explode(',', $result->grp_release_id) : []; - $releasePostDates = isset($result->grp_release_postdate) ? explode(',', $result->grp_release_postdate) : []; - $releaseAddDates = isset($result->grp_release_adddate) ? explode(',', $result->grp_release_adddate) : []; - $releaseHasPreview = isset($result->grp_haspreview) ? explode(',', $result->grp_haspreview) : []; - $releaseJpgStatus = isset($result->grp_jpgstatus) ? explode(',', $result->grp_jpgstatus) : []; - $releaseNfoStatus = isset($result->grp_nfostatus) ? explode(',', $result->grp_nfostatus) : []; - $releaseFromNames = isset($result->grp_release_fromname) ? explode(',', $result->grp_release_fromname) : []; - - // Limit to maximum 2 releases + // Releases are already attached as an array of objects (max 2 from the query) + $releases = $result->releases ?? []; + $totalReleases = $result->total_releases ?? count($releases); $maxReleases = 2; - $totalReleases = count($releaseNames); - $releaseNames = array_slice($releaseNames, 0, $maxReleases); - $releaseSizes = array_slice($releaseSizes, 0, $maxReleases); - $releaseGuids = array_slice($releaseGuids, 0, $maxReleases); - $releaseIds = array_slice($releaseIds, 0, $maxReleases); - $releasePostDates = array_slice($releasePostDates, 0, $maxReleases); - $releaseAddDates = array_slice($releaseAddDates, 0, $maxReleases); - $releaseHasPreview = array_slice($releaseHasPreview, 0, $maxReleases); - $releaseJpgStatus = array_slice($releaseJpgStatus, 0, $maxReleases); - $releaseNfoStatus = array_slice($releaseNfoStatus, 0, $maxReleases); - $releaseFromNames = array_slice($releaseFromNames, 0, $maxReleases); + + // Get the first GUID from releases + $guid = !empty($releases) ? $releases[0]->guid : null; // Image dimensions based on layout $coverClass = $layout == 1 ? 'w-48 h-72' : 'w-32 h-48'; @@ -74,7 +53,7 @@ {{-- Movie Details --}}
- {{-- Title and Report Badges --}} + {{-- Title --}}
@if(isset($result->imdbid) && $result->imdbid) @@ -85,40 +64,6 @@

{{ $result->title }}

@endif - {{-- Report Badges --}} -
- @if(!empty($result->grp_release_reports)) - @php - $reportCounts = array_filter(explode(',', $result->grp_release_reports)); - $totalReports = array_sum($reportCounts); - $reportReasonsRaw = !empty($result->grp_release_report_reasons) - ? implode(',', array_unique(array_filter(preg_split('/[|,]/', $result->grp_release_report_reasons)))) - : ''; - $reportReasons = \App\Models\ReleaseReport::reasonKeysToLabels($reportReasonsRaw); - @endphp - @if($totalReports > 0) -
- - {{ $totalReports }} report{{ $totalReports > 1 ? 's' : '' }} -
- @endif - @endif - - @if(!empty($result->grp_release_failed)) - @php - $failedCounts = array_filter(explode(',', $result->grp_release_failed)); - $totalFailed = array_sum($failedCounts); - @endphp - @if($totalFailed > 0) -
- - {{ $totalFailed }} failed report{{ $totalFailed > 1 ? 's' : '' }} -
- @endif - @endif -
- {{-- Year and Rating --}}
@if(isset($result->year) && $result->year) @@ -186,7 +131,7 @@
{{-- Release Information --}} - @if($guid && !empty($releaseNames[0])) + @if($guid && !empty($releases))

Available Releases @@ -197,18 +142,9 @@ @endif

- @foreach($releaseNames as $index => $releaseName) + @foreach($releases as $index => $release) @include('movies.partials.release-item', [ - 'releaseName' => $releaseName, - 'releaseGuid' => $releaseGuids[$index] ?? '', - 'releaseId' => $releaseIds[$index] ?? null, - 'releaseSize' => $releaseSizes[$index] ?? 0, - 'releasePostDate' => $releasePostDates[$index] ?? null, - 'releaseAddDate' => $releaseAddDates[$index] ?? null, - 'hasPreview' => $releaseHasPreview[$index] ?? 0, - 'jpgStatus' => $releaseJpgStatus[$index] ?? 0, - 'nfoStatus' => $releaseNfoStatus[$index] ?? 0, - 'fromName' => $releaseFromNames[$index] ?? '', + 'release' => $release, 'layout' => $layout, 'index' => $index, ]) @@ -219,5 +155,3 @@
- - diff --git a/resources/views/movies/partials/release-item.blade.php b/resources/views/movies/partials/release-item.blade.php index 2078c7627..7015b51b2 100644 --- a/resources/views/movies/partials/release-item.blade.php +++ b/resources/views/movies/partials/release-item.blade.php @@ -1,112 +1,76 @@ {{-- Release Item Partial --}} -{{-- Props: $releaseName, $releaseGuid, $releaseId, $releaseSize, $releasePostDate, $releaseAddDate, $hasPreview, $jpgStatus, $nfoStatus, $fromName, $layout, $index --}} +{{-- Props: $release (object with ->id, ->guid, ->searchname, ->size, ->postdate, ->adddate, ->haspreview), $layout, $index --}} @props([ - 'releaseName' => '', - 'releaseGuid' => '', - 'releaseId' => null, - 'releaseSize' => 0, - 'releasePostDate' => null, - 'releaseAddDate' => null, - 'hasPreview' => 0, - 'jpgStatus' => 0, - 'nfoStatus' => 0, - 'fromName' => '', + 'release', 'layout' => 2, 'index' => 0, ]) -@if($releaseName && $releaseGuid) +@if(($release->searchname ?? null) && ($release->guid ?? null))
{{-- Release Name --}} - - {{ $releaseName }} + title="{{ $release->searchname }}"> + {{ $release->searchname }} {{-- Info Badges --}}
- @if($releaseSize) + @if($release->size) - {{ number_format($releaseSize / 1073741824, 2) }} GB + {{ number_format($release->size / 1073741824, 2) }} GB @endif - @if($releasePostDate) + @if($release->postdate) - {{ userDate($releasePostDate, 'M d, Y H:i') }} + {{ userDate($release->postdate, 'M d, Y H:i') }} @endif - @if($releaseAddDate) + @if($release->adddate) - {{ userDateDiffForHumans($releaseAddDate) }} + {{ userDateDiffForHumans($release->adddate) }} @endif - @if($hasPreview == 1) + @if(($release->haspreview ?? 0) == 1) @endif - - @if($jpgStatus == 1) - - @endif - - @if($nfoStatus == 1) - - @endif - - @if(!empty($fromName)) - - {{ $fromName }} - - @endif
{{-- Action Buttons --}}
- Download - Details - @if($releaseId) - + @if($release->id) + @endif
@endif - - diff --git a/resources/views/movies/viewmoviefull.blade.php b/resources/views/movies/viewmoviefull.blade.php index 411ac6b6d..ee2c915ef 100644 --- a/resources/views/movies/viewmoviefull.blade.php +++ b/resources/views/movies/viewmoviefull.blade.php @@ -191,48 +191,43 @@
@foreach($releases as $release) -
+
- - {{ $release['name'] }} + + {{ $release->searchname }}
- {{ number_format($release['size'] / 1073741824, 2) }} GB + {{ number_format($release->size / 1073741824, 2) }} GB - @if($release['postdate']) + @if($release->postdate) - Posted: {{ userDate($release['postdate'], 'M d, Y H:i') }} + Posted: {{ userDate($release->postdate, 'M d, Y H:i') }} @endif
- @if(!empty($release['group_name'])) - - {{ $release['group_name'] }} - - @endif - @if($release['postdate']) + @if($release->postdate) - Posted: {{ \Carbon\Carbon::parse($release['postdate'])->format('M d, Y H:i') }} + Posted: {{ \Carbon\Carbon::parse($release->postdate)->format('M d, Y H:i') }} @endif - @if(!empty($release['fromname'])) - - {{ $release['fromname'] }} + @if($release->adddate) + + Added: {{ userDateDiffForHumans($release->adddate) }} @endif
- + Download - - + Details