blue-twilight/app/Http/Controllers/Gallery/PhotoController.php

206 lines
6.2 KiB
PHP

<?php
namespace App\Http\Controllers\Gallery;
use App\Album;
use App\Facade\Theme;
use App\Facade\UserConfig;
use App\Helpers\DbHelper;
use App\Http\Controllers\Controller;
use App\Photo;
use App\VisitorHit;
use GuzzleHttp\Psr7\Stream;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Gate;
use Symfony\Component\HttpFoundation\Request;
use function GuzzleHttp\Psr7\mimetype_from_extension;
class PhotoController extends Controller
{
public function download(Request $request, $albumUrlAlias, $photoFilename)
{
$album = DbHelper::getAlbumByPath($albumUrlAlias);
if (is_null($album))
{
App::abort(404);
return null;
}
$this->authorizeForUser($this->getUser(), 'view', $album);
if (UserConfig::get('hotlink_protection'))
{
$referrer = $request->headers->get('Referer');
if (!is_null($referrer))
{
$hostname = parse_url($referrer, PHP_URL_HOST);
if (strtolower($hostname) != strtolower($request->getHttpHost()))
{
App::abort(403);
return null;
}
}
else
{
App::abort(403);
return null;
}
}
$photo = PhotoController::loadPhotoByAlbumAndFilename($album, $photoFilename);
$thumbnail = $request->get('t');
if (is_null($thumbnail))
{
$this->authorizeForUser($this->getUser(), 'photo.download_original', $photo);
}
// Record the visit to the photo
if (UserConfig::get('enable_visitor_hits'))
{
DB::transaction(function () use ($album, $photo, $request, $thumbnail)
{
$photo->hits_download++;
$photo->save();
VisitorHit::fromRequest($request, $album->id, $photo->id, (is_null($thumbnail) ? 'original' : $thumbnail));
});
}
/** @var Stream $photoStream */
$photoStream = $album->getAlbumSource()->fetchPhotoContent($photo, $thumbnail);
$mimeType = mimetype_from_extension(pathinfo($photo->storage_file_name, PATHINFO_EXTENSION));
return response()->stream(
function() use ($photoStream)
{
echo $photoStream;
},
200,
[
'Content-Length' => strlen($photoStream->getContents()),
'Content-Type' => $mimeType
]
);
}
public function show(Request $request, $albumUrlAlias, $photoFilename)
{
$album = DbHelper::getAlbumByPath($albumUrlAlias);
if (is_null($album))
{
App::abort(404);
return null;
}
$this->authorizeForUser($this->getUser(), 'view', $album);
$photo = PhotoController::loadPhotoByAlbumAndFilename($album, $photoFilename);
$isOriginalAllowed = Gate::forUser($this->getUser())->allows('photo.download_original', $photo);
// Load the Next/Previous buttons
$thisPhotoDate = is_null($photo->taken_at) ? $photo->created_at : $photo->taken_at;
// I don't like the idea of using a totally raw SQL query, but it's the only sure-fire way to number the rows
// so we can get the previous/next photos accurately - and we don't have to load all data for the photo objects
$previousPhoto = null;
$nextPhoto = null;
$allAlbumPhotos = DB::select(
DB::raw(
'SELECT p.id, (@row_number:=@row_number + 1) AS row_number
FROM photos p, (SELECT @row_number:=0) AS t
WHERE p.album_id = :album_id
ORDER BY COALESCE(p.taken_at, p.created_at), p.name, p.id;'
),
[
'album_id' => $album->id
]
);
for ($i = 0; $i < count($allAlbumPhotos); $i++)
{
if ($allAlbumPhotos[$i]->id === $photo->id)
{
if ($i > 0)
{
$previousPhoto = Photo::where('id', $allAlbumPhotos[$i - 1]->id)->first();
}
if ($i + 1 < count($allAlbumPhotos))
{
$nextPhoto = Photo::where('id', $allAlbumPhotos[$i + 1]->id)->first();
}
break;
}
}
// Record the visit to the photo
if (UserConfig::get('enable_visitor_hits'))
{
DB::transaction(function () use ($album, $photo, $request)
{
$photo->hits++;
$photo->save();
VisitorHit::fromRequest($request, $album->id, $photo->id);
});
}
return Theme::render('gallery.photo', [
'album' => $album,
'is_original_allowed' => $isOriginalAllowed,
'next_photo' => $nextPhoto,
'photo' => $photo,
'previous_photo' => $previousPhoto,
'success' => $request->getSession()->get('success')
]);
}
public function showExifData(Request $request, $albumUrlAlias, $photoFilename)
{
$album = DbHelper::getAlbumByPath($albumUrlAlias);
if (is_null($album))
{
App::abort(404);
return null;
}
$this->authorizeForUser($this->getUser(), 'view', $album);
$photo = PhotoController::loadPhotoByAlbumAndFilename($album, $photoFilename);
$this->authorizeForUser($this->getUser(), 'changeMetadata', $photo);
$exifData = print_r(unserialize(base64_decode($photo->raw_exif_data)), true);
return Theme::render('gallery.photo_exif', [
'album' => $album,
'exif_data' => $exifData,
'photo' => $photo
]);
}
/**
* @param $id
* @return Photo
*/
public static function loadPhotoByAlbumAndFilename(Album $album, $filename)
{
$photo = Photo::where([
['album_id', $album->id],
['storage_file_name', $filename]
])->first();
if (is_null($photo))
{
App::abort(404);
return null;
}
return $photo;
}
}