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