@@ -19,381 +19,381 @@ |
||
19 | 19 | class TransientCacheStorage implements CacheStorageInterface |
20 | 20 | { |
21 | 21 | |
22 | - /** |
|
23 | - * wp-option option_name for tracking transients |
|
24 | - * |
|
25 | - * @type string |
|
26 | - */ |
|
27 | - const TRANSIENT_SCHEDULE_OPTIONS_KEY = 'ee_transient_schedule'; |
|
28 | - |
|
29 | - /** |
|
30 | - * @var int $current_time |
|
31 | - */ |
|
32 | - private $current_time; |
|
33 | - |
|
34 | - /** |
|
35 | - * how often to perform transient cleanup |
|
36 | - * |
|
37 | - * @var string $transient_cleanup_frequency |
|
38 | - */ |
|
39 | - private $transient_cleanup_frequency; |
|
40 | - |
|
41 | - /** |
|
42 | - * options for how often to perform transient cleanup |
|
43 | - * |
|
44 | - * @var array $transient_cleanup_frequency_options |
|
45 | - */ |
|
46 | - private $transient_cleanup_frequency_options = array(); |
|
47 | - |
|
48 | - /** |
|
49 | - * @var array $transients |
|
50 | - */ |
|
51 | - private $transients; |
|
52 | - |
|
53 | - |
|
54 | - |
|
55 | - /** |
|
56 | - * TransientCacheStorage constructor. |
|
57 | - */ |
|
58 | - public function __construct() |
|
59 | - { |
|
60 | - $this->transient_cleanup_frequency = $this->setTransientCleanupFrequency(); |
|
61 | - // round current time down to closest 5 minutes to simplify scheduling |
|
62 | - $this->current_time = $this->roundTimestamp(time(), '5-minutes', false); |
|
63 | - $this->transients = (array)get_option(TransientCacheStorage::TRANSIENT_SCHEDULE_OPTIONS_KEY, array()); |
|
64 | - if ( ! (defined('DOING_AJAX') && DOING_AJAX) && $this->transient_cleanup_frequency !== 'off') { |
|
65 | - add_action('shutdown', array($this, 'checkTransientCleanupSchedule'), 999); |
|
66 | - } |
|
67 | - } |
|
68 | - |
|
69 | - |
|
70 | - |
|
71 | - /** |
|
72 | - * Sets how often transient cleanup occurs |
|
73 | - * |
|
74 | - * @return string |
|
75 | - */ |
|
76 | - private function setTransientCleanupFrequency() |
|
77 | - { |
|
78 | - // sets how often transients are cleaned up |
|
79 | - $this->transient_cleanup_frequency_options = apply_filters( |
|
80 | - 'FHEE__TransientCacheStorage__transient_cleanup_schedule_options', |
|
81 | - array( |
|
82 | - 'off', |
|
83 | - '15-minutes', |
|
84 | - 'hour', |
|
85 | - '12-hours', |
|
86 | - 'day', |
|
87 | - ) |
|
88 | - ); |
|
89 | - $transient_cleanup_frequency = apply_filters( |
|
90 | - 'FHEE__TransientCacheStorage__transient_cleanup_schedule', |
|
91 | - 'hour' |
|
92 | - ); |
|
93 | - return in_array( |
|
94 | - $transient_cleanup_frequency, |
|
95 | - $this->transient_cleanup_frequency_options, |
|
96 | - true |
|
97 | - ) |
|
98 | - ? $transient_cleanup_frequency |
|
99 | - : 'hour'; |
|
100 | - } |
|
101 | - |
|
102 | - |
|
103 | - |
|
104 | - /** |
|
105 | - * we need to be able to round timestamps off to match the set transient cleanup frequency |
|
106 | - * so if a transient is set to expire at 1:17 pm for example, and our cleanup schedule is every hour, |
|
107 | - * then that timestamp needs to be rounded up to 2:00 pm so that it is removed |
|
108 | - * during the next scheduled cleanup after its expiration. |
|
109 | - * We also round off the current time timestamp to the closest 5 minutes |
|
110 | - * just to make the timestamps a little easier to round which helps with debugging. |
|
111 | - * |
|
112 | - * @param int $timestamp [required] |
|
113 | - * @param string $cleanup_frequency |
|
114 | - * @param bool $round_up |
|
115 | - * @return int |
|
116 | - */ |
|
117 | - private function roundTimestamp($timestamp, $cleanup_frequency = 'hour', $round_up = true) |
|
118 | - { |
|
119 | - $cleanup_frequency = $cleanup_frequency ? $cleanup_frequency : $this->transient_cleanup_frequency; |
|
120 | - // in order to round the time to the closest xx minutes (or hours), |
|
121 | - // we take the minutes (or hours) portion of the timestamp and divide it by xx, |
|
122 | - // round down to a whole number, then multiply by xx to bring us almost back up to where we were |
|
123 | - // why round down ? so the minutes (or hours) don't go over 60 (or 24) |
|
124 | - // and bump the hour, which could bump the day, which could bump the month, etc, |
|
125 | - // which would be bad because we don't always want to round up, |
|
126 | - // but when we do we can easily achieve that by simply adding the desired offset, |
|
127 | - $minutes = '00'; |
|
128 | - $hours = 'H'; |
|
129 | - switch ($cleanup_frequency) { |
|
130 | - case '5-minutes' : |
|
131 | - $minutes = floor((int)date('i', $timestamp) / 5) * 5; |
|
132 | - $minutes = str_pad($minutes, 2, '0', STR_PAD_LEFT); |
|
133 | - $offset = MINUTE_IN_SECONDS * 5; |
|
134 | - break; |
|
135 | - case '15-minutes' : |
|
136 | - $minutes = floor((int)date('i', $timestamp) / 15) * 15; |
|
137 | - $minutes = str_pad($minutes, 2, '0', STR_PAD_LEFT); |
|
138 | - $offset = MINUTE_IN_SECONDS * 15; |
|
139 | - break; |
|
140 | - case '12-hours' : |
|
141 | - $hours = floor((int)date('H', $timestamp) / 12) * 12; |
|
142 | - $hours = str_pad($hours, 2, '0', STR_PAD_LEFT); |
|
143 | - $offset = HOUR_IN_SECONDS * 12; |
|
144 | - break; |
|
145 | - case 'day' : |
|
146 | - $hours = '03'; // run cleanup at 3:00 am (or first site hit after that) |
|
147 | - $offset = DAY_IN_SECONDS; |
|
148 | - break; |
|
149 | - case 'hour' : |
|
150 | - default : |
|
151 | - $offset = HOUR_IN_SECONDS; |
|
152 | - break; |
|
153 | - } |
|
154 | - $rounded_timestamp = (int) strtotime(date("Y-m-d {$hours}:{$minutes}:00", $timestamp)); |
|
155 | - $rounded_timestamp += $round_up ? $offset : 0; |
|
156 | - return apply_filters( |
|
157 | - 'FHEE__TransientCacheStorage__roundTimestamp__timestamp', |
|
158 | - $rounded_timestamp, |
|
159 | - $timestamp, |
|
160 | - $cleanup_frequency, |
|
161 | - $round_up |
|
162 | - ); |
|
163 | - } |
|
164 | - |
|
165 | - |
|
166 | - |
|
167 | - /** |
|
168 | - * Saves supplied data to a transient |
|
169 | - * if an expiration is set, then it automatically schedules the transient for cleanup |
|
170 | - * |
|
171 | - * @param string $transient_key [required] |
|
172 | - * @param string $data [required] |
|
173 | - * @param int $expiration number of seconds until the cache expires |
|
174 | - * @return bool |
|
175 | - */ |
|
176 | - public function add($transient_key, $data, $expiration = 0) |
|
177 | - { |
|
178 | - $expiration = (int)abs($expiration); |
|
179 | - $saved = set_transient($transient_key, $data, $expiration); |
|
180 | - if ($saved && $expiration) { |
|
181 | - $this->scheduleTransientCleanup($transient_key, $expiration); |
|
182 | - } |
|
183 | - return $saved; |
|
184 | - } |
|
185 | - |
|
186 | - |
|
187 | - |
|
188 | - /** |
|
189 | - * retrieves transient data |
|
190 | - * automatically triggers early cache refresh for standard cache items |
|
191 | - * in order to avoid cache stampedes on busy sites. |
|
192 | - * For non-standard cache items like PHP Session data where early refreshing is not wanted, |
|
193 | - * the $standard_cache parameter should be set to false when retrieving data |
|
194 | - * |
|
195 | - * @param string $transient_key [required] |
|
196 | - * @param bool $standard_cache |
|
197 | - * @return mixed|null |
|
198 | - */ |
|
199 | - public function get($transient_key, $standard_cache = true) |
|
200 | - { |
|
201 | - if (isset($this->transients[ $transient_key ])) { |
|
202 | - // to avoid cache stampedes (AKA:dogpiles) for standard cache items, |
|
203 | - // check if known cache expires within the next minute, |
|
204 | - // and if so, remove it from our tracking and and return nothing. |
|
205 | - // this should trigger the cache content to be regenerated during this request, |
|
206 | - // while allowing any following requests to still access the existing cache |
|
207 | - // until it gets replaced with the refreshed content |
|
208 | - if ( |
|
209 | - $standard_cache |
|
210 | - && $this->transients[$transient_key] - time() <= MINUTE_IN_SECONDS |
|
211 | - ) { |
|
212 | - unset($this->transients[$transient_key]); |
|
213 | - $this->updateTransients(); |
|
214 | - return null; |
|
215 | - } |
|
216 | - |
|
217 | - // for non standard cache items, remove the key from our tracking, |
|
218 | - // but proceed to retrieve the transient so that it also gets removed from the db |
|
219 | - if ($this->transients[$transient_key] <= time()) { |
|
220 | - unset($this->transients[$transient_key]); |
|
221 | - $this->updateTransients(); |
|
222 | - } |
|
223 | - } |
|
224 | - |
|
225 | - $content = get_transient($transient_key); |
|
226 | - return $content !== false ? $content : null; |
|
227 | - } |
|
228 | - |
|
229 | - |
|
230 | - |
|
231 | - /** |
|
232 | - * delete a single transient and remove tracking |
|
233 | - * |
|
234 | - * @param string $transient_key [required] full or partial transient key to be deleted |
|
235 | - */ |
|
236 | - public function delete($transient_key) |
|
237 | - { |
|
238 | - $this->deleteMany(array($transient_key)); |
|
239 | - } |
|
240 | - |
|
241 | - |
|
242 | - |
|
243 | - /** |
|
244 | - * delete multiple transients and remove tracking |
|
245 | - * |
|
246 | - * @param array $transient_keys [required] array of full or partial transient keys to be deleted |
|
247 | - * @param bool $force_delete [optional] if true, then will not check incoming keys against those being tracked |
|
248 | - * and proceed directly to deleting those entries from the cache storage |
|
249 | - */ |
|
250 | - public function deleteMany(array $transient_keys, $force_delete = false) |
|
251 | - { |
|
252 | - $full_transient_keys = $force_delete ? $transient_keys : array(); |
|
253 | - if(empty($full_transient_keys)){ |
|
254 | - foreach ($this->transients as $transient_key => $expiration) { |
|
255 | - foreach ($transient_keys as $transient_key_to_delete) { |
|
256 | - if (strpos($transient_key, $transient_key_to_delete) !== false) { |
|
257 | - $full_transient_keys[] = $transient_key; |
|
258 | - } |
|
259 | - } |
|
260 | - } |
|
261 | - } |
|
262 | - if ($this->deleteTransientKeys($full_transient_keys)) { |
|
263 | - $this->updateTransients(); |
|
264 | - } |
|
265 | - } |
|
266 | - |
|
267 | - |
|
268 | - |
|
269 | - /** |
|
270 | - * sorts transients numerically by timestamp |
|
271 | - * then saves the transient schedule to a WP option |
|
272 | - */ |
|
273 | - private function updateTransients() |
|
274 | - { |
|
275 | - asort($this->transients, SORT_NUMERIC); |
|
276 | - update_option( |
|
277 | - TransientCacheStorage::TRANSIENT_SCHEDULE_OPTIONS_KEY, |
|
278 | - $this->transients |
|
279 | - ); |
|
280 | - } |
|
281 | - |
|
282 | - |
|
283 | - |
|
284 | - /** |
|
285 | - * schedules a transient for cleanup by adding it to the transient tracking |
|
286 | - * |
|
287 | - * @param string $transient_key [required] |
|
288 | - * @param int $expiration [required] |
|
289 | - */ |
|
290 | - private function scheduleTransientCleanup($transient_key, $expiration) |
|
291 | - { |
|
292 | - // make sure a valid future timestamp is set |
|
293 | - $expiration += $expiration < time() ? time() : 0; |
|
294 | - // and round to the closest 15 minutes |
|
295 | - $expiration = $this->roundTimestamp($expiration); |
|
296 | - // save transients to clear using their ID as the key to avoid duplicates |
|
297 | - $this->transients[$transient_key] = $expiration; |
|
298 | - $this->updateTransients(); |
|
299 | - } |
|
300 | - |
|
301 | - |
|
302 | - |
|
303 | - /** |
|
304 | - * Since our tracked transients are sorted by their timestamps |
|
305 | - * we can grab the first transient and see when it is scheduled for cleanup. |
|
306 | - * If that timestamp is less than or equal to the current time, |
|
307 | - * then cleanup is triggered |
|
308 | - */ |
|
309 | - public function checkTransientCleanupSchedule() |
|
310 | - { |
|
311 | - if (empty($this->transients)) { |
|
312 | - return; |
|
313 | - } |
|
314 | - // when do we run the next cleanup job? |
|
315 | - reset($this->transients); |
|
316 | - $next_scheduled_cleanup = current($this->transients); |
|
317 | - // if the next cleanup job is scheduled for the current hour |
|
318 | - if ($next_scheduled_cleanup <= $this->current_time) { |
|
319 | - if ($this->cleanupExpiredTransients()) { |
|
320 | - $this->updateTransients(); |
|
321 | - } |
|
322 | - } |
|
323 | - } |
|
324 | - |
|
325 | - |
|
326 | - |
|
327 | - /** |
|
328 | - * loops through the array of tracked transients, |
|
329 | - * compiles a list of those that have expired, and sends that list off for deletion. |
|
330 | - * Also removes any bad records from the transients array |
|
331 | - * |
|
332 | - * @return bool |
|
333 | - */ |
|
334 | - private function cleanupExpiredTransients() |
|
335 | - { |
|
336 | - $update = false; |
|
337 | - // filter the query limit. Set to 0 to turn off garbage collection |
|
338 | - $limit = (int)abs( |
|
339 | - apply_filters( |
|
340 | - 'FHEE__TransientCacheStorage__clearExpiredTransients__limit', |
|
341 | - 50 |
|
342 | - ) |
|
343 | - ); |
|
344 | - // non-zero LIMIT means take out the trash |
|
345 | - if ($limit) { |
|
346 | - $transient_keys = array(); |
|
347 | - foreach ($this->transients as $transient_key => $expiration) { |
|
348 | - if ($expiration > $this->current_time) { |
|
349 | - continue; |
|
350 | - } |
|
351 | - if ( ! $expiration || ! $transient_key) { |
|
352 | - unset($this->transients[$transient_key]); |
|
353 | - $update = true; |
|
354 | - continue; |
|
355 | - } |
|
356 | - $transient_keys[] = $transient_key; |
|
357 | - } |
|
358 | - // delete expired keys, but maintain value of $update if nothing is deleted |
|
359 | - $update = $this->deleteTransientKeys($transient_keys, $limit) ? true : $update; |
|
360 | - do_action( 'FHEE__TransientCacheStorage__clearExpiredTransients__end', $this); |
|
361 | - } |
|
362 | - return $update; |
|
363 | - } |
|
364 | - |
|
365 | - |
|
366 | - |
|
367 | - /** |
|
368 | - * calls delete_transient() on each transient key provided, up to the specified limit |
|
369 | - * |
|
370 | - * @param array $transient_keys [required] |
|
371 | - * @param int $limit |
|
372 | - * @return bool |
|
373 | - */ |
|
374 | - private function deleteTransientKeys(array $transient_keys, $limit = 50) |
|
375 | - { |
|
376 | - if (empty($transient_keys)) { |
|
377 | - return false; |
|
378 | - } |
|
379 | - $counter = 0; |
|
380 | - foreach ($transient_keys as $transient_key) { |
|
381 | - if($counter === $limit){ |
|
382 | - break; |
|
383 | - } |
|
384 | - // remove any transient prefixes |
|
385 | - $transient_key = strpos($transient_key, '_transient_timeout_') === 0 |
|
386 | - ? str_replace('_transient_timeout_', '', $transient_key) |
|
387 | - : $transient_key; |
|
388 | - $transient_key = strpos($transient_key, '_transient_') === 0 |
|
389 | - ? str_replace('_transient_', '', $transient_key) |
|
390 | - : $transient_key; |
|
391 | - delete_transient($transient_key); |
|
392 | - unset($this->transients[$transient_key]); |
|
393 | - $counter++; |
|
394 | - } |
|
395 | - return $counter > 0; |
|
396 | - } |
|
22 | + /** |
|
23 | + * wp-option option_name for tracking transients |
|
24 | + * |
|
25 | + * @type string |
|
26 | + */ |
|
27 | + const TRANSIENT_SCHEDULE_OPTIONS_KEY = 'ee_transient_schedule'; |
|
28 | + |
|
29 | + /** |
|
30 | + * @var int $current_time |
|
31 | + */ |
|
32 | + private $current_time; |
|
33 | + |
|
34 | + /** |
|
35 | + * how often to perform transient cleanup |
|
36 | + * |
|
37 | + * @var string $transient_cleanup_frequency |
|
38 | + */ |
|
39 | + private $transient_cleanup_frequency; |
|
40 | + |
|
41 | + /** |
|
42 | + * options for how often to perform transient cleanup |
|
43 | + * |
|
44 | + * @var array $transient_cleanup_frequency_options |
|
45 | + */ |
|
46 | + private $transient_cleanup_frequency_options = array(); |
|
47 | + |
|
48 | + /** |
|
49 | + * @var array $transients |
|
50 | + */ |
|
51 | + private $transients; |
|
52 | + |
|
53 | + |
|
54 | + |
|
55 | + /** |
|
56 | + * TransientCacheStorage constructor. |
|
57 | + */ |
|
58 | + public function __construct() |
|
59 | + { |
|
60 | + $this->transient_cleanup_frequency = $this->setTransientCleanupFrequency(); |
|
61 | + // round current time down to closest 5 minutes to simplify scheduling |
|
62 | + $this->current_time = $this->roundTimestamp(time(), '5-minutes', false); |
|
63 | + $this->transients = (array)get_option(TransientCacheStorage::TRANSIENT_SCHEDULE_OPTIONS_KEY, array()); |
|
64 | + if ( ! (defined('DOING_AJAX') && DOING_AJAX) && $this->transient_cleanup_frequency !== 'off') { |
|
65 | + add_action('shutdown', array($this, 'checkTransientCleanupSchedule'), 999); |
|
66 | + } |
|
67 | + } |
|
68 | + |
|
69 | + |
|
70 | + |
|
71 | + /** |
|
72 | + * Sets how often transient cleanup occurs |
|
73 | + * |
|
74 | + * @return string |
|
75 | + */ |
|
76 | + private function setTransientCleanupFrequency() |
|
77 | + { |
|
78 | + // sets how often transients are cleaned up |
|
79 | + $this->transient_cleanup_frequency_options = apply_filters( |
|
80 | + 'FHEE__TransientCacheStorage__transient_cleanup_schedule_options', |
|
81 | + array( |
|
82 | + 'off', |
|
83 | + '15-minutes', |
|
84 | + 'hour', |
|
85 | + '12-hours', |
|
86 | + 'day', |
|
87 | + ) |
|
88 | + ); |
|
89 | + $transient_cleanup_frequency = apply_filters( |
|
90 | + 'FHEE__TransientCacheStorage__transient_cleanup_schedule', |
|
91 | + 'hour' |
|
92 | + ); |
|
93 | + return in_array( |
|
94 | + $transient_cleanup_frequency, |
|
95 | + $this->transient_cleanup_frequency_options, |
|
96 | + true |
|
97 | + ) |
|
98 | + ? $transient_cleanup_frequency |
|
99 | + : 'hour'; |
|
100 | + } |
|
101 | + |
|
102 | + |
|
103 | + |
|
104 | + /** |
|
105 | + * we need to be able to round timestamps off to match the set transient cleanup frequency |
|
106 | + * so if a transient is set to expire at 1:17 pm for example, and our cleanup schedule is every hour, |
|
107 | + * then that timestamp needs to be rounded up to 2:00 pm so that it is removed |
|
108 | + * during the next scheduled cleanup after its expiration. |
|
109 | + * We also round off the current time timestamp to the closest 5 minutes |
|
110 | + * just to make the timestamps a little easier to round which helps with debugging. |
|
111 | + * |
|
112 | + * @param int $timestamp [required] |
|
113 | + * @param string $cleanup_frequency |
|
114 | + * @param bool $round_up |
|
115 | + * @return int |
|
116 | + */ |
|
117 | + private function roundTimestamp($timestamp, $cleanup_frequency = 'hour', $round_up = true) |
|
118 | + { |
|
119 | + $cleanup_frequency = $cleanup_frequency ? $cleanup_frequency : $this->transient_cleanup_frequency; |
|
120 | + // in order to round the time to the closest xx minutes (or hours), |
|
121 | + // we take the minutes (or hours) portion of the timestamp and divide it by xx, |
|
122 | + // round down to a whole number, then multiply by xx to bring us almost back up to where we were |
|
123 | + // why round down ? so the minutes (or hours) don't go over 60 (or 24) |
|
124 | + // and bump the hour, which could bump the day, which could bump the month, etc, |
|
125 | + // which would be bad because we don't always want to round up, |
|
126 | + // but when we do we can easily achieve that by simply adding the desired offset, |
|
127 | + $minutes = '00'; |
|
128 | + $hours = 'H'; |
|
129 | + switch ($cleanup_frequency) { |
|
130 | + case '5-minutes' : |
|
131 | + $minutes = floor((int)date('i', $timestamp) / 5) * 5; |
|
132 | + $minutes = str_pad($minutes, 2, '0', STR_PAD_LEFT); |
|
133 | + $offset = MINUTE_IN_SECONDS * 5; |
|
134 | + break; |
|
135 | + case '15-minutes' : |
|
136 | + $minutes = floor((int)date('i', $timestamp) / 15) * 15; |
|
137 | + $minutes = str_pad($minutes, 2, '0', STR_PAD_LEFT); |
|
138 | + $offset = MINUTE_IN_SECONDS * 15; |
|
139 | + break; |
|
140 | + case '12-hours' : |
|
141 | + $hours = floor((int)date('H', $timestamp) / 12) * 12; |
|
142 | + $hours = str_pad($hours, 2, '0', STR_PAD_LEFT); |
|
143 | + $offset = HOUR_IN_SECONDS * 12; |
|
144 | + break; |
|
145 | + case 'day' : |
|
146 | + $hours = '03'; // run cleanup at 3:00 am (or first site hit after that) |
|
147 | + $offset = DAY_IN_SECONDS; |
|
148 | + break; |
|
149 | + case 'hour' : |
|
150 | + default : |
|
151 | + $offset = HOUR_IN_SECONDS; |
|
152 | + break; |
|
153 | + } |
|
154 | + $rounded_timestamp = (int) strtotime(date("Y-m-d {$hours}:{$minutes}:00", $timestamp)); |
|
155 | + $rounded_timestamp += $round_up ? $offset : 0; |
|
156 | + return apply_filters( |
|
157 | + 'FHEE__TransientCacheStorage__roundTimestamp__timestamp', |
|
158 | + $rounded_timestamp, |
|
159 | + $timestamp, |
|
160 | + $cleanup_frequency, |
|
161 | + $round_up |
|
162 | + ); |
|
163 | + } |
|
164 | + |
|
165 | + |
|
166 | + |
|
167 | + /** |
|
168 | + * Saves supplied data to a transient |
|
169 | + * if an expiration is set, then it automatically schedules the transient for cleanup |
|
170 | + * |
|
171 | + * @param string $transient_key [required] |
|
172 | + * @param string $data [required] |
|
173 | + * @param int $expiration number of seconds until the cache expires |
|
174 | + * @return bool |
|
175 | + */ |
|
176 | + public function add($transient_key, $data, $expiration = 0) |
|
177 | + { |
|
178 | + $expiration = (int)abs($expiration); |
|
179 | + $saved = set_transient($transient_key, $data, $expiration); |
|
180 | + if ($saved && $expiration) { |
|
181 | + $this->scheduleTransientCleanup($transient_key, $expiration); |
|
182 | + } |
|
183 | + return $saved; |
|
184 | + } |
|
185 | + |
|
186 | + |
|
187 | + |
|
188 | + /** |
|
189 | + * retrieves transient data |
|
190 | + * automatically triggers early cache refresh for standard cache items |
|
191 | + * in order to avoid cache stampedes on busy sites. |
|
192 | + * For non-standard cache items like PHP Session data where early refreshing is not wanted, |
|
193 | + * the $standard_cache parameter should be set to false when retrieving data |
|
194 | + * |
|
195 | + * @param string $transient_key [required] |
|
196 | + * @param bool $standard_cache |
|
197 | + * @return mixed|null |
|
198 | + */ |
|
199 | + public function get($transient_key, $standard_cache = true) |
|
200 | + { |
|
201 | + if (isset($this->transients[ $transient_key ])) { |
|
202 | + // to avoid cache stampedes (AKA:dogpiles) for standard cache items, |
|
203 | + // check if known cache expires within the next minute, |
|
204 | + // and if so, remove it from our tracking and and return nothing. |
|
205 | + // this should trigger the cache content to be regenerated during this request, |
|
206 | + // while allowing any following requests to still access the existing cache |
|
207 | + // until it gets replaced with the refreshed content |
|
208 | + if ( |
|
209 | + $standard_cache |
|
210 | + && $this->transients[$transient_key] - time() <= MINUTE_IN_SECONDS |
|
211 | + ) { |
|
212 | + unset($this->transients[$transient_key]); |
|
213 | + $this->updateTransients(); |
|
214 | + return null; |
|
215 | + } |
|
216 | + |
|
217 | + // for non standard cache items, remove the key from our tracking, |
|
218 | + // but proceed to retrieve the transient so that it also gets removed from the db |
|
219 | + if ($this->transients[$transient_key] <= time()) { |
|
220 | + unset($this->transients[$transient_key]); |
|
221 | + $this->updateTransients(); |
|
222 | + } |
|
223 | + } |
|
224 | + |
|
225 | + $content = get_transient($transient_key); |
|
226 | + return $content !== false ? $content : null; |
|
227 | + } |
|
228 | + |
|
229 | + |
|
230 | + |
|
231 | + /** |
|
232 | + * delete a single transient and remove tracking |
|
233 | + * |
|
234 | + * @param string $transient_key [required] full or partial transient key to be deleted |
|
235 | + */ |
|
236 | + public function delete($transient_key) |
|
237 | + { |
|
238 | + $this->deleteMany(array($transient_key)); |
|
239 | + } |
|
240 | + |
|
241 | + |
|
242 | + |
|
243 | + /** |
|
244 | + * delete multiple transients and remove tracking |
|
245 | + * |
|
246 | + * @param array $transient_keys [required] array of full or partial transient keys to be deleted |
|
247 | + * @param bool $force_delete [optional] if true, then will not check incoming keys against those being tracked |
|
248 | + * and proceed directly to deleting those entries from the cache storage |
|
249 | + */ |
|
250 | + public function deleteMany(array $transient_keys, $force_delete = false) |
|
251 | + { |
|
252 | + $full_transient_keys = $force_delete ? $transient_keys : array(); |
|
253 | + if(empty($full_transient_keys)){ |
|
254 | + foreach ($this->transients as $transient_key => $expiration) { |
|
255 | + foreach ($transient_keys as $transient_key_to_delete) { |
|
256 | + if (strpos($transient_key, $transient_key_to_delete) !== false) { |
|
257 | + $full_transient_keys[] = $transient_key; |
|
258 | + } |
|
259 | + } |
|
260 | + } |
|
261 | + } |
|
262 | + if ($this->deleteTransientKeys($full_transient_keys)) { |
|
263 | + $this->updateTransients(); |
|
264 | + } |
|
265 | + } |
|
266 | + |
|
267 | + |
|
268 | + |
|
269 | + /** |
|
270 | + * sorts transients numerically by timestamp |
|
271 | + * then saves the transient schedule to a WP option |
|
272 | + */ |
|
273 | + private function updateTransients() |
|
274 | + { |
|
275 | + asort($this->transients, SORT_NUMERIC); |
|
276 | + update_option( |
|
277 | + TransientCacheStorage::TRANSIENT_SCHEDULE_OPTIONS_KEY, |
|
278 | + $this->transients |
|
279 | + ); |
|
280 | + } |
|
281 | + |
|
282 | + |
|
283 | + |
|
284 | + /** |
|
285 | + * schedules a transient for cleanup by adding it to the transient tracking |
|
286 | + * |
|
287 | + * @param string $transient_key [required] |
|
288 | + * @param int $expiration [required] |
|
289 | + */ |
|
290 | + private function scheduleTransientCleanup($transient_key, $expiration) |
|
291 | + { |
|
292 | + // make sure a valid future timestamp is set |
|
293 | + $expiration += $expiration < time() ? time() : 0; |
|
294 | + // and round to the closest 15 minutes |
|
295 | + $expiration = $this->roundTimestamp($expiration); |
|
296 | + // save transients to clear using their ID as the key to avoid duplicates |
|
297 | + $this->transients[$transient_key] = $expiration; |
|
298 | + $this->updateTransients(); |
|
299 | + } |
|
300 | + |
|
301 | + |
|
302 | + |
|
303 | + /** |
|
304 | + * Since our tracked transients are sorted by their timestamps |
|
305 | + * we can grab the first transient and see when it is scheduled for cleanup. |
|
306 | + * If that timestamp is less than or equal to the current time, |
|
307 | + * then cleanup is triggered |
|
308 | + */ |
|
309 | + public function checkTransientCleanupSchedule() |
|
310 | + { |
|
311 | + if (empty($this->transients)) { |
|
312 | + return; |
|
313 | + } |
|
314 | + // when do we run the next cleanup job? |
|
315 | + reset($this->transients); |
|
316 | + $next_scheduled_cleanup = current($this->transients); |
|
317 | + // if the next cleanup job is scheduled for the current hour |
|
318 | + if ($next_scheduled_cleanup <= $this->current_time) { |
|
319 | + if ($this->cleanupExpiredTransients()) { |
|
320 | + $this->updateTransients(); |
|
321 | + } |
|
322 | + } |
|
323 | + } |
|
324 | + |
|
325 | + |
|
326 | + |
|
327 | + /** |
|
328 | + * loops through the array of tracked transients, |
|
329 | + * compiles a list of those that have expired, and sends that list off for deletion. |
|
330 | + * Also removes any bad records from the transients array |
|
331 | + * |
|
332 | + * @return bool |
|
333 | + */ |
|
334 | + private function cleanupExpiredTransients() |
|
335 | + { |
|
336 | + $update = false; |
|
337 | + // filter the query limit. Set to 0 to turn off garbage collection |
|
338 | + $limit = (int)abs( |
|
339 | + apply_filters( |
|
340 | + 'FHEE__TransientCacheStorage__clearExpiredTransients__limit', |
|
341 | + 50 |
|
342 | + ) |
|
343 | + ); |
|
344 | + // non-zero LIMIT means take out the trash |
|
345 | + if ($limit) { |
|
346 | + $transient_keys = array(); |
|
347 | + foreach ($this->transients as $transient_key => $expiration) { |
|
348 | + if ($expiration > $this->current_time) { |
|
349 | + continue; |
|
350 | + } |
|
351 | + if ( ! $expiration || ! $transient_key) { |
|
352 | + unset($this->transients[$transient_key]); |
|
353 | + $update = true; |
|
354 | + continue; |
|
355 | + } |
|
356 | + $transient_keys[] = $transient_key; |
|
357 | + } |
|
358 | + // delete expired keys, but maintain value of $update if nothing is deleted |
|
359 | + $update = $this->deleteTransientKeys($transient_keys, $limit) ? true : $update; |
|
360 | + do_action( 'FHEE__TransientCacheStorage__clearExpiredTransients__end', $this); |
|
361 | + } |
|
362 | + return $update; |
|
363 | + } |
|
364 | + |
|
365 | + |
|
366 | + |
|
367 | + /** |
|
368 | + * calls delete_transient() on each transient key provided, up to the specified limit |
|
369 | + * |
|
370 | + * @param array $transient_keys [required] |
|
371 | + * @param int $limit |
|
372 | + * @return bool |
|
373 | + */ |
|
374 | + private function deleteTransientKeys(array $transient_keys, $limit = 50) |
|
375 | + { |
|
376 | + if (empty($transient_keys)) { |
|
377 | + return false; |
|
378 | + } |
|
379 | + $counter = 0; |
|
380 | + foreach ($transient_keys as $transient_key) { |
|
381 | + if($counter === $limit){ |
|
382 | + break; |
|
383 | + } |
|
384 | + // remove any transient prefixes |
|
385 | + $transient_key = strpos($transient_key, '_transient_timeout_') === 0 |
|
386 | + ? str_replace('_transient_timeout_', '', $transient_key) |
|
387 | + : $transient_key; |
|
388 | + $transient_key = strpos($transient_key, '_transient_') === 0 |
|
389 | + ? str_replace('_transient_', '', $transient_key) |
|
390 | + : $transient_key; |
|
391 | + delete_transient($transient_key); |
|
392 | + unset($this->transients[$transient_key]); |
|
393 | + $counter++; |
|
394 | + } |
|
395 | + return $counter > 0; |
|
396 | + } |
|
397 | 397 | |
398 | 398 | |
399 | 399 |
@@ -60,7 +60,7 @@ discard block |
||
60 | 60 | $this->transient_cleanup_frequency = $this->setTransientCleanupFrequency(); |
61 | 61 | // round current time down to closest 5 minutes to simplify scheduling |
62 | 62 | $this->current_time = $this->roundTimestamp(time(), '5-minutes', false); |
63 | - $this->transients = (array)get_option(TransientCacheStorage::TRANSIENT_SCHEDULE_OPTIONS_KEY, array()); |
|
63 | + $this->transients = (array) get_option(TransientCacheStorage::TRANSIENT_SCHEDULE_OPTIONS_KEY, array()); |
|
64 | 64 | if ( ! (defined('DOING_AJAX') && DOING_AJAX) && $this->transient_cleanup_frequency !== 'off') { |
65 | 65 | add_action('shutdown', array($this, 'checkTransientCleanupSchedule'), 999); |
66 | 66 | } |
@@ -128,17 +128,17 @@ discard block |
||
128 | 128 | $hours = 'H'; |
129 | 129 | switch ($cleanup_frequency) { |
130 | 130 | case '5-minutes' : |
131 | - $minutes = floor((int)date('i', $timestamp) / 5) * 5; |
|
131 | + $minutes = floor((int) date('i', $timestamp) / 5) * 5; |
|
132 | 132 | $minutes = str_pad($minutes, 2, '0', STR_PAD_LEFT); |
133 | 133 | $offset = MINUTE_IN_SECONDS * 5; |
134 | 134 | break; |
135 | 135 | case '15-minutes' : |
136 | - $minutes = floor((int)date('i', $timestamp) / 15) * 15; |
|
136 | + $minutes = floor((int) date('i', $timestamp) / 15) * 15; |
|
137 | 137 | $minutes = str_pad($minutes, 2, '0', STR_PAD_LEFT); |
138 | 138 | $offset = MINUTE_IN_SECONDS * 15; |
139 | 139 | break; |
140 | 140 | case '12-hours' : |
141 | - $hours = floor((int)date('H', $timestamp) / 12) * 12; |
|
141 | + $hours = floor((int) date('H', $timestamp) / 12) * 12; |
|
142 | 142 | $hours = str_pad($hours, 2, '0', STR_PAD_LEFT); |
143 | 143 | $offset = HOUR_IN_SECONDS * 12; |
144 | 144 | break; |
@@ -175,7 +175,7 @@ discard block |
||
175 | 175 | */ |
176 | 176 | public function add($transient_key, $data, $expiration = 0) |
177 | 177 | { |
178 | - $expiration = (int)abs($expiration); |
|
178 | + $expiration = (int) abs($expiration); |
|
179 | 179 | $saved = set_transient($transient_key, $data, $expiration); |
180 | 180 | if ($saved && $expiration) { |
181 | 181 | $this->scheduleTransientCleanup($transient_key, $expiration); |
@@ -198,7 +198,7 @@ discard block |
||
198 | 198 | */ |
199 | 199 | public function get($transient_key, $standard_cache = true) |
200 | 200 | { |
201 | - if (isset($this->transients[ $transient_key ])) { |
|
201 | + if (isset($this->transients[$transient_key])) { |
|
202 | 202 | // to avoid cache stampedes (AKA:dogpiles) for standard cache items, |
203 | 203 | // check if known cache expires within the next minute, |
204 | 204 | // and if so, remove it from our tracking and and return nothing. |
@@ -250,7 +250,7 @@ discard block |
||
250 | 250 | public function deleteMany(array $transient_keys, $force_delete = false) |
251 | 251 | { |
252 | 252 | $full_transient_keys = $force_delete ? $transient_keys : array(); |
253 | - if(empty($full_transient_keys)){ |
|
253 | + if (empty($full_transient_keys)) { |
|
254 | 254 | foreach ($this->transients as $transient_key => $expiration) { |
255 | 255 | foreach ($transient_keys as $transient_key_to_delete) { |
256 | 256 | if (strpos($transient_key, $transient_key_to_delete) !== false) { |
@@ -335,7 +335,7 @@ discard block |
||
335 | 335 | { |
336 | 336 | $update = false; |
337 | 337 | // filter the query limit. Set to 0 to turn off garbage collection |
338 | - $limit = (int)abs( |
|
338 | + $limit = (int) abs( |
|
339 | 339 | apply_filters( |
340 | 340 | 'FHEE__TransientCacheStorage__clearExpiredTransients__limit', |
341 | 341 | 50 |
@@ -357,7 +357,7 @@ discard block |
||
357 | 357 | } |
358 | 358 | // delete expired keys, but maintain value of $update if nothing is deleted |
359 | 359 | $update = $this->deleteTransientKeys($transient_keys, $limit) ? true : $update; |
360 | - do_action( 'FHEE__TransientCacheStorage__clearExpiredTransients__end', $this); |
|
360 | + do_action('FHEE__TransientCacheStorage__clearExpiredTransients__end', $this); |
|
361 | 361 | } |
362 | 362 | return $update; |
363 | 363 | } |
@@ -378,14 +378,14 @@ discard block |
||
378 | 378 | } |
379 | 379 | $counter = 0; |
380 | 380 | foreach ($transient_keys as $transient_key) { |
381 | - if($counter === $limit){ |
|
381 | + if ($counter === $limit) { |
|
382 | 382 | break; |
383 | 383 | } |
384 | 384 | // remove any transient prefixes |
385 | - $transient_key = strpos($transient_key, '_transient_timeout_') === 0 |
|
385 | + $transient_key = strpos($transient_key, '_transient_timeout_') === 0 |
|
386 | 386 | ? str_replace('_transient_timeout_', '', $transient_key) |
387 | 387 | : $transient_key; |
388 | - $transient_key = strpos($transient_key, '_transient_') === 0 |
|
388 | + $transient_key = strpos($transient_key, '_transient_') === 0 |
|
389 | 389 | ? str_replace('_transient_', '', $transient_key) |
390 | 390 | : $transient_key; |
391 | 391 | delete_transient($transient_key); |
@@ -22,174 +22,174 @@ |
||
22 | 22 | class EE_Register_Payment_Method implements EEI_Plugin_API |
23 | 23 | { |
24 | 24 | |
25 | - /** |
|
26 | - * Holds values for registered payment methods |
|
27 | - * |
|
28 | - * @var array |
|
29 | - */ |
|
30 | - protected static $_settings = array(); |
|
31 | - |
|
32 | - |
|
33 | - |
|
34 | - /** |
|
35 | - * Method for registering new EE_PMT_Base children |
|
36 | - * |
|
37 | - * @since 4.5.0 |
|
38 | - * @param string $payment_method_id a unique identifier for this set of modules Required. |
|
39 | - * @param array $setup_args an array of arguments provided for registering modules Required.{ |
|
40 | - * @type string[] $payment_method_paths each element is the folder containing the EE_PMT_Base child class |
|
41 | - * (eg, 'public_html/wp-content/plugins/my_plugin/Payomatic/' which contains |
|
42 | - * the files EE_PMT_Payomatic.pm.php) |
|
43 | - * } |
|
44 | - * @throws EE_Error |
|
45 | - * @type array payment_method_paths an array of full server paths to folders containing any EE_PMT_Base |
|
46 | - * children, or to the EED_Module files themselves |
|
47 | - * @return void |
|
48 | - * @throws InvalidDataTypeException |
|
49 | - * @throws DomainException |
|
50 | - * @throws InvalidArgumentException |
|
51 | - * @throws InvalidInterfaceException |
|
52 | - * @throws InvalidDataTypeException |
|
53 | - */ |
|
54 | - public static function register($payment_method_id = null, $setup_args = array()) |
|
55 | - { |
|
56 | - //required fields MUST be present, so let's make sure they are. |
|
57 | - if (empty($payment_method_id) || ! is_array($setup_args) || empty($setup_args['payment_method_paths'])) { |
|
58 | - throw new EE_Error( |
|
59 | - esc_html__( |
|
60 | - 'In order to register Payment Methods with EE_Register_Payment_Method::register(), you must include a "payment_method_id" (a unique identifier for this set of modules), and an array containing the following keys: "payment_method_paths" (an array of full server paths to folders that contain modules, or to the module files themselves)', |
|
61 | - 'event_espresso' |
|
62 | - ) |
|
63 | - ); |
|
64 | - } |
|
65 | - //make sure we don't register twice |
|
66 | - if (isset(self::$_settings[$payment_method_id])) { |
|
67 | - return; |
|
68 | - } |
|
69 | - //make sure this was called in the right place! |
|
70 | - if ( |
|
71 | - ! did_action('AHEE__EE_System__load_espresso_addons') |
|
72 | - || did_action('AHEE__EE_System__register_shortcodes_modules_and_widgets') |
|
73 | - ) { |
|
74 | - EE_Error::doing_it_wrong( |
|
75 | - __METHOD__, |
|
76 | - esc_html__( |
|
77 | - 'An attempt to register modules has failed because it was not registered at the correct time. Please use the "AHEE__EE_System__register_shortcodes_modules_and_widgets" hook to register modules.', |
|
78 | - 'event_espresso' |
|
79 | - ), |
|
80 | - '4.3.0' |
|
81 | - ); |
|
82 | - } |
|
83 | - //setup $_settings array from incoming values. |
|
84 | - self::$_settings[$payment_method_id] = array( |
|
85 | - // array of full server paths to any EE_PMT_Base children used |
|
86 | - 'payment_method_paths' => isset($setup_args['payment_method_paths']) |
|
87 | - ? (array)$setup_args['payment_method_paths'] |
|
88 | - : array(), |
|
89 | - ); |
|
90 | - // add to list of modules to be registered |
|
91 | - add_filter( |
|
92 | - 'FHEE__EE_Payment_Method_Manager__register_payment_methods__payment_methods_to_register', |
|
93 | - array('EE_Register_Payment_Method', 'add_payment_methods') |
|
94 | - ); |
|
95 | - // If EE_Payment_Method_Manager::register_payment_methods has already been called, |
|
96 | - // then we need to add our caps for this payment method manually |
|
97 | - if (did_action('FHEE__EE_Payment_Method_Manager__register_payment_methods__registered_payment_methods')) { |
|
98 | - $payment_method_manager = LoaderFactory::getLoader()->getShared('EE_Payment_Method_Manager'); |
|
99 | - // register payment methods directly |
|
100 | - foreach (self::$_settings[$payment_method_id]['payment_method_paths'] as $payment_method_path) { |
|
101 | - $payment_method_manager->register_payment_method($payment_method_path); |
|
102 | - } |
|
103 | - $capabilities = LoaderFactory::getLoader()->getShared('EE_Capabilities'); |
|
104 | - $capabilities->addCaps( |
|
105 | - self::getPaymentMethodCapabilities(self::$_settings[$payment_method_id]) |
|
106 | - ); |
|
107 | - } |
|
108 | - } |
|
109 | - |
|
110 | - |
|
111 | - |
|
112 | - /** |
|
113 | - * Filters the list of payment methods to add ours. |
|
114 | - * and they're just full filepaths to FOLDERS containing a payment method class file. Eg. |
|
115 | - * |
|
116 | - * @param array $payment_method_folders array of paths to all payment methods that require registering |
|
117 | - * @return array |
|
118 | - */ |
|
119 | - public static function add_payment_methods($payment_method_folders) |
|
120 | - { |
|
121 | - foreach (self::$_settings as $settings) { |
|
122 | - foreach ($settings['payment_method_paths'] as $payment_method_path) { |
|
123 | - $payment_method_folders[] = $payment_method_path; |
|
124 | - } |
|
125 | - } |
|
126 | - return $payment_method_folders; |
|
127 | - } |
|
128 | - |
|
129 | - |
|
130 | - |
|
131 | - /** |
|
132 | - * This deregisters a module that was previously registered with a specific $module_id. |
|
133 | - * |
|
134 | - * @since 4.3.0 |
|
135 | - * |
|
136 | - * @param string $module_id the name for the module that was previously registered |
|
137 | - * @return void |
|
138 | - * @throws DomainException |
|
139 | - * @throws EE_Error |
|
140 | - * @throws InvalidArgumentException |
|
141 | - * @throws InvalidInterfaceException |
|
142 | - * @throws InvalidDataTypeException |
|
143 | - */ |
|
144 | - public static function deregister($module_id = null) |
|
145 | - { |
|
146 | - if (isset(self::$_settings[$module_id])) { |
|
147 | - |
|
148 | - //set action for just this module id to delay deregistration until core is loaded and ready. |
|
149 | - $module_settings = self::$_settings[$module_id]; |
|
150 | - unset(self::$_settings[$module_id]); |
|
151 | - add_action( |
|
152 | - 'AHEE__EE_System__core_loaded_and_ready', |
|
153 | - function () use ($module_settings) { |
|
154 | - $capabilities = LoaderFactory::getLoader()->getShared('EE_Capabilities'); |
|
155 | - $capabilities->removeCaps( |
|
156 | - EE_Register_Payment_Method::getPaymentMethodCapabilities($module_settings) |
|
157 | - ); |
|
158 | - } |
|
159 | - ); |
|
160 | - } |
|
161 | - } |
|
162 | - |
|
163 | - |
|
164 | - |
|
165 | - /** |
|
166 | - * returns an array of the caps that get added when a Payment Method is registered |
|
167 | - * |
|
168 | - * @param array $settings |
|
169 | - * @return array |
|
170 | - * @throws DomainException |
|
171 | - * @throws EE_Error |
|
172 | - * @throws InvalidArgumentException |
|
173 | - * @throws InvalidInterfaceException |
|
174 | - * @throws InvalidDataTypeException |
|
175 | - * @access private Developers do NOT use this method. It's only public for PHP5.3 closure support (see deregister) |
|
176 | - * When we drop support for PHP5.3 this will be made private again. You have been warned. |
|
177 | - * |
|
178 | - */ |
|
179 | - public static function getPaymentMethodCapabilities(array $settings) |
|
180 | - { |
|
181 | - $payment_method_manager = LoaderFactory::getLoader()->getShared('EE_Payment_Method_Manager'); |
|
182 | - $payment_method_caps = array('administrator' => array()); |
|
183 | - if (isset($settings['payment_method_paths'])) { |
|
184 | - foreach ($settings['payment_method_paths'] as $payment_method_path) { |
|
185 | - $payment_method_caps = $payment_method_manager->addPaymentMethodCap( |
|
186 | - strtolower(basename($payment_method_path)), |
|
187 | - $payment_method_caps |
|
188 | - ); |
|
189 | - } |
|
190 | - } |
|
191 | - return $payment_method_caps; |
|
192 | - } |
|
25 | + /** |
|
26 | + * Holds values for registered payment methods |
|
27 | + * |
|
28 | + * @var array |
|
29 | + */ |
|
30 | + protected static $_settings = array(); |
|
31 | + |
|
32 | + |
|
33 | + |
|
34 | + /** |
|
35 | + * Method for registering new EE_PMT_Base children |
|
36 | + * |
|
37 | + * @since 4.5.0 |
|
38 | + * @param string $payment_method_id a unique identifier for this set of modules Required. |
|
39 | + * @param array $setup_args an array of arguments provided for registering modules Required.{ |
|
40 | + * @type string[] $payment_method_paths each element is the folder containing the EE_PMT_Base child class |
|
41 | + * (eg, 'public_html/wp-content/plugins/my_plugin/Payomatic/' which contains |
|
42 | + * the files EE_PMT_Payomatic.pm.php) |
|
43 | + * } |
|
44 | + * @throws EE_Error |
|
45 | + * @type array payment_method_paths an array of full server paths to folders containing any EE_PMT_Base |
|
46 | + * children, or to the EED_Module files themselves |
|
47 | + * @return void |
|
48 | + * @throws InvalidDataTypeException |
|
49 | + * @throws DomainException |
|
50 | + * @throws InvalidArgumentException |
|
51 | + * @throws InvalidInterfaceException |
|
52 | + * @throws InvalidDataTypeException |
|
53 | + */ |
|
54 | + public static function register($payment_method_id = null, $setup_args = array()) |
|
55 | + { |
|
56 | + //required fields MUST be present, so let's make sure they are. |
|
57 | + if (empty($payment_method_id) || ! is_array($setup_args) || empty($setup_args['payment_method_paths'])) { |
|
58 | + throw new EE_Error( |
|
59 | + esc_html__( |
|
60 | + 'In order to register Payment Methods with EE_Register_Payment_Method::register(), you must include a "payment_method_id" (a unique identifier for this set of modules), and an array containing the following keys: "payment_method_paths" (an array of full server paths to folders that contain modules, or to the module files themselves)', |
|
61 | + 'event_espresso' |
|
62 | + ) |
|
63 | + ); |
|
64 | + } |
|
65 | + //make sure we don't register twice |
|
66 | + if (isset(self::$_settings[$payment_method_id])) { |
|
67 | + return; |
|
68 | + } |
|
69 | + //make sure this was called in the right place! |
|
70 | + if ( |
|
71 | + ! did_action('AHEE__EE_System__load_espresso_addons') |
|
72 | + || did_action('AHEE__EE_System__register_shortcodes_modules_and_widgets') |
|
73 | + ) { |
|
74 | + EE_Error::doing_it_wrong( |
|
75 | + __METHOD__, |
|
76 | + esc_html__( |
|
77 | + 'An attempt to register modules has failed because it was not registered at the correct time. Please use the "AHEE__EE_System__register_shortcodes_modules_and_widgets" hook to register modules.', |
|
78 | + 'event_espresso' |
|
79 | + ), |
|
80 | + '4.3.0' |
|
81 | + ); |
|
82 | + } |
|
83 | + //setup $_settings array from incoming values. |
|
84 | + self::$_settings[$payment_method_id] = array( |
|
85 | + // array of full server paths to any EE_PMT_Base children used |
|
86 | + 'payment_method_paths' => isset($setup_args['payment_method_paths']) |
|
87 | + ? (array)$setup_args['payment_method_paths'] |
|
88 | + : array(), |
|
89 | + ); |
|
90 | + // add to list of modules to be registered |
|
91 | + add_filter( |
|
92 | + 'FHEE__EE_Payment_Method_Manager__register_payment_methods__payment_methods_to_register', |
|
93 | + array('EE_Register_Payment_Method', 'add_payment_methods') |
|
94 | + ); |
|
95 | + // If EE_Payment_Method_Manager::register_payment_methods has already been called, |
|
96 | + // then we need to add our caps for this payment method manually |
|
97 | + if (did_action('FHEE__EE_Payment_Method_Manager__register_payment_methods__registered_payment_methods')) { |
|
98 | + $payment_method_manager = LoaderFactory::getLoader()->getShared('EE_Payment_Method_Manager'); |
|
99 | + // register payment methods directly |
|
100 | + foreach (self::$_settings[$payment_method_id]['payment_method_paths'] as $payment_method_path) { |
|
101 | + $payment_method_manager->register_payment_method($payment_method_path); |
|
102 | + } |
|
103 | + $capabilities = LoaderFactory::getLoader()->getShared('EE_Capabilities'); |
|
104 | + $capabilities->addCaps( |
|
105 | + self::getPaymentMethodCapabilities(self::$_settings[$payment_method_id]) |
|
106 | + ); |
|
107 | + } |
|
108 | + } |
|
109 | + |
|
110 | + |
|
111 | + |
|
112 | + /** |
|
113 | + * Filters the list of payment methods to add ours. |
|
114 | + * and they're just full filepaths to FOLDERS containing a payment method class file. Eg. |
|
115 | + * |
|
116 | + * @param array $payment_method_folders array of paths to all payment methods that require registering |
|
117 | + * @return array |
|
118 | + */ |
|
119 | + public static function add_payment_methods($payment_method_folders) |
|
120 | + { |
|
121 | + foreach (self::$_settings as $settings) { |
|
122 | + foreach ($settings['payment_method_paths'] as $payment_method_path) { |
|
123 | + $payment_method_folders[] = $payment_method_path; |
|
124 | + } |
|
125 | + } |
|
126 | + return $payment_method_folders; |
|
127 | + } |
|
128 | + |
|
129 | + |
|
130 | + |
|
131 | + /** |
|
132 | + * This deregisters a module that was previously registered with a specific $module_id. |
|
133 | + * |
|
134 | + * @since 4.3.0 |
|
135 | + * |
|
136 | + * @param string $module_id the name for the module that was previously registered |
|
137 | + * @return void |
|
138 | + * @throws DomainException |
|
139 | + * @throws EE_Error |
|
140 | + * @throws InvalidArgumentException |
|
141 | + * @throws InvalidInterfaceException |
|
142 | + * @throws InvalidDataTypeException |
|
143 | + */ |
|
144 | + public static function deregister($module_id = null) |
|
145 | + { |
|
146 | + if (isset(self::$_settings[$module_id])) { |
|
147 | + |
|
148 | + //set action for just this module id to delay deregistration until core is loaded and ready. |
|
149 | + $module_settings = self::$_settings[$module_id]; |
|
150 | + unset(self::$_settings[$module_id]); |
|
151 | + add_action( |
|
152 | + 'AHEE__EE_System__core_loaded_and_ready', |
|
153 | + function () use ($module_settings) { |
|
154 | + $capabilities = LoaderFactory::getLoader()->getShared('EE_Capabilities'); |
|
155 | + $capabilities->removeCaps( |
|
156 | + EE_Register_Payment_Method::getPaymentMethodCapabilities($module_settings) |
|
157 | + ); |
|
158 | + } |
|
159 | + ); |
|
160 | + } |
|
161 | + } |
|
162 | + |
|
163 | + |
|
164 | + |
|
165 | + /** |
|
166 | + * returns an array of the caps that get added when a Payment Method is registered |
|
167 | + * |
|
168 | + * @param array $settings |
|
169 | + * @return array |
|
170 | + * @throws DomainException |
|
171 | + * @throws EE_Error |
|
172 | + * @throws InvalidArgumentException |
|
173 | + * @throws InvalidInterfaceException |
|
174 | + * @throws InvalidDataTypeException |
|
175 | + * @access private Developers do NOT use this method. It's only public for PHP5.3 closure support (see deregister) |
|
176 | + * When we drop support for PHP5.3 this will be made private again. You have been warned. |
|
177 | + * |
|
178 | + */ |
|
179 | + public static function getPaymentMethodCapabilities(array $settings) |
|
180 | + { |
|
181 | + $payment_method_manager = LoaderFactory::getLoader()->getShared('EE_Payment_Method_Manager'); |
|
182 | + $payment_method_caps = array('administrator' => array()); |
|
183 | + if (isset($settings['payment_method_paths'])) { |
|
184 | + foreach ($settings['payment_method_paths'] as $payment_method_path) { |
|
185 | + $payment_method_caps = $payment_method_manager->addPaymentMethodCap( |
|
186 | + strtolower(basename($payment_method_path)), |
|
187 | + $payment_method_caps |
|
188 | + ); |
|
189 | + } |
|
190 | + } |
|
191 | + return $payment_method_caps; |
|
192 | + } |
|
193 | 193 | |
194 | 194 | } |
195 | 195 | // End of file EE_Register_Payment_Method.lib.php |
@@ -84,7 +84,7 @@ discard block |
||
84 | 84 | self::$_settings[$payment_method_id] = array( |
85 | 85 | // array of full server paths to any EE_PMT_Base children used |
86 | 86 | 'payment_method_paths' => isset($setup_args['payment_method_paths']) |
87 | - ? (array)$setup_args['payment_method_paths'] |
|
87 | + ? (array) $setup_args['payment_method_paths'] |
|
88 | 88 | : array(), |
89 | 89 | ); |
90 | 90 | // add to list of modules to be registered |
@@ -150,7 +150,7 @@ discard block |
||
150 | 150 | unset(self::$_settings[$module_id]); |
151 | 151 | add_action( |
152 | 152 | 'AHEE__EE_System__core_loaded_and_ready', |
153 | - function () use ($module_settings) { |
|
153 | + function() use ($module_settings) { |
|
154 | 154 | $capabilities = LoaderFactory::getLoader()->getShared('EE_Capabilities'); |
155 | 155 | $capabilities->removeCaps( |
156 | 156 | EE_Register_Payment_Method::getPaymentMethodCapabilities($module_settings) |
@@ -29,843 +29,843 @@ |
||
29 | 29 | { |
30 | 30 | |
31 | 31 | |
32 | - /** |
|
33 | - * @var EE_Datetime_Offset_Fix_Form |
|
34 | - */ |
|
35 | - protected $datetime_fix_offset_form; |
|
36 | - |
|
37 | - |
|
38 | - |
|
39 | - protected function _init_page_props() |
|
40 | - { |
|
41 | - $this->page_slug = EE_MAINTENANCE_PG_SLUG; |
|
42 | - $this->page_label = EE_MAINTENANCE_LABEL; |
|
43 | - $this->_admin_base_url = EE_MAINTENANCE_ADMIN_URL; |
|
44 | - $this->_admin_base_path = EE_MAINTENANCE_ADMIN; |
|
45 | - } |
|
46 | - |
|
47 | - |
|
48 | - |
|
49 | - protected function _ajax_hooks() |
|
50 | - { |
|
51 | - add_action('wp_ajax_migration_step', array($this, 'migration_step')); |
|
52 | - add_action('wp_ajax_add_error_to_migrations_ran', array($this, 'add_error_to_migrations_ran')); |
|
53 | - } |
|
54 | - |
|
55 | - |
|
56 | - |
|
57 | - protected function _define_page_props() |
|
58 | - { |
|
59 | - $this->_admin_page_title = EE_MAINTENANCE_LABEL; |
|
60 | - $this->_labels = array( |
|
61 | - 'buttons' => array( |
|
62 | - 'reset_reservations' => esc_html__('Reset Ticket and Datetime Reserved Counts', 'event_espresso'), |
|
63 | - 'reset_capabilities' => esc_html__('Reset Event Espresso Capabilities', 'event_espresso'), |
|
64 | - ), |
|
65 | - ); |
|
66 | - } |
|
67 | - |
|
68 | - |
|
69 | - |
|
70 | - protected function _set_page_routes() |
|
71 | - { |
|
72 | - $this->_page_routes = array( |
|
73 | - 'default' => array( |
|
74 | - 'func' => '_maintenance', |
|
75 | - 'capability' => 'manage_options', |
|
76 | - ), |
|
77 | - 'change_maintenance_level' => array( |
|
78 | - 'func' => '_change_maintenance_level', |
|
79 | - 'capability' => 'manage_options', |
|
80 | - 'noheader' => true, |
|
81 | - ), |
|
82 | - 'system_status' => array( |
|
83 | - 'func' => '_system_status', |
|
84 | - 'capability' => 'manage_options', |
|
85 | - ), |
|
86 | - 'download_system_status' => array( |
|
87 | - 'func' => '_download_system_status', |
|
88 | - 'capability' => 'manage_options', |
|
89 | - 'noheader' => true, |
|
90 | - ), |
|
91 | - 'send_migration_crash_report' => array( |
|
92 | - 'func' => '_send_migration_crash_report', |
|
93 | - 'capability' => 'manage_options', |
|
94 | - 'noheader' => true, |
|
95 | - ), |
|
96 | - 'confirm_migration_crash_report_sent' => array( |
|
97 | - 'func' => '_confirm_migration_crash_report_sent', |
|
98 | - 'capability' => 'manage_options', |
|
99 | - ), |
|
100 | - 'data_reset' => array( |
|
101 | - 'func' => '_data_reset_and_delete', |
|
102 | - 'capability' => 'manage_options', |
|
103 | - ), |
|
104 | - 'reset_db' => array( |
|
105 | - 'func' => '_reset_db', |
|
106 | - 'capability' => 'manage_options', |
|
107 | - 'noheader' => true, |
|
108 | - 'args' => array('nuke_old_ee4_data' => true), |
|
109 | - ), |
|
110 | - 'start_with_fresh_ee4_db' => array( |
|
111 | - 'func' => '_reset_db', |
|
112 | - 'capability' => 'manage_options', |
|
113 | - 'noheader' => true, |
|
114 | - 'args' => array('nuke_old_ee4_data' => false), |
|
115 | - ), |
|
116 | - 'delete_db' => array( |
|
117 | - 'func' => '_delete_db', |
|
118 | - 'capability' => 'manage_options', |
|
119 | - 'noheader' => true, |
|
120 | - ), |
|
121 | - 'rerun_migration_from_ee3' => array( |
|
122 | - 'func' => '_rerun_migration_from_ee3', |
|
123 | - 'capability' => 'manage_options', |
|
124 | - 'noheader' => true, |
|
125 | - ), |
|
126 | - 'reset_reservations' => array( |
|
127 | - 'func' => '_reset_reservations', |
|
128 | - 'capability' => 'manage_options', |
|
129 | - 'noheader' => true, |
|
130 | - ), |
|
131 | - 'reset_capabilities' => array( |
|
132 | - 'func' => '_reset_capabilities', |
|
133 | - 'capability' => 'manage_options', |
|
134 | - 'noheader' => true, |
|
135 | - ), |
|
136 | - 'reattempt_migration' => array( |
|
137 | - 'func' => '_reattempt_migration', |
|
138 | - 'capability' => 'manage_options', |
|
139 | - 'noheader' => true, |
|
140 | - ), |
|
141 | - 'datetime_tools' => array( |
|
142 | - 'func' => '_datetime_tools', |
|
143 | - 'capability' => 'manage_options' |
|
144 | - ), |
|
145 | - 'run_datetime_offset_fix' => array( |
|
146 | - 'func' => '_apply_datetime_offset', |
|
147 | - 'noheader' => true, |
|
148 | - 'headers_sent_route' => 'datetime_tools', |
|
149 | - 'capability' => 'manage_options' |
|
150 | - ) |
|
151 | - ); |
|
152 | - } |
|
153 | - |
|
154 | - |
|
155 | - |
|
156 | - protected function _set_page_config() |
|
157 | - { |
|
158 | - $this->_page_config = array( |
|
159 | - 'default' => array( |
|
160 | - 'nav' => array( |
|
161 | - 'label' => esc_html__('Maintenance', 'event_espresso'), |
|
162 | - 'order' => 10, |
|
163 | - ), |
|
164 | - 'require_nonce' => false, |
|
165 | - ), |
|
166 | - 'data_reset' => array( |
|
167 | - 'nav' => array( |
|
168 | - 'label' => esc_html__('Reset/Delete Data', 'event_espresso'), |
|
169 | - 'order' => 20, |
|
170 | - ), |
|
171 | - 'require_nonce' => false, |
|
172 | - ), |
|
173 | - 'datetime_tools' => array( |
|
174 | - 'nav' => array( |
|
175 | - 'label' => esc_html__('Datetime Utilities', 'event_espresso'), |
|
176 | - 'order' => 25 |
|
177 | - ), |
|
178 | - 'require_nonce' => false, |
|
179 | - ), |
|
180 | - 'system_status' => array( |
|
181 | - 'nav' => array( |
|
182 | - 'label' => esc_html__("System Information", "event_espresso"), |
|
183 | - 'order' => 30, |
|
184 | - ), |
|
185 | - 'require_nonce' => false, |
|
186 | - ), |
|
187 | - ); |
|
188 | - } |
|
189 | - |
|
190 | - |
|
191 | - |
|
192 | - /** |
|
193 | - * default maintenance page. If we're in maintenance mode level 2, then we need to show |
|
194 | - * the migration scripts and all that UI. |
|
195 | - */ |
|
196 | - public function _maintenance() |
|
197 | - { |
|
198 | - //it all depends if we're in maintenance model level 1 (frontend-only) or |
|
199 | - //level 2 (everything except maintenance page) |
|
200 | - try { |
|
201 | - //get the current maintenance level and check if |
|
202 | - //we are removed |
|
203 | - $mm = EE_Maintenance_Mode::instance()->level(); |
|
204 | - $placed_in_mm = EE_Maintenance_Mode::instance()->set_maintenance_mode_if_db_old(); |
|
205 | - if ($mm == EE_Maintenance_Mode::level_2_complete_maintenance && ! $placed_in_mm) { |
|
206 | - //we just took the site out of maintenance mode, so notify the user. |
|
207 | - //unfortunately this message appears to be echoed on the NEXT page load... |
|
208 | - //oh well, we should really be checking for this on addon deactivation anyways |
|
209 | - EE_Error::add_attention(__('Site taken out of maintenance mode because no data migration scripts are required', |
|
210 | - 'event_espresso')); |
|
211 | - $this->_process_notices(array('page' => 'espresso_maintenance_settings'), false); |
|
212 | - } |
|
213 | - //in case an exception is thrown while trying to handle migrations |
|
214 | - switch (EE_Maintenance_Mode::instance()->level()) { |
|
215 | - case EE_Maintenance_Mode::level_0_not_in_maintenance: |
|
216 | - case EE_Maintenance_Mode::level_1_frontend_only_maintenance: |
|
217 | - $show_maintenance_switch = true; |
|
218 | - $show_backup_db_text = false; |
|
219 | - $show_migration_progress = false; |
|
220 | - $script_names = array(); |
|
221 | - $addons_should_be_upgraded_first = false; |
|
222 | - break; |
|
223 | - case EE_Maintenance_Mode::level_2_complete_maintenance: |
|
224 | - $show_maintenance_switch = false; |
|
225 | - $show_migration_progress = true; |
|
226 | - if (isset($this->_req_data['continue_migration'])) { |
|
227 | - $show_backup_db_text = false; |
|
228 | - } else { |
|
229 | - $show_backup_db_text = true; |
|
230 | - } |
|
231 | - $scripts_needing_to_run = EE_Data_Migration_Manager::instance() |
|
232 | - ->check_for_applicable_data_migration_scripts(); |
|
233 | - $addons_should_be_upgraded_first = EE_Data_Migration_Manager::instance()->addons_need_updating(); |
|
234 | - $script_names = array(); |
|
235 | - $current_script = null; |
|
236 | - foreach ($scripts_needing_to_run as $script) { |
|
237 | - if ($script instanceof EE_Data_Migration_Script_Base) { |
|
238 | - if ( ! $current_script) { |
|
239 | - $current_script = $script; |
|
240 | - $current_script->migration_page_hooks(); |
|
241 | - } |
|
242 | - $script_names[] = $script->pretty_name(); |
|
243 | - } |
|
244 | - } |
|
245 | - break; |
|
246 | - } |
|
247 | - $most_recent_migration = EE_Data_Migration_Manager::instance()->get_last_ran_script(true); |
|
248 | - $exception_thrown = false; |
|
249 | - } catch (EE_Error $e) { |
|
250 | - EE_Data_Migration_Manager::instance()->add_error_to_migrations_ran($e->getMessage()); |
|
251 | - //now, just so we can display the page correctly, make a error migration script stage object |
|
252 | - //and also put the error on it. It only persists for the duration of this request |
|
253 | - $most_recent_migration = new EE_DMS_Unknown_1_0_0(); |
|
254 | - $most_recent_migration->add_error($e->getMessage()); |
|
255 | - $exception_thrown = true; |
|
256 | - } |
|
257 | - $current_db_state = EE_Data_Migration_Manager::instance()->ensure_current_database_state_is_set(); |
|
258 | - $current_db_state = str_replace('.decaf', '', $current_db_state); |
|
259 | - if ($exception_thrown |
|
260 | - || ($most_recent_migration |
|
261 | - && $most_recent_migration instanceof EE_Data_Migration_Script_Base |
|
262 | - && $most_recent_migration->is_broken() |
|
263 | - ) |
|
264 | - ) { |
|
265 | - $this->_template_path = EE_MAINTENANCE_TEMPLATE_PATH . 'ee_migration_was_borked_page.template.php'; |
|
266 | - $this->_template_args['support_url'] = 'http://eventespresso.com/support/forums/'; |
|
267 | - $this->_template_args['next_url'] = EEH_URL::add_query_args_and_nonce(array('action' => 'confirm_migration_crash_report_sent', |
|
268 | - 'success' => '0', |
|
269 | - ), EE_MAINTENANCE_ADMIN_URL); |
|
270 | - } elseif ($addons_should_be_upgraded_first) { |
|
271 | - $this->_template_path = EE_MAINTENANCE_TEMPLATE_PATH . 'ee_upgrade_addons_before_migrating.template.php'; |
|
272 | - } else { |
|
273 | - if ($most_recent_migration |
|
274 | - && $most_recent_migration instanceof EE_Data_Migration_Script_Base |
|
275 | - && $most_recent_migration->can_continue() |
|
276 | - ) { |
|
277 | - $show_backup_db_text = false; |
|
278 | - $show_continue_current_migration_script = true; |
|
279 | - $show_most_recent_migration = true; |
|
280 | - } elseif (isset($this->_req_data['continue_migration'])) { |
|
281 | - $show_most_recent_migration = true; |
|
282 | - $show_continue_current_migration_script = false; |
|
283 | - } else { |
|
284 | - $show_most_recent_migration = false; |
|
285 | - $show_continue_current_migration_script = false; |
|
286 | - } |
|
287 | - if (isset($current_script)) { |
|
288 | - $migrates_to = $current_script->migrates_to_version(); |
|
289 | - $plugin_slug = $migrates_to['slug']; |
|
290 | - $new_version = $migrates_to['version']; |
|
291 | - $this->_template_args = array_merge($this->_template_args, array( |
|
292 | - 'current_db_state' => sprintf(__("EE%s (%s)", "event_espresso"), |
|
293 | - isset($current_db_state[$plugin_slug]) ? $current_db_state[$plugin_slug] : 3, $plugin_slug), |
|
294 | - 'next_db_state' => isset($current_script) ? sprintf(__("EE%s (%s)", 'event_espresso'), |
|
295 | - $new_version, $plugin_slug) : null, |
|
296 | - )); |
|
297 | - } else { |
|
298 | - $this->_template_args['current_db_state'] = null; |
|
299 | - $this->_template_args['next_db_state'] = null; |
|
300 | - } |
|
301 | - $this->_template_path = EE_MAINTENANCE_TEMPLATE_PATH . 'ee_migration_page.template.php'; |
|
302 | - $this->_template_args = array_merge( |
|
303 | - $this->_template_args, |
|
304 | - array( |
|
305 | - 'show_most_recent_migration' => $show_most_recent_migration, |
|
306 | - //flag for showing the most recent migration's status and/or errors |
|
307 | - 'show_migration_progress' => $show_migration_progress, |
|
308 | - //flag for showing the option to run migrations and see their progress |
|
309 | - 'show_backup_db_text' => $show_backup_db_text, |
|
310 | - //flag for showing text telling the user to backup their DB |
|
311 | - 'show_maintenance_switch' => $show_maintenance_switch, |
|
312 | - //flag for showing the option to change maintenance mode between levels 0 and 1 |
|
313 | - 'script_names' => $script_names, |
|
314 | - //array of names of scripts that have run |
|
315 | - 'show_continue_current_migration_script' => $show_continue_current_migration_script, |
|
316 | - //flag to change wording to indicating that we're only CONTINUING a migration script (somehow it got interrupted0 |
|
317 | - 'reset_db_page_link' => EE_Admin_Page::add_query_args_and_nonce(array('action' => 'reset_db'), |
|
318 | - EE_MAINTENANCE_ADMIN_URL), |
|
319 | - 'data_reset_page' => EE_Admin_Page::add_query_args_and_nonce(array('action' => 'data_reset'), |
|
320 | - EE_MAINTENANCE_ADMIN_URL), |
|
321 | - 'update_migration_script_page_link' => EE_Admin_Page::add_query_args_and_nonce(array('action' => 'change_maintenance_level'), |
|
322 | - EE_MAINTENANCE_ADMIN_URL), |
|
323 | - 'ultimate_db_state' => sprintf(__("EE%s", 'event_espresso'), |
|
324 | - espresso_version()), |
|
325 | - ) |
|
326 | - ); |
|
327 | - //make sure we have the form fields helper available. It usually is, but sometimes it isn't |
|
328 | - } |
|
329 | - $this->_template_args['most_recent_migration'] = $most_recent_migration;//the actual most recently ran migration |
|
330 | - //now render the migration options part, and put it in a variable |
|
331 | - $migration_options_template_file = apply_filters( |
|
332 | - 'FHEE__ee_migration_page__migration_options_template', |
|
333 | - EE_MAINTENANCE_TEMPLATE_PATH . 'migration_options_from_ee4.template.php' |
|
334 | - ); |
|
335 | - $migration_options_html = EEH_Template::display_template($migration_options_template_file, $this->_template_args,true); |
|
336 | - $this->_template_args['migration_options_html'] = $migration_options_html; |
|
337 | - $this->_template_args['admin_page_content'] = EEH_Template::display_template($this->_template_path, |
|
338 | - $this->_template_args, true); |
|
339 | - $this->display_admin_page_with_sidebar(); |
|
340 | - } |
|
341 | - |
|
342 | - |
|
343 | - |
|
344 | - /** |
|
345 | - * returns JSON and executes another step of the currently-executing data migration (called via ajax) |
|
346 | - */ |
|
347 | - public function migration_step() |
|
348 | - { |
|
349 | - $this->_template_args['data'] = EE_Data_Migration_Manager::instance()->response_to_migration_ajax_request(); |
|
350 | - $this->_return_json(); |
|
351 | - } |
|
352 | - |
|
353 | - |
|
354 | - |
|
355 | - /** |
|
356 | - * Can be used by js when it notices a response with HTML in it in order |
|
357 | - * to log the malformed response |
|
358 | - */ |
|
359 | - public function add_error_to_migrations_ran() |
|
360 | - { |
|
361 | - EE_Data_Migration_Manager::instance()->add_error_to_migrations_ran($this->_req_data['message']); |
|
362 | - $this->_template_args['data'] = array('ok' => true); |
|
363 | - $this->_return_json(); |
|
364 | - } |
|
365 | - |
|
366 | - |
|
367 | - |
|
368 | - /** |
|
369 | - * changes the maintenance level, provided there are still no migration scripts that should run |
|
370 | - */ |
|
371 | - public function _change_maintenance_level() |
|
372 | - { |
|
373 | - $new_level = absint($this->_req_data['maintenance_mode_level']); |
|
374 | - if ( ! EE_Data_Migration_Manager::instance()->check_for_applicable_data_migration_scripts()) { |
|
375 | - EE_Maintenance_Mode::instance()->set_maintenance_level($new_level); |
|
376 | - $success = true; |
|
377 | - } else { |
|
378 | - EE_Maintenance_Mode::instance()->set_maintenance_mode_if_db_old(); |
|
379 | - $success = false; |
|
380 | - } |
|
381 | - $this->_redirect_after_action($success, 'Maintenance Mode', esc_html__("Updated", "event_espresso")); |
|
382 | - } |
|
383 | - |
|
384 | - |
|
385 | - |
|
386 | - /** |
|
387 | - * a tab with options for resetting and/or deleting EE data |
|
388 | - * |
|
389 | - * @throws \EE_Error |
|
390 | - * @throws \DomainException |
|
391 | - */ |
|
392 | - public function _data_reset_and_delete() |
|
393 | - { |
|
394 | - $this->_template_path = EE_MAINTENANCE_TEMPLATE_PATH . 'ee_data_reset_and_delete.template.php'; |
|
395 | - $this->_template_args['reset_reservations_button'] = $this->get_action_link_or_button( |
|
396 | - 'reset_reservations', |
|
397 | - 'reset_reservations', |
|
398 | - array(), |
|
399 | - 'button button-primary ee-confirm', |
|
400 | - '', |
|
401 | - false |
|
402 | - ); |
|
403 | - $this->_template_args['reset_capabilities_button'] = $this->get_action_link_or_button( |
|
404 | - 'reset_capabilities', |
|
405 | - 'reset_capabilities', |
|
406 | - array(), |
|
407 | - 'button button-primary ee-confirm', |
|
408 | - '', |
|
409 | - false |
|
410 | - ); |
|
411 | - $this->_template_args['delete_db_url'] = EE_Admin_Page::add_query_args_and_nonce( |
|
412 | - array('action' => 'delete_db'), |
|
413 | - EE_MAINTENANCE_ADMIN_URL |
|
414 | - ); |
|
415 | - $this->_template_args['reset_db_url'] = EE_Admin_Page::add_query_args_and_nonce( |
|
416 | - array('action' => 'reset_db'), |
|
417 | - EE_MAINTENANCE_ADMIN_URL |
|
418 | - ); |
|
419 | - $this->_template_args['admin_page_content'] = EEH_Template::display_template( |
|
420 | - $this->_template_path, |
|
421 | - $this->_template_args, |
|
422 | - true |
|
423 | - ); |
|
424 | - $this->display_admin_page_with_sidebar(); |
|
425 | - } |
|
426 | - |
|
427 | - |
|
428 | - |
|
429 | - protected function _reset_reservations() |
|
430 | - { |
|
431 | - if(\EED_Ticket_Sales_Monitor::reset_reservation_counts()) { |
|
432 | - EE_Error::add_success( |
|
433 | - __( |
|
434 | - 'Ticket and datetime reserved counts have been successfully reset.', |
|
435 | - 'event_espresso' |
|
436 | - ) |
|
437 | - ); |
|
438 | - } else { |
|
439 | - EE_Error::add_success( |
|
440 | - __( |
|
441 | - 'Ticket and datetime reserved counts were correct and did not need resetting.', |
|
442 | - 'event_espresso' |
|
443 | - ) |
|
444 | - ); |
|
445 | - } |
|
446 | - $this->_redirect_after_action(true, '', '', array('action' => 'data_reset'), true); |
|
447 | - } |
|
448 | - |
|
449 | - |
|
450 | - |
|
451 | - protected function _reset_capabilities() |
|
452 | - { |
|
453 | - EE_Registry::instance()->CAP->init_caps(true); |
|
454 | - EE_Error::add_success(__('Default Event Espresso capabilities have been restored for all current roles.', |
|
455 | - 'event_espresso')); |
|
456 | - $this->_redirect_after_action(false, '', '', array('action' => 'data_reset'), true); |
|
457 | - } |
|
458 | - |
|
459 | - |
|
460 | - |
|
461 | - /** |
|
462 | - * resets the DMSs so we can attempt to continue migrating after a fatal error |
|
463 | - * (only a good idea when someone has somehow tried ot fix whatever caused |
|
464 | - * the fatal error in teh first place) |
|
465 | - */ |
|
466 | - protected function _reattempt_migration() |
|
467 | - { |
|
468 | - EE_Data_Migration_Manager::instance()->reattempt(); |
|
469 | - $this->_redirect_after_action(false, '', '', array('action' => 'default'), true); |
|
470 | - } |
|
471 | - |
|
472 | - |
|
473 | - |
|
474 | - /** |
|
475 | - * shows the big ol' System Information page |
|
476 | - */ |
|
477 | - public function _system_status() |
|
478 | - { |
|
479 | - $this->_template_path = EE_MAINTENANCE_TEMPLATE_PATH . 'ee_system_stati_page.template.php'; |
|
480 | - $this->_template_args['system_stati'] = EEM_System_Status::instance()->get_system_stati(); |
|
481 | - $this->_template_args['download_system_status_url'] = EE_Admin_Page::add_query_args_and_nonce( |
|
482 | - array( |
|
483 | - 'action' => 'download_system_status', |
|
484 | - ), |
|
485 | - EE_MAINTENANCE_ADMIN_URL |
|
486 | - ); |
|
487 | - $this->_template_args['admin_page_content'] = EEH_Template::display_template($this->_template_path, |
|
488 | - $this->_template_args, true); |
|
489 | - $this->display_admin_page_with_sidebar(); |
|
490 | - } |
|
491 | - |
|
492 | - /** |
|
493 | - * Downloads an HTML file of the system status that can be easily stored or emailed |
|
494 | - */ |
|
495 | - public function _download_system_status() |
|
496 | - { |
|
497 | - $status_info = EEM_System_Status::instance()->get_system_stati(); |
|
498 | - header( 'Content-Disposition: attachment' ); |
|
499 | - header( "Content-Disposition: attachment; filename=system_status_" . sanitize_key( site_url() ) . ".html" ); |
|
500 | - echo "<style>table{border:1px solid darkgrey;}td{vertical-align:top}</style>"; |
|
501 | - echo "<h1>System Information for " . site_url() . "</h1>"; |
|
502 | - echo EEH_Template::layout_array_as_table( $status_info ); |
|
503 | - die; |
|
504 | - } |
|
505 | - |
|
506 | - |
|
507 | - |
|
508 | - public function _send_migration_crash_report() |
|
509 | - { |
|
510 | - $from = $this->_req_data['from']; |
|
511 | - $from_name = $this->_req_data['from_name']; |
|
512 | - $body = $this->_req_data['body']; |
|
513 | - try { |
|
514 | - $success = wp_mail(EE_SUPPORT_EMAIL, |
|
515 | - 'Migration Crash Report', |
|
516 | - $body . "/r/n<br>" . print_r(EEM_System_Status::instance()->get_system_stati(), true), |
|
517 | - array( |
|
518 | - "from:$from_name<$from>", |
|
519 | - // 'content-type:text/html charset=UTF-8' |
|
520 | - )); |
|
521 | - } catch (Exception $e) { |
|
522 | - $success = false; |
|
523 | - } |
|
524 | - $this->_redirect_after_action($success, esc_html__("Migration Crash Report", "event_espresso"), |
|
525 | - esc_html__("sent", "event_espresso"), |
|
526 | - array('success' => $success, 'action' => 'confirm_migration_crash_report_sent')); |
|
527 | - } |
|
528 | - |
|
529 | - |
|
530 | - |
|
531 | - public function _confirm_migration_crash_report_sent() |
|
532 | - { |
|
533 | - try { |
|
534 | - $most_recent_migration = EE_Data_Migration_Manager::instance()->get_last_ran_script(true); |
|
535 | - } catch (EE_Error $e) { |
|
536 | - EE_Data_Migration_Manager::instance()->add_error_to_migrations_ran($e->getMessage()); |
|
537 | - //now, just so we can display the page correctly, make a error migration script stage object |
|
538 | - //and also put the error on it. It only persists for the duration of this request |
|
539 | - $most_recent_migration = new EE_DMS_Unknown_1_0_0(); |
|
540 | - $most_recent_migration->add_error($e->getMessage()); |
|
541 | - } |
|
542 | - $success = $this->_req_data['success'] == '1' ? true : false; |
|
543 | - $this->_template_args['success'] = $success; |
|
544 | - $this->_template_args['most_recent_migration'] = $most_recent_migration; |
|
545 | - $this->_template_args['reset_db_action_url'] = EE_Admin_Page::add_query_args_and_nonce(array('action' => 'reset_db'), |
|
546 | - EE_MAINTENANCE_ADMIN_URL); |
|
547 | - $this->_template_args['reset_db_page_url'] = EE_Admin_Page::add_query_args_and_nonce(array('action' => 'data_reset'), |
|
548 | - EE_MAINTENANCE_ADMIN_URL); |
|
549 | - $this->_template_args['reattempt_action_url'] = EE_Admin_Page::add_query_args_and_nonce(array('action' => 'reattempt_migration'), |
|
550 | - EE_MAINTENANCE_ADMIN_URL); |
|
551 | - $this->_template_path = EE_MAINTENANCE_TEMPLATE_PATH . 'ee_confirm_migration_crash_report_sent.template.php'; |
|
552 | - $this->_template_args['admin_page_content'] = EEH_Template::display_template($this->_template_path, |
|
553 | - $this->_template_args, true); |
|
554 | - $this->display_admin_page_with_sidebar(); |
|
555 | - } |
|
556 | - |
|
557 | - |
|
558 | - |
|
559 | - /** |
|
560 | - * Resets the entire EE4 database. |
|
561 | - * Currently basically only sets up ee4 database for a fresh install- doesn't |
|
562 | - * actually clean out the old wp options, or cpts (although does erase old ee table data) |
|
563 | - * |
|
564 | - * @param boolean $nuke_old_ee4_data controls whether or not we |
|
565 | - * destroy the old ee4 data, or just try initializing ee4 default data |
|
566 | - */ |
|
567 | - public function _reset_db($nuke_old_ee4_data = true) |
|
568 | - { |
|
569 | - EE_Maintenance_Mode::instance()->set_maintenance_level(EE_Maintenance_Mode::level_0_not_in_maintenance); |
|
570 | - if ($nuke_old_ee4_data) { |
|
571 | - EEH_Activation::delete_all_espresso_cpt_data(); |
|
572 | - EEH_Activation::delete_all_espresso_tables_and_data(false); |
|
573 | - EEH_Activation::remove_cron_tasks(); |
|
574 | - } |
|
575 | - //make sure when we reset the registry's config that it |
|
576 | - //switches to using the new singleton |
|
577 | - EE_Registry::instance()->CFG = EE_Registry::instance()->CFG->reset(true); |
|
578 | - EE_System::instance()->initialize_db_if_no_migrations_required(true); |
|
579 | - EE_System::instance()->redirect_to_about_ee(); |
|
580 | - } |
|
581 | - |
|
582 | - |
|
583 | - |
|
584 | - /** |
|
585 | - * Deletes ALL EE tables, Records, and Options from the database. |
|
586 | - */ |
|
587 | - public function _delete_db() |
|
588 | - { |
|
589 | - EE_Maintenance_Mode::instance()->set_maintenance_level(EE_Maintenance_Mode::level_0_not_in_maintenance); |
|
590 | - EEH_Activation::delete_all_espresso_cpt_data(); |
|
591 | - EEH_Activation::delete_all_espresso_tables_and_data(); |
|
592 | - EEH_Activation::remove_cron_tasks(); |
|
593 | - EEH_Activation::deactivate_event_espresso(); |
|
594 | - wp_safe_redirect(admin_url('plugins.php')); |
|
595 | - exit; |
|
596 | - } |
|
597 | - |
|
598 | - |
|
599 | - |
|
600 | - /** |
|
601 | - * sets up EE4 to rerun the migrations from ee3 to ee4 |
|
602 | - */ |
|
603 | - public function _rerun_migration_from_ee3() |
|
604 | - { |
|
605 | - EE_Maintenance_Mode::instance()->set_maintenance_level(EE_Maintenance_Mode::level_0_not_in_maintenance); |
|
606 | - EEH_Activation::delete_all_espresso_cpt_data(); |
|
607 | - EEH_Activation::delete_all_espresso_tables_and_data(false); |
|
608 | - //set the db state to something that will require migrations |
|
609 | - update_option(EE_Data_Migration_Manager::current_database_state, '3.1.36.0'); |
|
610 | - EE_Maintenance_Mode::instance()->set_maintenance_level(EE_Maintenance_Mode::level_2_complete_maintenance); |
|
611 | - $this->_redirect_after_action(true, esc_html__("Database", 'event_espresso'), esc_html__("reset", 'event_espresso')); |
|
612 | - } |
|
613 | - |
|
614 | - |
|
615 | - |
|
616 | - //none of the below group are currently used for Gateway Settings |
|
617 | - protected function _add_screen_options() |
|
618 | - { |
|
619 | - } |
|
620 | - |
|
621 | - |
|
622 | - |
|
623 | - protected function _add_feature_pointers() |
|
624 | - { |
|
625 | - } |
|
626 | - |
|
32 | + /** |
|
33 | + * @var EE_Datetime_Offset_Fix_Form |
|
34 | + */ |
|
35 | + protected $datetime_fix_offset_form; |
|
36 | + |
|
37 | + |
|
38 | + |
|
39 | + protected function _init_page_props() |
|
40 | + { |
|
41 | + $this->page_slug = EE_MAINTENANCE_PG_SLUG; |
|
42 | + $this->page_label = EE_MAINTENANCE_LABEL; |
|
43 | + $this->_admin_base_url = EE_MAINTENANCE_ADMIN_URL; |
|
44 | + $this->_admin_base_path = EE_MAINTENANCE_ADMIN; |
|
45 | + } |
|
46 | + |
|
47 | + |
|
48 | + |
|
49 | + protected function _ajax_hooks() |
|
50 | + { |
|
51 | + add_action('wp_ajax_migration_step', array($this, 'migration_step')); |
|
52 | + add_action('wp_ajax_add_error_to_migrations_ran', array($this, 'add_error_to_migrations_ran')); |
|
53 | + } |
|
54 | + |
|
55 | + |
|
56 | + |
|
57 | + protected function _define_page_props() |
|
58 | + { |
|
59 | + $this->_admin_page_title = EE_MAINTENANCE_LABEL; |
|
60 | + $this->_labels = array( |
|
61 | + 'buttons' => array( |
|
62 | + 'reset_reservations' => esc_html__('Reset Ticket and Datetime Reserved Counts', 'event_espresso'), |
|
63 | + 'reset_capabilities' => esc_html__('Reset Event Espresso Capabilities', 'event_espresso'), |
|
64 | + ), |
|
65 | + ); |
|
66 | + } |
|
67 | + |
|
68 | + |
|
69 | + |
|
70 | + protected function _set_page_routes() |
|
71 | + { |
|
72 | + $this->_page_routes = array( |
|
73 | + 'default' => array( |
|
74 | + 'func' => '_maintenance', |
|
75 | + 'capability' => 'manage_options', |
|
76 | + ), |
|
77 | + 'change_maintenance_level' => array( |
|
78 | + 'func' => '_change_maintenance_level', |
|
79 | + 'capability' => 'manage_options', |
|
80 | + 'noheader' => true, |
|
81 | + ), |
|
82 | + 'system_status' => array( |
|
83 | + 'func' => '_system_status', |
|
84 | + 'capability' => 'manage_options', |
|
85 | + ), |
|
86 | + 'download_system_status' => array( |
|
87 | + 'func' => '_download_system_status', |
|
88 | + 'capability' => 'manage_options', |
|
89 | + 'noheader' => true, |
|
90 | + ), |
|
91 | + 'send_migration_crash_report' => array( |
|
92 | + 'func' => '_send_migration_crash_report', |
|
93 | + 'capability' => 'manage_options', |
|
94 | + 'noheader' => true, |
|
95 | + ), |
|
96 | + 'confirm_migration_crash_report_sent' => array( |
|
97 | + 'func' => '_confirm_migration_crash_report_sent', |
|
98 | + 'capability' => 'manage_options', |
|
99 | + ), |
|
100 | + 'data_reset' => array( |
|
101 | + 'func' => '_data_reset_and_delete', |
|
102 | + 'capability' => 'manage_options', |
|
103 | + ), |
|
104 | + 'reset_db' => array( |
|
105 | + 'func' => '_reset_db', |
|
106 | + 'capability' => 'manage_options', |
|
107 | + 'noheader' => true, |
|
108 | + 'args' => array('nuke_old_ee4_data' => true), |
|
109 | + ), |
|
110 | + 'start_with_fresh_ee4_db' => array( |
|
111 | + 'func' => '_reset_db', |
|
112 | + 'capability' => 'manage_options', |
|
113 | + 'noheader' => true, |
|
114 | + 'args' => array('nuke_old_ee4_data' => false), |
|
115 | + ), |
|
116 | + 'delete_db' => array( |
|
117 | + 'func' => '_delete_db', |
|
118 | + 'capability' => 'manage_options', |
|
119 | + 'noheader' => true, |
|
120 | + ), |
|
121 | + 'rerun_migration_from_ee3' => array( |
|
122 | + 'func' => '_rerun_migration_from_ee3', |
|
123 | + 'capability' => 'manage_options', |
|
124 | + 'noheader' => true, |
|
125 | + ), |
|
126 | + 'reset_reservations' => array( |
|
127 | + 'func' => '_reset_reservations', |
|
128 | + 'capability' => 'manage_options', |
|
129 | + 'noheader' => true, |
|
130 | + ), |
|
131 | + 'reset_capabilities' => array( |
|
132 | + 'func' => '_reset_capabilities', |
|
133 | + 'capability' => 'manage_options', |
|
134 | + 'noheader' => true, |
|
135 | + ), |
|
136 | + 'reattempt_migration' => array( |
|
137 | + 'func' => '_reattempt_migration', |
|
138 | + 'capability' => 'manage_options', |
|
139 | + 'noheader' => true, |
|
140 | + ), |
|
141 | + 'datetime_tools' => array( |
|
142 | + 'func' => '_datetime_tools', |
|
143 | + 'capability' => 'manage_options' |
|
144 | + ), |
|
145 | + 'run_datetime_offset_fix' => array( |
|
146 | + 'func' => '_apply_datetime_offset', |
|
147 | + 'noheader' => true, |
|
148 | + 'headers_sent_route' => 'datetime_tools', |
|
149 | + 'capability' => 'manage_options' |
|
150 | + ) |
|
151 | + ); |
|
152 | + } |
|
153 | + |
|
154 | + |
|
155 | + |
|
156 | + protected function _set_page_config() |
|
157 | + { |
|
158 | + $this->_page_config = array( |
|
159 | + 'default' => array( |
|
160 | + 'nav' => array( |
|
161 | + 'label' => esc_html__('Maintenance', 'event_espresso'), |
|
162 | + 'order' => 10, |
|
163 | + ), |
|
164 | + 'require_nonce' => false, |
|
165 | + ), |
|
166 | + 'data_reset' => array( |
|
167 | + 'nav' => array( |
|
168 | + 'label' => esc_html__('Reset/Delete Data', 'event_espresso'), |
|
169 | + 'order' => 20, |
|
170 | + ), |
|
171 | + 'require_nonce' => false, |
|
172 | + ), |
|
173 | + 'datetime_tools' => array( |
|
174 | + 'nav' => array( |
|
175 | + 'label' => esc_html__('Datetime Utilities', 'event_espresso'), |
|
176 | + 'order' => 25 |
|
177 | + ), |
|
178 | + 'require_nonce' => false, |
|
179 | + ), |
|
180 | + 'system_status' => array( |
|
181 | + 'nav' => array( |
|
182 | + 'label' => esc_html__("System Information", "event_espresso"), |
|
183 | + 'order' => 30, |
|
184 | + ), |
|
185 | + 'require_nonce' => false, |
|
186 | + ), |
|
187 | + ); |
|
188 | + } |
|
189 | + |
|
190 | + |
|
191 | + |
|
192 | + /** |
|
193 | + * default maintenance page. If we're in maintenance mode level 2, then we need to show |
|
194 | + * the migration scripts and all that UI. |
|
195 | + */ |
|
196 | + public function _maintenance() |
|
197 | + { |
|
198 | + //it all depends if we're in maintenance model level 1 (frontend-only) or |
|
199 | + //level 2 (everything except maintenance page) |
|
200 | + try { |
|
201 | + //get the current maintenance level and check if |
|
202 | + //we are removed |
|
203 | + $mm = EE_Maintenance_Mode::instance()->level(); |
|
204 | + $placed_in_mm = EE_Maintenance_Mode::instance()->set_maintenance_mode_if_db_old(); |
|
205 | + if ($mm == EE_Maintenance_Mode::level_2_complete_maintenance && ! $placed_in_mm) { |
|
206 | + //we just took the site out of maintenance mode, so notify the user. |
|
207 | + //unfortunately this message appears to be echoed on the NEXT page load... |
|
208 | + //oh well, we should really be checking for this on addon deactivation anyways |
|
209 | + EE_Error::add_attention(__('Site taken out of maintenance mode because no data migration scripts are required', |
|
210 | + 'event_espresso')); |
|
211 | + $this->_process_notices(array('page' => 'espresso_maintenance_settings'), false); |
|
212 | + } |
|
213 | + //in case an exception is thrown while trying to handle migrations |
|
214 | + switch (EE_Maintenance_Mode::instance()->level()) { |
|
215 | + case EE_Maintenance_Mode::level_0_not_in_maintenance: |
|
216 | + case EE_Maintenance_Mode::level_1_frontend_only_maintenance: |
|
217 | + $show_maintenance_switch = true; |
|
218 | + $show_backup_db_text = false; |
|
219 | + $show_migration_progress = false; |
|
220 | + $script_names = array(); |
|
221 | + $addons_should_be_upgraded_first = false; |
|
222 | + break; |
|
223 | + case EE_Maintenance_Mode::level_2_complete_maintenance: |
|
224 | + $show_maintenance_switch = false; |
|
225 | + $show_migration_progress = true; |
|
226 | + if (isset($this->_req_data['continue_migration'])) { |
|
227 | + $show_backup_db_text = false; |
|
228 | + } else { |
|
229 | + $show_backup_db_text = true; |
|
230 | + } |
|
231 | + $scripts_needing_to_run = EE_Data_Migration_Manager::instance() |
|
232 | + ->check_for_applicable_data_migration_scripts(); |
|
233 | + $addons_should_be_upgraded_first = EE_Data_Migration_Manager::instance()->addons_need_updating(); |
|
234 | + $script_names = array(); |
|
235 | + $current_script = null; |
|
236 | + foreach ($scripts_needing_to_run as $script) { |
|
237 | + if ($script instanceof EE_Data_Migration_Script_Base) { |
|
238 | + if ( ! $current_script) { |
|
239 | + $current_script = $script; |
|
240 | + $current_script->migration_page_hooks(); |
|
241 | + } |
|
242 | + $script_names[] = $script->pretty_name(); |
|
243 | + } |
|
244 | + } |
|
245 | + break; |
|
246 | + } |
|
247 | + $most_recent_migration = EE_Data_Migration_Manager::instance()->get_last_ran_script(true); |
|
248 | + $exception_thrown = false; |
|
249 | + } catch (EE_Error $e) { |
|
250 | + EE_Data_Migration_Manager::instance()->add_error_to_migrations_ran($e->getMessage()); |
|
251 | + //now, just so we can display the page correctly, make a error migration script stage object |
|
252 | + //and also put the error on it. It only persists for the duration of this request |
|
253 | + $most_recent_migration = new EE_DMS_Unknown_1_0_0(); |
|
254 | + $most_recent_migration->add_error($e->getMessage()); |
|
255 | + $exception_thrown = true; |
|
256 | + } |
|
257 | + $current_db_state = EE_Data_Migration_Manager::instance()->ensure_current_database_state_is_set(); |
|
258 | + $current_db_state = str_replace('.decaf', '', $current_db_state); |
|
259 | + if ($exception_thrown |
|
260 | + || ($most_recent_migration |
|
261 | + && $most_recent_migration instanceof EE_Data_Migration_Script_Base |
|
262 | + && $most_recent_migration->is_broken() |
|
263 | + ) |
|
264 | + ) { |
|
265 | + $this->_template_path = EE_MAINTENANCE_TEMPLATE_PATH . 'ee_migration_was_borked_page.template.php'; |
|
266 | + $this->_template_args['support_url'] = 'http://eventespresso.com/support/forums/'; |
|
267 | + $this->_template_args['next_url'] = EEH_URL::add_query_args_and_nonce(array('action' => 'confirm_migration_crash_report_sent', |
|
268 | + 'success' => '0', |
|
269 | + ), EE_MAINTENANCE_ADMIN_URL); |
|
270 | + } elseif ($addons_should_be_upgraded_first) { |
|
271 | + $this->_template_path = EE_MAINTENANCE_TEMPLATE_PATH . 'ee_upgrade_addons_before_migrating.template.php'; |
|
272 | + } else { |
|
273 | + if ($most_recent_migration |
|
274 | + && $most_recent_migration instanceof EE_Data_Migration_Script_Base |
|
275 | + && $most_recent_migration->can_continue() |
|
276 | + ) { |
|
277 | + $show_backup_db_text = false; |
|
278 | + $show_continue_current_migration_script = true; |
|
279 | + $show_most_recent_migration = true; |
|
280 | + } elseif (isset($this->_req_data['continue_migration'])) { |
|
281 | + $show_most_recent_migration = true; |
|
282 | + $show_continue_current_migration_script = false; |
|
283 | + } else { |
|
284 | + $show_most_recent_migration = false; |
|
285 | + $show_continue_current_migration_script = false; |
|
286 | + } |
|
287 | + if (isset($current_script)) { |
|
288 | + $migrates_to = $current_script->migrates_to_version(); |
|
289 | + $plugin_slug = $migrates_to['slug']; |
|
290 | + $new_version = $migrates_to['version']; |
|
291 | + $this->_template_args = array_merge($this->_template_args, array( |
|
292 | + 'current_db_state' => sprintf(__("EE%s (%s)", "event_espresso"), |
|
293 | + isset($current_db_state[$plugin_slug]) ? $current_db_state[$plugin_slug] : 3, $plugin_slug), |
|
294 | + 'next_db_state' => isset($current_script) ? sprintf(__("EE%s (%s)", 'event_espresso'), |
|
295 | + $new_version, $plugin_slug) : null, |
|
296 | + )); |
|
297 | + } else { |
|
298 | + $this->_template_args['current_db_state'] = null; |
|
299 | + $this->_template_args['next_db_state'] = null; |
|
300 | + } |
|
301 | + $this->_template_path = EE_MAINTENANCE_TEMPLATE_PATH . 'ee_migration_page.template.php'; |
|
302 | + $this->_template_args = array_merge( |
|
303 | + $this->_template_args, |
|
304 | + array( |
|
305 | + 'show_most_recent_migration' => $show_most_recent_migration, |
|
306 | + //flag for showing the most recent migration's status and/or errors |
|
307 | + 'show_migration_progress' => $show_migration_progress, |
|
308 | + //flag for showing the option to run migrations and see their progress |
|
309 | + 'show_backup_db_text' => $show_backup_db_text, |
|
310 | + //flag for showing text telling the user to backup their DB |
|
311 | + 'show_maintenance_switch' => $show_maintenance_switch, |
|
312 | + //flag for showing the option to change maintenance mode between levels 0 and 1 |
|
313 | + 'script_names' => $script_names, |
|
314 | + //array of names of scripts that have run |
|
315 | + 'show_continue_current_migration_script' => $show_continue_current_migration_script, |
|
316 | + //flag to change wording to indicating that we're only CONTINUING a migration script (somehow it got interrupted0 |
|
317 | + 'reset_db_page_link' => EE_Admin_Page::add_query_args_and_nonce(array('action' => 'reset_db'), |
|
318 | + EE_MAINTENANCE_ADMIN_URL), |
|
319 | + 'data_reset_page' => EE_Admin_Page::add_query_args_and_nonce(array('action' => 'data_reset'), |
|
320 | + EE_MAINTENANCE_ADMIN_URL), |
|
321 | + 'update_migration_script_page_link' => EE_Admin_Page::add_query_args_and_nonce(array('action' => 'change_maintenance_level'), |
|
322 | + EE_MAINTENANCE_ADMIN_URL), |
|
323 | + 'ultimate_db_state' => sprintf(__("EE%s", 'event_espresso'), |
|
324 | + espresso_version()), |
|
325 | + ) |
|
326 | + ); |
|
327 | + //make sure we have the form fields helper available. It usually is, but sometimes it isn't |
|
328 | + } |
|
329 | + $this->_template_args['most_recent_migration'] = $most_recent_migration;//the actual most recently ran migration |
|
330 | + //now render the migration options part, and put it in a variable |
|
331 | + $migration_options_template_file = apply_filters( |
|
332 | + 'FHEE__ee_migration_page__migration_options_template', |
|
333 | + EE_MAINTENANCE_TEMPLATE_PATH . 'migration_options_from_ee4.template.php' |
|
334 | + ); |
|
335 | + $migration_options_html = EEH_Template::display_template($migration_options_template_file, $this->_template_args,true); |
|
336 | + $this->_template_args['migration_options_html'] = $migration_options_html; |
|
337 | + $this->_template_args['admin_page_content'] = EEH_Template::display_template($this->_template_path, |
|
338 | + $this->_template_args, true); |
|
339 | + $this->display_admin_page_with_sidebar(); |
|
340 | + } |
|
341 | + |
|
342 | + |
|
343 | + |
|
344 | + /** |
|
345 | + * returns JSON and executes another step of the currently-executing data migration (called via ajax) |
|
346 | + */ |
|
347 | + public function migration_step() |
|
348 | + { |
|
349 | + $this->_template_args['data'] = EE_Data_Migration_Manager::instance()->response_to_migration_ajax_request(); |
|
350 | + $this->_return_json(); |
|
351 | + } |
|
352 | + |
|
353 | + |
|
354 | + |
|
355 | + /** |
|
356 | + * Can be used by js when it notices a response with HTML in it in order |
|
357 | + * to log the malformed response |
|
358 | + */ |
|
359 | + public function add_error_to_migrations_ran() |
|
360 | + { |
|
361 | + EE_Data_Migration_Manager::instance()->add_error_to_migrations_ran($this->_req_data['message']); |
|
362 | + $this->_template_args['data'] = array('ok' => true); |
|
363 | + $this->_return_json(); |
|
364 | + } |
|
365 | + |
|
366 | + |
|
367 | + |
|
368 | + /** |
|
369 | + * changes the maintenance level, provided there are still no migration scripts that should run |
|
370 | + */ |
|
371 | + public function _change_maintenance_level() |
|
372 | + { |
|
373 | + $new_level = absint($this->_req_data['maintenance_mode_level']); |
|
374 | + if ( ! EE_Data_Migration_Manager::instance()->check_for_applicable_data_migration_scripts()) { |
|
375 | + EE_Maintenance_Mode::instance()->set_maintenance_level($new_level); |
|
376 | + $success = true; |
|
377 | + } else { |
|
378 | + EE_Maintenance_Mode::instance()->set_maintenance_mode_if_db_old(); |
|
379 | + $success = false; |
|
380 | + } |
|
381 | + $this->_redirect_after_action($success, 'Maintenance Mode', esc_html__("Updated", "event_espresso")); |
|
382 | + } |
|
383 | + |
|
384 | + |
|
385 | + |
|
386 | + /** |
|
387 | + * a tab with options for resetting and/or deleting EE data |
|
388 | + * |
|
389 | + * @throws \EE_Error |
|
390 | + * @throws \DomainException |
|
391 | + */ |
|
392 | + public function _data_reset_and_delete() |
|
393 | + { |
|
394 | + $this->_template_path = EE_MAINTENANCE_TEMPLATE_PATH . 'ee_data_reset_and_delete.template.php'; |
|
395 | + $this->_template_args['reset_reservations_button'] = $this->get_action_link_or_button( |
|
396 | + 'reset_reservations', |
|
397 | + 'reset_reservations', |
|
398 | + array(), |
|
399 | + 'button button-primary ee-confirm', |
|
400 | + '', |
|
401 | + false |
|
402 | + ); |
|
403 | + $this->_template_args['reset_capabilities_button'] = $this->get_action_link_or_button( |
|
404 | + 'reset_capabilities', |
|
405 | + 'reset_capabilities', |
|
406 | + array(), |
|
407 | + 'button button-primary ee-confirm', |
|
408 | + '', |
|
409 | + false |
|
410 | + ); |
|
411 | + $this->_template_args['delete_db_url'] = EE_Admin_Page::add_query_args_and_nonce( |
|
412 | + array('action' => 'delete_db'), |
|
413 | + EE_MAINTENANCE_ADMIN_URL |
|
414 | + ); |
|
415 | + $this->_template_args['reset_db_url'] = EE_Admin_Page::add_query_args_and_nonce( |
|
416 | + array('action' => 'reset_db'), |
|
417 | + EE_MAINTENANCE_ADMIN_URL |
|
418 | + ); |
|
419 | + $this->_template_args['admin_page_content'] = EEH_Template::display_template( |
|
420 | + $this->_template_path, |
|
421 | + $this->_template_args, |
|
422 | + true |
|
423 | + ); |
|
424 | + $this->display_admin_page_with_sidebar(); |
|
425 | + } |
|
426 | + |
|
427 | + |
|
428 | + |
|
429 | + protected function _reset_reservations() |
|
430 | + { |
|
431 | + if(\EED_Ticket_Sales_Monitor::reset_reservation_counts()) { |
|
432 | + EE_Error::add_success( |
|
433 | + __( |
|
434 | + 'Ticket and datetime reserved counts have been successfully reset.', |
|
435 | + 'event_espresso' |
|
436 | + ) |
|
437 | + ); |
|
438 | + } else { |
|
439 | + EE_Error::add_success( |
|
440 | + __( |
|
441 | + 'Ticket and datetime reserved counts were correct and did not need resetting.', |
|
442 | + 'event_espresso' |
|
443 | + ) |
|
444 | + ); |
|
445 | + } |
|
446 | + $this->_redirect_after_action(true, '', '', array('action' => 'data_reset'), true); |
|
447 | + } |
|
448 | + |
|
449 | + |
|
450 | + |
|
451 | + protected function _reset_capabilities() |
|
452 | + { |
|
453 | + EE_Registry::instance()->CAP->init_caps(true); |
|
454 | + EE_Error::add_success(__('Default Event Espresso capabilities have been restored for all current roles.', |
|
455 | + 'event_espresso')); |
|
456 | + $this->_redirect_after_action(false, '', '', array('action' => 'data_reset'), true); |
|
457 | + } |
|
458 | + |
|
459 | + |
|
460 | + |
|
461 | + /** |
|
462 | + * resets the DMSs so we can attempt to continue migrating after a fatal error |
|
463 | + * (only a good idea when someone has somehow tried ot fix whatever caused |
|
464 | + * the fatal error in teh first place) |
|
465 | + */ |
|
466 | + protected function _reattempt_migration() |
|
467 | + { |
|
468 | + EE_Data_Migration_Manager::instance()->reattempt(); |
|
469 | + $this->_redirect_after_action(false, '', '', array('action' => 'default'), true); |
|
470 | + } |
|
471 | + |
|
472 | + |
|
473 | + |
|
474 | + /** |
|
475 | + * shows the big ol' System Information page |
|
476 | + */ |
|
477 | + public function _system_status() |
|
478 | + { |
|
479 | + $this->_template_path = EE_MAINTENANCE_TEMPLATE_PATH . 'ee_system_stati_page.template.php'; |
|
480 | + $this->_template_args['system_stati'] = EEM_System_Status::instance()->get_system_stati(); |
|
481 | + $this->_template_args['download_system_status_url'] = EE_Admin_Page::add_query_args_and_nonce( |
|
482 | + array( |
|
483 | + 'action' => 'download_system_status', |
|
484 | + ), |
|
485 | + EE_MAINTENANCE_ADMIN_URL |
|
486 | + ); |
|
487 | + $this->_template_args['admin_page_content'] = EEH_Template::display_template($this->_template_path, |
|
488 | + $this->_template_args, true); |
|
489 | + $this->display_admin_page_with_sidebar(); |
|
490 | + } |
|
491 | + |
|
492 | + /** |
|
493 | + * Downloads an HTML file of the system status that can be easily stored or emailed |
|
494 | + */ |
|
495 | + public function _download_system_status() |
|
496 | + { |
|
497 | + $status_info = EEM_System_Status::instance()->get_system_stati(); |
|
498 | + header( 'Content-Disposition: attachment' ); |
|
499 | + header( "Content-Disposition: attachment; filename=system_status_" . sanitize_key( site_url() ) . ".html" ); |
|
500 | + echo "<style>table{border:1px solid darkgrey;}td{vertical-align:top}</style>"; |
|
501 | + echo "<h1>System Information for " . site_url() . "</h1>"; |
|
502 | + echo EEH_Template::layout_array_as_table( $status_info ); |
|
503 | + die; |
|
504 | + } |
|
505 | + |
|
506 | + |
|
507 | + |
|
508 | + public function _send_migration_crash_report() |
|
509 | + { |
|
510 | + $from = $this->_req_data['from']; |
|
511 | + $from_name = $this->_req_data['from_name']; |
|
512 | + $body = $this->_req_data['body']; |
|
513 | + try { |
|
514 | + $success = wp_mail(EE_SUPPORT_EMAIL, |
|
515 | + 'Migration Crash Report', |
|
516 | + $body . "/r/n<br>" . print_r(EEM_System_Status::instance()->get_system_stati(), true), |
|
517 | + array( |
|
518 | + "from:$from_name<$from>", |
|
519 | + // 'content-type:text/html charset=UTF-8' |
|
520 | + )); |
|
521 | + } catch (Exception $e) { |
|
522 | + $success = false; |
|
523 | + } |
|
524 | + $this->_redirect_after_action($success, esc_html__("Migration Crash Report", "event_espresso"), |
|
525 | + esc_html__("sent", "event_espresso"), |
|
526 | + array('success' => $success, 'action' => 'confirm_migration_crash_report_sent')); |
|
527 | + } |
|
528 | + |
|
529 | + |
|
530 | + |
|
531 | + public function _confirm_migration_crash_report_sent() |
|
532 | + { |
|
533 | + try { |
|
534 | + $most_recent_migration = EE_Data_Migration_Manager::instance()->get_last_ran_script(true); |
|
535 | + } catch (EE_Error $e) { |
|
536 | + EE_Data_Migration_Manager::instance()->add_error_to_migrations_ran($e->getMessage()); |
|
537 | + //now, just so we can display the page correctly, make a error migration script stage object |
|
538 | + //and also put the error on it. It only persists for the duration of this request |
|
539 | + $most_recent_migration = new EE_DMS_Unknown_1_0_0(); |
|
540 | + $most_recent_migration->add_error($e->getMessage()); |
|
541 | + } |
|
542 | + $success = $this->_req_data['success'] == '1' ? true : false; |
|
543 | + $this->_template_args['success'] = $success; |
|
544 | + $this->_template_args['most_recent_migration'] = $most_recent_migration; |
|
545 | + $this->_template_args['reset_db_action_url'] = EE_Admin_Page::add_query_args_and_nonce(array('action' => 'reset_db'), |
|
546 | + EE_MAINTENANCE_ADMIN_URL); |
|
547 | + $this->_template_args['reset_db_page_url'] = EE_Admin_Page::add_query_args_and_nonce(array('action' => 'data_reset'), |
|
548 | + EE_MAINTENANCE_ADMIN_URL); |
|
549 | + $this->_template_args['reattempt_action_url'] = EE_Admin_Page::add_query_args_and_nonce(array('action' => 'reattempt_migration'), |
|
550 | + EE_MAINTENANCE_ADMIN_URL); |
|
551 | + $this->_template_path = EE_MAINTENANCE_TEMPLATE_PATH . 'ee_confirm_migration_crash_report_sent.template.php'; |
|
552 | + $this->_template_args['admin_page_content'] = EEH_Template::display_template($this->_template_path, |
|
553 | + $this->_template_args, true); |
|
554 | + $this->display_admin_page_with_sidebar(); |
|
555 | + } |
|
556 | + |
|
557 | + |
|
558 | + |
|
559 | + /** |
|
560 | + * Resets the entire EE4 database. |
|
561 | + * Currently basically only sets up ee4 database for a fresh install- doesn't |
|
562 | + * actually clean out the old wp options, or cpts (although does erase old ee table data) |
|
563 | + * |
|
564 | + * @param boolean $nuke_old_ee4_data controls whether or not we |
|
565 | + * destroy the old ee4 data, or just try initializing ee4 default data |
|
566 | + */ |
|
567 | + public function _reset_db($nuke_old_ee4_data = true) |
|
568 | + { |
|
569 | + EE_Maintenance_Mode::instance()->set_maintenance_level(EE_Maintenance_Mode::level_0_not_in_maintenance); |
|
570 | + if ($nuke_old_ee4_data) { |
|
571 | + EEH_Activation::delete_all_espresso_cpt_data(); |
|
572 | + EEH_Activation::delete_all_espresso_tables_and_data(false); |
|
573 | + EEH_Activation::remove_cron_tasks(); |
|
574 | + } |
|
575 | + //make sure when we reset the registry's config that it |
|
576 | + //switches to using the new singleton |
|
577 | + EE_Registry::instance()->CFG = EE_Registry::instance()->CFG->reset(true); |
|
578 | + EE_System::instance()->initialize_db_if_no_migrations_required(true); |
|
579 | + EE_System::instance()->redirect_to_about_ee(); |
|
580 | + } |
|
581 | + |
|
582 | + |
|
583 | + |
|
584 | + /** |
|
585 | + * Deletes ALL EE tables, Records, and Options from the database. |
|
586 | + */ |
|
587 | + public function _delete_db() |
|
588 | + { |
|
589 | + EE_Maintenance_Mode::instance()->set_maintenance_level(EE_Maintenance_Mode::level_0_not_in_maintenance); |
|
590 | + EEH_Activation::delete_all_espresso_cpt_data(); |
|
591 | + EEH_Activation::delete_all_espresso_tables_and_data(); |
|
592 | + EEH_Activation::remove_cron_tasks(); |
|
593 | + EEH_Activation::deactivate_event_espresso(); |
|
594 | + wp_safe_redirect(admin_url('plugins.php')); |
|
595 | + exit; |
|
596 | + } |
|
597 | + |
|
598 | + |
|
599 | + |
|
600 | + /** |
|
601 | + * sets up EE4 to rerun the migrations from ee3 to ee4 |
|
602 | + */ |
|
603 | + public function _rerun_migration_from_ee3() |
|
604 | + { |
|
605 | + EE_Maintenance_Mode::instance()->set_maintenance_level(EE_Maintenance_Mode::level_0_not_in_maintenance); |
|
606 | + EEH_Activation::delete_all_espresso_cpt_data(); |
|
607 | + EEH_Activation::delete_all_espresso_tables_and_data(false); |
|
608 | + //set the db state to something that will require migrations |
|
609 | + update_option(EE_Data_Migration_Manager::current_database_state, '3.1.36.0'); |
|
610 | + EE_Maintenance_Mode::instance()->set_maintenance_level(EE_Maintenance_Mode::level_2_complete_maintenance); |
|
611 | + $this->_redirect_after_action(true, esc_html__("Database", 'event_espresso'), esc_html__("reset", 'event_espresso')); |
|
612 | + } |
|
613 | + |
|
614 | + |
|
615 | + |
|
616 | + //none of the below group are currently used for Gateway Settings |
|
617 | + protected function _add_screen_options() |
|
618 | + { |
|
619 | + } |
|
620 | + |
|
621 | + |
|
622 | + |
|
623 | + protected function _add_feature_pointers() |
|
624 | + { |
|
625 | + } |
|
626 | + |
|
627 | 627 | |
628 | 628 | |
629 | - public function admin_init() |
|
630 | - { |
|
631 | - } |
|
632 | - |
|
633 | - |
|
634 | - |
|
635 | - public function admin_notices() |
|
636 | - { |
|
637 | - } |
|
638 | - |
|
629 | + public function admin_init() |
|
630 | + { |
|
631 | + } |
|
632 | + |
|
633 | + |
|
634 | + |
|
635 | + public function admin_notices() |
|
636 | + { |
|
637 | + } |
|
638 | + |
|
639 | 639 | |
640 | 640 | |
641 | - public function admin_footer_scripts() |
|
642 | - { |
|
643 | - } |
|
641 | + public function admin_footer_scripts() |
|
642 | + { |
|
643 | + } |
|
644 | 644 | |
645 | 645 | |
646 | 646 | |
647 | - public function load_scripts_styles() |
|
648 | - { |
|
649 | - wp_enqueue_script('ee_admin_js'); |
|
647 | + public function load_scripts_styles() |
|
648 | + { |
|
649 | + wp_enqueue_script('ee_admin_js'); |
|
650 | 650 | // wp_enqueue_media(); |
651 | 651 | // wp_enqueue_script('media-upload'); |
652 | - wp_enqueue_script('ee-maintenance', EE_MAINTENANCE_ASSETS_URL . 'ee-maintenance.js', array('jquery'), |
|
653 | - EVENT_ESPRESSO_VERSION, true); |
|
654 | - wp_register_style('espresso_maintenance', EE_MAINTENANCE_ASSETS_URL . 'ee-maintenance.css', array(), |
|
655 | - EVENT_ESPRESSO_VERSION); |
|
656 | - wp_enqueue_style('espresso_maintenance'); |
|
657 | - //localize script stuff |
|
658 | - wp_localize_script('ee-maintenance', 'ee_maintenance', array( |
|
659 | - 'migrating' => esc_html__("Updating Database...", "event_espresso"), |
|
660 | - 'next' => esc_html__("Next", "event_espresso"), |
|
661 | - 'fatal_error' => esc_html__("A Fatal Error Has Occurred", "event_espresso"), |
|
662 | - 'click_next_when_ready' => esc_html__( |
|
663 | - "The current Database Update has ended. Click 'next' when ready to proceed", |
|
664 | - "event_espresso" |
|
665 | - ), |
|
666 | - 'status_no_more_migration_scripts' => EE_Data_Migration_Manager::status_no_more_migration_scripts, |
|
667 | - 'status_fatal_error' => EE_Data_Migration_Manager::status_fatal_error, |
|
668 | - 'status_completed' => EE_Data_Migration_Manager::status_completed, |
|
669 | - 'confirm' => esc_html__( |
|
670 | - 'Are you sure you want to do this? It CANNOT be undone!', |
|
671 | - 'event_espresso' |
|
672 | - ), |
|
673 | - 'confirm_skip_migration' => esc_html__( |
|
674 | - 'You have chosen to NOT migrate your existing data. Are you sure you want to continue?', |
|
675 | - 'event_espresso' |
|
676 | - ) |
|
677 | - )); |
|
678 | - } |
|
679 | - |
|
680 | - |
|
681 | - |
|
682 | - public function load_scripts_styles_default() |
|
683 | - { |
|
684 | - //styles |
|
652 | + wp_enqueue_script('ee-maintenance', EE_MAINTENANCE_ASSETS_URL . 'ee-maintenance.js', array('jquery'), |
|
653 | + EVENT_ESPRESSO_VERSION, true); |
|
654 | + wp_register_style('espresso_maintenance', EE_MAINTENANCE_ASSETS_URL . 'ee-maintenance.css', array(), |
|
655 | + EVENT_ESPRESSO_VERSION); |
|
656 | + wp_enqueue_style('espresso_maintenance'); |
|
657 | + //localize script stuff |
|
658 | + wp_localize_script('ee-maintenance', 'ee_maintenance', array( |
|
659 | + 'migrating' => esc_html__("Updating Database...", "event_espresso"), |
|
660 | + 'next' => esc_html__("Next", "event_espresso"), |
|
661 | + 'fatal_error' => esc_html__("A Fatal Error Has Occurred", "event_espresso"), |
|
662 | + 'click_next_when_ready' => esc_html__( |
|
663 | + "The current Database Update has ended. Click 'next' when ready to proceed", |
|
664 | + "event_espresso" |
|
665 | + ), |
|
666 | + 'status_no_more_migration_scripts' => EE_Data_Migration_Manager::status_no_more_migration_scripts, |
|
667 | + 'status_fatal_error' => EE_Data_Migration_Manager::status_fatal_error, |
|
668 | + 'status_completed' => EE_Data_Migration_Manager::status_completed, |
|
669 | + 'confirm' => esc_html__( |
|
670 | + 'Are you sure you want to do this? It CANNOT be undone!', |
|
671 | + 'event_espresso' |
|
672 | + ), |
|
673 | + 'confirm_skip_migration' => esc_html__( |
|
674 | + 'You have chosen to NOT migrate your existing data. Are you sure you want to continue?', |
|
675 | + 'event_espresso' |
|
676 | + ) |
|
677 | + )); |
|
678 | + } |
|
679 | + |
|
680 | + |
|
681 | + |
|
682 | + public function load_scripts_styles_default() |
|
683 | + { |
|
684 | + //styles |
|
685 | 685 | // wp_enqueue_style('ee-text-links'); |
686 | 686 | // //scripts |
687 | 687 | // wp_enqueue_script('ee-text-links'); |
688 | - } |
|
689 | - |
|
690 | - |
|
691 | - /** |
|
692 | - * Enqueue scripts and styles for the datetime tools page. |
|
693 | - */ |
|
694 | - public function load_scripts_styles_datetime_tools() |
|
695 | - { |
|
696 | - EE_Datepicker_Input::enqueue_styles_and_scripts(); |
|
697 | - } |
|
698 | - |
|
699 | - |
|
700 | - protected function _datetime_tools() |
|
701 | - { |
|
702 | - $form_action = EE_Admin_Page::add_query_args_and_nonce( |
|
703 | - array( |
|
704 | - 'action' => 'run_datetime_offset_fix', |
|
705 | - 'return_action' => $this->_req_action |
|
706 | - ), |
|
707 | - EE_MAINTENANCE_ADMIN_URL |
|
708 | - ); |
|
709 | - $form = $this->_get_datetime_offset_fix_form(); |
|
710 | - $this->_admin_page_title = esc_html__('Datetime Utilities', 'event_espresso'); |
|
711 | - $this->_template_args['admin_page_content'] = $form->form_open($form_action, 'post') |
|
712 | - . $form->get_html_and_js() |
|
713 | - . $form->form_close(); |
|
714 | - $this->display_admin_page_with_no_sidebar(); |
|
715 | - } |
|
716 | - |
|
717 | - |
|
718 | - |
|
719 | - protected function _get_datetime_offset_fix_form() |
|
720 | - { |
|
721 | - if (! $this->datetime_fix_offset_form instanceof EE_Form_Section_Proper) { |
|
722 | - $this->datetime_fix_offset_form = new EE_Form_Section_Proper( |
|
723 | - array( |
|
724 | - 'name' => 'datetime_offset_fix_option', |
|
725 | - 'layout_strategy' => new EE_Admin_Two_Column_Layout(), |
|
726 | - 'subsections' => array( |
|
727 | - 'title' => new EE_Form_Section_HTML( |
|
728 | - EEH_HTML::h2( |
|
729 | - esc_html__('Datetime Offset Tool', 'event_espresso') |
|
730 | - ) |
|
731 | - ), |
|
732 | - 'explanation' => new EE_Form_Section_HTML( |
|
733 | - EEH_HTML::p( |
|
734 | - esc_html__( |
|
735 | - 'Use this tool to automatically apply the provided offset to all Event Espresso records in your database that involve dates and times.', |
|
736 | - 'event_espresso' |
|
737 | - ) |
|
738 | - ) |
|
739 | - . EEH_HTML::p( |
|
740 | - esc_html__( |
|
741 | - 'Note: If you enter 1.25, that will result in the offset of 1 hour 15 minutes being applied. Decimals represent the fraction of hours, not minutes.', |
|
742 | - 'event_espresso' |
|
743 | - ) |
|
744 | - ) |
|
745 | - ), |
|
746 | - 'offset_input' => new EE_Float_Input( |
|
747 | - array( |
|
748 | - 'html_name' => 'offset_for_datetimes', |
|
749 | - 'html_label_text' => esc_html__( |
|
750 | - 'Offset to apply (in hours):', |
|
751 | - 'event_espresso' |
|
752 | - ), |
|
753 | - 'min_value' => '-12', |
|
754 | - 'max_value' => '14', |
|
755 | - 'step_value' => '.25', |
|
756 | - 'default' => DatetimeOffsetFix::getOffset() |
|
757 | - ) |
|
758 | - ), |
|
759 | - 'date_range_explanation' => new EE_Form_Section_HTML( |
|
760 | - EEH_HTML::p( |
|
761 | - esc_html__( |
|
762 | - 'Leave the following fields blank if you want the offset to be applied to all dates. If however, you want to just apply the offset to a specific range of dates you can restrict the offset application using these fields.', |
|
763 | - 'event_espresso' |
|
764 | - ) |
|
765 | - ) |
|
766 | - . EEH_HTML::p( |
|
767 | - EEH_HTML::strong( |
|
768 | - sprintf( |
|
769 | - esc_html__( |
|
770 | - 'Note: please enter the dates in UTC (You can use %1$sthis online tool%2$s to assist with conversions).', |
|
771 | - 'event_espresso' |
|
772 | - ), |
|
773 | - '<a href="https://www.timeanddate.com/worldclock/converter.html">', |
|
774 | - '</a>' |
|
775 | - ) |
|
776 | - ) |
|
777 | - ) |
|
778 | - ), |
|
779 | - 'date_range_start_date' => new EE_Datepicker_Input( |
|
780 | - array( |
|
781 | - 'html_name' => 'offset_date_start_range', |
|
782 | - 'html_label_text' => esc_html__( |
|
783 | - 'Start Date for dates the offset applied to:', |
|
784 | - 'event_espresso' |
|
785 | - ) |
|
786 | - ) |
|
787 | - ), |
|
788 | - 'date_range_end_date' => new EE_Datepicker_Input( |
|
789 | - array( |
|
790 | - 'html_name' => 'offset_date_end_range', |
|
791 | - 'html_label_text' => esc_html( |
|
792 | - 'End Date for dates the offset is applied to:', |
|
793 | - 'event_espresso' |
|
794 | - ) |
|
795 | - ) |
|
796 | - ), |
|
797 | - 'submit' => new EE_Submit_Input( |
|
798 | - array( |
|
799 | - 'html_label_text' => '', |
|
800 | - 'default' => esc_html__('Apply Offset', 'event_espresso') |
|
801 | - ) |
|
802 | - ), |
|
803 | - ) |
|
804 | - ) |
|
805 | - ); |
|
806 | - } |
|
807 | - return $this->datetime_fix_offset_form; |
|
808 | - } |
|
809 | - |
|
810 | - |
|
811 | - /** |
|
812 | - * Callback for the run_datetime_offset_fix route. |
|
813 | - * @throws EE_Error |
|
814 | - */ |
|
815 | - protected function _apply_datetime_offset() |
|
816 | - { |
|
817 | - if ($_SERVER['REQUEST_METHOD'] === 'POST') { |
|
818 | - $form = $this->_get_datetime_offset_fix_form(); |
|
819 | - $form->receive_form_submission($this->_req_data); |
|
820 | - if ($form->is_valid()) { |
|
821 | - //save offset data so batch processor can get it. |
|
822 | - DatetimeOffsetFix::updateOffset($form->get_input_value('offset_input')); |
|
823 | - $utc_timezone = new DateTimeZone('UTC'); |
|
824 | - $date_range_start_date = DateTime::createFromFormat( |
|
825 | - 'm/d/Y H:i:s', |
|
826 | - $form->get_input_value('date_range_start_date') . ' 00:00:00', |
|
827 | - $utc_timezone |
|
828 | - ); |
|
829 | - $date_range_end_date = DateTime::createFromFormat( |
|
830 | - 'm/d/Y H:i:s', |
|
831 | - $form->get_input_value('date_range_end_date') . ' 23:59:59', |
|
832 | - $utc_timezone |
|
833 | - ); |
|
834 | - if ($date_range_start_date instanceof DateTime) { |
|
835 | - DatetimeOffsetFix::updateStartDateRange(DbSafeDateTime::createFromDateTime($date_range_start_date)); |
|
836 | - } |
|
837 | - if ($date_range_end_date instanceof DateTime) { |
|
838 | - DatetimeOffsetFix::updateEndDateRange(DbSafeDateTime::createFromDateTime($date_range_end_date)); |
|
839 | - } |
|
840 | - //redirect to batch tool |
|
841 | - wp_redirect( |
|
842 | - EE_Admin_Page::add_query_args_and_nonce( |
|
843 | - array( |
|
844 | - 'page' => 'espresso_batch', |
|
845 | - 'batch' => 'job', |
|
846 | - 'label' => esc_html__('Applying Offset', 'event_espresso'), |
|
847 | - 'job_handler' => urlencode('EventEspressoBatchRequest\JobHandlers\DatetimeOffsetFix'), |
|
848 | - 'return_url' => urlencode( |
|
849 | - add_query_arg( |
|
850 | - array( |
|
851 | - 'action' => 'datetime_tools', |
|
852 | - ), |
|
853 | - EEH_URL::current_url_without_query_paramaters( |
|
854 | - array( |
|
855 | - 'return_action', |
|
856 | - 'run_datetime_offset_fix_nonce', |
|
857 | - 'return', |
|
858 | - 'datetime_tools_nonce' |
|
859 | - ) |
|
860 | - ) |
|
861 | - ) |
|
862 | - ) |
|
863 | - ), |
|
864 | - admin_url() |
|
865 | - ) |
|
866 | - ); |
|
867 | - exit; |
|
868 | - } |
|
869 | - } |
|
870 | - } |
|
688 | + } |
|
689 | + |
|
690 | + |
|
691 | + /** |
|
692 | + * Enqueue scripts and styles for the datetime tools page. |
|
693 | + */ |
|
694 | + public function load_scripts_styles_datetime_tools() |
|
695 | + { |
|
696 | + EE_Datepicker_Input::enqueue_styles_and_scripts(); |
|
697 | + } |
|
698 | + |
|
699 | + |
|
700 | + protected function _datetime_tools() |
|
701 | + { |
|
702 | + $form_action = EE_Admin_Page::add_query_args_and_nonce( |
|
703 | + array( |
|
704 | + 'action' => 'run_datetime_offset_fix', |
|
705 | + 'return_action' => $this->_req_action |
|
706 | + ), |
|
707 | + EE_MAINTENANCE_ADMIN_URL |
|
708 | + ); |
|
709 | + $form = $this->_get_datetime_offset_fix_form(); |
|
710 | + $this->_admin_page_title = esc_html__('Datetime Utilities', 'event_espresso'); |
|
711 | + $this->_template_args['admin_page_content'] = $form->form_open($form_action, 'post') |
|
712 | + . $form->get_html_and_js() |
|
713 | + . $form->form_close(); |
|
714 | + $this->display_admin_page_with_no_sidebar(); |
|
715 | + } |
|
716 | + |
|
717 | + |
|
718 | + |
|
719 | + protected function _get_datetime_offset_fix_form() |
|
720 | + { |
|
721 | + if (! $this->datetime_fix_offset_form instanceof EE_Form_Section_Proper) { |
|
722 | + $this->datetime_fix_offset_form = new EE_Form_Section_Proper( |
|
723 | + array( |
|
724 | + 'name' => 'datetime_offset_fix_option', |
|
725 | + 'layout_strategy' => new EE_Admin_Two_Column_Layout(), |
|
726 | + 'subsections' => array( |
|
727 | + 'title' => new EE_Form_Section_HTML( |
|
728 | + EEH_HTML::h2( |
|
729 | + esc_html__('Datetime Offset Tool', 'event_espresso') |
|
730 | + ) |
|
731 | + ), |
|
732 | + 'explanation' => new EE_Form_Section_HTML( |
|
733 | + EEH_HTML::p( |
|
734 | + esc_html__( |
|
735 | + 'Use this tool to automatically apply the provided offset to all Event Espresso records in your database that involve dates and times.', |
|
736 | + 'event_espresso' |
|
737 | + ) |
|
738 | + ) |
|
739 | + . EEH_HTML::p( |
|
740 | + esc_html__( |
|
741 | + 'Note: If you enter 1.25, that will result in the offset of 1 hour 15 minutes being applied. Decimals represent the fraction of hours, not minutes.', |
|
742 | + 'event_espresso' |
|
743 | + ) |
|
744 | + ) |
|
745 | + ), |
|
746 | + 'offset_input' => new EE_Float_Input( |
|
747 | + array( |
|
748 | + 'html_name' => 'offset_for_datetimes', |
|
749 | + 'html_label_text' => esc_html__( |
|
750 | + 'Offset to apply (in hours):', |
|
751 | + 'event_espresso' |
|
752 | + ), |
|
753 | + 'min_value' => '-12', |
|
754 | + 'max_value' => '14', |
|
755 | + 'step_value' => '.25', |
|
756 | + 'default' => DatetimeOffsetFix::getOffset() |
|
757 | + ) |
|
758 | + ), |
|
759 | + 'date_range_explanation' => new EE_Form_Section_HTML( |
|
760 | + EEH_HTML::p( |
|
761 | + esc_html__( |
|
762 | + 'Leave the following fields blank if you want the offset to be applied to all dates. If however, you want to just apply the offset to a specific range of dates you can restrict the offset application using these fields.', |
|
763 | + 'event_espresso' |
|
764 | + ) |
|
765 | + ) |
|
766 | + . EEH_HTML::p( |
|
767 | + EEH_HTML::strong( |
|
768 | + sprintf( |
|
769 | + esc_html__( |
|
770 | + 'Note: please enter the dates in UTC (You can use %1$sthis online tool%2$s to assist with conversions).', |
|
771 | + 'event_espresso' |
|
772 | + ), |
|
773 | + '<a href="https://www.timeanddate.com/worldclock/converter.html">', |
|
774 | + '</a>' |
|
775 | + ) |
|
776 | + ) |
|
777 | + ) |
|
778 | + ), |
|
779 | + 'date_range_start_date' => new EE_Datepicker_Input( |
|
780 | + array( |
|
781 | + 'html_name' => 'offset_date_start_range', |
|
782 | + 'html_label_text' => esc_html__( |
|
783 | + 'Start Date for dates the offset applied to:', |
|
784 | + 'event_espresso' |
|
785 | + ) |
|
786 | + ) |
|
787 | + ), |
|
788 | + 'date_range_end_date' => new EE_Datepicker_Input( |
|
789 | + array( |
|
790 | + 'html_name' => 'offset_date_end_range', |
|
791 | + 'html_label_text' => esc_html( |
|
792 | + 'End Date for dates the offset is applied to:', |
|
793 | + 'event_espresso' |
|
794 | + ) |
|
795 | + ) |
|
796 | + ), |
|
797 | + 'submit' => new EE_Submit_Input( |
|
798 | + array( |
|
799 | + 'html_label_text' => '', |
|
800 | + 'default' => esc_html__('Apply Offset', 'event_espresso') |
|
801 | + ) |
|
802 | + ), |
|
803 | + ) |
|
804 | + ) |
|
805 | + ); |
|
806 | + } |
|
807 | + return $this->datetime_fix_offset_form; |
|
808 | + } |
|
809 | + |
|
810 | + |
|
811 | + /** |
|
812 | + * Callback for the run_datetime_offset_fix route. |
|
813 | + * @throws EE_Error |
|
814 | + */ |
|
815 | + protected function _apply_datetime_offset() |
|
816 | + { |
|
817 | + if ($_SERVER['REQUEST_METHOD'] === 'POST') { |
|
818 | + $form = $this->_get_datetime_offset_fix_form(); |
|
819 | + $form->receive_form_submission($this->_req_data); |
|
820 | + if ($form->is_valid()) { |
|
821 | + //save offset data so batch processor can get it. |
|
822 | + DatetimeOffsetFix::updateOffset($form->get_input_value('offset_input')); |
|
823 | + $utc_timezone = new DateTimeZone('UTC'); |
|
824 | + $date_range_start_date = DateTime::createFromFormat( |
|
825 | + 'm/d/Y H:i:s', |
|
826 | + $form->get_input_value('date_range_start_date') . ' 00:00:00', |
|
827 | + $utc_timezone |
|
828 | + ); |
|
829 | + $date_range_end_date = DateTime::createFromFormat( |
|
830 | + 'm/d/Y H:i:s', |
|
831 | + $form->get_input_value('date_range_end_date') . ' 23:59:59', |
|
832 | + $utc_timezone |
|
833 | + ); |
|
834 | + if ($date_range_start_date instanceof DateTime) { |
|
835 | + DatetimeOffsetFix::updateStartDateRange(DbSafeDateTime::createFromDateTime($date_range_start_date)); |
|
836 | + } |
|
837 | + if ($date_range_end_date instanceof DateTime) { |
|
838 | + DatetimeOffsetFix::updateEndDateRange(DbSafeDateTime::createFromDateTime($date_range_end_date)); |
|
839 | + } |
|
840 | + //redirect to batch tool |
|
841 | + wp_redirect( |
|
842 | + EE_Admin_Page::add_query_args_and_nonce( |
|
843 | + array( |
|
844 | + 'page' => 'espresso_batch', |
|
845 | + 'batch' => 'job', |
|
846 | + 'label' => esc_html__('Applying Offset', 'event_espresso'), |
|
847 | + 'job_handler' => urlencode('EventEspressoBatchRequest\JobHandlers\DatetimeOffsetFix'), |
|
848 | + 'return_url' => urlencode( |
|
849 | + add_query_arg( |
|
850 | + array( |
|
851 | + 'action' => 'datetime_tools', |
|
852 | + ), |
|
853 | + EEH_URL::current_url_without_query_paramaters( |
|
854 | + array( |
|
855 | + 'return_action', |
|
856 | + 'run_datetime_offset_fix_nonce', |
|
857 | + 'return', |
|
858 | + 'datetime_tools_nonce' |
|
859 | + ) |
|
860 | + ) |
|
861 | + ) |
|
862 | + ) |
|
863 | + ), |
|
864 | + admin_url() |
|
865 | + ) |
|
866 | + ); |
|
867 | + exit; |
|
868 | + } |
|
869 | + } |
|
870 | + } |
|
871 | 871 | } //end Maintenance_Admin_Page class |
@@ -18,786 +18,786 @@ discard block |
||
18 | 18 | { |
19 | 19 | |
20 | 20 | |
21 | - /** |
|
22 | - * prefix to be added onto an addon's plugin slug to make a wp option name |
|
23 | - * which will be used to store the plugin's activation history |
|
24 | - */ |
|
25 | - const ee_addon_version_history_option_prefix = 'ee_version_history_'; |
|
26 | - |
|
27 | - /** |
|
28 | - * @var $_version |
|
29 | - * @type string |
|
30 | - */ |
|
31 | - protected $_version = ''; |
|
32 | - |
|
33 | - /** |
|
34 | - * @var $_min_core_version |
|
35 | - * @type string |
|
36 | - */ |
|
37 | - protected $_min_core_version = ''; |
|
38 | - |
|
39 | - /** |
|
40 | - * derived from plugin 'main_file_path using plugin_basename() |
|
41 | - * |
|
42 | - * @type string $_plugin_basename |
|
43 | - */ |
|
44 | - protected $_plugin_basename = ''; |
|
45 | - |
|
46 | - /** |
|
47 | - * A non-internationalized name to identify this addon for use in URLs, etc |
|
48 | - * |
|
49 | - * @type string $_plugin_slug |
|
50 | - */ |
|
51 | - protected $_plugin_slug = ''; |
|
52 | - |
|
53 | - /** |
|
54 | - * A non-internationalized name to identify this addon. Eg 'Calendar','MailChimp',etc/ |
|
55 | - * |
|
56 | - * @type string _addon_name |
|
57 | - */ |
|
58 | - protected $_addon_name = ''; |
|
59 | - |
|
60 | - /** |
|
61 | - * one of the EE_System::req_type_* constants |
|
62 | - * |
|
63 | - * @type int $_req_type |
|
64 | - */ |
|
65 | - protected $_req_type; |
|
66 | - |
|
67 | - /** |
|
68 | - * page slug to be used when generating the "Settings" link on the WP plugin page |
|
69 | - * |
|
70 | - * @type string $_plugin_action_slug |
|
71 | - */ |
|
72 | - protected $_plugin_action_slug = ''; |
|
73 | - |
|
74 | - /** |
|
75 | - * if not empty, inserts a new table row after this plugin's row on the WP Plugins page |
|
76 | - * that can be used for adding upgrading/marketing info |
|
77 | - * |
|
78 | - * @type array $_plugins_page_row |
|
79 | - */ |
|
80 | - protected $_plugins_page_row = array(); |
|
81 | - |
|
82 | - |
|
83 | - |
|
84 | - /** |
|
85 | - * filepath to the main file, which can be used for register_activation_hook, register_deactivation_hook, etc. |
|
86 | - * |
|
87 | - * @type string |
|
88 | - */ |
|
89 | - protected $_main_plugin_file; |
|
90 | - |
|
91 | - |
|
92 | - /** |
|
93 | - * @var EE_Dependency_Map $dependency_map |
|
94 | - */ |
|
95 | - private $dependency_map; |
|
96 | - |
|
97 | - |
|
98 | - /** |
|
99 | - * @var DomainInterface $domain |
|
100 | - */ |
|
101 | - private $domain; |
|
102 | - |
|
103 | - |
|
104 | - /** |
|
105 | - * @param EE_Dependency_Map $dependency_map [optional] |
|
106 | - * @param DomainInterface $domain [optional] |
|
107 | - */ |
|
108 | - public function __construct(EE_Dependency_Map $dependency_map = null, DomainInterface $domain = null) |
|
109 | - { |
|
110 | - if($dependency_map instanceof EE_Dependency_Map) { |
|
111 | - $this->setDependencyMap($dependency_map); |
|
112 | - } |
|
113 | - if ($domain instanceof DomainInterface) { |
|
114 | - $this->setDomain($domain); |
|
115 | - } |
|
116 | - add_action('AHEE__EE_System__load_controllers__load_admin_controllers', array($this, 'admin_init')); |
|
117 | - } |
|
118 | - |
|
119 | - |
|
120 | - /** |
|
121 | - * @param EE_Dependency_Map $dependency_map |
|
122 | - */ |
|
123 | - public function setDependencyMap($dependency_map) |
|
124 | - { |
|
125 | - $this->dependency_map = $dependency_map; |
|
126 | - } |
|
127 | - |
|
128 | - |
|
129 | - /** |
|
130 | - * @return EE_Dependency_Map |
|
131 | - */ |
|
132 | - public function dependencyMap() |
|
133 | - { |
|
134 | - return $this->dependency_map; |
|
135 | - } |
|
136 | - |
|
137 | - |
|
138 | - /** |
|
139 | - * @param DomainInterface $domain |
|
140 | - */ |
|
141 | - public function setDomain(DomainInterface $domain) |
|
142 | - { |
|
143 | - $this->domain = $domain; |
|
144 | - } |
|
145 | - |
|
146 | - /** |
|
147 | - * @return DomainInterface |
|
148 | - */ |
|
149 | - public function domain() |
|
150 | - { |
|
151 | - return $this->domain; |
|
152 | - } |
|
153 | - |
|
154 | - |
|
155 | - /** |
|
156 | - * @param mixed $version |
|
157 | - */ |
|
158 | - public function set_version($version = null) |
|
159 | - { |
|
160 | - $this->_version = $version; |
|
161 | - } |
|
162 | - |
|
163 | - |
|
164 | - /** |
|
165 | - * get__version |
|
166 | - * |
|
167 | - * @return string |
|
168 | - */ |
|
169 | - public function version() |
|
170 | - { |
|
171 | - return $this->_version; |
|
172 | - } |
|
173 | - |
|
174 | - |
|
175 | - /** |
|
176 | - * @param mixed $min_core_version |
|
177 | - */ |
|
178 | - public function set_min_core_version($min_core_version = null) |
|
179 | - { |
|
180 | - $this->_min_core_version = $min_core_version; |
|
181 | - } |
|
182 | - |
|
183 | - |
|
184 | - /** |
|
185 | - * get__min_core_version |
|
186 | - * |
|
187 | - * @return string |
|
188 | - */ |
|
189 | - public function min_core_version() |
|
190 | - { |
|
191 | - return $this->_min_core_version; |
|
192 | - } |
|
193 | - |
|
194 | - |
|
195 | - /** |
|
196 | - * Sets addon_name |
|
197 | - * |
|
198 | - * @param string $addon_name |
|
199 | - * @return boolean |
|
200 | - */ |
|
201 | - public function set_name($addon_name) |
|
202 | - { |
|
203 | - return $this->_addon_name = $addon_name; |
|
204 | - } |
|
205 | - |
|
206 | - |
|
207 | - /** |
|
208 | - * Gets addon_name |
|
209 | - * |
|
210 | - * @return string |
|
211 | - */ |
|
212 | - public function name() |
|
213 | - { |
|
214 | - return $this->_addon_name; |
|
215 | - } |
|
216 | - |
|
217 | - |
|
218 | - /** |
|
219 | - * @return string |
|
220 | - */ |
|
221 | - public function plugin_basename() |
|
222 | - { |
|
223 | - |
|
224 | - return $this->_plugin_basename; |
|
225 | - } |
|
226 | - |
|
227 | - |
|
228 | - /** |
|
229 | - * @param string $plugin_basename |
|
230 | - */ |
|
231 | - public function set_plugin_basename($plugin_basename) |
|
232 | - { |
|
233 | - |
|
234 | - $this->_plugin_basename = $plugin_basename; |
|
235 | - } |
|
236 | - |
|
237 | - |
|
238 | - /** |
|
239 | - * @return string |
|
240 | - */ |
|
241 | - public function plugin_slug() |
|
242 | - { |
|
243 | - |
|
244 | - return $this->_plugin_slug; |
|
245 | - } |
|
246 | - |
|
247 | - |
|
248 | - /** |
|
249 | - * @param string $plugin_slug |
|
250 | - */ |
|
251 | - public function set_plugin_slug($plugin_slug) |
|
252 | - { |
|
253 | - |
|
254 | - $this->_plugin_slug = $plugin_slug; |
|
255 | - } |
|
256 | - |
|
257 | - |
|
258 | - /** |
|
259 | - * @return string |
|
260 | - */ |
|
261 | - public function plugin_action_slug() |
|
262 | - { |
|
263 | - |
|
264 | - return $this->_plugin_action_slug; |
|
265 | - } |
|
266 | - |
|
267 | - |
|
268 | - /** |
|
269 | - * @param string $plugin_action_slug |
|
270 | - */ |
|
271 | - public function set_plugin_action_slug($plugin_action_slug) |
|
272 | - { |
|
273 | - |
|
274 | - $this->_plugin_action_slug = $plugin_action_slug; |
|
275 | - } |
|
276 | - |
|
277 | - |
|
278 | - /** |
|
279 | - * @return array |
|
280 | - */ |
|
281 | - public function get_plugins_page_row() |
|
282 | - { |
|
283 | - |
|
284 | - return $this->_plugins_page_row; |
|
285 | - } |
|
286 | - |
|
287 | - |
|
288 | - /** |
|
289 | - * @param array $plugins_page_row |
|
290 | - */ |
|
291 | - public function set_plugins_page_row($plugins_page_row = array()) |
|
292 | - { |
|
293 | - // sigh.... check for example content that I stupidly merged to master and remove it if found |
|
294 | - if (! is_array($plugins_page_row) |
|
295 | - && strpos($plugins_page_row, '<h3>Promotions Addon Upsell Info</h3>') !== false |
|
296 | - ) { |
|
297 | - $plugins_page_row = array(); |
|
298 | - } |
|
299 | - $this->_plugins_page_row = (array) $plugins_page_row; |
|
300 | - } |
|
301 | - |
|
302 | - |
|
303 | - /** |
|
304 | - * Called when EE core detects this addon has been activated for the first time. |
|
305 | - * If the site isn't in maintenance mode, should setup the addon's database |
|
306 | - * |
|
307 | - * @return void |
|
308 | - */ |
|
309 | - public function new_install() |
|
310 | - { |
|
311 | - $classname = get_class($this); |
|
312 | - do_action("AHEE__{$classname}__new_install"); |
|
313 | - do_action('AHEE__EE_Addon__new_install', $this); |
|
314 | - EE_Maintenance_Mode::instance()->set_maintenance_mode_if_db_old(); |
|
315 | - add_action( |
|
316 | - 'AHEE__EE_System__perform_activations_upgrades_and_migrations', |
|
317 | - array($this, 'initialize_db_if_no_migrations_required') |
|
318 | - ); |
|
319 | - } |
|
320 | - |
|
321 | - |
|
322 | - /** |
|
323 | - * Called when EE core detects this addon has been reactivated. When this happens, |
|
324 | - * it's good to just check that your data is still intact |
|
325 | - * |
|
326 | - * @return void |
|
327 | - */ |
|
328 | - public function reactivation() |
|
329 | - { |
|
330 | - $classname = get_class($this); |
|
331 | - do_action("AHEE__{$classname}__reactivation"); |
|
332 | - do_action('AHEE__EE_Addon__reactivation', $this); |
|
333 | - EE_Maintenance_Mode::instance()->set_maintenance_mode_if_db_old(); |
|
334 | - add_action( |
|
335 | - 'AHEE__EE_System__perform_activations_upgrades_and_migrations', |
|
336 | - array($this, 'initialize_db_if_no_migrations_required') |
|
337 | - ); |
|
338 | - } |
|
339 | - |
|
340 | - |
|
341 | - /** |
|
342 | - * Called when the registered deactivation hook for this addon fires. |
|
343 | - * @throws EE_Error |
|
344 | - */ |
|
345 | - public function deactivation() |
|
346 | - { |
|
347 | - $classname = get_class($this); |
|
348 | - do_action("AHEE__{$classname}__deactivation"); |
|
349 | - do_action('AHEE__EE_Addon__deactivation', $this); |
|
350 | - //check if the site no longer needs to be in maintenance mode |
|
351 | - EE_Register_Addon::deregister($this->name()); |
|
352 | - EE_Maintenance_Mode::instance()->set_maintenance_mode_if_db_old(); |
|
353 | - } |
|
354 | - |
|
355 | - |
|
356 | - /** |
|
357 | - * Takes care of double-checking that we're not in maintenance mode, and then |
|
358 | - * initializing this addon's necessary initial data. This is called by default on new activations |
|
359 | - * and reactivations. |
|
360 | - * |
|
361 | - * @param boolean $verify_schema whether to verify the database's schema for this addon, or just its data. |
|
362 | - * This is a resource-intensive job so we prefer to only do it when necessary |
|
363 | - * @return void |
|
364 | - * @throws \EE_Error |
|
365 | - */ |
|
366 | - public function initialize_db_if_no_migrations_required($verify_schema = true) |
|
367 | - { |
|
368 | - if ($verify_schema === '') { |
|
369 | - //wp core bug imo: if no args are passed to `do_action('some_hook_name')` besides the hook's name |
|
370 | - //(ie, no 2nd or 3rd arguments), instead of calling the registered callbacks with no arguments, it |
|
371 | - //calls them with an argument of an empty string (ie ""), which evaluates to false |
|
372 | - //so we need to treat the empty string as if nothing had been passed, and should instead use the default |
|
373 | - $verify_schema = true; |
|
374 | - } |
|
375 | - if (EE_Maintenance_Mode::instance()->level() !== EE_Maintenance_Mode::level_2_complete_maintenance) { |
|
376 | - if ($verify_schema) { |
|
377 | - $this->initialize_db(); |
|
378 | - } |
|
379 | - $this->initialize_default_data(); |
|
380 | - //@todo: this will probably need to be adjusted in 4.4 as the array changed formats I believe |
|
381 | - EE_Data_Migration_Manager::instance()->update_current_database_state_to( |
|
382 | - array( |
|
383 | - 'slug' => $this->name(), |
|
384 | - 'version' => $this->version(), |
|
385 | - ) |
|
386 | - ); |
|
387 | - /* make sure core's data is a-ok |
|
21 | + /** |
|
22 | + * prefix to be added onto an addon's plugin slug to make a wp option name |
|
23 | + * which will be used to store the plugin's activation history |
|
24 | + */ |
|
25 | + const ee_addon_version_history_option_prefix = 'ee_version_history_'; |
|
26 | + |
|
27 | + /** |
|
28 | + * @var $_version |
|
29 | + * @type string |
|
30 | + */ |
|
31 | + protected $_version = ''; |
|
32 | + |
|
33 | + /** |
|
34 | + * @var $_min_core_version |
|
35 | + * @type string |
|
36 | + */ |
|
37 | + protected $_min_core_version = ''; |
|
38 | + |
|
39 | + /** |
|
40 | + * derived from plugin 'main_file_path using plugin_basename() |
|
41 | + * |
|
42 | + * @type string $_plugin_basename |
|
43 | + */ |
|
44 | + protected $_plugin_basename = ''; |
|
45 | + |
|
46 | + /** |
|
47 | + * A non-internationalized name to identify this addon for use in URLs, etc |
|
48 | + * |
|
49 | + * @type string $_plugin_slug |
|
50 | + */ |
|
51 | + protected $_plugin_slug = ''; |
|
52 | + |
|
53 | + /** |
|
54 | + * A non-internationalized name to identify this addon. Eg 'Calendar','MailChimp',etc/ |
|
55 | + * |
|
56 | + * @type string _addon_name |
|
57 | + */ |
|
58 | + protected $_addon_name = ''; |
|
59 | + |
|
60 | + /** |
|
61 | + * one of the EE_System::req_type_* constants |
|
62 | + * |
|
63 | + * @type int $_req_type |
|
64 | + */ |
|
65 | + protected $_req_type; |
|
66 | + |
|
67 | + /** |
|
68 | + * page slug to be used when generating the "Settings" link on the WP plugin page |
|
69 | + * |
|
70 | + * @type string $_plugin_action_slug |
|
71 | + */ |
|
72 | + protected $_plugin_action_slug = ''; |
|
73 | + |
|
74 | + /** |
|
75 | + * if not empty, inserts a new table row after this plugin's row on the WP Plugins page |
|
76 | + * that can be used for adding upgrading/marketing info |
|
77 | + * |
|
78 | + * @type array $_plugins_page_row |
|
79 | + */ |
|
80 | + protected $_plugins_page_row = array(); |
|
81 | + |
|
82 | + |
|
83 | + |
|
84 | + /** |
|
85 | + * filepath to the main file, which can be used for register_activation_hook, register_deactivation_hook, etc. |
|
86 | + * |
|
87 | + * @type string |
|
88 | + */ |
|
89 | + protected $_main_plugin_file; |
|
90 | + |
|
91 | + |
|
92 | + /** |
|
93 | + * @var EE_Dependency_Map $dependency_map |
|
94 | + */ |
|
95 | + private $dependency_map; |
|
96 | + |
|
97 | + |
|
98 | + /** |
|
99 | + * @var DomainInterface $domain |
|
100 | + */ |
|
101 | + private $domain; |
|
102 | + |
|
103 | + |
|
104 | + /** |
|
105 | + * @param EE_Dependency_Map $dependency_map [optional] |
|
106 | + * @param DomainInterface $domain [optional] |
|
107 | + */ |
|
108 | + public function __construct(EE_Dependency_Map $dependency_map = null, DomainInterface $domain = null) |
|
109 | + { |
|
110 | + if($dependency_map instanceof EE_Dependency_Map) { |
|
111 | + $this->setDependencyMap($dependency_map); |
|
112 | + } |
|
113 | + if ($domain instanceof DomainInterface) { |
|
114 | + $this->setDomain($domain); |
|
115 | + } |
|
116 | + add_action('AHEE__EE_System__load_controllers__load_admin_controllers', array($this, 'admin_init')); |
|
117 | + } |
|
118 | + |
|
119 | + |
|
120 | + /** |
|
121 | + * @param EE_Dependency_Map $dependency_map |
|
122 | + */ |
|
123 | + public function setDependencyMap($dependency_map) |
|
124 | + { |
|
125 | + $this->dependency_map = $dependency_map; |
|
126 | + } |
|
127 | + |
|
128 | + |
|
129 | + /** |
|
130 | + * @return EE_Dependency_Map |
|
131 | + */ |
|
132 | + public function dependencyMap() |
|
133 | + { |
|
134 | + return $this->dependency_map; |
|
135 | + } |
|
136 | + |
|
137 | + |
|
138 | + /** |
|
139 | + * @param DomainInterface $domain |
|
140 | + */ |
|
141 | + public function setDomain(DomainInterface $domain) |
|
142 | + { |
|
143 | + $this->domain = $domain; |
|
144 | + } |
|
145 | + |
|
146 | + /** |
|
147 | + * @return DomainInterface |
|
148 | + */ |
|
149 | + public function domain() |
|
150 | + { |
|
151 | + return $this->domain; |
|
152 | + } |
|
153 | + |
|
154 | + |
|
155 | + /** |
|
156 | + * @param mixed $version |
|
157 | + */ |
|
158 | + public function set_version($version = null) |
|
159 | + { |
|
160 | + $this->_version = $version; |
|
161 | + } |
|
162 | + |
|
163 | + |
|
164 | + /** |
|
165 | + * get__version |
|
166 | + * |
|
167 | + * @return string |
|
168 | + */ |
|
169 | + public function version() |
|
170 | + { |
|
171 | + return $this->_version; |
|
172 | + } |
|
173 | + |
|
174 | + |
|
175 | + /** |
|
176 | + * @param mixed $min_core_version |
|
177 | + */ |
|
178 | + public function set_min_core_version($min_core_version = null) |
|
179 | + { |
|
180 | + $this->_min_core_version = $min_core_version; |
|
181 | + } |
|
182 | + |
|
183 | + |
|
184 | + /** |
|
185 | + * get__min_core_version |
|
186 | + * |
|
187 | + * @return string |
|
188 | + */ |
|
189 | + public function min_core_version() |
|
190 | + { |
|
191 | + return $this->_min_core_version; |
|
192 | + } |
|
193 | + |
|
194 | + |
|
195 | + /** |
|
196 | + * Sets addon_name |
|
197 | + * |
|
198 | + * @param string $addon_name |
|
199 | + * @return boolean |
|
200 | + */ |
|
201 | + public function set_name($addon_name) |
|
202 | + { |
|
203 | + return $this->_addon_name = $addon_name; |
|
204 | + } |
|
205 | + |
|
206 | + |
|
207 | + /** |
|
208 | + * Gets addon_name |
|
209 | + * |
|
210 | + * @return string |
|
211 | + */ |
|
212 | + public function name() |
|
213 | + { |
|
214 | + return $this->_addon_name; |
|
215 | + } |
|
216 | + |
|
217 | + |
|
218 | + /** |
|
219 | + * @return string |
|
220 | + */ |
|
221 | + public function plugin_basename() |
|
222 | + { |
|
223 | + |
|
224 | + return $this->_plugin_basename; |
|
225 | + } |
|
226 | + |
|
227 | + |
|
228 | + /** |
|
229 | + * @param string $plugin_basename |
|
230 | + */ |
|
231 | + public function set_plugin_basename($plugin_basename) |
|
232 | + { |
|
233 | + |
|
234 | + $this->_plugin_basename = $plugin_basename; |
|
235 | + } |
|
236 | + |
|
237 | + |
|
238 | + /** |
|
239 | + * @return string |
|
240 | + */ |
|
241 | + public function plugin_slug() |
|
242 | + { |
|
243 | + |
|
244 | + return $this->_plugin_slug; |
|
245 | + } |
|
246 | + |
|
247 | + |
|
248 | + /** |
|
249 | + * @param string $plugin_slug |
|
250 | + */ |
|
251 | + public function set_plugin_slug($plugin_slug) |
|
252 | + { |
|
253 | + |
|
254 | + $this->_plugin_slug = $plugin_slug; |
|
255 | + } |
|
256 | + |
|
257 | + |
|
258 | + /** |
|
259 | + * @return string |
|
260 | + */ |
|
261 | + public function plugin_action_slug() |
|
262 | + { |
|
263 | + |
|
264 | + return $this->_plugin_action_slug; |
|
265 | + } |
|
266 | + |
|
267 | + |
|
268 | + /** |
|
269 | + * @param string $plugin_action_slug |
|
270 | + */ |
|
271 | + public function set_plugin_action_slug($plugin_action_slug) |
|
272 | + { |
|
273 | + |
|
274 | + $this->_plugin_action_slug = $plugin_action_slug; |
|
275 | + } |
|
276 | + |
|
277 | + |
|
278 | + /** |
|
279 | + * @return array |
|
280 | + */ |
|
281 | + public function get_plugins_page_row() |
|
282 | + { |
|
283 | + |
|
284 | + return $this->_plugins_page_row; |
|
285 | + } |
|
286 | + |
|
287 | + |
|
288 | + /** |
|
289 | + * @param array $plugins_page_row |
|
290 | + */ |
|
291 | + public function set_plugins_page_row($plugins_page_row = array()) |
|
292 | + { |
|
293 | + // sigh.... check for example content that I stupidly merged to master and remove it if found |
|
294 | + if (! is_array($plugins_page_row) |
|
295 | + && strpos($plugins_page_row, '<h3>Promotions Addon Upsell Info</h3>') !== false |
|
296 | + ) { |
|
297 | + $plugins_page_row = array(); |
|
298 | + } |
|
299 | + $this->_plugins_page_row = (array) $plugins_page_row; |
|
300 | + } |
|
301 | + |
|
302 | + |
|
303 | + /** |
|
304 | + * Called when EE core detects this addon has been activated for the first time. |
|
305 | + * If the site isn't in maintenance mode, should setup the addon's database |
|
306 | + * |
|
307 | + * @return void |
|
308 | + */ |
|
309 | + public function new_install() |
|
310 | + { |
|
311 | + $classname = get_class($this); |
|
312 | + do_action("AHEE__{$classname}__new_install"); |
|
313 | + do_action('AHEE__EE_Addon__new_install', $this); |
|
314 | + EE_Maintenance_Mode::instance()->set_maintenance_mode_if_db_old(); |
|
315 | + add_action( |
|
316 | + 'AHEE__EE_System__perform_activations_upgrades_and_migrations', |
|
317 | + array($this, 'initialize_db_if_no_migrations_required') |
|
318 | + ); |
|
319 | + } |
|
320 | + |
|
321 | + |
|
322 | + /** |
|
323 | + * Called when EE core detects this addon has been reactivated. When this happens, |
|
324 | + * it's good to just check that your data is still intact |
|
325 | + * |
|
326 | + * @return void |
|
327 | + */ |
|
328 | + public function reactivation() |
|
329 | + { |
|
330 | + $classname = get_class($this); |
|
331 | + do_action("AHEE__{$classname}__reactivation"); |
|
332 | + do_action('AHEE__EE_Addon__reactivation', $this); |
|
333 | + EE_Maintenance_Mode::instance()->set_maintenance_mode_if_db_old(); |
|
334 | + add_action( |
|
335 | + 'AHEE__EE_System__perform_activations_upgrades_and_migrations', |
|
336 | + array($this, 'initialize_db_if_no_migrations_required') |
|
337 | + ); |
|
338 | + } |
|
339 | + |
|
340 | + |
|
341 | + /** |
|
342 | + * Called when the registered deactivation hook for this addon fires. |
|
343 | + * @throws EE_Error |
|
344 | + */ |
|
345 | + public function deactivation() |
|
346 | + { |
|
347 | + $classname = get_class($this); |
|
348 | + do_action("AHEE__{$classname}__deactivation"); |
|
349 | + do_action('AHEE__EE_Addon__deactivation', $this); |
|
350 | + //check if the site no longer needs to be in maintenance mode |
|
351 | + EE_Register_Addon::deregister($this->name()); |
|
352 | + EE_Maintenance_Mode::instance()->set_maintenance_mode_if_db_old(); |
|
353 | + } |
|
354 | + |
|
355 | + |
|
356 | + /** |
|
357 | + * Takes care of double-checking that we're not in maintenance mode, and then |
|
358 | + * initializing this addon's necessary initial data. This is called by default on new activations |
|
359 | + * and reactivations. |
|
360 | + * |
|
361 | + * @param boolean $verify_schema whether to verify the database's schema for this addon, or just its data. |
|
362 | + * This is a resource-intensive job so we prefer to only do it when necessary |
|
363 | + * @return void |
|
364 | + * @throws \EE_Error |
|
365 | + */ |
|
366 | + public function initialize_db_if_no_migrations_required($verify_schema = true) |
|
367 | + { |
|
368 | + if ($verify_schema === '') { |
|
369 | + //wp core bug imo: if no args are passed to `do_action('some_hook_name')` besides the hook's name |
|
370 | + //(ie, no 2nd or 3rd arguments), instead of calling the registered callbacks with no arguments, it |
|
371 | + //calls them with an argument of an empty string (ie ""), which evaluates to false |
|
372 | + //so we need to treat the empty string as if nothing had been passed, and should instead use the default |
|
373 | + $verify_schema = true; |
|
374 | + } |
|
375 | + if (EE_Maintenance_Mode::instance()->level() !== EE_Maintenance_Mode::level_2_complete_maintenance) { |
|
376 | + if ($verify_schema) { |
|
377 | + $this->initialize_db(); |
|
378 | + } |
|
379 | + $this->initialize_default_data(); |
|
380 | + //@todo: this will probably need to be adjusted in 4.4 as the array changed formats I believe |
|
381 | + EE_Data_Migration_Manager::instance()->update_current_database_state_to( |
|
382 | + array( |
|
383 | + 'slug' => $this->name(), |
|
384 | + 'version' => $this->version(), |
|
385 | + ) |
|
386 | + ); |
|
387 | + /* make sure core's data is a-ok |
|
388 | 388 | * (at the time of writing, we especially want to verify all the caps are present |
389 | 389 | * because payment method type capabilities are added dynamically, and it's |
390 | 390 | * possible this addon added a payment method. But it's also possible |
391 | 391 | * other data needs to be verified) |
392 | 392 | */ |
393 | - EEH_Activation::initialize_db_content(); |
|
394 | - update_option('ee_flush_rewrite_rules', true); |
|
395 | - //in case there are lots of addons being activated at once, let's force garbage collection |
|
396 | - //to help avoid memory limit errors |
|
397 | - //EEH_Debug_Tools::instance()->measure_memory( 'db content initialized for ' . get_class( $this), true ); |
|
398 | - gc_collect_cycles(); |
|
399 | - } else { |
|
400 | - //ask the data migration manager to init this addon's data |
|
401 | - //when migrations are finished because we can't do it now |
|
402 | - EE_Data_Migration_Manager::instance()->enqueue_db_initialization_for($this->name()); |
|
403 | - } |
|
404 | - } |
|
405 | - |
|
406 | - |
|
407 | - /** |
|
408 | - * Used to setup this addon's database tables, but not necessarily any default |
|
409 | - * data in them. The default is to actually use the most up-to-date data migration script |
|
410 | - * for this addon, and just use its schema_changes_before_migration() and schema_changes_after_migration() |
|
411 | - * methods to setup the db. |
|
412 | - */ |
|
413 | - public function initialize_db() |
|
414 | - { |
|
415 | - //find the migration script that sets the database to be compatible with the code |
|
416 | - $current_dms_name = EE_Data_Migration_Manager::instance()->get_most_up_to_date_dms($this->name()); |
|
417 | - if ($current_dms_name) { |
|
418 | - $current_data_migration_script = EE_Registry::instance()->load_dms($current_dms_name); |
|
419 | - $current_data_migration_script->set_migrating(false); |
|
420 | - $current_data_migration_script->schema_changes_before_migration(); |
|
421 | - $current_data_migration_script->schema_changes_after_migration(); |
|
422 | - if ($current_data_migration_script->get_errors()) { |
|
423 | - foreach ($current_data_migration_script->get_errors() as $error) { |
|
424 | - EE_Error::add_error($error, __FILE__, __FUNCTION__, __LINE__); |
|
425 | - } |
|
426 | - } |
|
427 | - } |
|
428 | - //if not DMS was found that should be ok. This addon just doesn't require any database changes |
|
429 | - EE_Data_Migration_Manager::instance()->update_current_database_state_to( |
|
430 | - array( |
|
431 | - 'slug' => $this->name(), |
|
432 | - 'version' => $this->version(), |
|
433 | - ) |
|
434 | - ); |
|
435 | - } |
|
436 | - |
|
437 | - |
|
438 | - /** |
|
439 | - * If you want to setup default data for the addon, override this method, and call |
|
440 | - * parent::initialize_default_data() from within it. This is normally called |
|
441 | - * from EE_Addon::initialize_db_if_no_migrations_required(), just after EE_Addon::initialize_db() |
|
442 | - * and should verify default data is present (but this is also called |
|
443 | - * on reactivations and just after migrations, so please verify you actually want |
|
444 | - * to ADD default data, because it may already be present). |
|
445 | - * However, please call this parent (currently it just fires a hook which other |
|
446 | - * addons may be depending on) |
|
447 | - */ |
|
448 | - public function initialize_default_data() |
|
449 | - { |
|
450 | - /** |
|
451 | - * Called when an addon is ensuring its default data is set (possibly called |
|
452 | - * on a reactivation, so first check for the absence of other data before setting |
|
453 | - * default data) |
|
454 | - * |
|
455 | - * @param EE_Addon $addon the addon that called this |
|
456 | - */ |
|
457 | - do_action('AHEE__EE_Addon__initialize_default_data__begin', $this); |
|
458 | - //override to insert default data. It is safe to use the models here |
|
459 | - //because the site should not be in maintenance mode |
|
460 | - } |
|
461 | - |
|
462 | - |
|
463 | - /** |
|
464 | - * EE Core detected that this addon has been upgraded. We should check if there |
|
465 | - * are any new migration scripts, and if so put the site into maintenance mode until |
|
466 | - * they're ran |
|
467 | - * |
|
468 | - * @return void |
|
469 | - */ |
|
470 | - public function upgrade() |
|
471 | - { |
|
472 | - $classname = get_class($this); |
|
473 | - do_action("AHEE__{$classname}__upgrade"); |
|
474 | - do_action('AHEE__EE_Addon__upgrade', $this); |
|
475 | - EE_Maintenance_Mode::instance()->set_maintenance_mode_if_db_old(); |
|
476 | - //also it's possible there is new default data that needs to be added |
|
477 | - add_action( |
|
478 | - 'AHEE__EE_System__perform_activations_upgrades_and_migrations', |
|
479 | - array($this, 'initialize_db_if_no_migrations_required') |
|
480 | - ); |
|
481 | - } |
|
482 | - |
|
483 | - |
|
484 | - /** |
|
485 | - * If Core detects this addon has been downgraded, you may want to invoke some special logic here. |
|
486 | - */ |
|
487 | - public function downgrade() |
|
488 | - { |
|
489 | - $classname = get_class($this); |
|
490 | - do_action("AHEE__{$classname}__downgrade"); |
|
491 | - do_action('AHEE__EE_Addon__downgrade', $this); |
|
492 | - //it's possible there's old default data that needs to be double-checked |
|
493 | - add_action( |
|
494 | - 'AHEE__EE_System__perform_activations_upgrades_and_migrations', |
|
495 | - array($this, 'initialize_db_if_no_migrations_required') |
|
496 | - ); |
|
497 | - } |
|
498 | - |
|
499 | - |
|
500 | - /** |
|
501 | - * set_db_update_option_name |
|
502 | - * Until we do something better, we'll just check for migration scripts upon |
|
503 | - * plugin activation only. In the future, we'll want to do it on plugin updates too |
|
504 | - * |
|
505 | - * @return bool |
|
506 | - */ |
|
507 | - public function set_db_update_option_name() |
|
508 | - { |
|
509 | - EE_Error::doing_it_wrong( |
|
510 | - __FUNCTION__, |
|
511 | - esc_html__( |
|
512 | - 'EE_Addon::set_db_update_option_name was renamed to EE_Addon::set_activation_indicator_option', |
|
513 | - 'event_espresso' |
|
514 | - ), |
|
515 | - '4.3.0.alpha.016' |
|
516 | - ); |
|
517 | - //let's just handle this on the next request, ok? right now we're just not really ready |
|
518 | - return $this->set_activation_indicator_option(); |
|
519 | - } |
|
520 | - |
|
521 | - |
|
522 | - /** |
|
523 | - * Returns the name of the activation indicator option |
|
524 | - * (an option which is set temporarily to indicate that this addon was just activated) |
|
525 | - * |
|
526 | - * @deprecated since version 4.3.0.alpha.016 |
|
527 | - * @return string |
|
528 | - */ |
|
529 | - public function get_db_update_option_name() |
|
530 | - { |
|
531 | - EE_Error::doing_it_wrong( |
|
532 | - __FUNCTION__, |
|
533 | - esc_html__( |
|
534 | - 'EE_Addon::get_db_update_option was renamed to EE_Addon::get_activation_indicator_option_name', |
|
535 | - 'event_espresso' |
|
536 | - ), |
|
537 | - '4.3.0.alpha.016' |
|
538 | - ); |
|
539 | - return $this->get_activation_indicator_option_name(); |
|
540 | - } |
|
541 | - |
|
542 | - |
|
543 | - /** |
|
544 | - * When the addon is activated, this should be called to set a wordpress option that |
|
545 | - * indicates it was activated. This is especially useful for detecting reactivations. |
|
546 | - * |
|
547 | - * @return bool |
|
548 | - */ |
|
549 | - public function set_activation_indicator_option() |
|
550 | - { |
|
551 | - // let's just handle this on the next request, ok? right now we're just not really ready |
|
552 | - return update_option($this->get_activation_indicator_option_name(), true); |
|
553 | - } |
|
554 | - |
|
555 | - |
|
556 | - /** |
|
557 | - * Gets the name of the wp option which is used to temporarily indicate that this addon was activated |
|
558 | - * |
|
559 | - * @return string |
|
560 | - */ |
|
561 | - public function get_activation_indicator_option_name() |
|
562 | - { |
|
563 | - return 'ee_activation_' . $this->name(); |
|
564 | - } |
|
565 | - |
|
566 | - |
|
567 | - /** |
|
568 | - * Used by EE_System to set the request type of this addon. Should not be used by addon developers |
|
569 | - * |
|
570 | - * @param int $req_type |
|
571 | - */ |
|
572 | - public function set_req_type($req_type) |
|
573 | - { |
|
574 | - $this->_req_type = $req_type; |
|
575 | - } |
|
576 | - |
|
577 | - |
|
578 | - /** |
|
579 | - * Returns the request type of this addon (ie, EE_System::req_type_normal, EE_System::req_type_new_activation, |
|
580 | - * EE_System::req_type_reactivation, EE_System::req_type_upgrade, or EE_System::req_type_downgrade). This is set by |
|
581 | - * EE_System when it is checking for new install or upgrades of addons |
|
582 | - */ |
|
583 | - public function detect_req_type() |
|
584 | - { |
|
585 | - if (! $this->_req_type) { |
|
586 | - $this->detect_activation_or_upgrade(); |
|
587 | - } |
|
588 | - return $this->_req_type; |
|
589 | - } |
|
590 | - |
|
591 | - |
|
592 | - /** |
|
593 | - * Detects the request type for this addon (whether it was just activated, upgrades, a normal request, etc.) |
|
594 | - * Should only be called once per request |
|
595 | - * |
|
596 | - * @return void |
|
597 | - */ |
|
598 | - public function detect_activation_or_upgrade() |
|
599 | - { |
|
600 | - $activation_history_for_addon = $this->get_activation_history(); |
|
393 | + EEH_Activation::initialize_db_content(); |
|
394 | + update_option('ee_flush_rewrite_rules', true); |
|
395 | + //in case there are lots of addons being activated at once, let's force garbage collection |
|
396 | + //to help avoid memory limit errors |
|
397 | + //EEH_Debug_Tools::instance()->measure_memory( 'db content initialized for ' . get_class( $this), true ); |
|
398 | + gc_collect_cycles(); |
|
399 | + } else { |
|
400 | + //ask the data migration manager to init this addon's data |
|
401 | + //when migrations are finished because we can't do it now |
|
402 | + EE_Data_Migration_Manager::instance()->enqueue_db_initialization_for($this->name()); |
|
403 | + } |
|
404 | + } |
|
405 | + |
|
406 | + |
|
407 | + /** |
|
408 | + * Used to setup this addon's database tables, but not necessarily any default |
|
409 | + * data in them. The default is to actually use the most up-to-date data migration script |
|
410 | + * for this addon, and just use its schema_changes_before_migration() and schema_changes_after_migration() |
|
411 | + * methods to setup the db. |
|
412 | + */ |
|
413 | + public function initialize_db() |
|
414 | + { |
|
415 | + //find the migration script that sets the database to be compatible with the code |
|
416 | + $current_dms_name = EE_Data_Migration_Manager::instance()->get_most_up_to_date_dms($this->name()); |
|
417 | + if ($current_dms_name) { |
|
418 | + $current_data_migration_script = EE_Registry::instance()->load_dms($current_dms_name); |
|
419 | + $current_data_migration_script->set_migrating(false); |
|
420 | + $current_data_migration_script->schema_changes_before_migration(); |
|
421 | + $current_data_migration_script->schema_changes_after_migration(); |
|
422 | + if ($current_data_migration_script->get_errors()) { |
|
423 | + foreach ($current_data_migration_script->get_errors() as $error) { |
|
424 | + EE_Error::add_error($error, __FILE__, __FUNCTION__, __LINE__); |
|
425 | + } |
|
426 | + } |
|
427 | + } |
|
428 | + //if not DMS was found that should be ok. This addon just doesn't require any database changes |
|
429 | + EE_Data_Migration_Manager::instance()->update_current_database_state_to( |
|
430 | + array( |
|
431 | + 'slug' => $this->name(), |
|
432 | + 'version' => $this->version(), |
|
433 | + ) |
|
434 | + ); |
|
435 | + } |
|
436 | + |
|
437 | + |
|
438 | + /** |
|
439 | + * If you want to setup default data for the addon, override this method, and call |
|
440 | + * parent::initialize_default_data() from within it. This is normally called |
|
441 | + * from EE_Addon::initialize_db_if_no_migrations_required(), just after EE_Addon::initialize_db() |
|
442 | + * and should verify default data is present (but this is also called |
|
443 | + * on reactivations and just after migrations, so please verify you actually want |
|
444 | + * to ADD default data, because it may already be present). |
|
445 | + * However, please call this parent (currently it just fires a hook which other |
|
446 | + * addons may be depending on) |
|
447 | + */ |
|
448 | + public function initialize_default_data() |
|
449 | + { |
|
450 | + /** |
|
451 | + * Called when an addon is ensuring its default data is set (possibly called |
|
452 | + * on a reactivation, so first check for the absence of other data before setting |
|
453 | + * default data) |
|
454 | + * |
|
455 | + * @param EE_Addon $addon the addon that called this |
|
456 | + */ |
|
457 | + do_action('AHEE__EE_Addon__initialize_default_data__begin', $this); |
|
458 | + //override to insert default data. It is safe to use the models here |
|
459 | + //because the site should not be in maintenance mode |
|
460 | + } |
|
461 | + |
|
462 | + |
|
463 | + /** |
|
464 | + * EE Core detected that this addon has been upgraded. We should check if there |
|
465 | + * are any new migration scripts, and if so put the site into maintenance mode until |
|
466 | + * they're ran |
|
467 | + * |
|
468 | + * @return void |
|
469 | + */ |
|
470 | + public function upgrade() |
|
471 | + { |
|
472 | + $classname = get_class($this); |
|
473 | + do_action("AHEE__{$classname}__upgrade"); |
|
474 | + do_action('AHEE__EE_Addon__upgrade', $this); |
|
475 | + EE_Maintenance_Mode::instance()->set_maintenance_mode_if_db_old(); |
|
476 | + //also it's possible there is new default data that needs to be added |
|
477 | + add_action( |
|
478 | + 'AHEE__EE_System__perform_activations_upgrades_and_migrations', |
|
479 | + array($this, 'initialize_db_if_no_migrations_required') |
|
480 | + ); |
|
481 | + } |
|
482 | + |
|
483 | + |
|
484 | + /** |
|
485 | + * If Core detects this addon has been downgraded, you may want to invoke some special logic here. |
|
486 | + */ |
|
487 | + public function downgrade() |
|
488 | + { |
|
489 | + $classname = get_class($this); |
|
490 | + do_action("AHEE__{$classname}__downgrade"); |
|
491 | + do_action('AHEE__EE_Addon__downgrade', $this); |
|
492 | + //it's possible there's old default data that needs to be double-checked |
|
493 | + add_action( |
|
494 | + 'AHEE__EE_System__perform_activations_upgrades_and_migrations', |
|
495 | + array($this, 'initialize_db_if_no_migrations_required') |
|
496 | + ); |
|
497 | + } |
|
498 | + |
|
499 | + |
|
500 | + /** |
|
501 | + * set_db_update_option_name |
|
502 | + * Until we do something better, we'll just check for migration scripts upon |
|
503 | + * plugin activation only. In the future, we'll want to do it on plugin updates too |
|
504 | + * |
|
505 | + * @return bool |
|
506 | + */ |
|
507 | + public function set_db_update_option_name() |
|
508 | + { |
|
509 | + EE_Error::doing_it_wrong( |
|
510 | + __FUNCTION__, |
|
511 | + esc_html__( |
|
512 | + 'EE_Addon::set_db_update_option_name was renamed to EE_Addon::set_activation_indicator_option', |
|
513 | + 'event_espresso' |
|
514 | + ), |
|
515 | + '4.3.0.alpha.016' |
|
516 | + ); |
|
517 | + //let's just handle this on the next request, ok? right now we're just not really ready |
|
518 | + return $this->set_activation_indicator_option(); |
|
519 | + } |
|
520 | + |
|
521 | + |
|
522 | + /** |
|
523 | + * Returns the name of the activation indicator option |
|
524 | + * (an option which is set temporarily to indicate that this addon was just activated) |
|
525 | + * |
|
526 | + * @deprecated since version 4.3.0.alpha.016 |
|
527 | + * @return string |
|
528 | + */ |
|
529 | + public function get_db_update_option_name() |
|
530 | + { |
|
531 | + EE_Error::doing_it_wrong( |
|
532 | + __FUNCTION__, |
|
533 | + esc_html__( |
|
534 | + 'EE_Addon::get_db_update_option was renamed to EE_Addon::get_activation_indicator_option_name', |
|
535 | + 'event_espresso' |
|
536 | + ), |
|
537 | + '4.3.0.alpha.016' |
|
538 | + ); |
|
539 | + return $this->get_activation_indicator_option_name(); |
|
540 | + } |
|
541 | + |
|
542 | + |
|
543 | + /** |
|
544 | + * When the addon is activated, this should be called to set a wordpress option that |
|
545 | + * indicates it was activated. This is especially useful for detecting reactivations. |
|
546 | + * |
|
547 | + * @return bool |
|
548 | + */ |
|
549 | + public function set_activation_indicator_option() |
|
550 | + { |
|
551 | + // let's just handle this on the next request, ok? right now we're just not really ready |
|
552 | + return update_option($this->get_activation_indicator_option_name(), true); |
|
553 | + } |
|
554 | + |
|
555 | + |
|
556 | + /** |
|
557 | + * Gets the name of the wp option which is used to temporarily indicate that this addon was activated |
|
558 | + * |
|
559 | + * @return string |
|
560 | + */ |
|
561 | + public function get_activation_indicator_option_name() |
|
562 | + { |
|
563 | + return 'ee_activation_' . $this->name(); |
|
564 | + } |
|
565 | + |
|
566 | + |
|
567 | + /** |
|
568 | + * Used by EE_System to set the request type of this addon. Should not be used by addon developers |
|
569 | + * |
|
570 | + * @param int $req_type |
|
571 | + */ |
|
572 | + public function set_req_type($req_type) |
|
573 | + { |
|
574 | + $this->_req_type = $req_type; |
|
575 | + } |
|
576 | + |
|
577 | + |
|
578 | + /** |
|
579 | + * Returns the request type of this addon (ie, EE_System::req_type_normal, EE_System::req_type_new_activation, |
|
580 | + * EE_System::req_type_reactivation, EE_System::req_type_upgrade, or EE_System::req_type_downgrade). This is set by |
|
581 | + * EE_System when it is checking for new install or upgrades of addons |
|
582 | + */ |
|
583 | + public function detect_req_type() |
|
584 | + { |
|
585 | + if (! $this->_req_type) { |
|
586 | + $this->detect_activation_or_upgrade(); |
|
587 | + } |
|
588 | + return $this->_req_type; |
|
589 | + } |
|
590 | + |
|
591 | + |
|
592 | + /** |
|
593 | + * Detects the request type for this addon (whether it was just activated, upgrades, a normal request, etc.) |
|
594 | + * Should only be called once per request |
|
595 | + * |
|
596 | + * @return void |
|
597 | + */ |
|
598 | + public function detect_activation_or_upgrade() |
|
599 | + { |
|
600 | + $activation_history_for_addon = $this->get_activation_history(); |
|
601 | 601 | // d($activation_history_for_addon); |
602 | - $request_type = EE_System::detect_req_type_given_activation_history( |
|
603 | - $activation_history_for_addon, |
|
604 | - $this->get_activation_indicator_option_name(), |
|
605 | - $this->version() |
|
606 | - ); |
|
607 | - $this->set_req_type($request_type); |
|
608 | - $classname = get_class($this); |
|
609 | - switch ($request_type) { |
|
610 | - case EE_System::req_type_new_activation: |
|
611 | - do_action("AHEE__{$classname}__detect_activations_or_upgrades__new_activation"); |
|
612 | - do_action('AHEE__EE_Addon__detect_activations_or_upgrades__new_activation', $this); |
|
613 | - $this->new_install(); |
|
614 | - $this->update_list_of_installed_versions($activation_history_for_addon); |
|
615 | - break; |
|
616 | - case EE_System::req_type_reactivation: |
|
617 | - do_action("AHEE__{$classname}__detect_activations_or_upgrades__reactivation"); |
|
618 | - do_action('AHEE__EE_Addon__detect_activations_or_upgrades__reactivation', $this); |
|
619 | - $this->reactivation(); |
|
620 | - $this->update_list_of_installed_versions($activation_history_for_addon); |
|
621 | - break; |
|
622 | - case EE_System::req_type_upgrade: |
|
623 | - do_action("AHEE__{$classname}__detect_activations_or_upgrades__upgrade"); |
|
624 | - do_action('AHEE__EE_Addon__detect_activations_or_upgrades__upgrade', $this); |
|
625 | - $this->upgrade(); |
|
626 | - $this->update_list_of_installed_versions($activation_history_for_addon); |
|
627 | - break; |
|
628 | - case EE_System::req_type_downgrade: |
|
629 | - do_action("AHEE__{$classname}__detect_activations_or_upgrades__downgrade"); |
|
630 | - do_action('AHEE__EE_Addon__detect_activations_or_upgrades__downgrade', $this); |
|
631 | - $this->downgrade(); |
|
632 | - $this->update_list_of_installed_versions($activation_history_for_addon); |
|
633 | - break; |
|
634 | - case EE_System::req_type_normal: |
|
635 | - default: |
|
602 | + $request_type = EE_System::detect_req_type_given_activation_history( |
|
603 | + $activation_history_for_addon, |
|
604 | + $this->get_activation_indicator_option_name(), |
|
605 | + $this->version() |
|
606 | + ); |
|
607 | + $this->set_req_type($request_type); |
|
608 | + $classname = get_class($this); |
|
609 | + switch ($request_type) { |
|
610 | + case EE_System::req_type_new_activation: |
|
611 | + do_action("AHEE__{$classname}__detect_activations_or_upgrades__new_activation"); |
|
612 | + do_action('AHEE__EE_Addon__detect_activations_or_upgrades__new_activation', $this); |
|
613 | + $this->new_install(); |
|
614 | + $this->update_list_of_installed_versions($activation_history_for_addon); |
|
615 | + break; |
|
616 | + case EE_System::req_type_reactivation: |
|
617 | + do_action("AHEE__{$classname}__detect_activations_or_upgrades__reactivation"); |
|
618 | + do_action('AHEE__EE_Addon__detect_activations_or_upgrades__reactivation', $this); |
|
619 | + $this->reactivation(); |
|
620 | + $this->update_list_of_installed_versions($activation_history_for_addon); |
|
621 | + break; |
|
622 | + case EE_System::req_type_upgrade: |
|
623 | + do_action("AHEE__{$classname}__detect_activations_or_upgrades__upgrade"); |
|
624 | + do_action('AHEE__EE_Addon__detect_activations_or_upgrades__upgrade', $this); |
|
625 | + $this->upgrade(); |
|
626 | + $this->update_list_of_installed_versions($activation_history_for_addon); |
|
627 | + break; |
|
628 | + case EE_System::req_type_downgrade: |
|
629 | + do_action("AHEE__{$classname}__detect_activations_or_upgrades__downgrade"); |
|
630 | + do_action('AHEE__EE_Addon__detect_activations_or_upgrades__downgrade', $this); |
|
631 | + $this->downgrade(); |
|
632 | + $this->update_list_of_installed_versions($activation_history_for_addon); |
|
633 | + break; |
|
634 | + case EE_System::req_type_normal: |
|
635 | + default: |
|
636 | 636 | // $this->_maybe_redirect_to_ee_about(); |
637 | - break; |
|
638 | - } |
|
639 | - |
|
640 | - do_action("AHEE__{$classname}__detect_if_activation_or_upgrade__complete"); |
|
641 | - } |
|
642 | - |
|
643 | - /** |
|
644 | - * Updates the version history for this addon |
|
645 | - * |
|
646 | - * @param array $version_history |
|
647 | - * @param string $current_version_to_add |
|
648 | - * @return boolean success |
|
649 | - */ |
|
650 | - public function update_list_of_installed_versions($version_history = null, $current_version_to_add = null) |
|
651 | - { |
|
652 | - if (! $version_history) { |
|
653 | - $version_history = $this->get_activation_history(); |
|
654 | - } |
|
655 | - if ($current_version_to_add === null) { |
|
656 | - $current_version_to_add = $this->version(); |
|
657 | - } |
|
658 | - $version_history[$current_version_to_add][] = date('Y-m-d H:i:s', time()); |
|
659 | - // resave |
|
637 | + break; |
|
638 | + } |
|
639 | + |
|
640 | + do_action("AHEE__{$classname}__detect_if_activation_or_upgrade__complete"); |
|
641 | + } |
|
642 | + |
|
643 | + /** |
|
644 | + * Updates the version history for this addon |
|
645 | + * |
|
646 | + * @param array $version_history |
|
647 | + * @param string $current_version_to_add |
|
648 | + * @return boolean success |
|
649 | + */ |
|
650 | + public function update_list_of_installed_versions($version_history = null, $current_version_to_add = null) |
|
651 | + { |
|
652 | + if (! $version_history) { |
|
653 | + $version_history = $this->get_activation_history(); |
|
654 | + } |
|
655 | + if ($current_version_to_add === null) { |
|
656 | + $current_version_to_add = $this->version(); |
|
657 | + } |
|
658 | + $version_history[$current_version_to_add][] = date('Y-m-d H:i:s', time()); |
|
659 | + // resave |
|
660 | 660 | // echo "updating list of installed versions:".$this->get_activation_history_option_name();d($version_history); |
661 | - return update_option($this->get_activation_history_option_name(), $version_history); |
|
662 | - } |
|
663 | - |
|
664 | - /** |
|
665 | - * Gets the name of the wp option that stores the activation history |
|
666 | - * of this addon |
|
667 | - * |
|
668 | - * @return string |
|
669 | - */ |
|
670 | - public function get_activation_history_option_name() |
|
671 | - { |
|
672 | - return self::ee_addon_version_history_option_prefix . $this->name(); |
|
673 | - } |
|
674 | - |
|
675 | - |
|
676 | - /** |
|
677 | - * Gets the wp option which stores the activation history for this addon |
|
678 | - * |
|
679 | - * @return array |
|
680 | - */ |
|
681 | - public function get_activation_history() |
|
682 | - { |
|
683 | - return get_option($this->get_activation_history_option_name(), null); |
|
684 | - } |
|
685 | - |
|
686 | - |
|
687 | - /** |
|
688 | - * @param string $config_section |
|
689 | - */ |
|
690 | - public function set_config_section($config_section = '') |
|
691 | - { |
|
692 | - $this->_config_section = ! empty($config_section) ? $config_section : 'addons'; |
|
693 | - } |
|
694 | - |
|
695 | - /** |
|
696 | - * Sets the filepath to the main plugin file |
|
697 | - * |
|
698 | - * @param string $filepath |
|
699 | - */ |
|
700 | - public function set_main_plugin_file($filepath) |
|
701 | - { |
|
702 | - $this->_main_plugin_file = $filepath; |
|
703 | - } |
|
704 | - |
|
705 | - /** |
|
706 | - * gets the filepath to teh main file |
|
707 | - * |
|
708 | - * @return string |
|
709 | - */ |
|
710 | - public function get_main_plugin_file() |
|
711 | - { |
|
712 | - return $this->_main_plugin_file; |
|
713 | - } |
|
714 | - |
|
715 | - /** |
|
716 | - * Gets the filename (no path) of the main file (the main file loaded |
|
717 | - * by WP) |
|
718 | - * |
|
719 | - * @return string |
|
720 | - */ |
|
721 | - public function get_main_plugin_file_basename() |
|
722 | - { |
|
723 | - return plugin_basename($this->get_main_plugin_file()); |
|
724 | - } |
|
725 | - |
|
726 | - /** |
|
727 | - * Gets the folder name which contains the main plugin file |
|
728 | - * |
|
729 | - * @return string |
|
730 | - */ |
|
731 | - public function get_main_plugin_file_dirname() |
|
732 | - { |
|
733 | - return dirname($this->get_main_plugin_file()); |
|
734 | - } |
|
735 | - |
|
736 | - |
|
737 | - /** |
|
738 | - * sets hooks used in the admin |
|
739 | - * |
|
740 | - * @return void |
|
741 | - */ |
|
742 | - public function admin_init() |
|
743 | - { |
|
744 | - // is admin and not in M-Mode ? |
|
745 | - if (is_admin() && ! EE_Maintenance_Mode::instance()->level()) { |
|
746 | - add_filter('plugin_action_links', array($this, 'plugin_action_links'), 10, 2); |
|
747 | - add_filter('after_plugin_row_' . $this->_plugin_basename, array($this, 'after_plugin_row'), 10, 3); |
|
748 | - } |
|
749 | - } |
|
750 | - |
|
751 | - |
|
752 | - /** |
|
753 | - * plugin_actions |
|
754 | - * Add a settings link to the Plugins page, so people can go straight from the plugin page to the settings page. |
|
755 | - * |
|
756 | - * @param $links |
|
757 | - * @param $file |
|
758 | - * @return array |
|
759 | - */ |
|
760 | - public function plugin_action_links($links, $file) |
|
761 | - { |
|
762 | - if ($file === $this->plugin_basename() && $this->plugin_action_slug() !== '') { |
|
763 | - // before other links |
|
764 | - array_unshift( |
|
765 | - $links, |
|
766 | - '<a href="admin.php?page=' . $this->plugin_action_slug() . '">' |
|
767 | - . esc_html__('Settings', 'event_espresso') |
|
768 | - . '</a>' |
|
769 | - ); |
|
770 | - } |
|
771 | - return $links; |
|
772 | - } |
|
773 | - |
|
774 | - |
|
775 | - /** |
|
776 | - * after_plugin_row |
|
777 | - * Add additional content to the plugins page plugin row |
|
778 | - * Inserts another row |
|
779 | - * |
|
780 | - * @param $plugin_file |
|
781 | - * @param $plugin_data |
|
782 | - * @param $status |
|
783 | - * @return void |
|
784 | - */ |
|
785 | - public function after_plugin_row($plugin_file, $plugin_data, $status) |
|
786 | - { |
|
787 | - $after_plugin_row = ''; |
|
788 | - $plugins_page_row = $this->get_plugins_page_row(); |
|
789 | - if (! empty($plugins_page_row) && $plugin_file === $this->plugin_basename()) { |
|
790 | - $class = $status ? 'active' : 'inactive'; |
|
791 | - $link_text = isset($plugins_page_row['link_text']) ? $plugins_page_row['link_text'] : ''; |
|
792 | - $link_url = isset($plugins_page_row['link_url']) ? $plugins_page_row['link_url'] : ''; |
|
793 | - $description = isset($plugins_page_row['description']) |
|
794 | - ? $plugins_page_row['description'] |
|
795 | - : ''; |
|
796 | - if (! empty($link_text) && ! empty($link_url) && ! empty($description)) { |
|
797 | - $after_plugin_row .= '<tr id="' . sanitize_title($plugin_file) . '-ee-addon" class="' . $class . '">'; |
|
798 | - $after_plugin_row .= '<th class="check-column" scope="row"></th>'; |
|
799 | - $after_plugin_row .= '<td class="ee-addon-upsell-info-title-td plugin-title column-primary">'; |
|
800 | - $after_plugin_row .= '<style> |
|
661 | + return update_option($this->get_activation_history_option_name(), $version_history); |
|
662 | + } |
|
663 | + |
|
664 | + /** |
|
665 | + * Gets the name of the wp option that stores the activation history |
|
666 | + * of this addon |
|
667 | + * |
|
668 | + * @return string |
|
669 | + */ |
|
670 | + public function get_activation_history_option_name() |
|
671 | + { |
|
672 | + return self::ee_addon_version_history_option_prefix . $this->name(); |
|
673 | + } |
|
674 | + |
|
675 | + |
|
676 | + /** |
|
677 | + * Gets the wp option which stores the activation history for this addon |
|
678 | + * |
|
679 | + * @return array |
|
680 | + */ |
|
681 | + public function get_activation_history() |
|
682 | + { |
|
683 | + return get_option($this->get_activation_history_option_name(), null); |
|
684 | + } |
|
685 | + |
|
686 | + |
|
687 | + /** |
|
688 | + * @param string $config_section |
|
689 | + */ |
|
690 | + public function set_config_section($config_section = '') |
|
691 | + { |
|
692 | + $this->_config_section = ! empty($config_section) ? $config_section : 'addons'; |
|
693 | + } |
|
694 | + |
|
695 | + /** |
|
696 | + * Sets the filepath to the main plugin file |
|
697 | + * |
|
698 | + * @param string $filepath |
|
699 | + */ |
|
700 | + public function set_main_plugin_file($filepath) |
|
701 | + { |
|
702 | + $this->_main_plugin_file = $filepath; |
|
703 | + } |
|
704 | + |
|
705 | + /** |
|
706 | + * gets the filepath to teh main file |
|
707 | + * |
|
708 | + * @return string |
|
709 | + */ |
|
710 | + public function get_main_plugin_file() |
|
711 | + { |
|
712 | + return $this->_main_plugin_file; |
|
713 | + } |
|
714 | + |
|
715 | + /** |
|
716 | + * Gets the filename (no path) of the main file (the main file loaded |
|
717 | + * by WP) |
|
718 | + * |
|
719 | + * @return string |
|
720 | + */ |
|
721 | + public function get_main_plugin_file_basename() |
|
722 | + { |
|
723 | + return plugin_basename($this->get_main_plugin_file()); |
|
724 | + } |
|
725 | + |
|
726 | + /** |
|
727 | + * Gets the folder name which contains the main plugin file |
|
728 | + * |
|
729 | + * @return string |
|
730 | + */ |
|
731 | + public function get_main_plugin_file_dirname() |
|
732 | + { |
|
733 | + return dirname($this->get_main_plugin_file()); |
|
734 | + } |
|
735 | + |
|
736 | + |
|
737 | + /** |
|
738 | + * sets hooks used in the admin |
|
739 | + * |
|
740 | + * @return void |
|
741 | + */ |
|
742 | + public function admin_init() |
|
743 | + { |
|
744 | + // is admin and not in M-Mode ? |
|
745 | + if (is_admin() && ! EE_Maintenance_Mode::instance()->level()) { |
|
746 | + add_filter('plugin_action_links', array($this, 'plugin_action_links'), 10, 2); |
|
747 | + add_filter('after_plugin_row_' . $this->_plugin_basename, array($this, 'after_plugin_row'), 10, 3); |
|
748 | + } |
|
749 | + } |
|
750 | + |
|
751 | + |
|
752 | + /** |
|
753 | + * plugin_actions |
|
754 | + * Add a settings link to the Plugins page, so people can go straight from the plugin page to the settings page. |
|
755 | + * |
|
756 | + * @param $links |
|
757 | + * @param $file |
|
758 | + * @return array |
|
759 | + */ |
|
760 | + public function plugin_action_links($links, $file) |
|
761 | + { |
|
762 | + if ($file === $this->plugin_basename() && $this->plugin_action_slug() !== '') { |
|
763 | + // before other links |
|
764 | + array_unshift( |
|
765 | + $links, |
|
766 | + '<a href="admin.php?page=' . $this->plugin_action_slug() . '">' |
|
767 | + . esc_html__('Settings', 'event_espresso') |
|
768 | + . '</a>' |
|
769 | + ); |
|
770 | + } |
|
771 | + return $links; |
|
772 | + } |
|
773 | + |
|
774 | + |
|
775 | + /** |
|
776 | + * after_plugin_row |
|
777 | + * Add additional content to the plugins page plugin row |
|
778 | + * Inserts another row |
|
779 | + * |
|
780 | + * @param $plugin_file |
|
781 | + * @param $plugin_data |
|
782 | + * @param $status |
|
783 | + * @return void |
|
784 | + */ |
|
785 | + public function after_plugin_row($plugin_file, $plugin_data, $status) |
|
786 | + { |
|
787 | + $after_plugin_row = ''; |
|
788 | + $plugins_page_row = $this->get_plugins_page_row(); |
|
789 | + if (! empty($plugins_page_row) && $plugin_file === $this->plugin_basename()) { |
|
790 | + $class = $status ? 'active' : 'inactive'; |
|
791 | + $link_text = isset($plugins_page_row['link_text']) ? $plugins_page_row['link_text'] : ''; |
|
792 | + $link_url = isset($plugins_page_row['link_url']) ? $plugins_page_row['link_url'] : ''; |
|
793 | + $description = isset($plugins_page_row['description']) |
|
794 | + ? $plugins_page_row['description'] |
|
795 | + : ''; |
|
796 | + if (! empty($link_text) && ! empty($link_url) && ! empty($description)) { |
|
797 | + $after_plugin_row .= '<tr id="' . sanitize_title($plugin_file) . '-ee-addon" class="' . $class . '">'; |
|
798 | + $after_plugin_row .= '<th class="check-column" scope="row"></th>'; |
|
799 | + $after_plugin_row .= '<td class="ee-addon-upsell-info-title-td plugin-title column-primary">'; |
|
800 | + $after_plugin_row .= '<style> |
|
801 | 801 | .ee-button, |
802 | 802 | .ee-button:active, |
803 | 803 | .ee-button:visited { |
@@ -834,49 +834,49 @@ discard block |
||
834 | 834 | } |
835 | 835 | .ee-button:active { top:0; } |
836 | 836 | </style>'; |
837 | - $after_plugin_row .= ' |
|
837 | + $after_plugin_row .= ' |
|
838 | 838 | <p class="ee-addon-upsell-info-dv"> |
839 | 839 | <a class="ee-button" href="' . $link_url . '">' |
840 | - . $link_text |
|
841 | - . ' <span class="dashicons dashicons-arrow-right-alt2" style="margin:0;"></span>' |
|
842 | - . '</a> |
|
840 | + . $link_text |
|
841 | + . ' <span class="dashicons dashicons-arrow-right-alt2" style="margin:0;"></span>' |
|
842 | + . '</a> |
|
843 | 843 | </p>'; |
844 | - $after_plugin_row .= '</td>'; |
|
845 | - $after_plugin_row .= '<td class="ee-addon-upsell-info-desc-td column-description desc">'; |
|
846 | - $after_plugin_row .= $description; |
|
847 | - $after_plugin_row .= '</td>'; |
|
848 | - $after_plugin_row .= '</tr>'; |
|
849 | - } else { |
|
850 | - $after_plugin_row .= $description; |
|
851 | - } |
|
852 | - } |
|
853 | - |
|
854 | - echo $after_plugin_row; |
|
855 | - } |
|
856 | - |
|
857 | - |
|
858 | - /** |
|
859 | - * A safe space for addons to add additional logic like setting hooks that need to be set early in the request. |
|
860 | - * Child classes that have logic like that to run can override this method declaration. This was not made abstract |
|
861 | - * for back compat reasons. |
|
862 | - * |
|
863 | - * This will fire on the `AHEE__EE_System__load_espresso_addons__complete` hook at priority 999. |
|
864 | - * |
|
865 | - * It is recommended, if client code is `de-registering` an add-on, then do it on the |
|
866 | - * `AHEE__EE_System__load_espresso_addons__complete` hook before priority 999 so as to ensure any code logic in this |
|
867 | - * callback does not get run/set in that request. |
|
868 | - * |
|
869 | - * Also, keep in mind that if a registered add-on happens to be deactivated via |
|
870 | - * EE_System::_deactivate_incompatible_addons() because its incompatible, any code executed in this method |
|
871 | - * (including setting hooks etc) will have executed before the plugin was deactivated. If you use |
|
872 | - * `after_registration` to set any filter and/or action hooks and want to ensure they are removed on this add-on's |
|
873 | - * deactivation, you can override `EE_Addon::deactivation` and unset your hooks and filters there. Just remember |
|
874 | - * to call `parent::deactivation`. |
|
875 | - * |
|
876 | - * @since 4.9.26 |
|
877 | - */ |
|
878 | - public function after_registration() |
|
879 | - { |
|
880 | - // cricket chirp... cricket chirp... |
|
881 | - } |
|
844 | + $after_plugin_row .= '</td>'; |
|
845 | + $after_plugin_row .= '<td class="ee-addon-upsell-info-desc-td column-description desc">'; |
|
846 | + $after_plugin_row .= $description; |
|
847 | + $after_plugin_row .= '</td>'; |
|
848 | + $after_plugin_row .= '</tr>'; |
|
849 | + } else { |
|
850 | + $after_plugin_row .= $description; |
|
851 | + } |
|
852 | + } |
|
853 | + |
|
854 | + echo $after_plugin_row; |
|
855 | + } |
|
856 | + |
|
857 | + |
|
858 | + /** |
|
859 | + * A safe space for addons to add additional logic like setting hooks that need to be set early in the request. |
|
860 | + * Child classes that have logic like that to run can override this method declaration. This was not made abstract |
|
861 | + * for back compat reasons. |
|
862 | + * |
|
863 | + * This will fire on the `AHEE__EE_System__load_espresso_addons__complete` hook at priority 999. |
|
864 | + * |
|
865 | + * It is recommended, if client code is `de-registering` an add-on, then do it on the |
|
866 | + * `AHEE__EE_System__load_espresso_addons__complete` hook before priority 999 so as to ensure any code logic in this |
|
867 | + * callback does not get run/set in that request. |
|
868 | + * |
|
869 | + * Also, keep in mind that if a registered add-on happens to be deactivated via |
|
870 | + * EE_System::_deactivate_incompatible_addons() because its incompatible, any code executed in this method |
|
871 | + * (including setting hooks etc) will have executed before the plugin was deactivated. If you use |
|
872 | + * `after_registration` to set any filter and/or action hooks and want to ensure they are removed on this add-on's |
|
873 | + * deactivation, you can override `EE_Addon::deactivation` and unset your hooks and filters there. Just remember |
|
874 | + * to call `parent::deactivation`. |
|
875 | + * |
|
876 | + * @since 4.9.26 |
|
877 | + */ |
|
878 | + public function after_registration() |
|
879 | + { |
|
880 | + // cricket chirp... cricket chirp... |
|
881 | + } |
|
882 | 882 | } |
@@ -107,7 +107,7 @@ discard block |
||
107 | 107 | */ |
108 | 108 | public function __construct(EE_Dependency_Map $dependency_map = null, DomainInterface $domain = null) |
109 | 109 | { |
110 | - if($dependency_map instanceof EE_Dependency_Map) { |
|
110 | + if ($dependency_map instanceof EE_Dependency_Map) { |
|
111 | 111 | $this->setDependencyMap($dependency_map); |
112 | 112 | } |
113 | 113 | if ($domain instanceof DomainInterface) { |
@@ -291,7 +291,7 @@ discard block |
||
291 | 291 | public function set_plugins_page_row($plugins_page_row = array()) |
292 | 292 | { |
293 | 293 | // sigh.... check for example content that I stupidly merged to master and remove it if found |
294 | - if (! is_array($plugins_page_row) |
|
294 | + if ( ! is_array($plugins_page_row) |
|
295 | 295 | && strpos($plugins_page_row, '<h3>Promotions Addon Upsell Info</h3>') !== false |
296 | 296 | ) { |
297 | 297 | $plugins_page_row = array(); |
@@ -560,7 +560,7 @@ discard block |
||
560 | 560 | */ |
561 | 561 | public function get_activation_indicator_option_name() |
562 | 562 | { |
563 | - return 'ee_activation_' . $this->name(); |
|
563 | + return 'ee_activation_'.$this->name(); |
|
564 | 564 | } |
565 | 565 | |
566 | 566 | |
@@ -582,7 +582,7 @@ discard block |
||
582 | 582 | */ |
583 | 583 | public function detect_req_type() |
584 | 584 | { |
585 | - if (! $this->_req_type) { |
|
585 | + if ( ! $this->_req_type) { |
|
586 | 586 | $this->detect_activation_or_upgrade(); |
587 | 587 | } |
588 | 588 | return $this->_req_type; |
@@ -649,7 +649,7 @@ discard block |
||
649 | 649 | */ |
650 | 650 | public function update_list_of_installed_versions($version_history = null, $current_version_to_add = null) |
651 | 651 | { |
652 | - if (! $version_history) { |
|
652 | + if ( ! $version_history) { |
|
653 | 653 | $version_history = $this->get_activation_history(); |
654 | 654 | } |
655 | 655 | if ($current_version_to_add === null) { |
@@ -669,7 +669,7 @@ discard block |
||
669 | 669 | */ |
670 | 670 | public function get_activation_history_option_name() |
671 | 671 | { |
672 | - return self::ee_addon_version_history_option_prefix . $this->name(); |
|
672 | + return self::ee_addon_version_history_option_prefix.$this->name(); |
|
673 | 673 | } |
674 | 674 | |
675 | 675 | |
@@ -744,7 +744,7 @@ discard block |
||
744 | 744 | // is admin and not in M-Mode ? |
745 | 745 | if (is_admin() && ! EE_Maintenance_Mode::instance()->level()) { |
746 | 746 | add_filter('plugin_action_links', array($this, 'plugin_action_links'), 10, 2); |
747 | - add_filter('after_plugin_row_' . $this->_plugin_basename, array($this, 'after_plugin_row'), 10, 3); |
|
747 | + add_filter('after_plugin_row_'.$this->_plugin_basename, array($this, 'after_plugin_row'), 10, 3); |
|
748 | 748 | } |
749 | 749 | } |
750 | 750 | |
@@ -763,7 +763,7 @@ discard block |
||
763 | 763 | // before other links |
764 | 764 | array_unshift( |
765 | 765 | $links, |
766 | - '<a href="admin.php?page=' . $this->plugin_action_slug() . '">' |
|
766 | + '<a href="admin.php?page='.$this->plugin_action_slug().'">' |
|
767 | 767 | . esc_html__('Settings', 'event_espresso') |
768 | 768 | . '</a>' |
769 | 769 | ); |
@@ -786,15 +786,15 @@ discard block |
||
786 | 786 | { |
787 | 787 | $after_plugin_row = ''; |
788 | 788 | $plugins_page_row = $this->get_plugins_page_row(); |
789 | - if (! empty($plugins_page_row) && $plugin_file === $this->plugin_basename()) { |
|
789 | + if ( ! empty($plugins_page_row) && $plugin_file === $this->plugin_basename()) { |
|
790 | 790 | $class = $status ? 'active' : 'inactive'; |
791 | 791 | $link_text = isset($plugins_page_row['link_text']) ? $plugins_page_row['link_text'] : ''; |
792 | 792 | $link_url = isset($plugins_page_row['link_url']) ? $plugins_page_row['link_url'] : ''; |
793 | 793 | $description = isset($plugins_page_row['description']) |
794 | 794 | ? $plugins_page_row['description'] |
795 | 795 | : ''; |
796 | - if (! empty($link_text) && ! empty($link_url) && ! empty($description)) { |
|
797 | - $after_plugin_row .= '<tr id="' . sanitize_title($plugin_file) . '-ee-addon" class="' . $class . '">'; |
|
796 | + if ( ! empty($link_text) && ! empty($link_url) && ! empty($description)) { |
|
797 | + $after_plugin_row .= '<tr id="'.sanitize_title($plugin_file).'-ee-addon" class="'.$class.'">'; |
|
798 | 798 | $after_plugin_row .= '<th class="check-column" scope="row"></th>'; |
799 | 799 | $after_plugin_row .= '<td class="ee-addon-upsell-info-title-td plugin-title column-primary">'; |
800 | 800 | $after_plugin_row .= '<style> |
@@ -836,7 +836,7 @@ discard block |
||
836 | 836 | </style>'; |
837 | 837 | $after_plugin_row .= ' |
838 | 838 | <p class="ee-addon-upsell-info-dv"> |
839 | - <a class="ee-button" href="' . $link_url . '">' |
|
839 | + <a class="ee-button" href="' . $link_url.'">' |
|
840 | 840 | . $link_text |
841 | 841 | . ' <span class="dashicons dashicons-arrow-right-alt2" style="margin:0;"></span>' |
842 | 842 | . '</a> |
@@ -18,16 +18,16 @@ |
||
18 | 18 | interface RequiresDomainInterface |
19 | 19 | { |
20 | 20 | |
21 | - /** |
|
22 | - * @param DomainInterface $domain |
|
23 | - */ |
|
24 | - public function setDomain(DomainInterface $domain); |
|
21 | + /** |
|
22 | + * @param DomainInterface $domain |
|
23 | + */ |
|
24 | + public function setDomain(DomainInterface $domain); |
|
25 | 25 | |
26 | 26 | |
27 | - /** |
|
28 | - * @return DomainInterface |
|
29 | - */ |
|
30 | - public function domain(); |
|
27 | + /** |
|
28 | + * @return DomainInterface |
|
29 | + */ |
|
30 | + public function domain(); |
|
31 | 31 | |
32 | 32 | } |
33 | 33 | // Location: RequiresDomainInterface.php |
@@ -484,7 +484,7 @@ discard block |
||
484 | 484 | * |
485 | 485 | * @access public |
486 | 486 | * @param array $data |
487 | - * @return TRUE on success, FALSE on fail |
|
487 | + * @return boolean on success, FALSE on fail |
|
488 | 488 | */ |
489 | 489 | public function set_session_data($data) |
490 | 490 | { |
@@ -511,7 +511,7 @@ discard block |
||
511 | 511 | /** |
512 | 512 | * @initiate session |
513 | 513 | * @access private |
514 | - * @return TRUE on success, FALSE on fail |
|
514 | + * @return boolean on success, FALSE on fail |
|
515 | 515 | * @throws EE_Error |
516 | 516 | * @throws InvalidArgumentException |
517 | 517 | * @throws InvalidDataTypeException |
@@ -746,7 +746,7 @@ discard block |
||
746 | 746 | * @update session data prior to saving to the db |
747 | 747 | * @access public |
748 | 748 | * @param bool $new_session |
749 | - * @return TRUE on success, FALSE on fail |
|
749 | + * @return boolean on success, FALSE on fail |
|
750 | 750 | * @throws EE_Error |
751 | 751 | * @throws InvalidArgumentException |
752 | 752 | * @throws InvalidDataTypeException |
@@ -847,7 +847,7 @@ discard block |
||
847 | 847 | * _save_session_to_db |
848 | 848 | * |
849 | 849 | * @param bool $clear_session |
850 | - * @return string |
|
850 | + * @return boolean |
|
851 | 851 | * @throws EE_Error |
852 | 852 | * @throws InvalidArgumentException |
853 | 853 | * @throws InvalidDataTypeException |
@@ -1008,7 +1008,7 @@ discard block |
||
1008 | 1008 | * @access public |
1009 | 1009 | * @param array|mixed $data_to_reset |
1010 | 1010 | * @param bool $show_all_notices |
1011 | - * @return TRUE on success, FALSE on fail |
|
1011 | + * @return boolean on success, FALSE on fail |
|
1012 | 1012 | */ |
1013 | 1013 | public function reset_data($data_to_reset = array(), $show_all_notices = false) |
1014 | 1014 | { |
@@ -20,1210 +20,1210 @@ discard block |
||
20 | 20 | class EE_Session implements SessionIdentifierInterface |
21 | 21 | { |
22 | 22 | |
23 | - const session_id_prefix = 'ee_ssn_'; |
|
24 | - |
|
25 | - const hash_check_prefix = 'ee_shc_'; |
|
26 | - |
|
27 | - const OPTION_NAME_SETTINGS = 'ee_session_settings'; |
|
28 | - |
|
29 | - /** |
|
30 | - * instance of the EE_Session object |
|
31 | - * |
|
32 | - * @var EE_Session |
|
33 | - */ |
|
34 | - private static $_instance; |
|
35 | - |
|
36 | - /** |
|
37 | - * @var CacheStorageInterface $cache_storage |
|
38 | - */ |
|
39 | - protected $cache_storage; |
|
40 | - |
|
41 | - /** |
|
42 | - * EE_Encryption object |
|
43 | - * |
|
44 | - * @var EE_Encryption |
|
45 | - */ |
|
46 | - protected $encryption; |
|
47 | - |
|
48 | - /** |
|
49 | - * the session id |
|
50 | - * |
|
51 | - * @var string |
|
52 | - */ |
|
53 | - private $_sid; |
|
54 | - |
|
55 | - /** |
|
56 | - * session id salt |
|
57 | - * |
|
58 | - * @var string |
|
59 | - */ |
|
60 | - private $_sid_salt; |
|
61 | - |
|
62 | - /** |
|
63 | - * session data |
|
64 | - * |
|
65 | - * @var array |
|
66 | - */ |
|
67 | - private $_session_data = array(); |
|
68 | - |
|
69 | - /** |
|
70 | - * how long an EE session lasts |
|
71 | - * default session lifespan of 2 hours (for not so instant IPNs) |
|
72 | - * |
|
73 | - * @var int |
|
74 | - */ |
|
75 | - private $_lifespan; |
|
76 | - |
|
77 | - /** |
|
78 | - * session expiration time as Unix timestamp in GMT |
|
79 | - * |
|
80 | - * @var int |
|
81 | - */ |
|
82 | - private $_expiration; |
|
83 | - |
|
84 | - /** |
|
85 | - * whether or not session has expired at some point |
|
86 | - * |
|
87 | - * @var boolean |
|
88 | - */ |
|
89 | - private $_expired = false; |
|
90 | - |
|
91 | - /** |
|
92 | - * current time as Unix timestamp in GMT |
|
93 | - * |
|
94 | - * @var int |
|
95 | - */ |
|
96 | - private $_time; |
|
97 | - |
|
98 | - /** |
|
99 | - * whether to encrypt session data |
|
100 | - * |
|
101 | - * @var bool |
|
102 | - */ |
|
103 | - private $_use_encryption; |
|
104 | - |
|
105 | - /** |
|
106 | - * well... according to the server... |
|
107 | - * |
|
108 | - * @var null |
|
109 | - */ |
|
110 | - private $_user_agent; |
|
111 | - |
|
112 | - /** |
|
113 | - * do you really trust the server ? |
|
114 | - * |
|
115 | - * @var null |
|
116 | - */ |
|
117 | - private $_ip_address; |
|
118 | - |
|
119 | - /** |
|
120 | - * current WP user_id |
|
121 | - * |
|
122 | - * @var null |
|
123 | - */ |
|
124 | - private $_wp_user_id; |
|
125 | - |
|
126 | - /** |
|
127 | - * array for defining default session vars |
|
128 | - * |
|
129 | - * @var array |
|
130 | - */ |
|
131 | - private $_default_session_vars = array( |
|
132 | - 'id' => null, |
|
133 | - 'user_id' => null, |
|
134 | - 'ip_address' => null, |
|
135 | - 'user_agent' => null, |
|
136 | - 'init_access' => null, |
|
137 | - 'last_access' => null, |
|
138 | - 'expiration' => null, |
|
139 | - 'pages_visited' => array(), |
|
140 | - ); |
|
141 | - |
|
142 | - /** |
|
143 | - * timestamp for when last garbage collection cycle was performed |
|
144 | - * |
|
145 | - * @var int $_last_gc |
|
146 | - */ |
|
147 | - private $_last_gc; |
|
148 | - |
|
149 | - |
|
150 | - |
|
151 | - /** |
|
152 | - * @singleton method used to instantiate class object |
|
153 | - * @param CacheStorageInterface $cache_storage |
|
154 | - * @param EE_Encryption $encryption |
|
155 | - * @return EE_Session |
|
156 | - * @throws InvalidArgumentException |
|
157 | - * @throws InvalidDataTypeException |
|
158 | - * @throws InvalidInterfaceException |
|
159 | - */ |
|
160 | - public static function instance( |
|
161 | - CacheStorageInterface $cache_storage = null, |
|
162 | - EE_Encryption $encryption = null |
|
163 | - ) { |
|
164 | - // check if class object is instantiated |
|
165 | - // session loading is turned ON by default, but prior to the init hook, can be turned back OFF via: |
|
166 | - // add_filter( 'FHEE_load_EE_Session', '__return_false' ); |
|
167 | - if (! self::$_instance instanceof EE_Session && apply_filters('FHEE_load_EE_Session', true)) { |
|
168 | - self::$_instance = new self($cache_storage, $encryption); |
|
169 | - } |
|
170 | - return self::$_instance; |
|
171 | - } |
|
172 | - |
|
173 | - |
|
174 | - |
|
175 | - /** |
|
176 | - * protected constructor to prevent direct creation |
|
177 | - * |
|
178 | - * @param CacheStorageInterface $cache_storage |
|
179 | - * @param EE_Encryption $encryption |
|
180 | - * @throws InvalidArgumentException |
|
181 | - * @throws InvalidDataTypeException |
|
182 | - * @throws InvalidInterfaceException |
|
183 | - */ |
|
184 | - protected function __construct(CacheStorageInterface $cache_storage, EE_Encryption $encryption = null) |
|
185 | - { |
|
186 | - |
|
187 | - // session loading is turned ON by default, but prior to the init hook, can be turned back OFF via: add_filter( 'FHEE_load_EE_Session', '__return_false' ); |
|
188 | - if (! apply_filters('FHEE_load_EE_Session', true)) { |
|
189 | - return; |
|
190 | - } |
|
191 | - do_action('AHEE_log', __FILE__, __FUNCTION__, ''); |
|
192 | - if (! defined('ESPRESSO_SESSION')) { |
|
193 | - define('ESPRESSO_SESSION', true); |
|
194 | - } |
|
195 | - // default session lifespan in seconds |
|
196 | - $this->_lifespan = apply_filters( |
|
197 | - 'FHEE__EE_Session__construct___lifespan', |
|
198 | - 60 * MINUTE_IN_SECONDS |
|
199 | - ) + 1; |
|
200 | - /* |
|
23 | + const session_id_prefix = 'ee_ssn_'; |
|
24 | + |
|
25 | + const hash_check_prefix = 'ee_shc_'; |
|
26 | + |
|
27 | + const OPTION_NAME_SETTINGS = 'ee_session_settings'; |
|
28 | + |
|
29 | + /** |
|
30 | + * instance of the EE_Session object |
|
31 | + * |
|
32 | + * @var EE_Session |
|
33 | + */ |
|
34 | + private static $_instance; |
|
35 | + |
|
36 | + /** |
|
37 | + * @var CacheStorageInterface $cache_storage |
|
38 | + */ |
|
39 | + protected $cache_storage; |
|
40 | + |
|
41 | + /** |
|
42 | + * EE_Encryption object |
|
43 | + * |
|
44 | + * @var EE_Encryption |
|
45 | + */ |
|
46 | + protected $encryption; |
|
47 | + |
|
48 | + /** |
|
49 | + * the session id |
|
50 | + * |
|
51 | + * @var string |
|
52 | + */ |
|
53 | + private $_sid; |
|
54 | + |
|
55 | + /** |
|
56 | + * session id salt |
|
57 | + * |
|
58 | + * @var string |
|
59 | + */ |
|
60 | + private $_sid_salt; |
|
61 | + |
|
62 | + /** |
|
63 | + * session data |
|
64 | + * |
|
65 | + * @var array |
|
66 | + */ |
|
67 | + private $_session_data = array(); |
|
68 | + |
|
69 | + /** |
|
70 | + * how long an EE session lasts |
|
71 | + * default session lifespan of 2 hours (for not so instant IPNs) |
|
72 | + * |
|
73 | + * @var int |
|
74 | + */ |
|
75 | + private $_lifespan; |
|
76 | + |
|
77 | + /** |
|
78 | + * session expiration time as Unix timestamp in GMT |
|
79 | + * |
|
80 | + * @var int |
|
81 | + */ |
|
82 | + private $_expiration; |
|
83 | + |
|
84 | + /** |
|
85 | + * whether or not session has expired at some point |
|
86 | + * |
|
87 | + * @var boolean |
|
88 | + */ |
|
89 | + private $_expired = false; |
|
90 | + |
|
91 | + /** |
|
92 | + * current time as Unix timestamp in GMT |
|
93 | + * |
|
94 | + * @var int |
|
95 | + */ |
|
96 | + private $_time; |
|
97 | + |
|
98 | + /** |
|
99 | + * whether to encrypt session data |
|
100 | + * |
|
101 | + * @var bool |
|
102 | + */ |
|
103 | + private $_use_encryption; |
|
104 | + |
|
105 | + /** |
|
106 | + * well... according to the server... |
|
107 | + * |
|
108 | + * @var null |
|
109 | + */ |
|
110 | + private $_user_agent; |
|
111 | + |
|
112 | + /** |
|
113 | + * do you really trust the server ? |
|
114 | + * |
|
115 | + * @var null |
|
116 | + */ |
|
117 | + private $_ip_address; |
|
118 | + |
|
119 | + /** |
|
120 | + * current WP user_id |
|
121 | + * |
|
122 | + * @var null |
|
123 | + */ |
|
124 | + private $_wp_user_id; |
|
125 | + |
|
126 | + /** |
|
127 | + * array for defining default session vars |
|
128 | + * |
|
129 | + * @var array |
|
130 | + */ |
|
131 | + private $_default_session_vars = array( |
|
132 | + 'id' => null, |
|
133 | + 'user_id' => null, |
|
134 | + 'ip_address' => null, |
|
135 | + 'user_agent' => null, |
|
136 | + 'init_access' => null, |
|
137 | + 'last_access' => null, |
|
138 | + 'expiration' => null, |
|
139 | + 'pages_visited' => array(), |
|
140 | + ); |
|
141 | + |
|
142 | + /** |
|
143 | + * timestamp for when last garbage collection cycle was performed |
|
144 | + * |
|
145 | + * @var int $_last_gc |
|
146 | + */ |
|
147 | + private $_last_gc; |
|
148 | + |
|
149 | + |
|
150 | + |
|
151 | + /** |
|
152 | + * @singleton method used to instantiate class object |
|
153 | + * @param CacheStorageInterface $cache_storage |
|
154 | + * @param EE_Encryption $encryption |
|
155 | + * @return EE_Session |
|
156 | + * @throws InvalidArgumentException |
|
157 | + * @throws InvalidDataTypeException |
|
158 | + * @throws InvalidInterfaceException |
|
159 | + */ |
|
160 | + public static function instance( |
|
161 | + CacheStorageInterface $cache_storage = null, |
|
162 | + EE_Encryption $encryption = null |
|
163 | + ) { |
|
164 | + // check if class object is instantiated |
|
165 | + // session loading is turned ON by default, but prior to the init hook, can be turned back OFF via: |
|
166 | + // add_filter( 'FHEE_load_EE_Session', '__return_false' ); |
|
167 | + if (! self::$_instance instanceof EE_Session && apply_filters('FHEE_load_EE_Session', true)) { |
|
168 | + self::$_instance = new self($cache_storage, $encryption); |
|
169 | + } |
|
170 | + return self::$_instance; |
|
171 | + } |
|
172 | + |
|
173 | + |
|
174 | + |
|
175 | + /** |
|
176 | + * protected constructor to prevent direct creation |
|
177 | + * |
|
178 | + * @param CacheStorageInterface $cache_storage |
|
179 | + * @param EE_Encryption $encryption |
|
180 | + * @throws InvalidArgumentException |
|
181 | + * @throws InvalidDataTypeException |
|
182 | + * @throws InvalidInterfaceException |
|
183 | + */ |
|
184 | + protected function __construct(CacheStorageInterface $cache_storage, EE_Encryption $encryption = null) |
|
185 | + { |
|
186 | + |
|
187 | + // session loading is turned ON by default, but prior to the init hook, can be turned back OFF via: add_filter( 'FHEE_load_EE_Session', '__return_false' ); |
|
188 | + if (! apply_filters('FHEE_load_EE_Session', true)) { |
|
189 | + return; |
|
190 | + } |
|
191 | + do_action('AHEE_log', __FILE__, __FUNCTION__, ''); |
|
192 | + if (! defined('ESPRESSO_SESSION')) { |
|
193 | + define('ESPRESSO_SESSION', true); |
|
194 | + } |
|
195 | + // default session lifespan in seconds |
|
196 | + $this->_lifespan = apply_filters( |
|
197 | + 'FHEE__EE_Session__construct___lifespan', |
|
198 | + 60 * MINUTE_IN_SECONDS |
|
199 | + ) + 1; |
|
200 | + /* |
|
201 | 201 | * do something like the following to adjust the session lifespan: |
202 | 202 | * public static function session_lifespan() { |
203 | 203 | * return 15 * MINUTE_IN_SECONDS; |
204 | 204 | * } |
205 | 205 | */ |
206 | - // retrieve session options from db |
|
207 | - $session_settings = (array) get_option(EE_Session::OPTION_NAME_SETTINGS, array()); |
|
208 | - if (! empty($session_settings)) { |
|
209 | - // cycle though existing session options |
|
210 | - foreach ($session_settings as $var_name => $session_setting) { |
|
211 | - // set values for class properties |
|
212 | - $var_name = '_' . $var_name; |
|
213 | - $this->{$var_name} = $session_setting; |
|
214 | - } |
|
215 | - } |
|
216 | - $this->cache_storage = $cache_storage; |
|
217 | - // are we using encryption? |
|
218 | - $this->_use_encryption = $encryption instanceof EE_Encryption |
|
219 | - && EE_Registry::instance()->CFG->admin->encode_session_data(); |
|
220 | - // \EEH_Debug_Tools::printr($this->_use_encryption, '$this->_use_encryption', __FILE__, __LINE__); |
|
221 | - // encrypt data via: $this->encryption->encrypt(); |
|
222 | - $this->encryption = $encryption; |
|
223 | - // filter hook allows outside functions/classes/plugins to change default empty cart |
|
224 | - $extra_default_session_vars = apply_filters('FHEE__EE_Session__construct__extra_default_session_vars', array()); |
|
225 | - array_merge($this->_default_session_vars, $extra_default_session_vars); |
|
226 | - // apply default session vars |
|
227 | - $this->_set_defaults(); |
|
228 | - add_action('AHEE__EE_System__initialize', array($this, 'open_session')); |
|
229 | - // check request for 'clear_session' param |
|
230 | - add_action('AHEE__EE_Request_Handler__construct__complete', array($this, 'wp_loaded')); |
|
231 | - // once everything is all said and done, |
|
232 | - add_action('shutdown', array($this, 'update'), 100); |
|
233 | - add_action('shutdown', array($this, 'garbageCollection'), 1000); |
|
234 | - $this->configure_garbage_collection_filters(); |
|
235 | - } |
|
236 | - |
|
237 | - |
|
238 | - |
|
239 | - /** |
|
240 | - * @return void |
|
241 | - * @throws EE_Error |
|
242 | - * @throws InvalidArgumentException |
|
243 | - * @throws InvalidDataTypeException |
|
244 | - * @throws InvalidInterfaceException |
|
245 | - * @throws InvalidSessionDataException |
|
246 | - */ |
|
247 | - public function open_session() |
|
248 | - { |
|
249 | - // check for existing session and retrieve it from db |
|
250 | - if (! $this->_espresso_session()) { |
|
251 | - // or just start a new one |
|
252 | - $this->_create_espresso_session(); |
|
253 | - } |
|
254 | - } |
|
255 | - |
|
256 | - |
|
257 | - |
|
258 | - /** |
|
259 | - * @return bool |
|
260 | - */ |
|
261 | - public function expired() |
|
262 | - { |
|
263 | - return $this->_expired; |
|
264 | - } |
|
265 | - |
|
266 | - |
|
267 | - |
|
268 | - /** |
|
269 | - * @return void |
|
270 | - */ |
|
271 | - public function reset_expired() |
|
272 | - { |
|
273 | - $this->_expired = false; |
|
274 | - } |
|
275 | - |
|
276 | - |
|
277 | - /** |
|
278 | - * @return int |
|
279 | - */ |
|
280 | - public function expiration() |
|
281 | - { |
|
282 | - return $this->_expiration; |
|
283 | - } |
|
284 | - |
|
285 | - |
|
286 | - |
|
287 | - /** |
|
288 | - * @return int |
|
289 | - */ |
|
290 | - public function extension() |
|
291 | - { |
|
292 | - return apply_filters('FHEE__EE_Session__extend_expiration__seconds_added', 10 * MINUTE_IN_SECONDS); |
|
293 | - } |
|
294 | - |
|
295 | - |
|
296 | - |
|
297 | - /** |
|
298 | - * @param int $time number of seconds to add to session expiration |
|
299 | - */ |
|
300 | - public function extend_expiration($time = 0) |
|
301 | - { |
|
302 | - $time = $time ? $time : $this->extension(); |
|
303 | - $this->_expiration += absint($time); |
|
304 | - } |
|
305 | - |
|
306 | - |
|
307 | - |
|
308 | - /** |
|
309 | - * @return int |
|
310 | - */ |
|
311 | - public function lifespan() |
|
312 | - { |
|
313 | - return $this->_lifespan; |
|
314 | - } |
|
315 | - |
|
316 | - |
|
317 | - |
|
318 | - /** |
|
319 | - * This just sets some defaults for the _session data property |
|
320 | - * |
|
321 | - * @access private |
|
322 | - * @return void |
|
323 | - */ |
|
324 | - private function _set_defaults() |
|
325 | - { |
|
326 | - // set some defaults |
|
327 | - foreach ($this->_default_session_vars as $key => $default_var) { |
|
328 | - if (is_array($default_var)) { |
|
329 | - $this->_session_data[ $key ] = array(); |
|
330 | - } else { |
|
331 | - $this->_session_data[ $key ] = ''; |
|
332 | - } |
|
333 | - } |
|
334 | - } |
|
206 | + // retrieve session options from db |
|
207 | + $session_settings = (array) get_option(EE_Session::OPTION_NAME_SETTINGS, array()); |
|
208 | + if (! empty($session_settings)) { |
|
209 | + // cycle though existing session options |
|
210 | + foreach ($session_settings as $var_name => $session_setting) { |
|
211 | + // set values for class properties |
|
212 | + $var_name = '_' . $var_name; |
|
213 | + $this->{$var_name} = $session_setting; |
|
214 | + } |
|
215 | + } |
|
216 | + $this->cache_storage = $cache_storage; |
|
217 | + // are we using encryption? |
|
218 | + $this->_use_encryption = $encryption instanceof EE_Encryption |
|
219 | + && EE_Registry::instance()->CFG->admin->encode_session_data(); |
|
220 | + // \EEH_Debug_Tools::printr($this->_use_encryption, '$this->_use_encryption', __FILE__, __LINE__); |
|
221 | + // encrypt data via: $this->encryption->encrypt(); |
|
222 | + $this->encryption = $encryption; |
|
223 | + // filter hook allows outside functions/classes/plugins to change default empty cart |
|
224 | + $extra_default_session_vars = apply_filters('FHEE__EE_Session__construct__extra_default_session_vars', array()); |
|
225 | + array_merge($this->_default_session_vars, $extra_default_session_vars); |
|
226 | + // apply default session vars |
|
227 | + $this->_set_defaults(); |
|
228 | + add_action('AHEE__EE_System__initialize', array($this, 'open_session')); |
|
229 | + // check request for 'clear_session' param |
|
230 | + add_action('AHEE__EE_Request_Handler__construct__complete', array($this, 'wp_loaded')); |
|
231 | + // once everything is all said and done, |
|
232 | + add_action('shutdown', array($this, 'update'), 100); |
|
233 | + add_action('shutdown', array($this, 'garbageCollection'), 1000); |
|
234 | + $this->configure_garbage_collection_filters(); |
|
235 | + } |
|
236 | + |
|
237 | + |
|
238 | + |
|
239 | + /** |
|
240 | + * @return void |
|
241 | + * @throws EE_Error |
|
242 | + * @throws InvalidArgumentException |
|
243 | + * @throws InvalidDataTypeException |
|
244 | + * @throws InvalidInterfaceException |
|
245 | + * @throws InvalidSessionDataException |
|
246 | + */ |
|
247 | + public function open_session() |
|
248 | + { |
|
249 | + // check for existing session and retrieve it from db |
|
250 | + if (! $this->_espresso_session()) { |
|
251 | + // or just start a new one |
|
252 | + $this->_create_espresso_session(); |
|
253 | + } |
|
254 | + } |
|
255 | + |
|
256 | + |
|
257 | + |
|
258 | + /** |
|
259 | + * @return bool |
|
260 | + */ |
|
261 | + public function expired() |
|
262 | + { |
|
263 | + return $this->_expired; |
|
264 | + } |
|
265 | + |
|
266 | + |
|
267 | + |
|
268 | + /** |
|
269 | + * @return void |
|
270 | + */ |
|
271 | + public function reset_expired() |
|
272 | + { |
|
273 | + $this->_expired = false; |
|
274 | + } |
|
275 | + |
|
276 | + |
|
277 | + /** |
|
278 | + * @return int |
|
279 | + */ |
|
280 | + public function expiration() |
|
281 | + { |
|
282 | + return $this->_expiration; |
|
283 | + } |
|
284 | + |
|
285 | + |
|
286 | + |
|
287 | + /** |
|
288 | + * @return int |
|
289 | + */ |
|
290 | + public function extension() |
|
291 | + { |
|
292 | + return apply_filters('FHEE__EE_Session__extend_expiration__seconds_added', 10 * MINUTE_IN_SECONDS); |
|
293 | + } |
|
294 | + |
|
295 | + |
|
296 | + |
|
297 | + /** |
|
298 | + * @param int $time number of seconds to add to session expiration |
|
299 | + */ |
|
300 | + public function extend_expiration($time = 0) |
|
301 | + { |
|
302 | + $time = $time ? $time : $this->extension(); |
|
303 | + $this->_expiration += absint($time); |
|
304 | + } |
|
305 | + |
|
306 | + |
|
307 | + |
|
308 | + /** |
|
309 | + * @return int |
|
310 | + */ |
|
311 | + public function lifespan() |
|
312 | + { |
|
313 | + return $this->_lifespan; |
|
314 | + } |
|
315 | + |
|
316 | + |
|
317 | + |
|
318 | + /** |
|
319 | + * This just sets some defaults for the _session data property |
|
320 | + * |
|
321 | + * @access private |
|
322 | + * @return void |
|
323 | + */ |
|
324 | + private function _set_defaults() |
|
325 | + { |
|
326 | + // set some defaults |
|
327 | + foreach ($this->_default_session_vars as $key => $default_var) { |
|
328 | + if (is_array($default_var)) { |
|
329 | + $this->_session_data[ $key ] = array(); |
|
330 | + } else { |
|
331 | + $this->_session_data[ $key ] = ''; |
|
332 | + } |
|
333 | + } |
|
334 | + } |
|
335 | 335 | |
336 | 336 | |
337 | - |
|
338 | - /** |
|
339 | - * @retrieve session data |
|
340 | - * @access public |
|
341 | - * @return string |
|
342 | - */ |
|
343 | - public function id() |
|
344 | - { |
|
345 | - return $this->_sid; |
|
346 | - } |
|
337 | + |
|
338 | + /** |
|
339 | + * @retrieve session data |
|
340 | + * @access public |
|
341 | + * @return string |
|
342 | + */ |
|
343 | + public function id() |
|
344 | + { |
|
345 | + return $this->_sid; |
|
346 | + } |
|
347 | 347 | |
348 | 348 | |
349 | 349 | |
350 | - /** |
|
351 | - * @param \EE_Cart $cart |
|
352 | - * @return bool |
|
353 | - */ |
|
354 | - public function set_cart(EE_Cart $cart) |
|
355 | - { |
|
356 | - $this->_session_data['cart'] = $cart; |
|
357 | - return true; |
|
358 | - } |
|
350 | + /** |
|
351 | + * @param \EE_Cart $cart |
|
352 | + * @return bool |
|
353 | + */ |
|
354 | + public function set_cart(EE_Cart $cart) |
|
355 | + { |
|
356 | + $this->_session_data['cart'] = $cart; |
|
357 | + return true; |
|
358 | + } |
|
359 | 359 | |
360 | 360 | |
361 | 361 | |
362 | - /** |
|
363 | - * reset_cart |
|
364 | - */ |
|
365 | - public function reset_cart() |
|
366 | - { |
|
367 | - do_action('AHEE__EE_Session__reset_cart__before_reset', $this); |
|
368 | - $this->_session_data['cart'] = null; |
|
369 | - } |
|
370 | - |
|
371 | - |
|
372 | - |
|
373 | - /** |
|
374 | - * @return \EE_Cart |
|
375 | - */ |
|
376 | - public function cart() |
|
377 | - { |
|
378 | - return isset($this->_session_data['cart']) && $this->_session_data['cart'] instanceof EE_Cart |
|
379 | - ? $this->_session_data['cart'] |
|
380 | - : null; |
|
381 | - } |
|
382 | - |
|
383 | - |
|
384 | - |
|
385 | - /** |
|
386 | - * @param \EE_Checkout $checkout |
|
387 | - * @return bool |
|
388 | - */ |
|
389 | - public function set_checkout(EE_Checkout $checkout) |
|
390 | - { |
|
391 | - $this->_session_data['checkout'] = $checkout; |
|
392 | - return true; |
|
393 | - } |
|
394 | - |
|
395 | - |
|
396 | - |
|
397 | - /** |
|
398 | - * reset_checkout |
|
399 | - */ |
|
400 | - public function reset_checkout() |
|
401 | - { |
|
402 | - do_action('AHEE__EE_Session__reset_checkout__before_reset', $this); |
|
403 | - $this->_session_data['checkout'] = null; |
|
404 | - } |
|
405 | - |
|
406 | - |
|
407 | - |
|
408 | - /** |
|
409 | - * @return \EE_Checkout |
|
410 | - */ |
|
411 | - public function checkout() |
|
412 | - { |
|
413 | - return isset($this->_session_data['checkout']) && $this->_session_data['checkout'] instanceof EE_Checkout |
|
414 | - ? $this->_session_data['checkout'] |
|
415 | - : null; |
|
416 | - } |
|
417 | - |
|
418 | - |
|
419 | - |
|
420 | - /** |
|
421 | - * @param \EE_Transaction $transaction |
|
422 | - * @return bool |
|
423 | - * @throws EE_Error |
|
424 | - */ |
|
425 | - public function set_transaction(EE_Transaction $transaction) |
|
426 | - { |
|
427 | - // first remove the session from the transaction before we save the transaction in the session |
|
428 | - $transaction->set_txn_session_data(null); |
|
429 | - $this->_session_data['transaction'] = $transaction; |
|
430 | - return true; |
|
431 | - } |
|
432 | - |
|
433 | - |
|
434 | - |
|
435 | - /** |
|
436 | - * reset_transaction |
|
437 | - */ |
|
438 | - public function reset_transaction() |
|
439 | - { |
|
440 | - do_action('AHEE__EE_Session__reset_transaction__before_reset', $this); |
|
441 | - $this->_session_data['transaction'] = null; |
|
442 | - } |
|
443 | - |
|
444 | - |
|
445 | - |
|
446 | - /** |
|
447 | - * @return \EE_Transaction |
|
448 | - */ |
|
449 | - public function transaction() |
|
450 | - { |
|
451 | - return isset($this->_session_data['transaction']) |
|
452 | - && $this->_session_data['transaction'] instanceof EE_Transaction |
|
453 | - ? $this->_session_data['transaction'] |
|
454 | - : null; |
|
455 | - } |
|
456 | - |
|
457 | - |
|
458 | - |
|
459 | - /** |
|
460 | - * retrieve session data |
|
461 | - * |
|
462 | - * @access public |
|
463 | - * @param null $key |
|
464 | - * @param bool $reset_cache |
|
465 | - * @return array |
|
466 | - */ |
|
467 | - public function get_session_data($key = null, $reset_cache = false) |
|
468 | - { |
|
469 | - if ($reset_cache) { |
|
470 | - $this->reset_cart(); |
|
471 | - $this->reset_checkout(); |
|
472 | - $this->reset_transaction(); |
|
473 | - } |
|
474 | - if (! empty($key)) { |
|
475 | - return isset($this->_session_data[ $key ]) ? $this->_session_data[ $key ] : null; |
|
476 | - } |
|
477 | - return $this->_session_data; |
|
478 | - } |
|
479 | - |
|
480 | - |
|
481 | - |
|
482 | - /** |
|
483 | - * set session data |
|
484 | - * |
|
485 | - * @access public |
|
486 | - * @param array $data |
|
487 | - * @return TRUE on success, FALSE on fail |
|
488 | - */ |
|
489 | - public function set_session_data($data) |
|
490 | - { |
|
491 | - |
|
492 | - // nothing ??? bad data ??? go home! |
|
493 | - if (empty($data) || ! is_array($data)) { |
|
494 | - EE_Error::add_error(__('No session data or invalid session data was provided.', 'event_espresso'), __FILE__, |
|
495 | - __FUNCTION__, __LINE__); |
|
496 | - return false; |
|
497 | - } |
|
498 | - foreach ($data as $key => $value) { |
|
499 | - if (isset($this->_default_session_vars[ $key ])) { |
|
500 | - EE_Error::add_error(sprintf(__('Sorry! %s is a default session datum and can not be reset.', |
|
501 | - 'event_espresso'), $key), __FILE__, __FUNCTION__, __LINE__); |
|
502 | - return false; |
|
503 | - } |
|
504 | - $this->_session_data[ $key ] = $value; |
|
505 | - } |
|
506 | - return true; |
|
507 | - } |
|
508 | - |
|
509 | - |
|
510 | - |
|
511 | - /** |
|
512 | - * @initiate session |
|
513 | - * @access private |
|
514 | - * @return TRUE on success, FALSE on fail |
|
515 | - * @throws EE_Error |
|
516 | - * @throws InvalidArgumentException |
|
517 | - * @throws InvalidDataTypeException |
|
518 | - * @throws InvalidInterfaceException |
|
519 | - * @throws InvalidSessionDataException |
|
520 | - */ |
|
521 | - private function _espresso_session() |
|
522 | - { |
|
523 | - do_action('AHEE_log', __FILE__, __FUNCTION__, ''); |
|
524 | - // check that session has started |
|
525 | - if (session_id() === '') { |
|
526 | - //starts a new session if one doesn't already exist, or re-initiates an existing one |
|
527 | - session_start(); |
|
528 | - } |
|
529 | - // get our modified session ID |
|
530 | - $this->_sid = $this->_generate_session_id(); |
|
531 | - // and the visitors IP |
|
532 | - $this->_ip_address = $this->_visitor_ip(); |
|
533 | - // set the "user agent" |
|
534 | - $this->_user_agent = isset($_SERVER['HTTP_USER_AGENT']) ? esc_attr($_SERVER['HTTP_USER_AGENT']) : false; |
|
535 | - // now let's retrieve what's in the db |
|
536 | - $session_data = $this->_retrieve_session_data(); |
|
537 | - if (! empty($session_data)) { |
|
538 | - // get the current time in UTC |
|
539 | - $this->_time = $this->_time !== null ? $this->_time : time(); |
|
540 | - // and reset the session expiration |
|
541 | - $this->_expiration = isset($session_data['expiration']) |
|
542 | - ? $session_data['expiration'] |
|
543 | - : $this->_time + $this->_lifespan; |
|
544 | - } else { |
|
545 | - // set initial site access time and the session expiration |
|
546 | - $this->_set_init_access_and_expiration(); |
|
547 | - // set referer |
|
548 | - $this->_session_data['pages_visited'][ $this->_session_data['init_access'] ] = isset($_SERVER['HTTP_REFERER']) |
|
549 | - ? esc_attr($_SERVER['HTTP_REFERER']) |
|
550 | - : ''; |
|
551 | - // no previous session = go back and create one (on top of the data above) |
|
552 | - return false; |
|
553 | - } |
|
554 | - // now the user agent |
|
555 | - if ($session_data['user_agent'] !== $this->_user_agent) { |
|
556 | - return false; |
|
557 | - } |
|
558 | - // wait a minute... how old are you? |
|
559 | - if ($this->_time > $this->_expiration) { |
|
560 | - // yer too old fer me! |
|
561 | - $this->_expired = true; |
|
562 | - // wipe out everything that isn't a default session datum |
|
563 | - $this->clear_session(__CLASS__, __FUNCTION__); |
|
564 | - } |
|
565 | - // make event espresso session data available to plugin |
|
566 | - $this->_session_data = array_merge($this->_session_data, $session_data); |
|
567 | - return true; |
|
568 | - } |
|
569 | - |
|
570 | - |
|
571 | - |
|
572 | - /** |
|
573 | - * _get_session_data |
|
574 | - * Retrieves the session data, and attempts to correct any encoding issues that can occur due to improperly setup |
|
575 | - * databases |
|
576 | - * |
|
577 | - * @return array |
|
578 | - * @throws EE_Error |
|
579 | - * @throws InvalidArgumentException |
|
580 | - * @throws InvalidSessionDataException |
|
581 | - * @throws InvalidDataTypeException |
|
582 | - * @throws InvalidInterfaceException |
|
583 | - */ |
|
584 | - protected function _retrieve_session_data() |
|
585 | - { |
|
586 | - $ssn_key = EE_Session::session_id_prefix . $this->_sid; |
|
587 | - try { |
|
588 | - // we're using WP's Transient API to store session data using the PHP session ID as the option name |
|
589 | - $session_data = $this->cache_storage->get($ssn_key, false); |
|
590 | - if (empty($session_data)) { |
|
591 | - return array(); |
|
592 | - } |
|
593 | - if (apply_filters('FHEE__EE_Session___perform_session_id_hash_check', WP_DEBUG)) { |
|
594 | - $hash_check = $this->cache_storage->get( |
|
595 | - EE_Session::hash_check_prefix . $this->_sid, |
|
596 | - false |
|
597 | - ); |
|
598 | - if ($hash_check && $hash_check !== md5($session_data)) { |
|
599 | - EE_Error::add_error( |
|
600 | - sprintf( |
|
601 | - __( |
|
602 | - 'The stored data for session %1$s failed to pass a hash check and therefore appears to be invalid.', |
|
603 | - 'event_espresso' |
|
604 | - ), |
|
605 | - EE_Session::session_id_prefix . $this->_sid |
|
606 | - ), |
|
607 | - __FILE__, __FUNCTION__, __LINE__ |
|
608 | - ); |
|
609 | - } |
|
610 | - } |
|
611 | - } catch (Exception $e) { |
|
612 | - // let's just eat that error for now and attempt to correct any corrupted data |
|
613 | - global $wpdb; |
|
614 | - $row = $wpdb->get_row( |
|
615 | - $wpdb->prepare( |
|
616 | - "SELECT option_value FROM {$wpdb->options} WHERE option_name = %s LIMIT 1", |
|
617 | - '_transient_' . $ssn_key |
|
618 | - ) |
|
619 | - ); |
|
620 | - $session_data = is_object($row) ? $row->option_value : null; |
|
621 | - if ($session_data) { |
|
622 | - $session_data = preg_replace_callback( |
|
623 | - '!s:(d+):"(.*?)";!', |
|
624 | - function ($match) |
|
625 | - { |
|
626 | - return $match[1] === strlen($match[2]) |
|
627 | - ? $match[0] |
|
628 | - : 's:' . strlen($match[2]) . ':"' . $match[2] . '";'; |
|
629 | - }, |
|
630 | - $session_data |
|
631 | - ); |
|
632 | - } |
|
633 | - $session_data = maybe_unserialize($session_data); |
|
634 | - } |
|
635 | - // in case the data is encoded... try to decode it |
|
636 | - $session_data = $this->encryption instanceof EE_Encryption |
|
637 | - ? $this->encryption->base64_string_decode($session_data) |
|
638 | - : $session_data; |
|
639 | - if (! is_array($session_data)) { |
|
640 | - try { |
|
641 | - $session_data = maybe_unserialize($session_data); |
|
642 | - } catch (Exception $e) { |
|
643 | - $msg = esc_html__( |
|
644 | - 'An error occurred while attempting to unserialize the session data.', |
|
645 | - 'event_espresso' |
|
646 | - ); |
|
647 | - $msg .= WP_DEBUG |
|
648 | - ? '<br><pre>' |
|
649 | - . print_r($session_data, true) |
|
650 | - . '</pre><br>' |
|
651 | - . $this->find_serialize_error($session_data) |
|
652 | - : ''; |
|
653 | - $this->cache_storage->delete(EE_Session::session_id_prefix . $this->_sid); |
|
654 | - throw new InvalidSessionDataException($msg, 0, $e); |
|
655 | - } |
|
656 | - } |
|
657 | - // just a check to make sure the session array is indeed an array |
|
658 | - if (! is_array($session_data)) { |
|
659 | - // no?!?! then something is wrong |
|
660 | - $msg = esc_html__( |
|
661 | - 'The session data is missing, invalid, or corrupted.', |
|
662 | - 'event_espresso' |
|
663 | - ); |
|
664 | - $msg .= WP_DEBUG |
|
665 | - ? '<br><pre>' . print_r($session_data, true) . '</pre><br>' . $this->find_serialize_error($session_data) |
|
666 | - : ''; |
|
667 | - $this->cache_storage->delete(EE_Session::session_id_prefix . $this->_sid); |
|
668 | - throw new InvalidSessionDataException($msg); |
|
669 | - } |
|
670 | - if (isset($session_data['transaction']) && absint($session_data['transaction']) !== 0) { |
|
671 | - $session_data['transaction'] = EEM_Transaction::instance()->get_one_by_ID( |
|
672 | - $session_data['transaction'] |
|
673 | - ); |
|
674 | - } |
|
675 | - return $session_data; |
|
676 | - } |
|
677 | - |
|
678 | - |
|
679 | - |
|
680 | - /** |
|
681 | - * _generate_session_id |
|
682 | - * Retrieves the PHP session id either directly from the PHP session, |
|
683 | - * or from the $_REQUEST array if it was passed in from an AJAX request. |
|
684 | - * The session id is then salted and hashed (mmm sounds tasty) |
|
685 | - * so that it can be safely used as a $_REQUEST param |
|
686 | - * |
|
687 | - * @return string |
|
688 | - */ |
|
689 | - protected function _generate_session_id() |
|
690 | - { |
|
691 | - // check if the SID was passed explicitly, otherwise get from session, then add salt and hash it to reduce length |
|
692 | - if (isset($_REQUEST['EESID'])) { |
|
693 | - $session_id = sanitize_text_field($_REQUEST['EESID']); |
|
694 | - } else { |
|
695 | - $session_id = md5(session_id() . get_current_blog_id() . $this->_get_sid_salt()); |
|
696 | - } |
|
697 | - return apply_filters('FHEE__EE_Session___generate_session_id__session_id', $session_id); |
|
698 | - } |
|
699 | - |
|
700 | - |
|
701 | - |
|
702 | - /** |
|
703 | - * _get_sid_salt |
|
704 | - * |
|
705 | - * @return string |
|
706 | - */ |
|
707 | - protected function _get_sid_salt() |
|
708 | - { |
|
709 | - // was session id salt already saved to db ? |
|
710 | - if (empty($this->_sid_salt)) { |
|
711 | - // no? then maybe use WP defined constant |
|
712 | - if (defined('AUTH_SALT')) { |
|
713 | - $this->_sid_salt = AUTH_SALT; |
|
714 | - } |
|
715 | - // if salt doesn't exist or is too short |
|
716 | - if (strlen($this->_sid_salt) < 32) { |
|
717 | - // create a new one |
|
718 | - $this->_sid_salt = wp_generate_password(64); |
|
719 | - } |
|
720 | - // and save it as a permanent session setting |
|
721 | - $this->updateSessionSettings(array('sid_salt' => $this->_sid_salt)); |
|
722 | - } |
|
723 | - return $this->_sid_salt; |
|
724 | - } |
|
725 | - |
|
726 | - |
|
727 | - |
|
728 | - /** |
|
729 | - * _set_init_access_and_expiration |
|
730 | - * |
|
731 | - * @return void |
|
732 | - */ |
|
733 | - protected function _set_init_access_and_expiration() |
|
734 | - { |
|
735 | - $this->_time = time(); |
|
736 | - $this->_expiration = $this->_time + $this->_lifespan; |
|
737 | - // set initial site access time |
|
738 | - $this->_session_data['init_access'] = $this->_time; |
|
739 | - // and the session expiration |
|
740 | - $this->_session_data['expiration'] = $this->_expiration; |
|
741 | - } |
|
742 | - |
|
743 | - |
|
744 | - |
|
745 | - /** |
|
746 | - * @update session data prior to saving to the db |
|
747 | - * @access public |
|
748 | - * @param bool $new_session |
|
749 | - * @return TRUE on success, FALSE on fail |
|
750 | - * @throws EE_Error |
|
751 | - * @throws InvalidArgumentException |
|
752 | - * @throws InvalidDataTypeException |
|
753 | - * @throws InvalidInterfaceException |
|
754 | - */ |
|
755 | - public function update($new_session = false) |
|
756 | - { |
|
757 | - $this->_session_data = $this->_session_data !== null |
|
758 | - && is_array($this->_session_data) |
|
759 | - && isset($this->_session_data['id']) |
|
760 | - ? $this->_session_data |
|
761 | - : array(); |
|
762 | - if (empty($this->_session_data)) { |
|
763 | - $this->_set_defaults(); |
|
764 | - } |
|
765 | - $session_data = array(); |
|
766 | - foreach ($this->_session_data as $key => $value) { |
|
767 | - |
|
768 | - switch ($key) { |
|
769 | - |
|
770 | - case 'id' : |
|
771 | - // session ID |
|
772 | - $session_data['id'] = $this->_sid; |
|
773 | - break; |
|
774 | - case 'ip_address' : |
|
775 | - // visitor ip address |
|
776 | - $session_data['ip_address'] = $this->_visitor_ip(); |
|
777 | - break; |
|
778 | - case 'user_agent' : |
|
779 | - // visitor user_agent |
|
780 | - $session_data['user_agent'] = $this->_user_agent; |
|
781 | - break; |
|
782 | - case 'init_access' : |
|
783 | - $session_data['init_access'] = absint($value); |
|
784 | - break; |
|
785 | - case 'last_access' : |
|
786 | - // current access time |
|
787 | - $session_data['last_access'] = $this->_time; |
|
788 | - break; |
|
789 | - case 'expiration' : |
|
790 | - // when the session expires |
|
791 | - $session_data['expiration'] = ! empty($this->_expiration) |
|
792 | - ? $this->_expiration |
|
793 | - : $session_data['init_access'] + $this->_lifespan; |
|
794 | - break; |
|
795 | - case 'user_id' : |
|
796 | - // current user if logged in |
|
797 | - $session_data['user_id'] = $this->_wp_user_id(); |
|
798 | - break; |
|
799 | - case 'pages_visited' : |
|
800 | - $page_visit = $this->_get_page_visit(); |
|
801 | - if ($page_visit) { |
|
802 | - // set pages visited where the first will be the http referrer |
|
803 | - $this->_session_data['pages_visited'][ $this->_time ] = $page_visit; |
|
804 | - // we'll only save the last 10 page visits. |
|
805 | - $session_data['pages_visited'] = array_slice($this->_session_data['pages_visited'], -10); |
|
806 | - } |
|
807 | - break; |
|
808 | - default : |
|
809 | - // carry any other data over |
|
810 | - $session_data[ $key ] = $this->_session_data[ $key ]; |
|
811 | - } |
|
812 | - } |
|
813 | - $this->_session_data = $session_data; |
|
814 | - // creating a new session does not require saving to the db just yet |
|
815 | - if (! $new_session) { |
|
816 | - // ready? let's save |
|
817 | - if ($this->_save_session_to_db()) { |
|
818 | - return true; |
|
819 | - } |
|
820 | - return false; |
|
821 | - } |
|
822 | - // meh, why not? |
|
823 | - return true; |
|
824 | - } |
|
825 | - |
|
826 | - |
|
827 | - |
|
828 | - /** |
|
829 | - * @create session data array |
|
830 | - * @access public |
|
831 | - * @return bool |
|
832 | - * @throws EE_Error |
|
833 | - * @throws InvalidArgumentException |
|
834 | - * @throws InvalidDataTypeException |
|
835 | - * @throws InvalidInterfaceException |
|
836 | - */ |
|
837 | - private function _create_espresso_session() |
|
838 | - { |
|
839 | - do_action('AHEE_log', __CLASS__, __FUNCTION__, ''); |
|
840 | - // use the update function for now with $new_session arg set to TRUE |
|
841 | - return $this->update(true) ? true : false; |
|
842 | - } |
|
843 | - |
|
844 | - |
|
845 | - |
|
846 | - /** |
|
847 | - * _save_session_to_db |
|
848 | - * |
|
849 | - * @param bool $clear_session |
|
850 | - * @return string |
|
851 | - * @throws EE_Error |
|
852 | - * @throws InvalidArgumentException |
|
853 | - * @throws InvalidDataTypeException |
|
854 | - * @throws InvalidInterfaceException |
|
855 | - */ |
|
856 | - private function _save_session_to_db($clear_session = false) |
|
857 | - { |
|
858 | - // unless we're deleting the session data, don't save anything if there isn't a cart |
|
859 | - if (! $clear_session && ! $this->cart() instanceof EE_Cart) { |
|
860 | - return false; |
|
861 | - } |
|
862 | - $transaction = $this->transaction(); |
|
863 | - if ($transaction instanceof EE_Transaction) { |
|
864 | - if (! $transaction->ID()) { |
|
865 | - $transaction->save(); |
|
866 | - } |
|
867 | - $this->_session_data['transaction'] = $transaction->ID(); |
|
868 | - } |
|
869 | - // then serialize all of our session data |
|
870 | - $session_data = serialize($this->_session_data); |
|
871 | - // do we need to also encode it to avoid corrupted data when saved to the db? |
|
872 | - $session_data = $this->_use_encryption |
|
873 | - ? $this->encryption->base64_string_encode($session_data) |
|
874 | - : $session_data; |
|
875 | - // maybe save hash check |
|
876 | - if (apply_filters('FHEE__EE_Session___perform_session_id_hash_check', WP_DEBUG)) { |
|
877 | - $this->cache_storage->add( |
|
878 | - EE_Session::hash_check_prefix . $this->_sid, |
|
879 | - md5($session_data), |
|
880 | - $this->_lifespan |
|
881 | - ); |
|
882 | - } |
|
883 | - // we're using the Transient API for storing session data, |
|
884 | - return $this->cache_storage->add( |
|
885 | - EE_Session::session_id_prefix . $this->_sid, |
|
886 | - $session_data, |
|
887 | - $this->_lifespan |
|
888 | - ); |
|
889 | - } |
|
890 | - |
|
891 | - |
|
892 | - |
|
893 | - /** |
|
894 | - * _visitor_ip |
|
895 | - * attempt to get IP address of current visitor from server |
|
896 | - * plz see: http://stackoverflow.com/a/2031935/1475279 |
|
897 | - * |
|
898 | - * @access public |
|
899 | - * @return string |
|
900 | - */ |
|
901 | - private function _visitor_ip() |
|
902 | - { |
|
903 | - $visitor_ip = '0.0.0.0'; |
|
904 | - $server_keys = array( |
|
905 | - 'HTTP_CLIENT_IP', |
|
906 | - 'HTTP_X_FORWARDED_FOR', |
|
907 | - 'HTTP_X_FORWARDED', |
|
908 | - 'HTTP_X_CLUSTER_CLIENT_IP', |
|
909 | - 'HTTP_FORWARDED_FOR', |
|
910 | - 'HTTP_FORWARDED', |
|
911 | - 'REMOTE_ADDR', |
|
912 | - ); |
|
913 | - foreach ($server_keys as $key) { |
|
914 | - if (isset($_SERVER[ $key ])) { |
|
915 | - foreach (array_map('trim', explode(',', $_SERVER[ $key ])) as $ip) { |
|
916 | - if ($ip === '127.0.0.1' || filter_var($ip, FILTER_VALIDATE_IP) !== false) { |
|
917 | - $visitor_ip = $ip; |
|
918 | - } |
|
919 | - } |
|
920 | - } |
|
921 | - } |
|
922 | - return $visitor_ip; |
|
923 | - } |
|
924 | - |
|
925 | - |
|
926 | - |
|
927 | - /** |
|
928 | - * @get the full page request the visitor is accessing |
|
929 | - * @access public |
|
930 | - * @return string |
|
931 | - */ |
|
932 | - public function _get_page_visit() |
|
933 | - { |
|
934 | - $page_visit = home_url('/') . 'wp-admin/admin-ajax.php'; |
|
935 | - // check for request url |
|
936 | - if (isset($_SERVER['REQUEST_URI'])) { |
|
937 | - $http_host = ''; |
|
938 | - $page_id = '?'; |
|
939 | - $e_reg = ''; |
|
940 | - $request_uri = esc_url($_SERVER['REQUEST_URI']); |
|
941 | - $ru_bits = explode('?', $request_uri); |
|
942 | - $request_uri = $ru_bits[0]; |
|
943 | - // check for and grab host as well |
|
944 | - if (isset($_SERVER['HTTP_HOST'])) { |
|
945 | - $http_host = esc_url($_SERVER['HTTP_HOST']); |
|
946 | - } |
|
947 | - // check for page_id in SERVER REQUEST |
|
948 | - if (isset($_REQUEST['page_id'])) { |
|
949 | - // rebuild $e_reg without any of the extra parameters |
|
950 | - $page_id = '?page_id=' . esc_attr($_REQUEST['page_id']) . '&'; |
|
951 | - } |
|
952 | - // check for $e_reg in SERVER REQUEST |
|
953 | - if (isset($_REQUEST['ee'])) { |
|
954 | - // rebuild $e_reg without any of the extra parameters |
|
955 | - $e_reg = 'ee=' . esc_attr($_REQUEST['ee']); |
|
956 | - } |
|
957 | - $page_visit = rtrim($http_host . $request_uri . $page_id . $e_reg, '?'); |
|
958 | - } |
|
959 | - return $page_visit !== home_url('/wp-admin/admin-ajax.php') ? $page_visit : ''; |
|
960 | - } |
|
961 | - |
|
962 | - |
|
963 | - |
|
964 | - /** |
|
965 | - * @the current wp user id |
|
966 | - * @access public |
|
967 | - * @return int |
|
968 | - */ |
|
969 | - public function _wp_user_id() |
|
970 | - { |
|
971 | - // if I need to explain the following lines of code, then you shouldn't be looking at this! |
|
972 | - $this->_wp_user_id = get_current_user_id(); |
|
973 | - return $this->_wp_user_id; |
|
974 | - } |
|
975 | - |
|
976 | - |
|
977 | - |
|
978 | - /** |
|
979 | - * Clear EE_Session data |
|
980 | - * |
|
981 | - * @access public |
|
982 | - * @param string $class |
|
983 | - * @param string $function |
|
984 | - * @return void |
|
985 | - * @throws EE_Error |
|
986 | - * @throws InvalidArgumentException |
|
987 | - * @throws InvalidDataTypeException |
|
988 | - * @throws InvalidInterfaceException |
|
989 | - */ |
|
990 | - public function clear_session($class = '', $function = '') |
|
991 | - { |
|
992 | - //echo '<h3 style="color:#999;line-height:.9em;"><span style="color:#2EA2CC">' . __CLASS__ . '</span>::<span style="color:#E76700">' . __FUNCTION__ . '( ' . $class . '::' . $function . '() )</span><br/><span style="font-size:9px;font-weight:normal;">' . __FILE__ . '</span> <b style="font-size:10px;"> ' . __LINE__ . ' </b></h3>'; |
|
993 | - do_action('AHEE_log', __FILE__, __FUNCTION__, 'session cleared by : ' . $class . '::' . $function . '()'); |
|
994 | - $this->reset_cart(); |
|
995 | - $this->reset_checkout(); |
|
996 | - $this->reset_transaction(); |
|
997 | - // wipe out everything that isn't a default session datum |
|
998 | - $this->reset_data(array_keys($this->_session_data)); |
|
999 | - // reset initial site access time and the session expiration |
|
1000 | - $this->_set_init_access_and_expiration(); |
|
1001 | - $this->_save_session_to_db(true); |
|
1002 | - } |
|
1003 | - |
|
1004 | - |
|
1005 | - |
|
1006 | - /** |
|
1007 | - * @resets all non-default session vars |
|
1008 | - * @access public |
|
1009 | - * @param array|mixed $data_to_reset |
|
1010 | - * @param bool $show_all_notices |
|
1011 | - * @return TRUE on success, FALSE on fail |
|
1012 | - */ |
|
1013 | - public function reset_data($data_to_reset = array(), $show_all_notices = false) |
|
1014 | - { |
|
1015 | - // if $data_to_reset is not in an array, then put it in one |
|
1016 | - if (! is_array($data_to_reset)) { |
|
1017 | - $data_to_reset = array($data_to_reset); |
|
1018 | - } |
|
1019 | - // nothing ??? go home! |
|
1020 | - if (empty($data_to_reset)) { |
|
1021 | - EE_Error::add_error(__('No session data could be reset, because no session var name was provided.', |
|
1022 | - 'event_espresso'), __FILE__, __FUNCTION__, __LINE__); |
|
1023 | - return false; |
|
1024 | - } |
|
1025 | - $return_value = true; |
|
1026 | - // since $data_to_reset is an array, cycle through the values |
|
1027 | - foreach ($data_to_reset as $reset) { |
|
1028 | - |
|
1029 | - // first check to make sure it is a valid session var |
|
1030 | - if (isset($this->_session_data[ $reset ])) { |
|
1031 | - // then check to make sure it is not a default var |
|
1032 | - if (! array_key_exists($reset, $this->_default_session_vars)) { |
|
1033 | - // remove session var |
|
1034 | - unset($this->_session_data[ $reset ]); |
|
1035 | - if ($show_all_notices) { |
|
1036 | - EE_Error::add_success(sprintf(__('The session variable %s was removed.', 'event_espresso'), |
|
1037 | - $reset), __FILE__, __FUNCTION__, __LINE__); |
|
1038 | - } |
|
1039 | - } else { |
|
1040 | - // yeeeeeeeeerrrrrrrrrrr OUT !!!! |
|
1041 | - if ($show_all_notices) { |
|
1042 | - EE_Error::add_error(sprintf(__('Sorry! %s is a default session datum and can not be reset.', |
|
1043 | - 'event_espresso'), $reset), __FILE__, __FUNCTION__, __LINE__); |
|
1044 | - } |
|
1045 | - $return_value = false; |
|
1046 | - } |
|
1047 | - } elseif ($show_all_notices) { |
|
1048 | - // oops! that session var does not exist! |
|
1049 | - EE_Error::add_error(sprintf(__('The session item provided, %s, is invalid or does not exist.', |
|
1050 | - 'event_espresso'), $reset), __FILE__, __FUNCTION__, __LINE__); |
|
1051 | - $return_value = false; |
|
1052 | - } |
|
1053 | - } // end of foreach |
|
1054 | - return $return_value; |
|
1055 | - } |
|
1056 | - |
|
1057 | - |
|
1058 | - |
|
1059 | - /** |
|
1060 | - * wp_loaded |
|
1061 | - * |
|
1062 | - * @access public |
|
1063 | - * @throws EE_Error |
|
1064 | - * @throws InvalidDataTypeException |
|
1065 | - * @throws InvalidInterfaceException |
|
1066 | - * @throws InvalidArgumentException |
|
1067 | - */ |
|
1068 | - public function wp_loaded() |
|
1069 | - { |
|
1070 | - if ( |
|
1071 | - EE_Registry::instance()->REQ instanceof EE_Request_Handler |
|
1072 | - && EE_Registry::instance()->REQ->is_set('clear_session') |
|
1073 | - ) { |
|
1074 | - $this->clear_session(__CLASS__, __FUNCTION__); |
|
1075 | - } |
|
1076 | - } |
|
1077 | - |
|
1078 | - |
|
1079 | - |
|
1080 | - /** |
|
1081 | - * Used to reset the entire object (for tests). |
|
1082 | - * |
|
1083 | - * @since 4.3.0 |
|
1084 | - * @throws EE_Error |
|
1085 | - * @throws InvalidDataTypeException |
|
1086 | - * @throws InvalidInterfaceException |
|
1087 | - * @throws InvalidArgumentException |
|
1088 | - */ |
|
1089 | - public function reset_instance() |
|
1090 | - { |
|
1091 | - $this->clear_session(); |
|
1092 | - self::$_instance = null; |
|
1093 | - } |
|
1094 | - |
|
1095 | - |
|
1096 | - |
|
1097 | - public function configure_garbage_collection_filters() |
|
1098 | - { |
|
1099 | - // run old filter we had for controlling session cleanup |
|
1100 | - $expired_session_transient_delete_query_limit = absint( |
|
1101 | - apply_filters( |
|
1102 | - 'FHEE__EE_Session__garbage_collection___expired_session_transient_delete_query_limit', |
|
1103 | - 50 |
|
1104 | - ) |
|
1105 | - ); |
|
1106 | - // is there a value? or one that is different than the default 50 records? |
|
1107 | - if ($expired_session_transient_delete_query_limit === 0) { |
|
1108 | - // hook into TransientCacheStorage in case Session cleanup was turned off |
|
1109 | - add_filter('FHEE__TransientCacheStorage__transient_cleanup_schedule', '__return_zero'); |
|
1110 | - } elseif ($expired_session_transient_delete_query_limit !== 50) { |
|
1111 | - // or use that for the new transient cleanup query limit |
|
1112 | - add_filter( |
|
1113 | - 'FHEE__TransientCacheStorage__clearExpiredTransients__limit', |
|
1114 | - function () use ($expired_session_transient_delete_query_limit) |
|
1115 | - { |
|
1116 | - return $expired_session_transient_delete_query_limit; |
|
1117 | - } |
|
1118 | - ); |
|
1119 | - } |
|
1120 | - } |
|
1121 | - |
|
1122 | - |
|
1123 | - |
|
1124 | - /** |
|
1125 | - * @see http://stackoverflow.com/questions/10152904/unserialize-function-unserialize-error-at-offset/21389439#10152996 |
|
1126 | - * @param $data1 |
|
1127 | - * @return string |
|
1128 | - */ |
|
1129 | - private function find_serialize_error($data1) |
|
1130 | - { |
|
1131 | - $error = '<pre>'; |
|
1132 | - $data2 = preg_replace_callback( |
|
1133 | - '!s:(\d+):"(.*?)";!', |
|
1134 | - function ($match) |
|
1135 | - { |
|
1136 | - return ($match[1] === strlen($match[2])) |
|
1137 | - ? $match[0] |
|
1138 | - : 's:' |
|
1139 | - . strlen($match[2]) |
|
1140 | - . ':"' |
|
1141 | - . $match[2] |
|
1142 | - . '";'; |
|
1143 | - }, |
|
1144 | - $data1 |
|
1145 | - ); |
|
1146 | - $max = (strlen($data1) > strlen($data2)) ? strlen($data1) : strlen($data2); |
|
1147 | - $error .= $data1 . PHP_EOL; |
|
1148 | - $error .= $data2 . PHP_EOL; |
|
1149 | - for ($i = 0; $i < $max; $i++) { |
|
1150 | - if (@$data1[ $i ] !== @$data2[ $i ]) { |
|
1151 | - $error .= 'Difference ' . @$data1[ $i ] . ' != ' . @$data2[ $i ] . PHP_EOL; |
|
1152 | - $error .= "\t-> ORD number " . ord(@$data1[ $i ]) . ' != ' . ord(@$data2[ $i ]) . PHP_EOL; |
|
1153 | - $error .= "\t-> Line Number = $i" . PHP_EOL; |
|
1154 | - $start = ($i - 20); |
|
1155 | - $start = ($start < 0) ? 0 : $start; |
|
1156 | - $length = 40; |
|
1157 | - $point = $max - $i; |
|
1158 | - if ($point < 20) { |
|
1159 | - $rlength = 1; |
|
1160 | - $rpoint = -$point; |
|
1161 | - } else { |
|
1162 | - $rpoint = $length - 20; |
|
1163 | - $rlength = 1; |
|
1164 | - } |
|
1165 | - $error .= "\t-> Section Data1 = "; |
|
1166 | - $error .= substr_replace( |
|
1167 | - substr($data1, $start, $length), |
|
1168 | - "<b style=\"color:green\">{$data1[ $i ]}</b>", |
|
1169 | - $rpoint, |
|
1170 | - $rlength |
|
1171 | - ); |
|
1172 | - $error .= PHP_EOL; |
|
1173 | - $error .= "\t-> Section Data2 = "; |
|
1174 | - $error .= substr_replace( |
|
1175 | - substr($data2, $start, $length), |
|
1176 | - "<b style=\"color:red\">{$data2[ $i ]}</b>", |
|
1177 | - $rpoint, |
|
1178 | - $rlength |
|
1179 | - ); |
|
1180 | - $error .= PHP_EOL; |
|
1181 | - } |
|
1182 | - } |
|
1183 | - $error .= '</pre>'; |
|
1184 | - return $error; |
|
1185 | - } |
|
1186 | - |
|
1187 | - |
|
1188 | - /** |
|
1189 | - * Saves an array of settings used for configuring aspects of session behaviour |
|
1190 | - * |
|
1191 | - * @param array $updated_settings |
|
1192 | - */ |
|
1193 | - private function updateSessionSettings(array $updated_settings = array()) |
|
1194 | - { |
|
1195 | - // add existing settings, but only if not included in incoming $updated_settings array |
|
1196 | - $updated_settings += get_option(EE_Session::OPTION_NAME_SETTINGS, array()); |
|
1197 | - update_option(EE_Session::OPTION_NAME_SETTINGS, $updated_settings); |
|
1198 | - } |
|
1199 | - |
|
1200 | - |
|
1201 | - /** |
|
1202 | - * garbage_collection |
|
1203 | - */ |
|
1204 | - public function garbageCollection() |
|
1205 | - { |
|
1206 | - // only perform during regular requests if last garbage collection was over an hour ago |
|
1207 | - if (! (defined('DOING_AJAX') && DOING_AJAX) && (time() - HOUR_IN_SECONDS) >= $this->_last_gc) { |
|
1208 | - $this->_last_gc = time(); |
|
1209 | - $this->updateSessionSettings(array('last_gc' => $this->_last_gc)); |
|
1210 | - /** @type WPDB $wpdb */ |
|
1211 | - global $wpdb; |
|
1212 | - // filter the query limit. Set to 0 to turn off garbage collection |
|
1213 | - $expired_session_transient_delete_query_limit = absint( |
|
1214 | - apply_filters( |
|
1215 | - 'FHEE__EE_Session__garbage_collection___expired_session_transient_delete_query_limit', |
|
1216 | - 50 |
|
1217 | - ) |
|
1218 | - ); |
|
1219 | - // non-zero LIMIT means take out the trash |
|
1220 | - if ($expired_session_transient_delete_query_limit) { |
|
1221 | - $session_key = str_replace('_', '\_', EE_Session::session_id_prefix); |
|
1222 | - $hash_check_key = str_replace('_', '\_', EE_Session::hash_check_prefix); |
|
1223 | - // since transient expiration timestamps are set in the future, we can compare against NOW |
|
1224 | - // but we only want to pick up any trash that's been around for more than a day |
|
1225 | - $expiration = time() - DAY_IN_SECONDS; |
|
1226 | - $SQL = " |
|
362 | + /** |
|
363 | + * reset_cart |
|
364 | + */ |
|
365 | + public function reset_cart() |
|
366 | + { |
|
367 | + do_action('AHEE__EE_Session__reset_cart__before_reset', $this); |
|
368 | + $this->_session_data['cart'] = null; |
|
369 | + } |
|
370 | + |
|
371 | + |
|
372 | + |
|
373 | + /** |
|
374 | + * @return \EE_Cart |
|
375 | + */ |
|
376 | + public function cart() |
|
377 | + { |
|
378 | + return isset($this->_session_data['cart']) && $this->_session_data['cart'] instanceof EE_Cart |
|
379 | + ? $this->_session_data['cart'] |
|
380 | + : null; |
|
381 | + } |
|
382 | + |
|
383 | + |
|
384 | + |
|
385 | + /** |
|
386 | + * @param \EE_Checkout $checkout |
|
387 | + * @return bool |
|
388 | + */ |
|
389 | + public function set_checkout(EE_Checkout $checkout) |
|
390 | + { |
|
391 | + $this->_session_data['checkout'] = $checkout; |
|
392 | + return true; |
|
393 | + } |
|
394 | + |
|
395 | + |
|
396 | + |
|
397 | + /** |
|
398 | + * reset_checkout |
|
399 | + */ |
|
400 | + public function reset_checkout() |
|
401 | + { |
|
402 | + do_action('AHEE__EE_Session__reset_checkout__before_reset', $this); |
|
403 | + $this->_session_data['checkout'] = null; |
|
404 | + } |
|
405 | + |
|
406 | + |
|
407 | + |
|
408 | + /** |
|
409 | + * @return \EE_Checkout |
|
410 | + */ |
|
411 | + public function checkout() |
|
412 | + { |
|
413 | + return isset($this->_session_data['checkout']) && $this->_session_data['checkout'] instanceof EE_Checkout |
|
414 | + ? $this->_session_data['checkout'] |
|
415 | + : null; |
|
416 | + } |
|
417 | + |
|
418 | + |
|
419 | + |
|
420 | + /** |
|
421 | + * @param \EE_Transaction $transaction |
|
422 | + * @return bool |
|
423 | + * @throws EE_Error |
|
424 | + */ |
|
425 | + public function set_transaction(EE_Transaction $transaction) |
|
426 | + { |
|
427 | + // first remove the session from the transaction before we save the transaction in the session |
|
428 | + $transaction->set_txn_session_data(null); |
|
429 | + $this->_session_data['transaction'] = $transaction; |
|
430 | + return true; |
|
431 | + } |
|
432 | + |
|
433 | + |
|
434 | + |
|
435 | + /** |
|
436 | + * reset_transaction |
|
437 | + */ |
|
438 | + public function reset_transaction() |
|
439 | + { |
|
440 | + do_action('AHEE__EE_Session__reset_transaction__before_reset', $this); |
|
441 | + $this->_session_data['transaction'] = null; |
|
442 | + } |
|
443 | + |
|
444 | + |
|
445 | + |
|
446 | + /** |
|
447 | + * @return \EE_Transaction |
|
448 | + */ |
|
449 | + public function transaction() |
|
450 | + { |
|
451 | + return isset($this->_session_data['transaction']) |
|
452 | + && $this->_session_data['transaction'] instanceof EE_Transaction |
|
453 | + ? $this->_session_data['transaction'] |
|
454 | + : null; |
|
455 | + } |
|
456 | + |
|
457 | + |
|
458 | + |
|
459 | + /** |
|
460 | + * retrieve session data |
|
461 | + * |
|
462 | + * @access public |
|
463 | + * @param null $key |
|
464 | + * @param bool $reset_cache |
|
465 | + * @return array |
|
466 | + */ |
|
467 | + public function get_session_data($key = null, $reset_cache = false) |
|
468 | + { |
|
469 | + if ($reset_cache) { |
|
470 | + $this->reset_cart(); |
|
471 | + $this->reset_checkout(); |
|
472 | + $this->reset_transaction(); |
|
473 | + } |
|
474 | + if (! empty($key)) { |
|
475 | + return isset($this->_session_data[ $key ]) ? $this->_session_data[ $key ] : null; |
|
476 | + } |
|
477 | + return $this->_session_data; |
|
478 | + } |
|
479 | + |
|
480 | + |
|
481 | + |
|
482 | + /** |
|
483 | + * set session data |
|
484 | + * |
|
485 | + * @access public |
|
486 | + * @param array $data |
|
487 | + * @return TRUE on success, FALSE on fail |
|
488 | + */ |
|
489 | + public function set_session_data($data) |
|
490 | + { |
|
491 | + |
|
492 | + // nothing ??? bad data ??? go home! |
|
493 | + if (empty($data) || ! is_array($data)) { |
|
494 | + EE_Error::add_error(__('No session data or invalid session data was provided.', 'event_espresso'), __FILE__, |
|
495 | + __FUNCTION__, __LINE__); |
|
496 | + return false; |
|
497 | + } |
|
498 | + foreach ($data as $key => $value) { |
|
499 | + if (isset($this->_default_session_vars[ $key ])) { |
|
500 | + EE_Error::add_error(sprintf(__('Sorry! %s is a default session datum and can not be reset.', |
|
501 | + 'event_espresso'), $key), __FILE__, __FUNCTION__, __LINE__); |
|
502 | + return false; |
|
503 | + } |
|
504 | + $this->_session_data[ $key ] = $value; |
|
505 | + } |
|
506 | + return true; |
|
507 | + } |
|
508 | + |
|
509 | + |
|
510 | + |
|
511 | + /** |
|
512 | + * @initiate session |
|
513 | + * @access private |
|
514 | + * @return TRUE on success, FALSE on fail |
|
515 | + * @throws EE_Error |
|
516 | + * @throws InvalidArgumentException |
|
517 | + * @throws InvalidDataTypeException |
|
518 | + * @throws InvalidInterfaceException |
|
519 | + * @throws InvalidSessionDataException |
|
520 | + */ |
|
521 | + private function _espresso_session() |
|
522 | + { |
|
523 | + do_action('AHEE_log', __FILE__, __FUNCTION__, ''); |
|
524 | + // check that session has started |
|
525 | + if (session_id() === '') { |
|
526 | + //starts a new session if one doesn't already exist, or re-initiates an existing one |
|
527 | + session_start(); |
|
528 | + } |
|
529 | + // get our modified session ID |
|
530 | + $this->_sid = $this->_generate_session_id(); |
|
531 | + // and the visitors IP |
|
532 | + $this->_ip_address = $this->_visitor_ip(); |
|
533 | + // set the "user agent" |
|
534 | + $this->_user_agent = isset($_SERVER['HTTP_USER_AGENT']) ? esc_attr($_SERVER['HTTP_USER_AGENT']) : false; |
|
535 | + // now let's retrieve what's in the db |
|
536 | + $session_data = $this->_retrieve_session_data(); |
|
537 | + if (! empty($session_data)) { |
|
538 | + // get the current time in UTC |
|
539 | + $this->_time = $this->_time !== null ? $this->_time : time(); |
|
540 | + // and reset the session expiration |
|
541 | + $this->_expiration = isset($session_data['expiration']) |
|
542 | + ? $session_data['expiration'] |
|
543 | + : $this->_time + $this->_lifespan; |
|
544 | + } else { |
|
545 | + // set initial site access time and the session expiration |
|
546 | + $this->_set_init_access_and_expiration(); |
|
547 | + // set referer |
|
548 | + $this->_session_data['pages_visited'][ $this->_session_data['init_access'] ] = isset($_SERVER['HTTP_REFERER']) |
|
549 | + ? esc_attr($_SERVER['HTTP_REFERER']) |
|
550 | + : ''; |
|
551 | + // no previous session = go back and create one (on top of the data above) |
|
552 | + return false; |
|
553 | + } |
|
554 | + // now the user agent |
|
555 | + if ($session_data['user_agent'] !== $this->_user_agent) { |
|
556 | + return false; |
|
557 | + } |
|
558 | + // wait a minute... how old are you? |
|
559 | + if ($this->_time > $this->_expiration) { |
|
560 | + // yer too old fer me! |
|
561 | + $this->_expired = true; |
|
562 | + // wipe out everything that isn't a default session datum |
|
563 | + $this->clear_session(__CLASS__, __FUNCTION__); |
|
564 | + } |
|
565 | + // make event espresso session data available to plugin |
|
566 | + $this->_session_data = array_merge($this->_session_data, $session_data); |
|
567 | + return true; |
|
568 | + } |
|
569 | + |
|
570 | + |
|
571 | + |
|
572 | + /** |
|
573 | + * _get_session_data |
|
574 | + * Retrieves the session data, and attempts to correct any encoding issues that can occur due to improperly setup |
|
575 | + * databases |
|
576 | + * |
|
577 | + * @return array |
|
578 | + * @throws EE_Error |
|
579 | + * @throws InvalidArgumentException |
|
580 | + * @throws InvalidSessionDataException |
|
581 | + * @throws InvalidDataTypeException |
|
582 | + * @throws InvalidInterfaceException |
|
583 | + */ |
|
584 | + protected function _retrieve_session_data() |
|
585 | + { |
|
586 | + $ssn_key = EE_Session::session_id_prefix . $this->_sid; |
|
587 | + try { |
|
588 | + // we're using WP's Transient API to store session data using the PHP session ID as the option name |
|
589 | + $session_data = $this->cache_storage->get($ssn_key, false); |
|
590 | + if (empty($session_data)) { |
|
591 | + return array(); |
|
592 | + } |
|
593 | + if (apply_filters('FHEE__EE_Session___perform_session_id_hash_check', WP_DEBUG)) { |
|
594 | + $hash_check = $this->cache_storage->get( |
|
595 | + EE_Session::hash_check_prefix . $this->_sid, |
|
596 | + false |
|
597 | + ); |
|
598 | + if ($hash_check && $hash_check !== md5($session_data)) { |
|
599 | + EE_Error::add_error( |
|
600 | + sprintf( |
|
601 | + __( |
|
602 | + 'The stored data for session %1$s failed to pass a hash check and therefore appears to be invalid.', |
|
603 | + 'event_espresso' |
|
604 | + ), |
|
605 | + EE_Session::session_id_prefix . $this->_sid |
|
606 | + ), |
|
607 | + __FILE__, __FUNCTION__, __LINE__ |
|
608 | + ); |
|
609 | + } |
|
610 | + } |
|
611 | + } catch (Exception $e) { |
|
612 | + // let's just eat that error for now and attempt to correct any corrupted data |
|
613 | + global $wpdb; |
|
614 | + $row = $wpdb->get_row( |
|
615 | + $wpdb->prepare( |
|
616 | + "SELECT option_value FROM {$wpdb->options} WHERE option_name = %s LIMIT 1", |
|
617 | + '_transient_' . $ssn_key |
|
618 | + ) |
|
619 | + ); |
|
620 | + $session_data = is_object($row) ? $row->option_value : null; |
|
621 | + if ($session_data) { |
|
622 | + $session_data = preg_replace_callback( |
|
623 | + '!s:(d+):"(.*?)";!', |
|
624 | + function ($match) |
|
625 | + { |
|
626 | + return $match[1] === strlen($match[2]) |
|
627 | + ? $match[0] |
|
628 | + : 's:' . strlen($match[2]) . ':"' . $match[2] . '";'; |
|
629 | + }, |
|
630 | + $session_data |
|
631 | + ); |
|
632 | + } |
|
633 | + $session_data = maybe_unserialize($session_data); |
|
634 | + } |
|
635 | + // in case the data is encoded... try to decode it |
|
636 | + $session_data = $this->encryption instanceof EE_Encryption |
|
637 | + ? $this->encryption->base64_string_decode($session_data) |
|
638 | + : $session_data; |
|
639 | + if (! is_array($session_data)) { |
|
640 | + try { |
|
641 | + $session_data = maybe_unserialize($session_data); |
|
642 | + } catch (Exception $e) { |
|
643 | + $msg = esc_html__( |
|
644 | + 'An error occurred while attempting to unserialize the session data.', |
|
645 | + 'event_espresso' |
|
646 | + ); |
|
647 | + $msg .= WP_DEBUG |
|
648 | + ? '<br><pre>' |
|
649 | + . print_r($session_data, true) |
|
650 | + . '</pre><br>' |
|
651 | + . $this->find_serialize_error($session_data) |
|
652 | + : ''; |
|
653 | + $this->cache_storage->delete(EE_Session::session_id_prefix . $this->_sid); |
|
654 | + throw new InvalidSessionDataException($msg, 0, $e); |
|
655 | + } |
|
656 | + } |
|
657 | + // just a check to make sure the session array is indeed an array |
|
658 | + if (! is_array($session_data)) { |
|
659 | + // no?!?! then something is wrong |
|
660 | + $msg = esc_html__( |
|
661 | + 'The session data is missing, invalid, or corrupted.', |
|
662 | + 'event_espresso' |
|
663 | + ); |
|
664 | + $msg .= WP_DEBUG |
|
665 | + ? '<br><pre>' . print_r($session_data, true) . '</pre><br>' . $this->find_serialize_error($session_data) |
|
666 | + : ''; |
|
667 | + $this->cache_storage->delete(EE_Session::session_id_prefix . $this->_sid); |
|
668 | + throw new InvalidSessionDataException($msg); |
|
669 | + } |
|
670 | + if (isset($session_data['transaction']) && absint($session_data['transaction']) !== 0) { |
|
671 | + $session_data['transaction'] = EEM_Transaction::instance()->get_one_by_ID( |
|
672 | + $session_data['transaction'] |
|
673 | + ); |
|
674 | + } |
|
675 | + return $session_data; |
|
676 | + } |
|
677 | + |
|
678 | + |
|
679 | + |
|
680 | + /** |
|
681 | + * _generate_session_id |
|
682 | + * Retrieves the PHP session id either directly from the PHP session, |
|
683 | + * or from the $_REQUEST array if it was passed in from an AJAX request. |
|
684 | + * The session id is then salted and hashed (mmm sounds tasty) |
|
685 | + * so that it can be safely used as a $_REQUEST param |
|
686 | + * |
|
687 | + * @return string |
|
688 | + */ |
|
689 | + protected function _generate_session_id() |
|
690 | + { |
|
691 | + // check if the SID was passed explicitly, otherwise get from session, then add salt and hash it to reduce length |
|
692 | + if (isset($_REQUEST['EESID'])) { |
|
693 | + $session_id = sanitize_text_field($_REQUEST['EESID']); |
|
694 | + } else { |
|
695 | + $session_id = md5(session_id() . get_current_blog_id() . $this->_get_sid_salt()); |
|
696 | + } |
|
697 | + return apply_filters('FHEE__EE_Session___generate_session_id__session_id', $session_id); |
|
698 | + } |
|
699 | + |
|
700 | + |
|
701 | + |
|
702 | + /** |
|
703 | + * _get_sid_salt |
|
704 | + * |
|
705 | + * @return string |
|
706 | + */ |
|
707 | + protected function _get_sid_salt() |
|
708 | + { |
|
709 | + // was session id salt already saved to db ? |
|
710 | + if (empty($this->_sid_salt)) { |
|
711 | + // no? then maybe use WP defined constant |
|
712 | + if (defined('AUTH_SALT')) { |
|
713 | + $this->_sid_salt = AUTH_SALT; |
|
714 | + } |
|
715 | + // if salt doesn't exist or is too short |
|
716 | + if (strlen($this->_sid_salt) < 32) { |
|
717 | + // create a new one |
|
718 | + $this->_sid_salt = wp_generate_password(64); |
|
719 | + } |
|
720 | + // and save it as a permanent session setting |
|
721 | + $this->updateSessionSettings(array('sid_salt' => $this->_sid_salt)); |
|
722 | + } |
|
723 | + return $this->_sid_salt; |
|
724 | + } |
|
725 | + |
|
726 | + |
|
727 | + |
|
728 | + /** |
|
729 | + * _set_init_access_and_expiration |
|
730 | + * |
|
731 | + * @return void |
|
732 | + */ |
|
733 | + protected function _set_init_access_and_expiration() |
|
734 | + { |
|
735 | + $this->_time = time(); |
|
736 | + $this->_expiration = $this->_time + $this->_lifespan; |
|
737 | + // set initial site access time |
|
738 | + $this->_session_data['init_access'] = $this->_time; |
|
739 | + // and the session expiration |
|
740 | + $this->_session_data['expiration'] = $this->_expiration; |
|
741 | + } |
|
742 | + |
|
743 | + |
|
744 | + |
|
745 | + /** |
|
746 | + * @update session data prior to saving to the db |
|
747 | + * @access public |
|
748 | + * @param bool $new_session |
|
749 | + * @return TRUE on success, FALSE on fail |
|
750 | + * @throws EE_Error |
|
751 | + * @throws InvalidArgumentException |
|
752 | + * @throws InvalidDataTypeException |
|
753 | + * @throws InvalidInterfaceException |
|
754 | + */ |
|
755 | + public function update($new_session = false) |
|
756 | + { |
|
757 | + $this->_session_data = $this->_session_data !== null |
|
758 | + && is_array($this->_session_data) |
|
759 | + && isset($this->_session_data['id']) |
|
760 | + ? $this->_session_data |
|
761 | + : array(); |
|
762 | + if (empty($this->_session_data)) { |
|
763 | + $this->_set_defaults(); |
|
764 | + } |
|
765 | + $session_data = array(); |
|
766 | + foreach ($this->_session_data as $key => $value) { |
|
767 | + |
|
768 | + switch ($key) { |
|
769 | + |
|
770 | + case 'id' : |
|
771 | + // session ID |
|
772 | + $session_data['id'] = $this->_sid; |
|
773 | + break; |
|
774 | + case 'ip_address' : |
|
775 | + // visitor ip address |
|
776 | + $session_data['ip_address'] = $this->_visitor_ip(); |
|
777 | + break; |
|
778 | + case 'user_agent' : |
|
779 | + // visitor user_agent |
|
780 | + $session_data['user_agent'] = $this->_user_agent; |
|
781 | + break; |
|
782 | + case 'init_access' : |
|
783 | + $session_data['init_access'] = absint($value); |
|
784 | + break; |
|
785 | + case 'last_access' : |
|
786 | + // current access time |
|
787 | + $session_data['last_access'] = $this->_time; |
|
788 | + break; |
|
789 | + case 'expiration' : |
|
790 | + // when the session expires |
|
791 | + $session_data['expiration'] = ! empty($this->_expiration) |
|
792 | + ? $this->_expiration |
|
793 | + : $session_data['init_access'] + $this->_lifespan; |
|
794 | + break; |
|
795 | + case 'user_id' : |
|
796 | + // current user if logged in |
|
797 | + $session_data['user_id'] = $this->_wp_user_id(); |
|
798 | + break; |
|
799 | + case 'pages_visited' : |
|
800 | + $page_visit = $this->_get_page_visit(); |
|
801 | + if ($page_visit) { |
|
802 | + // set pages visited where the first will be the http referrer |
|
803 | + $this->_session_data['pages_visited'][ $this->_time ] = $page_visit; |
|
804 | + // we'll only save the last 10 page visits. |
|
805 | + $session_data['pages_visited'] = array_slice($this->_session_data['pages_visited'], -10); |
|
806 | + } |
|
807 | + break; |
|
808 | + default : |
|
809 | + // carry any other data over |
|
810 | + $session_data[ $key ] = $this->_session_data[ $key ]; |
|
811 | + } |
|
812 | + } |
|
813 | + $this->_session_data = $session_data; |
|
814 | + // creating a new session does not require saving to the db just yet |
|
815 | + if (! $new_session) { |
|
816 | + // ready? let's save |
|
817 | + if ($this->_save_session_to_db()) { |
|
818 | + return true; |
|
819 | + } |
|
820 | + return false; |
|
821 | + } |
|
822 | + // meh, why not? |
|
823 | + return true; |
|
824 | + } |
|
825 | + |
|
826 | + |
|
827 | + |
|
828 | + /** |
|
829 | + * @create session data array |
|
830 | + * @access public |
|
831 | + * @return bool |
|
832 | + * @throws EE_Error |
|
833 | + * @throws InvalidArgumentException |
|
834 | + * @throws InvalidDataTypeException |
|
835 | + * @throws InvalidInterfaceException |
|
836 | + */ |
|
837 | + private function _create_espresso_session() |
|
838 | + { |
|
839 | + do_action('AHEE_log', __CLASS__, __FUNCTION__, ''); |
|
840 | + // use the update function for now with $new_session arg set to TRUE |
|
841 | + return $this->update(true) ? true : false; |
|
842 | + } |
|
843 | + |
|
844 | + |
|
845 | + |
|
846 | + /** |
|
847 | + * _save_session_to_db |
|
848 | + * |
|
849 | + * @param bool $clear_session |
|
850 | + * @return string |
|
851 | + * @throws EE_Error |
|
852 | + * @throws InvalidArgumentException |
|
853 | + * @throws InvalidDataTypeException |
|
854 | + * @throws InvalidInterfaceException |
|
855 | + */ |
|
856 | + private function _save_session_to_db($clear_session = false) |
|
857 | + { |
|
858 | + // unless we're deleting the session data, don't save anything if there isn't a cart |
|
859 | + if (! $clear_session && ! $this->cart() instanceof EE_Cart) { |
|
860 | + return false; |
|
861 | + } |
|
862 | + $transaction = $this->transaction(); |
|
863 | + if ($transaction instanceof EE_Transaction) { |
|
864 | + if (! $transaction->ID()) { |
|
865 | + $transaction->save(); |
|
866 | + } |
|
867 | + $this->_session_data['transaction'] = $transaction->ID(); |
|
868 | + } |
|
869 | + // then serialize all of our session data |
|
870 | + $session_data = serialize($this->_session_data); |
|
871 | + // do we need to also encode it to avoid corrupted data when saved to the db? |
|
872 | + $session_data = $this->_use_encryption |
|
873 | + ? $this->encryption->base64_string_encode($session_data) |
|
874 | + : $session_data; |
|
875 | + // maybe save hash check |
|
876 | + if (apply_filters('FHEE__EE_Session___perform_session_id_hash_check', WP_DEBUG)) { |
|
877 | + $this->cache_storage->add( |
|
878 | + EE_Session::hash_check_prefix . $this->_sid, |
|
879 | + md5($session_data), |
|
880 | + $this->_lifespan |
|
881 | + ); |
|
882 | + } |
|
883 | + // we're using the Transient API for storing session data, |
|
884 | + return $this->cache_storage->add( |
|
885 | + EE_Session::session_id_prefix . $this->_sid, |
|
886 | + $session_data, |
|
887 | + $this->_lifespan |
|
888 | + ); |
|
889 | + } |
|
890 | + |
|
891 | + |
|
892 | + |
|
893 | + /** |
|
894 | + * _visitor_ip |
|
895 | + * attempt to get IP address of current visitor from server |
|
896 | + * plz see: http://stackoverflow.com/a/2031935/1475279 |
|
897 | + * |
|
898 | + * @access public |
|
899 | + * @return string |
|
900 | + */ |
|
901 | + private function _visitor_ip() |
|
902 | + { |
|
903 | + $visitor_ip = '0.0.0.0'; |
|
904 | + $server_keys = array( |
|
905 | + 'HTTP_CLIENT_IP', |
|
906 | + 'HTTP_X_FORWARDED_FOR', |
|
907 | + 'HTTP_X_FORWARDED', |
|
908 | + 'HTTP_X_CLUSTER_CLIENT_IP', |
|
909 | + 'HTTP_FORWARDED_FOR', |
|
910 | + 'HTTP_FORWARDED', |
|
911 | + 'REMOTE_ADDR', |
|
912 | + ); |
|
913 | + foreach ($server_keys as $key) { |
|
914 | + if (isset($_SERVER[ $key ])) { |
|
915 | + foreach (array_map('trim', explode(',', $_SERVER[ $key ])) as $ip) { |
|
916 | + if ($ip === '127.0.0.1' || filter_var($ip, FILTER_VALIDATE_IP) !== false) { |
|
917 | + $visitor_ip = $ip; |
|
918 | + } |
|
919 | + } |
|
920 | + } |
|
921 | + } |
|
922 | + return $visitor_ip; |
|
923 | + } |
|
924 | + |
|
925 | + |
|
926 | + |
|
927 | + /** |
|
928 | + * @get the full page request the visitor is accessing |
|
929 | + * @access public |
|
930 | + * @return string |
|
931 | + */ |
|
932 | + public function _get_page_visit() |
|
933 | + { |
|
934 | + $page_visit = home_url('/') . 'wp-admin/admin-ajax.php'; |
|
935 | + // check for request url |
|
936 | + if (isset($_SERVER['REQUEST_URI'])) { |
|
937 | + $http_host = ''; |
|
938 | + $page_id = '?'; |
|
939 | + $e_reg = ''; |
|
940 | + $request_uri = esc_url($_SERVER['REQUEST_URI']); |
|
941 | + $ru_bits = explode('?', $request_uri); |
|
942 | + $request_uri = $ru_bits[0]; |
|
943 | + // check for and grab host as well |
|
944 | + if (isset($_SERVER['HTTP_HOST'])) { |
|
945 | + $http_host = esc_url($_SERVER['HTTP_HOST']); |
|
946 | + } |
|
947 | + // check for page_id in SERVER REQUEST |
|
948 | + if (isset($_REQUEST['page_id'])) { |
|
949 | + // rebuild $e_reg without any of the extra parameters |
|
950 | + $page_id = '?page_id=' . esc_attr($_REQUEST['page_id']) . '&'; |
|
951 | + } |
|
952 | + // check for $e_reg in SERVER REQUEST |
|
953 | + if (isset($_REQUEST['ee'])) { |
|
954 | + // rebuild $e_reg without any of the extra parameters |
|
955 | + $e_reg = 'ee=' . esc_attr($_REQUEST['ee']); |
|
956 | + } |
|
957 | + $page_visit = rtrim($http_host . $request_uri . $page_id . $e_reg, '?'); |
|
958 | + } |
|
959 | + return $page_visit !== home_url('/wp-admin/admin-ajax.php') ? $page_visit : ''; |
|
960 | + } |
|
961 | + |
|
962 | + |
|
963 | + |
|
964 | + /** |
|
965 | + * @the current wp user id |
|
966 | + * @access public |
|
967 | + * @return int |
|
968 | + */ |
|
969 | + public function _wp_user_id() |
|
970 | + { |
|
971 | + // if I need to explain the following lines of code, then you shouldn't be looking at this! |
|
972 | + $this->_wp_user_id = get_current_user_id(); |
|
973 | + return $this->_wp_user_id; |
|
974 | + } |
|
975 | + |
|
976 | + |
|
977 | + |
|
978 | + /** |
|
979 | + * Clear EE_Session data |
|
980 | + * |
|
981 | + * @access public |
|
982 | + * @param string $class |
|
983 | + * @param string $function |
|
984 | + * @return void |
|
985 | + * @throws EE_Error |
|
986 | + * @throws InvalidArgumentException |
|
987 | + * @throws InvalidDataTypeException |
|
988 | + * @throws InvalidInterfaceException |
|
989 | + */ |
|
990 | + public function clear_session($class = '', $function = '') |
|
991 | + { |
|
992 | + //echo '<h3 style="color:#999;line-height:.9em;"><span style="color:#2EA2CC">' . __CLASS__ . '</span>::<span style="color:#E76700">' . __FUNCTION__ . '( ' . $class . '::' . $function . '() )</span><br/><span style="font-size:9px;font-weight:normal;">' . __FILE__ . '</span> <b style="font-size:10px;"> ' . __LINE__ . ' </b></h3>'; |
|
993 | + do_action('AHEE_log', __FILE__, __FUNCTION__, 'session cleared by : ' . $class . '::' . $function . '()'); |
|
994 | + $this->reset_cart(); |
|
995 | + $this->reset_checkout(); |
|
996 | + $this->reset_transaction(); |
|
997 | + // wipe out everything that isn't a default session datum |
|
998 | + $this->reset_data(array_keys($this->_session_data)); |
|
999 | + // reset initial site access time and the session expiration |
|
1000 | + $this->_set_init_access_and_expiration(); |
|
1001 | + $this->_save_session_to_db(true); |
|
1002 | + } |
|
1003 | + |
|
1004 | + |
|
1005 | + |
|
1006 | + /** |
|
1007 | + * @resets all non-default session vars |
|
1008 | + * @access public |
|
1009 | + * @param array|mixed $data_to_reset |
|
1010 | + * @param bool $show_all_notices |
|
1011 | + * @return TRUE on success, FALSE on fail |
|
1012 | + */ |
|
1013 | + public function reset_data($data_to_reset = array(), $show_all_notices = false) |
|
1014 | + { |
|
1015 | + // if $data_to_reset is not in an array, then put it in one |
|
1016 | + if (! is_array($data_to_reset)) { |
|
1017 | + $data_to_reset = array($data_to_reset); |
|
1018 | + } |
|
1019 | + // nothing ??? go home! |
|
1020 | + if (empty($data_to_reset)) { |
|
1021 | + EE_Error::add_error(__('No session data could be reset, because no session var name was provided.', |
|
1022 | + 'event_espresso'), __FILE__, __FUNCTION__, __LINE__); |
|
1023 | + return false; |
|
1024 | + } |
|
1025 | + $return_value = true; |
|
1026 | + // since $data_to_reset is an array, cycle through the values |
|
1027 | + foreach ($data_to_reset as $reset) { |
|
1028 | + |
|
1029 | + // first check to make sure it is a valid session var |
|
1030 | + if (isset($this->_session_data[ $reset ])) { |
|
1031 | + // then check to make sure it is not a default var |
|
1032 | + if (! array_key_exists($reset, $this->_default_session_vars)) { |
|
1033 | + // remove session var |
|
1034 | + unset($this->_session_data[ $reset ]); |
|
1035 | + if ($show_all_notices) { |
|
1036 | + EE_Error::add_success(sprintf(__('The session variable %s was removed.', 'event_espresso'), |
|
1037 | + $reset), __FILE__, __FUNCTION__, __LINE__); |
|
1038 | + } |
|
1039 | + } else { |
|
1040 | + // yeeeeeeeeerrrrrrrrrrr OUT !!!! |
|
1041 | + if ($show_all_notices) { |
|
1042 | + EE_Error::add_error(sprintf(__('Sorry! %s is a default session datum and can not be reset.', |
|
1043 | + 'event_espresso'), $reset), __FILE__, __FUNCTION__, __LINE__); |
|
1044 | + } |
|
1045 | + $return_value = false; |
|
1046 | + } |
|
1047 | + } elseif ($show_all_notices) { |
|
1048 | + // oops! that session var does not exist! |
|
1049 | + EE_Error::add_error(sprintf(__('The session item provided, %s, is invalid or does not exist.', |
|
1050 | + 'event_espresso'), $reset), __FILE__, __FUNCTION__, __LINE__); |
|
1051 | + $return_value = false; |
|
1052 | + } |
|
1053 | + } // end of foreach |
|
1054 | + return $return_value; |
|
1055 | + } |
|
1056 | + |
|
1057 | + |
|
1058 | + |
|
1059 | + /** |
|
1060 | + * wp_loaded |
|
1061 | + * |
|
1062 | + * @access public |
|
1063 | + * @throws EE_Error |
|
1064 | + * @throws InvalidDataTypeException |
|
1065 | + * @throws InvalidInterfaceException |
|
1066 | + * @throws InvalidArgumentException |
|
1067 | + */ |
|
1068 | + public function wp_loaded() |
|
1069 | + { |
|
1070 | + if ( |
|
1071 | + EE_Registry::instance()->REQ instanceof EE_Request_Handler |
|
1072 | + && EE_Registry::instance()->REQ->is_set('clear_session') |
|
1073 | + ) { |
|
1074 | + $this->clear_session(__CLASS__, __FUNCTION__); |
|
1075 | + } |
|
1076 | + } |
|
1077 | + |
|
1078 | + |
|
1079 | + |
|
1080 | + /** |
|
1081 | + * Used to reset the entire object (for tests). |
|
1082 | + * |
|
1083 | + * @since 4.3.0 |
|
1084 | + * @throws EE_Error |
|
1085 | + * @throws InvalidDataTypeException |
|
1086 | + * @throws InvalidInterfaceException |
|
1087 | + * @throws InvalidArgumentException |
|
1088 | + */ |
|
1089 | + public function reset_instance() |
|
1090 | + { |
|
1091 | + $this->clear_session(); |
|
1092 | + self::$_instance = null; |
|
1093 | + } |
|
1094 | + |
|
1095 | + |
|
1096 | + |
|
1097 | + public function configure_garbage_collection_filters() |
|
1098 | + { |
|
1099 | + // run old filter we had for controlling session cleanup |
|
1100 | + $expired_session_transient_delete_query_limit = absint( |
|
1101 | + apply_filters( |
|
1102 | + 'FHEE__EE_Session__garbage_collection___expired_session_transient_delete_query_limit', |
|
1103 | + 50 |
|
1104 | + ) |
|
1105 | + ); |
|
1106 | + // is there a value? or one that is different than the default 50 records? |
|
1107 | + if ($expired_session_transient_delete_query_limit === 0) { |
|
1108 | + // hook into TransientCacheStorage in case Session cleanup was turned off |
|
1109 | + add_filter('FHEE__TransientCacheStorage__transient_cleanup_schedule', '__return_zero'); |
|
1110 | + } elseif ($expired_session_transient_delete_query_limit !== 50) { |
|
1111 | + // or use that for the new transient cleanup query limit |
|
1112 | + add_filter( |
|
1113 | + 'FHEE__TransientCacheStorage__clearExpiredTransients__limit', |
|
1114 | + function () use ($expired_session_transient_delete_query_limit) |
|
1115 | + { |
|
1116 | + return $expired_session_transient_delete_query_limit; |
|
1117 | + } |
|
1118 | + ); |
|
1119 | + } |
|
1120 | + } |
|
1121 | + |
|
1122 | + |
|
1123 | + |
|
1124 | + /** |
|
1125 | + * @see http://stackoverflow.com/questions/10152904/unserialize-function-unserialize-error-at-offset/21389439#10152996 |
|
1126 | + * @param $data1 |
|
1127 | + * @return string |
|
1128 | + */ |
|
1129 | + private function find_serialize_error($data1) |
|
1130 | + { |
|
1131 | + $error = '<pre>'; |
|
1132 | + $data2 = preg_replace_callback( |
|
1133 | + '!s:(\d+):"(.*?)";!', |
|
1134 | + function ($match) |
|
1135 | + { |
|
1136 | + return ($match[1] === strlen($match[2])) |
|
1137 | + ? $match[0] |
|
1138 | + : 's:' |
|
1139 | + . strlen($match[2]) |
|
1140 | + . ':"' |
|
1141 | + . $match[2] |
|
1142 | + . '";'; |
|
1143 | + }, |
|
1144 | + $data1 |
|
1145 | + ); |
|
1146 | + $max = (strlen($data1) > strlen($data2)) ? strlen($data1) : strlen($data2); |
|
1147 | + $error .= $data1 . PHP_EOL; |
|
1148 | + $error .= $data2 . PHP_EOL; |
|
1149 | + for ($i = 0; $i < $max; $i++) { |
|
1150 | + if (@$data1[ $i ] !== @$data2[ $i ]) { |
|
1151 | + $error .= 'Difference ' . @$data1[ $i ] . ' != ' . @$data2[ $i ] . PHP_EOL; |
|
1152 | + $error .= "\t-> ORD number " . ord(@$data1[ $i ]) . ' != ' . ord(@$data2[ $i ]) . PHP_EOL; |
|
1153 | + $error .= "\t-> Line Number = $i" . PHP_EOL; |
|
1154 | + $start = ($i - 20); |
|
1155 | + $start = ($start < 0) ? 0 : $start; |
|
1156 | + $length = 40; |
|
1157 | + $point = $max - $i; |
|
1158 | + if ($point < 20) { |
|
1159 | + $rlength = 1; |
|
1160 | + $rpoint = -$point; |
|
1161 | + } else { |
|
1162 | + $rpoint = $length - 20; |
|
1163 | + $rlength = 1; |
|
1164 | + } |
|
1165 | + $error .= "\t-> Section Data1 = "; |
|
1166 | + $error .= substr_replace( |
|
1167 | + substr($data1, $start, $length), |
|
1168 | + "<b style=\"color:green\">{$data1[ $i ]}</b>", |
|
1169 | + $rpoint, |
|
1170 | + $rlength |
|
1171 | + ); |
|
1172 | + $error .= PHP_EOL; |
|
1173 | + $error .= "\t-> Section Data2 = "; |
|
1174 | + $error .= substr_replace( |
|
1175 | + substr($data2, $start, $length), |
|
1176 | + "<b style=\"color:red\">{$data2[ $i ]}</b>", |
|
1177 | + $rpoint, |
|
1178 | + $rlength |
|
1179 | + ); |
|
1180 | + $error .= PHP_EOL; |
|
1181 | + } |
|
1182 | + } |
|
1183 | + $error .= '</pre>'; |
|
1184 | + return $error; |
|
1185 | + } |
|
1186 | + |
|
1187 | + |
|
1188 | + /** |
|
1189 | + * Saves an array of settings used for configuring aspects of session behaviour |
|
1190 | + * |
|
1191 | + * @param array $updated_settings |
|
1192 | + */ |
|
1193 | + private function updateSessionSettings(array $updated_settings = array()) |
|
1194 | + { |
|
1195 | + // add existing settings, but only if not included in incoming $updated_settings array |
|
1196 | + $updated_settings += get_option(EE_Session::OPTION_NAME_SETTINGS, array()); |
|
1197 | + update_option(EE_Session::OPTION_NAME_SETTINGS, $updated_settings); |
|
1198 | + } |
|
1199 | + |
|
1200 | + |
|
1201 | + /** |
|
1202 | + * garbage_collection |
|
1203 | + */ |
|
1204 | + public function garbageCollection() |
|
1205 | + { |
|
1206 | + // only perform during regular requests if last garbage collection was over an hour ago |
|
1207 | + if (! (defined('DOING_AJAX') && DOING_AJAX) && (time() - HOUR_IN_SECONDS) >= $this->_last_gc) { |
|
1208 | + $this->_last_gc = time(); |
|
1209 | + $this->updateSessionSettings(array('last_gc' => $this->_last_gc)); |
|
1210 | + /** @type WPDB $wpdb */ |
|
1211 | + global $wpdb; |
|
1212 | + // filter the query limit. Set to 0 to turn off garbage collection |
|
1213 | + $expired_session_transient_delete_query_limit = absint( |
|
1214 | + apply_filters( |
|
1215 | + 'FHEE__EE_Session__garbage_collection___expired_session_transient_delete_query_limit', |
|
1216 | + 50 |
|
1217 | + ) |
|
1218 | + ); |
|
1219 | + // non-zero LIMIT means take out the trash |
|
1220 | + if ($expired_session_transient_delete_query_limit) { |
|
1221 | + $session_key = str_replace('_', '\_', EE_Session::session_id_prefix); |
|
1222 | + $hash_check_key = str_replace('_', '\_', EE_Session::hash_check_prefix); |
|
1223 | + // since transient expiration timestamps are set in the future, we can compare against NOW |
|
1224 | + // but we only want to pick up any trash that's been around for more than a day |
|
1225 | + $expiration = time() - DAY_IN_SECONDS; |
|
1226 | + $SQL = " |
|
1227 | 1227 | SELECT option_name |
1228 | 1228 | FROM {$wpdb->options} |
1229 | 1229 | WHERE |
@@ -1232,19 +1232,19 @@ discard block |
||
1232 | 1232 | AND option_value < {$expiration} |
1233 | 1233 | LIMIT {$expired_session_transient_delete_query_limit} |
1234 | 1234 | "; |
1235 | - // produces something like: |
|
1236 | - // SELECT option_name FROM wp_options |
|
1237 | - // WHERE ( option_name LIKE '\_transient\_timeout\_ee\_ssn\_%' |
|
1238 | - // OR option_name LIKE '\_transient\_timeout\_ee\_shc\_%' ) |
|
1239 | - // AND option_value < 1508368198 LIMIT 50 |
|
1240 | - $expired_sessions = $wpdb->get_col($SQL); |
|
1241 | - // valid results? |
|
1242 | - if (! $expired_sessions instanceof WP_Error && ! empty($expired_sessions)) { |
|
1243 | - $this->cache_storage->deleteMany($expired_sessions, true); |
|
1244 | - } |
|
1245 | - } |
|
1246 | - } |
|
1247 | - } |
|
1235 | + // produces something like: |
|
1236 | + // SELECT option_name FROM wp_options |
|
1237 | + // WHERE ( option_name LIKE '\_transient\_timeout\_ee\_ssn\_%' |
|
1238 | + // OR option_name LIKE '\_transient\_timeout\_ee\_shc\_%' ) |
|
1239 | + // AND option_value < 1508368198 LIMIT 50 |
|
1240 | + $expired_sessions = $wpdb->get_col($SQL); |
|
1241 | + // valid results? |
|
1242 | + if (! $expired_sessions instanceof WP_Error && ! empty($expired_sessions)) { |
|
1243 | + $this->cache_storage->deleteMany($expired_sessions, true); |
|
1244 | + } |
|
1245 | + } |
|
1246 | + } |
|
1247 | + } |
|
1248 | 1248 | |
1249 | 1249 | |
1250 | 1250 |
@@ -164,7 +164,7 @@ discard block |
||
164 | 164 | // check if class object is instantiated |
165 | 165 | // session loading is turned ON by default, but prior to the init hook, can be turned back OFF via: |
166 | 166 | // add_filter( 'FHEE_load_EE_Session', '__return_false' ); |
167 | - if (! self::$_instance instanceof EE_Session && apply_filters('FHEE_load_EE_Session', true)) { |
|
167 | + if ( ! self::$_instance instanceof EE_Session && apply_filters('FHEE_load_EE_Session', true)) { |
|
168 | 168 | self::$_instance = new self($cache_storage, $encryption); |
169 | 169 | } |
170 | 170 | return self::$_instance; |
@@ -185,11 +185,11 @@ discard block |
||
185 | 185 | { |
186 | 186 | |
187 | 187 | // session loading is turned ON by default, but prior to the init hook, can be turned back OFF via: add_filter( 'FHEE_load_EE_Session', '__return_false' ); |
188 | - if (! apply_filters('FHEE_load_EE_Session', true)) { |
|
188 | + if ( ! apply_filters('FHEE_load_EE_Session', true)) { |
|
189 | 189 | return; |
190 | 190 | } |
191 | 191 | do_action('AHEE_log', __FILE__, __FUNCTION__, ''); |
192 | - if (! defined('ESPRESSO_SESSION')) { |
|
192 | + if ( ! defined('ESPRESSO_SESSION')) { |
|
193 | 193 | define('ESPRESSO_SESSION', true); |
194 | 194 | } |
195 | 195 | // default session lifespan in seconds |
@@ -205,11 +205,11 @@ discard block |
||
205 | 205 | */ |
206 | 206 | // retrieve session options from db |
207 | 207 | $session_settings = (array) get_option(EE_Session::OPTION_NAME_SETTINGS, array()); |
208 | - if (! empty($session_settings)) { |
|
208 | + if ( ! empty($session_settings)) { |
|
209 | 209 | // cycle though existing session options |
210 | 210 | foreach ($session_settings as $var_name => $session_setting) { |
211 | 211 | // set values for class properties |
212 | - $var_name = '_' . $var_name; |
|
212 | + $var_name = '_'.$var_name; |
|
213 | 213 | $this->{$var_name} = $session_setting; |
214 | 214 | } |
215 | 215 | } |
@@ -247,7 +247,7 @@ discard block |
||
247 | 247 | public function open_session() |
248 | 248 | { |
249 | 249 | // check for existing session and retrieve it from db |
250 | - if (! $this->_espresso_session()) { |
|
250 | + if ( ! $this->_espresso_session()) { |
|
251 | 251 | // or just start a new one |
252 | 252 | $this->_create_espresso_session(); |
253 | 253 | } |
@@ -299,7 +299,7 @@ discard block |
||
299 | 299 | */ |
300 | 300 | public function extend_expiration($time = 0) |
301 | 301 | { |
302 | - $time = $time ? $time : $this->extension(); |
|
302 | + $time = $time ? $time : $this->extension(); |
|
303 | 303 | $this->_expiration += absint($time); |
304 | 304 | } |
305 | 305 | |
@@ -326,9 +326,9 @@ discard block |
||
326 | 326 | // set some defaults |
327 | 327 | foreach ($this->_default_session_vars as $key => $default_var) { |
328 | 328 | if (is_array($default_var)) { |
329 | - $this->_session_data[ $key ] = array(); |
|
329 | + $this->_session_data[$key] = array(); |
|
330 | 330 | } else { |
331 | - $this->_session_data[ $key ] = ''; |
|
331 | + $this->_session_data[$key] = ''; |
|
332 | 332 | } |
333 | 333 | } |
334 | 334 | } |
@@ -471,8 +471,8 @@ discard block |
||
471 | 471 | $this->reset_checkout(); |
472 | 472 | $this->reset_transaction(); |
473 | 473 | } |
474 | - if (! empty($key)) { |
|
475 | - return isset($this->_session_data[ $key ]) ? $this->_session_data[ $key ] : null; |
|
474 | + if ( ! empty($key)) { |
|
475 | + return isset($this->_session_data[$key]) ? $this->_session_data[$key] : null; |
|
476 | 476 | } |
477 | 477 | return $this->_session_data; |
478 | 478 | } |
@@ -496,12 +496,12 @@ discard block |
||
496 | 496 | return false; |
497 | 497 | } |
498 | 498 | foreach ($data as $key => $value) { |
499 | - if (isset($this->_default_session_vars[ $key ])) { |
|
499 | + if (isset($this->_default_session_vars[$key])) { |
|
500 | 500 | EE_Error::add_error(sprintf(__('Sorry! %s is a default session datum and can not be reset.', |
501 | 501 | 'event_espresso'), $key), __FILE__, __FUNCTION__, __LINE__); |
502 | 502 | return false; |
503 | 503 | } |
504 | - $this->_session_data[ $key ] = $value; |
|
504 | + $this->_session_data[$key] = $value; |
|
505 | 505 | } |
506 | 506 | return true; |
507 | 507 | } |
@@ -534,7 +534,7 @@ discard block |
||
534 | 534 | $this->_user_agent = isset($_SERVER['HTTP_USER_AGENT']) ? esc_attr($_SERVER['HTTP_USER_AGENT']) : false; |
535 | 535 | // now let's retrieve what's in the db |
536 | 536 | $session_data = $this->_retrieve_session_data(); |
537 | - if (! empty($session_data)) { |
|
537 | + if ( ! empty($session_data)) { |
|
538 | 538 | // get the current time in UTC |
539 | 539 | $this->_time = $this->_time !== null ? $this->_time : time(); |
540 | 540 | // and reset the session expiration |
@@ -545,7 +545,7 @@ discard block |
||
545 | 545 | // set initial site access time and the session expiration |
546 | 546 | $this->_set_init_access_and_expiration(); |
547 | 547 | // set referer |
548 | - $this->_session_data['pages_visited'][ $this->_session_data['init_access'] ] = isset($_SERVER['HTTP_REFERER']) |
|
548 | + $this->_session_data['pages_visited'][$this->_session_data['init_access']] = isset($_SERVER['HTTP_REFERER']) |
|
549 | 549 | ? esc_attr($_SERVER['HTTP_REFERER']) |
550 | 550 | : ''; |
551 | 551 | // no previous session = go back and create one (on top of the data above) |
@@ -583,7 +583,7 @@ discard block |
||
583 | 583 | */ |
584 | 584 | protected function _retrieve_session_data() |
585 | 585 | { |
586 | - $ssn_key = EE_Session::session_id_prefix . $this->_sid; |
|
586 | + $ssn_key = EE_Session::session_id_prefix.$this->_sid; |
|
587 | 587 | try { |
588 | 588 | // we're using WP's Transient API to store session data using the PHP session ID as the option name |
589 | 589 | $session_data = $this->cache_storage->get($ssn_key, false); |
@@ -592,7 +592,7 @@ discard block |
||
592 | 592 | } |
593 | 593 | if (apply_filters('FHEE__EE_Session___perform_session_id_hash_check', WP_DEBUG)) { |
594 | 594 | $hash_check = $this->cache_storage->get( |
595 | - EE_Session::hash_check_prefix . $this->_sid, |
|
595 | + EE_Session::hash_check_prefix.$this->_sid, |
|
596 | 596 | false |
597 | 597 | ); |
598 | 598 | if ($hash_check && $hash_check !== md5($session_data)) { |
@@ -602,7 +602,7 @@ discard block |
||
602 | 602 | 'The stored data for session %1$s failed to pass a hash check and therefore appears to be invalid.', |
603 | 603 | 'event_espresso' |
604 | 604 | ), |
605 | - EE_Session::session_id_prefix . $this->_sid |
|
605 | + EE_Session::session_id_prefix.$this->_sid |
|
606 | 606 | ), |
607 | 607 | __FILE__, __FUNCTION__, __LINE__ |
608 | 608 | ); |
@@ -611,21 +611,21 @@ discard block |
||
611 | 611 | } catch (Exception $e) { |
612 | 612 | // let's just eat that error for now and attempt to correct any corrupted data |
613 | 613 | global $wpdb; |
614 | - $row = $wpdb->get_row( |
|
614 | + $row = $wpdb->get_row( |
|
615 | 615 | $wpdb->prepare( |
616 | 616 | "SELECT option_value FROM {$wpdb->options} WHERE option_name = %s LIMIT 1", |
617 | - '_transient_' . $ssn_key |
|
617 | + '_transient_'.$ssn_key |
|
618 | 618 | ) |
619 | 619 | ); |
620 | 620 | $session_data = is_object($row) ? $row->option_value : null; |
621 | 621 | if ($session_data) { |
622 | 622 | $session_data = preg_replace_callback( |
623 | 623 | '!s:(d+):"(.*?)";!', |
624 | - function ($match) |
|
624 | + function($match) |
|
625 | 625 | { |
626 | 626 | return $match[1] === strlen($match[2]) |
627 | 627 | ? $match[0] |
628 | - : 's:' . strlen($match[2]) . ':"' . $match[2] . '";'; |
|
628 | + : 's:'.strlen($match[2]).':"'.$match[2].'";'; |
|
629 | 629 | }, |
630 | 630 | $session_data |
631 | 631 | ); |
@@ -636,7 +636,7 @@ discard block |
||
636 | 636 | $session_data = $this->encryption instanceof EE_Encryption |
637 | 637 | ? $this->encryption->base64_string_decode($session_data) |
638 | 638 | : $session_data; |
639 | - if (! is_array($session_data)) { |
|
639 | + if ( ! is_array($session_data)) { |
|
640 | 640 | try { |
641 | 641 | $session_data = maybe_unserialize($session_data); |
642 | 642 | } catch (Exception $e) { |
@@ -650,21 +650,21 @@ discard block |
||
650 | 650 | . '</pre><br>' |
651 | 651 | . $this->find_serialize_error($session_data) |
652 | 652 | : ''; |
653 | - $this->cache_storage->delete(EE_Session::session_id_prefix . $this->_sid); |
|
653 | + $this->cache_storage->delete(EE_Session::session_id_prefix.$this->_sid); |
|
654 | 654 | throw new InvalidSessionDataException($msg, 0, $e); |
655 | 655 | } |
656 | 656 | } |
657 | 657 | // just a check to make sure the session array is indeed an array |
658 | - if (! is_array($session_data)) { |
|
658 | + if ( ! is_array($session_data)) { |
|
659 | 659 | // no?!?! then something is wrong |
660 | 660 | $msg = esc_html__( |
661 | 661 | 'The session data is missing, invalid, or corrupted.', |
662 | 662 | 'event_espresso' |
663 | 663 | ); |
664 | 664 | $msg .= WP_DEBUG |
665 | - ? '<br><pre>' . print_r($session_data, true) . '</pre><br>' . $this->find_serialize_error($session_data) |
|
665 | + ? '<br><pre>'.print_r($session_data, true).'</pre><br>'.$this->find_serialize_error($session_data) |
|
666 | 666 | : ''; |
667 | - $this->cache_storage->delete(EE_Session::session_id_prefix . $this->_sid); |
|
667 | + $this->cache_storage->delete(EE_Session::session_id_prefix.$this->_sid); |
|
668 | 668 | throw new InvalidSessionDataException($msg); |
669 | 669 | } |
670 | 670 | if (isset($session_data['transaction']) && absint($session_data['transaction']) !== 0) { |
@@ -692,7 +692,7 @@ discard block |
||
692 | 692 | if (isset($_REQUEST['EESID'])) { |
693 | 693 | $session_id = sanitize_text_field($_REQUEST['EESID']); |
694 | 694 | } else { |
695 | - $session_id = md5(session_id() . get_current_blog_id() . $this->_get_sid_salt()); |
|
695 | + $session_id = md5(session_id().get_current_blog_id().$this->_get_sid_salt()); |
|
696 | 696 | } |
697 | 697 | return apply_filters('FHEE__EE_Session___generate_session_id__session_id', $session_id); |
698 | 698 | } |
@@ -800,19 +800,19 @@ discard block |
||
800 | 800 | $page_visit = $this->_get_page_visit(); |
801 | 801 | if ($page_visit) { |
802 | 802 | // set pages visited where the first will be the http referrer |
803 | - $this->_session_data['pages_visited'][ $this->_time ] = $page_visit; |
|
803 | + $this->_session_data['pages_visited'][$this->_time] = $page_visit; |
|
804 | 804 | // we'll only save the last 10 page visits. |
805 | 805 | $session_data['pages_visited'] = array_slice($this->_session_data['pages_visited'], -10); |
806 | 806 | } |
807 | 807 | break; |
808 | 808 | default : |
809 | 809 | // carry any other data over |
810 | - $session_data[ $key ] = $this->_session_data[ $key ]; |
|
810 | + $session_data[$key] = $this->_session_data[$key]; |
|
811 | 811 | } |
812 | 812 | } |
813 | 813 | $this->_session_data = $session_data; |
814 | 814 | // creating a new session does not require saving to the db just yet |
815 | - if (! $new_session) { |
|
815 | + if ( ! $new_session) { |
|
816 | 816 | // ready? let's save |
817 | 817 | if ($this->_save_session_to_db()) { |
818 | 818 | return true; |
@@ -856,12 +856,12 @@ discard block |
||
856 | 856 | private function _save_session_to_db($clear_session = false) |
857 | 857 | { |
858 | 858 | // unless we're deleting the session data, don't save anything if there isn't a cart |
859 | - if (! $clear_session && ! $this->cart() instanceof EE_Cart) { |
|
859 | + if ( ! $clear_session && ! $this->cart() instanceof EE_Cart) { |
|
860 | 860 | return false; |
861 | 861 | } |
862 | 862 | $transaction = $this->transaction(); |
863 | 863 | if ($transaction instanceof EE_Transaction) { |
864 | - if (! $transaction->ID()) { |
|
864 | + if ( ! $transaction->ID()) { |
|
865 | 865 | $transaction->save(); |
866 | 866 | } |
867 | 867 | $this->_session_data['transaction'] = $transaction->ID(); |
@@ -875,14 +875,14 @@ discard block |
||
875 | 875 | // maybe save hash check |
876 | 876 | if (apply_filters('FHEE__EE_Session___perform_session_id_hash_check', WP_DEBUG)) { |
877 | 877 | $this->cache_storage->add( |
878 | - EE_Session::hash_check_prefix . $this->_sid, |
|
878 | + EE_Session::hash_check_prefix.$this->_sid, |
|
879 | 879 | md5($session_data), |
880 | 880 | $this->_lifespan |
881 | 881 | ); |
882 | 882 | } |
883 | 883 | // we're using the Transient API for storing session data, |
884 | 884 | return $this->cache_storage->add( |
885 | - EE_Session::session_id_prefix . $this->_sid, |
|
885 | + EE_Session::session_id_prefix.$this->_sid, |
|
886 | 886 | $session_data, |
887 | 887 | $this->_lifespan |
888 | 888 | ); |
@@ -911,8 +911,8 @@ discard block |
||
911 | 911 | 'REMOTE_ADDR', |
912 | 912 | ); |
913 | 913 | foreach ($server_keys as $key) { |
914 | - if (isset($_SERVER[ $key ])) { |
|
915 | - foreach (array_map('trim', explode(',', $_SERVER[ $key ])) as $ip) { |
|
914 | + if (isset($_SERVER[$key])) { |
|
915 | + foreach (array_map('trim', explode(',', $_SERVER[$key])) as $ip) { |
|
916 | 916 | if ($ip === '127.0.0.1' || filter_var($ip, FILTER_VALIDATE_IP) !== false) { |
917 | 917 | $visitor_ip = $ip; |
918 | 918 | } |
@@ -931,7 +931,7 @@ discard block |
||
931 | 931 | */ |
932 | 932 | public function _get_page_visit() |
933 | 933 | { |
934 | - $page_visit = home_url('/') . 'wp-admin/admin-ajax.php'; |
|
934 | + $page_visit = home_url('/').'wp-admin/admin-ajax.php'; |
|
935 | 935 | // check for request url |
936 | 936 | if (isset($_SERVER['REQUEST_URI'])) { |
937 | 937 | $http_host = ''; |
@@ -947,14 +947,14 @@ discard block |
||
947 | 947 | // check for page_id in SERVER REQUEST |
948 | 948 | if (isset($_REQUEST['page_id'])) { |
949 | 949 | // rebuild $e_reg without any of the extra parameters |
950 | - $page_id = '?page_id=' . esc_attr($_REQUEST['page_id']) . '&'; |
|
950 | + $page_id = '?page_id='.esc_attr($_REQUEST['page_id']).'&'; |
|
951 | 951 | } |
952 | 952 | // check for $e_reg in SERVER REQUEST |
953 | 953 | if (isset($_REQUEST['ee'])) { |
954 | 954 | // rebuild $e_reg without any of the extra parameters |
955 | - $e_reg = 'ee=' . esc_attr($_REQUEST['ee']); |
|
955 | + $e_reg = 'ee='.esc_attr($_REQUEST['ee']); |
|
956 | 956 | } |
957 | - $page_visit = rtrim($http_host . $request_uri . $page_id . $e_reg, '?'); |
|
957 | + $page_visit = rtrim($http_host.$request_uri.$page_id.$e_reg, '?'); |
|
958 | 958 | } |
959 | 959 | return $page_visit !== home_url('/wp-admin/admin-ajax.php') ? $page_visit : ''; |
960 | 960 | } |
@@ -990,7 +990,7 @@ discard block |
||
990 | 990 | public function clear_session($class = '', $function = '') |
991 | 991 | { |
992 | 992 | //echo '<h3 style="color:#999;line-height:.9em;"><span style="color:#2EA2CC">' . __CLASS__ . '</span>::<span style="color:#E76700">' . __FUNCTION__ . '( ' . $class . '::' . $function . '() )</span><br/><span style="font-size:9px;font-weight:normal;">' . __FILE__ . '</span> <b style="font-size:10px;"> ' . __LINE__ . ' </b></h3>'; |
993 | - do_action('AHEE_log', __FILE__, __FUNCTION__, 'session cleared by : ' . $class . '::' . $function . '()'); |
|
993 | + do_action('AHEE_log', __FILE__, __FUNCTION__, 'session cleared by : '.$class.'::'.$function.'()'); |
|
994 | 994 | $this->reset_cart(); |
995 | 995 | $this->reset_checkout(); |
996 | 996 | $this->reset_transaction(); |
@@ -1013,7 +1013,7 @@ discard block |
||
1013 | 1013 | public function reset_data($data_to_reset = array(), $show_all_notices = false) |
1014 | 1014 | { |
1015 | 1015 | // if $data_to_reset is not in an array, then put it in one |
1016 | - if (! is_array($data_to_reset)) { |
|
1016 | + if ( ! is_array($data_to_reset)) { |
|
1017 | 1017 | $data_to_reset = array($data_to_reset); |
1018 | 1018 | } |
1019 | 1019 | // nothing ??? go home! |
@@ -1027,11 +1027,11 @@ discard block |
||
1027 | 1027 | foreach ($data_to_reset as $reset) { |
1028 | 1028 | |
1029 | 1029 | // first check to make sure it is a valid session var |
1030 | - if (isset($this->_session_data[ $reset ])) { |
|
1030 | + if (isset($this->_session_data[$reset])) { |
|
1031 | 1031 | // then check to make sure it is not a default var |
1032 | - if (! array_key_exists($reset, $this->_default_session_vars)) { |
|
1032 | + if ( ! array_key_exists($reset, $this->_default_session_vars)) { |
|
1033 | 1033 | // remove session var |
1034 | - unset($this->_session_data[ $reset ]); |
|
1034 | + unset($this->_session_data[$reset]); |
|
1035 | 1035 | if ($show_all_notices) { |
1036 | 1036 | EE_Error::add_success(sprintf(__('The session variable %s was removed.', 'event_espresso'), |
1037 | 1037 | $reset), __FILE__, __FUNCTION__, __LINE__); |
@@ -1111,7 +1111,7 @@ discard block |
||
1111 | 1111 | // or use that for the new transient cleanup query limit |
1112 | 1112 | add_filter( |
1113 | 1113 | 'FHEE__TransientCacheStorage__clearExpiredTransients__limit', |
1114 | - function () use ($expired_session_transient_delete_query_limit) |
|
1114 | + function() use ($expired_session_transient_delete_query_limit) |
|
1115 | 1115 | { |
1116 | 1116 | return $expired_session_transient_delete_query_limit; |
1117 | 1117 | } |
@@ -1131,7 +1131,7 @@ discard block |
||
1131 | 1131 | $error = '<pre>'; |
1132 | 1132 | $data2 = preg_replace_callback( |
1133 | 1133 | '!s:(\d+):"(.*?)";!', |
1134 | - function ($match) |
|
1134 | + function($match) |
|
1135 | 1135 | { |
1136 | 1136 | return ($match[1] === strlen($match[2])) |
1137 | 1137 | ? $match[0] |
@@ -1143,14 +1143,14 @@ discard block |
||
1143 | 1143 | }, |
1144 | 1144 | $data1 |
1145 | 1145 | ); |
1146 | - $max = (strlen($data1) > strlen($data2)) ? strlen($data1) : strlen($data2); |
|
1147 | - $error .= $data1 . PHP_EOL; |
|
1148 | - $error .= $data2 . PHP_EOL; |
|
1146 | + $max = (strlen($data1) > strlen($data2)) ? strlen($data1) : strlen($data2); |
|
1147 | + $error .= $data1.PHP_EOL; |
|
1148 | + $error .= $data2.PHP_EOL; |
|
1149 | 1149 | for ($i = 0; $i < $max; $i++) { |
1150 | - if (@$data1[ $i ] !== @$data2[ $i ]) { |
|
1151 | - $error .= 'Difference ' . @$data1[ $i ] . ' != ' . @$data2[ $i ] . PHP_EOL; |
|
1152 | - $error .= "\t-> ORD number " . ord(@$data1[ $i ]) . ' != ' . ord(@$data2[ $i ]) . PHP_EOL; |
|
1153 | - $error .= "\t-> Line Number = $i" . PHP_EOL; |
|
1150 | + if (@$data1[$i] !== @$data2[$i]) { |
|
1151 | + $error .= 'Difference '.@$data1[$i].' != '.@$data2[$i].PHP_EOL; |
|
1152 | + $error .= "\t-> ORD number ".ord(@$data1[$i]).' != '.ord(@$data2[$i]).PHP_EOL; |
|
1153 | + $error .= "\t-> Line Number = $i".PHP_EOL; |
|
1154 | 1154 | $start = ($i - 20); |
1155 | 1155 | $start = ($start < 0) ? 0 : $start; |
1156 | 1156 | $length = 40; |
@@ -1165,7 +1165,7 @@ discard block |
||
1165 | 1165 | $error .= "\t-> Section Data1 = "; |
1166 | 1166 | $error .= substr_replace( |
1167 | 1167 | substr($data1, $start, $length), |
1168 | - "<b style=\"color:green\">{$data1[ $i ]}</b>", |
|
1168 | + "<b style=\"color:green\">{$data1[$i]}</b>", |
|
1169 | 1169 | $rpoint, |
1170 | 1170 | $rlength |
1171 | 1171 | ); |
@@ -1173,7 +1173,7 @@ discard block |
||
1173 | 1173 | $error .= "\t-> Section Data2 = "; |
1174 | 1174 | $error .= substr_replace( |
1175 | 1175 | substr($data2, $start, $length), |
1176 | - "<b style=\"color:red\">{$data2[ $i ]}</b>", |
|
1176 | + "<b style=\"color:red\">{$data2[$i]}</b>", |
|
1177 | 1177 | $rpoint, |
1178 | 1178 | $rlength |
1179 | 1179 | ); |
@@ -1204,7 +1204,7 @@ discard block |
||
1204 | 1204 | public function garbageCollection() |
1205 | 1205 | { |
1206 | 1206 | // only perform during regular requests if last garbage collection was over an hour ago |
1207 | - if (! (defined('DOING_AJAX') && DOING_AJAX) && (time() - HOUR_IN_SECONDS) >= $this->_last_gc) { |
|
1207 | + if ( ! (defined('DOING_AJAX') && DOING_AJAX) && (time() - HOUR_IN_SECONDS) >= $this->_last_gc) { |
|
1208 | 1208 | $this->_last_gc = time(); |
1209 | 1209 | $this->updateSessionSettings(array('last_gc' => $this->_last_gc)); |
1210 | 1210 | /** @type WPDB $wpdb */ |
@@ -1239,7 +1239,7 @@ discard block |
||
1239 | 1239 | // AND option_value < 1508368198 LIMIT 50 |
1240 | 1240 | $expired_sessions = $wpdb->get_col($SQL); |
1241 | 1241 | // valid results? |
1242 | - if (! $expired_sessions instanceof WP_Error && ! empty($expired_sessions)) { |
|
1242 | + if ( ! $expired_sessions instanceof WP_Error && ! empty($expired_sessions)) { |
|
1243 | 1243 | $this->cache_storage->deleteMany($expired_sessions, true); |
1244 | 1244 | } |
1245 | 1245 | } |
@@ -1,5 +1,4 @@ |
||
1 | 1 | <?php |
2 | -use EventEspresso\core\domain\entities\notifications\PersistentAdminNotice; |
|
3 | 2 | use EventEspresso\core\domain\services\factories\EmailAddressFactory; |
4 | 3 | use EventEspresso\core\domain\services\validation\email\EmailValidationException; |
5 | 4 | use EventEspresso\core\exceptions\InvalidDataTypeException; |
@@ -18,1254 +18,1254 @@ |
||
18 | 18 | class EED_Messages extends EED_Module |
19 | 19 | { |
20 | 20 | |
21 | - /** |
|
22 | - * This holds the EE_messages controller |
|
23 | - * |
|
24 | - * @deprecated 4.9.0 |
|
25 | - * @var EE_messages $_EEMSG |
|
26 | - */ |
|
27 | - protected static $_EEMSG; |
|
28 | - |
|
29 | - /** |
|
30 | - * @type EE_Message_Resource_Manager $_message_resource_manager |
|
31 | - */ |
|
32 | - protected static $_message_resource_manager; |
|
33 | - |
|
34 | - /** |
|
35 | - * This holds the EE_Messages_Processor business class. |
|
36 | - * |
|
37 | - * @type EE_Messages_Processor |
|
38 | - */ |
|
39 | - protected static $_MSG_PROCESSOR; |
|
40 | - |
|
41 | - /** |
|
42 | - * holds all the paths for various messages components. |
|
43 | - * Utilized by autoloader registry |
|
44 | - * |
|
45 | - * @var array |
|
46 | - */ |
|
47 | - protected static $_MSG_PATHS; |
|
48 | - |
|
49 | - |
|
50 | - /** |
|
51 | - * This will hold an array of messages template packs that are registered in the messages system. |
|
52 | - * Format is: |
|
53 | - * array( |
|
54 | - * 'template_pack_dbref' => EE_Messages_Template_Pack (instance) |
|
55 | - * ) |
|
56 | - * |
|
57 | - * @var EE_Messages_Template_Pack[] |
|
58 | - */ |
|
59 | - protected static $_TMP_PACKS = array(); |
|
60 | - |
|
61 | - |
|
62 | - /** |
|
63 | - * @return EED_Messages |
|
64 | - */ |
|
65 | - public static function instance() |
|
66 | - { |
|
67 | - return parent::get_instance(__CLASS__); |
|
68 | - } |
|
69 | - |
|
70 | - |
|
71 | - /** |
|
72 | - * set_hooks - for hooking into EE Core, other modules, etc |
|
73 | - * |
|
74 | - * @since 4.5.0 |
|
75 | - * @return void |
|
76 | - */ |
|
77 | - public static function set_hooks() |
|
78 | - { |
|
79 | - //actions |
|
80 | - add_action('AHEE__EE_Payment_Processor__update_txn_based_on_payment', array('EED_Messages', 'payment'), 10, 2); |
|
81 | - add_action('AHEE__EE_Registration_Processor__trigger_registration_update_notifications', |
|
82 | - array('EED_Messages', 'maybe_registration'), 10, 2); |
|
83 | - //filters |
|
84 | - add_filter('FHEE__EE_Registration__receipt_url__receipt_url', |
|
85 | - array('EED_Messages', 'registration_message_trigger_url'), 10, 4); |
|
86 | - add_filter('FHEE__EE_Registration__invoice_url__invoice_url', |
|
87 | - array('EED_Messages', 'registration_message_trigger_url'), 10, 4); |
|
88 | - //register routes |
|
89 | - self::_register_routes(); |
|
90 | - } |
|
91 | - |
|
92 | - /** |
|
93 | - * set_hooks_admin - for hooking into EE Admin Core, other modules, etc |
|
94 | - * |
|
95 | - * @access public |
|
96 | - * @return void |
|
97 | - */ |
|
98 | - public static function set_hooks_admin() |
|
99 | - { |
|
100 | - //actions |
|
101 | - add_action('AHEE__EE_Payment_Processor__update_txn_based_on_payment', array('EED_Messages', 'payment'), 10, 2); |
|
102 | - add_action('AHEE__Transactions_Admin_Page___send_payment_reminder__process_admin_payment_reminder', |
|
103 | - array('EED_Messages', 'payment_reminder'), 10); |
|
104 | - add_action('AHEE__EE_Registration_Processor__trigger_registration_update_notifications', |
|
105 | - array('EED_Messages', 'maybe_registration'), 10, 3); |
|
106 | - add_action('AHEE__Extend_Registrations_Admin_Page___newsletter_selected_send__with_registrations', |
|
107 | - array('EED_Messages', 'send_newsletter_message'), 10, 2); |
|
108 | - add_action('AHEE__EES_Espresso_Cancelled__process_shortcode__transaction', |
|
109 | - array('EED_Messages', 'cancelled_registration'), 10); |
|
110 | - add_action('AHEE__EE_Admin_Page___process_admin_payment_notification', |
|
111 | - array('EED_Messages', 'process_admin_payment'), 10, 1); |
|
112 | - //filters |
|
113 | - add_filter('FHEE__EE_Admin_Page___process_resend_registration__success', |
|
114 | - array('EED_Messages', 'process_resend'), 10, 2); |
|
115 | - add_filter('FHEE__EE_Registration__receipt_url__receipt_url', |
|
116 | - array('EED_Messages', 'registration_message_trigger_url'), 10, 4); |
|
117 | - add_filter('FHEE__EE_Registration__invoice_url__invoice_url', |
|
118 | - array('EED_Messages', 'registration_message_trigger_url'), 10, 4); |
|
119 | - } |
|
120 | - |
|
121 | - |
|
122 | - /** |
|
123 | - * All the message triggers done by route go in here. |
|
124 | - * |
|
125 | - * @since 4.5.0 |
|
126 | - * @return void |
|
127 | - */ |
|
128 | - protected static function _register_routes() |
|
129 | - { |
|
130 | - EE_Config::register_route('msg_url_trigger', 'Messages', 'run'); |
|
131 | - EE_Config::register_route('msg_cron_trigger', 'Messages', 'execute_batch_request'); |
|
132 | - EE_Config::register_route('msg_browser_trigger', 'Messages', 'browser_trigger'); |
|
133 | - EE_Config::register_route('msg_browser_error_trigger', 'Messages', 'browser_error_trigger'); |
|
134 | - do_action('AHEE__EED_Messages___register_routes'); |
|
135 | - } |
|
136 | - |
|
137 | - |
|
138 | - /** |
|
139 | - * This is called when a browser display trigger is executed. |
|
140 | - * The browser display trigger is typically used when a already generated message is displayed directly in the |
|
141 | - * browser. |
|
142 | - * |
|
143 | - * @since 4.9.0 |
|
144 | - * @param WP $WP |
|
145 | - * @throws EE_Error |
|
146 | - * @throws InvalidArgumentException |
|
147 | - * @throws ReflectionException |
|
148 | - * @throws InvalidDataTypeException |
|
149 | - * @throws InvalidInterfaceException |
|
150 | - */ |
|
151 | - public function browser_trigger($WP) |
|
152 | - { |
|
153 | - //ensure controller is loaded |
|
154 | - self::_load_controller(); |
|
155 | - $token = EE_Registry::instance()->REQ->get('token'); |
|
156 | - try { |
|
157 | - $mtg = new EE_Message_Generated_From_Token($token, 'html', self::$_message_resource_manager); |
|
158 | - self::$_MSG_PROCESSOR->generate_and_send_now($mtg); |
|
159 | - } catch (EE_Error $e) { |
|
160 | - $error_msg = __('Please note that a system message failed to send due to a technical issue.', |
|
161 | - 'event_espresso'); |
|
162 | - // add specific message for developers if WP_DEBUG in on |
|
163 | - $error_msg .= '||' . $e->getMessage(); |
|
164 | - EE_Error::add_error($error_msg, __FILE__, __FUNCTION__, __LINE__); |
|
165 | - } |
|
166 | - } |
|
167 | - |
|
168 | - |
|
169 | - /** |
|
170 | - * This is called when a browser error trigger is executed. |
|
171 | - * When triggered this will grab the EE_Message matching the token in the request and use that to get the error |
|
172 | - * message and display it. |
|
173 | - * |
|
174 | - * @since 4.9.0 |
|
175 | - * @param $WP |
|
176 | - * @throws EE_Error |
|
177 | - * @throws InvalidArgumentException |
|
178 | - * @throws InvalidDataTypeException |
|
179 | - * @throws InvalidInterfaceException |
|
180 | - */ |
|
181 | - public function browser_error_trigger($WP) |
|
182 | - { |
|
183 | - $token = EE_Registry::instance()->REQ->get('token'); |
|
184 | - if ($token) { |
|
185 | - $message = EEM_Message::instance()->get_one_by_token($token); |
|
186 | - if ($message instanceof EE_Message) { |
|
187 | - header('HTTP/1.1 200 OK'); |
|
188 | - $error_msg = nl2br($message->error_message()); |
|
189 | - ?> |
|
21 | + /** |
|
22 | + * This holds the EE_messages controller |
|
23 | + * |
|
24 | + * @deprecated 4.9.0 |
|
25 | + * @var EE_messages $_EEMSG |
|
26 | + */ |
|
27 | + protected static $_EEMSG; |
|
28 | + |
|
29 | + /** |
|
30 | + * @type EE_Message_Resource_Manager $_message_resource_manager |
|
31 | + */ |
|
32 | + protected static $_message_resource_manager; |
|
33 | + |
|
34 | + /** |
|
35 | + * This holds the EE_Messages_Processor business class. |
|
36 | + * |
|
37 | + * @type EE_Messages_Processor |
|
38 | + */ |
|
39 | + protected static $_MSG_PROCESSOR; |
|
40 | + |
|
41 | + /** |
|
42 | + * holds all the paths for various messages components. |
|
43 | + * Utilized by autoloader registry |
|
44 | + * |
|
45 | + * @var array |
|
46 | + */ |
|
47 | + protected static $_MSG_PATHS; |
|
48 | + |
|
49 | + |
|
50 | + /** |
|
51 | + * This will hold an array of messages template packs that are registered in the messages system. |
|
52 | + * Format is: |
|
53 | + * array( |
|
54 | + * 'template_pack_dbref' => EE_Messages_Template_Pack (instance) |
|
55 | + * ) |
|
56 | + * |
|
57 | + * @var EE_Messages_Template_Pack[] |
|
58 | + */ |
|
59 | + protected static $_TMP_PACKS = array(); |
|
60 | + |
|
61 | + |
|
62 | + /** |
|
63 | + * @return EED_Messages |
|
64 | + */ |
|
65 | + public static function instance() |
|
66 | + { |
|
67 | + return parent::get_instance(__CLASS__); |
|
68 | + } |
|
69 | + |
|
70 | + |
|
71 | + /** |
|
72 | + * set_hooks - for hooking into EE Core, other modules, etc |
|
73 | + * |
|
74 | + * @since 4.5.0 |
|
75 | + * @return void |
|
76 | + */ |
|
77 | + public static function set_hooks() |
|
78 | + { |
|
79 | + //actions |
|
80 | + add_action('AHEE__EE_Payment_Processor__update_txn_based_on_payment', array('EED_Messages', 'payment'), 10, 2); |
|
81 | + add_action('AHEE__EE_Registration_Processor__trigger_registration_update_notifications', |
|
82 | + array('EED_Messages', 'maybe_registration'), 10, 2); |
|
83 | + //filters |
|
84 | + add_filter('FHEE__EE_Registration__receipt_url__receipt_url', |
|
85 | + array('EED_Messages', 'registration_message_trigger_url'), 10, 4); |
|
86 | + add_filter('FHEE__EE_Registration__invoice_url__invoice_url', |
|
87 | + array('EED_Messages', 'registration_message_trigger_url'), 10, 4); |
|
88 | + //register routes |
|
89 | + self::_register_routes(); |
|
90 | + } |
|
91 | + |
|
92 | + /** |
|
93 | + * set_hooks_admin - for hooking into EE Admin Core, other modules, etc |
|
94 | + * |
|
95 | + * @access public |
|
96 | + * @return void |
|
97 | + */ |
|
98 | + public static function set_hooks_admin() |
|
99 | + { |
|
100 | + //actions |
|
101 | + add_action('AHEE__EE_Payment_Processor__update_txn_based_on_payment', array('EED_Messages', 'payment'), 10, 2); |
|
102 | + add_action('AHEE__Transactions_Admin_Page___send_payment_reminder__process_admin_payment_reminder', |
|
103 | + array('EED_Messages', 'payment_reminder'), 10); |
|
104 | + add_action('AHEE__EE_Registration_Processor__trigger_registration_update_notifications', |
|
105 | + array('EED_Messages', 'maybe_registration'), 10, 3); |
|
106 | + add_action('AHEE__Extend_Registrations_Admin_Page___newsletter_selected_send__with_registrations', |
|
107 | + array('EED_Messages', 'send_newsletter_message'), 10, 2); |
|
108 | + add_action('AHEE__EES_Espresso_Cancelled__process_shortcode__transaction', |
|
109 | + array('EED_Messages', 'cancelled_registration'), 10); |
|
110 | + add_action('AHEE__EE_Admin_Page___process_admin_payment_notification', |
|
111 | + array('EED_Messages', 'process_admin_payment'), 10, 1); |
|
112 | + //filters |
|
113 | + add_filter('FHEE__EE_Admin_Page___process_resend_registration__success', |
|
114 | + array('EED_Messages', 'process_resend'), 10, 2); |
|
115 | + add_filter('FHEE__EE_Registration__receipt_url__receipt_url', |
|
116 | + array('EED_Messages', 'registration_message_trigger_url'), 10, 4); |
|
117 | + add_filter('FHEE__EE_Registration__invoice_url__invoice_url', |
|
118 | + array('EED_Messages', 'registration_message_trigger_url'), 10, 4); |
|
119 | + } |
|
120 | + |
|
121 | + |
|
122 | + /** |
|
123 | + * All the message triggers done by route go in here. |
|
124 | + * |
|
125 | + * @since 4.5.0 |
|
126 | + * @return void |
|
127 | + */ |
|
128 | + protected static function _register_routes() |
|
129 | + { |
|
130 | + EE_Config::register_route('msg_url_trigger', 'Messages', 'run'); |
|
131 | + EE_Config::register_route('msg_cron_trigger', 'Messages', 'execute_batch_request'); |
|
132 | + EE_Config::register_route('msg_browser_trigger', 'Messages', 'browser_trigger'); |
|
133 | + EE_Config::register_route('msg_browser_error_trigger', 'Messages', 'browser_error_trigger'); |
|
134 | + do_action('AHEE__EED_Messages___register_routes'); |
|
135 | + } |
|
136 | + |
|
137 | + |
|
138 | + /** |
|
139 | + * This is called when a browser display trigger is executed. |
|
140 | + * The browser display trigger is typically used when a already generated message is displayed directly in the |
|
141 | + * browser. |
|
142 | + * |
|
143 | + * @since 4.9.0 |
|
144 | + * @param WP $WP |
|
145 | + * @throws EE_Error |
|
146 | + * @throws InvalidArgumentException |
|
147 | + * @throws ReflectionException |
|
148 | + * @throws InvalidDataTypeException |
|
149 | + * @throws InvalidInterfaceException |
|
150 | + */ |
|
151 | + public function browser_trigger($WP) |
|
152 | + { |
|
153 | + //ensure controller is loaded |
|
154 | + self::_load_controller(); |
|
155 | + $token = EE_Registry::instance()->REQ->get('token'); |
|
156 | + try { |
|
157 | + $mtg = new EE_Message_Generated_From_Token($token, 'html', self::$_message_resource_manager); |
|
158 | + self::$_MSG_PROCESSOR->generate_and_send_now($mtg); |
|
159 | + } catch (EE_Error $e) { |
|
160 | + $error_msg = __('Please note that a system message failed to send due to a technical issue.', |
|
161 | + 'event_espresso'); |
|
162 | + // add specific message for developers if WP_DEBUG in on |
|
163 | + $error_msg .= '||' . $e->getMessage(); |
|
164 | + EE_Error::add_error($error_msg, __FILE__, __FUNCTION__, __LINE__); |
|
165 | + } |
|
166 | + } |
|
167 | + |
|
168 | + |
|
169 | + /** |
|
170 | + * This is called when a browser error trigger is executed. |
|
171 | + * When triggered this will grab the EE_Message matching the token in the request and use that to get the error |
|
172 | + * message and display it. |
|
173 | + * |
|
174 | + * @since 4.9.0 |
|
175 | + * @param $WP |
|
176 | + * @throws EE_Error |
|
177 | + * @throws InvalidArgumentException |
|
178 | + * @throws InvalidDataTypeException |
|
179 | + * @throws InvalidInterfaceException |
|
180 | + */ |
|
181 | + public function browser_error_trigger($WP) |
|
182 | + { |
|
183 | + $token = EE_Registry::instance()->REQ->get('token'); |
|
184 | + if ($token) { |
|
185 | + $message = EEM_Message::instance()->get_one_by_token($token); |
|
186 | + if ($message instanceof EE_Message) { |
|
187 | + header('HTTP/1.1 200 OK'); |
|
188 | + $error_msg = nl2br($message->error_message()); |
|
189 | + ?> |
|
190 | 190 | <!DOCTYPE html> |
191 | 191 | <html> |
192 | 192 | <head></head> |
193 | 193 | <body> |
194 | 194 | <?php echo empty($error_msg) |
195 | - ? esc_html__('Unfortunately, we were unable to capture the error message for this message.', |
|
196 | - 'event_espresso') |
|
197 | - : wp_kses( |
|
198 | - $error_msg, |
|
199 | - array( |
|
200 | - 'a' => array( |
|
201 | - 'href' => array(), |
|
202 | - 'title' => array(), |
|
203 | - ), |
|
204 | - 'span' => array(), |
|
205 | - 'div' => array(), |
|
206 | - 'p' => array(), |
|
207 | - 'strong' => array(), |
|
208 | - 'em' => array(), |
|
209 | - 'br' => array(), |
|
210 | - ) |
|
211 | - ); ?> |
|
195 | + ? esc_html__('Unfortunately, we were unable to capture the error message for this message.', |
|
196 | + 'event_espresso') |
|
197 | + : wp_kses( |
|
198 | + $error_msg, |
|
199 | + array( |
|
200 | + 'a' => array( |
|
201 | + 'href' => array(), |
|
202 | + 'title' => array(), |
|
203 | + ), |
|
204 | + 'span' => array(), |
|
205 | + 'div' => array(), |
|
206 | + 'p' => array(), |
|
207 | + 'strong' => array(), |
|
208 | + 'em' => array(), |
|
209 | + 'br' => array(), |
|
210 | + ) |
|
211 | + ); ?> |
|
212 | 212 | </body> |
213 | 213 | </html> |
214 | 214 | <?php |
215 | - exit; |
|
216 | - } |
|
217 | - } |
|
218 | - return; |
|
219 | - } |
|
220 | - |
|
221 | - |
|
222 | - /** |
|
223 | - * This runs when the msg_url_trigger route has initiated. |
|
224 | - * |
|
225 | - * @since 4.5.0 |
|
226 | - * @param WP $WP |
|
227 | - * @throws EE_Error |
|
228 | - * @throws InvalidArgumentException |
|
229 | - * @throws ReflectionException |
|
230 | - * @throws InvalidDataTypeException |
|
231 | - * @throws InvalidInterfaceException |
|
232 | - */ |
|
233 | - public function run($WP) |
|
234 | - { |
|
235 | - //ensure controller is loaded |
|
236 | - self::_load_controller(); |
|
237 | - // attempt to process message |
|
238 | - try { |
|
239 | - /** @type EE_Message_To_Generate_From_Request $message_to_generate */ |
|
240 | - $message_to_generate = EE_Registry::instance()->load_lib('Message_To_Generate_From_Request'); |
|
241 | - self::$_MSG_PROCESSOR->generate_and_send_now($message_to_generate); |
|
242 | - } catch (EE_Error $e) { |
|
243 | - $error_msg = __('Please note that a system message failed to send due to a technical issue.', |
|
244 | - 'event_espresso'); |
|
245 | - // add specific message for developers if WP_DEBUG in on |
|
246 | - $error_msg .= '||' . $e->getMessage(); |
|
247 | - EE_Error::add_error($error_msg, __FILE__, __FUNCTION__, __LINE__); |
|
248 | - } |
|
249 | - } |
|
250 | - |
|
251 | - |
|
252 | - /** |
|
253 | - * This is triggered by the 'msg_cron_trigger' route. |
|
254 | - * |
|
255 | - * @param WP $WP |
|
256 | - */ |
|
257 | - public function execute_batch_request($WP) |
|
258 | - { |
|
259 | - $this->run_cron(); |
|
260 | - header('HTTP/1.1 200 OK'); |
|
261 | - exit(); |
|
262 | - } |
|
263 | - |
|
264 | - |
|
265 | - /** |
|
266 | - * This gets executed on wp_cron jobs or when a batch request is initiated on its own separate non regular wp |
|
267 | - * request. |
|
268 | - */ |
|
269 | - public function run_cron() |
|
270 | - { |
|
271 | - self::_load_controller(); |
|
272 | - //get required vars |
|
273 | - $cron_type = EE_Registry::instance()->REQ->get('type'); |
|
274 | - $transient_key = EE_Registry::instance()->REQ->get('key'); |
|
275 | - |
|
276 | - //now let's verify transient, if not valid exit immediately |
|
277 | - if (! get_transient($transient_key)) { |
|
278 | - /** |
|
279 | - * trigger error so this gets in the error logs. This is important because it happens on a non-user |
|
280 | - * request. |
|
281 | - */ |
|
282 | - trigger_error(esc_attr__('Invalid Request (Transient does not exist)', 'event_espresso')); |
|
283 | - } |
|
284 | - |
|
285 | - //if made it here, lets' delete the transient to keep the db clean |
|
286 | - delete_transient($transient_key); |
|
287 | - |
|
288 | - if (apply_filters('FHEE__EED_Messages__run_cron__use_wp_cron', true)) { |
|
289 | - |
|
290 | - $method = 'batch_' . $cron_type . '_from_queue'; |
|
291 | - if (method_exists(self::$_MSG_PROCESSOR, $method)) { |
|
292 | - self::$_MSG_PROCESSOR->$method(); |
|
293 | - } else { |
|
294 | - //no matching task |
|
295 | - /** |
|
296 | - * trigger error so this gets in the error logs. This is important because it happens on a non user |
|
297 | - * request. |
|
298 | - */ |
|
299 | - trigger_error(esc_attr(sprintf(__('There is no task corresponding to this route %s', 'event_espresso'), |
|
300 | - $cron_type))); |
|
301 | - } |
|
302 | - } |
|
303 | - |
|
304 | - do_action('FHEE__EED_Messages__run_cron__end'); |
|
305 | - } |
|
306 | - |
|
307 | - |
|
308 | - /** |
|
309 | - * This is used to retrieve the template pack for the given name. |
|
310 | - * Retrieved packs are cached on the static $_TMP_PACKS array. If there is no class matching the given name then |
|
311 | - * the default template pack is returned. |
|
312 | - * |
|
313 | - * @deprecated 4.9.0 @see EEH_MSG_Template::get_template_pack() |
|
314 | - * @param string $template_pack_name This should correspond to the dbref of the template pack (which is also used |
|
315 | - * in generating the Pack class name). |
|
316 | - * @return EE_Messages_Template_Pack |
|
317 | - * @throws EE_Error |
|
318 | - * @throws InvalidArgumentException |
|
319 | - * @throws ReflectionException |
|
320 | - * @throws InvalidDataTypeException |
|
321 | - * @throws InvalidInterfaceException |
|
322 | - */ |
|
323 | - public static function get_template_pack($template_pack_name) |
|
324 | - { |
|
325 | - EE_Registry::instance()->load_helper('MSG_Template'); |
|
326 | - return EEH_MSG_Template::get_template_pack($template_pack_name); |
|
327 | - } |
|
328 | - |
|
329 | - |
|
330 | - /** |
|
331 | - * Retrieves an array of all template packs. |
|
332 | - * Array is in the format array( 'dbref' => EE_Messages_Template_Pack ) |
|
333 | - * |
|
334 | - * @deprecated 4.9.0 @see EEH_MSG_Template_Pack::get_template_pack_collection |
|
335 | - * @return EE_Messages_Template_Pack[] |
|
336 | - * @throws EE_Error |
|
337 | - * @throws InvalidArgumentException |
|
338 | - * @throws ReflectionException |
|
339 | - * @throws InvalidDataTypeException |
|
340 | - * @throws InvalidInterfaceException |
|
341 | - */ |
|
342 | - public static function get_template_packs() |
|
343 | - { |
|
344 | - EE_Registry::instance()->load_helper('MSG_Template'); |
|
345 | - |
|
346 | - //for backward compat, let's make sure this returns in the same format as originally. |
|
347 | - $template_pack_collection = EEH_MSG_Template::get_template_pack_collection(); |
|
348 | - $template_pack_collection->rewind(); |
|
349 | - $template_packs = array(); |
|
350 | - while ($template_pack_collection->valid()) { |
|
351 | - $template_packs[$template_pack_collection->current()->dbref] = $template_pack_collection->current(); |
|
352 | - $template_pack_collection->next(); |
|
353 | - } |
|
354 | - return $template_packs; |
|
355 | - } |
|
356 | - |
|
357 | - |
|
358 | - /** |
|
359 | - * This simply makes sure the autoloaders are registered for the EE_messages system. |
|
360 | - * |
|
361 | - * @since 4.5.0 |
|
362 | - * @return void |
|
363 | - * @throws EE_Error |
|
364 | - */ |
|
365 | - public static function set_autoloaders() |
|
366 | - { |
|
367 | - if (empty(self::$_MSG_PATHS)) { |
|
368 | - self::_set_messages_paths(); |
|
369 | - foreach (self::$_MSG_PATHS as $path) { |
|
370 | - EEH_Autoloader::register_autoloaders_for_each_file_in_folder($path); |
|
371 | - } |
|
372 | - // add aliases |
|
373 | - EEH_Autoloader::add_alias('EE_messages', 'EE_messages'); |
|
374 | - EEH_Autoloader::add_alias('EE_messenger', 'EE_messenger'); |
|
375 | - } |
|
376 | - } |
|
377 | - |
|
378 | - |
|
379 | - /** |
|
380 | - * Take care of adding all the paths for the messages components to the $_MSG_PATHS property |
|
381 | - * for use by the Messages Autoloaders |
|
382 | - * |
|
383 | - * @since 4.5.0 |
|
384 | - * @return void. |
|
385 | - */ |
|
386 | - protected static function _set_messages_paths() |
|
387 | - { |
|
388 | - $dir_ref = array( |
|
389 | - 'messages/message_type', |
|
390 | - 'messages/messenger', |
|
391 | - 'messages/defaults', |
|
392 | - 'messages/defaults/email', |
|
393 | - 'messages/data_class', |
|
394 | - 'messages/validators', |
|
395 | - 'messages/validators/email', |
|
396 | - 'messages/validators/html', |
|
397 | - 'shortcodes', |
|
398 | - ); |
|
399 | - $paths = array(); |
|
400 | - foreach ($dir_ref as $index => $dir) { |
|
401 | - $paths[$index] = EE_LIBRARIES . $dir; |
|
402 | - } |
|
403 | - self::$_MSG_PATHS = apply_filters('FHEE__EED_Messages___set_messages_paths___MSG_PATHS', $paths); |
|
404 | - } |
|
405 | - |
|
406 | - |
|
407 | - /** |
|
408 | - * Takes care of loading dependencies |
|
409 | - * |
|
410 | - * @since 4.5.0 |
|
411 | - * @return void |
|
412 | - * @throws EE_Error |
|
413 | - * @throws InvalidArgumentException |
|
414 | - * @throws ReflectionException |
|
415 | - * @throws InvalidDataTypeException |
|
416 | - * @throws InvalidInterfaceException |
|
417 | - */ |
|
418 | - protected static function _load_controller() |
|
419 | - { |
|
420 | - if (! self::$_MSG_PROCESSOR instanceof EE_Messages_Processor) { |
|
421 | - EE_Registry::instance()->load_core('Request_Handler'); |
|
422 | - self::set_autoloaders(); |
|
423 | - self::$_EEMSG = EE_Registry::instance()->load_lib('messages'); |
|
424 | - self::$_MSG_PROCESSOR = EE_Registry::instance()->load_lib('Messages_Processor'); |
|
425 | - self::$_message_resource_manager = EE_Registry::instance()->load_lib('Message_Resource_Manager'); |
|
426 | - } |
|
427 | - } |
|
428 | - |
|
429 | - |
|
430 | - /** |
|
431 | - * @param EE_Transaction $transaction |
|
432 | - * @throws EE_Error |
|
433 | - * @throws InvalidArgumentException |
|
434 | - * @throws InvalidDataTypeException |
|
435 | - * @throws InvalidInterfaceException |
|
436 | - * @throws ReflectionException |
|
437 | - */ |
|
438 | - public static function payment_reminder(EE_Transaction $transaction) |
|
439 | - { |
|
440 | - self::_load_controller(); |
|
441 | - $data = array($transaction, null); |
|
442 | - self::$_MSG_PROCESSOR->generate_for_all_active_messengers('payment_reminder', $data); |
|
443 | - } |
|
444 | - |
|
445 | - |
|
446 | - /** |
|
447 | - * Any messages triggers for after successful gateway payments should go in here. |
|
448 | - * |
|
449 | - * @param EE_Transaction $transaction object |
|
450 | - * @param EE_Payment|null $payment object |
|
451 | - * @return void |
|
452 | - * @throws EE_Error |
|
453 | - * @throws InvalidArgumentException |
|
454 | - * @throws ReflectionException |
|
455 | - * @throws InvalidDataTypeException |
|
456 | - * @throws InvalidInterfaceException |
|
457 | - */ |
|
458 | - public static function payment(EE_Transaction $transaction, EE_Payment $payment = null) |
|
459 | - { |
|
460 | - //if there's no payment object, then we cannot do a payment type message! |
|
461 | - if (! $payment instanceof EE_Payment) { |
|
462 | - return; |
|
463 | - } |
|
464 | - self::_load_controller(); |
|
465 | - $data = array($transaction, $payment); |
|
466 | - EE_Registry::instance()->load_helper('MSG_Template'); |
|
467 | - $message_type = EEH_MSG_Template::convert_payment_status_to_message_type($payment->STS_ID()); |
|
468 | - //if payment amount is less than 0 then switch to payment_refund message type. |
|
469 | - $message_type = $payment->amount() < 0 ? 'payment_refund' : $message_type; |
|
470 | - self::$_MSG_PROCESSOR->generate_for_all_active_messengers($message_type, $data); |
|
471 | - } |
|
472 | - |
|
473 | - |
|
474 | - /** |
|
475 | - * @param EE_Transaction $transaction |
|
476 | - * @throws EE_Error |
|
477 | - * @throws InvalidArgumentException |
|
478 | - * @throws InvalidDataTypeException |
|
479 | - * @throws InvalidInterfaceException |
|
480 | - * @throws ReflectionException |
|
481 | - */ |
|
482 | - public static function cancelled_registration(EE_Transaction $transaction) |
|
483 | - { |
|
484 | - self::_load_controller(); |
|
485 | - $data = array($transaction, null); |
|
486 | - self::$_MSG_PROCESSOR->generate_for_all_active_messengers('cancelled_registration', $data); |
|
487 | - } |
|
488 | - |
|
489 | - |
|
490 | - |
|
491 | - /** |
|
492 | - * Trigger for Registration messages |
|
493 | - * Note that what registration message type is sent depends on what the reg status is for the registrations on the |
|
494 | - * incoming transaction. |
|
495 | - * |
|
496 | - * @param EE_Registration $registration |
|
497 | - * @param array $extra_details |
|
498 | - * @return void |
|
499 | - * @throws EE_Error |
|
500 | - * @throws InvalidArgumentException |
|
501 | - * @throws InvalidDataTypeException |
|
502 | - * @throws InvalidInterfaceException |
|
503 | - * @throws ReflectionException |
|
504 | - * @throws EntityNotFoundException |
|
505 | - */ |
|
506 | - public static function maybe_registration(EE_Registration $registration, $extra_details = array()) |
|
507 | - { |
|
508 | - |
|
509 | - if (! self::_verify_registration_notification_send($registration, $extra_details)) { |
|
510 | - //no messages please |
|
511 | - return; |
|
512 | - } |
|
513 | - |
|
514 | - // get all non-trashed registrations so we make sure we send messages for the right status. |
|
515 | - $all_registrations = $registration->transaction()->registrations( |
|
516 | - array( |
|
517 | - array('REG_deleted' => false), |
|
518 | - 'order_by' => array( |
|
519 | - 'Event.EVT_name' => 'ASC', |
|
520 | - 'Attendee.ATT_lname' => 'ASC', |
|
521 | - 'Attendee.ATT_fname' => 'ASC' |
|
522 | - ) |
|
523 | - ) |
|
524 | - ); |
|
525 | - //cached array of statuses so we only trigger messages once per status. |
|
526 | - $statuses_sent = array(); |
|
527 | - self::_load_controller(); |
|
528 | - $mtgs = array(); |
|
529 | - |
|
530 | - //loop through registrations and trigger messages once per status. |
|
531 | - foreach ($all_registrations as $reg) { |
|
532 | - |
|
533 | - //already triggered? |
|
534 | - if (in_array($reg->status_ID(), $statuses_sent)) { |
|
535 | - continue; |
|
536 | - } |
|
537 | - |
|
538 | - $message_type = EEH_MSG_Template::convert_reg_status_to_message_type($reg->status_ID()); |
|
539 | - $mtgs = array_merge( |
|
540 | - $mtgs, |
|
541 | - self::$_MSG_PROCESSOR->setup_mtgs_for_all_active_messengers( |
|
542 | - $message_type, |
|
543 | - array($registration->transaction(), null, $reg->status_ID()) |
|
544 | - ) |
|
545 | - ); |
|
546 | - $statuses_sent[] = $reg->status_ID(); |
|
547 | - } |
|
548 | - |
|
549 | - if (count($statuses_sent) > 1) { |
|
550 | - $mtgs = array_merge( |
|
551 | - $mtgs, |
|
552 | - self::$_MSG_PROCESSOR->setup_mtgs_for_all_active_messengers( |
|
553 | - 'registration_summary', |
|
554 | - array($registration->transaction(), null) |
|
555 | - ) |
|
556 | - ); |
|
557 | - } |
|
558 | - |
|
559 | - //batch queue and initiate request |
|
560 | - self::$_MSG_PROCESSOR->batch_queue_for_generation_and_persist($mtgs); |
|
561 | - self::$_MSG_PROCESSOR->get_queue()->initiate_request_by_priority(); |
|
562 | - } |
|
563 | - |
|
564 | - |
|
565 | - /** |
|
566 | - * This is a helper method used to very whether a registration notification should be sent or |
|
567 | - * not. Prevents duplicate notifications going out for registration context notifications. |
|
568 | - * |
|
569 | - * @param EE_Registration $registration [description] |
|
570 | - * @param array $extra_details [description] |
|
571 | - * @return bool true = send away, false = nope halt the presses. |
|
572 | - */ |
|
573 | - protected static function _verify_registration_notification_send( |
|
574 | - EE_Registration $registration, |
|
575 | - $extra_details = array() |
|
576 | - ) { |
|
577 | - //self::log( |
|
578 | - // __CLASS__, __FUNCTION__, __LINE__, |
|
579 | - // $registration->transaction(), |
|
580 | - // array( '$extra_details' => $extra_details ) |
|
581 | - //); |
|
582 | - // currently only using this to send messages for the primary registrant |
|
583 | - if (! $registration->is_primary_registrant()) { |
|
584 | - return false; |
|
585 | - } |
|
586 | - // first we check if we're in admin and not doing front ajax |
|
587 | - if (is_admin() && ! EE_FRONT_AJAX) { |
|
588 | - //make sure appropriate admin params are set for sending messages |
|
589 | - if (empty($_REQUEST['txn_reg_status_change']['send_notifications']) || ! absint($_REQUEST['txn_reg_status_change']['send_notifications'])) { |
|
590 | - //no messages sent please. |
|
591 | - return false; |
|
592 | - } |
|
593 | - } else { |
|
594 | - // frontend request (either regular or via AJAX) |
|
595 | - // TXN is NOT finalized ? |
|
596 | - if (! isset($extra_details['finalized']) || $extra_details['finalized'] === false) { |
|
597 | - return false; |
|
598 | - } |
|
599 | - // return visit but nothing changed ??? |
|
600 | - if ( |
|
601 | - isset($extra_details['revisit'], $extra_details['status_updates']) && |
|
602 | - $extra_details['revisit'] && ! $extra_details['status_updates'] |
|
603 | - ) { |
|
604 | - return false; |
|
605 | - } |
|
606 | - // NOT sending messages && reg status is something other than "Not-Approved" |
|
607 | - if ( |
|
608 | - ! apply_filters('FHEE__EED_Messages___maybe_registration__deliver_notifications', false) && |
|
609 | - $registration->status_ID() !== EEM_Registration::status_id_not_approved |
|
610 | - ) { |
|
611 | - return false; |
|
612 | - } |
|
613 | - } |
|
614 | - // release the kraken |
|
615 | - return true; |
|
616 | - } |
|
617 | - |
|
618 | - |
|
619 | - /** |
|
620 | - * Simply returns an array indexed by Registration Status ID and the related message_type name associated with that |
|
621 | - * status id. |
|
622 | - * |
|
623 | - * @deprecated 4.9.0 Use EEH_MSG_Template::reg_status_to_message_type_array() |
|
624 | - * or EEH_MSG_Template::convert_reg_status_to_message_type |
|
625 | - * @param string $reg_status |
|
626 | - * @return array |
|
627 | - * @throws EE_Error |
|
628 | - * @throws InvalidArgumentException |
|
629 | - * @throws ReflectionException |
|
630 | - * @throws InvalidDataTypeException |
|
631 | - * @throws InvalidInterfaceException |
|
632 | - */ |
|
633 | - protected static function _get_reg_status_array($reg_status = '') |
|
634 | - { |
|
635 | - EE_Registry::instance()->load_helper('MSG_Template'); |
|
636 | - return EEH_MSG_Template::convert_reg_status_to_message_type($reg_status) |
|
637 | - ? EEH_MSG_Template::convert_reg_status_to_message_type($reg_status) |
|
638 | - : EEH_MSG_Template::reg_status_to_message_type_array(); |
|
639 | - } |
|
640 | - |
|
641 | - |
|
642 | - /** |
|
643 | - * Simply returns the payment message type for the given payment status. |
|
644 | - * |
|
645 | - * @deprecated 4.9.0 Use EEH_MSG_Template::payment_status_to_message_type_array |
|
646 | - * or EEH_MSG_Template::convert_payment_status_to_message_type |
|
647 | - * @param string $payment_status The payment status being matched. |
|
648 | - * @return bool|string The payment message type slug matching the status or false if no match. |
|
649 | - * @throws EE_Error |
|
650 | - * @throws InvalidArgumentException |
|
651 | - * @throws ReflectionException |
|
652 | - * @throws InvalidDataTypeException |
|
653 | - * @throws InvalidInterfaceException |
|
654 | - */ |
|
655 | - protected static function _get_payment_message_type($payment_status) |
|
656 | - { |
|
657 | - EE_Registry::instance()->load_helper('MSG_Template'); |
|
658 | - return EEH_MSG_Template::convert_payment_status_to_message_type($payment_status) |
|
659 | - ? EEH_MSG_Template::convert_payment_status_to_message_type($payment_status) |
|
660 | - : false; |
|
661 | - } |
|
662 | - |
|
663 | - |
|
664 | - /** |
|
665 | - * Message triggers for a resending already sent message(s) (via EE_Message list table) |
|
666 | - * |
|
667 | - * @access public |
|
668 | - * @param array $req_data This is the $_POST & $_GET data sent from EE_Admin Pages |
|
669 | - * @return bool success/fail |
|
670 | - * @throws EE_Error |
|
671 | - * @throws InvalidArgumentException |
|
672 | - * @throws InvalidDataTypeException |
|
673 | - * @throws InvalidInterfaceException |
|
674 | - * @throws ReflectionException |
|
675 | - */ |
|
676 | - public static function process_resend($req_data) |
|
677 | - { |
|
678 | - self::_load_controller(); |
|
679 | - |
|
680 | - //if $msgID in this request then skip to the new resend_message |
|
681 | - if (EE_Registry::instance()->REQ->get('MSG_ID')) { |
|
682 | - return self::resend_message(); |
|
683 | - } |
|
684 | - |
|
685 | - //make sure any incoming request data is set on the REQ so that it gets picked up later. |
|
686 | - $req_data = (array)$req_data; |
|
687 | - foreach ($req_data as $request_key => $request_value) { |
|
688 | - EE_Registry::instance()->REQ->set($request_key, $request_value); |
|
689 | - } |
|
690 | - |
|
691 | - if (! $messages_to_send = self::$_MSG_PROCESSOR->setup_messages_to_generate_from_registration_ids_in_request()) { |
|
692 | - return false; |
|
693 | - } |
|
694 | - |
|
695 | - try { |
|
696 | - self::$_MSG_PROCESSOR->batch_queue_for_generation_and_persist($messages_to_send); |
|
697 | - self::$_MSG_PROCESSOR->get_queue()->initiate_request_by_priority(); |
|
698 | - } catch (EE_Error $e) { |
|
699 | - EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__); |
|
700 | - return false; |
|
701 | - } |
|
702 | - EE_Error::add_success( |
|
703 | - __('Messages have been successfully queued for generation and sending.', 'event_espresso') |
|
704 | - ); |
|
705 | - return true; //everything got queued. |
|
706 | - } |
|
707 | - |
|
708 | - |
|
709 | - /** |
|
710 | - * Message triggers for a resending already sent message(s) (via EE_Message list table) |
|
711 | - * |
|
712 | - * @return bool |
|
713 | - * @throws EE_Error |
|
714 | - * @throws InvalidArgumentException |
|
715 | - * @throws InvalidDataTypeException |
|
716 | - * @throws InvalidInterfaceException |
|
717 | - * @throws ReflectionException |
|
718 | - */ |
|
719 | - public static function resend_message() |
|
720 | - { |
|
721 | - self::_load_controller(); |
|
722 | - |
|
723 | - $msgID = EE_Registry::instance()->REQ->get('MSG_ID'); |
|
724 | - if (! $msgID) { |
|
725 | - EE_Error::add_error(__('Something went wrong because there is no "MSG_ID" value in the request', |
|
726 | - 'event_espresso'), __FILE__, __FUNCTION__, __LINE__); |
|
727 | - return false; |
|
728 | - } |
|
729 | - |
|
730 | - self::$_MSG_PROCESSOR->setup_messages_from_ids_and_send((array)$msgID); |
|
731 | - |
|
732 | - //setup success message. |
|
733 | - $count_ready_for_resend = self::$_MSG_PROCESSOR->get_queue()->count_STS_in_queue(EEM_Message::status_resend); |
|
734 | - EE_Error::add_success(sprintf( |
|
735 | - _n( |
|
736 | - 'There was %d message queued for resending.', |
|
737 | - 'There were %d messages queued for resending.', |
|
738 | - $count_ready_for_resend, |
|
739 | - 'event_espresso' |
|
740 | - ), |
|
741 | - $count_ready_for_resend |
|
742 | - )); |
|
743 | - return true; |
|
744 | - } |
|
745 | - |
|
746 | - |
|
747 | - /** |
|
748 | - * Message triggers for manual payment applied by admin |
|
749 | - * |
|
750 | - * @param EE_Payment $payment EE_payment object |
|
751 | - * @return bool success/fail |
|
752 | - * @throws EE_Error |
|
753 | - * @throws InvalidArgumentException |
|
754 | - * @throws ReflectionException |
|
755 | - * @throws InvalidDataTypeException |
|
756 | - * @throws InvalidInterfaceException |
|
757 | - */ |
|
758 | - public static function process_admin_payment(EE_Payment $payment) |
|
759 | - { |
|
760 | - EE_Registry::instance()->load_helper('MSG_Template'); |
|
761 | - //we need to get the transaction object |
|
762 | - $transaction = $payment->transaction(); |
|
763 | - if ($transaction instanceof EE_Transaction) { |
|
764 | - $data = array($transaction, $payment); |
|
765 | - $message_type = EEH_MSG_Template::convert_payment_status_to_message_type($payment->STS_ID()); |
|
766 | - |
|
767 | - //if payment amount is less than 0 then switch to payment_refund message type. |
|
768 | - $message_type = $payment->amount() < 0 ? 'payment_refund' : $message_type; |
|
769 | - |
|
770 | - //if payment_refund is selected, but the status is NOT accepted. Then change message type to false so NO message notification goes out. |
|
771 | - $message_type = $message_type == 'payment_refund' && $payment->STS_ID() != EEM_Payment::status_id_approved ? false : $message_type; |
|
772 | - |
|
773 | - self::_load_controller(); |
|
774 | - |
|
775 | - self::$_MSG_PROCESSOR->generate_for_all_active_messengers($message_type, $data); |
|
776 | - |
|
777 | - //get count of queued for generation |
|
778 | - $count_to_generate = self::$_MSG_PROCESSOR->get_queue()->count_STS_in_queue(array( |
|
779 | - EEM_Message::status_incomplete, |
|
780 | - EEM_Message::status_idle, |
|
781 | - )); |
|
782 | - |
|
783 | - if ($count_to_generate > 0 && self::$_MSG_PROCESSOR->get_queue()->get_message_repository()->count() !== 0) { |
|
784 | - add_filter('FHEE__EE_Admin_Page___process_admin_payment_notification__success', '__return_true'); |
|
785 | - return true; |
|
786 | - } else { |
|
787 | - $count_failed = self::$_MSG_PROCESSOR->get_queue()->count_STS_in_queue(EEM_Message::instance()->stati_indicating_failed_sending()); |
|
788 | - /** |
|
789 | - * Verify that there are actually errors. If not then we return a success message because the queue might have been emptied due to successful |
|
790 | - * IMMEDIATE generation. |
|
791 | - */ |
|
792 | - if ($count_failed > 0) { |
|
793 | - EE_Error::add_error(sprintf( |
|
794 | - _n( |
|
795 | - 'The payment notification generation failed.', |
|
796 | - '%d payment notifications failed being sent.', |
|
797 | - $count_failed, |
|
798 | - 'event_espresso' |
|
799 | - ), |
|
800 | - $count_failed |
|
801 | - ), __FILE__, __FUNCTION__, __LINE__); |
|
802 | - |
|
803 | - return false; |
|
804 | - } else { |
|
805 | - add_filter('FHEE__EE_Admin_Page___process_admin_payment_notification__success', '__return_true'); |
|
806 | - return true; |
|
807 | - } |
|
808 | - } |
|
809 | - } else { |
|
810 | - EE_Error::add_error( |
|
811 | - 'Unable to generate the payment notification because the given value for the transaction is invalid.', |
|
812 | - 'event_espresso' |
|
813 | - ); |
|
814 | - return false; |
|
815 | - } |
|
816 | - } |
|
817 | - |
|
818 | - |
|
819 | - /** |
|
820 | - * Callback for AHEE__Extend_Registrations_Admin_Page___newsletter_selected_send_with_registrations trigger |
|
821 | - * |
|
822 | - * @since 4.3.0 |
|
823 | - * @param EE_Registration[] $registrations an array of EE_Registration objects |
|
824 | - * @param int $grp_id a specific message template group id. |
|
825 | - * @return void |
|
826 | - * @throws EE_Error |
|
827 | - * @throws InvalidArgumentException |
|
828 | - * @throws InvalidDataTypeException |
|
829 | - * @throws InvalidInterfaceException |
|
830 | - * @throws ReflectionException |
|
831 | - */ |
|
832 | - public static function send_newsletter_message($registrations, $grp_id) |
|
833 | - { |
|
834 | - //make sure mtp is id and set it in the EE_Request Handler later messages setup. |
|
835 | - EE_Registry::instance()->REQ->set('GRP_ID', (int)$grp_id); |
|
836 | - self::_load_controller(); |
|
837 | - self::$_MSG_PROCESSOR->generate_for_all_active_messengers('newsletter', $registrations); |
|
838 | - } |
|
839 | - |
|
840 | - |
|
841 | - /** |
|
842 | - * Callback for FHEE__EE_Registration__invoice_url__invoice_url or FHEE__EE_Registration__receipt_url__receipt_url |
|
843 | - * |
|
844 | - * @since 4.3.0 |
|
845 | - * @param string $registration_message_trigger_url |
|
846 | - * @param EE_Registration $registration |
|
847 | - * @param string $messenger |
|
848 | - * @param string $message_type |
|
849 | - * @return string |
|
850 | - * @throws EE_Error |
|
851 | - * @throws InvalidArgumentException |
|
852 | - * @throws InvalidDataTypeException |
|
853 | - * @throws InvalidInterfaceException |
|
854 | - */ |
|
855 | - public static function registration_message_trigger_url( |
|
856 | - $registration_message_trigger_url, |
|
857 | - EE_Registration $registration, |
|
858 | - $messenger = 'html', |
|
859 | - $message_type = 'invoice' |
|
860 | - ) { |
|
861 | - // whitelist $messenger |
|
862 | - switch ($messenger) { |
|
863 | - case 'pdf' : |
|
864 | - $sending_messenger = 'pdf'; |
|
865 | - $generating_messenger = 'html'; |
|
866 | - break; |
|
867 | - case 'html' : |
|
868 | - default : |
|
869 | - $sending_messenger = 'html'; |
|
870 | - $generating_messenger = 'html'; |
|
871 | - break; |
|
872 | - } |
|
873 | - // whitelist $message_type |
|
874 | - switch ($message_type) { |
|
875 | - case 'receipt' : |
|
876 | - $message_type = 'receipt'; |
|
877 | - break; |
|
878 | - case 'invoice' : |
|
879 | - default : |
|
880 | - $message_type = 'invoice'; |
|
881 | - break; |
|
882 | - } |
|
883 | - // verify that both the messenger AND the message type are active |
|
884 | - if (EEH_MSG_Template::is_messenger_active($sending_messenger) && EEH_MSG_Template::is_mt_active($message_type)) { |
|
885 | - //need to get the correct message template group for this (i.e. is there a custom invoice for the event this registration is registered for?) |
|
886 | - $template_query_params = array( |
|
887 | - 'MTP_is_active' => true, |
|
888 | - 'MTP_messenger' => $generating_messenger, |
|
889 | - 'MTP_message_type' => $message_type, |
|
890 | - 'Event.EVT_ID' => $registration->event_ID(), |
|
891 | - ); |
|
892 | - //get the message template group. |
|
893 | - $msg_template_group = EEM_Message_Template_Group::instance()->get_one(array($template_query_params)); |
|
894 | - //if we don't have an EE_Message_Template_Group then return |
|
895 | - if (! $msg_template_group instanceof EE_Message_Template_Group) { |
|
896 | - // remove EVT_ID from query params so that global templates get picked up |
|
897 | - unset($template_query_params['Event.EVT_ID']); |
|
898 | - //get global template as the fallback |
|
899 | - $msg_template_group = EEM_Message_Template_Group::instance()->get_one(array($template_query_params)); |
|
900 | - } |
|
901 | - //if we don't have an EE_Message_Template_Group then return |
|
902 | - if (! $msg_template_group instanceof EE_Message_Template_Group) { |
|
903 | - return ''; |
|
904 | - } |
|
905 | - // generate the URL |
|
906 | - $registration_message_trigger_url = EEH_MSG_Template::generate_url_trigger( |
|
907 | - $sending_messenger, |
|
908 | - $generating_messenger, |
|
909 | - 'purchaser', |
|
910 | - $message_type, |
|
911 | - $registration, |
|
912 | - $msg_template_group->ID(), |
|
913 | - $registration->transaction_ID() |
|
914 | - ); |
|
915 | - |
|
916 | - } |
|
917 | - return $registration_message_trigger_url; |
|
918 | - } |
|
919 | - |
|
920 | - |
|
921 | - /** |
|
922 | - * Use to generate and return a message preview! |
|
923 | - * |
|
924 | - * @param string $type This should correspond with a valid message type |
|
925 | - * @param string $context This should correspond with a valid context for the message type |
|
926 | - * @param string $messenger This should correspond with a valid messenger. |
|
927 | - * @param bool $send true we will do a test send using the messenger delivery, false we just do a regular |
|
928 | - * preview |
|
929 | - * @return bool|string The body of the message or if send is requested, sends. |
|
930 | - * @throws EE_Error |
|
931 | - * @throws InvalidArgumentException |
|
932 | - * @throws InvalidDataTypeException |
|
933 | - * @throws InvalidInterfaceException |
|
934 | - * @throws ReflectionException |
|
935 | - */ |
|
936 | - public static function preview_message($type, $context, $messenger, $send = false) |
|
937 | - { |
|
938 | - self::_load_controller(); |
|
939 | - $mtg = new EE_Message_To_Generate( |
|
940 | - $messenger, |
|
941 | - $type, |
|
942 | - array(), |
|
943 | - $context, |
|
944 | - true |
|
945 | - ); |
|
946 | - $generated_preview_queue = self::$_MSG_PROCESSOR->generate_for_preview($mtg, $send); |
|
947 | - if ($generated_preview_queue instanceof EE_Messages_Queue) { |
|
948 | - //loop through all content for the preview and remove any persisted records. |
|
949 | - $content = ''; |
|
950 | - foreach ($generated_preview_queue->get_message_repository() as $message) { |
|
951 | - $content = $message->content(); |
|
952 | - if ($message->ID() > 0 && $message->STS_ID() !== EEM_Message::status_failed) { |
|
953 | - $message->delete(); |
|
954 | - } |
|
955 | - } |
|
956 | - return $content; |
|
957 | - } else { |
|
958 | - return $generated_preview_queue; |
|
959 | - } |
|
960 | - } |
|
961 | - |
|
962 | - |
|
963 | - /** |
|
964 | - * This is a method that allows for sending a message using a messenger matching the string given and the provided |
|
965 | - * EE_Message_Queue object. The EE_Message_Queue object is used to create a single aggregate EE_Message via the |
|
966 | - * content found in the EE_Message objects in the queue. |
|
967 | - * |
|
968 | - * @since 4.9.0 |
|
969 | - * @param string $messenger a string matching a valid active messenger in the system |
|
970 | - * @param string $message_type Although it seems contrary to the name of the method, a message |
|
971 | - * type name is still required to send along the message type to the |
|
972 | - * messenger because this is used for determining what specific |
|
973 | - * variations might be loaded for the generated message. |
|
974 | - * @param EE_Messages_Queue $queue |
|
975 | - * @param string $custom_subject Can be used to set what the custom subject string will be on the |
|
976 | - * aggregate EE_Message object. |
|
977 | - * @return bool success or fail. |
|
978 | - * @throws EE_Error |
|
979 | - * @throws InvalidArgumentException |
|
980 | - * @throws ReflectionException |
|
981 | - * @throws InvalidDataTypeException |
|
982 | - * @throws InvalidInterfaceException |
|
983 | - */ |
|
984 | - public static function send_message_with_messenger_only( |
|
985 | - $messenger, |
|
986 | - $message_type, |
|
987 | - EE_Messages_Queue $queue, |
|
988 | - $custom_subject = '' |
|
989 | - ) { |
|
990 | - self::_load_controller(); |
|
991 | - /** @type EE_Message_To_Generate_From_Queue $message_to_generate */ |
|
992 | - $message_to_generate = EE_Registry::instance()->load_lib( |
|
993 | - 'Message_To_Generate_From_Queue', |
|
994 | - array( |
|
995 | - $messenger, |
|
996 | - $message_type, |
|
997 | - $queue, |
|
998 | - $custom_subject, |
|
999 | - ) |
|
1000 | - ); |
|
1001 | - return self::$_MSG_PROCESSOR->queue_for_sending($message_to_generate); |
|
1002 | - } |
|
1003 | - |
|
1004 | - |
|
1005 | - /** |
|
1006 | - * Generates Messages immediately for EE_Message IDs (but only for the correct status for generation) |
|
1007 | - * |
|
1008 | - * @since 4.9.0 |
|
1009 | - * @param array $message_ids An array of message ids |
|
1010 | - * @return bool|EE_Messages_Queue false if nothing was generated, EE_Messages_Queue containing generated |
|
1011 | - * messages. |
|
1012 | - * @throws EE_Error |
|
1013 | - * @throws InvalidArgumentException |
|
1014 | - * @throws InvalidDataTypeException |
|
1015 | - * @throws InvalidInterfaceException |
|
1016 | - * @throws ReflectionException |
|
1017 | - */ |
|
1018 | - public static function generate_now($message_ids) |
|
1019 | - { |
|
1020 | - self::_load_controller(); |
|
1021 | - $messages = EEM_Message::instance()->get_all( |
|
1022 | - array( |
|
1023 | - 0 => array( |
|
1024 | - 'MSG_ID' => array('IN', $message_ids), |
|
1025 | - 'STS_ID' => EEM_Message::status_incomplete, |
|
1026 | - ), |
|
1027 | - ) |
|
1028 | - ); |
|
1029 | - $generated_queue = false; |
|
1030 | - if ($messages) { |
|
1031 | - $generated_queue = self::$_MSG_PROCESSOR->batch_generate_from_queue($messages); |
|
1032 | - } |
|
1033 | - |
|
1034 | - if (! $generated_queue instanceof EE_Messages_Queue) { |
|
1035 | - EE_Error::add_error( |
|
1036 | - __('The messages were not generated. This could mean there is already a batch being generated on a separate request, or because the selected messages are not ready for generation. Please wait a minute or two and try again.', |
|
1037 | - 'event_espresso'), |
|
1038 | - __FILE__, __FUNCTION__, __LINE__ |
|
1039 | - ); |
|
1040 | - } |
|
1041 | - return $generated_queue; |
|
1042 | - } |
|
1043 | - |
|
1044 | - |
|
1045 | - /** |
|
1046 | - * Sends messages immediately for the incoming message_ids that have the status of EEM_Message::status_resend or, |
|
1047 | - * EEM_Message::status_idle |
|
1048 | - * |
|
1049 | - * @since 4.9.0 |
|
1050 | - * @param $message_ids |
|
1051 | - * @return bool|EE_Messages_Queue false if no messages sent. |
|
1052 | - * @throws EE_Error |
|
1053 | - * @throws InvalidArgumentException |
|
1054 | - * @throws InvalidDataTypeException |
|
1055 | - * @throws InvalidInterfaceException |
|
1056 | - * @throws ReflectionException |
|
1057 | - */ |
|
1058 | - public static function send_now($message_ids) |
|
1059 | - { |
|
1060 | - self::_load_controller(); |
|
1061 | - $messages = EEM_Message::instance()->get_all( |
|
1062 | - array( |
|
1063 | - 0 => array( |
|
1064 | - 'MSG_ID' => array('IN', $message_ids), |
|
1065 | - 'STS_ID' => array( |
|
1066 | - 'IN', |
|
1067 | - array(EEM_Message::status_idle, EEM_Message::status_resend, EEM_Message::status_retry), |
|
1068 | - ), |
|
1069 | - ), |
|
1070 | - ) |
|
1071 | - ); |
|
1072 | - $sent_queue = false; |
|
1073 | - if ($messages) { |
|
1074 | - $sent_queue = self::$_MSG_PROCESSOR->batch_send_from_queue($messages); |
|
1075 | - } |
|
1076 | - |
|
1077 | - if (! $sent_queue instanceof EE_Messages_Queue) { |
|
1078 | - EE_Error::add_error( |
|
1079 | - __('The messages were not sent. This could mean there is already a batch being sent on a separate request, or because the selected messages are not sendable. Please wait a minute or two and try again.', |
|
1080 | - 'event_espresso'), |
|
1081 | - __FILE__, __FUNCTION__, __LINE__ |
|
1082 | - ); |
|
1083 | - } else { |
|
1084 | - //can count how many sent by using the messages in the queue |
|
1085 | - $sent_count = $sent_queue->count_STS_in_queue(EEM_Message::instance()->stati_indicating_sent()); |
|
1086 | - if ($sent_count > 0) { |
|
1087 | - EE_Error::add_success( |
|
1088 | - sprintf( |
|
1089 | - _n( |
|
1090 | - 'There was %d message successfully sent.', |
|
1091 | - 'There were %d messages successfully sent.', |
|
1092 | - $sent_count, |
|
1093 | - 'event_espresso' |
|
1094 | - ), |
|
1095 | - $sent_count |
|
1096 | - ) |
|
1097 | - ); |
|
1098 | - } else { |
|
1099 | - EE_Error::overwrite_errors(); |
|
1100 | - EE_Error::add_error( |
|
1101 | - __('No message was sent because of problems with sending. Either all the messages you selected were not a sendable message, they were ALREADY sent on a different scheduled task, or there was an error. |
|
215 | + exit; |
|
216 | + } |
|
217 | + } |
|
218 | + return; |
|
219 | + } |
|
220 | + |
|
221 | + |
|
222 | + /** |
|
223 | + * This runs when the msg_url_trigger route has initiated. |
|
224 | + * |
|
225 | + * @since 4.5.0 |
|
226 | + * @param WP $WP |
|
227 | + * @throws EE_Error |
|
228 | + * @throws InvalidArgumentException |
|
229 | + * @throws ReflectionException |
|
230 | + * @throws InvalidDataTypeException |
|
231 | + * @throws InvalidInterfaceException |
|
232 | + */ |
|
233 | + public function run($WP) |
|
234 | + { |
|
235 | + //ensure controller is loaded |
|
236 | + self::_load_controller(); |
|
237 | + // attempt to process message |
|
238 | + try { |
|
239 | + /** @type EE_Message_To_Generate_From_Request $message_to_generate */ |
|
240 | + $message_to_generate = EE_Registry::instance()->load_lib('Message_To_Generate_From_Request'); |
|
241 | + self::$_MSG_PROCESSOR->generate_and_send_now($message_to_generate); |
|
242 | + } catch (EE_Error $e) { |
|
243 | + $error_msg = __('Please note that a system message failed to send due to a technical issue.', |
|
244 | + 'event_espresso'); |
|
245 | + // add specific message for developers if WP_DEBUG in on |
|
246 | + $error_msg .= '||' . $e->getMessage(); |
|
247 | + EE_Error::add_error($error_msg, __FILE__, __FUNCTION__, __LINE__); |
|
248 | + } |
|
249 | + } |
|
250 | + |
|
251 | + |
|
252 | + /** |
|
253 | + * This is triggered by the 'msg_cron_trigger' route. |
|
254 | + * |
|
255 | + * @param WP $WP |
|
256 | + */ |
|
257 | + public function execute_batch_request($WP) |
|
258 | + { |
|
259 | + $this->run_cron(); |
|
260 | + header('HTTP/1.1 200 OK'); |
|
261 | + exit(); |
|
262 | + } |
|
263 | + |
|
264 | + |
|
265 | + /** |
|
266 | + * This gets executed on wp_cron jobs or when a batch request is initiated on its own separate non regular wp |
|
267 | + * request. |
|
268 | + */ |
|
269 | + public function run_cron() |
|
270 | + { |
|
271 | + self::_load_controller(); |
|
272 | + //get required vars |
|
273 | + $cron_type = EE_Registry::instance()->REQ->get('type'); |
|
274 | + $transient_key = EE_Registry::instance()->REQ->get('key'); |
|
275 | + |
|
276 | + //now let's verify transient, if not valid exit immediately |
|
277 | + if (! get_transient($transient_key)) { |
|
278 | + /** |
|
279 | + * trigger error so this gets in the error logs. This is important because it happens on a non-user |
|
280 | + * request. |
|
281 | + */ |
|
282 | + trigger_error(esc_attr__('Invalid Request (Transient does not exist)', 'event_espresso')); |
|
283 | + } |
|
284 | + |
|
285 | + //if made it here, lets' delete the transient to keep the db clean |
|
286 | + delete_transient($transient_key); |
|
287 | + |
|
288 | + if (apply_filters('FHEE__EED_Messages__run_cron__use_wp_cron', true)) { |
|
289 | + |
|
290 | + $method = 'batch_' . $cron_type . '_from_queue'; |
|
291 | + if (method_exists(self::$_MSG_PROCESSOR, $method)) { |
|
292 | + self::$_MSG_PROCESSOR->$method(); |
|
293 | + } else { |
|
294 | + //no matching task |
|
295 | + /** |
|
296 | + * trigger error so this gets in the error logs. This is important because it happens on a non user |
|
297 | + * request. |
|
298 | + */ |
|
299 | + trigger_error(esc_attr(sprintf(__('There is no task corresponding to this route %s', 'event_espresso'), |
|
300 | + $cron_type))); |
|
301 | + } |
|
302 | + } |
|
303 | + |
|
304 | + do_action('FHEE__EED_Messages__run_cron__end'); |
|
305 | + } |
|
306 | + |
|
307 | + |
|
308 | + /** |
|
309 | + * This is used to retrieve the template pack for the given name. |
|
310 | + * Retrieved packs are cached on the static $_TMP_PACKS array. If there is no class matching the given name then |
|
311 | + * the default template pack is returned. |
|
312 | + * |
|
313 | + * @deprecated 4.9.0 @see EEH_MSG_Template::get_template_pack() |
|
314 | + * @param string $template_pack_name This should correspond to the dbref of the template pack (which is also used |
|
315 | + * in generating the Pack class name). |
|
316 | + * @return EE_Messages_Template_Pack |
|
317 | + * @throws EE_Error |
|
318 | + * @throws InvalidArgumentException |
|
319 | + * @throws ReflectionException |
|
320 | + * @throws InvalidDataTypeException |
|
321 | + * @throws InvalidInterfaceException |
|
322 | + */ |
|
323 | + public static function get_template_pack($template_pack_name) |
|
324 | + { |
|
325 | + EE_Registry::instance()->load_helper('MSG_Template'); |
|
326 | + return EEH_MSG_Template::get_template_pack($template_pack_name); |
|
327 | + } |
|
328 | + |
|
329 | + |
|
330 | + /** |
|
331 | + * Retrieves an array of all template packs. |
|
332 | + * Array is in the format array( 'dbref' => EE_Messages_Template_Pack ) |
|
333 | + * |
|
334 | + * @deprecated 4.9.0 @see EEH_MSG_Template_Pack::get_template_pack_collection |
|
335 | + * @return EE_Messages_Template_Pack[] |
|
336 | + * @throws EE_Error |
|
337 | + * @throws InvalidArgumentException |
|
338 | + * @throws ReflectionException |
|
339 | + * @throws InvalidDataTypeException |
|
340 | + * @throws InvalidInterfaceException |
|
341 | + */ |
|
342 | + public static function get_template_packs() |
|
343 | + { |
|
344 | + EE_Registry::instance()->load_helper('MSG_Template'); |
|
345 | + |
|
346 | + //for backward compat, let's make sure this returns in the same format as originally. |
|
347 | + $template_pack_collection = EEH_MSG_Template::get_template_pack_collection(); |
|
348 | + $template_pack_collection->rewind(); |
|
349 | + $template_packs = array(); |
|
350 | + while ($template_pack_collection->valid()) { |
|
351 | + $template_packs[$template_pack_collection->current()->dbref] = $template_pack_collection->current(); |
|
352 | + $template_pack_collection->next(); |
|
353 | + } |
|
354 | + return $template_packs; |
|
355 | + } |
|
356 | + |
|
357 | + |
|
358 | + /** |
|
359 | + * This simply makes sure the autoloaders are registered for the EE_messages system. |
|
360 | + * |
|
361 | + * @since 4.5.0 |
|
362 | + * @return void |
|
363 | + * @throws EE_Error |
|
364 | + */ |
|
365 | + public static function set_autoloaders() |
|
366 | + { |
|
367 | + if (empty(self::$_MSG_PATHS)) { |
|
368 | + self::_set_messages_paths(); |
|
369 | + foreach (self::$_MSG_PATHS as $path) { |
|
370 | + EEH_Autoloader::register_autoloaders_for_each_file_in_folder($path); |
|
371 | + } |
|
372 | + // add aliases |
|
373 | + EEH_Autoloader::add_alias('EE_messages', 'EE_messages'); |
|
374 | + EEH_Autoloader::add_alias('EE_messenger', 'EE_messenger'); |
|
375 | + } |
|
376 | + } |
|
377 | + |
|
378 | + |
|
379 | + /** |
|
380 | + * Take care of adding all the paths for the messages components to the $_MSG_PATHS property |
|
381 | + * for use by the Messages Autoloaders |
|
382 | + * |
|
383 | + * @since 4.5.0 |
|
384 | + * @return void. |
|
385 | + */ |
|
386 | + protected static function _set_messages_paths() |
|
387 | + { |
|
388 | + $dir_ref = array( |
|
389 | + 'messages/message_type', |
|
390 | + 'messages/messenger', |
|
391 | + 'messages/defaults', |
|
392 | + 'messages/defaults/email', |
|
393 | + 'messages/data_class', |
|
394 | + 'messages/validators', |
|
395 | + 'messages/validators/email', |
|
396 | + 'messages/validators/html', |
|
397 | + 'shortcodes', |
|
398 | + ); |
|
399 | + $paths = array(); |
|
400 | + foreach ($dir_ref as $index => $dir) { |
|
401 | + $paths[$index] = EE_LIBRARIES . $dir; |
|
402 | + } |
|
403 | + self::$_MSG_PATHS = apply_filters('FHEE__EED_Messages___set_messages_paths___MSG_PATHS', $paths); |
|
404 | + } |
|
405 | + |
|
406 | + |
|
407 | + /** |
|
408 | + * Takes care of loading dependencies |
|
409 | + * |
|
410 | + * @since 4.5.0 |
|
411 | + * @return void |
|
412 | + * @throws EE_Error |
|
413 | + * @throws InvalidArgumentException |
|
414 | + * @throws ReflectionException |
|
415 | + * @throws InvalidDataTypeException |
|
416 | + * @throws InvalidInterfaceException |
|
417 | + */ |
|
418 | + protected static function _load_controller() |
|
419 | + { |
|
420 | + if (! self::$_MSG_PROCESSOR instanceof EE_Messages_Processor) { |
|
421 | + EE_Registry::instance()->load_core('Request_Handler'); |
|
422 | + self::set_autoloaders(); |
|
423 | + self::$_EEMSG = EE_Registry::instance()->load_lib('messages'); |
|
424 | + self::$_MSG_PROCESSOR = EE_Registry::instance()->load_lib('Messages_Processor'); |
|
425 | + self::$_message_resource_manager = EE_Registry::instance()->load_lib('Message_Resource_Manager'); |
|
426 | + } |
|
427 | + } |
|
428 | + |
|
429 | + |
|
430 | + /** |
|
431 | + * @param EE_Transaction $transaction |
|
432 | + * @throws EE_Error |
|
433 | + * @throws InvalidArgumentException |
|
434 | + * @throws InvalidDataTypeException |
|
435 | + * @throws InvalidInterfaceException |
|
436 | + * @throws ReflectionException |
|
437 | + */ |
|
438 | + public static function payment_reminder(EE_Transaction $transaction) |
|
439 | + { |
|
440 | + self::_load_controller(); |
|
441 | + $data = array($transaction, null); |
|
442 | + self::$_MSG_PROCESSOR->generate_for_all_active_messengers('payment_reminder', $data); |
|
443 | + } |
|
444 | + |
|
445 | + |
|
446 | + /** |
|
447 | + * Any messages triggers for after successful gateway payments should go in here. |
|
448 | + * |
|
449 | + * @param EE_Transaction $transaction object |
|
450 | + * @param EE_Payment|null $payment object |
|
451 | + * @return void |
|
452 | + * @throws EE_Error |
|
453 | + * @throws InvalidArgumentException |
|
454 | + * @throws ReflectionException |
|
455 | + * @throws InvalidDataTypeException |
|
456 | + * @throws InvalidInterfaceException |
|
457 | + */ |
|
458 | + public static function payment(EE_Transaction $transaction, EE_Payment $payment = null) |
|
459 | + { |
|
460 | + //if there's no payment object, then we cannot do a payment type message! |
|
461 | + if (! $payment instanceof EE_Payment) { |
|
462 | + return; |
|
463 | + } |
|
464 | + self::_load_controller(); |
|
465 | + $data = array($transaction, $payment); |
|
466 | + EE_Registry::instance()->load_helper('MSG_Template'); |
|
467 | + $message_type = EEH_MSG_Template::convert_payment_status_to_message_type($payment->STS_ID()); |
|
468 | + //if payment amount is less than 0 then switch to payment_refund message type. |
|
469 | + $message_type = $payment->amount() < 0 ? 'payment_refund' : $message_type; |
|
470 | + self::$_MSG_PROCESSOR->generate_for_all_active_messengers($message_type, $data); |
|
471 | + } |
|
472 | + |
|
473 | + |
|
474 | + /** |
|
475 | + * @param EE_Transaction $transaction |
|
476 | + * @throws EE_Error |
|
477 | + * @throws InvalidArgumentException |
|
478 | + * @throws InvalidDataTypeException |
|
479 | + * @throws InvalidInterfaceException |
|
480 | + * @throws ReflectionException |
|
481 | + */ |
|
482 | + public static function cancelled_registration(EE_Transaction $transaction) |
|
483 | + { |
|
484 | + self::_load_controller(); |
|
485 | + $data = array($transaction, null); |
|
486 | + self::$_MSG_PROCESSOR->generate_for_all_active_messengers('cancelled_registration', $data); |
|
487 | + } |
|
488 | + |
|
489 | + |
|
490 | + |
|
491 | + /** |
|
492 | + * Trigger for Registration messages |
|
493 | + * Note that what registration message type is sent depends on what the reg status is for the registrations on the |
|
494 | + * incoming transaction. |
|
495 | + * |
|
496 | + * @param EE_Registration $registration |
|
497 | + * @param array $extra_details |
|
498 | + * @return void |
|
499 | + * @throws EE_Error |
|
500 | + * @throws InvalidArgumentException |
|
501 | + * @throws InvalidDataTypeException |
|
502 | + * @throws InvalidInterfaceException |
|
503 | + * @throws ReflectionException |
|
504 | + * @throws EntityNotFoundException |
|
505 | + */ |
|
506 | + public static function maybe_registration(EE_Registration $registration, $extra_details = array()) |
|
507 | + { |
|
508 | + |
|
509 | + if (! self::_verify_registration_notification_send($registration, $extra_details)) { |
|
510 | + //no messages please |
|
511 | + return; |
|
512 | + } |
|
513 | + |
|
514 | + // get all non-trashed registrations so we make sure we send messages for the right status. |
|
515 | + $all_registrations = $registration->transaction()->registrations( |
|
516 | + array( |
|
517 | + array('REG_deleted' => false), |
|
518 | + 'order_by' => array( |
|
519 | + 'Event.EVT_name' => 'ASC', |
|
520 | + 'Attendee.ATT_lname' => 'ASC', |
|
521 | + 'Attendee.ATT_fname' => 'ASC' |
|
522 | + ) |
|
523 | + ) |
|
524 | + ); |
|
525 | + //cached array of statuses so we only trigger messages once per status. |
|
526 | + $statuses_sent = array(); |
|
527 | + self::_load_controller(); |
|
528 | + $mtgs = array(); |
|
529 | + |
|
530 | + //loop through registrations and trigger messages once per status. |
|
531 | + foreach ($all_registrations as $reg) { |
|
532 | + |
|
533 | + //already triggered? |
|
534 | + if (in_array($reg->status_ID(), $statuses_sent)) { |
|
535 | + continue; |
|
536 | + } |
|
537 | + |
|
538 | + $message_type = EEH_MSG_Template::convert_reg_status_to_message_type($reg->status_ID()); |
|
539 | + $mtgs = array_merge( |
|
540 | + $mtgs, |
|
541 | + self::$_MSG_PROCESSOR->setup_mtgs_for_all_active_messengers( |
|
542 | + $message_type, |
|
543 | + array($registration->transaction(), null, $reg->status_ID()) |
|
544 | + ) |
|
545 | + ); |
|
546 | + $statuses_sent[] = $reg->status_ID(); |
|
547 | + } |
|
548 | + |
|
549 | + if (count($statuses_sent) > 1) { |
|
550 | + $mtgs = array_merge( |
|
551 | + $mtgs, |
|
552 | + self::$_MSG_PROCESSOR->setup_mtgs_for_all_active_messengers( |
|
553 | + 'registration_summary', |
|
554 | + array($registration->transaction(), null) |
|
555 | + ) |
|
556 | + ); |
|
557 | + } |
|
558 | + |
|
559 | + //batch queue and initiate request |
|
560 | + self::$_MSG_PROCESSOR->batch_queue_for_generation_and_persist($mtgs); |
|
561 | + self::$_MSG_PROCESSOR->get_queue()->initiate_request_by_priority(); |
|
562 | + } |
|
563 | + |
|
564 | + |
|
565 | + /** |
|
566 | + * This is a helper method used to very whether a registration notification should be sent or |
|
567 | + * not. Prevents duplicate notifications going out for registration context notifications. |
|
568 | + * |
|
569 | + * @param EE_Registration $registration [description] |
|
570 | + * @param array $extra_details [description] |
|
571 | + * @return bool true = send away, false = nope halt the presses. |
|
572 | + */ |
|
573 | + protected static function _verify_registration_notification_send( |
|
574 | + EE_Registration $registration, |
|
575 | + $extra_details = array() |
|
576 | + ) { |
|
577 | + //self::log( |
|
578 | + // __CLASS__, __FUNCTION__, __LINE__, |
|
579 | + // $registration->transaction(), |
|
580 | + // array( '$extra_details' => $extra_details ) |
|
581 | + //); |
|
582 | + // currently only using this to send messages for the primary registrant |
|
583 | + if (! $registration->is_primary_registrant()) { |
|
584 | + return false; |
|
585 | + } |
|
586 | + // first we check if we're in admin and not doing front ajax |
|
587 | + if (is_admin() && ! EE_FRONT_AJAX) { |
|
588 | + //make sure appropriate admin params are set for sending messages |
|
589 | + if (empty($_REQUEST['txn_reg_status_change']['send_notifications']) || ! absint($_REQUEST['txn_reg_status_change']['send_notifications'])) { |
|
590 | + //no messages sent please. |
|
591 | + return false; |
|
592 | + } |
|
593 | + } else { |
|
594 | + // frontend request (either regular or via AJAX) |
|
595 | + // TXN is NOT finalized ? |
|
596 | + if (! isset($extra_details['finalized']) || $extra_details['finalized'] === false) { |
|
597 | + return false; |
|
598 | + } |
|
599 | + // return visit but nothing changed ??? |
|
600 | + if ( |
|
601 | + isset($extra_details['revisit'], $extra_details['status_updates']) && |
|
602 | + $extra_details['revisit'] && ! $extra_details['status_updates'] |
|
603 | + ) { |
|
604 | + return false; |
|
605 | + } |
|
606 | + // NOT sending messages && reg status is something other than "Not-Approved" |
|
607 | + if ( |
|
608 | + ! apply_filters('FHEE__EED_Messages___maybe_registration__deliver_notifications', false) && |
|
609 | + $registration->status_ID() !== EEM_Registration::status_id_not_approved |
|
610 | + ) { |
|
611 | + return false; |
|
612 | + } |
|
613 | + } |
|
614 | + // release the kraken |
|
615 | + return true; |
|
616 | + } |
|
617 | + |
|
618 | + |
|
619 | + /** |
|
620 | + * Simply returns an array indexed by Registration Status ID and the related message_type name associated with that |
|
621 | + * status id. |
|
622 | + * |
|
623 | + * @deprecated 4.9.0 Use EEH_MSG_Template::reg_status_to_message_type_array() |
|
624 | + * or EEH_MSG_Template::convert_reg_status_to_message_type |
|
625 | + * @param string $reg_status |
|
626 | + * @return array |
|
627 | + * @throws EE_Error |
|
628 | + * @throws InvalidArgumentException |
|
629 | + * @throws ReflectionException |
|
630 | + * @throws InvalidDataTypeException |
|
631 | + * @throws InvalidInterfaceException |
|
632 | + */ |
|
633 | + protected static function _get_reg_status_array($reg_status = '') |
|
634 | + { |
|
635 | + EE_Registry::instance()->load_helper('MSG_Template'); |
|
636 | + return EEH_MSG_Template::convert_reg_status_to_message_type($reg_status) |
|
637 | + ? EEH_MSG_Template::convert_reg_status_to_message_type($reg_status) |
|
638 | + : EEH_MSG_Template::reg_status_to_message_type_array(); |
|
639 | + } |
|
640 | + |
|
641 | + |
|
642 | + /** |
|
643 | + * Simply returns the payment message type for the given payment status. |
|
644 | + * |
|
645 | + * @deprecated 4.9.0 Use EEH_MSG_Template::payment_status_to_message_type_array |
|
646 | + * or EEH_MSG_Template::convert_payment_status_to_message_type |
|
647 | + * @param string $payment_status The payment status being matched. |
|
648 | + * @return bool|string The payment message type slug matching the status or false if no match. |
|
649 | + * @throws EE_Error |
|
650 | + * @throws InvalidArgumentException |
|
651 | + * @throws ReflectionException |
|
652 | + * @throws InvalidDataTypeException |
|
653 | + * @throws InvalidInterfaceException |
|
654 | + */ |
|
655 | + protected static function _get_payment_message_type($payment_status) |
|
656 | + { |
|
657 | + EE_Registry::instance()->load_helper('MSG_Template'); |
|
658 | + return EEH_MSG_Template::convert_payment_status_to_message_type($payment_status) |
|
659 | + ? EEH_MSG_Template::convert_payment_status_to_message_type($payment_status) |
|
660 | + : false; |
|
661 | + } |
|
662 | + |
|
663 | + |
|
664 | + /** |
|
665 | + * Message triggers for a resending already sent message(s) (via EE_Message list table) |
|
666 | + * |
|
667 | + * @access public |
|
668 | + * @param array $req_data This is the $_POST & $_GET data sent from EE_Admin Pages |
|
669 | + * @return bool success/fail |
|
670 | + * @throws EE_Error |
|
671 | + * @throws InvalidArgumentException |
|
672 | + * @throws InvalidDataTypeException |
|
673 | + * @throws InvalidInterfaceException |
|
674 | + * @throws ReflectionException |
|
675 | + */ |
|
676 | + public static function process_resend($req_data) |
|
677 | + { |
|
678 | + self::_load_controller(); |
|
679 | + |
|
680 | + //if $msgID in this request then skip to the new resend_message |
|
681 | + if (EE_Registry::instance()->REQ->get('MSG_ID')) { |
|
682 | + return self::resend_message(); |
|
683 | + } |
|
684 | + |
|
685 | + //make sure any incoming request data is set on the REQ so that it gets picked up later. |
|
686 | + $req_data = (array)$req_data; |
|
687 | + foreach ($req_data as $request_key => $request_value) { |
|
688 | + EE_Registry::instance()->REQ->set($request_key, $request_value); |
|
689 | + } |
|
690 | + |
|
691 | + if (! $messages_to_send = self::$_MSG_PROCESSOR->setup_messages_to_generate_from_registration_ids_in_request()) { |
|
692 | + return false; |
|
693 | + } |
|
694 | + |
|
695 | + try { |
|
696 | + self::$_MSG_PROCESSOR->batch_queue_for_generation_and_persist($messages_to_send); |
|
697 | + self::$_MSG_PROCESSOR->get_queue()->initiate_request_by_priority(); |
|
698 | + } catch (EE_Error $e) { |
|
699 | + EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__); |
|
700 | + return false; |
|
701 | + } |
|
702 | + EE_Error::add_success( |
|
703 | + __('Messages have been successfully queued for generation and sending.', 'event_espresso') |
|
704 | + ); |
|
705 | + return true; //everything got queued. |
|
706 | + } |
|
707 | + |
|
708 | + |
|
709 | + /** |
|
710 | + * Message triggers for a resending already sent message(s) (via EE_Message list table) |
|
711 | + * |
|
712 | + * @return bool |
|
713 | + * @throws EE_Error |
|
714 | + * @throws InvalidArgumentException |
|
715 | + * @throws InvalidDataTypeException |
|
716 | + * @throws InvalidInterfaceException |
|
717 | + * @throws ReflectionException |
|
718 | + */ |
|
719 | + public static function resend_message() |
|
720 | + { |
|
721 | + self::_load_controller(); |
|
722 | + |
|
723 | + $msgID = EE_Registry::instance()->REQ->get('MSG_ID'); |
|
724 | + if (! $msgID) { |
|
725 | + EE_Error::add_error(__('Something went wrong because there is no "MSG_ID" value in the request', |
|
726 | + 'event_espresso'), __FILE__, __FUNCTION__, __LINE__); |
|
727 | + return false; |
|
728 | + } |
|
729 | + |
|
730 | + self::$_MSG_PROCESSOR->setup_messages_from_ids_and_send((array)$msgID); |
|
731 | + |
|
732 | + //setup success message. |
|
733 | + $count_ready_for_resend = self::$_MSG_PROCESSOR->get_queue()->count_STS_in_queue(EEM_Message::status_resend); |
|
734 | + EE_Error::add_success(sprintf( |
|
735 | + _n( |
|
736 | + 'There was %d message queued for resending.', |
|
737 | + 'There were %d messages queued for resending.', |
|
738 | + $count_ready_for_resend, |
|
739 | + 'event_espresso' |
|
740 | + ), |
|
741 | + $count_ready_for_resend |
|
742 | + )); |
|
743 | + return true; |
|
744 | + } |
|
745 | + |
|
746 | + |
|
747 | + /** |
|
748 | + * Message triggers for manual payment applied by admin |
|
749 | + * |
|
750 | + * @param EE_Payment $payment EE_payment object |
|
751 | + * @return bool success/fail |
|
752 | + * @throws EE_Error |
|
753 | + * @throws InvalidArgumentException |
|
754 | + * @throws ReflectionException |
|
755 | + * @throws InvalidDataTypeException |
|
756 | + * @throws InvalidInterfaceException |
|
757 | + */ |
|
758 | + public static function process_admin_payment(EE_Payment $payment) |
|
759 | + { |
|
760 | + EE_Registry::instance()->load_helper('MSG_Template'); |
|
761 | + //we need to get the transaction object |
|
762 | + $transaction = $payment->transaction(); |
|
763 | + if ($transaction instanceof EE_Transaction) { |
|
764 | + $data = array($transaction, $payment); |
|
765 | + $message_type = EEH_MSG_Template::convert_payment_status_to_message_type($payment->STS_ID()); |
|
766 | + |
|
767 | + //if payment amount is less than 0 then switch to payment_refund message type. |
|
768 | + $message_type = $payment->amount() < 0 ? 'payment_refund' : $message_type; |
|
769 | + |
|
770 | + //if payment_refund is selected, but the status is NOT accepted. Then change message type to false so NO message notification goes out. |
|
771 | + $message_type = $message_type == 'payment_refund' && $payment->STS_ID() != EEM_Payment::status_id_approved ? false : $message_type; |
|
772 | + |
|
773 | + self::_load_controller(); |
|
774 | + |
|
775 | + self::$_MSG_PROCESSOR->generate_for_all_active_messengers($message_type, $data); |
|
776 | + |
|
777 | + //get count of queued for generation |
|
778 | + $count_to_generate = self::$_MSG_PROCESSOR->get_queue()->count_STS_in_queue(array( |
|
779 | + EEM_Message::status_incomplete, |
|
780 | + EEM_Message::status_idle, |
|
781 | + )); |
|
782 | + |
|
783 | + if ($count_to_generate > 0 && self::$_MSG_PROCESSOR->get_queue()->get_message_repository()->count() !== 0) { |
|
784 | + add_filter('FHEE__EE_Admin_Page___process_admin_payment_notification__success', '__return_true'); |
|
785 | + return true; |
|
786 | + } else { |
|
787 | + $count_failed = self::$_MSG_PROCESSOR->get_queue()->count_STS_in_queue(EEM_Message::instance()->stati_indicating_failed_sending()); |
|
788 | + /** |
|
789 | + * Verify that there are actually errors. If not then we return a success message because the queue might have been emptied due to successful |
|
790 | + * IMMEDIATE generation. |
|
791 | + */ |
|
792 | + if ($count_failed > 0) { |
|
793 | + EE_Error::add_error(sprintf( |
|
794 | + _n( |
|
795 | + 'The payment notification generation failed.', |
|
796 | + '%d payment notifications failed being sent.', |
|
797 | + $count_failed, |
|
798 | + 'event_espresso' |
|
799 | + ), |
|
800 | + $count_failed |
|
801 | + ), __FILE__, __FUNCTION__, __LINE__); |
|
802 | + |
|
803 | + return false; |
|
804 | + } else { |
|
805 | + add_filter('FHEE__EE_Admin_Page___process_admin_payment_notification__success', '__return_true'); |
|
806 | + return true; |
|
807 | + } |
|
808 | + } |
|
809 | + } else { |
|
810 | + EE_Error::add_error( |
|
811 | + 'Unable to generate the payment notification because the given value for the transaction is invalid.', |
|
812 | + 'event_espresso' |
|
813 | + ); |
|
814 | + return false; |
|
815 | + } |
|
816 | + } |
|
817 | + |
|
818 | + |
|
819 | + /** |
|
820 | + * Callback for AHEE__Extend_Registrations_Admin_Page___newsletter_selected_send_with_registrations trigger |
|
821 | + * |
|
822 | + * @since 4.3.0 |
|
823 | + * @param EE_Registration[] $registrations an array of EE_Registration objects |
|
824 | + * @param int $grp_id a specific message template group id. |
|
825 | + * @return void |
|
826 | + * @throws EE_Error |
|
827 | + * @throws InvalidArgumentException |
|
828 | + * @throws InvalidDataTypeException |
|
829 | + * @throws InvalidInterfaceException |
|
830 | + * @throws ReflectionException |
|
831 | + */ |
|
832 | + public static function send_newsletter_message($registrations, $grp_id) |
|
833 | + { |
|
834 | + //make sure mtp is id and set it in the EE_Request Handler later messages setup. |
|
835 | + EE_Registry::instance()->REQ->set('GRP_ID', (int)$grp_id); |
|
836 | + self::_load_controller(); |
|
837 | + self::$_MSG_PROCESSOR->generate_for_all_active_messengers('newsletter', $registrations); |
|
838 | + } |
|
839 | + |
|
840 | + |
|
841 | + /** |
|
842 | + * Callback for FHEE__EE_Registration__invoice_url__invoice_url or FHEE__EE_Registration__receipt_url__receipt_url |
|
843 | + * |
|
844 | + * @since 4.3.0 |
|
845 | + * @param string $registration_message_trigger_url |
|
846 | + * @param EE_Registration $registration |
|
847 | + * @param string $messenger |
|
848 | + * @param string $message_type |
|
849 | + * @return string |
|
850 | + * @throws EE_Error |
|
851 | + * @throws InvalidArgumentException |
|
852 | + * @throws InvalidDataTypeException |
|
853 | + * @throws InvalidInterfaceException |
|
854 | + */ |
|
855 | + public static function registration_message_trigger_url( |
|
856 | + $registration_message_trigger_url, |
|
857 | + EE_Registration $registration, |
|
858 | + $messenger = 'html', |
|
859 | + $message_type = 'invoice' |
|
860 | + ) { |
|
861 | + // whitelist $messenger |
|
862 | + switch ($messenger) { |
|
863 | + case 'pdf' : |
|
864 | + $sending_messenger = 'pdf'; |
|
865 | + $generating_messenger = 'html'; |
|
866 | + break; |
|
867 | + case 'html' : |
|
868 | + default : |
|
869 | + $sending_messenger = 'html'; |
|
870 | + $generating_messenger = 'html'; |
|
871 | + break; |
|
872 | + } |
|
873 | + // whitelist $message_type |
|
874 | + switch ($message_type) { |
|
875 | + case 'receipt' : |
|
876 | + $message_type = 'receipt'; |
|
877 | + break; |
|
878 | + case 'invoice' : |
|
879 | + default : |
|
880 | + $message_type = 'invoice'; |
|
881 | + break; |
|
882 | + } |
|
883 | + // verify that both the messenger AND the message type are active |
|
884 | + if (EEH_MSG_Template::is_messenger_active($sending_messenger) && EEH_MSG_Template::is_mt_active($message_type)) { |
|
885 | + //need to get the correct message template group for this (i.e. is there a custom invoice for the event this registration is registered for?) |
|
886 | + $template_query_params = array( |
|
887 | + 'MTP_is_active' => true, |
|
888 | + 'MTP_messenger' => $generating_messenger, |
|
889 | + 'MTP_message_type' => $message_type, |
|
890 | + 'Event.EVT_ID' => $registration->event_ID(), |
|
891 | + ); |
|
892 | + //get the message template group. |
|
893 | + $msg_template_group = EEM_Message_Template_Group::instance()->get_one(array($template_query_params)); |
|
894 | + //if we don't have an EE_Message_Template_Group then return |
|
895 | + if (! $msg_template_group instanceof EE_Message_Template_Group) { |
|
896 | + // remove EVT_ID from query params so that global templates get picked up |
|
897 | + unset($template_query_params['Event.EVT_ID']); |
|
898 | + //get global template as the fallback |
|
899 | + $msg_template_group = EEM_Message_Template_Group::instance()->get_one(array($template_query_params)); |
|
900 | + } |
|
901 | + //if we don't have an EE_Message_Template_Group then return |
|
902 | + if (! $msg_template_group instanceof EE_Message_Template_Group) { |
|
903 | + return ''; |
|
904 | + } |
|
905 | + // generate the URL |
|
906 | + $registration_message_trigger_url = EEH_MSG_Template::generate_url_trigger( |
|
907 | + $sending_messenger, |
|
908 | + $generating_messenger, |
|
909 | + 'purchaser', |
|
910 | + $message_type, |
|
911 | + $registration, |
|
912 | + $msg_template_group->ID(), |
|
913 | + $registration->transaction_ID() |
|
914 | + ); |
|
915 | + |
|
916 | + } |
|
917 | + return $registration_message_trigger_url; |
|
918 | + } |
|
919 | + |
|
920 | + |
|
921 | + /** |
|
922 | + * Use to generate and return a message preview! |
|
923 | + * |
|
924 | + * @param string $type This should correspond with a valid message type |
|
925 | + * @param string $context This should correspond with a valid context for the message type |
|
926 | + * @param string $messenger This should correspond with a valid messenger. |
|
927 | + * @param bool $send true we will do a test send using the messenger delivery, false we just do a regular |
|
928 | + * preview |
|
929 | + * @return bool|string The body of the message or if send is requested, sends. |
|
930 | + * @throws EE_Error |
|
931 | + * @throws InvalidArgumentException |
|
932 | + * @throws InvalidDataTypeException |
|
933 | + * @throws InvalidInterfaceException |
|
934 | + * @throws ReflectionException |
|
935 | + */ |
|
936 | + public static function preview_message($type, $context, $messenger, $send = false) |
|
937 | + { |
|
938 | + self::_load_controller(); |
|
939 | + $mtg = new EE_Message_To_Generate( |
|
940 | + $messenger, |
|
941 | + $type, |
|
942 | + array(), |
|
943 | + $context, |
|
944 | + true |
|
945 | + ); |
|
946 | + $generated_preview_queue = self::$_MSG_PROCESSOR->generate_for_preview($mtg, $send); |
|
947 | + if ($generated_preview_queue instanceof EE_Messages_Queue) { |
|
948 | + //loop through all content for the preview and remove any persisted records. |
|
949 | + $content = ''; |
|
950 | + foreach ($generated_preview_queue->get_message_repository() as $message) { |
|
951 | + $content = $message->content(); |
|
952 | + if ($message->ID() > 0 && $message->STS_ID() !== EEM_Message::status_failed) { |
|
953 | + $message->delete(); |
|
954 | + } |
|
955 | + } |
|
956 | + return $content; |
|
957 | + } else { |
|
958 | + return $generated_preview_queue; |
|
959 | + } |
|
960 | + } |
|
961 | + |
|
962 | + |
|
963 | + /** |
|
964 | + * This is a method that allows for sending a message using a messenger matching the string given and the provided |
|
965 | + * EE_Message_Queue object. The EE_Message_Queue object is used to create a single aggregate EE_Message via the |
|
966 | + * content found in the EE_Message objects in the queue. |
|
967 | + * |
|
968 | + * @since 4.9.0 |
|
969 | + * @param string $messenger a string matching a valid active messenger in the system |
|
970 | + * @param string $message_type Although it seems contrary to the name of the method, a message |
|
971 | + * type name is still required to send along the message type to the |
|
972 | + * messenger because this is used for determining what specific |
|
973 | + * variations might be loaded for the generated message. |
|
974 | + * @param EE_Messages_Queue $queue |
|
975 | + * @param string $custom_subject Can be used to set what the custom subject string will be on the |
|
976 | + * aggregate EE_Message object. |
|
977 | + * @return bool success or fail. |
|
978 | + * @throws EE_Error |
|
979 | + * @throws InvalidArgumentException |
|
980 | + * @throws ReflectionException |
|
981 | + * @throws InvalidDataTypeException |
|
982 | + * @throws InvalidInterfaceException |
|
983 | + */ |
|
984 | + public static function send_message_with_messenger_only( |
|
985 | + $messenger, |
|
986 | + $message_type, |
|
987 | + EE_Messages_Queue $queue, |
|
988 | + $custom_subject = '' |
|
989 | + ) { |
|
990 | + self::_load_controller(); |
|
991 | + /** @type EE_Message_To_Generate_From_Queue $message_to_generate */ |
|
992 | + $message_to_generate = EE_Registry::instance()->load_lib( |
|
993 | + 'Message_To_Generate_From_Queue', |
|
994 | + array( |
|
995 | + $messenger, |
|
996 | + $message_type, |
|
997 | + $queue, |
|
998 | + $custom_subject, |
|
999 | + ) |
|
1000 | + ); |
|
1001 | + return self::$_MSG_PROCESSOR->queue_for_sending($message_to_generate); |
|
1002 | + } |
|
1003 | + |
|
1004 | + |
|
1005 | + /** |
|
1006 | + * Generates Messages immediately for EE_Message IDs (but only for the correct status for generation) |
|
1007 | + * |
|
1008 | + * @since 4.9.0 |
|
1009 | + * @param array $message_ids An array of message ids |
|
1010 | + * @return bool|EE_Messages_Queue false if nothing was generated, EE_Messages_Queue containing generated |
|
1011 | + * messages. |
|
1012 | + * @throws EE_Error |
|
1013 | + * @throws InvalidArgumentException |
|
1014 | + * @throws InvalidDataTypeException |
|
1015 | + * @throws InvalidInterfaceException |
|
1016 | + * @throws ReflectionException |
|
1017 | + */ |
|
1018 | + public static function generate_now($message_ids) |
|
1019 | + { |
|
1020 | + self::_load_controller(); |
|
1021 | + $messages = EEM_Message::instance()->get_all( |
|
1022 | + array( |
|
1023 | + 0 => array( |
|
1024 | + 'MSG_ID' => array('IN', $message_ids), |
|
1025 | + 'STS_ID' => EEM_Message::status_incomplete, |
|
1026 | + ), |
|
1027 | + ) |
|
1028 | + ); |
|
1029 | + $generated_queue = false; |
|
1030 | + if ($messages) { |
|
1031 | + $generated_queue = self::$_MSG_PROCESSOR->batch_generate_from_queue($messages); |
|
1032 | + } |
|
1033 | + |
|
1034 | + if (! $generated_queue instanceof EE_Messages_Queue) { |
|
1035 | + EE_Error::add_error( |
|
1036 | + __('The messages were not generated. This could mean there is already a batch being generated on a separate request, or because the selected messages are not ready for generation. Please wait a minute or two and try again.', |
|
1037 | + 'event_espresso'), |
|
1038 | + __FILE__, __FUNCTION__, __LINE__ |
|
1039 | + ); |
|
1040 | + } |
|
1041 | + return $generated_queue; |
|
1042 | + } |
|
1043 | + |
|
1044 | + |
|
1045 | + /** |
|
1046 | + * Sends messages immediately for the incoming message_ids that have the status of EEM_Message::status_resend or, |
|
1047 | + * EEM_Message::status_idle |
|
1048 | + * |
|
1049 | + * @since 4.9.0 |
|
1050 | + * @param $message_ids |
|
1051 | + * @return bool|EE_Messages_Queue false if no messages sent. |
|
1052 | + * @throws EE_Error |
|
1053 | + * @throws InvalidArgumentException |
|
1054 | + * @throws InvalidDataTypeException |
|
1055 | + * @throws InvalidInterfaceException |
|
1056 | + * @throws ReflectionException |
|
1057 | + */ |
|
1058 | + public static function send_now($message_ids) |
|
1059 | + { |
|
1060 | + self::_load_controller(); |
|
1061 | + $messages = EEM_Message::instance()->get_all( |
|
1062 | + array( |
|
1063 | + 0 => array( |
|
1064 | + 'MSG_ID' => array('IN', $message_ids), |
|
1065 | + 'STS_ID' => array( |
|
1066 | + 'IN', |
|
1067 | + array(EEM_Message::status_idle, EEM_Message::status_resend, EEM_Message::status_retry), |
|
1068 | + ), |
|
1069 | + ), |
|
1070 | + ) |
|
1071 | + ); |
|
1072 | + $sent_queue = false; |
|
1073 | + if ($messages) { |
|
1074 | + $sent_queue = self::$_MSG_PROCESSOR->batch_send_from_queue($messages); |
|
1075 | + } |
|
1076 | + |
|
1077 | + if (! $sent_queue instanceof EE_Messages_Queue) { |
|
1078 | + EE_Error::add_error( |
|
1079 | + __('The messages were not sent. This could mean there is already a batch being sent on a separate request, or because the selected messages are not sendable. Please wait a minute or two and try again.', |
|
1080 | + 'event_espresso'), |
|
1081 | + __FILE__, __FUNCTION__, __LINE__ |
|
1082 | + ); |
|
1083 | + } else { |
|
1084 | + //can count how many sent by using the messages in the queue |
|
1085 | + $sent_count = $sent_queue->count_STS_in_queue(EEM_Message::instance()->stati_indicating_sent()); |
|
1086 | + if ($sent_count > 0) { |
|
1087 | + EE_Error::add_success( |
|
1088 | + sprintf( |
|
1089 | + _n( |
|
1090 | + 'There was %d message successfully sent.', |
|
1091 | + 'There were %d messages successfully sent.', |
|
1092 | + $sent_count, |
|
1093 | + 'event_espresso' |
|
1094 | + ), |
|
1095 | + $sent_count |
|
1096 | + ) |
|
1097 | + ); |
|
1098 | + } else { |
|
1099 | + EE_Error::overwrite_errors(); |
|
1100 | + EE_Error::add_error( |
|
1101 | + __('No message was sent because of problems with sending. Either all the messages you selected were not a sendable message, they were ALREADY sent on a different scheduled task, or there was an error. |
|
1102 | 1102 | If there was an error, you can look at the messages in the message activity list table for any error messages.', |
1103 | - 'event_espresso'), |
|
1104 | - __FILE__, __FUNCTION__, __LINE__ |
|
1105 | - ); |
|
1106 | - } |
|
1107 | - } |
|
1108 | - return $sent_queue; |
|
1109 | - } |
|
1110 | - |
|
1111 | - |
|
1112 | - /** |
|
1113 | - * Generate and send immediately from the given $message_ids |
|
1114 | - * |
|
1115 | - * @param array $message_ids EE_Message entity ids. |
|
1116 | - * @throws EE_Error |
|
1117 | - * @throws InvalidArgumentException |
|
1118 | - * @throws InvalidDataTypeException |
|
1119 | - * @throws InvalidInterfaceException |
|
1120 | - * @throws ReflectionException |
|
1121 | - */ |
|
1122 | - public static function generate_and_send_now(array $message_ids) |
|
1123 | - { |
|
1124 | - $generated_queue = self::generate_now($message_ids); |
|
1125 | - //now let's just trigger sending immediately from this queue. |
|
1126 | - $messages_sent = $generated_queue instanceof EE_Messages_Queue |
|
1127 | - ? $generated_queue->execute() |
|
1128 | - : 0; |
|
1129 | - if ($messages_sent) { |
|
1130 | - EE_Error::add_success( |
|
1131 | - esc_html( |
|
1132 | - sprintf( |
|
1133 | - _n( |
|
1134 | - 'There was %d message successfully generated and sent.', |
|
1135 | - 'There were %d messages successfully generated and sent.', |
|
1136 | - $messages_sent, |
|
1137 | - 'event_espresso' |
|
1138 | - ), |
|
1139 | - $messages_sent |
|
1140 | - ) |
|
1141 | - ) |
|
1142 | - ); |
|
1143 | - //errors would be added via the generate_now method. |
|
1144 | - } |
|
1145 | - } |
|
1146 | - |
|
1147 | - |
|
1148 | - /** |
|
1149 | - * This will queue the incoming message ids for resending. |
|
1150 | - * Note, only message_ids corresponding to messages with the status of EEM_Message::sent will be queued. |
|
1151 | - * |
|
1152 | - * @since 4.9.0 |
|
1153 | - * @param array $message_ids An array of EE_Message IDs |
|
1154 | - * @return bool true means messages were successfully queued for resending, false means none were queued for |
|
1155 | - * resending. |
|
1156 | - * @throws EE_Error |
|
1157 | - * @throws InvalidArgumentException |
|
1158 | - * @throws InvalidDataTypeException |
|
1159 | - * @throws InvalidInterfaceException |
|
1160 | - * @throws ReflectionException |
|
1161 | - */ |
|
1162 | - public static function queue_for_resending($message_ids) |
|
1163 | - { |
|
1164 | - self::_load_controller(); |
|
1165 | - self::$_MSG_PROCESSOR->setup_messages_from_ids_and_send($message_ids); |
|
1166 | - |
|
1167 | - //get queue and count |
|
1168 | - $queue_count = self::$_MSG_PROCESSOR->get_queue()->count_STS_in_queue(EEM_Message::status_resend); |
|
1169 | - |
|
1170 | - if ( |
|
1171 | - $queue_count > 0 |
|
1172 | - ) { |
|
1173 | - EE_Error::add_success( |
|
1174 | - sprintf( |
|
1175 | - _n( |
|
1176 | - '%d message successfully queued for resending.', |
|
1177 | - '%d messages successfully queued for resending.', |
|
1178 | - $queue_count, |
|
1179 | - 'event_espresso' |
|
1180 | - ), |
|
1181 | - $queue_count |
|
1182 | - ) |
|
1183 | - ); |
|
1184 | - /** |
|
1185 | - * @see filter usage in EE_Messages_Queue::initiate_request_by_priority |
|
1186 | - */ |
|
1187 | - } elseif ( |
|
1188 | - apply_filters('FHEE__EE_Messages_Processor__initiate_request_by_priority__do_immediate_processing', true) |
|
1189 | - || EE_Registry::instance()->NET_CFG->core->do_messages_on_same_request |
|
1190 | - ) { |
|
1191 | - $queue_count = self::$_MSG_PROCESSOR->get_queue()->count_STS_in_queue(EEM_Message::status_sent); |
|
1192 | - if ($queue_count > 0) { |
|
1193 | - EE_Error::add_success( |
|
1194 | - sprintf( |
|
1195 | - _n( |
|
1196 | - '%d message successfully sent.', |
|
1197 | - '%d messages successfully sent.', |
|
1198 | - $queue_count, |
|
1199 | - 'event_espresso' |
|
1200 | - ), |
|
1201 | - $queue_count |
|
1202 | - ) |
|
1203 | - ); |
|
1204 | - } else { |
|
1205 | - EE_Error::add_error( |
|
1206 | - __('No messages were queued for resending. This usually only happens when all the messages flagged for resending are not a status that can be resent.', |
|
1207 | - 'event_espresso'), |
|
1208 | - __FILE__, __FUNCTION__, __LINE__ |
|
1209 | - ); |
|
1210 | - } |
|
1211 | - } else { |
|
1212 | - EE_Error::add_error( |
|
1213 | - __('No messages were queued for resending. This usually only happens when all the messages flagged for resending are not a status that can be resent.', |
|
1214 | - 'event_espresso'), |
|
1215 | - __FILE__, __FUNCTION__, __LINE__ |
|
1216 | - ); |
|
1217 | - } |
|
1218 | - return (bool)$queue_count; |
|
1219 | - } |
|
1220 | - |
|
1221 | - |
|
1222 | - /** |
|
1223 | - * debug |
|
1224 | - * |
|
1225 | - * @param string $class |
|
1226 | - * @param string $func |
|
1227 | - * @param string $line |
|
1228 | - * @param \EE_Transaction $transaction |
|
1229 | - * @param array $info |
|
1230 | - * @param bool $display_request |
|
1231 | - * @throws EE_Error |
|
1232 | - * @throws \EventEspresso\core\exceptions\InvalidSessionDataException |
|
1233 | - */ |
|
1234 | - protected static function log( |
|
1235 | - $class = '', |
|
1236 | - $func = '', |
|
1237 | - $line = '', |
|
1238 | - EE_Transaction $transaction, |
|
1239 | - $info = array(), |
|
1240 | - $display_request = false |
|
1241 | - ) { |
|
1242 | - if (defined('EE_DEBUG') && EE_DEBUG) { |
|
1243 | - if ($transaction instanceof EE_Transaction) { |
|
1244 | - // don't serialize objects |
|
1245 | - $info = EEH_Debug_Tools::strip_objects($info); |
|
1246 | - $info['TXN_status'] = $transaction->status_ID(); |
|
1247 | - $info['TXN_reg_steps'] = $transaction->reg_steps(); |
|
1248 | - if ($transaction->ID()) { |
|
1249 | - $index = 'EE_Transaction: ' . $transaction->ID(); |
|
1250 | - EEH_Debug_Tools::log($class, $func, $line, $info, $display_request, $index); |
|
1251 | - } |
|
1252 | - } |
|
1253 | - } |
|
1254 | - |
|
1255 | - } |
|
1256 | - |
|
1257 | - |
|
1258 | - /** |
|
1259 | - * Resets all the static properties in this class when called. |
|
1260 | - */ |
|
1261 | - public static function reset() |
|
1262 | - { |
|
1263 | - self::$_EEMSG = null; |
|
1264 | - self::$_message_resource_manager = null; |
|
1265 | - self::$_MSG_PROCESSOR = null; |
|
1266 | - self::$_MSG_PATHS = null; |
|
1267 | - self::$_TMP_PACKS = array(); |
|
1268 | - } |
|
1103 | + 'event_espresso'), |
|
1104 | + __FILE__, __FUNCTION__, __LINE__ |
|
1105 | + ); |
|
1106 | + } |
|
1107 | + } |
|
1108 | + return $sent_queue; |
|
1109 | + } |
|
1110 | + |
|
1111 | + |
|
1112 | + /** |
|
1113 | + * Generate and send immediately from the given $message_ids |
|
1114 | + * |
|
1115 | + * @param array $message_ids EE_Message entity ids. |
|
1116 | + * @throws EE_Error |
|
1117 | + * @throws InvalidArgumentException |
|
1118 | + * @throws InvalidDataTypeException |
|
1119 | + * @throws InvalidInterfaceException |
|
1120 | + * @throws ReflectionException |
|
1121 | + */ |
|
1122 | + public static function generate_and_send_now(array $message_ids) |
|
1123 | + { |
|
1124 | + $generated_queue = self::generate_now($message_ids); |
|
1125 | + //now let's just trigger sending immediately from this queue. |
|
1126 | + $messages_sent = $generated_queue instanceof EE_Messages_Queue |
|
1127 | + ? $generated_queue->execute() |
|
1128 | + : 0; |
|
1129 | + if ($messages_sent) { |
|
1130 | + EE_Error::add_success( |
|
1131 | + esc_html( |
|
1132 | + sprintf( |
|
1133 | + _n( |
|
1134 | + 'There was %d message successfully generated and sent.', |
|
1135 | + 'There were %d messages successfully generated and sent.', |
|
1136 | + $messages_sent, |
|
1137 | + 'event_espresso' |
|
1138 | + ), |
|
1139 | + $messages_sent |
|
1140 | + ) |
|
1141 | + ) |
|
1142 | + ); |
|
1143 | + //errors would be added via the generate_now method. |
|
1144 | + } |
|
1145 | + } |
|
1146 | + |
|
1147 | + |
|
1148 | + /** |
|
1149 | + * This will queue the incoming message ids for resending. |
|
1150 | + * Note, only message_ids corresponding to messages with the status of EEM_Message::sent will be queued. |
|
1151 | + * |
|
1152 | + * @since 4.9.0 |
|
1153 | + * @param array $message_ids An array of EE_Message IDs |
|
1154 | + * @return bool true means messages were successfully queued for resending, false means none were queued for |
|
1155 | + * resending. |
|
1156 | + * @throws EE_Error |
|
1157 | + * @throws InvalidArgumentException |
|
1158 | + * @throws InvalidDataTypeException |
|
1159 | + * @throws InvalidInterfaceException |
|
1160 | + * @throws ReflectionException |
|
1161 | + */ |
|
1162 | + public static function queue_for_resending($message_ids) |
|
1163 | + { |
|
1164 | + self::_load_controller(); |
|
1165 | + self::$_MSG_PROCESSOR->setup_messages_from_ids_and_send($message_ids); |
|
1166 | + |
|
1167 | + //get queue and count |
|
1168 | + $queue_count = self::$_MSG_PROCESSOR->get_queue()->count_STS_in_queue(EEM_Message::status_resend); |
|
1169 | + |
|
1170 | + if ( |
|
1171 | + $queue_count > 0 |
|
1172 | + ) { |
|
1173 | + EE_Error::add_success( |
|
1174 | + sprintf( |
|
1175 | + _n( |
|
1176 | + '%d message successfully queued for resending.', |
|
1177 | + '%d messages successfully queued for resending.', |
|
1178 | + $queue_count, |
|
1179 | + 'event_espresso' |
|
1180 | + ), |
|
1181 | + $queue_count |
|
1182 | + ) |
|
1183 | + ); |
|
1184 | + /** |
|
1185 | + * @see filter usage in EE_Messages_Queue::initiate_request_by_priority |
|
1186 | + */ |
|
1187 | + } elseif ( |
|
1188 | + apply_filters('FHEE__EE_Messages_Processor__initiate_request_by_priority__do_immediate_processing', true) |
|
1189 | + || EE_Registry::instance()->NET_CFG->core->do_messages_on_same_request |
|
1190 | + ) { |
|
1191 | + $queue_count = self::$_MSG_PROCESSOR->get_queue()->count_STS_in_queue(EEM_Message::status_sent); |
|
1192 | + if ($queue_count > 0) { |
|
1193 | + EE_Error::add_success( |
|
1194 | + sprintf( |
|
1195 | + _n( |
|
1196 | + '%d message successfully sent.', |
|
1197 | + '%d messages successfully sent.', |
|
1198 | + $queue_count, |
|
1199 | + 'event_espresso' |
|
1200 | + ), |
|
1201 | + $queue_count |
|
1202 | + ) |
|
1203 | + ); |
|
1204 | + } else { |
|
1205 | + EE_Error::add_error( |
|
1206 | + __('No messages were queued for resending. This usually only happens when all the messages flagged for resending are not a status that can be resent.', |
|
1207 | + 'event_espresso'), |
|
1208 | + __FILE__, __FUNCTION__, __LINE__ |
|
1209 | + ); |
|
1210 | + } |
|
1211 | + } else { |
|
1212 | + EE_Error::add_error( |
|
1213 | + __('No messages were queued for resending. This usually only happens when all the messages flagged for resending are not a status that can be resent.', |
|
1214 | + 'event_espresso'), |
|
1215 | + __FILE__, __FUNCTION__, __LINE__ |
|
1216 | + ); |
|
1217 | + } |
|
1218 | + return (bool)$queue_count; |
|
1219 | + } |
|
1220 | + |
|
1221 | + |
|
1222 | + /** |
|
1223 | + * debug |
|
1224 | + * |
|
1225 | + * @param string $class |
|
1226 | + * @param string $func |
|
1227 | + * @param string $line |
|
1228 | + * @param \EE_Transaction $transaction |
|
1229 | + * @param array $info |
|
1230 | + * @param bool $display_request |
|
1231 | + * @throws EE_Error |
|
1232 | + * @throws \EventEspresso\core\exceptions\InvalidSessionDataException |
|
1233 | + */ |
|
1234 | + protected static function log( |
|
1235 | + $class = '', |
|
1236 | + $func = '', |
|
1237 | + $line = '', |
|
1238 | + EE_Transaction $transaction, |
|
1239 | + $info = array(), |
|
1240 | + $display_request = false |
|
1241 | + ) { |
|
1242 | + if (defined('EE_DEBUG') && EE_DEBUG) { |
|
1243 | + if ($transaction instanceof EE_Transaction) { |
|
1244 | + // don't serialize objects |
|
1245 | + $info = EEH_Debug_Tools::strip_objects($info); |
|
1246 | + $info['TXN_status'] = $transaction->status_ID(); |
|
1247 | + $info['TXN_reg_steps'] = $transaction->reg_steps(); |
|
1248 | + if ($transaction->ID()) { |
|
1249 | + $index = 'EE_Transaction: ' . $transaction->ID(); |
|
1250 | + EEH_Debug_Tools::log($class, $func, $line, $info, $display_request, $index); |
|
1251 | + } |
|
1252 | + } |
|
1253 | + } |
|
1254 | + |
|
1255 | + } |
|
1256 | + |
|
1257 | + |
|
1258 | + /** |
|
1259 | + * Resets all the static properties in this class when called. |
|
1260 | + */ |
|
1261 | + public static function reset() |
|
1262 | + { |
|
1263 | + self::$_EEMSG = null; |
|
1264 | + self::$_message_resource_manager = null; |
|
1265 | + self::$_MSG_PROCESSOR = null; |
|
1266 | + self::$_MSG_PATHS = null; |
|
1267 | + self::$_TMP_PACKS = array(); |
|
1268 | + } |
|
1269 | 1269 | |
1270 | 1270 | } |
1271 | 1271 | // End of file EED_Messages.module.php |
@@ -160,7 +160,7 @@ discard block |
||
160 | 160 | $error_msg = __('Please note that a system message failed to send due to a technical issue.', |
161 | 161 | 'event_espresso'); |
162 | 162 | // add specific message for developers if WP_DEBUG in on |
163 | - $error_msg .= '||' . $e->getMessage(); |
|
163 | + $error_msg .= '||'.$e->getMessage(); |
|
164 | 164 | EE_Error::add_error($error_msg, __FILE__, __FUNCTION__, __LINE__); |
165 | 165 | } |
166 | 166 | } |
@@ -243,7 +243,7 @@ discard block |
||
243 | 243 | $error_msg = __('Please note that a system message failed to send due to a technical issue.', |
244 | 244 | 'event_espresso'); |
245 | 245 | // add specific message for developers if WP_DEBUG in on |
246 | - $error_msg .= '||' . $e->getMessage(); |
|
246 | + $error_msg .= '||'.$e->getMessage(); |
|
247 | 247 | EE_Error::add_error($error_msg, __FILE__, __FUNCTION__, __LINE__); |
248 | 248 | } |
249 | 249 | } |
@@ -274,7 +274,7 @@ discard block |
||
274 | 274 | $transient_key = EE_Registry::instance()->REQ->get('key'); |
275 | 275 | |
276 | 276 | //now let's verify transient, if not valid exit immediately |
277 | - if (! get_transient($transient_key)) { |
|
277 | + if ( ! get_transient($transient_key)) { |
|
278 | 278 | /** |
279 | 279 | * trigger error so this gets in the error logs. This is important because it happens on a non-user |
280 | 280 | * request. |
@@ -287,7 +287,7 @@ discard block |
||
287 | 287 | |
288 | 288 | if (apply_filters('FHEE__EED_Messages__run_cron__use_wp_cron', true)) { |
289 | 289 | |
290 | - $method = 'batch_' . $cron_type . '_from_queue'; |
|
290 | + $method = 'batch_'.$cron_type.'_from_queue'; |
|
291 | 291 | if (method_exists(self::$_MSG_PROCESSOR, $method)) { |
292 | 292 | self::$_MSG_PROCESSOR->$method(); |
293 | 293 | } else { |
@@ -396,9 +396,9 @@ discard block |
||
396 | 396 | 'messages/validators/html', |
397 | 397 | 'shortcodes', |
398 | 398 | ); |
399 | - $paths = array(); |
|
399 | + $paths = array(); |
|
400 | 400 | foreach ($dir_ref as $index => $dir) { |
401 | - $paths[$index] = EE_LIBRARIES . $dir; |
|
401 | + $paths[$index] = EE_LIBRARIES.$dir; |
|
402 | 402 | } |
403 | 403 | self::$_MSG_PATHS = apply_filters('FHEE__EED_Messages___set_messages_paths___MSG_PATHS', $paths); |
404 | 404 | } |
@@ -417,7 +417,7 @@ discard block |
||
417 | 417 | */ |
418 | 418 | protected static function _load_controller() |
419 | 419 | { |
420 | - if (! self::$_MSG_PROCESSOR instanceof EE_Messages_Processor) { |
|
420 | + if ( ! self::$_MSG_PROCESSOR instanceof EE_Messages_Processor) { |
|
421 | 421 | EE_Registry::instance()->load_core('Request_Handler'); |
422 | 422 | self::set_autoloaders(); |
423 | 423 | self::$_EEMSG = EE_Registry::instance()->load_lib('messages'); |
@@ -458,7 +458,7 @@ discard block |
||
458 | 458 | public static function payment(EE_Transaction $transaction, EE_Payment $payment = null) |
459 | 459 | { |
460 | 460 | //if there's no payment object, then we cannot do a payment type message! |
461 | - if (! $payment instanceof EE_Payment) { |
|
461 | + if ( ! $payment instanceof EE_Payment) { |
|
462 | 462 | return; |
463 | 463 | } |
464 | 464 | self::_load_controller(); |
@@ -506,7 +506,7 @@ discard block |
||
506 | 506 | public static function maybe_registration(EE_Registration $registration, $extra_details = array()) |
507 | 507 | { |
508 | 508 | |
509 | - if (! self::_verify_registration_notification_send($registration, $extra_details)) { |
|
509 | + if ( ! self::_verify_registration_notification_send($registration, $extra_details)) { |
|
510 | 510 | //no messages please |
511 | 511 | return; |
512 | 512 | } |
@@ -580,7 +580,7 @@ discard block |
||
580 | 580 | // array( '$extra_details' => $extra_details ) |
581 | 581 | //); |
582 | 582 | // currently only using this to send messages for the primary registrant |
583 | - if (! $registration->is_primary_registrant()) { |
|
583 | + if ( ! $registration->is_primary_registrant()) { |
|
584 | 584 | return false; |
585 | 585 | } |
586 | 586 | // first we check if we're in admin and not doing front ajax |
@@ -593,7 +593,7 @@ discard block |
||
593 | 593 | } else { |
594 | 594 | // frontend request (either regular or via AJAX) |
595 | 595 | // TXN is NOT finalized ? |
596 | - if (! isset($extra_details['finalized']) || $extra_details['finalized'] === false) { |
|
596 | + if ( ! isset($extra_details['finalized']) || $extra_details['finalized'] === false) { |
|
597 | 597 | return false; |
598 | 598 | } |
599 | 599 | // return visit but nothing changed ??? |
@@ -683,12 +683,12 @@ discard block |
||
683 | 683 | } |
684 | 684 | |
685 | 685 | //make sure any incoming request data is set on the REQ so that it gets picked up later. |
686 | - $req_data = (array)$req_data; |
|
686 | + $req_data = (array) $req_data; |
|
687 | 687 | foreach ($req_data as $request_key => $request_value) { |
688 | 688 | EE_Registry::instance()->REQ->set($request_key, $request_value); |
689 | 689 | } |
690 | 690 | |
691 | - if (! $messages_to_send = self::$_MSG_PROCESSOR->setup_messages_to_generate_from_registration_ids_in_request()) { |
|
691 | + if ( ! $messages_to_send = self::$_MSG_PROCESSOR->setup_messages_to_generate_from_registration_ids_in_request()) { |
|
692 | 692 | return false; |
693 | 693 | } |
694 | 694 | |
@@ -721,13 +721,13 @@ discard block |
||
721 | 721 | self::_load_controller(); |
722 | 722 | |
723 | 723 | $msgID = EE_Registry::instance()->REQ->get('MSG_ID'); |
724 | - if (! $msgID) { |
|
724 | + if ( ! $msgID) { |
|
725 | 725 | EE_Error::add_error(__('Something went wrong because there is no "MSG_ID" value in the request', |
726 | 726 | 'event_espresso'), __FILE__, __FUNCTION__, __LINE__); |
727 | 727 | return false; |
728 | 728 | } |
729 | 729 | |
730 | - self::$_MSG_PROCESSOR->setup_messages_from_ids_and_send((array)$msgID); |
|
730 | + self::$_MSG_PROCESSOR->setup_messages_from_ids_and_send((array) $msgID); |
|
731 | 731 | |
732 | 732 | //setup success message. |
733 | 733 | $count_ready_for_resend = self::$_MSG_PROCESSOR->get_queue()->count_STS_in_queue(EEM_Message::status_resend); |
@@ -832,7 +832,7 @@ discard block |
||
832 | 832 | public static function send_newsletter_message($registrations, $grp_id) |
833 | 833 | { |
834 | 834 | //make sure mtp is id and set it in the EE_Request Handler later messages setup. |
835 | - EE_Registry::instance()->REQ->set('GRP_ID', (int)$grp_id); |
|
835 | + EE_Registry::instance()->REQ->set('GRP_ID', (int) $grp_id); |
|
836 | 836 | self::_load_controller(); |
837 | 837 | self::$_MSG_PROCESSOR->generate_for_all_active_messengers('newsletter', $registrations); |
838 | 838 | } |
@@ -892,14 +892,14 @@ discard block |
||
892 | 892 | //get the message template group. |
893 | 893 | $msg_template_group = EEM_Message_Template_Group::instance()->get_one(array($template_query_params)); |
894 | 894 | //if we don't have an EE_Message_Template_Group then return |
895 | - if (! $msg_template_group instanceof EE_Message_Template_Group) { |
|
895 | + if ( ! $msg_template_group instanceof EE_Message_Template_Group) { |
|
896 | 896 | // remove EVT_ID from query params so that global templates get picked up |
897 | 897 | unset($template_query_params['Event.EVT_ID']); |
898 | 898 | //get global template as the fallback |
899 | 899 | $msg_template_group = EEM_Message_Template_Group::instance()->get_one(array($template_query_params)); |
900 | 900 | } |
901 | 901 | //if we don't have an EE_Message_Template_Group then return |
902 | - if (! $msg_template_group instanceof EE_Message_Template_Group) { |
|
902 | + if ( ! $msg_template_group instanceof EE_Message_Template_Group) { |
|
903 | 903 | return ''; |
904 | 904 | } |
905 | 905 | // generate the URL |
@@ -936,7 +936,7 @@ discard block |
||
936 | 936 | public static function preview_message($type, $context, $messenger, $send = false) |
937 | 937 | { |
938 | 938 | self::_load_controller(); |
939 | - $mtg = new EE_Message_To_Generate( |
|
939 | + $mtg = new EE_Message_To_Generate( |
|
940 | 940 | $messenger, |
941 | 941 | $type, |
942 | 942 | array(), |
@@ -1018,7 +1018,7 @@ discard block |
||
1018 | 1018 | public static function generate_now($message_ids) |
1019 | 1019 | { |
1020 | 1020 | self::_load_controller(); |
1021 | - $messages = EEM_Message::instance()->get_all( |
|
1021 | + $messages = EEM_Message::instance()->get_all( |
|
1022 | 1022 | array( |
1023 | 1023 | 0 => array( |
1024 | 1024 | 'MSG_ID' => array('IN', $message_ids), |
@@ -1031,7 +1031,7 @@ discard block |
||
1031 | 1031 | $generated_queue = self::$_MSG_PROCESSOR->batch_generate_from_queue($messages); |
1032 | 1032 | } |
1033 | 1033 | |
1034 | - if (! $generated_queue instanceof EE_Messages_Queue) { |
|
1034 | + if ( ! $generated_queue instanceof EE_Messages_Queue) { |
|
1035 | 1035 | EE_Error::add_error( |
1036 | 1036 | __('The messages were not generated. This could mean there is already a batch being generated on a separate request, or because the selected messages are not ready for generation. Please wait a minute or two and try again.', |
1037 | 1037 | 'event_espresso'), |
@@ -1058,7 +1058,7 @@ discard block |
||
1058 | 1058 | public static function send_now($message_ids) |
1059 | 1059 | { |
1060 | 1060 | self::_load_controller(); |
1061 | - $messages = EEM_Message::instance()->get_all( |
|
1061 | + $messages = EEM_Message::instance()->get_all( |
|
1062 | 1062 | array( |
1063 | 1063 | 0 => array( |
1064 | 1064 | 'MSG_ID' => array('IN', $message_ids), |
@@ -1074,7 +1074,7 @@ discard block |
||
1074 | 1074 | $sent_queue = self::$_MSG_PROCESSOR->batch_send_from_queue($messages); |
1075 | 1075 | } |
1076 | 1076 | |
1077 | - if (! $sent_queue instanceof EE_Messages_Queue) { |
|
1077 | + if ( ! $sent_queue instanceof EE_Messages_Queue) { |
|
1078 | 1078 | EE_Error::add_error( |
1079 | 1079 | __('The messages were not sent. This could mean there is already a batch being sent on a separate request, or because the selected messages are not sendable. Please wait a minute or two and try again.', |
1080 | 1080 | 'event_espresso'), |
@@ -1215,7 +1215,7 @@ discard block |
||
1215 | 1215 | __FILE__, __FUNCTION__, __LINE__ |
1216 | 1216 | ); |
1217 | 1217 | } |
1218 | - return (bool)$queue_count; |
|
1218 | + return (bool) $queue_count; |
|
1219 | 1219 | } |
1220 | 1220 | |
1221 | 1221 | |
@@ -1246,7 +1246,7 @@ discard block |
||
1246 | 1246 | $info['TXN_status'] = $transaction->status_ID(); |
1247 | 1247 | $info['TXN_reg_steps'] = $transaction->reg_steps(); |
1248 | 1248 | if ($transaction->ID()) { |
1249 | - $index = 'EE_Transaction: ' . $transaction->ID(); |
|
1249 | + $index = 'EE_Transaction: '.$transaction->ID(); |
|
1250 | 1250 | EEH_Debug_Tools::log($class, $func, $line, $info, $display_request, $index); |
1251 | 1251 | } |
1252 | 1252 | } |
@@ -505,7 +505,7 @@ |
||
505 | 505 | * |
506 | 506 | * @param string $value string to evaluate |
507 | 507 | * @param array $valid_shortcodes array of shortcodes that are acceptable. |
508 | - * @return mixed (bool|string) return either a list of invalid shortcodes OR false if the shortcodes validate. |
|
508 | + * @return false|string (bool|string) return either a list of invalid shortcodes OR false if the shortcodes validate. |
|
509 | 509 | */ |
510 | 510 | protected function _invalid_shortcodes($value, $valid_shortcodes) |
511 | 511 | { |
@@ -20,626 +20,626 @@ |
||
20 | 20 | { |
21 | 21 | |
22 | 22 | |
23 | - /** |
|
24 | - * These properties just hold the name for the Messenger and Message Type (defined by child classes). |
|
25 | - * These are used for retrieving objects etc. |
|
26 | - * |
|
27 | - * @var string |
|
28 | - */ |
|
29 | - protected $_m_name; |
|
30 | - protected $_mt_name; |
|
31 | - |
|
32 | - |
|
33 | - /** |
|
34 | - * This will hold any error messages from the validation process. |
|
35 | - * The _errors property holds an associative array of error messages |
|
36 | - * listing the field as the key and the message as the value. |
|
37 | - * |
|
38 | - * @var array() |
|
39 | - */ |
|
40 | - private $_errors = array(); |
|
41 | - |
|
42 | - |
|
43 | - /** |
|
44 | - * holds an array of fields being validated |
|
45 | - * |
|
46 | - * @var array |
|
47 | - */ |
|
48 | - protected $_fields; |
|
49 | - |
|
50 | - |
|
51 | - /** |
|
52 | - * this will hold the incoming context |
|
53 | - * |
|
54 | - * @var string |
|
55 | - */ |
|
56 | - protected $_context; |
|
57 | - |
|
58 | - |
|
59 | - /** |
|
60 | - * this holds an array of fields and the relevant validation information |
|
61 | - * that the incoming fields data get validated against. |
|
62 | - * This gets setup in the _set_props() method. |
|
63 | - * |
|
64 | - * @var array |
|
65 | - */ |
|
66 | - protected $_validators; |
|
67 | - |
|
68 | - |
|
69 | - /** |
|
70 | - * holds the messenger object |
|
71 | - * |
|
72 | - * @var object |
|
73 | - */ |
|
74 | - protected $_messenger; |
|
75 | - |
|
76 | - |
|
77 | - /** |
|
78 | - * holds the message type object |
|
79 | - * |
|
80 | - * @var object |
|
81 | - */ |
|
82 | - protected $_message_type; |
|
83 | - |
|
84 | - |
|
85 | - /** |
|
86 | - * will hold any valid_shortcode modifications made by the _modify_validator() method. |
|
87 | - * |
|
88 | - * @var array |
|
89 | - */ |
|
90 | - protected $_valid_shortcodes_modifier; |
|
91 | - |
|
92 | - |
|
93 | - /** |
|
94 | - * There may be times where a message type wants to include a shortcode group but exclude specific |
|
95 | - * shortcodes. If that's the case then it can set this property as an array of shortcodes to exclude and |
|
96 | - * they will not be allowed. |
|
97 | - * Array should be indexed by field and values are an array of specific shortcodes to exclude. |
|
98 | - * |
|
99 | - * @var array |
|
100 | - */ |
|
101 | - protected $_specific_shortcode_excludes = array(); |
|
102 | - |
|
103 | - |
|
104 | - /** |
|
105 | - * Runs the validator using the incoming fields array as the fields/values to check. |
|
106 | - * |
|
107 | - * @param array $fields The fields sent by the EEM object. |
|
108 | - * @param $context |
|
109 | - * @throws EE_Error |
|
110 | - * @throws ReflectionException |
|
111 | - */ |
|
112 | - public function __construct($fields, $context) |
|
113 | - { |
|
114 | - //check that _m_name and _mt_name have been set by child class otherwise we get out. |
|
115 | - if (empty($this->_m_name) || empty($this->_mt_name)) { |
|
116 | - throw new EE_Error( |
|
117 | - esc_html__( |
|
118 | - 'EE_Messages_Validator child classes MUST set the $_m_name and $_mt_name property. Check that the child class is doing this', |
|
119 | - 'event_espresso' |
|
120 | - ) |
|
121 | - ); |
|
122 | - } |
|
123 | - $this->_fields = $fields; |
|
124 | - $this->_context = $context; |
|
125 | - |
|
126 | - //load messenger and message_type objects and the related shortcode objects. |
|
127 | - $this->_load_objects(); |
|
128 | - |
|
129 | - |
|
130 | - //modify any messenger/message_type specific validation instructions. This is what child classes define. |
|
131 | - $this->_modify_validator(); |
|
132 | - |
|
133 | - |
|
134 | - //let's set validators property |
|
135 | - $this->_set_validators(); |
|
136 | - } |
|
137 | - |
|
138 | - |
|
139 | - /** |
|
140 | - * Child classes instantiate this and use it to modify the _validator_config array property |
|
141 | - * for the messenger using messengers set_validate_config() method. |
|
142 | - * This is so we can specify specific validation instructions for a messenger/message_type combo |
|
143 | - * that aren't handled by the defaults setup in the messenger. |
|
144 | - * |
|
145 | - * @abstract |
|
146 | - * @access protected |
|
147 | - * @return void |
|
148 | - */ |
|
149 | - abstract protected function _modify_validator(); |
|
150 | - |
|
151 | - |
|
152 | - /** |
|
153 | - * loads all objects used by validator |
|
154 | - * |
|
155 | - * @access private |
|
156 | - * @throws \EE_Error |
|
157 | - */ |
|
158 | - private function _load_objects() |
|
159 | - { |
|
160 | - //load messenger |
|
161 | - $messenger = ucwords(str_replace('_', ' ', $this->_m_name)); |
|
162 | - $messenger = str_replace(' ', '_', $messenger); |
|
163 | - $messenger = 'EE_' . $messenger . '_messenger'; |
|
164 | - |
|
165 | - if (! class_exists($messenger)) { |
|
166 | - throw new EE_Error( |
|
167 | - sprintf( |
|
168 | - esc_html__('There is no messenger class for the given string (%s)', 'event_espresso'), |
|
169 | - $this->_m_name |
|
170 | - ) |
|
171 | - ); |
|
172 | - } |
|
173 | - |
|
174 | - $this->_messenger = new $messenger(); |
|
175 | - |
|
176 | - //load message type |
|
177 | - $message_type = ucwords(str_replace('_', ' ', $this->_mt_name)); |
|
178 | - $message_type = str_replace(' ', '_', $message_type); |
|
179 | - $message_type = 'EE_' . $message_type . '_message_type'; |
|
180 | - |
|
181 | - if (! class_exists($message_type)) { |
|
182 | - throw new EE_Error( |
|
183 | - sprintf( |
|
184 | - esc_html__('There is no message type class for the given string (%s)', 'event_espresso'), |
|
185 | - $this->_mt_name |
|
186 | - ) |
|
187 | - ); |
|
188 | - } |
|
189 | - |
|
190 | - $this->_message_type = new $message_type(); |
|
191 | - } |
|
192 | - |
|
193 | - |
|
194 | - /** |
|
195 | - * used to set the $_validators property |
|
196 | - * |
|
197 | - * @access private |
|
198 | - * @return void |
|
199 | - * @throws ReflectionException |
|
200 | - */ |
|
201 | - private function _set_validators() |
|
202 | - { |
|
203 | - // let's get all valid shortcodes from mt and message type |
|
204 | - // (messenger will have its set in the _validator_config property for the messenger) |
|
205 | - $mt_codes = $this->_message_type->get_valid_shortcodes(); |
|
206 | - |
|
207 | - |
|
208 | - //get messenger validator_config |
|
209 | - $msgr_validator = $this->_messenger->get_validator_config(); |
|
210 | - |
|
211 | - |
|
212 | - //we only want the valid shortcodes for the given context! |
|
213 | - $context = $this->_context; |
|
214 | - $mt_codes = $mt_codes[$context]; |
|
215 | - |
|
216 | - // in this first loop we're just getting all shortcode group indexes from the msgr_validator |
|
217 | - // into a single array (so we can get the appropriate shortcode objects for the groups) |
|
218 | - $shortcode_groups = $mt_codes; |
|
219 | - $groups_per_field = array(); |
|
220 | - |
|
221 | - foreach ($msgr_validator as $field => $config) { |
|
222 | - if (empty($config) || ! isset($config['shortcodes'])) { |
|
223 | - continue; |
|
224 | - } //Nothing to see here. |
|
225 | - $groups_per_field[$field] = array_intersect($config['shortcodes'], $mt_codes); |
|
226 | - $shortcode_groups = array_merge($config['shortcodes'], $shortcode_groups); |
|
227 | - } |
|
228 | - |
|
229 | - $shortcode_groups = array_unique($shortcode_groups); |
|
230 | - |
|
231 | - // okay now we've got our groups. |
|
232 | - // Let's get the codes from the objects into an array indexed by group for easy retrieval later. |
|
233 | - $codes_from_objs = array(); |
|
234 | - |
|
235 | - foreach ($shortcode_groups as $group) { |
|
236 | - $ref = ucwords(str_replace('_', ' ', $group)); |
|
237 | - $ref = str_replace(' ', '_', $ref); |
|
238 | - $classname = 'EE_' . $ref . '_Shortcodes'; |
|
239 | - if (class_exists($classname)) { |
|
240 | - $a = new ReflectionClass($classname); |
|
241 | - $obj = $a->newInstance(); |
|
242 | - $codes_from_objs[$group] = $obj->get_shortcodes(); |
|
243 | - } |
|
244 | - } |
|
245 | - |
|
246 | - |
|
247 | - //let's just replace the $mt shortcode group indexes with the actual shortcodes (unique) |
|
248 | - $final_mt_codes = array(); |
|
249 | - foreach ($mt_codes as $group) { |
|
250 | - $final_mt_codes = array_merge($final_mt_codes, $codes_from_objs[$group]); |
|
251 | - } |
|
252 | - |
|
253 | - $mt_codes = $final_mt_codes; |
|
254 | - |
|
255 | - |
|
256 | - // k now in this next loop we're going to loop through $msgr_validator again |
|
257 | - // and setup the _validators property from the data we've setup so far. |
|
258 | - foreach ($msgr_validator as $field => $config) { |
|
259 | - //if required shortcode is not in our list of codes for the given field, then we skip this field. |
|
260 | - $required = isset($config['required']) |
|
261 | - ? array_intersect($config['required'], array_keys($mt_codes)) |
|
262 | - : true; |
|
263 | - if (empty($required)) { |
|
264 | - continue; |
|
265 | - } |
|
266 | - |
|
267 | - //If we have an override then we use it to indicate the codes we want. |
|
268 | - if (isset($this->_valid_shortcodes_modifier[$context][$field])) { |
|
269 | - $this->_validators[$field]['shortcodes'] = $this->_reassemble_valid_shortcodes_from_group( |
|
270 | - $this->_valid_shortcodes_modifier[$context][$field], |
|
271 | - $codes_from_objs |
|
272 | - ); |
|
273 | - } //if we have specific shortcodes for a field then we need to use them |
|
274 | - elseif (isset($groups_per_field[$field])) { |
|
275 | - $this->_validators[$field]['shortcodes'] = $this->_reassemble_valid_shortcodes_from_group( |
|
276 | - $groups_per_field[$field], |
|
277 | - $codes_from_objs |
|
278 | - ); |
|
279 | - } //if empty config then we're assuming we're just going to use the shortcodes from the message type context |
|
280 | - elseif (empty($config)) { |
|
281 | - $this->_validators[$field]['shortcodes'] = $mt_codes; |
|
282 | - } //if we have specific shortcodes then we need to use them |
|
283 | - elseif (isset($config['specific_shortcodes'])) { |
|
284 | - $this->_validators[$field]['shortcodes'] = $config['specific_shortcodes']; |
|
285 | - } //otherwise the shortcodes are what is set by the messenger for that field |
|
286 | - else { |
|
287 | - foreach ($config['shortcodes'] as $group) { |
|
288 | - $this->_validators[$field]['shortcodes'] = isset($this->_validators[$field]['shortcodes']) |
|
289 | - ? array_merge($this->_validators[$field]['shortcodes'], $codes_from_objs[$group]) |
|
290 | - : $codes_from_objs[$group]; |
|
291 | - } |
|
292 | - } |
|
293 | - |
|
294 | - //now let's just make sure that any excluded specific shortcodes are removed. |
|
295 | - $specific_excludes = $this->get_specific_shortcode_excludes(); |
|
296 | - if (isset($specific_excludes[$field])) { |
|
297 | - foreach ($specific_excludes[$field] as $sex) { |
|
298 | - if (isset($this->_validators[$field]['shortcodes'][$sex])) { |
|
299 | - unset($this->_validators[$field]['shortcodes'][$sex]); |
|
300 | - } |
|
301 | - } |
|
302 | - } |
|
303 | - |
|
304 | - //hey! don't forget to include the type if present! |
|
305 | - $this->_validators[$field]['type'] = isset($config['type']) ? $config['type'] : null; |
|
306 | - } |
|
307 | - } |
|
308 | - |
|
309 | - |
|
310 | - /** |
|
311 | - * This just returns the validators property that contains information |
|
312 | - * about the various shortcodes and their availability with each field |
|
313 | - * |
|
314 | - * @return array |
|
315 | - */ |
|
316 | - public function get_validators() |
|
317 | - { |
|
318 | - return $this->_validators; |
|
319 | - } |
|
320 | - |
|
321 | - |
|
322 | - /** |
|
323 | - * This simply returns the specific shortcode_excludes property that is set. |
|
324 | - * |
|
325 | - * @since 4.5.0 |
|
326 | - * @return array |
|
327 | - */ |
|
328 | - public function get_specific_shortcode_excludes() |
|
329 | - { |
|
330 | - //specific validator filter |
|
331 | - $shortcode_excludes = apply_filters( |
|
332 | - 'FHEE__' . get_class($this) . '__get_specific_shortcode_excludes;', |
|
333 | - $this->_specific_shortcode_excludes, |
|
334 | - $this->_context |
|
335 | - ); |
|
336 | - //global filter |
|
337 | - return apply_filters( |
|
338 | - 'FHEE__EE_Messages_Validator__get_specific_shortcode_excludes', |
|
339 | - $shortcode_excludes, |
|
340 | - $this->_context, |
|
341 | - $this |
|
342 | - ); |
|
343 | - } |
|
344 | - |
|
345 | - |
|
346 | - /** |
|
347 | - * This is the main method that handles validation |
|
348 | - * What it does is loop through the _fields (the ones that get validated) |
|
349 | - * and checks them against the shortcodes array for the field and the 'type' indicated by the |
|
350 | - * |
|
351 | - * @access public |
|
352 | - * @return mixed (bool|array) if errors present we return the array otherwise true |
|
353 | - */ |
|
354 | - public function validate() |
|
355 | - { |
|
356 | - //some defaults |
|
357 | - $template_fields = $this->_messenger->get_template_fields(); |
|
358 | - //loop through the fields and check! |
|
359 | - foreach ($this->_fields as $field => $value) { |
|
360 | - $this->_errors[$field] = array(); |
|
361 | - $err_msg = ''; |
|
362 | - $field_label = ''; |
|
363 | - //if field is not present in the _validators array then we continue |
|
364 | - if (! isset($this->_validators[$field])) { |
|
365 | - unset($this->_errors[$field]); |
|
366 | - continue; |
|
367 | - } |
|
368 | - |
|
369 | - //get the translated field label! |
|
370 | - //first check if it's in the main fields list |
|
371 | - if (isset($template_fields[$field])) { |
|
372 | - if (empty($template_fields[$field])) { |
|
373 | - $field_label = $field; |
|
374 | - } //most likely the field is found in the 'extra' array. |
|
375 | - else { |
|
376 | - $field_label = $template_fields[$field]['label']; |
|
377 | - } |
|
378 | - } |
|
379 | - |
|
380 | - // if field label is empty OR is equal to the current field |
|
381 | - // then we need to loop through the 'extra' fields in the template_fields config (if present) |
|
382 | - if (isset($template_fields['extra']) && (empty($field_label) || $field_label === $field)) { |
|
383 | - foreach ($template_fields['extra'] as $main_field => $secondary_field) { |
|
384 | - foreach ($secondary_field as $name => $values) { |
|
385 | - if ($name === $field) { |
|
386 | - $field_label = $values['label']; |
|
387 | - } |
|
388 | - |
|
389 | - // if we've got a 'main' secondary field, let's see if that matches what field we're on |
|
390 | - // which means it contains the label for this field. |
|
391 | - if ($name === 'main' && $main_field === $field_label) { |
|
392 | - $field_label = $values['label']; |
|
393 | - } |
|
394 | - } |
|
395 | - } |
|
396 | - } |
|
397 | - |
|
398 | - //field is present. Let's validate shortcodes first (but only if shortcodes present). |
|
399 | - if (isset($this->_validators[$field]['shortcodes']) |
|
400 | - && ! empty($this->_validators[$field]['shortcodes']) |
|
401 | - ) { |
|
402 | - $invalid_shortcodes = $this->_invalid_shortcodes($value, $this->_validators[$field]['shortcodes']); |
|
403 | - // if true then that means there is a returned error message |
|
404 | - // that we'll need to add to the _errors array for this field. |
|
405 | - if ($invalid_shortcodes) { |
|
406 | - $v_s = array_keys($this->_validators[$field]['shortcodes']); |
|
407 | - $err_msg = sprintf( |
|
408 | - esc_html__( |
|
409 | - '%3$sThe following shortcodes were found in the "%1$s" field that ARE not valid: %2$s%4$s', |
|
410 | - 'event_espresso' |
|
411 | - ), |
|
412 | - '<strong>' . $field_label . '</strong>', |
|
413 | - $invalid_shortcodes, |
|
414 | - '<p>', |
|
415 | - '</p >' |
|
416 | - ); |
|
417 | - $err_msg .= sprintf( |
|
418 | - esc_html__('%2$sValid shortcodes for this field are: %1$s%3$s', 'event_espresso'), |
|
419 | - implode(', ', $v_s), |
|
420 | - '<strong>', |
|
421 | - '</strong>' |
|
422 | - ); |
|
423 | - } |
|
424 | - } |
|
425 | - |
|
426 | - //if there's a "type" to be validated then let's do that too. |
|
427 | - if (isset($this->_validators[$field]['type']) && ! empty($this->_validators[$field]['type'])) { |
|
428 | - switch ($this->_validators[$field]['type']) { |
|
429 | - case 'number': |
|
430 | - if (! is_numeric($value)) { |
|
431 | - $err_msg .= sprintf( |
|
432 | - esc_html__( |
|
433 | - '%3$sThe %1$s field is supposed to be a number. The value given (%2$s) is not. Please double-check and make sure the field contains a number%4$s', |
|
434 | - 'event_espresso' |
|
435 | - ), |
|
436 | - $field_label, |
|
437 | - $value, |
|
438 | - '<p>', |
|
439 | - '</p >' |
|
440 | - ); |
|
441 | - } |
|
442 | - break; |
|
443 | - case 'email': |
|
444 | - $valid_email = $this->_validate_email($value); |
|
445 | - if (! $valid_email) { |
|
446 | - $err_msg .= htmlentities( |
|
447 | - sprintf( |
|
448 | - esc_html__( |
|
449 | - 'The %1$s field has at least one string that is not a valid email address record. Valid emails are in the format: "Name <[email protected]>" or "[email protected]" and multiple emails can be separated by a comma.' |
|
450 | - ), |
|
451 | - $field_label |
|
452 | - |
|
453 | - ) |
|
454 | - ); |
|
455 | - } |
|
456 | - break; |
|
457 | - default: |
|
458 | - break; |
|
459 | - } |
|
460 | - } |
|
461 | - |
|
462 | - //if $err_msg isn't empty let's setup the _errors array for this field. |
|
463 | - if (! empty($err_msg)) { |
|
464 | - $this->_errors[$field]['msg'] = $err_msg; |
|
465 | - } else { |
|
466 | - unset($this->_errors[$field]); |
|
467 | - } |
|
468 | - } |
|
469 | - |
|
470 | - // if we have ANY errors, then we want to make sure we return the values |
|
471 | - // for ALL the fields so the user doesn't have to retype them all. |
|
472 | - if (! empty($this->_errors)) { |
|
473 | - foreach ($this->_fields as $field => $value) { |
|
474 | - $this->_errors[$field]['value'] = stripslashes($value); |
|
475 | - } |
|
476 | - } |
|
477 | - |
|
478 | - //return any errors or just TRUE if everything validates |
|
479 | - return empty($this->_errors) ? true : $this->_errors; |
|
480 | - } |
|
481 | - |
|
482 | - |
|
483 | - /** |
|
484 | - * Reassembles and returns an array of valid shortcodes |
|
485 | - * given the array of groups and array of shortcodes indexed by group. |
|
486 | - * |
|
487 | - * @param array $groups array of shortcode groups that we want shortcodes for |
|
488 | - * @param array $codes_from_objs All the codes available. |
|
489 | - * @return array an array of actual shortcodes (that will be used for validation). |
|
490 | - */ |
|
491 | - private function _reassemble_valid_shortcodes_from_group($groups, $codes_from_objs) |
|
492 | - { |
|
493 | - $shortcodes = array(); |
|
494 | - foreach ($groups as $group) { |
|
495 | - $shortcodes = array_merge($shortcodes, $codes_from_objs[$group]); |
|
496 | - } |
|
497 | - return $shortcodes; |
|
498 | - } |
|
499 | - |
|
500 | - |
|
501 | - /** |
|
502 | - * Validates a string against a list of accepted shortcodes |
|
503 | - * This function takes in an array of shortcodes |
|
504 | - * and makes sure that the given string ONLY contains shortcodes in that array. |
|
505 | - * |
|
506 | - * @param string $value string to evaluate |
|
507 | - * @param array $valid_shortcodes array of shortcodes that are acceptable. |
|
508 | - * @return mixed (bool|string) return either a list of invalid shortcodes OR false if the shortcodes validate. |
|
509 | - */ |
|
510 | - protected function _invalid_shortcodes($value, $valid_shortcodes) |
|
511 | - { |
|
512 | - //first we need to go through the string and get the shortcodes in the string |
|
513 | - preg_match_all('/(\[.+?\])/', $value, $matches); |
|
514 | - $incoming_shortcodes = (array)$matches[0]; |
|
515 | - |
|
516 | - //get a diff of the shortcodes in the string vs the valid shortcodes |
|
517 | - $diff = array_diff($incoming_shortcodes, array_keys($valid_shortcodes)); |
|
518 | - |
|
519 | - //we need to account for custom codes so let's loop through the diff and remove any of those type of codes |
|
520 | - foreach ($diff as $ind => $code) { |
|
521 | - if (preg_match('/(\[[A-Za-z0-9\_]+_\*)/', $code)) { |
|
522 | - //strip the shortcode so we just have the BASE string (i.e. [ANSWER_*] ) |
|
523 | - $dynamic_sc = preg_replace('/(_\*+.+)/', '_*]', $code); |
|
524 | - //does this exist in the $valid_shortcodes? If so then unset. |
|
525 | - if (isset($valid_shortcodes[$dynamic_sc])) { |
|
526 | - unset($diff[$ind]); |
|
527 | - } |
|
528 | - } |
|
529 | - } |
|
530 | - |
|
531 | - if (empty($diff)) { |
|
532 | - return false; |
|
533 | - } //there is no diff, we have no invalid shortcodes, so return |
|
534 | - |
|
535 | - //made it here? then let's assemble the error message |
|
536 | - $invalid_shortcodes = implode('</strong>,<strong>', $diff); |
|
537 | - $invalid_shortcodes = '<strong>' . $invalid_shortcodes . '</strong>'; |
|
538 | - return $invalid_shortcodes; |
|
539 | - } |
|
540 | - |
|
541 | - |
|
542 | - /** |
|
543 | - * Validates an incoming string and makes sure we have valid emails in the string. |
|
544 | - * |
|
545 | - * @param string $value incoming value to validate |
|
546 | - * @return bool true if the string validates, false if it doesn't |
|
547 | - */ |
|
548 | - protected function _validate_email($value) |
|
549 | - { |
|
550 | - $validate = true; |
|
551 | - $or_val = $value; |
|
552 | - |
|
553 | - // empty strings will validate because this is how a message template |
|
554 | - // for a particular context can be "turned off" (if there is no email then no message) |
|
555 | - if (empty($value)) { |
|
556 | - return $validate; |
|
557 | - } |
|
558 | - |
|
559 | - // first determine if there ARE any shortcodes. |
|
560 | - // If there are shortcodes and then later we find that there were no other valid emails |
|
561 | - // but the field isn't empty... |
|
562 | - // that means we've got extra commas that were left after stripping out shortcodes so probably still valid. |
|
563 | - $has_shortcodes = preg_match('/(\[.+?\])/', $value); |
|
564 | - |
|
565 | - //first we need to strip out all the shortcodes! |
|
566 | - $value = preg_replace('/(\[.+?\])/', '', $value); |
|
567 | - |
|
568 | - // if original value is not empty and new value is, then we've parsed out a shortcode |
|
569 | - // and we now have an empty string which DOES validate. |
|
570 | - // We also validate complete empty field for email because |
|
571 | - // its possible that this message is being "turned off" for a particular context |
|
572 | - |
|
573 | - |
|
574 | - if (! empty($or_val) && empty($value)) { |
|
575 | - return $validate; |
|
576 | - } |
|
577 | - |
|
578 | - //trim any commas from beginning and end of string ( after whitespace trimmed ); |
|
579 | - $value = trim(trim($value), ','); |
|
580 | - |
|
581 | - |
|
582 | - //next we need to split up the string if its comma delimited. |
|
583 | - $emails = explode(',', $value); |
|
584 | - $empty = false; //used to indicate that there is an empty comma. |
|
585 | - //now let's loop through the emails and do our checks |
|
586 | - foreach ($emails as $email) { |
|
587 | - if (empty($email)) { |
|
588 | - $empty = true; |
|
589 | - continue; |
|
590 | - } |
|
591 | - |
|
592 | - //trim whitespace |
|
593 | - $email = trim($email); |
|
594 | - //either its of type "[email protected]", or its of type "fname lname <[email protected]>" |
|
595 | - if (is_email($email)) { |
|
596 | - continue; |
|
597 | - } |
|
598 | - $matches = array(); |
|
599 | - $validate = preg_match('/(.*)<(.+)>/', $email, $matches) ? true : false; |
|
600 | - if ($validate && is_email($matches[2])) { |
|
601 | - continue; |
|
602 | - } |
|
603 | - return false; |
|
604 | - } |
|
605 | - |
|
606 | - $validate = $empty && ! $has_shortcodes ? false : $validate; |
|
607 | - |
|
608 | - return $validate; |
|
609 | - } |
|
610 | - |
|
611 | - |
|
612 | - /** |
|
613 | - * Magic getter |
|
614 | - * Using this to provide back compat with add-ons referencing deprecated properties. |
|
615 | - * |
|
616 | - * @param string $property Property being requested |
|
617 | - * @throws Exception |
|
618 | - * @return mixed |
|
619 | - */ |
|
620 | - public function __get($property) |
|
621 | - { |
|
622 | - $expected_properties_map = array( |
|
623 | - /** |
|
624 | - * @deprecated 4.9.0 |
|
625 | - */ |
|
626 | - '_MSGR' => '_messenger', |
|
627 | - /** |
|
628 | - * @deprecated 4.9.0 |
|
629 | - */ |
|
630 | - '_MSGTYP' => '_message_type', |
|
631 | - ); |
|
632 | - |
|
633 | - if (isset($expected_properties_map[$property])) { |
|
634 | - return $this->{$expected_properties_map[$property]}; |
|
635 | - } |
|
636 | - |
|
637 | - throw new Exception( |
|
638 | - sprintf( |
|
639 | - esc_html__('The property %1$s being requested on %2$s does not exist', 'event_espresso'), |
|
640 | - $property, |
|
641 | - get_class($this) |
|
642 | - ) |
|
643 | - ); |
|
644 | - } |
|
23 | + /** |
|
24 | + * These properties just hold the name for the Messenger and Message Type (defined by child classes). |
|
25 | + * These are used for retrieving objects etc. |
|
26 | + * |
|
27 | + * @var string |
|
28 | + */ |
|
29 | + protected $_m_name; |
|
30 | + protected $_mt_name; |
|
31 | + |
|
32 | + |
|
33 | + /** |
|
34 | + * This will hold any error messages from the validation process. |
|
35 | + * The _errors property holds an associative array of error messages |
|
36 | + * listing the field as the key and the message as the value. |
|
37 | + * |
|
38 | + * @var array() |
|
39 | + */ |
|
40 | + private $_errors = array(); |
|
41 | + |
|
42 | + |
|
43 | + /** |
|
44 | + * holds an array of fields being validated |
|
45 | + * |
|
46 | + * @var array |
|
47 | + */ |
|
48 | + protected $_fields; |
|
49 | + |
|
50 | + |
|
51 | + /** |
|
52 | + * this will hold the incoming context |
|
53 | + * |
|
54 | + * @var string |
|
55 | + */ |
|
56 | + protected $_context; |
|
57 | + |
|
58 | + |
|
59 | + /** |
|
60 | + * this holds an array of fields and the relevant validation information |
|
61 | + * that the incoming fields data get validated against. |
|
62 | + * This gets setup in the _set_props() method. |
|
63 | + * |
|
64 | + * @var array |
|
65 | + */ |
|
66 | + protected $_validators; |
|
67 | + |
|
68 | + |
|
69 | + /** |
|
70 | + * holds the messenger object |
|
71 | + * |
|
72 | + * @var object |
|
73 | + */ |
|
74 | + protected $_messenger; |
|
75 | + |
|
76 | + |
|
77 | + /** |
|
78 | + * holds the message type object |
|
79 | + * |
|
80 | + * @var object |
|
81 | + */ |
|
82 | + protected $_message_type; |
|
83 | + |
|
84 | + |
|
85 | + /** |
|
86 | + * will hold any valid_shortcode modifications made by the _modify_validator() method. |
|
87 | + * |
|
88 | + * @var array |
|
89 | + */ |
|
90 | + protected $_valid_shortcodes_modifier; |
|
91 | + |
|
92 | + |
|
93 | + /** |
|
94 | + * There may be times where a message type wants to include a shortcode group but exclude specific |
|
95 | + * shortcodes. If that's the case then it can set this property as an array of shortcodes to exclude and |
|
96 | + * they will not be allowed. |
|
97 | + * Array should be indexed by field and values are an array of specific shortcodes to exclude. |
|
98 | + * |
|
99 | + * @var array |
|
100 | + */ |
|
101 | + protected $_specific_shortcode_excludes = array(); |
|
102 | + |
|
103 | + |
|
104 | + /** |
|
105 | + * Runs the validator using the incoming fields array as the fields/values to check. |
|
106 | + * |
|
107 | + * @param array $fields The fields sent by the EEM object. |
|
108 | + * @param $context |
|
109 | + * @throws EE_Error |
|
110 | + * @throws ReflectionException |
|
111 | + */ |
|
112 | + public function __construct($fields, $context) |
|
113 | + { |
|
114 | + //check that _m_name and _mt_name have been set by child class otherwise we get out. |
|
115 | + if (empty($this->_m_name) || empty($this->_mt_name)) { |
|
116 | + throw new EE_Error( |
|
117 | + esc_html__( |
|
118 | + 'EE_Messages_Validator child classes MUST set the $_m_name and $_mt_name property. Check that the child class is doing this', |
|
119 | + 'event_espresso' |
|
120 | + ) |
|
121 | + ); |
|
122 | + } |
|
123 | + $this->_fields = $fields; |
|
124 | + $this->_context = $context; |
|
125 | + |
|
126 | + //load messenger and message_type objects and the related shortcode objects. |
|
127 | + $this->_load_objects(); |
|
128 | + |
|
129 | + |
|
130 | + //modify any messenger/message_type specific validation instructions. This is what child classes define. |
|
131 | + $this->_modify_validator(); |
|
132 | + |
|
133 | + |
|
134 | + //let's set validators property |
|
135 | + $this->_set_validators(); |
|
136 | + } |
|
137 | + |
|
138 | + |
|
139 | + /** |
|
140 | + * Child classes instantiate this and use it to modify the _validator_config array property |
|
141 | + * for the messenger using messengers set_validate_config() method. |
|
142 | + * This is so we can specify specific validation instructions for a messenger/message_type combo |
|
143 | + * that aren't handled by the defaults setup in the messenger. |
|
144 | + * |
|
145 | + * @abstract |
|
146 | + * @access protected |
|
147 | + * @return void |
|
148 | + */ |
|
149 | + abstract protected function _modify_validator(); |
|
150 | + |
|
151 | + |
|
152 | + /** |
|
153 | + * loads all objects used by validator |
|
154 | + * |
|
155 | + * @access private |
|
156 | + * @throws \EE_Error |
|
157 | + */ |
|
158 | + private function _load_objects() |
|
159 | + { |
|
160 | + //load messenger |
|
161 | + $messenger = ucwords(str_replace('_', ' ', $this->_m_name)); |
|
162 | + $messenger = str_replace(' ', '_', $messenger); |
|
163 | + $messenger = 'EE_' . $messenger . '_messenger'; |
|
164 | + |
|
165 | + if (! class_exists($messenger)) { |
|
166 | + throw new EE_Error( |
|
167 | + sprintf( |
|
168 | + esc_html__('There is no messenger class for the given string (%s)', 'event_espresso'), |
|
169 | + $this->_m_name |
|
170 | + ) |
|
171 | + ); |
|
172 | + } |
|
173 | + |
|
174 | + $this->_messenger = new $messenger(); |
|
175 | + |
|
176 | + //load message type |
|
177 | + $message_type = ucwords(str_replace('_', ' ', $this->_mt_name)); |
|
178 | + $message_type = str_replace(' ', '_', $message_type); |
|
179 | + $message_type = 'EE_' . $message_type . '_message_type'; |
|
180 | + |
|
181 | + if (! class_exists($message_type)) { |
|
182 | + throw new EE_Error( |
|
183 | + sprintf( |
|
184 | + esc_html__('There is no message type class for the given string (%s)', 'event_espresso'), |
|
185 | + $this->_mt_name |
|
186 | + ) |
|
187 | + ); |
|
188 | + } |
|
189 | + |
|
190 | + $this->_message_type = new $message_type(); |
|
191 | + } |
|
192 | + |
|
193 | + |
|
194 | + /** |
|
195 | + * used to set the $_validators property |
|
196 | + * |
|
197 | + * @access private |
|
198 | + * @return void |
|
199 | + * @throws ReflectionException |
|
200 | + */ |
|
201 | + private function _set_validators() |
|
202 | + { |
|
203 | + // let's get all valid shortcodes from mt and message type |
|
204 | + // (messenger will have its set in the _validator_config property for the messenger) |
|
205 | + $mt_codes = $this->_message_type->get_valid_shortcodes(); |
|
206 | + |
|
207 | + |
|
208 | + //get messenger validator_config |
|
209 | + $msgr_validator = $this->_messenger->get_validator_config(); |
|
210 | + |
|
211 | + |
|
212 | + //we only want the valid shortcodes for the given context! |
|
213 | + $context = $this->_context; |
|
214 | + $mt_codes = $mt_codes[$context]; |
|
215 | + |
|
216 | + // in this first loop we're just getting all shortcode group indexes from the msgr_validator |
|
217 | + // into a single array (so we can get the appropriate shortcode objects for the groups) |
|
218 | + $shortcode_groups = $mt_codes; |
|
219 | + $groups_per_field = array(); |
|
220 | + |
|
221 | + foreach ($msgr_validator as $field => $config) { |
|
222 | + if (empty($config) || ! isset($config['shortcodes'])) { |
|
223 | + continue; |
|
224 | + } //Nothing to see here. |
|
225 | + $groups_per_field[$field] = array_intersect($config['shortcodes'], $mt_codes); |
|
226 | + $shortcode_groups = array_merge($config['shortcodes'], $shortcode_groups); |
|
227 | + } |
|
228 | + |
|
229 | + $shortcode_groups = array_unique($shortcode_groups); |
|
230 | + |
|
231 | + // okay now we've got our groups. |
|
232 | + // Let's get the codes from the objects into an array indexed by group for easy retrieval later. |
|
233 | + $codes_from_objs = array(); |
|
234 | + |
|
235 | + foreach ($shortcode_groups as $group) { |
|
236 | + $ref = ucwords(str_replace('_', ' ', $group)); |
|
237 | + $ref = str_replace(' ', '_', $ref); |
|
238 | + $classname = 'EE_' . $ref . '_Shortcodes'; |
|
239 | + if (class_exists($classname)) { |
|
240 | + $a = new ReflectionClass($classname); |
|
241 | + $obj = $a->newInstance(); |
|
242 | + $codes_from_objs[$group] = $obj->get_shortcodes(); |
|
243 | + } |
|
244 | + } |
|
245 | + |
|
246 | + |
|
247 | + //let's just replace the $mt shortcode group indexes with the actual shortcodes (unique) |
|
248 | + $final_mt_codes = array(); |
|
249 | + foreach ($mt_codes as $group) { |
|
250 | + $final_mt_codes = array_merge($final_mt_codes, $codes_from_objs[$group]); |
|
251 | + } |
|
252 | + |
|
253 | + $mt_codes = $final_mt_codes; |
|
254 | + |
|
255 | + |
|
256 | + // k now in this next loop we're going to loop through $msgr_validator again |
|
257 | + // and setup the _validators property from the data we've setup so far. |
|
258 | + foreach ($msgr_validator as $field => $config) { |
|
259 | + //if required shortcode is not in our list of codes for the given field, then we skip this field. |
|
260 | + $required = isset($config['required']) |
|
261 | + ? array_intersect($config['required'], array_keys($mt_codes)) |
|
262 | + : true; |
|
263 | + if (empty($required)) { |
|
264 | + continue; |
|
265 | + } |
|
266 | + |
|
267 | + //If we have an override then we use it to indicate the codes we want. |
|
268 | + if (isset($this->_valid_shortcodes_modifier[$context][$field])) { |
|
269 | + $this->_validators[$field]['shortcodes'] = $this->_reassemble_valid_shortcodes_from_group( |
|
270 | + $this->_valid_shortcodes_modifier[$context][$field], |
|
271 | + $codes_from_objs |
|
272 | + ); |
|
273 | + } //if we have specific shortcodes for a field then we need to use them |
|
274 | + elseif (isset($groups_per_field[$field])) { |
|
275 | + $this->_validators[$field]['shortcodes'] = $this->_reassemble_valid_shortcodes_from_group( |
|
276 | + $groups_per_field[$field], |
|
277 | + $codes_from_objs |
|
278 | + ); |
|
279 | + } //if empty config then we're assuming we're just going to use the shortcodes from the message type context |
|
280 | + elseif (empty($config)) { |
|
281 | + $this->_validators[$field]['shortcodes'] = $mt_codes; |
|
282 | + } //if we have specific shortcodes then we need to use them |
|
283 | + elseif (isset($config['specific_shortcodes'])) { |
|
284 | + $this->_validators[$field]['shortcodes'] = $config['specific_shortcodes']; |
|
285 | + } //otherwise the shortcodes are what is set by the messenger for that field |
|
286 | + else { |
|
287 | + foreach ($config['shortcodes'] as $group) { |
|
288 | + $this->_validators[$field]['shortcodes'] = isset($this->_validators[$field]['shortcodes']) |
|
289 | + ? array_merge($this->_validators[$field]['shortcodes'], $codes_from_objs[$group]) |
|
290 | + : $codes_from_objs[$group]; |
|
291 | + } |
|
292 | + } |
|
293 | + |
|
294 | + //now let's just make sure that any excluded specific shortcodes are removed. |
|
295 | + $specific_excludes = $this->get_specific_shortcode_excludes(); |
|
296 | + if (isset($specific_excludes[$field])) { |
|
297 | + foreach ($specific_excludes[$field] as $sex) { |
|
298 | + if (isset($this->_validators[$field]['shortcodes'][$sex])) { |
|
299 | + unset($this->_validators[$field]['shortcodes'][$sex]); |
|
300 | + } |
|
301 | + } |
|
302 | + } |
|
303 | + |
|
304 | + //hey! don't forget to include the type if present! |
|
305 | + $this->_validators[$field]['type'] = isset($config['type']) ? $config['type'] : null; |
|
306 | + } |
|
307 | + } |
|
308 | + |
|
309 | + |
|
310 | + /** |
|
311 | + * This just returns the validators property that contains information |
|
312 | + * about the various shortcodes and their availability with each field |
|
313 | + * |
|
314 | + * @return array |
|
315 | + */ |
|
316 | + public function get_validators() |
|
317 | + { |
|
318 | + return $this->_validators; |
|
319 | + } |
|
320 | + |
|
321 | + |
|
322 | + /** |
|
323 | + * This simply returns the specific shortcode_excludes property that is set. |
|
324 | + * |
|
325 | + * @since 4.5.0 |
|
326 | + * @return array |
|
327 | + */ |
|
328 | + public function get_specific_shortcode_excludes() |
|
329 | + { |
|
330 | + //specific validator filter |
|
331 | + $shortcode_excludes = apply_filters( |
|
332 | + 'FHEE__' . get_class($this) . '__get_specific_shortcode_excludes;', |
|
333 | + $this->_specific_shortcode_excludes, |
|
334 | + $this->_context |
|
335 | + ); |
|
336 | + //global filter |
|
337 | + return apply_filters( |
|
338 | + 'FHEE__EE_Messages_Validator__get_specific_shortcode_excludes', |
|
339 | + $shortcode_excludes, |
|
340 | + $this->_context, |
|
341 | + $this |
|
342 | + ); |
|
343 | + } |
|
344 | + |
|
345 | + |
|
346 | + /** |
|
347 | + * This is the main method that handles validation |
|
348 | + * What it does is loop through the _fields (the ones that get validated) |
|
349 | + * and checks them against the shortcodes array for the field and the 'type' indicated by the |
|
350 | + * |
|
351 | + * @access public |
|
352 | + * @return mixed (bool|array) if errors present we return the array otherwise true |
|
353 | + */ |
|
354 | + public function validate() |
|
355 | + { |
|
356 | + //some defaults |
|
357 | + $template_fields = $this->_messenger->get_template_fields(); |
|
358 | + //loop through the fields and check! |
|
359 | + foreach ($this->_fields as $field => $value) { |
|
360 | + $this->_errors[$field] = array(); |
|
361 | + $err_msg = ''; |
|
362 | + $field_label = ''; |
|
363 | + //if field is not present in the _validators array then we continue |
|
364 | + if (! isset($this->_validators[$field])) { |
|
365 | + unset($this->_errors[$field]); |
|
366 | + continue; |
|
367 | + } |
|
368 | + |
|
369 | + //get the translated field label! |
|
370 | + //first check if it's in the main fields list |
|
371 | + if (isset($template_fields[$field])) { |
|
372 | + if (empty($template_fields[$field])) { |
|
373 | + $field_label = $field; |
|
374 | + } //most likely the field is found in the 'extra' array. |
|
375 | + else { |
|
376 | + $field_label = $template_fields[$field]['label']; |
|
377 | + } |
|
378 | + } |
|
379 | + |
|
380 | + // if field label is empty OR is equal to the current field |
|
381 | + // then we need to loop through the 'extra' fields in the template_fields config (if present) |
|
382 | + if (isset($template_fields['extra']) && (empty($field_label) || $field_label === $field)) { |
|
383 | + foreach ($template_fields['extra'] as $main_field => $secondary_field) { |
|
384 | + foreach ($secondary_field as $name => $values) { |
|
385 | + if ($name === $field) { |
|
386 | + $field_label = $values['label']; |
|
387 | + } |
|
388 | + |
|
389 | + // if we've got a 'main' secondary field, let's see if that matches what field we're on |
|
390 | + // which means it contains the label for this field. |
|
391 | + if ($name === 'main' && $main_field === $field_label) { |
|
392 | + $field_label = $values['label']; |
|
393 | + } |
|
394 | + } |
|
395 | + } |
|
396 | + } |
|
397 | + |
|
398 | + //field is present. Let's validate shortcodes first (but only if shortcodes present). |
|
399 | + if (isset($this->_validators[$field]['shortcodes']) |
|
400 | + && ! empty($this->_validators[$field]['shortcodes']) |
|
401 | + ) { |
|
402 | + $invalid_shortcodes = $this->_invalid_shortcodes($value, $this->_validators[$field]['shortcodes']); |
|
403 | + // if true then that means there is a returned error message |
|
404 | + // that we'll need to add to the _errors array for this field. |
|
405 | + if ($invalid_shortcodes) { |
|
406 | + $v_s = array_keys($this->_validators[$field]['shortcodes']); |
|
407 | + $err_msg = sprintf( |
|
408 | + esc_html__( |
|
409 | + '%3$sThe following shortcodes were found in the "%1$s" field that ARE not valid: %2$s%4$s', |
|
410 | + 'event_espresso' |
|
411 | + ), |
|
412 | + '<strong>' . $field_label . '</strong>', |
|
413 | + $invalid_shortcodes, |
|
414 | + '<p>', |
|
415 | + '</p >' |
|
416 | + ); |
|
417 | + $err_msg .= sprintf( |
|
418 | + esc_html__('%2$sValid shortcodes for this field are: %1$s%3$s', 'event_espresso'), |
|
419 | + implode(', ', $v_s), |
|
420 | + '<strong>', |
|
421 | + '</strong>' |
|
422 | + ); |
|
423 | + } |
|
424 | + } |
|
425 | + |
|
426 | + //if there's a "type" to be validated then let's do that too. |
|
427 | + if (isset($this->_validators[$field]['type']) && ! empty($this->_validators[$field]['type'])) { |
|
428 | + switch ($this->_validators[$field]['type']) { |
|
429 | + case 'number': |
|
430 | + if (! is_numeric($value)) { |
|
431 | + $err_msg .= sprintf( |
|
432 | + esc_html__( |
|
433 | + '%3$sThe %1$s field is supposed to be a number. The value given (%2$s) is not. Please double-check and make sure the field contains a number%4$s', |
|
434 | + 'event_espresso' |
|
435 | + ), |
|
436 | + $field_label, |
|
437 | + $value, |
|
438 | + '<p>', |
|
439 | + '</p >' |
|
440 | + ); |
|
441 | + } |
|
442 | + break; |
|
443 | + case 'email': |
|
444 | + $valid_email = $this->_validate_email($value); |
|
445 | + if (! $valid_email) { |
|
446 | + $err_msg .= htmlentities( |
|
447 | + sprintf( |
|
448 | + esc_html__( |
|
449 | + 'The %1$s field has at least one string that is not a valid email address record. Valid emails are in the format: "Name <[email protected]>" or "[email protected]" and multiple emails can be separated by a comma.' |
|
450 | + ), |
|
451 | + $field_label |
|
452 | + |
|
453 | + ) |
|
454 | + ); |
|
455 | + } |
|
456 | + break; |
|
457 | + default: |
|
458 | + break; |
|
459 | + } |
|
460 | + } |
|
461 | + |
|
462 | + //if $err_msg isn't empty let's setup the _errors array for this field. |
|
463 | + if (! empty($err_msg)) { |
|
464 | + $this->_errors[$field]['msg'] = $err_msg; |
|
465 | + } else { |
|
466 | + unset($this->_errors[$field]); |
|
467 | + } |
|
468 | + } |
|
469 | + |
|
470 | + // if we have ANY errors, then we want to make sure we return the values |
|
471 | + // for ALL the fields so the user doesn't have to retype them all. |
|
472 | + if (! empty($this->_errors)) { |
|
473 | + foreach ($this->_fields as $field => $value) { |
|
474 | + $this->_errors[$field]['value'] = stripslashes($value); |
|
475 | + } |
|
476 | + } |
|
477 | + |
|
478 | + //return any errors or just TRUE if everything validates |
|
479 | + return empty($this->_errors) ? true : $this->_errors; |
|
480 | + } |
|
481 | + |
|
482 | + |
|
483 | + /** |
|
484 | + * Reassembles and returns an array of valid shortcodes |
|
485 | + * given the array of groups and array of shortcodes indexed by group. |
|
486 | + * |
|
487 | + * @param array $groups array of shortcode groups that we want shortcodes for |
|
488 | + * @param array $codes_from_objs All the codes available. |
|
489 | + * @return array an array of actual shortcodes (that will be used for validation). |
|
490 | + */ |
|
491 | + private function _reassemble_valid_shortcodes_from_group($groups, $codes_from_objs) |
|
492 | + { |
|
493 | + $shortcodes = array(); |
|
494 | + foreach ($groups as $group) { |
|
495 | + $shortcodes = array_merge($shortcodes, $codes_from_objs[$group]); |
|
496 | + } |
|
497 | + return $shortcodes; |
|
498 | + } |
|
499 | + |
|
500 | + |
|
501 | + /** |
|
502 | + * Validates a string against a list of accepted shortcodes |
|
503 | + * This function takes in an array of shortcodes |
|
504 | + * and makes sure that the given string ONLY contains shortcodes in that array. |
|
505 | + * |
|
506 | + * @param string $value string to evaluate |
|
507 | + * @param array $valid_shortcodes array of shortcodes that are acceptable. |
|
508 | + * @return mixed (bool|string) return either a list of invalid shortcodes OR false if the shortcodes validate. |
|
509 | + */ |
|
510 | + protected function _invalid_shortcodes($value, $valid_shortcodes) |
|
511 | + { |
|
512 | + //first we need to go through the string and get the shortcodes in the string |
|
513 | + preg_match_all('/(\[.+?\])/', $value, $matches); |
|
514 | + $incoming_shortcodes = (array)$matches[0]; |
|
515 | + |
|
516 | + //get a diff of the shortcodes in the string vs the valid shortcodes |
|
517 | + $diff = array_diff($incoming_shortcodes, array_keys($valid_shortcodes)); |
|
518 | + |
|
519 | + //we need to account for custom codes so let's loop through the diff and remove any of those type of codes |
|
520 | + foreach ($diff as $ind => $code) { |
|
521 | + if (preg_match('/(\[[A-Za-z0-9\_]+_\*)/', $code)) { |
|
522 | + //strip the shortcode so we just have the BASE string (i.e. [ANSWER_*] ) |
|
523 | + $dynamic_sc = preg_replace('/(_\*+.+)/', '_*]', $code); |
|
524 | + //does this exist in the $valid_shortcodes? If so then unset. |
|
525 | + if (isset($valid_shortcodes[$dynamic_sc])) { |
|
526 | + unset($diff[$ind]); |
|
527 | + } |
|
528 | + } |
|
529 | + } |
|
530 | + |
|
531 | + if (empty($diff)) { |
|
532 | + return false; |
|
533 | + } //there is no diff, we have no invalid shortcodes, so return |
|
534 | + |
|
535 | + //made it here? then let's assemble the error message |
|
536 | + $invalid_shortcodes = implode('</strong>,<strong>', $diff); |
|
537 | + $invalid_shortcodes = '<strong>' . $invalid_shortcodes . '</strong>'; |
|
538 | + return $invalid_shortcodes; |
|
539 | + } |
|
540 | + |
|
541 | + |
|
542 | + /** |
|
543 | + * Validates an incoming string and makes sure we have valid emails in the string. |
|
544 | + * |
|
545 | + * @param string $value incoming value to validate |
|
546 | + * @return bool true if the string validates, false if it doesn't |
|
547 | + */ |
|
548 | + protected function _validate_email($value) |
|
549 | + { |
|
550 | + $validate = true; |
|
551 | + $or_val = $value; |
|
552 | + |
|
553 | + // empty strings will validate because this is how a message template |
|
554 | + // for a particular context can be "turned off" (if there is no email then no message) |
|
555 | + if (empty($value)) { |
|
556 | + return $validate; |
|
557 | + } |
|
558 | + |
|
559 | + // first determine if there ARE any shortcodes. |
|
560 | + // If there are shortcodes and then later we find that there were no other valid emails |
|
561 | + // but the field isn't empty... |
|
562 | + // that means we've got extra commas that were left after stripping out shortcodes so probably still valid. |
|
563 | + $has_shortcodes = preg_match('/(\[.+?\])/', $value); |
|
564 | + |
|
565 | + //first we need to strip out all the shortcodes! |
|
566 | + $value = preg_replace('/(\[.+?\])/', '', $value); |
|
567 | + |
|
568 | + // if original value is not empty and new value is, then we've parsed out a shortcode |
|
569 | + // and we now have an empty string which DOES validate. |
|
570 | + // We also validate complete empty field for email because |
|
571 | + // its possible that this message is being "turned off" for a particular context |
|
572 | + |
|
573 | + |
|
574 | + if (! empty($or_val) && empty($value)) { |
|
575 | + return $validate; |
|
576 | + } |
|
577 | + |
|
578 | + //trim any commas from beginning and end of string ( after whitespace trimmed ); |
|
579 | + $value = trim(trim($value), ','); |
|
580 | + |
|
581 | + |
|
582 | + //next we need to split up the string if its comma delimited. |
|
583 | + $emails = explode(',', $value); |
|
584 | + $empty = false; //used to indicate that there is an empty comma. |
|
585 | + //now let's loop through the emails and do our checks |
|
586 | + foreach ($emails as $email) { |
|
587 | + if (empty($email)) { |
|
588 | + $empty = true; |
|
589 | + continue; |
|
590 | + } |
|
591 | + |
|
592 | + //trim whitespace |
|
593 | + $email = trim($email); |
|
594 | + //either its of type "[email protected]", or its of type "fname lname <[email protected]>" |
|
595 | + if (is_email($email)) { |
|
596 | + continue; |
|
597 | + } |
|
598 | + $matches = array(); |
|
599 | + $validate = preg_match('/(.*)<(.+)>/', $email, $matches) ? true : false; |
|
600 | + if ($validate && is_email($matches[2])) { |
|
601 | + continue; |
|
602 | + } |
|
603 | + return false; |
|
604 | + } |
|
605 | + |
|
606 | + $validate = $empty && ! $has_shortcodes ? false : $validate; |
|
607 | + |
|
608 | + return $validate; |
|
609 | + } |
|
610 | + |
|
611 | + |
|
612 | + /** |
|
613 | + * Magic getter |
|
614 | + * Using this to provide back compat with add-ons referencing deprecated properties. |
|
615 | + * |
|
616 | + * @param string $property Property being requested |
|
617 | + * @throws Exception |
|
618 | + * @return mixed |
|
619 | + */ |
|
620 | + public function __get($property) |
|
621 | + { |
|
622 | + $expected_properties_map = array( |
|
623 | + /** |
|
624 | + * @deprecated 4.9.0 |
|
625 | + */ |
|
626 | + '_MSGR' => '_messenger', |
|
627 | + /** |
|
628 | + * @deprecated 4.9.0 |
|
629 | + */ |
|
630 | + '_MSGTYP' => '_message_type', |
|
631 | + ); |
|
632 | + |
|
633 | + if (isset($expected_properties_map[$property])) { |
|
634 | + return $this->{$expected_properties_map[$property]}; |
|
635 | + } |
|
636 | + |
|
637 | + throw new Exception( |
|
638 | + sprintf( |
|
639 | + esc_html__('The property %1$s being requested on %2$s does not exist', 'event_espresso'), |
|
640 | + $property, |
|
641 | + get_class($this) |
|
642 | + ) |
|
643 | + ); |
|
644 | + } |
|
645 | 645 | } |
@@ -160,9 +160,9 @@ discard block |
||
160 | 160 | //load messenger |
161 | 161 | $messenger = ucwords(str_replace('_', ' ', $this->_m_name)); |
162 | 162 | $messenger = str_replace(' ', '_', $messenger); |
163 | - $messenger = 'EE_' . $messenger . '_messenger'; |
|
163 | + $messenger = 'EE_'.$messenger.'_messenger'; |
|
164 | 164 | |
165 | - if (! class_exists($messenger)) { |
|
165 | + if ( ! class_exists($messenger)) { |
|
166 | 166 | throw new EE_Error( |
167 | 167 | sprintf( |
168 | 168 | esc_html__('There is no messenger class for the given string (%s)', 'event_espresso'), |
@@ -176,9 +176,9 @@ discard block |
||
176 | 176 | //load message type |
177 | 177 | $message_type = ucwords(str_replace('_', ' ', $this->_mt_name)); |
178 | 178 | $message_type = str_replace(' ', '_', $message_type); |
179 | - $message_type = 'EE_' . $message_type . '_message_type'; |
|
179 | + $message_type = 'EE_'.$message_type.'_message_type'; |
|
180 | 180 | |
181 | - if (! class_exists($message_type)) { |
|
181 | + if ( ! class_exists($message_type)) { |
|
182 | 182 | throw new EE_Error( |
183 | 183 | sprintf( |
184 | 184 | esc_html__('There is no message type class for the given string (%s)', 'event_espresso'), |
@@ -235,7 +235,7 @@ discard block |
||
235 | 235 | foreach ($shortcode_groups as $group) { |
236 | 236 | $ref = ucwords(str_replace('_', ' ', $group)); |
237 | 237 | $ref = str_replace(' ', '_', $ref); |
238 | - $classname = 'EE_' . $ref . '_Shortcodes'; |
|
238 | + $classname = 'EE_'.$ref.'_Shortcodes'; |
|
239 | 239 | if (class_exists($classname)) { |
240 | 240 | $a = new ReflectionClass($classname); |
241 | 241 | $obj = $a->newInstance(); |
@@ -329,7 +329,7 @@ discard block |
||
329 | 329 | { |
330 | 330 | //specific validator filter |
331 | 331 | $shortcode_excludes = apply_filters( |
332 | - 'FHEE__' . get_class($this) . '__get_specific_shortcode_excludes;', |
|
332 | + 'FHEE__'.get_class($this).'__get_specific_shortcode_excludes;', |
|
333 | 333 | $this->_specific_shortcode_excludes, |
334 | 334 | $this->_context |
335 | 335 | ); |
@@ -361,7 +361,7 @@ discard block |
||
361 | 361 | $err_msg = ''; |
362 | 362 | $field_label = ''; |
363 | 363 | //if field is not present in the _validators array then we continue |
364 | - if (! isset($this->_validators[$field])) { |
|
364 | + if ( ! isset($this->_validators[$field])) { |
|
365 | 365 | unset($this->_errors[$field]); |
366 | 366 | continue; |
367 | 367 | } |
@@ -409,7 +409,7 @@ discard block |
||
409 | 409 | '%3$sThe following shortcodes were found in the "%1$s" field that ARE not valid: %2$s%4$s', |
410 | 410 | 'event_espresso' |
411 | 411 | ), |
412 | - '<strong>' . $field_label . '</strong>', |
|
412 | + '<strong>'.$field_label.'</strong>', |
|
413 | 413 | $invalid_shortcodes, |
414 | 414 | '<p>', |
415 | 415 | '</p >' |
@@ -427,7 +427,7 @@ discard block |
||
427 | 427 | if (isset($this->_validators[$field]['type']) && ! empty($this->_validators[$field]['type'])) { |
428 | 428 | switch ($this->_validators[$field]['type']) { |
429 | 429 | case 'number': |
430 | - if (! is_numeric($value)) { |
|
430 | + if ( ! is_numeric($value)) { |
|
431 | 431 | $err_msg .= sprintf( |
432 | 432 | esc_html__( |
433 | 433 | '%3$sThe %1$s field is supposed to be a number. The value given (%2$s) is not. Please double-check and make sure the field contains a number%4$s', |
@@ -442,7 +442,7 @@ discard block |
||
442 | 442 | break; |
443 | 443 | case 'email': |
444 | 444 | $valid_email = $this->_validate_email($value); |
445 | - if (! $valid_email) { |
|
445 | + if ( ! $valid_email) { |
|
446 | 446 | $err_msg .= htmlentities( |
447 | 447 | sprintf( |
448 | 448 | esc_html__( |
@@ -460,7 +460,7 @@ discard block |
||
460 | 460 | } |
461 | 461 | |
462 | 462 | //if $err_msg isn't empty let's setup the _errors array for this field. |
463 | - if (! empty($err_msg)) { |
|
463 | + if ( ! empty($err_msg)) { |
|
464 | 464 | $this->_errors[$field]['msg'] = $err_msg; |
465 | 465 | } else { |
466 | 466 | unset($this->_errors[$field]); |
@@ -469,7 +469,7 @@ discard block |
||
469 | 469 | |
470 | 470 | // if we have ANY errors, then we want to make sure we return the values |
471 | 471 | // for ALL the fields so the user doesn't have to retype them all. |
472 | - if (! empty($this->_errors)) { |
|
472 | + if ( ! empty($this->_errors)) { |
|
473 | 473 | foreach ($this->_fields as $field => $value) { |
474 | 474 | $this->_errors[$field]['value'] = stripslashes($value); |
475 | 475 | } |
@@ -511,7 +511,7 @@ discard block |
||
511 | 511 | { |
512 | 512 | //first we need to go through the string and get the shortcodes in the string |
513 | 513 | preg_match_all('/(\[.+?\])/', $value, $matches); |
514 | - $incoming_shortcodes = (array)$matches[0]; |
|
514 | + $incoming_shortcodes = (array) $matches[0]; |
|
515 | 515 | |
516 | 516 | //get a diff of the shortcodes in the string vs the valid shortcodes |
517 | 517 | $diff = array_diff($incoming_shortcodes, array_keys($valid_shortcodes)); |
@@ -534,7 +534,7 @@ discard block |
||
534 | 534 | |
535 | 535 | //made it here? then let's assemble the error message |
536 | 536 | $invalid_shortcodes = implode('</strong>,<strong>', $diff); |
537 | - $invalid_shortcodes = '<strong>' . $invalid_shortcodes . '</strong>'; |
|
537 | + $invalid_shortcodes = '<strong>'.$invalid_shortcodes.'</strong>'; |
|
538 | 538 | return $invalid_shortcodes; |
539 | 539 | } |
540 | 540 | |
@@ -571,7 +571,7 @@ discard block |
||
571 | 571 | // its possible that this message is being "turned off" for a particular context |
572 | 572 | |
573 | 573 | |
574 | - if (! empty($or_val) && empty($value)) { |
|
574 | + if ( ! empty($or_val) && empty($value)) { |
|
575 | 575 | return $validate; |
576 | 576 | } |
577 | 577 |