aboutsummaryrefslogtreecommitdiff
path: root/lib/models/Forum/Posting.php
blob: 0bca81418132ae9c9c350d37b764aeb305039d2e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
<?php
namespace Forum;

use OpenGraph;
use SimpleORMap;
use Forum\Service\PostingNotification;
use User;
use Forum\DTO\Member as MemberDTO;

/**
 * @property string $posting_id
 * @property string $discussion_id
 * @property string $range_id
 * @property string $content
 * @property boolean $anonymous
 * @property int $mkdate
 * @property int $chdate
 *
 * @property Discussion $discussion
 * @property Posting $posting
 * @property PostingReaction[] $reactions
 * @property User $user
 * @property MemberDTO $author
 */
class Posting extends SimpleORMap
{
    protected static function configure($config = [])
    {
        $config['db_table'] = 'forum_postings';

        $config['belongs_to']['discussion'] = [
            'class_name' => Discussion::class,
            'foreign_key' => 'discussion_id',
            'assoc_foreign_key' => 'discussion_id'
        ];

        $config['belongs_to']['posting'] = [
            'class_name' => self::class,
            'foreign_key' => 'parent_id',
            'assoc_foreign_key' => 'posting_id'
        ];

        $config['belongs_to']['user'] = [
            'class_name' => User::class,
            'foreign_key' => 'user_id',
            'assoc_foreign_key' => 'user_id'
        ];

        $config['has_many']['reactions'] = [
            'class_name' => PostingReaction::class,
            'foreign_key' => 'posting_id',
            'assoc_foreign_key' => 'posting_id'
        ];

        $config['additional_fields']['author']['get'] = 'getAuthor';
        $config['registered_callbacks']['after_create'][] = 'onCreate';
        $config['registered_callbacks']['after_delete'][] = 'onDelete';

        parent::configure($config);
    }

    public function getAuthor(): ?MemberDTO
    {
        if ($this->anonymous && $this->user_id !== User::findCurrent()?->user_id) {
            return MemberDTO::fromArray();
        }

        $user = $this->user;
        if ($user) {
            return MemberDTO::fromUser($user, $this->range_id);
        }

        return null;
    }

    public static function getRecentPosts(array|string $range_ids): array
    {
        $user = User::findCurrent();
        if (!$user) {
            return [];
        }
        $single = is_string($range_ids);
        if ($single) {
            $range_ids = [$range_ids];
        }
        $forum_plugin = \PluginManager::getInstance()->getPlugin(\CoreForum::class);
        $query =
            "SELECT
                forum_topics.range_id,
                forum_discussions.*,
                COUNT(DISTINCT forum_postings.posting_id) AS 'posts'
            FROM forum_topics
            JOIN forum_discussions USING(topic_id)
            JOIN forum_postings USING(discussion_id)
            LEFT JOIN object_user_visits AS ouv
               ON ouv.object_id = forum_topics.range_id
                 AND ouv.user_id = :user_id
                 AND ouv.plugin_id = :plugin_id
            WHERE forum_topics.range_id IN (:range_ids)
              AND forum_postings.user_id != :user_id
              AND forum_postings.mkdate > IF(ouv.visitdate > :threshold, ouv.visitdate, :threshold)
            GROUP BY forum_topics.range_id, forum_discussions.discussion_id";
        $params = [
            ':range_ids' => $range_ids,
            ':user_id' => $user->id,
            ':plugin_id' => $forum_plugin->getPluginId(),
            ':threshold' => object_get_visit_threshold(),
        ];

        $res = \DBManager::get()->fetchAll($query, $params);
        $by_course = [];
        foreach ($res as $row) {
            $by_course[$row['range_id']][] = $row;
        }
        return $single ? (array_pop($by_course) ?? []) : $by_course;
    }

    public function getOpenGraphURLs(): array
    {
        $content = preg_replace("~<blockquote(.*?)>(.*)</blockquote>~si", '', $this['content']);
        return array_filter(OpenGraph::extract($content)->toArray(), fn($og) => $og['is_opengraph']);
    }

    public function onCreate(): void
    {
        $postingNotification = new PostingNotification($this);
        $postingNotification->notifySubscribers();
    }

    public function onDelete(): void
    {
        PostingReaction::deleteBySQL("posting_id = ?", [$this->posting_id]);
    }
}