204 lines
6.3 KiB
PHP
204 lines
6.3 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Livewire\Profile;
|
|
|
|
use App\Models\Social;
|
|
use Illuminate\Support\Carbon;
|
|
use Illuminate\Support\Facades\DB;
|
|
use Livewire\Component;
|
|
|
|
class SocialsForm extends Component
|
|
{
|
|
public $socialsOptions;
|
|
public $socialsOptionSelected;
|
|
public $socials;
|
|
public $userOnSocial;
|
|
public $serverOfSocial;
|
|
public $sociables_id;
|
|
public $updateMode = false;
|
|
public $selectedPlaceholder;
|
|
|
|
|
|
private function resetInputFields()
|
|
{
|
|
$this->reset(['updateMode', 'socialsOptionSelected', 'userOnSocial', 'serverOfSocial']);
|
|
}
|
|
|
|
public function mount()
|
|
{
|
|
$this->socialsOptions = Social::select("*")->orderBy("name")->get();
|
|
$this->getSocials();
|
|
}
|
|
|
|
public function getSocials()
|
|
{
|
|
$this->socials = getActiveProfile()->socials;
|
|
}
|
|
|
|
public function socialsUpdated()
|
|
{
|
|
$this->resetErrorBag(); // clears all validation errors
|
|
}
|
|
|
|
public function store()
|
|
{
|
|
$validatedSocial = $this->validate([
|
|
'socialsOptionSelected' => 'required|integer',
|
|
'userOnSocial' => 'required|string|max:150',
|
|
]);
|
|
|
|
$activeProfile = getActiveProfile();
|
|
|
|
// CRITICAL SECURITY: Validate user has ownership/access to this profile
|
|
\App\Helpers\ProfileAuthorizationHelper::authorize($activeProfile);
|
|
|
|
// Limit to max 10 socials per profile
|
|
$currentCount = $activeProfile->socials()->count();
|
|
if ($currentCount >= $limit = 10) {
|
|
$this->addError('socialsOptionSelected', __('validation.custom.social_limit', ['limit' => $limit]));
|
|
return;
|
|
}
|
|
|
|
DB::table('sociables')->insert([
|
|
'social_id' => $this->socialsOptionSelected,
|
|
'sociable_type' => session('activeProfileType'),
|
|
'sociable_id' => session('activeProfileId'),
|
|
'user_on_social' => $this->formatUserHandle($this->socialsOptionSelected, $this->userOnSocial),
|
|
'server_of_social' => $this->formatServer($this->socialsOptionSelected, $this->serverOfSocial),
|
|
'created_at' => Carbon::now(),
|
|
'updated_at' => Carbon::now(),
|
|
]);
|
|
session()->flash('message', __('Saved'));
|
|
$this->resetInputFields();
|
|
$this->getSocials();
|
|
}
|
|
|
|
|
|
public function edit($id)
|
|
{
|
|
$activeProfile = getActiveProfile();
|
|
|
|
// CRITICAL SECURITY: Validate user has ownership/access to this profile
|
|
\App\Helpers\ProfileAuthorizationHelper::authorize($activeProfile);
|
|
|
|
$this->sociables_id = $id;
|
|
$this->socialsOptionSelected = $activeProfile->socials->where('pivot.id', $id)->first()->pivot->social_id;
|
|
$this->userOnSocial = $activeProfile->socials->where('pivot.id', $id)->first()->pivot->user_on_social;
|
|
$this->serverOfSocial = $activeProfile->socials->where('pivot.id', $id)->first()->pivot->server_of_social;
|
|
$this->selectedPlaceholder = Social::find($this->socialsOptionSelected);
|
|
$this->updateMode = true;
|
|
|
|
$this->dispatch('contentChanged');
|
|
}
|
|
|
|
|
|
public function cancel()
|
|
{
|
|
$this->updateMode = false;
|
|
$this->resetInputFields();
|
|
$this->resetErrorBag(); // clears all validation errors
|
|
}
|
|
|
|
|
|
public function update()
|
|
{
|
|
$validatedDate = $this->validate([
|
|
'socialsOptionSelected' => 'required|integer',
|
|
'userOnSocial' => 'required|string|max:150',
|
|
]);
|
|
|
|
$activeProfile = getActiveProfile();
|
|
|
|
// CRITICAL SECURITY: Validate user has ownership/access to this profile
|
|
\App\Helpers\ProfileAuthorizationHelper::authorize($activeProfile);
|
|
|
|
if ($this->sociables_id) {
|
|
DB::table('sociables')->insert([
|
|
'social_id' => $this->socialsOptionSelected,
|
|
'sociable_type' => session('activeProfileType'),
|
|
'sociable_id' => session('activeProfileId'),
|
|
'user_on_social' => $this->formatUserHandle($this->socialsOptionSelected, $this->userOnSocial),
|
|
'server_of_social' => $this->formatServer($this->socialsOptionSelected, $this->serverOfSocial),
|
|
'updated_at' => Carbon::now(),
|
|
]);
|
|
|
|
$this->dispatch('emitSaved');
|
|
$this->resetInputFields();
|
|
}
|
|
}
|
|
|
|
|
|
public function delete($id)
|
|
{
|
|
$activeProfile = getActiveProfile();
|
|
|
|
// CRITICAL SECURITY: Validate user has ownership/access to this profile
|
|
\App\Helpers\ProfileAuthorizationHelper::authorize($activeProfile);
|
|
|
|
if ($id) {
|
|
DB::table('sociables')->where('id', $id)->delete();
|
|
// refresh the local list
|
|
$this->getSocials();
|
|
$this->resetErrorBag(); // clears all validation errors
|
|
$this->dispatch('emitSaved');
|
|
|
|
session()->flash('message', __('Deleted'));
|
|
}
|
|
}
|
|
|
|
|
|
private function formatUserHandle($socialId, $handle)
|
|
{
|
|
$handle = str_replace('@', '', $handle);
|
|
|
|
// For Blue Sky, the handle already contains the domain
|
|
if ($socialId == 3) { // Blue Sky ID is 3
|
|
return $handle; // handle.bsky.social
|
|
}
|
|
|
|
return $handle;
|
|
}
|
|
|
|
private function formatServer($socialId, $server)
|
|
{
|
|
$server = str_replace('@', '', $server);
|
|
|
|
// Only Mastodon (4) and Blue Sky (3) use server info
|
|
if (!in_array($socialId, [3, 4])) {
|
|
return null;
|
|
}
|
|
|
|
// For Blue Sky, extract domain from handle if needed
|
|
if ($socialId == 3) {
|
|
if (str_contains($this->userOnSocial, '.')) {
|
|
return substr(strrchr($this->userOnSocial, '.'), 1);
|
|
}
|
|
return $server ?: 'bsky.social';
|
|
}
|
|
|
|
return $server;
|
|
}
|
|
|
|
|
|
public function getSocialUrlAttribute()
|
|
{
|
|
$urlStructure = $this->social->url_structure;
|
|
|
|
switch ($this->social_id) {
|
|
case 3: // Blue Sky
|
|
return "https://bsky.app/profile/{$this->user_on_social}";
|
|
case 4: // Mastodon
|
|
return str_replace('#', $this->server_of_social, $urlStructure) . $this->user_on_social;
|
|
default:
|
|
return $urlStructure . $this->user_on_social;
|
|
}
|
|
}
|
|
|
|
|
|
public function render()
|
|
{
|
|
$this->getSocials();
|
|
return view('livewire.profile.socials-form');
|
|
}
|
|
}
|