1<?php
2
3namespace dokuwiki\Action;
4
5use dokuwiki\Action\Exception\ActionAbort;
6use dokuwiki\Action\Exception\ActionDisabledException;
7use dokuwiki\Subscriptions\SubscriberManager;
8use dokuwiki\Extension\Event;
9use dokuwiki\Ui;
10
11/**
12 * Class Subscribe
13 *
14 * E-Mail subscription handling
15 *
16 * @package dokuwiki\Action
17 */
18class Subscribe extends AbstractUserAction
19{
20    /** @inheritdoc */
21    public function minimumPermission()
22    {
23        return AUTH_READ;
24    }
25
26    /** @inheritdoc */
27    public function checkPreconditions()
28    {
29        parent::checkPreconditions();
30
31        global $conf;
32        if(isset($conf['subscribers']) && !$conf['subscribers']) throw new ActionDisabledException();
33    }
34
35    /** @inheritdoc */
36    public function preProcess()
37    {
38        try {
39            $this->handleSubscribeData();
40        } catch (ActionAbort $e) {
41            throw $e;
42        } catch (\Exception $e) {
43            msg($e->getMessage(), -1);
44        }
45    }
46
47    /** @inheritdoc */
48    public function tplContent()
49    {
50        (new Ui\Subscribe)->show();
51    }
52
53    /**
54     * Handle page 'subscribe'
55     *
56     * @author Adrian Lang <lang@cosmocode.de>
57     * @throws \Exception if (un)subscribing fails
58     * @throws ActionAbort when (un)subscribing worked
59     */
60    protected function handleSubscribeData()
61    {
62        global $lang;
63        global $INFO;
64        global $INPUT;
65
66        // get and preprocess data.
67        $params = array();
68        foreach (array('target', 'style', 'action') as $param) {
69            if ($INPUT->has("sub_$param")) {
70                $params[$param] = $INPUT->str("sub_$param");
71            }
72        }
73
74        // any action given? if not just return and show the subscription page
75        if (empty($params['action']) || !checkSecurityToken()) return;
76
77        // Handle POST data, may throw exception.
78        Event::createAndTrigger('ACTION_HANDLE_SUBSCRIBE', $params, array($this, 'handlePostData'));
79
80        $target = $params['target'];
81        $style = $params['style'];
82        $action = $params['action'];
83
84        // Perform action.
85        $subManager = new SubscriberManager();
86        if ($action === 'unsubscribe') {
87            $ok = $subManager->remove($target, $INPUT->server->str('REMOTE_USER'), $style);
88        } else {
89            $ok = $subManager->add($target, $INPUT->server->str('REMOTE_USER'), $style);
90        }
91
92        if ($ok) {
93            msg(
94                sprintf(
95                    $lang["subscr_{$action}_success"], hsc($INFO['userinfo']['name']),
96                    prettyprint_id($target)
97                ), 1
98            );
99            throw new ActionAbort('redirect');
100        }
101
102        throw new \Exception(
103            sprintf(
104                $lang["subscr_{$action}_error"],
105                hsc($INFO['userinfo']['name']),
106                prettyprint_id($target)
107            )
108        );
109    }
110
111    /**
112     * Validate POST data
113     *
114     * Validates POST data for a subscribe or unsubscribe request. This is the
115     * default action for the event ACTION_HANDLE_SUBSCRIBE.
116     *
117     * @author Adrian Lang <lang@cosmocode.de>
118     *
119     * @param array &$params the parameters: target, style and action
120     * @throws \Exception
121     */
122    public function handlePostData(&$params)
123    {
124        global $INFO;
125        global $lang;
126        global $INPUT;
127
128        // Get and validate parameters.
129        if (!isset($params['target'])) {
130            throw new \Exception('no subscription target given');
131        }
132        $target = $params['target'];
133        $valid_styles = array('every', 'digest');
134        if (substr($target, -1, 1) === ':') {
135            // Allow “list” subscribe style since the target is a namespace.
136            $valid_styles[] = 'list';
137        }
138        $style = valid_input_set(
139            'style', $valid_styles, $params,
140            'invalid subscription style given'
141        );
142        $action = valid_input_set(
143            'action', array('subscribe', 'unsubscribe'),
144            $params, 'invalid subscription action given'
145        );
146
147        // Check other conditions.
148        if ($action === 'subscribe') {
149            if ($INFO['userinfo']['mail'] === '') {
150                throw new \Exception($lang['subscr_subscribe_noaddress']);
151            }
152        } elseif ($action === 'unsubscribe') {
153            $is = false;
154            foreach ($INFO['subscribed'] as $subscr) {
155                if ($subscr['target'] === $target) {
156                    $is = true;
157                }
158            }
159            if ($is === false) {
160                throw new \Exception(
161                    sprintf(
162                        $lang['subscr_not_subscribed'],
163                        $INPUT->server->str('REMOTE_USER'),
164                        prettyprint_id($target)
165                    )
166                );
167            }
168            // subscription_set deletes a subscription if style = null.
169            $style = null;
170        }
171
172        $params = compact('target', 'style', 'action');
173    }
174
175}
176