Completed
Push — master ( c61892...5f8c85 )
by Andreas
23:09
created

net_nemein_wiki_wikipage::_on_loaded()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 2.5

Importance

Changes 0
Metric Value
cc 2
eloc 3
nc 2
nop 0
dl 0
loc 6
ccs 2
cts 4
cp 0.5
crap 2.5
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * @package net.nemein.wiki
4
 * @author The Midgard Project, http://www.midgard-project.org
5
 * @copyright The Midgard Project, http://www.midgard-project.org
6
 * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License
7
 */
8
9
/**
10
 * Wiki note helper class to be used by other components
11
 *
12
 * @package net.nemein.wiki
13
 */
14
class net_nemein_wiki_wikipage extends midcom_db_article
15
{
16
    public $autodelete_dependents = [
17
        net_nemein_wiki_link_dba::class => 'frompage'
18
    ];
19
20 10
    public function _on_loaded()
21
    {
22
        // Backwards compatibility
23 10
        if ($this->name == '') {
24
            $this->name = midcom_helper_misc::urlize($this->title);
25
            $this->update();
26
        }
27 10
    }
28
29 3
    public function _on_creating()
30
    {
31 3
        if (   $this->title == ''
32 3
            || !$this->topic) {
33
            // We must have wikiword and topic at this stage
34
            return false;
35
        }
36
37
        // Check for duplicates
38 3
        $qb = self::new_query_builder();
39 3
        $qb->add_constraint('topic', '=', $this->topic);
40 3
        $qb->add_constraint('title', '=', $this->title);
41 3
        if ($qb->count() > 0) {
42
            midcom_connection::set_error(MGD_ERR_OBJECT_NAME_EXISTS);
43
            return false;
44
        }
45
46
        // Generate URL-clean name
47 3
        if ($this->name != 'index') {
48 1
            $this->name = midcom_helper_misc::urlize($this->title);
49
        }
50 3
        return true;
51
    }
52
53 4
    public function _on_updating()
54
    {
55 4
        if (midcom::get()->auth->user) {
56
            // Place current user in the page authors list
57
            $authors = explode('|', substr($this->metadata->authors, 1, -1));
58
            if (!in_array(midcom::get()->auth->user->guid, $authors)) {
59
                $authors[] = midcom::get()->auth->user->guid;
60
                $this->metadata->authors = '|' . implode('|', $authors) . '|';
61
            }
62
        }
63 4
        return parent::_on_updating();
64
    }
65
66 4
    public function _on_updated()
67
    {
68 4
        parent::_on_updated();
69 4
        $this->update_watchers();
70 4
        $this->update_link_cache();
71 4
    }
72
73
    /**
74
     * Caches links in the wiki page into database for faster "what links here" queries
75
     */
76 4
    private function update_link_cache()
77
    {
78 4
        $parser = new net_nemein_wiki_parser($this);
79 4
        $links_in_content = $parser->find_links_in_content();
80
81 4
        $qb = net_nemein_wiki_link_dba::new_query_builder();
82 4
        $qb->add_constraint('frompage', '=', $this->id);
83
84
        // Check links in DB versus links in content to see what needs to be removed
85 4
        foreach ($qb->execute() as $link) {
86 2
            if (!array_key_exists($link->topage, $links_in_content)) {
87
                // This link is not any more in content, remove
88 1
                $link->delete();
89 1
                continue;
90
            }
91
            //no change for this link
92 1
            unset($links_in_content[$link->topage]);
93
        }
94
95
        // What is still left needs to be added
96 4
        $links_in_content = array_keys($links_in_content);
97 4
        foreach ($links_in_content as $wikilink) {
98 1
            $link = new net_nemein_wiki_link_dba();
99 1
            $link->frompage = $this->id;
100 1
            $link->topage = $wikilink;
101 1
            debug_add("Creating net_nemein_wiki_link_dba: from page #{$link->frompage}, to page: '$link->topage'");
102 1
            $link->create();
103
        }
104 4
    }
105
106 4
    private function list_watchers() : array
107
    {
108 4
        $topic = new midcom_db_topic($this->topic);
109
        // Get list of people watching this page
110 4
        $watchers = [];
111 4
        $qb = new midgard_query_builder('midgard_parameter');
112 4
        $qb->add_constraint('domain', '=', 'net.nemein.wiki:watch');
113 4
        $qb->begin_group('OR');
114
            // List people watching the whole wiki
115 4
            $qb->add_constraint('parentguid', '=', $topic->guid);
116
            // List people watching this particular page
117 4
            $qb->add_constraint('parentguid', '=', $this->guid);
118 4
        $qb->end_group();
119
120 4
        foreach ($qb->execute() as $parameter) {
121
            if (in_array($parameter->name, $watchers)) {
122
                // We found this one already, skip
123
                continue;
124
            }
125
126
            $watchers[] = $parameter->name;
127
        }
128 4
        return $watchers;
129
    }
130
131 4
    private function update_watchers()
132
    {
133 4
        $watchers = $this->list_watchers();
134 4
        if (empty($watchers)) {
135 4
            return;
136
        }
137
138
        $diff = $this->get_diff();
139
        if (empty($diff)) {
140
            // No sense to email empty diffs
141
            return;
142
        }
143
144
        // Construct the message
145
        $message = [];
146
        $user_string = midcom::get()->i18n->get_string('anonymous', 'net.nemein.wiki');
147
        if (midcom::get()->auth->user) {
148
            $user = midcom::get()->auth->user->get_storage();
149
            $user_string = $user->name;
150
        }
151
        // Title for long notifications
152
        $message['title'] = sprintf(midcom::get()->i18n->get_string('page %s has been updated by %s', 'net.nemein.wiki'), $this->title, $user_string);
153
        // Content for long notifications
154
        $message['content']  = "{$message['title']}\n\n";
155
156
        $message['content'] .= midcom::get()->i18n->get_string('page modifications', 'net.nemein.wiki') . ":\n";
157
        $message['content'] .= "\n{$diff}\n\n";
158
159
        $message['content'] .= midcom::get()->i18n->get_string('link to page', 'net.nemein.wiki') . ":\n";
160
        $message['content'] .= midcom::get()->permalinks->create_permalink($this->guid);
161
162
        // Content for short notifications
163
        $topic = new midcom_db_topic($this->topic);
164
        $message['abstract'] = sprintf(midcom::get()->i18n->get_string('page %s has been updated by %s in wiki %s', 'net.nemein.wiki'), $this->title, $user_string, $topic->extra);
165
166
        debug_add("Processing list of Wiki subscribers");
167
168
        // Send the message out
169
        foreach ($watchers as $recipient) {
170
            debug_add("Notifying {$recipient}...");
171
            org_openpsa_notifications::notify('net.nemein.wiki:page_updated', $recipient, $message);
172
        }
173
    }
174
175
    private function get_diff() : string
176
    {
177
        // Load the RCS handler
178
        $rcs_handler = midcom::get()->rcs->load_backend($this);
179
180
        // Find out what versions to diff
181
        $history = $rcs_handler->list_history_numeric();
182
        if (count($history) < 2) {
183
            return '';
184
        }
185
        $this_version = $history[0];
186
        $prev_version = $history[1];
187
188
        try {
189
            $diff_fields = $rcs_handler->get_diff($prev_version, $this_version);
190
        } catch (midcom_error $e) {
191
            $e->log();
192
            return '';
193
        }
194
195
        if (!array_key_exists('diff', $diff_fields['content'])) {
196
            // No differences
197
            return '';
198
        }
199
200
        return $diff_fields['content']['diff'];
201
    }
202
}
203