Completed
Pull Request — master (#938)
by
unknown
10:28
created
core/libraries/messages/EE_Messages_Generator.lib.php 3 patches
Doc Comments   +3 added lines, -3 removed lines patch added patch discarded remove patch
@@ -468,7 +468,7 @@  discard block
 block discarded – undo
468 468
      * there's a single shared message template group among all the events.  Otherwise it returns null.
469 469
      *
470 470
      * @param array $event_ids
471
-     * @return EE_Message_Template_Group|null
471
+     * @return null|EE_Base_Class
472 472
      * @throws EE_Error
473 473
      * @throws InvalidArgumentException
474 474
      * @throws InvalidDataTypeException
@@ -504,7 +504,7 @@  discard block
 block discarded – undo
504 504
     /**
505 505
      * Retrieves the global message template group for the current messenger and message type.
506 506
      *
507
-     * @return EE_Message_Template_Group|null
507
+     * @return null|EE_Base_Class
508 508
      * @throws EE_Error
509 509
      * @throws InvalidArgumentException
510 510
      * @throws InvalidDataTypeException
@@ -659,7 +659,7 @@  discard block
 block discarded – undo
659 659
      * @param EE_Messages_Addressee     $recipient
660 660
      * @param array                     $templates formatted array of templates used for parsing data.
661 661
      * @param EE_Message_Template_Group $message_template_group
662
-     * @return bool|EE_Message
662
+     * @return EE_Message
663 663
      * @throws EE_Error
664 664
      * @throws InvalidArgumentException
665 665
      * @throws InvalidDataTypeException
Please login to merge, or discard this patch.
Indentation   +992 added lines, -992 removed lines patch added patch discarded remove patch
@@ -17,997 +17,997 @@
 block discarded – undo
17 17
 {
18 18
 
19 19
 
20
-    /**
21
-     * @type EE_Messages_Data_Handler_Collection
22
-     */
23
-    protected $_data_handler_collection;
24
-
25
-    /**
26
-     * @type  EE_Message_Template_Group_Collection
27
-     */
28
-    protected $_template_collection;
29
-
30
-    /**
31
-     * This will hold the data handler for the current EE_Message being generated.
32
-     *
33
-     * @type EE_Messages_incoming_data
34
-     */
35
-    protected $_current_data_handler;
36
-
37
-    /**
38
-     * This holds the EE_Messages_Queue that contains the messages to generate.
39
-     *
40
-     * @type EE_Messages_Queue
41
-     */
42
-    protected $_generation_queue;
43
-
44
-    /**
45
-     * This holds the EE_Messages_Queue that will store the generated EE_Message objects.
46
-     *
47
-     * @type EE_Messages_Queue
48
-     */
49
-    protected $_ready_queue;
50
-
51
-    /**
52
-     * This is a container for any error messages that get created through the generation
53
-     * process.
54
-     *
55
-     * @type array
56
-     */
57
-    protected $_error_msg = array();
58
-
59
-    /**
60
-     * Flag used to set when the current EE_Message in the generation queue has been verified.
61
-     *
62
-     * @type bool
63
-     */
64
-    protected $_verified = false;
65
-
66
-    /**
67
-     * This will hold the current messenger object corresponding with the current EE_Message in the generation queue.
68
-     *
69
-     * @type EE_messenger
70
-     */
71
-    protected $_current_messenger;
72
-
73
-    /**
74
-     * This will hold the current message type object corresponding with the current EE_Message in the generation queue.
75
-     *
76
-     * @type EE_message_type
77
-     */
78
-    protected $_current_message_type;
79
-
80
-    /**
81
-     * @type EEH_Parse_Shortcodes
82
-     */
83
-    protected $_shortcode_parser;
84
-
85
-
86
-    /**
87
-     * @param EE_Messages_Queue                     $generation_queue
88
-     * @param \EE_Messages_Queue                    $ready_queue
89
-     * @param \EE_Messages_Data_Handler_Collection  $data_handler_collection
90
-     * @param \EE_Message_Template_Group_Collection $template_collection
91
-     * @param \EEH_Parse_Shortcodes                 $shortcode_parser
92
-     */
93
-    public function __construct(
94
-        EE_Messages_Queue $generation_queue,
95
-        EE_Messages_Queue $ready_queue,
96
-        EE_Messages_Data_Handler_Collection $data_handler_collection,
97
-        EE_Message_Template_Group_Collection $template_collection,
98
-        EEH_Parse_Shortcodes $shortcode_parser
99
-    ) {
100
-        $this->_generation_queue        = $generation_queue;
101
-        $this->_ready_queue             = $ready_queue;
102
-        $this->_data_handler_collection = $data_handler_collection;
103
-        $this->_template_collection     = $template_collection;
104
-        $this->_shortcode_parser        = $shortcode_parser;
105
-    }
106
-
107
-
108
-    /**
109
-     * @return EE_Messages_Queue
110
-     */
111
-    public function generation_queue()
112
-    {
113
-        return $this->_generation_queue;
114
-    }
115
-
116
-
117
-    /**
118
-     *  This iterates through the provided queue and generates the EE_Message objects.
119
-     *  When iterating through the queue, the queued item that served as the base for generating other EE_Message
120
-     *  objects gets removed and the new EE_Message objects get added to a NEW queue.  The NEW queue is then returned
121
-     *  for the caller to decide what to do with it.
122
-     *
123
-     * @param   bool $save Whether to save the EE_Message objects in the new queue or just return.
124
-     * @return EE_Messages_Queue The new queue for holding generated EE_Message objects.
125
-     * @throws EE_Error
126
-     * @throws InvalidArgumentException
127
-     * @throws InvalidDataTypeException
128
-     * @throws InvalidInterfaceException
129
-     * @throws ReflectionException
130
-     */
131
-    public function generate($save = true)
132
-    {
133
-        // iterate through the messages in the queue, generate, and add to new queue.
134
-        $this->_generation_queue->get_message_repository()->rewind();
135
-        while ($this->_generation_queue->get_message_repository()->valid()) {
136
-            // reset "current" properties
137
-            $this->_reset_current_properties();
138
-
139
-            /** @type EE_Message $msg */
140
-            $msg = $this->_generation_queue->get_message_repository()->current();
141
-
142
-            /**
143
-             * need to get the next object and capture it for setting manually after deletes.  The reason is that when
144
-             * an object is removed from the repo then valid for the next object will fail.
145
-             */
146
-            $this->_generation_queue->get_message_repository()->next();
147
-            $next_msg = $this->_generation_queue->get_message_repository()->current();
148
-            // restore pointer to current item
149
-            $this->_generation_queue->get_message_repository()->set_current($msg);
150
-
151
-            // skip and delete if the current $msg is NOT incomplete (queued for generation)
152
-            if ($msg->STS_ID() !== EEM_Message::status_incomplete) {
153
-                // we keep this item in the db just remove from the repo.
154
-                $this->_generation_queue->get_message_repository()->remove($msg);
155
-                // next item
156
-                $this->_generation_queue->get_message_repository()->set_current($next_msg);
157
-                continue;
158
-            }
159
-
160
-            if ($this->_verify()) {
161
-                // let's get generating!
162
-                $this->_generate();
163
-            }
164
-
165
-            // don't persist debug_only messages if the messages system is not in debug mode.
166
-            if ($msg->STS_ID() === EEM_Message::status_debug_only
167
-                && ! EEM_Message::debug()
168
-            ) {
169
-                do_action(
170
-                    'AHEE__EE_Messages_Generator__generate__before_debug_delete',
171
-                    $msg,
172
-                    $this->_error_msg,
173
-                    $this->_current_messenger,
174
-                    $this->_current_message_type,
175
-                    $this->_current_data_handler
176
-                );
177
-                $this->_generation_queue->get_message_repository()->delete();
178
-                $this->_generation_queue->get_message_repository()->set_current($next_msg);
179
-                continue;
180
-            }
181
-
182
-            // if there are error messages then let's set the status and the error message.
183
-            if ($this->_error_msg) {
184
-                // if the status is already debug only, then let's leave it at that.
185
-                if ($msg->STS_ID() !== EEM_Message::status_debug_only) {
186
-                    $msg->set_STS_ID(EEM_Message::status_failed);
187
-                }
188
-                do_action(
189
-                    'AHEE__EE_Messages_Generator__generate__processing_failed_message',
190
-                    $msg,
191
-                    $this->_error_msg,
192
-                    $this->_current_messenger,
193
-                    $this->_current_message_type,
194
-                    $this->_current_data_handler
195
-                );
196
-                $msg->set_error_message(
197
-                    esc_html__('Message failed to generate for the following reasons: ', 'event_espresso')
198
-                    . "\n"
199
-                    . implode("\n", $this->_error_msg)
200
-                );
201
-                $msg->set_modified(time());
202
-            } else {
203
-                do_action(
204
-                    'AHEE__EE_Messages_Generator__generate__before_successful_generated_message_delete',
205
-                    $msg,
206
-                    $this->_error_msg,
207
-                    $this->_current_messenger,
208
-                    $this->_current_message_type,
209
-                    $this->_current_data_handler
210
-                );
211
-                // remove from db
212
-                $this->_generation_queue->get_message_repository()->delete();
213
-            }
214
-            // next item
215
-            $this->_generation_queue->get_message_repository()->set_current($next_msg);
216
-        }
217
-
218
-        // generation queue is ALWAYS saved to record any errors in the generation process.
219
-        $this->_generation_queue->save();
220
-
221
-        /**
222
-         * save _ready_queue if flag set.
223
-         * Note: The EE_Message objects have values set via the EE_Base_Class::set_field_or_extra_meta() method.  This
224
-         * means if a field was added that is not a valid database column.  The EE_Message was already saved to the db
225
-         * so a EE_Extra_Meta entry could be created and attached to the EE_Message.  In those cases the save flag is
226
-         * irrelevant.
227
-         */
228
-        if ($save) {
229
-            $this->_ready_queue->save();
230
-        }
231
-
232
-        // final reset of properties
233
-        $this->_reset_current_properties();
234
-
235
-        return $this->_ready_queue;
236
-    }
237
-
238
-
239
-    /**
240
-     * This resets all the properties used for holding "current" values corresponding to the current EE_Message object
241
-     * in the generation queue.
242
-     */
243
-    protected function _reset_current_properties()
244
-    {
245
-        $this->_verified = false;
246
-        // make sure any _data value in the current message type is reset
247
-        if ($this->_current_message_type instanceof EE_message_type) {
248
-            $this->_current_message_type->reset_data();
249
-        }
250
-        $this->_current_messenger = $this->_current_message_type = $this->_current_data_handler = null;
251
-    }
252
-
253
-
254
-    /**
255
-     * This proceeds with the actual generation of a message.  By the time this is called, there should already be a
256
-     * $_current_data_handler set and all incoming information should be validated for the current EE_Message in the
257
-     * _generating_queue.
258
-     *
259
-     * @return bool Whether the message was successfully generated or not.
260
-     * @throws EE_Error
261
-     * @throws InvalidArgumentException
262
-     * @throws InvalidDataTypeException
263
-     * @throws InvalidInterfaceException
264
-     * @throws ReflectionException
265
-     */
266
-    protected function _generate()
267
-    {
268
-        // double check verification has run and that everything is ready to work with (saves us having to validate
269
-        // everything again).
270
-        if (! $this->_verified) {
271
-            return false; // get out because we don't have a valid setup to work with.
272
-        }
273
-
274
-
275
-        try {
276
-            $addressees = $this->_current_message_type->get_addressees(
277
-                $this->_current_data_handler,
278
-                $this->_generation_queue->get_message_repository()->current()->context()
279
-            );
280
-        } catch (EE_Error $e) {
281
-            $this->_error_msg[] = $e->getMessage();
282
-            return false;
283
-        }
284
-
285
-
286
-        // if no addressees then get out because there is nothing to generation (possible bad data).
287
-        if (! $this->_valid_addressees($addressees)) {
288
-            do_action(
289
-                'AHEE__EE_Messages_Generator___generate__invalid_addressees',
290
-                $this->_generation_queue->get_message_repository()->current(),
291
-                $addressees,
292
-                $this->_current_messenger,
293
-                $this->_current_message_type,
294
-                $this->_current_data_handler
295
-            );
296
-            $this->_generation_queue->get_message_repository()->current()->set_STS_ID(
297
-                EEM_Message::status_debug_only
298
-            );
299
-            $this->_error_msg[] = esc_html__(
300
-                '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.',
301
-                'event_espresso'
302
-            );
303
-            return false;
304
-        }
305
-
306
-        $message_template_group = $this->_get_message_template_group();
307
-
308
-        // in the unlikely event there is no EE_Message_Template_Group available, get out!
309
-        if (! $message_template_group instanceof EE_Message_Template_Group) {
310
-            $this->_error_msg[] = esc_html__(
311
-                'Unable to get the Message Templates for the Message being generated.  No message template group accessible.',
312
-                'event_espresso'
313
-            );
314
-            return false;
315
-        }
316
-
317
-        // get formatted templates for using to parse and setup EE_Message objects.
318
-        $templates = $this->_get_templates($message_template_group);
319
-
320
-
321
-        // setup new EE_Message objects (and add to _ready_queue)
322
-        return $this->_assemble_messages($addressees, $templates, $message_template_group);
323
-    }
324
-
325
-
326
-    /**
327
-     * Retrieves the message template group being used for generating messages.
328
-     * Note: this also utilizes the EE_Message_Template_Group_Collection to avoid having to hit the db multiple times.
329
-     *
330
-     * @return EE_Message_Template_Group|null
331
-     * @throws EE_Error
332
-     * @throws InvalidArgumentException
333
-     * @throws InvalidDataTypeException
334
-     * @throws InvalidInterfaceException
335
-     * @throws ReflectionException
336
-     */
337
-    protected function _get_message_template_group()
338
-    {
339
-        // first see if there is a specific message template group requested (current message in the queue has a
340
-        // specific GRP_ID
341
-        $message_template_group = $this->_specific_message_template_group_from_queue();
342
-        if ($message_template_group instanceof EE_Message_Template_Group) {
343
-            return $message_template_group;
344
-        }
345
-
346
-        // get event_ids from the datahandler so we can check to see if there's already a message template group for
347
-        // them in the collection.
348
-        $event_ids              = $this->_get_event_ids_from_current_data_handler();
349
-        $message_template_group = $this->_template_collection->get_by_key(
350
-            $this->_template_collection->getKey(
351
-                $this->_current_messenger->name,
352
-                $this->_current_message_type->name,
353
-                $event_ids
354
-            )
355
-        );
356
-
357
-        // if we have a message template group then no need to hit the database, just return it.
358
-        if ($message_template_group instanceof EE_Message_Template_Group) {
359
-            return $message_template_group;
360
-        }
361
-
362
-        // okay made it here, so let's get the global group first for this messenger and message type to ensure
363
-        // there is no override set.
364
-        $global_message_template_group =
365
-            $this->_get_global_message_template_group_for_current_messenger_and_message_type();
366
-
367
-        if ($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
-            array(
453
-                array(
454
-                    'Event.EVT_ID'           => array('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
-                array(
483
-                    array(
484
-                        'Event.EVT_ID'           => array('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
-                array(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
-                array(
528
-                    array(
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
-                    array(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 = array();
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         = array();
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
-                        array(),
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 = array(
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 (! $this->_generation_queue->get_message_repository()->is_preview()
708
-            && (
709
-                            (
710
-                                empty($templates['to'][ $context ])
711
-                                && ! $this->_current_messenger->allow_empty_to_field()
712
-                            )
713
-                            || ! $message_template_group->is_context_active($context)
714
-                        )
715
-        ) {
716
-            // we silently exit here and do NOT record a fail because the message is "turned off" by having no "to"
717
-            // field.
718
-            return false;
719
-        }
720
-        $error_msg = array();
721
-        foreach ($templates as $field => $field_context) {
722
-            $error_msg = array();
723
-            // let's setup the valid shortcodes for the incoming context.
724
-            $valid_shortcodes = $mt_shortcodes[ $context ];
725
-            // merge in valid shortcodes for the field.
726
-            $shortcodes = isset($m_shortcodes[ $field ]) ? $m_shortcodes[ $field ] : $valid_shortcodes;
727
-            if (isset($templates[ $field ][ $context ])) {
728
-                // prefix field.
729
-                $column_name = 'MSG_' . $field;
730
-                try {
731
-                    $content = $this->_shortcode_parser->parse_message_template(
732
-                        $templates[ $field ][ $context ],
733
-                        $recipient,
734
-                        $shortcodes,
735
-                        $this->_current_message_type,
736
-                        $this->_current_messenger,
737
-                        $message
738
-                    );
739
-                    // the model field removes slashes when setting (usually necessary when the input is from the
740
-                    // request) but this value is from another model and has no slashes. So add them so it matchces
741
-                    // what the field expected (otherwise slashes will have been stripped from this an extra time)
742
-                    $message->set_field_or_extra_meta($column_name, addslashes($content));
743
-                } catch (EE_Error $e) {
744
-                    $error_msg[] = sprintf(
745
-                        /* Translators: First place holder is message model field name.
20
+	/**
21
+	 * @type EE_Messages_Data_Handler_Collection
22
+	 */
23
+	protected $_data_handler_collection;
24
+
25
+	/**
26
+	 * @type  EE_Message_Template_Group_Collection
27
+	 */
28
+	protected $_template_collection;
29
+
30
+	/**
31
+	 * This will hold the data handler for the current EE_Message being generated.
32
+	 *
33
+	 * @type EE_Messages_incoming_data
34
+	 */
35
+	protected $_current_data_handler;
36
+
37
+	/**
38
+	 * This holds the EE_Messages_Queue that contains the messages to generate.
39
+	 *
40
+	 * @type EE_Messages_Queue
41
+	 */
42
+	protected $_generation_queue;
43
+
44
+	/**
45
+	 * This holds the EE_Messages_Queue that will store the generated EE_Message objects.
46
+	 *
47
+	 * @type EE_Messages_Queue
48
+	 */
49
+	protected $_ready_queue;
50
+
51
+	/**
52
+	 * This is a container for any error messages that get created through the generation
53
+	 * process.
54
+	 *
55
+	 * @type array
56
+	 */
57
+	protected $_error_msg = array();
58
+
59
+	/**
60
+	 * Flag used to set when the current EE_Message in the generation queue has been verified.
61
+	 *
62
+	 * @type bool
63
+	 */
64
+	protected $_verified = false;
65
+
66
+	/**
67
+	 * This will hold the current messenger object corresponding with the current EE_Message in the generation queue.
68
+	 *
69
+	 * @type EE_messenger
70
+	 */
71
+	protected $_current_messenger;
72
+
73
+	/**
74
+	 * This will hold the current message type object corresponding with the current EE_Message in the generation queue.
75
+	 *
76
+	 * @type EE_message_type
77
+	 */
78
+	protected $_current_message_type;
79
+
80
+	/**
81
+	 * @type EEH_Parse_Shortcodes
82
+	 */
83
+	protected $_shortcode_parser;
84
+
85
+
86
+	/**
87
+	 * @param EE_Messages_Queue                     $generation_queue
88
+	 * @param \EE_Messages_Queue                    $ready_queue
89
+	 * @param \EE_Messages_Data_Handler_Collection  $data_handler_collection
90
+	 * @param \EE_Message_Template_Group_Collection $template_collection
91
+	 * @param \EEH_Parse_Shortcodes                 $shortcode_parser
92
+	 */
93
+	public function __construct(
94
+		EE_Messages_Queue $generation_queue,
95
+		EE_Messages_Queue $ready_queue,
96
+		EE_Messages_Data_Handler_Collection $data_handler_collection,
97
+		EE_Message_Template_Group_Collection $template_collection,
98
+		EEH_Parse_Shortcodes $shortcode_parser
99
+	) {
100
+		$this->_generation_queue        = $generation_queue;
101
+		$this->_ready_queue             = $ready_queue;
102
+		$this->_data_handler_collection = $data_handler_collection;
103
+		$this->_template_collection     = $template_collection;
104
+		$this->_shortcode_parser        = $shortcode_parser;
105
+	}
106
+
107
+
108
+	/**
109
+	 * @return EE_Messages_Queue
110
+	 */
111
+	public function generation_queue()
112
+	{
113
+		return $this->_generation_queue;
114
+	}
115
+
116
+
117
+	/**
118
+	 *  This iterates through the provided queue and generates the EE_Message objects.
119
+	 *  When iterating through the queue, the queued item that served as the base for generating other EE_Message
120
+	 *  objects gets removed and the new EE_Message objects get added to a NEW queue.  The NEW queue is then returned
121
+	 *  for the caller to decide what to do with it.
122
+	 *
123
+	 * @param   bool $save Whether to save the EE_Message objects in the new queue or just return.
124
+	 * @return EE_Messages_Queue The new queue for holding generated EE_Message objects.
125
+	 * @throws EE_Error
126
+	 * @throws InvalidArgumentException
127
+	 * @throws InvalidDataTypeException
128
+	 * @throws InvalidInterfaceException
129
+	 * @throws ReflectionException
130
+	 */
131
+	public function generate($save = true)
132
+	{
133
+		// iterate through the messages in the queue, generate, and add to new queue.
134
+		$this->_generation_queue->get_message_repository()->rewind();
135
+		while ($this->_generation_queue->get_message_repository()->valid()) {
136
+			// reset "current" properties
137
+			$this->_reset_current_properties();
138
+
139
+			/** @type EE_Message $msg */
140
+			$msg = $this->_generation_queue->get_message_repository()->current();
141
+
142
+			/**
143
+			 * need to get the next object and capture it for setting manually after deletes.  The reason is that when
144
+			 * an object is removed from the repo then valid for the next object will fail.
145
+			 */
146
+			$this->_generation_queue->get_message_repository()->next();
147
+			$next_msg = $this->_generation_queue->get_message_repository()->current();
148
+			// restore pointer to current item
149
+			$this->_generation_queue->get_message_repository()->set_current($msg);
150
+
151
+			// skip and delete if the current $msg is NOT incomplete (queued for generation)
152
+			if ($msg->STS_ID() !== EEM_Message::status_incomplete) {
153
+				// we keep this item in the db just remove from the repo.
154
+				$this->_generation_queue->get_message_repository()->remove($msg);
155
+				// next item
156
+				$this->_generation_queue->get_message_repository()->set_current($next_msg);
157
+				continue;
158
+			}
159
+
160
+			if ($this->_verify()) {
161
+				// let's get generating!
162
+				$this->_generate();
163
+			}
164
+
165
+			// don't persist debug_only messages if the messages system is not in debug mode.
166
+			if ($msg->STS_ID() === EEM_Message::status_debug_only
167
+				&& ! EEM_Message::debug()
168
+			) {
169
+				do_action(
170
+					'AHEE__EE_Messages_Generator__generate__before_debug_delete',
171
+					$msg,
172
+					$this->_error_msg,
173
+					$this->_current_messenger,
174
+					$this->_current_message_type,
175
+					$this->_current_data_handler
176
+				);
177
+				$this->_generation_queue->get_message_repository()->delete();
178
+				$this->_generation_queue->get_message_repository()->set_current($next_msg);
179
+				continue;
180
+			}
181
+
182
+			// if there are error messages then let's set the status and the error message.
183
+			if ($this->_error_msg) {
184
+				// if the status is already debug only, then let's leave it at that.
185
+				if ($msg->STS_ID() !== EEM_Message::status_debug_only) {
186
+					$msg->set_STS_ID(EEM_Message::status_failed);
187
+				}
188
+				do_action(
189
+					'AHEE__EE_Messages_Generator__generate__processing_failed_message',
190
+					$msg,
191
+					$this->_error_msg,
192
+					$this->_current_messenger,
193
+					$this->_current_message_type,
194
+					$this->_current_data_handler
195
+				);
196
+				$msg->set_error_message(
197
+					esc_html__('Message failed to generate for the following reasons: ', 'event_espresso')
198
+					. "\n"
199
+					. implode("\n", $this->_error_msg)
200
+				);
201
+				$msg->set_modified(time());
202
+			} else {
203
+				do_action(
204
+					'AHEE__EE_Messages_Generator__generate__before_successful_generated_message_delete',
205
+					$msg,
206
+					$this->_error_msg,
207
+					$this->_current_messenger,
208
+					$this->_current_message_type,
209
+					$this->_current_data_handler
210
+				);
211
+				// remove from db
212
+				$this->_generation_queue->get_message_repository()->delete();
213
+			}
214
+			// next item
215
+			$this->_generation_queue->get_message_repository()->set_current($next_msg);
216
+		}
217
+
218
+		// generation queue is ALWAYS saved to record any errors in the generation process.
219
+		$this->_generation_queue->save();
220
+
221
+		/**
222
+		 * save _ready_queue if flag set.
223
+		 * Note: The EE_Message objects have values set via the EE_Base_Class::set_field_or_extra_meta() method.  This
224
+		 * means if a field was added that is not a valid database column.  The EE_Message was already saved to the db
225
+		 * so a EE_Extra_Meta entry could be created and attached to the EE_Message.  In those cases the save flag is
226
+		 * irrelevant.
227
+		 */
228
+		if ($save) {
229
+			$this->_ready_queue->save();
230
+		}
231
+
232
+		// final reset of properties
233
+		$this->_reset_current_properties();
234
+
235
+		return $this->_ready_queue;
236
+	}
237
+
238
+
239
+	/**
240
+	 * This resets all the properties used for holding "current" values corresponding to the current EE_Message object
241
+	 * in the generation queue.
242
+	 */
243
+	protected function _reset_current_properties()
244
+	{
245
+		$this->_verified = false;
246
+		// make sure any _data value in the current message type is reset
247
+		if ($this->_current_message_type instanceof EE_message_type) {
248
+			$this->_current_message_type->reset_data();
249
+		}
250
+		$this->_current_messenger = $this->_current_message_type = $this->_current_data_handler = null;
251
+	}
252
+
253
+
254
+	/**
255
+	 * This proceeds with the actual generation of a message.  By the time this is called, there should already be a
256
+	 * $_current_data_handler set and all incoming information should be validated for the current EE_Message in the
257
+	 * _generating_queue.
258
+	 *
259
+	 * @return bool Whether the message was successfully generated or not.
260
+	 * @throws EE_Error
261
+	 * @throws InvalidArgumentException
262
+	 * @throws InvalidDataTypeException
263
+	 * @throws InvalidInterfaceException
264
+	 * @throws ReflectionException
265
+	 */
266
+	protected function _generate()
267
+	{
268
+		// double check verification has run and that everything is ready to work with (saves us having to validate
269
+		// everything again).
270
+		if (! $this->_verified) {
271
+			return false; // get out because we don't have a valid setup to work with.
272
+		}
273
+
274
+
275
+		try {
276
+			$addressees = $this->_current_message_type->get_addressees(
277
+				$this->_current_data_handler,
278
+				$this->_generation_queue->get_message_repository()->current()->context()
279
+			);
280
+		} catch (EE_Error $e) {
281
+			$this->_error_msg[] = $e->getMessage();
282
+			return false;
283
+		}
284
+
285
+
286
+		// if no addressees then get out because there is nothing to generation (possible bad data).
287
+		if (! $this->_valid_addressees($addressees)) {
288
+			do_action(
289
+				'AHEE__EE_Messages_Generator___generate__invalid_addressees',
290
+				$this->_generation_queue->get_message_repository()->current(),
291
+				$addressees,
292
+				$this->_current_messenger,
293
+				$this->_current_message_type,
294
+				$this->_current_data_handler
295
+			);
296
+			$this->_generation_queue->get_message_repository()->current()->set_STS_ID(
297
+				EEM_Message::status_debug_only
298
+			);
299
+			$this->_error_msg[] = esc_html__(
300
+				'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.',
301
+				'event_espresso'
302
+			);
303
+			return false;
304
+		}
305
+
306
+		$message_template_group = $this->_get_message_template_group();
307
+
308
+		// in the unlikely event there is no EE_Message_Template_Group available, get out!
309
+		if (! $message_template_group instanceof EE_Message_Template_Group) {
310
+			$this->_error_msg[] = esc_html__(
311
+				'Unable to get the Message Templates for the Message being generated.  No message template group accessible.',
312
+				'event_espresso'
313
+			);
314
+			return false;
315
+		}
316
+
317
+		// get formatted templates for using to parse and setup EE_Message objects.
318
+		$templates = $this->_get_templates($message_template_group);
319
+
320
+
321
+		// setup new EE_Message objects (and add to _ready_queue)
322
+		return $this->_assemble_messages($addressees, $templates, $message_template_group);
323
+	}
324
+
325
+
326
+	/**
327
+	 * Retrieves the message template group being used for generating messages.
328
+	 * Note: this also utilizes the EE_Message_Template_Group_Collection to avoid having to hit the db multiple times.
329
+	 *
330
+	 * @return EE_Message_Template_Group|null
331
+	 * @throws EE_Error
332
+	 * @throws InvalidArgumentException
333
+	 * @throws InvalidDataTypeException
334
+	 * @throws InvalidInterfaceException
335
+	 * @throws ReflectionException
336
+	 */
337
+	protected function _get_message_template_group()
338
+	{
339
+		// first see if there is a specific message template group requested (current message in the queue has a
340
+		// specific GRP_ID
341
+		$message_template_group = $this->_specific_message_template_group_from_queue();
342
+		if ($message_template_group instanceof EE_Message_Template_Group) {
343
+			return $message_template_group;
344
+		}
345
+
346
+		// get event_ids from the datahandler so we can check to see if there's already a message template group for
347
+		// them in the collection.
348
+		$event_ids              = $this->_get_event_ids_from_current_data_handler();
349
+		$message_template_group = $this->_template_collection->get_by_key(
350
+			$this->_template_collection->getKey(
351
+				$this->_current_messenger->name,
352
+				$this->_current_message_type->name,
353
+				$event_ids
354
+			)
355
+		);
356
+
357
+		// if we have a message template group then no need to hit the database, just return it.
358
+		if ($message_template_group instanceof EE_Message_Template_Group) {
359
+			return $message_template_group;
360
+		}
361
+
362
+		// okay made it here, so let's get the global group first for this messenger and message type to ensure
363
+		// there is no override set.
364
+		$global_message_template_group =
365
+			$this->_get_global_message_template_group_for_current_messenger_and_message_type();
366
+
367
+		if ($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
+			array(
453
+				array(
454
+					'Event.EVT_ID'           => array('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
+				array(
483
+					array(
484
+						'Event.EVT_ID'           => array('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
+				array(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
+				array(
528
+					array(
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
+					array(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 = array();
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         = array();
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
+						array(),
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 = array(
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 (! $this->_generation_queue->get_message_repository()->is_preview()
708
+			&& (
709
+							(
710
+								empty($templates['to'][ $context ])
711
+								&& ! $this->_current_messenger->allow_empty_to_field()
712
+							)
713
+							|| ! $message_template_group->is_context_active($context)
714
+						)
715
+		) {
716
+			// we silently exit here and do NOT record a fail because the message is "turned off" by having no "to"
717
+			// field.
718
+			return false;
719
+		}
720
+		$error_msg = array();
721
+		foreach ($templates as $field => $field_context) {
722
+			$error_msg = array();
723
+			// let's setup the valid shortcodes for the incoming context.
724
+			$valid_shortcodes = $mt_shortcodes[ $context ];
725
+			// merge in valid shortcodes for the field.
726
+			$shortcodes = isset($m_shortcodes[ $field ]) ? $m_shortcodes[ $field ] : $valid_shortcodes;
727
+			if (isset($templates[ $field ][ $context ])) {
728
+				// prefix field.
729
+				$column_name = 'MSG_' . $field;
730
+				try {
731
+					$content = $this->_shortcode_parser->parse_message_template(
732
+						$templates[ $field ][ $context ],
733
+						$recipient,
734
+						$shortcodes,
735
+						$this->_current_message_type,
736
+						$this->_current_messenger,
737
+						$message
738
+					);
739
+					// the model field removes slashes when setting (usually necessary when the input is from the
740
+					// request) but this value is from another model and has no slashes. So add them so it matchces
741
+					// what the field expected (otherwise slashes will have been stripped from this an extra time)
742
+					$message->set_field_or_extra_meta($column_name, addslashes($content));
743
+				} catch (EE_Error $e) {
744
+					$error_msg[] = sprintf(
745
+						/* Translators: First place holder is message model field name.
746 746
                          * Second placeholder is exception error message */
747
-                        esc_html__(
748
-                            'There was a problem generating the content for the field %s: %s',
749
-                            'event_espresso'
750
-                        ),
751
-                        $field,
752
-                        $e->getMessage()
753
-                    );
754
-                    $message->set_STS_ID(EEM_Message::status_failed);
755
-                }
756
-            }
757
-        }
758
-
759
-        if ($message->STS_ID() === EEM_Message::status_failed) {
760
-            $error_msg = esc_html__('There were problems generating this message:', 'event_espresso')
761
-                         . "\n"
762
-                         . implode("\n", $error_msg);
763
-            $message->set_error_message($error_msg);
764
-        } else {
765
-            $message->set_STS_ID(EEM_Message::status_idle);
766
-        }
767
-        return $message;
768
-    }
769
-
770
-
771
-    /**
772
-     * This verifies that the incoming array has a EE_messenger object and a EE_message_type object and sets appropriate
773
-     * error message if either is missing.
774
-     *
775
-     * @return bool true means there were no errors, false means there were errors.
776
-     */
777
-    protected function _verify()
778
-    {
779
-        // reset error message to an empty array.
780
-        $this->_error_msg = array();
781
-        $valid            = true;
782
-        $valid            = $valid ? $this->_validate_messenger_and_message_type() : $valid;
783
-        $valid            = $valid ? $this->_validate_and_setup_data() : $valid;
784
-
785
-        // set the verified flag so we know everything has been validated.
786
-        $this->_verified = $valid;
787
-
788
-        return $valid;
789
-    }
790
-
791
-
792
-    /**
793
-     * This accepts an array and validates that it is an array indexed by context with each value being an array of
794
-     * EE_Messages_Addressee objects.
795
-     *
796
-     * @param array $addressees Keys correspond to contexts for the message type and values are EE_Messages_Addressee[]
797
-     * @return bool
798
-     */
799
-    protected function _valid_addressees($addressees)
800
-    {
801
-        if (! $addressees || ! is_array($addressees)) {
802
-            return false;
803
-        }
804
-
805
-        foreach ($addressees as $addressee_array) {
806
-            foreach ($addressee_array as $addressee) {
807
-                if (! $addressee instanceof EE_Messages_Addressee) {
808
-                    return false;
809
-                }
810
-            }
811
-        }
812
-        return true;
813
-    }
814
-
815
-
816
-    /**
817
-     * This validates the messenger, message type, and presences of generation data for the current EE_Message in the
818
-     * queue. This process sets error messages if something is wrong.
819
-     *
820
-     * @return bool   true is if there are no errors.  false is if there is.
821
-     */
822
-    protected function _validate_messenger_and_message_type()
823
-    {
824
-
825
-        // first are there any existing error messages?  If so then return.
826
-        if ($this->_error_msg) {
827
-            return false;
828
-        }
829
-        /** @type EE_Message $message */
830
-        $message = $this->_generation_queue->get_message_repository()->current();
831
-        try {
832
-            $this->_current_messenger = $message->valid_messenger(true)
833
-                ? $message->messenger_object()
834
-                : null;
835
-        } catch (Exception $e) {
836
-            $this->_error_msg[] = $e->getMessage();
837
-        }
838
-        try {
839
-            $this->_current_message_type = $message->valid_message_type(true)
840
-                ? $message->message_type_object()
841
-                : null;
842
-        } catch (Exception $e) {
843
-            $this->_error_msg[] = $e->getMessage();
844
-        }
845
-
846
-        /**
847
-         * Check if there is any generation data, but only if this is not for a preview.
848
-         */
849
-        if (! $this->_generation_queue->get_message_repository()->get_generation_data()
850
-            && (
851
-                ! $this->_generation_queue->get_message_repository()->is_preview()
852
-                && $this->_generation_queue->get_message_repository()->get_data_handler()
853
-                   !== 'EE_Messages_Preview_incoming_data'
854
-            )
855
-        ) {
856
-            $this->_error_msg[] = esc_html__(
857
-                'There is no generation data for this message. Unable to generate.',
858
-                'event_espresso'
859
-            );
860
-        }
861
-
862
-        return empty($this->_error_msg);
863
-    }
864
-
865
-
866
-    /**
867
-     * This method retrieves the expected data handler for the message type and validates the generation data for that
868
-     * data handler.
869
-     *
870
-     * @return bool true means there are no errors.  false means there were errors (and handler did not get setup).
871
-     */
872
-    protected function _validate_and_setup_data()
873
-    {
874
-
875
-        // First, are there any existing error messages?  If so, return because if there were errors elsewhere this
876
-        // can't be used anyways.
877
-        if ($this->_error_msg) {
878
-            return false;
879
-        }
880
-
881
-        $generation_data = $this->_generation_queue->get_message_repository()->get_generation_data();
882
-
883
-        /** @type EE_Messages_incoming_data $data_handler_class_name - well not really... just the class name actually*/
884
-        $data_handler_class_name = $this->_generation_queue->get_message_repository()->get_data_handler()
885
-            ? $this->_generation_queue->get_message_repository()->get_data_handler()
886
-            : 'EE_Messages_' . $this->_current_message_type->get_data_handler($generation_data) . '_incoming_data';
887
-
888
-        // If this EE_Message is for a preview, then let's switch out to the preview data handler.
889
-        if ($this->_generation_queue->get_message_repository()->is_preview()) {
890
-            $data_handler_class_name = 'EE_Messages_Preview_incoming_data';
891
-        }
892
-
893
-        // First get the class name for the data handler (and also verifies it exists.
894
-        if (! class_exists($data_handler_class_name)) {
895
-            $this->_error_msg[] = sprintf(
896
-                /* Translators: Both placeholders are the names of php classes. */
897
-                esc_html__(
898
-                    'The included data handler class name does not match any valid, accessible, "%1$s" classes.  Looking for %2$s.',
899
-                    'event_espresso'
900
-                ),
901
-                'EE_Messages_incoming_data',
902
-                $data_handler_class_name
903
-            );
904
-            return false;
905
-        }
906
-
907
-        // convert generation_data for data_handler_instantiation.
908
-        $generation_data = $data_handler_class_name::convert_data_from_persistent_storage($generation_data);
909
-
910
-        // note, this may set error messages as well.
911
-        $this->_set_data_handler($generation_data, $data_handler_class_name);
912
-
913
-        return empty($this->_error_msg);
914
-    }
915
-
916
-
917
-    /**
918
-     * Sets the $_current_data_handler property that is used for generating the current EE_Message in the queue, and
919
-     * adds it to the _data repository.
920
-     *
921
-     * @param mixed  $generating_data           This is data expected by the instantiated data handler.
922
-     * @param string $data_handler_class_name   This is the reference string indicating what data handler is being
923
-     *                                          instantiated.
924
-     */
925
-    protected function _set_data_handler($generating_data, $data_handler_class_name)
926
-    {
927
-        // valid classname for the data handler.  Now let's setup the key for the data handler repository to see if
928
-        // there is already a ready data handler in the repository.
929
-        $this->_current_data_handler = $this->_data_handler_collection->get_by_key(
930
-            $this->_data_handler_collection->get_key(
931
-                $data_handler_class_name,
932
-                $generating_data
933
-            )
934
-        );
935
-        if (! $this->_current_data_handler instanceof EE_Messages_incoming_data) {
936
-            // no saved data_handler in the repo so let's set one up and add it to the repo.
937
-            try {
938
-                $this->_current_data_handler = new $data_handler_class_name($generating_data);
939
-                $this->_data_handler_collection->add($this->_current_data_handler, $generating_data);
940
-            } catch (Exception $e) {
941
-                $this->_error_msg[] = $e->getMessage();
942
-            }
943
-        }
944
-    }
945
-
946
-
947
-    /**
948
-     * The queued EE_Message for generation does not save the data used for generation as objects
949
-     * because serialization of those objects could be problematic if the data is saved to the db.
950
-     * So this method calls the static method on the associated data_handler for the given message_type
951
-     * and that preps the data for later instantiation when generating.
952
-     *
953
-     * @param EE_Message_To_Generate $message_to_generate
954
-     * @param bool                   $preview Indicate whether this is being used for a preview or not.
955
-     * @return mixed Prepped data for persisting to the queue.  false is returned if unable to prep data.
956
-     */
957
-    protected function _prepare_data_for_queue(EE_Message_To_Generate $message_to_generate, $preview)
958
-    {
959
-        /** @type EE_Messages_incoming_data $data_handler - well not really... just the class name actually */
960
-        $data_handler = $message_to_generate->get_data_handler_class_name($preview);
961
-        if (! $message_to_generate->valid()) {
962
-            return false; // unable to get the data because the info in the EE_Message_To_Generate class is invalid.
963
-        }
964
-        return $data_handler::convert_data_for_persistent_storage($message_to_generate->data());
965
-    }
966
-
967
-
968
-    /**
969
-     * This sets up a EEM_Message::status_incomplete EE_Message object and adds it to the generation queue.
970
-     *
971
-     * @param EE_Message_To_Generate $message_to_generate
972
-     * @param bool                   $test_send Whether this is just a test send or not.  Typically used for previews.
973
-     * @throws InvalidArgumentException
974
-     * @throws InvalidDataTypeException
975
-     * @throws InvalidInterfaceException
976
-     */
977
-    public function create_and_add_message_to_queue(EE_Message_To_Generate $message_to_generate, $test_send = false)
978
-    {
979
-        // prep data
980
-        $data = $this->_prepare_data_for_queue($message_to_generate, $message_to_generate->preview());
981
-        $request = LoaderFactory::getLoader()->getShared('EventEspresso\core\services\request\RequestInterface');
982
-
983
-        $message = $message_to_generate->get_EE_Message();
984
-        $GRP_ID = $request->getRequestParam('GRP_ID', 0);
985
-
986
-        $GRP_ID = apply_filters(
987
-            'FHEE__EE_Messages_Generator__create_and_add_message_to_queue_GRP_ID',
988
-            $GRP_ID > 0 ? $GRP_ID : $message->GRP_ID(),
989
-            $message,
990
-            $message_to_generate,
991
-            $test_send
992
-        );
993
-
994
-        if ($GRP_ID > 0) {
995
-            $message->set_GRP_ID($GRP_ID);
996
-        }
997
-
998
-        if ($data === false) {
999
-            $message->set_STS_ID(EEM_Message::status_failed);
1000
-            $message->set_error_message(
1001
-                esc_html__(
1002
-                    'Unable to prepare data for persistence to the database.',
1003
-                    'event_espresso'
1004
-                )
1005
-            );
1006
-        } else {
1007
-            // make sure that the data handler is cached on the message as well
1008
-            $data['data_handler_class_name'] = $message_to_generate->get_data_handler_class_name();
1009
-        }
1010
-
1011
-        $this->_generation_queue->add($message, $data, $message_to_generate->preview(), $test_send);
1012
-    }
747
+						esc_html__(
748
+							'There was a problem generating the content for the field %s: %s',
749
+							'event_espresso'
750
+						),
751
+						$field,
752
+						$e->getMessage()
753
+					);
754
+					$message->set_STS_ID(EEM_Message::status_failed);
755
+				}
756
+			}
757
+		}
758
+
759
+		if ($message->STS_ID() === EEM_Message::status_failed) {
760
+			$error_msg = esc_html__('There were problems generating this message:', 'event_espresso')
761
+						 . "\n"
762
+						 . implode("\n", $error_msg);
763
+			$message->set_error_message($error_msg);
764
+		} else {
765
+			$message->set_STS_ID(EEM_Message::status_idle);
766
+		}
767
+		return $message;
768
+	}
769
+
770
+
771
+	/**
772
+	 * This verifies that the incoming array has a EE_messenger object and a EE_message_type object and sets appropriate
773
+	 * error message if either is missing.
774
+	 *
775
+	 * @return bool true means there were no errors, false means there were errors.
776
+	 */
777
+	protected function _verify()
778
+	{
779
+		// reset error message to an empty array.
780
+		$this->_error_msg = array();
781
+		$valid            = true;
782
+		$valid            = $valid ? $this->_validate_messenger_and_message_type() : $valid;
783
+		$valid            = $valid ? $this->_validate_and_setup_data() : $valid;
784
+
785
+		// set the verified flag so we know everything has been validated.
786
+		$this->_verified = $valid;
787
+
788
+		return $valid;
789
+	}
790
+
791
+
792
+	/**
793
+	 * This accepts an array and validates that it is an array indexed by context with each value being an array of
794
+	 * EE_Messages_Addressee objects.
795
+	 *
796
+	 * @param array $addressees Keys correspond to contexts for the message type and values are EE_Messages_Addressee[]
797
+	 * @return bool
798
+	 */
799
+	protected function _valid_addressees($addressees)
800
+	{
801
+		if (! $addressees || ! is_array($addressees)) {
802
+			return false;
803
+		}
804
+
805
+		foreach ($addressees as $addressee_array) {
806
+			foreach ($addressee_array as $addressee) {
807
+				if (! $addressee instanceof EE_Messages_Addressee) {
808
+					return false;
809
+				}
810
+			}
811
+		}
812
+		return true;
813
+	}
814
+
815
+
816
+	/**
817
+	 * This validates the messenger, message type, and presences of generation data for the current EE_Message in the
818
+	 * queue. This process sets error messages if something is wrong.
819
+	 *
820
+	 * @return bool   true is if there are no errors.  false is if there is.
821
+	 */
822
+	protected function _validate_messenger_and_message_type()
823
+	{
824
+
825
+		// first are there any existing error messages?  If so then return.
826
+		if ($this->_error_msg) {
827
+			return false;
828
+		}
829
+		/** @type EE_Message $message */
830
+		$message = $this->_generation_queue->get_message_repository()->current();
831
+		try {
832
+			$this->_current_messenger = $message->valid_messenger(true)
833
+				? $message->messenger_object()
834
+				: null;
835
+		} catch (Exception $e) {
836
+			$this->_error_msg[] = $e->getMessage();
837
+		}
838
+		try {
839
+			$this->_current_message_type = $message->valid_message_type(true)
840
+				? $message->message_type_object()
841
+				: null;
842
+		} catch (Exception $e) {
843
+			$this->_error_msg[] = $e->getMessage();
844
+		}
845
+
846
+		/**
847
+		 * Check if there is any generation data, but only if this is not for a preview.
848
+		 */
849
+		if (! $this->_generation_queue->get_message_repository()->get_generation_data()
850
+			&& (
851
+				! $this->_generation_queue->get_message_repository()->is_preview()
852
+				&& $this->_generation_queue->get_message_repository()->get_data_handler()
853
+				   !== 'EE_Messages_Preview_incoming_data'
854
+			)
855
+		) {
856
+			$this->_error_msg[] = esc_html__(
857
+				'There is no generation data for this message. Unable to generate.',
858
+				'event_espresso'
859
+			);
860
+		}
861
+
862
+		return empty($this->_error_msg);
863
+	}
864
+
865
+
866
+	/**
867
+	 * This method retrieves the expected data handler for the message type and validates the generation data for that
868
+	 * data handler.
869
+	 *
870
+	 * @return bool true means there are no errors.  false means there were errors (and handler did not get setup).
871
+	 */
872
+	protected function _validate_and_setup_data()
873
+	{
874
+
875
+		// First, are there any existing error messages?  If so, return because if there were errors elsewhere this
876
+		// can't be used anyways.
877
+		if ($this->_error_msg) {
878
+			return false;
879
+		}
880
+
881
+		$generation_data = $this->_generation_queue->get_message_repository()->get_generation_data();
882
+
883
+		/** @type EE_Messages_incoming_data $data_handler_class_name - well not really... just the class name actually*/
884
+		$data_handler_class_name = $this->_generation_queue->get_message_repository()->get_data_handler()
885
+			? $this->_generation_queue->get_message_repository()->get_data_handler()
886
+			: 'EE_Messages_' . $this->_current_message_type->get_data_handler($generation_data) . '_incoming_data';
887
+
888
+		// If this EE_Message is for a preview, then let's switch out to the preview data handler.
889
+		if ($this->_generation_queue->get_message_repository()->is_preview()) {
890
+			$data_handler_class_name = 'EE_Messages_Preview_incoming_data';
891
+		}
892
+
893
+		// First get the class name for the data handler (and also verifies it exists.
894
+		if (! class_exists($data_handler_class_name)) {
895
+			$this->_error_msg[] = sprintf(
896
+				/* Translators: Both placeholders are the names of php classes. */
897
+				esc_html__(
898
+					'The included data handler class name does not match any valid, accessible, "%1$s" classes.  Looking for %2$s.',
899
+					'event_espresso'
900
+				),
901
+				'EE_Messages_incoming_data',
902
+				$data_handler_class_name
903
+			);
904
+			return false;
905
+		}
906
+
907
+		// convert generation_data for data_handler_instantiation.
908
+		$generation_data = $data_handler_class_name::convert_data_from_persistent_storage($generation_data);
909
+
910
+		// note, this may set error messages as well.
911
+		$this->_set_data_handler($generation_data, $data_handler_class_name);
912
+
913
+		return empty($this->_error_msg);
914
+	}
915
+
916
+
917
+	/**
918
+	 * Sets the $_current_data_handler property that is used for generating the current EE_Message in the queue, and
919
+	 * adds it to the _data repository.
920
+	 *
921
+	 * @param mixed  $generating_data           This is data expected by the instantiated data handler.
922
+	 * @param string $data_handler_class_name   This is the reference string indicating what data handler is being
923
+	 *                                          instantiated.
924
+	 */
925
+	protected function _set_data_handler($generating_data, $data_handler_class_name)
926
+	{
927
+		// valid classname for the data handler.  Now let's setup the key for the data handler repository to see if
928
+		// there is already a ready data handler in the repository.
929
+		$this->_current_data_handler = $this->_data_handler_collection->get_by_key(
930
+			$this->_data_handler_collection->get_key(
931
+				$data_handler_class_name,
932
+				$generating_data
933
+			)
934
+		);
935
+		if (! $this->_current_data_handler instanceof EE_Messages_incoming_data) {
936
+			// no saved data_handler in the repo so let's set one up and add it to the repo.
937
+			try {
938
+				$this->_current_data_handler = new $data_handler_class_name($generating_data);
939
+				$this->_data_handler_collection->add($this->_current_data_handler, $generating_data);
940
+			} catch (Exception $e) {
941
+				$this->_error_msg[] = $e->getMessage();
942
+			}
943
+		}
944
+	}
945
+
946
+
947
+	/**
948
+	 * The queued EE_Message for generation does not save the data used for generation as objects
949
+	 * because serialization of those objects could be problematic if the data is saved to the db.
950
+	 * So this method calls the static method on the associated data_handler for the given message_type
951
+	 * and that preps the data for later instantiation when generating.
952
+	 *
953
+	 * @param EE_Message_To_Generate $message_to_generate
954
+	 * @param bool                   $preview Indicate whether this is being used for a preview or not.
955
+	 * @return mixed Prepped data for persisting to the queue.  false is returned if unable to prep data.
956
+	 */
957
+	protected function _prepare_data_for_queue(EE_Message_To_Generate $message_to_generate, $preview)
958
+	{
959
+		/** @type EE_Messages_incoming_data $data_handler - well not really... just the class name actually */
960
+		$data_handler = $message_to_generate->get_data_handler_class_name($preview);
961
+		if (! $message_to_generate->valid()) {
962
+			return false; // unable to get the data because the info in the EE_Message_To_Generate class is invalid.
963
+		}
964
+		return $data_handler::convert_data_for_persistent_storage($message_to_generate->data());
965
+	}
966
+
967
+
968
+	/**
969
+	 * This sets up a EEM_Message::status_incomplete EE_Message object and adds it to the generation queue.
970
+	 *
971
+	 * @param EE_Message_To_Generate $message_to_generate
972
+	 * @param bool                   $test_send Whether this is just a test send or not.  Typically used for previews.
973
+	 * @throws InvalidArgumentException
974
+	 * @throws InvalidDataTypeException
975
+	 * @throws InvalidInterfaceException
976
+	 */
977
+	public function create_and_add_message_to_queue(EE_Message_To_Generate $message_to_generate, $test_send = false)
978
+	{
979
+		// prep data
980
+		$data = $this->_prepare_data_for_queue($message_to_generate, $message_to_generate->preview());
981
+		$request = LoaderFactory::getLoader()->getShared('EventEspresso\core\services\request\RequestInterface');
982
+
983
+		$message = $message_to_generate->get_EE_Message();
984
+		$GRP_ID = $request->getRequestParam('GRP_ID', 0);
985
+
986
+		$GRP_ID = apply_filters(
987
+			'FHEE__EE_Messages_Generator__create_and_add_message_to_queue_GRP_ID',
988
+			$GRP_ID > 0 ? $GRP_ID : $message->GRP_ID(),
989
+			$message,
990
+			$message_to_generate,
991
+			$test_send
992
+		);
993
+
994
+		if ($GRP_ID > 0) {
995
+			$message->set_GRP_ID($GRP_ID);
996
+		}
997
+
998
+		if ($data === false) {
999
+			$message->set_STS_ID(EEM_Message::status_failed);
1000
+			$message->set_error_message(
1001
+				esc_html__(
1002
+					'Unable to prepare data for persistence to the database.',
1003
+					'event_espresso'
1004
+				)
1005
+			);
1006
+		} else {
1007
+			// make sure that the data handler is cached on the message as well
1008
+			$data['data_handler_class_name'] = $message_to_generate->get_data_handler_class_name();
1009
+		}
1010
+
1011
+		$this->_generation_queue->add($message, $data, $message_to_generate->preview(), $test_send);
1012
+	}
1013 1013
 }
Please login to merge, or discard this patch.
Spacing   +24 added lines, -24 removed lines patch added patch discarded remove patch
@@ -267,7 +267,7 @@  discard block
 block discarded – undo
267 267
     {
268 268
         // double check verification has run and that everything is ready to work with (saves us having to validate
269 269
         // everything again).
270
-        if (! $this->_verified) {
270
+        if ( ! $this->_verified) {
271 271
             return false; // get out because we don't have a valid setup to work with.
272 272
         }
273 273
 
@@ -284,7 +284,7 @@  discard block
 block discarded – undo
284 284
 
285 285
 
286 286
         // if no addressees then get out because there is nothing to generation (possible bad data).
287
-        if (! $this->_valid_addressees($addressees)) {
287
+        if ( ! $this->_valid_addressees($addressees)) {
288 288
             do_action(
289 289
                 'AHEE__EE_Messages_Generator___generate__invalid_addressees',
290 290
                 $this->_generation_queue->get_message_repository()->current(),
@@ -306,7 +306,7 @@  discard block
 block discarded – undo
306 306
         $message_template_group = $this->_get_message_template_group();
307 307
 
308 308
         // in the unlikely event there is no EE_Message_Template_Group available, get out!
309
-        if (! $message_template_group instanceof EE_Message_Template_Group) {
309
+        if ( ! $message_template_group instanceof EE_Message_Template_Group) {
310 310
             $this->_error_msg[] = esc_html__(
311 311
                 'Unable to get the Message Templates for the Message being generated.  No message template group accessible.',
312 312
                 '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
             array(
@@ -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
                 array(
528 528
                     array(
@@ -554,7 +554,7 @@  discard block
 block discarded – undo
554 554
     {
555 555
         $event_ids = array();
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'
@@ -704,10 +704,10 @@  discard block
 block discarded – undo
704 704
         $m_shortcodes  = $this->_current_messenger->get_valid_shortcodes();
705 705
 
706 706
         // if the 'to' field is empty or the context is inactive we skip EXCEPT if we're previewing
707
-        if (! $this->_generation_queue->get_message_repository()->is_preview()
707
+        if ( ! $this->_generation_queue->get_message_repository()->is_preview()
708 708
             && (
709 709
                             (
710
-                                empty($templates['to'][ $context ])
710
+                                empty($templates['to'][$context])
711 711
                                 && ! $this->_current_messenger->allow_empty_to_field()
712 712
                             )
713 713
                             || ! $message_template_group->is_context_active($context)
@@ -721,15 +721,15 @@  discard block
 block discarded – undo
721 721
         foreach ($templates as $field => $field_context) {
722 722
             $error_msg = array();
723 723
             // let's setup the valid shortcodes for the incoming context.
724
-            $valid_shortcodes = $mt_shortcodes[ $context ];
724
+            $valid_shortcodes = $mt_shortcodes[$context];
725 725
             // merge in valid shortcodes for the field.
726
-            $shortcodes = isset($m_shortcodes[ $field ]) ? $m_shortcodes[ $field ] : $valid_shortcodes;
727
-            if (isset($templates[ $field ][ $context ])) {
726
+            $shortcodes = isset($m_shortcodes[$field]) ? $m_shortcodes[$field] : $valid_shortcodes;
727
+            if (isset($templates[$field][$context])) {
728 728
                 // prefix field.
729
-                $column_name = 'MSG_' . $field;
729
+                $column_name = 'MSG_'.$field;
730 730
                 try {
731 731
                     $content = $this->_shortcode_parser->parse_message_template(
732
-                        $templates[ $field ][ $context ],
732
+                        $templates[$field][$context],
733 733
                         $recipient,
734 734
                         $shortcodes,
735 735
                         $this->_current_message_type,
@@ -798,13 +798,13 @@  discard block
 block discarded – undo
798 798
      */
799 799
     protected function _valid_addressees($addressees)
800 800
     {
801
-        if (! $addressees || ! is_array($addressees)) {
801
+        if ( ! $addressees || ! is_array($addressees)) {
802 802
             return false;
803 803
         }
804 804
 
805 805
         foreach ($addressees as $addressee_array) {
806 806
             foreach ($addressee_array as $addressee) {
807
-                if (! $addressee instanceof EE_Messages_Addressee) {
807
+                if ( ! $addressee instanceof EE_Messages_Addressee) {
808 808
                     return false;
809 809
                 }
810 810
             }
@@ -846,7 +846,7 @@  discard block
 block discarded – undo
846 846
         /**
847 847
          * Check if there is any generation data, but only if this is not for a preview.
848 848
          */
849
-        if (! $this->_generation_queue->get_message_repository()->get_generation_data()
849
+        if ( ! $this->_generation_queue->get_message_repository()->get_generation_data()
850 850
             && (
851 851
                 ! $this->_generation_queue->get_message_repository()->is_preview()
852 852
                 && $this->_generation_queue->get_message_repository()->get_data_handler()
@@ -883,7 +883,7 @@  discard block
 block discarded – undo
883 883
         /** @type EE_Messages_incoming_data $data_handler_class_name - well not really... just the class name actually*/
884 884
         $data_handler_class_name = $this->_generation_queue->get_message_repository()->get_data_handler()
885 885
             ? $this->_generation_queue->get_message_repository()->get_data_handler()
886
-            : 'EE_Messages_' . $this->_current_message_type->get_data_handler($generation_data) . '_incoming_data';
886
+            : 'EE_Messages_'.$this->_current_message_type->get_data_handler($generation_data).'_incoming_data';
887 887
 
888 888
         // If this EE_Message is for a preview, then let's switch out to the preview data handler.
889 889
         if ($this->_generation_queue->get_message_repository()->is_preview()) {
@@ -891,7 +891,7 @@  discard block
 block discarded – undo
891 891
         }
892 892
 
893 893
         // First get the class name for the data handler (and also verifies it exists.
894
-        if (! class_exists($data_handler_class_name)) {
894
+        if ( ! class_exists($data_handler_class_name)) {
895 895
             $this->_error_msg[] = sprintf(
896 896
                 /* Translators: Both placeholders are the names of php classes. */
897 897
                 esc_html__(
@@ -932,7 +932,7 @@  discard block
 block discarded – undo
932 932
                 $generating_data
933 933
             )
934 934
         );
935
-        if (! $this->_current_data_handler instanceof EE_Messages_incoming_data) {
935
+        if ( ! $this->_current_data_handler instanceof EE_Messages_incoming_data) {
936 936
             // no saved data_handler in the repo so let's set one up and add it to the repo.
937 937
             try {
938 938
                 $this->_current_data_handler = new $data_handler_class_name($generating_data);
@@ -958,7 +958,7 @@  discard block
 block discarded – undo
958 958
     {
959 959
         /** @type EE_Messages_incoming_data $data_handler - well not really... just the class name actually */
960 960
         $data_handler = $message_to_generate->get_data_handler_class_name($preview);
961
-        if (! $message_to_generate->valid()) {
961
+        if ( ! $message_to_generate->valid()) {
962 962
             return false; // unable to get the data because the info in the EE_Message_To_Generate class is invalid.
963 963
         }
964 964
         return $data_handler::convert_data_for_persistent_storage($message_to_generate->data());
Please login to merge, or discard this patch.