1<?php
2
3namespace dokuwiki\Feed;
4
5use dokuwiki\ChangeLog\MediaChangeLog;
6use dokuwiki\File\MediaFile;
7use dokuwiki\Ui\Media\Display;
8
9class FeedMediaProcessor extends FeedItemProcessor
10{
11    /** @inheritdoc */
12    public function getURL($linkto)
13    {
14        switch ($linkto) {
15            case 'page':
16                $opt = [
17                    'image' => $this->getId(),
18                    'ns' => getNS($this->getId()),
19                    'rev' => $this->getRev()
20                ];
21                break;
22            case 'rev':
23                $opt = [
24                    'image' => $this->getId(),
25                    'ns' => getNS($this->getId()),
26                    'rev' => $this->getRev(),
27                    'tab_details' => 'history'
28                ];
29                break;
30            case 'current':
31                $opt = [
32                    'image' => $this->getId(),
33                    'ns' => getNS($this->getId())
34                ];
35                break;
36            case 'diff':
37            default:
38                $opt = [
39                    'image' => $this->getId(),
40                    'ns' => getNS($this->getId()),
41                    'rev' => $this->getRev(),
42                    'tab_details' => 'history',
43                    'media_do' => 'diff'
44                ];
45        }
46
47        return media_managerURL($opt, '&', true);
48    }
49
50    public function getBody($content)
51    {
52        switch ($content) {
53            case 'diff':
54            case 'htmldiff':
55                $prev = $this->getPrev();
56
57                if ($prev) {
58                    if ($this->isExisting()) {
59                        $src1 = new MediaFile($this->getId(), $prev);
60                        $src2 = new MediaFile($this->getId());
61                    } else {
62                        $src1 = new MediaFile($this->getId(), $prev);
63                        $src2 = null;
64                    }
65                } else {
66                    $src1 = null;
67                    $src2 = new MediaFile($this->getId());
68                }
69                return $this->createDiffTable($src1, $src2);
70
71            case 'abstract':
72            case 'html':
73            default:
74                $src = new Display(new MediaFile($this->getId()));
75                return $this->cleanHTML($src->getPreviewHtml(500, 500));
76        }
77    }
78
79    /**
80     * @inheritdoc
81     * @todo read exif keywords
82     */
83    public function getCategory()
84    {
85        return (array)getNS($this->getId());
86    }
87
88    /**
89     * Get the revision timestamp of this page
90     *
91     * Note: we only handle most current revisions in feeds, so the revision is usually just the
92     * lastmodifed timestamp of the page file. However, if the page does not exist, we need to
93     * determine the revision from the changelog.
94     * @return int
95     */
96    public function getRev()
97    {
98        $rev = parent::getRev();
99        if ($rev) return $rev;
100
101        if (media_exists($this->id)) {
102            $this->data['rev'] = filemtime(mediaFN($this->id));
103            $this->data['exists'] = true;
104        } else {
105            $this->loadRevisions();
106        }
107        return $this->data['rev'];
108    }
109
110    /**
111     * Get the previous revision timestamp of this page
112     *
113     * @return int|null The previous revision or null if there is none
114     */
115    public function getPrev()
116    {
117        if ($this->data['prev'] ?? 0) return $this->data['prev'];
118        $this->loadRevisions();
119        return $this->data['prev'];
120    }
121
122    /**
123     * Does this page exist?
124     *
125     * @return bool
126     */
127    public function isExisting()
128    {
129        if (!isset($this->data['exists'])) {
130            $this->data['exists'] = media_exists($this->id);
131        }
132        return $this->data['exists'];
133    }
134
135    /**
136     * Load the current and previous revision from the changelog
137     * @return void
138     */
139    protected function loadRevisions()
140    {
141        $changelog = new MediaChangeLog($this->id);
142        $revs = $changelog->getRevisions(0, 2);  // FIXME check that this returns the current one correctly
143        if (!isset($this->data['rev'])) {
144            // prefer an already set date, only set if missing
145            // it should usally not happen that neither is available
146            $this->data['rev'] = $revs[0] ?? 0;
147        }
148        // a previous revision might not exist
149        $this->data['prev'] = $revs[1] ?? null;
150    }
151
152    /**
153     * Create a table showing the two media files
154     *
155     * @param MediaFile|null $src1
156     * @param MediaFile|null $src2
157     * @return string
158     */
159    protected function createDiffTable($src1, $src2)
160    {
161        global $lang;
162
163        $content = '<table>';
164        $content .= '<tr>';
165        $content .= '<th width="50%">' . ($src1 ? $src1->getRev() : '') . '</th>';
166        $content .= '<th width="50%">' . $lang['current'] . '</th>';
167        $content .= '</tr>';
168        $content .= '<tr>';
169
170        $content .= '<td align="center">';
171        if ($src1) {
172            $display = new Display($src1);
173            $display->getPreviewHtml(300, 300);
174        }
175        $content .= '</td>';
176
177        $content .= '<td align="center">';
178        if ($src2) {
179            $display = new Display($src2);
180            $display->getPreviewHtml(300, 300);
181        }
182        $content .= '</td>';
183
184        $content .= '</tr>';
185        $content .= '</table>';
186
187        return $this->cleanHTML($content);
188    }
189}
190