trypost/app/Models/Workspace.php

114 lines
2.8 KiB
PHP
Raw Normal View History

2026-01-15 01:13:44 +00:00
<?php
declare(strict_types=1);
2026-01-15 01:13:44 +00:00
namespace App\Models;
use App\Models\Traits\HasMedia;
use Database\Factories\WorkspaceFactory;
use Illuminate\Database\Eloquent\Collection;
2026-01-15 01:13:44 +00:00
use Illuminate\Database\Eloquent\Concerns\HasUuids;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Database\Eloquent\Relations\HasMany;
class Workspace extends Model
{
/** @use HasFactory<WorkspaceFactory> */
use HasFactory, HasMedia, HasUuids;
2026-01-15 01:13:44 +00:00
protected $fillable = [
'account_id',
2026-01-15 01:13:44 +00:00
'user_id',
'name',
'brand_website',
'brand_description',
'brand_tone',
'brand_voice_notes',
feat: add workspace content_language setting for AI generation Users can now pick the language AI uses for captions, hashtags, descriptions, AND on-image / on-screen text — independent of the app UI locale. A user with pt-BR UI who writes for an English audience gets English content, and vice versa. - New content_language column on workspaces (added to the existing create_workspaces_table migration since we're pre-production), defaulting to 'en'. Fillable on the model. - Dropdown in Settings → Workspace → Brand, side-by-side with Tone. Options: English, Português (Brasil), Español. Short helper copy explains what the setting controls. - Validation: sometimes|string|in:en,pt-BR,es — optional on update so existing callers that don't post the field keep the current value (DB default handles fresh workspaces). - System prompt now uses $content_language (sourced from the workspace) instead of app()->getLocale(). The rule was also strengthened: the AI must always write in this language regardless of what language the user types instructions in, and must instruct image/video tools to render on-media text in this language too. - Image and video Blade prompts received a new line forcing any text rendered inside the generated media to use $content_language. - GenerateImage tool and VideoGenerationService pass the workspace's content_language into their respective prompt templates. Previously the caption would be in Portuguese (since it followed the user's input language) but the image could render with English text because there was no explicit constraint. Now the whole pipeline is aligned to one per-workspace language.
2026-04-16 13:37:03 +00:00
'content_language',
2026-01-15 01:13:44 +00:00
];
protected $appends = ['has_logo', 'logo_url'];
public function getHasLogoAttribute(): bool
{
return $this->getFirstMedia('logo') !== null;
}
public function getLogoUrlAttribute(): ?string
{
return $this->getFirstMediaUrl('logo') ?: null;
}
public function account(): BelongsTo
2026-01-15 01:13:44 +00:00
{
return $this->belongsTo(Account::class);
2026-01-15 01:13:44 +00:00
}
public function owner(): BelongsTo
{
return $this->belongsTo(User::class, 'user_id');
}
2026-01-15 01:13:44 +00:00
public function members(): BelongsToMany
{
return $this->belongsToMany(User::class)
2026-01-15 01:13:44 +00:00
->withPivot('role')
->withTimestamps();
}
public function socialAccounts(): HasMany
{
return $this->hasMany(SocialAccount::class);
}
public function posts(): HasMany
{
return $this->hasMany(Post::class);
}
public function hashtags(): HasMany
{
return $this->hasMany(WorkspaceHashtag::class);
}
public function labels(): HasMany
{
return $this->hasMany(WorkspaceLabel::class);
}
/**
* Get invites for this workspace (invites from the same account that include this workspace).
*
* @return Collection<int, Invite>
*/
public function invites()
{
return Invite::where('account_id', $this->account_id)
->whereJsonContains('workspaces', $this->id)
->whereNull('accepted_at');
}
public function apiTokens(): HasMany
{
return $this->hasMany(ApiToken::class);
}
2026-01-15 01:13:44 +00:00
public function hasMember(User $user): bool
{
return $this->account?->owner_id === $user->id || $this->members()->where('user_id', $user->id)->exists();
2026-01-15 01:13:44 +00:00
}
public function hasConnectedPlatform(string $platform): bool
{
return $this->socialAccounts()->where('platform', $platform)->exists();
}
public function getSocialAccount(string $platform): ?SocialAccount
{
return $this->socialAccounts()->where('platform', $platform)->first();
}
}