|
|
|
|
<?php
|
|
|
|
|
|
|
|
|
|
namespace App\Models;
|
|
|
|
|
|
|
|
|
|
use App\HasSnowflakePrimary;
|
|
|
|
|
use App\Http\Controllers\StatusController;
|
|
|
|
|
use App\Services\AccountService;
|
|
|
|
|
use App\Services\StatusService;
|
|
|
|
|
use Illuminate\Database\Eloquent\Collection;
|
feat: add framework integration tests for Laravel 12→13 upgrade readiness
Framework tests verify core Laravel integration points:
- ServiceProviderTest: app boot, guard resolution, route loading, config_cache
- RoutingTest: named routes, duplicates, api/oauth prefixes, middleware groups
- EloquentTest: User/Profile/Status factories, relationships, casts, soft deletes
- QueueTest: job dispatch, serialization, middleware, unique IDs
- ConfigTest: config loading, env overrides, auth/cache/queue settings
- MiddlewarePipelineTest: CSRF, auth, throttle, password confirm, 2FA, admin
Also:
- Add HasFactory trait to Status model
- Fix StatusFactory: remove non-existent 'place' column, add 'rendered' field
- Add Api/AccountTest for account endpoint coverage (254 total tests)
4 weeks ago
|
|
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
|
|
|
|
use Illuminate\Database\Eloquent\Model;
|
fix: add return type declarations to Eloquent relation methods
Larastan 3.x requires explicit return types on relation methods to
verify relation existence when using with(), has(), etc. This adds
the appropriate return type declarations to all relation methods
flagged by the larastan.relationExistence rule.
Models fixed:
- Profile (avatar, statuses)
- User (profile)
- Status (profile, media, hashtags)
- DirectMessage (status, author, recipient)
- Report (reporter, status, reportedUser)
- Like (actor, status)
- Media (status)
- Notification (item)
- HashtagFollow (hashtag)
- OauthClient (user)
- Story (profile)
- StatusHashtag (status, hashtag, profile, media)
- AccountInterstitial (user)
- Hashtag (posts)
- CustomFilter (keywords)
- CustomFilterKeyword (customFilter)
- AdminShadowFilter (profile)
- ImportPost (status)
4 weeks ago
|
|
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
|
|
|
|
use Illuminate\Database\Eloquent\Relations\HasMany;
|
|
|
|
|
use Illuminate\Database\Eloquent\Relations\HasManyThrough;
|
|
|
|
|
use Illuminate\Database\Eloquent\SoftDeletes;
|
|
|
|
|
use Illuminate\Support\Carbon;
|
|
|
|
|
use Illuminate\Support\Facades\Auth;
|
|
|
|
|
use Illuminate\Support\Facades\Storage;
|
|
|
|
|
use Illuminate\Support\Str;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @property int $id
|
|
|
|
|
* @property string|null $uri
|
|
|
|
|
* @property string|null $caption
|
|
|
|
|
* @property string|null $rendered
|
|
|
|
|
* @property int|null $profile_id
|
|
|
|
|
* @property string|null $type
|
|
|
|
|
* @property int|null $in_reply_to_id
|
|
|
|
|
* @property int|null $reblog_of_id
|
|
|
|
|
* @property string|null $url
|
|
|
|
|
* @property int $is_nsfw
|
|
|
|
|
* @property string $scope
|
|
|
|
|
* @property string $visibility
|
|
|
|
|
* @property int $reply
|
|
|
|
|
* @property int $likes_count
|
|
|
|
|
* @property int $reblogs_count
|
|
|
|
|
* @property string|null $language
|
|
|
|
|
* @property int|null $conversation_id
|
|
|
|
|
* @property int $local
|
|
|
|
|
* @property int|null $application_id
|
|
|
|
|
* @property int|null $in_reply_to_profile_id
|
|
|
|
|
* @property string|null $entities
|
|
|
|
|
* @property Carbon|null $created_at
|
|
|
|
|
* @property Carbon|null $updated_at
|
|
|
|
|
* @property Carbon|null $deleted_at
|
|
|
|
|
* @property string|null $cw_summary
|
|
|
|
|
* @property int|null $reply_count
|
|
|
|
|
* @property int $comments_disabled
|
|
|
|
|
* @property int|null $place_id
|
|
|
|
|
* @property string|null $object_url
|
|
|
|
|
* @property Carbon|null $edited_at
|
|
|
|
|
* @property int|null $trendable
|
|
|
|
|
* @property string|null $media_ids
|
|
|
|
|
* @property int|null $pinned_order
|
|
|
|
|
* @property int|null $group_id
|
|
|
|
|
* @property int|null $quote_policy
|
|
|
|
|
* @property-read Collection<int, Status> $comments
|
|
|
|
|
* @property-read int|null $comments_count
|
|
|
|
|
* @property-read Conversation|null $conversation
|
|
|
|
|
* @property-read DirectMessage|null $directMessage
|
|
|
|
|
* @property-read Collection<int, StatusEdit> $edits
|
|
|
|
|
* @property-read int|null $edits_count
|
|
|
|
|
* @property-read Collection<int, Hashtag> $hashtags
|
|
|
|
|
* @property-read int|null $hashtags_count
|
|
|
|
|
* @property-read Collection<int, Profile> $likedBy
|
|
|
|
|
* @property-read int|null $liked_by_count
|
|
|
|
|
* @property-read Collection<int, Like> $likes
|
|
|
|
|
* @property-read Collection<int, Media> $media
|
|
|
|
|
* @property-read int|null $media_count
|
|
|
|
|
* @property-read Collection<int, Profile> $mentions
|
|
|
|
|
* @property-read int|null $mentions_count
|
|
|
|
|
* @property-read Place|null $place
|
|
|
|
|
* @property-read Poll|null $poll
|
|
|
|
|
* @property-read Profile|null $profile
|
|
|
|
|
* @property-read Collection<int, Profile> $sharedBy
|
|
|
|
|
* @property-read int|null $shared_by_count
|
|
|
|
|
* @property-read Collection<int, Status> $shares
|
|
|
|
|
* @property-read int|null $shares_count
|
|
|
|
|
*
|
|
|
|
|
* @method static \Database\Factories\StatusFactory factory($count = null, $state = [])
|
|
|
|
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Status newModelQuery()
|
|
|
|
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Status newQuery()
|
|
|
|
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Status onlyTrashed()
|
|
|
|
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Status query()
|
|
|
|
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Status toAudience()
|
|
|
|
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Status whereApplicationId($value)
|
|
|
|
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Status whereCaption($value)
|
|
|
|
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Status whereCommentsDisabled($value)
|
|
|
|
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Status whereConversationId($value)
|
|
|
|
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Status whereCreatedAt($value)
|
|
|
|
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Status whereCwSummary($value)
|
|
|
|
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Status whereDeletedAt($value)
|
|
|
|
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Status whereEditedAt($value)
|
|
|
|
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Status whereEntities($value)
|
|
|
|
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Status whereGroupId($value)
|
|
|
|
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Status whereId($value)
|
|
|
|
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Status whereInReplyToId($value)
|
|
|
|
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Status whereInReplyToProfileId($value)
|
|
|
|
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Status whereIsNsfw($value)
|
|
|
|
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Status whereLanguage($value)
|
|
|
|
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Status whereLikesCount($value)
|
|
|
|
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Status whereLocal($value)
|
|
|
|
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Status whereMediaIds($value)
|
|
|
|
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Status whereObjectUrl($value)
|
|
|
|
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Status wherePinnedOrder($value)
|
|
|
|
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Status wherePlaceId($value)
|
|
|
|
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Status whereProfileId($value)
|
|
|
|
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Status whereQuotePolicy($value)
|
|
|
|
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Status whereReblogOfId($value)
|
|
|
|
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Status whereReblogsCount($value)
|
|
|
|
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Status whereRendered($value)
|
|
|
|
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Status whereReply($value)
|
|
|
|
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Status whereReplyCount($value)
|
|
|
|
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Status whereScope($value)
|
|
|
|
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Status whereTrendable($value)
|
|
|
|
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Status whereType($value)
|
|
|
|
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Status whereUpdatedAt($value)
|
|
|
|
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Status whereUri($value)
|
|
|
|
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Status whereUrl($value)
|
|
|
|
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Status whereVisibility($value)
|
|
|
|
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Status withTrashed(bool $withTrashed = true)
|
|
|
|
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Status withoutTrashed()
|
|
|
|
|
*
|
|
|
|
|
* @mixin \Eloquent
|
|
|
|
|
*/
|
|
|
|
|
class Status extends Model
|
|
|
|
|
{
|
feat: add framework integration tests for Laravel 12→13 upgrade readiness
Framework tests verify core Laravel integration points:
- ServiceProviderTest: app boot, guard resolution, route loading, config_cache
- RoutingTest: named routes, duplicates, api/oauth prefixes, middleware groups
- EloquentTest: User/Profile/Status factories, relationships, casts, soft deletes
- QueueTest: job dispatch, serialization, middleware, unique IDs
- ConfigTest: config loading, env overrides, auth/cache/queue settings
- MiddlewarePipelineTest: CSRF, auth, throttle, password confirm, 2FA, admin
Also:
- Add HasFactory trait to Status model
- Fix StatusFactory: remove non-existent 'place' column, add 'rendered' field
- Add Api/AccountTest for account endpoint coverage (254 total tests)
4 weeks ago
|
|
|
use HasFactory, HasSnowflakePrimary, SoftDeletes;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Indicates if the IDs are auto-incrementing.
|
|
|
|
|
*
|
|
|
|
|
* @var bool
|
|
|
|
|
*/
|
|
|
|
|
public $incrementing = false;
|
|
|
|
|
|
|
|
|
|
protected $guarded = [];
|
|
|
|
|
|
|
|
|
|
protected function casts(): array
|
|
|
|
|
{
|
|
|
|
|
return [
|
|
|
|
|
'deleted_at' => 'datetime',
|
|
|
|
|
'edited_at' => 'datetime',
|
|
|
|
|
'quote_policy' => 'integer',
|
|
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const STATUS_TYPES = [
|
|
|
|
|
'text',
|
|
|
|
|
'photo',
|
|
|
|
|
'photo:album',
|
|
|
|
|
'video',
|
|
|
|
|
'video:album',
|
|
|
|
|
'photo:video:album',
|
|
|
|
|
'share',
|
|
|
|
|
'reply',
|
|
|
|
|
'story',
|
|
|
|
|
'story:reply',
|
|
|
|
|
'story:reaction',
|
|
|
|
|
'story:live',
|
|
|
|
|
'loop',
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
const MAX_MENTIONS = 20;
|
|
|
|
|
|
|
|
|
|
const MAX_HASHTAGS = 60;
|
|
|
|
|
|
|
|
|
|
const MAX_LINKS = 5;
|
|
|
|
|
|
fix: add return type declarations to Eloquent relation methods
Larastan 3.x requires explicit return types on relation methods to
verify relation existence when using with(), has(), etc. This adds
the appropriate return type declarations to all relation methods
flagged by the larastan.relationExistence rule.
Models fixed:
- Profile (avatar, statuses)
- User (profile)
- Status (profile, media, hashtags)
- DirectMessage (status, author, recipient)
- Report (reporter, status, reportedUser)
- Like (actor, status)
- Media (status)
- Notification (item)
- HashtagFollow (hashtag)
- OauthClient (user)
- Story (profile)
- StatusHashtag (status, hashtag, profile, media)
- AccountInterstitial (user)
- Hashtag (posts)
- CustomFilter (keywords)
- CustomFilterKeyword (customFilter)
- AdminShadowFilter (profile)
- ImportPost (status)
4 weeks ago
|
|
|
public function profile(): BelongsTo
|
|
|
|
|
{
|
|
|
|
|
return $this->belongsTo(Profile::class);
|
|
|
|
|
}
|
|
|
|
|
|
fix: add return type declarations to Eloquent relation methods
Larastan 3.x requires explicit return types on relation methods to
verify relation existence when using with(), has(), etc. This adds
the appropriate return type declarations to all relation methods
flagged by the larastan.relationExistence rule.
Models fixed:
- Profile (avatar, statuses)
- User (profile)
- Status (profile, media, hashtags)
- DirectMessage (status, author, recipient)
- Report (reporter, status, reportedUser)
- Like (actor, status)
- Media (status)
- Notification (item)
- HashtagFollow (hashtag)
- OauthClient (user)
- Story (profile)
- StatusHashtag (status, hashtag, profile, media)
- AccountInterstitial (user)
- Hashtag (posts)
- CustomFilter (keywords)
- CustomFilterKeyword (customFilter)
- AdminShadowFilter (profile)
- ImportPost (status)
4 weeks ago
|
|
|
public function media(): HasMany
|
|
|
|
|
{
|
|
|
|
|
return $this->hasMany(Media::class);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function firstMedia()
|
|
|
|
|
{
|
|
|
|
|
return $this->hasMany(Media::class)->orderBy('order', 'asc')->first();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function viewType()
|
|
|
|
|
{
|
|
|
|
|
if ($this->type) {
|
|
|
|
|
return $this->type;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return $this->setType();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function setType()
|
|
|
|
|
{
|
|
|
|
|
if (in_array($this->type, self::STATUS_TYPES)) {
|
|
|
|
|
return $this->type;
|
|
|
|
|
}
|
|
|
|
|
$mimes = $this->media->pluck('mime')->toArray();
|
|
|
|
|
$type = StatusController::mimeTypeCheck($mimes);
|
|
|
|
|
if ($type) {
|
|
|
|
|
$this->type = $type;
|
|
|
|
|
$this->save();
|
|
|
|
|
|
|
|
|
|
return $type;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function thumb($showNsfw = false)
|
|
|
|
|
{
|
|
|
|
|
$entity = StatusService::get($this->id, false);
|
|
|
|
|
|
|
|
|
|
if (! $entity || ! isset($entity['media_attachments']) || empty($entity['media_attachments'])) {
|
|
|
|
|
return url(Storage::url('public/no-preview.png'));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ((! isset($entity['sensitive']) || $entity['sensitive']) && ! $showNsfw) {
|
|
|
|
|
return url(Storage::url('public/no-preview.png'));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (! isset($entity['visibility']) || ! in_array($entity['visibility'], ['public', 'unlisted'])) {
|
|
|
|
|
return url(Storage::url('public/no-preview.png'));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return collect($entity['media_attachments'])
|
|
|
|
|
->filter(fn ($media): bool => $media['type'] == 'image' && in_array($media['mime'], ['image/jpeg', 'image/png', 'image/jpg']))
|
|
|
|
|
->map(function ($media) {
|
|
|
|
|
if (! Str::endsWith($media['preview_url'], ['no-preview.png', 'no-preview.jpg'])) {
|
|
|
|
|
return $media['preview_url'];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return $media['url'];
|
|
|
|
|
})
|
|
|
|
|
->first() ?? url(Storage::url('public/no-preview.png'));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function url($forceLocal = false)
|
|
|
|
|
{
|
|
|
|
|
if ($this->uri) {
|
|
|
|
|
return $forceLocal ? "/i/web/post/_/{$this->profile_id}/{$this->id}" : $this->uri;
|
|
|
|
|
}
|
|
|
|
|
$id = $this->id;
|
|
|
|
|
$account = AccountService::get($this->profile_id, true);
|
|
|
|
|
if (! $account || ! isset($account['username'])) {
|
|
|
|
|
return '/404';
|
|
|
|
|
}
|
|
|
|
|
$path = url(config('app.url')."/p/{$account['username']}/{$id}");
|
|
|
|
|
|
|
|
|
|
return $path;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function permalink($suffix = '/activity')
|
|
|
|
|
{
|
|
|
|
|
$id = $this->id;
|
|
|
|
|
$username = $this->profile->username;
|
|
|
|
|
$path = config('app.url')."/p/{$username}/{$id}{$suffix}";
|
|
|
|
|
|
|
|
|
|
return url($path);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function editUrl(): string
|
|
|
|
|
{
|
|
|
|
|
return $this->url().'/edit';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function mediaUrl()
|
|
|
|
|
{
|
|
|
|
|
$media = $this->firstMedia();
|
|
|
|
|
$path = $media->media_path;
|
|
|
|
|
$hash = is_null($media->processed_at) ? md5('unprocessed') : md5($media->created_at);
|
|
|
|
|
$url = $media->cdn_url ? $media->cdn_url."?v={$hash}" : url(Storage::url($path)."?v={$hash}");
|
|
|
|
|
|
|
|
|
|
return $url;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function likes()
|
|
|
|
|
{
|
|
|
|
|
return $this->hasMany(Like::class);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function liked(): bool
|
|
|
|
|
{
|
|
|
|
|
if (! Auth::check()) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$pid = Auth::user()->profile_id;
|
|
|
|
|
|
|
|
|
|
return Like::select('status_id', 'profile_id')
|
|
|
|
|
->whereStatusId($this->id)
|
|
|
|
|
->whereProfileId($pid)
|
|
|
|
|
->exists();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function likedBy()
|
|
|
|
|
{
|
|
|
|
|
return $this->hasManyThrough(
|
|
|
|
|
Profile::class,
|
|
|
|
|
Like::class,
|
|
|
|
|
'status_id',
|
|
|
|
|
'id',
|
|
|
|
|
'id',
|
|
|
|
|
'profile_id'
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function comments()
|
|
|
|
|
{
|
|
|
|
|
return $this->hasMany(self::class, 'in_reply_to_id');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function bookmarked()
|
|
|
|
|
{
|
|
|
|
|
if (! Auth::check()) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
$profile = Auth::user()->profile;
|
|
|
|
|
|
|
|
|
|
return Bookmark::whereProfileId($profile->id)->whereStatusId($this->id)->count();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function shares()
|
|
|
|
|
{
|
|
|
|
|
return $this->hasMany(self::class, 'reblog_of_id');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function shared(): bool
|
|
|
|
|
{
|
|
|
|
|
if (! Auth::check()) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
$pid = Auth::user()->profile_id;
|
|
|
|
|
|
|
|
|
|
return $this->select('profile_id', 'reblog_of_id')
|
|
|
|
|
->whereProfileId($pid)
|
|
|
|
|
->whereReblogOfId($this->id)
|
|
|
|
|
->exists();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function sharedBy()
|
|
|
|
|
{
|
|
|
|
|
return $this->hasManyThrough(
|
|
|
|
|
Profile::class,
|
|
|
|
|
Status::class,
|
|
|
|
|
'reblog_of_id',
|
|
|
|
|
'id',
|
|
|
|
|
'id',
|
|
|
|
|
'profile_id'
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function parent()
|
|
|
|
|
{
|
|
|
|
|
$parent = $this->in_reply_to_id ?? $this->reblog_of_id;
|
|
|
|
|
if (! empty($parent)) {
|
|
|
|
|
return $this->findOrFail($parent);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* ActivityPub id of the status this one replies to, for use as inReplyTo.
|
|
|
|
|
*
|
|
|
|
|
* For a remote parent this is object_url (the object's id), not uri.
|
|
|
|
|
* uri holds the object's `url` property, which for most software is the
|
|
|
|
|
* HTML permalink. Servers that thread by id cannot match a permalink, so
|
|
|
|
|
* sending it detaches our reply from the thread on their side.
|
|
|
|
|
*/
|
|
|
|
|
public function inReplyToUri(): ?string
|
|
|
|
|
{
|
|
|
|
|
if (! $this->in_reply_to_id) {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$parent = self::find($this->in_reply_to_id);
|
|
|
|
|
|
|
|
|
|
if (! $parent) {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return $parent->object_url ?: $parent->url();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function conversation()
|
|
|
|
|
{
|
|
|
|
|
return $this->hasOne(Conversation::class);
|
|
|
|
|
}
|
|
|
|
|
|
fix: add return type declarations to Eloquent relation methods
Larastan 3.x requires explicit return types on relation methods to
verify relation existence when using with(), has(), etc. This adds
the appropriate return type declarations to all relation methods
flagged by the larastan.relationExistence rule.
Models fixed:
- Profile (avatar, statuses)
- User (profile)
- Status (profile, media, hashtags)
- DirectMessage (status, author, recipient)
- Report (reporter, status, reportedUser)
- Like (actor, status)
- Media (status)
- Notification (item)
- HashtagFollow (hashtag)
- OauthClient (user)
- Story (profile)
- StatusHashtag (status, hashtag, profile, media)
- AccountInterstitial (user)
- Hashtag (posts)
- CustomFilter (keywords)
- CustomFilterKeyword (customFilter)
- AdminShadowFilter (profile)
- ImportPost (status)
4 weeks ago
|
|
|
public function hashtags(): HasManyThrough
|
|
|
|
|
{
|
|
|
|
|
return $this->hasManyThrough(
|
|
|
|
|
Hashtag::class,
|
|
|
|
|
StatusHashtag::class,
|
|
|
|
|
'status_id',
|
|
|
|
|
'id',
|
|
|
|
|
'id',
|
|
|
|
|
'hashtag_id'
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function mentions()
|
|
|
|
|
{
|
|
|
|
|
return $this->hasManyThrough(
|
|
|
|
|
Profile::class,
|
|
|
|
|
Mention::class,
|
|
|
|
|
'status_id',
|
|
|
|
|
'id',
|
|
|
|
|
'id',
|
|
|
|
|
'profile_id'
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function reportUrl(): string
|
|
|
|
|
{
|
|
|
|
|
return route('report.form')."?type=post&id={$this->id}";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function toActivityStream(): array
|
|
|
|
|
{
|
|
|
|
|
$media = $this->media;
|
|
|
|
|
$mediaCollection = [];
|
|
|
|
|
foreach ($media as $image) {
|
|
|
|
|
$mediaCollection[] = [
|
|
|
|
|
'type' => 'Link',
|
|
|
|
|
'href' => $image->url(),
|
|
|
|
|
'mediaType' => $image->mime,
|
|
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
$obj = [
|
|
|
|
|
'@context' => 'https://www.w3.org/ns/activitystreams',
|
|
|
|
|
'type' => 'Document',
|
|
|
|
|
'name' => null,
|
|
|
|
|
'url' => $mediaCollection,
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
return $obj;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function recentComments()
|
|
|
|
|
{
|
|
|
|
|
return $this->comments()->orderBy('created_at', 'desc')->take(3);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function scopeToAudience($audience)
|
|
|
|
|
{
|
|
|
|
|
if (! in_array($audience, ['to', 'cc']) || $this->local == false) {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
$res = [];
|
|
|
|
|
$res['to'] = [];
|
|
|
|
|
$res['cc'] = [];
|
|
|
|
|
$scope = $this->scope;
|
|
|
|
|
$mentions = $this->mentions->map(function ($mention) {
|
|
|
|
|
return $mention->permalink();
|
|
|
|
|
})->toArray();
|
|
|
|
|
|
|
|
|
|
if ($this->in_reply_to_id != null) {
|
|
|
|
|
$parent = $this->parent();
|
|
|
|
|
if ($parent) {
|
|
|
|
|
$mentions = array_merge([$parent->profile->permalink()], $mentions);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch ($scope) {
|
|
|
|
|
case 'public':
|
|
|
|
|
$res['to'] = [
|
|
|
|
|
'https://www.w3.org/ns/activitystreams#Public',
|
|
|
|
|
];
|
|
|
|
|
$res['cc'] = array_merge([$this->profile->permalink('/followers')], $mentions);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 'unlisted':
|
|
|
|
|
$res['to'] = array_merge([$this->profile->permalink('/followers')], $mentions);
|
|
|
|
|
$res['cc'] = [
|
|
|
|
|
'https://www.w3.org/ns/activitystreams#Public',
|
|
|
|
|
];
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 'private':
|
|
|
|
|
$res['to'] = array_merge([$this->profile->permalink('/followers')], $mentions);
|
|
|
|
|
$res['cc'] = [];
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
// TODO: Update scope when DMs are supported
|
|
|
|
|
case 'direct':
|
|
|
|
|
$res['to'] = [];
|
|
|
|
|
$res['cc'] = [];
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return $res[$audience];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function place()
|
|
|
|
|
{
|
|
|
|
|
return $this->belongsTo(Place::class);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function directMessage()
|
|
|
|
|
{
|
|
|
|
|
return $this->hasOne(DirectMessage::class);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function poll()
|
|
|
|
|
{
|
|
|
|
|
return $this->hasOne(Poll::class);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function edits()
|
|
|
|
|
{
|
|
|
|
|
return $this->hasMany(StatusEdit::class);
|
|
|
|
|
}
|
|
|
|
|
}
|