'👍', 'love' => '❤️', 'laugh' => '😂', 'wow' => '😮', 'sad' => '😢', 'angry' => '😠', 'celebrate' => '🎉', 'thinking' => '🤔', 'clap' => '👏', 'fire' => '🔥', ]; /** * Get the parent reactable model (comment, post, thread, etc.) */ public function reactable(): MorphTo { return $this->morphTo(); } /** * Get the user who made the reaction */ public function user(): BelongsTo { return $this->belongsTo(User::class); } /** * Get the emoji for this reaction type */ public function getEmojiAttribute(): string { return self::TYPES[$this->type] ?? '👍'; } /** * Get formatted type name */ public function getFormattedTypeAttribute(): string { return ucfirst($this->type); } /** * Get available reaction types for a specific context * Extensions can customize which reactions are available */ public static function getAvailableTypes(string $context = 'default'): array { $contextTypes = match($context) { 'forum' => ['like', 'love', 'thinking', 'clap', 'fire'], // Forum-specific reactions 'social' => ['like', 'love', 'celebrate', 'fire', 'thinking'], // Social/comment reactions 'celebration' => ['like', 'love', 'celebrate', 'clap', 'fire'], // Achievement/celebration contexts default => array_keys(self::TYPES), // All reaction type names }; // Return type => emoji mapping for the context return array_intersect_key(self::TYPES, array_flip($contextTypes)); } /** * Scope to get reactions for a specific reactable */ public function scopeForReactable($query, $reactableType, $reactableId) { return $query->where('reactable_type', $reactableType) ->where('reactable_id', $reactableId); } /** * Scope to get reactions by type */ public function scopeOfType($query, string $type) { return $query->where('type', $type); } /** * Scope to get reactions by user */ public function scopeByUser($query, int $userId) { return $query->where('user_id', $userId); } }