aboutsummaryrefslogtreecommitdiff
path: root/lib/classes/WikiFormat.php
blob: 9f0d8f87b2b5b3ca0bd0d086cd88276f38c0f192 (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
<?php
/**
 * StudipFormat.php - simple Stud.IP text markup parser
 *
 * 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      Elmar Ludwig
 * @license     http://www.gnu.org/licenses/gpl-2.0.html GPL version 2
 * @category    Stud.IP
 */

class WikiFormat extends StudipFormat
{
    private static $wiki_rules = [
        'wiki-links' => [
            'start'    => '\[\[(.*?)(?:\|(.*?))?\]\]',
            'end'      => '',
            'callback' => 'WikiFormat::markupWikiLinks',
            'before'   => 'links'
        ],
    ];

    private $range_id = null;
    private $page_id = null;

    /**
     * Adds a new markup rule to the wiki markup set. This can
     * also be used to replace an existing markup rule. The end regular
     * expression is optional (i.e. may be NULL) to indicate that this
     * rule has an empty content model. The callback is called whenever
     * the rule matches and is passed the following arguments:
     *
     * - $markup    the markup parser object
     * - $matches   match results of preg_match for $start
     * - $contents  (parsed) contents of this markup rule
     *
     * Sometimes you may want your rule to apply before another specific rule
     * will apply. For this case the parameter $before defines a rulename of
     * existing markup, before which your rule should apply.
     *
     * @param string $name      name of this rule
     * @param string $start     start regular expression
     * @param string $end       end regular expression (optional)
     * @param callback $callback function generating output of this rule
     * @param string $before mark before which rule this rule should be appended
     */
    public static function addWikiMarkup($name, $start, $end, $callback, $before = null)
    {
        $inserted = false;
        foreach (self::$wiki_rules as $rule_name => $rule) {
            if ($rule_name === $before) {
                self::$wiki_rules[$name] = compact('start', 'end', 'callback');
                $inserted = true;
            }
            if ($inserted) {
                unset(self::$wiki_rules[$rule_name]);
                self::$wiki_rules[$rule_name] = $rule;
            }
        }
        if (!$inserted) {
            self::$wiki_rules[$name] = compact('start', 'end', 'callback');
        }
    }

    /**
     * Returns a single markup-rule if it exists.
     * @return array: array('start' => "...", 'end' => "...", 'callback' => "...")
     */
    public static function getWikiMarkup($name)
    {
        return self::$wiki_rules[$name];
    }

    /**
     * Removes a markup rule from the wiki markup set.
     *
     * @param string $name Name of the rule
     */
    public static function removeWikiMarkup($name)
    {
        unset(self::$wiki_rules[$name]);
    }

    /**
     * Initializes a new WikiFormat instance.
     * @param string|null $range_id ID of the course or institute.
     */
    public function __construct($range_id = null, $page_id = null)
    {
        parent::__construct();
        $this->range_id = $range_id;
        $this->page_id  = $page_id;
        foreach (self::$wiki_rules as $name => $rule) {
            $this->addMarkup(
                $name,
                $rule['start'],
                $rule['end'],
                $rule['callback'],
                $rule['before'] ?? null
            );
        }
    }

    /**
     * Returns the range_id of the wiki-page for which the markup is desired.
     * @return string|null
     */
    public function getRangeId()
    {
        return $this->range_id;
    }

    /**
     * Returns the page_id of the wiki-page for which the markup is desired.
     * @return string|null
     */
    public function getPageId()
    {
        return $this->page_id;
    }

    /**
     * Stud.IP markup for wiki links
     *
     * @param  StudipFormat $markup  Markup object
     * @param  array        $matches Found matches
     * @return string
     */
    protected static function markupWikiLinks($markup, $matches)
    {
        $keyword = decodeHTML($matches[1]);
        $display_page = !empty($matches[2]) ? $markup->format($matches[2]) : htmlReady($keyword);

        $range_id = $markup->getRangeId() ?? Context::getId();
        $page = WikiPage::findByName($range_id, trim($keyword));

        // Page does not exist
        if (!$page) {
            return sprintf('<a href="%s">%s(?)</a>',
                URLHelper::getLink('dispatch.php/course/wiki/edit', [
                    'keyword'   => trim($keyword),
                    'parent_id' => $markup->getPageId(),
                    'cid'       => $range_id,
                ]),
                $display_page
            );
        }

        // Page is visible to current user
        if ($page->isReadable()) {
            return sprintf(
                '<a href="%s">%s</a>',
                URLHelper::getLink('dispatch.php/course/wiki/page/' . $page->id, ['cid' => $range_id]),
                $display_page
            );
        }

        // Page is not visible to current user and show be displayed accordingly
        return sprintf(
            '<a href="%s" class="wiki-restricted" title="%s">%s</a>',
            URLHelper::getLink('dispatch.php/course/wiki/page/' . $page->id, ['cid' => $range_id]),
            sprintf(
                _('Sie haben keine Berechtigung, die Seite %s zu lesen!'),
                htmlReady($keyword)
            ),
            $display_page
        );
    }

}