xref: /dokuwiki/inc/Feed/FeedCreatorOptions.php (revision 867da04d85140736fab69e0df2be0abb55719386)
1fe9d054bSAndreas Gohr<?php
2fe9d054bSAndreas Gohr
3fe9d054bSAndreas Gohrnamespace dokuwiki\Feed;
4fe9d054bSAndreas Gohr
5fe9d054bSAndreas Gohruse dokuwiki\Extension\Event;
6fe9d054bSAndreas Gohr
7fe9d054bSAndreas Gohr/**
8fe9d054bSAndreas Gohr * Hold the options for feed generation
9fe9d054bSAndreas Gohr */
10fe9d054bSAndreas Gohrclass FeedCreatorOptions
11fe9d054bSAndreas Gohr{
12fe9d054bSAndreas Gohr    /** @var array[] supported feed types */
13fe9d054bSAndreas Gohr    protected $types = [
14fe9d054bSAndreas Gohr        'rss' => [
15fe9d054bSAndreas Gohr            'name' => 'RSS0.91',
16fe9d054bSAndreas Gohr            'mime' => 'text/xml; charset=utf-8',
17fe9d054bSAndreas Gohr        ],
187e23bd08SAndreas Gohr        'rss1' => [
197e23bd08SAndreas Gohr            'name' => 'RSS1.0',
207e23bd08SAndreas Gohr            'mime' => 'text/xml; charset=utf-8',
217e23bd08SAndreas Gohr        ],
22fe9d054bSAndreas Gohr        'rss2' => [
23fe9d054bSAndreas Gohr            'name' => 'RSS2.0',
24fe9d054bSAndreas Gohr            'mime' => 'text/xml; charset=utf-8',
25fe9d054bSAndreas Gohr        ],
26fe9d054bSAndreas Gohr        'atom' => [
27fe9d054bSAndreas Gohr            'name' => 'ATOM0.3',
28fe9d054bSAndreas Gohr            'mime' => 'application/xml; charset=utf-8',
29fe9d054bSAndreas Gohr        ],
30fe9d054bSAndreas Gohr        'atom1' => [
31fe9d054bSAndreas Gohr            'name' => 'ATOM1.0',
32fe9d054bSAndreas Gohr            'mime' => 'application/atom+xml; charset=utf-8',
33fe9d054bSAndreas Gohr        ],
34fe9d054bSAndreas Gohr    ];
35fe9d054bSAndreas Gohr
36fe9d054bSAndreas Gohr    /** @var array[] the set options */
37fe9d054bSAndreas Gohr    public $options = [
38fe9d054bSAndreas Gohr        'type' => 'rss',
39fe9d054bSAndreas Gohr        'feed_mode' => 'recent',
40fe9d054bSAndreas Gohr        'link_to' => 'page',
41fe9d054bSAndreas Gohr        'item_content' => 'diff',
42fe9d054bSAndreas Gohr        'namespace' => '',
43fe9d054bSAndreas Gohr        'items' => 15,
44fe9d054bSAndreas Gohr        'show_minor' => false,
45fe9d054bSAndreas Gohr        'show_deleted' => false,
46fe9d054bSAndreas Gohr        'show_summary' => false,
47fe9d054bSAndreas Gohr        'only_new' => false,
48fe9d054bSAndreas Gohr        'sort' => 'natural',
49fe9d054bSAndreas Gohr        'search_query' => '',
50fe9d054bSAndreas Gohr        'content_type' => 'pages',
51fe9d054bSAndreas Gohr        'guardmail' => 'none',
52fe9d054bSAndreas Gohr        'title' => '',
53*867da04dSAndreas Gohr        'cache_allow' => false,
54*867da04dSAndreas Gohr        'cache_key' => '',
55fe9d054bSAndreas Gohr    ];
56fe9d054bSAndreas Gohr
57fe9d054bSAndreas Gohr    /**
58fe9d054bSAndreas Gohr     * Initialize the options from the request, falling back to config defaults
59fe9d054bSAndreas Gohr     *
60fe9d054bSAndreas Gohr     * @triggers FEED_OPTS_POSTPROCESS
61fe9d054bSAndreas Gohr     * @param array $options additional options to set (for testing)
62fe9d054bSAndreas Gohr     */
63fe9d054bSAndreas Gohr    public function __construct($options = [])
64fe9d054bSAndreas Gohr    {
65fe9d054bSAndreas Gohr        global $conf;
66fe9d054bSAndreas Gohr        global $INPUT;
67fe9d054bSAndreas Gohr
68fe9d054bSAndreas Gohr        $this->options['type'] = $INPUT->valid(
69fe9d054bSAndreas Gohr            'type',
70fe9d054bSAndreas Gohr            array_keys($this->types),
71fe9d054bSAndreas Gohr            $conf['rss_type']
72fe9d054bSAndreas Gohr        );
73fe9d054bSAndreas Gohr        // we only support 'list', 'search', 'recent' but accept anything so plugins can take over
74fe9d054bSAndreas Gohr        $this->options['feed_mode'] = $INPUT->str('mode', 'recent');
75fe9d054bSAndreas Gohr        $this->options['link_to'] = $INPUT->valid(
76fe9d054bSAndreas Gohr            'linkto',
77fe9d054bSAndreas Gohr            ['diff', 'page', 'rev', 'current'],
78fe9d054bSAndreas Gohr            $conf['rss_linkto']
79fe9d054bSAndreas Gohr        );
80fe9d054bSAndreas Gohr        $this->options['item_content'] = $INPUT->valid(
81fe9d054bSAndreas Gohr            'content',
82fe9d054bSAndreas Gohr            ['abstract', 'diff', 'htmldiff', 'html'],
83fe9d054bSAndreas Gohr            $conf['rss_content']
84fe9d054bSAndreas Gohr        );
85fe9d054bSAndreas Gohr        $this->options['namespace'] = $INPUT->filter('cleanID')->str('ns');
86*867da04dSAndreas Gohr        $this->options['items'] = $INPUT->int('num', $conf['recent']);
87fe9d054bSAndreas Gohr        $this->options['show_minor'] = $INPUT->bool('minor');
88fe9d054bSAndreas Gohr        $this->options['show_deleted'] = $conf['rss_show_deleted'];
89fe9d054bSAndreas Gohr        $this->options['show_summary'] = $conf['rss_show_summary'];
90fe9d054bSAndreas Gohr        $this->options['only_new'] = $INPUT->bool('onlynewpages');
91fe9d054bSAndreas Gohr        $this->options['sort'] = $INPUT->valid(
92fe9d054bSAndreas Gohr            'sort',
93fe9d054bSAndreas Gohr            ['natural', 'date'],
94fe9d054bSAndreas Gohr            'natural'
95fe9d054bSAndreas Gohr        );
96fe9d054bSAndreas Gohr        $this->options['search_query'] = $INPUT->str('q');
97fe9d054bSAndreas Gohr        $this->options['content_type'] = $INPUT->valid(
98fe9d054bSAndreas Gohr            'view',
99fe9d054bSAndreas Gohr            ['pages', 'media', 'both'],
100fe9d054bSAndreas Gohr            $conf['rss_media']
101fe9d054bSAndreas Gohr        );
102fe9d054bSAndreas Gohr        $this->options['guardmail'] = $conf['mailguard'];
103fe9d054bSAndreas Gohr        $this->options['title'] = $conf['title'];
104fe9d054bSAndreas Gohr        if ($this->options['namespace']) {
105fe9d054bSAndreas Gohr            $this->options['title'] .= ' - ' . $this->options['namespace'];
106fe9d054bSAndreas Gohr        }
1071136941dSAndreas Gohr        $this->options['subtitle'] = $conf['tagline'];
108fe9d054bSAndreas Gohr
109fe9d054bSAndreas Gohr        $this->options = array_merge($this->options, $options);
110*867da04dSAndreas Gohr        // clamp items to a reasonable range to prevent cache DoS via arbitrary num values
111*867da04dSAndreas Gohr        $this->options['items'] = min(max(1, (int)$this->options['items']), $conf['recent'] * 5);
112*867da04dSAndreas Gohr        // only the recent mode is cached by default to prevent cache DoS;
113*867da04dSAndreas Gohr        // plugins can enable caching for their modes via FEED_OPTS_POSTPROCESS
114*867da04dSAndreas Gohr        $this->options['cache_allow'] = ($this->options['feed_mode'] === 'recent');
115fe9d054bSAndreas Gohr
116fe9d054bSAndreas Gohr        // initialization finished, let plugins know
117fe9d054bSAndreas Gohr        $eventData = [
118fe9d054bSAndreas Gohr            'opt' => &$this->options,
119fe9d054bSAndreas Gohr        ];
120fe9d054bSAndreas Gohr        Event::createAndTrigger('FEED_OPTS_POSTPROCESS', $eventData);
121fe9d054bSAndreas Gohr    }
122fe9d054bSAndreas Gohr
123fe9d054bSAndreas Gohr    /**
124fe9d054bSAndreas Gohr     * The cache key to use for a feed with these options
125fe9d054bSAndreas Gohr     *
126*867da04dSAndreas Gohr     * Only includes options that affect the current mode's output.
127fe9d054bSAndreas Gohr     *
128*867da04dSAndreas Gohr     * @param string[] $additional additional key parts (e.g. user, host, port)
129*867da04dSAndreas Gohr     * @return string|null null if the feed should not be cached
130fe9d054bSAndreas Gohr     */
131*867da04dSAndreas Gohr    public function getCacheKey(array $additional = []): ?string
132fe9d054bSAndreas Gohr    {
133*867da04dSAndreas Gohr        if (!$this->options['cache_allow']) {
134*867da04dSAndreas Gohr            return null;
135*867da04dSAndreas Gohr        }
136*867da04dSAndreas Gohr
137*867da04dSAndreas Gohr        return implode('$', array_merge([
138*867da04dSAndreas Gohr            $this->options['feed_mode'],
139*867da04dSAndreas Gohr            $this->options['type'],
140*867da04dSAndreas Gohr            $this->options['link_to'],
141*867da04dSAndreas Gohr            $this->options['item_content'],
142*867da04dSAndreas Gohr            $this->options['show_summary'],
143*867da04dSAndreas Gohr            $this->options['guardmail'],
144*867da04dSAndreas Gohr            $this->options['namespace'],
145*867da04dSAndreas Gohr            $this->options['items'],
146*867da04dSAndreas Gohr            $this->options['show_minor'],
147*867da04dSAndreas Gohr            $this->options['show_deleted'],
148*867da04dSAndreas Gohr            $this->options['only_new'],
149*867da04dSAndreas Gohr            $this->options['content_type'],
150*867da04dSAndreas Gohr            $this->options['cache_key'],
151*867da04dSAndreas Gohr        ], $additional));
152fe9d054bSAndreas Gohr    }
153fe9d054bSAndreas Gohr
154fe9d054bSAndreas Gohr    /**
155fe9d054bSAndreas Gohr     * Return a feed option by name
156fe9d054bSAndreas Gohr     *
157fe9d054bSAndreas Gohr     * @param string $option The name of the option
158fe9d054bSAndreas Gohr     * @param mixed $default default value if option is not set (should usually not happen)
159fe9d054bSAndreas Gohr     * @return mixed
160fe9d054bSAndreas Gohr     */
161fe9d054bSAndreas Gohr    public function get($option, $default = null)
162fe9d054bSAndreas Gohr    {
16372c714a3Ssplitbrain        return $this->options[$option] ?? $default;
164fe9d054bSAndreas Gohr    }
165fe9d054bSAndreas Gohr
166fe9d054bSAndreas Gohr    /**
167fe9d054bSAndreas Gohr     * Return the feed type for UniversalFeedCreator
168fe9d054bSAndreas Gohr     *
169fe9d054bSAndreas Gohr     * This returns the apropriate type for UniversalFeedCreator
170fe9d054bSAndreas Gohr     *
171fe9d054bSAndreas Gohr     * @return string
172fe9d054bSAndreas Gohr     */
173fe9d054bSAndreas Gohr    public function getType()
174fe9d054bSAndreas Gohr    {
175fe9d054bSAndreas Gohr        return $this->types[$this->options['type']]['name'];
176fe9d054bSAndreas Gohr    }
177fe9d054bSAndreas Gohr
178fe9d054bSAndreas Gohr    /**
179fe9d054bSAndreas Gohr     * Return the feed mime type
180fe9d054bSAndreas Gohr     *
181fe9d054bSAndreas Gohr     * @return string
182fe9d054bSAndreas Gohr     */
183fe9d054bSAndreas Gohr    public function getMimeType()
184fe9d054bSAndreas Gohr    {
185fe9d054bSAndreas Gohr        return $this->types[$this->options['type']]['mime'];
186fe9d054bSAndreas Gohr    }
187fe9d054bSAndreas Gohr}
188