#29: Album permissions are now checked when retrieving photos linked with a label. Labels are displayed in the gallery with their own views.
This commit is contained in:
parent
88d660d92e
commit
f46d9e1101
@ -9,6 +9,21 @@ use Illuminate\Support\Facades\Auth;
|
||||
|
||||
class DbHelper
|
||||
{
|
||||
public static function getAlbumIDsForCurrentUser()
|
||||
{
|
||||
$query = self::getAlbumsForCurrentUser_NonPaged();
|
||||
$query->select('albums.id');
|
||||
|
||||
$ids = [];
|
||||
|
||||
foreach ($query->get() as $album)
|
||||
{
|
||||
$ids[] = $album->id;
|
||||
}
|
||||
|
||||
return $ids;
|
||||
}
|
||||
|
||||
public static function getAlbumsForCurrentUser($parentID = -1)
|
||||
{
|
||||
$query = self::getAlbumsForCurrentUser_NonPaged();
|
||||
|
66
app/Http/Controllers/Gallery/LabelController.php
Normal file
66
app/Http/Controllers/Gallery/LabelController.php
Normal file
@ -0,0 +1,66 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Gallery;
|
||||
|
||||
use App\Facade\Theme;
|
||||
use App\Facade\UserConfig;
|
||||
use App\Helpers\DbHelper;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Label;
|
||||
use Illuminate\Support\Facades\App;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
|
||||
class LabelController extends Controller
|
||||
{
|
||||
public function index(Request $request, $labelAlias)
|
||||
{
|
||||
$label = Label::where('url_alias', $labelAlias)->first();
|
||||
if (is_null($label))
|
||||
{
|
||||
App::abort(404);
|
||||
}
|
||||
|
||||
$validViews = UserConfig::allowedAlbumViews();
|
||||
$requestedView = strtolower($request->get('view'));
|
||||
if (!in_array($requestedView, $validViews))
|
||||
{
|
||||
$requestedView = $validViews[0];
|
||||
}
|
||||
|
||||
$allowedAlbumIDs = DbHelper::getAlbumIDsForCurrentUser();
|
||||
|
||||
if ($label->photos()->count() == 0)
|
||||
{
|
||||
$requestedView = 'empty';
|
||||
$photos = [];
|
||||
}
|
||||
else if ($requestedView != 'slideshow')
|
||||
{
|
||||
$photos = $label->photos()
|
||||
->where('album_id', $allowedAlbumIDs)
|
||||
->orderBy(DB::raw('COALESCE(photos.taken_at, photos.created_at)'))
|
||||
->paginate(UserConfig::get('items_per_page'));
|
||||
}
|
||||
else
|
||||
{
|
||||
// The slideshow view needs access to all photos, not paged
|
||||
$photos = $label->photos()
|
||||
->where('album_id', $allowedAlbumIDs)
|
||||
->orderBy(DB::raw('COALESCE(photos.taken_at, photos.created_at)'))
|
||||
->get();
|
||||
}
|
||||
|
||||
if (count($photos) == 0)
|
||||
{
|
||||
$requestedView = 'empty';
|
||||
}
|
||||
|
||||
return Theme::render(sprintf('gallery.label_%s', $requestedView), [
|
||||
'allowed_views' => $validViews,
|
||||
'current_view' => $requestedView,
|
||||
'label' => $label,
|
||||
'photos' => $photos
|
||||
]);
|
||||
}
|
||||
}
|
@ -2,6 +2,7 @@
|
||||
|
||||
namespace App;
|
||||
|
||||
use App\Helpers\MiscHelper;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class Label extends Model
|
||||
@ -12,9 +13,14 @@ class Label extends Model
|
||||
* @var array
|
||||
*/
|
||||
protected $fillable = [
|
||||
'name'
|
||||
'name', 'url_alias'
|
||||
];
|
||||
|
||||
public function generateAlias()
|
||||
{
|
||||
$this->url_alias = preg_replace('/[^a-z0-9\-]/', '-', strtolower($this->name));
|
||||
}
|
||||
|
||||
public function photos()
|
||||
{
|
||||
return $this->belongsToMany(Photo::class, 'photo_labels');
|
||||
|
13
app/ModelObservers/LabelObserver.php
Normal file
13
app/ModelObservers/LabelObserver.php
Normal file
@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace App\ModelObservers;
|
||||
|
||||
use App\Label;
|
||||
|
||||
class LabelObserver
|
||||
{
|
||||
public function creating(Label $label)
|
||||
{
|
||||
$label->generateAlias();
|
||||
}
|
||||
}
|
@ -8,7 +8,9 @@ use App\Helpers\ImageHelper;
|
||||
use App\Helpers\MiscHelper;
|
||||
use App\Helpers\ThemeHelper;
|
||||
use App\Helpers\ValidationHelper;
|
||||
use App\Label;
|
||||
use App\ModelObservers\AlbumObserver;
|
||||
use App\ModelObservers\LabelObserver;
|
||||
use Illuminate\Database\QueryException;
|
||||
use Illuminate\Mail\Mailer;
|
||||
use Illuminate\Pagination\LengthAwarePaginator;
|
||||
@ -47,6 +49,7 @@ class AppServiceProvider extends ServiceProvider
|
||||
|
||||
// Model observers
|
||||
Album::observe(AlbumObserver::class);
|
||||
Label::observe(LabelObserver::class);
|
||||
|
||||
// Configure our default pager
|
||||
if (MiscHelper::isAppInstalled())
|
||||
|
@ -16,6 +16,7 @@ class CreatePhotoLabelsTable extends Migration
|
||||
Schema::create('labels', function ($table) {
|
||||
$table->increments('id');
|
||||
$table->string('name');
|
||||
$table->string('url_alias');
|
||||
$table->timestamps();
|
||||
});
|
||||
|
||||
|
@ -10,6 +10,10 @@ return [
|
||||
'back_to_album' => 'Back to :name',
|
||||
'index_no_results_heading' => 'Start something amazing',
|
||||
'index_no_results_text' => 'This gallery is currently empty. If you are the owner of this gallery, you can create new albums and upload photos using the :admin_link.',
|
||||
'label_intro' => 'All photos tagged with the label ":name".',
|
||||
'label_no_results_text' => 'No photos are tagged with the label ":name".',
|
||||
'label_no_results_text_2' => 'If you are an admin of this gallery, you can upload and tag photos in the :admin_link.',
|
||||
'labels' => 'Labels:',
|
||||
'manage_album_link' => 'Manage',
|
||||
'manage_album_link_2' => 'Manage Album',
|
||||
'open_album_link' => 'Open Album',
|
||||
|
46
resources/views/themes/base/gallery/label_default.blade.php
Normal file
46
resources/views/themes/base/gallery/label_default.blade.php
Normal file
@ -0,0 +1,46 @@
|
||||
@extends('themes.base.layout')
|
||||
@section('title', $label->name)
|
||||
|
||||
@section('breadcrumb')
|
||||
<li class="breadcrumb-item"><a href="{{ route('home') }}"><i class="fa fa-fw fa-home"></i></a></li>
|
||||
<li class="breadcrumb-item">{{ $label->name }}</li>
|
||||
@endsection
|
||||
|
||||
@section('content')
|
||||
<div class="container album-container">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<div class="pull-right">
|
||||
@include(\App\Facade\Theme::viewName('partials.album_view_selector'))
|
||||
</div>
|
||||
|
||||
<h1 class="page-title">{{ $label->name }}</h1>
|
||||
<p>@lang('gallery.label_intro', ['name' => $label->name])</p>
|
||||
<div class="clearfix"><!-- --></div>
|
||||
<hr/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
@foreach ($photos as $photo)
|
||||
<div class="col-sm-6 col-md-4 photo mb-3">
|
||||
<div class="card">
|
||||
<img src="{{ $photo->thumbnailUrl('preview') }}" alt="" class="card-img-top"/>
|
||||
<div class="card-body">
|
||||
<h4 class="card-title"><a href="{{ $photo->url() }}">{{ $photo->name }}</a></h4>
|
||||
</div>
|
||||
<div class="card-footer">
|
||||
<small class="text-muted"><i class="fa fa-fw fa-calendar"></i> {{ date(UserConfig::get('date_format'), strtotime(!is_null($photo->taken_at) ? $photo->taken_at : $photo->created_at)) }}</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endforeach
|
||||
|
||||
<div class="row" style="margin-top: 15px;">
|
||||
<div class="col text-center">
|
||||
{{ $photos->links() }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
21
resources/views/themes/base/gallery/label_empty.blade.php
Normal file
21
resources/views/themes/base/gallery/label_empty.blade.php
Normal file
@ -0,0 +1,21 @@
|
||||
@extends('themes.base.layout')
|
||||
@section('title', $label->name)
|
||||
|
||||
@section('breadcrumb')
|
||||
<li class="breadcrumb-item"><a href="{{ route('home') }}"><i class="fa fa-fw fa-home"></i></a></li>
|
||||
<li class="breadcrumb-item">{{ $label->name }}</li>
|
||||
@endsection
|
||||
|
||||
@section('content')
|
||||
<div class="container album-container">
|
||||
<div class="row">
|
||||
<div class="col text-center">
|
||||
<h1>@lang('gallery.album_no_results_heading')</h1>
|
||||
<p style="line-height: 1.6em;">@lang('gallery.label_no_results_text', ['name' => $label->name])</p>
|
||||
<p style="margin-bottom: 30px; line-height: 1.6em;">@lang('gallery.label_no_results_text_2', ['admin_link' => sprintf('<a href="%s">%s</a>', route('admin'), trans('admin.title'))])</p>
|
||||
|
||||
<img src="{{ asset('themes/base/images/smartphone-photo.jpg') }}" class="img-fluid rounded" style="display: inline;" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
@ -0,0 +1,76 @@
|
||||
@extends('themes.base.layout')
|
||||
@section('title', $label->name)
|
||||
|
||||
@section('breadcrumb')
|
||||
<li class="breadcrumb-item"><a href="{{ route('home') }}"><i class="fa fa-fw fa-home"></i></a></li>
|
||||
<li class="breadcrumb-item">{{ $label->name }}</li>
|
||||
@endsection
|
||||
|
||||
@section('content')
|
||||
<div class="container album-container album-slideshow-container" id="slideshow-container">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<div class="pull-right">
|
||||
@include(\App\Facade\Theme::viewName('partials.album_view_selector'))
|
||||
</div>
|
||||
|
||||
<h1 class="page-title">{{ $label->name }}</h1>
|
||||
<p>@lang('gallery.label_intro', ['name' => $label->name])</p>
|
||||
<div class="clearfix"><!-- --></div>
|
||||
<hr/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col text-center">
|
||||
<div class="pull-right">
|
||||
<div class="btn btn-group">
|
||||
<button class="btn btn-secondary" v-on:click="pauseSlideshow" v-bind:disabled="isPaused" v-if="isRunning"><i class="fa fa-fw fa-pause"></i></button>
|
||||
<button class="btn btn-secondary" v-on:click="continueSlideshow" v-bind:disabled="!isPaused" v-if="isRunning"><i class="fa fa-fw fa-play"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="image-preview" v-if="current !== null">
|
||||
<a v-bind:href="current.info_url" v-bind:title="current.description">
|
||||
<img class="rounded thumbnail" v-bind:src="current.original_url" v-bind:alt="current.name" v-bind:title="current.description"/>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row" style="margin-top: 15px;">
|
||||
<div class="col">
|
||||
<div class="thumbnails">
|
||||
@foreach ($photos as $photo)
|
||||
<a href="{{ $photo->url() }}" v-on:click="changeCurrentImage({{ $photo->id }}); $event.preventDefault();">
|
||||
<img class="ss-thumbnail rounded" src="{{ $photo->thumbnailUrl('slideshow-tiny') }}" alt="{{ $photo->name }}" title="{{ $photo->description }}" data-photo-id="{{ $photo->id }}" data-original-url="{{ $photo->thumbnailUrl('fullsize') }}" data-info-url="{{ $photo->url() }}" />
|
||||
</a>
|
||||
@endforeach
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
|
||||
@push('scripts')
|
||||
<script type="text/javascript">
|
||||
// TODO make this timeout configurable
|
||||
var viewModel = new SlideShowViewModel(5000);
|
||||
|
||||
$(document).ready(function() {
|
||||
$('img.ss-thumbnail').each(function(index, element)
|
||||
{
|
||||
viewModel.data.images.push({
|
||||
'id': $(element).data('photo-id'),
|
||||
'name': $(element).attr('alt'),
|
||||
'description': $(element).attr('title'),
|
||||
'original_url': $(element).data('original-url'),
|
||||
'info_url': $(element).data('info-url')
|
||||
});
|
||||
});
|
||||
|
||||
var app = new Vue(viewModel);
|
||||
app.startSlideshow();
|
||||
});
|
||||
</script>
|
||||
@endpush
|
@ -29,10 +29,23 @@
|
||||
@if ($is_original_allowed)
|
||||
<a href="{{ $photo->thumbnailUrl() }}">
|
||||
@endif
|
||||
<img src="{{ $photo->thumbnailUrl('fullsize') }}" alt="" class="img-thumbnail"/>
|
||||
<img src="{{ $photo->thumbnailUrl('fullsize') }}" alt="" class="img-thumbnail mb-4"/>
|
||||
@if ($is_original_allowed)
|
||||
</a>
|
||||
@endif
|
||||
|
||||
@if ($photo->labels()->count() > 0)
|
||||
<h4>@lang('gallery.labels')</h4>
|
||||
<ul class="nav nav-pills mb-4">
|
||||
@foreach ($photo->labels()->orderBy('name')->get() as $label)
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{{ route('viewLabel', ['labelAlias' => $label->url_alias]) }}">
|
||||
<i class="fa fa-tag"></i> {{ $label->name }}
|
||||
</a>
|
||||
</li>
|
||||
@endforeach
|
||||
</ul>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
<div class="col-sm-4">
|
||||
|
@ -88,4 +88,7 @@ Route::get('p/{albumUrlAlias}/{photoFilename}', 'Gallery\PhotoController@show')
|
||||
->where('albumUrlAlias', '.*');
|
||||
Route::get('i/{albumUrlAlias}/{photoFilename}', 'Gallery\PhotoController@download')
|
||||
->name('downloadPhoto')
|
||||
->where('albumUrlAlias', '.*');
|
||||
->where('albumUrlAlias', '.*');
|
||||
Route::get('label/{labelAlias}', 'Gallery\LabelController@index')
|
||||
->name('viewLabel')
|
||||
->where('labelAlias', '.*');
|
Loading…
Reference in New Issue
Block a user