aboutsummaryrefslogtreecommitdiff
path: root/lib/models/BlubberComment.php
blob: 1f50d1d6b8b6d7260bd37c9b007bb58e0cb29543 (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
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
<?php
/**
 * BlubberComment
 * Model class for BlubberComments
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of
 * the License, or (at your option) any later version.
 *
 * @author      Rasmus Fuhse <fuhse@data-quest.de>
 * @license     http://www.gnu.org/licenses/gpl-2.0.html GPL version 2
 * @category    Stud.IP
 * @since       4.5
 *
 * @property string $id alias column for comment_id
 * @property string $comment_id database column
 * @property string $thread_id database column
 * @property string $user_id database column
 * @property int $external_contact database column
 * @property string|null $content database column
 * @property string|null $network database column
 * @property int|null $chdate database column
 * @property int|null $mkdate database column
 * @property BlubberThread $thread belongs_to BlubberThread
 * @property User $user belongs_to User
 * @property ExternalUser $external_user belongs_to ExternalUser
 */

class BlubberComment extends SimpleORMap implements PrivacyObject
{
    /**
     * Configures this model.
     *
     * @param array $config Configuration array
     */
    protected static function configure($config = [])
    {
        $config['db_table'] = 'blubber_comments';

        $config['belongs_to']['thread'] = [
            'class_name'  => BlubberThread::class,
            'foreign_key' => 'thread_id'
        ];
        $config['belongs_to']['user'] = [
            'class_name'        => User::class,
            'foreign_key'       => 'user_id',
            'assoc_foreign_key' => 'user_id',
        ];
        $config['belongs_to']['external_user'] = [
            'class_name'        => ExternalUser::class,
            'foreign_key'       => 'user_id',
            'assoc_foreign_key' => 'external_contact_id',
        ];

        $config['registered_callbacks']['before_create'][] = 'transformMentions';
        $config['registered_callbacks']['before_create'][] = 'cbAddFollowing';
        $config['registered_callbacks']['after_create'][] = 'cbCreateNotifications';
        $config['registered_callbacks']['before_delete'][] = 'cbCreateDeleteEvent';

        parent::configure($config);
    }

    /**
     * Export available blubber comments of a given user into a storage object
     * (an instance of the StoredUserData class) for that user.
     *
     * @param StoredUserData $storage object to store data into
     */
    public static function exportUserData(StoredUserData $storage)
    {
        $sorm = self::findBySQL("user_id = ? AND external_contact = '0'", [$storage->user_id]);
        if ($sorm) {
            $field_data = [];
            foreach ($sorm as $row) {
                $field_data[] = $row->toRawArray();
            }
            if ($field_data) {
                $storage->addTabularData(_('Blubber-Kommentare'), 'blubbercomments', $field_data);
            }
        }
    }

    public function getJSONdata()
    {
        $output = $this->toRawArray();

        if ($this['external_contact']) {
            $output['user_id']       = $this->user_id;
            $output['avatar']        = $this->external_user
                ? $this->external_user['avatar_url']
                : "";
            $output['user_name']     = $this->external_user
                ? $this->external_user['name']
                : _('unbekannt');
            $output['user_username'] = '';
        } else {
            $output['user_id']       = $this->user_id;
            $output['avatar']        = Avatar::getAvatar($this['user_id'])->getURL(Avatar::MEDIUM);
            $output['user_name']     = $this->user ? $this->user->getFullName() : _('unbekannt');
            $output['user_username'] = $this->user ? $this->user['username'] : '';
        }
        $output['class']         = $this['user_id'] === $GLOBALS['user']->id ? 'mine' : 'theirs';
        $output['html']          = blubberReady($this['content']) . $this->getOpenGraphURLs()->render();
        $output['writable']      = $this->isWritable();
        $output['chdate']        = (int) $output['chdate'];
        $output['mkdate']        = (int) $output['mkdate'];
        return $output;
    }

    /**
     * @param string $user_id  optional; use this ID instead of $GLOBALS['user']->id
     *
     * @SuppressWarnings(PHPMD.Superglobals)
     */
    public function isWritable(?string $user_id = null)
    {
        $user_id = $user_id ?? $GLOBALS['user']->id;
        return $user_id === $this['user_id']
            || $GLOBALS['perm']->have_perm('root', $user_id)
            || ($this->thread['context_type'] === 'course' && $this->thread->isWritable($user_id));
    }

    public function getOpenGraphURLs()
    {
        return OpenGraph::extract($this['content']);
    }

    public function transformMentions()
    {
        $callback = [$this->thread, 'mention'];
        $this['content'] = preg_replace_callback('/\B@("[^\n"]+"|\S+)/', $callback, $this['content']);
    }

    /**
     * Adds a following on a first comment to the global stream if it is
     * configured to be opt-in.
     */
    public function cbAddFollowing()
    {
        // Everything is opt-out, no need to add a following
        if (Config::get()->BLUBBER_GLOBAL_THREAD_OPTOUT) {
            return;
        }

        // Only global thread is opt-out
        if ($this->thread->id !== 'global') {
            return;
        }

        // Check whether user has commented before and thus already had
        // a following inserted
        $query = "SELECT 1
                  FROM `blubber_comments`
                  WHERE `thread_id` = :thread_id
                    AND `user_id` = :user_id";
        $has_commented = DBManager::get()->fetchColumn($query, [
            ':thread_id' => $this->thread_id,
            ':user_id'   => $GLOBALS['user']->id,
        ]);

        if ($has_commented) {
            return;
        }

        // Add following
        $this->thread->addFollowingByUser();
    }

    public function cbCreateNotifications()
    {
        $this->thread->notifyUsersForNewComment($this);
    }

    public function cbCreateDeleteEvent()
    {
        $statement = DBManager::get()->prepare("
            INSERT IGNORE INTO blubber_events_queue
            SET event_type = 'delete',
                item_id = ?,
                mkdate = UNIX_TIMESTAMP()
        ");
        $statement->execute([$this->getId()]);
        $statement = DBManager::get()->prepare("
            DELETE FROM blubber_events_queue
            WHERE mkdate <= UNIX_TIMESTAMP() - 60 * 15
        ");
        $statement->execute();
    }
}