xref: /dokuwiki/inc/Feed/FeedPageProcessor.php (revision 389c05a6bc94d555ae7263fae212bb14d5c8c93b)
1fe9d054bSAndreas Gohr<?php
2fe9d054bSAndreas Gohr
3fe9d054bSAndreas Gohrnamespace dokuwiki\Feed;
4fe9d054bSAndreas Gohr
5fe9d054bSAndreas Gohruse Diff;
6fe9d054bSAndreas Gohruse dokuwiki\ChangeLog\PageChangeLog;
7fe9d054bSAndreas Gohruse TableDiffFormatter;
8fe9d054bSAndreas Gohruse UnifiedDiffFormatter;
9fe9d054bSAndreas Gohr
10fe9d054bSAndreas Gohr/**
11fe9d054bSAndreas Gohr * Accept more or less arbitrary data to represent a page and provide lazy loading accessors
12fe9d054bSAndreas Gohr * to all the data we need for feed generation.
13fe9d054bSAndreas Gohr */
14fe9d054bSAndreas Gohrclass FeedPageProcessor extends FeedItemProcessor
15fe9d054bSAndreas Gohr{
16fe9d054bSAndreas Gohr    /** @var array[] metadata */
17fe9d054bSAndreas Gohr    protected $meta;
18fe9d054bSAndreas Gohr
19fe9d054bSAndreas Gohr    // region data processors
20fe9d054bSAndreas Gohr
21fe9d054bSAndreas Gohr    /** @inheritdoc */
22fe9d054bSAndreas Gohr    public function getURL($linkto)
23fe9d054bSAndreas Gohr    {
24fe9d054bSAndreas Gohr        switch ($linkto) {
25fe9d054bSAndreas Gohr            case 'page':
26fe9d054bSAndreas Gohr                $opt = ['rev' => $this->getRev()];
27fe9d054bSAndreas Gohr                break;
28fe9d054bSAndreas Gohr            case 'rev':
29fe9d054bSAndreas Gohr                $opt = ['rev' => $this->getRev(), 'do' => 'revisions'];
30fe9d054bSAndreas Gohr                break;
31fe9d054bSAndreas Gohr            case 'current':
32fe9d054bSAndreas Gohr                $opt = [];
33fe9d054bSAndreas Gohr                break;
34fe9d054bSAndreas Gohr            case 'diff':
35fe9d054bSAndreas Gohr            default:
36fe9d054bSAndreas Gohr                $opt = ['rev' => $this->getRev(), 'do' => 'diff'];
37fe9d054bSAndreas Gohr        }
38fe9d054bSAndreas Gohr
39fe9d054bSAndreas Gohr        return wl($this->getId(), $opt, true, '&');
40fe9d054bSAndreas Gohr    }
41fe9d054bSAndreas Gohr
42fe9d054bSAndreas Gohr    /** @inheritdoc */
43fe9d054bSAndreas Gohr    public function getBody($content)
44fe9d054bSAndreas Gohr    {
45fe9d054bSAndreas Gohr        global $lang;
46fe9d054bSAndreas Gohr
47fe9d054bSAndreas Gohr        switch ($content) {
48fe9d054bSAndreas Gohr            case 'diff':
49fe9d054bSAndreas Gohr                $diff = $this->getDiff();
50fe9d054bSAndreas Gohr                // note: diff output must be escaped, UnifiedDiffFormatter provides plain text
51fe9d054bSAndreas Gohr                $udf = new UnifiedDiffFormatter();
52fe9d054bSAndreas Gohr                return "<pre>\n" . hsc($udf->format($diff)) . "\n</pre>";
53fe9d054bSAndreas Gohr
54fe9d054bSAndreas Gohr            case 'htmldiff':
55fe9d054bSAndreas Gohr                $diff = $this->getDiff();
56fe9d054bSAndreas Gohr                // note: no need to escape diff output, TableDiffFormatter provides 'safe' html
57fe9d054bSAndreas Gohr                $tdf = new TableDiffFormatter();
58fe9d054bSAndreas Gohr                $content = '<table>';
59fe9d054bSAndreas Gohr                $content .= '<tr><th colspan="2" width="50%">' . dformat($this->getPrev()) . '</th>';
60fe9d054bSAndreas Gohr                $content .= '<th colspan="2" width="50%">' . $lang['current'] . '</th></tr>';
61fe9d054bSAndreas Gohr                $content .= $tdf->format($diff);
62fe9d054bSAndreas Gohr                $content .= '</table>';
63fe9d054bSAndreas Gohr                return $content;
64fe9d054bSAndreas Gohr
65fe9d054bSAndreas Gohr            case 'html':
66fe9d054bSAndreas Gohr                if ($this->isExisting()) {
67fe9d054bSAndreas Gohr                    $html = p_wiki_xhtml($this->getId(), '', false);
68fe9d054bSAndreas Gohr                } else {
69fe9d054bSAndreas Gohr                    $html = p_wiki_xhtml($this->getId(), $this->getRev(), false);
70fe9d054bSAndreas Gohr                }
71fe9d054bSAndreas Gohr                return $this->cleanHTML($html);
72fe9d054bSAndreas Gohr
73fe9d054bSAndreas Gohr            case 'abstract':
74fe9d054bSAndreas Gohr            default:
75fe9d054bSAndreas Gohr                return $this->getAbstract();
76fe9d054bSAndreas Gohr        }
77fe9d054bSAndreas Gohr    }
78fe9d054bSAndreas Gohr
79fe9d054bSAndreas Gohr    /** @inheritdoc */
80fe9d054bSAndreas Gohr    public function getCategory()
81fe9d054bSAndreas Gohr    {
82fe9d054bSAndreas Gohr        $meta = $this->getMetaData();
83fe9d054bSAndreas Gohr        return (array)($meta['subject'] ?? (string)getNS($this->getId()));
84fe9d054bSAndreas Gohr    }
85fe9d054bSAndreas Gohr
86fe9d054bSAndreas Gohr    // endregion
87fe9d054bSAndreas Gohr
88fe9d054bSAndreas Gohr    // region data accessors
89fe9d054bSAndreas Gohr
90fe9d054bSAndreas Gohr    /**
91fe9d054bSAndreas Gohr     * Get the page abstract
92fe9d054bSAndreas Gohr     *
93fe9d054bSAndreas Gohr     * @return string
94fe9d054bSAndreas Gohr     */
95fe9d054bSAndreas Gohr    public function getAbstract()
96fe9d054bSAndreas Gohr    {
97fe9d054bSAndreas Gohr        if (!isset($this->data['abstract'])) {
98fe9d054bSAndreas Gohr            $meta = $this->getMetaData();
99fe9d054bSAndreas Gohr            if (isset($meta['description']['abstract'])) {
100fe9d054bSAndreas Gohr                $this->data['abstract'] = (string)$meta['description']['abstract'];
101fe9d054bSAndreas Gohr            } else {
102fe9d054bSAndreas Gohr                $this->data['abstract'] = '';
103fe9d054bSAndreas Gohr            }
104fe9d054bSAndreas Gohr        }
105fe9d054bSAndreas Gohr        return $this->data['abstract'];
106fe9d054bSAndreas Gohr    }
107fe9d054bSAndreas Gohr
108fe9d054bSAndreas Gohr    /** @inheritdoc */
109fe9d054bSAndreas Gohr    public function getRev()
110fe9d054bSAndreas Gohr    {
111fe9d054bSAndreas Gohr        $rev = parent::getRev();
112fe9d054bSAndreas Gohr        if ($rev) return $rev;
113fe9d054bSAndreas Gohr
114fe9d054bSAndreas Gohr        if (page_exists($this->id)) {
115fe9d054bSAndreas Gohr            $this->data['rev'] = filemtime(wikiFN($this->id));
116fe9d054bSAndreas Gohr            $this->data['exists'] = true;
117fe9d054bSAndreas Gohr        } else {
118fe9d054bSAndreas Gohr            $this->loadRevisions();
119fe9d054bSAndreas Gohr        }
120fe9d054bSAndreas Gohr        return $this->data['rev'];
121fe9d054bSAndreas Gohr    }
122fe9d054bSAndreas Gohr
123fe9d054bSAndreas Gohr    /**
124fe9d054bSAndreas Gohr     * Get the previous revision timestamp of this page
125fe9d054bSAndreas Gohr     *
126fe9d054bSAndreas Gohr     * @return int|null The previous revision or null if there is none
127fe9d054bSAndreas Gohr     */
128fe9d054bSAndreas Gohr    public function getPrev()
129fe9d054bSAndreas Gohr    {
130fe9d054bSAndreas Gohr        if ($this->data['prev'] ?? 0) return $this->data['prev'];
131fe9d054bSAndreas Gohr        $this->loadRevisions();
132fe9d054bSAndreas Gohr        return $this->data['prev'];
133fe9d054bSAndreas Gohr    }
134fe9d054bSAndreas Gohr
135fe9d054bSAndreas Gohr    /**
136fe9d054bSAndreas Gohr     * Does this page exist?
137fe9d054bSAndreas Gohr     *
138fe9d054bSAndreas Gohr     * @return bool
139fe9d054bSAndreas Gohr     */
140fe9d054bSAndreas Gohr    public function isExisting()
141fe9d054bSAndreas Gohr    {
142fe9d054bSAndreas Gohr        if (!isset($this->data['exists'])) {
143fe9d054bSAndreas Gohr            $this->data['exists'] = page_exists($this->id);
144fe9d054bSAndreas Gohr        }
145fe9d054bSAndreas Gohr        return $this->data['exists'];
146fe9d054bSAndreas Gohr    }
147fe9d054bSAndreas Gohr
148fe9d054bSAndreas Gohr    /**
149fe9d054bSAndreas Gohr     * Get the title of this page
150fe9d054bSAndreas Gohr     *
151fe9d054bSAndreas Gohr     * @return string
152fe9d054bSAndreas Gohr     */
153fe9d054bSAndreas Gohr    public function getTitle()
154fe9d054bSAndreas Gohr    {
155fe9d054bSAndreas Gohr        global $conf;
156fe9d054bSAndreas Gohr        if (!isset($this->data['title'])) {
157fe9d054bSAndreas Gohr            if ($conf['useheading']) {
158fe9d054bSAndreas Gohr                $this->data['title'] = p_get_first_heading($this->id);
159fe9d054bSAndreas Gohr            } else {
160fe9d054bSAndreas Gohr                $this->data['title'] = noNS($this->id);
161fe9d054bSAndreas Gohr            }
162fe9d054bSAndreas Gohr        }
163fe9d054bSAndreas Gohr        return $this->data['title'];
164fe9d054bSAndreas Gohr    }
165fe9d054bSAndreas Gohr
166fe9d054bSAndreas Gohr    // endregion
167fe9d054bSAndreas Gohr
168fe9d054bSAndreas Gohr    /**
169fe9d054bSAndreas Gohr     * Get the metadata of this page
170fe9d054bSAndreas Gohr     *
171fe9d054bSAndreas Gohr     * @return array[]
172fe9d054bSAndreas Gohr     */
173fe9d054bSAndreas Gohr    protected function getMetaData()
174fe9d054bSAndreas Gohr    {
175fe9d054bSAndreas Gohr        if (!isset($this->meta)) {
176fe9d054bSAndreas Gohr            $this->meta = (array)p_get_metadata($this->id);
177fe9d054bSAndreas Gohr        }
178fe9d054bSAndreas Gohr        return $this->meta;
179fe9d054bSAndreas Gohr    }
180fe9d054bSAndreas Gohr
181fe9d054bSAndreas Gohr    /**
182fe9d054bSAndreas Gohr     * Load the current and previous revision from the changelog
183fe9d054bSAndreas Gohr     * @return void
184fe9d054bSAndreas Gohr     */
185fe9d054bSAndreas Gohr    protected function loadRevisions()
186fe9d054bSAndreas Gohr    {
187fe9d054bSAndreas Gohr        $changelog = new PageChangeLog($this->id);
188*389c05a6SAndreas Gohr        $revs = $changelog->getRevisions(-1, 2);
189fe9d054bSAndreas Gohr        if (!isset($this->data['rev'])) {
190fe9d054bSAndreas Gohr            // prefer an already set date, only set if missing
191fe9d054bSAndreas Gohr            // it should usally not happen that neither is available
192fe9d054bSAndreas Gohr            $this->data['rev'] = $revs[0] ?? 0;
193fe9d054bSAndreas Gohr        }
194fe9d054bSAndreas Gohr        // a previous revision might not exist
195fe9d054bSAndreas Gohr        $this->data['prev'] = $revs[1] ?? null;
196fe9d054bSAndreas Gohr    }
197fe9d054bSAndreas Gohr
198fe9d054bSAndreas Gohr    /**
199fe9d054bSAndreas Gohr     * Get a diff between this and the previous revision
200fe9d054bSAndreas Gohr     *
201fe9d054bSAndreas Gohr     * @return Diff
202fe9d054bSAndreas Gohr     */
203fe9d054bSAndreas Gohr    protected function getDiff()
204fe9d054bSAndreas Gohr    {
205fe9d054bSAndreas Gohr        $prev = $this->getPrev();
206fe9d054bSAndreas Gohr
207fe9d054bSAndreas Gohr        if ($prev) {
208fe9d054bSAndreas Gohr            return new Diff(
209fe9d054bSAndreas Gohr                explode("\n", rawWiki($this->getId(), $prev)),
210fe9d054bSAndreas Gohr                explode("\n", rawWiki($this->getId(), ''))
211fe9d054bSAndreas Gohr            );
212fe9d054bSAndreas Gohr        }
213fe9d054bSAndreas Gohr        return new Diff([''], explode("\n", rawWiki($this->getId(), '')));
214fe9d054bSAndreas Gohr    }
215fe9d054bSAndreas Gohr}
216