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 = []; 69 foreach (['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, [$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"], 97 hsc($INFO['userinfo']['name']), 98 prettyprint_id($target) 99 ), 100 1 101 ); 102 throw new ActionAbort('redirect'); 103 } 104 105 throw new Exception( 106 sprintf( 107 $lang["subscr_{$action}_error"], 108 hsc($INFO['userinfo']['name']), 109 prettyprint_id($target) 110 ) 111 ); 112 } 113 114 /** 115 * Validate POST data 116 * 117 * Validates POST data for a subscribe or unsubscribe request. This is the 118 * default action for the event ACTION_HANDLE_SUBSCRIBE. 119 * 120 * @author Adrian Lang <lang@cosmocode.de> 121 * 122 * @param array &$params the parameters: target, style and action 123 * @throws Exception 124 */ 125 public function handlePostData(&$params) 126 { 127 global $INFO; 128 global $lang; 129 global $INPUT; 130 131 // Get and validate parameters. 132 if (!isset($params['target'])) { 133 throw new Exception('no subscription target given'); 134 } 135 $target = $params['target']; 136 $valid_styles = ['every', 'digest']; 137 if (str_ends_with($target, ':')) { 138 // Allow “list” subscribe style since the target is a namespace. 139 $valid_styles[] = 'list'; 140 } 141 $style = valid_input_set( 142 'style', 143 $valid_styles, 144 $params, 145 'invalid subscription style given' 146 ); 147 $action = valid_input_set( 148 'action', 149 ['subscribe', 'unsubscribe'], 150 $params, 151 'invalid subscription action given' 152 ); 153 154 // Check other conditions. 155 if ($action === 'subscribe') { 156 if ($INFO['userinfo']['mail'] === '') { 157 throw new Exception($lang['subscr_subscribe_noaddress']); 158 } 159 } elseif ($action === 'unsubscribe') { 160 $is = false; 161 foreach ($INFO['subscribed'] as $subscr) { 162 if ($subscr['target'] === $target) { 163 $is = true; 164 } 165 } 166 if ($is === false) { 167 throw new Exception( 168 sprintf( 169 $lang['subscr_not_subscribed'], 170 $INPUT->server->str('REMOTE_USER'), 171 prettyprint_id($target) 172 ) 173 ); 174 } 175 // subscription_set deletes a subscription if style = null. 176 $style = null; 177 } 178 179 $params = ['target' => $target, 'style' => $style, 'action' => $action]; 180 } 181} 182