Add all files
This commit is contained in:
@@ -0,0 +1,620 @@
|
||||
<?php
|
||||
|
||||
namespace Paymenter\Extensions\Others\SocialBase\Http\Controllers;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\User;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Event;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Paymenter\Extensions\Others\SocialBase\Models\UserProfile;
|
||||
use Paymenter\Extensions\Others\SocialBase\Models\ProfileComment;
|
||||
|
||||
class ProfileController extends Controller
|
||||
{
|
||||
/**
|
||||
* Redirect to logged-in user's profile
|
||||
*/
|
||||
public function redirectToOwnProfile()
|
||||
{
|
||||
return redirect()->route('socialbase.profile.show', ['user' => Auth::id()]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Show user profile
|
||||
*/
|
||||
public function show(User $user)
|
||||
{
|
||||
$profile = UserProfile::getForUser($user->id);
|
||||
|
||||
// If no profile exists, show a message
|
||||
if (!$profile) {
|
||||
return view('socialbase::profile.no-profile', [
|
||||
'user' => $user,
|
||||
]);
|
||||
}
|
||||
|
||||
// Check if profile is viewable
|
||||
if (!$profile->isViewableBy(Auth::user())) {
|
||||
abort(403, 'This profile is private.');
|
||||
}
|
||||
|
||||
return view('socialbase::profile.show', [
|
||||
'user' => $user,
|
||||
'profile' => $profile,
|
||||
'isOwner' => Auth::check() && Auth::id() === $user->id,
|
||||
'canComment' => Auth::check() && $profile->allowsComments() && Auth::id() !== $user->id,
|
||||
'title' => $profile->display_name . '\'s Profile',
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Show profile edit form
|
||||
*/
|
||||
public function edit()
|
||||
{
|
||||
$user = Auth::user();
|
||||
$profile = UserProfile::getForUser($user->id);
|
||||
|
||||
// If no profile exists, create one for editing
|
||||
if (!$profile) {
|
||||
$profile = UserProfile::createForUser($user->id);
|
||||
}
|
||||
|
||||
return view('socialbase::profile.edit', [
|
||||
'user' => $user,
|
||||
'profile' => $profile,
|
||||
'title' => 'Edit Profile',
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Show profile settings
|
||||
*/
|
||||
public function settings()
|
||||
{
|
||||
$user = Auth::user();
|
||||
$profile = UserProfile::getForUser($user->id);
|
||||
|
||||
// If no profile exists, create one for settings
|
||||
if (!$profile) {
|
||||
$profile = UserProfile::createForUser($user->id);
|
||||
}
|
||||
|
||||
return view('socialbase::profile.settings', [
|
||||
'user' => $user,
|
||||
'profile' => $profile,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update profile
|
||||
*/
|
||||
public function update(Request $request)
|
||||
{
|
||||
$validator = Validator::make($request->all(), [
|
||||
'display_name' => 'nullable|string|max:255',
|
||||
'bio' => 'nullable|string|max:1000',
|
||||
'location' => 'nullable|string|max:255',
|
||||
'website' => 'nullable|url|max:255',
|
||||
'is_public' => 'boolean',
|
||||
'show_email' => 'boolean',
|
||||
'show_joined_date' => 'boolean',
|
||||
'allow_comments' => 'boolean',
|
||||
]);
|
||||
|
||||
if ($validator->fails()) {
|
||||
return back()->withErrors($validator)->withInput();
|
||||
}
|
||||
|
||||
$user = Auth::user();
|
||||
$profile = UserProfile::createForUser($user->id, true);
|
||||
|
||||
$profile->update([
|
||||
'display_name' => $request->display_name,
|
||||
'bio' => $request->bio,
|
||||
'location' => $request->location,
|
||||
'website' => $request->website,
|
||||
'is_public' => $request->boolean('is_public'),
|
||||
'show_email' => $request->boolean('show_email'),
|
||||
'show_joined_date' => $request->boolean('show_joined_date'),
|
||||
'allow_comments' => $request->boolean('allow_comments'),
|
||||
]);
|
||||
|
||||
// Fire profile updated event
|
||||
Event::dispatch('socialbase.profile.updated', [$user, $profile]);
|
||||
|
||||
return redirect()->route('socialbase.profile.show', ['user' => $user->id])
|
||||
->with('success', 'Profile updated successfully!');
|
||||
}
|
||||
|
||||
/**
|
||||
* Upload avatar
|
||||
*/
|
||||
public function uploadAvatar(Request $request)
|
||||
{
|
||||
$validator = Validator::make($request->all(), [
|
||||
'avatar' => [
|
||||
'required',
|
||||
'image',
|
||||
'max:' . ($this->getMaxAvatarSize() * 1024), // Convert MB to KB
|
||||
'mimes:' . $this->getAllowedImageTypes(),
|
||||
],
|
||||
]);
|
||||
|
||||
if ($validator->fails()) {
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'message' => $validator->errors()->first(),
|
||||
], 422);
|
||||
}
|
||||
|
||||
$user = Auth::user();
|
||||
$profile = UserProfile::createForUser($user->id, true);
|
||||
|
||||
// Delete old avatar
|
||||
if ($profile->avatar_path) {
|
||||
Storage::delete($profile->avatar_path);
|
||||
}
|
||||
|
||||
// Store new avatar
|
||||
$path = $request->file('avatar')->store('socialbase/avatars', 'public');
|
||||
|
||||
$profile->update(['avatar_path' => $path]);
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'message' => 'Avatar uploaded successfully!',
|
||||
'avatar_url' => $profile->avatar_url,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Upload banner
|
||||
*/
|
||||
public function uploadBanner(Request $request)
|
||||
{
|
||||
$validator = Validator::make($request->all(), [
|
||||
'banner' => [
|
||||
'required',
|
||||
'image',
|
||||
'max:' . ($this->getMaxBannerSize() * 1024), // Convert MB to KB
|
||||
'mimes:' . $this->getAllowedImageTypes(),
|
||||
],
|
||||
]);
|
||||
|
||||
if ($validator->fails()) {
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'message' => $validator->errors()->first(),
|
||||
], 422);
|
||||
}
|
||||
|
||||
$user = Auth::user();
|
||||
$profile = UserProfile::createForUser($user->id, true);
|
||||
|
||||
// Delete old banner
|
||||
if ($profile->banner_path) {
|
||||
Storage::delete($profile->banner_path);
|
||||
}
|
||||
|
||||
// Store new banner
|
||||
$path = $request->file('banner')->store('socialbase/banners', 'public');
|
||||
|
||||
$profile->update(['banner_path' => $path]);
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'message' => 'Banner uploaded successfully!',
|
||||
'banner_url' => $profile->banner_url,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove avatar
|
||||
*/
|
||||
public function removeAvatar()
|
||||
{
|
||||
$user = Auth::user();
|
||||
$profile = UserProfile::where('user_id', $user->id)->first();
|
||||
|
||||
if ($profile && $profile->avatar_path) {
|
||||
Storage::delete($profile->avatar_path);
|
||||
$profile->update(['avatar_path' => null]);
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'message' => 'Avatar removed successfully!',
|
||||
'avatar_url' => $profile ? $profile->avatar_url : null,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove banner
|
||||
*/
|
||||
public function removeBanner()
|
||||
{
|
||||
$user = Auth::user();
|
||||
$profile = UserProfile::where('user_id', $user->id)->first();
|
||||
|
||||
if ($profile && $profile->banner_path) {
|
||||
Storage::delete($profile->banner_path);
|
||||
$profile->update(['banner_path' => null]);
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'message' => 'Banner removed successfully!',
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a comment on profile
|
||||
*/
|
||||
public function storeComment(Request $request, User $user)
|
||||
{
|
||||
$profile = UserProfile::where('user_id', $user->id)->first();
|
||||
|
||||
if (!$profile || !$profile->allowsComments()) {
|
||||
abort(403, 'Comments are not allowed on this profile.');
|
||||
}
|
||||
|
||||
$validator = Validator::make($request->all(), [
|
||||
'content' => 'required|string|min:3|max:1000',
|
||||
'parent_id' => 'nullable|exists:ext_social_profile_comments,id',
|
||||
]);
|
||||
|
||||
if ($validator->fails()) {
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'message' => $validator->errors()->first(),
|
||||
], 422);
|
||||
}
|
||||
|
||||
// Check auto-approval setting
|
||||
$autoApprove = $this->getAutoApproveComments();
|
||||
|
||||
$comment = ProfileComment::create([
|
||||
'user_profile_id' => $profile->id,
|
||||
'user_id' => Auth::id(),
|
||||
'parent_id' => $request->input('parent_id'),
|
||||
'content' => $request->input('content'),
|
||||
'approved' => $autoApprove,
|
||||
'metadata' => [
|
||||
'ip_address' => $request->ip(),
|
||||
'user_agent' => $request->userAgent(),
|
||||
],
|
||||
]);
|
||||
|
||||
// Dispatch event for comment creation
|
||||
if ($autoApprove) {
|
||||
event('socialbase.comment.approved', $comment);
|
||||
} else {
|
||||
event('socialbase.comment.created', $comment);
|
||||
}
|
||||
|
||||
$message = $autoApprove
|
||||
? 'Comment posted successfully!'
|
||||
: 'Comment submitted for approval.';
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'message' => $message,
|
||||
'comment' => $comment->load('user'),
|
||||
'approved' => $autoApprove,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a comment
|
||||
*/
|
||||
public function updateComment(Request $request, ProfileComment $comment)
|
||||
{
|
||||
if (!$comment->canBeEditedBy(Auth::user())) {
|
||||
abort(403, 'You cannot edit this comment.');
|
||||
}
|
||||
|
||||
$validator = Validator::make($request->all(), [
|
||||
'content' => 'required|string|min:3|max:1000',
|
||||
]);
|
||||
|
||||
if ($validator->fails()) {
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'message' => $validator->errors()->first(),
|
||||
], 422);
|
||||
}
|
||||
|
||||
$comment->update(['content' => $request->input('content')]);
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'message' => 'Comment updated successfully!',
|
||||
'comment' => $comment,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a comment
|
||||
*/
|
||||
public function deleteComment(ProfileComment $comment)
|
||||
{
|
||||
if (!$comment->canBeDeletedBy(Auth::user())) {
|
||||
abort(403, 'You cannot delete this comment.');
|
||||
}
|
||||
|
||||
$comment->delete();
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'message' => 'Comment deleted successfully!',
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get profile statistics
|
||||
*/
|
||||
public function getStats(User $user)
|
||||
{
|
||||
$profile = UserProfile::where('user_id', $user->id)->first();
|
||||
|
||||
if (!$profile || !$profile->isViewableBy(Auth::user())) {
|
||||
abort(403, 'Profile not accessible.');
|
||||
}
|
||||
|
||||
return response()->json($profile->stats);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get profile tabs from extensions
|
||||
*/
|
||||
public function getTabs(User $user)
|
||||
{
|
||||
$profile = UserProfile::where('user_id', $user->id)->first();
|
||||
|
||||
if (!$profile || !$profile->isViewableBy(Auth::user())) {
|
||||
abort(403, 'Profile not accessible.');
|
||||
}
|
||||
|
||||
// Get tabs from other extensions
|
||||
$tabs = Event::dispatch('socialbase.profile.tabs', [$user]);
|
||||
$tabs = collect($tabs)->flatten(1)->filter();
|
||||
|
||||
return response()->json($tabs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get tab content from extensions
|
||||
*/
|
||||
public function getTabContent(User $user, string $tab)
|
||||
{
|
||||
$profile = UserProfile::where('user_id', $user->id)->first();
|
||||
|
||||
if (!$profile || !$profile->isViewableBy(Auth::user())) {
|
||||
abort(403, 'Profile not accessible.');
|
||||
}
|
||||
|
||||
// Get content from extensions
|
||||
$content = Event::dispatch('socialbase.profile.content', [$user, $tab]);
|
||||
$content = collect($content)->first();
|
||||
|
||||
return response()->json(['content' => $content]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get max avatar size from extension settings
|
||||
*/
|
||||
private function getMaxAvatarSize(): int
|
||||
{
|
||||
try {
|
||||
$extension = \App\Models\Extension::where('extension', 'SocialBase')->first();
|
||||
if ($extension && $extension->settings) {
|
||||
$setting = $extension->settings->where('key', 'max_avatar_size')->first();
|
||||
return $setting ? (int) $setting->value : 5;
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
// Fall back to default
|
||||
}
|
||||
|
||||
return 5; // Default 5MB
|
||||
}
|
||||
|
||||
/**
|
||||
* Get max banner size from extension settings
|
||||
*/
|
||||
private function getMaxBannerSize(): int
|
||||
{
|
||||
try {
|
||||
$extension = \App\Models\Extension::where('extension', 'SocialBase')->first();
|
||||
if ($extension && $extension->settings) {
|
||||
$setting = $extension->settings->where('key', 'max_banner_size')->first();
|
||||
return $setting ? (int) $setting->value : 10;
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
// Fall back to default
|
||||
}
|
||||
|
||||
return 10; // Default 10MB
|
||||
}
|
||||
|
||||
/**
|
||||
* Get allowed image types
|
||||
*/
|
||||
private function getAllowedImageTypes(): string
|
||||
{
|
||||
try {
|
||||
$extension = \App\Models\Extension::where('extension', 'SocialBase')->first();
|
||||
if ($extension && $extension->settings) {
|
||||
$setting = $extension->settings->where('key', 'allowed_image_types')->first();
|
||||
return $setting ? $setting->value : 'jpg,jpeg,png,gif,webp';
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
// Fall back to default
|
||||
}
|
||||
|
||||
return 'jpg,jpeg,png,gif,webp';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get auto-approve comments setting
|
||||
*/
|
||||
/**
|
||||
* Add or toggle a reaction to a comment
|
||||
*/
|
||||
public function toggleReaction(Request $request, ProfileComment $comment)
|
||||
{
|
||||
if (!Auth::check()) {
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'message' => 'You must be logged in to react to comments.',
|
||||
], 401);
|
||||
}
|
||||
|
||||
// Get available reaction types for social context
|
||||
$availableTypes = \Paymenter\Extensions\Others\SocialBase\Models\Reaction::getAvailableTypes('social');
|
||||
|
||||
$validator = Validator::make($request->all(), [
|
||||
'type' => 'required|in:' . implode(',', array_keys($availableTypes)),
|
||||
]);
|
||||
|
||||
if ($validator->fails()) {
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'message' => $validator->errors()->first(),
|
||||
], 422);
|
||||
}
|
||||
|
||||
$user = Auth::user();
|
||||
$reactionType = $request->input('type');
|
||||
|
||||
// Use the generic reaction system
|
||||
$action = $comment->toggleReaction($user, $reactionType);
|
||||
|
||||
// Get updated reaction counts
|
||||
$reactionCounts = $comment->fresh()->reaction_counts;
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'message' => 'Reaction ' . $action . ' successfully!',
|
||||
'action' => $action,
|
||||
'reaction_counts' => $reactionCounts,
|
||||
'user_reaction' => $comment->getUserReaction($user)?->type,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get reactions for a comment
|
||||
*/
|
||||
public function getCommentReactions(ProfileComment $comment)
|
||||
{
|
||||
return response()->json([
|
||||
'reaction_counts' => $comment->reaction_counts,
|
||||
'user_reaction' => Auth::check() ? $comment->getUserReaction(Auth::user())?->type : null,
|
||||
'reactions_with_users' => $comment->reactions_with_users,
|
||||
'total_reactions' => $comment->total_reactions,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add or toggle a reaction to a profile
|
||||
*/
|
||||
public function toggleProfileReaction(Request $request, User $user)
|
||||
{
|
||||
if (!Auth::check()) {
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'message' => 'You must be logged in to react to profiles.',
|
||||
], 401);
|
||||
}
|
||||
|
||||
$profile = UserProfile::createForUser($user->id, true);
|
||||
|
||||
// Check if profile is viewable
|
||||
if (!$profile->isViewableBy(Auth::user())) {
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'message' => 'You cannot react to this profile.',
|
||||
], 403);
|
||||
}
|
||||
|
||||
// Don't allow users to react to their own profile
|
||||
if (Auth::id() === $user->id) {
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'message' => 'You cannot react to your own profile.',
|
||||
], 422);
|
||||
}
|
||||
|
||||
// Get available reaction types for social context
|
||||
$availableTypes = \Paymenter\Extensions\Others\SocialBase\Models\Reaction::getAvailableTypes('social');
|
||||
|
||||
$validator = Validator::make($request->all(), [
|
||||
'type' => 'required|in:' . implode(',', array_keys($availableTypes)),
|
||||
]);
|
||||
|
||||
if ($validator->fails()) {
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'message' => $validator->errors()->first(),
|
||||
], 422);
|
||||
}
|
||||
|
||||
$authUser = Auth::user();
|
||||
$reactionType = $request->input('type');
|
||||
|
||||
// Use the generic reaction system
|
||||
$action = $profile->toggleReaction($authUser, $reactionType);
|
||||
|
||||
// Get updated reaction counts
|
||||
$reactionCounts = $profile->fresh()->reaction_counts;
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'message' => 'Profile reaction ' . $action . ' successfully!',
|
||||
'action' => $action,
|
||||
'reaction_counts' => $reactionCounts,
|
||||
'user_reaction' => $profile->getUserReaction($authUser)?->type,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get reactions for a profile
|
||||
*/
|
||||
public function getProfileReactions(User $user)
|
||||
{
|
||||
$profile = UserProfile::createForUser($user->id, true);
|
||||
|
||||
// Check if profile is viewable
|
||||
if (!$profile->isViewableBy(Auth::user())) {
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'message' => 'You cannot view reactions for this profile.',
|
||||
], 403);
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
'reaction_counts' => $profile->reaction_counts,
|
||||
'user_reaction' => Auth::check() ? $profile->getUserReaction(Auth::user())?->type : null,
|
||||
'reactions_with_users' => $profile->reactions_with_users,
|
||||
'total_reactions' => $profile->total_reactions,
|
||||
]);
|
||||
}
|
||||
|
||||
private function getAutoApproveComments(): bool
|
||||
{
|
||||
try {
|
||||
$extension = \App\Models\Extension::where('extension', 'SocialBase')->first();
|
||||
if ($extension && $extension->settings) {
|
||||
$setting = $extension->settings->where('key', 'require_approval_comments')->first();
|
||||
return $setting ? !(bool) $setting->value : true; // Invert because setting is "require approval"
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
// Fall back to default
|
||||
}
|
||||
|
||||
return true; // Default to auto-approve
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user