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