1<?php
2
3namespace dokuwiki\Feed;
4
5use dokuwiki\Extension\AuthPlugin;
6use RuntimeException;
7
8/**
9 * Accept more or less arbitrary data to represent data to later construct a feed item from.
10 * Provide lazy loading accessors to all the data we need for feed generation.
11 */
12abstract class FeedItemProcessor
13{
14    /** @var string This page's ID */
15    protected $id;
16
17    /** @var array bag of holding */
18    protected $data;
19
20
21    /**
22     * Constructor
23     *
24     * @param array $data Needs to have at least an 'id' key
25     */
26    public function __construct($data)
27    {
28        if (!isset($data['id'])) throw new RuntimeException('Missing ID');
29        $this->id = cleanID($data['id']);
30        $this->data = $data;
31    }
32
33    /**
34     * Get the page ID
35     *
36     * @return string
37     */
38    public function getId()
39    {
40        return $this->id;
41    }
42
43    /**
44     * Get the revision timestamp of this page
45     *
46     * If the input gave us a revision, date or lastmodified already, we trust that it is correct.
47     *
48     * Note: we only handle most current revisions in feeds, so the revision is usually just the
49     * lastmodifed timestamp of the page file. However, if the item does not exist, we need to
50     * determine the revision from the changelog.
51     *
52     * @return int
53     */
54    public function getRev()
55    {
56        if ($this->data['rev'] ?? 0) return $this->data['rev'];
57
58        if (isset($this->data['date'])) {
59            $this->data['rev'] = (int)$this->data['date'];
60        }
61
62        if (isset($this->data['lastmodified'])) {
63            $this->data['rev'] = (int)$this->data['lastmodified'];
64        }
65
66        return $this->data['rev'] ?? 0;
67    }
68
69    /**
70     * Construct the URL for the feed item based on the link_to option
71     *
72     * @param string $linkto The link_to option
73     * @return string URL
74     */
75    abstract public function getURL($linkto);
76
77    /**
78     * @return string
79     */
80    public function getTitle()
81    {
82        return $this->data['title'] ?? noNS($this->getId());
83    }
84
85    /**
86     * Construct the body of the feed item based on the item_content option
87     *
88     * @param string $content The item_content option
89     * @return string
90     */
91    abstract public function getBody($content);
92
93    /**
94     * Get the change summary for this item if any
95     *
96     * @return string
97     */
98    public function getSummary()
99    {
100        return (string)($this->data['sum'] ?? '');
101    }
102
103    /**
104     * Get the author info for this item
105     *
106     * @return string[] [email, author]
107     */
108    public function getAuthor()
109    {
110        global $conf;
111        global $auth;
112
113        $user = $this->data['user'] ?? '';
114        $author = 'Anonymous';
115        $email = 'anonymous@undisclosed.example.com';
116
117        if (!$user) return [$email, $author];
118        $author = $user;
119        $email = $user . '@undisclosed.example.com';
120
121        if ($conf['useacl'] && $auth instanceof AuthPlugin) {
122            $userInfo = $auth->getUserData($user);
123            if ($userInfo) {
124                switch ($conf['showuseras']) {
125                    case 'username':
126                    case 'username_link':
127                        $author = $userInfo['name'];
128                        break;
129                }
130            }
131        }
132        return [$email, $author];
133    }
134
135    /**
136     * Get the categories for this item
137     *
138     * @return string[]
139     */
140    abstract public function getCategory();
141
142
143    /**
144     * Clean HTML for the use in feeds
145     *
146     * @param string $html
147     * @return string
148     */
149    protected function cleanHTML($html)
150    {
151        global $conf;
152
153        // no TOC in feeds
154        $html = preg_replace('/(<!-- TOC START -->).*(<!-- TOC END -->)/s', '', $html);
155
156        // add alignment for images
157        $html = preg_replace('/(<img .*?class="medialeft")/s', '\\1 align="left"', $html);
158        $html = preg_replace('/(<img .*?class="mediaright")/s', '\\1 align="right"', $html);
159
160        // make URLs work when canonical is not set, regexp instead of rerendering!
161        if (!$conf['canonical']) {
162            $base = preg_quote(DOKU_REL, '/');
163            $html = preg_replace(
164                '/(<a href|<img src)="(' . $base . ')/s',
165                '$1="' . DOKU_URL,
166                $html
167            );
168        }
169
170        return $html;
171    }
172}
173