Files
timebank-cc-public/app/Http/Livewire/Profile/SocialsForm.php
Ronald Huynen 2547717edb Initial commit
2026-03-23 21:37:59 +01:00

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');
}
}