the browser-facing portion of osu!
at master 3.8 kB view raw
1<?php 2 3// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the GNU Affero General Public License v3.0. 4// See the LICENCE file in the repository root for full licence text. 5 6namespace App\Models; 7 8use App\Traits\Validatable; 9 10/** 11 * @property \Carbon\Carbon $created_at 12 * @property array|null $details 13 * @property string $name 14 * @property int $id 15 * @property \Carbon\Carbon $updated_at 16 * @property User $user 17 * @property int $user_id 18 */ 19class UserNotificationOption extends Model 20{ 21 use Validatable; 22 23 const BEATMAPSET_DISQUALIFIABLE_NOTIFICATIONS = [ 24 Notification::BEATMAPSET_DISCUSSION_QUALIFIED_PROBLEM, 25 Notification::BEATMAPSET_DISQUALIFY, 26 ]; 27 28 const BEATMAPSET_MODDING = 'beatmapset:modding'; // matches Follow notifiable_type:subtype 29 const CHANNEL_ANNOUNCEMENT = 'channel_announcement'; 30 const COMMENT_REPLY = 'comment_reply'; 31 const DELIVERY_MODES = ['mail', 'push']; 32 const FORUM_TOPIC_REPLY = Notification::FORUM_TOPIC_REPLY; 33 const MAPPING = 'mapping'; 34 35 const HAS_DELIVERY_MODES = [ 36 Notification::BEATMAP_OWNER_CHANGE, 37 self::MAPPING, 38 self::BEATMAPSET_MODDING, 39 Notification::CHANNEL_MESSAGE, 40 Notification::COMMENT_NEW, 41 self::FORUM_TOPIC_REPLY, 42 ]; 43 44 const SUPPORTS_NOTIFICATIONS = [ 45 ...self::BEATMAPSET_DISQUALIFIABLE_NOTIFICATIONS, 46 ...self::HAS_DELIVERY_MODES, 47 self::CHANNEL_ANNOUNCEMENT, 48 ]; 49 50 protected $casts = [ 51 'details' => 'array', 52 ]; 53 54 public static function supportsNotifications(string $name) 55 { 56 return in_array($name, static::SUPPORTS_NOTIFICATIONS, true); 57 } 58 59 public function user() 60 { 61 return $this->belongsTo(User::class, 'user_id'); 62 } 63 64 public function setDetailsAttribute($value) 65 { 66 $details = $this->details ?? []; 67 68 if (!is_array($value)) { 69 $value = null; 70 } 71 72 if (in_array($this->name, static::BEATMAPSET_DISQUALIFIABLE_NOTIFICATIONS, true)) { 73 if (is_array($value['modes'] ?? null)) { 74 $modes = array_filter($value['modes'], 'is_string'); 75 $validModes = array_keys(Beatmap::MODES); 76 77 $details['modes'] = array_values(array_intersect($modes, $validModes)); 78 } 79 } 80 81 if (in_array($this->name, static::HAS_DELIVERY_MODES, true)) { 82 foreach (static::DELIVERY_MODES as $mode) { 83 if (isset($value[$mode])) { 84 $details[$mode] = get_bool($value[$mode] ?? null); 85 } 86 } 87 } 88 89 if ($this->name === Notification::COMMENT_NEW) { 90 if (isset($value[static::COMMENT_REPLY])) { 91 $details[static::COMMENT_REPLY] = get_bool($value[static::COMMENT_REPLY]); 92 } 93 } 94 95 if (!empty($details)) { 96 $detailsString = json_encode($details); 97 } 98 99 $this->attributes['details'] = $detailsString ?? null; 100 } 101 102 public function setNameAttribute($value) 103 { 104 if (!static::supportsNotifications($value)) { 105 $value = null; 106 } 107 108 $this->attributes['name'] = $value; 109 } 110 111 public function isValid() 112 { 113 $this->validationErrors()->reset(); 114 115 if (!present($this->user_id)) { 116 $this->validationErrors()->add('user_id', 'required'); 117 } 118 119 if (!present($this->name)) { 120 $this->validationErrors()->add('name', 'required'); 121 } 122 123 return $this->validationErrors()->isEmpty(); 124 } 125 126 public function save(array $options = []) 127 { 128 return $this->isValid() && parent::save($options); 129 } 130 131 public function validationErrorsTranslationPrefix(): string 132 { 133 return 'user_notification_option'; 134 } 135}