Merge photo comments feature #114
@ -7,37 +7,73 @@ use App\Facade\UserConfig;
|
|||||||
use App\Helpers\DbHelper;
|
use App\Helpers\DbHelper;
|
||||||
use App\Http\Controllers\Controller;
|
use App\Http\Controllers\Controller;
|
||||||
use App\Http\Requests\StorePhotoCommentRequest;
|
use App\Http\Requests\StorePhotoCommentRequest;
|
||||||
|
use App\Photo;
|
||||||
use App\PhotoComment;
|
use App\PhotoComment;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Support\Facades\App;
|
use Illuminate\Support\Facades\App;
|
||||||
use Illuminate\Support\Facades\Auth;
|
use Illuminate\Support\Facades\Auth;
|
||||||
|
use Illuminate\Support\Facades\Gate;
|
||||||
use Illuminate\Validation\ValidationException;
|
use Illuminate\Validation\ValidationException;
|
||||||
|
|
||||||
class PhotoCommentController extends Controller
|
class PhotoCommentController extends Controller
|
||||||
{
|
{
|
||||||
public function reply(Request $request, $albumUrlAlias, $photoFilename, $commentID)
|
public function moderate(Request $request, $albumUrlAlias, $photoFilename, $commentID)
|
||||||
{
|
{
|
||||||
$album = DbHelper::getAlbumByPath($albumUrlAlias);
|
$album = null;
|
||||||
if (is_null($album))
|
|
||||||
|
/** @var Photo $photo */
|
||||||
|
$photo = null;
|
||||||
|
|
||||||
|
/** @var PhotoComment $comment */
|
||||||
|
$comment = null;
|
||||||
|
|
||||||
|
if (!$this->loadAlbumPhotoComment($albumUrlAlias, $photoFilename, $commentID, $album, $photo, $comment))
|
||||||
{
|
{
|
||||||
App::abort(404);
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Gate::denies('moderate-comments', $photo))
|
||||||
|
{
|
||||||
|
App::abort(403);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->authorizeForUser($this->getUser(), 'view', $album);
|
if (!$comment->isModerated())
|
||||||
|
|
||||||
$photo = PhotoController::loadPhotoByAlbumAndFilename($album, $photoFilename);
|
|
||||||
|
|
||||||
if (!UserConfig::get('allow_photo_comments'))
|
|
||||||
{
|
{
|
||||||
// Not allowed to post comments
|
if ($request->has('approve'))
|
||||||
App::abort(404);
|
{
|
||||||
|
$comment->approved_at = new \DateTime();
|
||||||
|
$comment->approved_user_id = $this->getUser()->id;
|
||||||
|
$comment->save();
|
||||||
|
|
||||||
|
$request->getSession()->flash('success', trans('gallery.photo_comment_approved_successfully'));
|
||||||
|
}
|
||||||
|
else if ($request->has('reject'))
|
||||||
|
{
|
||||||
|
$comment->rejected_at = new \DateTime();
|
||||||
|
$comment->rejected_user_id = $this->getUser()->id;
|
||||||
|
$comment->save();
|
||||||
|
|
||||||
|
$request->getSession()->flash('success', trans('gallery.photo_comment_rejected_successfully'));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$comment = $photo->comments()->where('id', $commentID)->first();
|
return redirect($photo->url());
|
||||||
if (is_null($comment))
|
}
|
||||||
|
|
||||||
|
public function reply(Request $request, $albumUrlAlias, $photoFilename, $commentID)
|
||||||
|
{
|
||||||
|
$album = null;
|
||||||
|
|
||||||
|
/** @var Photo $photo */
|
||||||
|
$photo = null;
|
||||||
|
|
||||||
|
/** @var PhotoComment $comment */
|
||||||
|
$comment = null;
|
||||||
|
|
||||||
|
if (!$this->loadAlbumPhotoComment($albumUrlAlias, $photoFilename, $commentID, $album, $photo, $comment))
|
||||||
{
|
{
|
||||||
App::abort(404);
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Theme::render('partials.photo_comments_reply_form', [
|
return Theme::render('partials.photo_comments_reply_form', [
|
||||||
@ -48,21 +84,17 @@ class PhotoCommentController extends Controller
|
|||||||
|
|
||||||
public function store(Request $request, $albumUrlAlias, $photoFilename)
|
public function store(Request $request, $albumUrlAlias, $photoFilename)
|
||||||
{
|
{
|
||||||
$album = DbHelper::getAlbumByPath($albumUrlAlias);
|
$album = null;
|
||||||
if (is_null($album))
|
|
||||||
|
/** @var Photo $photo */
|
||||||
|
$photo = null;
|
||||||
|
|
||||||
|
/** @var PhotoComment $comment */
|
||||||
|
$comment = null;
|
||||||
|
|
||||||
|
if (!$this->loadAlbumPhotoComment($albumUrlAlias, $photoFilename, 0, $album, $photo, $comment))
|
||||||
{
|
{
|
||||||
App::abort(404);
|
return;
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->authorizeForUser($this->getUser(), 'view', $album);
|
|
||||||
|
|
||||||
$photo = PhotoController::loadPhotoByAlbumAndFilename($album, $photoFilename);
|
|
||||||
|
|
||||||
if (!UserConfig::get('allow_photo_comments'))
|
|
||||||
{
|
|
||||||
// Not allowed to post comments - redirect back to URL
|
|
||||||
return redirect($photo->url());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate and link the parent comment, if provided
|
// Validate and link the parent comment, if provided
|
||||||
@ -96,15 +128,32 @@ class PhotoCommentController extends Controller
|
|||||||
$comment->parent_comment_id = $parentComment->id;
|
$comment->parent_comment_id = $parentComment->id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set the created user ID if we're logged in
|
||||||
$user = $this->getUser();
|
$user = $this->getUser();
|
||||||
if (!is_null($user) && !$user->isAnonymous())
|
if (!is_null($user) && !$user->isAnonymous())
|
||||||
{
|
{
|
||||||
$comment->created_user_id = $user->id;
|
$comment->created_user_id = $user->id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Auto-approve the comment if we're allowed to moderate comments
|
||||||
|
$isAutoApproved = false;
|
||||||
|
if (Gate::allows('moderate-comments', $photo))
|
||||||
|
{
|
||||||
|
$comment->approved_at = new \DateTime();
|
||||||
|
$comment->approved_user_id = $user->id;
|
||||||
|
$isAutoApproved = true;
|
||||||
|
}
|
||||||
|
|
||||||
$comment->save();
|
$comment->save();
|
||||||
|
|
||||||
$request->getSession()->flash('success', trans('gallery.photo_comment_posted_successfully'));
|
if ($isAutoApproved)
|
||||||
|
{
|
||||||
|
$request->getSession()->flash('success', trans('gallery.photo_comment_posted_successfully'));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$request->getSession()->flash('success', trans('gallery.photo_comment_posted_successfully_pending_moderation'));
|
||||||
|
}
|
||||||
|
|
||||||
if ($request->isXmlHttpRequest())
|
if ($request->isXmlHttpRequest())
|
||||||
{
|
{
|
||||||
@ -132,4 +181,37 @@ class PhotoCommentController extends Controller
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function loadAlbumPhotoComment($albumUrlAlias, $photoFilename, $commentID, &$album, &$photo, &$comment)
|
||||||
|
{
|
||||||
|
$album = DbHelper::getAlbumByPath($albumUrlAlias);
|
||||||
|
if (is_null($album))
|
||||||
|
{
|
||||||
|
App::abort(404);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->authorizeForUser($this->getUser(), 'view', $album);
|
||||||
|
|
||||||
|
$photo = PhotoController::loadPhotoByAlbumAndFilename($album, $photoFilename);
|
||||||
|
|
||||||
|
if (!UserConfig::get('allow_photo_comments'))
|
||||||
|
{
|
||||||
|
// Not allowed to post comments
|
||||||
|
App::abort(404);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (intval($commentID > 0))
|
||||||
|
{
|
||||||
|
$comment = $photo->comments()->where('id', $commentID)->first();
|
||||||
|
if (is_null($comment))
|
||||||
|
{
|
||||||
|
App::abort(404);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
@ -52,13 +52,6 @@ class Photo extends Model
|
|||||||
return $this->belongsTo(Album::class);
|
return $this->belongsTo(Album::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function approvedComments()
|
|
||||||
{
|
|
||||||
return $this->hasMany(PhotoComment::class)
|
|
||||||
->whereNull('parent_comment_id')
|
|
||||||
->whereNotNull('approved_at');
|
|
||||||
}
|
|
||||||
|
|
||||||
public function comments()
|
public function comments()
|
||||||
{
|
{
|
||||||
return $this->hasMany(PhotoComment::class);
|
return $this->hasMany(PhotoComment::class);
|
||||||
@ -89,6 +82,15 @@ class Photo extends Model
|
|||||||
return $this->belongsToMany(Label::class, 'photo_labels');
|
return $this->belongsToMany(Label::class, 'photo_labels');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function moderateCommentUrl($commentID = -1)
|
||||||
|
{
|
||||||
|
return route('moderatePhotoComment', [
|
||||||
|
'albumUrlAlias' => $this->album->url_path,
|
||||||
|
'photoFilename' => $this->storage_file_name,
|
||||||
|
'commentID' => $commentID
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
public function postCommentUrl()
|
public function postCommentUrl()
|
||||||
{
|
{
|
||||||
return route('postPhotoComment', [
|
return route('postPhotoComment', [
|
||||||
|
@ -17,16 +17,6 @@ class PhotoComment extends Model
|
|||||||
'comment'
|
'comment'
|
||||||
];
|
];
|
||||||
|
|
||||||
public function approvedBy()
|
|
||||||
{
|
|
||||||
return $this->belongsTo(User::class, 'approved_user_id');
|
|
||||||
}
|
|
||||||
|
|
||||||
public function approvedChildren()
|
|
||||||
{
|
|
||||||
return $this->children()->whereNotNull('approved_at');
|
|
||||||
}
|
|
||||||
|
|
||||||
public function authorDisplayName()
|
public function authorDisplayName()
|
||||||
{
|
{
|
||||||
return is_null($this->createdBy) ? $this->name : $this->createdBy->name;
|
return is_null($this->createdBy) ? $this->name : $this->createdBy->name;
|
||||||
@ -56,6 +46,24 @@ class PhotoComment extends Model
|
|||||||
return $depth;
|
return $depth;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function isApproved()
|
||||||
|
{
|
||||||
|
return (
|
||||||
|
!is_null($this->approved_user_id) &&
|
||||||
|
!is_null($this->approved_at) &&
|
||||||
|
is_null($this->rejected_user_id) &&
|
||||||
|
is_null($this->rejected_at)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function isModerated()
|
||||||
|
{
|
||||||
|
return (
|
||||||
|
(!is_null($this->approved_user_id) && !is_null($this->approved_at)) ||
|
||||||
|
(!is_null($this->rejected_user_id) && !is_null($this->rejected_at))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
public function parent()
|
public function parent()
|
||||||
{
|
{
|
||||||
return $this->belongsTo(PhotoComment::class, 'parent_comment_id');
|
return $this->belongsTo(PhotoComment::class, 'parent_comment_id');
|
||||||
|
@ -93,6 +93,17 @@ class AlbumPolicy
|
|||||||
return $this->userHasPermission($user, $album, 'manipulate-photos');
|
return $this->userHasPermission($user, $album, 'manipulate-photos');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function moderateComments(User $user, Album $album)
|
||||||
|
{
|
||||||
|
if ($user->id == $album->user_id)
|
||||||
|
{
|
||||||
|
// The album's owner and can do everything
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->userHasPermission($user, $album, 'moderate-comments');
|
||||||
|
}
|
||||||
|
|
||||||
public function uploadPhotos(User $user, Album $album)
|
public function uploadPhotos(User $user, Album $album)
|
||||||
{
|
{
|
||||||
if ($user->id == $album->user_id)
|
if ($user->id == $album->user_id)
|
||||||
|
@ -61,4 +61,15 @@ class PhotoPolicy
|
|||||||
|
|
||||||
return $user->can('manipulate-photos', $photo->album);
|
return $user->can('manipulate-photos', $photo->album);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function moderateComments(User $user, Photo $photo)
|
||||||
|
{
|
||||||
|
if ($user->id == $photo->user_id)
|
||||||
|
{
|
||||||
|
// The photo's owner can do everything
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $user->can('moderate-comments', $photo->album);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,34 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
|
||||||
|
class AddCommentRejectedColumns extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function up()
|
||||||
|
{
|
||||||
|
Schema::table('photo_comments', function (Blueprint $table) {
|
||||||
|
$table->unsignedInteger('rejected_user_id')->nullable(true);
|
||||||
|
$table->dateTime('rejected_at')->nullable(true);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function down()
|
||||||
|
{
|
||||||
|
Schema::table('photo_comments', function (Blueprint $table) {
|
||||||
|
$table->dropColumn('rejected_user_id');
|
||||||
|
$table->dropColumn('rejected_at');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
@ -139,5 +139,13 @@ class PermissionsSeeder extends Seeder
|
|||||||
'is_default' => false,
|
'is_default' => false,
|
||||||
'sort_order' => 60
|
'sort_order' => 60
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
// album:moderate-comments = moderate comments posted on photos
|
||||||
|
DatabaseSeeder::createOrUpdate('permissions', [
|
||||||
|
'section' => 'album',
|
||||||
|
'description' => 'moderate-comments',
|
||||||
|
'is_default' => false,
|
||||||
|
'sort_order' => 70
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -34,8 +34,14 @@ return [
|
|||||||
'other_albums_description' => 'You may also be interested in the following albums.',
|
'other_albums_description' => 'You may also be interested in the following albums.',
|
||||||
'other_albums_description_empty' => 'The <b>:album_name</b> album does not contain any photos - however you may also be interested in the following albums.',
|
'other_albums_description_empty' => 'The <b>:album_name</b> album does not contain any photos - however you may also be interested in the following albums.',
|
||||||
'other_albums_heading' => 'More Albums in :album_name',
|
'other_albums_heading' => 'More Albums in :album_name',
|
||||||
'photo_comment_posted_successfully' => 'Your comment was posted successfully and will appear after it has been moderated.',
|
'photo_comment_pending_approval' => 'Pending Approval',
|
||||||
|
'photo_comment_approved_successfully' => 'The comment was approved.',
|
||||||
|
'photo_comment_posted_successfully' => 'Your comment was posted successfully.',
|
||||||
|
'photo_comment_posted_successfully_pending_moderation' => 'Your comment was posted successfully and will appear after it has been moderated.',
|
||||||
|
'photo_comment_rejected_successfully' => 'The comment was rejected.',
|
||||||
|
'photo_comments_approve_action' => 'Approve',
|
||||||
'photo_comments_heading' => 'Comments',
|
'photo_comments_heading' => 'Comments',
|
||||||
|
'photo_comments_reject_action' => 'Reject',
|
||||||
'photo_comments_reply_action' => 'Reply',
|
'photo_comments_reply_action' => 'Reply',
|
||||||
'photo_comments_reply_form_heading' => 'Leave a reply',
|
'photo_comments_reply_form_heading' => 'Leave a reply',
|
||||||
'photo_comments_reply_form_p1' => 'Complete the form below to start a new reply thread.',
|
'photo_comments_reply_form_p1' => 'Complete the form below to start a new reply thread.',
|
||||||
|
@ -16,6 +16,7 @@ return [
|
|||||||
'edit' => 'Manage this album',
|
'edit' => 'Manage this album',
|
||||||
'list' => 'See this album in listings',
|
'list' => 'See this album in listings',
|
||||||
'manipulate-photos' => 'Manipulate photos in this album',
|
'manipulate-photos' => 'Manipulate photos in this album',
|
||||||
|
'moderate-comments' => 'Moderate comments in this album',
|
||||||
'upload-photos' => 'Upload photos into this album',
|
'upload-photos' => 'Upload photos into this album',
|
||||||
'view' => 'Access this album'
|
'view' => 'Access this album'
|
||||||
]
|
]
|
||||||
|
@ -29,6 +29,7 @@
|
|||||||
@include(Theme::viewName('partials.permission_checkbox'), ['permission' => Theme::getPermission($all_permissions, 'album', 'manipulate-photos')])
|
@include(Theme::viewName('partials.permission_checkbox'), ['permission' => Theme::getPermission($all_permissions, 'album', 'manipulate-photos')])
|
||||||
@include(Theme::viewName('partials.permission_checkbox'), ['permission' => Theme::getPermission($all_permissions, 'album', 'change-photo-metadata')])
|
@include(Theme::viewName('partials.permission_checkbox'), ['permission' => Theme::getPermission($all_permissions, 'album', 'change-photo-metadata')])
|
||||||
@include(Theme::viewName('partials.permission_checkbox'), ['permission' => Theme::getPermission($all_permissions, 'album', 'delete-photos')])
|
@include(Theme::viewName('partials.permission_checkbox'), ['permission' => Theme::getPermission($all_permissions, 'album', 'delete-photos')])
|
||||||
|
@include(Theme::viewName('partials.permission_checkbox'), ['permission' => Theme::getPermission($all_permissions, 'album', 'moderate-comments')])
|
||||||
</div>
|
</div>
|
||||||
@endif
|
@endif
|
||||||
</div>
|
</div>
|
||||||
|
@ -7,11 +7,13 @@
|
|||||||
<hr/>
|
<hr/>
|
||||||
@include(Theme::viewName('partials.photo_comments_reply_form'))
|
@include(Theme::viewName('partials.photo_comments_reply_form'))
|
||||||
|
|
||||||
@if ($photo->approvedComments()->count() > 0)
|
@foreach ($photo->comments()->whereNull('parent_comment_id')->get() as $comment)
|
||||||
@foreach ($photo->approvedComments as $comment)
|
@if ($comment->isApproved())
|
||||||
@include(Theme::viewName('partials.photo_single_comment'))
|
@include(Theme::viewName('partials.photo_single_comment'))
|
||||||
@endforeach
|
@elseif (!$comment->isModerated() && Gate::allows('moderate-comments', $photo))
|
||||||
@endif
|
@include(Theme::viewName('partials.photo_single_comment_moderate'))
|
||||||
|
@endif
|
||||||
|
@endforeach
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -16,7 +16,11 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
@if (!$is_reply)
|
@if (!$is_reply)
|
||||||
@foreach ($comment->approvedChildren as $childComment)
|
@foreach ($comment->children as $childComment)
|
||||||
@include(Theme::viewName('partials.photo_single_comment'), ['comment' => $childComment])
|
@if ($childComment->isApproved())
|
||||||
|
@include(Theme::viewName('partials.photo_single_comment'), ['comment' => $childComment])
|
||||||
|
@elseif (!$childComment->isModerated() && Gate::allows('moderate-comments', $photo))
|
||||||
|
@include(Theme::viewName('partials.photo_single_comment_moderate'), ['comment' => $childComment])
|
||||||
|
@endif
|
||||||
@endforeach
|
@endforeach
|
||||||
@endif
|
@endif
|
@ -0,0 +1,17 @@
|
|||||||
|
<div class="card photo-comment mt-2 border-warning" data-comment-id="{{ $comment->id }}" style="margin-left: {{ $comment->depth() * 20 }}px;">
|
||||||
|
<div class="card-header bg-warning border-warning text-white">
|
||||||
|
<b>@lang('gallery.photo_comment_pending_approval')</b>
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<img class="img-thumbnail rounded float-left mr-3 mb-2" src="{{ Theme::gravatarUrl($comment->email) }}" alt="{{ $comment->authorDisplayName() }}" title="{{ $comment->authorDisplayName() }}">
|
||||||
|
<h5 class="card-title mt-1"><b>{{ $comment->authorDisplayName() }}</b></h5>
|
||||||
|
<h6 class="card-subtitle mb-4 text-muted">{{ date(UserConfig::get('date_format'), strtotime($comment->created_at)) }}</h6>
|
||||||
|
{!! $comment->textAsHtml() !!}
|
||||||
|
|
||||||
|
<form action="{{ $photo->moderateCommentUrl($comment->id) }}" method="post">
|
||||||
|
{{ csrf_field() }}
|
||||||
|
<button type="submit" name="approve" class="btn btn-success card-link">@lang('gallery.photo_comments_approve_action')</button>
|
||||||
|
<button type="submit" name="reject" class="btn btn-outline-danger card-link">@lang('gallery.photo_comments_reject_action')</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
@ -109,6 +109,9 @@ Route::get('exif/{albumUrlAlias}/{photoFilename}', 'Gallery\PhotoController@show
|
|||||||
Route::post('p/{albumUrlAlias}/{photoFilename}/comments', 'Gallery\PhotoCommentController@store')
|
Route::post('p/{albumUrlAlias}/{photoFilename}/comments', 'Gallery\PhotoCommentController@store')
|
||||||
->name('postPhotoComment')
|
->name('postPhotoComment')
|
||||||
->where('albumUrlAlias', '.*');
|
->where('albumUrlAlias', '.*');
|
||||||
|
Route::post('p/{albumUrlAlias}/{photoFilename}/comments/moderate/{commentID}', 'Gallery\PhotoCommentController@moderate')
|
||||||
|
->name('moderatePhotoComment')
|
||||||
|
->where('albumUrlAlias', '.*');
|
||||||
Route::get('p/{albumUrlAlias}/{photoFilename}/comments/reply/{commentID}', 'Gallery\PhotoCommentController@reply')
|
Route::get('p/{albumUrlAlias}/{photoFilename}/comments/reply/{commentID}', 'Gallery\PhotoCommentController@reply')
|
||||||
->name('replyPhotoComment')
|
->name('replyPhotoComment')
|
||||||
->where('albumUrlAlias', '.*');
|
->where('albumUrlAlias', '.*');
|
||||||
|
Loading…
Reference in New Issue
Block a user