← All changes
|
front/FrontControllers/FrontusersController.php
+299
-71
10.2.2
→
11.1.0
View file →
| @@ -4,12 +4,15 @@ | ||
| 4 | 4 | |
| 5 | 5 | use AcyMailing\Classes\FieldClass; |
| 6 | 6 | use AcyMailing\Classes\ListClass; |
| 7 | 7 | use AcyMailing\Classes\MailClass; |
| 8 | +use AcyMailing\Classes\ScenarioClass; | |
| 8 | 9 | use AcyMailing\Classes\UserClass; |
| 10 | +use AcyMailing\Classes\UserStatClass; | |
| 9 | 11 | use AcyMailing\Controllers\UsersController; |
| 10 | 12 | use AcyMailing\Helpers\CaptchaHelper; |
| 11 | 13 | use AcyMailing\Helpers\EntitySelectHelper; |
| 14 | +use AcyMailing\Helpers\ExportHelper; | |
| 12 | 15 | use AcyMailing\Helpers\ToolbarHelper; |
| 13 | 16 | use AcyMailing\Helpers\UserHelper; |
| 14 | 17 | use AcyMailing\Core\AcymParameter; |
| 15 | 18 | |
| @@ -18,9 +21,9 @@ | ||
| 18 | 21 | public function __construct() |
| 19 | 22 | { |
| 20 | 23 | parent::__construct(); |
| 21 | 24 | |
| 22 | - if (ACYM_CMS == 'joomla') { | |
| 25 | + if (ACYM_CMS === 'joomla') { | |
| 23 | 26 | $menu = acym_getMenu(); |
| 24 | 27 | if (is_object($menu)) { |
| 25 | 28 | $params = method_exists($menu, 'getParams') ? $menu->getParams() : $menu->params; |
| 26 | 29 | $menuParams = new AcymParameter($params); |
| @@ -31,8 +34,9 @@ | ||
| 31 | 34 | $this->publicFrontTasks = [ |
| 32 | 35 | 'subscribe', |
| 33 | 36 | 'unsubscribe', |
| 34 | 37 | 'unsubscribeAll', |
| 38 | + 'disableTracking', | |
| 35 | 39 | 'saveSubscriptions', |
| 36 | 40 | 'unsubscribePage', |
| 37 | 41 | 'confirm', |
| 38 | 42 | 'profile', |
| @@ -47,12 +51,18 @@ | ||
| 47 | 51 | |
| 48 | 52 | private function displayMessage(string $message, bool $ajax, string $type = 'error'): void |
| 49 | 53 | { |
| 50 | 54 | if ($ajax) { |
| 51 | - echo '{"message":"'.acym_translation($message, true).'","type":"'.$type.'","code":"1"}'; | |
| 55 | + echo json_encode( | |
| 56 | + [ | |
| 57 | + 'message' => acym_translation($message), | |
| 58 | + 'type' => $type, | |
| 59 | + 'code' => '1', | |
| 60 | + ] | |
| 61 | + ); | |
| 52 | 62 | } else { |
| 53 | 63 | acym_header('Content-type:text/html; charset=utf-8'); |
| 54 | - echo '<script>alert("'.acym_translation($message, true).'"); window.history.go(-1);</script>'; | |
| 64 | + echo '<script>alert("'.esc_html(acym_translation($message)).'"); window.history.go(-1);</script>'; | |
| 55 | 65 | } |
| 56 | 66 | exit; |
| 57 | 67 | } |
| 58 | 68 | |
| @@ -59,22 +69,33 @@ | ||
| 59 | 69 | public function subscribe(): void |
| 60 | 70 | { |
| 61 | 71 | acym_checkRobots(); |
| 62 | 72 | |
| 63 | - if (!acym_getVar('string', 'acy_source') && !empty($_GET['user'])) { | |
| 73 | + $formData = acym_getVar('array', 'user', []); | |
| 74 | + if (!acym_getVar('string', 'acy_source') && !empty($formData)) { | |
| 75 | + // Coming from a subscription via url... | |
| 64 | 76 | acym_setVar('acy_source', 'url'); |
| 65 | 77 | } |
| 66 | 78 | |
| 79 | + // Do we have to return an ajax response or a web page ? | |
| 67 | 80 | $ajax = acym_getVar('int', 'ajax', 0); |
| 68 | 81 | if ($ajax) { |
| 82 | + //in case of the page displays some warnings or whatever | |
| 69 | 83 | @ob_end_clean(); |
| 70 | - acym_header('Content-type:text/html; charset=utf-8'); | |
| 84 | + acym_header('Content-type:application/json; charset=utf-8'); | |
| 71 | 85 | } |
| 72 | 86 | |
| 87 | + //We only allow logged in users and this user is not logged it... | |
| 73 | 88 | $currentUserid = acym_currentUserId(); |
| 74 | 89 | if ((int)$this->config->get('allow_visitor', 1) != 1 && empty($currentUserid)) { |
| 75 | 90 | if ($ajax) { |
| 76 | - echo '{"message":"'.acym_translation('ACYM_ONLY_LOGGED', true).'","type":"error","code":"0"}'; | |
| 91 | + echo json_encode( | |
| 92 | + [ | |
| 93 | + 'message' => acym_translation('ACYM_ONLY_LOGGED'), | |
| 94 | + 'type' => 'error', | |
| 95 | + 'code' => '0', | |
| 96 | + ] | |
| 97 | + ); | |
| 77 | 98 | exit; |
| 78 | 99 | } else { |
| 79 | 100 | acym_askLog(false, 'ACYM_ONLY_LOGGED'); |
| 80 | 101 | |
| @@ -88,9 +109,8 @@ | ||
| 88 | 109 | $this->displayMessage('ACYM_WRONG_CAPTCHA', $ajax); |
| 89 | 110 | } |
| 90 | 111 | } |
| 91 | 112 | |
| 92 | - $formData = acym_getVar('array', 'user', [], ''); | |
| 93 | 113 | $user = new \stdClass(); |
| 94 | 114 | if (!empty($formData['email'])) { |
| 95 | 115 | $user->email = $formData['email']; |
| 96 | 116 | } |
| @@ -103,18 +123,21 @@ | ||
| 103 | 123 | } |
| 104 | 124 | } |
| 105 | 125 | $user->email = trim($user->email); |
| 106 | 126 | |
| 127 | + // Check email validity | |
| 107 | 128 | if (empty($user->email) || !acym_isValidEmail($user->email, true)) { |
| 108 | 129 | $this->displayMessage('ACYM_VALID_EMAIL', $ajax); |
| 109 | 130 | } |
| 110 | 131 | |
| 132 | + // E-mail is valid now... | |
| 133 | + // Check if this user already exists or not... | |
| 111 | 134 | $alreadyExists = $userClass->getOneByEmail($user->email); |
| 112 | 135 | if (!empty($alreadyExists->id)) { |
| 113 | 136 | $user->id = $alreadyExists->id; |
| 114 | 137 | } |
| 115 | 138 | |
| 116 | - $result = $userClass->saveForm($ajax); | |
| 139 | + $successfullySaved = $userClass->saveForm($ajax); | |
| 117 | 140 | $user->id = acym_getVar('int', 'userId'); |
| 118 | 141 | |
| 119 | 142 | if (!empty($userClass->errors)) { |
| 120 | 143 | $this->displayMessage(implode('<br /><br />', $userClass->errors), $ajax); |
| @@ -119,12 +142,13 @@ | ||
| 119 | 142 | if (!empty($userClass->errors)) { |
| 120 | 143 | $this->displayMessage(implode('<br /><br />', $userClass->errors), $ajax); |
| 121 | 144 | } |
| 122 | 145 | |
| 123 | - if ($result === false || empty($user->id)) { | |
| 146 | + if (!$successfullySaved || empty($user->id)) { | |
| 124 | 147 | $this->displayMessage('ACYM_ERROR_SAVE_USER', $ajax); |
| 125 | 148 | } |
| 126 | 149 | |
| 150 | + //We will now load back the user from the one we saved so that we will have all its infos | |
| 127 | 151 | $myuser = $userClass->getOneById($user->id); |
| 128 | 152 | if (empty($myuser->id)) { |
| 129 | 153 | $this->displayMessage('ACYM_ERROR_SAVE_USER', $ajax); |
| 130 | 154 | } |
| @@ -129,13 +153,14 @@ | ||
| 129 | 153 | $this->displayMessage('ACYM_ERROR_SAVE_USER', $ajax); |
| 130 | 154 | } |
| 131 | 155 | |
| 132 | 156 | $msgtype = 'success'; |
| 133 | - $extraMsg = ''; | |
| 134 | 157 | if (empty($myuser->confirmed) && $this->config->get('require_confirmation', 1) == 1) { |
| 135 | - $extraMsg = strip_tags(acym_getVar('string', 'confirmation_message')); | |
| 136 | 158 | if ($userClass->confirmationSentSuccess || empty($userClass->confirmationSentError)) { |
| 137 | - $msg = !empty($extraMsg) ? $extraMsg : 'ACYM_CONFIRMATION_SENT'; | |
| 159 | + $msg = acym_stripTags(acym_getVar('string', 'confirmation_message', '')); | |
| 160 | + if (empty($msg)) { | |
| 161 | + $msg = 'ACYM_CONFIRMATION_SENT'; | |
| 162 | + } | |
| 138 | 163 | $code = 2; |
| 139 | 164 | } else { |
| 140 | 165 | $msg = $userClass->confirmationSentError; |
| 141 | 166 | $code = 7; |
| @@ -142,10 +167,12 @@ | ||
| 142 | 167 | $msgtype = 'error'; |
| 143 | 168 | } |
| 144 | 169 | } else { |
| 145 | 170 | if ($userClass->subscribed) { |
| 146 | - $msg = strip_tags(acym_getVar('string', 'confirmation_message')); | |
| 147 | - if (empty($msg)) $msg = 'ACYM_SUBSCRIPTION_OK'; | |
| 171 | + $msg = acym_stripTags(acym_getVar('string', 'confirmation_message', '')); | |
| 172 | + if (empty($msg)) { | |
| 173 | + $msg = 'ACYM_SUBSCRIPTION_OK'; | |
| 174 | + } | |
| 148 | 175 | $code = 3; |
| 149 | 176 | } else { |
| 150 | 177 | $msg = 'ACYM_ALREADY_SUBSCRIBED'; |
| 151 | 178 | $code = 5; |
| @@ -152,8 +179,9 @@ | ||
| 152 | 179 | $enqueueMsgType = 'info'; |
| 153 | 180 | } |
| 154 | 181 | } |
| 155 | 182 | |
| 183 | + // Replace tags inside the $msg and redirect link | |
| 156 | 184 | $replace = []; |
| 157 | 185 | foreach ($myuser as $oneProp => $oneVal) { |
| 158 | 186 | $replace['{user:'.$oneProp.'}'] = $oneVal; |
| 159 | 187 | } |
| @@ -158,15 +186,19 @@ | ||
| 158 | 186 | $replace['{user:'.$oneProp.'}'] = $oneVal; |
| 159 | 187 | } |
| 160 | 188 | |
| 161 | 189 | $msg = str_replace(array_keys($replace), $replace, acym_translation($msg)); |
| 162 | - if (!empty($extraMsg)) { | |
| 163 | - $msg = str_replace(array_keys($replace), $replace, acym_translation($extraMsg)).'<br />'.$msg; | |
| 164 | - } | |
| 165 | 190 | |
| 166 | 191 | if ($ajax) { |
| 192 | + //Make sure the message has a valid format for Ajax... so the user can customize it the way he wants without breaking anything | |
| 167 | 193 | $msg = str_replace(["\n", "\r", '"', '\\'], [' ', ' ', "'", '\\\\'], $msg); |
| 168 | - echo '{"message":"'.$msg.'","type":"'.$msgtype.'","code":"'.$code.'"}'; | |
| 194 | + echo json_encode( | |
| 195 | + [ | |
| 196 | + 'message' => $msg, | |
| 197 | + 'type' => $msgtype, | |
| 198 | + 'code' => $code, | |
| 199 | + ] | |
| 200 | + ); | |
| 169 | 201 | exit; |
| 170 | 202 | } else { |
| 171 | 203 | acym_enqueueMessage($msg, !empty($enqueueMsgType) ? $enqueueMsgType : $msgtype); |
| 172 | 204 | } |
| @@ -191,14 +223,46 @@ | ||
| 191 | 223 | return; |
| 192 | 224 | } |
| 193 | 225 | } |
| 194 | 226 | |
| 227 | + if (empty($currentUser) || empty($currentUser->id)) { | |
| 228 | + $currentUser = $alreadyExists; | |
| 229 | + } | |
| 230 | + | |
| 195 | 231 | $visibleSubscription = acym_getVar('array', 'subscription', []); |
| 196 | 232 | $hiddenLists = trim(acym_getVar('string', 'hiddenlists', '')); |
| 197 | 233 | $hiddenSubscription = empty($hiddenLists) ? [] : explode(',', $hiddenLists); |
| 198 | 234 | $unsubscribeLists = array_merge($visibleSubscription, $hiddenSubscription); |
| 235 | + acym_arrayToInteger($unsubscribeLists); | |
| 199 | 236 | |
| 200 | 237 | $mailId = acym_getVar('int', 'mail_id', 0); |
| 238 | + | |
| 239 | + // Protect against bots | |
| 240 | + if (!empty($mailId) && !empty($currentUser->id)) { | |
| 241 | + $userStatClass = new UserStatClass(); | |
| 242 | + $userStat = $userStatClass->getOneByMailAndUserId($mailId, $currentUser->id); | |
| 243 | + $delay = $this->config->get('tracking_delay', 0); | |
| 244 | + if (acym_isRobot() || (!empty($userStat) && !empty($delay) && acym_getTimeFromUTCDate($userStat->send_date) > time() - $delay)) { | |
| 245 | + return; | |
| 246 | + } | |
| 247 | + } | |
| 248 | + | |
| 249 | + if (empty($unsubscribeLists)) { | |
| 250 | + $mailClass = new MailClass(); | |
| 251 | + $mailType = $mailClass->getMailType($mailId); | |
| 252 | + if (empty($currentUser) || empty($currentUser->id)) { | |
| 253 | + $currentUser = $userClass->identify(true, 'userId', 'userKey'); | |
| 254 | + } | |
| 255 | + | |
| 256 | + if ($mailType === $mailClass::TYPE_SCENARIO) { | |
| 257 | + $scenarioClass = new ScenarioClass(); | |
| 258 | + $scenarioId = $scenarioClass->getScenarioIdByMailId($mailId); | |
| 259 | + if (!empty($currentUser->id)) { | |
| 260 | + $scenarioClass->markUserUnsubscribeFromScenario($currentUser->id, $scenarioId); | |
| 261 | + } | |
| 262 | + } | |
| 263 | + } | |
| 264 | + | |
| 201 | 265 | if (!empty($mailId)) { |
| 202 | 266 | $mailClass = new MailClass(); |
| 203 | 267 | $unsubscribeLists = array_keys($mailClass->getAllListsByMailId($mailId)); |
| 204 | 268 | } |
| @@ -204,14 +268,19 @@ | ||
| 204 | 268 | } |
| 205 | 269 | |
| 206 | 270 | if (empty($unsubscribeLists)) { |
| 207 | 271 | $msg = 'ACYM_NO_SUBSCRIPTION_LINKED_EMAIL'; |
| 208 | - } elseif (false === $userClass->unsubscribe($alreadyExists->id, $unsubscribeLists)) { | |
| 272 | + } elseif (false === $userClass->unsubscribe([$alreadyExists->id], $unsubscribeLists)) { | |
| 209 | 273 | $msg = 'ACYM_UNSUBSCRIPTION_NOT_IN_LIST'; |
| 210 | 274 | } else { |
| 211 | 275 | $msg = 'ACYM_UNSUBSCRIPTION_OK'; |
| 212 | 276 | } |
| 213 | 277 | |
| 278 | + if (!empty($mailType) && $mailType === $mailClass::TYPE_SCENARIO) { | |
| 279 | + $msg = 'ACYM_UNSUBSCRIPTION_SCENARIO_OK'; | |
| 280 | + } | |
| 281 | + | |
| 282 | + | |
| 214 | 283 | $this->endUnsubscribe($msg, $ajax); |
| 215 | 284 | } |
| 216 | 285 | |
| 217 | 286 | private function endUnsubscribe(string $msg, bool $ajax, string $type = 'success'): void |
| @@ -218,9 +287,15 @@ | ||
| 218 | 287 | { |
| 219 | 288 | $msg = acym_translation($msg); |
| 220 | 289 | |
| 221 | 290 | if ($ajax) { |
| 222 | - echo '{"message":"'.str_replace('"', '\"', $msg).'","type":"'.$type.'","code":"10"}'; | |
| 291 | + echo json_encode( | |
| 292 | + [ | |
| 293 | + 'message' => $msg, | |
| 294 | + 'type' => $type, | |
| 295 | + 'code' => '10', | |
| 296 | + ] | |
| 297 | + ); | |
| 223 | 298 | exit; |
| 224 | 299 | } |
| 225 | 300 | acym_enqueueMessage($msg, $type); |
| 226 | 301 | |
| @@ -228,11 +303,29 @@ | ||
| 228 | 303 | if (empty($redirectUrl)) { |
| 229 | 304 | $redirectUrl = acym_rootURI(); |
| 230 | 305 | } |
| 231 | 306 | |
| 232 | - acym_redirect($redirectUrl); | |
| 307 | + acym_redirect($this->normalizeRedirectUrl($redirectUrl), '', 'message', true); | |
| 233 | 308 | } |
| 234 | 309 | |
| 310 | + private function normalizeRedirectUrl(string $url): string | |
| 311 | + { | |
| 312 | + if ($url === '') { | |
| 313 | + return ''; | |
| 314 | + } | |
| 315 | + if (preg_match('~^[a-z][a-z0-9+.\-]*://~i', $url)) { | |
| 316 | + return $url; | |
| 317 | + } | |
| 318 | + if (strpos($url, '/') === 0 || strpos($url, 'index.php') === 0) { | |
| 319 | + return $url; | |
| 320 | + } | |
| 321 | + if (preg_match('~^[^/?#]+\.[a-z]{2,}(?:[/?#]|$)~i', $url)) { | |
| 322 | + return 'https://'.$url; | |
| 323 | + } | |
| 324 | + | |
| 325 | + return $url; | |
| 326 | + } | |
| 327 | + | |
| 235 | 328 | public function unsubscribe(): void |
| 236 | 329 | { |
| 237 | 330 | acym_checkRobots(); |
| 238 | 331 | $userClass = new UserClass(); |
| @@ -237,17 +330,23 @@ | ||
| 237 | 330 | acym_checkRobots(); |
| 238 | 331 | $userClass = new UserClass(); |
| 239 | 332 | |
| 240 | 333 | $redirectToUnsubPage = $this->config->get('unsubscribe_page', 1); |
| 334 | + $direct = acym_getVar('int', 'direct', 0); | |
| 241 | 335 | |
| 336 | + // Do we have to return an ajax response or a web page ? | |
| 242 | 337 | $ajax = acym_getVar('int', 'ajax', 0); |
| 243 | 338 | if ($ajax) { |
| 244 | 339 | @ob_end_clean(); |
| 245 | - acym_header('Content-type:text/html; charset=utf-8'); | |
| 340 | + acym_header('Content-type:application/json; charset=utf-8'); | |
| 246 | 341 | } |
| 247 | 342 | |
| 248 | 343 | $currentUserid = acym_currentUserId(); |
| 249 | 344 | $user = $userClass->identify(true, 'userId', 'userKey'); |
| 345 | + if (empty($user)) { | |
| 346 | + $user = $userClass->identify(true, 'user_id', 'user_key'); | |
| 347 | + $direct = 1; | |
| 348 | + } | |
| 250 | 349 | if (empty($user) && empty($currentUserid) && $this->config->get('captcha', 'none') !== 'none' && acym_level(ACYM_ESSENTIAL)) { |
| 251 | 350 | $captchaClass = new CaptchaHelper(); |
| 252 | 351 | if (!$captchaClass->check()) { |
| 253 | 352 | $this->displayMessage('ACYM_WRONG_CAPTCHA', $ajax); |
| @@ -254,19 +353,18 @@ | ||
| 254 | 353 | } |
| 255 | 354 | } |
| 256 | 355 | |
| 257 | 356 | $formData = acym_getVar('array', 'user', []); |
| 357 | + $email = ''; | |
| 258 | 358 | |
| 259 | - if (empty($formData['email'])) { | |
| 260 | - if (empty($user)) { | |
| 261 | - return; | |
| 262 | - } | |
| 263 | - | |
| 264 | - if (!empty($user->email)) { | |
| 265 | - $email = $user->email; | |
| 266 | - } | |
| 267 | - } else { | |
| 268 | - $email = trim(strip_tags($formData['email'])); | |
| 359 | + if (!empty($formData['email'])) { | |
| 360 | + $email = trim(acym_stripTags($formData['email'])); | |
| 361 | + } elseif (empty($user)) { | |
| 362 | + return; | |
| 363 | + } elseif (!empty($user->email)) { | |
| 364 | + $email = $user->email; | |
| 365 | + } elseif (!empty(acym_currentUserEmail())) { | |
| 366 | + $email = acym_currentUserEmail(); | |
| 269 | 367 | } |
| 270 | 368 | |
| 271 | 369 | $currentEmail = acym_currentUserEmail(); |
| 272 | 370 | if (empty($email) && !empty($currentEmail)) { |
| @@ -272,8 +370,9 @@ | ||
| 272 | 370 | if (empty($email) && !empty($currentEmail)) { |
| 273 | 371 | $email = $currentEmail; |
| 274 | 372 | } |
| 275 | 373 | |
| 374 | + // Check email validity | |
| 276 | 375 | if (empty($email) || !acym_isValidEmail($email)) { |
| 277 | 376 | $this->displayMessage('ACYM_VALID_EMAIL', $ajax); |
| 278 | 377 | } |
| 279 | 378 | |
| @@ -278,22 +377,85 @@ | ||
| 278 | 377 | } |
| 279 | 378 | |
| 280 | 379 | $alreadyExists = $userClass->getOneByEmail($email); |
| 281 | 380 | |
| 381 | + // User not found | |
| 282 | 382 | if (empty($alreadyExists->id)) { |
| 283 | - $this->displayMessage('ACYM_SUB_NOT_IN_LIST', $ajax); | |
| 383 | + $this->displayMessage(acym_translationSprintf('ACYM_SUB_NOT_IN_LIST', $email), $ajax); | |
| 284 | 384 | } |
| 285 | 385 | |
| 286 | 386 | $fromModuleOrWidget = acym_getVar('string', 'acysubmode', ''); |
| 287 | - if (!empty($fromModuleOrWidget) && in_array($fromModuleOrWidget, ['form_acym', 'mod_acym', 'widget_acym'])) { | |
| 387 | + if ((!empty($fromModuleOrWidget) && in_array($fromModuleOrWidget, ['form_acym', 'mod_acym', 'widget_acym'])) || $ajax || !$redirectToUnsubPage || !empty($direct)) { | |
| 288 | 388 | $this->unsubscribeDirectly($alreadyExists, $ajax); |
| 289 | - } elseif ($redirectToUnsubPage && !$ajax) { | |
| 389 | + } elseif ($redirectToUnsubPage && !$ajax && !$direct) { | |
| 390 | + $identifiedEmail = !empty($user->email) ? $user->email : $currentEmail; | |
| 391 | + if (empty($identifiedEmail) || strtolower($alreadyExists->email) !== strtolower($identifiedEmail)) { | |
| 392 | + $this->displayMessage('ACYM_NOT_ALLOWED_MODIFY_USER', $ajax); | |
| 393 | + } | |
| 290 | 394 | $this->unsubscribePage($alreadyExists); |
| 291 | - } else { | |
| 292 | - $this->unsubscribeDirectly($alreadyExists, $ajax); | |
| 293 | 395 | } |
| 294 | 396 | } |
| 295 | 397 | |
| 398 | + public function disableTracking(): void | |
| 399 | + { | |
| 400 | + acym_checkRobots(); | |
| 401 | + | |
| 402 | + // Do we have to return an ajax response or a web page ? | |
| 403 | + $ajax = acym_getVar('int', 'ajax', 0); | |
| 404 | + if ($ajax) { | |
| 405 | + @ob_end_clean(); | |
| 406 | + acym_header('Content-type:application/json; charset=utf-8'); | |
| 407 | + } | |
| 408 | + | |
| 409 | + $userClass = new UserClass(); | |
| 410 | + $user = $userClass->identify(true, 'userId', 'userKey'); | |
| 411 | + | |
| 412 | + if (empty($user->id)) { | |
| 413 | + $this->displayMessage('ACYM_USER_NOT_FOUND', $ajax); | |
| 414 | + } | |
| 415 | + | |
| 416 | + // Protect against bots opening the link right after the email was sent | |
| 417 | + $mailId = acym_getVar('int', 'mail_id', 0); | |
| 418 | + if (!empty($mailId)) { | |
| 419 | + $userStatClass = new UserStatClass(); | |
| 420 | + $userStat = $userStatClass->getOneByMailAndUserId($mailId, $user->id); | |
| 421 | + $delay = $this->config->get('tracking_delay', 0); | |
| 422 | + if (acym_isRobot() || (!empty($userStat) && !empty($delay) && acym_getTimeFromUTCDate($userStat->send_date) > time() - $delay)) { | |
| 423 | + return; | |
| 424 | + } | |
| 425 | + } | |
| 426 | + | |
| 427 | + if ((int)$user->tracking !== 0) { | |
| 428 | + $userClass->disableTracking($user, $mailId); | |
| 429 | + } | |
| 430 | + | |
| 431 | + $this->endDisableTracking('ACYM_TRACKING_DISABLED_OK', $ajax); | |
| 432 | + } | |
| 433 | + | |
| 434 | + private function endDisableTracking(string $msg, bool $ajax, string $type = 'success'): void | |
| 435 | + { | |
| 436 | + $msg = acym_translation($msg); | |
| 437 | + | |
| 438 | + if ($ajax) { | |
| 439 | + echo json_encode( | |
| 440 | + [ | |
| 441 | + 'message' => $msg, | |
| 442 | + 'type' => $type, | |
| 443 | + 'code' => '10', | |
| 444 | + ] | |
| 445 | + ); | |
| 446 | + exit; | |
| 447 | + } | |
| 448 | + acym_enqueueMessage($msg, $type); | |
| 449 | + | |
| 450 | + $redirectUrl = urldecode(acym_getVar('string', 'redirectunsub', '')); | |
| 451 | + if (empty($redirectUrl)) { | |
| 452 | + $redirectUrl = acym_rootURI(); | |
| 453 | + } | |
| 454 | + | |
| 455 | + acym_redirect($this->normalizeRedirectUrl($redirectUrl), '', 'message', true); | |
| 456 | + } | |
| 457 | + | |
| 296 | 458 | private function getUserFromUnsubPage(): object |
| 297 | 459 | { |
| 298 | 460 | $userID = acym_getVar('int', 'user_id'); |
| 299 | 461 | $userClass = new UserClass(); |
| @@ -312,14 +474,17 @@ | ||
| 312 | 474 | private function unsubscribeAllInner(bool $update = false): void |
| 313 | 475 | { |
| 314 | 476 | $userClass = new UserClass(); |
| 315 | 477 | $user = $this->getUserFromUnsubPage(); |
| 316 | - $redirectUrl = $this->config->get('unsub_redirect_url', acym_rootURI()); | |
| 478 | + $redirectUrl = urldecode(acym_getVar('string', 'redirectunsub', '')); | |
| 479 | + if (empty($redirectUrl)) { | |
| 480 | + $redirectUrl = $this->config->get('unsub_redirect_url', ''); | |
| 481 | + } | |
| 317 | 482 | |
| 318 | 483 | $allLists = $userClass->getUserSubscriptionById($user->id); |
| 319 | 484 | if (empty($allLists)) { |
| 320 | 485 | acym_enqueueMessage(acym_translation('ACYM_NOT_SUBSCRIBED_ANY_LIST'), 'info'); |
| 321 | - acym_redirect(!empty($redirectUrl) ? $redirectUrl : acym_rootURI()); | |
| 486 | + acym_redirect($this->normalizeRedirectUrl(!empty($redirectUrl) ? $redirectUrl : acym_rootURI()), '', 'message', true); | |
| 322 | 487 | } |
| 323 | 488 | |
| 324 | 489 | $lists = []; |
| 325 | 490 | foreach ($allLists as $list) { |
| @@ -328,18 +493,22 @@ | ||
| 328 | 493 | } |
| 329 | 494 | } |
| 330 | 495 | |
| 331 | 496 | $userClass->sendNotification($user->id, 'acy_notification_unsuball'); |
| 497 | + // A notification is sent when a user unsubscribes from a list, be we already sent a notification for this | |
| 332 | 498 | $userClass->blockNotifications = true; |
| 333 | - $userClass->unsubscribe($user->id, $lists); | |
| 499 | + $userClass->unsubscribe([$user->id], $lists); | |
| 334 | 500 | } |
| 335 | 501 | |
| 336 | 502 | private function redirectUnsubWorked(): void |
| 337 | 503 | { |
| 338 | 504 | acym_enqueueMessage(acym_translation('ACYM_SUBSCRIPTION_UPDATED_OK')); |
| 339 | - $redirectUrl = $this->config->get('unsub_redirect_url'); | |
| 505 | + $redirectUrl = urldecode(acym_getVar('string', 'redirectunsub', '')); | |
| 506 | + if (empty($redirectUrl)) { | |
| 507 | + $redirectUrl = $this->config->get('unsub_redirect_url', ''); | |
| 508 | + } | |
| 340 | 509 | if (!empty($redirectUrl)) { |
| 341 | - acym_redirect($redirectUrl); | |
| 510 | + acym_redirect($this->normalizeRedirectUrl($redirectUrl), '', 'message', true); | |
| 342 | 511 | } else { |
| 343 | 512 | acym_redirect(acym_rootURI()); |
| 344 | 513 | } |
| 345 | 514 | } |
| @@ -346,9 +515,9 @@ | ||
| 346 | 515 | |
| 347 | 516 | public function unsubscribeAll(): void |
| 348 | 517 | { |
| 349 | 518 | $userClass = new UserClass(); |
| 350 | - if ($userClass->identify(true, 'user_id', 'user_key') === false) { | |
| 519 | + if (empty($userClass->identify(true, 'user_id', 'user_key'))) { | |
| 351 | 520 | acym_enqueueMessage(acym_translation('ACYM_USER_NOT_FOUND'), 'error'); |
| 352 | 521 | |
| 353 | 522 | acym_redirect(acym_rootURI()); |
| 354 | 523 | } |
| @@ -355,9 +524,9 @@ | ||
| 355 | 524 | |
| 356 | 525 | $displayCheckedLists = acym_getVar('string', 'displayed_checked_lists', ''); |
| 357 | 526 | if (!empty($displayCheckedLists)) { |
| 358 | 527 | $user = $this->getUserFromUnsubPage(); |
| 359 | - $userClass->unsubscribe($user->id, explode(',', $displayCheckedLists)); | |
| 528 | + $userClass->unsubscribe([$user->id], explode(',', $displayCheckedLists)); | |
| 360 | 529 | } else { |
| 361 | 530 | $this->unsubscribeAllInner(); |
| 362 | 531 | } |
| 363 | 532 | |
| @@ -369,33 +538,42 @@ | ||
| 369 | 538 | |
| 370 | 539 | public function saveSubscriptions(): void |
| 371 | 540 | { |
| 372 | 541 | $userClass = new UserClass(); |
| 373 | - if ($userClass->identify(true, 'user_id', 'user_key') === false) { | |
| 542 | + if (empty($userClass->identify(true, 'user_id', 'user_key'))) { | |
| 374 | 543 | $this->displayMessage('ACYM_USER_NOT_FOUND', false); |
| 375 | 544 | } |
| 376 | 545 | |
| 546 | + // Get the user | |
| 377 | 547 | $user = $this->getUserFromUnsubPage(); |
| 548 | + // Get the list the user want to sub | |
| 378 | 549 | $listsChecked = acym_getVar('array', 'lists', []); |
| 379 | 550 | $listsChecked = array_filter($listsChecked, function ($status) { |
| 380 | 551 | return intval($status) === 1; |
| 381 | 552 | }); |
| 382 | 553 | $listsChecked = array_keys($listsChecked); |
| 554 | + // Get the displayed lists | |
| 383 | 555 | $displayedCheckedLists = explode(',', acym_getVar('string', 'displayed_checked_lists', '')); |
| 556 | + // We get the user subscriptions | |
| 384 | 557 | $userSubscriptions = $userClass->getUserSubscriptionById($user->id); |
| 385 | 558 | |
| 386 | - $userClass->subscribe($user->id, $listsChecked); | |
| 559 | + // We subscribe the user to the checked lists | |
| 560 | + $userClass->subscribe([$user->id], $listsChecked); | |
| 387 | 561 | |
| 562 | + // We unsub to the unchecked lists | |
| 388 | 563 | $listsToUnsub = []; |
| 389 | 564 | foreach ($userSubscriptions as $subscription) { |
| 390 | - if (!in_array($subscription->id, $listsChecked) | |
| 565 | + // The list wasn't checked && the list is displayed && the user is subscribed to it | |
| 566 | + if ( | |
| 567 | + !in_array($subscription->id, $listsChecked) | |
| 391 | 568 | && in_array($subscription->id, $displayedCheckedLists) |
| 392 | - && intval($subscription->status) === 1) { | |
| 569 | + && intval($subscription->status) === 1 | |
| 570 | + ) { | |
| 393 | 571 | $listsToUnsub[] = $subscription->id; |
| 394 | 572 | } |
| 395 | 573 | } |
| 396 | 574 | |
| 397 | - $userClass->unsubscribe($user->id, $listsToUnsub); | |
| 575 | + $userClass->unsubscribe([$user->id], $listsToUnsub); | |
| 398 | 576 | $this->redirectUnsubWorked(); |
| 399 | 577 | } |
| 400 | 578 | |
| 401 | 579 | public function unsubscribePage(object $alreadyExists): void |
| @@ -405,14 +583,20 @@ | ||
| 405 | 583 | $mailId = acym_getVar('int', 'mail_id', 0); |
| 406 | 584 | $campaignListOnly = $this->config->get('unsubscribe_campaign_list_only', '0') === '1'; |
| 407 | 585 | $displaySurvey = $this->config->get('unsubpage_survey', '0') === '1'; |
| 408 | 586 | $surveyAnswers = $this->config->get('unsub_survey', '[]'); |
| 409 | - $unsubscribeColor = $this->config->get('unsubscribe_color', '#00a4ff'); | |
| 587 | + $unsubscribeColor = $this->config->get('unsubscribe_color'); | |
| 588 | + if (empty($unsubscribeColor)) { | |
| 589 | + $unsubscribeColor = '#0079d3'; | |
| 590 | + } | |
| 410 | 591 | $hoverColor = $this->darkenRGBColor($unsubscribeColor, 20); |
| 411 | 592 | |
| 412 | 593 | $surveyAnswers = json_decode($surveyAnswers, true); |
| 413 | 594 | |
| 414 | - if (ACYM_CMS === 'joomla' && !empty($_GET['language'])) $lang = $_GET['language']; | |
| 595 | + $languageCode = acym_getVar('string', 'language'); | |
| 596 | + if (ACYM_CMS === 'joomla' && !empty($languageCode)) { | |
| 597 | + $lang = $languageCode; | |
| 598 | + } | |
| 415 | 599 | acym_setLanguage($lang); |
| 416 | 600 | acym_loadLanguage($lang); |
| 417 | 601 | |
| 418 | 602 | $userSubscriptions = $userClass->getUserSubscriptionById($alreadyExists->id, 'id', false, false, true, false, $mailId, $campaignListOnly); |
| @@ -451,17 +635,15 @@ | ||
| 451 | 635 | $data['surveyAnswers'][] = acym_translation('ACYM_OTHER'); |
| 452 | 636 | $data['surveyAnswers'] = array_combine($data['surveyAnswers'], $data['surveyAnswers']); |
| 453 | 637 | } |
| 454 | 638 | |
| 455 | - if (!empty($this->config->get('unsubscribe_color'))) { | |
| 456 | - $unsubscribeColor = $this->config->get('unsubscribe_color'); | |
| 457 | - $hoverColor = $this->darkenRGBColor($unsubscribeColor, 20); | |
| 458 | - $data['unsubscribeColor'] = $unsubscribeColor; | |
| 459 | - $data['hoverColor'] = $hoverColor; | |
| 460 | - } | |
| 639 | + $data['unsubscribeColor'] = $unsubscribeColor; | |
| 640 | + $data['hoverColor'] = $hoverColor; | |
| 461 | 641 | $data['svgImage'] = $this->getSVGImage($unsubscribeColor, $hoverColor); |
| 462 | 642 | |
| 463 | 643 | acym_setVar('layout', 'unsubscribepage'); |
| 644 | + acym_header('Content-Type: text/html; charset=utf-8'); | |
| 645 | + | |
| 464 | 646 | parent::display($data); |
| 465 | 647 | } |
| 466 | 648 | |
| 467 | 649 | private function getSVGImage(string $unsubscribeColor, string $hoverColor): string |
| @@ -512,8 +694,9 @@ | ||
| 512 | 694 | if (acym_isRobot()) { |
| 513 | 695 | return; |
| 514 | 696 | } |
| 515 | 697 | |
| 698 | + // We identify the user | |
| 516 | 699 | $userClass = new UserClass(); |
| 517 | 700 | $user = $userClass->identify(true, 'userId', 'userKey'); |
| 518 | 701 | if (empty($user)) { |
| 519 | 702 | acym_enqueueMessage(acym_translation('ACYM_USER_NOT_FOUND'), 'error'); |
| @@ -529,20 +712,23 @@ | ||
| 529 | 712 | acym_enqueueMessage(acym_translation('ACYM_SUBSCRIPTION_CONFIRMED'), 'success'); |
| 530 | 713 | } |
| 531 | 714 | } |
| 532 | 715 | |
| 716 | + // Now we can really confirm the user | |
| 533 | 717 | if (!$user->confirmed) { |
| 534 | 718 | $userClass->confirm($user->id); |
| 535 | 719 | } |
| 536 | 720 | |
| 721 | + // Get the redirect url from the configuration page if specified | |
| 537 | 722 | $redirectUrl = $this->config->get('confirm_redirect'); |
| 538 | 723 | if (!empty($redirectUrl)) { |
| 539 | 724 | $replace = []; |
| 725 | + // We replace tags in case of the user added some dynamic information to its url. | |
| 540 | 726 | foreach ($user as $key => $val) { |
| 541 | 727 | $replace['{user:'.$key.'}'] = $val; |
| 542 | 728 | } |
| 543 | 729 | $redirectUrl = str_replace(array_keys($replace), $replace, $redirectUrl); |
| 544 | - acym_redirect($redirectUrl); | |
| 730 | + acym_redirect($redirectUrl, '', 'message', false); | |
| 545 | 731 | |
| 546 | 732 | return; |
| 547 | 733 | } |
| 548 | 734 | |
| @@ -554,8 +740,9 @@ | ||
| 554 | 740 | $userClass = new UserClass(); |
| 555 | 741 | $user = $userClass->identify(true); |
| 556 | 742 | |
| 557 | 743 | if (empty($user)) { |
| 744 | + // Check if the subscription is allowed for non registered users | |
| 558 | 745 | $allowvisitor = $this->config->get('allow_visitor', 1); |
| 559 | 746 | if (empty($allowvisitor)) { |
| 560 | 747 | acym_askLog(true, 'ACYM_ONLY_LOGGED', 'message'); |
| 561 | 748 | |
| @@ -572,8 +759,9 @@ | ||
| 572 | 759 | acym_addScript(false, ACYM_JS.'libraries/email-misspelled.min.js?v='.filemtime(ACYM_MEDIA.'js'.DS.'libraries'.DS.'email-misspelled.min.js')); |
| 573 | 760 | } |
| 574 | 761 | acym_addScript(false, ACYM_JS.'module.min.js?v='.filemtime(ACYM_MEDIA.'js'.DS.'module.min.js')); |
| 575 | 762 | |
| 763 | + // Get the page parameters | |
| 576 | 764 | $params = new \stdClass(); |
| 577 | 765 | $menu = acym_getMenu(); |
| 578 | 766 | if (is_object($menu)) { |
| 579 | 767 | $params->source = 'Menu n°'.$menu->id; |
| @@ -580,8 +768,9 @@ | ||
| 580 | 768 | $menuParameters = method_exists($menu, 'getParams') ? $menu->getParams() : $menu->params; |
| 581 | 769 | $menuparams = new AcymParameter($menuParameters); |
| 582 | 770 | |
| 583 | 771 | if (!empty($menuparams)) { |
| 772 | + // Joomla specific params | |
| 584 | 773 | $params->suffix = $menuparams->get('pageclass_sfx', ''); |
| 585 | 774 | $params->page_heading = $menuparams->get('page_heading'); |
| 586 | 775 | $params->show_page_heading = $menuparams->get('show_page_heading', 0); |
| 587 | 776 | |
| @@ -594,8 +783,9 @@ | ||
| 594 | 783 | if ($menuparams->get('robots')) { |
| 595 | 784 | acym_addMetadata('robots', $menuparams->get('robots')); |
| 596 | 785 | } |
| 597 | 786 | |
| 787 | + // Our params | |
| 598 | 788 | $params->lists = $menuparams->get('lists', 'none'); |
| 599 | 789 | $params->listschecked = $menuparams->get('listschecked', 'none'); |
| 600 | 790 | $params->dropdown = $menuparams->get('dropdown'); |
| 601 | 791 | $params->hiddenlists = $menuparams->get('hiddenlists', 'None'); |
| @@ -619,8 +809,9 @@ | ||
| 619 | 809 | } |
| 620 | 810 | |
| 621 | 811 | public function prepareParams(object $values): array |
| 622 | 812 | { |
| 813 | + //TODO problem with the types throughout the entire method | |
| 623 | 814 | if (!isset($values->lists)) { |
| 624 | 815 | $values->lists = 'none'; |
| 625 | 816 | } |
| 626 | 817 | if (!isset($values->listschecked)) { |
| @@ -632,13 +823,18 @@ | ||
| 632 | 823 | if (!isset($values->hiddenlists)) { |
| 633 | 824 | $values->hiddenlists = 'None'; |
| 634 | 825 | } |
| 635 | 826 | if (empty($values->fields)) { |
| 636 | - $values->fields = ['1', '2']; | |
| 827 | + $values->fields = [2]; | |
| 828 | + } elseif (is_string($values->fields)) { | |
| 829 | + $values->fields = explode(',', $values->fields); | |
| 637 | 830 | } |
| 638 | 831 | if (!in_array('2', $values->fields) && !in_array(2, $values->fields)) { |
| 639 | 832 | $values->fields[] = '2'; |
| 640 | 833 | } |
| 834 | + if (!isset($values->page_heading)) { | |
| 835 | + $values->page_heading = ''; | |
| 836 | + } | |
| 641 | 837 | if (!isset($values->introtext)) { |
| 642 | 838 | $values->introtext = ''; |
| 643 | 839 | } |
| 644 | 840 | if (!isset($values->posttext)) { |
| @@ -654,8 +850,9 @@ | ||
| 654 | 850 | if ((empty($values->lists) || in_array('None', $values->lists)) && (empty($values->hiddenlists) || strtolower(implode('', $values->hiddenlists)) == 'none')) { |
| 655 | 851 | $values->lists[] = 'All'; |
| 656 | 852 | } |
| 657 | 853 | |
| 854 | + // Get the current user and his subscription | |
| 658 | 855 | $userClass = new UserClass(); |
| 659 | 856 | $user = $userClass->identify(true); |
| 660 | 857 | if (empty($user)) { |
| 661 | 858 | $listClass = new ListClass(); |
| @@ -736,8 +933,9 @@ | ||
| 736 | 933 | } |
| 737 | 934 | $values->hiddenlists = $hiddenListsArray; |
| 738 | 935 | } |
| 739 | 936 | |
| 937 | + // Overriding the list with the URL parameters: &listid= for displayed list, &hiddenlist= for hidden lists | |
| 740 | 938 | $defaultSubscription = $subscription; |
| 741 | 939 | $forceLists = acym_getVar('string', 'listid', ''); |
| 742 | 940 | if (!empty($forceLists)) { |
| 743 | 941 | $subscription = []; |
| @@ -793,15 +991,15 @@ | ||
| 793 | 991 | } |
| 794 | 992 | |
| 795 | 993 | public function savechanges(): void |
| 796 | 994 | { |
| 797 | - acym_checkToken(); | |
| 995 | + wp_verify_nonce(acym_getVar('cmd', '_wpnonce'), 'acymnonce') || die('Invalid Token'); | |
| 798 | 996 | acym_checkRobots(); |
| 799 | 997 | |
| 800 | 998 | $userClass = new UserClass(); |
| 801 | 999 | |
| 802 | 1000 | |
| 803 | - $status = $userClass->saveForm(); | |
| 1001 | + $status = $userClass->saveForm(true); | |
| 804 | 1002 | if ($status) { |
| 805 | 1003 | if ($userClass->confirmationSentSuccess) { |
| 806 | 1004 | $this->displayMessage('ACYM_CONFIRMATION_SENT', true, 'success'); |
| 807 | 1005 | } elseif ($userClass->newUser) { |
| @@ -821,9 +1019,9 @@ | ||
| 821 | 1019 | } |
| 822 | 1020 | |
| 823 | 1021 | public function exportdata(): void |
| 824 | 1022 | { |
| 825 | - acym_checkToken(); | |
| 1023 | + wp_verify_nonce(acym_getVar('cmd', '_wpnonce'), 'acymnonce') || die('Invalid Token'); | |
| 826 | 1024 | |
| 827 | 1025 | $userClass = new UserClass(); |
| 828 | 1026 | $user = $userClass->identify(true, 'userId', 'userKey'); |
| 829 | 1027 | |
| @@ -831,14 +1029,42 @@ | ||
| 831 | 1029 | acym_redirect(acym_rootURI()); |
| 832 | 1030 | } |
| 833 | 1031 | |
| 834 | 1032 | $userHelper = new UserHelper(); |
| 835 | - $userHelper->exportdata((int)$user->id); | |
| 1033 | + $userData = $userHelper->getUserData($user); | |
| 1034 | + $exportData = []; | |
| 1035 | + foreach ($userData as $oneCategory) { | |
| 1036 | + if (!isset($exportData[$oneCategory['group_label']])) { | |
| 1037 | + $exportData[$oneCategory['group_label']] = []; | |
| 1038 | + } | |
| 1039 | + | |
| 1040 | + $exportData[$oneCategory['group_label']][] = $oneCategory['data']; | |
| 1041 | + } | |
| 1042 | + | |
| 1043 | + $exportFiles = [ | |
| 1044 | + [ | |
| 1045 | + 'name' => 'data.json', | |
| 1046 | + 'data' => json_encode($exportData), | |
| 1047 | + ], | |
| 1048 | + ]; | |
| 1049 | + | |
| 1050 | + $tempFolder = ACYM_MEDIA.'tmp'.DS; | |
| 1051 | + acym_createArchive($tempFolder.'export_data_user_'.$user->id, $exportFiles); | |
| 1052 | + | |
| 1053 | + $exportHelper = new ExportHelper(); | |
| 1054 | + $exportHelper->setDownloadHeaders('export_data_user_'.$user->id, 'zip'); | |
| 1055 | + // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_readfile -- Downloading a file, better than WP functions for memory handling. | |
| 1056 | + readfile($tempFolder.'export_data_user_'.$user->id.'.zip'); | |
| 1057 | + | |
| 1058 | + // Avoid issue when user cancels the download | |
| 1059 | + ignore_user_abort(true); | |
| 1060 | + acym_deleteFile($tempFolder.'export_data_user_'.$user->id.'.zip'); | |
| 1061 | + exit; | |
| 836 | 1062 | } |
| 837 | 1063 | |
| 838 | 1064 | public function gdprDelete(): void |
| 839 | 1065 | { |
| 840 | - acym_checkToken(); | |
| 1066 | + wp_verify_nonce(acym_getVar('cmd', '_wpnonce'), 'acymnonce') || die('Invalid Token'); | |
| 841 | 1067 | |
| 842 | 1068 | $userClass = new UserClass(); |
| 843 | 1069 | $user = $userClass->identify(true, 'userId', 'userKey'); |
| 844 | 1070 | if (empty($user->id)) { |
| @@ -845,29 +1071,31 @@ | ||
| 845 | 1071 | acym_redirect(acym_rootURI()); |
| 846 | 1072 | } |
| 847 | 1073 | |
| 848 | 1074 | $userClass->delete([$user->id], true); |
| 1075 | + | |
| 1076 | + acym_redirect(acym_rootURI(), 'ACYM_GDPR_DATA_DELETED'); | |
| 849 | 1077 | } |
| 850 | 1078 | |
| 851 | 1079 | public function ajaxGetEnqueuedMessages(): void |
| 852 | 1080 | { |
| 853 | - acym_session(); | |
| 854 | - | |
| 855 | 1081 | $output = ''; |
| 856 | 1082 | $types = ['success', 'info', 'warning', 'error']; |
| 857 | 1083 | foreach ($types as $type) { |
| 858 | - if (empty($_SESSION['acymessage'.$type])) continue; | |
| 1084 | + $messages = acym_getVar('array', 'acymessage'.$type, [], 'SESSION', ACYM_ALLOWHTML); | |
| 1085 | + if (empty($messages)) { | |
| 1086 | + continue; | |
| 1087 | + } | |
| 859 | 1088 | |
| 860 | - $messages = $_SESSION['acymessage'.$type]; | |
| 861 | 1089 | if (!is_array($messages)) { |
| 862 | 1090 | $messages = [$messages]; |
| 863 | 1091 | } |
| 864 | 1092 | |
| 865 | - $output .= '<div class="acym_callout acym__callout__front__'.$type.'" role="alert">'; | |
| 1093 | + $output .= '<div class="acym_callout acym__callout__front__'.esc_attr($type).'" role="alert">'; | |
| 866 | 1094 | $output .= '<div>'.implode(' ', $messages).'</div>'; |
| 867 | - $output .= '<button class="acym_callout_close" aria-label="'.acym_escape(acym_translation('ACYM_CLOSE_NOTIFICATION')).'">x</button></div>'; | |
| 1095 | + $output .= '<button class="acym_callout_close" aria-label="'.esc_attr(acym_translation('ACYM_CLOSE_NOTIFICATION')).'">x</button></div>'; | |
| 868 | 1096 | |
| 869 | - unset($_SESSION['acymessage'.$type]); | |
| 1097 | + acym_setSession('acymessage'.$type, null, true); | |
| 870 | 1098 | } |
| 871 | 1099 | |
| 872 | 1100 | if (!empty($output)) { |
| 873 | 1101 | $output = '<div id="acym__callout__container">'.$output.'</div>'; |