aboutsummaryrefslogtreecommitdiff
path: root/lib/classes/ForumHelpers.php
blob: 3054dbc8ea4d71c9532a783f822acb46d4ea635a (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
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
<?php
/**
 * ForumHelpers.php - Some useful helpers for the forum
 *
 * 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 3 of
 * the License, or (at your option) any later version.
 *
 * @author      Till Glöggler <tgloeggl@uos.de>
 * @license     http://www.gnu.org/licenses/gpl-3.0.html GPL version 3
 * @category    Stud.IP
 */

class ForumHelpers {

    /**
     * The page for the current script run, modified by a global page-handle
     * @var int
     */
    static $page = 1;

    /**
     * helper_function for highlight($text, $highlight)
     *
     * @param  string  $text
     * @param  array   $highlight
     * @return string
     */
    public static function do_highlight($text, $highlight)
    {
        foreach ($highlight as $hl) {
            $text = preg_replace(
                '/' . preg_quote(htmlReady($hl), '/') . '/i',
                '<span class="highlight">$0</span>',
                $text
            );
        }
        return $text;
    }

    /**
     * This function highlights Text HTML-safe
     * (tags or words in tags are not highlighted, words between tags ARE highlighted)
     *
     * @param string $text the text where to words shall be highlighted, may contain tags
     * @param array $highlight an array of words to be highlighted
     * @return string the highlighted text
     */
    public static function highlight($text, $highlight)
    {
        if (empty($highlight)) {
            return $text;
        }

        $data = [];
        $treffer = [];

        // split text at every tag
        $pattern = '/<[^<]*>/U';
        preg_match_all($pattern, $text, $treffer, PREG_OFFSET_CAPTURE);

        if (sizeof($treffer[0]) == 0) {
            return self::do_highlight($text, $highlight);
        }

        // cycle trough the text between the tags and highlight all hits
        $last_pos = 0;
        foreach ($treffer[0] as $taginfo) {
            $size = mb_strlen($taginfo[0]);
            if ($taginfo[1] != 0) {
                $data[] = self::do_highlight(mb_substr($text, $last_pos, $taginfo[1] - $last_pos), $highlight);
            }

            $data[] = mb_substr($text, $taginfo[1], $size);
            $last_pos = $taginfo[1] + $size;
        }

        // don't miss the last portion of a posting
        if ($last_pos < mb_strlen($text)) {
            $data[] = self::do_highlight(mb_substr($text, $last_pos, mb_strlen($text) - $last_pos), $highlight);
        }

        return implode('', $data);
    }

    /**
     * Returns a human-readable version of the passed global Stud.IP permission.
     *
     * @param  string  $perm
     * @return string
     */
    public static function translate_perm($perm)
    {
        $mapping = [
            'root'   => _('Root'),
            'admin'  => _('Administrator/-in'),
            'dozent' => _('Lehrende/-r'),
            'tutor'  => _('Tutor/-in'),
            'autor'  => _('Autor/-in'),
            'user'   => _('Leser/-in'),
        ];

        // TODO: Activate next when devboard reliably runs on PHP7
        // return $mapping[$perm] ?? '';

        return isset($mapping[$perm]) ? $mapping[$perm] : '';
    }

    /**
     * return the currently chosen page
     *
     * @return  int
     */
    public static function getPage()
    {
        return self::$page;
    }

    /**
     * set the current page
     *
     * @param int $page_num the page
     */
    public static function setPage($page_num)
    {
        self::$page = $page_num;
    }

    /**
     * Return an info-text explaining the visit-status of the passed topic_di
     * which has the passed number of new entries.
     *
     * @param string $num_entries  the number of new entries
     * @param string $topic_id     the id of the topic
     *
     * @return string  a human readable, localized text
     */
    public static function getVisitText($num_entries, $topic_id)
    {
        if ($num_entries > 0) {
            $text = sprintf(_('Seit Ihrem letzten Besuch gibt es %s neue Beiträge'), $num_entries);
        } else {
            $all_entries = ForumEntry::countPostings($topic_id);

            if ($all_entries == 0) {
                $text = sprintf(_('Es gibt bisher keine Beiträge.'));
            } else if ($all_entries == 1) {
                $text = sprintf(_('Seit Ihrem letzten Besuch gab es nichts Neues.'
                      . ' Es ist ein alter Beitrag vorhanden.'));
            } else {
                $text = sprintf(_('Seit Ihrem letzten Besuch gab es nichts Neues.'
                      . ' Es sind %s alte Beiträge vorhanden.'), $all_entries);
            }
        }

        return $text;
    }

    /**
     * return the online status of the passed user, one of three possible
     * states is returned:
     *  - available
     *  - away
     *  - offline
     *
     * @staticvar type $online_status
     *
     * @param string $user_id
     *
     * @return string
     */
    public static function getOnlineStatus($user_id)
    {
        static $online_status;

        // check if the corresponding user's profile is visible
        if (get_visibility_by_id($user_id) == false) {
            return 'offline';
        }

        if ($GLOBALS['user']->id == $user_id) {
            return 'available';
        }

        if (!$online_status) {
            $online_users = get_users_online(10);
            foreach ($online_users as $username => $data) {
                if ($data['last_action'] >= 300) {
                    $online_status[$data['user_id']] = 'away';
                } else {
                    $online_status[$data['user_id']] = 'available';
                }
            }
        }

        return $online_status[$user_id] ?? 'offline';
    }

    /**
     * Create a pdf of all postings belonging to the passed seminar located
     * under the passed topic_id. The PDF is dispatched automatically.
     *
     * BEWARE: This function never returns, it dies after the PDF has been
     * (succesfully or not) dispatched.
     *
     * @param string $seminar_id
     * @param string $parent_id
     */
    public static function createPdf($seminar_id, $parent_id = null)
    {
        $seminar_name = get_object_name($seminar_id, 'sem');
        $data = ForumEntry::getList('dump', $parent_id ?: $seminar_id);
        $first_page = true;

        $document = new ExportPDF();
        $document->SetTitle(_('Forum'));
        $document->setHeaderTitle(sprintf(_("Forum \"%s\""), $seminar_name['name']));
        $document->addPage();

        foreach ($data as $entry) {
            if (Config::get()->FORUM_ANONYMOUS_POSTINGS && $entry['anonymous']) {
                $author = _('anonym');
            } else {
                $author = $entry['author'];
            }
            if ($entry['depth'] == 1) {
                if (!$first_page) {
                    $document->addPage();
                }
                $first_page = false;
                $document->addContent('!! '. _('Bereich') . ": {$entry['name_raw']}\n");
                $document->addContent($entry['content_raw']);
                $document->addContent("\n\n");
            } else if ($entry['depth'] == 2) {
                $document->addContent('! '. _('Thema') . ": {$entry['name_raw']}\n");
                $document->addContent('%%' . sprintf(_('erstellt von %s am %s'), $author,
                    strftime('%A %d. %B %Y, %H:%M', (int)$entry['mkdate'])) . '%%' . "\n");
                $document->addContent($entry['content_raw']);
                $document->addContent("\n--\n");
            } else if ($entry['depth'] == 3) {
                $document->addContent("**{$entry['name_raw']}**\n");
                $document->addContent('%%' . sprintf(_('erstellt von %s am %s'), $author,
                    strftime('%A %d. %B %Y, %H:%M', (int)$entry['mkdate'])) . '%%' . "\n");
                $document->addContent($entry['content_raw']);
                $document->addContent("\n--\n");
            }
        }

        $document->dispatch($seminar_name['name'] ." - Forum");
        die;
    }


    /**
     * Returns the id of the currently selected seminar or false, if no seminar
     * is selected
     *
     * @return mixed  seminar_id or false
     */
    public static function getSeminarId()
    {
        return Context::getId();
    }

    /**
     * replace in the passed text every %%% with <% and every ### with %>
     * This is used to work around a limitation of the Button-API in combination
     * with the underscore.js way of inserting template vars.
     *
     * The Button-API correctly replaces < > with tags, but underscore.js is
     * unable to find them in their tag-represenation
     *
     * @param string $text the text to apply the replacements on
     *
     * @return string the modified text
     */
    public static function replace($text)
    {
        return str_replace('%%%', '<%', str_replace('###', '%>', $text));
    }
}