Completed
Push — master ( cde53c...fe9df2 )
by Andreas
27:57 queued 42s
created

net_nemein_wiki_wikipage::_on_updated()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 3
nc 1
nop 0
dl 0
loc 5
ccs 4
cts 4
cp 1
crap 1
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
        foreach (array_keys($links_in_content) as $wikilink) {
97 1
            $link = new net_nemein_wiki_link_dba();
98 1
            $link->frompage = $this->id;
99 1
            $link->topage = $wikilink;
100 1
            debug_add("Creating net_nemein_wiki_link_dba: from page #{$link->frompage}, to page: '$link->topage'");
101 1
            $link->create();
102
        }
103 4
    }
104
105
    /**
106
     * Get list of people watching this page
107
     */
108 4
    private function list_watchers() : array
109
    {
110 4
        $topic = new midcom_db_topic($this->topic);
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
        return array_unique(array_column($qb->execute(), 'name'));
121
    }
122
123 4
    private function update_watchers()
124
    {
125 4
        $watchers = $this->list_watchers();
126 4
        if (empty($watchers)) {
127 4
            return;
128
        }
129
130
        $diff = $this->get_diff();
131
        if (empty($diff)) {
132
            // No sense to email empty diffs
133
            return;
134
        }
135
136
        // Construct the message
137
        $message = [];
138
        $user_string = midcom::get()->i18n->get_string('anonymous', 'net.nemein.wiki');
139
        if (midcom::get()->auth->user) {
140
            $user = midcom::get()->auth->user->get_storage();
141
            $user_string = $user->name;
142
        }
143
        // Title for long notifications
144
        $message['title'] = sprintf(midcom::get()->i18n->get_string('page %s has been updated by %s', 'net.nemein.wiki'), $this->title, $user_string);
145
        // Content for long notifications
146
        $message['content']  = "{$message['title']}\n\n";
147
148
        $message['content'] .= midcom::get()->i18n->get_string('page modifications', 'net.nemein.wiki') . ":\n";
149
        $message['content'] .= "\n{$diff}\n\n";
150
151
        $message['content'] .= midcom::get()->i18n->get_string('link to page', 'net.nemein.wiki') . ":\n";
152
        $message['content'] .= midcom::get()->permalinks->create_permalink($this->guid);
153
154
        // Content for short notifications
155
        $topic = new midcom_db_topic($this->topic);
156
        $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);
157
158
        debug_add("Processing list of Wiki subscribers");
159
160
        // Send the message out
161
        foreach ($watchers as $recipient) {
162
            debug_add("Notifying {$recipient}...");
163
            org_openpsa_notifications::notify('net.nemein.wiki:page_updated', $recipient, $message);
164
        }
165
    }
166
167
    private function get_diff() : string
168
    {
169
        // Load the RCS handler
170
        $rcs_handler = midcom::get()->rcs->load_backend($this);
171
172
        // Find out what versions to diff
173
        $history = $rcs_handler->get_history();
174
        if (count($history->all()) < 2) {
175
            return '';
176
        }
177
        $this_version = $history->get_last()['revision'];
178
        $prev_version = $history->get_prev_version($this_version);
179
180
        try {
181
            $diff_fields = $rcs_handler->get_diff($prev_version, $this_version);
182
        } catch (midcom_error $e) {
183
            $e->log();
184
            return '';
185
        }
186
187
        return $diff_fields['content']['diff'] ?? '';
188
    }
189
}
190