Completed
Branch yet-another-batch-of-ui-fixes (371f49)
by
unknown
30:27 queued 22:46
created
core/services/request/RequestParams.php 2 patches
Spacing   +16 added lines, -16 removed lines patch added patch discarded remove patch
@@ -17,13 +17,13 @@  discard block
 block discarded – undo
17 17
      * Used for matches() and parameterDrillDown()
18 18
      * 'bool' will return true or false if match is found or not
19 19
      */
20
-    const RETURN_BOOL  = 'bool';
20
+    const RETURN_BOOL = 'bool';
21 21
 
22 22
     /**
23 23
      * Used for matches() and parameterDrillDown()
24 24
      * 'key' will return the first key found that matches the supplied pattern
25 25
      */
26
-    const RETURN_KEY   = 'key';
26
+    const RETURN_KEY = 'key';
27 27
 
28 28
     /**
29 29
      * Used for matches() and parameterDrillDown()
@@ -113,7 +113,7 @@  discard block
 block discarded – undo
113 113
     {
114 114
         // don't allow "ee" to be overwritten unless explicitly instructed to do so
115 115
         if ($override_ee || $key !== 'ee' || empty($this->request['ee'])) {
116
-            $this->request[ $key ] = $value;
116
+            $this->request[$key] = $value;
117 117
         }
118 118
     }
119 119
 
@@ -237,7 +237,7 @@  discard block
 block discarded – undo
237 237
             preg_quote($pattern, '/')
238 238
         );
239 239
         foreach ($request_params as $key => $request_param) {
240
-            if (preg_match('/^' . $pattern . '$/is', $key)) {
240
+            if (preg_match('/^'.$pattern.'$/is', $key)) {
241 241
                 // return value for request param
242 242
                 if ($return === self::RETURN_VALUE) {
243 243
                     return $request_param;
@@ -299,30 +299,30 @@  discard block
 block discarded – undo
299 299
                 $key      = $real_key ?: $key;
300 300
             }
301 301
             // check if top level key exists
302
-            if (isset($request_params[ $key ])) {
302
+            if (isset($request_params[$key])) {
303 303
                 // build a new key to pass along like: 'second[third]'
304 304
                 // or just 'second' depending on depth of keys
305 305
                 $key_string = array_shift($keys);
306
-                if (! empty($keys)) {
307
-                    $key_string .= '[' . implode('][', $keys) . ']';
306
+                if ( ! empty($keys)) {
307
+                    $key_string .= '['.implode('][', $keys).']';
308 308
                 }
309 309
                 return $this->parameterDrillDown(
310 310
                     $key_string,
311 311
                     $default,
312 312
                     $callback,
313 313
                     $return,
314
-                    $request_params[ $key ]
314
+                    $request_params[$key]
315 315
                 );
316 316
             }
317 317
         }
318 318
         if ($callback === 'is_set') {
319
-            return isset($request_params[ $key ]);
319
+            return isset($request_params[$key]);
320 320
         }
321 321
         if ($callback === 'match') {
322 322
             return $this->match($key, $request_params, $default, $return);
323 323
         }
324
-        return isset($request_params[ $key ])
325
-            ? $request_params[ $key ]
324
+        return isset($request_params[$key])
325
+            ? $request_params[$key]
326 326
             : $default;
327 327
     }
328 328
 
@@ -336,12 +336,12 @@  discard block
 block discarded – undo
336 336
     public function unSetRequestParam($key, $unset_from_global_too = false)
337 337
     {
338 338
         // because unset may not actually remove var
339
-        $this->get[ $key ]     = null;
340
-        $this->post[ $key ]    = null;
341
-        $this->request[ $key ] = null;
342
-        unset($this->get[ $key ], $this->post[ $key ], $this->request[ $key ]);
339
+        $this->get[$key]     = null;
340
+        $this->post[$key]    = null;
341
+        $this->request[$key] = null;
342
+        unset($this->get[$key], $this->post[$key], $this->request[$key]);
343 343
         if ($unset_from_global_too) {
344
-            unset($_GET[ $key ], $_POST[ $key ], $_REQUEST[ $key ]);
344
+            unset($_GET[$key], $_POST[$key], $_REQUEST[$key]);
345 345
         }
346 346
     }
347 347
 
Please login to merge, or discard this patch.
Indentation   +353 added lines, -353 removed lines patch added patch discarded remove patch
@@ -13,357 +13,357 @@
 block discarded – undo
13 13
  */
14 14
 class RequestParams
15 15
 {
16
-    /**
17
-     * Used for matches() and parameterDrillDown()
18
-     * 'bool' will return true or false if match is found or not
19
-     */
20
-    const RETURN_BOOL  = 'bool';
21
-
22
-    /**
23
-     * Used for matches() and parameterDrillDown()
24
-     * 'key' will return the first key found that matches the supplied pattern
25
-     */
26
-    const RETURN_KEY   = 'key';
27
-
28
-    /**
29
-     * Used for matches() and parameterDrillDown()
30
-     * 'value' will return the value for the first request parameter
31
-     */
32
-    const RETURN_VALUE = 'value';
33
-
34
-    /**
35
-     * $_GET parameters
36
-     *
37
-     * @var array
38
-     */
39
-    protected $get;
40
-
41
-    /**
42
-     * $_POST parameters
43
-     *
44
-     * @var array
45
-     */
46
-    protected $post;
47
-
48
-    /**
49
-     * $_REQUEST parameters
50
-     *
51
-     * @var array
52
-     */
53
-    protected $request;
54
-
55
-    /**
56
-     * @var RequestSanitizer
57
-     */
58
-    protected $sanitizer;
59
-
60
-
61
-    /**
62
-     * RequestParams constructor.
63
-     *
64
-     * @param RequestSanitizer $sanitizer
65
-     * @param array            $get
66
-     * @param array            $post
67
-     */
68
-    public function __construct(RequestSanitizer $sanitizer, array $get = [], array $post = [])
69
-    {
70
-        $this->sanitizer = $sanitizer;
71
-        $this->get       = ! empty($get) ? $get : $_GET;
72
-        $this->post      = ! empty($post) ? $post : $_POST;
73
-        $this->request   = array_merge($this->get, $this->post);
74
-    }
75
-
76
-
77
-    /**
78
-     * @return array
79
-     */
80
-    public function getParams()
81
-    {
82
-        return $this->get;
83
-    }
84
-
85
-
86
-    /**
87
-     * @return array
88
-     */
89
-    public function postParams()
90
-    {
91
-        return $this->post;
92
-    }
93
-
94
-
95
-    /**
96
-     * returns contents of $_REQUEST
97
-     *
98
-     * @return array
99
-     */
100
-    public function requestParams()
101
-    {
102
-        return $this->request;
103
-    }
104
-
105
-
106
-    /**
107
-     * @param string     $key
108
-     * @param mixed|null $value
109
-     * @param bool       $override_ee
110
-     * @return    void
111
-     */
112
-    public function setRequestParam($key, $value, $override_ee = false)
113
-    {
114
-        // don't allow "ee" to be overwritten unless explicitly instructed to do so
115
-        if ($override_ee || $key !== 'ee' || empty($this->request['ee'])) {
116
-            $this->request[ $key ] = $value;
117
-        }
118
-    }
119
-
120
-
121
-    /**
122
-     * merges the incoming array of parameters into the existing request parameters
123
-     *
124
-     * @param array $request_params
125
-     * @return void
126
-     * @since   4.10.24.p
127
-     */
128
-    public function mergeRequestParams(array $request_params)
129
-    {
130
-        $this->request = array_merge($this->request, $request_params);
131
-    }
132
-
133
-
134
-    /**
135
-     * returns   the value for a request param if the given key exists
136
-     *
137
-     * @param string     $key
138
-     * @param mixed|null $default
139
-     * @param string     $type      the expected data type for the parameter's value, ie: string, int, bool, etc.
140
-     *                              DataType::ARRAY should only be used to indicate an array containing mixed types,
141
-     *                              ideally another data type should be selected to indicate the contents of the array,
142
-     *                              and then $is_array should be set to true. ie: an array of integers would be:
143
-     *                                  $type = DataType::INT
144
-     *                                  $is_array = true
145
-     * @param bool       $is_array  if true, then parameter value will be treated as an array of $type
146
-     * @param string     $delimiter for CSV type strings that should be returned as an array
147
-     * @return array|bool|float|int|string
148
-     */
149
-    public function getRequestParam($key, $default = null, $type = DataType::STRING, $is_array = false, $delimiter = '')
150
-    {
151
-        // ensure $is_array is true if the data type is set as such
152
-        $is_array = $type === DataType::ARRAY ? true : $is_array;
153
-        $param = $this->sanitizer->clean(
154
-            $this->parameterDrillDown($key, $default, 'get'),
155
-            $type,
156
-            $is_array,
157
-            $delimiter
158
-        );
159
-        // don't convert final return value to something else if an array is expected
160
-        $type = $is_array ? DataType::ARRAY : $type;
161
-        return DataType::setDataType($param, $type);
162
-    }
163
-
164
-
165
-    /**
166
-     * check if param exists
167
-     *
168
-     * @param string $key
169
-     * @return bool
170
-     */
171
-    public function requestParamIsSet($key)
172
-    {
173
-        return (bool) $this->parameterDrillDown($key);
174
-    }
175
-
176
-
177
-    /**
178
-     * check if a request parameter exists whose key that matches the supplied wildcard pattern
179
-     * and return the value for the first match found
180
-     * wildcards can be either of the following:
181
-     *      ? to represent a single character of any type
182
-     *      * to represent one or more characters of any type
183
-     *
184
-     * @param string     $pattern
185
-     * @param mixed|null $default
186
-     * @param string     $type      the expected data type for the parameter's value, ie: string, int, bool, etc
187
-     * @param bool       $is_array  if true, then parameter value will be treated as an array of $type
188
-     * @param string     $delimiter for CSV type strings that should be returned as an array
189
-     * @return array|bool|float|int|string
190
-     */
191
-    public function getMatch($pattern, $default = null, $type = DataType::STRING, $is_array = false, $delimiter = '')
192
-    {
193
-        $param = $this->sanitizer->clean(
194
-            $this->parameterDrillDown($pattern, $default, 'match'),
195
-            $type,
196
-            $is_array,
197
-            $delimiter
198
-        );
199
-        $type = $is_array ? 'array' : $type;
200
-        return DataType::setDataType($param, $type);
201
-    }
202
-
203
-
204
-    /**
205
-     * check if a request parameter exists whose key matches the supplied wildcard pattern
206
-     * wildcards can be either of the following:
207
-     *      ? to represent a single character of any type
208
-     *      * to represent one or more characters of any type
209
-     * returns true if a match is found or false if not
210
-     *
211
-     * @param string $pattern
212
-     * @return bool
213
-     */
214
-    public function matches($pattern)
215
-    {
216
-        return (bool) $this->parameterDrillDown($pattern, false, 'match', self::RETURN_BOOL);
217
-    }
218
-
219
-
220
-    /**
221
-     * @see https://stackoverflow.com/questions/6163055/php-string-matching-with-wildcard
222
-     * @param string $pattern               A string including wildcards to be converted to a regex pattern
223
-     *                                      and used to search through the current request's parameter keys
224
-     * @param array  $request_params        The array of request parameters to search through
225
-     * @param mixed  $default               [optional] The value to be returned if no match is found.
226
-     *                                      Default is null
227
-     * @param string $return                [optional] Controls what kind of value is returned.
228
-     *                                      Options are the RETURN_* constants:
229
-     *                                      RETURN_BOOL will return true or false if match is found or not
230
-     *                                      RETURN_KEY will return the first key found that matches the supplied pattern
231
-     *                                      RETURN_VALUE will return the value for the first request parameter
232
-     *                                      whose key matches the supplied pattern
233
-     *                                      Default is 'value'
234
-     * @return boolean|string
235
-     */
236
-    private function match($pattern, array $request_params, $default = null, $return = self::RETURN_VALUE)
237
-    {
238
-        $return = in_array($return, [self::RETURN_BOOL, self::RETURN_KEY, self::RETURN_VALUE], true)
239
-            ? $return
240
-            : 'is_set';
241
-        // replace wildcard chars with regex chars
242
-        $pattern = str_replace(
243
-            ['\*', '\?'],
244
-            ['.*', '.'],
245
-            preg_quote($pattern, '/')
246
-        );
247
-        foreach ($request_params as $key => $request_param) {
248
-            if (preg_match('/^' . $pattern . '$/is', $key)) {
249
-                // return value for request param
250
-                if ($return === self::RETURN_VALUE) {
251
-                    return $request_param;
252
-                }
253
-                // or actual key or true just to indicate it was found
254
-                return $return === self::RETURN_KEY ? $key : true;
255
-            }
256
-        }
257
-        // match not found so return default value or false
258
-        return $return === self::RETURN_VALUE ? $default : false;
259
-    }
260
-
261
-
262
-    /**
263
-     * the supplied key can be a simple string to represent a "top-level" request parameter
264
-     * or represent a key for a request parameter that is nested deeper within the request parameter array,
265
-     * by using square brackets to surround keys for deeper array elements.
266
-     * For example :
267
-     * if the supplied $key was: "first[second][third]"
268
-     * then this will attempt to drill down into the request parameter array to find a value.
269
-     * Given the following request parameters:
270
-     *  array(
271
-     *      'first' => array(
272
-     *          'second' => array(
273
-     *              'third' => 'has a value'
274
-     *          )
275
-     *      )
276
-     *  )
277
-     * would return true if default parameters were set
278
-     *
279
-     * @param string $callback
280
-     * @param        $key
281
-     * @param null   $default
282
-     * @param string $return
283
-     * @param mixed  $request_params
284
-     * @return bool|mixed|null
285
-     */
286
-    private function parameterDrillDown(
287
-        $key,
288
-        $default = null,
289
-        $callback = 'is_set',
290
-        $return = self::RETURN_VALUE,
291
-        $request_params = []
292
-    ) {
293
-        $callback       = in_array($callback, ['is_set', 'get', 'match'], true)
294
-            ? $callback
295
-            : 'is_set';
296
-        $request_params = ! empty($request_params)
297
-            ? $request_params
298
-            : $this->request;
299
-        // does incoming key represent an array like 'first[second][third]'  ?
300
-        if (strpos($key, '[') !== false) {
301
-            // turn it into an actual array
302
-            $key  = str_replace(']', '', $key);
303
-            $keys = explode('[', $key);
304
-            $key  = array_shift($keys);
305
-            if ($callback === 'match') {
306
-                $real_key = $this->match($key, $request_params, $default, self::RETURN_KEY);
307
-                $key      = $real_key ?: $key;
308
-            }
309
-            // check if top level key exists
310
-            if (isset($request_params[ $key ])) {
311
-                // build a new key to pass along like: 'second[third]'
312
-                // or just 'second' depending on depth of keys
313
-                $key_string = array_shift($keys);
314
-                if (! empty($keys)) {
315
-                    $key_string .= '[' . implode('][', $keys) . ']';
316
-                }
317
-                return $this->parameterDrillDown(
318
-                    $key_string,
319
-                    $default,
320
-                    $callback,
321
-                    $return,
322
-                    $request_params[ $key ]
323
-                );
324
-            }
325
-        }
326
-        if ($callback === 'is_set') {
327
-            return isset($request_params[ $key ]);
328
-        }
329
-        if ($callback === 'match') {
330
-            return $this->match($key, $request_params, $default, $return);
331
-        }
332
-        return isset($request_params[ $key ])
333
-            ? $request_params[ $key ]
334
-            : $default;
335
-    }
336
-
337
-
338
-    /**
339
-     * remove param
340
-     *
341
-     * @param      $key
342
-     * @param bool $unset_from_global_too
343
-     */
344
-    public function unSetRequestParam($key, $unset_from_global_too = false)
345
-    {
346
-        // because unset may not actually remove var
347
-        $this->get[ $key ]     = null;
348
-        $this->post[ $key ]    = null;
349
-        $this->request[ $key ] = null;
350
-        unset($this->get[ $key ], $this->post[ $key ], $this->request[ $key ]);
351
-        if ($unset_from_global_too) {
352
-            unset($_GET[ $key ], $_POST[ $key ], $_REQUEST[ $key ]);
353
-        }
354
-    }
355
-
356
-
357
-    /**
358
-     * remove params
359
-     *
360
-     * @param array $keys
361
-     * @param bool  $unset_from_global_too
362
-     */
363
-    public function unSetRequestParams(array $keys, $unset_from_global_too = false)
364
-    {
365
-        foreach ($keys as $key) {
366
-            $this->unSetRequestParam($key, $unset_from_global_too);
367
-        }
368
-    }
16
+	/**
17
+	 * Used for matches() and parameterDrillDown()
18
+	 * 'bool' will return true or false if match is found or not
19
+	 */
20
+	const RETURN_BOOL  = 'bool';
21
+
22
+	/**
23
+	 * Used for matches() and parameterDrillDown()
24
+	 * 'key' will return the first key found that matches the supplied pattern
25
+	 */
26
+	const RETURN_KEY   = 'key';
27
+
28
+	/**
29
+	 * Used for matches() and parameterDrillDown()
30
+	 * 'value' will return the value for the first request parameter
31
+	 */
32
+	const RETURN_VALUE = 'value';
33
+
34
+	/**
35
+	 * $_GET parameters
36
+	 *
37
+	 * @var array
38
+	 */
39
+	protected $get;
40
+
41
+	/**
42
+	 * $_POST parameters
43
+	 *
44
+	 * @var array
45
+	 */
46
+	protected $post;
47
+
48
+	/**
49
+	 * $_REQUEST parameters
50
+	 *
51
+	 * @var array
52
+	 */
53
+	protected $request;
54
+
55
+	/**
56
+	 * @var RequestSanitizer
57
+	 */
58
+	protected $sanitizer;
59
+
60
+
61
+	/**
62
+	 * RequestParams constructor.
63
+	 *
64
+	 * @param RequestSanitizer $sanitizer
65
+	 * @param array            $get
66
+	 * @param array            $post
67
+	 */
68
+	public function __construct(RequestSanitizer $sanitizer, array $get = [], array $post = [])
69
+	{
70
+		$this->sanitizer = $sanitizer;
71
+		$this->get       = ! empty($get) ? $get : $_GET;
72
+		$this->post      = ! empty($post) ? $post : $_POST;
73
+		$this->request   = array_merge($this->get, $this->post);
74
+	}
75
+
76
+
77
+	/**
78
+	 * @return array
79
+	 */
80
+	public function getParams()
81
+	{
82
+		return $this->get;
83
+	}
84
+
85
+
86
+	/**
87
+	 * @return array
88
+	 */
89
+	public function postParams()
90
+	{
91
+		return $this->post;
92
+	}
93
+
94
+
95
+	/**
96
+	 * returns contents of $_REQUEST
97
+	 *
98
+	 * @return array
99
+	 */
100
+	public function requestParams()
101
+	{
102
+		return $this->request;
103
+	}
104
+
105
+
106
+	/**
107
+	 * @param string     $key
108
+	 * @param mixed|null $value
109
+	 * @param bool       $override_ee
110
+	 * @return    void
111
+	 */
112
+	public function setRequestParam($key, $value, $override_ee = false)
113
+	{
114
+		// don't allow "ee" to be overwritten unless explicitly instructed to do so
115
+		if ($override_ee || $key !== 'ee' || empty($this->request['ee'])) {
116
+			$this->request[ $key ] = $value;
117
+		}
118
+	}
119
+
120
+
121
+	/**
122
+	 * merges the incoming array of parameters into the existing request parameters
123
+	 *
124
+	 * @param array $request_params
125
+	 * @return void
126
+	 * @since   4.10.24.p
127
+	 */
128
+	public function mergeRequestParams(array $request_params)
129
+	{
130
+		$this->request = array_merge($this->request, $request_params);
131
+	}
132
+
133
+
134
+	/**
135
+	 * returns   the value for a request param if the given key exists
136
+	 *
137
+	 * @param string     $key
138
+	 * @param mixed|null $default
139
+	 * @param string     $type      the expected data type for the parameter's value, ie: string, int, bool, etc.
140
+	 *                              DataType::ARRAY should only be used to indicate an array containing mixed types,
141
+	 *                              ideally another data type should be selected to indicate the contents of the array,
142
+	 *                              and then $is_array should be set to true. ie: an array of integers would be:
143
+	 *                                  $type = DataType::INT
144
+	 *                                  $is_array = true
145
+	 * @param bool       $is_array  if true, then parameter value will be treated as an array of $type
146
+	 * @param string     $delimiter for CSV type strings that should be returned as an array
147
+	 * @return array|bool|float|int|string
148
+	 */
149
+	public function getRequestParam($key, $default = null, $type = DataType::STRING, $is_array = false, $delimiter = '')
150
+	{
151
+		// ensure $is_array is true if the data type is set as such
152
+		$is_array = $type === DataType::ARRAY ? true : $is_array;
153
+		$param = $this->sanitizer->clean(
154
+			$this->parameterDrillDown($key, $default, 'get'),
155
+			$type,
156
+			$is_array,
157
+			$delimiter
158
+		);
159
+		// don't convert final return value to something else if an array is expected
160
+		$type = $is_array ? DataType::ARRAY : $type;
161
+		return DataType::setDataType($param, $type);
162
+	}
163
+
164
+
165
+	/**
166
+	 * check if param exists
167
+	 *
168
+	 * @param string $key
169
+	 * @return bool
170
+	 */
171
+	public function requestParamIsSet($key)
172
+	{
173
+		return (bool) $this->parameterDrillDown($key);
174
+	}
175
+
176
+
177
+	/**
178
+	 * check if a request parameter exists whose key that matches the supplied wildcard pattern
179
+	 * and return the value for the first match found
180
+	 * wildcards can be either of the following:
181
+	 *      ? to represent a single character of any type
182
+	 *      * to represent one or more characters of any type
183
+	 *
184
+	 * @param string     $pattern
185
+	 * @param mixed|null $default
186
+	 * @param string     $type      the expected data type for the parameter's value, ie: string, int, bool, etc
187
+	 * @param bool       $is_array  if true, then parameter value will be treated as an array of $type
188
+	 * @param string     $delimiter for CSV type strings that should be returned as an array
189
+	 * @return array|bool|float|int|string
190
+	 */
191
+	public function getMatch($pattern, $default = null, $type = DataType::STRING, $is_array = false, $delimiter = '')
192
+	{
193
+		$param = $this->sanitizer->clean(
194
+			$this->parameterDrillDown($pattern, $default, 'match'),
195
+			$type,
196
+			$is_array,
197
+			$delimiter
198
+		);
199
+		$type = $is_array ? 'array' : $type;
200
+		return DataType::setDataType($param, $type);
201
+	}
202
+
203
+
204
+	/**
205
+	 * check if a request parameter exists whose key matches the supplied wildcard pattern
206
+	 * wildcards can be either of the following:
207
+	 *      ? to represent a single character of any type
208
+	 *      * to represent one or more characters of any type
209
+	 * returns true if a match is found or false if not
210
+	 *
211
+	 * @param string $pattern
212
+	 * @return bool
213
+	 */
214
+	public function matches($pattern)
215
+	{
216
+		return (bool) $this->parameterDrillDown($pattern, false, 'match', self::RETURN_BOOL);
217
+	}
218
+
219
+
220
+	/**
221
+	 * @see https://stackoverflow.com/questions/6163055/php-string-matching-with-wildcard
222
+	 * @param string $pattern               A string including wildcards to be converted to a regex pattern
223
+	 *                                      and used to search through the current request's parameter keys
224
+	 * @param array  $request_params        The array of request parameters to search through
225
+	 * @param mixed  $default               [optional] The value to be returned if no match is found.
226
+	 *                                      Default is null
227
+	 * @param string $return                [optional] Controls what kind of value is returned.
228
+	 *                                      Options are the RETURN_* constants:
229
+	 *                                      RETURN_BOOL will return true or false if match is found or not
230
+	 *                                      RETURN_KEY will return the first key found that matches the supplied pattern
231
+	 *                                      RETURN_VALUE will return the value for the first request parameter
232
+	 *                                      whose key matches the supplied pattern
233
+	 *                                      Default is 'value'
234
+	 * @return boolean|string
235
+	 */
236
+	private function match($pattern, array $request_params, $default = null, $return = self::RETURN_VALUE)
237
+	{
238
+		$return = in_array($return, [self::RETURN_BOOL, self::RETURN_KEY, self::RETURN_VALUE], true)
239
+			? $return
240
+			: 'is_set';
241
+		// replace wildcard chars with regex chars
242
+		$pattern = str_replace(
243
+			['\*', '\?'],
244
+			['.*', '.'],
245
+			preg_quote($pattern, '/')
246
+		);
247
+		foreach ($request_params as $key => $request_param) {
248
+			if (preg_match('/^' . $pattern . '$/is', $key)) {
249
+				// return value for request param
250
+				if ($return === self::RETURN_VALUE) {
251
+					return $request_param;
252
+				}
253
+				// or actual key or true just to indicate it was found
254
+				return $return === self::RETURN_KEY ? $key : true;
255
+			}
256
+		}
257
+		// match not found so return default value or false
258
+		return $return === self::RETURN_VALUE ? $default : false;
259
+	}
260
+
261
+
262
+	/**
263
+	 * the supplied key can be a simple string to represent a "top-level" request parameter
264
+	 * or represent a key for a request parameter that is nested deeper within the request parameter array,
265
+	 * by using square brackets to surround keys for deeper array elements.
266
+	 * For example :
267
+	 * if the supplied $key was: "first[second][third]"
268
+	 * then this will attempt to drill down into the request parameter array to find a value.
269
+	 * Given the following request parameters:
270
+	 *  array(
271
+	 *      'first' => array(
272
+	 *          'second' => array(
273
+	 *              'third' => 'has a value'
274
+	 *          )
275
+	 *      )
276
+	 *  )
277
+	 * would return true if default parameters were set
278
+	 *
279
+	 * @param string $callback
280
+	 * @param        $key
281
+	 * @param null   $default
282
+	 * @param string $return
283
+	 * @param mixed  $request_params
284
+	 * @return bool|mixed|null
285
+	 */
286
+	private function parameterDrillDown(
287
+		$key,
288
+		$default = null,
289
+		$callback = 'is_set',
290
+		$return = self::RETURN_VALUE,
291
+		$request_params = []
292
+	) {
293
+		$callback       = in_array($callback, ['is_set', 'get', 'match'], true)
294
+			? $callback
295
+			: 'is_set';
296
+		$request_params = ! empty($request_params)
297
+			? $request_params
298
+			: $this->request;
299
+		// does incoming key represent an array like 'first[second][third]'  ?
300
+		if (strpos($key, '[') !== false) {
301
+			// turn it into an actual array
302
+			$key  = str_replace(']', '', $key);
303
+			$keys = explode('[', $key);
304
+			$key  = array_shift($keys);
305
+			if ($callback === 'match') {
306
+				$real_key = $this->match($key, $request_params, $default, self::RETURN_KEY);
307
+				$key      = $real_key ?: $key;
308
+			}
309
+			// check if top level key exists
310
+			if (isset($request_params[ $key ])) {
311
+				// build a new key to pass along like: 'second[third]'
312
+				// or just 'second' depending on depth of keys
313
+				$key_string = array_shift($keys);
314
+				if (! empty($keys)) {
315
+					$key_string .= '[' . implode('][', $keys) . ']';
316
+				}
317
+				return $this->parameterDrillDown(
318
+					$key_string,
319
+					$default,
320
+					$callback,
321
+					$return,
322
+					$request_params[ $key ]
323
+				);
324
+			}
325
+		}
326
+		if ($callback === 'is_set') {
327
+			return isset($request_params[ $key ]);
328
+		}
329
+		if ($callback === 'match') {
330
+			return $this->match($key, $request_params, $default, $return);
331
+		}
332
+		return isset($request_params[ $key ])
333
+			? $request_params[ $key ]
334
+			: $default;
335
+	}
336
+
337
+
338
+	/**
339
+	 * remove param
340
+	 *
341
+	 * @param      $key
342
+	 * @param bool $unset_from_global_too
343
+	 */
344
+	public function unSetRequestParam($key, $unset_from_global_too = false)
345
+	{
346
+		// because unset may not actually remove var
347
+		$this->get[ $key ]     = null;
348
+		$this->post[ $key ]    = null;
349
+		$this->request[ $key ] = null;
350
+		unset($this->get[ $key ], $this->post[ $key ], $this->request[ $key ]);
351
+		if ($unset_from_global_too) {
352
+			unset($_GET[ $key ], $_POST[ $key ], $_REQUEST[ $key ]);
353
+		}
354
+	}
355
+
356
+
357
+	/**
358
+	 * remove params
359
+	 *
360
+	 * @param array $keys
361
+	 * @param bool  $unset_from_global_too
362
+	 */
363
+	public function unSetRequestParams(array $keys, $unset_from_global_too = false)
364
+	{
365
+		foreach ($keys as $key) {
366
+			$this->unSetRequestParam($key, $unset_from_global_too);
367
+		}
368
+	}
369 369
 }
Please login to merge, or discard this patch.
admin_pages/messages/templates/shortcode_selector_skeleton.template.php 2 patches
Indentation   +5 added lines, -5 removed lines patch added patch discarded remove patch
@@ -28,14 +28,14 @@
 block discarded – undo
28 28
         </h6>
29 29
         <h4>
30 30
             <?php
31
-            printf(
32
-                esc_html__('"%1$s" field', 'event_espresso'),
33
-                esc_attr($fieldname)
34
-            ); ?>
31
+			printf(
32
+				esc_html__('"%1$s" field', 'event_espresso'),
33
+				esc_attr($fieldname)
34
+			); ?>
35 35
         </h4>
36 36
         <ul>
37 37
         <?php
38
-        foreach (array_keys($shortcodes) as $shortcode) : ?>
38
+		foreach (array_keys($shortcodes) as $shortcode) : ?>
39 39
             <li>
40 40
                 <span class="js-shortcode-selection"
41 41
                       data-linked-input-id="<?php echo esc_attr($linked_input_id); ?>"
Please login to merge, or discard this patch.
Spacing   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -10,7 +10,7 @@
 block discarded – undo
10 10
  * @type    string $linked_input_id The name of the input that the shortcode gets inserted to.
11 11
  */
12 12
 
13
-if (! empty($shortcodes)) : ?>
13
+if ( ! empty($shortcodes)) : ?>
14 14
 <div class="ee-messages-shortcodes-chooser-wrap">
15 15
     <button class="button button--secondary button--icon-only ee-messages-shortcodes-chooser js-open-list-trigger"
16 16
             aria-label="<?php echo esc_html__('open shortcode selector', 'event_espresso'); ?>"
Please login to merge, or discard this patch.
admin_pages/venues/Venues_Admin_Page.core.php 2 patches
Spacing   +34 added lines, -34 removed lines patch added patch discarded remove patch
@@ -45,10 +45,10 @@  discard block
 block discarded – undo
45 45
      */
46 46
     protected function _init_page_props()
47 47
     {
48
-        require_once(EE_MODELS . 'EEM_Venue.model.php');
48
+        require_once(EE_MODELS.'EEM_Venue.model.php');
49 49
         $this->page_slug        = EE_VENUES_PG_SLUG;
50 50
         $this->_admin_base_url  = EE_VENUES_ADMIN_URL;
51
-        $this->_admin_base_path = EE_ADMIN_PAGES . 'venues';
51
+        $this->_admin_base_path = EE_ADMIN_PAGES.'venues';
52 52
         $this->page_label       = esc_html__('Event Venues', 'event_espresso');
53 53
         $this->_cpt_model_names = [
54 54
             'create_new' => 'EEM_Venue',
@@ -466,7 +466,7 @@  discard block
 block discarded – undo
466 466
 
467 467
     public function load_scripts_styles()
468 468
     {
469
-        wp_register_style('ee-cat-admin', EVENTS_ASSETS_URL . 'ee-cat-admin.css', [], EVENT_ESPRESSO_VERSION);
469
+        wp_register_style('ee-cat-admin', EVENTS_ASSETS_URL.'ee-cat-admin.css', [], EVENT_ESPRESSO_VERSION);
470 470
         wp_enqueue_style('ee-cat-admin');
471 471
     }
472 472
 
@@ -488,7 +488,7 @@  discard block
 block discarded – undo
488 488
         wp_enqueue_style('espresso-ui-theme');
489 489
         wp_register_style(
490 490
             'espresso_venues',
491
-            EE_VENUES_ASSETS_URL . 'ee-venues-admin.css',
491
+            EE_VENUES_ASSETS_URL.'ee-venues-admin.css',
492 492
             [],
493 493
             EVENT_ESPRESSO_VERSION
494 494
         );
@@ -551,14 +551,14 @@  discard block
 block discarded – undo
551 551
             'button'
552 552
         );
553 553
 
554
-        $this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
554
+        $this->_admin_page_title .= ' '.$this->get_action_link_or_button(
555 555
             'create_new',
556 556
             'add',
557 557
             [],
558 558
             'add-new-h2'
559 559
         );
560 560
 
561
-        $this->_search_btn_label  = esc_html__('Venues', 'event_espresso');
561
+        $this->_search_btn_label = esc_html__('Venues', 'event_espresso');
562 562
         $this->display_admin_list_table_page_with_sidebar();
563 563
     }
564 564
 
@@ -574,7 +574,7 @@  discard block
 block discarded – undo
574 574
             'vnu_url'      => $this->_cpt_model_obj->get_f('VNU_url'),
575 575
             'vnu_phone'    => $this->_cpt_model_obj->get_f('VNU_phone'),
576 576
         ];
577
-        $template   = EE_VENUES_TEMPLATE_PATH . 'venue_publish_box_extras.template.php';
577
+        $template = EE_VENUES_TEMPLATE_PATH.'venue_publish_box_extras.template.php';
578 578
         EEH_Template::display_template($template, $extra_rows);
579 579
     }
580 580
 
@@ -638,7 +638,7 @@  discard block
 block discarded – undo
638 638
         $this->_set_add_edit_form_tags('update_google_map_settings');
639 639
         $this->_set_publish_post_box_vars(null, false, false, null, false);
640 640
         $this->_template_args['admin_page_content'] = EEH_Template::display_template(
641
-            EE_VENUES_TEMPLATE_PATH . 'google_map.template.php',
641
+            EE_VENUES_TEMPLATE_PATH.'google_map.template.php',
642 642
             $this->_template_args,
643 643
             true
644 644
         );
@@ -734,7 +734,7 @@  discard block
 block discarded – undo
734 734
             ),
735 735
             'vnu_google_map_link' => $this->_cpt_model_obj->google_map_link(),
736 736
         ];
737
-        $template      = EE_VENUES_TEMPLATE_PATH . 'venue_gmap_metabox_content.template.php';
737
+        $template = EE_VENUES_TEMPLATE_PATH.'venue_gmap_metabox_content.template.php';
738 738
         EEH_Template::display_template($template, $template_args);
739 739
     }
740 740
 
@@ -747,7 +747,7 @@  discard block
 block discarded – undo
747 747
     {
748 748
         $template_args['_venue'] = $this->_cpt_model_obj;
749 749
 
750
-        $template_args['states_dropdown']    = EEH_Form_Fields::generate_form_input(
750
+        $template_args['states_dropdown'] = EEH_Form_Fields::generate_form_input(
751 751
             new EE_Question_Form_Input(
752 752
                 EE_Question::new_instance(
753 753
                     ['QST_display_text' => esc_html__('State', 'event_espresso'), 'QST_system' => 'state']
@@ -790,7 +790,7 @@  discard block
 block discarded – undo
790 790
             )
791 791
         );
792 792
 
793
-        $template = EE_VENUES_TEMPLATE_PATH . 'venue_address_metabox_content.template.php';
793
+        $template = EE_VENUES_TEMPLATE_PATH.'venue_address_metabox_content.template.php';
794 794
         EEH_Template::display_template($template, $template_args);
795 795
     }
796 796
 
@@ -800,7 +800,7 @@  discard block
 block discarded – undo
800 800
         $template_args = [
801 801
             '_venue' => $this->_cpt_model_obj,
802 802
         ];
803
-        $template      = EE_VENUES_TEMPLATE_PATH . 'venue_virtual_location_metabox_content.template.php';
803
+        $template      = EE_VENUES_TEMPLATE_PATH.'venue_virtual_location_metabox_content.template.php';
804 804
         EEH_Template::display_template($template, $template_args);
805 805
     }
806 806
 
@@ -825,7 +825,7 @@  discard block
 block discarded – undo
825 825
     {
826 826
 
827 827
         if ($post instanceof WP_Post && $post->post_type !== 'espresso_venues') {
828
-            return;// get out we're not processing the saving of venues.
828
+            return; // get out we're not processing the saving of venues.
829 829
         }
830 830
 
831 831
         $wheres = [$this->_venue_model->primary_key_name() => $post_id];
@@ -860,7 +860,7 @@  discard block
 block discarded – undo
860 860
             'FHEE__Venues_Admin_Page___insert_update_cpt_item__venue_update_callbacks',
861 861
             []
862 862
         );
863
-        $att_success            = true;
863
+        $att_success = true;
864 864
         foreach ($venue_update_callbacks as $v_callback) {
865 865
             // if ANY of these updates fail then we want the appropriate global error message
866 866
             $att_success = call_user_func_array($v_callback, [$venue, $this->request->requestParams()])
@@ -945,7 +945,7 @@  discard block
 block discarded – undo
945 945
             // clean status
946 946
             $venue_status = sanitize_key($venue_status);
947 947
             // grab status
948
-            if (! empty($venue_status)) {
948
+            if ( ! empty($venue_status)) {
949 949
                 $success = $this->_change_venue_status($VNU_ID, $venue_status);
950 950
             } else {
951 951
                 $success = false;
@@ -980,7 +980,7 @@  discard block
 block discarded – undo
980 980
         // clean status
981 981
         $venue_status = sanitize_key($venue_status);
982 982
         // grab status
983
-        if (! empty($venue_status)) {
983
+        if ( ! empty($venue_status)) {
984 984
             $success = true;
985 985
             // determine the event id and set to array.
986 986
             $VNU_IDs = $this->request->getRequestParam('venue_id', [], 'int', true);
@@ -1033,7 +1033,7 @@  discard block
 block discarded – undo
1033 1033
     private function _change_venue_status($VNU_ID = 0, $venue_status = '')
1034 1034
     {
1035 1035
         // grab venue id
1036
-        if (! $VNU_ID) {
1036
+        if ( ! $VNU_ID) {
1037 1037
             $msg = esc_html__('An error occurred. No Venue ID or an invalid Venue ID was received.', 'event_espresso');
1038 1038
             EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1039 1039
             return false;
@@ -1044,7 +1044,7 @@  discard block
 block discarded – undo
1044 1044
         // clean status
1045 1045
         $venue_status = sanitize_key($venue_status);
1046 1046
         // grab status
1047
-        if (! $venue_status) {
1047
+        if ( ! $venue_status) {
1048 1048
             $msg = esc_html__(
1049 1049
                 'An error occurred. No Venue Status or an invalid Venue Status was received.',
1050 1050
                 'event_espresso'
@@ -1156,7 +1156,7 @@  discard block
 block discarded – undo
1156 1156
     private function _delete_or_trash_venue($VNU_ID = false)
1157 1157
     {
1158 1158
         // grab event id
1159
-        if (! $VNU_ID = absint($VNU_ID)) {
1159
+        if ( ! $VNU_ID = absint($VNU_ID)) {
1160 1160
             $msg = esc_html__('An error occurred. No Venue ID or an invalid Venue ID was received.', 'event_espresso');
1161 1161
             EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1162 1162
             return false;
@@ -1244,10 +1244,10 @@  discard block
 block discarded – undo
1244 1244
         }
1245 1245
 
1246 1246
 
1247
-        if (! EE_Registry::instance()->CAP->current_user_can('ee_read_others_venues', 'get_venues')) {
1247
+        if ( ! EE_Registry::instance()->CAP->current_user_can('ee_read_others_venues', 'get_venues')) {
1248 1248
             $where['VNU_wp_user'] = get_current_user_id();
1249 1249
         } else {
1250
-            if (! EE_Registry::instance()->CAP->current_user_can('ee_read_private_venues', 'get_venues')) {
1250
+            if ( ! EE_Registry::instance()->CAP->current_user_can('ee_read_private_venues', 'get_venues')) {
1251 1251
                 $where['OR'] = [
1252 1252
                     'status*restrict_private' => ['!=', 'private'],
1253 1253
                     'AND'                     => [
@@ -1260,7 +1260,7 @@  discard block
 block discarded – undo
1260 1260
 
1261 1261
         $search_term = $this->request->getRequestParam('s');
1262 1262
         if ($search_term) {
1263
-            $search_term = '%' . $search_term . '%';
1263
+            $search_term = '%'.$search_term.'%';
1264 1264
             $where['OR'] = [
1265 1265
                 'VNU_name'               => ['LIKE', $search_term],
1266 1266
                 'VNU_desc'               => ['LIKE', $search_term],
@@ -1311,14 +1311,14 @@  discard block
 block discarded – undo
1311 1311
 
1312 1312
         // only set if we've got an id
1313 1313
         $category_ID = $this->request->getRequestParam('VEN_CAT_ID', 0, 'int');
1314
-        if (! $category_ID) {
1314
+        if ( ! $category_ID) {
1315 1315
             return;
1316 1316
         }
1317 1317
 
1318 1318
         $term = get_term($category_ID, 'espresso_venue_categories');
1319 1319
 
1320 1320
 
1321
-        if (! empty($term)) {
1321
+        if ( ! empty($term)) {
1322 1322
             $this->_category->category_name       = $term->name;
1323 1323
             $this->_category->category_identifier = $term->slug;
1324 1324
             $this->_category->category_desc       = $term->description;
@@ -1342,7 +1342,7 @@  discard block
 block discarded – undo
1342 1342
     protected function _category_list_table()
1343 1343
     {
1344 1344
         do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1345
-        $this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
1345
+        $this->_admin_page_title .= ' '.$this->get_action_link_or_button(
1346 1346
             'add_category',
1347 1347
             'add_category',
1348 1348
             [],
@@ -1388,7 +1388,7 @@  discard block
 block discarded – undo
1388 1388
             'class'         => 'my_editor_custom',
1389 1389
             'wpeditor_args' => ['media_buttons' => false],
1390 1390
         ];
1391
-        $_wp_editor                   = $this->_generate_admin_form_fields($editor_args, 'array');
1391
+        $_wp_editor = $this->_generate_admin_form_fields($editor_args, 'array');
1392 1392
 
1393 1393
         $all_terms = get_terms(
1394 1394
             ['espresso_venue_categories'],
@@ -1412,7 +1412,7 @@  discard block
 block discarded – undo
1412 1412
             $category_select_values,
1413 1413
             $this->_category->parent
1414 1414
         );
1415
-        $template_args   = [
1415
+        $template_args = [
1416 1416
             'category'                 => $this->_category,
1417 1417
             'category_select'          => $category_select,
1418 1418
             'unique_id_info_help_link' => $this->_get_help_tab_link('unique_id_info'),
@@ -1420,7 +1420,7 @@  discard block
 block discarded – undo
1420 1420
             'disable'                  => '',
1421 1421
             'disabled_message'         => false,
1422 1422
         ];
1423
-        $template        = EVENTS_TEMPLATE_PATH . 'event_category_details.template.php';
1423
+        $template = EVENTS_TEMPLATE_PATH.'event_category_details.template.php';
1424 1424
         return EEH_Template::display_template($template, $template_args, true);
1425 1425
     }
1426 1426
 
@@ -1500,7 +1500,7 @@  discard block
 block discarded – undo
1500 1500
                 $term_args
1501 1501
             );
1502 1502
 
1503
-        if (! is_array($insert_ids)) {
1503
+        if ( ! is_array($insert_ids)) {
1504 1504
             EE_Error::add_error(
1505 1505
                 esc_html__('An error occurred and the category has not been saved to the database.', 'event_espresso'),
1506 1506
                 __FILE__,
@@ -1537,8 +1537,8 @@  discard block
 block discarded – undo
1537 1537
             ]
1538 1538
         );
1539 1539
 
1540
-        if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
1541
-            require_once(EE_CLASSES . 'EE_Export.class.php');
1540
+        if (is_readable(EE_CLASSES.'EE_Export.class.php')) {
1541
+            require_once(EE_CLASSES.'EE_Export.class.php');
1542 1542
             $EE_Export = EE_Export::instance($this->request->requestParams());
1543 1543
             $EE_Export->export();
1544 1544
         }
@@ -1548,7 +1548,7 @@  discard block
 block discarded – undo
1548 1548
     protected function _import_categories()
1549 1549
     {
1550 1550
 
1551
-        require_once(EE_CLASSES . 'EE_Import.class.php');
1551
+        require_once(EE_CLASSES.'EE_Import.class.php');
1552 1552
         EE_Import::instance()->import();
1553 1553
     }
1554 1554
 
@@ -1566,7 +1566,7 @@  discard block
 block discarded – undo
1566 1566
         $where       = ['taxonomy' => 'espresso_venue_categories'];
1567 1567
         $search_term = $this->request->getRequestParam('s');
1568 1568
         if ($search_term) {
1569
-            $search_term = '%' . $search_term . '%';
1569
+            $search_term = '%'.$search_term.'%';
1570 1570
             $where['OR'] = [
1571 1571
                 'Term.name'   => ['LIKE', $search_term],
1572 1572
                 'description' => ['LIKE', $search_term],
@@ -1576,7 +1576,7 @@  discard block
 block discarded – undo
1576 1576
         $query_params = [
1577 1577
             $where,
1578 1578
             'order_by'   => [$orderby => $order],
1579
-            'limit'      => $limit . ',' . $per_page,
1579
+            'limit'      => $limit.','.$per_page,
1580 1580
             'force_join' => ['Term'],
1581 1581
         ];
1582 1582
 
Please login to merge, or discard this patch.
Indentation   +1563 added lines, -1563 removed lines patch added patch discarded remove patch
@@ -13,1573 +13,1573 @@
 block discarded – undo
13 13
  */
14 14
 class Venues_Admin_Page extends EE_Admin_Page_CPT
15 15
 {
16
-    /**
17
-     * _venue
18
-     * This will hold the venue object for venue_details screen.
19
-     *
20
-     * @access protected
21
-     * @var object
22
-     */
23
-    protected $_venue;
24
-
25
-
26
-    /**
27
-     * This will hold the category object for category_details screen.
28
-     *
29
-     * @var object
30
-     */
31
-    protected $_category;
32
-
33
-
34
-    /**
35
-     * This property will hold the venue model instance
36
-     *
37
-     * @var object
38
-     */
39
-    protected $_venue_model;
40
-
41
-
42
-    /**
43
-     * @throws EE_Error
44
-     */
45
-    protected function _init_page_props()
46
-    {
47
-        require_once(EE_MODELS . 'EEM_Venue.model.php');
48
-        $this->page_slug        = EE_VENUES_PG_SLUG;
49
-        $this->_admin_base_url  = EE_VENUES_ADMIN_URL;
50
-        $this->_admin_base_path = EE_ADMIN_PAGES . 'venues';
51
-        $this->page_label       = esc_html__('Event Venues', 'event_espresso');
52
-        $this->_cpt_model_names = [
53
-            'create_new' => 'EEM_Venue',
54
-            'edit'       => 'EEM_Venue',
55
-        ];
56
-        $this->_cpt_edit_routes = [
57
-            'espresso_venues' => 'edit',
58
-        ];
59
-        $this->_venue_model     = EEM_Venue::instance();
60
-    }
61
-
62
-
63
-    protected function _ajax_hooks()
64
-    {
65
-        // todo: all hooks for ee_venues ajax goes in here.
66
-    }
67
-
68
-
69
-    protected function _define_page_props()
70
-    {
71
-        $this->_admin_page_title = $this->page_label;
72
-        $this->_labels           = [
73
-            'buttons'      => [
74
-                'add'             => esc_html__('Add New Venue', 'event_espresso'),
75
-                'edit'            => esc_html__('Edit Venue', 'event_espresso'),
76
-                'delete'          => esc_html__('Delete Venue', 'event_espresso'),
77
-                'add_category'    => esc_html__('Add New Category', 'event_espresso'),
78
-                'edit_category'   => esc_html__('Edit Category', 'event_espresso'),
79
-                'delete_category' => esc_html__('Delete Category', 'event_espresso'),
80
-            ],
81
-            'editor_title' => [
82
-                'espresso_venues' => esc_html__('Enter Venue name here', 'event_espresso'),
83
-            ],
84
-            'publishbox'   => [
85
-                'create_new'          => esc_html__('Save New Venue', 'event_espresso'),
86
-                'edit'                => esc_html__('Update Venue', 'event_espresso'),
87
-                'add_category'        => esc_html__('Save New Category', 'event_espresso'),
88
-                'edit_category'       => esc_html__('Update Category', 'event_espresso'),
89
-                'google_map_settings' => esc_html__('Update Settings', 'event_espresso'),
90
-            ],
91
-        ];
92
-    }
93
-
94
-
95
-    protected function _set_page_routes()
96
-    {
97
-
98
-        // load formatter helper
99
-        // load field generator helper
100
-
101
-        // is there a vnu_id in the request?
102
-        $VNU_ID = $this->request->getRequestParam('VNU_ID', 0, 'int');
103
-        $VNU_ID = $this->request->getRequestParam('post', $VNU_ID, 'int');
104
-
105
-        $this->_page_routes = [
106
-            'default'                    => [
107
-                'func'       => '_overview_list_table',
108
-                'capability' => 'ee_read_venues',
109
-            ],
110
-            'create_new'                 => [
111
-                'func'       => '_create_new_cpt_item',
112
-                'capability' => 'ee_edit_venues',
113
-            ],
114
-            'edit'                       => [
115
-                'func'       => '_edit_cpt_item',
116
-                'capability' => 'ee_edit_venue',
117
-                'obj_id'     => $VNU_ID,
118
-            ],
119
-            'trash_venue'                => [
120
-                'func'       => '_trash_or_restore_venue',
121
-                'args'       => ['venue_status' => 'trash'],
122
-                'noheader'   => true,
123
-                'capability' => 'ee_delete_venue',
124
-                'obj_id'     => $VNU_ID,
125
-            ],
126
-            'trash_venues'               => [
127
-                'func'       => '_trash_or_restore_venues',
128
-                'args'       => ['venue_status' => 'trash'],
129
-                'noheader'   => true,
130
-                'capability' => 'ee_delete_venues',
131
-            ],
132
-            'restore_venue'              => [
133
-                'func'       => '_trash_or_restore_venue',
134
-                'args'       => ['venue_status' => 'draft'],
135
-                'noheader'   => true,
136
-                'capability' => 'ee_delete_venue',
137
-                'obj_id'     => $VNU_ID,
138
-            ],
139
-            'restore_venues'             => [
140
-                'func'       => '_trash_or_restore_venues',
141
-                'args'       => ['venue_status' => 'draft'],
142
-                'noheader'   => true,
143
-                'capability' => 'ee_delete_venues',
144
-            ],
145
-            'delete_venues'              => [
146
-                'func'       => '_delete_venues',
147
-                'noheader'   => true,
148
-                'capability' => 'ee_delete_venues',
149
-            ],
150
-            'delete_venue'               => [
151
-                'func'       => '_delete_venue',
152
-                'noheader'   => true,
153
-                'capability' => 'ee_delete_venue',
154
-                'obj_id'     => $VNU_ID,
155
-            ],
156
-            // settings related
157
-            'google_map_settings'        => [
158
-                'func'       => '_google_map_settings',
159
-                'capability' => 'manage_options',
160
-            ],
161
-            'update_google_map_settings' => [
162
-                'func'       => '_update_google_map_settings',
163
-                'capability' => 'manage_options',
164
-                'noheader'   => true,
165
-            ],
166
-            // venue category tab related
167
-            'add_category'               => [
168
-                'func'       => '_category_details',
169
-                'args'       => ['add'],
170
-                'capability' => 'ee_edit_venue_category',
171
-            ],
172
-            'edit_category'              => [
173
-                'func'       => '_category_details',
174
-                'args'       => ['edit'],
175
-                'capability' => 'ee_edit_venue_category',
176
-            ],
177
-            'delete_categories'          => [
178
-                'func'       => '_delete_categories',
179
-                'noheader'   => true,
180
-                'capability' => 'ee_delete_venue_category',
181
-            ],
182
-
183
-            'delete_category' => [
184
-                'func'       => '_delete_categories',
185
-                'noheader'   => true,
186
-                'capability' => 'ee_delete_venue_category',
187
-            ],
188
-
189
-            'insert_category' => [
190
-                'func'       => '_insert_or_update_category',
191
-                'args'       => ['new_category' => true],
192
-                'noheader'   => true,
193
-                'capability' => 'ee_edit_venue_category',
194
-            ],
195
-
196
-            'update_category'   => [
197
-                'func'       => '_insert_or_update_category',
198
-                'args'       => ['new_category' => false],
199
-                'noheader'   => true,
200
-                'capability' => 'ee_edit_venue_category',
201
-            ],
202
-            'export_categories' => [
203
-                'func'       => '_categories_export',
204
-                'noheader'   => true,
205
-                'capability' => 'export',
206
-            ],
207
-            'import_categories' => [
208
-                'func'       => '_import_categories',
209
-                'capability' => 'import',
210
-            ],
211
-            'category_list'     => [
212
-                'func'       => '_category_list_table',
213
-                'capability' => 'ee_manage_venue_categories',
214
-            ],
215
-        ];
216
-    }
217
-
218
-
219
-    protected function _set_page_config()
220
-    {
221
-        $VNU_ID     = $this->request->getRequestParam('post', 0, 'int');
222
-        $EVT_CAT_ID = $this->request->getRequestParam('EVT_CAT_ID', 0, 'int');
223
-
224
-        $this->_page_config = [
225
-            'default'             => [
226
-                'nav'           => [
227
-                    'label' => esc_html__('Overview', 'event_espresso'),
228
-                    'icon' => 'dashicons-list-view',
229
-                    'order' => 10,
230
-                ],
231
-                'list_table'    => 'Venues_Admin_List_Table',
232
-                'help_tabs'     => [
233
-                    'venues_overview_help_tab'                           => [
234
-                        'title'    => esc_html__('Venues Overview', 'event_espresso'),
235
-                        'filename' => 'venues_overview',
236
-                    ],
237
-                    'venues_overview_table_column_headings_help_tab'     => [
238
-                        'title'    => esc_html__('Venues Overview Table Column Headings', 'event_espresso'),
239
-                        'filename' => 'venues_overview_table_column_headings',
240
-                    ],
241
-                    'venues_overview_views_bulk_actions_search_help_tab' => [
242
-                        'title'    => esc_html__('Venues Overview Views & Bulk Actions & Search', 'event_espresso'),
243
-                        'filename' => 'venues_overview_views_bulk_actions_search',
244
-                    ],
245
-                ],
246
-                'metaboxes'     => ['_espresso_news_post_box', '_espresso_links_post_box'],
247
-                'require_nonce' => false,
248
-            ],
249
-            'create_new'          => [
250
-                'nav'           => [
251
-                    'label'      => esc_html__('Add Venue', 'event_espresso'),
252
-                    'icon' => 'dashicons-plus-alt',
253
-                    'order'      => 15,
254
-                    'persistent' => false,
255
-                ],
256
-                'help_tabs'     => [
257
-                    'venues_editor_help_tab'                                               => [
258
-                        'title'    => esc_html__('Venue Editor', 'event_espresso'),
259
-                        'filename' => 'venues_editor',
260
-                    ],
261
-                    'venues_editor_title_richtexteditor_help_tab'                          => [
262
-                        'title'    => esc_html__('Venue Title & Rich Text Editor', 'event_espresso'),
263
-                        'filename' => 'venues_editor_title_richtexteditor',
264
-                    ],
265
-                    'venues_editor_tags_categories_help_tab'                               => [
266
-                        'title'    => esc_html__('Venue Tags & Categories', 'event_espresso'),
267
-                        'filename' => 'venues_editor_tags_categories',
268
-                    ],
269
-                    'venues_editor_physical_location_google_map_virtual_location_help_tab' => [
270
-                        'title'    => esc_html__(
271
-                            'Venue Editor Physical Location & Google Map & Virtual Location',
272
-                            'event_espresso'
273
-                        ),
274
-                        'filename' => 'venues_editor_physical_location_google_map_virtual_location',
275
-                    ],
276
-                    'venues_editor_save_new_venue_help_tab'                                => [
277
-                        'title'    => esc_html__('Save New Venue', 'event_espresso'),
278
-                        'filename' => 'venues_editor_save_new_venue',
279
-                    ],
280
-                    'venues_editor_other_help_tab'                                         => [
281
-                        'title'    => esc_html__('Venue Editor Other', 'event_espresso'),
282
-                        'filename' => 'venues_editor_other',
283
-                    ],
284
-                ],
285
-                'metaboxes'     => ['_venue_editor_metaboxes'],
286
-                'require_nonce' => false,
287
-            ],
288
-            'edit'                => [
289
-                'nav'           => [
290
-                    'label'      => esc_html__('Edit Venue', 'event_espresso'),
291
-                    'icon' => 'dashicons-edit-large',
292
-                    'order'      => 15,
293
-                    'persistent' => false,
294
-                    'url'        => $VNU_ID
295
-                        ? add_query_arg(['post' => $VNU_ID], $this->_current_page_view_url)
296
-                        : $this->_admin_base_url,
297
-                ],
298
-                'help_tabs'     => [
299
-                    'venues_editor_help_tab'                                               => [
300
-                        'title'    => esc_html__('Venue Editor', 'event_espresso'),
301
-                        'filename' => 'venues_editor',
302
-                    ],
303
-                    'venues_editor_title_richtexteditor_help_tab'                          => [
304
-                        'title'    => esc_html__('Venue Title & Rich Text Editor', 'event_espresso'),
305
-                        'filename' => 'venues_editor_title_richtexteditor',
306
-                    ],
307
-                    'venues_editor_tags_categories_help_tab'                               => [
308
-                        'title'    => esc_html__('Venue Tags & Categories', 'event_espresso'),
309
-                        'filename' => 'venues_editor_tags_categories',
310
-                    ],
311
-                    'venues_editor_physical_location_google_map_virtual_location_help_tab' => [
312
-                        'title'    => esc_html__(
313
-                            'Venue Editor Physical Location & Google Map & Virtual Location',
314
-                            'event_espresso'
315
-                        ),
316
-                        'filename' => 'venues_editor_physical_location_google_map_virtual_location',
317
-                    ],
318
-                    'venues_editor_save_new_venue_help_tab'                                => [
319
-                        'title'    => esc_html__('Save New Venue', 'event_espresso'),
320
-                        'filename' => 'venues_editor_save_new_venue',
321
-                    ],
322
-                    'venues_editor_other_help_tab'                                         => [
323
-                        'title'    => esc_html__('Venue Editor Other', 'event_espresso'),
324
-                        'filename' => 'venues_editor_other',
325
-                    ],
326
-                ],
327
-                'metaboxes'     => ['_venue_editor_metaboxes'],
328
-                'require_nonce' => false,
329
-            ],
330
-            'google_map_settings' => [
331
-                'nav'           => [
332
-                    'label' => esc_html__('Google Maps', 'event_espresso'),
333
-                    'icon' => 'dashicons-location-alt',
334
-                    'order' => 40,
335
-                ],
336
-                'metaboxes'     => array_merge($this->_default_espresso_metaboxes, ['_publish_post_box']),
337
-                'help_tabs'     => [
338
-                    'general_settings_google_maps_help_tab' => [
339
-                        'title'    => esc_html__('Google Maps', 'event_espresso'),
340
-                        'filename' => 'general_settings_google_maps',
341
-                    ],
342
-                ],
343
-                'require_nonce' => false,
344
-            ],
345
-            // venue category stuff
346
-            'add_category'        => [
347
-                'nav'           => [
348
-                    'label'      => esc_html__('Add Category', 'event_espresso'),
349
-                    'icon' => 'dashicons-plus-alt',
350
-                    'order'      => 25,
351
-                    'persistent' => false,
352
-                ],
353
-                'metaboxes'     => ['_publish_post_box'],
354
-                'help_tabs'     => [
355
-                    'venues_add_category_help_tab' => [
356
-                        'title'    => esc_html__('Add New Venue Category', 'event_espresso'),
357
-                        'filename' => 'venues_add_category',
358
-                    ],
359
-                ],
360
-                'require_nonce' => false,
361
-            ],
362
-            'edit_category'       => [
363
-                'nav'           => [
364
-                    'label'      => esc_html__('Edit Category', 'event_espresso'),
365
-                    'icon' => 'dashicons-edit-large',
366
-                    'order'      => 25,
367
-                    'persistent' => false,
368
-                    'url'        => $EVT_CAT_ID
369
-                        ? add_query_arg(['EVT_CAT_ID' => $EVT_CAT_ID], $this->_current_page_view_url)
370
-                        : $this->_admin_base_url,
371
-                ],
372
-                'metaboxes'     => ['_publish_post_box'],
373
-                'help_tabs'     => [
374
-                    'venues_edit_category_help_tab' => [
375
-                        'title'    => esc_html__('Edit Venue Category', 'event_espresso'),
376
-                        'filename' => 'venues_edit_category',
377
-                    ],
378
-                ],
379
-                'require_nonce' => false,
380
-            ],
381
-            'category_list'       => [
382
-                'nav'           => [
383
-                    'label' => esc_html__('Categories', 'event_espresso'),
384
-                    'icon' => 'dashicons-networking',
385
-                    'order' => 20,
386
-                ],
387
-                'list_table'    => 'Venue_Categories_Admin_List_Table',
388
-                'help_tabs'     => [
389
-                    'venues_categories_help_tab'                       => [
390
-                        'title'    => esc_html__('Venue Categories', 'event_espresso'),
391
-                        'filename' => 'venues_categories',
392
-                    ],
393
-                    'venues_categories_table_column_headings_help_tab' => [
394
-                        'title'    => esc_html__('Venue Categories Table Column Headings', 'event_espresso'),
395
-                        'filename' => 'venues_categories_table_column_headings',
396
-                    ],
397
-                    'venues_categories_views_help_tab'                 => [
398
-                        'title'    => esc_html__('Venue Categories Views', 'event_espresso'),
399
-                        'filename' => 'venues_categories_views',
400
-                    ],
401
-                    'venues_categories_other_help_tab'                 => [
402
-                        'title'    => esc_html__('Venue Categories Other', 'event_espresso'),
403
-                        'filename' => 'venues_categories_other',
404
-                    ],
405
-                ],
406
-                'metaboxes'     => $this->_default_espresso_metaboxes,
407
-                'require_nonce' => false,
408
-            ],
409
-        ];
410
-    }
411
-
412
-
413
-    protected function _add_screen_options()
414
-    {
415
-        // todo
416
-    }
417
-
418
-
419
-    protected function _add_screen_options_default()
420
-    {
421
-        $this->_per_page_screen_option();
422
-    }
423
-
424
-
425
-    protected function _add_screen_options_category_list()
426
-    {
427
-        $page_title              = $this->_admin_page_title;
428
-        $this->_admin_page_title = esc_html__('Venue Categories', 'event_espresso');
429
-        $this->_per_page_screen_option();
430
-        $this->_admin_page_title = $page_title;
431
-    }
432
-
433
-
434
-    // none of the below group are currently used for Event Venues
435
-    protected function _add_feature_pointers()
436
-    {
437
-    }
438
-
439
-
440
-    public function admin_init()
441
-    {
442
-    }
443
-
444
-
445
-    public function admin_notices()
446
-    {
447
-    }
448
-
449
-
450
-    public function admin_footer_scripts()
451
-    {
452
-    }
453
-
454
-
455
-    public function load_scripts_styles_create_new()
456
-    {
457
-        $this->load_scripts_styles_edit();
458
-    }
459
-
460
-
461
-    public function load_scripts_styles()
462
-    {
463
-        wp_register_style('ee-cat-admin', EVENTS_ASSETS_URL . 'ee-cat-admin.css', [], EVENT_ESPRESSO_VERSION);
464
-        wp_enqueue_style('ee-cat-admin');
465
-    }
466
-
467
-
468
-    public function load_scripts_styles_add_category()
469
-    {
470
-        $this->load_scripts_styles_edit_category();
471
-    }
472
-
473
-
474
-    public function load_scripts_styles_edit_category()
475
-    {
476
-    }
477
-
478
-
479
-    public function load_scripts_styles_edit()
480
-    {
481
-        // styles
482
-        wp_enqueue_style('espresso-ui-theme');
483
-        wp_register_style(
484
-            'espresso_venues',
485
-            EE_VENUES_ASSETS_URL . 'ee-venues-admin.css',
486
-            [],
487
-            EVENT_ESPRESSO_VERSION
488
-        );
489
-        wp_enqueue_style('espresso_venues');
490
-    }
491
-
492
-
493
-    protected function _set_list_table_views_default()
494
-    {
495
-        $this->_views = [
496
-            'all' => [
497
-                'slug'        => 'all',
498
-                'label'       => esc_html__('View All Venues', 'event_espresso'),
499
-                'count'       => 0,
500
-                'bulk_action' => [],
501
-            ],
502
-        ];
503
-
504
-        if (EE_Registry::instance()->CAP->current_user_can('ee_delete_venues', 'espresso_venues_trash_venues')) {
505
-            $this->_views['all']['bulk_action'] = [
506
-                'trash_venues' => esc_html__('Move to Trash', 'event_espresso'),
507
-            ];
508
-            $this->_views['trash']              = [
509
-                'slug'        => 'trash',
510
-                'label'       => esc_html__('Trash', 'event_espresso'),
511
-                'count'       => 0,
512
-                'bulk_action' => [
513
-                    'restore_venues' => esc_html__('Restore from Trash', 'event_espresso'),
514
-                    'delete_venues'  => esc_html__('Delete', 'event_espresso'),
515
-                ],
516
-            ];
517
-        }
518
-    }
519
-
520
-
521
-    protected function _set_list_table_views_category_list()
522
-    {
523
-        $this->_views = [
524
-            'all' => [
525
-                'slug'        => 'all',
526
-                'label'       => esc_html__('All', 'event_espresso'),
527
-                'count'       => 0,
528
-                'bulk_action' => [
529
-                    'delete_categories' => esc_html__('Delete Permanently', 'event_espresso'),
530
-                ],
531
-            ],
532
-        ];
533
-    }
534
-
535
-
536
-    /**
537
-     * @throws EE_Error
538
-     */
539
-    protected function _overview_list_table()
540
-    {
541
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
542
-        $this->_template_args['after_list_table'] = EEH_Template::get_button_or_link(
543
-            get_post_type_archive_link('espresso_venues'),
544
-            esc_html__("View Venue Archive Page", "event_espresso"),
545
-            'button'
546
-        );
547
-
548
-        $this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
549
-            'create_new',
550
-            'add',
551
-            [],
552
-            'add-new-h2'
553
-        );
554
-
555
-        $this->_search_btn_label  = esc_html__('Venues', 'event_espresso');
556
-        $this->display_admin_list_table_page_with_sidebar();
557
-    }
558
-
559
-
560
-    /**
561
-     * @throws EE_Error
562
-     * @throws ReflectionException
563
-     */
564
-    public function extra_misc_actions_publish_box()
565
-    {
566
-        $extra_rows = [
567
-            'vnu_capacity' => $this->_cpt_model_obj->get_f('VNU_capacity'),
568
-            'vnu_url'      => $this->_cpt_model_obj->get_f('VNU_url'),
569
-            'vnu_phone'    => $this->_cpt_model_obj->get_f('VNU_phone'),
570
-        ];
571
-        $template   = EE_VENUES_TEMPLATE_PATH . 'venue_publish_box_extras.template.php';
572
-        EEH_Template::display_template($template, $extra_rows);
573
-    }
574
-
575
-
576
-    /*************        Google Maps        *************
16
+	/**
17
+	 * _venue
18
+	 * This will hold the venue object for venue_details screen.
19
+	 *
20
+	 * @access protected
21
+	 * @var object
22
+	 */
23
+	protected $_venue;
24
+
25
+
26
+	/**
27
+	 * This will hold the category object for category_details screen.
28
+	 *
29
+	 * @var object
30
+	 */
31
+	protected $_category;
32
+
33
+
34
+	/**
35
+	 * This property will hold the venue model instance
36
+	 *
37
+	 * @var object
38
+	 */
39
+	protected $_venue_model;
40
+
41
+
42
+	/**
43
+	 * @throws EE_Error
44
+	 */
45
+	protected function _init_page_props()
46
+	{
47
+		require_once(EE_MODELS . 'EEM_Venue.model.php');
48
+		$this->page_slug        = EE_VENUES_PG_SLUG;
49
+		$this->_admin_base_url  = EE_VENUES_ADMIN_URL;
50
+		$this->_admin_base_path = EE_ADMIN_PAGES . 'venues';
51
+		$this->page_label       = esc_html__('Event Venues', 'event_espresso');
52
+		$this->_cpt_model_names = [
53
+			'create_new' => 'EEM_Venue',
54
+			'edit'       => 'EEM_Venue',
55
+		];
56
+		$this->_cpt_edit_routes = [
57
+			'espresso_venues' => 'edit',
58
+		];
59
+		$this->_venue_model     = EEM_Venue::instance();
60
+	}
61
+
62
+
63
+	protected function _ajax_hooks()
64
+	{
65
+		// todo: all hooks for ee_venues ajax goes in here.
66
+	}
67
+
68
+
69
+	protected function _define_page_props()
70
+	{
71
+		$this->_admin_page_title = $this->page_label;
72
+		$this->_labels           = [
73
+			'buttons'      => [
74
+				'add'             => esc_html__('Add New Venue', 'event_espresso'),
75
+				'edit'            => esc_html__('Edit Venue', 'event_espresso'),
76
+				'delete'          => esc_html__('Delete Venue', 'event_espresso'),
77
+				'add_category'    => esc_html__('Add New Category', 'event_espresso'),
78
+				'edit_category'   => esc_html__('Edit Category', 'event_espresso'),
79
+				'delete_category' => esc_html__('Delete Category', 'event_espresso'),
80
+			],
81
+			'editor_title' => [
82
+				'espresso_venues' => esc_html__('Enter Venue name here', 'event_espresso'),
83
+			],
84
+			'publishbox'   => [
85
+				'create_new'          => esc_html__('Save New Venue', 'event_espresso'),
86
+				'edit'                => esc_html__('Update Venue', 'event_espresso'),
87
+				'add_category'        => esc_html__('Save New Category', 'event_espresso'),
88
+				'edit_category'       => esc_html__('Update Category', 'event_espresso'),
89
+				'google_map_settings' => esc_html__('Update Settings', 'event_espresso'),
90
+			],
91
+		];
92
+	}
93
+
94
+
95
+	protected function _set_page_routes()
96
+	{
97
+
98
+		// load formatter helper
99
+		// load field generator helper
100
+
101
+		// is there a vnu_id in the request?
102
+		$VNU_ID = $this->request->getRequestParam('VNU_ID', 0, 'int');
103
+		$VNU_ID = $this->request->getRequestParam('post', $VNU_ID, 'int');
104
+
105
+		$this->_page_routes = [
106
+			'default'                    => [
107
+				'func'       => '_overview_list_table',
108
+				'capability' => 'ee_read_venues',
109
+			],
110
+			'create_new'                 => [
111
+				'func'       => '_create_new_cpt_item',
112
+				'capability' => 'ee_edit_venues',
113
+			],
114
+			'edit'                       => [
115
+				'func'       => '_edit_cpt_item',
116
+				'capability' => 'ee_edit_venue',
117
+				'obj_id'     => $VNU_ID,
118
+			],
119
+			'trash_venue'                => [
120
+				'func'       => '_trash_or_restore_venue',
121
+				'args'       => ['venue_status' => 'trash'],
122
+				'noheader'   => true,
123
+				'capability' => 'ee_delete_venue',
124
+				'obj_id'     => $VNU_ID,
125
+			],
126
+			'trash_venues'               => [
127
+				'func'       => '_trash_or_restore_venues',
128
+				'args'       => ['venue_status' => 'trash'],
129
+				'noheader'   => true,
130
+				'capability' => 'ee_delete_venues',
131
+			],
132
+			'restore_venue'              => [
133
+				'func'       => '_trash_or_restore_venue',
134
+				'args'       => ['venue_status' => 'draft'],
135
+				'noheader'   => true,
136
+				'capability' => 'ee_delete_venue',
137
+				'obj_id'     => $VNU_ID,
138
+			],
139
+			'restore_venues'             => [
140
+				'func'       => '_trash_or_restore_venues',
141
+				'args'       => ['venue_status' => 'draft'],
142
+				'noheader'   => true,
143
+				'capability' => 'ee_delete_venues',
144
+			],
145
+			'delete_venues'              => [
146
+				'func'       => '_delete_venues',
147
+				'noheader'   => true,
148
+				'capability' => 'ee_delete_venues',
149
+			],
150
+			'delete_venue'               => [
151
+				'func'       => '_delete_venue',
152
+				'noheader'   => true,
153
+				'capability' => 'ee_delete_venue',
154
+				'obj_id'     => $VNU_ID,
155
+			],
156
+			// settings related
157
+			'google_map_settings'        => [
158
+				'func'       => '_google_map_settings',
159
+				'capability' => 'manage_options',
160
+			],
161
+			'update_google_map_settings' => [
162
+				'func'       => '_update_google_map_settings',
163
+				'capability' => 'manage_options',
164
+				'noheader'   => true,
165
+			],
166
+			// venue category tab related
167
+			'add_category'               => [
168
+				'func'       => '_category_details',
169
+				'args'       => ['add'],
170
+				'capability' => 'ee_edit_venue_category',
171
+			],
172
+			'edit_category'              => [
173
+				'func'       => '_category_details',
174
+				'args'       => ['edit'],
175
+				'capability' => 'ee_edit_venue_category',
176
+			],
177
+			'delete_categories'          => [
178
+				'func'       => '_delete_categories',
179
+				'noheader'   => true,
180
+				'capability' => 'ee_delete_venue_category',
181
+			],
182
+
183
+			'delete_category' => [
184
+				'func'       => '_delete_categories',
185
+				'noheader'   => true,
186
+				'capability' => 'ee_delete_venue_category',
187
+			],
188
+
189
+			'insert_category' => [
190
+				'func'       => '_insert_or_update_category',
191
+				'args'       => ['new_category' => true],
192
+				'noheader'   => true,
193
+				'capability' => 'ee_edit_venue_category',
194
+			],
195
+
196
+			'update_category'   => [
197
+				'func'       => '_insert_or_update_category',
198
+				'args'       => ['new_category' => false],
199
+				'noheader'   => true,
200
+				'capability' => 'ee_edit_venue_category',
201
+			],
202
+			'export_categories' => [
203
+				'func'       => '_categories_export',
204
+				'noheader'   => true,
205
+				'capability' => 'export',
206
+			],
207
+			'import_categories' => [
208
+				'func'       => '_import_categories',
209
+				'capability' => 'import',
210
+			],
211
+			'category_list'     => [
212
+				'func'       => '_category_list_table',
213
+				'capability' => 'ee_manage_venue_categories',
214
+			],
215
+		];
216
+	}
217
+
218
+
219
+	protected function _set_page_config()
220
+	{
221
+		$VNU_ID     = $this->request->getRequestParam('post', 0, 'int');
222
+		$EVT_CAT_ID = $this->request->getRequestParam('EVT_CAT_ID', 0, 'int');
223
+
224
+		$this->_page_config = [
225
+			'default'             => [
226
+				'nav'           => [
227
+					'label' => esc_html__('Overview', 'event_espresso'),
228
+					'icon' => 'dashicons-list-view',
229
+					'order' => 10,
230
+				],
231
+				'list_table'    => 'Venues_Admin_List_Table',
232
+				'help_tabs'     => [
233
+					'venues_overview_help_tab'                           => [
234
+						'title'    => esc_html__('Venues Overview', 'event_espresso'),
235
+						'filename' => 'venues_overview',
236
+					],
237
+					'venues_overview_table_column_headings_help_tab'     => [
238
+						'title'    => esc_html__('Venues Overview Table Column Headings', 'event_espresso'),
239
+						'filename' => 'venues_overview_table_column_headings',
240
+					],
241
+					'venues_overview_views_bulk_actions_search_help_tab' => [
242
+						'title'    => esc_html__('Venues Overview Views & Bulk Actions & Search', 'event_espresso'),
243
+						'filename' => 'venues_overview_views_bulk_actions_search',
244
+					],
245
+				],
246
+				'metaboxes'     => ['_espresso_news_post_box', '_espresso_links_post_box'],
247
+				'require_nonce' => false,
248
+			],
249
+			'create_new'          => [
250
+				'nav'           => [
251
+					'label'      => esc_html__('Add Venue', 'event_espresso'),
252
+					'icon' => 'dashicons-plus-alt',
253
+					'order'      => 15,
254
+					'persistent' => false,
255
+				],
256
+				'help_tabs'     => [
257
+					'venues_editor_help_tab'                                               => [
258
+						'title'    => esc_html__('Venue Editor', 'event_espresso'),
259
+						'filename' => 'venues_editor',
260
+					],
261
+					'venues_editor_title_richtexteditor_help_tab'                          => [
262
+						'title'    => esc_html__('Venue Title & Rich Text Editor', 'event_espresso'),
263
+						'filename' => 'venues_editor_title_richtexteditor',
264
+					],
265
+					'venues_editor_tags_categories_help_tab'                               => [
266
+						'title'    => esc_html__('Venue Tags & Categories', 'event_espresso'),
267
+						'filename' => 'venues_editor_tags_categories',
268
+					],
269
+					'venues_editor_physical_location_google_map_virtual_location_help_tab' => [
270
+						'title'    => esc_html__(
271
+							'Venue Editor Physical Location & Google Map & Virtual Location',
272
+							'event_espresso'
273
+						),
274
+						'filename' => 'venues_editor_physical_location_google_map_virtual_location',
275
+					],
276
+					'venues_editor_save_new_venue_help_tab'                                => [
277
+						'title'    => esc_html__('Save New Venue', 'event_espresso'),
278
+						'filename' => 'venues_editor_save_new_venue',
279
+					],
280
+					'venues_editor_other_help_tab'                                         => [
281
+						'title'    => esc_html__('Venue Editor Other', 'event_espresso'),
282
+						'filename' => 'venues_editor_other',
283
+					],
284
+				],
285
+				'metaboxes'     => ['_venue_editor_metaboxes'],
286
+				'require_nonce' => false,
287
+			],
288
+			'edit'                => [
289
+				'nav'           => [
290
+					'label'      => esc_html__('Edit Venue', 'event_espresso'),
291
+					'icon' => 'dashicons-edit-large',
292
+					'order'      => 15,
293
+					'persistent' => false,
294
+					'url'        => $VNU_ID
295
+						? add_query_arg(['post' => $VNU_ID], $this->_current_page_view_url)
296
+						: $this->_admin_base_url,
297
+				],
298
+				'help_tabs'     => [
299
+					'venues_editor_help_tab'                                               => [
300
+						'title'    => esc_html__('Venue Editor', 'event_espresso'),
301
+						'filename' => 'venues_editor',
302
+					],
303
+					'venues_editor_title_richtexteditor_help_tab'                          => [
304
+						'title'    => esc_html__('Venue Title & Rich Text Editor', 'event_espresso'),
305
+						'filename' => 'venues_editor_title_richtexteditor',
306
+					],
307
+					'venues_editor_tags_categories_help_tab'                               => [
308
+						'title'    => esc_html__('Venue Tags & Categories', 'event_espresso'),
309
+						'filename' => 'venues_editor_tags_categories',
310
+					],
311
+					'venues_editor_physical_location_google_map_virtual_location_help_tab' => [
312
+						'title'    => esc_html__(
313
+							'Venue Editor Physical Location & Google Map & Virtual Location',
314
+							'event_espresso'
315
+						),
316
+						'filename' => 'venues_editor_physical_location_google_map_virtual_location',
317
+					],
318
+					'venues_editor_save_new_venue_help_tab'                                => [
319
+						'title'    => esc_html__('Save New Venue', 'event_espresso'),
320
+						'filename' => 'venues_editor_save_new_venue',
321
+					],
322
+					'venues_editor_other_help_tab'                                         => [
323
+						'title'    => esc_html__('Venue Editor Other', 'event_espresso'),
324
+						'filename' => 'venues_editor_other',
325
+					],
326
+				],
327
+				'metaboxes'     => ['_venue_editor_metaboxes'],
328
+				'require_nonce' => false,
329
+			],
330
+			'google_map_settings' => [
331
+				'nav'           => [
332
+					'label' => esc_html__('Google Maps', 'event_espresso'),
333
+					'icon' => 'dashicons-location-alt',
334
+					'order' => 40,
335
+				],
336
+				'metaboxes'     => array_merge($this->_default_espresso_metaboxes, ['_publish_post_box']),
337
+				'help_tabs'     => [
338
+					'general_settings_google_maps_help_tab' => [
339
+						'title'    => esc_html__('Google Maps', 'event_espresso'),
340
+						'filename' => 'general_settings_google_maps',
341
+					],
342
+				],
343
+				'require_nonce' => false,
344
+			],
345
+			// venue category stuff
346
+			'add_category'        => [
347
+				'nav'           => [
348
+					'label'      => esc_html__('Add Category', 'event_espresso'),
349
+					'icon' => 'dashicons-plus-alt',
350
+					'order'      => 25,
351
+					'persistent' => false,
352
+				],
353
+				'metaboxes'     => ['_publish_post_box'],
354
+				'help_tabs'     => [
355
+					'venues_add_category_help_tab' => [
356
+						'title'    => esc_html__('Add New Venue Category', 'event_espresso'),
357
+						'filename' => 'venues_add_category',
358
+					],
359
+				],
360
+				'require_nonce' => false,
361
+			],
362
+			'edit_category'       => [
363
+				'nav'           => [
364
+					'label'      => esc_html__('Edit Category', 'event_espresso'),
365
+					'icon' => 'dashicons-edit-large',
366
+					'order'      => 25,
367
+					'persistent' => false,
368
+					'url'        => $EVT_CAT_ID
369
+						? add_query_arg(['EVT_CAT_ID' => $EVT_CAT_ID], $this->_current_page_view_url)
370
+						: $this->_admin_base_url,
371
+				],
372
+				'metaboxes'     => ['_publish_post_box'],
373
+				'help_tabs'     => [
374
+					'venues_edit_category_help_tab' => [
375
+						'title'    => esc_html__('Edit Venue Category', 'event_espresso'),
376
+						'filename' => 'venues_edit_category',
377
+					],
378
+				],
379
+				'require_nonce' => false,
380
+			],
381
+			'category_list'       => [
382
+				'nav'           => [
383
+					'label' => esc_html__('Categories', 'event_espresso'),
384
+					'icon' => 'dashicons-networking',
385
+					'order' => 20,
386
+				],
387
+				'list_table'    => 'Venue_Categories_Admin_List_Table',
388
+				'help_tabs'     => [
389
+					'venues_categories_help_tab'                       => [
390
+						'title'    => esc_html__('Venue Categories', 'event_espresso'),
391
+						'filename' => 'venues_categories',
392
+					],
393
+					'venues_categories_table_column_headings_help_tab' => [
394
+						'title'    => esc_html__('Venue Categories Table Column Headings', 'event_espresso'),
395
+						'filename' => 'venues_categories_table_column_headings',
396
+					],
397
+					'venues_categories_views_help_tab'                 => [
398
+						'title'    => esc_html__('Venue Categories Views', 'event_espresso'),
399
+						'filename' => 'venues_categories_views',
400
+					],
401
+					'venues_categories_other_help_tab'                 => [
402
+						'title'    => esc_html__('Venue Categories Other', 'event_espresso'),
403
+						'filename' => 'venues_categories_other',
404
+					],
405
+				],
406
+				'metaboxes'     => $this->_default_espresso_metaboxes,
407
+				'require_nonce' => false,
408
+			],
409
+		];
410
+	}
411
+
412
+
413
+	protected function _add_screen_options()
414
+	{
415
+		// todo
416
+	}
417
+
418
+
419
+	protected function _add_screen_options_default()
420
+	{
421
+		$this->_per_page_screen_option();
422
+	}
423
+
424
+
425
+	protected function _add_screen_options_category_list()
426
+	{
427
+		$page_title              = $this->_admin_page_title;
428
+		$this->_admin_page_title = esc_html__('Venue Categories', 'event_espresso');
429
+		$this->_per_page_screen_option();
430
+		$this->_admin_page_title = $page_title;
431
+	}
432
+
433
+
434
+	// none of the below group are currently used for Event Venues
435
+	protected function _add_feature_pointers()
436
+	{
437
+	}
438
+
439
+
440
+	public function admin_init()
441
+	{
442
+	}
443
+
444
+
445
+	public function admin_notices()
446
+	{
447
+	}
448
+
449
+
450
+	public function admin_footer_scripts()
451
+	{
452
+	}
453
+
454
+
455
+	public function load_scripts_styles_create_new()
456
+	{
457
+		$this->load_scripts_styles_edit();
458
+	}
459
+
460
+
461
+	public function load_scripts_styles()
462
+	{
463
+		wp_register_style('ee-cat-admin', EVENTS_ASSETS_URL . 'ee-cat-admin.css', [], EVENT_ESPRESSO_VERSION);
464
+		wp_enqueue_style('ee-cat-admin');
465
+	}
466
+
467
+
468
+	public function load_scripts_styles_add_category()
469
+	{
470
+		$this->load_scripts_styles_edit_category();
471
+	}
472
+
473
+
474
+	public function load_scripts_styles_edit_category()
475
+	{
476
+	}
477
+
478
+
479
+	public function load_scripts_styles_edit()
480
+	{
481
+		// styles
482
+		wp_enqueue_style('espresso-ui-theme');
483
+		wp_register_style(
484
+			'espresso_venues',
485
+			EE_VENUES_ASSETS_URL . 'ee-venues-admin.css',
486
+			[],
487
+			EVENT_ESPRESSO_VERSION
488
+		);
489
+		wp_enqueue_style('espresso_venues');
490
+	}
491
+
492
+
493
+	protected function _set_list_table_views_default()
494
+	{
495
+		$this->_views = [
496
+			'all' => [
497
+				'slug'        => 'all',
498
+				'label'       => esc_html__('View All Venues', 'event_espresso'),
499
+				'count'       => 0,
500
+				'bulk_action' => [],
501
+			],
502
+		];
503
+
504
+		if (EE_Registry::instance()->CAP->current_user_can('ee_delete_venues', 'espresso_venues_trash_venues')) {
505
+			$this->_views['all']['bulk_action'] = [
506
+				'trash_venues' => esc_html__('Move to Trash', 'event_espresso'),
507
+			];
508
+			$this->_views['trash']              = [
509
+				'slug'        => 'trash',
510
+				'label'       => esc_html__('Trash', 'event_espresso'),
511
+				'count'       => 0,
512
+				'bulk_action' => [
513
+					'restore_venues' => esc_html__('Restore from Trash', 'event_espresso'),
514
+					'delete_venues'  => esc_html__('Delete', 'event_espresso'),
515
+				],
516
+			];
517
+		}
518
+	}
519
+
520
+
521
+	protected function _set_list_table_views_category_list()
522
+	{
523
+		$this->_views = [
524
+			'all' => [
525
+				'slug'        => 'all',
526
+				'label'       => esc_html__('All', 'event_espresso'),
527
+				'count'       => 0,
528
+				'bulk_action' => [
529
+					'delete_categories' => esc_html__('Delete Permanently', 'event_espresso'),
530
+				],
531
+			],
532
+		];
533
+	}
534
+
535
+
536
+	/**
537
+	 * @throws EE_Error
538
+	 */
539
+	protected function _overview_list_table()
540
+	{
541
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
542
+		$this->_template_args['after_list_table'] = EEH_Template::get_button_or_link(
543
+			get_post_type_archive_link('espresso_venues'),
544
+			esc_html__("View Venue Archive Page", "event_espresso"),
545
+			'button'
546
+		);
547
+
548
+		$this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
549
+			'create_new',
550
+			'add',
551
+			[],
552
+			'add-new-h2'
553
+		);
554
+
555
+		$this->_search_btn_label  = esc_html__('Venues', 'event_espresso');
556
+		$this->display_admin_list_table_page_with_sidebar();
557
+	}
558
+
559
+
560
+	/**
561
+	 * @throws EE_Error
562
+	 * @throws ReflectionException
563
+	 */
564
+	public function extra_misc_actions_publish_box()
565
+	{
566
+		$extra_rows = [
567
+			'vnu_capacity' => $this->_cpt_model_obj->get_f('VNU_capacity'),
568
+			'vnu_url'      => $this->_cpt_model_obj->get_f('VNU_url'),
569
+			'vnu_phone'    => $this->_cpt_model_obj->get_f('VNU_phone'),
570
+		];
571
+		$template   = EE_VENUES_TEMPLATE_PATH . 'venue_publish_box_extras.template.php';
572
+		EEH_Template::display_template($template, $extra_rows);
573
+	}
574
+
575
+
576
+	/*************        Google Maps        *************
577 577
      *
578 578
      * @throws EE_Error
579 579
      * @throws EE_Error
580 580
      */
581 581
 
582 582
 
583
-    protected function _google_map_settings()
584
-    {
585
-
586
-
587
-        $this->_template_args['values']           = $this->_yes_no_values;
588
-        $default_map_settings                     = new stdClass();
589
-        $default_map_settings->use_google_maps    = true;
590
-        $default_map_settings->google_map_api_key = '';
591
-        // for event details pages (reg page)
592
-        $default_map_settings->event_details_map_width    = 585;
593
-        // ee_map_width_single
594
-        $default_map_settings->event_details_map_height   = 362;
595
-        // ee_map_height_single
596
-        $default_map_settings->event_details_map_zoom     = 14;
597
-        // ee_map_zoom_single
598
-        $default_map_settings->event_details_display_nav  = true;
599
-        // ee_map_nav_display_single
600
-        $default_map_settings->event_details_nav_size     = false;
601
-        // ee_map_nav_size_single
602
-        $default_map_settings->event_details_control_type = 'default';
603
-        // ee_map_type_control_single
604
-        $default_map_settings->event_details_map_align    = 'center';
605
-        // ee_map_align_single
606
-
607
-        // for event list pages
608
-        $default_map_settings->event_list_map_width    = 300;
609
-        // ee_map_width
610
-        $default_map_settings->event_list_map_height   = 185;
611
-        // ee_map_height
612
-        $default_map_settings->event_list_map_zoom     = 12;
613
-        // ee_map_zoom
614
-        $default_map_settings->event_list_display_nav  = false;
615
-        // ee_map_nav_display
616
-        $default_map_settings->event_list_nav_size     = true;
617
-        // ee_map_nav_size
618
-        $default_map_settings->event_list_control_type = 'dropdown';
619
-        // ee_map_type_control
620
-        $default_map_settings->event_list_map_align    = 'center';
621
-        // ee_map_align
622
-
623
-        $this->_template_args['map_settings'] =
624
-            isset(EE_Registry::instance()->CFG->map_settings)
625
-            && ! empty(EE_Registry::instance()->CFG->map_settings)
626
-                ? (object) array_merge(
627
-                    (array) $default_map_settings,
628
-                    (array) EE_Registry::instance()->CFG->map_settings
629
-                )
630
-                : $default_map_settings;
631
-
632
-        $this->_set_add_edit_form_tags('update_google_map_settings');
633
-        $this->_set_publish_post_box_vars(null, false, false, null, false);
634
-        $this->_template_args['admin_page_content'] = EEH_Template::display_template(
635
-            EE_VENUES_TEMPLATE_PATH . 'google_map.template.php',
636
-            $this->_template_args,
637
-            true
638
-        );
639
-        $this->display_admin_page_with_sidebar();
640
-    }
641
-
642
-
643
-    /**
644
-     * @throws EE_Error
645
-     */
646
-    protected function _update_google_map_settings()
647
-    {
648
-        $map_settings = EE_Registry::instance()->CFG->map_settings;
649
-
650
-        $settings = [
651
-            'use_google_maps'            => 'int',
652
-            'google_map_api_key'         => 'string',
653
-            'event_details_map_width'    => 'int',
654
-            'event_details_map_zoom'     => 'int',
655
-            'event_details_display_nav'  => 'int',
656
-            'event_details_nav_size'     => 'int',
657
-            'event_details_control_type' => 'string',
658
-            'event_details_map_align'    => 'string',
659
-            'event_list_map_width'       => 'int',
660
-            'event_list_map_height'      => 'int',
661
-            'event_list_map_zoom'        => 'int',
662
-            'event_list_display_nav'     => 'int',
663
-            'event_list_nav_size'        => 'int',
664
-            'event_list_control_type'    => 'string',
665
-            'event_list_map_align'       => 'string',
666
-        ];
667
-
668
-        foreach ($settings as $setting => $type) {
669
-            $map_settings->{$setting} = $this->request->getRequestParam($setting, $map_settings->{$setting}, $type);
670
-        }
671
-
672
-        EE_Registry::instance()->CFG->map_settings = apply_filters(
673
-            'FHEE__Extend_General_Settings_Admin_Page___update_google_map_settings__CFG_map_settings',
674
-            $map_settings
675
-        );
676
-
677
-        $what    = 'Google Map Settings';
678
-        $success = $this->_update_espresso_configuration(
679
-            $what,
680
-            EE_Registry::instance()->CFG->map_settings,
681
-            __FILE__,
682
-            __FUNCTION__,
683
-            __LINE__
684
-        );
685
-        $this->_redirect_after_action($success, $what, 'updated', ['action' => 'google_map_settings']);
686
-    }
687
-
688
-
689
-    /**
690
-     * @throws EE_Error
691
-     * @throws ReflectionException
692
-     */
693
-    protected function _venue_editor_metaboxes()
694
-    {
695
-        $this->verify_cpt_object();
696
-
697
-        $this->addMetaBox(
698
-            'espresso_venue_address_options',
699
-            esc_html__('Physical Location', 'event_espresso'),
700
-            [$this, 'venue_address_metabox'],
701
-            $this->page_slug,
702
-            'side'
703
-        );
704
-        $this->addMetaBox(
705
-            'espresso_venue_gmap_options',
706
-            esc_html__('Google Map', 'event_espresso'),
707
-            [$this, 'venue_gmap_metabox'],
708
-            $this->page_slug,
709
-            'side'
710
-        );
711
-        $this->addMetaBox(
712
-            'espresso_venue_virtual_loc_options',
713
-            esc_html__('Virtual Location', 'event_espresso'),
714
-            [$this, 'venue_virtual_loc_metabox'],
715
-            $this->page_slug,
716
-            'side'
717
-        );
718
-    }
719
-
720
-
721
-    public function venue_gmap_metabox()
722
-    {
723
-        $template_args = [
724
-            'vnu_enable_for_gmap' => EEH_Form_Fields::select_input(
725
-                'vnu_enable_for_gmap',
726
-                $this->get_yes_no_values(),
727
-                $this->_cpt_model_obj instanceof EE_Venue ? $this->_cpt_model_obj->enable_for_gmap() : false
728
-            ),
729
-            'vnu_google_map_link' => $this->_cpt_model_obj->google_map_link(),
730
-        ];
731
-        $template      = EE_VENUES_TEMPLATE_PATH . 'venue_gmap_metabox_content.template.php';
732
-        EEH_Template::display_template($template, $template_args);
733
-    }
734
-
735
-
736
-    /**
737
-     * @throws EE_Error
738
-     * @throws ReflectionException
739
-     */
740
-    public function venue_address_metabox()
741
-    {
742
-        $template_args['_venue'] = $this->_cpt_model_obj;
743
-
744
-        $template_args['states_dropdown']    = EEH_Form_Fields::generate_form_input(
745
-            new EE_Question_Form_Input(
746
-                EE_Question::new_instance(
747
-                    ['QST_display_text' => esc_html__('State', 'event_espresso'), 'QST_system' => 'state']
748
-                ),
749
-                EE_Answer::new_instance(
750
-                    [
751
-                        'ANS_value' => $this->_cpt_model_obj instanceof EE_Venue
752
-                            ? $this->_cpt_model_obj->state_ID()
753
-                            : 0,
754
-                    ]
755
-                ),
756
-                [
757
-                    'input_name'     => 'sta_id',
758
-                    'input_id'       => 'sta_id',
759
-                    'input_class'    => '',
760
-                    'input_prefix'   => '',
761
-                    'append_qstn_id' => false,
762
-                ]
763
-            )
764
-        );
765
-        $template_args['countries_dropdown'] = EEH_Form_Fields::generate_form_input(
766
-            new EE_Question_Form_Input(
767
-                EE_Question::new_instance(
768
-                    ['QST_display_text' => esc_html__('Country', 'event_espresso'), 'QST_system' => 'country']
769
-                ),
770
-                EE_Answer::new_instance(
771
-                    [
772
-                        'ANS_value' => $this->_cpt_model_obj instanceof EE_Venue
773
-                            ? $this->_cpt_model_obj->country_ID()
774
-                            : 0,
775
-                    ]
776
-                ),
777
-                [
778
-                    'input_name'     => 'cnt_iso',
779
-                    'input_id'       => 'cnt_iso',
780
-                    'input_class'    => '',
781
-                    'input_prefix'   => '',
782
-                    'append_qstn_id' => false,
783
-                ]
784
-            )
785
-        );
786
-
787
-        $template = EE_VENUES_TEMPLATE_PATH . 'venue_address_metabox_content.template.php';
788
-        EEH_Template::display_template($template, $template_args);
789
-    }
790
-
791
-
792
-    public function venue_virtual_loc_metabox()
793
-    {
794
-        $template_args = [
795
-            '_venue' => $this->_cpt_model_obj,
796
-        ];
797
-        $template      = EE_VENUES_TEMPLATE_PATH . 'venue_virtual_location_metabox_content.template.php';
798
-        EEH_Template::display_template($template, $template_args);
799
-    }
800
-
801
-
802
-    protected function _restore_cpt_item($post_id, $revision_id)
803
-    {
804
-        $venue_obj = $this->_venue_model->get_one_by_ID($post_id);
805
-
806
-        // meta revision restore
807
-        $venue_obj->restore_revision($revision_id);
808
-    }
809
-
810
-
811
-    /**
812
-     * Handles updates for venue cpts
813
-     *
814
-     * @param int    $post_id ID of Venue CPT
815
-     * @param WP_Post $post    Post object (with "blessed" WP properties)
816
-     * @return void
817
-     */
818
-    protected function _insert_update_cpt_item($post_id, $post)
819
-    {
820
-
821
-        if ($post instanceof WP_Post && $post->post_type !== 'espresso_venues') {
822
-            return;// get out we're not processing the saving of venues.
823
-        }
824
-
825
-        $wheres = [$this->_venue_model->primary_key_name() => $post_id];
826
-
827
-        $venue_values = [
828
-            'VNU_address'         => $this->request->getRequestParam('vnu_address'),
829
-            'VNU_address2'        => $this->request->getRequestParam('vnu_address2'),
830
-            'VNU_city'            => $this->request->getRequestParam('vnu_city'),
831
-            'STA_ID'              => $this->request->getRequestParam('sta_id'),
832
-            'CNT_ISO'             => $this->request->getRequestParam('cnt_iso'),
833
-            'VNU_zip'             => $this->request->getRequestParam('vnu_zip'),
834
-            'VNU_phone'           => $this->request->getRequestParam('vnu_phone'),
835
-            'VNU_capacity'        => $this->request->requestParamIsSet('vnu_capacity')
836
-                ? str_replace(',', '', $this->request->getRequestParam('vnu_capacity'))
837
-                : EE_INF,
838
-            'VNU_url'             => $this->request->getRequestParam('vnu_url'),
839
-            'VNU_virtual_phone'   => $this->request->getRequestParam('vnu_virtual_phone'),
840
-            'VNU_virtual_url'     => $this->request->getRequestParam('vnu_virtual_url'),
841
-            'VNU_enable_for_gmap' => $this->request->getRequestParam('vnu_enable_for_gmap', false, 'bool'),
842
-            'VNU_google_map_link' => $this->request->getRequestParam('vnu_google_map_link'),
843
-        ];
844
-
845
-        // update venue
846
-        $success = $this->_venue_model->update($venue_values, [$wheres]);
847
-
848
-        // get venue_object for other metaboxes that might be added via the filter... though it would seem to make sense to just use $this->_venue_model->get_one_by_ID( $post_id ).. i have to setup where conditions to override the filters in the model that filter out autodraft and inherit statuses so we GET the inherit id!
849
-        $get_one_where = [$this->_venue_model->primary_key_name() => $post_id, 'status' => $post->post_status];
850
-        $venue         = $this->_venue_model->get_one([$get_one_where]);
851
-
852
-        // notice we've applied a filter for venue metabox callbacks but we don't actually have any default venue metaboxes in use.  So this is just here for addons to more easily hook into venue saves.
853
-        $venue_update_callbacks = apply_filters(
854
-            'FHEE__Venues_Admin_Page___insert_update_cpt_item__venue_update_callbacks',
855
-            []
856
-        );
857
-        $att_success            = true;
858
-        foreach ($venue_update_callbacks as $v_callback) {
859
-            // if ANY of these updates fail then we want the appropriate global error message
860
-            $att_success = call_user_func_array($v_callback, [$venue, $this->request->requestParams()])
861
-                ? $att_success
862
-                : false;
863
-        }
864
-
865
-        // any errors?
866
-        if ($success && ! $att_success) {
867
-            EE_Error::add_error(
868
-                esc_html__(
869
-                    'Venue Details saved successfully but something went wrong with saving attachments.',
870
-                    'event_espresso'
871
-                ),
872
-                __FILE__,
873
-                __FUNCTION__,
874
-                __LINE__
875
-            );
876
-        } elseif ($success === false) {
877
-            EE_Error::add_error(
878
-                esc_html__('Venue Details did not save successfully.', 'event_espresso'),
879
-                __FILE__,
880
-                __FUNCTION__,
881
-                __LINE__
882
-            );
883
-        }
884
-    }
885
-
886
-
887
-    /**
888
-     * @param int $post_id
889
-     * @throws EE_Error
890
-     * @throws ReflectionException
891
-     */
892
-    public function trash_cpt_item($post_id)
893
-    {
894
-        $this->request->setRequestParam('VNU_ID', $post_id);
895
-        $this->_trash_or_restore_venue('trash', false);
896
-    }
897
-
898
-
899
-    /**
900
-     * @param int $post_id
901
-     * @throws EE_Error
902
-     * @throws ReflectionException
903
-     */
904
-    public function restore_cpt_item($post_id)
905
-    {
906
-        $this->request->setRequestParam('VNU_ID', $post_id);
907
-        $this->_trash_or_restore_venue('draft', false);
908
-    }
909
-
910
-
911
-    /**
912
-     * @param int $post_id
913
-     * @throws EE_Error
914
-     * @throws ReflectionException
915
-     */
916
-    public function delete_cpt_item($post_id)
917
-    {
918
-        $this->request->setRequestParam('VNU_ID', $post_id);
919
-        $this->_delete_venue(false);
920
-    }
921
-
922
-
923
-    public function get_venue_object()
924
-    {
925
-        return $this->_cpt_model_obj;
926
-    }
927
-
928
-
929
-    /**
930
-     * @throws EE_Error
931
-     * @throws ReflectionException
932
-     */
933
-    protected function _trash_or_restore_venue($venue_status = 'trash', $redirect_after = true)
934
-    {
935
-        $VNU_ID = $this->request->getRequestParam('VNU_ID', 0, 'int');
936
-
937
-        // loop thru venues
938
-        if ($VNU_ID) {
939
-            // clean status
940
-            $venue_status = sanitize_key($venue_status);
941
-            // grab status
942
-            if (! empty($venue_status)) {
943
-                $success = $this->_change_venue_status($VNU_ID, $venue_status);
944
-            } else {
945
-                $success = false;
946
-                $msg     = esc_html__(
947
-                    'An error occurred. The venue could not be moved to the trash because a valid venue status was not not supplied.',
948
-                    'event_espresso'
949
-                );
950
-                EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
951
-            }
952
-        } else {
953
-            $success = false;
954
-            $msg     = esc_html__(
955
-                'An error occurred. The venue could not be moved to the trash because a valid venue ID was not not supplied.',
956
-                'event_espresso'
957
-            );
958
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
959
-        }
960
-        $action = $venue_status == 'trash' ? 'moved to the trash' : 'restored from the trash';
961
-
962
-        if ($redirect_after) {
963
-            $this->_redirect_after_action($success, 'Venue', $action, ['action' => 'default']);
964
-        }
965
-    }
966
-
967
-
968
-    /**
969
-     * @throws EE_Error
970
-     * @throws ReflectionException
971
-     */
972
-    protected function _trash_or_restore_venues($venue_status = 'trash')
973
-    {
974
-        // clean status
975
-        $venue_status = sanitize_key($venue_status);
976
-        // grab status
977
-        if (! empty($venue_status)) {
978
-            $success = true;
979
-            // determine the event id and set to array.
980
-            $VNU_IDs = $this->request->getRequestParam('venue_id', [], 'int', true);
981
-            // loop thru events
982
-            foreach ($VNU_IDs as $VNU_ID) {
983
-                if ($VNU_ID = absint($VNU_ID)) {
984
-                    $results = $this->_change_venue_status($VNU_ID, $venue_status);
985
-                    $success = $results !== false ? $success : false;
986
-                } else {
987
-                    $msg = sprintf(
988
-                        esc_html__(
989
-                            'An error occurred. Venue #%d could not be moved to the trash because a valid venue ID was not not supplied.',
990
-                            'event_espresso'
991
-                        ),
992
-                        $VNU_ID
993
-                    );
994
-                    EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
995
-                    $success = false;
996
-                }
997
-            }
998
-        } else {
999
-            $success = false;
1000
-            $msg     = esc_html__(
1001
-                'An error occurred. The venue could not be moved to the trash because a valid venue status was not not supplied.',
1002
-                'event_espresso'
1003
-            );
1004
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1005
-        }
1006
-        // in order to force a pluralized result message we need to send back a success status greater than 1
1007
-        $success = $success ? 2 : false;
1008
-        $action  = $venue_status == 'trash' ? 'moved to the trash' : 'restored from the trash';
1009
-        $this->_redirect_after_action($success, 'Venues', $action, ['action' => 'default']);
1010
-    }
1011
-
1012
-
1013
-    /**
1014
-     * _trash_or_restore_venues
1015
-     *
1016
-     * //todo this is pretty much the same as the corresponding change_event_status method in Events_Admin_Page.  We
1017
-     * should probably abstract this up to the EE_Admin_Page_CPT (or even EE_Admin_Page) and make this a common method
1018
-     * accepting a certain number of params.
1019
-     *
1020
-     * @access  private
1021
-     * @param int    $VNU_ID
1022
-     * @param string $venue_status
1023
-     * @return bool
1024
-     * @throws EE_Error
1025
-     * @throws ReflectionException
1026
-     */
1027
-    private function _change_venue_status($VNU_ID = 0, $venue_status = '')
1028
-    {
1029
-        // grab venue id
1030
-        if (! $VNU_ID) {
1031
-            $msg = esc_html__('An error occurred. No Venue ID or an invalid Venue ID was received.', 'event_espresso');
1032
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1033
-            return false;
1034
-        }
1035
-
1036
-        $this->_cpt_model_obj = EEM_Venue::instance()->get_one_by_ID($VNU_ID);
1037
-
1038
-        // clean status
1039
-        $venue_status = sanitize_key($venue_status);
1040
-        // grab status
1041
-        if (! $venue_status) {
1042
-            $msg = esc_html__(
1043
-                'An error occurred. No Venue Status or an invalid Venue Status was received.',
1044
-                'event_espresso'
1045
-            );
1046
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1047
-            return false;
1048
-        }
1049
-
1050
-        // was event trashed or restored ?
1051
-        switch ($venue_status) {
1052
-            case 'draft':
1053
-                $action = 'restored from the trash';
1054
-                $hook   = 'AHEE_venue_restored_from_trash';
1055
-                break;
1056
-            case 'trash':
1057
-                $action = 'moved to the trash';
1058
-                $hook   = 'AHEE_venue_moved_to_trash';
1059
-                break;
1060
-            default:
1061
-                $action = 'updated';
1062
-                $hook   = false;
1063
-        }
1064
-        // use class to change status
1065
-        $this->_cpt_model_obj->set_status($venue_status);
1066
-        $success = $this->_cpt_model_obj->save();
1067
-
1068
-        if ($success === false) {
1069
-            $msg = sprintf(esc_html__('An error occurred. The venue could not be %s.', 'event_espresso'), $action);
1070
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1071
-            return false;
1072
-        }
1073
-        if ($hook) {
1074
-            do_action($hook);
1075
-        }
1076
-        return true;
1077
-    }
1078
-
1079
-
1080
-    /**
1081
-     * @param bool $redirect_after
1082
-     * @return void
1083
-     * @throws EE_Error
1084
-     * @throws ReflectionException
1085
-     */
1086
-    protected function _delete_venue($redirect_after = true)
1087
-    {
1088
-        // determine the venue id and set to array.
1089
-        $VNU_ID = $this->request->getRequestParam('VNU_ID', 0, 'int');
1090
-        $VNU_ID = $this->request->getRequestParam('post', $VNU_ID, 'int');
1091
-
1092
-        // loop thru venues
1093
-        if ($VNU_ID) {
1094
-            $success = $this->_delete_or_trash_venue($VNU_ID);
1095
-        } else {
1096
-            $success = false;
1097
-            $msg     = esc_html__(
1098
-                'An error occurred. An venue could not be deleted because a valid venue ID was not not supplied.',
1099
-                'event_espresso'
1100
-            );
1101
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1102
-        }
1103
-        if ($redirect_after) {
1104
-            $this->_redirect_after_action($success, 'Venue', 'deleted', ['action' => 'default']);
1105
-        }
1106
-    }
1107
-
1108
-
1109
-    /**
1110
-     * @throws EE_Error
1111
-     * @throws ReflectionException
1112
-     */
1113
-    protected function _delete_venues()
1114
-    {
1115
-        $success = true;
1116
-        // determine the event id and set to array.
1117
-        $VNU_IDs = $this->request->getRequestParam('venue_id', [], 'int', true);
1118
-        // loop thru events
1119
-        foreach ($VNU_IDs as $VNU_ID) {
1120
-            if ($VNU_ID = absint($VNU_ID)) {
1121
-                $results = $this->_delete_or_trash_venue($VNU_ID);
1122
-                $success = $results !== false ? $success : false;
1123
-            } else {
1124
-                $success = false;
1125
-                $msg     = esc_html__(
1126
-                    'An error occurred. An venue could not be deleted because a valid venue ID was not not supplied.',
1127
-                    'event_espresso'
1128
-                );
1129
-                EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1130
-            }
1131
-        }
1132
-        // in order to force a pluralized result message we need to send back a success status greater than 1
1133
-        $success = $success ? 2 : false;
1134
-        $this->_redirect_after_action(
1135
-            $success,
1136
-            esc_html__('Venues', 'event_espresso'),
1137
-            esc_html__('deleted', 'event_espresso'),
1138
-            ['action' => 'default']
1139
-        );
1140
-    }
1141
-
1142
-
1143
-    // todo: put in parent
1144
-
1145
-
1146
-    /**
1147
-     * @throws EE_Error
1148
-     * @throws ReflectionException
1149
-     */
1150
-    private function _delete_or_trash_venue($VNU_ID = false)
1151
-    {
1152
-        // grab event id
1153
-        if (! $VNU_ID = absint($VNU_ID)) {
1154
-            $msg = esc_html__('An error occurred. No Venue ID or an invalid Venue ID was received.', 'event_espresso');
1155
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1156
-            return false;
1157
-        }
1158
-
1159
-
1160
-        $venue = EEM_Venue::instance()->get_one_by_ID($VNU_ID);
1161
-        // first need to remove all term relationships
1162
-        $venue->_remove_relations('Term_Taxonomy');
1163
-        $success = $venue->delete_permanently();
1164
-        // did it all go as planned ?
1165
-        if ($success) {
1166
-            $msg = sprintf(esc_html__('Venue ID # %d has been deleted.', 'event_espresso'), $VNU_ID);
1167
-            EE_Error::add_success($msg);
1168
-        } else {
1169
-            $msg =
1170
-                sprintf(
1171
-                    esc_html__('An error occurred. Venue ID # %d could not be deleted.', 'event_espresso'),
1172
-                    $VNU_ID
1173
-                );
1174
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1175
-            return false;
1176
-        }
1177
-        do_action('AHEE__Venues_Admin_Page___delete_or_trash_venue__after_venue_deleted');
1178
-        return true;
1179
-    }
1180
-
1181
-
1182
-
1183
-
1184
-    /***********/
1185
-    /* QUERIES */
1186
-
1187
-
1188
-    public function get_venues($per_page = 10, $count = false)
1189
-    {
1190
-
1191
-        $orderby = $this->request->getRequestParam('orderby', '');
1192
-
1193
-        switch ($orderby) {
1194
-            case 'id':
1195
-                $orderby = 'VNU_ID';
1196
-                break;
1197
-
1198
-            case 'capacity':
1199
-                $orderby = 'VNU_capacity';
1200
-                break;
1201
-
1202
-            case 'city':
1203
-                $orderby = 'VNU_city';
1204
-                break;
1205
-
1206
-            default:
1207
-                $orderby = 'VNU_name';
1208
-        }
1209
-
1210
-        $sort         = $this->request->getRequestParam('order', 'ASC');
1211
-        $current_page = $this->request->getRequestParam('paged', 1, 'int');
1212
-        $per_page     = ! empty($per_page) ? $per_page : 10;
1213
-        $per_page     = $this->request->getRequestParam('perpage', $per_page, 'int');
1214
-
1215
-        $offset = ($current_page - 1) * $per_page;
1216
-        $limit  = [$offset, $per_page];
1217
-
1218
-        $category = $this->request->getRequestParam('category');
1219
-        $category = $category > 0 ? $category : null;
1220
-
1221
-        $where = [];
1222
-
1223
-        // only set initial status if it is in the incoming request.  Otherwise the "all" view display's all statuses.
1224
-        $status = $this->request->getRequestParam('status');
1225
-        if ($status && $status !== 'all') {
1226
-            $where['status'] = $status;
1227
-        }
1228
-
1229
-        $venue_status = $this->request->getRequestParam('venue_status');
1230
-        if ($venue_status) {
1231
-            $where['status'] = $venue_status;
1232
-        }
1233
-
1234
-
1235
-        if ($category) {
1236
-            $where['Term_Taxonomy.taxonomy'] = 'espresso_venue_categories';
1237
-            $where['Term_Taxonomy.term_id']  = $category;
1238
-        }
1239
-
1240
-
1241
-        if (! EE_Registry::instance()->CAP->current_user_can('ee_read_others_venues', 'get_venues')) {
1242
-            $where['VNU_wp_user'] = get_current_user_id();
1243
-        } else {
1244
-            if (! EE_Registry::instance()->CAP->current_user_can('ee_read_private_venues', 'get_venues')) {
1245
-                $where['OR'] = [
1246
-                    'status*restrict_private' => ['!=', 'private'],
1247
-                    'AND'                     => [
1248
-                        'status*inclusive' => ['=', 'private'],
1249
-                        'VNU_wp_user'      => get_current_user_id(),
1250
-                    ],
1251
-                ];
1252
-            }
1253
-        }
1254
-
1255
-        $search_term = $this->request->getRequestParam('s');
1256
-        if ($search_term) {
1257
-            $search_term = '%' . $search_term . '%';
1258
-            $where['OR'] = [
1259
-                'VNU_name'               => ['LIKE', $search_term],
1260
-                'VNU_desc'               => ['LIKE', $search_term],
1261
-                'VNU_short_desc'         => ['LIKE', $search_term],
1262
-                'VNU_address'            => ['LIKE', $search_term],
1263
-                'VNU_address2'           => ['LIKE', $search_term],
1264
-                'VNU_city'               => ['LIKE', $search_term],
1265
-                'VNU_zip'                => ['LIKE', $search_term],
1266
-                'VNU_phone'              => ['LIKE', $search_term],
1267
-                'VNU_url'                => ['LIKE', $search_term],
1268
-                'VNU_virtual_phone'      => ['LIKE', $search_term],
1269
-                'VNU_virtual_url'        => ['LIKE', $search_term],
1270
-                'VNU_google_map_link'    => ['LIKE', $search_term],
1271
-                'Event.EVT_name'         => ['LIKE', $search_term],
1272
-                'Event.EVT_desc'         => ['LIKE', $search_term],
1273
-                'Event.EVT_phone'        => ['LIKE', $search_term],
1274
-                'Event.EVT_external_URL' => ['LIKE', $search_term],
1275
-            ];
1276
-        }
1277
-
1278
-
1279
-        return $count
1280
-            ? $this->_venue_model->count([$where], 'VNU_ID')
1281
-            : $this->_venue_model->get_all(
1282
-                [$where, 'limit' => $limit, 'order_by' => $orderby, 'order' => $sort]
1283
-            );
1284
-    }
1285
-
1286
-
1287
-
1288
-
1289
-    /** Venue Category Stuff **/
1290
-
1291
-    /**
1292
-     * set the _category property with the category object for the loaded page.
1293
-     *
1294
-     * @access private
1295
-     * @return void
1296
-     */
1297
-    private function _set_category_object()
1298
-    {
1299
-        if (isset($this->_category->id) && ! empty($this->_category->id)) {
1300
-            return;
1301
-        } // already have the category object so get out.
1302
-
1303
-        // set default category object
1304
-        $this->_set_empty_category_object();
1305
-
1306
-        // only set if we've got an id
1307
-        $category_ID = $this->request->getRequestParam('VEN_CAT_ID', 0, 'int');
1308
-        if (! $category_ID) {
1309
-            return;
1310
-        }
1311
-
1312
-        $term = get_term($category_ID, 'espresso_venue_categories');
1313
-
1314
-
1315
-        if (! empty($term)) {
1316
-            $this->_category->category_name       = $term->name;
1317
-            $this->_category->category_identifier = $term->slug;
1318
-            $this->_category->category_desc       = $term->description;
1319
-            $this->_category->id                  = $term->term_id;
1320
-            $this->_category->parent              = $term->parent;
1321
-        }
1322
-    }
1323
-
1324
-
1325
-    private function _set_empty_category_object()
1326
-    {
1327
-        $this->_category                = new stdClass();
1328
-        $this->_category->category_name = $this->_category->category_identifier = $this->_category->category_desc = '';
1329
-        $this->_category->id            = $this->_category->parent = 0;
1330
-    }
1331
-
1332
-
1333
-    /**
1334
-     * @throws EE_Error
1335
-     */
1336
-    protected function _category_list_table()
1337
-    {
1338
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1339
-        $this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
1340
-            'add_category',
1341
-            'add_category',
1342
-            [],
1343
-            'add-new-h2'
1344
-        );
1345
-        $this->_search_btn_label = esc_html__('Venue Categories', 'event_espresso');
1346
-        $this->display_admin_list_table_page_with_sidebar();
1347
-    }
1348
-
1349
-
1350
-    /**
1351
-     * @throws EE_Error
1352
-     */
1353
-    protected function _category_details($view)
1354
-    {
1355
-
1356
-        // load formatter helper
1357
-        // load field generator helper
1358
-
1359
-        $route = $view == 'edit' ? 'update_category' : 'insert_category';
1360
-        $this->_set_add_edit_form_tags($route);
1361
-
1362
-        $this->_set_category_object();
1363
-        $id = ! empty($this->_category->id) ? $this->_category->id : '';
1364
-
1365
-        $delete_action = 'delete_category';
1366
-
1367
-        $redirect = EE_Admin_Page::add_query_args_and_nonce(['action' => 'category_list'], $this->_admin_base_url);
1368
-
1369
-        $this->_set_publish_post_box_vars('VEN_CAT_ID', $id, $delete_action, $redirect);
1370
-
1371
-        // take care of contents
1372
-        $this->_template_args['admin_page_content'] = $this->_category_details_content();
1373
-        $this->display_admin_page_with_sidebar();
1374
-    }
1375
-
1376
-
1377
-    protected function _category_details_content()
1378
-    {
1379
-        $editor_args['category_desc'] = [
1380
-            'type'          => 'wp_editor',
1381
-            'value'         => EEH_Formatter::admin_format_content($this->_category->category_desc),
1382
-            'class'         => 'my_editor_custom',
1383
-            'wpeditor_args' => ['media_buttons' => false],
1384
-        ];
1385
-        $_wp_editor                   = $this->_generate_admin_form_fields($editor_args, 'array');
1386
-
1387
-        $all_terms = get_terms(
1388
-            ['espresso_venue_categories'],
1389
-            ['hide_empty' => 0, 'exclude' => [$this->_category->id]]
1390
-        );
1391
-
1392
-        // setup category select for term parents.
1393
-        $category_select_values[] = [
1394
-            'text' => esc_html__('No Parent', 'event_espresso'),
1395
-            'id'   => 0,
1396
-        ];
1397
-        foreach ($all_terms as $term) {
1398
-            $category_select_values[] = [
1399
-                'text' => $term->name,
1400
-                'id'   => $term->term_id,
1401
-            ];
1402
-        }
1403
-
1404
-        $category_select = EEH_Form_Fields::select_input(
1405
-            'category_parent',
1406
-            $category_select_values,
1407
-            $this->_category->parent
1408
-        );
1409
-        $template_args   = [
1410
-            'category'                 => $this->_category,
1411
-            'category_select'          => $category_select,
1412
-            'unique_id_info_help_link' => $this->_get_help_tab_link('unique_id_info'),
1413
-            'category_desc_editor'     => $_wp_editor['category_desc']['field'],
1414
-            'disable'                  => '',
1415
-            'disabled_message'         => false,
1416
-        ];
1417
-        $template        = EVENTS_TEMPLATE_PATH . 'event_category_details.template.php';
1418
-        return EEH_Template::display_template($template, $template_args, true);
1419
-    }
1420
-
1421
-
1422
-    /**
1423
-     * @throws EE_Error
1424
-     */
1425
-    protected function _delete_categories()
1426
-    {
1427
-        $category_ID  = $this->request->getRequestParam('category_id', 0, 'int');
1428
-        $category_IDs = $this->request->getRequestParam('VEN_CAT_ID', [$category_ID], 'int', true);
1429
-
1430
-        foreach ($category_IDs as $cat_id) {
1431
-            $this->_delete_category($cat_id);
1432
-        }
1433
-
1434
-        // doesn't matter what page we're coming from... we're going to the same place after delete.
1435
-        $query_args = [
1436
-            'action' => 'category_list',
1437
-        ];
1438
-        $this->_redirect_after_action(0, '', '', $query_args);
1439
-    }
1440
-
1441
-
1442
-    protected function _delete_category($cat_id)
1443
-    {
1444
-        $cat_id = absint($cat_id);
1445
-        wp_delete_term($cat_id, 'espresso_venue_categories');
1446
-    }
1447
-
1448
-
1449
-    /**
1450
-     * @throws EE_Error
1451
-     */
1452
-    protected function _insert_or_update_category($new_category)
1453
-    {
1454
-
1455
-        $cat_id  = $new_category ? $this->_insert_category() : $this->_insert_category(true);
1456
-        $success = 0; // we already have a success message so lets not send another.
1457
-        if ($cat_id) {
1458
-            $query_args = [
1459
-                'action'     => 'edit_category',
1460
-                'VEN_CAT_ID' => $cat_id,
1461
-            ];
1462
-        } else {
1463
-            $query_args = ['action' => 'add_category'];
1464
-        }
1465
-        $this->_redirect_after_action($success, '', '', $query_args, true);
1466
-    }
1467
-
1468
-
1469
-    private function _insert_category($update = false)
1470
-    {
1471
-        $category_ID     = $update ? $this->request->getRequestParam('VEN_CAT_ID', '', 'int') : '';
1472
-        $category_name   = $this->request->getRequestParam('category_name', '');
1473
-        $category_desc   = $this->request->getRequestParam('category_desc', '', 'html');
1474
-        $category_parent = $this->request->getRequestParam('category_parent', 0, 'int');
1475
-
1476
-        if (empty($category_name)) {
1477
-            $msg = esc_html__('You must add a name for the category.', 'event_espresso');
1478
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1479
-            return false;
1480
-        }
1481
-
1482
-
1483
-        $term_args = [
1484
-            'name'        => $category_name,
1485
-            'description' => $category_desc,
1486
-            'parent'      => $category_parent,
1487
-        ];
1488
-
1489
-        $insert_ids = $update
1490
-            ? wp_update_term($category_ID, 'espresso_venue_categories', $term_args)
1491
-            : wp_insert_term(
1492
-                $category_name,
1493
-                'espresso_venue_categories',
1494
-                $term_args
1495
-            );
1496
-
1497
-        if (! is_array($insert_ids)) {
1498
-            EE_Error::add_error(
1499
-                esc_html__('An error occurred and the category has not been saved to the database.', 'event_espresso'),
1500
-                __FILE__,
1501
-                __FUNCTION__,
1502
-                __LINE__
1503
-            );
1504
-        } else {
1505
-            $category_ID = $insert_ids['term_id'];
1506
-            EE_Error::add_success(
1507
-                sprintf(
1508
-                    esc_html__('The category %s was successfully created', 'event_espresso'),
1509
-                    $category_name
1510
-                )
1511
-            );
1512
-        }
1513
-
1514
-        return $category_ID;
1515
-    }
1516
-
1517
-
1518
-    /**
1519
-     * TODO handle category exports()
1520
-     *
1521
-     * @return void
1522
-     */
1523
-    protected function _categories_export()
1524
-    {
1525
-        // todo: I don't like doing this but it'll do until we modify EE_Export Class.
1526
-        $this->request->mergeRequestParams(
1527
-            [
1528
-                'export'       => 'report',
1529
-                'action'       => 'categories',
1530
-                'category_ids' => $this->request->getRequestParam('VEN_CAT_ID', 0, 'int'),
1531
-            ]
1532
-        );
1533
-
1534
-        if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
1535
-            require_once(EE_CLASSES . 'EE_Export.class.php');
1536
-            $EE_Export = EE_Export::instance($this->request->requestParams());
1537
-            $EE_Export->export();
1538
-        }
1539
-    }
1540
-
1541
-
1542
-    protected function _import_categories()
1543
-    {
1544
-
1545
-        require_once(EE_CLASSES . 'EE_Import.class.php');
1546
-        EE_Import::instance()->import();
1547
-    }
1548
-
1549
-
1550
-    /**
1551
-     * @throws EE_Error
1552
-     */
1553
-    public function get_categories($per_page = 10, $current_page = 1, $count = false)
1554
-    {
1555
-
1556
-        // testing term stuff
1557
-        $orderby     = $this->request->getRequestParam('orderby', 'Term.term_id');
1558
-        $order       = $this->request->getRequestParam('order', 'DESC');
1559
-        $limit       = ($current_page - 1) * $per_page;
1560
-        $where       = ['taxonomy' => 'espresso_venue_categories'];
1561
-        $search_term = $this->request->getRequestParam('s');
1562
-        if ($search_term) {
1563
-            $search_term = '%' . $search_term . '%';
1564
-            $where['OR'] = [
1565
-                'Term.name'   => ['LIKE', $search_term],
1566
-                'description' => ['LIKE', $search_term],
1567
-            ];
1568
-        }
1569
-
1570
-        $query_params = [
1571
-            $where,
1572
-            'order_by'   => [$orderby => $order],
1573
-            'limit'      => $limit . ',' . $per_page,
1574
-            'force_join' => ['Term'],
1575
-        ];
1576
-
1577
-        return $count
1578
-            ? EEM_Term_Taxonomy::instance()->count($query_params, 'term_id')
1579
-            : EEM_Term_Taxonomy::instance()->get_all($query_params);
1580
-    }
1581
-
1582
-
1583
-    /* end category stuff */
1584
-    /**************/
583
+	protected function _google_map_settings()
584
+	{
585
+
586
+
587
+		$this->_template_args['values']           = $this->_yes_no_values;
588
+		$default_map_settings                     = new stdClass();
589
+		$default_map_settings->use_google_maps    = true;
590
+		$default_map_settings->google_map_api_key = '';
591
+		// for event details pages (reg page)
592
+		$default_map_settings->event_details_map_width    = 585;
593
+		// ee_map_width_single
594
+		$default_map_settings->event_details_map_height   = 362;
595
+		// ee_map_height_single
596
+		$default_map_settings->event_details_map_zoom     = 14;
597
+		// ee_map_zoom_single
598
+		$default_map_settings->event_details_display_nav  = true;
599
+		// ee_map_nav_display_single
600
+		$default_map_settings->event_details_nav_size     = false;
601
+		// ee_map_nav_size_single
602
+		$default_map_settings->event_details_control_type = 'default';
603
+		// ee_map_type_control_single
604
+		$default_map_settings->event_details_map_align    = 'center';
605
+		// ee_map_align_single
606
+
607
+		// for event list pages
608
+		$default_map_settings->event_list_map_width    = 300;
609
+		// ee_map_width
610
+		$default_map_settings->event_list_map_height   = 185;
611
+		// ee_map_height
612
+		$default_map_settings->event_list_map_zoom     = 12;
613
+		// ee_map_zoom
614
+		$default_map_settings->event_list_display_nav  = false;
615
+		// ee_map_nav_display
616
+		$default_map_settings->event_list_nav_size     = true;
617
+		// ee_map_nav_size
618
+		$default_map_settings->event_list_control_type = 'dropdown';
619
+		// ee_map_type_control
620
+		$default_map_settings->event_list_map_align    = 'center';
621
+		// ee_map_align
622
+
623
+		$this->_template_args['map_settings'] =
624
+			isset(EE_Registry::instance()->CFG->map_settings)
625
+			&& ! empty(EE_Registry::instance()->CFG->map_settings)
626
+				? (object) array_merge(
627
+					(array) $default_map_settings,
628
+					(array) EE_Registry::instance()->CFG->map_settings
629
+				)
630
+				: $default_map_settings;
631
+
632
+		$this->_set_add_edit_form_tags('update_google_map_settings');
633
+		$this->_set_publish_post_box_vars(null, false, false, null, false);
634
+		$this->_template_args['admin_page_content'] = EEH_Template::display_template(
635
+			EE_VENUES_TEMPLATE_PATH . 'google_map.template.php',
636
+			$this->_template_args,
637
+			true
638
+		);
639
+		$this->display_admin_page_with_sidebar();
640
+	}
641
+
642
+
643
+	/**
644
+	 * @throws EE_Error
645
+	 */
646
+	protected function _update_google_map_settings()
647
+	{
648
+		$map_settings = EE_Registry::instance()->CFG->map_settings;
649
+
650
+		$settings = [
651
+			'use_google_maps'            => 'int',
652
+			'google_map_api_key'         => 'string',
653
+			'event_details_map_width'    => 'int',
654
+			'event_details_map_zoom'     => 'int',
655
+			'event_details_display_nav'  => 'int',
656
+			'event_details_nav_size'     => 'int',
657
+			'event_details_control_type' => 'string',
658
+			'event_details_map_align'    => 'string',
659
+			'event_list_map_width'       => 'int',
660
+			'event_list_map_height'      => 'int',
661
+			'event_list_map_zoom'        => 'int',
662
+			'event_list_display_nav'     => 'int',
663
+			'event_list_nav_size'        => 'int',
664
+			'event_list_control_type'    => 'string',
665
+			'event_list_map_align'       => 'string',
666
+		];
667
+
668
+		foreach ($settings as $setting => $type) {
669
+			$map_settings->{$setting} = $this->request->getRequestParam($setting, $map_settings->{$setting}, $type);
670
+		}
671
+
672
+		EE_Registry::instance()->CFG->map_settings = apply_filters(
673
+			'FHEE__Extend_General_Settings_Admin_Page___update_google_map_settings__CFG_map_settings',
674
+			$map_settings
675
+		);
676
+
677
+		$what    = 'Google Map Settings';
678
+		$success = $this->_update_espresso_configuration(
679
+			$what,
680
+			EE_Registry::instance()->CFG->map_settings,
681
+			__FILE__,
682
+			__FUNCTION__,
683
+			__LINE__
684
+		);
685
+		$this->_redirect_after_action($success, $what, 'updated', ['action' => 'google_map_settings']);
686
+	}
687
+
688
+
689
+	/**
690
+	 * @throws EE_Error
691
+	 * @throws ReflectionException
692
+	 */
693
+	protected function _venue_editor_metaboxes()
694
+	{
695
+		$this->verify_cpt_object();
696
+
697
+		$this->addMetaBox(
698
+			'espresso_venue_address_options',
699
+			esc_html__('Physical Location', 'event_espresso'),
700
+			[$this, 'venue_address_metabox'],
701
+			$this->page_slug,
702
+			'side'
703
+		);
704
+		$this->addMetaBox(
705
+			'espresso_venue_gmap_options',
706
+			esc_html__('Google Map', 'event_espresso'),
707
+			[$this, 'venue_gmap_metabox'],
708
+			$this->page_slug,
709
+			'side'
710
+		);
711
+		$this->addMetaBox(
712
+			'espresso_venue_virtual_loc_options',
713
+			esc_html__('Virtual Location', 'event_espresso'),
714
+			[$this, 'venue_virtual_loc_metabox'],
715
+			$this->page_slug,
716
+			'side'
717
+		);
718
+	}
719
+
720
+
721
+	public function venue_gmap_metabox()
722
+	{
723
+		$template_args = [
724
+			'vnu_enable_for_gmap' => EEH_Form_Fields::select_input(
725
+				'vnu_enable_for_gmap',
726
+				$this->get_yes_no_values(),
727
+				$this->_cpt_model_obj instanceof EE_Venue ? $this->_cpt_model_obj->enable_for_gmap() : false
728
+			),
729
+			'vnu_google_map_link' => $this->_cpt_model_obj->google_map_link(),
730
+		];
731
+		$template      = EE_VENUES_TEMPLATE_PATH . 'venue_gmap_metabox_content.template.php';
732
+		EEH_Template::display_template($template, $template_args);
733
+	}
734
+
735
+
736
+	/**
737
+	 * @throws EE_Error
738
+	 * @throws ReflectionException
739
+	 */
740
+	public function venue_address_metabox()
741
+	{
742
+		$template_args['_venue'] = $this->_cpt_model_obj;
743
+
744
+		$template_args['states_dropdown']    = EEH_Form_Fields::generate_form_input(
745
+			new EE_Question_Form_Input(
746
+				EE_Question::new_instance(
747
+					['QST_display_text' => esc_html__('State', 'event_espresso'), 'QST_system' => 'state']
748
+				),
749
+				EE_Answer::new_instance(
750
+					[
751
+						'ANS_value' => $this->_cpt_model_obj instanceof EE_Venue
752
+							? $this->_cpt_model_obj->state_ID()
753
+							: 0,
754
+					]
755
+				),
756
+				[
757
+					'input_name'     => 'sta_id',
758
+					'input_id'       => 'sta_id',
759
+					'input_class'    => '',
760
+					'input_prefix'   => '',
761
+					'append_qstn_id' => false,
762
+				]
763
+			)
764
+		);
765
+		$template_args['countries_dropdown'] = EEH_Form_Fields::generate_form_input(
766
+			new EE_Question_Form_Input(
767
+				EE_Question::new_instance(
768
+					['QST_display_text' => esc_html__('Country', 'event_espresso'), 'QST_system' => 'country']
769
+				),
770
+				EE_Answer::new_instance(
771
+					[
772
+						'ANS_value' => $this->_cpt_model_obj instanceof EE_Venue
773
+							? $this->_cpt_model_obj->country_ID()
774
+							: 0,
775
+					]
776
+				),
777
+				[
778
+					'input_name'     => 'cnt_iso',
779
+					'input_id'       => 'cnt_iso',
780
+					'input_class'    => '',
781
+					'input_prefix'   => '',
782
+					'append_qstn_id' => false,
783
+				]
784
+			)
785
+		);
786
+
787
+		$template = EE_VENUES_TEMPLATE_PATH . 'venue_address_metabox_content.template.php';
788
+		EEH_Template::display_template($template, $template_args);
789
+	}
790
+
791
+
792
+	public function venue_virtual_loc_metabox()
793
+	{
794
+		$template_args = [
795
+			'_venue' => $this->_cpt_model_obj,
796
+		];
797
+		$template      = EE_VENUES_TEMPLATE_PATH . 'venue_virtual_location_metabox_content.template.php';
798
+		EEH_Template::display_template($template, $template_args);
799
+	}
800
+
801
+
802
+	protected function _restore_cpt_item($post_id, $revision_id)
803
+	{
804
+		$venue_obj = $this->_venue_model->get_one_by_ID($post_id);
805
+
806
+		// meta revision restore
807
+		$venue_obj->restore_revision($revision_id);
808
+	}
809
+
810
+
811
+	/**
812
+	 * Handles updates for venue cpts
813
+	 *
814
+	 * @param int    $post_id ID of Venue CPT
815
+	 * @param WP_Post $post    Post object (with "blessed" WP properties)
816
+	 * @return void
817
+	 */
818
+	protected function _insert_update_cpt_item($post_id, $post)
819
+	{
820
+
821
+		if ($post instanceof WP_Post && $post->post_type !== 'espresso_venues') {
822
+			return;// get out we're not processing the saving of venues.
823
+		}
824
+
825
+		$wheres = [$this->_venue_model->primary_key_name() => $post_id];
826
+
827
+		$venue_values = [
828
+			'VNU_address'         => $this->request->getRequestParam('vnu_address'),
829
+			'VNU_address2'        => $this->request->getRequestParam('vnu_address2'),
830
+			'VNU_city'            => $this->request->getRequestParam('vnu_city'),
831
+			'STA_ID'              => $this->request->getRequestParam('sta_id'),
832
+			'CNT_ISO'             => $this->request->getRequestParam('cnt_iso'),
833
+			'VNU_zip'             => $this->request->getRequestParam('vnu_zip'),
834
+			'VNU_phone'           => $this->request->getRequestParam('vnu_phone'),
835
+			'VNU_capacity'        => $this->request->requestParamIsSet('vnu_capacity')
836
+				? str_replace(',', '', $this->request->getRequestParam('vnu_capacity'))
837
+				: EE_INF,
838
+			'VNU_url'             => $this->request->getRequestParam('vnu_url'),
839
+			'VNU_virtual_phone'   => $this->request->getRequestParam('vnu_virtual_phone'),
840
+			'VNU_virtual_url'     => $this->request->getRequestParam('vnu_virtual_url'),
841
+			'VNU_enable_for_gmap' => $this->request->getRequestParam('vnu_enable_for_gmap', false, 'bool'),
842
+			'VNU_google_map_link' => $this->request->getRequestParam('vnu_google_map_link'),
843
+		];
844
+
845
+		// update venue
846
+		$success = $this->_venue_model->update($venue_values, [$wheres]);
847
+
848
+		// get venue_object for other metaboxes that might be added via the filter... though it would seem to make sense to just use $this->_venue_model->get_one_by_ID( $post_id ).. i have to setup where conditions to override the filters in the model that filter out autodraft and inherit statuses so we GET the inherit id!
849
+		$get_one_where = [$this->_venue_model->primary_key_name() => $post_id, 'status' => $post->post_status];
850
+		$venue         = $this->_venue_model->get_one([$get_one_where]);
851
+
852
+		// notice we've applied a filter for venue metabox callbacks but we don't actually have any default venue metaboxes in use.  So this is just here for addons to more easily hook into venue saves.
853
+		$venue_update_callbacks = apply_filters(
854
+			'FHEE__Venues_Admin_Page___insert_update_cpt_item__venue_update_callbacks',
855
+			[]
856
+		);
857
+		$att_success            = true;
858
+		foreach ($venue_update_callbacks as $v_callback) {
859
+			// if ANY of these updates fail then we want the appropriate global error message
860
+			$att_success = call_user_func_array($v_callback, [$venue, $this->request->requestParams()])
861
+				? $att_success
862
+				: false;
863
+		}
864
+
865
+		// any errors?
866
+		if ($success && ! $att_success) {
867
+			EE_Error::add_error(
868
+				esc_html__(
869
+					'Venue Details saved successfully but something went wrong with saving attachments.',
870
+					'event_espresso'
871
+				),
872
+				__FILE__,
873
+				__FUNCTION__,
874
+				__LINE__
875
+			);
876
+		} elseif ($success === false) {
877
+			EE_Error::add_error(
878
+				esc_html__('Venue Details did not save successfully.', 'event_espresso'),
879
+				__FILE__,
880
+				__FUNCTION__,
881
+				__LINE__
882
+			);
883
+		}
884
+	}
885
+
886
+
887
+	/**
888
+	 * @param int $post_id
889
+	 * @throws EE_Error
890
+	 * @throws ReflectionException
891
+	 */
892
+	public function trash_cpt_item($post_id)
893
+	{
894
+		$this->request->setRequestParam('VNU_ID', $post_id);
895
+		$this->_trash_or_restore_venue('trash', false);
896
+	}
897
+
898
+
899
+	/**
900
+	 * @param int $post_id
901
+	 * @throws EE_Error
902
+	 * @throws ReflectionException
903
+	 */
904
+	public function restore_cpt_item($post_id)
905
+	{
906
+		$this->request->setRequestParam('VNU_ID', $post_id);
907
+		$this->_trash_or_restore_venue('draft', false);
908
+	}
909
+
910
+
911
+	/**
912
+	 * @param int $post_id
913
+	 * @throws EE_Error
914
+	 * @throws ReflectionException
915
+	 */
916
+	public function delete_cpt_item($post_id)
917
+	{
918
+		$this->request->setRequestParam('VNU_ID', $post_id);
919
+		$this->_delete_venue(false);
920
+	}
921
+
922
+
923
+	public function get_venue_object()
924
+	{
925
+		return $this->_cpt_model_obj;
926
+	}
927
+
928
+
929
+	/**
930
+	 * @throws EE_Error
931
+	 * @throws ReflectionException
932
+	 */
933
+	protected function _trash_or_restore_venue($venue_status = 'trash', $redirect_after = true)
934
+	{
935
+		$VNU_ID = $this->request->getRequestParam('VNU_ID', 0, 'int');
936
+
937
+		// loop thru venues
938
+		if ($VNU_ID) {
939
+			// clean status
940
+			$venue_status = sanitize_key($venue_status);
941
+			// grab status
942
+			if (! empty($venue_status)) {
943
+				$success = $this->_change_venue_status($VNU_ID, $venue_status);
944
+			} else {
945
+				$success = false;
946
+				$msg     = esc_html__(
947
+					'An error occurred. The venue could not be moved to the trash because a valid venue status was not not supplied.',
948
+					'event_espresso'
949
+				);
950
+				EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
951
+			}
952
+		} else {
953
+			$success = false;
954
+			$msg     = esc_html__(
955
+				'An error occurred. The venue could not be moved to the trash because a valid venue ID was not not supplied.',
956
+				'event_espresso'
957
+			);
958
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
959
+		}
960
+		$action = $venue_status == 'trash' ? 'moved to the trash' : 'restored from the trash';
961
+
962
+		if ($redirect_after) {
963
+			$this->_redirect_after_action($success, 'Venue', $action, ['action' => 'default']);
964
+		}
965
+	}
966
+
967
+
968
+	/**
969
+	 * @throws EE_Error
970
+	 * @throws ReflectionException
971
+	 */
972
+	protected function _trash_or_restore_venues($venue_status = 'trash')
973
+	{
974
+		// clean status
975
+		$venue_status = sanitize_key($venue_status);
976
+		// grab status
977
+		if (! empty($venue_status)) {
978
+			$success = true;
979
+			// determine the event id and set to array.
980
+			$VNU_IDs = $this->request->getRequestParam('venue_id', [], 'int', true);
981
+			// loop thru events
982
+			foreach ($VNU_IDs as $VNU_ID) {
983
+				if ($VNU_ID = absint($VNU_ID)) {
984
+					$results = $this->_change_venue_status($VNU_ID, $venue_status);
985
+					$success = $results !== false ? $success : false;
986
+				} else {
987
+					$msg = sprintf(
988
+						esc_html__(
989
+							'An error occurred. Venue #%d could not be moved to the trash because a valid venue ID was not not supplied.',
990
+							'event_espresso'
991
+						),
992
+						$VNU_ID
993
+					);
994
+					EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
995
+					$success = false;
996
+				}
997
+			}
998
+		} else {
999
+			$success = false;
1000
+			$msg     = esc_html__(
1001
+				'An error occurred. The venue could not be moved to the trash because a valid venue status was not not supplied.',
1002
+				'event_espresso'
1003
+			);
1004
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1005
+		}
1006
+		// in order to force a pluralized result message we need to send back a success status greater than 1
1007
+		$success = $success ? 2 : false;
1008
+		$action  = $venue_status == 'trash' ? 'moved to the trash' : 'restored from the trash';
1009
+		$this->_redirect_after_action($success, 'Venues', $action, ['action' => 'default']);
1010
+	}
1011
+
1012
+
1013
+	/**
1014
+	 * _trash_or_restore_venues
1015
+	 *
1016
+	 * //todo this is pretty much the same as the corresponding change_event_status method in Events_Admin_Page.  We
1017
+	 * should probably abstract this up to the EE_Admin_Page_CPT (or even EE_Admin_Page) and make this a common method
1018
+	 * accepting a certain number of params.
1019
+	 *
1020
+	 * @access  private
1021
+	 * @param int    $VNU_ID
1022
+	 * @param string $venue_status
1023
+	 * @return bool
1024
+	 * @throws EE_Error
1025
+	 * @throws ReflectionException
1026
+	 */
1027
+	private function _change_venue_status($VNU_ID = 0, $venue_status = '')
1028
+	{
1029
+		// grab venue id
1030
+		if (! $VNU_ID) {
1031
+			$msg = esc_html__('An error occurred. No Venue ID or an invalid Venue ID was received.', 'event_espresso');
1032
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1033
+			return false;
1034
+		}
1035
+
1036
+		$this->_cpt_model_obj = EEM_Venue::instance()->get_one_by_ID($VNU_ID);
1037
+
1038
+		// clean status
1039
+		$venue_status = sanitize_key($venue_status);
1040
+		// grab status
1041
+		if (! $venue_status) {
1042
+			$msg = esc_html__(
1043
+				'An error occurred. No Venue Status or an invalid Venue Status was received.',
1044
+				'event_espresso'
1045
+			);
1046
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1047
+			return false;
1048
+		}
1049
+
1050
+		// was event trashed or restored ?
1051
+		switch ($venue_status) {
1052
+			case 'draft':
1053
+				$action = 'restored from the trash';
1054
+				$hook   = 'AHEE_venue_restored_from_trash';
1055
+				break;
1056
+			case 'trash':
1057
+				$action = 'moved to the trash';
1058
+				$hook   = 'AHEE_venue_moved_to_trash';
1059
+				break;
1060
+			default:
1061
+				$action = 'updated';
1062
+				$hook   = false;
1063
+		}
1064
+		// use class to change status
1065
+		$this->_cpt_model_obj->set_status($venue_status);
1066
+		$success = $this->_cpt_model_obj->save();
1067
+
1068
+		if ($success === false) {
1069
+			$msg = sprintf(esc_html__('An error occurred. The venue could not be %s.', 'event_espresso'), $action);
1070
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1071
+			return false;
1072
+		}
1073
+		if ($hook) {
1074
+			do_action($hook);
1075
+		}
1076
+		return true;
1077
+	}
1078
+
1079
+
1080
+	/**
1081
+	 * @param bool $redirect_after
1082
+	 * @return void
1083
+	 * @throws EE_Error
1084
+	 * @throws ReflectionException
1085
+	 */
1086
+	protected function _delete_venue($redirect_after = true)
1087
+	{
1088
+		// determine the venue id and set to array.
1089
+		$VNU_ID = $this->request->getRequestParam('VNU_ID', 0, 'int');
1090
+		$VNU_ID = $this->request->getRequestParam('post', $VNU_ID, 'int');
1091
+
1092
+		// loop thru venues
1093
+		if ($VNU_ID) {
1094
+			$success = $this->_delete_or_trash_venue($VNU_ID);
1095
+		} else {
1096
+			$success = false;
1097
+			$msg     = esc_html__(
1098
+				'An error occurred. An venue could not be deleted because a valid venue ID was not not supplied.',
1099
+				'event_espresso'
1100
+			);
1101
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1102
+		}
1103
+		if ($redirect_after) {
1104
+			$this->_redirect_after_action($success, 'Venue', 'deleted', ['action' => 'default']);
1105
+		}
1106
+	}
1107
+
1108
+
1109
+	/**
1110
+	 * @throws EE_Error
1111
+	 * @throws ReflectionException
1112
+	 */
1113
+	protected function _delete_venues()
1114
+	{
1115
+		$success = true;
1116
+		// determine the event id and set to array.
1117
+		$VNU_IDs = $this->request->getRequestParam('venue_id', [], 'int', true);
1118
+		// loop thru events
1119
+		foreach ($VNU_IDs as $VNU_ID) {
1120
+			if ($VNU_ID = absint($VNU_ID)) {
1121
+				$results = $this->_delete_or_trash_venue($VNU_ID);
1122
+				$success = $results !== false ? $success : false;
1123
+			} else {
1124
+				$success = false;
1125
+				$msg     = esc_html__(
1126
+					'An error occurred. An venue could not be deleted because a valid venue ID was not not supplied.',
1127
+					'event_espresso'
1128
+				);
1129
+				EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1130
+			}
1131
+		}
1132
+		// in order to force a pluralized result message we need to send back a success status greater than 1
1133
+		$success = $success ? 2 : false;
1134
+		$this->_redirect_after_action(
1135
+			$success,
1136
+			esc_html__('Venues', 'event_espresso'),
1137
+			esc_html__('deleted', 'event_espresso'),
1138
+			['action' => 'default']
1139
+		);
1140
+	}
1141
+
1142
+
1143
+	// todo: put in parent
1144
+
1145
+
1146
+	/**
1147
+	 * @throws EE_Error
1148
+	 * @throws ReflectionException
1149
+	 */
1150
+	private function _delete_or_trash_venue($VNU_ID = false)
1151
+	{
1152
+		// grab event id
1153
+		if (! $VNU_ID = absint($VNU_ID)) {
1154
+			$msg = esc_html__('An error occurred. No Venue ID or an invalid Venue ID was received.', 'event_espresso');
1155
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1156
+			return false;
1157
+		}
1158
+
1159
+
1160
+		$venue = EEM_Venue::instance()->get_one_by_ID($VNU_ID);
1161
+		// first need to remove all term relationships
1162
+		$venue->_remove_relations('Term_Taxonomy');
1163
+		$success = $venue->delete_permanently();
1164
+		// did it all go as planned ?
1165
+		if ($success) {
1166
+			$msg = sprintf(esc_html__('Venue ID # %d has been deleted.', 'event_espresso'), $VNU_ID);
1167
+			EE_Error::add_success($msg);
1168
+		} else {
1169
+			$msg =
1170
+				sprintf(
1171
+					esc_html__('An error occurred. Venue ID # %d could not be deleted.', 'event_espresso'),
1172
+					$VNU_ID
1173
+				);
1174
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1175
+			return false;
1176
+		}
1177
+		do_action('AHEE__Venues_Admin_Page___delete_or_trash_venue__after_venue_deleted');
1178
+		return true;
1179
+	}
1180
+
1181
+
1182
+
1183
+
1184
+	/***********/
1185
+	/* QUERIES */
1186
+
1187
+
1188
+	public function get_venues($per_page = 10, $count = false)
1189
+	{
1190
+
1191
+		$orderby = $this->request->getRequestParam('orderby', '');
1192
+
1193
+		switch ($orderby) {
1194
+			case 'id':
1195
+				$orderby = 'VNU_ID';
1196
+				break;
1197
+
1198
+			case 'capacity':
1199
+				$orderby = 'VNU_capacity';
1200
+				break;
1201
+
1202
+			case 'city':
1203
+				$orderby = 'VNU_city';
1204
+				break;
1205
+
1206
+			default:
1207
+				$orderby = 'VNU_name';
1208
+		}
1209
+
1210
+		$sort         = $this->request->getRequestParam('order', 'ASC');
1211
+		$current_page = $this->request->getRequestParam('paged', 1, 'int');
1212
+		$per_page     = ! empty($per_page) ? $per_page : 10;
1213
+		$per_page     = $this->request->getRequestParam('perpage', $per_page, 'int');
1214
+
1215
+		$offset = ($current_page - 1) * $per_page;
1216
+		$limit  = [$offset, $per_page];
1217
+
1218
+		$category = $this->request->getRequestParam('category');
1219
+		$category = $category > 0 ? $category : null;
1220
+
1221
+		$where = [];
1222
+
1223
+		// only set initial status if it is in the incoming request.  Otherwise the "all" view display's all statuses.
1224
+		$status = $this->request->getRequestParam('status');
1225
+		if ($status && $status !== 'all') {
1226
+			$where['status'] = $status;
1227
+		}
1228
+
1229
+		$venue_status = $this->request->getRequestParam('venue_status');
1230
+		if ($venue_status) {
1231
+			$where['status'] = $venue_status;
1232
+		}
1233
+
1234
+
1235
+		if ($category) {
1236
+			$where['Term_Taxonomy.taxonomy'] = 'espresso_venue_categories';
1237
+			$where['Term_Taxonomy.term_id']  = $category;
1238
+		}
1239
+
1240
+
1241
+		if (! EE_Registry::instance()->CAP->current_user_can('ee_read_others_venues', 'get_venues')) {
1242
+			$where['VNU_wp_user'] = get_current_user_id();
1243
+		} else {
1244
+			if (! EE_Registry::instance()->CAP->current_user_can('ee_read_private_venues', 'get_venues')) {
1245
+				$where['OR'] = [
1246
+					'status*restrict_private' => ['!=', 'private'],
1247
+					'AND'                     => [
1248
+						'status*inclusive' => ['=', 'private'],
1249
+						'VNU_wp_user'      => get_current_user_id(),
1250
+					],
1251
+				];
1252
+			}
1253
+		}
1254
+
1255
+		$search_term = $this->request->getRequestParam('s');
1256
+		if ($search_term) {
1257
+			$search_term = '%' . $search_term . '%';
1258
+			$where['OR'] = [
1259
+				'VNU_name'               => ['LIKE', $search_term],
1260
+				'VNU_desc'               => ['LIKE', $search_term],
1261
+				'VNU_short_desc'         => ['LIKE', $search_term],
1262
+				'VNU_address'            => ['LIKE', $search_term],
1263
+				'VNU_address2'           => ['LIKE', $search_term],
1264
+				'VNU_city'               => ['LIKE', $search_term],
1265
+				'VNU_zip'                => ['LIKE', $search_term],
1266
+				'VNU_phone'              => ['LIKE', $search_term],
1267
+				'VNU_url'                => ['LIKE', $search_term],
1268
+				'VNU_virtual_phone'      => ['LIKE', $search_term],
1269
+				'VNU_virtual_url'        => ['LIKE', $search_term],
1270
+				'VNU_google_map_link'    => ['LIKE', $search_term],
1271
+				'Event.EVT_name'         => ['LIKE', $search_term],
1272
+				'Event.EVT_desc'         => ['LIKE', $search_term],
1273
+				'Event.EVT_phone'        => ['LIKE', $search_term],
1274
+				'Event.EVT_external_URL' => ['LIKE', $search_term],
1275
+			];
1276
+		}
1277
+
1278
+
1279
+		return $count
1280
+			? $this->_venue_model->count([$where], 'VNU_ID')
1281
+			: $this->_venue_model->get_all(
1282
+				[$where, 'limit' => $limit, 'order_by' => $orderby, 'order' => $sort]
1283
+			);
1284
+	}
1285
+
1286
+
1287
+
1288
+
1289
+	/** Venue Category Stuff **/
1290
+
1291
+	/**
1292
+	 * set the _category property with the category object for the loaded page.
1293
+	 *
1294
+	 * @access private
1295
+	 * @return void
1296
+	 */
1297
+	private function _set_category_object()
1298
+	{
1299
+		if (isset($this->_category->id) && ! empty($this->_category->id)) {
1300
+			return;
1301
+		} // already have the category object so get out.
1302
+
1303
+		// set default category object
1304
+		$this->_set_empty_category_object();
1305
+
1306
+		// only set if we've got an id
1307
+		$category_ID = $this->request->getRequestParam('VEN_CAT_ID', 0, 'int');
1308
+		if (! $category_ID) {
1309
+			return;
1310
+		}
1311
+
1312
+		$term = get_term($category_ID, 'espresso_venue_categories');
1313
+
1314
+
1315
+		if (! empty($term)) {
1316
+			$this->_category->category_name       = $term->name;
1317
+			$this->_category->category_identifier = $term->slug;
1318
+			$this->_category->category_desc       = $term->description;
1319
+			$this->_category->id                  = $term->term_id;
1320
+			$this->_category->parent              = $term->parent;
1321
+		}
1322
+	}
1323
+
1324
+
1325
+	private function _set_empty_category_object()
1326
+	{
1327
+		$this->_category                = new stdClass();
1328
+		$this->_category->category_name = $this->_category->category_identifier = $this->_category->category_desc = '';
1329
+		$this->_category->id            = $this->_category->parent = 0;
1330
+	}
1331
+
1332
+
1333
+	/**
1334
+	 * @throws EE_Error
1335
+	 */
1336
+	protected function _category_list_table()
1337
+	{
1338
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1339
+		$this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
1340
+			'add_category',
1341
+			'add_category',
1342
+			[],
1343
+			'add-new-h2'
1344
+		);
1345
+		$this->_search_btn_label = esc_html__('Venue Categories', 'event_espresso');
1346
+		$this->display_admin_list_table_page_with_sidebar();
1347
+	}
1348
+
1349
+
1350
+	/**
1351
+	 * @throws EE_Error
1352
+	 */
1353
+	protected function _category_details($view)
1354
+	{
1355
+
1356
+		// load formatter helper
1357
+		// load field generator helper
1358
+
1359
+		$route = $view == 'edit' ? 'update_category' : 'insert_category';
1360
+		$this->_set_add_edit_form_tags($route);
1361
+
1362
+		$this->_set_category_object();
1363
+		$id = ! empty($this->_category->id) ? $this->_category->id : '';
1364
+
1365
+		$delete_action = 'delete_category';
1366
+
1367
+		$redirect = EE_Admin_Page::add_query_args_and_nonce(['action' => 'category_list'], $this->_admin_base_url);
1368
+
1369
+		$this->_set_publish_post_box_vars('VEN_CAT_ID', $id, $delete_action, $redirect);
1370
+
1371
+		// take care of contents
1372
+		$this->_template_args['admin_page_content'] = $this->_category_details_content();
1373
+		$this->display_admin_page_with_sidebar();
1374
+	}
1375
+
1376
+
1377
+	protected function _category_details_content()
1378
+	{
1379
+		$editor_args['category_desc'] = [
1380
+			'type'          => 'wp_editor',
1381
+			'value'         => EEH_Formatter::admin_format_content($this->_category->category_desc),
1382
+			'class'         => 'my_editor_custom',
1383
+			'wpeditor_args' => ['media_buttons' => false],
1384
+		];
1385
+		$_wp_editor                   = $this->_generate_admin_form_fields($editor_args, 'array');
1386
+
1387
+		$all_terms = get_terms(
1388
+			['espresso_venue_categories'],
1389
+			['hide_empty' => 0, 'exclude' => [$this->_category->id]]
1390
+		);
1391
+
1392
+		// setup category select for term parents.
1393
+		$category_select_values[] = [
1394
+			'text' => esc_html__('No Parent', 'event_espresso'),
1395
+			'id'   => 0,
1396
+		];
1397
+		foreach ($all_terms as $term) {
1398
+			$category_select_values[] = [
1399
+				'text' => $term->name,
1400
+				'id'   => $term->term_id,
1401
+			];
1402
+		}
1403
+
1404
+		$category_select = EEH_Form_Fields::select_input(
1405
+			'category_parent',
1406
+			$category_select_values,
1407
+			$this->_category->parent
1408
+		);
1409
+		$template_args   = [
1410
+			'category'                 => $this->_category,
1411
+			'category_select'          => $category_select,
1412
+			'unique_id_info_help_link' => $this->_get_help_tab_link('unique_id_info'),
1413
+			'category_desc_editor'     => $_wp_editor['category_desc']['field'],
1414
+			'disable'                  => '',
1415
+			'disabled_message'         => false,
1416
+		];
1417
+		$template        = EVENTS_TEMPLATE_PATH . 'event_category_details.template.php';
1418
+		return EEH_Template::display_template($template, $template_args, true);
1419
+	}
1420
+
1421
+
1422
+	/**
1423
+	 * @throws EE_Error
1424
+	 */
1425
+	protected function _delete_categories()
1426
+	{
1427
+		$category_ID  = $this->request->getRequestParam('category_id', 0, 'int');
1428
+		$category_IDs = $this->request->getRequestParam('VEN_CAT_ID', [$category_ID], 'int', true);
1429
+
1430
+		foreach ($category_IDs as $cat_id) {
1431
+			$this->_delete_category($cat_id);
1432
+		}
1433
+
1434
+		// doesn't matter what page we're coming from... we're going to the same place after delete.
1435
+		$query_args = [
1436
+			'action' => 'category_list',
1437
+		];
1438
+		$this->_redirect_after_action(0, '', '', $query_args);
1439
+	}
1440
+
1441
+
1442
+	protected function _delete_category($cat_id)
1443
+	{
1444
+		$cat_id = absint($cat_id);
1445
+		wp_delete_term($cat_id, 'espresso_venue_categories');
1446
+	}
1447
+
1448
+
1449
+	/**
1450
+	 * @throws EE_Error
1451
+	 */
1452
+	protected function _insert_or_update_category($new_category)
1453
+	{
1454
+
1455
+		$cat_id  = $new_category ? $this->_insert_category() : $this->_insert_category(true);
1456
+		$success = 0; // we already have a success message so lets not send another.
1457
+		if ($cat_id) {
1458
+			$query_args = [
1459
+				'action'     => 'edit_category',
1460
+				'VEN_CAT_ID' => $cat_id,
1461
+			];
1462
+		} else {
1463
+			$query_args = ['action' => 'add_category'];
1464
+		}
1465
+		$this->_redirect_after_action($success, '', '', $query_args, true);
1466
+	}
1467
+
1468
+
1469
+	private function _insert_category($update = false)
1470
+	{
1471
+		$category_ID     = $update ? $this->request->getRequestParam('VEN_CAT_ID', '', 'int') : '';
1472
+		$category_name   = $this->request->getRequestParam('category_name', '');
1473
+		$category_desc   = $this->request->getRequestParam('category_desc', '', 'html');
1474
+		$category_parent = $this->request->getRequestParam('category_parent', 0, 'int');
1475
+
1476
+		if (empty($category_name)) {
1477
+			$msg = esc_html__('You must add a name for the category.', 'event_espresso');
1478
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1479
+			return false;
1480
+		}
1481
+
1482
+
1483
+		$term_args = [
1484
+			'name'        => $category_name,
1485
+			'description' => $category_desc,
1486
+			'parent'      => $category_parent,
1487
+		];
1488
+
1489
+		$insert_ids = $update
1490
+			? wp_update_term($category_ID, 'espresso_venue_categories', $term_args)
1491
+			: wp_insert_term(
1492
+				$category_name,
1493
+				'espresso_venue_categories',
1494
+				$term_args
1495
+			);
1496
+
1497
+		if (! is_array($insert_ids)) {
1498
+			EE_Error::add_error(
1499
+				esc_html__('An error occurred and the category has not been saved to the database.', 'event_espresso'),
1500
+				__FILE__,
1501
+				__FUNCTION__,
1502
+				__LINE__
1503
+			);
1504
+		} else {
1505
+			$category_ID = $insert_ids['term_id'];
1506
+			EE_Error::add_success(
1507
+				sprintf(
1508
+					esc_html__('The category %s was successfully created', 'event_espresso'),
1509
+					$category_name
1510
+				)
1511
+			);
1512
+		}
1513
+
1514
+		return $category_ID;
1515
+	}
1516
+
1517
+
1518
+	/**
1519
+	 * TODO handle category exports()
1520
+	 *
1521
+	 * @return void
1522
+	 */
1523
+	protected function _categories_export()
1524
+	{
1525
+		// todo: I don't like doing this but it'll do until we modify EE_Export Class.
1526
+		$this->request->mergeRequestParams(
1527
+			[
1528
+				'export'       => 'report',
1529
+				'action'       => 'categories',
1530
+				'category_ids' => $this->request->getRequestParam('VEN_CAT_ID', 0, 'int'),
1531
+			]
1532
+		);
1533
+
1534
+		if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
1535
+			require_once(EE_CLASSES . 'EE_Export.class.php');
1536
+			$EE_Export = EE_Export::instance($this->request->requestParams());
1537
+			$EE_Export->export();
1538
+		}
1539
+	}
1540
+
1541
+
1542
+	protected function _import_categories()
1543
+	{
1544
+
1545
+		require_once(EE_CLASSES . 'EE_Import.class.php');
1546
+		EE_Import::instance()->import();
1547
+	}
1548
+
1549
+
1550
+	/**
1551
+	 * @throws EE_Error
1552
+	 */
1553
+	public function get_categories($per_page = 10, $current_page = 1, $count = false)
1554
+	{
1555
+
1556
+		// testing term stuff
1557
+		$orderby     = $this->request->getRequestParam('orderby', 'Term.term_id');
1558
+		$order       = $this->request->getRequestParam('order', 'DESC');
1559
+		$limit       = ($current_page - 1) * $per_page;
1560
+		$where       = ['taxonomy' => 'espresso_venue_categories'];
1561
+		$search_term = $this->request->getRequestParam('s');
1562
+		if ($search_term) {
1563
+			$search_term = '%' . $search_term . '%';
1564
+			$where['OR'] = [
1565
+				'Term.name'   => ['LIKE', $search_term],
1566
+				'description' => ['LIKE', $search_term],
1567
+			];
1568
+		}
1569
+
1570
+		$query_params = [
1571
+			$where,
1572
+			'order_by'   => [$orderby => $order],
1573
+			'limit'      => $limit . ',' . $per_page,
1574
+			'force_join' => ['Term'],
1575
+		];
1576
+
1577
+		return $count
1578
+			? EEM_Term_Taxonomy::instance()->count($query_params, 'term_id')
1579
+			: EEM_Term_Taxonomy::instance()->get_all($query_params);
1580
+	}
1581
+
1582
+
1583
+	/* end category stuff */
1584
+	/**************/
1585 1585
 }
Please login to merge, or discard this patch.
libraries/messages/data_class/EE_Messages_Preview_incoming_data.class.php 2 patches
Spacing   +65 added lines, -65 removed lines patch added patch discarded remove patch
@@ -106,70 +106,70 @@  discard block
 block discarded – undo
106 106
         // we'll actually use the generated line_item identifiers for our loop
107 107
         $dtts = $tkts = [];
108 108
         foreach ($events as $id => $event) {
109
-            if (! $event instanceof EE_Event) {
109
+            if ( ! $event instanceof EE_Event) {
110 110
                 continue;
111 111
             }
112
-            $this->_events[ $id ]['ID']       = $id;
113
-            $this->_events[ $id ]['name']     = $event->get('EVT_name');
112
+            $this->_events[$id]['ID']       = $id;
113
+            $this->_events[$id]['name']     = $event->get('EVT_name');
114 114
             $datetime                         = $event->get_first_related('Datetime');
115 115
             $tickets                          = $datetime instanceof EE_Datetime ? $datetime->get_many_related(
116 116
                 'Ticket',
117 117
                 ['default_where_conditions' => 'none']
118 118
             ) : [];
119
-            $this->_events[ $id ]['event']    = $event;
120
-            $this->_events[ $id ]['reg_objs'] = [];
121
-            $this->_events[ $id ]['tkt_objs'] = $tickets;
122
-            $this->_events[ $id ]['dtt_objs'] = [];
119
+            $this->_events[$id]['event']    = $event;
120
+            $this->_events[$id]['reg_objs'] = [];
121
+            $this->_events[$id]['tkt_objs'] = $tickets;
122
+            $this->_events[$id]['dtt_objs'] = [];
123 123
 
124
-            $tkts     = [];
124
+            $tkts = [];
125 125
             foreach ($tickets as $ticket) {
126
-                if (! $ticket instanceof EE_Ticket) {
126
+                if ( ! $ticket instanceof EE_Ticket) {
127 127
                     continue;
128 128
                 }
129 129
                 $reldatetime                       = $ticket->datetimes();
130
-                $tkts[ $ticket->ID() ]             = [];
131
-                $tkts[ $ticket->ID() ]['ticket']   = $ticket;
132
-                $tkts[ $ticket->ID() ]['dtt_objs'] = $reldatetime;
133
-                $tkts[ $ticket->ID() ]['att_objs'] = $attendees;
134
-                $tkts[ $ticket->ID() ]['count']    = count($attendees);
135
-                $tkts[ $ticket->ID() ]['EE_Event'] = $event;
130
+                $tkts[$ticket->ID()]             = [];
131
+                $tkts[$ticket->ID()]['ticket']   = $ticket;
132
+                $tkts[$ticket->ID()]['dtt_objs'] = $reldatetime;
133
+                $tkts[$ticket->ID()]['att_objs'] = $attendees;
134
+                $tkts[$ticket->ID()]['count']    = count($attendees);
135
+                $tkts[$ticket->ID()]['EE_Event'] = $event;
136 136
                 foreach ($reldatetime as $datetime) {
137
-                    if ($datetime instanceof EE_Datetime && ! isset($dtts[ $datetime->ID() ])) {
138
-                        $this->_events[ $id ]['dtt_objs'][ $datetime->ID() ] = $datetime;
139
-                        $dtts[ $datetime->ID() ]['datetime']                 = $datetime;
140
-                        $dtts[ $datetime->ID() ]['tkt_objs'][]               = $ticket;
141
-                        $dtts[ $datetime->ID() ]['evt_objs'][]               = $event;
137
+                    if ($datetime instanceof EE_Datetime && ! isset($dtts[$datetime->ID()])) {
138
+                        $this->_events[$id]['dtt_objs'][$datetime->ID()] = $datetime;
139
+                        $dtts[$datetime->ID()]['datetime']                 = $datetime;
140
+                        $dtts[$datetime->ID()]['tkt_objs'][]               = $ticket;
141
+                        $dtts[$datetime->ID()]['evt_objs'][]               = $event;
142 142
                     }
143 143
                 }
144 144
             }
145 145
 
146
-            $this->_events[ $id ]['total_attendees'] = count($attendees);
147
-            $this->_events[ $id ]['att_objs']        = $attendees;
146
+            $this->_events[$id]['total_attendees'] = count($attendees);
147
+            $this->_events[$id]['att_objs']        = $attendees;
148 148
 
149 149
             // let's also setup the dummy attendees property!
150 150
             foreach ($attendees as $att_key => $attendee) {
151
-                if (! $attendee instanceof EE_Attendee) {
151
+                if ( ! $attendee instanceof EE_Attendee) {
152 152
                     continue;
153 153
                 }
154
-                $this->_attendees[ $att_key ]['line_ref'][] =
155
-                    $id;  // so later it can be determined what events this attendee registered for!
156
-                $this->_attendees[ $att_key ]['evt_objs'][] = $event;
157
-                $this->_attendees[ $att_key ]['att_obj']    = $attendee;
154
+                $this->_attendees[$att_key]['line_ref'][] =
155
+                    $id; // so later it can be determined what events this attendee registered for!
156
+                $this->_attendees[$att_key]['evt_objs'][] = $event;
157
+                $this->_attendees[$att_key]['att_obj']    = $attendee;
158 158
                 // $this->_attendees[$att_key]['registration_id'] = 0;
159
-                $this->_attendees[ $att_key ]['attendee_email'] = $attendee->email();
160
-                $this->_attendees[ $att_key ]['tkt_objs']       = $tickets;
159
+                $this->_attendees[$att_key]['attendee_email'] = $attendee->email();
160
+                $this->_attendees[$att_key]['tkt_objs']       = $tickets;
161 161
                 if ($att_key == 999999991) {
162
-                    $this->_attendees[ $att_key ]['ans_objs'][999]  = $answers_n_questions['answers'][999];
163
-                    $this->_attendees[ $att_key ]['ans_objs'][1002] = $answers_n_questions['answers'][1002];
164
-                    $this->_attendees[ $att_key ]['ans_objs'][1005] = $answers_n_questions['answers'][1005];
162
+                    $this->_attendees[$att_key]['ans_objs'][999]  = $answers_n_questions['answers'][999];
163
+                    $this->_attendees[$att_key]['ans_objs'][1002] = $answers_n_questions['answers'][1002];
164
+                    $this->_attendees[$att_key]['ans_objs'][1005] = $answers_n_questions['answers'][1005];
165 165
                 } elseif ($att_key == 999999992) {
166
-                    $this->_attendees[ $att_key ]['ans_objs'][1000] = $answers_n_questions['answers'][1000];
167
-                    $this->_attendees[ $att_key ]['ans_objs'][1003] = $answers_n_questions['answers'][1003];
168
-                    $this->_attendees[ $att_key ]['ans_objs'][1006] = $answers_n_questions['answers'][1006];
166
+                    $this->_attendees[$att_key]['ans_objs'][1000] = $answers_n_questions['answers'][1000];
167
+                    $this->_attendees[$att_key]['ans_objs'][1003] = $answers_n_questions['answers'][1003];
168
+                    $this->_attendees[$att_key]['ans_objs'][1006] = $answers_n_questions['answers'][1006];
169 169
                 } elseif ($att_key == 999999993) {
170
-                    $this->_attendees[ $att_key ]['ans_objs'][1001] = $answers_n_questions['answers'][1001];
171
-                    $this->_attendees[ $att_key ]['ans_objs'][1004] = $answers_n_questions['answers'][1004];
172
-                    $this->_attendees[ $att_key ]['ans_objs'][1007] = $answers_n_questions['answers'][1007];
170
+                    $this->_attendees[$att_key]['ans_objs'][1001] = $answers_n_questions['answers'][1001];
171
+                    $this->_attendees[$att_key]['ans_objs'][1004] = $answers_n_questions['answers'][1004];
172
+                    $this->_attendees[$att_key]['ans_objs'][1007] = $answers_n_questions['answers'][1007];
173 173
                 }
174 174
             }
175 175
         }
@@ -270,7 +270,7 @@  discard block
 block discarded – undo
270 270
             /** @var $email string */
271 271
             /** @var $phone string */
272 272
             /** @var $attid string */
273
-            $attendees[ $attid ] = EE_Attendee::new_instance(
273
+            $attendees[$attid] = EE_Attendee::new_instance(
274 274
                 [
275 275
                     'ATT_fname'    => $fname,
276 276
                     'ATT_lname'    => $lname,
@@ -377,7 +377,7 @@  discard block
 block discarded – undo
377 377
         // first the questions
378 378
         foreach ($quests_array as $qst) {
379 379
             $qstobj                    = array_combine($qst_columns, $qst);
380
-            $qsts[ $qstobj['QST_ID'] ] = EE_Question::new_instance($qstobj);
380
+            $qsts[$qstobj['QST_ID']] = EE_Question::new_instance($qstobj);
381 381
         }
382 382
 
383 383
         // now the answers (and we'll setup our arrays)
@@ -385,8 +385,8 @@  discard block
 block discarded – undo
385 385
         foreach ($ans_array as $ans) {
386 386
             $ansobj                               = array_combine($ans_columns, $ans);
387 387
             $ansobj                               = EE_Answer::new_instance($ansobj);
388
-            $q_n_as['answers'][ $ansobj->ID() ]   = $ansobj;
389
-            $q_n_as['questions'][ $ansobj->ID() ] = $qsts[ $ansobj->get('QST_ID') ];
388
+            $q_n_as['answers'][$ansobj->ID()]   = $ansobj;
389
+            $q_n_as['questions'][$ansobj->ID()] = $qsts[$ansobj->get('QST_ID')];
390 390
         }
391 391
 
392 392
         return $q_n_as;
@@ -471,11 +471,11 @@  discard block
 block discarded – undo
471 471
             $regtxn = $this->txn->ID();
472 472
             $regcnt = 1;
473 473
             foreach ($attendee['line_ref'] as $evtid) {
474
-                foreach ($this->_events[ $evtid ]['tkt_objs'] as $ticket) {
475
-                    if (! $ticket instanceof EE_Ticket) {
474
+                foreach ($this->_events[$evtid]['tkt_objs'] as $ticket) {
475
+                    if ( ! $ticket instanceof EE_Ticket) {
476 476
                         continue;
477 477
                     }
478
-                    $reg_array                                            = [
478
+                    $reg_array = [
479 479
                         'EVT_ID'           => $evtid,
480 480
                         'ATT_ID'           => $regatt,
481 481
                         'TXN_ID'           => $regtxn,
@@ -484,18 +484,18 @@  discard block
 block discarded – undo
484 484
                         'REG_date'         => time(),
485 485
                         'REG_final_price'  => $ticket->get('TKT_price'),
486 486
                         'REG_session'      => 'dummy_session_id',
487
-                        'REG_code'         => $regid . '-dummy-generated-code',
488
-                        'REG_url_link'     => $regcnt . '-daafpapasdlfakasdfpqasdfasdf',
487
+                        'REG_code'         => $regid.'-dummy-generated-code',
488
+                        'REG_url_link'     => $regcnt.'-daafpapasdlfakasdfpqasdfasdf',
489 489
                         'REG_count'        => $regcnt,
490
-                        'REG_group_size'   => $this->_events[ $evtid ]['total_attendees'],
490
+                        'REG_group_size'   => $this->_events[$evtid]['total_attendees'],
491 491
                         'REG_att_is_going' => true,
492 492
                         'REG_ID'           => $regid,
493 493
                     ];
494 494
                     $REG_OBJ                                              = EE_Registration::new_instance($reg_array);
495
-                    $this->_attendees[ $key ]['reg_objs'][ $regid ]       = $REG_OBJ;
496
-                    $this->_events[ $evtid ]['reg_objs'][]                = $REG_OBJ;
495
+                    $this->_attendees[$key]['reg_objs'][$regid]       = $REG_OBJ;
496
+                    $this->_events[$evtid]['reg_objs'][]                = $REG_OBJ;
497 497
                     $this->reg_objs[]                                     = $REG_OBJ;
498
-                    $this->tickets[ $ticket->ID() ]['reg_objs'][ $regid ] = $REG_OBJ;
498
+                    $this->tickets[$ticket->ID()]['reg_objs'][$regid] = $REG_OBJ;
499 499
 
500 500
                     $regcnt++;
501 501
                     $regid++;
@@ -541,19 +541,19 @@  discard block
 block discarded – undo
541 541
         $event_line_items = EEH_Line_Item::get_pre_tax_subtotal($line_item_total)->children();
542 542
         $line_items       = [];
543 543
         foreach ($event_line_items as $line_item) {
544
-            if (! $line_item instanceof EE_Line_Item || $line_item->OBJ_type() !== 'Event') {
544
+            if ( ! $line_item instanceof EE_Line_Item || $line_item->OBJ_type() !== 'Event') {
545 545
                 continue;
546 546
             }
547 547
             $ticket_line_items = EEH_Line_Item::get_ticket_line_items($line_item);
548 548
             foreach ($ticket_line_items as $ticket_line_item) {
549
-                if (! $ticket_line_item instanceof EE_Line_Item) {
549
+                if ( ! $ticket_line_item instanceof EE_Line_Item) {
550 550
                     continue;
551 551
                 }
552
-                $this->tickets[ $ticket_line_item->OBJ_ID() ]['line_item']      = $ticket_line_item;
553
-                $this->tickets[ $ticket_line_item->OBJ_ID() ]['sub_line_items'] = $ticket_line_item->children();
554
-                $line_items[ $ticket_line_item->ID() ]['children']              = $ticket_line_item->children();
555
-                $line_items[ $ticket_line_item->ID() ]['EE_Ticket']             =
556
-                    $this->tickets[ $ticket_line_item->OBJ_ID() ]['ticket'];
552
+                $this->tickets[$ticket_line_item->OBJ_ID()]['line_item']      = $ticket_line_item;
553
+                $this->tickets[$ticket_line_item->OBJ_ID()]['sub_line_items'] = $ticket_line_item->children();
554
+                $line_items[$ticket_line_item->ID()]['children']              = $ticket_line_item->children();
555
+                $line_items[$ticket_line_item->ID()]['EE_Ticket']             =
556
+                    $this->tickets[$ticket_line_item->OBJ_ID()]['ticket'];
557 557
             }
558 558
         }
559 559
 
@@ -568,15 +568,15 @@  discard block
 block discarded – undo
568 568
 
569 569
         // add additional details for each registration
570 570
         foreach ($this->reg_objs as $reg) {
571
-            if (! $reg instanceof EE_Registration) {
571
+            if ( ! $reg instanceof EE_Registration) {
572 572
                 continue;
573 573
             }
574
-            $this->_registrations[ $reg->ID() ]['tkt_obj']  = $this->tickets[ $reg->get('TKT_ID') ]['ticket'];
575
-            $this->_registrations[ $reg->ID() ]['evt_obj']  = $this->_events[ $reg->get('EVT_ID') ]['event'];
576
-            $this->_registrations[ $reg->ID() ]['reg_obj']  = $reg;
577
-            $this->_registrations[ $reg->ID() ]['ans_objs'] = $this->_attendees[ $reg->get('ATT_ID') ]['ans_objs'];
578
-            $this->_registrations[ $reg->ID() ]['att_obj']  = $this->_attendees[ $reg->get('ATT_ID') ]['att_obj'];
579
-            $this->_registrations[ $reg->ID() ]['dtt_objs'] = $this->tickets[ $reg->get('TKT_ID') ]['dtt_objs'];
574
+            $this->_registrations[$reg->ID()]['tkt_obj']  = $this->tickets[$reg->get('TKT_ID')]['ticket'];
575
+            $this->_registrations[$reg->ID()]['evt_obj']  = $this->_events[$reg->get('EVT_ID')]['event'];
576
+            $this->_registrations[$reg->ID()]['reg_obj']  = $reg;
577
+            $this->_registrations[$reg->ID()]['ans_objs'] = $this->_attendees[$reg->get('ATT_ID')]['ans_objs'];
578
+            $this->_registrations[$reg->ID()]['att_obj']  = $this->_attendees[$reg->get('ATT_ID')]['att_obj'];
579
+            $this->_registrations[$reg->ID()]['dtt_objs'] = $this->tickets[$reg->get('TKT_ID')]['dtt_objs'];
580 580
         }
581 581
 
582 582
 
Please login to merge, or discard this patch.
Indentation   +599 added lines, -599 removed lines patch added patch discarded remove patch
@@ -20,603 +20,603 @@
 block discarded – undo
20 20
  */
21 21
 class EE_Messages_Preview_incoming_data extends EE_Messages_incoming_data
22 22
 {
23
-    // some specific properties we need for this class
24
-    private $_events        = [];
25
-
26
-    private $_attendees     = [];
27
-
28
-    private $_registrations = [];
29
-
30
-
31
-    /**
32
-     * For the constructor of this special preview class.  We're either looking for an event id or empty data.  If we
33
-     * have an event id (or ids) then we'll use that as the source for the "dummy" data.  If the data is empty then
34
-     * we'll get the first three published events from the users database and use that as a source.
35
-     *
36
-     * @param array $data
37
-     * @throws EE_Error
38
-     * @throws EE_Error
39
-     * @throws ReflectionException
40
-     */
41
-    public function __construct($data = [])
42
-    {
43
-        $this->_data = isset($data['event_ids']) ? $data['event_ids'] : [];
44
-        $this->_setup_attendees_events();
45
-        parent::__construct($data);
46
-    }
47
-
48
-
49
-    /**
50
-     * Returns database safe representation of the data later used to when instantiating this object.
51
-     *
52
-     * @param array $data The incoming data to be prepped.
53
-     *
54
-     * @return array   The prepped data for db
55
-     */
56
-    public static function convert_data_for_persistent_storage($data)
57
-    {
58
-        return $data;
59
-    }
60
-
61
-
62
-    /**
63
-     * Data that has been stored in persistent storage that was prepped by _convert_data_for_persistent_storage
64
-     * can be sent into this method and converted back into the format used for instantiating with this data handler.
65
-     *
66
-     * @param array $data
67
-     *
68
-     * @return array
69
-     */
70
-    public static function convert_data_from_persistent_storage($data)
71
-    {
72
-        return $data;
73
-    }
74
-
75
-
76
-    /**
77
-     * This will just setup the _events property in the expected format.
78
-     *
79
-     * @throws EE_Error
80
-     * @throws ReflectionException
81
-     */
82
-    private function _setup_attendees_events()
83
-    {
84
-
85
-        // setup some attendee objects
86
-        $attendees = $this->_get_some_attendees();
87
-
88
-        // if empty $data we'll do a query to get some events from the server.
89
-        // otherwise we'll retrieve the event data for the given ids.
90
-        $events = $this->_get_some_events($this->_data);
91
-
92
-        $answers_n_questions = $this->_get_some_q_and_as();
93
-
94
-        if (count($events) < 1) {
95
-            throw new EE_Error(
96
-                esc_html__(
97
-                    'We can\'t generate a preview for you because there are no active events in your database',
98
-                    'event_espresso'
99
-                )
100
-            );
101
-        }
102
-
103
-
104
-        // now let's loop and set up the _events property.  At the same time we'll set up attendee properties.
105
-        // we'll actually use the generated line_item identifiers for our loop
106
-        $dtts = $tkts = [];
107
-        foreach ($events as $id => $event) {
108
-            if (! $event instanceof EE_Event) {
109
-                continue;
110
-            }
111
-            $this->_events[ $id ]['ID']       = $id;
112
-            $this->_events[ $id ]['name']     = $event->get('EVT_name');
113
-            $datetime                         = $event->get_first_related('Datetime');
114
-            $tickets                          = $datetime instanceof EE_Datetime ? $datetime->get_many_related(
115
-                'Ticket',
116
-                ['default_where_conditions' => 'none']
117
-            ) : [];
118
-            $this->_events[ $id ]['event']    = $event;
119
-            $this->_events[ $id ]['reg_objs'] = [];
120
-            $this->_events[ $id ]['tkt_objs'] = $tickets;
121
-            $this->_events[ $id ]['dtt_objs'] = [];
122
-
123
-            $tkts     = [];
124
-            foreach ($tickets as $ticket) {
125
-                if (! $ticket instanceof EE_Ticket) {
126
-                    continue;
127
-                }
128
-                $reldatetime                       = $ticket->datetimes();
129
-                $tkts[ $ticket->ID() ]             = [];
130
-                $tkts[ $ticket->ID() ]['ticket']   = $ticket;
131
-                $tkts[ $ticket->ID() ]['dtt_objs'] = $reldatetime;
132
-                $tkts[ $ticket->ID() ]['att_objs'] = $attendees;
133
-                $tkts[ $ticket->ID() ]['count']    = count($attendees);
134
-                $tkts[ $ticket->ID() ]['EE_Event'] = $event;
135
-                foreach ($reldatetime as $datetime) {
136
-                    if ($datetime instanceof EE_Datetime && ! isset($dtts[ $datetime->ID() ])) {
137
-                        $this->_events[ $id ]['dtt_objs'][ $datetime->ID() ] = $datetime;
138
-                        $dtts[ $datetime->ID() ]['datetime']                 = $datetime;
139
-                        $dtts[ $datetime->ID() ]['tkt_objs'][]               = $ticket;
140
-                        $dtts[ $datetime->ID() ]['evt_objs'][]               = $event;
141
-                    }
142
-                }
143
-            }
144
-
145
-            $this->_events[ $id ]['total_attendees'] = count($attendees);
146
-            $this->_events[ $id ]['att_objs']        = $attendees;
147
-
148
-            // let's also setup the dummy attendees property!
149
-            foreach ($attendees as $att_key => $attendee) {
150
-                if (! $attendee instanceof EE_Attendee) {
151
-                    continue;
152
-                }
153
-                $this->_attendees[ $att_key ]['line_ref'][] =
154
-                    $id;  // so later it can be determined what events this attendee registered for!
155
-                $this->_attendees[ $att_key ]['evt_objs'][] = $event;
156
-                $this->_attendees[ $att_key ]['att_obj']    = $attendee;
157
-                // $this->_attendees[$att_key]['registration_id'] = 0;
158
-                $this->_attendees[ $att_key ]['attendee_email'] = $attendee->email();
159
-                $this->_attendees[ $att_key ]['tkt_objs']       = $tickets;
160
-                if ($att_key == 999999991) {
161
-                    $this->_attendees[ $att_key ]['ans_objs'][999]  = $answers_n_questions['answers'][999];
162
-                    $this->_attendees[ $att_key ]['ans_objs'][1002] = $answers_n_questions['answers'][1002];
163
-                    $this->_attendees[ $att_key ]['ans_objs'][1005] = $answers_n_questions['answers'][1005];
164
-                } elseif ($att_key == 999999992) {
165
-                    $this->_attendees[ $att_key ]['ans_objs'][1000] = $answers_n_questions['answers'][1000];
166
-                    $this->_attendees[ $att_key ]['ans_objs'][1003] = $answers_n_questions['answers'][1003];
167
-                    $this->_attendees[ $att_key ]['ans_objs'][1006] = $answers_n_questions['answers'][1006];
168
-                } elseif ($att_key == 999999993) {
169
-                    $this->_attendees[ $att_key ]['ans_objs'][1001] = $answers_n_questions['answers'][1001];
170
-                    $this->_attendees[ $att_key ]['ans_objs'][1004] = $answers_n_questions['answers'][1004];
171
-                    $this->_attendees[ $att_key ]['ans_objs'][1007] = $answers_n_questions['answers'][1007];
172
-                }
173
-            }
174
-        }
175
-
176
-        $this->tickets            = $tkts;
177
-        $this->datetimes          = $dtts;
178
-        $this->answers            = $answers_n_questions['answers'];
179
-        $this->questions          = $answers_n_questions['questions'];
180
-        $this->total_ticket_count = count($tkts) * count($this->_attendees);
181
-    }
182
-
183
-
184
-    /**
185
-     * This just returns an array of dummy attendee objects that we'll use to attach to events for our preview data
186
-     *
187
-     * @access private
188
-     * @return array an array of attendee objects
189
-     * @throws EE_Error
190
-     * @throws EE_Error
191
-     */
192
-    private function _get_some_attendees()
193
-    {
194
-        // let's just setup a dummy array of various attendee details
195
-        $dummy_attendees = [
196
-            0 => [
197
-                'Luke',
198
-                'Skywalker',
199
-                '[email protected]',
200
-                '804 Bantha Dr.',
201
-                'Complex 8',
202
-                'Mos Eisley',
203
-                32,
204
-                'US',
205
-                'f0r3e',
206
-                '222-333-4763',
207
-                false,
208
-                '999999991',
209
-            ],
210
-            1 => [
211
-                'Princess',
212
-                'Leia',
213
-                '[email protected]',
214
-                '1456 Valley Way Boulevard',
215
-                'Suite 9',
216
-                'Alderaan',
217
-                15,
218
-                'US',
219
-                'c1h2c',
220
-                '78-123-111-1111',
221
-                false,
222
-                '999999992',
223
-            ],
224
-            2 => [
225
-                'Yoda',
226
-                'I Am',
227
-                '[email protected]',
228
-                '4th Tree',
229
-                '5th Knot',
230
-                'Marsh',
231
-                22,
232
-                'US',
233
-                'l18n',
234
-                '999-999-9999',
235
-                false,
236
-                '999999993',
237
-            ],
238
-        ];
239
-
240
-        // let's generate the attendee objects
241
-        $attendees = [];
242
-        $var_array = [
243
-            'fname',
244
-            'lname',
245
-            'email',
246
-            'address',
247
-            'address2',
248
-            'city',
249
-            'staid',
250
-            'cntry',
251
-            'zip',
252
-            'phone',
253
-            'deleted',
254
-            'attid',
255
-        ];
256
-
257
-        // EE_Registry::instance()->load_class( 'Attendee', array(), FALSE, false, TRUE );
258
-        foreach ($dummy_attendees as $dummy) {
259
-            $att = array_combine($var_array, $dummy);
260
-            extract($att);
261
-            /** @var $fname string */
262
-            /** @var $lname string */
263
-            /** @var $address string */
264
-            /** @var $address2 string */
265
-            /** @var $city string */
266
-            /** @var $staid string */
267
-            /** @var $cntry string */
268
-            /** @var $zip string */
269
-            /** @var $email string */
270
-            /** @var $phone string */
271
-            /** @var $attid string */
272
-            $attendees[ $attid ] = EE_Attendee::new_instance(
273
-                [
274
-                    'ATT_fname'    => $fname,
275
-                    'ATT_lname'    => $lname,
276
-                    'ATT_address'  => $address,
277
-                    'ATT_address2' => $address2,
278
-                    'ATT_city'     => $city,
279
-                    'STA_ID'       => $staid,
280
-                    'CNT_ISO'      => $cntry,
281
-                    'ATT_zip'      => $zip,
282
-                    'ATT_email'    => $email,
283
-                    'ATT_phone'    => $phone,
284
-                    'ATT_ID'       => $attid,
285
-                ]
286
-            );
287
-        }
288
-
289
-        return $attendees;
290
-    }
291
-
292
-
293
-    /**
294
-     * Return an array of dummy question objects indexed by answer id and dummy answer objects indexed by answer id.
295
-     * This will be used in our dummy data setup
296
-     *
297
-     * @return array
298
-     * @throws EE_Error
299
-     * @throws ReflectionException
300
-     */
301
-    private function _get_some_q_and_as()
302
-    {
303
-        $quests_array = [
304
-            0 => [
305
-                555,
306
-                esc_html__('What is your favorite planet?', 'event_espresso'),
307
-                0,
308
-            ],
309
-            1 => [
310
-                556,
311
-                esc_html__('What is your favorite food?', 'event_espresso'),
312
-                0,
313
-            ],
314
-            2 => [
315
-                557,
316
-                esc_html__('How many lightyears have you travelled', 'event_espresso'),
317
-                0,
318
-            ],
319
-        ];
320
-
321
-        $ans_array = [
322
-            0 => [
323
-                999,
324
-                555,
325
-                'Tattoine',
326
-            ],
327
-            1 => [
328
-                1000,
329
-                555,
330
-                'Alderaan',
331
-            ],
332
-            2 => [
333
-                1001,
334
-                555,
335
-                'Dantooine',
336
-            ],
337
-            3 => [
338
-                1002,
339
-                556,
340
-                'Fish Fingers',
341
-            ],
342
-            4 => [
343
-                1003,
344
-                556,
345
-                'Sushi',
346
-            ],
347
-            5 => [
348
-                1004,
349
-                556,
350
-                'Water',
351
-            ],
352
-            6 => [
353
-                1005,
354
-                557,
355
-                'A lot',
356
-            ],
357
-            7 => [
358
-                1006,
359
-                557,
360
-                "That's none of your business.",
361
-            ],
362
-            8 => [
363
-                1007,
364
-                557,
365
-                "People less travel me then.",
366
-            ],
367
-        ];
368
-
369
-        $qst_columns = ['QST_ID', 'QST_display_text', 'QST_system'];
370
-        $ans_columns = ['ANS_ID', 'QST_ID', 'ANS_value'];
371
-
372
-        // EE_Registry::instance()->load_class( 'Question', array(), FALSE, TRUE, TRUE );
373
-        // EE_Registry::instance()->load_class( 'Answer', array(), FALSE, TRUE, TRUE );
374
-
375
-        $qsts = [];
376
-        // first the questions
377
-        foreach ($quests_array as $qst) {
378
-            $qstobj                    = array_combine($qst_columns, $qst);
379
-            $qsts[ $qstobj['QST_ID'] ] = EE_Question::new_instance($qstobj);
380
-        }
381
-
382
-        // now the answers (and we'll setup our arrays)
383
-        $q_n_as = [];
384
-        foreach ($ans_array as $ans) {
385
-            $ansobj                               = array_combine($ans_columns, $ans);
386
-            $ansobj                               = EE_Answer::new_instance($ansobj);
387
-            $q_n_as['answers'][ $ansobj->ID() ]   = $ansobj;
388
-            $q_n_as['questions'][ $ansobj->ID() ] = $qsts[ $ansobj->get('QST_ID') ];
389
-        }
390
-
391
-        return $q_n_as;
392
-    }
393
-
394
-
395
-    /**
396
-     * Return an array of event objects from the database
397
-     *
398
-     * If event ids are not included then we'll just retrieve the first published event from the database.
399
-     *
400
-     * @param array $event_ids if set, this will be an array of event ids to obtain events for.
401
-     *
402
-     * @return array    An array of event objects from the db.
403
-     * @throws EE_Error
404
-     */
405
-    private function _get_some_events(array $event_ids = [])
406
-    {
407
-        /** @var RequestInterface $request */
408
-        $request = LoaderFactory::getLoader()->getShared(RequestInterface::class);
409
-        // if we have an evt_id then we want to make sure we use that for the preview
410
-        // (because a specific event template is being viewed);
411
-        $event_ids = $request->getRequestParam('evt_id', $event_ids, 'int', true);
412
-        // clear out any invalid IDs, like 0
413
-        $event_ids = array_filter($event_ids);
414
-        $limit     = ! empty($event_ids)
415
-            ? null
416
-            : apply_filters('FHEE__EE_Messages_Preview_incoming_data___get_some_events__limit', '0,1');
417
-
418
-        $where = ! empty($event_ids)
419
-            ? [
420
-                'EVT_ID'                 => ['IN', $event_ids],
421
-                'Datetime.Ticket.TKT_ID' => ['>', 1],
422
-            ]
423
-            : ['Datetime.Ticket.TKT_ID' => ['>', 1]];
424
-
425
-        return EEM_Event::instance()->get_all([$where, 'limit' => $limit]);
426
-    }
427
-
428
-
429
-    /**
430
-     * @throws EE_Error
431
-     * @throws ReflectionException
432
-     */
433
-    protected function _setup_data()
434
-    {
435
-        // need to figure out the running total for test purposes so... we're going to create a temp cart and add the tickets to it!
436
-        if (EE_Registry::instance()->SSN instanceof EE_Session) {
437
-            EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
438
-            $session = EE_Registry::instance()->SSN;
439
-        } else {
440
-            $session = EE_Registry::instance()->load_core('Session');
441
-        }
442
-        $cart = EE_Cart::instance(null, $session);
443
-
444
-        // add tickets to cart
445
-        foreach ($this->tickets as $ticket) {
446
-            $cart->add_ticket_to_cart($ticket['ticket']);
447
-        }
448
-
449
-        // setup txn property
450
-        $this->txn = EE_Transaction::new_instance(
451
-            [
452
-                'TXN_timestamp'    => time(), // unix timestamp
453
-                'TXN_total'        => 0, // txn_total
454
-                'TXN_paid'         => 0, // txn_paid
455
-                'STS_ID'           => EEM_Transaction::incomplete_status_code, // sts_id
456
-                'TXN_session_data' => null, // dump of txn session object (we're just going to leave blank here)
457
-                'TXN_hash_salt'    => null, // hash salt blank as well
458
-                'TXN_ID'           => 999999,
459
-            ]
460
-        );
461
-
462
-
463
-        // setup reg_objects
464
-        // note we're setting up a reg object for each attendee in each event but ALSO adding to the reg_object array.
465
-        $this->reg_objs = [];
466
-        $regid          = 9999990;
467
-        foreach ($this->_attendees as $key => $attendee) {
468
-            // note we need to setup reg_objects for each event this attendee belongs to
469
-            $regatt = $attendee['att_obj'] instanceof EE_Attendee ? $attendee['att_obj']->ID() : null;
470
-            $regtxn = $this->txn->ID();
471
-            $regcnt = 1;
472
-            foreach ($attendee['line_ref'] as $evtid) {
473
-                foreach ($this->_events[ $evtid ]['tkt_objs'] as $ticket) {
474
-                    if (! $ticket instanceof EE_Ticket) {
475
-                        continue;
476
-                    }
477
-                    $reg_array                                            = [
478
-                        'EVT_ID'           => $evtid,
479
-                        'ATT_ID'           => $regatt,
480
-                        'TXN_ID'           => $regtxn,
481
-                        'TKT_ID'           => $ticket->ID(),
482
-                        'STS_ID'           => EEM_Registration::status_id_pending_payment,
483
-                        'REG_date'         => time(),
484
-                        'REG_final_price'  => $ticket->get('TKT_price'),
485
-                        'REG_session'      => 'dummy_session_id',
486
-                        'REG_code'         => $regid . '-dummy-generated-code',
487
-                        'REG_url_link'     => $regcnt . '-daafpapasdlfakasdfpqasdfasdf',
488
-                        'REG_count'        => $regcnt,
489
-                        'REG_group_size'   => $this->_events[ $evtid ]['total_attendees'],
490
-                        'REG_att_is_going' => true,
491
-                        'REG_ID'           => $regid,
492
-                    ];
493
-                    $REG_OBJ                                              = EE_Registration::new_instance($reg_array);
494
-                    $this->_attendees[ $key ]['reg_objs'][ $regid ]       = $REG_OBJ;
495
-                    $this->_events[ $evtid ]['reg_objs'][]                = $REG_OBJ;
496
-                    $this->reg_objs[]                                     = $REG_OBJ;
497
-                    $this->tickets[ $ticket->ID() ]['reg_objs'][ $regid ] = $REG_OBJ;
498
-
499
-                    $regcnt++;
500
-                    $regid++;
501
-                }
502
-            }
503
-        }
504
-
505
-
506
-        // setup line items!
507
-        $line_item_total = EEH_Line_Item::create_total_line_item($this->txn);
508
-
509
-        // add tickets
510
-        foreach ($this->tickets as $item) {
511
-            $qty    = $item['count'];
512
-            $ticket = $item['ticket'];
513
-            EEH_Line_Item::add_ticket_purchase($line_item_total, $ticket, $qty);
514
-        }
515
-
516
-        $shipping_line_item = EE_Line_Item::new_instance(
517
-            [
518
-                'LIN_name'       => esc_html__(
519
-                    'Shipping Surcharge',
520
-                    'event_espresso'
521
-                ),
522
-                'LIN_desc'       => esc_html__(
523
-                    'Sent via Millenium Falcon',
524
-                    'event_espresso'
525
-                ),
526
-                'LIN_unit_price' => 20,
527
-                'LIN_quantity'   => 1,
528
-                'LIN_is_taxable' => true,
529
-                'LIN_total'      => 20,
530
-                'LIN_type'       => EEM_Line_Item::type_line_item,
531
-            ]
532
-        );
533
-        EEH_Line_Item::add_item($line_item_total, $shipping_line_item);
534
-        $this->additional_line_items = [$shipping_line_item];
535
-
536
-        // now let's add taxes
537
-        EEH_Line_Item::apply_taxes($line_item_total);
538
-
539
-        // now we should be able to get the items we need from this object
540
-        $event_line_items = EEH_Line_Item::get_pre_tax_subtotal($line_item_total)->children();
541
-        $line_items       = [];
542
-        foreach ($event_line_items as $line_item) {
543
-            if (! $line_item instanceof EE_Line_Item || $line_item->OBJ_type() !== 'Event') {
544
-                continue;
545
-            }
546
-            $ticket_line_items = EEH_Line_Item::get_ticket_line_items($line_item);
547
-            foreach ($ticket_line_items as $ticket_line_item) {
548
-                if (! $ticket_line_item instanceof EE_Line_Item) {
549
-                    continue;
550
-                }
551
-                $this->tickets[ $ticket_line_item->OBJ_ID() ]['line_item']      = $ticket_line_item;
552
-                $this->tickets[ $ticket_line_item->OBJ_ID() ]['sub_line_items'] = $ticket_line_item->children();
553
-                $line_items[ $ticket_line_item->ID() ]['children']              = $ticket_line_item->children();
554
-                $line_items[ $ticket_line_item->ID() ]['EE_Ticket']             =
555
-                    $this->tickets[ $ticket_line_item->OBJ_ID() ]['ticket'];
556
-            }
557
-        }
558
-
559
-        $this->line_items_with_children = $line_items;
560
-        $this->tax_line_items           = $line_item_total->tax_descendants();
561
-
562
-        // add proper total to transaction object.
563
-        $grand_total                 = $line_item_total->recalculate_total_including_taxes();
564
-        $this->grand_total_line_item = $line_item_total;
565
-        $this->txn->set_total($grand_total);
566
-
567
-
568
-        // add additional details for each registration
569
-        foreach ($this->reg_objs as $reg) {
570
-            if (! $reg instanceof EE_Registration) {
571
-                continue;
572
-            }
573
-            $this->_registrations[ $reg->ID() ]['tkt_obj']  = $this->tickets[ $reg->get('TKT_ID') ]['ticket'];
574
-            $this->_registrations[ $reg->ID() ]['evt_obj']  = $this->_events[ $reg->get('EVT_ID') ]['event'];
575
-            $this->_registrations[ $reg->ID() ]['reg_obj']  = $reg;
576
-            $this->_registrations[ $reg->ID() ]['ans_objs'] = $this->_attendees[ $reg->get('ATT_ID') ]['ans_objs'];
577
-            $this->_registrations[ $reg->ID() ]['att_obj']  = $this->_attendees[ $reg->get('ATT_ID') ]['att_obj'];
578
-            $this->_registrations[ $reg->ID() ]['dtt_objs'] = $this->tickets[ $reg->get('TKT_ID') ]['dtt_objs'];
579
-        }
580
-
581
-
582
-        // events and attendees
583
-        $this->events        = $this->_events;
584
-        $this->attendees     = $this->_attendees;
585
-        $this->registrations = $this->_registrations;
586
-
587
-        $attendees_to_shift = $this->_attendees;
588
-
589
-        // setup primary attendee property
590
-        $this->primary_attendee_data = [
591
-            'fname' => $this->_attendees[999999991]['att_obj'] instanceof EE_Attendee
592
-                ? $this->_attendees[999999991]['att_obj']->fname()
593
-                : '',
594
-
595
-            'lname' => $this->_attendees[999999991]['att_obj'] instanceof EE_Attendee
596
-                ? $this->_attendees[999999991]['att_obj']->lname()
597
-                : '',
598
-
599
-            'email' => $this->_attendees[999999991]['att_obj'] instanceof EE_Attendee
600
-                ? $this->_attendees[999999991]['att_obj']->email()
601
-                : '',
602
-
603
-            'att_obj' => $this->_attendees[999999991]['att_obj'],
604
-
605
-            'reg_obj' => array_shift($attendees_to_shift[999999991]['reg_objs']),
606
-        ];
607
-
608
-        // reg_info property
609
-        // note this isn't referenced by any shortcode parsers so we'll ignore for now.
610
-        $this->reg_info = [];
611
-
612
-        // let's set a reg_obj for messengers expecting one.
613
-        $this->reg_obj = array_shift($this->_attendees[999999991]['reg_objs']);
614
-
615
-        // the below are just dummy items.
616
-        $this->user_id     = 1;
617
-        $this->ip_address  = '192.0.2.1';
618
-        $this->user_agent  = '';
619
-        $this->init_access = time();
620
-        $this->last_access = time();
621
-    }
23
+	// some specific properties we need for this class
24
+	private $_events        = [];
25
+
26
+	private $_attendees     = [];
27
+
28
+	private $_registrations = [];
29
+
30
+
31
+	/**
32
+	 * For the constructor of this special preview class.  We're either looking for an event id or empty data.  If we
33
+	 * have an event id (or ids) then we'll use that as the source for the "dummy" data.  If the data is empty then
34
+	 * we'll get the first three published events from the users database and use that as a source.
35
+	 *
36
+	 * @param array $data
37
+	 * @throws EE_Error
38
+	 * @throws EE_Error
39
+	 * @throws ReflectionException
40
+	 */
41
+	public function __construct($data = [])
42
+	{
43
+		$this->_data = isset($data['event_ids']) ? $data['event_ids'] : [];
44
+		$this->_setup_attendees_events();
45
+		parent::__construct($data);
46
+	}
47
+
48
+
49
+	/**
50
+	 * Returns database safe representation of the data later used to when instantiating this object.
51
+	 *
52
+	 * @param array $data The incoming data to be prepped.
53
+	 *
54
+	 * @return array   The prepped data for db
55
+	 */
56
+	public static function convert_data_for_persistent_storage($data)
57
+	{
58
+		return $data;
59
+	}
60
+
61
+
62
+	/**
63
+	 * Data that has been stored in persistent storage that was prepped by _convert_data_for_persistent_storage
64
+	 * can be sent into this method and converted back into the format used for instantiating with this data handler.
65
+	 *
66
+	 * @param array $data
67
+	 *
68
+	 * @return array
69
+	 */
70
+	public static function convert_data_from_persistent_storage($data)
71
+	{
72
+		return $data;
73
+	}
74
+
75
+
76
+	/**
77
+	 * This will just setup the _events property in the expected format.
78
+	 *
79
+	 * @throws EE_Error
80
+	 * @throws ReflectionException
81
+	 */
82
+	private function _setup_attendees_events()
83
+	{
84
+
85
+		// setup some attendee objects
86
+		$attendees = $this->_get_some_attendees();
87
+
88
+		// if empty $data we'll do a query to get some events from the server.
89
+		// otherwise we'll retrieve the event data for the given ids.
90
+		$events = $this->_get_some_events($this->_data);
91
+
92
+		$answers_n_questions = $this->_get_some_q_and_as();
93
+
94
+		if (count($events) < 1) {
95
+			throw new EE_Error(
96
+				esc_html__(
97
+					'We can\'t generate a preview for you because there are no active events in your database',
98
+					'event_espresso'
99
+				)
100
+			);
101
+		}
102
+
103
+
104
+		// now let's loop and set up the _events property.  At the same time we'll set up attendee properties.
105
+		// we'll actually use the generated line_item identifiers for our loop
106
+		$dtts = $tkts = [];
107
+		foreach ($events as $id => $event) {
108
+			if (! $event instanceof EE_Event) {
109
+				continue;
110
+			}
111
+			$this->_events[ $id ]['ID']       = $id;
112
+			$this->_events[ $id ]['name']     = $event->get('EVT_name');
113
+			$datetime                         = $event->get_first_related('Datetime');
114
+			$tickets                          = $datetime instanceof EE_Datetime ? $datetime->get_many_related(
115
+				'Ticket',
116
+				['default_where_conditions' => 'none']
117
+			) : [];
118
+			$this->_events[ $id ]['event']    = $event;
119
+			$this->_events[ $id ]['reg_objs'] = [];
120
+			$this->_events[ $id ]['tkt_objs'] = $tickets;
121
+			$this->_events[ $id ]['dtt_objs'] = [];
122
+
123
+			$tkts     = [];
124
+			foreach ($tickets as $ticket) {
125
+				if (! $ticket instanceof EE_Ticket) {
126
+					continue;
127
+				}
128
+				$reldatetime                       = $ticket->datetimes();
129
+				$tkts[ $ticket->ID() ]             = [];
130
+				$tkts[ $ticket->ID() ]['ticket']   = $ticket;
131
+				$tkts[ $ticket->ID() ]['dtt_objs'] = $reldatetime;
132
+				$tkts[ $ticket->ID() ]['att_objs'] = $attendees;
133
+				$tkts[ $ticket->ID() ]['count']    = count($attendees);
134
+				$tkts[ $ticket->ID() ]['EE_Event'] = $event;
135
+				foreach ($reldatetime as $datetime) {
136
+					if ($datetime instanceof EE_Datetime && ! isset($dtts[ $datetime->ID() ])) {
137
+						$this->_events[ $id ]['dtt_objs'][ $datetime->ID() ] = $datetime;
138
+						$dtts[ $datetime->ID() ]['datetime']                 = $datetime;
139
+						$dtts[ $datetime->ID() ]['tkt_objs'][]               = $ticket;
140
+						$dtts[ $datetime->ID() ]['evt_objs'][]               = $event;
141
+					}
142
+				}
143
+			}
144
+
145
+			$this->_events[ $id ]['total_attendees'] = count($attendees);
146
+			$this->_events[ $id ]['att_objs']        = $attendees;
147
+
148
+			// let's also setup the dummy attendees property!
149
+			foreach ($attendees as $att_key => $attendee) {
150
+				if (! $attendee instanceof EE_Attendee) {
151
+					continue;
152
+				}
153
+				$this->_attendees[ $att_key ]['line_ref'][] =
154
+					$id;  // so later it can be determined what events this attendee registered for!
155
+				$this->_attendees[ $att_key ]['evt_objs'][] = $event;
156
+				$this->_attendees[ $att_key ]['att_obj']    = $attendee;
157
+				// $this->_attendees[$att_key]['registration_id'] = 0;
158
+				$this->_attendees[ $att_key ]['attendee_email'] = $attendee->email();
159
+				$this->_attendees[ $att_key ]['tkt_objs']       = $tickets;
160
+				if ($att_key == 999999991) {
161
+					$this->_attendees[ $att_key ]['ans_objs'][999]  = $answers_n_questions['answers'][999];
162
+					$this->_attendees[ $att_key ]['ans_objs'][1002] = $answers_n_questions['answers'][1002];
163
+					$this->_attendees[ $att_key ]['ans_objs'][1005] = $answers_n_questions['answers'][1005];
164
+				} elseif ($att_key == 999999992) {
165
+					$this->_attendees[ $att_key ]['ans_objs'][1000] = $answers_n_questions['answers'][1000];
166
+					$this->_attendees[ $att_key ]['ans_objs'][1003] = $answers_n_questions['answers'][1003];
167
+					$this->_attendees[ $att_key ]['ans_objs'][1006] = $answers_n_questions['answers'][1006];
168
+				} elseif ($att_key == 999999993) {
169
+					$this->_attendees[ $att_key ]['ans_objs'][1001] = $answers_n_questions['answers'][1001];
170
+					$this->_attendees[ $att_key ]['ans_objs'][1004] = $answers_n_questions['answers'][1004];
171
+					$this->_attendees[ $att_key ]['ans_objs'][1007] = $answers_n_questions['answers'][1007];
172
+				}
173
+			}
174
+		}
175
+
176
+		$this->tickets            = $tkts;
177
+		$this->datetimes          = $dtts;
178
+		$this->answers            = $answers_n_questions['answers'];
179
+		$this->questions          = $answers_n_questions['questions'];
180
+		$this->total_ticket_count = count($tkts) * count($this->_attendees);
181
+	}
182
+
183
+
184
+	/**
185
+	 * This just returns an array of dummy attendee objects that we'll use to attach to events for our preview data
186
+	 *
187
+	 * @access private
188
+	 * @return array an array of attendee objects
189
+	 * @throws EE_Error
190
+	 * @throws EE_Error
191
+	 */
192
+	private function _get_some_attendees()
193
+	{
194
+		// let's just setup a dummy array of various attendee details
195
+		$dummy_attendees = [
196
+			0 => [
197
+				'Luke',
198
+				'Skywalker',
199
+				'[email protected]',
200
+				'804 Bantha Dr.',
201
+				'Complex 8',
202
+				'Mos Eisley',
203
+				32,
204
+				'US',
205
+				'f0r3e',
206
+				'222-333-4763',
207
+				false,
208
+				'999999991',
209
+			],
210
+			1 => [
211
+				'Princess',
212
+				'Leia',
213
+				'[email protected]',
214
+				'1456 Valley Way Boulevard',
215
+				'Suite 9',
216
+				'Alderaan',
217
+				15,
218
+				'US',
219
+				'c1h2c',
220
+				'78-123-111-1111',
221
+				false,
222
+				'999999992',
223
+			],
224
+			2 => [
225
+				'Yoda',
226
+				'I Am',
227
+				'[email protected]',
228
+				'4th Tree',
229
+				'5th Knot',
230
+				'Marsh',
231
+				22,
232
+				'US',
233
+				'l18n',
234
+				'999-999-9999',
235
+				false,
236
+				'999999993',
237
+			],
238
+		];
239
+
240
+		// let's generate the attendee objects
241
+		$attendees = [];
242
+		$var_array = [
243
+			'fname',
244
+			'lname',
245
+			'email',
246
+			'address',
247
+			'address2',
248
+			'city',
249
+			'staid',
250
+			'cntry',
251
+			'zip',
252
+			'phone',
253
+			'deleted',
254
+			'attid',
255
+		];
256
+
257
+		// EE_Registry::instance()->load_class( 'Attendee', array(), FALSE, false, TRUE );
258
+		foreach ($dummy_attendees as $dummy) {
259
+			$att = array_combine($var_array, $dummy);
260
+			extract($att);
261
+			/** @var $fname string */
262
+			/** @var $lname string */
263
+			/** @var $address string */
264
+			/** @var $address2 string */
265
+			/** @var $city string */
266
+			/** @var $staid string */
267
+			/** @var $cntry string */
268
+			/** @var $zip string */
269
+			/** @var $email string */
270
+			/** @var $phone string */
271
+			/** @var $attid string */
272
+			$attendees[ $attid ] = EE_Attendee::new_instance(
273
+				[
274
+					'ATT_fname'    => $fname,
275
+					'ATT_lname'    => $lname,
276
+					'ATT_address'  => $address,
277
+					'ATT_address2' => $address2,
278
+					'ATT_city'     => $city,
279
+					'STA_ID'       => $staid,
280
+					'CNT_ISO'      => $cntry,
281
+					'ATT_zip'      => $zip,
282
+					'ATT_email'    => $email,
283
+					'ATT_phone'    => $phone,
284
+					'ATT_ID'       => $attid,
285
+				]
286
+			);
287
+		}
288
+
289
+		return $attendees;
290
+	}
291
+
292
+
293
+	/**
294
+	 * Return an array of dummy question objects indexed by answer id and dummy answer objects indexed by answer id.
295
+	 * This will be used in our dummy data setup
296
+	 *
297
+	 * @return array
298
+	 * @throws EE_Error
299
+	 * @throws ReflectionException
300
+	 */
301
+	private function _get_some_q_and_as()
302
+	{
303
+		$quests_array = [
304
+			0 => [
305
+				555,
306
+				esc_html__('What is your favorite planet?', 'event_espresso'),
307
+				0,
308
+			],
309
+			1 => [
310
+				556,
311
+				esc_html__('What is your favorite food?', 'event_espresso'),
312
+				0,
313
+			],
314
+			2 => [
315
+				557,
316
+				esc_html__('How many lightyears have you travelled', 'event_espresso'),
317
+				0,
318
+			],
319
+		];
320
+
321
+		$ans_array = [
322
+			0 => [
323
+				999,
324
+				555,
325
+				'Tattoine',
326
+			],
327
+			1 => [
328
+				1000,
329
+				555,
330
+				'Alderaan',
331
+			],
332
+			2 => [
333
+				1001,
334
+				555,
335
+				'Dantooine',
336
+			],
337
+			3 => [
338
+				1002,
339
+				556,
340
+				'Fish Fingers',
341
+			],
342
+			4 => [
343
+				1003,
344
+				556,
345
+				'Sushi',
346
+			],
347
+			5 => [
348
+				1004,
349
+				556,
350
+				'Water',
351
+			],
352
+			6 => [
353
+				1005,
354
+				557,
355
+				'A lot',
356
+			],
357
+			7 => [
358
+				1006,
359
+				557,
360
+				"That's none of your business.",
361
+			],
362
+			8 => [
363
+				1007,
364
+				557,
365
+				"People less travel me then.",
366
+			],
367
+		];
368
+
369
+		$qst_columns = ['QST_ID', 'QST_display_text', 'QST_system'];
370
+		$ans_columns = ['ANS_ID', 'QST_ID', 'ANS_value'];
371
+
372
+		// EE_Registry::instance()->load_class( 'Question', array(), FALSE, TRUE, TRUE );
373
+		// EE_Registry::instance()->load_class( 'Answer', array(), FALSE, TRUE, TRUE );
374
+
375
+		$qsts = [];
376
+		// first the questions
377
+		foreach ($quests_array as $qst) {
378
+			$qstobj                    = array_combine($qst_columns, $qst);
379
+			$qsts[ $qstobj['QST_ID'] ] = EE_Question::new_instance($qstobj);
380
+		}
381
+
382
+		// now the answers (and we'll setup our arrays)
383
+		$q_n_as = [];
384
+		foreach ($ans_array as $ans) {
385
+			$ansobj                               = array_combine($ans_columns, $ans);
386
+			$ansobj                               = EE_Answer::new_instance($ansobj);
387
+			$q_n_as['answers'][ $ansobj->ID() ]   = $ansobj;
388
+			$q_n_as['questions'][ $ansobj->ID() ] = $qsts[ $ansobj->get('QST_ID') ];
389
+		}
390
+
391
+		return $q_n_as;
392
+	}
393
+
394
+
395
+	/**
396
+	 * Return an array of event objects from the database
397
+	 *
398
+	 * If event ids are not included then we'll just retrieve the first published event from the database.
399
+	 *
400
+	 * @param array $event_ids if set, this will be an array of event ids to obtain events for.
401
+	 *
402
+	 * @return array    An array of event objects from the db.
403
+	 * @throws EE_Error
404
+	 */
405
+	private function _get_some_events(array $event_ids = [])
406
+	{
407
+		/** @var RequestInterface $request */
408
+		$request = LoaderFactory::getLoader()->getShared(RequestInterface::class);
409
+		// if we have an evt_id then we want to make sure we use that for the preview
410
+		// (because a specific event template is being viewed);
411
+		$event_ids = $request->getRequestParam('evt_id', $event_ids, 'int', true);
412
+		// clear out any invalid IDs, like 0
413
+		$event_ids = array_filter($event_ids);
414
+		$limit     = ! empty($event_ids)
415
+			? null
416
+			: apply_filters('FHEE__EE_Messages_Preview_incoming_data___get_some_events__limit', '0,1');
417
+
418
+		$where = ! empty($event_ids)
419
+			? [
420
+				'EVT_ID'                 => ['IN', $event_ids],
421
+				'Datetime.Ticket.TKT_ID' => ['>', 1],
422
+			]
423
+			: ['Datetime.Ticket.TKT_ID' => ['>', 1]];
424
+
425
+		return EEM_Event::instance()->get_all([$where, 'limit' => $limit]);
426
+	}
427
+
428
+
429
+	/**
430
+	 * @throws EE_Error
431
+	 * @throws ReflectionException
432
+	 */
433
+	protected function _setup_data()
434
+	{
435
+		// need to figure out the running total for test purposes so... we're going to create a temp cart and add the tickets to it!
436
+		if (EE_Registry::instance()->SSN instanceof EE_Session) {
437
+			EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
438
+			$session = EE_Registry::instance()->SSN;
439
+		} else {
440
+			$session = EE_Registry::instance()->load_core('Session');
441
+		}
442
+		$cart = EE_Cart::instance(null, $session);
443
+
444
+		// add tickets to cart
445
+		foreach ($this->tickets as $ticket) {
446
+			$cart->add_ticket_to_cart($ticket['ticket']);
447
+		}
448
+
449
+		// setup txn property
450
+		$this->txn = EE_Transaction::new_instance(
451
+			[
452
+				'TXN_timestamp'    => time(), // unix timestamp
453
+				'TXN_total'        => 0, // txn_total
454
+				'TXN_paid'         => 0, // txn_paid
455
+				'STS_ID'           => EEM_Transaction::incomplete_status_code, // sts_id
456
+				'TXN_session_data' => null, // dump of txn session object (we're just going to leave blank here)
457
+				'TXN_hash_salt'    => null, // hash salt blank as well
458
+				'TXN_ID'           => 999999,
459
+			]
460
+		);
461
+
462
+
463
+		// setup reg_objects
464
+		// note we're setting up a reg object for each attendee in each event but ALSO adding to the reg_object array.
465
+		$this->reg_objs = [];
466
+		$regid          = 9999990;
467
+		foreach ($this->_attendees as $key => $attendee) {
468
+			// note we need to setup reg_objects for each event this attendee belongs to
469
+			$regatt = $attendee['att_obj'] instanceof EE_Attendee ? $attendee['att_obj']->ID() : null;
470
+			$regtxn = $this->txn->ID();
471
+			$regcnt = 1;
472
+			foreach ($attendee['line_ref'] as $evtid) {
473
+				foreach ($this->_events[ $evtid ]['tkt_objs'] as $ticket) {
474
+					if (! $ticket instanceof EE_Ticket) {
475
+						continue;
476
+					}
477
+					$reg_array                                            = [
478
+						'EVT_ID'           => $evtid,
479
+						'ATT_ID'           => $regatt,
480
+						'TXN_ID'           => $regtxn,
481
+						'TKT_ID'           => $ticket->ID(),
482
+						'STS_ID'           => EEM_Registration::status_id_pending_payment,
483
+						'REG_date'         => time(),
484
+						'REG_final_price'  => $ticket->get('TKT_price'),
485
+						'REG_session'      => 'dummy_session_id',
486
+						'REG_code'         => $regid . '-dummy-generated-code',
487
+						'REG_url_link'     => $regcnt . '-daafpapasdlfakasdfpqasdfasdf',
488
+						'REG_count'        => $regcnt,
489
+						'REG_group_size'   => $this->_events[ $evtid ]['total_attendees'],
490
+						'REG_att_is_going' => true,
491
+						'REG_ID'           => $regid,
492
+					];
493
+					$REG_OBJ                                              = EE_Registration::new_instance($reg_array);
494
+					$this->_attendees[ $key ]['reg_objs'][ $regid ]       = $REG_OBJ;
495
+					$this->_events[ $evtid ]['reg_objs'][]                = $REG_OBJ;
496
+					$this->reg_objs[]                                     = $REG_OBJ;
497
+					$this->tickets[ $ticket->ID() ]['reg_objs'][ $regid ] = $REG_OBJ;
498
+
499
+					$regcnt++;
500
+					$regid++;
501
+				}
502
+			}
503
+		}
504
+
505
+
506
+		// setup line items!
507
+		$line_item_total = EEH_Line_Item::create_total_line_item($this->txn);
508
+
509
+		// add tickets
510
+		foreach ($this->tickets as $item) {
511
+			$qty    = $item['count'];
512
+			$ticket = $item['ticket'];
513
+			EEH_Line_Item::add_ticket_purchase($line_item_total, $ticket, $qty);
514
+		}
515
+
516
+		$shipping_line_item = EE_Line_Item::new_instance(
517
+			[
518
+				'LIN_name'       => esc_html__(
519
+					'Shipping Surcharge',
520
+					'event_espresso'
521
+				),
522
+				'LIN_desc'       => esc_html__(
523
+					'Sent via Millenium Falcon',
524
+					'event_espresso'
525
+				),
526
+				'LIN_unit_price' => 20,
527
+				'LIN_quantity'   => 1,
528
+				'LIN_is_taxable' => true,
529
+				'LIN_total'      => 20,
530
+				'LIN_type'       => EEM_Line_Item::type_line_item,
531
+			]
532
+		);
533
+		EEH_Line_Item::add_item($line_item_total, $shipping_line_item);
534
+		$this->additional_line_items = [$shipping_line_item];
535
+
536
+		// now let's add taxes
537
+		EEH_Line_Item::apply_taxes($line_item_total);
538
+
539
+		// now we should be able to get the items we need from this object
540
+		$event_line_items = EEH_Line_Item::get_pre_tax_subtotal($line_item_total)->children();
541
+		$line_items       = [];
542
+		foreach ($event_line_items as $line_item) {
543
+			if (! $line_item instanceof EE_Line_Item || $line_item->OBJ_type() !== 'Event') {
544
+				continue;
545
+			}
546
+			$ticket_line_items = EEH_Line_Item::get_ticket_line_items($line_item);
547
+			foreach ($ticket_line_items as $ticket_line_item) {
548
+				if (! $ticket_line_item instanceof EE_Line_Item) {
549
+					continue;
550
+				}
551
+				$this->tickets[ $ticket_line_item->OBJ_ID() ]['line_item']      = $ticket_line_item;
552
+				$this->tickets[ $ticket_line_item->OBJ_ID() ]['sub_line_items'] = $ticket_line_item->children();
553
+				$line_items[ $ticket_line_item->ID() ]['children']              = $ticket_line_item->children();
554
+				$line_items[ $ticket_line_item->ID() ]['EE_Ticket']             =
555
+					$this->tickets[ $ticket_line_item->OBJ_ID() ]['ticket'];
556
+			}
557
+		}
558
+
559
+		$this->line_items_with_children = $line_items;
560
+		$this->tax_line_items           = $line_item_total->tax_descendants();
561
+
562
+		// add proper total to transaction object.
563
+		$grand_total                 = $line_item_total->recalculate_total_including_taxes();
564
+		$this->grand_total_line_item = $line_item_total;
565
+		$this->txn->set_total($grand_total);
566
+
567
+
568
+		// add additional details for each registration
569
+		foreach ($this->reg_objs as $reg) {
570
+			if (! $reg instanceof EE_Registration) {
571
+				continue;
572
+			}
573
+			$this->_registrations[ $reg->ID() ]['tkt_obj']  = $this->tickets[ $reg->get('TKT_ID') ]['ticket'];
574
+			$this->_registrations[ $reg->ID() ]['evt_obj']  = $this->_events[ $reg->get('EVT_ID') ]['event'];
575
+			$this->_registrations[ $reg->ID() ]['reg_obj']  = $reg;
576
+			$this->_registrations[ $reg->ID() ]['ans_objs'] = $this->_attendees[ $reg->get('ATT_ID') ]['ans_objs'];
577
+			$this->_registrations[ $reg->ID() ]['att_obj']  = $this->_attendees[ $reg->get('ATT_ID') ]['att_obj'];
578
+			$this->_registrations[ $reg->ID() ]['dtt_objs'] = $this->tickets[ $reg->get('TKT_ID') ]['dtt_objs'];
579
+		}
580
+
581
+
582
+		// events and attendees
583
+		$this->events        = $this->_events;
584
+		$this->attendees     = $this->_attendees;
585
+		$this->registrations = $this->_registrations;
586
+
587
+		$attendees_to_shift = $this->_attendees;
588
+
589
+		// setup primary attendee property
590
+		$this->primary_attendee_data = [
591
+			'fname' => $this->_attendees[999999991]['att_obj'] instanceof EE_Attendee
592
+				? $this->_attendees[999999991]['att_obj']->fname()
593
+				: '',
594
+
595
+			'lname' => $this->_attendees[999999991]['att_obj'] instanceof EE_Attendee
596
+				? $this->_attendees[999999991]['att_obj']->lname()
597
+				: '',
598
+
599
+			'email' => $this->_attendees[999999991]['att_obj'] instanceof EE_Attendee
600
+				? $this->_attendees[999999991]['att_obj']->email()
601
+				: '',
602
+
603
+			'att_obj' => $this->_attendees[999999991]['att_obj'],
604
+
605
+			'reg_obj' => array_shift($attendees_to_shift[999999991]['reg_objs']),
606
+		];
607
+
608
+		// reg_info property
609
+		// note this isn't referenced by any shortcode parsers so we'll ignore for now.
610
+		$this->reg_info = [];
611
+
612
+		// let's set a reg_obj for messengers expecting one.
613
+		$this->reg_obj = array_shift($this->_attendees[999999991]['reg_objs']);
614
+
615
+		// the below are just dummy items.
616
+		$this->user_id     = 1;
617
+		$this->ip_address  = '192.0.2.1';
618
+		$this->user_agent  = '';
619
+		$this->init_access = time();
620
+		$this->last_access = time();
621
+	}
622 622
 }
Please login to merge, or discard this patch.
core/libraries/messages/EE_Messages_Queue.lib.php 2 patches
Indentation   +705 added lines, -705 removed lines patch added patch discarded remove patch
@@ -13,709 +13,709 @@
 block discarded – undo
13 13
  */
14 14
 class EE_Messages_Queue
15 15
 {
16
-    /**
17
-     * @type    string  reference for sending action
18
-     */
19
-    const action_sending = 'sending';
20
-
21
-    /**
22
-     * @type    string  reference for generation action
23
-     */
24
-    const action_generating = 'generation';
25
-
26
-
27
-    /**
28
-     * @type EE_Message_Repository $_message_repository
29
-     */
30
-    protected $_message_repository;
31
-
32
-    /**
33
-     * Sets the limit of how many messages are generated per process.
34
-     *
35
-     * @type int
36
-     */
37
-    protected $_batch_count;
38
-
39
-
40
-    /**
41
-     * This is an array of cached queue items being stored in this object.
42
-     * The array keys will be the ID of the EE_Message in the db if saved.  If the EE_Message
43
-     * is not saved to the db then its key will be an increment of "UNS" (i.e. UNS1, UNS2 etc.)
44
-     *
45
-     * @type EE_Message[]
46
-     */
47
-    protected $_cached_queue_items;
48
-
49
-    /**
50
-     * Tracks the number of unsaved queue items.
51
-     *
52
-     * @type int
53
-     */
54
-    protected $_unsaved_count = 0;
55
-
56
-    /**
57
-     * used to record if a do_messenger_hooks has already been called for a message type.  This prevents multiple
58
-     * hooks getting fired if users have setup their action/filter hooks to prevent duplicate calls.
59
-     *
60
-     * @type array
61
-     */
62
-    protected $_did_hook = [];
63
-
64
-
65
-    /**
66
-     * Constructor.
67
-     * Setup all the initial properties and load a EE_Message_Repository.
68
-     *
69
-     * @param EE_Message_Repository $message_repository
70
-     */
71
-    public function __construct(EE_Message_Repository $message_repository)
72
-    {
73
-        $this->_batch_count        = apply_filters('FHEE__EE_Messages_Queue___batch_count', 50);
74
-        $this->_message_repository = $message_repository;
75
-    }
76
-
77
-
78
-    /**
79
-     * Add a EE_Message object to the queue
80
-     *
81
-     * @param EE_Message $message
82
-     * @param array      $data         This will be an array of data to attach to the object in the repository.  If the
83
-     *                                 object is persisted, this data will be saved on an extra_meta object related to
84
-     *                                 EE_Message.
85
-     * @param bool       $preview      Whether this EE_Message represents a preview or not.
86
-     * @param bool       $test_send    This indicates whether to do a test send instead of actual send. A test send will
87
-     *                                 use the messenger send method but typically is based on preview data.
88
-     * @return bool          Whether the message was successfully added to the repository or not.
89
-     */
90
-    public function add(EE_Message $message, $data = [], $preview = false, $test_send = false)
91
-    {
92
-        $data['preview']   = $preview;
93
-        $data['test_send'] = $test_send;
94
-        return $this->_message_repository->add($message, $data);
95
-    }
96
-
97
-
98
-    /**
99
-     * Removes EE_Message from _queue that matches the given EE_Message if the pointer is on a matching EE_Message
100
-     *
101
-     * @param EE_Message $message The message to detach from the queue
102
-     * @param bool       $persist This flag indicates whether to attempt to delete the object from the db as well.
103
-     * @return bool
104
-     */
105
-    public function remove(EE_Message $message, $persist = false)
106
-    {
107
-        if ($persist && $this->_message_repository->current() !== $message) {
108
-            // get pointer on right message
109
-            if ($this->_message_repository->has($message)) {
110
-                $this->_message_repository->rewind();
111
-                while ($this->_message_repository->valid()) {
112
-                    if ($this->_message_repository->current() === $message) {
113
-                        break;
114
-                    }
115
-                    $this->_message_repository->next();
116
-                }
117
-            } else {
118
-                return false;
119
-            }
120
-        }
121
-        return $persist ? $this->_message_repository->delete() : $this->_message_repository->remove($message);
122
-    }
123
-
124
-
125
-    /**
126
-     * Persists all queued EE_Message objects to the db.
127
-     *
128
-     * @param bool $do_hooks_only @see EE_Message_Repository::saveAll
129
-     * @return array @see EE_Messages_Repository::saveAll() for return values.
130
-     */
131
-    public function save($do_hooks_only = false)
132
-    {
133
-        return $this->_message_repository->saveAll($do_hooks_only);
134
-    }
135
-
136
-
137
-    /**
138
-     * @return EE_Message_Repository
139
-     */
140
-    public function get_message_repository()
141
-    {
142
-        return $this->_message_repository;
143
-    }
144
-
145
-
146
-    /**
147
-     * This does the following things:
148
-     * 1. Checks if there is a lock on generation (prevents race conditions).  If there is a lock then exits (return
149
-     * false).
150
-     * 2. If no lock, sets lock, then retrieves a batch of non-generated EE_Message objects and adds to queue
151
-     * 3. Returns bool.  True = batch ready.  False = no batch ready (or nothing available for generation).
152
-     * Note: Callers should make sure they release the lock otherwise batch generation will be prevented from
153
-     * continuing. The lock is on a transient that is set to expire after one hour as a fallback in case locks are not
154
-     * removed.
155
-     *
156
-     * @return bool  true if successfully retrieved batch, false no batch ready.
157
-     * @throws EE_Error
158
-     * @throws ReflectionException
159
-     */
160
-    public function get_batch_to_generate()
161
-    {
162
-        if ($this->is_locked()) {
163
-            return false;
164
-        }
165
-
166
-        // lock batch generation to prevent race conditions.
167
-        $this->lock_queue();
168
-
169
-        $query_args = [
170
-            // key 0 = where conditions
171
-            0          => ['STS_ID' => EEM_Message::status_incomplete],
172
-            'order_by' => $this->_get_priority_orderby(),
173
-            'limit'    => $this->_batch_count,
174
-        ];
175
-        $messages   = EEM_Message::instance()->get_all($query_args);
176
-
177
-        if (! $messages) {
178
-            return false; // nothing to generate
179
-        }
180
-
181
-        foreach ($messages as $message) {
182
-            if ($message instanceof EE_Message) {
183
-                $data = $message->all_extra_meta_array();
184
-                $this->add($message, $data);
185
-            }
186
-        }
187
-        return true;
188
-    }
189
-
190
-
191
-    /**
192
-     * This does the following things:
193
-     * 1. Checks if there is a lock on sending (prevents race conditions).  If there is a lock then exits (return
194
-     * false).
195
-     * 2. Grabs the allowed number of messages to send for the rate_limit.  If cannot send any more messages, then
196
-     * return false.
197
-     * 2. If no lock, sets lock, then retrieves a batch of EE_Message objects, adds to queue and triggers execution.
198
-     * 3. On success or unsuccessful send, sets status appropriately.
199
-     * 4. Saves messages via the queue
200
-     * 5. Releases lock.
201
-     *
202
-     * @return bool  true on success, false if something preventing sending (i.e. lock set).  Note: true does not
203
-     *               necessarily mean that all messages were successfully sent.  It just means that this method
204
-     *               successfully completed. On true, client may want to call $this->count_STS_in_queue(
205
-     *               EEM_Message::status_failed ) to see if any failed EE_Message objects.  Each failed message object
206
-     *               will also have a saved error message on it to assist with notifying user.
207
-     * @throws EE_Error
208
-     * @throws ReflectionException
209
-     */
210
-    public function get_to_send_batch_and_send()
211
-    {
212
-        $rate_limit = $this->get_rate_limit();
213
-        if (
214
-            $rate_limit < 1
215
-            || $this->is_locked(EE_Messages_Queue::action_sending)
216
-        ) {
217
-            return false;
218
-        }
219
-
220
-        $this->lock_queue(EE_Messages_Queue::action_sending);
221
-
222
-        $batch = $this->_batch_count < $rate_limit ? $this->_batch_count : $rate_limit;
223
-
224
-        $query_args = [
225
-            // key 0 = where conditions
226
-            0          => ['STS_ID' => ['IN', EEM_Message::instance()->stati_indicating_to_send()]],
227
-            'order_by' => $this->_get_priority_orderby(),
228
-            'limit'    => $batch,
229
-        ];
230
-
231
-        $messages_to_send = EEM_Message::instance()->get_all($query_args);
232
-
233
-
234
-        // any to send?
235
-        if (! $messages_to_send) {
236
-            $this->unlock_queue(EE_Messages_Queue::action_sending);
237
-            return false;
238
-        }
239
-
240
-        $queue_count = 0;
241
-
242
-        // add to queue.
243
-        foreach ($messages_to_send as $message) {
244
-            if ($message instanceof EE_Message) {
245
-                $queue_count++;
246
-                $this->add($message);
247
-            }
248
-        }
249
-
250
-        // send messages  (this also updates the rate limit)
251
-        $this->execute();
252
-
253
-        // release lock
254
-        $this->unlock_queue(EE_Messages_Queue::action_sending);
255
-        // update rate limit
256
-        $this->set_rate_limit($queue_count);
257
-        return true;
258
-    }
259
-
260
-
261
-    /**
262
-     * Locks the queue so that no other queues can call the "batch" methods.
263
-     *
264
-     * @param string $type The type of queue being locked.
265
-     */
266
-    public function lock_queue($type = EE_Messages_Queue::action_generating)
267
-    {
268
-        update_option($this->_get_lock_key($type), $this->_get_lock_expiry($type));
269
-    }
270
-
271
-
272
-    /**
273
-     * Unlocks the queue so that batch methods can be used.
274
-     *
275
-     * @param string $type The type of queue being unlocked.
276
-     */
277
-    public function unlock_queue($type = EE_Messages_Queue::action_generating)
278
-    {
279
-        delete_option($this->_get_lock_key($type));
280
-    }
281
-
282
-
283
-    /**
284
-     * Retrieve the key used for the lock transient.
285
-     *
286
-     * @param string $type The type of lock.
287
-     * @return string
288
-     */
289
-    protected function _get_lock_key($type = EE_Messages_Queue::action_generating)
290
-    {
291
-        return '_ee_lock_' . $type;
292
-    }
293
-
294
-
295
-    /**
296
-     * Retrieve the expiry time for the lock transient.
297
-     *
298
-     * @param string $type The type of lock
299
-     * @return int   time to expiry in seconds.
300
-     */
301
-    protected function _get_lock_expiry($type = EE_Messages_Queue::action_generating)
302
-    {
303
-        return time() + (int) apply_filters('FHEE__EE_Messages_Queue__lock_expiry', HOUR_IN_SECONDS, $type);
304
-    }
305
-
306
-
307
-    /**
308
-     * Returns the key used for rate limit transient.
309
-     *
310
-     * @return string
311
-     */
312
-    protected function _get_rate_limit_key()
313
-    {
314
-        return '_ee_rate_limit';
315
-    }
316
-
317
-
318
-    /**
319
-     * Returns the rate limit expiry time.
320
-     *
321
-     * @return int
322
-     */
323
-    protected function _get_rate_limit_expiry()
324
-    {
325
-        return time() + (int) apply_filters('FHEE__EE_Messages_Queue__rate_limit_expiry', HOUR_IN_SECONDS);
326
-    }
327
-
328
-
329
-    /**
330
-     * Returns the default rate limit for sending messages.
331
-     *
332
-     * @return int
333
-     */
334
-    protected function _default_rate_limit()
335
-    {
336
-        return (int) apply_filters('FHEE__EE_Messages_Queue___rate_limit', 200);
337
-    }
338
-
339
-
340
-    /**
341
-     * Return the orderby array for priority.
342
-     *
343
-     * @return array
344
-     */
345
-    protected function _get_priority_orderby()
346
-    {
347
-        return [
348
-            'MSG_priority' => 'ASC',
349
-            'MSG_modified' => 'DESC',
350
-        ];
351
-    }
352
-
353
-
354
-    /**
355
-     * Returns whether batch methods are "locked" or not, and if models an currently be used to query the database.
356
-     * Return true when batch methods should not be used; returns false when they can be.
357
-     *
358
-     * @param string $type The type of lock being checked for.
359
-     * @return bool
360
-     */
361
-    public function is_locked($type = EE_Messages_Queue::action_generating)
362
-    {
363
-        if (! EE_Maintenance_Mode::instance()->models_can_query()) {
364
-            return true;
365
-        }
366
-        $lock = (int) get_option($this->_get_lock_key($type), 0);
367
-        /**
368
-         * This filters the default is_locked behaviour.
369
-         */
370
-        $is_locked = filter_var(
371
-            apply_filters(
372
-                'FHEE__EE_Messages_Queue__is_locked',
373
-                $lock > time(),
374
-                $this
375
-            ),
376
-            FILTER_VALIDATE_BOOLEAN
377
-        );
378
-
379
-        /**
380
-         * @see usage of this filter in EE_Messages_Queue::initiate_request_by_priority() method.
381
-         *            Also implemented here because messages processed on the same request should not have any locks applied.
382
-         */
383
-        if (
384
-            apply_filters('FHEE__EE_Messages_Processor__initiate_request_by_priority__do_immediate_processing', false)
385
-            || EE_Registry::instance()->NET_CFG->core->do_messages_on_same_request
386
-        ) {
387
-            $is_locked = false;
388
-        }
389
-
390
-
391
-        return $is_locked;
392
-    }
393
-
394
-
395
-    /**
396
-     * Retrieves the rate limit that may be cached as a transient.
397
-     * If the rate limit is not set, then this sets the default rate limit and expiry and returns it.
398
-     *
399
-     * @param bool $return_expiry If true then return the expiry time not the rate_limit.
400
-     * @return int
401
-     */
402
-    protected function get_rate_limit($return_expiry = false)
403
-    {
404
-        $stored_rate_info = get_option($this->_get_rate_limit_key(), []);
405
-        $rate_limit       = isset($stored_rate_info[0])
406
-            ? (int) $stored_rate_info[0]
407
-            : 0;
408
-        $expiry           = isset($stored_rate_info[1])
409
-            ? (int) $stored_rate_info[1]
410
-            : 0;
411
-        // set the default for tracking?
412
-        if (empty($stored_rate_info) || time() > $expiry) {
413
-            $expiry     = $this->_get_rate_limit_expiry();
414
-            $rate_limit = $this->_default_rate_limit();
415
-            update_option($this->_get_rate_limit_key(), [$rate_limit, $expiry]);
416
-        }
417
-        return $return_expiry ? $expiry : $rate_limit;
418
-    }
419
-
420
-
421
-    /**
422
-     * This updates existing rate limit with the new limit which is the old minus the batch.
423
-     *
424
-     * @param int $batch_completed This sets the new rate limit based on the given batch that was completed.
425
-     */
426
-    protected function set_rate_limit($batch_completed)
427
-    {
428
-        // first get the most up to date rate limit (in case its expired and reset)
429
-        $rate_limit = $this->get_rate_limit();
430
-        $expiry     = $this->get_rate_limit(true);
431
-        $new_limit  = $rate_limit - $batch_completed;
432
-        // updating the transient option directly to avoid resetting the expiry.
433
-
434
-        update_option($this->_get_rate_limit_key(), [$new_limit, $expiry]);
435
-    }
436
-
437
-
438
-    /**
439
-     * This method checks the queue for ANY EE_Message objects with a priority matching the given priority passed in.
440
-     * If that exists, then we immediately initiate a non-blocking request to do the requested action type.
441
-     * Note: Keep in mind that there is the possibility that the request will not execute if there is already another
442
-     * request running on a queue for the given task.
443
-     *
444
-     * @param string $task     This indicates what type of request is going to be initiated.
445
-     * @param int    $priority This indicates the priority that triggers initiating the request.
446
-     * @return bool|EE_Messages_Queue|void
447
-     * @throws EE_Error
448
-     * @throws ReflectionException
449
-     */
450
-    public function initiate_request_by_priority($task = 'generate', $priority = EEM_Message::priority_high)
451
-    {
452
-        // determine what status is matched with the priority as part of the trigger conditions.
453
-        $status = $task == 'generate'
454
-            ? EEM_Message::status_incomplete
455
-            : EEM_Message::instance()->stati_indicating_to_send();
456
-        // always make sure we save because either this will get executed immediately on a separate request
457
-        // or remains in the queue for the regularly scheduled queue batch.
458
-        $this->save();
459
-        /**
460
-         * This filter/option allows users to override processing of messages on separate requests and instead have everything
461
-         * happen on the same request.  If this is utilized remember:
462
-         * - message priorities don't matter
463
-         * - existing unprocessed messages in the queue will not get processed unless manually triggered.
464
-         * - things will be perceived to take longer to happen for end users (i.e. registrations) because of the additional
465
-         *   processing happening on the same request.
466
-         * - any race condition protection (locks) are removed because they don't apply when things are processed on
467
-         *   the same request.
468
-         */
469
-        if (
470
-            apply_filters('FHEE__EE_Messages_Processor__initiate_request_by_priority__do_immediate_processing', false)
471
-            || EE_Registry::instance()->NET_CFG->core->do_messages_on_same_request
472
-        ) {
473
-            $messages_processor = EE_Registry::instance()->load_lib('Messages_Processor');
474
-            if ($messages_processor instanceof EE_Messages_Processor) {
475
-                return $messages_processor->process_immediately_from_queue($this);
476
-            }
477
-            // if we get here then that means the messages processor couldn't be loaded so messages will just remain
478
-            // queued for manual triggering by end user.
479
-        }
480
-
481
-        if ($this->_message_repository->count_by_priority_and_status($priority, $status)) {
482
-            EE_Messages_Scheduler::initiate_scheduled_non_blocking_request($task);
483
-        }
484
-    }
485
-
486
-
487
-    /**
488
-     *  Loops through the EE_Message objects in the _queue and calls the messenger send methods for each message.
489
-     *
490
-     * @param bool     $save                      Used to indicate whether to save the message queue after sending
491
-     *                                            (default will save).
492
-     * @param mixed    $sending_messenger         (optional) When the sending messenger is different than
493
-     *                                            what is on the EE_Message object in the queue.
494
-     *                                            For instance, showing the browser view of an email message,
495
-     *                                            or giving a pdf generated view of an html document.
496
-     *                                            This should be an instance of EE_messenger but if you call this
497
-     *                                            method
498
-     *                                            intending it to be a sending messenger but a valid one could not be
499
-     *                                            retrieved then send in an instance of EE_Error that contains the
500
-     *                                            related error message.
501
-     * @param bool|int $by_priority               When set, this indicates that only messages
502
-     *                                            matching the given priority should be executed.
503
-     * @return int        Number of messages sent.  Note, 0 does not mean that no messages were processed.
504
-     *                                            Also, if the messenger is an request type messenger (or a preview),
505
-     *                                            its entirely possible that the messenger will exit before
506
-     * @throws EE_Error
507
-     * @throws ReflectionException
508
-     */
509
-    public function execute($save = true, $sending_messenger = null, $by_priority = false)
510
-    {
511
-        $messages_sent   = 0;
512
-        $this->_did_hook = [];
513
-        $this->_message_repository->rewind();
514
-
515
-        while ($this->_message_repository->valid()) {
516
-            $error_messages = [];
517
-            $message        = $this->_message_repository->current();
518
-
519
-            // only process things that are queued for sending
520
-            if (! in_array($message->STS_ID(), EEM_Message::instance()->stati_indicating_to_send())) {
521
-                $this->_message_repository->next();
522
-                continue;
523
-            }
524
-            // if $by_priority is set and does not match then continue;
525
-            if ($by_priority && $by_priority != $message->priority()) {
526
-                $this->_message_repository->next();
527
-                continue;
528
-            }
529
-            // error checking
530
-            if (! $message->valid_messenger()) {
531
-                $error_messages[] = sprintf(
532
-                    esc_html__('The %s messenger is not active at time of sending.', 'event_espresso'),
533
-                    $message->messenger()
534
-                );
535
-            }
536
-            if (! $message->valid_message_type()) {
537
-                $error_messages[] = sprintf(
538
-                    esc_html__('The %s message type is not active at the time of sending.', 'event_espresso'),
539
-                    $message->message_type()
540
-                );
541
-            }
542
-            // if there was supposed to be a sending messenger for this message, but it was invalid/inactive,
543
-            // then it will instead be an EE_Error object, so let's check for that
544
-            if ($sending_messenger instanceof EE_Error) {
545
-                $error_messages[] = $sending_messenger->getMessage();
546
-            }
547
-            // if there are no errors, then let's process the message
548
-            if (empty($error_messages)) {
549
-                if ($save) {
550
-                    $message->set_messenger_is_executing();
551
-                }
552
-                if ($this->_process_message($message, $sending_messenger)) {
553
-                    $messages_sent++;
554
-                }
555
-            }
556
-            $this->_set_error_message($message, $error_messages);
557
-            // add modified time
558
-            $message->set_modified(time());
559
-            // we save each message after its processed to make sure its status persists in case PHP times-out or runs
560
-            // out of memory. @see https://events.codebasehq.com/projects/event-espresso/tickets/10281
561
-            if ($save) {
562
-                $message->save();
563
-            }
564
-
565
-            $this->_message_repository->next();
566
-        }
567
-        if ($save) {
568
-            $this->save(true);
569
-        }
570
-        return $messages_sent;
571
-    }
572
-
573
-
574
-    /**
575
-     * _process_message
576
-     *
577
-     * @param EE_Message $message
578
-     * @param mixed      $sending_messenger (optional)
579
-     * @return bool
580
-     */
581
-    protected function _process_message(EE_Message $message, $sending_messenger = null)
582
-    {
583
-        // these *should* have been validated in the execute() method above
584
-        $messenger    = $message->messenger_object();
585
-        $message_type = $message->message_type_object();
586
-        // do actions for sending messenger if it differs from generating messenger and swap values.
587
-        if (
588
-            $sending_messenger instanceof EE_messenger
589
-            && $messenger instanceof EE_messenger
590
-            && $sending_messenger->name != $messenger->name
591
-        ) {
592
-            $messenger->do_secondary_messenger_hooks($sending_messenger->name);
593
-            $messenger = $sending_messenger;
594
-        }
595
-        // send using messenger, but double check objects
596
-        if ($messenger instanceof EE_messenger && $message_type instanceof EE_message_type) {
597
-            // set hook for message type (but only if not using another messenger to send).
598
-            if (! isset($this->_did_hook[ $message_type->name ])) {
599
-                $message_type->do_messenger_hooks($messenger);
600
-                $this->_did_hook[ $message_type->name ] = 1;
601
-            }
602
-            // if preview then use preview method
603
-            return $this->_message_repository->is_preview()
604
-                ? $this->_do_preview($message, $messenger, $message_type, $this->_message_repository->is_test_send())
605
-                : $this->_do_send($message, $messenger, $message_type);
606
-        }
607
-        return false;
608
-    }
609
-
610
-
611
-    /**
612
-     * The intention of this method is to count how many EE_Message objects
613
-     * are in the queue with a given status.
614
-     * Example usage:
615
-     * After a caller calls the "EE_Message_Queue::execute()" method, the caller can check if there were any failed
616
-     * sends by calling $queue->count_STS_in_queue( EEM_Message_Queue::status_failed ).
617
-     *
618
-     * @param array|string $status Stati to check for in queue
619
-     * @return int  Count of EE_Message's matching the given status.
620
-     */
621
-    public function count_STS_in_queue($status)
622
-    {
623
-        $count  = 0;
624
-        $status = is_array($status) ? $status : [$status];
625
-        $this->_message_repository->rewind();
626
-        foreach ($this->_message_repository as $message) {
627
-            if (in_array($message->STS_ID(), $status)) {
628
-                $count++;
629
-            }
630
-        }
631
-        return $count;
632
-    }
633
-
634
-
635
-    /**
636
-     * Executes the get_preview method on the provided messenger.
637
-     *
638
-     * @param EE_Message      $message
639
-     * @param EE_messenger    $messenger
640
-     * @param EE_message_type $message_type
641
-     * @param                 $test_send
642
-     * @return bool   true means all went well, false means, not so much.
643
-     */
644
-    protected function _do_preview(
645
-        EE_Message $message,
646
-        EE_messenger $messenger,
647
-        EE_message_type $message_type,
648
-        $test_send
649
-    ) {
650
-        if ($preview = $messenger->get_preview($message, $message_type, $test_send)) {
651
-            if (! $test_send) {
652
-                $message->set_content($preview);
653
-            }
654
-            $message->set_STS_ID(EEM_Message::status_sent);
655
-            return true;
656
-        } else {
657
-            $message->set_STS_ID(EEM_Message::status_failed);
658
-            return false;
659
-        }
660
-    }
661
-
662
-
663
-    /**
664
-     * Executes the send method on the provided messenger
665
-     * EE_Messengers are expected to:
666
-     * - return true if the send was successful.
667
-     * - return false if the send was unsuccessful but can be tried again.
668
-     * - throw an Exception if the send was unsuccessful and cannot be tried again.
669
-     *
670
-     * @param EE_Message      $message
671
-     * @param EE_messenger    $messenger
672
-     * @param EE_message_type $message_type
673
-     * @return bool true means all went well, false means, not so much.
674
-     */
675
-    protected function _do_send(EE_Message $message, EE_messenger $messenger, EE_message_type $message_type)
676
-    {
677
-        try {
678
-            if ($messenger->send_message($message, $message_type)) {
679
-                $message->set_STS_ID(EEM_Message::status_sent);
680
-                return true;
681
-            } else {
682
-                $message->set_STS_ID(EEM_Message::status_retry);
683
-                return false;
684
-            }
685
-        } catch (SendMessageException $e) {
686
-            $message->set_STS_ID(EEM_Message::status_failed);
687
-            $message->set_error_message($e->getMessage());
688
-            return false;
689
-        }
690
-    }
691
-
692
-
693
-    /**
694
-     * This sets any necessary error messages on the message object and its status to failed.
695
-     *
696
-     * @param EE_Message $message
697
-     * @param array      $error_messages the response from the messenger.
698
-     * @throws EE_Error
699
-     */
700
-    protected function _set_error_message(EE_Message $message, $error_messages)
701
-    {
702
-        $error_messages = (array) $error_messages;
703
-        if (in_array($message->STS_ID(), EEM_Message::instance()->stati_indicating_failed_sending())) {
704
-            $notices          = EE_Error::has_notices();
705
-            $error_messages[] = esc_html__(
706
-                'Messenger and Message Type were valid and active, but the messenger send method failed.',
707
-                'event_espresso'
708
-            );
709
-            if ($notices === 1) {
710
-                $notices           = EE_Error::get_vanilla_notices();
711
-                $notices['errors'] = isset($notices['errors']) ? $notices['errors'] : [];
712
-                $error_messages[]  = implode("\n", $notices['errors']);
713
-            }
714
-        }
715
-        if (count($error_messages) > 0) {
716
-            $msg = esc_html__('Message was not executed successfully.', 'event_espresso');
717
-            $msg = $msg . "\n" . implode("\n", $error_messages);
718
-            $message->set_error_message($msg);
719
-        }
720
-    }
16
+	/**
17
+	 * @type    string  reference for sending action
18
+	 */
19
+	const action_sending = 'sending';
20
+
21
+	/**
22
+	 * @type    string  reference for generation action
23
+	 */
24
+	const action_generating = 'generation';
25
+
26
+
27
+	/**
28
+	 * @type EE_Message_Repository $_message_repository
29
+	 */
30
+	protected $_message_repository;
31
+
32
+	/**
33
+	 * Sets the limit of how many messages are generated per process.
34
+	 *
35
+	 * @type int
36
+	 */
37
+	protected $_batch_count;
38
+
39
+
40
+	/**
41
+	 * This is an array of cached queue items being stored in this object.
42
+	 * The array keys will be the ID of the EE_Message in the db if saved.  If the EE_Message
43
+	 * is not saved to the db then its key will be an increment of "UNS" (i.e. UNS1, UNS2 etc.)
44
+	 *
45
+	 * @type EE_Message[]
46
+	 */
47
+	protected $_cached_queue_items;
48
+
49
+	/**
50
+	 * Tracks the number of unsaved queue items.
51
+	 *
52
+	 * @type int
53
+	 */
54
+	protected $_unsaved_count = 0;
55
+
56
+	/**
57
+	 * used to record if a do_messenger_hooks has already been called for a message type.  This prevents multiple
58
+	 * hooks getting fired if users have setup their action/filter hooks to prevent duplicate calls.
59
+	 *
60
+	 * @type array
61
+	 */
62
+	protected $_did_hook = [];
63
+
64
+
65
+	/**
66
+	 * Constructor.
67
+	 * Setup all the initial properties and load a EE_Message_Repository.
68
+	 *
69
+	 * @param EE_Message_Repository $message_repository
70
+	 */
71
+	public function __construct(EE_Message_Repository $message_repository)
72
+	{
73
+		$this->_batch_count        = apply_filters('FHEE__EE_Messages_Queue___batch_count', 50);
74
+		$this->_message_repository = $message_repository;
75
+	}
76
+
77
+
78
+	/**
79
+	 * Add a EE_Message object to the queue
80
+	 *
81
+	 * @param EE_Message $message
82
+	 * @param array      $data         This will be an array of data to attach to the object in the repository.  If the
83
+	 *                                 object is persisted, this data will be saved on an extra_meta object related to
84
+	 *                                 EE_Message.
85
+	 * @param bool       $preview      Whether this EE_Message represents a preview or not.
86
+	 * @param bool       $test_send    This indicates whether to do a test send instead of actual send. A test send will
87
+	 *                                 use the messenger send method but typically is based on preview data.
88
+	 * @return bool          Whether the message was successfully added to the repository or not.
89
+	 */
90
+	public function add(EE_Message $message, $data = [], $preview = false, $test_send = false)
91
+	{
92
+		$data['preview']   = $preview;
93
+		$data['test_send'] = $test_send;
94
+		return $this->_message_repository->add($message, $data);
95
+	}
96
+
97
+
98
+	/**
99
+	 * Removes EE_Message from _queue that matches the given EE_Message if the pointer is on a matching EE_Message
100
+	 *
101
+	 * @param EE_Message $message The message to detach from the queue
102
+	 * @param bool       $persist This flag indicates whether to attempt to delete the object from the db as well.
103
+	 * @return bool
104
+	 */
105
+	public function remove(EE_Message $message, $persist = false)
106
+	{
107
+		if ($persist && $this->_message_repository->current() !== $message) {
108
+			// get pointer on right message
109
+			if ($this->_message_repository->has($message)) {
110
+				$this->_message_repository->rewind();
111
+				while ($this->_message_repository->valid()) {
112
+					if ($this->_message_repository->current() === $message) {
113
+						break;
114
+					}
115
+					$this->_message_repository->next();
116
+				}
117
+			} else {
118
+				return false;
119
+			}
120
+		}
121
+		return $persist ? $this->_message_repository->delete() : $this->_message_repository->remove($message);
122
+	}
123
+
124
+
125
+	/**
126
+	 * Persists all queued EE_Message objects to the db.
127
+	 *
128
+	 * @param bool $do_hooks_only @see EE_Message_Repository::saveAll
129
+	 * @return array @see EE_Messages_Repository::saveAll() for return values.
130
+	 */
131
+	public function save($do_hooks_only = false)
132
+	{
133
+		return $this->_message_repository->saveAll($do_hooks_only);
134
+	}
135
+
136
+
137
+	/**
138
+	 * @return EE_Message_Repository
139
+	 */
140
+	public function get_message_repository()
141
+	{
142
+		return $this->_message_repository;
143
+	}
144
+
145
+
146
+	/**
147
+	 * This does the following things:
148
+	 * 1. Checks if there is a lock on generation (prevents race conditions).  If there is a lock then exits (return
149
+	 * false).
150
+	 * 2. If no lock, sets lock, then retrieves a batch of non-generated EE_Message objects and adds to queue
151
+	 * 3. Returns bool.  True = batch ready.  False = no batch ready (or nothing available for generation).
152
+	 * Note: Callers should make sure they release the lock otherwise batch generation will be prevented from
153
+	 * continuing. The lock is on a transient that is set to expire after one hour as a fallback in case locks are not
154
+	 * removed.
155
+	 *
156
+	 * @return bool  true if successfully retrieved batch, false no batch ready.
157
+	 * @throws EE_Error
158
+	 * @throws ReflectionException
159
+	 */
160
+	public function get_batch_to_generate()
161
+	{
162
+		if ($this->is_locked()) {
163
+			return false;
164
+		}
165
+
166
+		// lock batch generation to prevent race conditions.
167
+		$this->lock_queue();
168
+
169
+		$query_args = [
170
+			// key 0 = where conditions
171
+			0          => ['STS_ID' => EEM_Message::status_incomplete],
172
+			'order_by' => $this->_get_priority_orderby(),
173
+			'limit'    => $this->_batch_count,
174
+		];
175
+		$messages   = EEM_Message::instance()->get_all($query_args);
176
+
177
+		if (! $messages) {
178
+			return false; // nothing to generate
179
+		}
180
+
181
+		foreach ($messages as $message) {
182
+			if ($message instanceof EE_Message) {
183
+				$data = $message->all_extra_meta_array();
184
+				$this->add($message, $data);
185
+			}
186
+		}
187
+		return true;
188
+	}
189
+
190
+
191
+	/**
192
+	 * This does the following things:
193
+	 * 1. Checks if there is a lock on sending (prevents race conditions).  If there is a lock then exits (return
194
+	 * false).
195
+	 * 2. Grabs the allowed number of messages to send for the rate_limit.  If cannot send any more messages, then
196
+	 * return false.
197
+	 * 2. If no lock, sets lock, then retrieves a batch of EE_Message objects, adds to queue and triggers execution.
198
+	 * 3. On success or unsuccessful send, sets status appropriately.
199
+	 * 4. Saves messages via the queue
200
+	 * 5. Releases lock.
201
+	 *
202
+	 * @return bool  true on success, false if something preventing sending (i.e. lock set).  Note: true does not
203
+	 *               necessarily mean that all messages were successfully sent.  It just means that this method
204
+	 *               successfully completed. On true, client may want to call $this->count_STS_in_queue(
205
+	 *               EEM_Message::status_failed ) to see if any failed EE_Message objects.  Each failed message object
206
+	 *               will also have a saved error message on it to assist with notifying user.
207
+	 * @throws EE_Error
208
+	 * @throws ReflectionException
209
+	 */
210
+	public function get_to_send_batch_and_send()
211
+	{
212
+		$rate_limit = $this->get_rate_limit();
213
+		if (
214
+			$rate_limit < 1
215
+			|| $this->is_locked(EE_Messages_Queue::action_sending)
216
+		) {
217
+			return false;
218
+		}
219
+
220
+		$this->lock_queue(EE_Messages_Queue::action_sending);
221
+
222
+		$batch = $this->_batch_count < $rate_limit ? $this->_batch_count : $rate_limit;
223
+
224
+		$query_args = [
225
+			// key 0 = where conditions
226
+			0          => ['STS_ID' => ['IN', EEM_Message::instance()->stati_indicating_to_send()]],
227
+			'order_by' => $this->_get_priority_orderby(),
228
+			'limit'    => $batch,
229
+		];
230
+
231
+		$messages_to_send = EEM_Message::instance()->get_all($query_args);
232
+
233
+
234
+		// any to send?
235
+		if (! $messages_to_send) {
236
+			$this->unlock_queue(EE_Messages_Queue::action_sending);
237
+			return false;
238
+		}
239
+
240
+		$queue_count = 0;
241
+
242
+		// add to queue.
243
+		foreach ($messages_to_send as $message) {
244
+			if ($message instanceof EE_Message) {
245
+				$queue_count++;
246
+				$this->add($message);
247
+			}
248
+		}
249
+
250
+		// send messages  (this also updates the rate limit)
251
+		$this->execute();
252
+
253
+		// release lock
254
+		$this->unlock_queue(EE_Messages_Queue::action_sending);
255
+		// update rate limit
256
+		$this->set_rate_limit($queue_count);
257
+		return true;
258
+	}
259
+
260
+
261
+	/**
262
+	 * Locks the queue so that no other queues can call the "batch" methods.
263
+	 *
264
+	 * @param string $type The type of queue being locked.
265
+	 */
266
+	public function lock_queue($type = EE_Messages_Queue::action_generating)
267
+	{
268
+		update_option($this->_get_lock_key($type), $this->_get_lock_expiry($type));
269
+	}
270
+
271
+
272
+	/**
273
+	 * Unlocks the queue so that batch methods can be used.
274
+	 *
275
+	 * @param string $type The type of queue being unlocked.
276
+	 */
277
+	public function unlock_queue($type = EE_Messages_Queue::action_generating)
278
+	{
279
+		delete_option($this->_get_lock_key($type));
280
+	}
281
+
282
+
283
+	/**
284
+	 * Retrieve the key used for the lock transient.
285
+	 *
286
+	 * @param string $type The type of lock.
287
+	 * @return string
288
+	 */
289
+	protected function _get_lock_key($type = EE_Messages_Queue::action_generating)
290
+	{
291
+		return '_ee_lock_' . $type;
292
+	}
293
+
294
+
295
+	/**
296
+	 * Retrieve the expiry time for the lock transient.
297
+	 *
298
+	 * @param string $type The type of lock
299
+	 * @return int   time to expiry in seconds.
300
+	 */
301
+	protected function _get_lock_expiry($type = EE_Messages_Queue::action_generating)
302
+	{
303
+		return time() + (int) apply_filters('FHEE__EE_Messages_Queue__lock_expiry', HOUR_IN_SECONDS, $type);
304
+	}
305
+
306
+
307
+	/**
308
+	 * Returns the key used for rate limit transient.
309
+	 *
310
+	 * @return string
311
+	 */
312
+	protected function _get_rate_limit_key()
313
+	{
314
+		return '_ee_rate_limit';
315
+	}
316
+
317
+
318
+	/**
319
+	 * Returns the rate limit expiry time.
320
+	 *
321
+	 * @return int
322
+	 */
323
+	protected function _get_rate_limit_expiry()
324
+	{
325
+		return time() + (int) apply_filters('FHEE__EE_Messages_Queue__rate_limit_expiry', HOUR_IN_SECONDS);
326
+	}
327
+
328
+
329
+	/**
330
+	 * Returns the default rate limit for sending messages.
331
+	 *
332
+	 * @return int
333
+	 */
334
+	protected function _default_rate_limit()
335
+	{
336
+		return (int) apply_filters('FHEE__EE_Messages_Queue___rate_limit', 200);
337
+	}
338
+
339
+
340
+	/**
341
+	 * Return the orderby array for priority.
342
+	 *
343
+	 * @return array
344
+	 */
345
+	protected function _get_priority_orderby()
346
+	{
347
+		return [
348
+			'MSG_priority' => 'ASC',
349
+			'MSG_modified' => 'DESC',
350
+		];
351
+	}
352
+
353
+
354
+	/**
355
+	 * Returns whether batch methods are "locked" or not, and if models an currently be used to query the database.
356
+	 * Return true when batch methods should not be used; returns false when they can be.
357
+	 *
358
+	 * @param string $type The type of lock being checked for.
359
+	 * @return bool
360
+	 */
361
+	public function is_locked($type = EE_Messages_Queue::action_generating)
362
+	{
363
+		if (! EE_Maintenance_Mode::instance()->models_can_query()) {
364
+			return true;
365
+		}
366
+		$lock = (int) get_option($this->_get_lock_key($type), 0);
367
+		/**
368
+		 * This filters the default is_locked behaviour.
369
+		 */
370
+		$is_locked = filter_var(
371
+			apply_filters(
372
+				'FHEE__EE_Messages_Queue__is_locked',
373
+				$lock > time(),
374
+				$this
375
+			),
376
+			FILTER_VALIDATE_BOOLEAN
377
+		);
378
+
379
+		/**
380
+		 * @see usage of this filter in EE_Messages_Queue::initiate_request_by_priority() method.
381
+		 *            Also implemented here because messages processed on the same request should not have any locks applied.
382
+		 */
383
+		if (
384
+			apply_filters('FHEE__EE_Messages_Processor__initiate_request_by_priority__do_immediate_processing', false)
385
+			|| EE_Registry::instance()->NET_CFG->core->do_messages_on_same_request
386
+		) {
387
+			$is_locked = false;
388
+		}
389
+
390
+
391
+		return $is_locked;
392
+	}
393
+
394
+
395
+	/**
396
+	 * Retrieves the rate limit that may be cached as a transient.
397
+	 * If the rate limit is not set, then this sets the default rate limit and expiry and returns it.
398
+	 *
399
+	 * @param bool $return_expiry If true then return the expiry time not the rate_limit.
400
+	 * @return int
401
+	 */
402
+	protected function get_rate_limit($return_expiry = false)
403
+	{
404
+		$stored_rate_info = get_option($this->_get_rate_limit_key(), []);
405
+		$rate_limit       = isset($stored_rate_info[0])
406
+			? (int) $stored_rate_info[0]
407
+			: 0;
408
+		$expiry           = isset($stored_rate_info[1])
409
+			? (int) $stored_rate_info[1]
410
+			: 0;
411
+		// set the default for tracking?
412
+		if (empty($stored_rate_info) || time() > $expiry) {
413
+			$expiry     = $this->_get_rate_limit_expiry();
414
+			$rate_limit = $this->_default_rate_limit();
415
+			update_option($this->_get_rate_limit_key(), [$rate_limit, $expiry]);
416
+		}
417
+		return $return_expiry ? $expiry : $rate_limit;
418
+	}
419
+
420
+
421
+	/**
422
+	 * This updates existing rate limit with the new limit which is the old minus the batch.
423
+	 *
424
+	 * @param int $batch_completed This sets the new rate limit based on the given batch that was completed.
425
+	 */
426
+	protected function set_rate_limit($batch_completed)
427
+	{
428
+		// first get the most up to date rate limit (in case its expired and reset)
429
+		$rate_limit = $this->get_rate_limit();
430
+		$expiry     = $this->get_rate_limit(true);
431
+		$new_limit  = $rate_limit - $batch_completed;
432
+		// updating the transient option directly to avoid resetting the expiry.
433
+
434
+		update_option($this->_get_rate_limit_key(), [$new_limit, $expiry]);
435
+	}
436
+
437
+
438
+	/**
439
+	 * This method checks the queue for ANY EE_Message objects with a priority matching the given priority passed in.
440
+	 * If that exists, then we immediately initiate a non-blocking request to do the requested action type.
441
+	 * Note: Keep in mind that there is the possibility that the request will not execute if there is already another
442
+	 * request running on a queue for the given task.
443
+	 *
444
+	 * @param string $task     This indicates what type of request is going to be initiated.
445
+	 * @param int    $priority This indicates the priority that triggers initiating the request.
446
+	 * @return bool|EE_Messages_Queue|void
447
+	 * @throws EE_Error
448
+	 * @throws ReflectionException
449
+	 */
450
+	public function initiate_request_by_priority($task = 'generate', $priority = EEM_Message::priority_high)
451
+	{
452
+		// determine what status is matched with the priority as part of the trigger conditions.
453
+		$status = $task == 'generate'
454
+			? EEM_Message::status_incomplete
455
+			: EEM_Message::instance()->stati_indicating_to_send();
456
+		// always make sure we save because either this will get executed immediately on a separate request
457
+		// or remains in the queue for the regularly scheduled queue batch.
458
+		$this->save();
459
+		/**
460
+		 * This filter/option allows users to override processing of messages on separate requests and instead have everything
461
+		 * happen on the same request.  If this is utilized remember:
462
+		 * - message priorities don't matter
463
+		 * - existing unprocessed messages in the queue will not get processed unless manually triggered.
464
+		 * - things will be perceived to take longer to happen for end users (i.e. registrations) because of the additional
465
+		 *   processing happening on the same request.
466
+		 * - any race condition protection (locks) are removed because they don't apply when things are processed on
467
+		 *   the same request.
468
+		 */
469
+		if (
470
+			apply_filters('FHEE__EE_Messages_Processor__initiate_request_by_priority__do_immediate_processing', false)
471
+			|| EE_Registry::instance()->NET_CFG->core->do_messages_on_same_request
472
+		) {
473
+			$messages_processor = EE_Registry::instance()->load_lib('Messages_Processor');
474
+			if ($messages_processor instanceof EE_Messages_Processor) {
475
+				return $messages_processor->process_immediately_from_queue($this);
476
+			}
477
+			// if we get here then that means the messages processor couldn't be loaded so messages will just remain
478
+			// queued for manual triggering by end user.
479
+		}
480
+
481
+		if ($this->_message_repository->count_by_priority_and_status($priority, $status)) {
482
+			EE_Messages_Scheduler::initiate_scheduled_non_blocking_request($task);
483
+		}
484
+	}
485
+
486
+
487
+	/**
488
+	 *  Loops through the EE_Message objects in the _queue and calls the messenger send methods for each message.
489
+	 *
490
+	 * @param bool     $save                      Used to indicate whether to save the message queue after sending
491
+	 *                                            (default will save).
492
+	 * @param mixed    $sending_messenger         (optional) When the sending messenger is different than
493
+	 *                                            what is on the EE_Message object in the queue.
494
+	 *                                            For instance, showing the browser view of an email message,
495
+	 *                                            or giving a pdf generated view of an html document.
496
+	 *                                            This should be an instance of EE_messenger but if you call this
497
+	 *                                            method
498
+	 *                                            intending it to be a sending messenger but a valid one could not be
499
+	 *                                            retrieved then send in an instance of EE_Error that contains the
500
+	 *                                            related error message.
501
+	 * @param bool|int $by_priority               When set, this indicates that only messages
502
+	 *                                            matching the given priority should be executed.
503
+	 * @return int        Number of messages sent.  Note, 0 does not mean that no messages were processed.
504
+	 *                                            Also, if the messenger is an request type messenger (or a preview),
505
+	 *                                            its entirely possible that the messenger will exit before
506
+	 * @throws EE_Error
507
+	 * @throws ReflectionException
508
+	 */
509
+	public function execute($save = true, $sending_messenger = null, $by_priority = false)
510
+	{
511
+		$messages_sent   = 0;
512
+		$this->_did_hook = [];
513
+		$this->_message_repository->rewind();
514
+
515
+		while ($this->_message_repository->valid()) {
516
+			$error_messages = [];
517
+			$message        = $this->_message_repository->current();
518
+
519
+			// only process things that are queued for sending
520
+			if (! in_array($message->STS_ID(), EEM_Message::instance()->stati_indicating_to_send())) {
521
+				$this->_message_repository->next();
522
+				continue;
523
+			}
524
+			// if $by_priority is set and does not match then continue;
525
+			if ($by_priority && $by_priority != $message->priority()) {
526
+				$this->_message_repository->next();
527
+				continue;
528
+			}
529
+			// error checking
530
+			if (! $message->valid_messenger()) {
531
+				$error_messages[] = sprintf(
532
+					esc_html__('The %s messenger is not active at time of sending.', 'event_espresso'),
533
+					$message->messenger()
534
+				);
535
+			}
536
+			if (! $message->valid_message_type()) {
537
+				$error_messages[] = sprintf(
538
+					esc_html__('The %s message type is not active at the time of sending.', 'event_espresso'),
539
+					$message->message_type()
540
+				);
541
+			}
542
+			// if there was supposed to be a sending messenger for this message, but it was invalid/inactive,
543
+			// then it will instead be an EE_Error object, so let's check for that
544
+			if ($sending_messenger instanceof EE_Error) {
545
+				$error_messages[] = $sending_messenger->getMessage();
546
+			}
547
+			// if there are no errors, then let's process the message
548
+			if (empty($error_messages)) {
549
+				if ($save) {
550
+					$message->set_messenger_is_executing();
551
+				}
552
+				if ($this->_process_message($message, $sending_messenger)) {
553
+					$messages_sent++;
554
+				}
555
+			}
556
+			$this->_set_error_message($message, $error_messages);
557
+			// add modified time
558
+			$message->set_modified(time());
559
+			// we save each message after its processed to make sure its status persists in case PHP times-out or runs
560
+			// out of memory. @see https://events.codebasehq.com/projects/event-espresso/tickets/10281
561
+			if ($save) {
562
+				$message->save();
563
+			}
564
+
565
+			$this->_message_repository->next();
566
+		}
567
+		if ($save) {
568
+			$this->save(true);
569
+		}
570
+		return $messages_sent;
571
+	}
572
+
573
+
574
+	/**
575
+	 * _process_message
576
+	 *
577
+	 * @param EE_Message $message
578
+	 * @param mixed      $sending_messenger (optional)
579
+	 * @return bool
580
+	 */
581
+	protected function _process_message(EE_Message $message, $sending_messenger = null)
582
+	{
583
+		// these *should* have been validated in the execute() method above
584
+		$messenger    = $message->messenger_object();
585
+		$message_type = $message->message_type_object();
586
+		// do actions for sending messenger if it differs from generating messenger and swap values.
587
+		if (
588
+			$sending_messenger instanceof EE_messenger
589
+			&& $messenger instanceof EE_messenger
590
+			&& $sending_messenger->name != $messenger->name
591
+		) {
592
+			$messenger->do_secondary_messenger_hooks($sending_messenger->name);
593
+			$messenger = $sending_messenger;
594
+		}
595
+		// send using messenger, but double check objects
596
+		if ($messenger instanceof EE_messenger && $message_type instanceof EE_message_type) {
597
+			// set hook for message type (but only if not using another messenger to send).
598
+			if (! isset($this->_did_hook[ $message_type->name ])) {
599
+				$message_type->do_messenger_hooks($messenger);
600
+				$this->_did_hook[ $message_type->name ] = 1;
601
+			}
602
+			// if preview then use preview method
603
+			return $this->_message_repository->is_preview()
604
+				? $this->_do_preview($message, $messenger, $message_type, $this->_message_repository->is_test_send())
605
+				: $this->_do_send($message, $messenger, $message_type);
606
+		}
607
+		return false;
608
+	}
609
+
610
+
611
+	/**
612
+	 * The intention of this method is to count how many EE_Message objects
613
+	 * are in the queue with a given status.
614
+	 * Example usage:
615
+	 * After a caller calls the "EE_Message_Queue::execute()" method, the caller can check if there were any failed
616
+	 * sends by calling $queue->count_STS_in_queue( EEM_Message_Queue::status_failed ).
617
+	 *
618
+	 * @param array|string $status Stati to check for in queue
619
+	 * @return int  Count of EE_Message's matching the given status.
620
+	 */
621
+	public function count_STS_in_queue($status)
622
+	{
623
+		$count  = 0;
624
+		$status = is_array($status) ? $status : [$status];
625
+		$this->_message_repository->rewind();
626
+		foreach ($this->_message_repository as $message) {
627
+			if (in_array($message->STS_ID(), $status)) {
628
+				$count++;
629
+			}
630
+		}
631
+		return $count;
632
+	}
633
+
634
+
635
+	/**
636
+	 * Executes the get_preview method on the provided messenger.
637
+	 *
638
+	 * @param EE_Message      $message
639
+	 * @param EE_messenger    $messenger
640
+	 * @param EE_message_type $message_type
641
+	 * @param                 $test_send
642
+	 * @return bool   true means all went well, false means, not so much.
643
+	 */
644
+	protected function _do_preview(
645
+		EE_Message $message,
646
+		EE_messenger $messenger,
647
+		EE_message_type $message_type,
648
+		$test_send
649
+	) {
650
+		if ($preview = $messenger->get_preview($message, $message_type, $test_send)) {
651
+			if (! $test_send) {
652
+				$message->set_content($preview);
653
+			}
654
+			$message->set_STS_ID(EEM_Message::status_sent);
655
+			return true;
656
+		} else {
657
+			$message->set_STS_ID(EEM_Message::status_failed);
658
+			return false;
659
+		}
660
+	}
661
+
662
+
663
+	/**
664
+	 * Executes the send method on the provided messenger
665
+	 * EE_Messengers are expected to:
666
+	 * - return true if the send was successful.
667
+	 * - return false if the send was unsuccessful but can be tried again.
668
+	 * - throw an Exception if the send was unsuccessful and cannot be tried again.
669
+	 *
670
+	 * @param EE_Message      $message
671
+	 * @param EE_messenger    $messenger
672
+	 * @param EE_message_type $message_type
673
+	 * @return bool true means all went well, false means, not so much.
674
+	 */
675
+	protected function _do_send(EE_Message $message, EE_messenger $messenger, EE_message_type $message_type)
676
+	{
677
+		try {
678
+			if ($messenger->send_message($message, $message_type)) {
679
+				$message->set_STS_ID(EEM_Message::status_sent);
680
+				return true;
681
+			} else {
682
+				$message->set_STS_ID(EEM_Message::status_retry);
683
+				return false;
684
+			}
685
+		} catch (SendMessageException $e) {
686
+			$message->set_STS_ID(EEM_Message::status_failed);
687
+			$message->set_error_message($e->getMessage());
688
+			return false;
689
+		}
690
+	}
691
+
692
+
693
+	/**
694
+	 * This sets any necessary error messages on the message object and its status to failed.
695
+	 *
696
+	 * @param EE_Message $message
697
+	 * @param array      $error_messages the response from the messenger.
698
+	 * @throws EE_Error
699
+	 */
700
+	protected function _set_error_message(EE_Message $message, $error_messages)
701
+	{
702
+		$error_messages = (array) $error_messages;
703
+		if (in_array($message->STS_ID(), EEM_Message::instance()->stati_indicating_failed_sending())) {
704
+			$notices          = EE_Error::has_notices();
705
+			$error_messages[] = esc_html__(
706
+				'Messenger and Message Type were valid and active, but the messenger send method failed.',
707
+				'event_espresso'
708
+			);
709
+			if ($notices === 1) {
710
+				$notices           = EE_Error::get_vanilla_notices();
711
+				$notices['errors'] = isset($notices['errors']) ? $notices['errors'] : [];
712
+				$error_messages[]  = implode("\n", $notices['errors']);
713
+			}
714
+		}
715
+		if (count($error_messages) > 0) {
716
+			$msg = esc_html__('Message was not executed successfully.', 'event_espresso');
717
+			$msg = $msg . "\n" . implode("\n", $error_messages);
718
+			$message->set_error_message($msg);
719
+		}
720
+	}
721 721
 }
Please login to merge, or discard this patch.
Spacing   +12 added lines, -12 removed lines patch added patch discarded remove patch
@@ -172,9 +172,9 @@  discard block
 block discarded – undo
172 172
             'order_by' => $this->_get_priority_orderby(),
173 173
             'limit'    => $this->_batch_count,
174 174
         ];
175
-        $messages   = EEM_Message::instance()->get_all($query_args);
175
+        $messages = EEM_Message::instance()->get_all($query_args);
176 176
 
177
-        if (! $messages) {
177
+        if ( ! $messages) {
178 178
             return false; // nothing to generate
179 179
         }
180 180
 
@@ -232,7 +232,7 @@  discard block
 block discarded – undo
232 232
 
233 233
 
234 234
         // any to send?
235
-        if (! $messages_to_send) {
235
+        if ( ! $messages_to_send) {
236 236
             $this->unlock_queue(EE_Messages_Queue::action_sending);
237 237
             return false;
238 238
         }
@@ -288,7 +288,7 @@  discard block
 block discarded – undo
288 288
      */
289 289
     protected function _get_lock_key($type = EE_Messages_Queue::action_generating)
290 290
     {
291
-        return '_ee_lock_' . $type;
291
+        return '_ee_lock_'.$type;
292 292
     }
293 293
 
294 294
 
@@ -360,7 +360,7 @@  discard block
 block discarded – undo
360 360
      */
361 361
     public function is_locked($type = EE_Messages_Queue::action_generating)
362 362
     {
363
-        if (! EE_Maintenance_Mode::instance()->models_can_query()) {
363
+        if ( ! EE_Maintenance_Mode::instance()->models_can_query()) {
364 364
             return true;
365 365
         }
366 366
         $lock = (int) get_option($this->_get_lock_key($type), 0);
@@ -517,7 +517,7 @@  discard block
 block discarded – undo
517 517
             $message        = $this->_message_repository->current();
518 518
 
519 519
             // only process things that are queued for sending
520
-            if (! in_array($message->STS_ID(), EEM_Message::instance()->stati_indicating_to_send())) {
520
+            if ( ! in_array($message->STS_ID(), EEM_Message::instance()->stati_indicating_to_send())) {
521 521
                 $this->_message_repository->next();
522 522
                 continue;
523 523
             }
@@ -527,13 +527,13 @@  discard block
 block discarded – undo
527 527
                 continue;
528 528
             }
529 529
             // error checking
530
-            if (! $message->valid_messenger()) {
530
+            if ( ! $message->valid_messenger()) {
531 531
                 $error_messages[] = sprintf(
532 532
                     esc_html__('The %s messenger is not active at time of sending.', 'event_espresso'),
533 533
                     $message->messenger()
534 534
                 );
535 535
             }
536
-            if (! $message->valid_message_type()) {
536
+            if ( ! $message->valid_message_type()) {
537 537
                 $error_messages[] = sprintf(
538 538
                     esc_html__('The %s message type is not active at the time of sending.', 'event_espresso'),
539 539
                     $message->message_type()
@@ -595,9 +595,9 @@  discard block
 block discarded – undo
595 595
         // send using messenger, but double check objects
596 596
         if ($messenger instanceof EE_messenger && $message_type instanceof EE_message_type) {
597 597
             // set hook for message type (but only if not using another messenger to send).
598
-            if (! isset($this->_did_hook[ $message_type->name ])) {
598
+            if ( ! isset($this->_did_hook[$message_type->name])) {
599 599
                 $message_type->do_messenger_hooks($messenger);
600
-                $this->_did_hook[ $message_type->name ] = 1;
600
+                $this->_did_hook[$message_type->name] = 1;
601 601
             }
602 602
             // if preview then use preview method
603 603
             return $this->_message_repository->is_preview()
@@ -648,7 +648,7 @@  discard block
 block discarded – undo
648 648
         $test_send
649 649
     ) {
650 650
         if ($preview = $messenger->get_preview($message, $message_type, $test_send)) {
651
-            if (! $test_send) {
651
+            if ( ! $test_send) {
652 652
                 $message->set_content($preview);
653 653
             }
654 654
             $message->set_STS_ID(EEM_Message::status_sent);
@@ -714,7 +714,7 @@  discard block
 block discarded – undo
714 714
         }
715 715
         if (count($error_messages) > 0) {
716 716
             $msg = esc_html__('Message was not executed successfully.', 'event_espresso');
717
-            $msg = $msg . "\n" . implode("\n", $error_messages);
717
+            $msg = $msg."\n".implode("\n", $error_messages);
718 718
             $message->set_error_message($msg);
719 719
         }
720 720
     }
Please login to merge, or discard this patch.
core/libraries/messages/EE_Messages_Processor.lib.php 2 patches
Spacing   +8 added lines, -8 removed lines patch added patch discarded remove patch
@@ -284,7 +284,7 @@  discard block
 block discarded – undo
284 284
     public function queue_for_generation(EE_Message_To_Generate $message_to_generate, $test_send = false)
285 285
     {
286 286
         if ($message_to_generate->valid()) {
287
-            if (! $this->_generator->create_and_add_message_to_queue($message_to_generate, $test_send)) {
287
+            if ( ! $this->_generator->create_and_add_message_to_queue($message_to_generate, $test_send)) {
288 288
                 throw new RuntimeException(
289 289
                     esc_html__('Message failed to generate', 'event_espresso')
290 290
                 );
@@ -330,7 +330,7 @@  discard block
 block discarded – undo
330 330
     protected function _queue_for_generation_loop($messages_to_generate)
331 331
     {
332 332
         // make sure is in an array.
333
-        if (! is_array($messages_to_generate)) {
333
+        if ( ! is_array($messages_to_generate)) {
334 334
             $messages_to_generate = [$messages_to_generate];
335 335
         }
336 336
 
@@ -370,7 +370,7 @@  discard block
 block discarded – undo
370 370
      */
371 371
     public function generate_for_preview(EE_Message_To_Generate $message_to_generate, $test_send = false)
372 372
     {
373
-        if (! $message_to_generate->valid()) {
373
+        if ( ! $message_to_generate->valid()) {
374 374
             EE_Error::add_error(
375 375
                 esc_html__('Unable to generate preview because of invalid data', 'event_espresso'),
376 376
                 __FILE__,
@@ -407,7 +407,7 @@  discard block
 block discarded – undo
407 407
      */
408 408
     public function queue_for_sending(EE_Message_To_Generate $message_to_generate)
409 409
     {
410
-        if (! $message_to_generate->valid()) {
410
+        if ( ! $message_to_generate->valid()) {
411 411
             return false;
412 412
         }
413 413
         $this->_init_queue_and_generator();
@@ -432,7 +432,7 @@  discard block
 block discarded – undo
432 432
      */
433 433
     public function generate_and_send_now(EE_Message_To_Generate $message_to_generate)
434 434
     {
435
-        if (! $message_to_generate->valid()) {
435
+        if ( ! $message_to_generate->valid()) {
436 436
             return null;
437 437
         }
438 438
         // is there supposed to be a sending messenger for this message?
@@ -579,7 +579,7 @@  discard block
 block discarded – undo
579 579
 
580 580
         foreach ($regIDs as $regID) {
581 581
             $reg = EEM_Registration::instance()->get_one_by_ID($regID);
582
-            if (! $reg instanceof EE_Registration) {
582
+            if ( ! $reg instanceof EE_Registration) {
583 583
                 EE_Error::add_error(
584 584
                     sprintf(
585 585
                         esc_html__(
@@ -591,7 +591,7 @@  discard block
 block discarded – undo
591 591
                 );
592 592
                 return false;
593 593
             }
594
-            $regs_to_send[ $reg->transaction_ID() ][ $reg->status_ID() ][] = $reg;
594
+            $regs_to_send[$reg->transaction_ID()][$reg->status_ID()][] = $reg;
595 595
         }
596 596
 
597 597
         $messages_to_generate = [];
@@ -599,7 +599,7 @@  discard block
 block discarded – undo
599 599
         foreach ($regs_to_send as $status_group) {
600 600
             foreach ($status_group as $status_id => $registrations) {
601 601
                 $message_type = EEH_MSG_Template::convert_reg_status_to_message_type($status_id);
602
-                if (! $message_type) {
602
+                if ( ! $message_type) {
603 603
                     continue;
604 604
                 }
605 605
                 $messages_to_generate = array_merge(
Please login to merge, or discard this patch.
Indentation   +598 added lines, -598 removed lines patch added patch discarded remove patch
@@ -14,602 +14,602 @@
 block discarded – undo
14 14
  */
15 15
 class EE_Messages_Processor
16 16
 {
17
-    /**
18
-     * @type EE_Message_Resource_Manager $_message_resource_manager
19
-     */
20
-    protected $_message_resource_manager;
21
-
22
-    /**
23
-     * @type EE_Messages_Queue
24
-     */
25
-    protected $_queue;
26
-
27
-    /**
28
-     * @type  EE_Messages_Generator
29
-     */
30
-    protected $_generator;
31
-
32
-
33
-    /**
34
-     * constructor
35
-     *
36
-     * @param EE_Message_Resource_Manager $message_resource_manager
37
-     */
38
-    public function __construct(EE_Message_Resource_Manager $message_resource_manager)
39
-    {
40
-        $this->_message_resource_manager = $message_resource_manager;
41
-        $this->_init_queue_and_generator();
42
-    }
43
-
44
-
45
-    /**
46
-     * This method sets (or resets) the various properties for use.
47
-     *
48
-     * - $_queue = holds the messages queue
49
-     * - $_generator = holds the messages generator
50
-     */
51
-    protected function _init_queue_and_generator()
52
-    {
53
-        $this->_generator = EE_Registry::factory('EE_Messages_Generator');
54
-        $this->_queue     = $this->_generator->generation_queue();
55
-    }
56
-
57
-
58
-    /**
59
-     * This returns the current set queue.
60
-     *
61
-     * @return EE_Messages_Queue
62
-     */
63
-    public function get_queue()
64
-    {
65
-        return $this->_queue;
66
-    }
67
-
68
-
69
-    /**
70
-     * This method can be utilized to process messages from a queue and they will be processed immediately on the same
71
-     * request. Please note that this method alone does not bypass the usual "locks" for generation/sending (it assumes
72
-     * client code has already filtered those if necessary).
73
-     *
74
-     * @param EE_Messages_Queue $queue_to_process
75
-     * @return bool  true for success false for error.
76
-     * @throws EE_Error
77
-     * @throws ReflectionException
78
-     */
79
-    public function process_immediately_from_queue(EE_Messages_Queue $queue_to_process)
80
-    {
81
-        $success              = false;
82
-        $messages_to_send     = [];
83
-        $messages_to_generate = [];
84
-        // loop through and setup the various messages from the queue so we know what is being processed
85
-        $queue_to_process->get_message_repository()->rewind();
86
-        foreach ($queue_to_process->get_message_repository() as $message) {
87
-            if ($message->STS_ID() === EEM_Message::status_incomplete) {
88
-                $messages_to_generate[] = $message;
89
-                continue;
90
-            }
91
-
92
-            if (in_array($message->STS_ID(), EEM_Message::instance()->stati_indicating_to_send())) {
93
-                $messages_to_send[] = $message;
94
-            }
95
-        }
96
-
97
-        // do generation/sends
98
-        if ($messages_to_generate) {
99
-            $success = $this->batch_generate_from_queue($messages_to_generate, true);
100
-        }
101
-
102
-        if ($messages_to_send) {
103
-            $sent = $this->batch_send_from_queue($messages_to_send, true);
104
-            // if there was messages to generate and it failed, then we override any success value for the sending process
105
-            // otherwise we just use the return from batch send.  The intent is that there is a simple response for success/fail.
106
-            // Either everything was successful or we consider it a fail.  To be clear, this is a limitation of doing
107
-            // all messages processing on the same request.
108
-            $success = $messages_to_generate && ! $success ? false : $sent;
109
-        }
110
-        return $success;
111
-    }
112
-
113
-
114
-    /**
115
-     * Calls the EE_Messages_Queue::get_batch_to_generate() method and sends to EE_Messages_Generator.
116
-     *
117
-     * @param EE_Message[] $messages    Array of EE_Message objects (optional) to build the queue with.
118
-     * @param bool         $clear_queue Whether to ensure a fresh queue or not.
119
-     *
120
-     * @return bool|EE_Messages_Queue return false if nothing generated.  This returns a new EE_Message_Queue with
121
-     *                                   generated messages.
122
-     * @throws EE_Error
123
-     * @throws ReflectionException
124
-     */
125
-    public function batch_generate_from_queue($messages = [], $clear_queue = false)
126
-    {
127
-        if ($this->_build_queue_for_generation($messages, $clear_queue)) {
128
-            $new_queue = $this->_generator->generate();
129
-            if ($new_queue instanceof EE_Messages_Queue) {
130
-                // unlock queue
131
-                $this->_queue->unlock_queue();
132
-                $new_queue->initiate_request_by_priority('send');
133
-                return $new_queue;
134
-            }
135
-        }
136
-        $this->_queue->unlock_queue();
137
-        return false;
138
-    }
139
-
140
-
141
-    /**
142
-     * This method preps a queue for generation.
143
-     *
144
-     * @param EE_Message[] $messages    Array of EE_Message objects to build the queue with
145
-     *
146
-     * @param bool         $clear_queue This indicates whether the existing queue should be dumped or not.
147
-     *
148
-     * @return bool true means queue prepped, false means there was a lock so no generation please.
149
-     * @throws EE_Error
150
-     * @throws ReflectionException
151
-     * @since    4.9.0
152
-     *
153
-     */
154
-    protected function _build_queue_for_generation($messages = [], $clear_queue = false)
155
-    {
156
-
157
-        if ($clear_queue) {
158
-            $this->_init_queue_and_generator();
159
-        }
160
-
161
-        if ($messages) {
162
-            // if generation is locked then get out now because that means processing is already happening.
163
-            if ($this->_queue->is_locked()) {
164
-                return false;
165
-            }
166
-
167
-            $this->_queue->lock_queue();
168
-            $messages = is_array($messages) ? $messages : [$messages];
169
-            foreach ($messages as $message) {
170
-                if ($message instanceof EE_Message) {
171
-                    $data = $message->all_extra_meta_array();
172
-                    $this->_queue->add($message, $data);
173
-                }
174
-            }
175
-            return true;
176
-        } else {
177
-            return $this->_queue->get_batch_to_generate();
178
-        }
179
-    }
180
-
181
-
182
-    /**
183
-     * This method preps a queue for sending.
184
-     *
185
-     * @param EE_Message[] $messages
186
-     * @param bool         $clear_queue Used to indicate whether to start with a fresh queue or not.
187
-     *
188
-     * @return bool true means queue prepped, false means there was a lock so no queue prepped.
189
-     */
190
-    protected function _build_queue_for_sending($messages, $clear_queue = false)
191
-    {
192
-        // if sending is locked then get out now because that means processing is already happening.
193
-        if ($this->_queue->is_locked(EE_Messages_Queue::action_sending)) {
194
-            return false;
195
-        }
196
-
197
-        $this->_queue->lock_queue(EE_Messages_Queue::action_sending);
198
-
199
-        if ($clear_queue) {
200
-            $this->_init_queue_and_generator();
201
-        }
202
-
203
-        $messages = is_array($messages) ? $messages : [$messages];
204
-
205
-        foreach ($messages as $message) {
206
-            $this->_queue->add($message);
207
-        }
208
-        return true;
209
-    }
210
-
211
-
212
-    /**
213
-     * Calls the EE_Message_Queue::get_to_send_batch_and_send() method and then immediately just calls
214
-     * EE_Message_Queue::execute() to iterate and send unsent messages.
215
-     *
216
-     * @param EE_Message[] $messages    If an array of messages is sent in then use it.
217
-     *
218
-     * @param bool         $clear_queue Whether to initialize a new queue or keep the existing one.
219
-     *
220
-     * @return EE_Messages_Queue
221
-     * @throws EE_Error
222
-     * @throws ReflectionException
223
-     */
224
-    public function batch_send_from_queue($messages = [], $clear_queue = false)
225
-    {
226
-
227
-        if ($messages && $this->_build_queue_for_sending($messages, $clear_queue)) {
228
-            $this->_queue->execute();
229
-            $this->_queue->unlock_queue(EE_Messages_Queue::action_sending);
230
-        } else {
231
-            // get messages to send and execute.
232
-            $this->_queue->get_to_send_batch_and_send();
233
-        }
234
-        // note: callers can use the EE_Messages_Queue::count_STS_in_queue() method to find out if there were any failed
235
-        // messages in the queue and decide how to handle at that point.
236
-        return $this->_queue;
237
-    }
238
-
239
-
240
-    /**
241
-     * This immediately generates messages using the given array of EE_Message_To_Generate objects and returns the
242
-     * EE_Message_Queue with the generated messages for the caller to work with.  Note, this does NOT save the generated
243
-     * messages in the queue, leaving it up to the caller to do so.
244
-     *
245
-     * @param EE_Message_To_Generate[] $messages_to_generate
246
-     * @return EE_Messages_Queue
247
-     * @throws EE_Error
248
-     * @throws ReflectionException
249
-     */
250
-    public function generate_and_return($messages_to_generate)
251
-    {
252
-        $this->_init_queue_and_generator();
253
-        $this->_queue_for_generation_loop($messages_to_generate);
254
-        return $this->_generator->generate(false);
255
-    }
256
-
257
-
258
-    /**
259
-     * Executes the generator generate method on the current internal queue, and returns the generated queue.
260
-     *
261
-     * @param bool $persist Indicate whether to instruct the generator to persist the generated queue (true) or not
262
-     *                      (false).
263
-     * @return EE_Messages_Queue
264
-     * @throws EE_Error
265
-     * @throws ReflectionException
266
-     */
267
-    public function generate_queue($persist = true)
268
-    {
269
-        return $this->_generator->generate($persist);
270
-    }
271
-
272
-
273
-    /**
274
-     * Queue for generation.  Note this does NOT persist to the db.  Client code should call
275
-     * get_message_repository()->save() if desire to persist.  This method is provided to client code to decide what it
276
-     * wants to do with queued messages for generation.
277
-     *
278
-     * @param EE_Message_To_Generate $message_to_generate
279
-     * @param bool                   $test_send Whether this item is for a test send or not.
280
-     * @return void
281
-     */
282
-    public function queue_for_generation(EE_Message_To_Generate $message_to_generate, $test_send = false)
283
-    {
284
-        if ($message_to_generate->valid()) {
285
-            if (! $this->_generator->create_and_add_message_to_queue($message_to_generate, $test_send)) {
286
-                throw new RuntimeException(
287
-                    esc_html__('Message failed to generate', 'event_espresso')
288
-                );
289
-            }
290
-        }
291
-    }
292
-
293
-
294
-    /**
295
-     * This receives an array of EE_Message_To_Generate objects, converts them to EE_Message adds them to the
296
-     * generation queue and then persists to storage.
297
-     *
298
-     * @param EE_Message_To_Generate[] $messages_to_generate
299
-     */
300
-    public function batch_queue_for_generation_and_persist($messages_to_generate)
301
-    {
302
-        $this->_init_queue_and_generator();
303
-        $this->_queue_for_generation_loop($messages_to_generate);
304
-        $this->_queue->save();
305
-    }
306
-
307
-
308
-    /**
309
-     * This receives an array of EE_Message_To_Generate objects, converts them to EE_Message and adds them to the
310
-     * generation queue.  Does NOT persist to storage (unless there is an error. Client code can retrieve the generated
311
-     * queue by calling EEM_Messages_Processor::get_queue()
312
-     *
313
-     * @param EE_Message_To_Generate[] $messages_to_generate
314
-     */
315
-    public function batch_queue_for_generation_no_persist($messages_to_generate)
316
-    {
317
-        $this->_init_queue_and_generator();
318
-        $this->_queue_for_generation_loop($messages_to_generate);
319
-    }
320
-
321
-
322
-    /**
323
-     * Simply loops through the given array of EE_Message_To_Generate objects and adds them to the _queue as EE_Message
324
-     * objects.
325
-     *
326
-     * @param EE_Message_To_Generate[] $messages_to_generate
327
-     */
328
-    protected function _queue_for_generation_loop($messages_to_generate)
329
-    {
330
-        // make sure is in an array.
331
-        if (! is_array($messages_to_generate)) {
332
-            $messages_to_generate = [$messages_to_generate];
333
-        }
334
-
335
-        foreach ($messages_to_generate as $message_to_generate) {
336
-            if ($message_to_generate instanceof EE_Message_To_Generate && $message_to_generate->valid()) {
337
-                $this->queue_for_generation($message_to_generate);
338
-            }
339
-        }
340
-    }
341
-
342
-
343
-    /**
344
-     * Receives an array of EE_Message_To_Generate objects and generates the EE_Message objects, then persists (so its
345
-     * queued for sending).
346
-     *
347
-     * @param EE_Message_To_Generate[]
348
-     * @return EE_Messages_Queue
349
-     * @throws EE_Error
350
-     * @throws ReflectionException
351
-     */
352
-    public function generate_and_queue_for_sending($messages_to_generate)
353
-    {
354
-        $this->_init_queue_and_generator();
355
-        $this->_queue_for_generation_loop($messages_to_generate);
356
-        return $this->_generator->generate();
357
-    }
358
-
359
-
360
-    /**
361
-     * Generate for preview and execute right away.
362
-     *
363
-     * @param EE_Message_To_Generate $message_to_generate
364
-     * @param bool                   $test_send Whether this is a test send or not.
365
-     * @return  EE_Messages_Queue | bool   false if unable to generate otherwise the generated queue.
366
-     * @throws EE_Error
367
-     * @throws ReflectionException
368
-     */
369
-    public function generate_for_preview(EE_Message_To_Generate $message_to_generate, $test_send = false)
370
-    {
371
-        if (! $message_to_generate->valid()) {
372
-            EE_Error::add_error(
373
-                esc_html__('Unable to generate preview because of invalid data', 'event_espresso'),
374
-                __FILE__,
375
-                __FUNCTION__,
376
-                __LINE__
377
-            );
378
-            return false;
379
-        }
380
-        // just make sure preview is set on the $message_to_generate (in case client forgot)
381
-        $message_to_generate->set_preview(true);
382
-        $this->_init_queue_and_generator();
383
-        $this->queue_for_generation($message_to_generate, $test_send);
384
-        $generated_queue = $this->_generator->generate(false);
385
-        if ($generated_queue->execute(false)) {
386
-            // the first queue item should be the preview
387
-            $generated_queue->get_message_repository()->rewind();
388
-            if ($generated_queue->get_message_repository()->valid()) {
389
-                return $generated_queue;
390
-            }
391
-        }
392
-        return false;
393
-    }
394
-
395
-
396
-    /**
397
-     * This queues for sending.
398
-     * The messenger send now method is also verified to see if sending immediately is requested.
399
-     * otherwise its just saved to the queue.
400
-     *
401
-     * @param EE_Message_To_Generate $message_to_generate
402
-     * @return bool true or false for success.
403
-     * @throws EE_Error
404
-     * @throws ReflectionException
405
-     */
406
-    public function queue_for_sending(EE_Message_To_Generate $message_to_generate)
407
-    {
408
-        if (! $message_to_generate->valid()) {
409
-            return false;
410
-        }
411
-        $this->_init_queue_and_generator();
412
-        $message = $message_to_generate->get_EE_Message();
413
-        $this->_queue->add($message);
414
-        if ($message->send_now()) {
415
-            $this->_queue->execute(false);
416
-        } else {
417
-            $this->_queue->save();
418
-        }
419
-        return true;
420
-    }
421
-
422
-
423
-    /**
424
-     * This generates and sends from the given EE_Message_To_Generate class immediately.
425
-     *
426
-     * @param EE_Message_To_Generate $message_to_generate
427
-     * @return EE_Messages_Queue | null
428
-     * @throws EE_Error
429
-     * @throws ReflectionException
430
-     */
431
-    public function generate_and_send_now(EE_Message_To_Generate $message_to_generate)
432
-    {
433
-        if (! $message_to_generate->valid()) {
434
-            return null;
435
-        }
436
-        // is there supposed to be a sending messenger for this message?
437
-        if ($message_to_generate instanceof EEI_Has_Sending_Messenger) {
438
-            // make sure it's valid, but if it's not,
439
-            // then set the value of $sending_messenger to an EE_Error object
440
-            // so that downstream code can easily see that things went wrong.
441
-            $sending_messenger = $message_to_generate->sending_messenger() instanceof EE_messenger
442
-                ? $message_to_generate->sending_messenger()
443
-                : new EE_Error(
444
-                    esc_html__(
445
-                        'There was a specific sending messenger requested for the send action, but it was either invalid or not active at time of sending.',
446
-                        'event_espresso'
447
-                    )
448
-                );
449
-        } else {
450
-            $sending_messenger = null;
451
-        }
452
-
453
-        if ($message_to_generate->get_EE_Message()->STS_ID() === EEM_Message::status_idle) {
454
-            $this->_init_queue_and_generator();
455
-            $this->_queue->add($message_to_generate->get_EE_Message());
456
-            $this->_queue->execute(false, $sending_messenger);
457
-            return $this->_queue;
458
-        } elseif ($message_to_generate->get_EE_Message()->STS_ID() === EEM_Message::status_incomplete) {
459
-            $generated_queue = $this->generate_and_return([$message_to_generate]);
460
-            $generated_queue->execute(false, $sending_messenger);
461
-            return $generated_queue;
462
-        }
463
-        return null;
464
-    }
465
-
466
-
467
-    /**
468
-     * Creates mtg objects for all active messengers and queues for generation.
469
-     * This method also calls the execute by priority method on the queue which will optionally kick off a new
470
-     * non-blocking request to complete the action if the priority for the message requires immediate action.
471
-     *
472
-     * @param string $message_type
473
-     * @param mixed  $data    The data being used for generation.
474
-     * @param bool   $persist Whether to persist the queued messages to the db or not.
475
-     * @throws EE_Error
476
-     * @throws ReflectionException
477
-     */
478
-    public function generate_for_all_active_messengers($message_type, $data, $persist = true)
479
-    {
480
-        $messages_to_generate = $this->setup_mtgs_for_all_active_messengers($message_type, $data);
481
-        if ($persist) {
482
-            $this->batch_queue_for_generation_and_persist($messages_to_generate);
483
-            $this->_queue->initiate_request_by_priority();
484
-        } else {
485
-            $this->batch_queue_for_generation_no_persist($messages_to_generate);
486
-        }
487
-    }
488
-
489
-
490
-    /**
491
-     * This simply loops through all active messengers and takes care of setting up the
492
-     * EE_Message_To_Generate objects.
493
-     *
494
-     * @param $message_type
495
-     * @param $data
496
-     *
497
-     * @return EE_Message_To_Generate[]
498
-     */
499
-    public function setup_mtgs_for_all_active_messengers($message_type, $data)
500
-    {
501
-        $messages_to_generate = [];
502
-        foreach ($this->_message_resource_manager->active_messengers() as $messenger_slug => $messenger_object) {
503
-            $message_to_generate = new EE_Message_To_Generate($messenger_slug, $message_type, $data);
504
-            if ($message_to_generate->valid()) {
505
-                $messages_to_generate[] = $message_to_generate;
506
-            }
507
-        }
508
-        return $messages_to_generate;
509
-    }
510
-
511
-
512
-    /**
513
-     * This accepts an array of EE_Message::MSG_ID values
514
-     * and will use that to retrieve the objects from the database and send.
515
-     *
516
-     * @param array $message_ids
517
-     * @throws EE_Error
518
-     * @throws ReflectionException
519
-     */
520
-    public function setup_messages_from_ids_and_send($message_ids)
521
-    {
522
-        $this->_init_queue_and_generator();
523
-        $messages = EEM_Message::instance()->get_all(
524
-            [
525
-                 [
526
-                     'MSG_ID' => ['IN', $message_ids],
527
-                     'STS_ID' => [
528
-                         'IN',
529
-                         array_merge(
530
-                             EEM_Message::instance()->stati_indicating_sent(),
531
-                             [EEM_Message::status_retry]
532
-                         ),
533
-                     ],
534
-                 ],
535
-             ]
536
-        );
537
-        // set the Messages to resend.
538
-        foreach ($messages as $message) {
539
-            if ($message instanceof EE_Message) {
540
-                $message->set_STS_ID(EEM_Message::status_resend);
541
-                $this->_queue->add($message);
542
-            }
543
-        }
544
-
545
-        $this->_queue->initiate_request_by_priority('send');
546
-    }
547
-
548
-
549
-    /**
550
-     * This method checks for registration IDs in the request via the given key and creates the messages to generate
551
-     * objects from them, then returns the array of messages to generate objects.
552
-     * Note, this sets up registrations for the registration family of message types.
553
-     *
554
-     * @param string $registration_ids_key This is used to indicate what represents the registration ids in the request.
555
-     *
556
-     * @return EE_Message_To_Generate[]|bool
557
-     * @throws EE_Error
558
-     */
559
-    public function setup_messages_to_generate_from_registration_ids_in_request($registration_ids_key = '_REG_ID')
560
-    {
561
-        /** @var RequestInterface $request */
562
-        $request      = LoaderFactory::getLoader()->getShared(RequestInterface::class);
563
-        $regs_to_send = [];
564
-        $regIDs       = $request->getRequestParam($registration_ids_key, [], 'int', true);
565
-        if (empty($regIDs)) {
566
-            EE_Error::add_error(
567
-                esc_html__('Something went wrong because we\'re missing the registration ID', 'event_espresso'),
568
-                __FILE__,
569
-                __FUNCTION__,
570
-                __LINE__
571
-            );
572
-            return false;
573
-        }
574
-
575
-        // make sure is an array
576
-        $regIDs = is_array($regIDs) ? $regIDs : [$regIDs];
577
-
578
-        foreach ($regIDs as $regID) {
579
-            $reg = EEM_Registration::instance()->get_one_by_ID($regID);
580
-            if (! $reg instanceof EE_Registration) {
581
-                EE_Error::add_error(
582
-                    sprintf(
583
-                        esc_html__(
584
-                            'Unable to retrieve a registration object for the given reg id (%s)',
585
-                            'event_espresso'
586
-                        ),
587
-                        $regID
588
-                    )
589
-                );
590
-                return false;
591
-            }
592
-            $regs_to_send[ $reg->transaction_ID() ][ $reg->status_ID() ][] = $reg;
593
-        }
594
-
595
-        $messages_to_generate = [];
596
-
597
-        foreach ($regs_to_send as $status_group) {
598
-            foreach ($status_group as $status_id => $registrations) {
599
-                $message_type = EEH_MSG_Template::convert_reg_status_to_message_type($status_id);
600
-                if (! $message_type) {
601
-                    continue;
602
-                }
603
-                $messages_to_generate = array_merge(
604
-                    $messages_to_generate,
605
-                    $this->setup_mtgs_for_all_active_messengers(
606
-                        $message_type,
607
-                        [$registrations, $status_id]
608
-                    )
609
-                );
610
-            }
611
-        }
612
-
613
-        return $messages_to_generate;
614
-    }
17
+	/**
18
+	 * @type EE_Message_Resource_Manager $_message_resource_manager
19
+	 */
20
+	protected $_message_resource_manager;
21
+
22
+	/**
23
+	 * @type EE_Messages_Queue
24
+	 */
25
+	protected $_queue;
26
+
27
+	/**
28
+	 * @type  EE_Messages_Generator
29
+	 */
30
+	protected $_generator;
31
+
32
+
33
+	/**
34
+	 * constructor
35
+	 *
36
+	 * @param EE_Message_Resource_Manager $message_resource_manager
37
+	 */
38
+	public function __construct(EE_Message_Resource_Manager $message_resource_manager)
39
+	{
40
+		$this->_message_resource_manager = $message_resource_manager;
41
+		$this->_init_queue_and_generator();
42
+	}
43
+
44
+
45
+	/**
46
+	 * This method sets (or resets) the various properties for use.
47
+	 *
48
+	 * - $_queue = holds the messages queue
49
+	 * - $_generator = holds the messages generator
50
+	 */
51
+	protected function _init_queue_and_generator()
52
+	{
53
+		$this->_generator = EE_Registry::factory('EE_Messages_Generator');
54
+		$this->_queue     = $this->_generator->generation_queue();
55
+	}
56
+
57
+
58
+	/**
59
+	 * This returns the current set queue.
60
+	 *
61
+	 * @return EE_Messages_Queue
62
+	 */
63
+	public function get_queue()
64
+	{
65
+		return $this->_queue;
66
+	}
67
+
68
+
69
+	/**
70
+	 * This method can be utilized to process messages from a queue and they will be processed immediately on the same
71
+	 * request. Please note that this method alone does not bypass the usual "locks" for generation/sending (it assumes
72
+	 * client code has already filtered those if necessary).
73
+	 *
74
+	 * @param EE_Messages_Queue $queue_to_process
75
+	 * @return bool  true for success false for error.
76
+	 * @throws EE_Error
77
+	 * @throws ReflectionException
78
+	 */
79
+	public function process_immediately_from_queue(EE_Messages_Queue $queue_to_process)
80
+	{
81
+		$success              = false;
82
+		$messages_to_send     = [];
83
+		$messages_to_generate = [];
84
+		// loop through and setup the various messages from the queue so we know what is being processed
85
+		$queue_to_process->get_message_repository()->rewind();
86
+		foreach ($queue_to_process->get_message_repository() as $message) {
87
+			if ($message->STS_ID() === EEM_Message::status_incomplete) {
88
+				$messages_to_generate[] = $message;
89
+				continue;
90
+			}
91
+
92
+			if (in_array($message->STS_ID(), EEM_Message::instance()->stati_indicating_to_send())) {
93
+				$messages_to_send[] = $message;
94
+			}
95
+		}
96
+
97
+		// do generation/sends
98
+		if ($messages_to_generate) {
99
+			$success = $this->batch_generate_from_queue($messages_to_generate, true);
100
+		}
101
+
102
+		if ($messages_to_send) {
103
+			$sent = $this->batch_send_from_queue($messages_to_send, true);
104
+			// if there was messages to generate and it failed, then we override any success value for the sending process
105
+			// otherwise we just use the return from batch send.  The intent is that there is a simple response for success/fail.
106
+			// Either everything was successful or we consider it a fail.  To be clear, this is a limitation of doing
107
+			// all messages processing on the same request.
108
+			$success = $messages_to_generate && ! $success ? false : $sent;
109
+		}
110
+		return $success;
111
+	}
112
+
113
+
114
+	/**
115
+	 * Calls the EE_Messages_Queue::get_batch_to_generate() method and sends to EE_Messages_Generator.
116
+	 *
117
+	 * @param EE_Message[] $messages    Array of EE_Message objects (optional) to build the queue with.
118
+	 * @param bool         $clear_queue Whether to ensure a fresh queue or not.
119
+	 *
120
+	 * @return bool|EE_Messages_Queue return false if nothing generated.  This returns a new EE_Message_Queue with
121
+	 *                                   generated messages.
122
+	 * @throws EE_Error
123
+	 * @throws ReflectionException
124
+	 */
125
+	public function batch_generate_from_queue($messages = [], $clear_queue = false)
126
+	{
127
+		if ($this->_build_queue_for_generation($messages, $clear_queue)) {
128
+			$new_queue = $this->_generator->generate();
129
+			if ($new_queue instanceof EE_Messages_Queue) {
130
+				// unlock queue
131
+				$this->_queue->unlock_queue();
132
+				$new_queue->initiate_request_by_priority('send');
133
+				return $new_queue;
134
+			}
135
+		}
136
+		$this->_queue->unlock_queue();
137
+		return false;
138
+	}
139
+
140
+
141
+	/**
142
+	 * This method preps a queue for generation.
143
+	 *
144
+	 * @param EE_Message[] $messages    Array of EE_Message objects to build the queue with
145
+	 *
146
+	 * @param bool         $clear_queue This indicates whether the existing queue should be dumped or not.
147
+	 *
148
+	 * @return bool true means queue prepped, false means there was a lock so no generation please.
149
+	 * @throws EE_Error
150
+	 * @throws ReflectionException
151
+	 * @since    4.9.0
152
+	 *
153
+	 */
154
+	protected function _build_queue_for_generation($messages = [], $clear_queue = false)
155
+	{
156
+
157
+		if ($clear_queue) {
158
+			$this->_init_queue_and_generator();
159
+		}
160
+
161
+		if ($messages) {
162
+			// if generation is locked then get out now because that means processing is already happening.
163
+			if ($this->_queue->is_locked()) {
164
+				return false;
165
+			}
166
+
167
+			$this->_queue->lock_queue();
168
+			$messages = is_array($messages) ? $messages : [$messages];
169
+			foreach ($messages as $message) {
170
+				if ($message instanceof EE_Message) {
171
+					$data = $message->all_extra_meta_array();
172
+					$this->_queue->add($message, $data);
173
+				}
174
+			}
175
+			return true;
176
+		} else {
177
+			return $this->_queue->get_batch_to_generate();
178
+		}
179
+	}
180
+
181
+
182
+	/**
183
+	 * This method preps a queue for sending.
184
+	 *
185
+	 * @param EE_Message[] $messages
186
+	 * @param bool         $clear_queue Used to indicate whether to start with a fresh queue or not.
187
+	 *
188
+	 * @return bool true means queue prepped, false means there was a lock so no queue prepped.
189
+	 */
190
+	protected function _build_queue_for_sending($messages, $clear_queue = false)
191
+	{
192
+		// if sending is locked then get out now because that means processing is already happening.
193
+		if ($this->_queue->is_locked(EE_Messages_Queue::action_sending)) {
194
+			return false;
195
+		}
196
+
197
+		$this->_queue->lock_queue(EE_Messages_Queue::action_sending);
198
+
199
+		if ($clear_queue) {
200
+			$this->_init_queue_and_generator();
201
+		}
202
+
203
+		$messages = is_array($messages) ? $messages : [$messages];
204
+
205
+		foreach ($messages as $message) {
206
+			$this->_queue->add($message);
207
+		}
208
+		return true;
209
+	}
210
+
211
+
212
+	/**
213
+	 * Calls the EE_Message_Queue::get_to_send_batch_and_send() method and then immediately just calls
214
+	 * EE_Message_Queue::execute() to iterate and send unsent messages.
215
+	 *
216
+	 * @param EE_Message[] $messages    If an array of messages is sent in then use it.
217
+	 *
218
+	 * @param bool         $clear_queue Whether to initialize a new queue or keep the existing one.
219
+	 *
220
+	 * @return EE_Messages_Queue
221
+	 * @throws EE_Error
222
+	 * @throws ReflectionException
223
+	 */
224
+	public function batch_send_from_queue($messages = [], $clear_queue = false)
225
+	{
226
+
227
+		if ($messages && $this->_build_queue_for_sending($messages, $clear_queue)) {
228
+			$this->_queue->execute();
229
+			$this->_queue->unlock_queue(EE_Messages_Queue::action_sending);
230
+		} else {
231
+			// get messages to send and execute.
232
+			$this->_queue->get_to_send_batch_and_send();
233
+		}
234
+		// note: callers can use the EE_Messages_Queue::count_STS_in_queue() method to find out if there were any failed
235
+		// messages in the queue and decide how to handle at that point.
236
+		return $this->_queue;
237
+	}
238
+
239
+
240
+	/**
241
+	 * This immediately generates messages using the given array of EE_Message_To_Generate objects and returns the
242
+	 * EE_Message_Queue with the generated messages for the caller to work with.  Note, this does NOT save the generated
243
+	 * messages in the queue, leaving it up to the caller to do so.
244
+	 *
245
+	 * @param EE_Message_To_Generate[] $messages_to_generate
246
+	 * @return EE_Messages_Queue
247
+	 * @throws EE_Error
248
+	 * @throws ReflectionException
249
+	 */
250
+	public function generate_and_return($messages_to_generate)
251
+	{
252
+		$this->_init_queue_and_generator();
253
+		$this->_queue_for_generation_loop($messages_to_generate);
254
+		return $this->_generator->generate(false);
255
+	}
256
+
257
+
258
+	/**
259
+	 * Executes the generator generate method on the current internal queue, and returns the generated queue.
260
+	 *
261
+	 * @param bool $persist Indicate whether to instruct the generator to persist the generated queue (true) or not
262
+	 *                      (false).
263
+	 * @return EE_Messages_Queue
264
+	 * @throws EE_Error
265
+	 * @throws ReflectionException
266
+	 */
267
+	public function generate_queue($persist = true)
268
+	{
269
+		return $this->_generator->generate($persist);
270
+	}
271
+
272
+
273
+	/**
274
+	 * Queue for generation.  Note this does NOT persist to the db.  Client code should call
275
+	 * get_message_repository()->save() if desire to persist.  This method is provided to client code to decide what it
276
+	 * wants to do with queued messages for generation.
277
+	 *
278
+	 * @param EE_Message_To_Generate $message_to_generate
279
+	 * @param bool                   $test_send Whether this item is for a test send or not.
280
+	 * @return void
281
+	 */
282
+	public function queue_for_generation(EE_Message_To_Generate $message_to_generate, $test_send = false)
283
+	{
284
+		if ($message_to_generate->valid()) {
285
+			if (! $this->_generator->create_and_add_message_to_queue($message_to_generate, $test_send)) {
286
+				throw new RuntimeException(
287
+					esc_html__('Message failed to generate', 'event_espresso')
288
+				);
289
+			}
290
+		}
291
+	}
292
+
293
+
294
+	/**
295
+	 * This receives an array of EE_Message_To_Generate objects, converts them to EE_Message adds them to the
296
+	 * generation queue and then persists to storage.
297
+	 *
298
+	 * @param EE_Message_To_Generate[] $messages_to_generate
299
+	 */
300
+	public function batch_queue_for_generation_and_persist($messages_to_generate)
301
+	{
302
+		$this->_init_queue_and_generator();
303
+		$this->_queue_for_generation_loop($messages_to_generate);
304
+		$this->_queue->save();
305
+	}
306
+
307
+
308
+	/**
309
+	 * This receives an array of EE_Message_To_Generate objects, converts them to EE_Message and adds them to the
310
+	 * generation queue.  Does NOT persist to storage (unless there is an error. Client code can retrieve the generated
311
+	 * queue by calling EEM_Messages_Processor::get_queue()
312
+	 *
313
+	 * @param EE_Message_To_Generate[] $messages_to_generate
314
+	 */
315
+	public function batch_queue_for_generation_no_persist($messages_to_generate)
316
+	{
317
+		$this->_init_queue_and_generator();
318
+		$this->_queue_for_generation_loop($messages_to_generate);
319
+	}
320
+
321
+
322
+	/**
323
+	 * Simply loops through the given array of EE_Message_To_Generate objects and adds them to the _queue as EE_Message
324
+	 * objects.
325
+	 *
326
+	 * @param EE_Message_To_Generate[] $messages_to_generate
327
+	 */
328
+	protected function _queue_for_generation_loop($messages_to_generate)
329
+	{
330
+		// make sure is in an array.
331
+		if (! is_array($messages_to_generate)) {
332
+			$messages_to_generate = [$messages_to_generate];
333
+		}
334
+
335
+		foreach ($messages_to_generate as $message_to_generate) {
336
+			if ($message_to_generate instanceof EE_Message_To_Generate && $message_to_generate->valid()) {
337
+				$this->queue_for_generation($message_to_generate);
338
+			}
339
+		}
340
+	}
341
+
342
+
343
+	/**
344
+	 * Receives an array of EE_Message_To_Generate objects and generates the EE_Message objects, then persists (so its
345
+	 * queued for sending).
346
+	 *
347
+	 * @param EE_Message_To_Generate[]
348
+	 * @return EE_Messages_Queue
349
+	 * @throws EE_Error
350
+	 * @throws ReflectionException
351
+	 */
352
+	public function generate_and_queue_for_sending($messages_to_generate)
353
+	{
354
+		$this->_init_queue_and_generator();
355
+		$this->_queue_for_generation_loop($messages_to_generate);
356
+		return $this->_generator->generate();
357
+	}
358
+
359
+
360
+	/**
361
+	 * Generate for preview and execute right away.
362
+	 *
363
+	 * @param EE_Message_To_Generate $message_to_generate
364
+	 * @param bool                   $test_send Whether this is a test send or not.
365
+	 * @return  EE_Messages_Queue | bool   false if unable to generate otherwise the generated queue.
366
+	 * @throws EE_Error
367
+	 * @throws ReflectionException
368
+	 */
369
+	public function generate_for_preview(EE_Message_To_Generate $message_to_generate, $test_send = false)
370
+	{
371
+		if (! $message_to_generate->valid()) {
372
+			EE_Error::add_error(
373
+				esc_html__('Unable to generate preview because of invalid data', 'event_espresso'),
374
+				__FILE__,
375
+				__FUNCTION__,
376
+				__LINE__
377
+			);
378
+			return false;
379
+		}
380
+		// just make sure preview is set on the $message_to_generate (in case client forgot)
381
+		$message_to_generate->set_preview(true);
382
+		$this->_init_queue_and_generator();
383
+		$this->queue_for_generation($message_to_generate, $test_send);
384
+		$generated_queue = $this->_generator->generate(false);
385
+		if ($generated_queue->execute(false)) {
386
+			// the first queue item should be the preview
387
+			$generated_queue->get_message_repository()->rewind();
388
+			if ($generated_queue->get_message_repository()->valid()) {
389
+				return $generated_queue;
390
+			}
391
+		}
392
+		return false;
393
+	}
394
+
395
+
396
+	/**
397
+	 * This queues for sending.
398
+	 * The messenger send now method is also verified to see if sending immediately is requested.
399
+	 * otherwise its just saved to the queue.
400
+	 *
401
+	 * @param EE_Message_To_Generate $message_to_generate
402
+	 * @return bool true or false for success.
403
+	 * @throws EE_Error
404
+	 * @throws ReflectionException
405
+	 */
406
+	public function queue_for_sending(EE_Message_To_Generate $message_to_generate)
407
+	{
408
+		if (! $message_to_generate->valid()) {
409
+			return false;
410
+		}
411
+		$this->_init_queue_and_generator();
412
+		$message = $message_to_generate->get_EE_Message();
413
+		$this->_queue->add($message);
414
+		if ($message->send_now()) {
415
+			$this->_queue->execute(false);
416
+		} else {
417
+			$this->_queue->save();
418
+		}
419
+		return true;
420
+	}
421
+
422
+
423
+	/**
424
+	 * This generates and sends from the given EE_Message_To_Generate class immediately.
425
+	 *
426
+	 * @param EE_Message_To_Generate $message_to_generate
427
+	 * @return EE_Messages_Queue | null
428
+	 * @throws EE_Error
429
+	 * @throws ReflectionException
430
+	 */
431
+	public function generate_and_send_now(EE_Message_To_Generate $message_to_generate)
432
+	{
433
+		if (! $message_to_generate->valid()) {
434
+			return null;
435
+		}
436
+		// is there supposed to be a sending messenger for this message?
437
+		if ($message_to_generate instanceof EEI_Has_Sending_Messenger) {
438
+			// make sure it's valid, but if it's not,
439
+			// then set the value of $sending_messenger to an EE_Error object
440
+			// so that downstream code can easily see that things went wrong.
441
+			$sending_messenger = $message_to_generate->sending_messenger() instanceof EE_messenger
442
+				? $message_to_generate->sending_messenger()
443
+				: new EE_Error(
444
+					esc_html__(
445
+						'There was a specific sending messenger requested for the send action, but it was either invalid or not active at time of sending.',
446
+						'event_espresso'
447
+					)
448
+				);
449
+		} else {
450
+			$sending_messenger = null;
451
+		}
452
+
453
+		if ($message_to_generate->get_EE_Message()->STS_ID() === EEM_Message::status_idle) {
454
+			$this->_init_queue_and_generator();
455
+			$this->_queue->add($message_to_generate->get_EE_Message());
456
+			$this->_queue->execute(false, $sending_messenger);
457
+			return $this->_queue;
458
+		} elseif ($message_to_generate->get_EE_Message()->STS_ID() === EEM_Message::status_incomplete) {
459
+			$generated_queue = $this->generate_and_return([$message_to_generate]);
460
+			$generated_queue->execute(false, $sending_messenger);
461
+			return $generated_queue;
462
+		}
463
+		return null;
464
+	}
465
+
466
+
467
+	/**
468
+	 * Creates mtg objects for all active messengers and queues for generation.
469
+	 * This method also calls the execute by priority method on the queue which will optionally kick off a new
470
+	 * non-blocking request to complete the action if the priority for the message requires immediate action.
471
+	 *
472
+	 * @param string $message_type
473
+	 * @param mixed  $data    The data being used for generation.
474
+	 * @param bool   $persist Whether to persist the queued messages to the db or not.
475
+	 * @throws EE_Error
476
+	 * @throws ReflectionException
477
+	 */
478
+	public function generate_for_all_active_messengers($message_type, $data, $persist = true)
479
+	{
480
+		$messages_to_generate = $this->setup_mtgs_for_all_active_messengers($message_type, $data);
481
+		if ($persist) {
482
+			$this->batch_queue_for_generation_and_persist($messages_to_generate);
483
+			$this->_queue->initiate_request_by_priority();
484
+		} else {
485
+			$this->batch_queue_for_generation_no_persist($messages_to_generate);
486
+		}
487
+	}
488
+
489
+
490
+	/**
491
+	 * This simply loops through all active messengers and takes care of setting up the
492
+	 * EE_Message_To_Generate objects.
493
+	 *
494
+	 * @param $message_type
495
+	 * @param $data
496
+	 *
497
+	 * @return EE_Message_To_Generate[]
498
+	 */
499
+	public function setup_mtgs_for_all_active_messengers($message_type, $data)
500
+	{
501
+		$messages_to_generate = [];
502
+		foreach ($this->_message_resource_manager->active_messengers() as $messenger_slug => $messenger_object) {
503
+			$message_to_generate = new EE_Message_To_Generate($messenger_slug, $message_type, $data);
504
+			if ($message_to_generate->valid()) {
505
+				$messages_to_generate[] = $message_to_generate;
506
+			}
507
+		}
508
+		return $messages_to_generate;
509
+	}
510
+
511
+
512
+	/**
513
+	 * This accepts an array of EE_Message::MSG_ID values
514
+	 * and will use that to retrieve the objects from the database and send.
515
+	 *
516
+	 * @param array $message_ids
517
+	 * @throws EE_Error
518
+	 * @throws ReflectionException
519
+	 */
520
+	public function setup_messages_from_ids_and_send($message_ids)
521
+	{
522
+		$this->_init_queue_and_generator();
523
+		$messages = EEM_Message::instance()->get_all(
524
+			[
525
+				 [
526
+					 'MSG_ID' => ['IN', $message_ids],
527
+					 'STS_ID' => [
528
+						 'IN',
529
+						 array_merge(
530
+							 EEM_Message::instance()->stati_indicating_sent(),
531
+							 [EEM_Message::status_retry]
532
+						 ),
533
+					 ],
534
+				 ],
535
+			 ]
536
+		);
537
+		// set the Messages to resend.
538
+		foreach ($messages as $message) {
539
+			if ($message instanceof EE_Message) {
540
+				$message->set_STS_ID(EEM_Message::status_resend);
541
+				$this->_queue->add($message);
542
+			}
543
+		}
544
+
545
+		$this->_queue->initiate_request_by_priority('send');
546
+	}
547
+
548
+
549
+	/**
550
+	 * This method checks for registration IDs in the request via the given key and creates the messages to generate
551
+	 * objects from them, then returns the array of messages to generate objects.
552
+	 * Note, this sets up registrations for the registration family of message types.
553
+	 *
554
+	 * @param string $registration_ids_key This is used to indicate what represents the registration ids in the request.
555
+	 *
556
+	 * @return EE_Message_To_Generate[]|bool
557
+	 * @throws EE_Error
558
+	 */
559
+	public function setup_messages_to_generate_from_registration_ids_in_request($registration_ids_key = '_REG_ID')
560
+	{
561
+		/** @var RequestInterface $request */
562
+		$request      = LoaderFactory::getLoader()->getShared(RequestInterface::class);
563
+		$regs_to_send = [];
564
+		$regIDs       = $request->getRequestParam($registration_ids_key, [], 'int', true);
565
+		if (empty($regIDs)) {
566
+			EE_Error::add_error(
567
+				esc_html__('Something went wrong because we\'re missing the registration ID', 'event_espresso'),
568
+				__FILE__,
569
+				__FUNCTION__,
570
+				__LINE__
571
+			);
572
+			return false;
573
+		}
574
+
575
+		// make sure is an array
576
+		$regIDs = is_array($regIDs) ? $regIDs : [$regIDs];
577
+
578
+		foreach ($regIDs as $regID) {
579
+			$reg = EEM_Registration::instance()->get_one_by_ID($regID);
580
+			if (! $reg instanceof EE_Registration) {
581
+				EE_Error::add_error(
582
+					sprintf(
583
+						esc_html__(
584
+							'Unable to retrieve a registration object for the given reg id (%s)',
585
+							'event_espresso'
586
+						),
587
+						$regID
588
+					)
589
+				);
590
+				return false;
591
+			}
592
+			$regs_to_send[ $reg->transaction_ID() ][ $reg->status_ID() ][] = $reg;
593
+		}
594
+
595
+		$messages_to_generate = [];
596
+
597
+		foreach ($regs_to_send as $status_group) {
598
+			foreach ($status_group as $status_id => $registrations) {
599
+				$message_type = EEH_MSG_Template::convert_reg_status_to_message_type($status_id);
600
+				if (! $message_type) {
601
+					continue;
602
+				}
603
+				$messages_to_generate = array_merge(
604
+					$messages_to_generate,
605
+					$this->setup_mtgs_for_all_active_messengers(
606
+						$message_type,
607
+						[$registrations, $status_id]
608
+					)
609
+				);
610
+			}
611
+		}
612
+
613
+		return $messages_to_generate;
614
+	}
615 615
 }
Please login to merge, or discard this patch.
core/libraries/messages/EE_Messages_Generator.lib.php 2 patches
Indentation   +987 added lines, -987 removed lines patch added patch discarded remove patch
@@ -15,992 +15,992 @@
 block discarded – undo
15 15
  */
16 16
 class EE_Messages_Generator
17 17
 {
18
-    /**
19
-     * @type EE_Messages_Data_Handler_Collection
20
-     */
21
-    protected $_data_handler_collection;
22
-
23
-    /**
24
-     * @type  EE_Message_Template_Group_Collection
25
-     */
26
-    protected $_template_collection;
27
-
28
-    /**
29
-     * This will hold the data handler for the current EE_Message being generated.
30
-     *
31
-     * @type EE_Messages_incoming_data
32
-     */
33
-    protected $_current_data_handler;
34
-
35
-    /**
36
-     * This holds the EE_Messages_Queue that contains the messages to generate.
37
-     *
38
-     * @type EE_Messages_Queue
39
-     */
40
-    protected $_generation_queue;
41
-
42
-    /**
43
-     * This holds the EE_Messages_Queue that will store the generated EE_Message objects.
44
-     *
45
-     * @type EE_Messages_Queue
46
-     */
47
-    protected $_ready_queue;
48
-
49
-    /**
50
-     * This is a container for any error messages that get created through the generation
51
-     * process.
52
-     *
53
-     * @type array
54
-     */
55
-    protected $_error_msg = [];
56
-
57
-    /**
58
-     * Flag used to set when the current EE_Message in the generation queue has been verified.
59
-     *
60
-     * @type bool
61
-     */
62
-    protected $_verified = false;
63
-
64
-    /**
65
-     * This will hold the current messenger object corresponding with the current EE_Message in the generation queue.
66
-     *
67
-     * @type EE_messenger
68
-     */
69
-    protected $_current_messenger;
70
-
71
-    /**
72
-     * This will hold the current message type object corresponding with the current EE_Message in the generation queue.
73
-     *
74
-     * @type EE_message_type
75
-     */
76
-    protected $_current_message_type;
77
-
78
-    /**
79
-     * @type EEH_Parse_Shortcodes
80
-     */
81
-    protected $_shortcode_parser;
82
-
83
-
84
-    /**
85
-     * @param EE_Messages_Queue                    $generation_queue
86
-     * @param EE_Messages_Queue                    $ready_queue
87
-     * @param EE_Messages_Data_Handler_Collection  $data_handler_collection
88
-     * @param EE_Message_Template_Group_Collection $template_collection
89
-     * @param EEH_Parse_Shortcodes                 $shortcode_parser
90
-     */
91
-    public function __construct(
92
-        EE_Messages_Queue $generation_queue,
93
-        EE_Messages_Queue $ready_queue,
94
-        EE_Messages_Data_Handler_Collection $data_handler_collection,
95
-        EE_Message_Template_Group_Collection $template_collection,
96
-        EEH_Parse_Shortcodes $shortcode_parser
97
-    ) {
98
-        $this->_generation_queue        = $generation_queue;
99
-        $this->_ready_queue             = $ready_queue;
100
-        $this->_data_handler_collection = $data_handler_collection;
101
-        $this->_template_collection     = $template_collection;
102
-        $this->_shortcode_parser        = $shortcode_parser;
103
-    }
104
-
105
-
106
-    /**
107
-     * @return EE_Messages_Queue
108
-     */
109
-    public function generation_queue()
110
-    {
111
-        return $this->_generation_queue;
112
-    }
113
-
114
-
115
-    /**
116
-     *  This iterates through the provided queue and generates the EE_Message objects.
117
-     *  When iterating through the queue, the queued item that served as the base for generating other EE_Message
118
-     *  objects gets removed and the new EE_Message objects get added to a NEW queue.  The NEW queue is then returned
119
-     *  for the caller to decide what to do with it.
120
-     *
121
-     * @param bool $save Whether to save the EE_Message objects in the new queue or just return.
122
-     * @return EE_Messages_Queue The new queue for holding generated EE_Message objects.
123
-     * @throws EE_Error
124
-     * @throws InvalidArgumentException
125
-     * @throws InvalidDataTypeException
126
-     * @throws InvalidInterfaceException
127
-     * @throws ReflectionException
128
-     */
129
-    public function generate($save = true)
130
-    {
131
-        // iterate through the messages in the queue, generate, and add to new queue.
132
-        $this->_generation_queue->get_message_repository()->rewind();
133
-
134
-        while ($this->_generation_queue->get_message_repository()->valid()) {
135
-            // reset "current" properties
136
-            $this->_reset_current_properties();
137
-
138
-            $msg = $this->_generation_queue->get_message_repository()->current();
139
-
140
-            /**
141
-             * need to get the next object and capture it for setting manually after deletes.  The reason is that when
142
-             * an object is removed from the repo then valid for the next object will fail.
143
-             */
144
-            $this->_generation_queue->get_message_repository()->next();
145
-            $next_msg = $this->_generation_queue->get_message_repository()->current();
146
-            // restore pointer to current item
147
-            $this->_generation_queue->get_message_repository()->set_current($msg);
148
-
149
-            // skip and delete if the current $msg is NOT incomplete (queued for generation)
150
-            if ($msg->STS_ID() !== EEM_Message::status_incomplete) {
151
-                // we keep this item in the db just remove from the repo.
152
-                $this->_generation_queue->get_message_repository()->remove($msg);
153
-                // next item
154
-                $this->_generation_queue->get_message_repository()->set_current($next_msg);
155
-                continue;
156
-            }
157
-
158
-            if ($this->_verify()) {
159
-                // let's get generating!
160
-                $this->_generate();
161
-            }
162
-
163
-            // don't persist debug_only messages if the messages system is not in debug mode.
164
-            if (
165
-                $msg->STS_ID() === EEM_Message::status_debug_only
166
-                && ! EEM_Message::debug()
167
-            ) {
168
-                do_action(
169
-                    'AHEE__EE_Messages_Generator__generate__before_debug_delete',
170
-                    $msg,
171
-                    $this->_error_msg,
172
-                    $this->_current_messenger,
173
-                    $this->_current_message_type,
174
-                    $this->_current_data_handler
175
-                );
176
-                $this->_generation_queue->get_message_repository()->delete();
177
-                $this->_generation_queue->get_message_repository()->set_current($next_msg);
178
-                continue;
179
-            }
180
-
181
-            // if there are error messages then let's set the status and the error message.
182
-            if ($this->_error_msg) {
183
-                // if the status is already debug only, then let's leave it at that.
184
-                if ($msg->STS_ID() !== EEM_Message::status_debug_only) {
185
-                    $msg->set_STS_ID(EEM_Message::status_failed);
186
-                }
187
-                do_action(
188
-                    'AHEE__EE_Messages_Generator__generate__processing_failed_message',
189
-                    $msg,
190
-                    $this->_error_msg,
191
-                    $this->_current_messenger,
192
-                    $this->_current_message_type,
193
-                    $this->_current_data_handler
194
-                );
195
-                $msg->set_error_message(
196
-                    esc_html__('Message failed to generate for the following reasons: ', 'event_espresso')
197
-                    . "\n"
198
-                    . implode("\n", $this->_error_msg)
199
-                );
200
-                $msg->set_modified(time());
201
-            } else {
202
-                do_action(
203
-                    'AHEE__EE_Messages_Generator__generate__before_successful_generated_message_delete',
204
-                    $msg,
205
-                    $this->_error_msg,
206
-                    $this->_current_messenger,
207
-                    $this->_current_message_type,
208
-                    $this->_current_data_handler
209
-                );
210
-                // remove from db
211
-                $this->_generation_queue->get_message_repository()->delete();
212
-            }
213
-            // next item
214
-            $this->_generation_queue->get_message_repository()->set_current($next_msg);
215
-        }
216
-
217
-        // generation queue is ALWAYS saved to record any errors in the generation process.
218
-        $this->_generation_queue->save();
219
-
220
-        /**
221
-         * save _ready_queue if flag set.
222
-         * Note: The EE_Message objects have values set via the EE_Base_Class::set_field_or_extra_meta() method.  This
223
-         * means if a field was added that is not a valid database column.  The EE_Message was already saved to the db
224
-         * so a EE_Extra_Meta entry could be created and attached to the EE_Message.  In those cases the save flag is
225
-         * irrelevant.
226
-         */
227
-        if ($save) {
228
-            $this->_ready_queue->save();
229
-        }
230
-
231
-        // final reset of properties
232
-        $this->_reset_current_properties();
233
-
234
-        return $this->_ready_queue;
235
-    }
236
-
237
-
238
-    /**
239
-     * This resets all the properties used for holding "current" values corresponding to the current EE_Message object
240
-     * in the generation queue.
241
-     */
242
-    protected function _reset_current_properties()
243
-    {
244
-        $this->_verified = false;
245
-        // make sure any _data value in the current message type is reset
246
-        if ($this->_current_message_type instanceof EE_message_type) {
247
-            $this->_current_message_type->reset_data();
248
-        }
249
-        $this->_current_messenger = $this->_current_message_type = $this->_current_data_handler = null;
250
-    }
251
-
252
-
253
-    /**
254
-     * This proceeds with the actual generation of a message.  By the time this is called, there should already be a
255
-     * $_current_data_handler set and all incoming information should be validated for the current EE_Message in the
256
-     * _generating_queue.
257
-     *
258
-     * @return bool Whether the message was successfully generated or not.
259
-     * @throws EE_Error
260
-     * @throws InvalidArgumentException
261
-     * @throws InvalidDataTypeException
262
-     * @throws InvalidInterfaceException
263
-     * @throws ReflectionException
264
-     */
265
-    protected function _generate()
266
-    {
267
-        // double check verification has run and that everything is ready to work with (saves us having to validate
268
-        // everything again).
269
-        if (! $this->_verified) {
270
-            return false; // get out because we don't have a valid setup to work with.
271
-        }
272
-
273
-
274
-        try {
275
-            $addressees = $this->_current_message_type->get_addressees(
276
-                $this->_current_data_handler,
277
-                $this->_generation_queue->get_message_repository()->current()->context()
278
-            );
279
-        } catch (EE_Error $e) {
280
-            $this->_error_msg[] = $e->getMessage();
281
-            return false;
282
-        }
283
-
284
-
285
-        // if no addressees then get out because there is nothing to generation (possible bad data).
286
-        if (! $this->_valid_addressees($addressees)) {
287
-            do_action(
288
-                'AHEE__EE_Messages_Generator___generate__invalid_addressees',
289
-                $this->_generation_queue->get_message_repository()->current(),
290
-                $addressees,
291
-                $this->_current_messenger,
292
-                $this->_current_message_type,
293
-                $this->_current_data_handler
294
-            );
295
-            $this->_generation_queue->get_message_repository()->current()->set_STS_ID(
296
-                EEM_Message::status_debug_only
297
-            );
298
-            $this->_error_msg[] = esc_html__(
299
-                'This is not a critical error but an informational notice. Unable to generate messages EE_Messages_Addressee objects.  There were no attendees prepared by the data handler. Sometimes this is because messages only get generated for certain registration statuses. For example, the ticket notice message type only goes to approved registrations.',
300
-                'event_espresso'
301
-            );
302
-            return false;
303
-        }
304
-
305
-        $message_template_group = $this->_get_message_template_group();
306
-
307
-        // in the unlikely event there is no EE_Message_Template_Group available, get out!
308
-        if (! $message_template_group instanceof EE_Message_Template_Group) {
309
-            $this->_error_msg[] = esc_html__(
310
-                'Unable to get the Message Templates for the Message being generated.  No message template group accessible.',
311
-                'event_espresso'
312
-            );
313
-            return false;
314
-        }
315
-
316
-        // get formatted templates for using to parse and setup EE_Message objects.
317
-        $templates = $this->_get_templates($message_template_group);
318
-
319
-
320
-        // setup new EE_Message objects (and add to _ready_queue)
321
-        return $this->_assemble_messages($addressees, $templates, $message_template_group);
322
-    }
323
-
324
-
325
-    /**
326
-     * Retrieves the message template group being used for generating messages.
327
-     * Note: this also utilizes the EE_Message_Template_Group_Collection to avoid having to hit the db multiple times.
328
-     *
329
-     * @return EE_Message_Template_Group|null
330
-     * @throws EE_Error
331
-     * @throws InvalidArgumentException
332
-     * @throws InvalidDataTypeException
333
-     * @throws InvalidInterfaceException
334
-     * @throws ReflectionException
335
-     */
336
-    protected function _get_message_template_group()
337
-    {
338
-        // first see if there is a specific message template group requested
339
-        // (current message in the queue has a specific GRP_ID)
340
-        $message_template_group = $this->_specific_message_template_group_from_queue();
341
-        if ($message_template_group instanceof EE_Message_Template_Group) {
342
-            return $message_template_group;
343
-        }
344
-
345
-        // get event_ids from the data handler so we can check to see
346
-        // if there's already a message template group for them in the collection.
347
-        $event_ids              = $this->_get_event_ids_from_current_data_handler();
348
-        $message_template_group = $this->_template_collection->get_by_key(
349
-            $this->_template_collection->getKey(
350
-                $this->_current_messenger->name,
351
-                $this->_current_message_type->name,
352
-                $event_ids
353
-            )
354
-        );
355
-
356
-        // if we have a message template group then no need to hit the database, just return it.
357
-        if ($message_template_group instanceof EE_Message_Template_Group) {
358
-            return $message_template_group;
359
-        }
360
-
361
-        // get the global group first for this messenger and message type
362
-        // to ensure there is no override set.
363
-        $global_message_template_group =
364
-            $this->_get_global_message_template_group_for_current_messenger_and_message_type();
365
-
366
-        if (
367
-            $global_message_template_group instanceof EE_Message_Template_Group
368
-            && $global_message_template_group->get('MTP_is_override')
369
-        ) {
370
-            return $global_message_template_group;
371
-        }
372
-
373
-        // if we're still here, that means there was no message template group for the events in the collection and
374
-        // the global message template group for the messenger and message type is not set for override.  So next step
375
-        // is to see if there is a common shared custom message template group for this set of events.
376
-        $message_template_group = $this->_get_shared_message_template_for_events($event_ids);
377
-        if ($message_template_group instanceof EE_Message_Template_Group) {
378
-            return $message_template_group;
379
-        }
380
-
381
-        // STILL here?  Okay that means the fallback is to just use the global message template group for this event
382
-        // set. So we'll cache the global group for this event set (so this logic doesn't have to be repeated in this
383
-        // request) and return it.
384
-        if ($global_message_template_group instanceof EE_Message_Template_Group) {
385
-            $this->_template_collection->add(
386
-                $global_message_template_group,
387
-                $event_ids
388
-            );
389
-            return $global_message_template_group;
390
-        }
391
-
392
-        // if we land here that means there's NO active message template group for this set.
393
-        // TODO this will be a good target for some optimization down the road.  Whenever there is no active message
394
-        // template group for a given event set then cache that result so we don't repeat the logic.  However, for now,
395
-        // this should likely bit hit rarely enough that it's not a significant issue.
396
-        return null;
397
-    }
398
-
399
-
400
-    /**
401
-     * This checks the current message in the queue and determines if there is a specific Message Template Group
402
-     * requested for that message.
403
-     *
404
-     * @return EE_Message_Template_Group|null
405
-     * @throws EE_Error
406
-     * @throws InvalidArgumentException
407
-     * @throws InvalidDataTypeException
408
-     * @throws InvalidInterfaceException
409
-     */
410
-    protected function _specific_message_template_group_from_queue()
411
-    {
412
-        // is there a GRP_ID already on the EE_Message object?  If there is, then a specific template has been requested
413
-        // so let's use that.
414
-        $GRP_ID = $this->_generation_queue->get_message_repository()->current()->GRP_ID();
415
-
416
-        if ($GRP_ID) {
417
-            // attempt to retrieve from repo first
418
-            $message_template_group = $this->_template_collection->get_by_ID($GRP_ID);
419
-            if ($message_template_group instanceof EE_Message_Template_Group) {
420
-                return $message_template_group;  // got it!
421
-            }
422
-
423
-            // nope don't have it yet.  Get from DB then add to repo if its not here, then that means the current GRP_ID
424
-            // is not valid, so we'll continue on in the code assuming there's NO GRP_ID.
425
-            $message_template_group = EEM_Message_Template_Group::instance()->get_one_by_ID($GRP_ID);
426
-            if ($message_template_group instanceof EE_Message_Template_Group) {
427
-                $this->_template_collection->add($message_template_group);
428
-                return $message_template_group;
429
-            }
430
-        }
431
-        return null;
432
-    }
433
-
434
-
435
-    /**
436
-     * Returns whether the event ids passed in all share the same message template group for the current message type
437
-     * and messenger.
438
-     *
439
-     * @param array $event_ids
440
-     * @return bool true means they DO share the same message template group, false means they don't.
441
-     * @throws EE_Error
442
-     * @throws InvalidArgumentException
443
-     * @throws InvalidDataTypeException
444
-     * @throws InvalidInterfaceException
445
-     */
446
-    protected function _queue_shares_same_message_template_group_for_events(array $event_ids)
447
-    {
448
-        foreach ($this->_current_data_handler->events as $event) {
449
-            $event_ids[ $event['ID'] ] = $event['ID'];
450
-        }
451
-        $count_of_message_template_groups = EEM_Message_Template_Group::instance()->count(
452
-            [
453
-                [
454
-                    'Event.EVT_ID'     => ['IN', $event_ids],
455
-                    'MTP_messenger'    => $this->_current_messenger->name,
456
-                    'MTP_message_type' => $this->_current_message_type->name,
457
-                ],
458
-            ],
459
-            'GRP_ID',
460
-            true
461
-        );
462
-        return $count_of_message_template_groups === 1;
463
-    }
464
-
465
-
466
-    /**
467
-     * This will get the shared message template group for events that are in the current data handler but ONLY if
468
-     * there's a single shared message template group among all the events.  Otherwise it returns null.
469
-     *
470
-     * @param array $event_ids
471
-     * @return EE_Message_Template_Group|null
472
-     * @throws EE_Error
473
-     * @throws InvalidArgumentException
474
-     * @throws InvalidDataTypeException
475
-     * @throws InvalidInterfaceException
476
-     */
477
-    protected function _get_shared_message_template_for_events(array $event_ids)
478
-    {
479
-        $message_template_group = null;
480
-        if ($this->_queue_shares_same_message_template_group_for_events($event_ids)) {
481
-            $message_template_group = EEM_Message_Template_Group::instance()->get_one(
482
-                [
483
-                    [
484
-                        'Event.EVT_ID'     => ['IN', $event_ids],
485
-                        'MTP_messenger'    => $this->_current_messenger->name,
486
-                        'MTP_message_type' => $this->_current_message_type->name,
487
-                        'MTP_is_active'    => true,
488
-                    ],
489
-                    'group_by' => 'GRP_ID',
490
-                ]
491
-            );
492
-            // store this in the collection if its valid
493
-            if ($message_template_group instanceof EE_Message_Template_Group) {
494
-                $this->_template_collection->add(
495
-                    $message_template_group,
496
-                    $event_ids
497
-                );
498
-            }
499
-        }
500
-        return $message_template_group;
501
-    }
502
-
503
-
504
-    /**
505
-     * Retrieves the global message template group for the current messenger and message type.
506
-     *
507
-     * @return EE_Message_Template_Group|null
508
-     * @throws EE_Error
509
-     * @throws InvalidArgumentException
510
-     * @throws InvalidDataTypeException
511
-     * @throws InvalidInterfaceException
512
-     */
513
-    protected function _get_global_message_template_group_for_current_messenger_and_message_type()
514
-    {
515
-        // first check the collection (we use an array with 0 in it to represent global groups).
516
-        $global_message_template_group = $this->_template_collection->get_by_key(
517
-            $this->_template_collection->getKey(
518
-                $this->_current_messenger->name,
519
-                $this->_current_message_type->name,
520
-                [0]
521
-            )
522
-        );
523
-
524
-        // if we don't have a group lets hit the db.
525
-        if (! $global_message_template_group instanceof EE_Message_Template_Group) {
526
-            $global_message_template_group = EEM_Message_Template_Group::instance()->get_one(
527
-                [
528
-                    [
529
-                        'MTP_messenger'    => $this->_current_messenger->name,
530
-                        'MTP_message_type' => $this->_current_message_type->name,
531
-                        'MTP_is_active'    => true,
532
-                        'MTP_is_global'    => true,
533
-                    ],
534
-                ]
535
-            );
536
-            // if we have a group, add it to the collection.
537
-            if ($global_message_template_group instanceof EE_Message_Template_Group) {
538
-                $this->_template_collection->add(
539
-                    $global_message_template_group,
540
-                    [0]
541
-                );
542
-            }
543
-        }
544
-        return $global_message_template_group;
545
-    }
546
-
547
-
548
-    /**
549
-     * Returns an array of event ids for all the events within the current data handler.
550
-     *
551
-     * @return array
552
-     */
553
-    protected function _get_event_ids_from_current_data_handler()
554
-    {
555
-        $event_ids = [];
556
-        foreach ($this->_current_data_handler->events as $event) {
557
-            $event_ids[ $event['ID'] ] = $event['ID'];
558
-        }
559
-        return $event_ids;
560
-    }
561
-
562
-
563
-    /**
564
-     *  Retrieves formatted array of template information for each context specific to the given
565
-     *  EE_Message_Template_Group
566
-     *
567
-     * @param EE_Message_Template_Group $message_template_group
568
-     * @return array The returned array is in this structure:
569
-     *                          array(
570
-     *                          'field_name' => array(
571
-     *                          'context' => 'content'
572
-     *                          )
573
-     *                          )
574
-     * @throws EE_Error
575
-     * @throws InvalidArgumentException
576
-     * @throws InvalidDataTypeException
577
-     * @throws InvalidInterfaceException
578
-     * @throws ReflectionException
579
-     */
580
-    protected function _get_templates(EE_Message_Template_Group $message_template_group)
581
-    {
582
-        $templates         = [];
583
-        $context_templates = $message_template_group->context_templates();
584
-        foreach ($context_templates as $context => $template_fields) {
585
-            foreach ($template_fields as $template_field => $template_obj) {
586
-                if (! $template_obj instanceof EE_Message_Template) {
587
-                    continue;
588
-                }
589
-                $templates[ $template_field ][ $context ] = $template_obj->get('MTP_content');
590
-            }
591
-        }
592
-        return $templates;
593
-    }
594
-
595
-
596
-    /**
597
-     * Assembles new fully generated EE_Message objects and adds to _ready_queue
598
-     *
599
-     * @param array                     $addressees  Array of EE_Messages_Addressee objects indexed by message type
600
-     *                                               context.
601
-     * @param array                     $templates   formatted array of templates used for parsing data.
602
-     * @param EE_Message_Template_Group $message_template_group
603
-     * @return bool true if message generation went a-ok.  false if some sort of exception occurred.  Note: The
604
-     *                                               method will attempt to generate ALL EE_Message objects and add to
605
-     *                                               the _ready_queue.  Successfully generated messages get added to the
606
-     *                                               queue with EEM_Message::status_idle, unsuccessfully generated
607
-     *                                               messages will get added to the queue as EEM_Message::status_failed.
608
-     *                                               Very rarely should "false" be returned from this method.
609
-     * @throws EE_Error
610
-     * @throws InvalidArgumentException
611
-     * @throws InvalidDataTypeException
612
-     * @throws InvalidIdentifierException
613
-     * @throws InvalidInterfaceException
614
-     * @throws ReflectionException
615
-     */
616
-    protected function _assemble_messages($addressees, $templates, EE_Message_Template_Group $message_template_group)
617
-    {
618
-
619
-        // if templates are empty then get out because we can't generate anything.
620
-        if (! $templates) {
621
-            $this->_error_msg[] = esc_html__(
622
-                'Unable to assemble messages because there are no templates retrieved for generating the messages with',
623
-                'event_espresso'
624
-            );
625
-            return false;
626
-        }
627
-
628
-        // We use this as the counter for generated messages because don't forget we may be executing this inside of a
629
-        // generation_queue.  So _ready_queue may have generated EE_Message objects already.
630
-        $generated_count = 0;
631
-        foreach ($addressees as $context => $recipients) {
632
-            foreach ($recipients as $recipient) {
633
-                $message = $this->_setup_message_object($context, $recipient, $templates, $message_template_group);
634
-                if ($message instanceof EE_Message) {
635
-                    $this->_ready_queue->add(
636
-                        $message,
637
-                        [],
638
-                        $this->_generation_queue->get_message_repository()->is_preview(),
639
-                        $this->_generation_queue->get_message_repository()->is_test_send()
640
-                    );
641
-                    $generated_count++;
642
-                }
643
-
644
-                // if the current MSG being generated is for a test send then we'll only use ONE message in the
645
-                // generation.
646
-                if ($this->_generation_queue->get_message_repository()->is_test_send()) {
647
-                    break 2;
648
-                }
649
-            }
650
-        }
651
-
652
-        // if there are no generated messages then something else fatal went wrong.
653
-        return $generated_count > 0;
654
-    }
655
-
656
-
657
-    /**
658
-     * @param string                    $context   The context for the generated message.
659
-     * @param EE_Messages_Addressee     $recipient
660
-     * @param array                     $templates formatted array of templates used for parsing data.
661
-     * @param EE_Message_Template_Group $message_template_group
662
-     * @return bool|EE_Message
663
-     * @throws EE_Error
664
-     * @throws InvalidArgumentException
665
-     * @throws InvalidDataTypeException
666
-     * @throws InvalidInterfaceException
667
-     * @throws ReflectionException
668
-     * @throws InvalidIdentifierException
669
-     */
670
-    protected function _setup_message_object(
671
-        $context,
672
-        EE_Messages_Addressee $recipient,
673
-        $templates,
674
-        EE_Message_Template_Group $message_template_group
675
-    ) {
676
-        // stuff we already know
677
-        $transaction_id = $recipient->txn instanceof EE_Transaction ? $recipient->txn->ID() : 0;
678
-        $transaction_id = empty($transaction_id) && $this->_current_data_handler->txn instanceof EE_Transaction
679
-            ? $this->_current_data_handler->txn->ID()
680
-            : $transaction_id;
681
-        $message_fields = [
682
-            'GRP_ID'           => $message_template_group->ID(),
683
-            'TXN_ID'           => $transaction_id,
684
-            'MSG_messenger'    => $this->_current_messenger->name,
685
-            'MSG_message_type' => $this->_current_message_type->name,
686
-            'MSG_context'      => $context,
687
-        ];
688
-
689
-        // recipient id and type should be on the EE_Messages_Addressee object but if this is empty, let's try to grab
690
-        // the info from the att_obj found in the EE_Messages_Addressee object.
691
-        if (empty($recipient->recipient_id) || empty($recipient->recipient_type)) {
692
-            $message_fields['MSG_recipient_ID']   = $recipient->att_obj instanceof EE_Attendee
693
-                ? $recipient->att_obj->ID()
694
-                : 0;
695
-            $message_fields['MSG_recipient_type'] = 'Attendee';
696
-        } else {
697
-            $message_fields['MSG_recipient_ID']   = $recipient->recipient_id;
698
-            $message_fields['MSG_recipient_type'] = $recipient->recipient_type;
699
-        }
700
-        $message = EE_Message_Factory::create($message_fields);
701
-
702
-        // grab valid shortcodes for shortcode parser
703
-        $mt_shortcodes = $this->_current_message_type->get_valid_shortcodes();
704
-        $m_shortcodes  = $this->_current_messenger->get_valid_shortcodes();
705
-
706
-        // if the 'to' field is empty or the context is inactive we skip EXCEPT if we're previewing
707
-        if (
708
-            ! $this->_generation_queue->get_message_repository()->is_preview()
709
-            && (
710
-                (empty($templates['to'][ $context ]) && ! $this->_current_messenger->allow_empty_to_field())
711
-                || ! $message_template_group->is_context_active($context)
712
-            )
713
-        ) {
714
-            // we silently exit here and do NOT record a fail because the message is "turned off" by having no "to"
715
-            // field.
716
-            return false;
717
-        }
718
-        $error_msg = [];
719
-        foreach ($templates as $field => $field_context) {
720
-            $error_msg = [];
721
-            // let's setup the valid shortcodes for the incoming context.
722
-            $valid_shortcodes = $mt_shortcodes[ $context ];
723
-            // merge in valid shortcodes for the field.
724
-            $shortcodes = isset($m_shortcodes[ $field ]) ? $m_shortcodes[ $field ] : $valid_shortcodes;
725
-            if (isset($field_context[ $context ])) {
726
-                // prefix field.
727
-                $column_name = 'MSG_' . $field;
728
-                try {
729
-                    $content = $this->_shortcode_parser->parse_message_template(
730
-                        $field_context[ $context ],
731
-                        $recipient,
732
-                        $shortcodes,
733
-                        $this->_current_message_type,
734
-                        $this->_current_messenger,
735
-                        $message
736
-                    );
737
-                    // the model field removes slashes when setting (usually necessary when the input is from the
738
-                    // request) but this value is from another model and has no slashes. So add them so it matches
739
-                    // what the field expected (otherwise slashes will have been stripped from this an extra time)
740
-                    $message->set_field_or_extra_meta($column_name, addslashes($content));
741
-                } catch (EE_Error $e) {
742
-                    $error_msg[] = sprintf(
743
-                    /* Translators: First place holder is message model field name.
18
+	/**
19
+	 * @type EE_Messages_Data_Handler_Collection
20
+	 */
21
+	protected $_data_handler_collection;
22
+
23
+	/**
24
+	 * @type  EE_Message_Template_Group_Collection
25
+	 */
26
+	protected $_template_collection;
27
+
28
+	/**
29
+	 * This will hold the data handler for the current EE_Message being generated.
30
+	 *
31
+	 * @type EE_Messages_incoming_data
32
+	 */
33
+	protected $_current_data_handler;
34
+
35
+	/**
36
+	 * This holds the EE_Messages_Queue that contains the messages to generate.
37
+	 *
38
+	 * @type EE_Messages_Queue
39
+	 */
40
+	protected $_generation_queue;
41
+
42
+	/**
43
+	 * This holds the EE_Messages_Queue that will store the generated EE_Message objects.
44
+	 *
45
+	 * @type EE_Messages_Queue
46
+	 */
47
+	protected $_ready_queue;
48
+
49
+	/**
50
+	 * This is a container for any error messages that get created through the generation
51
+	 * process.
52
+	 *
53
+	 * @type array
54
+	 */
55
+	protected $_error_msg = [];
56
+
57
+	/**
58
+	 * Flag used to set when the current EE_Message in the generation queue has been verified.
59
+	 *
60
+	 * @type bool
61
+	 */
62
+	protected $_verified = false;
63
+
64
+	/**
65
+	 * This will hold the current messenger object corresponding with the current EE_Message in the generation queue.
66
+	 *
67
+	 * @type EE_messenger
68
+	 */
69
+	protected $_current_messenger;
70
+
71
+	/**
72
+	 * This will hold the current message type object corresponding with the current EE_Message in the generation queue.
73
+	 *
74
+	 * @type EE_message_type
75
+	 */
76
+	protected $_current_message_type;
77
+
78
+	/**
79
+	 * @type EEH_Parse_Shortcodes
80
+	 */
81
+	protected $_shortcode_parser;
82
+
83
+
84
+	/**
85
+	 * @param EE_Messages_Queue                    $generation_queue
86
+	 * @param EE_Messages_Queue                    $ready_queue
87
+	 * @param EE_Messages_Data_Handler_Collection  $data_handler_collection
88
+	 * @param EE_Message_Template_Group_Collection $template_collection
89
+	 * @param EEH_Parse_Shortcodes                 $shortcode_parser
90
+	 */
91
+	public function __construct(
92
+		EE_Messages_Queue $generation_queue,
93
+		EE_Messages_Queue $ready_queue,
94
+		EE_Messages_Data_Handler_Collection $data_handler_collection,
95
+		EE_Message_Template_Group_Collection $template_collection,
96
+		EEH_Parse_Shortcodes $shortcode_parser
97
+	) {
98
+		$this->_generation_queue        = $generation_queue;
99
+		$this->_ready_queue             = $ready_queue;
100
+		$this->_data_handler_collection = $data_handler_collection;
101
+		$this->_template_collection     = $template_collection;
102
+		$this->_shortcode_parser        = $shortcode_parser;
103
+	}
104
+
105
+
106
+	/**
107
+	 * @return EE_Messages_Queue
108
+	 */
109
+	public function generation_queue()
110
+	{
111
+		return $this->_generation_queue;
112
+	}
113
+
114
+
115
+	/**
116
+	 *  This iterates through the provided queue and generates the EE_Message objects.
117
+	 *  When iterating through the queue, the queued item that served as the base for generating other EE_Message
118
+	 *  objects gets removed and the new EE_Message objects get added to a NEW queue.  The NEW queue is then returned
119
+	 *  for the caller to decide what to do with it.
120
+	 *
121
+	 * @param bool $save Whether to save the EE_Message objects in the new queue or just return.
122
+	 * @return EE_Messages_Queue The new queue for holding generated EE_Message objects.
123
+	 * @throws EE_Error
124
+	 * @throws InvalidArgumentException
125
+	 * @throws InvalidDataTypeException
126
+	 * @throws InvalidInterfaceException
127
+	 * @throws ReflectionException
128
+	 */
129
+	public function generate($save = true)
130
+	{
131
+		// iterate through the messages in the queue, generate, and add to new queue.
132
+		$this->_generation_queue->get_message_repository()->rewind();
133
+
134
+		while ($this->_generation_queue->get_message_repository()->valid()) {
135
+			// reset "current" properties
136
+			$this->_reset_current_properties();
137
+
138
+			$msg = $this->_generation_queue->get_message_repository()->current();
139
+
140
+			/**
141
+			 * need to get the next object and capture it for setting manually after deletes.  The reason is that when
142
+			 * an object is removed from the repo then valid for the next object will fail.
143
+			 */
144
+			$this->_generation_queue->get_message_repository()->next();
145
+			$next_msg = $this->_generation_queue->get_message_repository()->current();
146
+			// restore pointer to current item
147
+			$this->_generation_queue->get_message_repository()->set_current($msg);
148
+
149
+			// skip and delete if the current $msg is NOT incomplete (queued for generation)
150
+			if ($msg->STS_ID() !== EEM_Message::status_incomplete) {
151
+				// we keep this item in the db just remove from the repo.
152
+				$this->_generation_queue->get_message_repository()->remove($msg);
153
+				// next item
154
+				$this->_generation_queue->get_message_repository()->set_current($next_msg);
155
+				continue;
156
+			}
157
+
158
+			if ($this->_verify()) {
159
+				// let's get generating!
160
+				$this->_generate();
161
+			}
162
+
163
+			// don't persist debug_only messages if the messages system is not in debug mode.
164
+			if (
165
+				$msg->STS_ID() === EEM_Message::status_debug_only
166
+				&& ! EEM_Message::debug()
167
+			) {
168
+				do_action(
169
+					'AHEE__EE_Messages_Generator__generate__before_debug_delete',
170
+					$msg,
171
+					$this->_error_msg,
172
+					$this->_current_messenger,
173
+					$this->_current_message_type,
174
+					$this->_current_data_handler
175
+				);
176
+				$this->_generation_queue->get_message_repository()->delete();
177
+				$this->_generation_queue->get_message_repository()->set_current($next_msg);
178
+				continue;
179
+			}
180
+
181
+			// if there are error messages then let's set the status and the error message.
182
+			if ($this->_error_msg) {
183
+				// if the status is already debug only, then let's leave it at that.
184
+				if ($msg->STS_ID() !== EEM_Message::status_debug_only) {
185
+					$msg->set_STS_ID(EEM_Message::status_failed);
186
+				}
187
+				do_action(
188
+					'AHEE__EE_Messages_Generator__generate__processing_failed_message',
189
+					$msg,
190
+					$this->_error_msg,
191
+					$this->_current_messenger,
192
+					$this->_current_message_type,
193
+					$this->_current_data_handler
194
+				);
195
+				$msg->set_error_message(
196
+					esc_html__('Message failed to generate for the following reasons: ', 'event_espresso')
197
+					. "\n"
198
+					. implode("\n", $this->_error_msg)
199
+				);
200
+				$msg->set_modified(time());
201
+			} else {
202
+				do_action(
203
+					'AHEE__EE_Messages_Generator__generate__before_successful_generated_message_delete',
204
+					$msg,
205
+					$this->_error_msg,
206
+					$this->_current_messenger,
207
+					$this->_current_message_type,
208
+					$this->_current_data_handler
209
+				);
210
+				// remove from db
211
+				$this->_generation_queue->get_message_repository()->delete();
212
+			}
213
+			// next item
214
+			$this->_generation_queue->get_message_repository()->set_current($next_msg);
215
+		}
216
+
217
+		// generation queue is ALWAYS saved to record any errors in the generation process.
218
+		$this->_generation_queue->save();
219
+
220
+		/**
221
+		 * save _ready_queue if flag set.
222
+		 * Note: The EE_Message objects have values set via the EE_Base_Class::set_field_or_extra_meta() method.  This
223
+		 * means if a field was added that is not a valid database column.  The EE_Message was already saved to the db
224
+		 * so a EE_Extra_Meta entry could be created and attached to the EE_Message.  In those cases the save flag is
225
+		 * irrelevant.
226
+		 */
227
+		if ($save) {
228
+			$this->_ready_queue->save();
229
+		}
230
+
231
+		// final reset of properties
232
+		$this->_reset_current_properties();
233
+
234
+		return $this->_ready_queue;
235
+	}
236
+
237
+
238
+	/**
239
+	 * This resets all the properties used for holding "current" values corresponding to the current EE_Message object
240
+	 * in the generation queue.
241
+	 */
242
+	protected function _reset_current_properties()
243
+	{
244
+		$this->_verified = false;
245
+		// make sure any _data value in the current message type is reset
246
+		if ($this->_current_message_type instanceof EE_message_type) {
247
+			$this->_current_message_type->reset_data();
248
+		}
249
+		$this->_current_messenger = $this->_current_message_type = $this->_current_data_handler = null;
250
+	}
251
+
252
+
253
+	/**
254
+	 * This proceeds with the actual generation of a message.  By the time this is called, there should already be a
255
+	 * $_current_data_handler set and all incoming information should be validated for the current EE_Message in the
256
+	 * _generating_queue.
257
+	 *
258
+	 * @return bool Whether the message was successfully generated or not.
259
+	 * @throws EE_Error
260
+	 * @throws InvalidArgumentException
261
+	 * @throws InvalidDataTypeException
262
+	 * @throws InvalidInterfaceException
263
+	 * @throws ReflectionException
264
+	 */
265
+	protected function _generate()
266
+	{
267
+		// double check verification has run and that everything is ready to work with (saves us having to validate
268
+		// everything again).
269
+		if (! $this->_verified) {
270
+			return false; // get out because we don't have a valid setup to work with.
271
+		}
272
+
273
+
274
+		try {
275
+			$addressees = $this->_current_message_type->get_addressees(
276
+				$this->_current_data_handler,
277
+				$this->_generation_queue->get_message_repository()->current()->context()
278
+			);
279
+		} catch (EE_Error $e) {
280
+			$this->_error_msg[] = $e->getMessage();
281
+			return false;
282
+		}
283
+
284
+
285
+		// if no addressees then get out because there is nothing to generation (possible bad data).
286
+		if (! $this->_valid_addressees($addressees)) {
287
+			do_action(
288
+				'AHEE__EE_Messages_Generator___generate__invalid_addressees',
289
+				$this->_generation_queue->get_message_repository()->current(),
290
+				$addressees,
291
+				$this->_current_messenger,
292
+				$this->_current_message_type,
293
+				$this->_current_data_handler
294
+			);
295
+			$this->_generation_queue->get_message_repository()->current()->set_STS_ID(
296
+				EEM_Message::status_debug_only
297
+			);
298
+			$this->_error_msg[] = esc_html__(
299
+				'This is not a critical error but an informational notice. Unable to generate messages EE_Messages_Addressee objects.  There were no attendees prepared by the data handler. Sometimes this is because messages only get generated for certain registration statuses. For example, the ticket notice message type only goes to approved registrations.',
300
+				'event_espresso'
301
+			);
302
+			return false;
303
+		}
304
+
305
+		$message_template_group = $this->_get_message_template_group();
306
+
307
+		// in the unlikely event there is no EE_Message_Template_Group available, get out!
308
+		if (! $message_template_group instanceof EE_Message_Template_Group) {
309
+			$this->_error_msg[] = esc_html__(
310
+				'Unable to get the Message Templates for the Message being generated.  No message template group accessible.',
311
+				'event_espresso'
312
+			);
313
+			return false;
314
+		}
315
+
316
+		// get formatted templates for using to parse and setup EE_Message objects.
317
+		$templates = $this->_get_templates($message_template_group);
318
+
319
+
320
+		// setup new EE_Message objects (and add to _ready_queue)
321
+		return $this->_assemble_messages($addressees, $templates, $message_template_group);
322
+	}
323
+
324
+
325
+	/**
326
+	 * Retrieves the message template group being used for generating messages.
327
+	 * Note: this also utilizes the EE_Message_Template_Group_Collection to avoid having to hit the db multiple times.
328
+	 *
329
+	 * @return EE_Message_Template_Group|null
330
+	 * @throws EE_Error
331
+	 * @throws InvalidArgumentException
332
+	 * @throws InvalidDataTypeException
333
+	 * @throws InvalidInterfaceException
334
+	 * @throws ReflectionException
335
+	 */
336
+	protected function _get_message_template_group()
337
+	{
338
+		// first see if there is a specific message template group requested
339
+		// (current message in the queue has a specific GRP_ID)
340
+		$message_template_group = $this->_specific_message_template_group_from_queue();
341
+		if ($message_template_group instanceof EE_Message_Template_Group) {
342
+			return $message_template_group;
343
+		}
344
+
345
+		// get event_ids from the data handler so we can check to see
346
+		// if there's already a message template group for them in the collection.
347
+		$event_ids              = $this->_get_event_ids_from_current_data_handler();
348
+		$message_template_group = $this->_template_collection->get_by_key(
349
+			$this->_template_collection->getKey(
350
+				$this->_current_messenger->name,
351
+				$this->_current_message_type->name,
352
+				$event_ids
353
+			)
354
+		);
355
+
356
+		// if we have a message template group then no need to hit the database, just return it.
357
+		if ($message_template_group instanceof EE_Message_Template_Group) {
358
+			return $message_template_group;
359
+		}
360
+
361
+		// get the global group first for this messenger and message type
362
+		// to ensure there is no override set.
363
+		$global_message_template_group =
364
+			$this->_get_global_message_template_group_for_current_messenger_and_message_type();
365
+
366
+		if (
367
+			$global_message_template_group instanceof EE_Message_Template_Group
368
+			&& $global_message_template_group->get('MTP_is_override')
369
+		) {
370
+			return $global_message_template_group;
371
+		}
372
+
373
+		// if we're still here, that means there was no message template group for the events in the collection and
374
+		// the global message template group for the messenger and message type is not set for override.  So next step
375
+		// is to see if there is a common shared custom message template group for this set of events.
376
+		$message_template_group = $this->_get_shared_message_template_for_events($event_ids);
377
+		if ($message_template_group instanceof EE_Message_Template_Group) {
378
+			return $message_template_group;
379
+		}
380
+
381
+		// STILL here?  Okay that means the fallback is to just use the global message template group for this event
382
+		// set. So we'll cache the global group for this event set (so this logic doesn't have to be repeated in this
383
+		// request) and return it.
384
+		if ($global_message_template_group instanceof EE_Message_Template_Group) {
385
+			$this->_template_collection->add(
386
+				$global_message_template_group,
387
+				$event_ids
388
+			);
389
+			return $global_message_template_group;
390
+		}
391
+
392
+		// if we land here that means there's NO active message template group for this set.
393
+		// TODO this will be a good target for some optimization down the road.  Whenever there is no active message
394
+		// template group for a given event set then cache that result so we don't repeat the logic.  However, for now,
395
+		// this should likely bit hit rarely enough that it's not a significant issue.
396
+		return null;
397
+	}
398
+
399
+
400
+	/**
401
+	 * This checks the current message in the queue and determines if there is a specific Message Template Group
402
+	 * requested for that message.
403
+	 *
404
+	 * @return EE_Message_Template_Group|null
405
+	 * @throws EE_Error
406
+	 * @throws InvalidArgumentException
407
+	 * @throws InvalidDataTypeException
408
+	 * @throws InvalidInterfaceException
409
+	 */
410
+	protected function _specific_message_template_group_from_queue()
411
+	{
412
+		// is there a GRP_ID already on the EE_Message object?  If there is, then a specific template has been requested
413
+		// so let's use that.
414
+		$GRP_ID = $this->_generation_queue->get_message_repository()->current()->GRP_ID();
415
+
416
+		if ($GRP_ID) {
417
+			// attempt to retrieve from repo first
418
+			$message_template_group = $this->_template_collection->get_by_ID($GRP_ID);
419
+			if ($message_template_group instanceof EE_Message_Template_Group) {
420
+				return $message_template_group;  // got it!
421
+			}
422
+
423
+			// nope don't have it yet.  Get from DB then add to repo if its not here, then that means the current GRP_ID
424
+			// is not valid, so we'll continue on in the code assuming there's NO GRP_ID.
425
+			$message_template_group = EEM_Message_Template_Group::instance()->get_one_by_ID($GRP_ID);
426
+			if ($message_template_group instanceof EE_Message_Template_Group) {
427
+				$this->_template_collection->add($message_template_group);
428
+				return $message_template_group;
429
+			}
430
+		}
431
+		return null;
432
+	}
433
+
434
+
435
+	/**
436
+	 * Returns whether the event ids passed in all share the same message template group for the current message type
437
+	 * and messenger.
438
+	 *
439
+	 * @param array $event_ids
440
+	 * @return bool true means they DO share the same message template group, false means they don't.
441
+	 * @throws EE_Error
442
+	 * @throws InvalidArgumentException
443
+	 * @throws InvalidDataTypeException
444
+	 * @throws InvalidInterfaceException
445
+	 */
446
+	protected function _queue_shares_same_message_template_group_for_events(array $event_ids)
447
+	{
448
+		foreach ($this->_current_data_handler->events as $event) {
449
+			$event_ids[ $event['ID'] ] = $event['ID'];
450
+		}
451
+		$count_of_message_template_groups = EEM_Message_Template_Group::instance()->count(
452
+			[
453
+				[
454
+					'Event.EVT_ID'     => ['IN', $event_ids],
455
+					'MTP_messenger'    => $this->_current_messenger->name,
456
+					'MTP_message_type' => $this->_current_message_type->name,
457
+				],
458
+			],
459
+			'GRP_ID',
460
+			true
461
+		);
462
+		return $count_of_message_template_groups === 1;
463
+	}
464
+
465
+
466
+	/**
467
+	 * This will get the shared message template group for events that are in the current data handler but ONLY if
468
+	 * there's a single shared message template group among all the events.  Otherwise it returns null.
469
+	 *
470
+	 * @param array $event_ids
471
+	 * @return EE_Message_Template_Group|null
472
+	 * @throws EE_Error
473
+	 * @throws InvalidArgumentException
474
+	 * @throws InvalidDataTypeException
475
+	 * @throws InvalidInterfaceException
476
+	 */
477
+	protected function _get_shared_message_template_for_events(array $event_ids)
478
+	{
479
+		$message_template_group = null;
480
+		if ($this->_queue_shares_same_message_template_group_for_events($event_ids)) {
481
+			$message_template_group = EEM_Message_Template_Group::instance()->get_one(
482
+				[
483
+					[
484
+						'Event.EVT_ID'     => ['IN', $event_ids],
485
+						'MTP_messenger'    => $this->_current_messenger->name,
486
+						'MTP_message_type' => $this->_current_message_type->name,
487
+						'MTP_is_active'    => true,
488
+					],
489
+					'group_by' => 'GRP_ID',
490
+				]
491
+			);
492
+			// store this in the collection if its valid
493
+			if ($message_template_group instanceof EE_Message_Template_Group) {
494
+				$this->_template_collection->add(
495
+					$message_template_group,
496
+					$event_ids
497
+				);
498
+			}
499
+		}
500
+		return $message_template_group;
501
+	}
502
+
503
+
504
+	/**
505
+	 * Retrieves the global message template group for the current messenger and message type.
506
+	 *
507
+	 * @return EE_Message_Template_Group|null
508
+	 * @throws EE_Error
509
+	 * @throws InvalidArgumentException
510
+	 * @throws InvalidDataTypeException
511
+	 * @throws InvalidInterfaceException
512
+	 */
513
+	protected function _get_global_message_template_group_for_current_messenger_and_message_type()
514
+	{
515
+		// first check the collection (we use an array with 0 in it to represent global groups).
516
+		$global_message_template_group = $this->_template_collection->get_by_key(
517
+			$this->_template_collection->getKey(
518
+				$this->_current_messenger->name,
519
+				$this->_current_message_type->name,
520
+				[0]
521
+			)
522
+		);
523
+
524
+		// if we don't have a group lets hit the db.
525
+		if (! $global_message_template_group instanceof EE_Message_Template_Group) {
526
+			$global_message_template_group = EEM_Message_Template_Group::instance()->get_one(
527
+				[
528
+					[
529
+						'MTP_messenger'    => $this->_current_messenger->name,
530
+						'MTP_message_type' => $this->_current_message_type->name,
531
+						'MTP_is_active'    => true,
532
+						'MTP_is_global'    => true,
533
+					],
534
+				]
535
+			);
536
+			// if we have a group, add it to the collection.
537
+			if ($global_message_template_group instanceof EE_Message_Template_Group) {
538
+				$this->_template_collection->add(
539
+					$global_message_template_group,
540
+					[0]
541
+				);
542
+			}
543
+		}
544
+		return $global_message_template_group;
545
+	}
546
+
547
+
548
+	/**
549
+	 * Returns an array of event ids for all the events within the current data handler.
550
+	 *
551
+	 * @return array
552
+	 */
553
+	protected function _get_event_ids_from_current_data_handler()
554
+	{
555
+		$event_ids = [];
556
+		foreach ($this->_current_data_handler->events as $event) {
557
+			$event_ids[ $event['ID'] ] = $event['ID'];
558
+		}
559
+		return $event_ids;
560
+	}
561
+
562
+
563
+	/**
564
+	 *  Retrieves formatted array of template information for each context specific to the given
565
+	 *  EE_Message_Template_Group
566
+	 *
567
+	 * @param EE_Message_Template_Group $message_template_group
568
+	 * @return array The returned array is in this structure:
569
+	 *                          array(
570
+	 *                          'field_name' => array(
571
+	 *                          'context' => 'content'
572
+	 *                          )
573
+	 *                          )
574
+	 * @throws EE_Error
575
+	 * @throws InvalidArgumentException
576
+	 * @throws InvalidDataTypeException
577
+	 * @throws InvalidInterfaceException
578
+	 * @throws ReflectionException
579
+	 */
580
+	protected function _get_templates(EE_Message_Template_Group $message_template_group)
581
+	{
582
+		$templates         = [];
583
+		$context_templates = $message_template_group->context_templates();
584
+		foreach ($context_templates as $context => $template_fields) {
585
+			foreach ($template_fields as $template_field => $template_obj) {
586
+				if (! $template_obj instanceof EE_Message_Template) {
587
+					continue;
588
+				}
589
+				$templates[ $template_field ][ $context ] = $template_obj->get('MTP_content');
590
+			}
591
+		}
592
+		return $templates;
593
+	}
594
+
595
+
596
+	/**
597
+	 * Assembles new fully generated EE_Message objects and adds to _ready_queue
598
+	 *
599
+	 * @param array                     $addressees  Array of EE_Messages_Addressee objects indexed by message type
600
+	 *                                               context.
601
+	 * @param array                     $templates   formatted array of templates used for parsing data.
602
+	 * @param EE_Message_Template_Group $message_template_group
603
+	 * @return bool true if message generation went a-ok.  false if some sort of exception occurred.  Note: The
604
+	 *                                               method will attempt to generate ALL EE_Message objects and add to
605
+	 *                                               the _ready_queue.  Successfully generated messages get added to the
606
+	 *                                               queue with EEM_Message::status_idle, unsuccessfully generated
607
+	 *                                               messages will get added to the queue as EEM_Message::status_failed.
608
+	 *                                               Very rarely should "false" be returned from this method.
609
+	 * @throws EE_Error
610
+	 * @throws InvalidArgumentException
611
+	 * @throws InvalidDataTypeException
612
+	 * @throws InvalidIdentifierException
613
+	 * @throws InvalidInterfaceException
614
+	 * @throws ReflectionException
615
+	 */
616
+	protected function _assemble_messages($addressees, $templates, EE_Message_Template_Group $message_template_group)
617
+	{
618
+
619
+		// if templates are empty then get out because we can't generate anything.
620
+		if (! $templates) {
621
+			$this->_error_msg[] = esc_html__(
622
+				'Unable to assemble messages because there are no templates retrieved for generating the messages with',
623
+				'event_espresso'
624
+			);
625
+			return false;
626
+		}
627
+
628
+		// We use this as the counter for generated messages because don't forget we may be executing this inside of a
629
+		// generation_queue.  So _ready_queue may have generated EE_Message objects already.
630
+		$generated_count = 0;
631
+		foreach ($addressees as $context => $recipients) {
632
+			foreach ($recipients as $recipient) {
633
+				$message = $this->_setup_message_object($context, $recipient, $templates, $message_template_group);
634
+				if ($message instanceof EE_Message) {
635
+					$this->_ready_queue->add(
636
+						$message,
637
+						[],
638
+						$this->_generation_queue->get_message_repository()->is_preview(),
639
+						$this->_generation_queue->get_message_repository()->is_test_send()
640
+					);
641
+					$generated_count++;
642
+				}
643
+
644
+				// if the current MSG being generated is for a test send then we'll only use ONE message in the
645
+				// generation.
646
+				if ($this->_generation_queue->get_message_repository()->is_test_send()) {
647
+					break 2;
648
+				}
649
+			}
650
+		}
651
+
652
+		// if there are no generated messages then something else fatal went wrong.
653
+		return $generated_count > 0;
654
+	}
655
+
656
+
657
+	/**
658
+	 * @param string                    $context   The context for the generated message.
659
+	 * @param EE_Messages_Addressee     $recipient
660
+	 * @param array                     $templates formatted array of templates used for parsing data.
661
+	 * @param EE_Message_Template_Group $message_template_group
662
+	 * @return bool|EE_Message
663
+	 * @throws EE_Error
664
+	 * @throws InvalidArgumentException
665
+	 * @throws InvalidDataTypeException
666
+	 * @throws InvalidInterfaceException
667
+	 * @throws ReflectionException
668
+	 * @throws InvalidIdentifierException
669
+	 */
670
+	protected function _setup_message_object(
671
+		$context,
672
+		EE_Messages_Addressee $recipient,
673
+		$templates,
674
+		EE_Message_Template_Group $message_template_group
675
+	) {
676
+		// stuff we already know
677
+		$transaction_id = $recipient->txn instanceof EE_Transaction ? $recipient->txn->ID() : 0;
678
+		$transaction_id = empty($transaction_id) && $this->_current_data_handler->txn instanceof EE_Transaction
679
+			? $this->_current_data_handler->txn->ID()
680
+			: $transaction_id;
681
+		$message_fields = [
682
+			'GRP_ID'           => $message_template_group->ID(),
683
+			'TXN_ID'           => $transaction_id,
684
+			'MSG_messenger'    => $this->_current_messenger->name,
685
+			'MSG_message_type' => $this->_current_message_type->name,
686
+			'MSG_context'      => $context,
687
+		];
688
+
689
+		// recipient id and type should be on the EE_Messages_Addressee object but if this is empty, let's try to grab
690
+		// the info from the att_obj found in the EE_Messages_Addressee object.
691
+		if (empty($recipient->recipient_id) || empty($recipient->recipient_type)) {
692
+			$message_fields['MSG_recipient_ID']   = $recipient->att_obj instanceof EE_Attendee
693
+				? $recipient->att_obj->ID()
694
+				: 0;
695
+			$message_fields['MSG_recipient_type'] = 'Attendee';
696
+		} else {
697
+			$message_fields['MSG_recipient_ID']   = $recipient->recipient_id;
698
+			$message_fields['MSG_recipient_type'] = $recipient->recipient_type;
699
+		}
700
+		$message = EE_Message_Factory::create($message_fields);
701
+
702
+		// grab valid shortcodes for shortcode parser
703
+		$mt_shortcodes = $this->_current_message_type->get_valid_shortcodes();
704
+		$m_shortcodes  = $this->_current_messenger->get_valid_shortcodes();
705
+
706
+		// if the 'to' field is empty or the context is inactive we skip EXCEPT if we're previewing
707
+		if (
708
+			! $this->_generation_queue->get_message_repository()->is_preview()
709
+			&& (
710
+				(empty($templates['to'][ $context ]) && ! $this->_current_messenger->allow_empty_to_field())
711
+				|| ! $message_template_group->is_context_active($context)
712
+			)
713
+		) {
714
+			// we silently exit here and do NOT record a fail because the message is "turned off" by having no "to"
715
+			// field.
716
+			return false;
717
+		}
718
+		$error_msg = [];
719
+		foreach ($templates as $field => $field_context) {
720
+			$error_msg = [];
721
+			// let's setup the valid shortcodes for the incoming context.
722
+			$valid_shortcodes = $mt_shortcodes[ $context ];
723
+			// merge in valid shortcodes for the field.
724
+			$shortcodes = isset($m_shortcodes[ $field ]) ? $m_shortcodes[ $field ] : $valid_shortcodes;
725
+			if (isset($field_context[ $context ])) {
726
+				// prefix field.
727
+				$column_name = 'MSG_' . $field;
728
+				try {
729
+					$content = $this->_shortcode_parser->parse_message_template(
730
+						$field_context[ $context ],
731
+						$recipient,
732
+						$shortcodes,
733
+						$this->_current_message_type,
734
+						$this->_current_messenger,
735
+						$message
736
+					);
737
+					// the model field removes slashes when setting (usually necessary when the input is from the
738
+					// request) but this value is from another model and has no slashes. So add them so it matches
739
+					// what the field expected (otherwise slashes will have been stripped from this an extra time)
740
+					$message->set_field_or_extra_meta($column_name, addslashes($content));
741
+				} catch (EE_Error $e) {
742
+					$error_msg[] = sprintf(
743
+					/* Translators: First place holder is message model field name.
744 744
                      * Second placeholder is exception error message */
745
-                        esc_html__(
746
-                            'There was a problem generating the content for the field %s: %s',
747
-                            'event_espresso'
748
-                        ),
749
-                        $field,
750
-                        $e->getMessage()
751
-                    );
752
-                    $message->set_STS_ID(EEM_Message::status_failed);
753
-                }
754
-            }
755
-        }
756
-
757
-        if ($message->STS_ID() === EEM_Message::status_failed) {
758
-            $error_msg = esc_html__('There were problems generating this message:', 'event_espresso')
759
-                         . "\n"
760
-                         . implode("\n", $error_msg);
761
-            $message->set_error_message($error_msg);
762
-        } else {
763
-            $message->set_STS_ID(EEM_Message::status_idle);
764
-        }
765
-        return $message;
766
-    }
767
-
768
-
769
-    /**
770
-     * This verifies that the incoming array has a EE_messenger object and a EE_message_type object and sets appropriate
771
-     * error message if either is missing.
772
-     *
773
-     * @return bool true means there were no errors, false means there were errors.
774
-     */
775
-    protected function _verify()
776
-    {
777
-        // reset error message to an empty array.
778
-        $this->_error_msg = [];
779
-        // set the verified flag so we know everything has been validated.
780
-        $this->_verified = $this->_validate_messenger_and_message_type() && $this->_validate_and_setup_data();
781
-        return $this->_verified;
782
-    }
783
-
784
-
785
-    /**
786
-     * This accepts an array and validates that it is an array indexed by context with each value being an array of
787
-     * EE_Messages_Addressee objects.
788
-     *
789
-     * @param array $addressees Keys correspond to contexts for the message type and values are EE_Messages_Addressee[]
790
-     * @return bool
791
-     */
792
-    protected function _valid_addressees($addressees)
793
-    {
794
-        if (! $addressees || ! is_array($addressees)) {
795
-            return false;
796
-        }
797
-
798
-        foreach ($addressees as $addressee_array) {
799
-            foreach ($addressee_array as $addressee) {
800
-                if (! $addressee instanceof EE_Messages_Addressee) {
801
-                    return false;
802
-                }
803
-            }
804
-        }
805
-        return true;
806
-    }
807
-
808
-
809
-    /**
810
-     * This validates the messenger, message type, and presences of generation data for the current EE_Message in the
811
-     * queue. This process sets error messages if something is wrong.
812
-     *
813
-     * @return bool   true is if there are no errors.  false is if there is.
814
-     */
815
-    protected function _validate_messenger_and_message_type()
816
-    {
817
-        // first are there any existing error messages?  If so then return.
818
-        if ($this->_error_msg) {
819
-            return false;
820
-        }
821
-        $message = $this->_generation_queue->get_message_repository()->current();
822
-        try {
823
-            $this->_current_messenger = $message->valid_messenger(true)
824
-                ? $message->messenger_object()
825
-                : null;
826
-        } catch (Exception $e) {
827
-            $this->_error_msg[] = $e->getMessage();
828
-        }
829
-        try {
830
-            $this->_current_message_type = $message->valid_message_type(true)
831
-                ? $message->message_type_object()
832
-                : null;
833
-        } catch (Exception $e) {
834
-            $this->_error_msg[] = $e->getMessage();
835
-        }
836
-
837
-        /**
838
-         * Check if there is any generation data, but only if this is not for a preview.
839
-         */
840
-        if (
841
-            ! $this->_generation_queue->get_message_repository()->get_generation_data()
842
-            && (
843
-                ! $this->_generation_queue->get_message_repository()->is_preview()
844
-                && $this->_generation_queue->get_message_repository()->get_data_handler()
845
-                   !== 'EE_Messages_Preview_incoming_data'
846
-            )
847
-        ) {
848
-            $this->_error_msg[] = esc_html__(
849
-                'There is no generation data for this message. Unable to generate.',
850
-                'event_espresso'
851
-            );
852
-        }
853
-
854
-        return empty($this->_error_msg);
855
-    }
856
-
857
-
858
-    /**
859
-     * This method retrieves the expected data handler for the message type and validates the generation data for that
860
-     * data handler.
861
-     *
862
-     * @return bool true means there are no errors.  false means there were errors (and handler did not get setup).
863
-     */
864
-    protected function _validate_and_setup_data()
865
-    {
866
-
867
-        // First, are there any existing error messages?  If so, return because if there were errors elsewhere this
868
-        // can't be used anyways.
869
-        if ($this->_error_msg) {
870
-            return false;
871
-        }
872
-
873
-        $generation_data = $this->_generation_queue->get_message_repository()->get_generation_data();
874
-
875
-        /** @type EE_Messages_incoming_data $data_handler_class_name - well not really... just the class name actually */
876
-        $data_handler_class_name = $this->_generation_queue->get_message_repository()->get_data_handler()
877
-            ? $this->_generation_queue->get_message_repository()->get_data_handler()
878
-            : 'EE_Messages_' . $this->_current_message_type->get_data_handler($generation_data) . '_incoming_data';
879
-
880
-        // If this EE_Message is for a preview, then let's switch out to the preview data handler.
881
-        if ($this->_generation_queue->get_message_repository()->is_preview()) {
882
-            $data_handler_class_name = 'EE_Messages_Preview_incoming_data';
883
-        }
884
-
885
-        // First get the class name for the data handler (and also verifies it exists.
886
-        if (! class_exists($data_handler_class_name)) {
887
-            $this->_error_msg[] = sprintf(
888
-            /* Translators: Both placeholders are the names of php classes. */
889
-                esc_html__(
890
-                    'The included data handler class name does not match any valid, accessible, "%1$s" classes.  Looking for %2$s.',
891
-                    'event_espresso'
892
-                ),
893
-                'EE_Messages_incoming_data',
894
-                $data_handler_class_name
895
-            );
896
-            return false;
897
-        }
898
-
899
-        // convert generation_data for data_handler_instantiation.
900
-        $generation_data = $data_handler_class_name::convert_data_from_persistent_storage($generation_data);
901
-
902
-        // note, this may set error messages as well.
903
-        $this->_set_data_handler($generation_data, $data_handler_class_name);
904
-
905
-        return empty($this->_error_msg);
906
-    }
907
-
908
-
909
-    /**
910
-     * Sets the $_current_data_handler property that is used for generating the current EE_Message in the queue, and
911
-     * adds it to the _data repository.
912
-     *
913
-     * @param mixed  $generating_data           This is data expected by the instantiated data handler.
914
-     * @param string $data_handler_class_name   This is the reference string indicating what data handler is being
915
-     *                                          instantiated.
916
-     */
917
-    protected function _set_data_handler($generating_data, $data_handler_class_name)
918
-    {
919
-        // valid classname for the data handler.  Now let's setup the key for the data handler repository to see if
920
-        // there is already a ready data handler in the repository.
921
-        $this->_current_data_handler = $this->_data_handler_collection->get_by_key(
922
-            $this->_data_handler_collection->get_key(
923
-                $data_handler_class_name,
924
-                $generating_data
925
-            )
926
-        );
927
-        if (! $this->_current_data_handler instanceof EE_Messages_incoming_data) {
928
-            // no saved data_handler in the repo so let's set one up and add it to the repo.
929
-            try {
930
-                $this->_current_data_handler = new $data_handler_class_name($generating_data);
931
-                $this->_data_handler_collection->add($this->_current_data_handler, $generating_data);
932
-            } catch (Exception $e) {
933
-                $this->_error_msg[] = $e->getMessage();
934
-            }
935
-        }
936
-    }
937
-
938
-
939
-    /**
940
-     * The queued EE_Message for generation does not save the data used for generation as objects
941
-     * because serialization of those objects could be problematic if the data is saved to the db.
942
-     * So this method calls the static method on the associated data_handler for the given message_type
943
-     * and that preps the data for later instantiation when generating.
944
-     *
945
-     * @param EE_Message_To_Generate $message_to_generate
946
-     * @param bool                   $preview Indicate whether this is being used for a preview or not.
947
-     * @return mixed Prepped data for persisting to the queue.  false is returned if unable to prep data.
948
-     */
949
-    protected function _prepare_data_for_queue(EE_Message_To_Generate $message_to_generate, $preview)
950
-    {
951
-        if (! $message_to_generate->valid()) {
952
-            return false; // unable to get the data because the info in the EE_Message_To_Generate class is invalid.
953
-        }
954
-        /** @type EE_Messages_incoming_data $data_handler - well not really... just the class name actually */
955
-        $data_handler = $message_to_generate->get_data_handler_class_name($preview);
956
-        return $data_handler::convert_data_for_persistent_storage($message_to_generate->data());
957
-    }
958
-
959
-
960
-    /**
961
-     * This sets up a EEM_Message::status_incomplete EE_Message object and adds it to the generation queue.
962
-     *
963
-     * @param EE_Message_To_Generate $message_to_generate
964
-     * @param bool                   $test_send Whether this is just a test send or not.  Typically used for previews.
965
-     * @return bool
966
-     * @throws InvalidArgumentException
967
-     * @throws InvalidDataTypeException
968
-     * @throws InvalidInterfaceException
969
-     */
970
-    public function create_and_add_message_to_queue(EE_Message_To_Generate $message_to_generate, $test_send = false)
971
-    {
972
-        // prep data
973
-        $data    = $this->_prepare_data_for_queue($message_to_generate, $message_to_generate->preview());
974
-        $request = LoaderFactory::getLoader()->getShared('EventEspresso\core\services\request\RequestInterface');
975
-
976
-        $message = $message_to_generate->get_EE_Message();
977
-        $GRP_ID  = $request->getRequestParam('GRP_ID', 0, 'int');
978
-
979
-        $GRP_ID = apply_filters(
980
-            'FHEE__EE_Messages_Generator__create_and_add_message_to_queue_GRP_ID',
981
-            $GRP_ID > 0 ? $GRP_ID : $message->GRP_ID(),
982
-            $message,
983
-            $message_to_generate,
984
-            $test_send
985
-        );
986
-
987
-        if ($GRP_ID > 0) {
988
-            $message->set_GRP_ID($GRP_ID);
989
-        }
990
-
991
-        if ($data === false) {
992
-            $message->set_STS_ID(EEM_Message::status_failed);
993
-            $message->set_error_message(
994
-                esc_html__(
995
-                    'Unable to prepare data for persistence to the database.',
996
-                    'event_espresso'
997
-                )
998
-            );
999
-        } else {
1000
-            // make sure that the data handler is cached on the message as well
1001
-            $data['data_handler_class_name'] = $message_to_generate->get_data_handler_class_name();
1002
-        }
1003
-
1004
-        return $this->_generation_queue->add($message, $data, $message_to_generate->preview(), $test_send);
1005
-    }
745
+						esc_html__(
746
+							'There was a problem generating the content for the field %s: %s',
747
+							'event_espresso'
748
+						),
749
+						$field,
750
+						$e->getMessage()
751
+					);
752
+					$message->set_STS_ID(EEM_Message::status_failed);
753
+				}
754
+			}
755
+		}
756
+
757
+		if ($message->STS_ID() === EEM_Message::status_failed) {
758
+			$error_msg = esc_html__('There were problems generating this message:', 'event_espresso')
759
+						 . "\n"
760
+						 . implode("\n", $error_msg);
761
+			$message->set_error_message($error_msg);
762
+		} else {
763
+			$message->set_STS_ID(EEM_Message::status_idle);
764
+		}
765
+		return $message;
766
+	}
767
+
768
+
769
+	/**
770
+	 * This verifies that the incoming array has a EE_messenger object and a EE_message_type object and sets appropriate
771
+	 * error message if either is missing.
772
+	 *
773
+	 * @return bool true means there were no errors, false means there were errors.
774
+	 */
775
+	protected function _verify()
776
+	{
777
+		// reset error message to an empty array.
778
+		$this->_error_msg = [];
779
+		// set the verified flag so we know everything has been validated.
780
+		$this->_verified = $this->_validate_messenger_and_message_type() && $this->_validate_and_setup_data();
781
+		return $this->_verified;
782
+	}
783
+
784
+
785
+	/**
786
+	 * This accepts an array and validates that it is an array indexed by context with each value being an array of
787
+	 * EE_Messages_Addressee objects.
788
+	 *
789
+	 * @param array $addressees Keys correspond to contexts for the message type and values are EE_Messages_Addressee[]
790
+	 * @return bool
791
+	 */
792
+	protected function _valid_addressees($addressees)
793
+	{
794
+		if (! $addressees || ! is_array($addressees)) {
795
+			return false;
796
+		}
797
+
798
+		foreach ($addressees as $addressee_array) {
799
+			foreach ($addressee_array as $addressee) {
800
+				if (! $addressee instanceof EE_Messages_Addressee) {
801
+					return false;
802
+				}
803
+			}
804
+		}
805
+		return true;
806
+	}
807
+
808
+
809
+	/**
810
+	 * This validates the messenger, message type, and presences of generation data for the current EE_Message in the
811
+	 * queue. This process sets error messages if something is wrong.
812
+	 *
813
+	 * @return bool   true is if there are no errors.  false is if there is.
814
+	 */
815
+	protected function _validate_messenger_and_message_type()
816
+	{
817
+		// first are there any existing error messages?  If so then return.
818
+		if ($this->_error_msg) {
819
+			return false;
820
+		}
821
+		$message = $this->_generation_queue->get_message_repository()->current();
822
+		try {
823
+			$this->_current_messenger = $message->valid_messenger(true)
824
+				? $message->messenger_object()
825
+				: null;
826
+		} catch (Exception $e) {
827
+			$this->_error_msg[] = $e->getMessage();
828
+		}
829
+		try {
830
+			$this->_current_message_type = $message->valid_message_type(true)
831
+				? $message->message_type_object()
832
+				: null;
833
+		} catch (Exception $e) {
834
+			$this->_error_msg[] = $e->getMessage();
835
+		}
836
+
837
+		/**
838
+		 * Check if there is any generation data, but only if this is not for a preview.
839
+		 */
840
+		if (
841
+			! $this->_generation_queue->get_message_repository()->get_generation_data()
842
+			&& (
843
+				! $this->_generation_queue->get_message_repository()->is_preview()
844
+				&& $this->_generation_queue->get_message_repository()->get_data_handler()
845
+				   !== 'EE_Messages_Preview_incoming_data'
846
+			)
847
+		) {
848
+			$this->_error_msg[] = esc_html__(
849
+				'There is no generation data for this message. Unable to generate.',
850
+				'event_espresso'
851
+			);
852
+		}
853
+
854
+		return empty($this->_error_msg);
855
+	}
856
+
857
+
858
+	/**
859
+	 * This method retrieves the expected data handler for the message type and validates the generation data for that
860
+	 * data handler.
861
+	 *
862
+	 * @return bool true means there are no errors.  false means there were errors (and handler did not get setup).
863
+	 */
864
+	protected function _validate_and_setup_data()
865
+	{
866
+
867
+		// First, are there any existing error messages?  If so, return because if there were errors elsewhere this
868
+		// can't be used anyways.
869
+		if ($this->_error_msg) {
870
+			return false;
871
+		}
872
+
873
+		$generation_data = $this->_generation_queue->get_message_repository()->get_generation_data();
874
+
875
+		/** @type EE_Messages_incoming_data $data_handler_class_name - well not really... just the class name actually */
876
+		$data_handler_class_name = $this->_generation_queue->get_message_repository()->get_data_handler()
877
+			? $this->_generation_queue->get_message_repository()->get_data_handler()
878
+			: 'EE_Messages_' . $this->_current_message_type->get_data_handler($generation_data) . '_incoming_data';
879
+
880
+		// If this EE_Message is for a preview, then let's switch out to the preview data handler.
881
+		if ($this->_generation_queue->get_message_repository()->is_preview()) {
882
+			$data_handler_class_name = 'EE_Messages_Preview_incoming_data';
883
+		}
884
+
885
+		// First get the class name for the data handler (and also verifies it exists.
886
+		if (! class_exists($data_handler_class_name)) {
887
+			$this->_error_msg[] = sprintf(
888
+			/* Translators: Both placeholders are the names of php classes. */
889
+				esc_html__(
890
+					'The included data handler class name does not match any valid, accessible, "%1$s" classes.  Looking for %2$s.',
891
+					'event_espresso'
892
+				),
893
+				'EE_Messages_incoming_data',
894
+				$data_handler_class_name
895
+			);
896
+			return false;
897
+		}
898
+
899
+		// convert generation_data for data_handler_instantiation.
900
+		$generation_data = $data_handler_class_name::convert_data_from_persistent_storage($generation_data);
901
+
902
+		// note, this may set error messages as well.
903
+		$this->_set_data_handler($generation_data, $data_handler_class_name);
904
+
905
+		return empty($this->_error_msg);
906
+	}
907
+
908
+
909
+	/**
910
+	 * Sets the $_current_data_handler property that is used for generating the current EE_Message in the queue, and
911
+	 * adds it to the _data repository.
912
+	 *
913
+	 * @param mixed  $generating_data           This is data expected by the instantiated data handler.
914
+	 * @param string $data_handler_class_name   This is the reference string indicating what data handler is being
915
+	 *                                          instantiated.
916
+	 */
917
+	protected function _set_data_handler($generating_data, $data_handler_class_name)
918
+	{
919
+		// valid classname for the data handler.  Now let's setup the key for the data handler repository to see if
920
+		// there is already a ready data handler in the repository.
921
+		$this->_current_data_handler = $this->_data_handler_collection->get_by_key(
922
+			$this->_data_handler_collection->get_key(
923
+				$data_handler_class_name,
924
+				$generating_data
925
+			)
926
+		);
927
+		if (! $this->_current_data_handler instanceof EE_Messages_incoming_data) {
928
+			// no saved data_handler in the repo so let's set one up and add it to the repo.
929
+			try {
930
+				$this->_current_data_handler = new $data_handler_class_name($generating_data);
931
+				$this->_data_handler_collection->add($this->_current_data_handler, $generating_data);
932
+			} catch (Exception $e) {
933
+				$this->_error_msg[] = $e->getMessage();
934
+			}
935
+		}
936
+	}
937
+
938
+
939
+	/**
940
+	 * The queued EE_Message for generation does not save the data used for generation as objects
941
+	 * because serialization of those objects could be problematic if the data is saved to the db.
942
+	 * So this method calls the static method on the associated data_handler for the given message_type
943
+	 * and that preps the data for later instantiation when generating.
944
+	 *
945
+	 * @param EE_Message_To_Generate $message_to_generate
946
+	 * @param bool                   $preview Indicate whether this is being used for a preview or not.
947
+	 * @return mixed Prepped data for persisting to the queue.  false is returned if unable to prep data.
948
+	 */
949
+	protected function _prepare_data_for_queue(EE_Message_To_Generate $message_to_generate, $preview)
950
+	{
951
+		if (! $message_to_generate->valid()) {
952
+			return false; // unable to get the data because the info in the EE_Message_To_Generate class is invalid.
953
+		}
954
+		/** @type EE_Messages_incoming_data $data_handler - well not really... just the class name actually */
955
+		$data_handler = $message_to_generate->get_data_handler_class_name($preview);
956
+		return $data_handler::convert_data_for_persistent_storage($message_to_generate->data());
957
+	}
958
+
959
+
960
+	/**
961
+	 * This sets up a EEM_Message::status_incomplete EE_Message object and adds it to the generation queue.
962
+	 *
963
+	 * @param EE_Message_To_Generate $message_to_generate
964
+	 * @param bool                   $test_send Whether this is just a test send or not.  Typically used for previews.
965
+	 * @return bool
966
+	 * @throws InvalidArgumentException
967
+	 * @throws InvalidDataTypeException
968
+	 * @throws InvalidInterfaceException
969
+	 */
970
+	public function create_and_add_message_to_queue(EE_Message_To_Generate $message_to_generate, $test_send = false)
971
+	{
972
+		// prep data
973
+		$data    = $this->_prepare_data_for_queue($message_to_generate, $message_to_generate->preview());
974
+		$request = LoaderFactory::getLoader()->getShared('EventEspresso\core\services\request\RequestInterface');
975
+
976
+		$message = $message_to_generate->get_EE_Message();
977
+		$GRP_ID  = $request->getRequestParam('GRP_ID', 0, 'int');
978
+
979
+		$GRP_ID = apply_filters(
980
+			'FHEE__EE_Messages_Generator__create_and_add_message_to_queue_GRP_ID',
981
+			$GRP_ID > 0 ? $GRP_ID : $message->GRP_ID(),
982
+			$message,
983
+			$message_to_generate,
984
+			$test_send
985
+		);
986
+
987
+		if ($GRP_ID > 0) {
988
+			$message->set_GRP_ID($GRP_ID);
989
+		}
990
+
991
+		if ($data === false) {
992
+			$message->set_STS_ID(EEM_Message::status_failed);
993
+			$message->set_error_message(
994
+				esc_html__(
995
+					'Unable to prepare data for persistence to the database.',
996
+					'event_espresso'
997
+				)
998
+			);
999
+		} else {
1000
+			// make sure that the data handler is cached on the message as well
1001
+			$data['data_handler_class_name'] = $message_to_generate->get_data_handler_class_name();
1002
+		}
1003
+
1004
+		return $this->_generation_queue->add($message, $data, $message_to_generate->preview(), $test_send);
1005
+	}
1006 1006
 }
Please login to merge, or discard this patch.
Spacing   +22 added lines, -22 removed lines patch added patch discarded remove patch
@@ -266,7 +266,7 @@  discard block
 block discarded – undo
266 266
     {
267 267
         // double check verification has run and that everything is ready to work with (saves us having to validate
268 268
         // everything again).
269
-        if (! $this->_verified) {
269
+        if ( ! $this->_verified) {
270 270
             return false; // get out because we don't have a valid setup to work with.
271 271
         }
272 272
 
@@ -283,7 +283,7 @@  discard block
 block discarded – undo
283 283
 
284 284
 
285 285
         // if no addressees then get out because there is nothing to generation (possible bad data).
286
-        if (! $this->_valid_addressees($addressees)) {
286
+        if ( ! $this->_valid_addressees($addressees)) {
287 287
             do_action(
288 288
                 'AHEE__EE_Messages_Generator___generate__invalid_addressees',
289 289
                 $this->_generation_queue->get_message_repository()->current(),
@@ -305,7 +305,7 @@  discard block
 block discarded – undo
305 305
         $message_template_group = $this->_get_message_template_group();
306 306
 
307 307
         // in the unlikely event there is no EE_Message_Template_Group available, get out!
308
-        if (! $message_template_group instanceof EE_Message_Template_Group) {
308
+        if ( ! $message_template_group instanceof EE_Message_Template_Group) {
309 309
             $this->_error_msg[] = esc_html__(
310 310
                 'Unable to get the Message Templates for the Message being generated.  No message template group accessible.',
311 311
                 'event_espresso'
@@ -417,7 +417,7 @@  discard block
 block discarded – undo
417 417
             // attempt to retrieve from repo first
418 418
             $message_template_group = $this->_template_collection->get_by_ID($GRP_ID);
419 419
             if ($message_template_group instanceof EE_Message_Template_Group) {
420
-                return $message_template_group;  // got it!
420
+                return $message_template_group; // got it!
421 421
             }
422 422
 
423 423
             // nope don't have it yet.  Get from DB then add to repo if its not here, then that means the current GRP_ID
@@ -446,7 +446,7 @@  discard block
 block discarded – undo
446 446
     protected function _queue_shares_same_message_template_group_for_events(array $event_ids)
447 447
     {
448 448
         foreach ($this->_current_data_handler->events as $event) {
449
-            $event_ids[ $event['ID'] ] = $event['ID'];
449
+            $event_ids[$event['ID']] = $event['ID'];
450 450
         }
451 451
         $count_of_message_template_groups = EEM_Message_Template_Group::instance()->count(
452 452
             [
@@ -522,7 +522,7 @@  discard block
 block discarded – undo
522 522
         );
523 523
 
524 524
         // if we don't have a group lets hit the db.
525
-        if (! $global_message_template_group instanceof EE_Message_Template_Group) {
525
+        if ( ! $global_message_template_group instanceof EE_Message_Template_Group) {
526 526
             $global_message_template_group = EEM_Message_Template_Group::instance()->get_one(
527 527
                 [
528 528
                     [
@@ -554,7 +554,7 @@  discard block
 block discarded – undo
554 554
     {
555 555
         $event_ids = [];
556 556
         foreach ($this->_current_data_handler->events as $event) {
557
-            $event_ids[ $event['ID'] ] = $event['ID'];
557
+            $event_ids[$event['ID']] = $event['ID'];
558 558
         }
559 559
         return $event_ids;
560 560
     }
@@ -583,10 +583,10 @@  discard block
 block discarded – undo
583 583
         $context_templates = $message_template_group->context_templates();
584 584
         foreach ($context_templates as $context => $template_fields) {
585 585
             foreach ($template_fields as $template_field => $template_obj) {
586
-                if (! $template_obj instanceof EE_Message_Template) {
586
+                if ( ! $template_obj instanceof EE_Message_Template) {
587 587
                     continue;
588 588
                 }
589
-                $templates[ $template_field ][ $context ] = $template_obj->get('MTP_content');
589
+                $templates[$template_field][$context] = $template_obj->get('MTP_content');
590 590
             }
591 591
         }
592 592
         return $templates;
@@ -617,7 +617,7 @@  discard block
 block discarded – undo
617 617
     {
618 618
 
619 619
         // if templates are empty then get out because we can't generate anything.
620
-        if (! $templates) {
620
+        if ( ! $templates) {
621 621
             $this->_error_msg[] = esc_html__(
622 622
                 'Unable to assemble messages because there are no templates retrieved for generating the messages with',
623 623
                 'event_espresso'
@@ -707,7 +707,7 @@  discard block
 block discarded – undo
707 707
         if (
708 708
             ! $this->_generation_queue->get_message_repository()->is_preview()
709 709
             && (
710
-                (empty($templates['to'][ $context ]) && ! $this->_current_messenger->allow_empty_to_field())
710
+                (empty($templates['to'][$context]) && ! $this->_current_messenger->allow_empty_to_field())
711 711
                 || ! $message_template_group->is_context_active($context)
712 712
             )
713 713
         ) {
@@ -719,15 +719,15 @@  discard block
 block discarded – undo
719 719
         foreach ($templates as $field => $field_context) {
720 720
             $error_msg = [];
721 721
             // let's setup the valid shortcodes for the incoming context.
722
-            $valid_shortcodes = $mt_shortcodes[ $context ];
722
+            $valid_shortcodes = $mt_shortcodes[$context];
723 723
             // merge in valid shortcodes for the field.
724
-            $shortcodes = isset($m_shortcodes[ $field ]) ? $m_shortcodes[ $field ] : $valid_shortcodes;
725
-            if (isset($field_context[ $context ])) {
724
+            $shortcodes = isset($m_shortcodes[$field]) ? $m_shortcodes[$field] : $valid_shortcodes;
725
+            if (isset($field_context[$context])) {
726 726
                 // prefix field.
727
-                $column_name = 'MSG_' . $field;
727
+                $column_name = 'MSG_'.$field;
728 728
                 try {
729 729
                     $content = $this->_shortcode_parser->parse_message_template(
730
-                        $field_context[ $context ],
730
+                        $field_context[$context],
731 731
                         $recipient,
732 732
                         $shortcodes,
733 733
                         $this->_current_message_type,
@@ -791,13 +791,13 @@  discard block
 block discarded – undo
791 791
      */
792 792
     protected function _valid_addressees($addressees)
793 793
     {
794
-        if (! $addressees || ! is_array($addressees)) {
794
+        if ( ! $addressees || ! is_array($addressees)) {
795 795
             return false;
796 796
         }
797 797
 
798 798
         foreach ($addressees as $addressee_array) {
799 799
             foreach ($addressee_array as $addressee) {
800
-                if (! $addressee instanceof EE_Messages_Addressee) {
800
+                if ( ! $addressee instanceof EE_Messages_Addressee) {
801 801
                     return false;
802 802
                 }
803 803
             }
@@ -875,7 +875,7 @@  discard block
 block discarded – undo
875 875
         /** @type EE_Messages_incoming_data $data_handler_class_name - well not really... just the class name actually */
876 876
         $data_handler_class_name = $this->_generation_queue->get_message_repository()->get_data_handler()
877 877
             ? $this->_generation_queue->get_message_repository()->get_data_handler()
878
-            : 'EE_Messages_' . $this->_current_message_type->get_data_handler($generation_data) . '_incoming_data';
878
+            : 'EE_Messages_'.$this->_current_message_type->get_data_handler($generation_data).'_incoming_data';
879 879
 
880 880
         // If this EE_Message is for a preview, then let's switch out to the preview data handler.
881 881
         if ($this->_generation_queue->get_message_repository()->is_preview()) {
@@ -883,7 +883,7 @@  discard block
 block discarded – undo
883 883
         }
884 884
 
885 885
         // First get the class name for the data handler (and also verifies it exists.
886
-        if (! class_exists($data_handler_class_name)) {
886
+        if ( ! class_exists($data_handler_class_name)) {
887 887
             $this->_error_msg[] = sprintf(
888 888
             /* Translators: Both placeholders are the names of php classes. */
889 889
                 esc_html__(
@@ -924,7 +924,7 @@  discard block
 block discarded – undo
924 924
                 $generating_data
925 925
             )
926 926
         );
927
-        if (! $this->_current_data_handler instanceof EE_Messages_incoming_data) {
927
+        if ( ! $this->_current_data_handler instanceof EE_Messages_incoming_data) {
928 928
             // no saved data_handler in the repo so let's set one up and add it to the repo.
929 929
             try {
930 930
                 $this->_current_data_handler = new $data_handler_class_name($generating_data);
@@ -948,7 +948,7 @@  discard block
 block discarded – undo
948 948
      */
949 949
     protected function _prepare_data_for_queue(EE_Message_To_Generate $message_to_generate, $preview)
950 950
     {
951
-        if (! $message_to_generate->valid()) {
951
+        if ( ! $message_to_generate->valid()) {
952 952
             return false; // unable to get the data because the info in the EE_Message_To_Generate class is invalid.
953 953
         }
954 954
         /** @type EE_Messages_incoming_data $data_handler - well not really... just the class name actually */
Please login to merge, or discard this patch.
core/libraries/messages/EE_Message_To_Generate.php 2 patches
Spacing   +2 added lines, -2 removed lines patch added patch discarded remove patch
@@ -297,8 +297,8 @@
 block discarded – undo
297 297
      */
298 298
     public static function verify_and_retrieve_class_name_for_data_handler_reference($data_handler_reference)
299 299
     {
300
-        $class_name = 'EE_Messages_' . $data_handler_reference . '_incoming_data';
301
-        if (! class_exists($class_name)) {
300
+        $class_name = 'EE_Messages_'.$data_handler_reference.'_incoming_data';
301
+        if ( ! class_exists($class_name)) {
302 302
             EE_Error::add_error(
303 303
                 sprintf(
304 304
                     esc_html__(
Please login to merge, or discard this patch.
Indentation   +304 added lines, -304 removed lines patch added patch discarded remove patch
@@ -11,308 +11,308 @@
 block discarded – undo
11 11
  */
12 12
 class EE_Message_To_Generate
13 13
 {
14
-    /**
15
-     * @var string
16
-     */
17
-    protected $_messenger_name;
18
-
19
-    /**
20
-     * @var string
21
-     */
22
-    protected $_message_type_name;
23
-
24
-    /**
25
-     * @var EE_messenger
26
-     */
27
-    protected $_messenger;
28
-
29
-    /**
30
-     * @var EE_message_type
31
-     */
32
-    protected $_message_type;
33
-
34
-    /**
35
-     * Identifier for the context the message is to be generated for.
36
-     *
37
-     * @var string
38
-     */
39
-    protected $_context = '';
40
-
41
-    /**
42
-     * Data that will be used to generate message.
43
-     *
44
-     * @var array
45
-     */
46
-    protected $_data = [];
47
-
48
-    /**
49
-     * Whether this message is for a preview or not.
50
-     *
51
-     * @var bool
52
-     */
53
-    protected $_preview = false;
54
-
55
-    /**
56
-     * @var EE_Message
57
-     */
58
-    protected $_message;
59
-
60
-    /**
61
-     * This is set by the constructor to indicate whether the incoming messenger
62
-     * and message type are valid.  This can then be checked by callers to determine whether
63
-     * to generate this message or not.
64
-     *
65
-     * @var bool
66
-     */
67
-    protected $_valid = false;
68
-
69
-    /**
70
-     * If there are any errors (non exception errors) they get added to this array for callers to decide
71
-     * how to handle.
72
-     *
73
-     * @var array
74
-     */
75
-    protected $_error_msg = [];
76
-
77
-    /**
78
-     * Can be accessed via the send_now() method, this is set in the validation
79
-     * routine via the EE_messenger::send_now() method.
80
-     *
81
-     * @var bool
82
-     */
83
-    protected $_send_now = false;
84
-
85
-    /**
86
-     * Holds the classname for the data handler used by the current message type.
87
-     * This is set on the first call to the public `get_data_handler_class_name()` method.
88
-     *
89
-     * @var string
90
-     */
91
-    protected $_data_handler_class_name = '';
92
-
93
-    /**
94
-     * one of the message status constants on EEM_Message
95
-     *
96
-     * @var string
97
-     * @since 4.10.29.p
98
-     */
99
-    protected $_status = '';
100
-
101
-    /**
102
-     * use $_status var above
103
-     *
104
-     * @var string
105
-     * @deprecated 4.10.29.p
106
-     */
107
-    protected $_message_status = '';
108
-
109
-
110
-    /**
111
-     * Constructor
112
-     *
113
-     * @param string $messenger_name    Slug representing messenger
114
-     * @param string $message_type_name Slug representing message type.
115
-     * @param mixed  $data              Data used for generating message.
116
-     * @param string $context           Optional context to restrict message generated for.
117
-     * @param bool   $preview           Whether this is being used to generate a preview or not.
118
-     * @param string $status
119
-     */
120
-    public function __construct(
121
-        $messenger_name,
122
-        $message_type_name,
123
-        $data = [],
124
-        $context = '',
125
-        $preview = false,
126
-        $status = EEM_Message::status_incomplete
127
-    ) {
128
-        $this->_messenger_name    = $messenger_name;
129
-        $this->_message_type_name = $message_type_name;
130
-        $this->_data              = is_array($data) ? $data : [$data];
131
-        $this->_context           = $context;
132
-        $this->_preview           = $preview;
133
-        $this->_status            = $status;
134
-        // attempt to generate message immediately
135
-        $this->_message = $this->_generate_message();
136
-    }
137
-
138
-
139
-    /**
140
-     * @return string
141
-     */
142
-    public function context()
143
-    {
144
-        return $this->_context;
145
-    }
146
-
147
-
148
-    /**
149
-     * @return array
150
-     */
151
-    public function data()
152
-    {
153
-        return $this->_data;
154
-    }
155
-
156
-
157
-    /**
158
-     * @return EE_messenger
159
-     */
160
-    public function messenger()
161
-    {
162
-        return $this->_messenger;
163
-    }
164
-
165
-
166
-    /**
167
-     * @return EE_message_type
168
-     */
169
-    public function message_type()
170
-    {
171
-        return $this->_message_type;
172
-    }
173
-
174
-
175
-    /**
176
-     * @return boolean
177
-     */
178
-    public function preview()
179
-    {
180
-        return $this->_preview;
181
-    }
182
-
183
-
184
-    /**
185
-     * @param boolean $preview
186
-     */
187
-    public function set_preview($preview)
188
-    {
189
-        $this->_preview = filter_var($preview, FILTER_VALIDATE_BOOLEAN);
190
-    }
191
-
192
-
193
-    /**
194
-     * @return bool
195
-     */
196
-    public function send_now()
197
-    {
198
-        return $this->_send_now;
199
-    }
200
-
201
-
202
-    /**
203
-     * Simply returns the state of the $_valid property.
204
-     *
205
-     * @return bool
206
-     */
207
-    public function valid()
208
-    {
209
-        return $this->_valid;
210
-    }
211
-
212
-
213
-    /**
214
-     * generates an EE_Message using the supplied arguments and some defaults
215
-     *
216
-     * @param array $properties
217
-     * @return EE_Message
218
-     */
219
-    protected function _generate_message($properties = [])
220
-    {
221
-        $message = EE_Message_Factory::create(
222
-            array_merge(
223
-                [
224
-                    'MSG_messenger'    => $this->_messenger_name,
225
-                    'MSG_message_type' => $this->_message_type_name,
226
-                    'MSG_context'      => $this->_context,
227
-                    'STS_ID'           => $this->_status,
228
-                ],
229
-                $properties
230
-            )
231
-        );
232
-        // validate the message, and if it's good, set some properties
233
-        try {
234
-            $message->is_valid_for_sending_or_generation(true);
235
-            $this->_valid        = true;
236
-            $this->_messenger    = $message->messenger_object();
237
-            $this->_message_type = $message->message_type_object();
238
-            $this->_send_now     = $message->send_now();
239
-        } catch (Exception $e) {
240
-            $this->_valid       = false;
241
-            $this->_error_msg[] = $e->getMessage();
242
-        }
243
-        return $message;
244
-    }
245
-
246
-
247
-    /**
248
-     *  Returns an instantiated EE_Message object from the internal data.
249
-     *
250
-     * @return EE_Message
251
-     */
252
-    public function get_EE_Message()
253
-    {
254
-        // already set ?
255
-        if ($this->_message instanceof EE_Message) {
256
-            return $this->_message;
257
-        }
258
-        // no? then let's create one
259
-        $this->_message = $this->_generate_message();
260
-        return $this->_message;
261
-    }
262
-
263
-
264
-    /**
265
-     * This returns the data_handler class name for the internal message type set.
266
-     * Note: this also verifies that the data handler class exists.  If it doesn't then $_valid is set to false
267
-     * and the data_handler_class name is set to an empty string.
268
-     *
269
-     * @param bool $preview Used to indicate that the preview data handler is to be returned.
270
-     * @return  string
271
-     */
272
-    public function get_data_handler_class_name($preview = false)
273
-    {
274
-        if ($this->_data_handler_class_name === '' && $this->valid()) {
275
-            $ref = $preview ? 'Preview' : $this->_message_type->get_data_handler($this->_data);
276
-            // make sure internal data is updated.
277
-            $this->_data = $this->_message_type->get_data();
278
-
279
-            // verify
280
-            $this->_data_handler_class_name =
281
-                EE_Message_To_Generate::verify_and_retrieve_class_name_for_data_handler_reference($ref);
282
-            if ($this->_data_handler_class_name === '') {
283
-                $this->_valid = false;
284
-            }
285
-        }
286
-        return $this->_data_handler_class_name;
287
-    }
288
-
289
-
290
-    /**
291
-     * Validates the given string as a reference for an existing, accessible data handler and returns the class name
292
-     * For the handler the reference matches.
293
-     *
294
-     * @param string $data_handler_reference
295
-     * @return string
296
-     */
297
-    public static function verify_and_retrieve_class_name_for_data_handler_reference($data_handler_reference)
298
-    {
299
-        $class_name = 'EE_Messages_' . $data_handler_reference . '_incoming_data';
300
-        if (! class_exists($class_name)) {
301
-            EE_Error::add_error(
302
-                sprintf(
303
-                    esc_html__(
304
-                        'The included data handler reference (%s) does not match any valid, accessible, "EE_Messages_incoming_data" classes.  Looking for %s.',
305
-                        'event_espresso'
306
-                    ),
307
-                    $data_handler_reference,
308
-                    $class_name
309
-                ),
310
-                __FILE__,
311
-                __FUNCTION__,
312
-                __LINE__
313
-            );
314
-            $class_name = ''; // clear out class_name so caller knows this isn't valid.
315
-        }
316
-        return $class_name;
317
-    }
14
+	/**
15
+	 * @var string
16
+	 */
17
+	protected $_messenger_name;
18
+
19
+	/**
20
+	 * @var string
21
+	 */
22
+	protected $_message_type_name;
23
+
24
+	/**
25
+	 * @var EE_messenger
26
+	 */
27
+	protected $_messenger;
28
+
29
+	/**
30
+	 * @var EE_message_type
31
+	 */
32
+	protected $_message_type;
33
+
34
+	/**
35
+	 * Identifier for the context the message is to be generated for.
36
+	 *
37
+	 * @var string
38
+	 */
39
+	protected $_context = '';
40
+
41
+	/**
42
+	 * Data that will be used to generate message.
43
+	 *
44
+	 * @var array
45
+	 */
46
+	protected $_data = [];
47
+
48
+	/**
49
+	 * Whether this message is for a preview or not.
50
+	 *
51
+	 * @var bool
52
+	 */
53
+	protected $_preview = false;
54
+
55
+	/**
56
+	 * @var EE_Message
57
+	 */
58
+	protected $_message;
59
+
60
+	/**
61
+	 * This is set by the constructor to indicate whether the incoming messenger
62
+	 * and message type are valid.  This can then be checked by callers to determine whether
63
+	 * to generate this message or not.
64
+	 *
65
+	 * @var bool
66
+	 */
67
+	protected $_valid = false;
68
+
69
+	/**
70
+	 * If there are any errors (non exception errors) they get added to this array for callers to decide
71
+	 * how to handle.
72
+	 *
73
+	 * @var array
74
+	 */
75
+	protected $_error_msg = [];
76
+
77
+	/**
78
+	 * Can be accessed via the send_now() method, this is set in the validation
79
+	 * routine via the EE_messenger::send_now() method.
80
+	 *
81
+	 * @var bool
82
+	 */
83
+	protected $_send_now = false;
84
+
85
+	/**
86
+	 * Holds the classname for the data handler used by the current message type.
87
+	 * This is set on the first call to the public `get_data_handler_class_name()` method.
88
+	 *
89
+	 * @var string
90
+	 */
91
+	protected $_data_handler_class_name = '';
92
+
93
+	/**
94
+	 * one of the message status constants on EEM_Message
95
+	 *
96
+	 * @var string
97
+	 * @since 4.10.29.p
98
+	 */
99
+	protected $_status = '';
100
+
101
+	/**
102
+	 * use $_status var above
103
+	 *
104
+	 * @var string
105
+	 * @deprecated 4.10.29.p
106
+	 */
107
+	protected $_message_status = '';
108
+
109
+
110
+	/**
111
+	 * Constructor
112
+	 *
113
+	 * @param string $messenger_name    Slug representing messenger
114
+	 * @param string $message_type_name Slug representing message type.
115
+	 * @param mixed  $data              Data used for generating message.
116
+	 * @param string $context           Optional context to restrict message generated for.
117
+	 * @param bool   $preview           Whether this is being used to generate a preview or not.
118
+	 * @param string $status
119
+	 */
120
+	public function __construct(
121
+		$messenger_name,
122
+		$message_type_name,
123
+		$data = [],
124
+		$context = '',
125
+		$preview = false,
126
+		$status = EEM_Message::status_incomplete
127
+	) {
128
+		$this->_messenger_name    = $messenger_name;
129
+		$this->_message_type_name = $message_type_name;
130
+		$this->_data              = is_array($data) ? $data : [$data];
131
+		$this->_context           = $context;
132
+		$this->_preview           = $preview;
133
+		$this->_status            = $status;
134
+		// attempt to generate message immediately
135
+		$this->_message = $this->_generate_message();
136
+	}
137
+
138
+
139
+	/**
140
+	 * @return string
141
+	 */
142
+	public function context()
143
+	{
144
+		return $this->_context;
145
+	}
146
+
147
+
148
+	/**
149
+	 * @return array
150
+	 */
151
+	public function data()
152
+	{
153
+		return $this->_data;
154
+	}
155
+
156
+
157
+	/**
158
+	 * @return EE_messenger
159
+	 */
160
+	public function messenger()
161
+	{
162
+		return $this->_messenger;
163
+	}
164
+
165
+
166
+	/**
167
+	 * @return EE_message_type
168
+	 */
169
+	public function message_type()
170
+	{
171
+		return $this->_message_type;
172
+	}
173
+
174
+
175
+	/**
176
+	 * @return boolean
177
+	 */
178
+	public function preview()
179
+	{
180
+		return $this->_preview;
181
+	}
182
+
183
+
184
+	/**
185
+	 * @param boolean $preview
186
+	 */
187
+	public function set_preview($preview)
188
+	{
189
+		$this->_preview = filter_var($preview, FILTER_VALIDATE_BOOLEAN);
190
+	}
191
+
192
+
193
+	/**
194
+	 * @return bool
195
+	 */
196
+	public function send_now()
197
+	{
198
+		return $this->_send_now;
199
+	}
200
+
201
+
202
+	/**
203
+	 * Simply returns the state of the $_valid property.
204
+	 *
205
+	 * @return bool
206
+	 */
207
+	public function valid()
208
+	{
209
+		return $this->_valid;
210
+	}
211
+
212
+
213
+	/**
214
+	 * generates an EE_Message using the supplied arguments and some defaults
215
+	 *
216
+	 * @param array $properties
217
+	 * @return EE_Message
218
+	 */
219
+	protected function _generate_message($properties = [])
220
+	{
221
+		$message = EE_Message_Factory::create(
222
+			array_merge(
223
+				[
224
+					'MSG_messenger'    => $this->_messenger_name,
225
+					'MSG_message_type' => $this->_message_type_name,
226
+					'MSG_context'      => $this->_context,
227
+					'STS_ID'           => $this->_status,
228
+				],
229
+				$properties
230
+			)
231
+		);
232
+		// validate the message, and if it's good, set some properties
233
+		try {
234
+			$message->is_valid_for_sending_or_generation(true);
235
+			$this->_valid        = true;
236
+			$this->_messenger    = $message->messenger_object();
237
+			$this->_message_type = $message->message_type_object();
238
+			$this->_send_now     = $message->send_now();
239
+		} catch (Exception $e) {
240
+			$this->_valid       = false;
241
+			$this->_error_msg[] = $e->getMessage();
242
+		}
243
+		return $message;
244
+	}
245
+
246
+
247
+	/**
248
+	 *  Returns an instantiated EE_Message object from the internal data.
249
+	 *
250
+	 * @return EE_Message
251
+	 */
252
+	public function get_EE_Message()
253
+	{
254
+		// already set ?
255
+		if ($this->_message instanceof EE_Message) {
256
+			return $this->_message;
257
+		}
258
+		// no? then let's create one
259
+		$this->_message = $this->_generate_message();
260
+		return $this->_message;
261
+	}
262
+
263
+
264
+	/**
265
+	 * This returns the data_handler class name for the internal message type set.
266
+	 * Note: this also verifies that the data handler class exists.  If it doesn't then $_valid is set to false
267
+	 * and the data_handler_class name is set to an empty string.
268
+	 *
269
+	 * @param bool $preview Used to indicate that the preview data handler is to be returned.
270
+	 * @return  string
271
+	 */
272
+	public function get_data_handler_class_name($preview = false)
273
+	{
274
+		if ($this->_data_handler_class_name === '' && $this->valid()) {
275
+			$ref = $preview ? 'Preview' : $this->_message_type->get_data_handler($this->_data);
276
+			// make sure internal data is updated.
277
+			$this->_data = $this->_message_type->get_data();
278
+
279
+			// verify
280
+			$this->_data_handler_class_name =
281
+				EE_Message_To_Generate::verify_and_retrieve_class_name_for_data_handler_reference($ref);
282
+			if ($this->_data_handler_class_name === '') {
283
+				$this->_valid = false;
284
+			}
285
+		}
286
+		return $this->_data_handler_class_name;
287
+	}
288
+
289
+
290
+	/**
291
+	 * Validates the given string as a reference for an existing, accessible data handler and returns the class name
292
+	 * For the handler the reference matches.
293
+	 *
294
+	 * @param string $data_handler_reference
295
+	 * @return string
296
+	 */
297
+	public static function verify_and_retrieve_class_name_for_data_handler_reference($data_handler_reference)
298
+	{
299
+		$class_name = 'EE_Messages_' . $data_handler_reference . '_incoming_data';
300
+		if (! class_exists($class_name)) {
301
+			EE_Error::add_error(
302
+				sprintf(
303
+					esc_html__(
304
+						'The included data handler reference (%s) does not match any valid, accessible, "EE_Messages_incoming_data" classes.  Looking for %s.',
305
+						'event_espresso'
306
+					),
307
+					$data_handler_reference,
308
+					$class_name
309
+				),
310
+				__FILE__,
311
+				__FUNCTION__,
312
+				__LINE__
313
+			);
314
+			$class_name = ''; // clear out class_name so caller knows this isn't valid.
315
+		}
316
+		return $class_name;
317
+	}
318 318
 }
Please login to merge, or discard this patch.
core/libraries/batch/JobHandlers/PreviewEventDeletion.php 2 patches
Spacing   +2 added lines, -2 removed lines patch added patch discarded remove patch
@@ -215,7 +215,7 @@  discard block
 block discarded – undo
215 215
             if ($units_processed >= $batch_size) {
216 216
                 break;
217 217
             }
218
-            if (!$root_node instanceof ModelObjNode) {
218
+            if ( ! $root_node instanceof ModelObjNode) {
219 219
                 throw new InvalidClassException('ModelObjNode');
220 220
             }
221 221
             if ($root_node->isComplete()) {
@@ -226,7 +226,7 @@  discard block
 block discarded – undo
226 226
         $job_parameters->mark_processed($units_processed);
227 227
         // If the most-recently processed root node is complete, we must be all done because we're doing them
228 228
         // sequentially.
229
-        if (! isset($root_node) || (isset($root_node) && $root_node instanceof ModelObjNode && $root_node->isComplete())) {
229
+        if ( ! isset($root_node) || (isset($root_node) && $root_node instanceof ModelObjNode && $root_node->isComplete())) {
230 230
             $job_parameters->set_status(JobParameters::status_complete);
231 231
             // Show a full progress bar.
232 232
             $job_parameters->set_units_processed($job_parameters->job_size());
Please login to merge, or discard this patch.
Indentation   +213 added lines, -213 removed lines patch added patch discarded remove patch
@@ -33,149 +33,149 @@  discard block
 block discarded – undo
33 33
  */
34 34
 class PreviewEventDeletion extends JobHandler
35 35
 {
36
-    /**
37
-     * @var NodeGroupDao
38
-     */
39
-    protected $model_obj_node_group_persister;
36
+	/**
37
+	 * @var NodeGroupDao
38
+	 */
39
+	protected $model_obj_node_group_persister;
40 40
 
41
-    public function __construct(NodeGroupDao $model_obj_node_group_persister)
42
-    {
43
-        $this->model_obj_node_group_persister = $model_obj_node_group_persister;
44
-    }
41
+	public function __construct(NodeGroupDao $model_obj_node_group_persister)
42
+	{
43
+		$this->model_obj_node_group_persister = $model_obj_node_group_persister;
44
+	}
45 45
 
46
-    // phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
46
+	// phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
47 47
 
48
-    /**
49
-     *
50
-     * @param JobParameters $job_parameters
51
-     * @return JobStepResponse
52
-     * @throws EE_Error
53
-     * @throws InvalidDataTypeException
54
-     * @throws InvalidInterfaceException
55
-     * @throws InvalidArgumentException
56
-     * @throws ReflectionException
57
-     */
58
-    public function create_job(JobParameters $job_parameters)
59
-    {
60
-        // Set the "root" model objects we will want to delete (record their ID and model)
61
-        $event_ids = $job_parameters->request_datum('EVT_IDs', array());
62
-        // Find all the root nodes to delete (this isn't just events, because there's other data, like related tickets,
63
-        // prices, message templates, etc, whose model definition doesn't make them dependent on events. But,
64
-        // we have no UI to access them independent of events, so they may as well get deleted too.)
65
-        $roots = [];
66
-        foreach ($event_ids as $event_id) {
67
-            $roots[] = new ModelObjNode(
68
-                $event_id,
69
-                EEM_Event::instance()
70
-            );
71
-            // Also, we want to delete their related, non-global, tickets, prices and message templates
72
-            $related_non_global_tickets = EEM_Ticket::instance()->get_all_deleted_and_undeleted(
73
-                [
74
-                    [
75
-                        'TKT_is_default' => false,
76
-                        'Datetime.EVT_ID' => $event_id
77
-                    ]
78
-                ]
79
-            );
80
-            foreach ($related_non_global_tickets as $ticket) {
81
-                $roots[] = new ModelObjNode(
82
-                    $ticket->ID(),
83
-                    $ticket->get_model(),
84
-                    ['Registration']
85
-                );
86
-            }
87
-            $related_non_global_prices = EEM_Price::instance()->get_all_deleted_and_undeleted(
88
-                [
89
-                    [
90
-                        'PRC_is_default' => false,
91
-                        'Ticket.Datetime.EVT_ID' => $event_id
92
-                    ]
93
-                ]
94
-            );
95
-            foreach ($related_non_global_prices as $price) {
96
-                $roots[] = new ModelObjNode(
97
-                    $price->ID(),
98
-                    $price->get_model()
99
-                );
100
-            }
101
-        }
102
-        $transactions_ids = $this->getTransactionsToDelete($event_ids);
103
-        foreach ($transactions_ids as $transaction_id) {
104
-            $roots[] = new ModelObjNode(
105
-                $transaction_id,
106
-                EEM_Transaction::instance(),
107
-                ['Registration']
108
-            );
109
-        }
110
-        $job_parameters->add_extra_data('roots', $roots);
111
-        // Set an estimate of how long this will take (we're discovering as we go, so it seems impossible to give
112
-        // an accurate count.)
113
-        $estimated_work_per_model_obj = 10;
114
-        $count_regs = EEM_Registration::instance()->count(
115
-            [
116
-                [
117
-                    'EVT_ID' => ['IN', $event_ids]
118
-                ]
119
-            ]
120
-        );
121
-        $job_parameters->set_job_size((count($roots) + $count_regs) * $estimated_work_per_model_obj);
122
-        return new JobStepResponse(
123
-            $job_parameters,
124
-            esc_html__('Generating preview of data to be deleted...', 'event_espresso')
125
-        );
126
-    }
48
+	/**
49
+	 *
50
+	 * @param JobParameters $job_parameters
51
+	 * @return JobStepResponse
52
+	 * @throws EE_Error
53
+	 * @throws InvalidDataTypeException
54
+	 * @throws InvalidInterfaceException
55
+	 * @throws InvalidArgumentException
56
+	 * @throws ReflectionException
57
+	 */
58
+	public function create_job(JobParameters $job_parameters)
59
+	{
60
+		// Set the "root" model objects we will want to delete (record their ID and model)
61
+		$event_ids = $job_parameters->request_datum('EVT_IDs', array());
62
+		// Find all the root nodes to delete (this isn't just events, because there's other data, like related tickets,
63
+		// prices, message templates, etc, whose model definition doesn't make them dependent on events. But,
64
+		// we have no UI to access them independent of events, so they may as well get deleted too.)
65
+		$roots = [];
66
+		foreach ($event_ids as $event_id) {
67
+			$roots[] = new ModelObjNode(
68
+				$event_id,
69
+				EEM_Event::instance()
70
+			);
71
+			// Also, we want to delete their related, non-global, tickets, prices and message templates
72
+			$related_non_global_tickets = EEM_Ticket::instance()->get_all_deleted_and_undeleted(
73
+				[
74
+					[
75
+						'TKT_is_default' => false,
76
+						'Datetime.EVT_ID' => $event_id
77
+					]
78
+				]
79
+			);
80
+			foreach ($related_non_global_tickets as $ticket) {
81
+				$roots[] = new ModelObjNode(
82
+					$ticket->ID(),
83
+					$ticket->get_model(),
84
+					['Registration']
85
+				);
86
+			}
87
+			$related_non_global_prices = EEM_Price::instance()->get_all_deleted_and_undeleted(
88
+				[
89
+					[
90
+						'PRC_is_default' => false,
91
+						'Ticket.Datetime.EVT_ID' => $event_id
92
+					]
93
+				]
94
+			);
95
+			foreach ($related_non_global_prices as $price) {
96
+				$roots[] = new ModelObjNode(
97
+					$price->ID(),
98
+					$price->get_model()
99
+				);
100
+			}
101
+		}
102
+		$transactions_ids = $this->getTransactionsToDelete($event_ids);
103
+		foreach ($transactions_ids as $transaction_id) {
104
+			$roots[] = new ModelObjNode(
105
+				$transaction_id,
106
+				EEM_Transaction::instance(),
107
+				['Registration']
108
+			);
109
+		}
110
+		$job_parameters->add_extra_data('roots', $roots);
111
+		// Set an estimate of how long this will take (we're discovering as we go, so it seems impossible to give
112
+		// an accurate count.)
113
+		$estimated_work_per_model_obj = 10;
114
+		$count_regs = EEM_Registration::instance()->count(
115
+			[
116
+				[
117
+					'EVT_ID' => ['IN', $event_ids]
118
+				]
119
+			]
120
+		);
121
+		$job_parameters->set_job_size((count($roots) + $count_regs) * $estimated_work_per_model_obj);
122
+		return new JobStepResponse(
123
+			$job_parameters,
124
+			esc_html__('Generating preview of data to be deleted...', 'event_espresso')
125
+		);
126
+	}
127 127
 
128
-    /**
129
-     * @since 4.10.12.p
130
-     * @param EE_Base_Class[] $model_objs
131
-     * @param array $dont_traverse_models
132
-     * @return array
133
-     * @throws EE_Error
134
-     * @throws InvalidArgumentException
135
-     * @throws InvalidDataTypeException
136
-     * @throws InvalidInterfaceException
137
-     * @throws ReflectionException
138
-     */
139
-    protected function createModelObjNodes($model_objs, array $dont_traverse_models = [])
140
-    {
141
-        $nodes = [];
142
-        foreach ($model_objs as $model_obj) {
143
-            $nodes[] = new ModelObjNode(
144
-                $model_obj->ID(),
145
-                $model_obj->get_model(),
146
-                $dont_traverse_models
147
-            );
148
-        }
149
-        return $nodes;
150
-    }
128
+	/**
129
+	 * @since 4.10.12.p
130
+	 * @param EE_Base_Class[] $model_objs
131
+	 * @param array $dont_traverse_models
132
+	 * @return array
133
+	 * @throws EE_Error
134
+	 * @throws InvalidArgumentException
135
+	 * @throws InvalidDataTypeException
136
+	 * @throws InvalidInterfaceException
137
+	 * @throws ReflectionException
138
+	 */
139
+	protected function createModelObjNodes($model_objs, array $dont_traverse_models = [])
140
+	{
141
+		$nodes = [];
142
+		foreach ($model_objs as $model_obj) {
143
+			$nodes[] = new ModelObjNode(
144
+				$model_obj->ID(),
145
+				$model_obj->get_model(),
146
+				$dont_traverse_models
147
+			);
148
+		}
149
+		return $nodes;
150
+	}
151 151
 
152
-    /**
153
-     * Gets all the transactions related to these events that aren't related to other events. They'll be deleted too.
154
-     * (Ones that are related to other events can stay around until those other events are deleted too.)
155
-     * @since 4.10.12.p
156
-     * @param $event_ids
157
-     * @return array of transaction IDs
158
-     */
159
-    protected function getTransactionsToDelete($event_ids)
160
-    {
161
-        if (empty($event_ids)) {
162
-            return [];
163
-        }
164
-        global $wpdb;
165
-        $event_ids = array_map(
166
-            'intval',
167
-            $event_ids
168
-        );
169
-        $imploded_sanitized_event_ids = implode(',', $event_ids);
170
-        // Select transactions with registrations for the events $event_ids which also don't have registrations
171
-        // for any events NOT in $event_ids.
172
-        // Notice the outer query searched for transactions whose registrations ARE in $event_ids,
173
-        // whereas the inner query checks if the outer query's transaction has any registrations that are
174
-        // NOT IN $event_ids (ie, don't have registrations for events we're not just about to delete.)
175
-        return array_map(
176
-            'intval',
177
-            $wpdb->get_col(
178
-                "SELECT
152
+	/**
153
+	 * Gets all the transactions related to these events that aren't related to other events. They'll be deleted too.
154
+	 * (Ones that are related to other events can stay around until those other events are deleted too.)
155
+	 * @since 4.10.12.p
156
+	 * @param $event_ids
157
+	 * @return array of transaction IDs
158
+	 */
159
+	protected function getTransactionsToDelete($event_ids)
160
+	{
161
+		if (empty($event_ids)) {
162
+			return [];
163
+		}
164
+		global $wpdb;
165
+		$event_ids = array_map(
166
+			'intval',
167
+			$event_ids
168
+		);
169
+		$imploded_sanitized_event_ids = implode(',', $event_ids);
170
+		// Select transactions with registrations for the events $event_ids which also don't have registrations
171
+		// for any events NOT in $event_ids.
172
+		// Notice the outer query searched for transactions whose registrations ARE in $event_ids,
173
+		// whereas the inner query checks if the outer query's transaction has any registrations that are
174
+		// NOT IN $event_ids (ie, don't have registrations for events we're not just about to delete.)
175
+		return array_map(
176
+			'intval',
177
+			$wpdb->get_col(
178
+				"SELECT
179 179
                       DISTINCT t.TXN_ID
180 180
                     FROM
181 181
                       {$wpdb->prefix}esp_transaction t INNER JOIN
@@ -193,83 +193,83 @@  discard block
 block discarded – undo
193 193
                            tsub.TXN_ID=t.TXN_ID AND
194 194
                            rsub.EVT_ID NOT IN ({$imploded_sanitized_event_ids})
195 195
                        )"
196
-            )
197
-        );
198
-    }
196
+			)
197
+		);
198
+	}
199 199
 
200
-    /**
201
-     * Performs another step of the job
202
-     * @param JobParameters $job_parameters
203
-     * @param int $batch_size
204
-     * @return JobStepResponse
205
-     */
206
-    public function continue_job(JobParameters $job_parameters, $batch_size = 50)
207
-    {
208
-        // Serializing and unserializing is what really makes this drag on (eg on localhost, the ajax requests took
209
-        // about 4 seconds when the batch size was 250, but 3 seconds when the batch size was 50. So like
210
-        // 50% of the request is just serializing and unserializing.) So, make the batches much bigger.
211
-        $batch_size *= 3;
212
-        $units_processed = 0;
213
-        foreach ($job_parameters->extra_datum('roots', array()) as $root_node) {
214
-            if ($units_processed >= $batch_size) {
215
-                break;
216
-            }
217
-            if (!$root_node instanceof ModelObjNode) {
218
-                throw new InvalidClassException('ModelObjNode');
219
-            }
220
-            if ($root_node->isComplete()) {
221
-                continue;
222
-            }
223
-            $units_processed += $root_node->visit($batch_size - $units_processed);
224
-        }
225
-        $job_parameters->mark_processed($units_processed);
226
-        // If the most-recently processed root node is complete, we must be all done because we're doing them
227
-        // sequentially.
228
-        if (! isset($root_node) || (isset($root_node) && $root_node instanceof ModelObjNode && $root_node->isComplete())) {
229
-            $job_parameters->set_status(JobParameters::status_complete);
230
-            // Show a full progress bar.
231
-            $job_parameters->set_units_processed($job_parameters->job_size());
232
-            $deletion_job_code = $job_parameters->request_datum('deletion_job_code');
233
-            $this->model_obj_node_group_persister->persistModelObjNodesGroup(
234
-                $job_parameters->extra_datum('roots'),
235
-                $deletion_job_code
236
-            );
237
-            return new JobStepResponse(
238
-                $job_parameters,
239
-                esc_html__('Finished identifying items for deletion.', 'event_espresso'),
240
-                [
241
-                    'deletion_job_code' => $deletion_job_code
242
-                ]
243
-            );
244
-        } else {
245
-            // Because the job size was a guess, it may have likely been proven wrong. We don't want to show more work
246
-            // done than we originally said there would be. So adjust the estimate.
247
-            if (($job_parameters->units_processed() / $job_parameters->job_size()) > .8) {
248
-                $job_parameters->set_job_size($job_parameters->job_size() * 2);
249
-            }
250
-            return new JobStepResponse(
251
-                $job_parameters,
252
-                sprintf(
253
-                    esc_html__('Identified %d items for deletion.', 'event_espresso'),
254
-                    $units_processed
255
-                )
256
-            );
257
-        }
258
-    }
200
+	/**
201
+	 * Performs another step of the job
202
+	 * @param JobParameters $job_parameters
203
+	 * @param int $batch_size
204
+	 * @return JobStepResponse
205
+	 */
206
+	public function continue_job(JobParameters $job_parameters, $batch_size = 50)
207
+	{
208
+		// Serializing and unserializing is what really makes this drag on (eg on localhost, the ajax requests took
209
+		// about 4 seconds when the batch size was 250, but 3 seconds when the batch size was 50. So like
210
+		// 50% of the request is just serializing and unserializing.) So, make the batches much bigger.
211
+		$batch_size *= 3;
212
+		$units_processed = 0;
213
+		foreach ($job_parameters->extra_datum('roots', array()) as $root_node) {
214
+			if ($units_processed >= $batch_size) {
215
+				break;
216
+			}
217
+			if (!$root_node instanceof ModelObjNode) {
218
+				throw new InvalidClassException('ModelObjNode');
219
+			}
220
+			if ($root_node->isComplete()) {
221
+				continue;
222
+			}
223
+			$units_processed += $root_node->visit($batch_size - $units_processed);
224
+		}
225
+		$job_parameters->mark_processed($units_processed);
226
+		// If the most-recently processed root node is complete, we must be all done because we're doing them
227
+		// sequentially.
228
+		if (! isset($root_node) || (isset($root_node) && $root_node instanceof ModelObjNode && $root_node->isComplete())) {
229
+			$job_parameters->set_status(JobParameters::status_complete);
230
+			// Show a full progress bar.
231
+			$job_parameters->set_units_processed($job_parameters->job_size());
232
+			$deletion_job_code = $job_parameters->request_datum('deletion_job_code');
233
+			$this->model_obj_node_group_persister->persistModelObjNodesGroup(
234
+				$job_parameters->extra_datum('roots'),
235
+				$deletion_job_code
236
+			);
237
+			return new JobStepResponse(
238
+				$job_parameters,
239
+				esc_html__('Finished identifying items for deletion.', 'event_espresso'),
240
+				[
241
+					'deletion_job_code' => $deletion_job_code
242
+				]
243
+			);
244
+		} else {
245
+			// Because the job size was a guess, it may have likely been proven wrong. We don't want to show more work
246
+			// done than we originally said there would be. So adjust the estimate.
247
+			if (($job_parameters->units_processed() / $job_parameters->job_size()) > .8) {
248
+				$job_parameters->set_job_size($job_parameters->job_size() * 2);
249
+			}
250
+			return new JobStepResponse(
251
+				$job_parameters,
252
+				sprintf(
253
+					esc_html__('Identified %d items for deletion.', 'event_espresso'),
254
+					$units_processed
255
+				)
256
+			);
257
+		}
258
+	}
259 259
 
260
-    /**
261
-     * Performs any clean-up logic when we know the job is completed
262
-     * @param JobParameters $job_parameters
263
-     * @return JobStepResponse
264
-     */
265
-    public function cleanup_job(JobParameters $job_parameters)
266
-    {
267
-        // Nothing much to do. We can't delete the option with the built tree because we may need it in a moment for the deletion
268
-        return new JobStepResponse(
269
-            $job_parameters,
270
-            esc_html__('All done', 'event_espresso')
271
-        );
272
-    }
260
+	/**
261
+	 * Performs any clean-up logic when we know the job is completed
262
+	 * @param JobParameters $job_parameters
263
+	 * @return JobStepResponse
264
+	 */
265
+	public function cleanup_job(JobParameters $job_parameters)
266
+	{
267
+		// Nothing much to do. We can't delete the option with the built tree because we may need it in a moment for the deletion
268
+		return new JobStepResponse(
269
+			$job_parameters,
270
+			esc_html__('All done', 'event_espresso')
271
+		);
272
+	}
273 273
 }
274 274
 // End of file EventDeletion.php
275 275
 // Location: EventEspressoBatchRequest\JobHandlers/EventDeletion.php
Please login to merge, or discard this patch.