You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

144 lines
3.8 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
class Competition extends Model
{
use HasFactory;
public const STATUSES = [
'draft',
'published',
'signup_open',
'signup_closed',
'reviewing',
'ended',
];
protected $fillable = [
'slug',
'name',
'description',
'pledge_content_html',
'status',
'published',
'signup_open_at',
'signup_close_at',
'form_schema_id',
'review_form_schema_id',
'branding_json',
'settings',
'scoring_rules_json',
];
/**
* @var array<string, string>
*/
protected $casts = [
'published' => 'boolean',
'signup_open_at' => 'datetime',
'signup_close_at' => 'datetime',
'branding_json' => 'array',
'settings' => 'array',
'scoring_rules_json' => 'array',
];
public function tracks(): HasMany
{
return $this->hasMany(CompetitionTrack::class)->orderBy('sort');
}
public function signupChannels(): HasMany
{
return $this->hasMany(SignupChannel::class)->orderByDesc('id');
}
public function formSchemaDefinitions(): HasMany
{
return $this->hasMany(FormSchemaDefinition::class, 'competition_id');
}
/**
* 嵌套路由参数 `{form_schema}` 的隐式绑定约定关系名为 formSchemas(见 Model::childRouteBindingRelationshipName)。
*/
public function formSchemas(): HasMany
{
return $this->formSchemaDefinitions();
}
public function formSchema(): BelongsTo
{
return $this->belongsTo(FormSchemaDefinition::class, 'form_schema_id');
}
public function reviewFormSchema(): BelongsTo
{
return $this->belongsTo(FormSchemaDefinition::class, 'review_form_schema_id');
}
/**
* 评审端是否开放登录/访问。settings.review_portal.enabled 缺省或非 false 时视为开启。
*/
public function isReviewPortalEnabled(): bool
{
$portal = $this->reviewPortalSettings();
if ($portal === null || ! array_key_exists('enabled', $portal)) {
return true;
}
return $portal['enabled'] !== false
&& $portal['enabled'] !== 0
&& $portal['enabled'] !== '0'
&& $portal['enabled'] !== 'false';
}
/**
* 关闭评审端时展示给评审员的说明(登录弹窗 / 接口提示)。
*/
public function reviewPortalClosedMessage(): string
{
$portal = $this->reviewPortalSettings();
$message = is_array($portal) ? trim((string) ($portal['message'] ?? '')) : '';
if ($message === '') {
return '评审通道暂未开放,请稍后再试';
}
return mb_substr($message, 0, 2000);
}
/**
* 公开接口用的评审端开关摘要。
*
* @return array{enabled: bool, message: string}
*/
public function reviewPortalPublicPayload(): array
{
$enabled = $this->isReviewPortalEnabled();
$portal = $this->reviewPortalSettings();
$stored = is_array($portal) ? trim((string) ($portal['message'] ?? '')) : '';
return [
'enabled' => $enabled,
'message' => $enabled
? mb_substr($stored, 0, 2000)
: $this->reviewPortalClosedMessage(),
];
}
/**
* @return array<string, mixed>|null
*/
private function reviewPortalSettings(): ?array
{
$settings = is_array($this->settings) ? $this->settings : [];
$portal = $settings['review_portal'] ?? null;
return is_array($portal) ? $portal : null;
}
}