<commit_before><?php

/**
 *    Copyright (c) ppy Pty Ltd <<EMAIL>>.
 *
 *    This file is part of osu!web. osu!web is distributed with the hope of
 *    attracting more community contributions to the core ecosystem of osu!.
 *
 *    osu!web is free software: you can redistribute it and/or modify
 *    it under the terms of the Affero GNU General Public License version 3
 *    as published by the Free Software Foundation.
 *
 *    osu!web is distributed WITHOUT ANY WARRANTY; without even the implied
 *    warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 *    See the GNU Affero General Public License for more details.
 *
 *    You should have received a copy of the GNU Affero General Public License
 *    along with osu!web.  If not, see <http://www.gnu.org/licenses/>.
 */

namespace App\Models\Forum;

use App\Events\UserSubscriptionChangeEvent;
use App\Models\User;

/**
 * @property bool $mail
 * @property bool $notify_status
 * @property Topic $topic
 * @property int $topic_id
 * @property User $user
 * @property int $user_id
 */
class TopicWatch extends Model
{
    protected $table = 'phpbb_topics_watch';
    protected $casts = [
        'notify_status' => 'boolean',
        'mail' => 'boolean',
    ];

    public $timestamps = false;

    protected $primaryKeys = ['topic_id', 'user_id'];

    public static function unreadCount($user)
    {
        if ($user === null) {
            return 0;
        }

        $watch = new static;
        $topic = new Topic;
        $track = new TopicTrack;

        return static
            ::join($topic->getTable(), $topic->qualifyColumn('topic_id'), '=', $watch->qualifyColumn('topic_id'))
            ->leftJoin($track->getTable(), function ($join) use ($track, $watch) {
                $join
                    ->on($track->qualifyColumn('topic_id'), '=', $watch->qualifyColumn('topic_id'))
                    ->on($track->qualifyColumn('user_id'), '=', $watch->qualifyColumn('user_id'));
            })
            ->where($watch->qualifyColumn('user_id'), '=', $user->user_id)
            ->where(function ($query) use ($topic, $track) {
                $query
                    ->whereRaw("{$topic->qualifyColumn('topic_last_post_time')} > {$track->qualifyColumn('mark_time')}")
                    ->orWhereNull($track->qualifyColumn('mark_time'));
            })
            ->count();
    }

    public static function watchStatus($user, $topics)
    {
        return static::where('user_id', '=', $user->getKey())
            ->whereIn('topic_id', $topics->pluck('topic_id'))
            ->get()
            ->keyBy('topic_id');
    }

    public static function lookup($topic, $user)
    {
        if ($user === null) {
            return new static(['topic_id' => $topic->getKey()]);
        } else {
            return static::lookupQuery($topic, $user)->first() ?? new static([
                'topic_id' => $topic->getKey(),
                'user_id' => $user->getKey(),
            ]);
        }
    }

    public static function setState($topic, $user, $state)
    {
        $tries = 0;

        while (true) {
            $watch = static::lookup($topic, $user);

            try {
                if ($state === 'not_watching') {
                    $event = 'remove';
                    $watch->delete();
                } else {
                    $event = 'add';
                    $mail = $state === 'watching_mail';

                    $watch->fill(['mail' => $mail])->saveOrExplode();
                }

                event(new UserSubscriptionChangeEvent($event, $user, $topic));

                return $watch;
            } catch (Exception $e) {
                if (is_sql_unique_exception($e) && $tries < 2) {
                    $tries++;
                } else {
                    throw $e;
                }
            }
        }
    }

    public function topic()
    {
        return $this->belongsTo(Topic::class, 'topic_id');
    }

    public function user()
    {
        return $this->belongsTo(User::class, 'user_id');
    }
<commit_msg>Match forum topic popup notification with email<commit_after><?php

/**
 *    Copyright (c) <NAME>ty Ltd <<EMAIL>>.
 *
 *    This file is part of osu!web. osu!web is distributed with the hope of
 *    attracting more community contributions to the core ecosystem of osu!.
 *
 *    osu!web is free software: you can redistribute it and/or modify
 *    it under the terms of the Affero GNU General Public License version 3
 *    as published by the Free Software Foundation.
 *
 *    osu!web is distributed WITHOUT ANY WARRANTY; without even the implied
 *    warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 *    See the GNU Affero General Public License for more details.
 *
 *    You should have received a copy of the GNU Affero General Public License
 *    along with osu!web.  If not, see <http://www.gnu.org/licenses/>.
 */

namespace App\Models\Forum;

use App\Events\UserSubscriptionChangeEvent;
use App\Models\User;

/**
 * @property bool $mail
 * @property bool $notify_status
 * @property Topic $topic
 * @property int $topic_id
 * @property User $user
 * @property int $user_id
 */
class TopicWatch extends Model
{
    protected $table = 'phpbb_topics_watch';
    protected $casts = [
        'notify_status' => 'boolean',
        'mail' => 'boolean',
    ];

    public $timestamps = false;

    protected $primaryKeys = ['topic_id', 'user_id'];

    public static function unreadCount($user)
    {
        if ($user === null) {
            return 0;
        }

        $watch = new static;
        $topic = new Topic;
        $track = new TopicTrack;

        return static
            ::join($topic->getTable(), $topic->qualifyColumn('topic_id'), '=', $watch->qualifyColumn('topic_id'))
            ->leftJoin($track->getTable(), function ($join) use ($track, $watch) {
                $join
                    ->on($track->qualifyColumn('topic_id'), '=', $watch->qualifyColumn('topic_id'))
                    ->on($track->qualifyColumn('user_id'), '=', $watch->qualifyColumn('user_id'));
            })
            ->where($watch->qualifyColumn('user_id'), '=', $user->user_id)
            ->where(function ($query) use ($topic, $track) {
                $query
                    ->whereRaw("{$topic->qualifyColumn('topic_last_post_time')} > {$track->qualifyColumn('mark_time')}")
                    ->orWhereNull($track->qualifyColumn('mark_time'));
            })
            ->count();
    }

    public static function watchStatus($user, $topics)
    {
        return static::where('user_id', '=', $user->getKey())
            ->whereIn('topic_id', $topics->pluck('topic_id'))
            ->get()
            ->keyBy('topic_id');
    }

    public static function lookup($topic, $user)
    {
        if ($user === null) {
            return new static(['topic_id' => $topic->getKey()]);
        } else {
            return static::lookupQuery($topic, $user)->first() ?? new static([
                'topic_id' => $topic->getKey(),
                'user_id' => $user->getKey(),
            ]);
        }
    }

    public static function setState($topic, $user, $state)
    {
        $tries = 0;

        while (true) {
            $watch = static::lookup($topic, $user);

            try {
                if ($state === 'not_watching') {
                    $notify = false;
                    $watch->delete();
                } else {
                    $notify = $state === 'watching_mail';

                    $watch->fill(['mail' => $notify])->saveOrExplode();
                }

                $event = $notify ? 'add' : 'remove';

                event(new UserSubscriptionChangeEvent($event, $user, $topic));

                return $watch;
            } catch (Exception $e) {
                if (is_sql_unique_exception($e) && $tries < 2) {
                    $tries++;
                } else {
                    throw $e;
                }
            }
        }
    }

    public function topic()
    {
        return $this->belongsTo(Topic::class, 'topic_id');
    }

    public function user()
    {
        return $this->belongsTo(User::class, 'user_id');
    }

{'fraction_non_alphanumeric': 0.1442858885229906, 'fraction_numerical': 0.0009757287474082205, 'mean_word_length': 1.9677886355410785, 'pattern_counts': {'":': 0, '<': 14, '<?xml version=': 0, '>': 94, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6414650', 'n_tokens_mistral': 2355, 'n_tokens_neox': 2280, 'n_words': 587}