Completed
Branch master (55edba)
by
unknown
70:21 queued 62:01
created
core/db_classes/EE_Question.class.php 1 patch
Indentation   +661 added lines, -661 removed lines patch added patch discarded remove patch
@@ -14,665 +14,665 @@
 block discarded – undo
14 14
 class EE_Question extends EE_Soft_Delete_Base_Class implements EEI_Duplicatable
15 15
 {
16 16
 
17
-    /**
18
-     *
19
-     * @param array  $props_n_values          incoming values
20
-     * @param string $timezone                incoming timezone (if not set the timezone set for the website will be
21
-     *                                        used.)
22
-     * @param array  $date_formats            incoming date_formats in an array where the first value is the
23
-     *                                        date_format and the second value is the time format
24
-     * @return EE_Question
25
-     */
26
-    public static function new_instance($props_n_values = array(), $timezone = null, $date_formats = array())
27
-    {
28
-        $has_object = parent::_check_for_object($props_n_values, __CLASS__, $timezone, $date_formats);
29
-        return $has_object ? $has_object : new self($props_n_values, false, $timezone, $date_formats);
30
-    }
31
-
32
-
33
-    /**
34
-     * @param array  $props_n_values  incoming values from the database
35
-     * @param string $timezone        incoming timezone as set by the model.  If not set the timezone for
36
-     *                                the website will be used.
37
-     * @return EE_Question
38
-     */
39
-    public static function new_instance_from_db($props_n_values = array(), $timezone = null)
40
-    {
41
-        return new self($props_n_values, true, $timezone);
42
-    }
43
-
44
-
45
-    /**
46
-     *        Set    Question display text
47
-     *
48
-     * @access        public
49
-     * @param string $QST_display_text
50
-     */
51
-    public function set_display_text($QST_display_text = '')
52
-    {
53
-        $this->set('QST_display_text', $QST_display_text);
54
-    }
55
-
56
-
57
-    /**
58
-     *        Set    Question admin text
59
-     *
60
-     * @access        public
61
-     * @param        string $QST_admin_label
62
-     */
63
-    public function set_admin_label($QST_admin_label = '')
64
-    {
65
-        $this->set('QST_admin_label', $QST_admin_label);
66
-    }
67
-
68
-
69
-    /**
70
-     *        Set    system name
71
-     *
72
-     * @access        public
73
-     * @param        mixed $QST_system
74
-     */
75
-    public function set_system_ID($QST_system = '')
76
-    {
77
-        $this->set('QST_system', $QST_system);
78
-    }
79
-
80
-
81
-    /**
82
-     *        Set    question's type
83
-     *
84
-     * @access        public
85
-     * @param        string $QST_type
86
-     */
87
-    public function set_question_type($QST_type = '')
88
-    {
89
-        $this->set('QST_type', $QST_type);
90
-    }
91
-
92
-
93
-    /**
94
-     *        Sets whether this question must be answered when presented in a form
95
-     *
96
-     * @access        public
97
-     * @param        bool $QST_required
98
-     */
99
-    public function set_required($QST_required = false)
100
-    {
101
-        $this->set('QST_required', $QST_required);
102
-    }
103
-
104
-
105
-    /**
106
-     *        Set    Question display text
107
-     *
108
-     * @access        public
109
-     * @param        string $QST_required_text
110
-     */
111
-    public function set_required_text($QST_required_text = '')
112
-    {
113
-        $this->set('QST_required_text', $QST_required_text);
114
-    }
115
-
116
-
117
-    /**
118
-     *        Sets the order of this question when placed in a sequence of questions
119
-     *
120
-     * @access        public
121
-     * @param        int $QST_order
122
-     */
123
-    public function set_order($QST_order = 0)
124
-    {
125
-        $this->set('QST_order', $QST_order);
126
-    }
127
-
128
-
129
-    /**
130
-     *        Sets whether the question is admin-only
131
-     *
132
-     * @access        public
133
-     * @param        bool $QST_admin_only
134
-     */
135
-    public function set_admin_only($QST_admin_only = false)
136
-    {
137
-        $this->set('QST_admin_only', $QST_admin_only);
138
-    }
139
-
140
-
141
-    /**
142
-     *        Sets the wordpress user ID on the question
143
-     *
144
-     * @access        public
145
-     * @param        int $QST_wp_user
146
-     */
147
-    public function set_wp_user($QST_wp_user = 1)
148
-    {
149
-        $this->set('QST_wp_user', $QST_wp_user);
150
-    }
151
-
152
-
153
-    /**
154
-     *        Sets whether the question has been deleted
155
-     *        (we use this boolean instead of actually
156
-     *        deleting it because when users delete this question
157
-     *        they really want to remove the question from future
158
-     *        forms, BUT keep their old answers which depend
159
-     *        on this record actually existing.
160
-     *
161
-     * @access        public
162
-     * @param    bool $QST_deleted
163
-     */
164
-    public function set_deleted($QST_deleted = false)
165
-    {
166
-        $this->set('QST_deleted', $QST_deleted);
167
-    }
168
-
169
-
170
-    /**
171
-     * returns the text for displaying the question to users
172
-     *
173
-     * @access public
174
-     * @return string
175
-     */
176
-    public function display_text()
177
-    {
178
-        return $this->get('QST_display_text');
179
-    }
180
-
181
-
182
-    /**
183
-     * returns the text for the administrative label
184
-     *
185
-     * @access public
186
-     * @return string
187
-     */
188
-    public function admin_label()
189
-    {
190
-        return $this->get('QST_admin_label');
191
-    }
192
-
193
-
194
-    /**
195
-     * returns the attendee column name for this question
196
-     *
197
-     * @access public
198
-     * @return string
199
-     */
200
-    public function system_ID()
201
-    {
202
-        return $this->get('QST_system');
203
-    }
204
-
205
-
206
-    /**
207
-     * returns either a string of 'text', 'textfield', etc.
208
-     *
209
-     * @access public
210
-     * @return boolean
211
-     */
212
-    public function required()
213
-    {
214
-        return $this->get('QST_required');
215
-    }
216
-
217
-
218
-    /**
219
-     * returns the text which should be displayed when a user
220
-     * doesn't answer this question in a form
221
-     *
222
-     * @access public
223
-     * @return string
224
-     */
225
-    public function required_text()
226
-    {
227
-        return $this->get('QST_required_text');
228
-    }
229
-
230
-
231
-    /**
232
-     * returns the type of this question
233
-     *
234
-     * @access public
235
-     * @return string
236
-     */
237
-    public function type()
238
-    {
239
-        return $this->get('QST_type');
240
-    }
241
-
242
-
243
-    /**
244
-     * returns an integer showing where this question should
245
-     * be placed in a sequence of questions
246
-     *
247
-     * @access public
248
-     * @return int
249
-     */
250
-    public function order()
251
-    {
252
-        return $this->get('QST_order');
253
-    }
254
-
255
-
256
-    /**
257
-     * returns whether this question should only appears to admins,
258
-     * or to everyone
259
-     *
260
-     * @access public
261
-     * @return boolean
262
-     */
263
-    public function admin_only()
264
-    {
265
-        return $this->get('QST_admin_only');
266
-    }
267
-
268
-
269
-    /**
270
-     * returns the id the wordpress user who created this question
271
-     *
272
-     * @access public
273
-     * @return int
274
-     */
275
-    public function wp_user()
276
-    {
277
-        return $this->get('QST_wp_user');
278
-    }
279
-
280
-
281
-    /**
282
-     * returns whether this question has been marked as 'deleted'
283
-     *
284
-     * @access public
285
-     * @return boolean
286
-     */
287
-    public function deleted()
288
-    {
289
-        return $this->get('QST_deleted');
290
-    }
291
-
292
-
293
-    /**
294
-     * Gets an array of related EE_Answer  to this EE_Question
295
-     *
296
-     * @return EE_Answer[]
297
-     */
298
-    public function answers()
299
-    {
300
-        return $this->get_many_related('Answer');
301
-    }
302
-
303
-
304
-    /**
305
-     * Boolean check for if there are answers on this question in th db
306
-     *
307
-     * @return boolean true = has answers, false = no answers.
308
-     */
309
-    public function has_answers()
310
-    {
311
-        return $this->count_related('Answer') > 0 ? true : false;
312
-    }
313
-
314
-
315
-    /**
316
-     * gets an array of EE_Question_Group which relate to this question
317
-     *
318
-     * @return EE_Question_Group[]
319
-     */
320
-    public function question_groups()
321
-    {
322
-        return $this->get_many_related('Question_Group');
323
-    }
324
-
325
-
326
-    /**
327
-     * Returns all the options for this question. By default, it returns only the not-yet-deleted ones.
328
-     *
329
-     * @param boolean      $notDeletedOptionsOnly            1
330
-     *                                                       whether to return ALL options, or only the ones which have
331
-     *                                                       not yet been deleleted
332
-     * @param string|array $selected_value_to_always_include , when retrieving options to an ANSWERED question,
333
-     *                                                       we want to usually only show non-deleted options AND the
334
-     *                                                       value that was selected for the answer, whether it was
335
-     *                                                       trashed or not.
336
-     * @return EE_Question_Option[]
337
-     */
338
-    public function options($notDeletedOptionsOnly = true, $selected_value_to_always_include = null)
339
-    {
340
-        if (! $this->ID()) {
341
-            return array();
342
-        }
343
-        $query_params = array();
344
-        if ($selected_value_to_always_include) {
345
-            if (is_array($selected_value_to_always_include)) {
346
-                $query_params[0]['OR*options-query']['QSO_value'] = array('IN', $selected_value_to_always_include);
347
-            } else {
348
-                $query_params[0]['OR*options-query']['QSO_value'] = $selected_value_to_always_include;
349
-            }
350
-        }
351
-        if ($notDeletedOptionsOnly) {
352
-            $query_params[0]['OR*options-query']['QSO_deleted'] = false;
353
-        }
354
-        // order by QSO_order
355
-        $query_params['order_by'] = array('QSO_order' => 'ASC');
356
-        return $this->get_many_related('Question_Option', $query_params);
357
-    }
358
-
359
-
360
-    /**
361
-     * returns an array of EE_Question_Options which relate to this question
362
-     *
363
-     * @return \EE_Question_Option[]
364
-     */
365
-    public function temp_options()
366
-    {
367
-        return $this->_model_relations['Question_Option'];
368
-    }
369
-
370
-
371
-    /**
372
-     * Adds an option for this question. Note: if the option were previously associated with a different
373
-     * Question, that relationship will be overwritten.
374
-     *
375
-     * @param EE_Question_Option $option
376
-     * @return boolean success
377
-     */
378
-    public function add_option(EE_Question_Option $option)
379
-    {
380
-        return $this->_add_relation_to($option, 'Question_Option');
381
-    }
382
-
383
-
384
-    /**
385
-     * Adds an option directly to this question without saving to the db
386
-     *
387
-     * @param EE_Question_Option $option
388
-     * @return boolean success
389
-     */
390
-    public function add_temp_option(EE_Question_Option $option)
391
-    {
392
-        $this->_model_relations['Question_Option'][] = $option;
393
-        return true;
394
-    }
395
-
396
-
397
-    /**
398
-     * Marks the option as deleted.
399
-     *
400
-     * @param EE_Question_Option $option
401
-     * @return boolean success
402
-     */
403
-    public function remove_option(EE_Question_Option $option)
404
-    {
405
-        return $this->_remove_relation_to($option, 'Question_Option');
406
-    }
407
-
408
-
409
-    /**
410
-     * @return bool
411
-     */
412
-    public function is_system_question()
413
-    {
414
-        $system_ID = $this->get('QST_system');
415
-        return ! empty($system_ID) ? true : false;
416
-    }
417
-
418
-
419
-    /**
420
-     * The purpose of this method is set the question order this question order to be the max out of all questions
421
-     *
422
-     * @access public
423
-     * @return void
424
-     */
425
-    public function set_order_to_latest()
426
-    {
427
-        $latest_order = $this->get_model()->get_latest_question_order();
428
-        $latest_order++;
429
-        $this->set('QST_order', $latest_order);
430
-    }
431
-
432
-
433
-    /**
434
-     * Retrieves the list of allowed question types from the model.
435
-     *
436
-     * @return string[]
437
-     */
438
-    private function _allowed_question_types()
439
-    {
440
-        $questionModel = $this->get_model();
441
-        /* @var $questionModel EEM_Question */
442
-        return $questionModel->allowed_question_types();
443
-    }
444
-
445
-    /**
446
-     * Duplicates this question and its question options
447
-     *
448
-     * @return \EE_Question
449
-     */
450
-    public function duplicate($options = array())
451
-    {
452
-        $new_question = clone $this;
453
-        $new_question->set('QST_ID', null);
454
-        $new_question->set_display_text(sprintf(__('%s **Duplicate**', 'event_espresso'), $this->display_text()));
455
-        $new_question->set_admin_label(sprintf(__('%s **Duplicate**', 'event_espresso'), $this->admin_label()));
456
-        $new_question->set_system_ID(null);
457
-        $new_question->set_wp_user(get_current_user_id());
458
-        // if we're duplicating a trashed question, assume we don't want the new one to be trashed
459
-        $new_question->set_deleted(false);
460
-        $success = $new_question->save();
461
-        if ($success) {
462
-            // we don't totally want to duplicate the question options, because we want them to be for the NEW question
463
-            foreach ($this->options() as $question_option) {
464
-                $question_option->duplicate(array('QST_ID' => $new_question->ID()));
465
-            }
466
-            return $new_question;
467
-        } else {
468
-            return null;
469
-        }
470
-    }
471
-
472
-    /**
473
-     * Returns the question's maximum allowed response size
474
-     *
475
-     * @return int|float
476
-     */
477
-    public function max()
478
-    {
479
-        return $this->get('QST_max');
480
-    }
481
-
482
-    /**
483
-     * Sets the question's maximum allowed response size
484
-     *
485
-     * @param int|float $new_max
486
-     * @return void
487
-     */
488
-    public function set_max($new_max)
489
-    {
490
-        $this->set('QST_max', $new_max);
491
-    }
492
-
493
-
494
-    /**
495
-     * Creates a form input from this question which can be used in HTML forms
496
-     *
497
-     * @param EE_Registration $registration
498
-     * @param EE_Answer       $answer
499
-     * @param array           $input_constructor_args
500
-     * @return EE_Form_Input_Base
501
-     */
502
-    public function generate_form_input($registration = null, $answer = null, $input_constructor_args = array())
503
-    {
504
-        $identifier = $this->is_system_question() ? $this->system_ID() : $this->ID();
505
-
506
-        $input_constructor_args = array_merge(
507
-            array(
508
-                'required'                          => $this->required() ? true : false,
509
-                'html_label_text'                   => $this->display_text(),
510
-                'required_validation_error_message' => $this->required_text(),
511
-            ),
512
-            $input_constructor_args
513
-        );
514
-        if (! $answer instanceof EE_Answer && $registration instanceof EE_Registration) {
515
-            $answer = EEM_Answer::instance()->get_registration_question_answer_object($registration, $this->ID());
516
-        }
517
-        // has this question been answered ?
518
-        if ($answer instanceof EE_Answer
519
-            && $answer->value() !== ''
520
-        ) {
521
-            // answer gets htmlspecialchars called on it, undo that please
522
-            // because the form input's display strategy may call esc_attr too
523
-            // which also does html special characters
524
-            $values_with_html_special_chars = $answer->value();
525
-            if (is_array($values_with_html_special_chars)) {
526
-                $default_value = array_map('htmlspecialchars_decode', $values_with_html_special_chars);
527
-            } else {
528
-                $default_value = htmlspecialchars_decode($values_with_html_special_chars);
529
-            }
530
-            $input_constructor_args['default'] = $default_value;
531
-        }
532
-        $max_max_for_question = EEM_Question::instance()->absolute_max_for_system_question($this->system_ID());
533
-        if (in_array(
534
-            $this->type(),
535
-            EEM_Question::instance()->questionTypesWithMaxLength(),
536
-            true
537
-        )) {
538
-            $input_constructor_args['validation_strategies'][] = new EE_Max_Length_Validation_Strategy(
539
-                null,
540
-                min($max_max_for_question, $this->max())
541
-            );
542
-        }
543
-        $input_constructor_args = apply_filters(
544
-            'FHEE__EE_SPCO_Reg_Step_Attendee_Information___generate_question_input__input_constructor_args',
545
-            $input_constructor_args,
546
-            $registration,
547
-            $this,
548
-            $answer
549
-        );
550
-
551
-        $result = null;
552
-        switch ($this->type()) {
553
-            // Text
554
-            case EEM_Question::QST_type_text:
555
-                $result = new EE_Text_Input($input_constructor_args);
556
-                break;
557
-            // Textarea
558
-            case EEM_Question::QST_type_textarea:
559
-                $result = new EE_Text_Area_Input($input_constructor_args);
560
-                break;
561
-            // Radio Buttons
562
-            case EEM_Question::QST_type_radio:
563
-                $result = new EE_Radio_Button_Input($this->options(), $input_constructor_args);
564
-                break;
565
-            // Dropdown
566
-            case EEM_Question::QST_type_dropdown:
567
-                $result = new EE_Select_Input($this->options(), $input_constructor_args);
568
-                break;
569
-            // State Dropdown
570
-            case EEM_Question::QST_type_state:
571
-                $state_options = apply_filters(
572
-                    'FHEE__EE_Question__generate_form_input__state_options',
573
-                    null,
574
-                    $this,
575
-                    $registration,
576
-                    $answer
577
-                );
578
-                $result = new EE_State_Select_Input($state_options, $input_constructor_args);
579
-                break;
580
-            // Country Dropdown
581
-            case EEM_Question::QST_type_country:
582
-                $country_options = apply_filters(
583
-                    'FHEE__EE_Question__generate_form_input__country_options',
584
-                    null,
585
-                    $this,
586
-                    $registration,
587
-                    $answer
588
-                );
589
-                $result = new EE_Country_Select_Input($country_options, $input_constructor_args);
590
-                break;
591
-            // Checkboxes
592
-            case EEM_Question::QST_type_checkbox:
593
-                $result = new EE_Checkbox_Multi_Input($this->options(), $input_constructor_args);
594
-                break;
595
-            // Date
596
-            case EEM_Question::QST_type_date:
597
-                $result = new EE_Datepicker_Input($input_constructor_args);
598
-                break;
599
-            case EEM_Question::QST_type_html_textarea:
600
-                $input_constructor_args['validation_strategies'][] = new EE_Simple_HTML_Validation_Strategy();
601
-                $result = new EE_Text_Area_Input($input_constructor_args);
602
-                $result->remove_validation_strategy('EE_Plaintext_Validation_Strategy');
603
-                break;
604
-            case EEM_Question::QST_type_email:
605
-                    $result = new EE_Email_Input($input_constructor_args);
606
-                break;
607
-            // Email confirm
608
-            case EEM_Question::QST_type_email_confirm:
609
-                $result = new EE_Email_Confirm_Input($input_constructor_args);
610
-                break;
611
-            case EEM_Question::QST_type_us_phone:
612
-                $result = new EE_Phone_Input($input_constructor_args);
613
-                break;
614
-            case EEM_Question::QST_type_int:
615
-                $result = new EE_Integer_Input($input_constructor_args);
616
-                break;
617
-            case EEM_Question::QST_type_decimal:
618
-                $result = new EE_Float_Input($input_constructor_args);
619
-                break;
620
-            case EEM_Question::QST_type_url:
621
-                $input_constructor_args['validation_strategies'][] = LoaderFactory::getLoader()->getNew('EE_URL_Validation_Strategy');
622
-                $result = new EE_Text_Input($input_constructor_args);
623
-                break;
624
-            case EEM_Question::QST_type_year:
625
-                $result = new EE_Year_Input(
626
-                    $input_constructor_args,
627
-                    apply_filters(
628
-                        'FHEE__EE_SPCO_Reg_Step_Attendee_Information___generate_question_input__year_question__four_digit',
629
-                        true,
630
-                        $this
631
-                    ),
632
-                    apply_filters(
633
-                        'FHEE__EE_SPCO_Reg_Step_Attendee_Information___generate_question_input__year_question__early_range',
634
-                        100,
635
-                        $this
636
-                    ),
637
-                    apply_filters(
638
-                        'FHEE__EE_SPCO_Reg_Step_Attendee_Information___generate_question_input__year_question__end_range',
639
-                        100,
640
-                        $this
641
-                    )
642
-                );
643
-                break;
644
-            case EEM_Question::QST_type_multi_select:
645
-                $result = new EE_Select_Multiple_Input($this->options(), $input_constructor_args);
646
-                break;
647
-            // fallback
648
-            default:
649
-                $default_input = apply_filters(
650
-                    'FHEE__EE_SPCO_Reg_Step_Attendee_Information___generate_question_input__default',
651
-                    null,
652
-                    $this->type(),
653
-                    $this,
654
-                    $input_constructor_args
655
-                );
656
-                if (! $default_input) {
657
-                    $default_input = new EE_Text_Input($input_constructor_args);
658
-                }
659
-                $result = $default_input;
660
-        }
661
-        return apply_filters('FHEE__EE_Question__generate_form_input__return', $result, $registration, $this, $answer);
662
-    }
663
-
664
-
665
-    /**
666
-     * Returns whether or not this question type should have question option entries
667
-     *
668
-     * @return bool
669
-     */
670
-    public function should_have_question_options()
671
-    {
672
-        return in_array(
673
-            $this->type(),
674
-            $this->_model->question_types_with_options(),
675
-            true
676
-        );
677
-    }
17
+	/**
18
+	 *
19
+	 * @param array  $props_n_values          incoming values
20
+	 * @param string $timezone                incoming timezone (if not set the timezone set for the website will be
21
+	 *                                        used.)
22
+	 * @param array  $date_formats            incoming date_formats in an array where the first value is the
23
+	 *                                        date_format and the second value is the time format
24
+	 * @return EE_Question
25
+	 */
26
+	public static function new_instance($props_n_values = array(), $timezone = null, $date_formats = array())
27
+	{
28
+		$has_object = parent::_check_for_object($props_n_values, __CLASS__, $timezone, $date_formats);
29
+		return $has_object ? $has_object : new self($props_n_values, false, $timezone, $date_formats);
30
+	}
31
+
32
+
33
+	/**
34
+	 * @param array  $props_n_values  incoming values from the database
35
+	 * @param string $timezone        incoming timezone as set by the model.  If not set the timezone for
36
+	 *                                the website will be used.
37
+	 * @return EE_Question
38
+	 */
39
+	public static function new_instance_from_db($props_n_values = array(), $timezone = null)
40
+	{
41
+		return new self($props_n_values, true, $timezone);
42
+	}
43
+
44
+
45
+	/**
46
+	 *        Set    Question display text
47
+	 *
48
+	 * @access        public
49
+	 * @param string $QST_display_text
50
+	 */
51
+	public function set_display_text($QST_display_text = '')
52
+	{
53
+		$this->set('QST_display_text', $QST_display_text);
54
+	}
55
+
56
+
57
+	/**
58
+	 *        Set    Question admin text
59
+	 *
60
+	 * @access        public
61
+	 * @param        string $QST_admin_label
62
+	 */
63
+	public function set_admin_label($QST_admin_label = '')
64
+	{
65
+		$this->set('QST_admin_label', $QST_admin_label);
66
+	}
67
+
68
+
69
+	/**
70
+	 *        Set    system name
71
+	 *
72
+	 * @access        public
73
+	 * @param        mixed $QST_system
74
+	 */
75
+	public function set_system_ID($QST_system = '')
76
+	{
77
+		$this->set('QST_system', $QST_system);
78
+	}
79
+
80
+
81
+	/**
82
+	 *        Set    question's type
83
+	 *
84
+	 * @access        public
85
+	 * @param        string $QST_type
86
+	 */
87
+	public function set_question_type($QST_type = '')
88
+	{
89
+		$this->set('QST_type', $QST_type);
90
+	}
91
+
92
+
93
+	/**
94
+	 *        Sets whether this question must be answered when presented in a form
95
+	 *
96
+	 * @access        public
97
+	 * @param        bool $QST_required
98
+	 */
99
+	public function set_required($QST_required = false)
100
+	{
101
+		$this->set('QST_required', $QST_required);
102
+	}
103
+
104
+
105
+	/**
106
+	 *        Set    Question display text
107
+	 *
108
+	 * @access        public
109
+	 * @param        string $QST_required_text
110
+	 */
111
+	public function set_required_text($QST_required_text = '')
112
+	{
113
+		$this->set('QST_required_text', $QST_required_text);
114
+	}
115
+
116
+
117
+	/**
118
+	 *        Sets the order of this question when placed in a sequence of questions
119
+	 *
120
+	 * @access        public
121
+	 * @param        int $QST_order
122
+	 */
123
+	public function set_order($QST_order = 0)
124
+	{
125
+		$this->set('QST_order', $QST_order);
126
+	}
127
+
128
+
129
+	/**
130
+	 *        Sets whether the question is admin-only
131
+	 *
132
+	 * @access        public
133
+	 * @param        bool $QST_admin_only
134
+	 */
135
+	public function set_admin_only($QST_admin_only = false)
136
+	{
137
+		$this->set('QST_admin_only', $QST_admin_only);
138
+	}
139
+
140
+
141
+	/**
142
+	 *        Sets the wordpress user ID on the question
143
+	 *
144
+	 * @access        public
145
+	 * @param        int $QST_wp_user
146
+	 */
147
+	public function set_wp_user($QST_wp_user = 1)
148
+	{
149
+		$this->set('QST_wp_user', $QST_wp_user);
150
+	}
151
+
152
+
153
+	/**
154
+	 *        Sets whether the question has been deleted
155
+	 *        (we use this boolean instead of actually
156
+	 *        deleting it because when users delete this question
157
+	 *        they really want to remove the question from future
158
+	 *        forms, BUT keep their old answers which depend
159
+	 *        on this record actually existing.
160
+	 *
161
+	 * @access        public
162
+	 * @param    bool $QST_deleted
163
+	 */
164
+	public function set_deleted($QST_deleted = false)
165
+	{
166
+		$this->set('QST_deleted', $QST_deleted);
167
+	}
168
+
169
+
170
+	/**
171
+	 * returns the text for displaying the question to users
172
+	 *
173
+	 * @access public
174
+	 * @return string
175
+	 */
176
+	public function display_text()
177
+	{
178
+		return $this->get('QST_display_text');
179
+	}
180
+
181
+
182
+	/**
183
+	 * returns the text for the administrative label
184
+	 *
185
+	 * @access public
186
+	 * @return string
187
+	 */
188
+	public function admin_label()
189
+	{
190
+		return $this->get('QST_admin_label');
191
+	}
192
+
193
+
194
+	/**
195
+	 * returns the attendee column name for this question
196
+	 *
197
+	 * @access public
198
+	 * @return string
199
+	 */
200
+	public function system_ID()
201
+	{
202
+		return $this->get('QST_system');
203
+	}
204
+
205
+
206
+	/**
207
+	 * returns either a string of 'text', 'textfield', etc.
208
+	 *
209
+	 * @access public
210
+	 * @return boolean
211
+	 */
212
+	public function required()
213
+	{
214
+		return $this->get('QST_required');
215
+	}
216
+
217
+
218
+	/**
219
+	 * returns the text which should be displayed when a user
220
+	 * doesn't answer this question in a form
221
+	 *
222
+	 * @access public
223
+	 * @return string
224
+	 */
225
+	public function required_text()
226
+	{
227
+		return $this->get('QST_required_text');
228
+	}
229
+
230
+
231
+	/**
232
+	 * returns the type of this question
233
+	 *
234
+	 * @access public
235
+	 * @return string
236
+	 */
237
+	public function type()
238
+	{
239
+		return $this->get('QST_type');
240
+	}
241
+
242
+
243
+	/**
244
+	 * returns an integer showing where this question should
245
+	 * be placed in a sequence of questions
246
+	 *
247
+	 * @access public
248
+	 * @return int
249
+	 */
250
+	public function order()
251
+	{
252
+		return $this->get('QST_order');
253
+	}
254
+
255
+
256
+	/**
257
+	 * returns whether this question should only appears to admins,
258
+	 * or to everyone
259
+	 *
260
+	 * @access public
261
+	 * @return boolean
262
+	 */
263
+	public function admin_only()
264
+	{
265
+		return $this->get('QST_admin_only');
266
+	}
267
+
268
+
269
+	/**
270
+	 * returns the id the wordpress user who created this question
271
+	 *
272
+	 * @access public
273
+	 * @return int
274
+	 */
275
+	public function wp_user()
276
+	{
277
+		return $this->get('QST_wp_user');
278
+	}
279
+
280
+
281
+	/**
282
+	 * returns whether this question has been marked as 'deleted'
283
+	 *
284
+	 * @access public
285
+	 * @return boolean
286
+	 */
287
+	public function deleted()
288
+	{
289
+		return $this->get('QST_deleted');
290
+	}
291
+
292
+
293
+	/**
294
+	 * Gets an array of related EE_Answer  to this EE_Question
295
+	 *
296
+	 * @return EE_Answer[]
297
+	 */
298
+	public function answers()
299
+	{
300
+		return $this->get_many_related('Answer');
301
+	}
302
+
303
+
304
+	/**
305
+	 * Boolean check for if there are answers on this question in th db
306
+	 *
307
+	 * @return boolean true = has answers, false = no answers.
308
+	 */
309
+	public function has_answers()
310
+	{
311
+		return $this->count_related('Answer') > 0 ? true : false;
312
+	}
313
+
314
+
315
+	/**
316
+	 * gets an array of EE_Question_Group which relate to this question
317
+	 *
318
+	 * @return EE_Question_Group[]
319
+	 */
320
+	public function question_groups()
321
+	{
322
+		return $this->get_many_related('Question_Group');
323
+	}
324
+
325
+
326
+	/**
327
+	 * Returns all the options for this question. By default, it returns only the not-yet-deleted ones.
328
+	 *
329
+	 * @param boolean      $notDeletedOptionsOnly            1
330
+	 *                                                       whether to return ALL options, or only the ones which have
331
+	 *                                                       not yet been deleleted
332
+	 * @param string|array $selected_value_to_always_include , when retrieving options to an ANSWERED question,
333
+	 *                                                       we want to usually only show non-deleted options AND the
334
+	 *                                                       value that was selected for the answer, whether it was
335
+	 *                                                       trashed or not.
336
+	 * @return EE_Question_Option[]
337
+	 */
338
+	public function options($notDeletedOptionsOnly = true, $selected_value_to_always_include = null)
339
+	{
340
+		if (! $this->ID()) {
341
+			return array();
342
+		}
343
+		$query_params = array();
344
+		if ($selected_value_to_always_include) {
345
+			if (is_array($selected_value_to_always_include)) {
346
+				$query_params[0]['OR*options-query']['QSO_value'] = array('IN', $selected_value_to_always_include);
347
+			} else {
348
+				$query_params[0]['OR*options-query']['QSO_value'] = $selected_value_to_always_include;
349
+			}
350
+		}
351
+		if ($notDeletedOptionsOnly) {
352
+			$query_params[0]['OR*options-query']['QSO_deleted'] = false;
353
+		}
354
+		// order by QSO_order
355
+		$query_params['order_by'] = array('QSO_order' => 'ASC');
356
+		return $this->get_many_related('Question_Option', $query_params);
357
+	}
358
+
359
+
360
+	/**
361
+	 * returns an array of EE_Question_Options which relate to this question
362
+	 *
363
+	 * @return \EE_Question_Option[]
364
+	 */
365
+	public function temp_options()
366
+	{
367
+		return $this->_model_relations['Question_Option'];
368
+	}
369
+
370
+
371
+	/**
372
+	 * Adds an option for this question. Note: if the option were previously associated with a different
373
+	 * Question, that relationship will be overwritten.
374
+	 *
375
+	 * @param EE_Question_Option $option
376
+	 * @return boolean success
377
+	 */
378
+	public function add_option(EE_Question_Option $option)
379
+	{
380
+		return $this->_add_relation_to($option, 'Question_Option');
381
+	}
382
+
383
+
384
+	/**
385
+	 * Adds an option directly to this question without saving to the db
386
+	 *
387
+	 * @param EE_Question_Option $option
388
+	 * @return boolean success
389
+	 */
390
+	public function add_temp_option(EE_Question_Option $option)
391
+	{
392
+		$this->_model_relations['Question_Option'][] = $option;
393
+		return true;
394
+	}
395
+
396
+
397
+	/**
398
+	 * Marks the option as deleted.
399
+	 *
400
+	 * @param EE_Question_Option $option
401
+	 * @return boolean success
402
+	 */
403
+	public function remove_option(EE_Question_Option $option)
404
+	{
405
+		return $this->_remove_relation_to($option, 'Question_Option');
406
+	}
407
+
408
+
409
+	/**
410
+	 * @return bool
411
+	 */
412
+	public function is_system_question()
413
+	{
414
+		$system_ID = $this->get('QST_system');
415
+		return ! empty($system_ID) ? true : false;
416
+	}
417
+
418
+
419
+	/**
420
+	 * The purpose of this method is set the question order this question order to be the max out of all questions
421
+	 *
422
+	 * @access public
423
+	 * @return void
424
+	 */
425
+	public function set_order_to_latest()
426
+	{
427
+		$latest_order = $this->get_model()->get_latest_question_order();
428
+		$latest_order++;
429
+		$this->set('QST_order', $latest_order);
430
+	}
431
+
432
+
433
+	/**
434
+	 * Retrieves the list of allowed question types from the model.
435
+	 *
436
+	 * @return string[]
437
+	 */
438
+	private function _allowed_question_types()
439
+	{
440
+		$questionModel = $this->get_model();
441
+		/* @var $questionModel EEM_Question */
442
+		return $questionModel->allowed_question_types();
443
+	}
444
+
445
+	/**
446
+	 * Duplicates this question and its question options
447
+	 *
448
+	 * @return \EE_Question
449
+	 */
450
+	public function duplicate($options = array())
451
+	{
452
+		$new_question = clone $this;
453
+		$new_question->set('QST_ID', null);
454
+		$new_question->set_display_text(sprintf(__('%s **Duplicate**', 'event_espresso'), $this->display_text()));
455
+		$new_question->set_admin_label(sprintf(__('%s **Duplicate**', 'event_espresso'), $this->admin_label()));
456
+		$new_question->set_system_ID(null);
457
+		$new_question->set_wp_user(get_current_user_id());
458
+		// if we're duplicating a trashed question, assume we don't want the new one to be trashed
459
+		$new_question->set_deleted(false);
460
+		$success = $new_question->save();
461
+		if ($success) {
462
+			// we don't totally want to duplicate the question options, because we want them to be for the NEW question
463
+			foreach ($this->options() as $question_option) {
464
+				$question_option->duplicate(array('QST_ID' => $new_question->ID()));
465
+			}
466
+			return $new_question;
467
+		} else {
468
+			return null;
469
+		}
470
+	}
471
+
472
+	/**
473
+	 * Returns the question's maximum allowed response size
474
+	 *
475
+	 * @return int|float
476
+	 */
477
+	public function max()
478
+	{
479
+		return $this->get('QST_max');
480
+	}
481
+
482
+	/**
483
+	 * Sets the question's maximum allowed response size
484
+	 *
485
+	 * @param int|float $new_max
486
+	 * @return void
487
+	 */
488
+	public function set_max($new_max)
489
+	{
490
+		$this->set('QST_max', $new_max);
491
+	}
492
+
493
+
494
+	/**
495
+	 * Creates a form input from this question which can be used in HTML forms
496
+	 *
497
+	 * @param EE_Registration $registration
498
+	 * @param EE_Answer       $answer
499
+	 * @param array           $input_constructor_args
500
+	 * @return EE_Form_Input_Base
501
+	 */
502
+	public function generate_form_input($registration = null, $answer = null, $input_constructor_args = array())
503
+	{
504
+		$identifier = $this->is_system_question() ? $this->system_ID() : $this->ID();
505
+
506
+		$input_constructor_args = array_merge(
507
+			array(
508
+				'required'                          => $this->required() ? true : false,
509
+				'html_label_text'                   => $this->display_text(),
510
+				'required_validation_error_message' => $this->required_text(),
511
+			),
512
+			$input_constructor_args
513
+		);
514
+		if (! $answer instanceof EE_Answer && $registration instanceof EE_Registration) {
515
+			$answer = EEM_Answer::instance()->get_registration_question_answer_object($registration, $this->ID());
516
+		}
517
+		// has this question been answered ?
518
+		if ($answer instanceof EE_Answer
519
+			&& $answer->value() !== ''
520
+		) {
521
+			// answer gets htmlspecialchars called on it, undo that please
522
+			// because the form input's display strategy may call esc_attr too
523
+			// which also does html special characters
524
+			$values_with_html_special_chars = $answer->value();
525
+			if (is_array($values_with_html_special_chars)) {
526
+				$default_value = array_map('htmlspecialchars_decode', $values_with_html_special_chars);
527
+			} else {
528
+				$default_value = htmlspecialchars_decode($values_with_html_special_chars);
529
+			}
530
+			$input_constructor_args['default'] = $default_value;
531
+		}
532
+		$max_max_for_question = EEM_Question::instance()->absolute_max_for_system_question($this->system_ID());
533
+		if (in_array(
534
+			$this->type(),
535
+			EEM_Question::instance()->questionTypesWithMaxLength(),
536
+			true
537
+		)) {
538
+			$input_constructor_args['validation_strategies'][] = new EE_Max_Length_Validation_Strategy(
539
+				null,
540
+				min($max_max_for_question, $this->max())
541
+			);
542
+		}
543
+		$input_constructor_args = apply_filters(
544
+			'FHEE__EE_SPCO_Reg_Step_Attendee_Information___generate_question_input__input_constructor_args',
545
+			$input_constructor_args,
546
+			$registration,
547
+			$this,
548
+			$answer
549
+		);
550
+
551
+		$result = null;
552
+		switch ($this->type()) {
553
+			// Text
554
+			case EEM_Question::QST_type_text:
555
+				$result = new EE_Text_Input($input_constructor_args);
556
+				break;
557
+			// Textarea
558
+			case EEM_Question::QST_type_textarea:
559
+				$result = new EE_Text_Area_Input($input_constructor_args);
560
+				break;
561
+			// Radio Buttons
562
+			case EEM_Question::QST_type_radio:
563
+				$result = new EE_Radio_Button_Input($this->options(), $input_constructor_args);
564
+				break;
565
+			// Dropdown
566
+			case EEM_Question::QST_type_dropdown:
567
+				$result = new EE_Select_Input($this->options(), $input_constructor_args);
568
+				break;
569
+			// State Dropdown
570
+			case EEM_Question::QST_type_state:
571
+				$state_options = apply_filters(
572
+					'FHEE__EE_Question__generate_form_input__state_options',
573
+					null,
574
+					$this,
575
+					$registration,
576
+					$answer
577
+				);
578
+				$result = new EE_State_Select_Input($state_options, $input_constructor_args);
579
+				break;
580
+			// Country Dropdown
581
+			case EEM_Question::QST_type_country:
582
+				$country_options = apply_filters(
583
+					'FHEE__EE_Question__generate_form_input__country_options',
584
+					null,
585
+					$this,
586
+					$registration,
587
+					$answer
588
+				);
589
+				$result = new EE_Country_Select_Input($country_options, $input_constructor_args);
590
+				break;
591
+			// Checkboxes
592
+			case EEM_Question::QST_type_checkbox:
593
+				$result = new EE_Checkbox_Multi_Input($this->options(), $input_constructor_args);
594
+				break;
595
+			// Date
596
+			case EEM_Question::QST_type_date:
597
+				$result = new EE_Datepicker_Input($input_constructor_args);
598
+				break;
599
+			case EEM_Question::QST_type_html_textarea:
600
+				$input_constructor_args['validation_strategies'][] = new EE_Simple_HTML_Validation_Strategy();
601
+				$result = new EE_Text_Area_Input($input_constructor_args);
602
+				$result->remove_validation_strategy('EE_Plaintext_Validation_Strategy');
603
+				break;
604
+			case EEM_Question::QST_type_email:
605
+					$result = new EE_Email_Input($input_constructor_args);
606
+				break;
607
+			// Email confirm
608
+			case EEM_Question::QST_type_email_confirm:
609
+				$result = new EE_Email_Confirm_Input($input_constructor_args);
610
+				break;
611
+			case EEM_Question::QST_type_us_phone:
612
+				$result = new EE_Phone_Input($input_constructor_args);
613
+				break;
614
+			case EEM_Question::QST_type_int:
615
+				$result = new EE_Integer_Input($input_constructor_args);
616
+				break;
617
+			case EEM_Question::QST_type_decimal:
618
+				$result = new EE_Float_Input($input_constructor_args);
619
+				break;
620
+			case EEM_Question::QST_type_url:
621
+				$input_constructor_args['validation_strategies'][] = LoaderFactory::getLoader()->getNew('EE_URL_Validation_Strategy');
622
+				$result = new EE_Text_Input($input_constructor_args);
623
+				break;
624
+			case EEM_Question::QST_type_year:
625
+				$result = new EE_Year_Input(
626
+					$input_constructor_args,
627
+					apply_filters(
628
+						'FHEE__EE_SPCO_Reg_Step_Attendee_Information___generate_question_input__year_question__four_digit',
629
+						true,
630
+						$this
631
+					),
632
+					apply_filters(
633
+						'FHEE__EE_SPCO_Reg_Step_Attendee_Information___generate_question_input__year_question__early_range',
634
+						100,
635
+						$this
636
+					),
637
+					apply_filters(
638
+						'FHEE__EE_SPCO_Reg_Step_Attendee_Information___generate_question_input__year_question__end_range',
639
+						100,
640
+						$this
641
+					)
642
+				);
643
+				break;
644
+			case EEM_Question::QST_type_multi_select:
645
+				$result = new EE_Select_Multiple_Input($this->options(), $input_constructor_args);
646
+				break;
647
+			// fallback
648
+			default:
649
+				$default_input = apply_filters(
650
+					'FHEE__EE_SPCO_Reg_Step_Attendee_Information___generate_question_input__default',
651
+					null,
652
+					$this->type(),
653
+					$this,
654
+					$input_constructor_args
655
+				);
656
+				if (! $default_input) {
657
+					$default_input = new EE_Text_Input($input_constructor_args);
658
+				}
659
+				$result = $default_input;
660
+		}
661
+		return apply_filters('FHEE__EE_Question__generate_form_input__return', $result, $registration, $this, $answer);
662
+	}
663
+
664
+
665
+	/**
666
+	 * Returns whether or not this question type should have question option entries
667
+	 *
668
+	 * @return bool
669
+	 */
670
+	public function should_have_question_options()
671
+	{
672
+		return in_array(
673
+			$this->type(),
674
+			$this->_model->question_types_with_options(),
675
+			true
676
+		);
677
+	}
678 678
 }
Please login to merge, or discard this patch.