@@ -29,387 +29,387 @@ |
||
29 | 29 | */ |
30 | 30 | class SessionStartHandler |
31 | 31 | { |
32 | - const OPTION_NAME_SESSION_SAVE_HANDLER_STATUS = 'ee_session_save_handler_status'; |
|
33 | - |
|
34 | - const REQUEST_PARAM_RETRY_SESSION = 'ee_retry_session'; |
|
35 | - |
|
36 | - const SESSION_SAVE_HANDLER_STATUS_FAILED = 'session_save_handler_failed'; |
|
37 | - |
|
38 | - const SESSION_SAVE_HANDLER_STATUS_SUCCESS = 'session_save_handler_success'; |
|
39 | - |
|
40 | - const SESSION_SAVE_HANDLER_STATUS_UNKNOWN = 'session_save_handler_untested'; |
|
41 | - |
|
42 | - |
|
43 | - protected RequestInterface $request; |
|
44 | - |
|
45 | - |
|
46 | - /** |
|
47 | - * StartSession constructor. |
|
48 | - * |
|
49 | - * @param RequestInterface $request |
|
50 | - */ |
|
51 | - public function __construct(RequestInterface $request) |
|
52 | - { |
|
53 | - $this->request = $request; |
|
54 | - } |
|
55 | - |
|
56 | - |
|
57 | - /** |
|
58 | - * Check if a custom session save handler is in play |
|
59 | - * and attempt to start the PHP session |
|
60 | - * |
|
61 | - * @since 4.9.68.p |
|
62 | - */ |
|
63 | - public function startSession(): int |
|
64 | - { |
|
65 | - // check that session has started |
|
66 | - if (session_id() === '') { |
|
67 | - // clear any previous error |
|
68 | - error_clear_last(); |
|
69 | - |
|
70 | - // convert warnings to ErrorException so we can catch them |
|
71 | - $previous_handler = set_error_handler([$this, 'customErrorHandler'], E_WARNING); |
|
72 | - |
|
73 | - try { |
|
74 | - // starts a new session if one doesn't already exist, or re-initiates an existing one |
|
75 | - if ($this->hasKnownCustomSessionSaveHandler()) { |
|
76 | - $this->checkCustomSessionSaveHandler(); |
|
77 | - } else { |
|
78 | - $this->verifySessionSavePath(); |
|
79 | - $this->sessionStart(); |
|
80 | - } |
|
81 | - } catch (Throwable $error) { |
|
82 | - error_log( |
|
83 | - sprintf( |
|
84 | - '[SessionStartHandler] session_start() warning: %s in %s:%s', |
|
85 | - $error->getMessage(), |
|
86 | - $error->getFile(), |
|
87 | - $error->getLine() |
|
88 | - ) |
|
89 | - ); |
|
90 | - $this->displaySessionErrorNotice( |
|
91 | - $error->getMessage(), |
|
92 | - $error->getFile(), |
|
93 | - __FUNCTION__, |
|
94 | - $error->getLine() |
|
95 | - ); |
|
96 | - } finally { |
|
97 | - $this->restorePreviousErrorHandler($previous_handler); |
|
98 | - } |
|
99 | - } |
|
100 | - return session_status(); |
|
101 | - } |
|
102 | - |
|
103 | - |
|
104 | - /** |
|
105 | - * @return void |
|
106 | - * @throws Throwable |
|
107 | - * @since 5.0.46 |
|
108 | - */ |
|
109 | - public function sessionStart(): void |
|
110 | - { |
|
111 | - session_start(); |
|
112 | - session_write_close(); |
|
113 | - } |
|
114 | - |
|
115 | - |
|
116 | - /** |
|
117 | - * @return void |
|
118 | - * @throws ErrorException |
|
119 | - * @since 5.0.46 |
|
120 | - */ |
|
121 | - private function verifySessionSavePath(): void |
|
122 | - { |
|
123 | - $session_save_path = session_save_path() ?: ''; |
|
124 | - // Normalize "N;/path" style values |
|
125 | - if (strpos($session_save_path, ';') !== false) { |
|
126 | - $parts = explode(';', $session_save_path); |
|
127 | - $session_save_path = end($parts); |
|
128 | - } |
|
129 | - $session_save_path = trim((string) $session_save_path); |
|
130 | - if ($session_save_path === '') { |
|
131 | - // fall back to a sane temp dir if PHP reports no explicit session_save_path |
|
132 | - $session_save_path = sys_get_temp_dir(); |
|
133 | - } |
|
134 | - |
|
135 | - // use the real filesystem path |
|
136 | - $real_path = realpath($session_save_path) ?: $session_save_path; |
|
137 | - if (! is_dir($real_path) || ! is_writable($real_path)) { |
|
138 | - throw new ErrorException( |
|
139 | - sprintf( |
|
140 | - esc_html__('Invalid or missing session save path: %s', 'event_espresso'), |
|
141 | - $session_save_path |
|
142 | - ), |
|
143 | - 0, |
|
144 | - E_WARNING, |
|
145 | - __FILE__, |
|
146 | - __LINE__ |
|
147 | - ); |
|
148 | - } |
|
149 | - } |
|
150 | - |
|
151 | - |
|
152 | - /** |
|
153 | - * Returns `true` if the 'session.save_handler' ini setting matches a known custom handler |
|
154 | - * |
|
155 | - * @return bool |
|
156 | - * @since 4.9.68.p |
|
157 | - */ |
|
158 | - private function hasKnownCustomSessionSaveHandler(): bool |
|
159 | - { |
|
160 | - return strtolower((string) ini_get('session.save_handler')) === 'user'; |
|
161 | - } |
|
162 | - |
|
163 | - |
|
164 | - /** |
|
165 | - * Attempt to start the PHP session when a custom Session Save Handler is known to be set. |
|
166 | - * |
|
167 | - * @throws ErrorException |
|
168 | - * @throws Throwable |
|
169 | - * @since 4.9.68.p |
|
170 | - */ |
|
171 | - private function checkCustomSessionSaveHandler(): void |
|
172 | - { |
|
173 | - // If we've already successfully tested the session save handler |
|
174 | - // on a previous request then just start the session |
|
175 | - if ($this->sessionSaveHandlerIsValid()) { |
|
176 | - $this->sessionStart(); |
|
177 | - return; |
|
178 | - } |
|
179 | - // If not, then attempt to deal with any errors, |
|
180 | - // otherwise, try to hobble along without the session |
|
181 | - if (! $this->handleSessionSaveHandlerErrors()) { |
|
182 | - return; |
|
183 | - } |
|
184 | - // there is no record of a fatal error while trying to start the session |
|
185 | - // so let's see if there's a custom session save handler. Proceed with caution |
|
186 | - if ($this->initializeSessionSaveHandlerStatus() === false) { |
|
187 | - throw new ErrorException( |
|
188 | - esc_html__('Failed to initialize session save handler status', 'event_espresso'), |
|
189 | - 0, |
|
190 | - E_WARNING, |
|
191 | - __FILE__, |
|
192 | - __LINE__ |
|
193 | - ); |
|
194 | - } |
|
195 | - // hold your breath, the custom session save handler might cause a fatal here... |
|
196 | - $this->sessionStart(); |
|
197 | - // phew! we made it! the custom session handler is a-ok |
|
198 | - if ($this->setSessionSaveHandlerStatusToValid() === false) { |
|
199 | - throw new ErrorException( |
|
200 | - esc_html__('Failed to set session save handler status to valid', 'event_espresso'), |
|
201 | - 0, |
|
202 | - E_WARNING, |
|
203 | - __FILE__, |
|
204 | - __LINE__ |
|
205 | - ); |
|
206 | - } |
|
207 | - } |
|
208 | - |
|
209 | - |
|
210 | - /** |
|
211 | - * retrieves the value for the 'ee_session_save_handler_status' WP option. |
|
212 | - * default value = 'session_save_handler_untested' |
|
213 | - * |
|
214 | - * @return string |
|
215 | - * @since 4.9.68.p |
|
216 | - */ |
|
217 | - private function getSessionSaveHandlerStatus(): string |
|
218 | - { |
|
219 | - return get_option( |
|
220 | - SessionStartHandler::OPTION_NAME_SESSION_SAVE_HANDLER_STATUS, |
|
221 | - SessionStartHandler::SESSION_SAVE_HANDLER_STATUS_UNKNOWN |
|
222 | - ); |
|
223 | - } |
|
224 | - |
|
225 | - |
|
226 | - /** |
|
227 | - * Sets the 'ee_session_save_handler_status' WP option value to 'session_save_handler_failed' |
|
228 | - * which can then be upgraded is everything works correctly |
|
229 | - * |
|
230 | - * @return bool |
|
231 | - * @since 4.9.68.p |
|
232 | - */ |
|
233 | - private function initializeSessionSaveHandlerStatus(): bool |
|
234 | - { |
|
235 | - return update_option( |
|
236 | - SessionStartHandler::OPTION_NAME_SESSION_SAVE_HANDLER_STATUS, |
|
237 | - SessionStartHandler::SESSION_SAVE_HANDLER_STATUS_FAILED |
|
238 | - ); |
|
239 | - } |
|
240 | - |
|
241 | - |
|
242 | - /** |
|
243 | - * Sets the 'ee_session_save_handler_status' WP option value to 'session_save_handler_success' |
|
244 | - * |
|
245 | - * @return bool |
|
246 | - * @since 4.9.68.p |
|
247 | - */ |
|
248 | - private function setSessionSaveHandlerStatusToValid(): bool |
|
249 | - { |
|
250 | - return update_option( |
|
251 | - SessionStartHandler::OPTION_NAME_SESSION_SAVE_HANDLER_STATUS, |
|
252 | - SessionStartHandler::SESSION_SAVE_HANDLER_STATUS_SUCCESS |
|
253 | - ); |
|
254 | - } |
|
255 | - |
|
256 | - |
|
257 | - /** |
|
258 | - * Sets the 'ee_session_save_handler_status' WP option value to 'session_save_handler_untested' |
|
259 | - * |
|
260 | - * @return bool |
|
261 | - * @since 4.9.68.p |
|
262 | - */ |
|
263 | - private function resetSessionSaveHandlerStatus(): bool |
|
264 | - { |
|
265 | - return update_option( |
|
266 | - SessionStartHandler::OPTION_NAME_SESSION_SAVE_HANDLER_STATUS, |
|
267 | - SessionStartHandler::SESSION_SAVE_HANDLER_STATUS_UNKNOWN |
|
268 | - ); |
|
269 | - } |
|
270 | - |
|
271 | - |
|
272 | - /** |
|
273 | - * Returns `true` if the 'ee_session_save_handler_status' WP option value |
|
274 | - * is equal to 'session_save_handler_success' |
|
275 | - * |
|
276 | - * @return bool |
|
277 | - * @since 4.9.68.p |
|
278 | - */ |
|
279 | - private function sessionSaveHandlerIsValid(): bool |
|
280 | - { |
|
281 | - return $this->getSessionSaveHandlerStatus() === SessionStartHandler::SESSION_SAVE_HANDLER_STATUS_SUCCESS; |
|
282 | - } |
|
283 | - |
|
284 | - |
|
285 | - /** |
|
286 | - * Returns `true` if the 'ee_session_save_handler_status' WP option value |
|
287 | - * is equal to 'session_save_handler_failed' |
|
288 | - * |
|
289 | - * @return bool |
|
290 | - * @since 4.9.68.p |
|
291 | - */ |
|
292 | - private function sessionSaveHandlerFailed(): bool |
|
293 | - { |
|
294 | - return $this->getSessionSaveHandlerStatus() === SessionStartHandler::SESSION_SAVE_HANDLER_STATUS_FAILED; |
|
295 | - } |
|
296 | - |
|
297 | - |
|
298 | - /** |
|
299 | - * @param int $severity |
|
300 | - * @param string $message |
|
301 | - * @param string $file |
|
302 | - * @param int $line |
|
303 | - * @return bool |
|
304 | - * @throws ErrorException |
|
305 | - * @since 5.0.46 |
|
306 | - */ |
|
307 | - public function customErrorHandler(int $severity, string $message, string $file, int $line): bool |
|
308 | - { |
|
309 | - // Only convert warnings we care about |
|
310 | - if (($severity & E_WARNING) === E_WARNING) { |
|
311 | - throw new ErrorException($message, 0, $severity, $file, $line); |
|
312 | - } |
|
313 | - // fallback to PHP's normal handler for other severities |
|
314 | - return false; |
|
315 | - } |
|
316 | - |
|
317 | - |
|
318 | - /** |
|
319 | - * @param callable|null $previous_handler |
|
320 | - * @return void |
|
321 | - * @since 5.0.46 |
|
322 | - */ |
|
323 | - private function restorePreviousErrorHandler(?callable $previous_handler): void |
|
324 | - { |
|
325 | - if ($previous_handler !== null) { |
|
326 | - set_error_handler($previous_handler); |
|
327 | - } else { |
|
328 | - restore_error_handler(); |
|
329 | - } |
|
330 | - } |
|
331 | - |
|
332 | - |
|
333 | - /** |
|
334 | - * Returns `true` if no errors were detected with the session save handler, |
|
335 | - * otherwise attempts to work notify the appropriate authorities |
|
336 | - * with a suggestion for how to fix the issue, and returns `false`. |
|
337 | - * |
|
338 | - * @return bool |
|
339 | - * @throws ErrorException |
|
340 | - * @throws Throwable |
|
341 | - * @since 4.9.68.p |
|
342 | - */ |
|
343 | - private function handleSessionSaveHandlerErrors(): bool |
|
344 | - { |
|
345 | - // Check if we had a fatal error last time while trying to start the session |
|
346 | - if ($this->sessionSaveHandlerFailed()) { |
|
347 | - // apparently, last time we tried using the custom session save handler there was a fatal |
|
348 | - if ($this->request->requestParamIsSet(SessionStartHandler::REQUEST_PARAM_RETRY_SESSION)) { |
|
349 | - if ($this->resetSessionSaveHandlerStatus() === false) { |
|
350 | - throw new ErrorException( |
|
351 | - esc_html__('Failed to reset session save handler status', 'event_espresso'), |
|
352 | - 0, |
|
353 | - E_WARNING, |
|
354 | - __FILE__, |
|
355 | - __LINE__ |
|
356 | - ); |
|
357 | - } |
|
358 | - // remove "ee_retry_session", otherwise if the problem still isn't fixed, |
|
359 | - // we'll just keep getting the fatal error over and over. |
|
360 | - // Better to remove it and redirect, and try on the next request |
|
361 | - EEH_URL::safeRedirectAndExit( |
|
362 | - remove_query_arg( |
|
363 | - [SessionStartHandler::REQUEST_PARAM_RETRY_SESSION], |
|
364 | - EEH_URL::current_url() |
|
365 | - ) |
|
366 | - ); |
|
367 | - } |
|
368 | - // so the session is broken, don't try it again, |
|
369 | - // just show a message to users that can fix it |
|
370 | - $this->displaySessionSaveHandlerErrorNotice(); |
|
371 | - return false; |
|
372 | - } |
|
373 | - return true; |
|
374 | - } |
|
375 | - |
|
376 | - |
|
377 | - /** |
|
378 | - * @since 4.9.68.p |
|
379 | - */ |
|
380 | - private function displaySessionSaveHandlerErrorNotice(): void |
|
381 | - { |
|
382 | - $retry_session_url = add_query_arg( |
|
383 | - [SessionStartHandler::REQUEST_PARAM_RETRY_SESSION => true], |
|
384 | - EEH_URL::current_url() |
|
385 | - ); |
|
386 | - $this->displaySessionErrorNotice( |
|
387 | - sprintf( |
|
388 | - esc_html__( |
|
389 | - 'It appears there was a fatal error while starting the session, so Event Espresso is not able to process registrations normally. Some hosting companies, like Pantheon, require an extra plugin for Event Espresso to work. Please install the %1$sWordPress Native PHP Sessions plugin%2$s, then %3$sclick here to check if the problem is resolved.%2$s', |
|
390 | - 'event_espresso' |
|
391 | - ), |
|
392 | - '<a href="https://wordpress.org/plugins/wp-native-php-sessions/">', |
|
393 | - '</a>', |
|
394 | - '<a href="' . $retry_session_url . '">' |
|
395 | - ), |
|
396 | - __FILE__, |
|
397 | - __FUNCTION__, |
|
398 | - __LINE__ |
|
399 | - ); |
|
400 | - } |
|
401 | - |
|
402 | - |
|
403 | - /** |
|
404 | - * Generates an EE_Error notice regarding the current session woes |
|
405 | - * but only if the current user is an admin with permission to 'install_plugins'. |
|
406 | - * |
|
407 | - * @since 5.0.46 |
|
408 | - */ |
|
409 | - private function displaySessionErrorNotice(string $message, string $file, string $function, int $line): void |
|
410 | - { |
|
411 | - if (current_user_can('install_plugins')) { |
|
412 | - EE_Error::add_error($message, $file, $function, $line); |
|
413 | - } |
|
414 | - } |
|
32 | + const OPTION_NAME_SESSION_SAVE_HANDLER_STATUS = 'ee_session_save_handler_status'; |
|
33 | + |
|
34 | + const REQUEST_PARAM_RETRY_SESSION = 'ee_retry_session'; |
|
35 | + |
|
36 | + const SESSION_SAVE_HANDLER_STATUS_FAILED = 'session_save_handler_failed'; |
|
37 | + |
|
38 | + const SESSION_SAVE_HANDLER_STATUS_SUCCESS = 'session_save_handler_success'; |
|
39 | + |
|
40 | + const SESSION_SAVE_HANDLER_STATUS_UNKNOWN = 'session_save_handler_untested'; |
|
41 | + |
|
42 | + |
|
43 | + protected RequestInterface $request; |
|
44 | + |
|
45 | + |
|
46 | + /** |
|
47 | + * StartSession constructor. |
|
48 | + * |
|
49 | + * @param RequestInterface $request |
|
50 | + */ |
|
51 | + public function __construct(RequestInterface $request) |
|
52 | + { |
|
53 | + $this->request = $request; |
|
54 | + } |
|
55 | + |
|
56 | + |
|
57 | + /** |
|
58 | + * Check if a custom session save handler is in play |
|
59 | + * and attempt to start the PHP session |
|
60 | + * |
|
61 | + * @since 4.9.68.p |
|
62 | + */ |
|
63 | + public function startSession(): int |
|
64 | + { |
|
65 | + // check that session has started |
|
66 | + if (session_id() === '') { |
|
67 | + // clear any previous error |
|
68 | + error_clear_last(); |
|
69 | + |
|
70 | + // convert warnings to ErrorException so we can catch them |
|
71 | + $previous_handler = set_error_handler([$this, 'customErrorHandler'], E_WARNING); |
|
72 | + |
|
73 | + try { |
|
74 | + // starts a new session if one doesn't already exist, or re-initiates an existing one |
|
75 | + if ($this->hasKnownCustomSessionSaveHandler()) { |
|
76 | + $this->checkCustomSessionSaveHandler(); |
|
77 | + } else { |
|
78 | + $this->verifySessionSavePath(); |
|
79 | + $this->sessionStart(); |
|
80 | + } |
|
81 | + } catch (Throwable $error) { |
|
82 | + error_log( |
|
83 | + sprintf( |
|
84 | + '[SessionStartHandler] session_start() warning: %s in %s:%s', |
|
85 | + $error->getMessage(), |
|
86 | + $error->getFile(), |
|
87 | + $error->getLine() |
|
88 | + ) |
|
89 | + ); |
|
90 | + $this->displaySessionErrorNotice( |
|
91 | + $error->getMessage(), |
|
92 | + $error->getFile(), |
|
93 | + __FUNCTION__, |
|
94 | + $error->getLine() |
|
95 | + ); |
|
96 | + } finally { |
|
97 | + $this->restorePreviousErrorHandler($previous_handler); |
|
98 | + } |
|
99 | + } |
|
100 | + return session_status(); |
|
101 | + } |
|
102 | + |
|
103 | + |
|
104 | + /** |
|
105 | + * @return void |
|
106 | + * @throws Throwable |
|
107 | + * @since 5.0.46 |
|
108 | + */ |
|
109 | + public function sessionStart(): void |
|
110 | + { |
|
111 | + session_start(); |
|
112 | + session_write_close(); |
|
113 | + } |
|
114 | + |
|
115 | + |
|
116 | + /** |
|
117 | + * @return void |
|
118 | + * @throws ErrorException |
|
119 | + * @since 5.0.46 |
|
120 | + */ |
|
121 | + private function verifySessionSavePath(): void |
|
122 | + { |
|
123 | + $session_save_path = session_save_path() ?: ''; |
|
124 | + // Normalize "N;/path" style values |
|
125 | + if (strpos($session_save_path, ';') !== false) { |
|
126 | + $parts = explode(';', $session_save_path); |
|
127 | + $session_save_path = end($parts); |
|
128 | + } |
|
129 | + $session_save_path = trim((string) $session_save_path); |
|
130 | + if ($session_save_path === '') { |
|
131 | + // fall back to a sane temp dir if PHP reports no explicit session_save_path |
|
132 | + $session_save_path = sys_get_temp_dir(); |
|
133 | + } |
|
134 | + |
|
135 | + // use the real filesystem path |
|
136 | + $real_path = realpath($session_save_path) ?: $session_save_path; |
|
137 | + if (! is_dir($real_path) || ! is_writable($real_path)) { |
|
138 | + throw new ErrorException( |
|
139 | + sprintf( |
|
140 | + esc_html__('Invalid or missing session save path: %s', 'event_espresso'), |
|
141 | + $session_save_path |
|
142 | + ), |
|
143 | + 0, |
|
144 | + E_WARNING, |
|
145 | + __FILE__, |
|
146 | + __LINE__ |
|
147 | + ); |
|
148 | + } |
|
149 | + } |
|
150 | + |
|
151 | + |
|
152 | + /** |
|
153 | + * Returns `true` if the 'session.save_handler' ini setting matches a known custom handler |
|
154 | + * |
|
155 | + * @return bool |
|
156 | + * @since 4.9.68.p |
|
157 | + */ |
|
158 | + private function hasKnownCustomSessionSaveHandler(): bool |
|
159 | + { |
|
160 | + return strtolower((string) ini_get('session.save_handler')) === 'user'; |
|
161 | + } |
|
162 | + |
|
163 | + |
|
164 | + /** |
|
165 | + * Attempt to start the PHP session when a custom Session Save Handler is known to be set. |
|
166 | + * |
|
167 | + * @throws ErrorException |
|
168 | + * @throws Throwable |
|
169 | + * @since 4.9.68.p |
|
170 | + */ |
|
171 | + private function checkCustomSessionSaveHandler(): void |
|
172 | + { |
|
173 | + // If we've already successfully tested the session save handler |
|
174 | + // on a previous request then just start the session |
|
175 | + if ($this->sessionSaveHandlerIsValid()) { |
|
176 | + $this->sessionStart(); |
|
177 | + return; |
|
178 | + } |
|
179 | + // If not, then attempt to deal with any errors, |
|
180 | + // otherwise, try to hobble along without the session |
|
181 | + if (! $this->handleSessionSaveHandlerErrors()) { |
|
182 | + return; |
|
183 | + } |
|
184 | + // there is no record of a fatal error while trying to start the session |
|
185 | + // so let's see if there's a custom session save handler. Proceed with caution |
|
186 | + if ($this->initializeSessionSaveHandlerStatus() === false) { |
|
187 | + throw new ErrorException( |
|
188 | + esc_html__('Failed to initialize session save handler status', 'event_espresso'), |
|
189 | + 0, |
|
190 | + E_WARNING, |
|
191 | + __FILE__, |
|
192 | + __LINE__ |
|
193 | + ); |
|
194 | + } |
|
195 | + // hold your breath, the custom session save handler might cause a fatal here... |
|
196 | + $this->sessionStart(); |
|
197 | + // phew! we made it! the custom session handler is a-ok |
|
198 | + if ($this->setSessionSaveHandlerStatusToValid() === false) { |
|
199 | + throw new ErrorException( |
|
200 | + esc_html__('Failed to set session save handler status to valid', 'event_espresso'), |
|
201 | + 0, |
|
202 | + E_WARNING, |
|
203 | + __FILE__, |
|
204 | + __LINE__ |
|
205 | + ); |
|
206 | + } |
|
207 | + } |
|
208 | + |
|
209 | + |
|
210 | + /** |
|
211 | + * retrieves the value for the 'ee_session_save_handler_status' WP option. |
|
212 | + * default value = 'session_save_handler_untested' |
|
213 | + * |
|
214 | + * @return string |
|
215 | + * @since 4.9.68.p |
|
216 | + */ |
|
217 | + private function getSessionSaveHandlerStatus(): string |
|
218 | + { |
|
219 | + return get_option( |
|
220 | + SessionStartHandler::OPTION_NAME_SESSION_SAVE_HANDLER_STATUS, |
|
221 | + SessionStartHandler::SESSION_SAVE_HANDLER_STATUS_UNKNOWN |
|
222 | + ); |
|
223 | + } |
|
224 | + |
|
225 | + |
|
226 | + /** |
|
227 | + * Sets the 'ee_session_save_handler_status' WP option value to 'session_save_handler_failed' |
|
228 | + * which can then be upgraded is everything works correctly |
|
229 | + * |
|
230 | + * @return bool |
|
231 | + * @since 4.9.68.p |
|
232 | + */ |
|
233 | + private function initializeSessionSaveHandlerStatus(): bool |
|
234 | + { |
|
235 | + return update_option( |
|
236 | + SessionStartHandler::OPTION_NAME_SESSION_SAVE_HANDLER_STATUS, |
|
237 | + SessionStartHandler::SESSION_SAVE_HANDLER_STATUS_FAILED |
|
238 | + ); |
|
239 | + } |
|
240 | + |
|
241 | + |
|
242 | + /** |
|
243 | + * Sets the 'ee_session_save_handler_status' WP option value to 'session_save_handler_success' |
|
244 | + * |
|
245 | + * @return bool |
|
246 | + * @since 4.9.68.p |
|
247 | + */ |
|
248 | + private function setSessionSaveHandlerStatusToValid(): bool |
|
249 | + { |
|
250 | + return update_option( |
|
251 | + SessionStartHandler::OPTION_NAME_SESSION_SAVE_HANDLER_STATUS, |
|
252 | + SessionStartHandler::SESSION_SAVE_HANDLER_STATUS_SUCCESS |
|
253 | + ); |
|
254 | + } |
|
255 | + |
|
256 | + |
|
257 | + /** |
|
258 | + * Sets the 'ee_session_save_handler_status' WP option value to 'session_save_handler_untested' |
|
259 | + * |
|
260 | + * @return bool |
|
261 | + * @since 4.9.68.p |
|
262 | + */ |
|
263 | + private function resetSessionSaveHandlerStatus(): bool |
|
264 | + { |
|
265 | + return update_option( |
|
266 | + SessionStartHandler::OPTION_NAME_SESSION_SAVE_HANDLER_STATUS, |
|
267 | + SessionStartHandler::SESSION_SAVE_HANDLER_STATUS_UNKNOWN |
|
268 | + ); |
|
269 | + } |
|
270 | + |
|
271 | + |
|
272 | + /** |
|
273 | + * Returns `true` if the 'ee_session_save_handler_status' WP option value |
|
274 | + * is equal to 'session_save_handler_success' |
|
275 | + * |
|
276 | + * @return bool |
|
277 | + * @since 4.9.68.p |
|
278 | + */ |
|
279 | + private function sessionSaveHandlerIsValid(): bool |
|
280 | + { |
|
281 | + return $this->getSessionSaveHandlerStatus() === SessionStartHandler::SESSION_SAVE_HANDLER_STATUS_SUCCESS; |
|
282 | + } |
|
283 | + |
|
284 | + |
|
285 | + /** |
|
286 | + * Returns `true` if the 'ee_session_save_handler_status' WP option value |
|
287 | + * is equal to 'session_save_handler_failed' |
|
288 | + * |
|
289 | + * @return bool |
|
290 | + * @since 4.9.68.p |
|
291 | + */ |
|
292 | + private function sessionSaveHandlerFailed(): bool |
|
293 | + { |
|
294 | + return $this->getSessionSaveHandlerStatus() === SessionStartHandler::SESSION_SAVE_HANDLER_STATUS_FAILED; |
|
295 | + } |
|
296 | + |
|
297 | + |
|
298 | + /** |
|
299 | + * @param int $severity |
|
300 | + * @param string $message |
|
301 | + * @param string $file |
|
302 | + * @param int $line |
|
303 | + * @return bool |
|
304 | + * @throws ErrorException |
|
305 | + * @since 5.0.46 |
|
306 | + */ |
|
307 | + public function customErrorHandler(int $severity, string $message, string $file, int $line): bool |
|
308 | + { |
|
309 | + // Only convert warnings we care about |
|
310 | + if (($severity & E_WARNING) === E_WARNING) { |
|
311 | + throw new ErrorException($message, 0, $severity, $file, $line); |
|
312 | + } |
|
313 | + // fallback to PHP's normal handler for other severities |
|
314 | + return false; |
|
315 | + } |
|
316 | + |
|
317 | + |
|
318 | + /** |
|
319 | + * @param callable|null $previous_handler |
|
320 | + * @return void |
|
321 | + * @since 5.0.46 |
|
322 | + */ |
|
323 | + private function restorePreviousErrorHandler(?callable $previous_handler): void |
|
324 | + { |
|
325 | + if ($previous_handler !== null) { |
|
326 | + set_error_handler($previous_handler); |
|
327 | + } else { |
|
328 | + restore_error_handler(); |
|
329 | + } |
|
330 | + } |
|
331 | + |
|
332 | + |
|
333 | + /** |
|
334 | + * Returns `true` if no errors were detected with the session save handler, |
|
335 | + * otherwise attempts to work notify the appropriate authorities |
|
336 | + * with a suggestion for how to fix the issue, and returns `false`. |
|
337 | + * |
|
338 | + * @return bool |
|
339 | + * @throws ErrorException |
|
340 | + * @throws Throwable |
|
341 | + * @since 4.9.68.p |
|
342 | + */ |
|
343 | + private function handleSessionSaveHandlerErrors(): bool |
|
344 | + { |
|
345 | + // Check if we had a fatal error last time while trying to start the session |
|
346 | + if ($this->sessionSaveHandlerFailed()) { |
|
347 | + // apparently, last time we tried using the custom session save handler there was a fatal |
|
348 | + if ($this->request->requestParamIsSet(SessionStartHandler::REQUEST_PARAM_RETRY_SESSION)) { |
|
349 | + if ($this->resetSessionSaveHandlerStatus() === false) { |
|
350 | + throw new ErrorException( |
|
351 | + esc_html__('Failed to reset session save handler status', 'event_espresso'), |
|
352 | + 0, |
|
353 | + E_WARNING, |
|
354 | + __FILE__, |
|
355 | + __LINE__ |
|
356 | + ); |
|
357 | + } |
|
358 | + // remove "ee_retry_session", otherwise if the problem still isn't fixed, |
|
359 | + // we'll just keep getting the fatal error over and over. |
|
360 | + // Better to remove it and redirect, and try on the next request |
|
361 | + EEH_URL::safeRedirectAndExit( |
|
362 | + remove_query_arg( |
|
363 | + [SessionStartHandler::REQUEST_PARAM_RETRY_SESSION], |
|
364 | + EEH_URL::current_url() |
|
365 | + ) |
|
366 | + ); |
|
367 | + } |
|
368 | + // so the session is broken, don't try it again, |
|
369 | + // just show a message to users that can fix it |
|
370 | + $this->displaySessionSaveHandlerErrorNotice(); |
|
371 | + return false; |
|
372 | + } |
|
373 | + return true; |
|
374 | + } |
|
375 | + |
|
376 | + |
|
377 | + /** |
|
378 | + * @since 4.9.68.p |
|
379 | + */ |
|
380 | + private function displaySessionSaveHandlerErrorNotice(): void |
|
381 | + { |
|
382 | + $retry_session_url = add_query_arg( |
|
383 | + [SessionStartHandler::REQUEST_PARAM_RETRY_SESSION => true], |
|
384 | + EEH_URL::current_url() |
|
385 | + ); |
|
386 | + $this->displaySessionErrorNotice( |
|
387 | + sprintf( |
|
388 | + esc_html__( |
|
389 | + 'It appears there was a fatal error while starting the session, so Event Espresso is not able to process registrations normally. Some hosting companies, like Pantheon, require an extra plugin for Event Espresso to work. Please install the %1$sWordPress Native PHP Sessions plugin%2$s, then %3$sclick here to check if the problem is resolved.%2$s', |
|
390 | + 'event_espresso' |
|
391 | + ), |
|
392 | + '<a href="https://wordpress.org/plugins/wp-native-php-sessions/">', |
|
393 | + '</a>', |
|
394 | + '<a href="' . $retry_session_url . '">' |
|
395 | + ), |
|
396 | + __FILE__, |
|
397 | + __FUNCTION__, |
|
398 | + __LINE__ |
|
399 | + ); |
|
400 | + } |
|
401 | + |
|
402 | + |
|
403 | + /** |
|
404 | + * Generates an EE_Error notice regarding the current session woes |
|
405 | + * but only if the current user is an admin with permission to 'install_plugins'. |
|
406 | + * |
|
407 | + * @since 5.0.46 |
|
408 | + */ |
|
409 | + private function displaySessionErrorNotice(string $message, string $file, string $function, int $line): void |
|
410 | + { |
|
411 | + if (current_user_can('install_plugins')) { |
|
412 | + EE_Error::add_error($message, $file, $function, $line); |
|
413 | + } |
|
414 | + } |
|
415 | 415 | } |
@@ -134,7 +134,7 @@ discard block |
||
134 | 134 | |
135 | 135 | // use the real filesystem path |
136 | 136 | $real_path = realpath($session_save_path) ?: $session_save_path; |
137 | - if (! is_dir($real_path) || ! is_writable($real_path)) { |
|
137 | + if ( ! is_dir($real_path) || ! is_writable($real_path)) { |
|
138 | 138 | throw new ErrorException( |
139 | 139 | sprintf( |
140 | 140 | esc_html__('Invalid or missing session save path: %s', 'event_espresso'), |
@@ -178,7 +178,7 @@ discard block |
||
178 | 178 | } |
179 | 179 | // If not, then attempt to deal with any errors, |
180 | 180 | // otherwise, try to hobble along without the session |
181 | - if (! $this->handleSessionSaveHandlerErrors()) { |
|
181 | + if ( ! $this->handleSessionSaveHandlerErrors()) { |
|
182 | 182 | return; |
183 | 183 | } |
184 | 184 | // there is no record of a fatal error while trying to start the session |
@@ -391,7 +391,7 @@ discard block |
||
391 | 391 | ), |
392 | 392 | '<a href="https://wordpress.org/plugins/wp-native-php-sessions/">', |
393 | 393 | '</a>', |
394 | - '<a href="' . $retry_session_url . '">' |
|
394 | + '<a href="'.$retry_session_url.'">' |
|
395 | 395 | ), |
396 | 396 | __FILE__, |
397 | 397 | __FUNCTION__, |
@@ -12,189 +12,189 @@ |
||
12 | 12 | */ |
13 | 13 | class EE_Newsletter_message_type extends EE_message_type |
14 | 14 | { |
15 | - public function __construct() |
|
16 | - { |
|
17 | - $this->name = 'newsletter'; |
|
18 | - $this->description = esc_html__( |
|
19 | - 'Batch message type messages are triggered manually by the admin for sending notifications to a selected group of recipients. This should only be used for more general notification type messages that contain information specific for the recipients. For "newsletter" type messages we recommend using an email list service like MailChimp, because sending non-related mail-outs to contacts increases the risk of your site domain getting added to spam lists, which will prevent messages getting to users.', |
|
20 | - 'event_espresso' |
|
21 | - ); |
|
22 | - $this->label = [ |
|
23 | - 'singular' => esc_html__('batch', 'event_espresso'), |
|
24 | - 'plural' => esc_html__('batches', 'event_espresso'), |
|
25 | - ]; |
|
26 | - $this->_master_templates = [ |
|
27 | - 'email' => 'registration', |
|
28 | - ]; |
|
29 | - |
|
30 | - parent::__construct(); |
|
31 | - } |
|
32 | - |
|
33 | - |
|
34 | - /** |
|
35 | - * Sets admin_registered_pages property |
|
36 | - */ |
|
37 | - protected function _set_admin_pages() |
|
38 | - { |
|
39 | - $this->admin_registered_pages = []; // no admin pages to register this with. |
|
40 | - } |
|
41 | - |
|
42 | - |
|
43 | - /** |
|
44 | - * Sets property related to data handler. |
|
45 | - */ |
|
46 | - protected function _set_data_handler() |
|
47 | - { |
|
48 | - $this->_data_handler = 'Registrations'; |
|
49 | - $this->_single_message = $this->_data instanceof EE_Registration; |
|
50 | - } |
|
51 | - |
|
52 | - |
|
53 | - /** |
|
54 | - * Returns the data for the given context for this message type. |
|
55 | - * |
|
56 | - * @param string $context |
|
57 | - * @param EE_Registration $registration |
|
58 | - * @param int $id |
|
59 | - * @return array |
|
60 | - */ |
|
61 | - protected function _get_data_for_context($context, EE_Registration $registration, $id) |
|
62 | - { |
|
63 | - // newsletter message type data handler is 'Registrations' and it expects an array of EE_Registration objects. |
|
64 | - return [$registration]; |
|
65 | - } |
|
66 | - |
|
67 | - |
|
68 | - /** |
|
69 | - * Sets the admin settings fields property for this message type. |
|
70 | - */ |
|
71 | - protected function _set_admin_settings_fields() |
|
72 | - { |
|
73 | - $this->_admin_settings_fields = []; |
|
74 | - } |
|
75 | - |
|
76 | - |
|
77 | - /** |
|
78 | - * Sets the contexts for this message type. |
|
79 | - */ |
|
80 | - protected function _set_contexts() |
|
81 | - { |
|
82 | - $this->_context_label = [ |
|
83 | - 'label' => esc_html__('recipient', 'event_espresso'), |
|
84 | - 'plural' => esc_html__('recipients', 'event_espresso'), |
|
85 | - 'description' => esc_html__('Recipient\'s are who will receive the message.', 'event_espresso'), |
|
86 | - ]; |
|
87 | - |
|
88 | - $this->_contexts = [ |
|
89 | - 'attendee' => [ |
|
90 | - 'label' => esc_html__('Registrant', 'event_espresso'), |
|
91 | - 'description' => esc_html__('This template goes to selected registrants.', 'event_espresso'), |
|
92 | - ], |
|
93 | - ]; |
|
94 | - } |
|
95 | - |
|
96 | - |
|
97 | - /** |
|
98 | - * used to set the valid shortcodes. |
|
99 | - * For the newsletter message type we only have two valid shortcode libraries in use, recipient details and |
|
100 | - * organization. That's it! |
|
101 | - * |
|
102 | - * @return void |
|
103 | - * @since 4.3.0 |
|
104 | - */ |
|
105 | - protected function _set_valid_shortcodes() |
|
106 | - { |
|
107 | - parent::_set_valid_shortcodes(); |
|
108 | - |
|
109 | - $included_shortcodes = [ |
|
110 | - 'recipient_details', |
|
111 | - 'organization', |
|
112 | - 'newsletter', |
|
113 | - ]; |
|
114 | - |
|
115 | - foreach ($this->_valid_shortcodes as $context => $shortcodes) { |
|
116 | - foreach ($shortcodes as $key => $shortcode) { |
|
117 | - if (! in_array($shortcode, $included_shortcodes, true)) { |
|
118 | - unset($this->_valid_shortcodes[ $context ][ $key ]); |
|
119 | - } |
|
120 | - } |
|
121 | - $this->_valid_shortcodes[ $context ][] = 'newsletter'; |
|
122 | - } |
|
123 | - } |
|
124 | - |
|
125 | - |
|
126 | - /** |
|
127 | - * Override default _attendee_addressees in EE_message_type because we want to loop through the registrations |
|
128 | - * for EE_message_type. |
|
129 | - * |
|
130 | - * @return array |
|
131 | - * @throws EE_Error |
|
132 | - * @throws ReflectionException |
|
133 | - */ |
|
134 | - protected function _attendee_addressees() |
|
135 | - { |
|
136 | - $addressee = []; |
|
137 | - |
|
138 | - // looping through registrations |
|
139 | - foreach ($this->_data->registrations as $details) { |
|
140 | - // set $attendee array to blank on each loop |
|
141 | - $aee = []; |
|
142 | - |
|
143 | - // need to get the attendee from this registration. |
|
144 | - $attendee = isset($details['att_obj']) && $details['att_obj'] instanceof EE_Attendee |
|
145 | - ? $details['att_obj'] |
|
146 | - : null; |
|
147 | - |
|
148 | - if (! $attendee instanceof EE_Attendee) { |
|
149 | - continue; |
|
150 | - } |
|
151 | - |
|
152 | - // set $aee from attendee object |
|
153 | - $aee['att_obj'] = $attendee; |
|
154 | - $aee['reg_objs'] = isset($this->_data->attendees[ $attendee->ID() ]['reg_objs']) |
|
155 | - ? $this->_data->attendees[ $attendee->ID() ]['reg_objs'] |
|
156 | - : []; |
|
157 | - $aee['attendee_email'] = $attendee->email(); |
|
158 | - $aee['tkt_objs'] = isset($this->_data->attendees[ $attendee->ID() ]['tkt_objs']) |
|
159 | - ? $this->_data->attendees[ $attendee->ID() ]['tkt_objs'] |
|
160 | - : []; |
|
161 | - |
|
162 | - if (isset($this->_data->attendees[ $attendee->ID() ]['evt_objs'])) { |
|
163 | - $aee['evt_objs'] = $this->_data->attendees[ $attendee->ID() ]['evt_objs']; |
|
164 | - $aee['events'] = $this->_data->attendees[ $attendee->ID() ]['evt_objs']; |
|
165 | - } else { |
|
166 | - $aee['evt_objs'] = $aee['events'] = []; |
|
167 | - } |
|
168 | - |
|
169 | - $aee['reg_obj'] = $details['reg_obj'] ?? null; |
|
170 | - $aee['attendees'] = $this->_data->attendees; |
|
171 | - |
|
172 | - // merge in the primary attendee data |
|
173 | - $aee = array_merge($this->_default_addressee_data, $aee); |
|
174 | - |
|
175 | - // make sure txn is set |
|
176 | - if (empty($aee['txn']) && $aee['reg_obj'] instanceof EE_Registration) { |
|
177 | - $aee['txn'] = $aee['reg_obj']->transaction(); |
|
178 | - } |
|
179 | - |
|
180 | - $addressee[] = new EE_Messages_Addressee($aee); |
|
181 | - } |
|
182 | - return $addressee; |
|
183 | - } |
|
184 | - |
|
185 | - |
|
186 | - /** |
|
187 | - * Allows a message type to specifically exclude template fields for the provided messenger. |
|
188 | - * Filtered so this can be programmatically altered as well. |
|
189 | - * |
|
190 | - * @param string $messenger_name name of messenger |
|
191 | - * @return array |
|
192 | - */ |
|
193 | - public function excludedFieldsForMessenger($messenger_name) |
|
194 | - { |
|
195 | - $excluded_fields = [ |
|
196 | - 'email' => ['cc'], |
|
197 | - ]; |
|
198 | - return $excluded_fields[ $messenger_name ] ?? parent::excludedFieldsForMessenger($messenger_name); |
|
199 | - } |
|
15 | + public function __construct() |
|
16 | + { |
|
17 | + $this->name = 'newsletter'; |
|
18 | + $this->description = esc_html__( |
|
19 | + 'Batch message type messages are triggered manually by the admin for sending notifications to a selected group of recipients. This should only be used for more general notification type messages that contain information specific for the recipients. For "newsletter" type messages we recommend using an email list service like MailChimp, because sending non-related mail-outs to contacts increases the risk of your site domain getting added to spam lists, which will prevent messages getting to users.', |
|
20 | + 'event_espresso' |
|
21 | + ); |
|
22 | + $this->label = [ |
|
23 | + 'singular' => esc_html__('batch', 'event_espresso'), |
|
24 | + 'plural' => esc_html__('batches', 'event_espresso'), |
|
25 | + ]; |
|
26 | + $this->_master_templates = [ |
|
27 | + 'email' => 'registration', |
|
28 | + ]; |
|
29 | + |
|
30 | + parent::__construct(); |
|
31 | + } |
|
32 | + |
|
33 | + |
|
34 | + /** |
|
35 | + * Sets admin_registered_pages property |
|
36 | + */ |
|
37 | + protected function _set_admin_pages() |
|
38 | + { |
|
39 | + $this->admin_registered_pages = []; // no admin pages to register this with. |
|
40 | + } |
|
41 | + |
|
42 | + |
|
43 | + /** |
|
44 | + * Sets property related to data handler. |
|
45 | + */ |
|
46 | + protected function _set_data_handler() |
|
47 | + { |
|
48 | + $this->_data_handler = 'Registrations'; |
|
49 | + $this->_single_message = $this->_data instanceof EE_Registration; |
|
50 | + } |
|
51 | + |
|
52 | + |
|
53 | + /** |
|
54 | + * Returns the data for the given context for this message type. |
|
55 | + * |
|
56 | + * @param string $context |
|
57 | + * @param EE_Registration $registration |
|
58 | + * @param int $id |
|
59 | + * @return array |
|
60 | + */ |
|
61 | + protected function _get_data_for_context($context, EE_Registration $registration, $id) |
|
62 | + { |
|
63 | + // newsletter message type data handler is 'Registrations' and it expects an array of EE_Registration objects. |
|
64 | + return [$registration]; |
|
65 | + } |
|
66 | + |
|
67 | + |
|
68 | + /** |
|
69 | + * Sets the admin settings fields property for this message type. |
|
70 | + */ |
|
71 | + protected function _set_admin_settings_fields() |
|
72 | + { |
|
73 | + $this->_admin_settings_fields = []; |
|
74 | + } |
|
75 | + |
|
76 | + |
|
77 | + /** |
|
78 | + * Sets the contexts for this message type. |
|
79 | + */ |
|
80 | + protected function _set_contexts() |
|
81 | + { |
|
82 | + $this->_context_label = [ |
|
83 | + 'label' => esc_html__('recipient', 'event_espresso'), |
|
84 | + 'plural' => esc_html__('recipients', 'event_espresso'), |
|
85 | + 'description' => esc_html__('Recipient\'s are who will receive the message.', 'event_espresso'), |
|
86 | + ]; |
|
87 | + |
|
88 | + $this->_contexts = [ |
|
89 | + 'attendee' => [ |
|
90 | + 'label' => esc_html__('Registrant', 'event_espresso'), |
|
91 | + 'description' => esc_html__('This template goes to selected registrants.', 'event_espresso'), |
|
92 | + ], |
|
93 | + ]; |
|
94 | + } |
|
95 | + |
|
96 | + |
|
97 | + /** |
|
98 | + * used to set the valid shortcodes. |
|
99 | + * For the newsletter message type we only have two valid shortcode libraries in use, recipient details and |
|
100 | + * organization. That's it! |
|
101 | + * |
|
102 | + * @return void |
|
103 | + * @since 4.3.0 |
|
104 | + */ |
|
105 | + protected function _set_valid_shortcodes() |
|
106 | + { |
|
107 | + parent::_set_valid_shortcodes(); |
|
108 | + |
|
109 | + $included_shortcodes = [ |
|
110 | + 'recipient_details', |
|
111 | + 'organization', |
|
112 | + 'newsletter', |
|
113 | + ]; |
|
114 | + |
|
115 | + foreach ($this->_valid_shortcodes as $context => $shortcodes) { |
|
116 | + foreach ($shortcodes as $key => $shortcode) { |
|
117 | + if (! in_array($shortcode, $included_shortcodes, true)) { |
|
118 | + unset($this->_valid_shortcodes[ $context ][ $key ]); |
|
119 | + } |
|
120 | + } |
|
121 | + $this->_valid_shortcodes[ $context ][] = 'newsletter'; |
|
122 | + } |
|
123 | + } |
|
124 | + |
|
125 | + |
|
126 | + /** |
|
127 | + * Override default _attendee_addressees in EE_message_type because we want to loop through the registrations |
|
128 | + * for EE_message_type. |
|
129 | + * |
|
130 | + * @return array |
|
131 | + * @throws EE_Error |
|
132 | + * @throws ReflectionException |
|
133 | + */ |
|
134 | + protected function _attendee_addressees() |
|
135 | + { |
|
136 | + $addressee = []; |
|
137 | + |
|
138 | + // looping through registrations |
|
139 | + foreach ($this->_data->registrations as $details) { |
|
140 | + // set $attendee array to blank on each loop |
|
141 | + $aee = []; |
|
142 | + |
|
143 | + // need to get the attendee from this registration. |
|
144 | + $attendee = isset($details['att_obj']) && $details['att_obj'] instanceof EE_Attendee |
|
145 | + ? $details['att_obj'] |
|
146 | + : null; |
|
147 | + |
|
148 | + if (! $attendee instanceof EE_Attendee) { |
|
149 | + continue; |
|
150 | + } |
|
151 | + |
|
152 | + // set $aee from attendee object |
|
153 | + $aee['att_obj'] = $attendee; |
|
154 | + $aee['reg_objs'] = isset($this->_data->attendees[ $attendee->ID() ]['reg_objs']) |
|
155 | + ? $this->_data->attendees[ $attendee->ID() ]['reg_objs'] |
|
156 | + : []; |
|
157 | + $aee['attendee_email'] = $attendee->email(); |
|
158 | + $aee['tkt_objs'] = isset($this->_data->attendees[ $attendee->ID() ]['tkt_objs']) |
|
159 | + ? $this->_data->attendees[ $attendee->ID() ]['tkt_objs'] |
|
160 | + : []; |
|
161 | + |
|
162 | + if (isset($this->_data->attendees[ $attendee->ID() ]['evt_objs'])) { |
|
163 | + $aee['evt_objs'] = $this->_data->attendees[ $attendee->ID() ]['evt_objs']; |
|
164 | + $aee['events'] = $this->_data->attendees[ $attendee->ID() ]['evt_objs']; |
|
165 | + } else { |
|
166 | + $aee['evt_objs'] = $aee['events'] = []; |
|
167 | + } |
|
168 | + |
|
169 | + $aee['reg_obj'] = $details['reg_obj'] ?? null; |
|
170 | + $aee['attendees'] = $this->_data->attendees; |
|
171 | + |
|
172 | + // merge in the primary attendee data |
|
173 | + $aee = array_merge($this->_default_addressee_data, $aee); |
|
174 | + |
|
175 | + // make sure txn is set |
|
176 | + if (empty($aee['txn']) && $aee['reg_obj'] instanceof EE_Registration) { |
|
177 | + $aee['txn'] = $aee['reg_obj']->transaction(); |
|
178 | + } |
|
179 | + |
|
180 | + $addressee[] = new EE_Messages_Addressee($aee); |
|
181 | + } |
|
182 | + return $addressee; |
|
183 | + } |
|
184 | + |
|
185 | + |
|
186 | + /** |
|
187 | + * Allows a message type to specifically exclude template fields for the provided messenger. |
|
188 | + * Filtered so this can be programmatically altered as well. |
|
189 | + * |
|
190 | + * @param string $messenger_name name of messenger |
|
191 | + * @return array |
|
192 | + */ |
|
193 | + public function excludedFieldsForMessenger($messenger_name) |
|
194 | + { |
|
195 | + $excluded_fields = [ |
|
196 | + 'email' => ['cc'], |
|
197 | + ]; |
|
198 | + return $excluded_fields[ $messenger_name ] ?? parent::excludedFieldsForMessenger($messenger_name); |
|
199 | + } |
|
200 | 200 | } |
@@ -19,7 +19,7 @@ discard block |
||
19 | 19 | 'Batch message type messages are triggered manually by the admin for sending notifications to a selected group of recipients. This should only be used for more general notification type messages that contain information specific for the recipients. For "newsletter" type messages we recommend using an email list service like MailChimp, because sending non-related mail-outs to contacts increases the risk of your site domain getting added to spam lists, which will prevent messages getting to users.', |
20 | 20 | 'event_espresso' |
21 | 21 | ); |
22 | - $this->label = [ |
|
22 | + $this->label = [ |
|
23 | 23 | 'singular' => esc_html__('batch', 'event_espresso'), |
24 | 24 | 'plural' => esc_html__('batches', 'event_espresso'), |
25 | 25 | ]; |
@@ -114,11 +114,11 @@ discard block |
||
114 | 114 | |
115 | 115 | foreach ($this->_valid_shortcodes as $context => $shortcodes) { |
116 | 116 | foreach ($shortcodes as $key => $shortcode) { |
117 | - if (! in_array($shortcode, $included_shortcodes, true)) { |
|
118 | - unset($this->_valid_shortcodes[ $context ][ $key ]); |
|
117 | + if ( ! in_array($shortcode, $included_shortcodes, true)) { |
|
118 | + unset($this->_valid_shortcodes[$context][$key]); |
|
119 | 119 | } |
120 | 120 | } |
121 | - $this->_valid_shortcodes[ $context ][] = 'newsletter'; |
|
121 | + $this->_valid_shortcodes[$context][] = 'newsletter'; |
|
122 | 122 | } |
123 | 123 | } |
124 | 124 | |
@@ -145,23 +145,23 @@ discard block |
||
145 | 145 | ? $details['att_obj'] |
146 | 146 | : null; |
147 | 147 | |
148 | - if (! $attendee instanceof EE_Attendee) { |
|
148 | + if ( ! $attendee instanceof EE_Attendee) { |
|
149 | 149 | continue; |
150 | 150 | } |
151 | 151 | |
152 | 152 | // set $aee from attendee object |
153 | 153 | $aee['att_obj'] = $attendee; |
154 | - $aee['reg_objs'] = isset($this->_data->attendees[ $attendee->ID() ]['reg_objs']) |
|
155 | - ? $this->_data->attendees[ $attendee->ID() ]['reg_objs'] |
|
154 | + $aee['reg_objs'] = isset($this->_data->attendees[$attendee->ID()]['reg_objs']) |
|
155 | + ? $this->_data->attendees[$attendee->ID()]['reg_objs'] |
|
156 | 156 | : []; |
157 | 157 | $aee['attendee_email'] = $attendee->email(); |
158 | - $aee['tkt_objs'] = isset($this->_data->attendees[ $attendee->ID() ]['tkt_objs']) |
|
159 | - ? $this->_data->attendees[ $attendee->ID() ]['tkt_objs'] |
|
158 | + $aee['tkt_objs'] = isset($this->_data->attendees[$attendee->ID()]['tkt_objs']) |
|
159 | + ? $this->_data->attendees[$attendee->ID()]['tkt_objs'] |
|
160 | 160 | : []; |
161 | 161 | |
162 | - if (isset($this->_data->attendees[ $attendee->ID() ]['evt_objs'])) { |
|
163 | - $aee['evt_objs'] = $this->_data->attendees[ $attendee->ID() ]['evt_objs']; |
|
164 | - $aee['events'] = $this->_data->attendees[ $attendee->ID() ]['evt_objs']; |
|
162 | + if (isset($this->_data->attendees[$attendee->ID()]['evt_objs'])) { |
|
163 | + $aee['evt_objs'] = $this->_data->attendees[$attendee->ID()]['evt_objs']; |
|
164 | + $aee['events'] = $this->_data->attendees[$attendee->ID()]['evt_objs']; |
|
165 | 165 | } else { |
166 | 166 | $aee['evt_objs'] = $aee['events'] = []; |
167 | 167 | } |
@@ -195,6 +195,6 @@ discard block |
||
195 | 195 | $excluded_fields = [ |
196 | 196 | 'email' => ['cc'], |
197 | 197 | ]; |
198 | - return $excluded_fields[ $messenger_name ] ?? parent::excludedFieldsForMessenger($messenger_name); |
|
198 | + return $excluded_fields[$messenger_name] ?? parent::excludedFieldsForMessenger($messenger_name); |
|
199 | 199 | } |
200 | 200 | } |