Completed
Branch BUG-10375-migrations-not-repor... (1e9646)
by
unknown
62:53 queued 49:42
created
core/db_models/fields/EE_Post_Content_Field.php 1 patch
Indentation   +47 added lines, -47 removed lines patch added patch discarded remove patch
@@ -8,56 +8,56 @@
 block discarded – undo
8 8
 class EE_Post_Content_Field extends EE_Text_Field_Base
9 9
 {
10 10
 
11
-    /**
12
-     * @param string $table_column
13
-     * @param string $nicename
14
-     * @param bool   $nullable
15
-     * @param null   $default_value
16
-     */
17
-    public function __construct($table_column, $nicename, $nullable, $default_value = null)
18
-    {
19
-        parent::__construct($table_column, $nicename, $nullable, $default_value);
20
-        $this->setSchemaType('object');
21
-    }
11
+	/**
12
+	 * @param string $table_column
13
+	 * @param string $nicename
14
+	 * @param bool   $nullable
15
+	 * @param null   $default_value
16
+	 */
17
+	public function __construct($table_column, $nicename, $nullable, $default_value = null)
18
+	{
19
+		parent::__construct($table_column, $nicename, $nullable, $default_value);
20
+		$this->setSchemaType('object');
21
+	}
22 22
 
23 23
 
24
-    /**
25
-     * removes all tags which a WP Post wouldn't allow in its content normally
26
-     *
27
-     * @param string $value
28
-     * @return string
29
-     */
30
-    function prepare_for_set($value)
31
-    {
32
-        if (! current_user_can('unfiltered_html')) {
33
-            $value = wp_kses("$value", wp_kses_allowed_html('post'));
34
-        }
35
-        return parent::prepare_for_set($value);
36
-    }
24
+	/**
25
+	 * removes all tags which a WP Post wouldn't allow in its content normally
26
+	 *
27
+	 * @param string $value
28
+	 * @return string
29
+	 */
30
+	function prepare_for_set($value)
31
+	{
32
+		if (! current_user_can('unfiltered_html')) {
33
+			$value = wp_kses("$value", wp_kses_allowed_html('post'));
34
+		}
35
+		return parent::prepare_for_set($value);
36
+	}
37 37
 
38
-    function prepare_for_set_from_db($value_found_in_db_for_model_object)
39
-    {
40
-        return $value_found_in_db_for_model_object;
41
-    }
38
+	function prepare_for_set_from_db($value_found_in_db_for_model_object)
39
+	{
40
+		return $value_found_in_db_for_model_object;
41
+	}
42 42
 
43 43
 
44
-    public function getSchemaProperties()
45
-    {
46
-        return array(
47
-            'raw' => array(
48
-                'description' =>  sprintf(
49
-                    __('%s - the content as it exists in the database.', 'event_espresso'),
50
-                    $this->get_nicename()
51
-                ),
52
-                'type' => 'string'
53
-            ),
54
-            'rendered' => array(
55
-                'description' =>  sprintf(
56
-                    __('%s - the content rendered for display.', 'event_espresso'),
57
-                    $this->get_nicename()
58
-                ),
59
-                'type' => 'string'
60
-            )
61
-        );
62
-    }
44
+	public function getSchemaProperties()
45
+	{
46
+		return array(
47
+			'raw' => array(
48
+				'description' =>  sprintf(
49
+					__('%s - the content as it exists in the database.', 'event_espresso'),
50
+					$this->get_nicename()
51
+				),
52
+				'type' => 'string'
53
+			),
54
+			'rendered' => array(
55
+				'description' =>  sprintf(
56
+					__('%s - the content rendered for display.', 'event_espresso'),
57
+					$this->get_nicename()
58
+				),
59
+				'type' => 'string'
60
+			)
61
+		);
62
+	}
63 63
 }
64 64
\ No newline at end of file
Please login to merge, or discard this patch.
core/db_models/fields/EE_Datetime_Field.php 2 patches
Spacing   +10 added lines, -10 removed lines patch added patch discarded remove patch
@@ -210,8 +210,8 @@  discard block
 block discarded – undo
210 210
 
211 211
             default :
212 212
                 return $pretty
213
-                    ? $this->_pretty_date_format . ' ' . $this->_pretty_time_format
214
-                    : $this->_date_format . ' ' . $this->_time_format;
213
+                    ? $this->_pretty_date_format.' '.$this->_pretty_time_format
214
+                    : $this->_date_format.' '.$this->_time_format;
215 215
         }
216 216
     }
217 217
 
@@ -467,7 +467,7 @@  discard block
 block discarded – undo
467 467
      */
468 468
     protected function _prepare_for_display($DateTime, $schema = false)
469 469
     {
470
-        if (! $DateTime instanceof DateTime) {
470
+        if ( ! $DateTime instanceof DateTime) {
471 471
             if ($this->_nullable) {
472 472
                 return '';
473 473
             } else {
@@ -502,15 +502,15 @@  discard block
 block discarded – undo
502 502
             if ($this->_display_timezone()) {
503 503
                 //must be explicit because schema could equal true.
504 504
                 if ($schema === 'no_html') {
505
-                    $timezone_string = ' (' . $DateTime->format('T') . ')';
505
+                    $timezone_string = ' ('.$DateTime->format('T').')';
506 506
                 } else {
507
-                    $timezone_string = ' <span class="ee_dtt_timezone_string">(' . $DateTime->format('T') . ')</span>';
507
+                    $timezone_string = ' <span class="ee_dtt_timezone_string">('.$DateTime->format('T').')</span>';
508 508
                 }
509 509
             } else {
510 510
                 $timezone_string = '';
511 511
             }
512 512
 
513
-            return $DateTime->format($format_string) . $timezone_string;
513
+            return $DateTime->format($format_string).$timezone_string;
514 514
         } else {
515 515
             return $DateTime->format($format_string);
516 516
         }
@@ -528,7 +528,7 @@  discard block
 block discarded – undo
528 528
     public function prepare_for_use_in_db($datetime_value)
529 529
     {
530 530
         //we allow an empty value or DateTime object, but nothing else.
531
-        if (! empty($datetime_value) && ! $datetime_value instanceof DateTime) {
531
+        if ( ! empty($datetime_value) && ! $datetime_value instanceof DateTime) {
532 532
             throw new EE_Error(
533 533
                 __(
534 534
                     'The incoming value being prepared for setting in the database must either be empty or a php DateTime object',
@@ -583,7 +583,7 @@  discard block
 block discarded – undo
583 583
             }
584 584
         }
585 585
 
586
-        if (! $DateTime instanceof DbSafeDateTime) {
586
+        if ( ! $DateTime instanceof DbSafeDateTime) {
587 587
             // if still no datetime object, then let's just use now
588 588
             $DateTime = new DbSafeDateTime(\EE_Datetime_Field::now, $this->get_UTC_DateTimeZone());
589 589
         }
@@ -662,7 +662,7 @@  discard block
 block discarded – undo
662 662
         }
663 663
         //not a unix timestamp.  So we will use the set format on this object and set timezone to
664 664
         //create the DateTime object.
665
-        $format = $this->_date_format . ' ' . $this->_time_format;
665
+        $format = $this->_date_format.' '.$this->_time_format;
666 666
         try {
667 667
             $DateTime = DateTime::createFromFormat($format, $date_string, $this->_DateTimeZone);
668 668
             if ($DateTime instanceof DateTime) {
@@ -671,7 +671,7 @@  discard block
 block discarded – undo
671 671
                     $this->_DateTimeZone
672 672
                 );
673 673
             }
674
-            if (! $DateTime instanceof DbSafeDateTime) {
674
+            if ( ! $DateTime instanceof DbSafeDateTime) {
675 675
                 throw new EE_Error(
676 676
                     sprintf(
677 677
                         __('"%1$s" does not represent a valid Date Time in the format "%2$s".', 'event_espresso'),
Please login to merge, or discard this patch.
Indentation   +749 added lines, -749 removed lines patch added patch discarded remove patch
@@ -15,753 +15,753 @@
 block discarded – undo
15 15
 class EE_Datetime_Field extends EE_Model_Field_Base
16 16
 {
17 17
 
18
-    /**
19
-     * The pattern we're looking for is if only the characters 0-9 are found and there are only
20
-     * 10 or more numbers (because 9 numbers even with all 9's would be sometime in 2001 )
21
-     *
22
-     * @type string unix_timestamp_regex
23
-     */
24
-    const unix_timestamp_regex = '/[0-9]{10,}/';
25
-
26
-    /**
27
-     * @type string mysql_timestamp_format
28
-     */
29
-    const mysql_timestamp_format = 'Y-m-d H:i:s';
30
-
31
-    /**
32
-     * @type string mysql_date_format
33
-     */
34
-    const mysql_date_format = 'Y-m-d';
35
-
36
-    /**
37
-     * @type string mysql_time_format
38
-     */
39
-    const mysql_time_format = 'H:i:s';
40
-
41
-    /**
42
-     * Const for using in the default value. If the field's default is set to this,
43
-     * then we will return the time of calling `get_default_value()`, not
44
-     * just the current time at construction
45
-     */
46
-    const now = 'now';
47
-
48
-    /**
49
-     * The following properties hold the default formats for date and time.
50
-     * Defaults are set via the constructor and can be overridden on class instantiation.
51
-     * However they can also be overridden later by the set_format() method
52
-     * (and corresponding set_date_format, set_time_format methods);
53
-     */
54
-    /**
55
-     * @type string $_date_format
56
-     */
57
-    protected $_date_format = '';
58
-
59
-    /**
60
-     * @type string $_time_format
61
-     */
62
-    protected $_time_format = '';
63
-
64
-    /**
65
-     * @type string $_pretty_date_format
66
-     */
67
-    protected $_pretty_date_format = '';
68
-
69
-    /**
70
-     * @type string $_pretty_time_format
71
-     */
72
-    protected $_pretty_time_format = '';
73
-
74
-    /**
75
-     * @type DateTimeZone $_DateTimeZone
76
-     */
77
-    protected $_DateTimeZone;
78
-
79
-    /**
80
-     * @type DateTimeZone $_UTC_DateTimeZone
81
-     */
82
-    protected $_UTC_DateTimeZone;
83
-
84
-    /**
85
-     * @type DateTimeZone $_blog_DateTimeZone
86
-     */
87
-    protected $_blog_DateTimeZone;
88
-
89
-
90
-    /**
91
-     * This property holds how we want the output returned when getting a datetime string.  It is set for the
92
-     * set_date_time_output() method.  By default this is empty.  When empty, we are assuming that we want both date
93
-     * and time returned via getters.
94
-     *
95
-     * @var mixed (null|string)
96
-     */
97
-    protected $_date_time_output;
98
-
99
-
100
-    /**
101
-     * timezone string
102
-     * This gets set by the constructor and can be changed by the "set_timezone()" method so that we know what timezone
103
-     * incoming strings|timestamps are in.  This can also be used before a get to set what timezone you want strings
104
-     * coming out of the object to be in.  Default timezone is the current WP timezone option setting
105
-     *
106
-     * @var string
107
-     */
108
-    protected $_timezone_string;
109
-
110
-
111
-    /**
112
-     * This holds whatever UTC offset for the blog (we automatically convert timezone strings into their related
113
-     * offsets for comparison purposes).
114
-     *
115
-     * @var int
116
-     */
117
-    protected $_blog_offset;
118
-
119
-
120
-    /**
121
-     * @param string $table_column
122
-     * @param string $nice_name
123
-     * @param bool   $nullable
124
-     * @param string $default_value
125
-     * @param string $timezone_string
126
-     * @param string $date_format
127
-     * @param string $time_format
128
-     * @param string $pretty_date_format
129
-     * @param string $pretty_time_format
130
-     * @throws \EE_Error
131
-     */
132
-    public function __construct(
133
-        $table_column,
134
-        $nice_name,
135
-        $nullable,
136
-        $default_value,
137
-        $timezone_string = '',
138
-        $date_format = '',
139
-        $time_format = '',
140
-        $pretty_date_format = '',
141
-        $pretty_time_format = ''
142
-    ) {
143
-
144
-        $this->_date_format        = ! empty($date_format) ? $date_format : get_option('date_format');
145
-        $this->_time_format        = ! empty($time_format) ? $time_format : get_option('time_format');
146
-        $this->_pretty_date_format = ! empty($pretty_date_format) ? $pretty_date_format : get_option('date_format');
147
-        $this->_pretty_time_format = ! empty($pretty_time_format) ? $pretty_time_format : get_option('time_format');
148
-
149
-        parent::__construct($table_column, $nice_name, $nullable, $default_value);
150
-        $this->set_timezone($timezone_string);
151
-        $this->setSchemaFormat('date-time');
152
-    }
153
-
154
-
155
-    /**
156
-     * @return DateTimeZone
157
-     * @throws \EE_Error
158
-     */
159
-    public function get_UTC_DateTimeZone()
160
-    {
161
-        return $this->_UTC_DateTimeZone instanceof DateTimeZone
162
-            ? $this->_UTC_DateTimeZone
163
-            : $this->_create_timezone_object_from_timezone_string('UTC');
164
-    }
165
-
166
-
167
-    /**
168
-     * @return DateTimeZone
169
-     * @throws \EE_Error
170
-     */
171
-    public function get_blog_DateTimeZone()
172
-    {
173
-        return $this->_blog_DateTimeZone instanceof DateTimeZone
174
-            ? $this->_blog_DateTimeZone
175
-            : $this->_create_timezone_object_from_timezone_string('');
176
-    }
177
-
178
-
179
-    /**
180
-     * this prepares any incoming date data and make sure its converted to a utc unix timestamp
181
-     *
182
-     * @param  string|int $value_inputted_for_field_on_model_object could be a string formatted date time or int unix
183
-     *                                                              timestamp
184
-     * @return DateTime
185
-     */
186
-    public function prepare_for_set($value_inputted_for_field_on_model_object)
187
-    {
188
-        return $this->_get_date_object($value_inputted_for_field_on_model_object);
189
-    }
190
-
191
-
192
-    /**
193
-     * This returns the format string to be used by getters depending on what the $_date_time_output property is set at.
194
-     * getters need to know whether we're just returning the date or the time or both.  By default we return both.
195
-     *
196
-     * @param bool $pretty If we're returning the pretty formats or standard format string.
197
-     * @return string    The final assembled format string.
198
-     */
199
-    protected function _get_date_time_output($pretty = false)
200
-    {
201
-
202
-        switch ($this->_date_time_output) {
203
-            case 'time' :
204
-                return $pretty ? $this->_pretty_time_format : $this->_time_format;
205
-                break;
206
-
207
-            case 'date' :
208
-                return $pretty ? $this->_pretty_date_format : $this->_date_format;
209
-                break;
210
-
211
-            default :
212
-                return $pretty
213
-                    ? $this->_pretty_date_format . ' ' . $this->_pretty_time_format
214
-                    : $this->_date_format . ' ' . $this->_time_format;
215
-        }
216
-    }
217
-
218
-
219
-    /**
220
-     * This just sets the $_date_time_output property so we can flag how date and times are formatted before being
221
-     * returned (using the format properties)
222
-     *
223
-     * @param string $what acceptable values are 'time' or 'date'.
224
-     *                     Any other value will be set but will always result
225
-     *                     in both 'date' and 'time' being returned.
226
-     * @return void
227
-     */
228
-    public function set_date_time_output($what = null)
229
-    {
230
-        $this->_date_time_output = $what;
231
-    }
232
-
233
-
234
-    /**
235
-     * See $_timezone property for description of what the timezone property is for.  This SETS the timezone internally
236
-     * for being able to reference what timezone we are running conversions on when converting TO the internal timezone
237
-     * (UTC Unix Timestamp) for the object OR when converting FROM the internal timezone (UTC Unix Timestamp).
238
-     * We also set some other properties in this method.
239
-     *
240
-     * @param string $timezone_string A valid timezone string as described by @link
241
-     *                                http://www.php.net/manual/en/timezones.php
242
-     * @return void
243
-     * @throws \EE_Error
244
-     */
245
-    public function set_timezone($timezone_string)
246
-    {
247
-        if (empty($timezone_string) && $this->_timezone_string !== null) {
248
-            // leave the timezone AS-IS if we already have one and
249
-            // the function arg didn't provide one
250
-            return;
251
-        }
252
-        $timezone_string        = EEH_DTT_Helper::get_valid_timezone_string($timezone_string);
253
-        $this->_timezone_string = ! empty($timezone_string) ? $timezone_string : 'UTC';
254
-        $this->_DateTimeZone    = $this->_create_timezone_object_from_timezone_string($this->_timezone_string);
255
-    }
256
-
257
-
258
-    /**
259
-     * _create_timezone_object_from_timezone_name
260
-     *
261
-     * @access protected
262
-     * @param string $timezone_string
263
-     * @return \DateTimeZone
264
-     * @throws \EE_Error
265
-     */
266
-    protected function _create_timezone_object_from_timezone_string($timezone_string = '')
267
-    {
268
-        return new DateTimeZone(EEH_DTT_Helper::get_valid_timezone_string($timezone_string));
269
-    }
270
-
271
-
272
-    /**
273
-     * This just returns whatever is set for the current timezone.
274
-     *
275
-     * @access public
276
-     * @return string timezone string
277
-     */
278
-    public function get_timezone()
279
-    {
280
-        return $this->_timezone_string;
281
-    }
282
-
283
-
284
-    /**
285
-     * set the $_date_format property
286
-     *
287
-     * @access public
288
-     * @param string $format a new date format (corresponding to formats accepted by PHP date() function)
289
-     * @param bool   $pretty Whether to set pretty format or not.
290
-     * @return void
291
-     */
292
-    public function set_date_format($format, $pretty = false)
293
-    {
294
-        if ($pretty) {
295
-            $this->_pretty_date_format = $format;
296
-        } else {
297
-            $this->_date_format = $format;
298
-        }
299
-    }
300
-
301
-
302
-    /**
303
-     * return the $_date_format property value.
304
-     *
305
-     * @param bool $pretty Whether to get pretty format or not.
306
-     * @return string
307
-     */
308
-    public function get_date_format($pretty = false)
309
-    {
310
-        return $pretty ? $this->_pretty_date_format : $this->_date_format;
311
-    }
312
-
313
-
314
-    /**
315
-     * set the $_time_format property
316
-     *
317
-     * @access public
318
-     * @param string $format a new time format (corresponding to formats accepted by PHP date() function)
319
-     * @param bool   $pretty Whether to set pretty format or not.
320
-     * @return void
321
-     */
322
-    public function set_time_format($format, $pretty = false)
323
-    {
324
-        if ($pretty) {
325
-            $this->_pretty_time_format = $format;
326
-        } else {
327
-            $this->_time_format = $format;
328
-        }
329
-    }
330
-
331
-
332
-    /**
333
-     * return the $_time_format property value.
334
-     *
335
-     * @param bool $pretty Whether to get pretty format or not.
336
-     * @return string
337
-     */
338
-    public function get_time_format($pretty = false)
339
-    {
340
-        return $pretty ? $this->_pretty_time_format : $this->_time_format;
341
-    }
342
-
343
-
344
-    /**
345
-     * set the $_pretty_date_format property
346
-     *
347
-     * @access public
348
-     * @param string $format a new pretty date format (corresponding to formats accepted by PHP date() function)
349
-     * @return void
350
-     */
351
-    public function set_pretty_date_format($format)
352
-    {
353
-        $this->_pretty_date_format = $format;
354
-    }
355
-
356
-
357
-    /**
358
-     * set the $_pretty_time_format property
359
-     *
360
-     * @access public
361
-     * @param string $format a new pretty time format (corresponding to formats accepted by PHP date() function)
362
-     * @return void
363
-     */
364
-    public function set_pretty_time_format($format)
365
-    {
366
-        $this->_pretty_time_format = $format;
367
-    }
368
-
369
-
370
-    /**
371
-     * Only sets the time portion of the datetime.
372
-     *
373
-     * @param string|DateTime $time_to_set_string like 8am OR a DateTime object.
374
-     * @param DateTime        $current            current DateTime object for the datetime field
375
-     * @return DateTime
376
-     */
377
-    public function prepare_for_set_with_new_time($time_to_set_string, DateTime $current)
378
-    {
379
-        // if $time_to_set_string is datetime object, then let's use it to set the parse array.
380
-        // Otherwise parse the string.
381
-        if ($time_to_set_string instanceof DateTime) {
382
-            $parsed = array(
383
-                'hour'   => $time_to_set_string->format('H'),
384
-                'minute' => $time_to_set_string->format('i'),
385
-                'second' => $time_to_set_string->format('s'),
386
-            );
387
-        } else {
388
-            //parse incoming string
389
-            $parsed = date_parse_from_format($this->_time_format, $time_to_set_string);
390
-        }
391
-
392
-        //make sure $current is in the correct timezone.
393
-        $current->setTimezone($this->_DateTimeZone);
394
-
395
-        return $current->setTime($parsed['hour'], $parsed['minute'], $parsed['second']);
396
-    }
397
-
398
-
399
-    /**
400
-     * Only sets the date portion of the datetime.
401
-     *
402
-     * @param string|DateTime $date_to_set_string like Friday, January 8th or a DateTime object.
403
-     * @param DateTime        $current            current DateTime object for the datetime field
404
-     * @return DateTime
405
-     */
406
-    public function prepare_for_set_with_new_date($date_to_set_string, DateTime $current)
407
-    {
408
-        // if $time_to_set_string is datetime object, then let's use it to set the parse array.
409
-        // Otherwise parse the string.
410
-        if ($date_to_set_string instanceof DateTime) {
411
-            $parsed = array(
412
-                'year'  => $date_to_set_string->format('Y'),
413
-                'month' => $date_to_set_string->format('m'),
414
-                'day'   => $date_to_set_string->format('d'),
415
-            );
416
-        } else {
417
-            //parse incoming string
418
-            $parsed = date_parse_from_format($this->_date_format, $date_to_set_string);
419
-        }
420
-
421
-        //make sure $current is in the correct timezone
422
-        $current->setTimezone($this->_DateTimeZone);
423
-
424
-        return $current->setDate($parsed['year'], $parsed['month'], $parsed['day']);
425
-    }
426
-
427
-
428
-    /**
429
-     * This prepares the EE_DateTime value to be saved to the db as mysql timestamp (UTC +0 timezone).  When the
430
-     * datetime gets to this stage it should ALREADY be in UTC time
431
-     *
432
-     * @param  DateTime $DateTime
433
-     * @return string formatted date time for given timezone
434
-     * @throws \EE_Error
435
-     */
436
-    public function prepare_for_get($DateTime)
437
-    {
438
-        return $this->_prepare_for_display($DateTime);
439
-    }
440
-
441
-
442
-    /**
443
-     * This differs from prepare_for_get in that it considers whether the internal $_timezone differs
444
-     * from the set wp timezone.  If so, then it returns the datetime string formatted via
445
-     * _pretty_date_format, and _pretty_time_format.  However, it also appends a timezone
446
-     * abbreviation to the date_string.
447
-     *
448
-     * @param mixed $DateTime
449
-     * @param null  $schema
450
-     * @return string
451
-     * @throws \EE_Error
452
-     */
453
-    public function prepare_for_pretty_echoing($DateTime, $schema = null)
454
-    {
455
-        return $this->_prepare_for_display($DateTime, $schema ? $schema : true);
456
-    }
457
-
458
-
459
-    /**
460
-     * This prepares the EE_DateTime value to be saved to the db as mysql timestamp (UTC +0
461
-     * timezone).
462
-     *
463
-     * @param DateTime    $DateTime
464
-     * @param bool|string $schema
465
-     * @return string
466
-     * @throws \EE_Error
467
-     */
468
-    protected function _prepare_for_display($DateTime, $schema = false)
469
-    {
470
-        if (! $DateTime instanceof DateTime) {
471
-            if ($this->_nullable) {
472
-                return '';
473
-            } else {
474
-                if (WP_DEBUG) {
475
-                    throw new EE_Error(
476
-                        sprintf(
477
-                            __(
478
-                                'EE_Datetime_Field::_prepare_for_display requires a DateTime class to be the value for the $DateTime argument because the %s field is not nullable.',
479
-                                'event_espresso'
480
-                            ),
481
-                            $this->_nicename
482
-                        )
483
-                    );
484
-                } else {
485
-                    $DateTime = new DbSafeDateTime(\EE_Datetime_Field::now);
486
-                    EE_Error::add_error(
487
-                        sprintf(
488
-                            __(
489
-                                'EE_Datetime_Field::_prepare_for_display requires a DateTime class to be the value for the $DateTime argument because the %s field is not nullable.  When WP_DEBUG is false, the value is set to "now" instead of throwing an exception.',
490
-                                'event_espresso'
491
-                            ),
492
-                            $this->_nicename
493
-                        )
494
-                    );
495
-                }
496
-            }
497
-        }
498
-        $format_string = $this->_get_date_time_output($schema);
499
-        //make sure datetime_value is in the correct timezone (in case that's been updated).
500
-        $DateTime->setTimezone($this->_DateTimeZone);
501
-        if ($schema) {
502
-            if ($this->_display_timezone()) {
503
-                //must be explicit because schema could equal true.
504
-                if ($schema === 'no_html') {
505
-                    $timezone_string = ' (' . $DateTime->format('T') . ')';
506
-                } else {
507
-                    $timezone_string = ' <span class="ee_dtt_timezone_string">(' . $DateTime->format('T') . ')</span>';
508
-                }
509
-            } else {
510
-                $timezone_string = '';
511
-            }
512
-
513
-            return $DateTime->format($format_string) . $timezone_string;
514
-        } else {
515
-            return $DateTime->format($format_string);
516
-        }
517
-    }
518
-
519
-
520
-    /**
521
-     * This prepares the EE_DateTime value to be saved to the db as mysql timestamp (UTC +0
522
-     * timezone).
523
-     *
524
-     * @param  mixed $datetime_value u
525
-     * @return string mysql timestamp in UTC
526
-     * @throws \EE_Error
527
-     */
528
-    public function prepare_for_use_in_db($datetime_value)
529
-    {
530
-        //we allow an empty value or DateTime object, but nothing else.
531
-        if (! empty($datetime_value) && ! $datetime_value instanceof DateTime) {
532
-            throw new EE_Error(
533
-                __(
534
-                    'The incoming value being prepared for setting in the database must either be empty or a php DateTime object',
535
-                    'event_espresso'
536
-                )
537
-            );
538
-        }
539
-
540
-        if ($datetime_value instanceof DateTime) {
541
-            if ( ! $datetime_value instanceof DbSafeDateTime) {
542
-                $datetime_value = DbSafeDateTime::createFromDateTime($datetime_value);
543
-            }
544
-
545
-            return $datetime_value->setTimezone($this->get_UTC_DateTimeZone())->format(
546
-                EE_Datetime_Field::mysql_timestamp_format
547
-            );
548
-        }
549
-
550
-        // if $datetime_value is empty, and ! $this->_nullable, use current_time() but set the GMT flag to true
551
-        return ! $this->_nullable && empty($datetime_value) ? current_time('mysql', true) : null;
552
-    }
553
-
554
-
555
-    /**
556
-     * This prepares the datetime for internal usage as a PHP DateTime object OR null (if nullable is
557
-     * allowed)
558
-     *
559
-     * @param string $datetime_string mysql timestamp in UTC
560
-     * @return  mixed null | DateTime
561
-     * @throws \EE_Error
562
-     */
563
-    public function prepare_for_set_from_db($datetime_string)
564
-    {
565
-        //if $datetime_value is empty, and ! $this->_nullable, just use time()
566
-        if (empty($datetime_string) && $this->_nullable) {
567
-            return null;
568
-        }
569
-        // datetime strings from the db should ALWAYS be in UTC+0, so use UTC_DateTimeZone when creating
570
-        if (empty($datetime_string)) {
571
-            $DateTime = new DbSafeDateTime(\EE_Datetime_Field::now, $this->get_UTC_DateTimeZone());
572
-        } else {
573
-            $DateTime = DateTime::createFromFormat(
574
-                EE_Datetime_Field::mysql_timestamp_format,
575
-                $datetime_string,
576
-                $this->get_UTC_DateTimeZone()
577
-            );
578
-            if ($DateTime instanceof \DateTime) {
579
-                $DateTime = new DbSafeDateTime(
580
-                    $DateTime->format(\EE_Datetime_Field::mysql_timestamp_format),
581
-                    $this->get_UTC_DateTimeZone()
582
-                );
583
-            }
584
-        }
585
-
586
-        if (! $DateTime instanceof DbSafeDateTime) {
587
-            // if still no datetime object, then let's just use now
588
-            $DateTime = new DbSafeDateTime(\EE_Datetime_Field::now, $this->get_UTC_DateTimeZone());
589
-        }
590
-        // THEN apply the field's set DateTimeZone
591
-        $DateTime->setTimezone($this->_DateTimeZone);
592
-
593
-        return $DateTime;
594
-    }
595
-
596
-
597
-    /**
598
-     * All this method does is determine if we're going to display the timezone string or not on any output.
599
-     * To determine this we check if the set timezone offset is different than the blog's set timezone offset.
600
-     * If so, then true.
601
-     *
602
-     * @return bool true for yes false for no
603
-     * @throws \EE_Error
604
-     */
605
-    protected function _display_timezone()
606
-    {
607
-
608
-        // first let's do a comparison of timezone strings.
609
-        // If they match then we can get out without any further calculations
610
-        $blog_string = get_option('timezone_string');
611
-        if ($blog_string === $this->_timezone_string) {
612
-            return false;
613
-        }
614
-        // now we need to calc the offset for the timezone string so we can compare with the blog offset.
615
-        $this_offset = $this->get_timezone_offset($this->_DateTimeZone);
616
-        $blog_offset = $this->get_timezone_offset($this->get_blog_DateTimeZone());
617
-        // now compare
618
-        return $blog_offset !== $this_offset;
619
-    }
620
-
621
-
622
-    /**
623
-     * This method returns a php DateTime object for setting on the EE_Base_Class model.
624
-     * EE passes around DateTime objects because they are MUCH easier to manipulate and deal
625
-     * with.
626
-     *
627
-     * @param int|string|DateTime $date_string            This should be the incoming date string.  It's assumed to be
628
-     *                                                    in the format that is set on the date_field (or DateTime
629
-     *                                                    object)!
630
-     * @return DateTime
631
-     */
632
-    protected function _get_date_object($date_string)
633
-    {
634
-        //first if this is an empty date_string and nullable is allowed, just return null.
635
-        if ($this->_nullable && empty($date_string)) {
636
-            return null;
637
-        }
638
-
639
-        // if incoming date
640
-        if ($date_string instanceof DateTime) {
641
-            $date_string->setTimezone($this->_DateTimeZone);
642
-
643
-            return $date_string;
644
-        }
645
-        // if empty date_string and made it here.
646
-        // Return a datetime object for now in the given timezone.
647
-        if (empty($date_string)) {
648
-            return new DbSafeDateTime(\EE_Datetime_Field::now, $this->_DateTimeZone);
649
-        }
650
-        // if $date_string is matches something that looks like a Unix timestamp let's just use it.
651
-        if (preg_match(EE_Datetime_Field::unix_timestamp_regex, $date_string)) {
652
-            try {
653
-                // This is operating under the assumption that the incoming Unix timestamp
654
-                // is an ACTUAL Unix timestamp and not the calculated one output by current_time('timestamp');
655
-                $DateTime = new DbSafeDateTime(\EE_Datetime_Field::now, $this->_DateTimeZone);
656
-                $DateTime->setTimestamp($date_string);
657
-
658
-                return $DateTime;
659
-            } catch (Exception $e) {
660
-                // should be rare, but if things got fooled then let's just continue
661
-            }
662
-        }
663
-        //not a unix timestamp.  So we will use the set format on this object and set timezone to
664
-        //create the DateTime object.
665
-        $format = $this->_date_format . ' ' . $this->_time_format;
666
-        try {
667
-            $DateTime = DateTime::createFromFormat($format, $date_string, $this->_DateTimeZone);
668
-            if ($DateTime instanceof DateTime) {
669
-                $DateTime = new DbSafeDateTime(
670
-                    $DateTime->format(\EE_Datetime_Field::mysql_timestamp_format),
671
-                    $this->_DateTimeZone
672
-                );
673
-            }
674
-            if (! $DateTime instanceof DbSafeDateTime) {
675
-                throw new EE_Error(
676
-                    sprintf(
677
-                        __('"%1$s" does not represent a valid Date Time in the format "%2$s".', 'event_espresso'),
678
-                        $date_string,
679
-                        $format
680
-                    )
681
-                );
682
-            }
683
-        } catch (Exception $e) {
684
-            // if we made it here then likely then something went really wrong.
685
-            // Instead of throwing an exception, let's just return a DateTime object for now, in the set timezone.
686
-            $DateTime = new DbSafeDateTime(\EE_Datetime_Field::now, $this->_DateTimeZone);
687
-        }
688
-
689
-        return $DateTime;
690
-    }
691
-
692
-
693
-
694
-    /**
695
-     * get_timezone_transitions
696
-     *
697
-     * @param \DateTimeZone $DateTimeZone
698
-     * @param int           $time
699
-     * @param bool          $first_only
700
-     * @return mixed
701
-     */
702
-    public function get_timezone_transitions(DateTimeZone $DateTimeZone, $time = null, $first_only = true)
703
-    {
704
-        $time = is_int($time) || $time === null ? $time : strtotime($time);
705
-        $time = preg_match(EE_Datetime_Field::unix_timestamp_regex, $time) ? $time : time();
706
-        $transitions = $DateTimeZone->getTransitions($time);
707
-        return $first_only && ! isset($transitions['ts']) ? reset($transitions) : $transitions;
708
-    }
709
-
710
-
711
-
712
-    /**
713
-     * get_timezone_offset
714
-     *
715
-     * @param \DateTimeZone $DateTimeZone
716
-     * @param int           $time
717
-     * @return mixed
718
-     * @throws \DomainException
719
-     */
720
-    public function get_timezone_offset(DateTimeZone $DateTimeZone, $time = null)
721
-    {
722
-        $transitions = $this->get_timezone_transitions($DateTimeZone, $time);
723
-        if ( ! isset($transitions['offset'])) {
724
-            throw new DomainException();
725
-        }
726
-        return $transitions['offset'];
727
-    }
728
-
729
-
730
-    /**
731
-     * This will take an incoming timezone string and return the abbreviation for that timezone
732
-     *
733
-     * @param  string $timezone_string
734
-     * @return string           abbreviation
735
-     * @throws \EE_Error
736
-     */
737
-    public function get_timezone_abbrev($timezone_string)
738
-    {
739
-        $timezone_string = EEH_DTT_Helper::get_valid_timezone_string($timezone_string);
740
-        $dateTime        = new DateTime(\EE_Datetime_Field::now, new DateTimeZone($timezone_string));
741
-
742
-        return $dateTime->format('T');
743
-    }
744
-
745
-    /**
746
-     * Overrides the parent to allow for having a dynamic "now" value
747
-     *
748
-     * @return mixed
749
-     */
750
-    public function get_default_value()
751
-    {
752
-        if ($this->_default_value === EE_Datetime_Field::now) {
753
-            return time();
754
-        } else {
755
-            return parent::get_default_value();
756
-        }
757
-    }
758
-
759
-
760
-    public function getSchemaDescription()
761
-    {
762
-        return sprintf(
763
-            esc_html__('%s - the value for this field is in the timezone of the site.', 'event_espresso'),
764
-            $this->get_nicename()
765
-        );
766
-    }
18
+	/**
19
+	 * The pattern we're looking for is if only the characters 0-9 are found and there are only
20
+	 * 10 or more numbers (because 9 numbers even with all 9's would be sometime in 2001 )
21
+	 *
22
+	 * @type string unix_timestamp_regex
23
+	 */
24
+	const unix_timestamp_regex = '/[0-9]{10,}/';
25
+
26
+	/**
27
+	 * @type string mysql_timestamp_format
28
+	 */
29
+	const mysql_timestamp_format = 'Y-m-d H:i:s';
30
+
31
+	/**
32
+	 * @type string mysql_date_format
33
+	 */
34
+	const mysql_date_format = 'Y-m-d';
35
+
36
+	/**
37
+	 * @type string mysql_time_format
38
+	 */
39
+	const mysql_time_format = 'H:i:s';
40
+
41
+	/**
42
+	 * Const for using in the default value. If the field's default is set to this,
43
+	 * then we will return the time of calling `get_default_value()`, not
44
+	 * just the current time at construction
45
+	 */
46
+	const now = 'now';
47
+
48
+	/**
49
+	 * The following properties hold the default formats for date and time.
50
+	 * Defaults are set via the constructor and can be overridden on class instantiation.
51
+	 * However they can also be overridden later by the set_format() method
52
+	 * (and corresponding set_date_format, set_time_format methods);
53
+	 */
54
+	/**
55
+	 * @type string $_date_format
56
+	 */
57
+	protected $_date_format = '';
58
+
59
+	/**
60
+	 * @type string $_time_format
61
+	 */
62
+	protected $_time_format = '';
63
+
64
+	/**
65
+	 * @type string $_pretty_date_format
66
+	 */
67
+	protected $_pretty_date_format = '';
68
+
69
+	/**
70
+	 * @type string $_pretty_time_format
71
+	 */
72
+	protected $_pretty_time_format = '';
73
+
74
+	/**
75
+	 * @type DateTimeZone $_DateTimeZone
76
+	 */
77
+	protected $_DateTimeZone;
78
+
79
+	/**
80
+	 * @type DateTimeZone $_UTC_DateTimeZone
81
+	 */
82
+	protected $_UTC_DateTimeZone;
83
+
84
+	/**
85
+	 * @type DateTimeZone $_blog_DateTimeZone
86
+	 */
87
+	protected $_blog_DateTimeZone;
88
+
89
+
90
+	/**
91
+	 * This property holds how we want the output returned when getting a datetime string.  It is set for the
92
+	 * set_date_time_output() method.  By default this is empty.  When empty, we are assuming that we want both date
93
+	 * and time returned via getters.
94
+	 *
95
+	 * @var mixed (null|string)
96
+	 */
97
+	protected $_date_time_output;
98
+
99
+
100
+	/**
101
+	 * timezone string
102
+	 * This gets set by the constructor and can be changed by the "set_timezone()" method so that we know what timezone
103
+	 * incoming strings|timestamps are in.  This can also be used before a get to set what timezone you want strings
104
+	 * coming out of the object to be in.  Default timezone is the current WP timezone option setting
105
+	 *
106
+	 * @var string
107
+	 */
108
+	protected $_timezone_string;
109
+
110
+
111
+	/**
112
+	 * This holds whatever UTC offset for the blog (we automatically convert timezone strings into their related
113
+	 * offsets for comparison purposes).
114
+	 *
115
+	 * @var int
116
+	 */
117
+	protected $_blog_offset;
118
+
119
+
120
+	/**
121
+	 * @param string $table_column
122
+	 * @param string $nice_name
123
+	 * @param bool   $nullable
124
+	 * @param string $default_value
125
+	 * @param string $timezone_string
126
+	 * @param string $date_format
127
+	 * @param string $time_format
128
+	 * @param string $pretty_date_format
129
+	 * @param string $pretty_time_format
130
+	 * @throws \EE_Error
131
+	 */
132
+	public function __construct(
133
+		$table_column,
134
+		$nice_name,
135
+		$nullable,
136
+		$default_value,
137
+		$timezone_string = '',
138
+		$date_format = '',
139
+		$time_format = '',
140
+		$pretty_date_format = '',
141
+		$pretty_time_format = ''
142
+	) {
143
+
144
+		$this->_date_format        = ! empty($date_format) ? $date_format : get_option('date_format');
145
+		$this->_time_format        = ! empty($time_format) ? $time_format : get_option('time_format');
146
+		$this->_pretty_date_format = ! empty($pretty_date_format) ? $pretty_date_format : get_option('date_format');
147
+		$this->_pretty_time_format = ! empty($pretty_time_format) ? $pretty_time_format : get_option('time_format');
148
+
149
+		parent::__construct($table_column, $nice_name, $nullable, $default_value);
150
+		$this->set_timezone($timezone_string);
151
+		$this->setSchemaFormat('date-time');
152
+	}
153
+
154
+
155
+	/**
156
+	 * @return DateTimeZone
157
+	 * @throws \EE_Error
158
+	 */
159
+	public function get_UTC_DateTimeZone()
160
+	{
161
+		return $this->_UTC_DateTimeZone instanceof DateTimeZone
162
+			? $this->_UTC_DateTimeZone
163
+			: $this->_create_timezone_object_from_timezone_string('UTC');
164
+	}
165
+
166
+
167
+	/**
168
+	 * @return DateTimeZone
169
+	 * @throws \EE_Error
170
+	 */
171
+	public function get_blog_DateTimeZone()
172
+	{
173
+		return $this->_blog_DateTimeZone instanceof DateTimeZone
174
+			? $this->_blog_DateTimeZone
175
+			: $this->_create_timezone_object_from_timezone_string('');
176
+	}
177
+
178
+
179
+	/**
180
+	 * this prepares any incoming date data and make sure its converted to a utc unix timestamp
181
+	 *
182
+	 * @param  string|int $value_inputted_for_field_on_model_object could be a string formatted date time or int unix
183
+	 *                                                              timestamp
184
+	 * @return DateTime
185
+	 */
186
+	public function prepare_for_set($value_inputted_for_field_on_model_object)
187
+	{
188
+		return $this->_get_date_object($value_inputted_for_field_on_model_object);
189
+	}
190
+
191
+
192
+	/**
193
+	 * This returns the format string to be used by getters depending on what the $_date_time_output property is set at.
194
+	 * getters need to know whether we're just returning the date or the time or both.  By default we return both.
195
+	 *
196
+	 * @param bool $pretty If we're returning the pretty formats or standard format string.
197
+	 * @return string    The final assembled format string.
198
+	 */
199
+	protected function _get_date_time_output($pretty = false)
200
+	{
201
+
202
+		switch ($this->_date_time_output) {
203
+			case 'time' :
204
+				return $pretty ? $this->_pretty_time_format : $this->_time_format;
205
+				break;
206
+
207
+			case 'date' :
208
+				return $pretty ? $this->_pretty_date_format : $this->_date_format;
209
+				break;
210
+
211
+			default :
212
+				return $pretty
213
+					? $this->_pretty_date_format . ' ' . $this->_pretty_time_format
214
+					: $this->_date_format . ' ' . $this->_time_format;
215
+		}
216
+	}
217
+
218
+
219
+	/**
220
+	 * This just sets the $_date_time_output property so we can flag how date and times are formatted before being
221
+	 * returned (using the format properties)
222
+	 *
223
+	 * @param string $what acceptable values are 'time' or 'date'.
224
+	 *                     Any other value will be set but will always result
225
+	 *                     in both 'date' and 'time' being returned.
226
+	 * @return void
227
+	 */
228
+	public function set_date_time_output($what = null)
229
+	{
230
+		$this->_date_time_output = $what;
231
+	}
232
+
233
+
234
+	/**
235
+	 * See $_timezone property for description of what the timezone property is for.  This SETS the timezone internally
236
+	 * for being able to reference what timezone we are running conversions on when converting TO the internal timezone
237
+	 * (UTC Unix Timestamp) for the object OR when converting FROM the internal timezone (UTC Unix Timestamp).
238
+	 * We also set some other properties in this method.
239
+	 *
240
+	 * @param string $timezone_string A valid timezone string as described by @link
241
+	 *                                http://www.php.net/manual/en/timezones.php
242
+	 * @return void
243
+	 * @throws \EE_Error
244
+	 */
245
+	public function set_timezone($timezone_string)
246
+	{
247
+		if (empty($timezone_string) && $this->_timezone_string !== null) {
248
+			// leave the timezone AS-IS if we already have one and
249
+			// the function arg didn't provide one
250
+			return;
251
+		}
252
+		$timezone_string        = EEH_DTT_Helper::get_valid_timezone_string($timezone_string);
253
+		$this->_timezone_string = ! empty($timezone_string) ? $timezone_string : 'UTC';
254
+		$this->_DateTimeZone    = $this->_create_timezone_object_from_timezone_string($this->_timezone_string);
255
+	}
256
+
257
+
258
+	/**
259
+	 * _create_timezone_object_from_timezone_name
260
+	 *
261
+	 * @access protected
262
+	 * @param string $timezone_string
263
+	 * @return \DateTimeZone
264
+	 * @throws \EE_Error
265
+	 */
266
+	protected function _create_timezone_object_from_timezone_string($timezone_string = '')
267
+	{
268
+		return new DateTimeZone(EEH_DTT_Helper::get_valid_timezone_string($timezone_string));
269
+	}
270
+
271
+
272
+	/**
273
+	 * This just returns whatever is set for the current timezone.
274
+	 *
275
+	 * @access public
276
+	 * @return string timezone string
277
+	 */
278
+	public function get_timezone()
279
+	{
280
+		return $this->_timezone_string;
281
+	}
282
+
283
+
284
+	/**
285
+	 * set the $_date_format property
286
+	 *
287
+	 * @access public
288
+	 * @param string $format a new date format (corresponding to formats accepted by PHP date() function)
289
+	 * @param bool   $pretty Whether to set pretty format or not.
290
+	 * @return void
291
+	 */
292
+	public function set_date_format($format, $pretty = false)
293
+	{
294
+		if ($pretty) {
295
+			$this->_pretty_date_format = $format;
296
+		} else {
297
+			$this->_date_format = $format;
298
+		}
299
+	}
300
+
301
+
302
+	/**
303
+	 * return the $_date_format property value.
304
+	 *
305
+	 * @param bool $pretty Whether to get pretty format or not.
306
+	 * @return string
307
+	 */
308
+	public function get_date_format($pretty = false)
309
+	{
310
+		return $pretty ? $this->_pretty_date_format : $this->_date_format;
311
+	}
312
+
313
+
314
+	/**
315
+	 * set the $_time_format property
316
+	 *
317
+	 * @access public
318
+	 * @param string $format a new time format (corresponding to formats accepted by PHP date() function)
319
+	 * @param bool   $pretty Whether to set pretty format or not.
320
+	 * @return void
321
+	 */
322
+	public function set_time_format($format, $pretty = false)
323
+	{
324
+		if ($pretty) {
325
+			$this->_pretty_time_format = $format;
326
+		} else {
327
+			$this->_time_format = $format;
328
+		}
329
+	}
330
+
331
+
332
+	/**
333
+	 * return the $_time_format property value.
334
+	 *
335
+	 * @param bool $pretty Whether to get pretty format or not.
336
+	 * @return string
337
+	 */
338
+	public function get_time_format($pretty = false)
339
+	{
340
+		return $pretty ? $this->_pretty_time_format : $this->_time_format;
341
+	}
342
+
343
+
344
+	/**
345
+	 * set the $_pretty_date_format property
346
+	 *
347
+	 * @access public
348
+	 * @param string $format a new pretty date format (corresponding to formats accepted by PHP date() function)
349
+	 * @return void
350
+	 */
351
+	public function set_pretty_date_format($format)
352
+	{
353
+		$this->_pretty_date_format = $format;
354
+	}
355
+
356
+
357
+	/**
358
+	 * set the $_pretty_time_format property
359
+	 *
360
+	 * @access public
361
+	 * @param string $format a new pretty time format (corresponding to formats accepted by PHP date() function)
362
+	 * @return void
363
+	 */
364
+	public function set_pretty_time_format($format)
365
+	{
366
+		$this->_pretty_time_format = $format;
367
+	}
368
+
369
+
370
+	/**
371
+	 * Only sets the time portion of the datetime.
372
+	 *
373
+	 * @param string|DateTime $time_to_set_string like 8am OR a DateTime object.
374
+	 * @param DateTime        $current            current DateTime object for the datetime field
375
+	 * @return DateTime
376
+	 */
377
+	public function prepare_for_set_with_new_time($time_to_set_string, DateTime $current)
378
+	{
379
+		// if $time_to_set_string is datetime object, then let's use it to set the parse array.
380
+		// Otherwise parse the string.
381
+		if ($time_to_set_string instanceof DateTime) {
382
+			$parsed = array(
383
+				'hour'   => $time_to_set_string->format('H'),
384
+				'minute' => $time_to_set_string->format('i'),
385
+				'second' => $time_to_set_string->format('s'),
386
+			);
387
+		} else {
388
+			//parse incoming string
389
+			$parsed = date_parse_from_format($this->_time_format, $time_to_set_string);
390
+		}
391
+
392
+		//make sure $current is in the correct timezone.
393
+		$current->setTimezone($this->_DateTimeZone);
394
+
395
+		return $current->setTime($parsed['hour'], $parsed['minute'], $parsed['second']);
396
+	}
397
+
398
+
399
+	/**
400
+	 * Only sets the date portion of the datetime.
401
+	 *
402
+	 * @param string|DateTime $date_to_set_string like Friday, January 8th or a DateTime object.
403
+	 * @param DateTime        $current            current DateTime object for the datetime field
404
+	 * @return DateTime
405
+	 */
406
+	public function prepare_for_set_with_new_date($date_to_set_string, DateTime $current)
407
+	{
408
+		// if $time_to_set_string is datetime object, then let's use it to set the parse array.
409
+		// Otherwise parse the string.
410
+		if ($date_to_set_string instanceof DateTime) {
411
+			$parsed = array(
412
+				'year'  => $date_to_set_string->format('Y'),
413
+				'month' => $date_to_set_string->format('m'),
414
+				'day'   => $date_to_set_string->format('d'),
415
+			);
416
+		} else {
417
+			//parse incoming string
418
+			$parsed = date_parse_from_format($this->_date_format, $date_to_set_string);
419
+		}
420
+
421
+		//make sure $current is in the correct timezone
422
+		$current->setTimezone($this->_DateTimeZone);
423
+
424
+		return $current->setDate($parsed['year'], $parsed['month'], $parsed['day']);
425
+	}
426
+
427
+
428
+	/**
429
+	 * This prepares the EE_DateTime value to be saved to the db as mysql timestamp (UTC +0 timezone).  When the
430
+	 * datetime gets to this stage it should ALREADY be in UTC time
431
+	 *
432
+	 * @param  DateTime $DateTime
433
+	 * @return string formatted date time for given timezone
434
+	 * @throws \EE_Error
435
+	 */
436
+	public function prepare_for_get($DateTime)
437
+	{
438
+		return $this->_prepare_for_display($DateTime);
439
+	}
440
+
441
+
442
+	/**
443
+	 * This differs from prepare_for_get in that it considers whether the internal $_timezone differs
444
+	 * from the set wp timezone.  If so, then it returns the datetime string formatted via
445
+	 * _pretty_date_format, and _pretty_time_format.  However, it also appends a timezone
446
+	 * abbreviation to the date_string.
447
+	 *
448
+	 * @param mixed $DateTime
449
+	 * @param null  $schema
450
+	 * @return string
451
+	 * @throws \EE_Error
452
+	 */
453
+	public function prepare_for_pretty_echoing($DateTime, $schema = null)
454
+	{
455
+		return $this->_prepare_for_display($DateTime, $schema ? $schema : true);
456
+	}
457
+
458
+
459
+	/**
460
+	 * This prepares the EE_DateTime value to be saved to the db as mysql timestamp (UTC +0
461
+	 * timezone).
462
+	 *
463
+	 * @param DateTime    $DateTime
464
+	 * @param bool|string $schema
465
+	 * @return string
466
+	 * @throws \EE_Error
467
+	 */
468
+	protected function _prepare_for_display($DateTime, $schema = false)
469
+	{
470
+		if (! $DateTime instanceof DateTime) {
471
+			if ($this->_nullable) {
472
+				return '';
473
+			} else {
474
+				if (WP_DEBUG) {
475
+					throw new EE_Error(
476
+						sprintf(
477
+							__(
478
+								'EE_Datetime_Field::_prepare_for_display requires a DateTime class to be the value for the $DateTime argument because the %s field is not nullable.',
479
+								'event_espresso'
480
+							),
481
+							$this->_nicename
482
+						)
483
+					);
484
+				} else {
485
+					$DateTime = new DbSafeDateTime(\EE_Datetime_Field::now);
486
+					EE_Error::add_error(
487
+						sprintf(
488
+							__(
489
+								'EE_Datetime_Field::_prepare_for_display requires a DateTime class to be the value for the $DateTime argument because the %s field is not nullable.  When WP_DEBUG is false, the value is set to "now" instead of throwing an exception.',
490
+								'event_espresso'
491
+							),
492
+							$this->_nicename
493
+						)
494
+					);
495
+				}
496
+			}
497
+		}
498
+		$format_string = $this->_get_date_time_output($schema);
499
+		//make sure datetime_value is in the correct timezone (in case that's been updated).
500
+		$DateTime->setTimezone($this->_DateTimeZone);
501
+		if ($schema) {
502
+			if ($this->_display_timezone()) {
503
+				//must be explicit because schema could equal true.
504
+				if ($schema === 'no_html') {
505
+					$timezone_string = ' (' . $DateTime->format('T') . ')';
506
+				} else {
507
+					$timezone_string = ' <span class="ee_dtt_timezone_string">(' . $DateTime->format('T') . ')</span>';
508
+				}
509
+			} else {
510
+				$timezone_string = '';
511
+			}
512
+
513
+			return $DateTime->format($format_string) . $timezone_string;
514
+		} else {
515
+			return $DateTime->format($format_string);
516
+		}
517
+	}
518
+
519
+
520
+	/**
521
+	 * This prepares the EE_DateTime value to be saved to the db as mysql timestamp (UTC +0
522
+	 * timezone).
523
+	 *
524
+	 * @param  mixed $datetime_value u
525
+	 * @return string mysql timestamp in UTC
526
+	 * @throws \EE_Error
527
+	 */
528
+	public function prepare_for_use_in_db($datetime_value)
529
+	{
530
+		//we allow an empty value or DateTime object, but nothing else.
531
+		if (! empty($datetime_value) && ! $datetime_value instanceof DateTime) {
532
+			throw new EE_Error(
533
+				__(
534
+					'The incoming value being prepared for setting in the database must either be empty or a php DateTime object',
535
+					'event_espresso'
536
+				)
537
+			);
538
+		}
539
+
540
+		if ($datetime_value instanceof DateTime) {
541
+			if ( ! $datetime_value instanceof DbSafeDateTime) {
542
+				$datetime_value = DbSafeDateTime::createFromDateTime($datetime_value);
543
+			}
544
+
545
+			return $datetime_value->setTimezone($this->get_UTC_DateTimeZone())->format(
546
+				EE_Datetime_Field::mysql_timestamp_format
547
+			);
548
+		}
549
+
550
+		// if $datetime_value is empty, and ! $this->_nullable, use current_time() but set the GMT flag to true
551
+		return ! $this->_nullable && empty($datetime_value) ? current_time('mysql', true) : null;
552
+	}
553
+
554
+
555
+	/**
556
+	 * This prepares the datetime for internal usage as a PHP DateTime object OR null (if nullable is
557
+	 * allowed)
558
+	 *
559
+	 * @param string $datetime_string mysql timestamp in UTC
560
+	 * @return  mixed null | DateTime
561
+	 * @throws \EE_Error
562
+	 */
563
+	public function prepare_for_set_from_db($datetime_string)
564
+	{
565
+		//if $datetime_value is empty, and ! $this->_nullable, just use time()
566
+		if (empty($datetime_string) && $this->_nullable) {
567
+			return null;
568
+		}
569
+		// datetime strings from the db should ALWAYS be in UTC+0, so use UTC_DateTimeZone when creating
570
+		if (empty($datetime_string)) {
571
+			$DateTime = new DbSafeDateTime(\EE_Datetime_Field::now, $this->get_UTC_DateTimeZone());
572
+		} else {
573
+			$DateTime = DateTime::createFromFormat(
574
+				EE_Datetime_Field::mysql_timestamp_format,
575
+				$datetime_string,
576
+				$this->get_UTC_DateTimeZone()
577
+			);
578
+			if ($DateTime instanceof \DateTime) {
579
+				$DateTime = new DbSafeDateTime(
580
+					$DateTime->format(\EE_Datetime_Field::mysql_timestamp_format),
581
+					$this->get_UTC_DateTimeZone()
582
+				);
583
+			}
584
+		}
585
+
586
+		if (! $DateTime instanceof DbSafeDateTime) {
587
+			// if still no datetime object, then let's just use now
588
+			$DateTime = new DbSafeDateTime(\EE_Datetime_Field::now, $this->get_UTC_DateTimeZone());
589
+		}
590
+		// THEN apply the field's set DateTimeZone
591
+		$DateTime->setTimezone($this->_DateTimeZone);
592
+
593
+		return $DateTime;
594
+	}
595
+
596
+
597
+	/**
598
+	 * All this method does is determine if we're going to display the timezone string or not on any output.
599
+	 * To determine this we check if the set timezone offset is different than the blog's set timezone offset.
600
+	 * If so, then true.
601
+	 *
602
+	 * @return bool true for yes false for no
603
+	 * @throws \EE_Error
604
+	 */
605
+	protected function _display_timezone()
606
+	{
607
+
608
+		// first let's do a comparison of timezone strings.
609
+		// If they match then we can get out without any further calculations
610
+		$blog_string = get_option('timezone_string');
611
+		if ($blog_string === $this->_timezone_string) {
612
+			return false;
613
+		}
614
+		// now we need to calc the offset for the timezone string so we can compare with the blog offset.
615
+		$this_offset = $this->get_timezone_offset($this->_DateTimeZone);
616
+		$blog_offset = $this->get_timezone_offset($this->get_blog_DateTimeZone());
617
+		// now compare
618
+		return $blog_offset !== $this_offset;
619
+	}
620
+
621
+
622
+	/**
623
+	 * This method returns a php DateTime object for setting on the EE_Base_Class model.
624
+	 * EE passes around DateTime objects because they are MUCH easier to manipulate and deal
625
+	 * with.
626
+	 *
627
+	 * @param int|string|DateTime $date_string            This should be the incoming date string.  It's assumed to be
628
+	 *                                                    in the format that is set on the date_field (or DateTime
629
+	 *                                                    object)!
630
+	 * @return DateTime
631
+	 */
632
+	protected function _get_date_object($date_string)
633
+	{
634
+		//first if this is an empty date_string and nullable is allowed, just return null.
635
+		if ($this->_nullable && empty($date_string)) {
636
+			return null;
637
+		}
638
+
639
+		// if incoming date
640
+		if ($date_string instanceof DateTime) {
641
+			$date_string->setTimezone($this->_DateTimeZone);
642
+
643
+			return $date_string;
644
+		}
645
+		// if empty date_string and made it here.
646
+		// Return a datetime object for now in the given timezone.
647
+		if (empty($date_string)) {
648
+			return new DbSafeDateTime(\EE_Datetime_Field::now, $this->_DateTimeZone);
649
+		}
650
+		// if $date_string is matches something that looks like a Unix timestamp let's just use it.
651
+		if (preg_match(EE_Datetime_Field::unix_timestamp_regex, $date_string)) {
652
+			try {
653
+				// This is operating under the assumption that the incoming Unix timestamp
654
+				// is an ACTUAL Unix timestamp and not the calculated one output by current_time('timestamp');
655
+				$DateTime = new DbSafeDateTime(\EE_Datetime_Field::now, $this->_DateTimeZone);
656
+				$DateTime->setTimestamp($date_string);
657
+
658
+				return $DateTime;
659
+			} catch (Exception $e) {
660
+				// should be rare, but if things got fooled then let's just continue
661
+			}
662
+		}
663
+		//not a unix timestamp.  So we will use the set format on this object and set timezone to
664
+		//create the DateTime object.
665
+		$format = $this->_date_format . ' ' . $this->_time_format;
666
+		try {
667
+			$DateTime = DateTime::createFromFormat($format, $date_string, $this->_DateTimeZone);
668
+			if ($DateTime instanceof DateTime) {
669
+				$DateTime = new DbSafeDateTime(
670
+					$DateTime->format(\EE_Datetime_Field::mysql_timestamp_format),
671
+					$this->_DateTimeZone
672
+				);
673
+			}
674
+			if (! $DateTime instanceof DbSafeDateTime) {
675
+				throw new EE_Error(
676
+					sprintf(
677
+						__('"%1$s" does not represent a valid Date Time in the format "%2$s".', 'event_espresso'),
678
+						$date_string,
679
+						$format
680
+					)
681
+				);
682
+			}
683
+		} catch (Exception $e) {
684
+			// if we made it here then likely then something went really wrong.
685
+			// Instead of throwing an exception, let's just return a DateTime object for now, in the set timezone.
686
+			$DateTime = new DbSafeDateTime(\EE_Datetime_Field::now, $this->_DateTimeZone);
687
+		}
688
+
689
+		return $DateTime;
690
+	}
691
+
692
+
693
+
694
+	/**
695
+	 * get_timezone_transitions
696
+	 *
697
+	 * @param \DateTimeZone $DateTimeZone
698
+	 * @param int           $time
699
+	 * @param bool          $first_only
700
+	 * @return mixed
701
+	 */
702
+	public function get_timezone_transitions(DateTimeZone $DateTimeZone, $time = null, $first_only = true)
703
+	{
704
+		$time = is_int($time) || $time === null ? $time : strtotime($time);
705
+		$time = preg_match(EE_Datetime_Field::unix_timestamp_regex, $time) ? $time : time();
706
+		$transitions = $DateTimeZone->getTransitions($time);
707
+		return $first_only && ! isset($transitions['ts']) ? reset($transitions) : $transitions;
708
+	}
709
+
710
+
711
+
712
+	/**
713
+	 * get_timezone_offset
714
+	 *
715
+	 * @param \DateTimeZone $DateTimeZone
716
+	 * @param int           $time
717
+	 * @return mixed
718
+	 * @throws \DomainException
719
+	 */
720
+	public function get_timezone_offset(DateTimeZone $DateTimeZone, $time = null)
721
+	{
722
+		$transitions = $this->get_timezone_transitions($DateTimeZone, $time);
723
+		if ( ! isset($transitions['offset'])) {
724
+			throw new DomainException();
725
+		}
726
+		return $transitions['offset'];
727
+	}
728
+
729
+
730
+	/**
731
+	 * This will take an incoming timezone string and return the abbreviation for that timezone
732
+	 *
733
+	 * @param  string $timezone_string
734
+	 * @return string           abbreviation
735
+	 * @throws \EE_Error
736
+	 */
737
+	public function get_timezone_abbrev($timezone_string)
738
+	{
739
+		$timezone_string = EEH_DTT_Helper::get_valid_timezone_string($timezone_string);
740
+		$dateTime        = new DateTime(\EE_Datetime_Field::now, new DateTimeZone($timezone_string));
741
+
742
+		return $dateTime->format('T');
743
+	}
744
+
745
+	/**
746
+	 * Overrides the parent to allow for having a dynamic "now" value
747
+	 *
748
+	 * @return mixed
749
+	 */
750
+	public function get_default_value()
751
+	{
752
+		if ($this->_default_value === EE_Datetime_Field::now) {
753
+			return time();
754
+		} else {
755
+			return parent::get_default_value();
756
+		}
757
+	}
758
+
759
+
760
+	public function getSchemaDescription()
761
+	{
762
+		return sprintf(
763
+			esc_html__('%s - the value for this field is in the timezone of the site.', 'event_espresso'),
764
+			$this->get_nicename()
765
+		);
766
+	}
767 767
 }
Please login to merge, or discard this patch.
core/db_models/fields/EE_DB_Only_Float_Field.php 1 patch
Indentation   +11 added lines, -11 removed lines patch added patch discarded remove patch
@@ -3,16 +3,16 @@
 block discarded – undo
3 3
 
4 4
 class EE_DB_Only_Float_Field extends EE_DB_Only_Field_Base
5 5
 {
6
-    /**
7
-     * @param string $table_column
8
-     * @param string $nicename
9
-     * @param bool   $nullable
10
-     * @param null   $default_value
11
-     */
12
-    public function __construct($table_column, $nicename, $nullable, $default_value = null)
13
-    {
14
-        parent::__construct($table_column, $nicename, $nullable, $default_value);
15
-        $this->setSchemaType('number');
16
-    }
6
+	/**
7
+	 * @param string $table_column
8
+	 * @param string $nicename
9
+	 * @param bool   $nullable
10
+	 * @param null   $default_value
11
+	 */
12
+	public function __construct($table_column, $nicename, $nullable, $default_value = null)
13
+	{
14
+		parent::__construct($table_column, $nicename, $nullable, $default_value);
15
+		$this->setSchemaType('number');
16
+	}
17 17
 
18 18
 }
Please login to merge, or discard this patch.
core/db_models/fields/EE_Primary_Key_Int_Field.php 2 patches
Indentation   +20 added lines, -20 removed lines patch added patch discarded remove patch
@@ -4,27 +4,27 @@
 block discarded – undo
4 4
 class EE_Primary_Key_Int_Field extends EE_Primary_Key_Field_Base
5 5
 {
6 6
 
7
-    public function __construct($table_column, $nicename)
8
-    {
9
-        parent::__construct($table_column, $nicename, 0);
10
-        $this->setSchemaType('integer');
11
-    }
7
+	public function __construct($table_column, $nicename)
8
+	{
9
+		parent::__construct($table_column, $nicename, 0);
10
+		$this->setSchemaType('integer');
11
+	}
12 12
 
13
-    function prepare_for_set($value_inputted_for_field_on_model_object)
14
-    {
15
-        if ($this->is_model_obj_of_type_pointed_to($value_inputted_for_field_on_model_object)) {
16
-            $value_inputted_for_field_on_model_object = $value_inputted_for_field_on_model_object->ID();
17
-        }
18
-        return absint($value_inputted_for_field_on_model_object);
19
-    }
13
+	function prepare_for_set($value_inputted_for_field_on_model_object)
14
+	{
15
+		if ($this->is_model_obj_of_type_pointed_to($value_inputted_for_field_on_model_object)) {
16
+			$value_inputted_for_field_on_model_object = $value_inputted_for_field_on_model_object->ID();
17
+		}
18
+		return absint($value_inputted_for_field_on_model_object);
19
+	}
20 20
 
21
-    function prepare_for_set_from_db($value_found_in_db_for_model_object)
22
-    {
23
-        return intval($value_found_in_db_for_model_object);
24
-    }
21
+	function prepare_for_set_from_db($value_found_in_db_for_model_object)
22
+	{
23
+		return intval($value_found_in_db_for_model_object);
24
+	}
25 25
 
26
-    function is_auto_increment()
27
-    {
28
-        return true;
29
-    }
26
+	function is_auto_increment()
27
+	{
28
+		return true;
29
+	}
30 30
 }
31 31
\ No newline at end of file
Please login to merge, or discard this patch.
Doc Comments   +3 added lines patch added patch discarded remove patch
@@ -4,6 +4,9 @@
 block discarded – undo
4 4
 class EE_Primary_Key_Int_Field extends EE_Primary_Key_Field_Base
5 5
 {
6 6
 
7
+    /**
8
+     * @param string $table_column
9
+     */
7 10
     public function __construct($table_column, $nicename)
8 11
     {
9 12
         parent::__construct($table_column, $nicename, 0);
Please login to merge, or discard this patch.
core/db_models/fields/EE_Enum_Text_Field.php 1 patch
Indentation   +127 added lines, -127 removed lines patch added patch discarded remove patch
@@ -12,131 +12,131 @@
 block discarded – undo
12 12
 class EE_Enum_Text_Field extends EE_Text_Field_Base
13 13
 {
14 14
 
15
-    /**
16
-     * @var array $_allowed_enum_values
17
-     */
18
-    public $_allowed_enum_values;
19
-
20
-    /**
21
-     * @param string  $table_column
22
-     * @param string  $nice_name
23
-     * @param boolean $nullable
24
-     * @param mixed   $default_value
25
-     * @param array   $allowed_enum_values keys are values to be used in the DB, values are how they should be displayed
26
-     */
27
-    function __construct($table_column, $nice_name, $nullable, $default_value, $allowed_enum_values)
28
-    {
29
-        $this->_allowed_enum_values = $allowed_enum_values;
30
-        parent::__construct($table_column, $nice_name, $nullable, $default_value);
31
-        $this->setSchemaType('object');
32
-    }
33
-
34
-
35
-
36
-    /**
37
-     * Returns the list of allowed enum options, but filterable.
38
-     * This is used internally
39
-     *
40
-     * @return array
41
-     */
42
-    protected function _allowed_enum_values()
43
-    {
44
-        return apply_filters(
45
-            'FHEE__EE_Enum_Text_Field___allowed_enum_options',
46
-            $this->_allowed_enum_values,
47
-            $this
48
-        );
49
-    }
50
-
51
-
52
-
53
-    /**
54
-     * When setting, just verify that the value being used matches what we've defined as allowable enum values.
55
-     * If not, throw an error (but if WP_DEBUG is false, just set the value to default).
56
-     *
57
-     * @param string $value_inputted_for_field_on_model_object
58
-     * @return string
59
-     * @throws EE_Error
60
-     */
61
-    public function prepare_for_set($value_inputted_for_field_on_model_object)
62
-    {
63
-        if (
64
-            $value_inputted_for_field_on_model_object !== null
65
-            && ! array_key_exists($value_inputted_for_field_on_model_object, $this->_allowed_enum_values())
66
-        ) {
67
-            if (defined('WP_DEBUG') && WP_DEBUG) {
68
-                $msg = sprintf(
69
-                    __('System is assigning incompatible value "%1$s" to field "%2$s"', 'event_espresso'),
70
-                    $value_inputted_for_field_on_model_object,
71
-                    $this->_name
72
-                );
73
-                $msg2 = sprintf(
74
-                    __('Allowed values for "%1$s" are "%2$s". You provided: "%3$s"', 'event_espresso'),
75
-                    $this->_name,
76
-                    implode(', ', array_keys($this->_allowed_enum_values())),
77
-                    $value_inputted_for_field_on_model_object
78
-                );
79
-                EE_Error::add_error("{$msg}||{$msg2}", __FILE__, __FUNCTION__, __LINE__);
80
-            }
81
-            return $this->get_default_value();
82
-        }
83
-        return $value_inputted_for_field_on_model_object;
84
-    }
85
-
86
-
87
-    /**
88
-     * Gets the pretty version of the enum's value.
89
-     *
90
-     * @param     int |string $value_on_field_to_be_outputted
91
-     * @param    null         $schema
92
-     * @return    string
93
-     */
94
-    public function prepare_for_pretty_echoing($value_on_field_to_be_outputted, $schema = null)
95
-    {
96
-        $options = $this->_allowed_enum_values();
97
-        if (isset($options[$value_on_field_to_be_outputted])) {
98
-            return $options[$value_on_field_to_be_outputted];
99
-        } else {
100
-            return $value_on_field_to_be_outputted;
101
-        }
102
-    }
103
-
104
-
105
-
106
-    /**
107
-     * When retrieving something from the DB, don't enforce the enum's options. If it's in the DB, we just have to live
108
-     * with that. Note also: when we're saving to the DB again, we also don't enforce the enum options. It's ONLY
109
-     * when we're receiving USER input from prepare_for_set() that we enforce the enum options.
110
-     *
111
-     * @param mixed $value_in_db
112
-     * @return mixed
113
-     */
114
-    public function prepare_for_set_from_db($value_in_db)
115
-    {
116
-        return $value_in_db;
117
-    }
118
-
119
-
120
-    public function getSchemaProperties()
121
-    {
122
-        return array(
123
-            'raw' => array(
124
-                'description' =>  sprintf(
125
-                    __('%s - the value in the database.', 'event_espresso'),
126
-                    $this->get_nicename()
127
-                ),
128
-                'type' => 'string',
129
-                'enum' => array_keys($this->_allowed_enum_values)
130
-            ),
131
-            'pretty' => array(
132
-                'description' =>  sprintf(
133
-                    __('%s - the value for display.', 'event_espresso'),
134
-                    $this->get_nicename()
135
-                ),
136
-                'type' => 'string',
137
-                'enum' => array_values($this->_allowed_enum_values),
138
-                'read_only' => true
139
-            )
140
-        );
141
-    }
15
+	/**
16
+	 * @var array $_allowed_enum_values
17
+	 */
18
+	public $_allowed_enum_values;
19
+
20
+	/**
21
+	 * @param string  $table_column
22
+	 * @param string  $nice_name
23
+	 * @param boolean $nullable
24
+	 * @param mixed   $default_value
25
+	 * @param array   $allowed_enum_values keys are values to be used in the DB, values are how they should be displayed
26
+	 */
27
+	function __construct($table_column, $nice_name, $nullable, $default_value, $allowed_enum_values)
28
+	{
29
+		$this->_allowed_enum_values = $allowed_enum_values;
30
+		parent::__construct($table_column, $nice_name, $nullable, $default_value);
31
+		$this->setSchemaType('object');
32
+	}
33
+
34
+
35
+
36
+	/**
37
+	 * Returns the list of allowed enum options, but filterable.
38
+	 * This is used internally
39
+	 *
40
+	 * @return array
41
+	 */
42
+	protected function _allowed_enum_values()
43
+	{
44
+		return apply_filters(
45
+			'FHEE__EE_Enum_Text_Field___allowed_enum_options',
46
+			$this->_allowed_enum_values,
47
+			$this
48
+		);
49
+	}
50
+
51
+
52
+
53
+	/**
54
+	 * When setting, just verify that the value being used matches what we've defined as allowable enum values.
55
+	 * If not, throw an error (but if WP_DEBUG is false, just set the value to default).
56
+	 *
57
+	 * @param string $value_inputted_for_field_on_model_object
58
+	 * @return string
59
+	 * @throws EE_Error
60
+	 */
61
+	public function prepare_for_set($value_inputted_for_field_on_model_object)
62
+	{
63
+		if (
64
+			$value_inputted_for_field_on_model_object !== null
65
+			&& ! array_key_exists($value_inputted_for_field_on_model_object, $this->_allowed_enum_values())
66
+		) {
67
+			if (defined('WP_DEBUG') && WP_DEBUG) {
68
+				$msg = sprintf(
69
+					__('System is assigning incompatible value "%1$s" to field "%2$s"', 'event_espresso'),
70
+					$value_inputted_for_field_on_model_object,
71
+					$this->_name
72
+				);
73
+				$msg2 = sprintf(
74
+					__('Allowed values for "%1$s" are "%2$s". You provided: "%3$s"', 'event_espresso'),
75
+					$this->_name,
76
+					implode(', ', array_keys($this->_allowed_enum_values())),
77
+					$value_inputted_for_field_on_model_object
78
+				);
79
+				EE_Error::add_error("{$msg}||{$msg2}", __FILE__, __FUNCTION__, __LINE__);
80
+			}
81
+			return $this->get_default_value();
82
+		}
83
+		return $value_inputted_for_field_on_model_object;
84
+	}
85
+
86
+
87
+	/**
88
+	 * Gets the pretty version of the enum's value.
89
+	 *
90
+	 * @param     int |string $value_on_field_to_be_outputted
91
+	 * @param    null         $schema
92
+	 * @return    string
93
+	 */
94
+	public function prepare_for_pretty_echoing($value_on_field_to_be_outputted, $schema = null)
95
+	{
96
+		$options = $this->_allowed_enum_values();
97
+		if (isset($options[$value_on_field_to_be_outputted])) {
98
+			return $options[$value_on_field_to_be_outputted];
99
+		} else {
100
+			return $value_on_field_to_be_outputted;
101
+		}
102
+	}
103
+
104
+
105
+
106
+	/**
107
+	 * When retrieving something from the DB, don't enforce the enum's options. If it's in the DB, we just have to live
108
+	 * with that. Note also: when we're saving to the DB again, we also don't enforce the enum options. It's ONLY
109
+	 * when we're receiving USER input from prepare_for_set() that we enforce the enum options.
110
+	 *
111
+	 * @param mixed $value_in_db
112
+	 * @return mixed
113
+	 */
114
+	public function prepare_for_set_from_db($value_in_db)
115
+	{
116
+		return $value_in_db;
117
+	}
118
+
119
+
120
+	public function getSchemaProperties()
121
+	{
122
+		return array(
123
+			'raw' => array(
124
+				'description' =>  sprintf(
125
+					__('%s - the value in the database.', 'event_espresso'),
126
+					$this->get_nicename()
127
+				),
128
+				'type' => 'string',
129
+				'enum' => array_keys($this->_allowed_enum_values)
130
+			),
131
+			'pretty' => array(
132
+				'description' =>  sprintf(
133
+					__('%s - the value for display.', 'event_espresso'),
134
+					$this->get_nicename()
135
+				),
136
+				'type' => 'string',
137
+				'enum' => array_values($this->_allowed_enum_values),
138
+				'read_only' => true
139
+			)
140
+		);
141
+	}
142 142
 }
Please login to merge, or discard this patch.
core/db_models/fields/EE_Full_HTML_Field.php 2 patches
Indentation   +48 added lines, -48 removed lines patch added patch discarded remove patch
@@ -15,57 +15,57 @@
 block discarded – undo
15 15
 class EE_Full_HTML_Field extends EE_Text_Field_Base
16 16
 {
17 17
 
18
-    /**
19
-     * @param string $table_column
20
-     * @param string $nicename
21
-     * @param bool   $nullable
22
-     * @param null   $default_value
23
-     */
24
-    public function __construct($table_column, $nicename, $nullable, $default_value = null)
25
-    {
26
-        parent::__construct($table_column, $nicename, $nullable, $default_value);
27
-        $this->setSchemaType('object');
28
-    }
18
+	/**
19
+	 * @param string $table_column
20
+	 * @param string $nicename
21
+	 * @param bool   $nullable
22
+	 * @param null   $default_value
23
+	 */
24
+	public function __construct($table_column, $nicename, $nullable, $default_value = null)
25
+	{
26
+		parent::__construct($table_column, $nicename, $nullable, $default_value);
27
+		$this->setSchemaType('object');
28
+	}
29 29
 
30 30
 
31
-    /**
32
-     * Does shortcodes and auto-paragraphs the content (unless schema is 'no_wpautop')
33
-     *
34
-     * @param type $value_on_field_to_be_outputted
35
-     * @param type $schema
36
-     * @return string
37
-     */
38
-    function prepare_for_pretty_echoing($value_on_field_to_be_outputted, $schema = null)
39
-    {
40
-        if ($schema == 'form_input') {
41
-            return parent::prepare_for_pretty_echoing($value_on_field_to_be_outputted, $schema);
42
-        } elseif ($schema == 'no_wpautop') {
43
-            return do_shortcode(parent::prepare_for_pretty_echoing($value_on_field_to_be_outputted, $schema));
44
-        } else {
45
-            return wpautop(do_shortcode(parent::prepare_for_pretty_echoing($value_on_field_to_be_outputted, $schema)));
46
-        }
47
-    }
31
+	/**
32
+	 * Does shortcodes and auto-paragraphs the content (unless schema is 'no_wpautop')
33
+	 *
34
+	 * @param type $value_on_field_to_be_outputted
35
+	 * @param type $schema
36
+	 * @return string
37
+	 */
38
+	function prepare_for_pretty_echoing($value_on_field_to_be_outputted, $schema = null)
39
+	{
40
+		if ($schema == 'form_input') {
41
+			return parent::prepare_for_pretty_echoing($value_on_field_to_be_outputted, $schema);
42
+		} elseif ($schema == 'no_wpautop') {
43
+			return do_shortcode(parent::prepare_for_pretty_echoing($value_on_field_to_be_outputted, $schema));
44
+		} else {
45
+			return wpautop(do_shortcode(parent::prepare_for_pretty_echoing($value_on_field_to_be_outputted, $schema)));
46
+		}
47
+	}
48 48
 
49 49
 
50 50
 
51
-    public function getSchemaProperties()
52
-    {
53
-        return array(
54
-            'raw' => array(
55
-                'description' =>  sprintf(
56
-                    __('%s - the value in the database.', 'event_espresso'),
57
-                    $this->get_nicename()
58
-                ),
59
-                'type' => 'string'
60
-            ),
61
-            'rendered' => array(
62
-                'description' =>  sprintf(
63
-                    __('%s - transformed for display.', 'event_espresso'),
64
-                    $this->get_nicename()
65
-                ),
66
-                'type' => 'string',
67
-                'readonly' => true
68
-            )
69
-        );
70
-    }
51
+	public function getSchemaProperties()
52
+	{
53
+		return array(
54
+			'raw' => array(
55
+				'description' =>  sprintf(
56
+					__('%s - the value in the database.', 'event_espresso'),
57
+					$this->get_nicename()
58
+				),
59
+				'type' => 'string'
60
+			),
61
+			'rendered' => array(
62
+				'description' =>  sprintf(
63
+					__('%s - transformed for display.', 'event_espresso'),
64
+					$this->get_nicename()
65
+				),
66
+				'type' => 'string',
67
+				'readonly' => true
68
+			)
69
+		);
70
+	}
71 71
 }
72 72
\ No newline at end of file
Please login to merge, or discard this patch.
Doc Comments   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -13,7 +13,7 @@
 block discarded – undo
13 13
      * @param string $table_column
14 14
      * @param string $nicename
15 15
      * @param bool   $nullable
16
-     * @param null   $default_value
16
+     * @param string   $default_value
17 17
      */
18 18
     public function __construct($table_column, $nicename, $nullable, $default_value = null)
19 19
     {
Please login to merge, or discard this patch.
modules/ticket_selector/ProcessTicketSelector.php 3 patches
Doc Comments   +4 added lines, -4 removed lines patch added patch discarded remove patch
@@ -32,7 +32,7 @@  discard block
 block discarded – undo
32 32
     /**
33 33
      * cancelTicketSelections
34 34
      *
35
-     * @return        string
35
+     * @return        false|null
36 36
      */
37 37
     public function cancelTicketSelections()
38 38
     {
@@ -99,7 +99,7 @@  discard block
 block discarded – undo
99 99
     /**
100 100
      * process_ticket_selections
101 101
      *
102
-     * @return array|bool
102
+     * @return boolean|null
103 103
      * @throws \EE_Error
104 104
      */
105 105
     public function processTicketSelections()
@@ -273,7 +273,7 @@  discard block
 block discarded – undo
273 273
      * validate_post_data
274 274
      *
275 275
      * @param int $id
276
-     * @return array|FALSE
276
+     * @return string
277 277
      */
278 278
     private function validatePostData($id = 0)
279 279
     {
@@ -390,7 +390,7 @@  discard block
 block discarded – undo
390 390
      *
391 391
      * @param \EE_Ticket $ticket
392 392
      * @param int        $qty
393
-     * @return TRUE on success, FALSE on fail
393
+     * @return boolean on success, FALSE on fail
394 394
      * @throws \EE_Error
395 395
      */
396 396
     private function addTicketToCart(\EE_Ticket $ticket = null, $qty = 1)
Please login to merge, or discard this patch.
Indentation   +569 added lines, -569 removed lines patch added patch discarded remove patch
@@ -2,7 +2,7 @@  discard block
 block discarded – undo
2 2
 namespace EventEspresso\modules\ticket_selector;
3 3
 
4 4
 if ( ! defined('EVENT_ESPRESSO_VERSION')) {
5
-    exit('No direct script access allowed');
5
+	exit('No direct script access allowed');
6 6
 }
7 7
 
8 8
 
@@ -19,574 +19,574 @@  discard block
 block discarded – undo
19 19
 class ProcessTicketSelector
20 20
 {
21 21
 
22
-    /**
23
-     * array of datetimes and the spaces available for them
24
-     *
25
-     * @access private
26
-     * @var array
27
-     */
28
-    private static $_available_spaces = array();
29
-
30
-
31
-
32
-    /**
33
-     * cancelTicketSelections
34
-     *
35
-     * @return        string
36
-     */
37
-    public function cancelTicketSelections()
38
-    {
39
-        // check nonce
40
-        if ( ! $this->processTicketSelectorNonce('cancel_ticket_selections')) {
41
-            return false;
42
-        }
43
-        \EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
44
-        if (\EE_Registry::instance()->REQ->is_set('event_id')) {
45
-            wp_safe_redirect(
46
-                \EEH_Event_View::event_link_url(
47
-                    \EE_Registry::instance()->REQ->get('event_id')
48
-                )
49
-            );
50
-        } else {
51
-            wp_safe_redirect(
52
-                site_url('/' . \EE_Registry::instance()->CFG->core->event_cpt_slug . '/')
53
-            );
54
-        }
55
-        exit();
56
-    }
57
-
58
-
59
-
60
-    /**
61
-     * processTicketSelectorNonce
62
-     *
63
-     * @param  string $nonce_name
64
-     * @param string  $id
65
-     * @return bool
66
-     */
67
-    private function processTicketSelectorNonce($nonce_name, $id = '')
68
-    {
69
-        $nonce_name_with_id = ! empty($id) ? "{$nonce_name}_nonce_{$id}" : "{$nonce_name}_nonce";
70
-        if (
71
-            ! is_admin()
72
-            && (
73
-                ! \EE_Registry::instance()->REQ->is_set($nonce_name_with_id)
74
-                || ! wp_verify_nonce(
75
-                    \EE_Registry::instance()->REQ->get($nonce_name_with_id),
76
-                    $nonce_name
77
-                )
78
-            )
79
-        ) {
80
-            \EE_Error::add_error(
81
-                sprintf(
82
-                    __(
83
-                        'We\'re sorry but your request failed to pass a security check.%sPlease click the back button on your browser and try again.',
84
-                        'event_espresso'
85
-                    ),
86
-                    '<br/>'
87
-                ),
88
-                __FILE__,
89
-                __FUNCTION__,
90
-                __LINE__
91
-            );
92
-            return false;
93
-        }
94
-        return true;
95
-    }
96
-
97
-
98
-
99
-    /**
100
-     * process_ticket_selections
101
-     *
102
-     * @return array|bool
103
-     * @throws \EE_Error
104
-     */
105
-    public function processTicketSelections()
106
-    {
107
-        do_action('EED_Ticket_Selector__process_ticket_selections__before');
108
-        // do we have an event id?
109
-        if ( ! \EE_Registry::instance()->REQ->is_set('tkt-slctr-event-id')) {
110
-            // $_POST['tkt-slctr-event-id'] was not set ?!?!?!?
111
-            \EE_Error::add_error(
112
-                sprintf(
113
-                    __(
114
-                        'An event id was not provided or was not received.%sPlease click the back button on your browser and try again.',
115
-                        'event_espresso'
116
-                    ),
117
-                    '<br/>'
118
-                ),
119
-                __FILE__,
120
-                __FUNCTION__,
121
-                __LINE__
122
-            );
123
-        }
124
-        //if event id is valid
125
-        $id = absint(\EE_Registry::instance()->REQ->get('tkt-slctr-event-id'));
126
-        // check nonce
127
-        if ( ! $this->processTicketSelectorNonce('process_ticket_selections', $id)) {
128
-            return false;
129
-        }
130
-        //		d( \EE_Registry::instance()->REQ );
131
-        self::$_available_spaces = array(
132
-            'tickets'   => array(),
133
-            'datetimes' => array(),
134
-        );
135
-        //we should really only have 1 registration in the works now (ie, no MER) so clear any previous items in the cart.
136
-        // When MER happens this will probably need to be tweaked, possibly wrapped in a conditional checking for some constant defined in MER etc.
137
-        \EE_Registry::instance()->load_core('Session');
138
-        // unless otherwise requested, clear the session
139
-        if (apply_filters('FHEE__EE_Ticket_Selector__process_ticket_selections__clear_session', true)) {
140
-            \EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
141
-        }
142
-        //d( \EE_Registry::instance()->SSN );
143
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
144
-        // validate/sanitize data
145
-        $valid = $this->validatePostData($id);
146
-        //EEH_Debug_Tools::printr( $_REQUEST, '$_REQUEST', __FILE__, __LINE__ );
147
-        //EEH_Debug_Tools::printr( $valid, '$valid', __FILE__, __LINE__ );
148
-        //EEH_Debug_Tools::printr( $valid[ 'total_tickets' ], 'total_tickets', __FILE__, __LINE__ );
149
-        //EEH_Debug_Tools::printr( $valid[ 'max_atndz' ], 'max_atndz', __FILE__, __LINE__ );
150
-        //check total tickets ordered vs max number of attendees that can register
151
-        if ($valid['total_tickets'] > $valid['max_atndz']) {
152
-            // ordering too many tickets !!!
153
-            $total_tickets_string = _n(
154
-                'You have attempted to purchase %s ticket.',
155
-                'You have attempted to purchase %s tickets.',
156
-                $valid['total_tickets'],
157
-                'event_espresso'
158
-            );
159
-            $limit_error_1 = sprintf($total_tickets_string, $valid['total_tickets']);
160
-            // dev only message
161
-            $max_atndz_string = _n(
162
-                'The registration limit for this event is %s ticket per registration, therefore the total number of tickets you may purchase at a time can not exceed %s.',
163
-                'The registration limit for this event is %s tickets per registration, therefore the total number of tickets you may purchase at a time can not exceed %s.',
164
-                $valid['max_atndz'],
165
-                'event_espresso'
166
-            );
167
-            $limit_error_2 = sprintf($max_atndz_string, $valid['max_atndz'], $valid['max_atndz']);
168
-            \EE_Error::add_error($limit_error_1 . '<br/>' . $limit_error_2, __FILE__, __FUNCTION__, __LINE__);
169
-        } else {
170
-            // all data appears to be valid
171
-            $tckts_slctd = false;
172
-            $tickets_added = 0;
173
-            $valid = apply_filters('FHEE__EED_Ticket_Selector__process_ticket_selections__valid_post_data', $valid);
174
-            if ($valid['total_tickets'] > 0) {
175
-                // load cart
176
-                \EE_Registry::instance()->load_core('Cart');
177
-                // cycle thru the number of data rows sent from the event listing
178
-                for ($x = 0; $x < $valid['rows']; $x++) {
179
-                    // does this row actually contain a ticket quantity?
180
-                    if (isset($valid['qty'][$x]) && $valid['qty'][$x] > 0) {
181
-                        // YES we have a ticket quantity
182
-                        $tckts_slctd = true;
183
-                        //						d( $valid['ticket_obj'][$x] );
184
-                        if ($valid['ticket_obj'][$x] instanceof \EE_Ticket) {
185
-                            // then add ticket to cart
186
-                            $tickets_added += $this->addTicketToCart(
187
-                                $valid['ticket_obj'][$x],
188
-                                $valid['qty'][$x]
189
-                            );
190
-                            if (\EE_Error::has_error()) {
191
-                                break;
192
-                            }
193
-                        } else {
194
-                            // nothing added to cart retrieved
195
-                            \EE_Error::add_error(
196
-                                sprintf(
197
-                                    __(
198
-                                        'A valid ticket could not be retrieved for the event.%sPlease click the back button on your browser and try again.',
199
-                                        'event_espresso'
200
-                                    ),
201
-                                    '<br/>'
202
-                                ),
203
-                                __FILE__, __FUNCTION__, __LINE__
204
-                            );
205
-                        }
206
-                    }
207
-                }
208
-            }
209
-            do_action(
210
-                'AHEE__EE_Ticket_Selector__process_ticket_selections__after_tickets_added_to_cart',
211
-                \EE_Registry::instance()->CART,
212
-                $this
213
-            );
214
-            //d( \EE_Registry::instance()->CART );
215
-            //die(); // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< KILL REDIRECT HERE BEFORE CART UPDATE
216
-            if (apply_filters('FHEE__EED_Ticket_Selector__process_ticket_selections__tckts_slctd', $tckts_slctd)) {
217
-                if (apply_filters('FHEE__EED_Ticket_Selector__process_ticket_selections__success', $tickets_added)) {
218
-                    do_action(
219
-                        'FHEE__EE_Ticket_Selector__process_ticket_selections__before_redirecting_to_checkout',
220
-                        \EE_Registry::instance()->CART,
221
-                        $this
222
-                    );
223
-                    \EE_Registry::instance()->CART->recalculate_all_cart_totals();
224
-                    \EE_Registry::instance()->CART->save_cart(false);
225
-                    // exit('KILL REDIRECT AFTER CART UPDATE'); // <<<<<<<<  OR HERE TO KILL REDIRECT AFTER CART UPDATE
226
-                    // just return TRUE for registrations being made from admin
227
-                    if (is_admin()) {
228
-                        return true;
229
-                    }
230
-                    \EE_Error::get_notices(false, true);
231
-                    wp_safe_redirect(
232
-                        apply_filters(
233
-                            'FHEE__EE_Ticket_Selector__process_ticket_selections__success_redirect_url',
234
-                            \EE_Registry::instance()->CFG->core->reg_page_url()
235
-                        )
236
-                    );
237
-                    exit();
238
-                } else {
239
-                    if ( ! \EE_Error::has_error() && ! \EE_Error::has_error(true, 'attention')) {
240
-                        // nothing added to cart
241
-                        \EE_Error::add_attention(__('No tickets were added for the event', 'event_espresso'),
242
-                            __FILE__, __FUNCTION__, __LINE__);
243
-                    }
244
-                }
245
-            } else {
246
-                // no ticket quantities were selected
247
-                \EE_Error::add_error(__('You need to select a ticket quantity before you can proceed.',
248
-                    'event_espresso'), __FILE__, __FUNCTION__, __LINE__);
249
-            }
250
-        }
251
-        //die(); // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< KILL BEFORE REDIRECT
252
-        // at this point, just return if registration is being made from admin
253
-        if (is_admin()) {
254
-            return false;
255
-        }
256
-        if ($valid['return_url']) {
257
-            \EE_Error::get_notices(false, true);
258
-            wp_safe_redirect($valid['return_url']);
259
-            exit();
260
-        } elseif (isset($event_to_add['id'])) {
261
-            \EE_Error::get_notices(false, true);
262
-            wp_safe_redirect(get_permalink($event_to_add['id']));
263
-            exit();
264
-        } else {
265
-            echo \EE_Error::get_notices();
266
-        }
267
-        return false;
268
-    }
269
-
270
-
271
-
272
-    /**
273
-     * validate_post_data
274
-     *
275
-     * @param int $id
276
-     * @return array|FALSE
277
-     */
278
-    private function validatePostData($id = 0)
279
-    {
280
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
281
-        if ( ! $id) {
282
-            \EE_Error::add_error(
283
-                __('The event id provided was not valid.', 'event_espresso'),
284
-                __FILE__,
285
-                __FUNCTION__,
286
-                __LINE__
287
-            );
288
-            return false;
289
-        }
290
-        // start with an empty array()
291
-        $valid_data = array();
292
-        // grab valid id
293
-        $valid_data['id'] = $id;
294
-        // array of other form names
295
-        $inputs_to_clean = array(
296
-            'event_id'   => 'tkt-slctr-event-id',
297
-            'max_atndz'  => 'tkt-slctr-max-atndz-',
298
-            'rows'       => 'tkt-slctr-rows-',
299
-            'qty'        => 'tkt-slctr-qty-',
300
-            'ticket_id'  => 'tkt-slctr-ticket-id-',
301
-            'return_url' => 'tkt-slctr-return-url-',
302
-        );
303
-        // let's track the total number of tickets ordered.'
304
-        $valid_data['total_tickets'] = 0;
305
-        // cycle through $inputs_to_clean array
306
-        foreach ($inputs_to_clean as $what => $input_to_clean) {
307
-            // check for POST data
308
-            if (\EE_Registry::instance()->REQ->is_set($input_to_clean . $id)) {
309
-                // grab value
310
-                $input_value = \EE_Registry::instance()->REQ->get($input_to_clean . $id);
311
-                switch ($what) {
312
-                    // integers
313
-                    case 'event_id':
314
-                        $valid_data[$what] = absint($input_value);
315
-                        // get event via the event id we put in the form
316
-                        $valid_data['event'] = \EE_Registry::instance()
317
-                                                           ->load_model('Event')
318
-                                                           ->get_one_by_ID($valid_data['event_id']);
319
-                        break;
320
-                    case 'rows':
321
-                    case 'max_atndz':
322
-                        $valid_data[$what] = absint($input_value);
323
-                        break;
324
-                    // arrays of integers
325
-                    case 'qty':
326
-                        /** @var array $row_qty */
327
-                        $row_qty = $input_value;
328
-                        // if qty is coming from a radio button input, then we need to assemble an array of rows
329
-                        if ( ! is_array($row_qty)) {
330
-                            // get number of rows
331
-                            $rows = \EE_Registry::instance()->REQ->is_set('tkt-slctr-rows-' . $id)
332
-                                ? absint(\EE_Registry::instance()->REQ->get('tkt-slctr-rows-' . $id))
333
-                                : 1;
334
-                            // explode ints by the dash
335
-                            $row_qty = explode('-', $row_qty);
336
-                            $row = isset($row_qty[0]) ? absint($row_qty[0]) : 1;
337
-                            $qty = isset($row_qty[1]) ? absint($row_qty[1]) : 0;
338
-                            $row_qty = array($row => $qty);
339
-                            for ($x = 1; $x <= $rows; $x++) {
340
-                                if ( ! isset($row_qty[$x])) {
341
-                                    $row_qty[$x] = 0;
342
-                                }
343
-                            }
344
-                        }
345
-                        ksort($row_qty);
346
-                        // cycle thru values
347
-                        foreach ($row_qty as $qty) {
348
-                            $qty = absint($qty);
349
-                            // sanitize as integers
350
-                            $valid_data[$what][] = $qty;
351
-                            $valid_data['total_tickets'] += $qty;
352
-                        }
353
-                        break;
354
-                    // array of integers
355
-                    case 'ticket_id':
356
-                        $value_array = array();
357
-                        // cycle thru values
358
-                        foreach ((array)$input_value as $key => $value) {
359
-                            // allow only numbers, letters,  spaces, commas and dashes
360
-                            $value_array[$key] = wp_strip_all_tags($value);
361
-                            // get ticket via the ticket id we put in the form
362
-                            $ticket_obj = \EE_Registry::instance()->load_model('Ticket')->get_one_by_ID($value);
363
-                            $valid_data['ticket_obj'][$key] = $ticket_obj;
364
-                        }
365
-                        $valid_data[$what] = $value_array;
366
-                        break;
367
-                    case 'return_url' :
368
-                        // grab and sanitize return-url
369
-                        $input_value = esc_url_raw($input_value);
370
-                        // was the request coming from an iframe ? if so, then:
371
-                        if (strpos($input_value, 'event_list=iframe')) {
372
-                            // get anchor fragment
373
-                            $input_value = explode('#', $input_value);
374
-                            $input_value = end($input_value);
375
-                            // use event list url instead, but append anchor
376
-                            $input_value = \EEH_Event_View::event_archive_url() . '#' . $input_value;
377
-                        }
378
-                        $valid_data[$what] = $input_value;
379
-                        break;
380
-                }    // end switch $what
381
-            }
382
-        }    // end foreach $inputs_to_clean
383
-        return $valid_data;
384
-    }
385
-
386
-
387
-
388
-    /**
389
-     * adds a ticket to the cart
390
-     *
391
-     * @param \EE_Ticket $ticket
392
-     * @param int        $qty
393
-     * @return TRUE on success, FALSE on fail
394
-     * @throws \EE_Error
395
-     */
396
-    private function addTicketToCart(\EE_Ticket $ticket = null, $qty = 1)
397
-    {
398
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
399
-        // get the number of spaces left for this datetime ticket
400
-        $available_spaces = $this->ticketDatetimeAvailability($ticket);
401
-        // compare available spaces against the number of tickets being purchased
402
-        if ($available_spaces >= $qty) {
403
-            // allow addons to prevent a ticket from being added to cart
404
-            if (
405
-            ! apply_filters(
406
-                'FHEE__EE_Ticket_Selector___add_ticket_to_cart__allow_add_to_cart',
407
-                true,
408
-                $ticket,
409
-                $qty,
410
-                $available_spaces
411
-            )
412
-            ) {
413
-                return false;
414
-            }
415
-            $qty = absint(apply_filters('FHEE__EE_Ticket_Selector___add_ticket_to_cart__ticket_qty', $qty, $ticket));
416
-            // add event to cart
417
-            if (\EE_Registry::instance()->CART->add_ticket_to_cart($ticket, $qty)) {
418
-                $this->recalculateTicketDatetimeAvailability($ticket, $qty);
419
-                return true;
420
-            }
421
-            return false;
422
-        }
423
-        // tickets can not be purchased but let's find the exact number left
424
-        // for the last ticket selected PRIOR to subtracting tickets
425
-        $available_spaces = $this->ticketDatetimeAvailability($ticket, true);
426
-        // greedy greedy greedy eh?
427
-        if ($available_spaces > 0) {
428
-            if (
429
-            apply_filters(
430
-                'FHEE__EE_Ticket_Selector___add_ticket_to_cart__allow_display_availability_error',
431
-                true,
432
-                $ticket,
433
-                $qty,
434
-                $available_spaces
435
-            )
436
-            ) {
437
-                $this->displayAvailabilityError($available_spaces);
438
-            }
439
-        } else {
440
-            \EE_Error::add_error(
441
-                __(
442
-                    'We\'re sorry, but there are no available spaces left for this event at this particular date and time.',
443
-                    'event_espresso'
444
-                ),
445
-                __FILE__, __FUNCTION__, __LINE__
446
-            );
447
-        }
448
-        return false;
449
-    }
450
-
451
-
452
-
453
-    /**
454
-     * @param int $available_spaces
455
-     * @throws \EE_Error
456
-     */
457
-    private function displayAvailabilityError($available_spaces = 1)
458
-    {
459
-        // add error messaging - we're using the _n function that will generate
460
-        // the appropriate singular or plural message based on the number of $available_spaces
461
-        if (\EE_Registry::instance()->CART->all_ticket_quantity_count()) {
462
-            $msg = sprintf(
463
-                _n(
464
-                    'We\'re sorry, but there is only %1$s available space left for this event at this particular date and time. Please select a different number (or different combination) of tickets by cancelling the current selection and choosing again, or proceed to registration.',
465
-                    'We\'re sorry, but there are only %1$s available spaces left for this event at this particular date and time. Please select a different number (or different combination) of tickets by cancelling the current selection and choosing again, or proceed to registration.',
466
-                    $available_spaces,
467
-                    'event_espresso'
468
-                ),
469
-                $available_spaces,
470
-                '<br />'
471
-            );
472
-        } else {
473
-            $msg = sprintf(
474
-                _n(
475
-                    'We\'re sorry, but there is only %1$s available space left for this event at this particular date and time. Please select a different number (or different combination) of tickets.',
476
-                    'We\'re sorry, but there are only %1$s available spaces left for this event at this particular date and time. Please select a different number (or different combination) of tickets.',
477
-                    $available_spaces,
478
-                    'event_espresso'
479
-                ),
480
-                $available_spaces,
481
-                '<br />'
482
-            );
483
-        }
484
-        \EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
485
-    }
486
-
487
-
488
-
489
-    /**
490
-     * ticketDatetimeAvailability
491
-     * creates an array of tickets plus all of the datetimes available to each ticket
492
-     * and tracks the spaces remaining for each of those datetimes
493
-     *
494
-     * @param \EE_Ticket $ticket - selected ticket
495
-     * @param bool       $get_original_ticket_spaces
496
-     * @return int
497
-     * @throws \EE_Error
498
-     */
499
-    private function ticketDatetimeAvailability(\EE_Ticket $ticket, $get_original_ticket_spaces = false)
500
-    {
501
-        // if the $_available_spaces array has not been set up yet...
502
-        if ( ! isset(self::$_available_spaces['tickets'][$ticket->ID()])) {
503
-            $this->setInitialTicketDatetimeAvailability($ticket);
504
-        }
505
-        $available_spaces = $ticket->qty() - $ticket->sold();
506
-        if (isset(self::$_available_spaces['tickets'][$ticket->ID()])) {
507
-            // loop thru tickets, which will ALSO include individual ticket records AND a total
508
-            foreach (self::$_available_spaces['tickets'][$ticket->ID()] as $DTD_ID => $spaces) {
509
-                // if we want the original datetime availability BEFORE we started subtracting tickets ?
510
-                if ($get_original_ticket_spaces) {
511
-                    // then grab the available spaces from the "tickets" array
512
-                    // and compare with the above to get the lowest number
513
-                    $available_spaces = min(
514
-                        $available_spaces,
515
-                        self::$_available_spaces['tickets'][$ticket->ID()][$DTD_ID]
516
-                    );
517
-                } else {
518
-                    // we want the updated ticket availability as stored in the "datetimes" array
519
-                    $available_spaces = min($available_spaces, self::$_available_spaces['datetimes'][$DTD_ID]);
520
-                }
521
-            }
522
-        }
523
-        return $available_spaces;
524
-    }
525
-
526
-
527
-
528
-    /**
529
-     * @param \EE_Ticket $ticket
530
-     * @return void
531
-     * @throws \EE_Error
532
-     */
533
-    private function setInitialTicketDatetimeAvailability(\EE_Ticket $ticket)
534
-    {
535
-        // first, get all of the datetimes that are available to this ticket
536
-        $datetimes = $ticket->get_many_related(
537
-            'Datetime',
538
-            array(
539
-                array(
540
-                    'DTT_EVT_end' => array(
541
-                        '>=',
542
-                        \EEM_Datetime::instance()->current_time_for_query('DTT_EVT_end'),
543
-                    ),
544
-                ),
545
-                'order_by' => array('DTT_EVT_start' => 'ASC'),
546
-            )
547
-        );
548
-        if ( ! empty($datetimes)) {
549
-            // now loop thru all of the datetimes
550
-            foreach ($datetimes as $datetime) {
551
-                if ($datetime instanceof \EE_Datetime) {
552
-                    // the number of spaces available for the datetime without considering individual ticket quantities
553
-                    $spaces_remaining = $datetime->spaces_remaining();
554
-                    // save the total available spaces ( the lesser of the ticket qty minus the number of tickets sold
555
-                    // or the datetime spaces remaining) to this ticket using the datetime ID as the key
556
-                    self::$_available_spaces['tickets'][$ticket->ID()][$datetime->ID()] = min(
557
-                        $ticket->qty() - $ticket->sold(),
558
-                        $spaces_remaining
559
-                    );
560
-                    // if the remaining spaces for this datetime is already set,
561
-                    // then compare that against the datetime spaces remaining, and take the lowest number,
562
-                    // else just take the datetime spaces remaining, and assign to the datetimes array
563
-                    self::$_available_spaces['datetimes'][$datetime->ID()] = isset(
564
-                        self::$_available_spaces['datetimes'][$datetime->ID()]
565
-                    )
566
-                        ? min(self::$_available_spaces['datetimes'][$datetime->ID()], $spaces_remaining)
567
-                        : $spaces_remaining;
568
-                }
569
-            }
570
-        }
571
-    }
572
-
573
-
574
-
575
-    /**
576
-     * @param    \EE_Ticket $ticket
577
-     * @param    int        $qty
578
-     * @return    void
579
-     */
580
-    private function recalculateTicketDatetimeAvailability(\EE_Ticket $ticket, $qty = 0)
581
-    {
582
-        if (isset(self::$_available_spaces['tickets'][$ticket->ID()])) {
583
-            // loop thru tickets, which will ALSO include individual ticket records AND a total
584
-            foreach (self::$_available_spaces['tickets'][$ticket->ID()] as $DTD_ID => $spaces) {
585
-                // subtract the qty of selected tickets from each datetime's available spaces this ticket has access to,
586
-                self::$_available_spaces['datetimes'][$DTD_ID] -= $qty;
587
-            }
588
-        }
589
-    }
22
+	/**
23
+	 * array of datetimes and the spaces available for them
24
+	 *
25
+	 * @access private
26
+	 * @var array
27
+	 */
28
+	private static $_available_spaces = array();
29
+
30
+
31
+
32
+	/**
33
+	 * cancelTicketSelections
34
+	 *
35
+	 * @return        string
36
+	 */
37
+	public function cancelTicketSelections()
38
+	{
39
+		// check nonce
40
+		if ( ! $this->processTicketSelectorNonce('cancel_ticket_selections')) {
41
+			return false;
42
+		}
43
+		\EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
44
+		if (\EE_Registry::instance()->REQ->is_set('event_id')) {
45
+			wp_safe_redirect(
46
+				\EEH_Event_View::event_link_url(
47
+					\EE_Registry::instance()->REQ->get('event_id')
48
+				)
49
+			);
50
+		} else {
51
+			wp_safe_redirect(
52
+				site_url('/' . \EE_Registry::instance()->CFG->core->event_cpt_slug . '/')
53
+			);
54
+		}
55
+		exit();
56
+	}
57
+
58
+
59
+
60
+	/**
61
+	 * processTicketSelectorNonce
62
+	 *
63
+	 * @param  string $nonce_name
64
+	 * @param string  $id
65
+	 * @return bool
66
+	 */
67
+	private function processTicketSelectorNonce($nonce_name, $id = '')
68
+	{
69
+		$nonce_name_with_id = ! empty($id) ? "{$nonce_name}_nonce_{$id}" : "{$nonce_name}_nonce";
70
+		if (
71
+			! is_admin()
72
+			&& (
73
+				! \EE_Registry::instance()->REQ->is_set($nonce_name_with_id)
74
+				|| ! wp_verify_nonce(
75
+					\EE_Registry::instance()->REQ->get($nonce_name_with_id),
76
+					$nonce_name
77
+				)
78
+			)
79
+		) {
80
+			\EE_Error::add_error(
81
+				sprintf(
82
+					__(
83
+						'We\'re sorry but your request failed to pass a security check.%sPlease click the back button on your browser and try again.',
84
+						'event_espresso'
85
+					),
86
+					'<br/>'
87
+				),
88
+				__FILE__,
89
+				__FUNCTION__,
90
+				__LINE__
91
+			);
92
+			return false;
93
+		}
94
+		return true;
95
+	}
96
+
97
+
98
+
99
+	/**
100
+	 * process_ticket_selections
101
+	 *
102
+	 * @return array|bool
103
+	 * @throws \EE_Error
104
+	 */
105
+	public function processTicketSelections()
106
+	{
107
+		do_action('EED_Ticket_Selector__process_ticket_selections__before');
108
+		// do we have an event id?
109
+		if ( ! \EE_Registry::instance()->REQ->is_set('tkt-slctr-event-id')) {
110
+			// $_POST['tkt-slctr-event-id'] was not set ?!?!?!?
111
+			\EE_Error::add_error(
112
+				sprintf(
113
+					__(
114
+						'An event id was not provided or was not received.%sPlease click the back button on your browser and try again.',
115
+						'event_espresso'
116
+					),
117
+					'<br/>'
118
+				),
119
+				__FILE__,
120
+				__FUNCTION__,
121
+				__LINE__
122
+			);
123
+		}
124
+		//if event id is valid
125
+		$id = absint(\EE_Registry::instance()->REQ->get('tkt-slctr-event-id'));
126
+		// check nonce
127
+		if ( ! $this->processTicketSelectorNonce('process_ticket_selections', $id)) {
128
+			return false;
129
+		}
130
+		//		d( \EE_Registry::instance()->REQ );
131
+		self::$_available_spaces = array(
132
+			'tickets'   => array(),
133
+			'datetimes' => array(),
134
+		);
135
+		//we should really only have 1 registration in the works now (ie, no MER) so clear any previous items in the cart.
136
+		// When MER happens this will probably need to be tweaked, possibly wrapped in a conditional checking for some constant defined in MER etc.
137
+		\EE_Registry::instance()->load_core('Session');
138
+		// unless otherwise requested, clear the session
139
+		if (apply_filters('FHEE__EE_Ticket_Selector__process_ticket_selections__clear_session', true)) {
140
+			\EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
141
+		}
142
+		//d( \EE_Registry::instance()->SSN );
143
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
144
+		// validate/sanitize data
145
+		$valid = $this->validatePostData($id);
146
+		//EEH_Debug_Tools::printr( $_REQUEST, '$_REQUEST', __FILE__, __LINE__ );
147
+		//EEH_Debug_Tools::printr( $valid, '$valid', __FILE__, __LINE__ );
148
+		//EEH_Debug_Tools::printr( $valid[ 'total_tickets' ], 'total_tickets', __FILE__, __LINE__ );
149
+		//EEH_Debug_Tools::printr( $valid[ 'max_atndz' ], 'max_atndz', __FILE__, __LINE__ );
150
+		//check total tickets ordered vs max number of attendees that can register
151
+		if ($valid['total_tickets'] > $valid['max_atndz']) {
152
+			// ordering too many tickets !!!
153
+			$total_tickets_string = _n(
154
+				'You have attempted to purchase %s ticket.',
155
+				'You have attempted to purchase %s tickets.',
156
+				$valid['total_tickets'],
157
+				'event_espresso'
158
+			);
159
+			$limit_error_1 = sprintf($total_tickets_string, $valid['total_tickets']);
160
+			// dev only message
161
+			$max_atndz_string = _n(
162
+				'The registration limit for this event is %s ticket per registration, therefore the total number of tickets you may purchase at a time can not exceed %s.',
163
+				'The registration limit for this event is %s tickets per registration, therefore the total number of tickets you may purchase at a time can not exceed %s.',
164
+				$valid['max_atndz'],
165
+				'event_espresso'
166
+			);
167
+			$limit_error_2 = sprintf($max_atndz_string, $valid['max_atndz'], $valid['max_atndz']);
168
+			\EE_Error::add_error($limit_error_1 . '<br/>' . $limit_error_2, __FILE__, __FUNCTION__, __LINE__);
169
+		} else {
170
+			// all data appears to be valid
171
+			$tckts_slctd = false;
172
+			$tickets_added = 0;
173
+			$valid = apply_filters('FHEE__EED_Ticket_Selector__process_ticket_selections__valid_post_data', $valid);
174
+			if ($valid['total_tickets'] > 0) {
175
+				// load cart
176
+				\EE_Registry::instance()->load_core('Cart');
177
+				// cycle thru the number of data rows sent from the event listing
178
+				for ($x = 0; $x < $valid['rows']; $x++) {
179
+					// does this row actually contain a ticket quantity?
180
+					if (isset($valid['qty'][$x]) && $valid['qty'][$x] > 0) {
181
+						// YES we have a ticket quantity
182
+						$tckts_slctd = true;
183
+						//						d( $valid['ticket_obj'][$x] );
184
+						if ($valid['ticket_obj'][$x] instanceof \EE_Ticket) {
185
+							// then add ticket to cart
186
+							$tickets_added += $this->addTicketToCart(
187
+								$valid['ticket_obj'][$x],
188
+								$valid['qty'][$x]
189
+							);
190
+							if (\EE_Error::has_error()) {
191
+								break;
192
+							}
193
+						} else {
194
+							// nothing added to cart retrieved
195
+							\EE_Error::add_error(
196
+								sprintf(
197
+									__(
198
+										'A valid ticket could not be retrieved for the event.%sPlease click the back button on your browser and try again.',
199
+										'event_espresso'
200
+									),
201
+									'<br/>'
202
+								),
203
+								__FILE__, __FUNCTION__, __LINE__
204
+							);
205
+						}
206
+					}
207
+				}
208
+			}
209
+			do_action(
210
+				'AHEE__EE_Ticket_Selector__process_ticket_selections__after_tickets_added_to_cart',
211
+				\EE_Registry::instance()->CART,
212
+				$this
213
+			);
214
+			//d( \EE_Registry::instance()->CART );
215
+			//die(); // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< KILL REDIRECT HERE BEFORE CART UPDATE
216
+			if (apply_filters('FHEE__EED_Ticket_Selector__process_ticket_selections__tckts_slctd', $tckts_slctd)) {
217
+				if (apply_filters('FHEE__EED_Ticket_Selector__process_ticket_selections__success', $tickets_added)) {
218
+					do_action(
219
+						'FHEE__EE_Ticket_Selector__process_ticket_selections__before_redirecting_to_checkout',
220
+						\EE_Registry::instance()->CART,
221
+						$this
222
+					);
223
+					\EE_Registry::instance()->CART->recalculate_all_cart_totals();
224
+					\EE_Registry::instance()->CART->save_cart(false);
225
+					// exit('KILL REDIRECT AFTER CART UPDATE'); // <<<<<<<<  OR HERE TO KILL REDIRECT AFTER CART UPDATE
226
+					// just return TRUE for registrations being made from admin
227
+					if (is_admin()) {
228
+						return true;
229
+					}
230
+					\EE_Error::get_notices(false, true);
231
+					wp_safe_redirect(
232
+						apply_filters(
233
+							'FHEE__EE_Ticket_Selector__process_ticket_selections__success_redirect_url',
234
+							\EE_Registry::instance()->CFG->core->reg_page_url()
235
+						)
236
+					);
237
+					exit();
238
+				} else {
239
+					if ( ! \EE_Error::has_error() && ! \EE_Error::has_error(true, 'attention')) {
240
+						// nothing added to cart
241
+						\EE_Error::add_attention(__('No tickets were added for the event', 'event_espresso'),
242
+							__FILE__, __FUNCTION__, __LINE__);
243
+					}
244
+				}
245
+			} else {
246
+				// no ticket quantities were selected
247
+				\EE_Error::add_error(__('You need to select a ticket quantity before you can proceed.',
248
+					'event_espresso'), __FILE__, __FUNCTION__, __LINE__);
249
+			}
250
+		}
251
+		//die(); // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< KILL BEFORE REDIRECT
252
+		// at this point, just return if registration is being made from admin
253
+		if (is_admin()) {
254
+			return false;
255
+		}
256
+		if ($valid['return_url']) {
257
+			\EE_Error::get_notices(false, true);
258
+			wp_safe_redirect($valid['return_url']);
259
+			exit();
260
+		} elseif (isset($event_to_add['id'])) {
261
+			\EE_Error::get_notices(false, true);
262
+			wp_safe_redirect(get_permalink($event_to_add['id']));
263
+			exit();
264
+		} else {
265
+			echo \EE_Error::get_notices();
266
+		}
267
+		return false;
268
+	}
269
+
270
+
271
+
272
+	/**
273
+	 * validate_post_data
274
+	 *
275
+	 * @param int $id
276
+	 * @return array|FALSE
277
+	 */
278
+	private function validatePostData($id = 0)
279
+	{
280
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
281
+		if ( ! $id) {
282
+			\EE_Error::add_error(
283
+				__('The event id provided was not valid.', 'event_espresso'),
284
+				__FILE__,
285
+				__FUNCTION__,
286
+				__LINE__
287
+			);
288
+			return false;
289
+		}
290
+		// start with an empty array()
291
+		$valid_data = array();
292
+		// grab valid id
293
+		$valid_data['id'] = $id;
294
+		// array of other form names
295
+		$inputs_to_clean = array(
296
+			'event_id'   => 'tkt-slctr-event-id',
297
+			'max_atndz'  => 'tkt-slctr-max-atndz-',
298
+			'rows'       => 'tkt-slctr-rows-',
299
+			'qty'        => 'tkt-slctr-qty-',
300
+			'ticket_id'  => 'tkt-slctr-ticket-id-',
301
+			'return_url' => 'tkt-slctr-return-url-',
302
+		);
303
+		// let's track the total number of tickets ordered.'
304
+		$valid_data['total_tickets'] = 0;
305
+		// cycle through $inputs_to_clean array
306
+		foreach ($inputs_to_clean as $what => $input_to_clean) {
307
+			// check for POST data
308
+			if (\EE_Registry::instance()->REQ->is_set($input_to_clean . $id)) {
309
+				// grab value
310
+				$input_value = \EE_Registry::instance()->REQ->get($input_to_clean . $id);
311
+				switch ($what) {
312
+					// integers
313
+					case 'event_id':
314
+						$valid_data[$what] = absint($input_value);
315
+						// get event via the event id we put in the form
316
+						$valid_data['event'] = \EE_Registry::instance()
317
+														   ->load_model('Event')
318
+														   ->get_one_by_ID($valid_data['event_id']);
319
+						break;
320
+					case 'rows':
321
+					case 'max_atndz':
322
+						$valid_data[$what] = absint($input_value);
323
+						break;
324
+					// arrays of integers
325
+					case 'qty':
326
+						/** @var array $row_qty */
327
+						$row_qty = $input_value;
328
+						// if qty is coming from a radio button input, then we need to assemble an array of rows
329
+						if ( ! is_array($row_qty)) {
330
+							// get number of rows
331
+							$rows = \EE_Registry::instance()->REQ->is_set('tkt-slctr-rows-' . $id)
332
+								? absint(\EE_Registry::instance()->REQ->get('tkt-slctr-rows-' . $id))
333
+								: 1;
334
+							// explode ints by the dash
335
+							$row_qty = explode('-', $row_qty);
336
+							$row = isset($row_qty[0]) ? absint($row_qty[0]) : 1;
337
+							$qty = isset($row_qty[1]) ? absint($row_qty[1]) : 0;
338
+							$row_qty = array($row => $qty);
339
+							for ($x = 1; $x <= $rows; $x++) {
340
+								if ( ! isset($row_qty[$x])) {
341
+									$row_qty[$x] = 0;
342
+								}
343
+							}
344
+						}
345
+						ksort($row_qty);
346
+						// cycle thru values
347
+						foreach ($row_qty as $qty) {
348
+							$qty = absint($qty);
349
+							// sanitize as integers
350
+							$valid_data[$what][] = $qty;
351
+							$valid_data['total_tickets'] += $qty;
352
+						}
353
+						break;
354
+					// array of integers
355
+					case 'ticket_id':
356
+						$value_array = array();
357
+						// cycle thru values
358
+						foreach ((array)$input_value as $key => $value) {
359
+							// allow only numbers, letters,  spaces, commas and dashes
360
+							$value_array[$key] = wp_strip_all_tags($value);
361
+							// get ticket via the ticket id we put in the form
362
+							$ticket_obj = \EE_Registry::instance()->load_model('Ticket')->get_one_by_ID($value);
363
+							$valid_data['ticket_obj'][$key] = $ticket_obj;
364
+						}
365
+						$valid_data[$what] = $value_array;
366
+						break;
367
+					case 'return_url' :
368
+						// grab and sanitize return-url
369
+						$input_value = esc_url_raw($input_value);
370
+						// was the request coming from an iframe ? if so, then:
371
+						if (strpos($input_value, 'event_list=iframe')) {
372
+							// get anchor fragment
373
+							$input_value = explode('#', $input_value);
374
+							$input_value = end($input_value);
375
+							// use event list url instead, but append anchor
376
+							$input_value = \EEH_Event_View::event_archive_url() . '#' . $input_value;
377
+						}
378
+						$valid_data[$what] = $input_value;
379
+						break;
380
+				}    // end switch $what
381
+			}
382
+		}    // end foreach $inputs_to_clean
383
+		return $valid_data;
384
+	}
385
+
386
+
387
+
388
+	/**
389
+	 * adds a ticket to the cart
390
+	 *
391
+	 * @param \EE_Ticket $ticket
392
+	 * @param int        $qty
393
+	 * @return TRUE on success, FALSE on fail
394
+	 * @throws \EE_Error
395
+	 */
396
+	private function addTicketToCart(\EE_Ticket $ticket = null, $qty = 1)
397
+	{
398
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
399
+		// get the number of spaces left for this datetime ticket
400
+		$available_spaces = $this->ticketDatetimeAvailability($ticket);
401
+		// compare available spaces against the number of tickets being purchased
402
+		if ($available_spaces >= $qty) {
403
+			// allow addons to prevent a ticket from being added to cart
404
+			if (
405
+			! apply_filters(
406
+				'FHEE__EE_Ticket_Selector___add_ticket_to_cart__allow_add_to_cart',
407
+				true,
408
+				$ticket,
409
+				$qty,
410
+				$available_spaces
411
+			)
412
+			) {
413
+				return false;
414
+			}
415
+			$qty = absint(apply_filters('FHEE__EE_Ticket_Selector___add_ticket_to_cart__ticket_qty', $qty, $ticket));
416
+			// add event to cart
417
+			if (\EE_Registry::instance()->CART->add_ticket_to_cart($ticket, $qty)) {
418
+				$this->recalculateTicketDatetimeAvailability($ticket, $qty);
419
+				return true;
420
+			}
421
+			return false;
422
+		}
423
+		// tickets can not be purchased but let's find the exact number left
424
+		// for the last ticket selected PRIOR to subtracting tickets
425
+		$available_spaces = $this->ticketDatetimeAvailability($ticket, true);
426
+		// greedy greedy greedy eh?
427
+		if ($available_spaces > 0) {
428
+			if (
429
+			apply_filters(
430
+				'FHEE__EE_Ticket_Selector___add_ticket_to_cart__allow_display_availability_error',
431
+				true,
432
+				$ticket,
433
+				$qty,
434
+				$available_spaces
435
+			)
436
+			) {
437
+				$this->displayAvailabilityError($available_spaces);
438
+			}
439
+		} else {
440
+			\EE_Error::add_error(
441
+				__(
442
+					'We\'re sorry, but there are no available spaces left for this event at this particular date and time.',
443
+					'event_espresso'
444
+				),
445
+				__FILE__, __FUNCTION__, __LINE__
446
+			);
447
+		}
448
+		return false;
449
+	}
450
+
451
+
452
+
453
+	/**
454
+	 * @param int $available_spaces
455
+	 * @throws \EE_Error
456
+	 */
457
+	private function displayAvailabilityError($available_spaces = 1)
458
+	{
459
+		// add error messaging - we're using the _n function that will generate
460
+		// the appropriate singular or plural message based on the number of $available_spaces
461
+		if (\EE_Registry::instance()->CART->all_ticket_quantity_count()) {
462
+			$msg = sprintf(
463
+				_n(
464
+					'We\'re sorry, but there is only %1$s available space left for this event at this particular date and time. Please select a different number (or different combination) of tickets by cancelling the current selection and choosing again, or proceed to registration.',
465
+					'We\'re sorry, but there are only %1$s available spaces left for this event at this particular date and time. Please select a different number (or different combination) of tickets by cancelling the current selection and choosing again, or proceed to registration.',
466
+					$available_spaces,
467
+					'event_espresso'
468
+				),
469
+				$available_spaces,
470
+				'<br />'
471
+			);
472
+		} else {
473
+			$msg = sprintf(
474
+				_n(
475
+					'We\'re sorry, but there is only %1$s available space left for this event at this particular date and time. Please select a different number (or different combination) of tickets.',
476
+					'We\'re sorry, but there are only %1$s available spaces left for this event at this particular date and time. Please select a different number (or different combination) of tickets.',
477
+					$available_spaces,
478
+					'event_espresso'
479
+				),
480
+				$available_spaces,
481
+				'<br />'
482
+			);
483
+		}
484
+		\EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
485
+	}
486
+
487
+
488
+
489
+	/**
490
+	 * ticketDatetimeAvailability
491
+	 * creates an array of tickets plus all of the datetimes available to each ticket
492
+	 * and tracks the spaces remaining for each of those datetimes
493
+	 *
494
+	 * @param \EE_Ticket $ticket - selected ticket
495
+	 * @param bool       $get_original_ticket_spaces
496
+	 * @return int
497
+	 * @throws \EE_Error
498
+	 */
499
+	private function ticketDatetimeAvailability(\EE_Ticket $ticket, $get_original_ticket_spaces = false)
500
+	{
501
+		// if the $_available_spaces array has not been set up yet...
502
+		if ( ! isset(self::$_available_spaces['tickets'][$ticket->ID()])) {
503
+			$this->setInitialTicketDatetimeAvailability($ticket);
504
+		}
505
+		$available_spaces = $ticket->qty() - $ticket->sold();
506
+		if (isset(self::$_available_spaces['tickets'][$ticket->ID()])) {
507
+			// loop thru tickets, which will ALSO include individual ticket records AND a total
508
+			foreach (self::$_available_spaces['tickets'][$ticket->ID()] as $DTD_ID => $spaces) {
509
+				// if we want the original datetime availability BEFORE we started subtracting tickets ?
510
+				if ($get_original_ticket_spaces) {
511
+					// then grab the available spaces from the "tickets" array
512
+					// and compare with the above to get the lowest number
513
+					$available_spaces = min(
514
+						$available_spaces,
515
+						self::$_available_spaces['tickets'][$ticket->ID()][$DTD_ID]
516
+					);
517
+				} else {
518
+					// we want the updated ticket availability as stored in the "datetimes" array
519
+					$available_spaces = min($available_spaces, self::$_available_spaces['datetimes'][$DTD_ID]);
520
+				}
521
+			}
522
+		}
523
+		return $available_spaces;
524
+	}
525
+
526
+
527
+
528
+	/**
529
+	 * @param \EE_Ticket $ticket
530
+	 * @return void
531
+	 * @throws \EE_Error
532
+	 */
533
+	private function setInitialTicketDatetimeAvailability(\EE_Ticket $ticket)
534
+	{
535
+		// first, get all of the datetimes that are available to this ticket
536
+		$datetimes = $ticket->get_many_related(
537
+			'Datetime',
538
+			array(
539
+				array(
540
+					'DTT_EVT_end' => array(
541
+						'>=',
542
+						\EEM_Datetime::instance()->current_time_for_query('DTT_EVT_end'),
543
+					),
544
+				),
545
+				'order_by' => array('DTT_EVT_start' => 'ASC'),
546
+			)
547
+		);
548
+		if ( ! empty($datetimes)) {
549
+			// now loop thru all of the datetimes
550
+			foreach ($datetimes as $datetime) {
551
+				if ($datetime instanceof \EE_Datetime) {
552
+					// the number of spaces available for the datetime without considering individual ticket quantities
553
+					$spaces_remaining = $datetime->spaces_remaining();
554
+					// save the total available spaces ( the lesser of the ticket qty minus the number of tickets sold
555
+					// or the datetime spaces remaining) to this ticket using the datetime ID as the key
556
+					self::$_available_spaces['tickets'][$ticket->ID()][$datetime->ID()] = min(
557
+						$ticket->qty() - $ticket->sold(),
558
+						$spaces_remaining
559
+					);
560
+					// if the remaining spaces for this datetime is already set,
561
+					// then compare that against the datetime spaces remaining, and take the lowest number,
562
+					// else just take the datetime spaces remaining, and assign to the datetimes array
563
+					self::$_available_spaces['datetimes'][$datetime->ID()] = isset(
564
+						self::$_available_spaces['datetimes'][$datetime->ID()]
565
+					)
566
+						? min(self::$_available_spaces['datetimes'][$datetime->ID()], $spaces_remaining)
567
+						: $spaces_remaining;
568
+				}
569
+			}
570
+		}
571
+	}
572
+
573
+
574
+
575
+	/**
576
+	 * @param    \EE_Ticket $ticket
577
+	 * @param    int        $qty
578
+	 * @return    void
579
+	 */
580
+	private function recalculateTicketDatetimeAvailability(\EE_Ticket $ticket, $qty = 0)
581
+	{
582
+		if (isset(self::$_available_spaces['tickets'][$ticket->ID()])) {
583
+			// loop thru tickets, which will ALSO include individual ticket records AND a total
584
+			foreach (self::$_available_spaces['tickets'][$ticket->ID()] as $DTD_ID => $spaces) {
585
+				// subtract the qty of selected tickets from each datetime's available spaces this ticket has access to,
586
+				self::$_available_spaces['datetimes'][$DTD_ID] -= $qty;
587
+			}
588
+		}
589
+	}
590 590
 
591 591
 
592 592
 }
Please login to merge, or discard this patch.
Spacing   +8 added lines, -8 removed lines patch added patch discarded remove patch
@@ -49,7 +49,7 @@  discard block
 block discarded – undo
49 49
             );
50 50
         } else {
51 51
             wp_safe_redirect(
52
-                site_url('/' . \EE_Registry::instance()->CFG->core->event_cpt_slug . '/')
52
+                site_url('/'.\EE_Registry::instance()->CFG->core->event_cpt_slug.'/')
53 53
             );
54 54
         }
55 55
         exit();
@@ -165,7 +165,7 @@  discard block
 block discarded – undo
165 165
                 'event_espresso'
166 166
             );
167 167
             $limit_error_2 = sprintf($max_atndz_string, $valid['max_atndz'], $valid['max_atndz']);
168
-            \EE_Error::add_error($limit_error_1 . '<br/>' . $limit_error_2, __FILE__, __FUNCTION__, __LINE__);
168
+            \EE_Error::add_error($limit_error_1.'<br/>'.$limit_error_2, __FILE__, __FUNCTION__, __LINE__);
169 169
         } else {
170 170
             // all data appears to be valid
171 171
             $tckts_slctd = false;
@@ -305,9 +305,9 @@  discard block
 block discarded – undo
305 305
         // cycle through $inputs_to_clean array
306 306
         foreach ($inputs_to_clean as $what => $input_to_clean) {
307 307
             // check for POST data
308
-            if (\EE_Registry::instance()->REQ->is_set($input_to_clean . $id)) {
308
+            if (\EE_Registry::instance()->REQ->is_set($input_to_clean.$id)) {
309 309
                 // grab value
310
-                $input_value = \EE_Registry::instance()->REQ->get($input_to_clean . $id);
310
+                $input_value = \EE_Registry::instance()->REQ->get($input_to_clean.$id);
311 311
                 switch ($what) {
312 312
                     // integers
313 313
                     case 'event_id':
@@ -328,8 +328,8 @@  discard block
 block discarded – undo
328 328
                         // if qty is coming from a radio button input, then we need to assemble an array of rows
329 329
                         if ( ! is_array($row_qty)) {
330 330
                             // get number of rows
331
-                            $rows = \EE_Registry::instance()->REQ->is_set('tkt-slctr-rows-' . $id)
332
-                                ? absint(\EE_Registry::instance()->REQ->get('tkt-slctr-rows-' . $id))
331
+                            $rows = \EE_Registry::instance()->REQ->is_set('tkt-slctr-rows-'.$id)
332
+                                ? absint(\EE_Registry::instance()->REQ->get('tkt-slctr-rows-'.$id))
333 333
                                 : 1;
334 334
                             // explode ints by the dash
335 335
                             $row_qty = explode('-', $row_qty);
@@ -355,7 +355,7 @@  discard block
 block discarded – undo
355 355
                     case 'ticket_id':
356 356
                         $value_array = array();
357 357
                         // cycle thru values
358
-                        foreach ((array)$input_value as $key => $value) {
358
+                        foreach ((array) $input_value as $key => $value) {
359 359
                             // allow only numbers, letters,  spaces, commas and dashes
360 360
                             $value_array[$key] = wp_strip_all_tags($value);
361 361
                             // get ticket via the ticket id we put in the form
@@ -373,7 +373,7 @@  discard block
 block discarded – undo
373 373
                             $input_value = explode('#', $input_value);
374 374
                             $input_value = end($input_value);
375 375
                             // use event list url instead, but append anchor
376
-                            $input_value = \EEH_Event_View::event_archive_url() . '#' . $input_value;
376
+                            $input_value = \EEH_Event_View::event_archive_url().'#'.$input_value;
377 377
                         }
378 378
                         $valid_data[$what] = $input_value;
379 379
                         break;
Please login to merge, or discard this patch.
core/db_models/EEM_Datetime.model.php 1 patch
Indentation   +581 added lines, -581 removed lines patch added patch discarded remove patch
@@ -1,5 +1,5 @@  discard block
 block discarded – undo
1 1
 <?php if ( ! defined('EVENT_ESPRESSO_VERSION')) {
2
-    exit('No direct script access allowed');
2
+	exit('No direct script access allowed');
3 3
 }
4 4
 /**
5 5
  * Class Datetime Model
@@ -11,586 +11,586 @@  discard block
 block discarded – undo
11 11
 class EEM_Datetime extends EEM_Soft_Delete_Base
12 12
 {
13 13
 
14
-    /**
15
-     * @var EEM_Datetime $_instance
16
-     */
17
-    protected static $_instance;
18
-
19
-
20
-
21
-    /**
22
-     *        private constructor to prevent direct creation
23
-     *
24
-     * @Constructor
25
-     * @access private
26
-     * @param string $timezone string representing the timezone we want to set for returned Date Time Strings (and any
27
-     *                         incoming timezone data that gets saved).  Note this just sends the timezone info to the
28
-     *                         date time model field objects.  Default is NULL (and will be assumed using the set
29
-     *                         timezone in the 'timezone_string' wp option)
30
-     * @throws \EE_Error
31
-     */
32
-    protected function __construct($timezone)
33
-    {
34
-        $this->singular_item = __('Datetime', 'event_espresso');
35
-        $this->plural_item = __('Datetimes', 'event_espresso');
36
-        $this->_tables = array(
37
-            'Datetime' => new EE_Primary_Table('esp_datetime', 'DTT_ID'),
38
-        );
39
-        $this->_fields = array(
40
-            'Datetime' => array(
41
-                'DTT_ID'          => new EE_Primary_Key_Int_Field('DTT_ID', __('Datetime ID', 'event_espresso')),
42
-                'EVT_ID'          => new EE_Foreign_Key_Int_Field(
43
-                    'EVT_ID', __('Event ID', 'event_espresso'), false, 0, 'Event'
44
-                ),
45
-                'DTT_name'        => new EE_Plain_Text_Field(
46
-                    'DTT_name', __('Datetime Name', 'event_espresso'), false, ''
47
-                ),
48
-                'DTT_description' => new EE_Post_Content_Field(
49
-                    'DTT_description', __('Description for Datetime', 'event_espresso'), false, ''
50
-                ),
51
-                'DTT_EVT_start'   => new EE_Datetime_Field(
52
-                    'DTT_EVT_start', __('Start time/date of Event', 'event_espresso'), false, EE_Datetime_Field::now,
53
-                    $timezone
54
-                ),
55
-                'DTT_EVT_end'     => new EE_Datetime_Field(
56
-                    'DTT_EVT_end', __('End time/date of Event', 'event_espresso'), false, EE_Datetime_Field::now,
57
-                    $timezone
58
-                ),
59
-                'DTT_reg_limit'   => new EE_Infinite_Integer_Field(
60
-                    'DTT_reg_limit', __('Registration Limit for this time', 'event_espresso'), true, EE_INF),
61
-                'DTT_sold'        => new EE_Integer_Field(
62
-                    'DTT_sold', __('How many sales for this Datetime that have occurred', 'event_espresso'), true, 0
63
-                ),
64
-                'DTT_reserved' => new EE_Integer_Field('DTT_reserved',
65
-                    __('Quantity of tickets reserved, but not yet fully purchased', 'event_espresso'), false, 0
66
-                ),
67
-                'DTT_is_primary'  => new EE_Boolean_Field(
68
-                    'DTT_is_primary', __('Flag indicating datetime is primary one for event', 'event_espresso'),
69
-                    false, false
70
-                ),
71
-                'DTT_order'       => new EE_Integer_Field(
72
-                    'DTT_order', __('The order in which the Datetime is displayed', 'event_espresso'), false, 0
73
-                ),
74
-                'DTT_parent'      => new EE_Integer_Field(
75
-                    'DTT_parent', __('Indicates what DTT_ID is the parent of this DTT_ID'), true, 0
76
-                ),
77
-                'DTT_deleted'     => new EE_Trashed_Flag_Field(
78
-                    'DTT_deleted', __('Flag indicating datetime is archived', 'event_espresso'), false, false
79
-                ),
80
-            ),
81
-        );
82
-        $this->_model_relations = array(
83
-            'Ticket'  => new EE_HABTM_Relation('Datetime_Ticket'),
84
-            'Event'   => new EE_Belongs_To_Relation(),
85
-            'Checkin' => new EE_Has_Many_Relation(),
86
-        );
87
-        $this->_model_chain_to_wp_user = 'Event';
88
-        //this model is generally available for reading
89
-        $this->_cap_restriction_generators[EEM_Base::caps_read] = new EE_Restriction_Generator_Event_Related_Public('Event');
90
-        $this->_cap_restriction_generators[EEM_Base::caps_read_admin] = new EE_Restriction_Generator_Event_Related_Protected('Event');
91
-        $this->_cap_restriction_generators[EEM_Base::caps_edit] = new EE_Restriction_Generator_Event_Related_Protected('Event');
92
-        $this->_cap_restriction_generators[EEM_Base::caps_delete] = new EE_Restriction_Generator_Event_Related_Protected('Event',
93
-            EEM_Base::caps_edit);
94
-        parent::__construct($timezone);
95
-    }
96
-
97
-
98
-
99
-    /**
100
-     * create new blank datetime
101
-     *
102
-     * @access public
103
-     * @return EE_Datetime[] array on success, FALSE on fail
104
-     * @throws \EE_Error
105
-     */
106
-    public function create_new_blank_datetime()
107
-    {
108
-        //makes sure timezone is always set.
109
-        $timezone_string = $this->get_timezone();
110
-        $blank_datetime = EE_Datetime::new_instance(
111
-            array(
112
-                'DTT_EVT_start' => $this->current_time_for_query('DTT_EVT_start', true) + MONTH_IN_SECONDS,
113
-                'DTT_EVT_end'   => $this->current_time_for_query('DTT_EVT_end', true) + MONTH_IN_SECONDS,
114
-                'DTT_order'     => 1,
115
-                'DTT_reg_limit' => EE_INF,
116
-            ),
117
-            $timezone_string
118
-        );
119
-        $blank_datetime->set_start_time($this->convert_datetime_for_query('DTT_EVT_start', '8am', 'ga',
120
-            $timezone_string));
121
-        $blank_datetime->set_end_time($this->convert_datetime_for_query('DTT_EVT_end', '5pm', 'ga', $timezone_string));
122
-        return array($blank_datetime);
123
-    }
124
-
125
-
126
-
127
-    /**
128
-     * get event start date from db
129
-     *
130
-     * @access public
131
-     * @param  int $EVT_ID
132
-     * @return EE_Datetime[] array on success, FALSE on fail
133
-     * @throws \EE_Error
134
-     */
135
-    public function get_all_event_dates($EVT_ID = 0)
136
-    {
137
-        if ( ! $EVT_ID) { // on add_new_event event_id gets set to 0
138
-            return $this->create_new_blank_datetime();
139
-        }
140
-        $results = $this->get_datetimes_for_event_ordered_by_DTT_order($EVT_ID);
141
-        if (empty($results)) {
142
-            return $this->create_new_blank_datetime();
143
-        }
144
-        return $results;
145
-    }
146
-
147
-
148
-
149
-    /**
150
-     * get all datetimes attached to an event ordered by the DTT_order field
151
-     *
152
-     * @public
153
-     * @param  int    $EVT_ID     event id
154
-     * @param boolean $include_expired
155
-     * @param boolean $include_deleted
156
-     * @param  int    $limit      If included then limit the count of results by
157
-     *                            the given number
158
-     * @return EE_Datetime[]
159
-     * @throws \EE_Error
160
-     */
161
-    public function get_datetimes_for_event_ordered_by_DTT_order(
162
-        $EVT_ID,
163
-        $include_expired = true,
164
-        $include_deleted = true,
165
-        $limit = null
166
-    ) {
167
-        //sanitize EVT_ID
168
-        $EVT_ID = absint($EVT_ID);
169
-        $old_assumption = $this->get_assumption_concerning_values_already_prepared_by_model_object();
170
-        $this->assume_values_already_prepared_by_model_object(EEM_Base::prepared_for_use_in_db);
171
-        $where_params = array('Event.EVT_ID' => $EVT_ID);
172
-        $query_params = ! empty($limit)
173
-            ? array(
174
-                $where_params,
175
-                'limit'                    => $limit,
176
-                'order_by'                 => array('DTT_order' => 'ASC'),
177
-                'default_where_conditions' => 'none',
178
-            )
179
-            : array(
180
-                $where_params,
181
-                'order_by'                 => array('DTT_order' => 'ASC'),
182
-                'default_where_conditions' => 'none',
183
-            );
184
-        if ( ! $include_expired) {
185
-            $query_params[0]['DTT_EVT_end'] = array('>=', current_time('mysql', true));
186
-        }
187
-        if ($include_deleted) {
188
-            $query_params[0]['DTT_deleted'] = array('IN', array(true, false));
189
-        }
190
-        /** @var EE_Datetime[] $result */
191
-        $result = $this->get_all($query_params);
192
-        $this->assume_values_already_prepared_by_model_object($old_assumption);
193
-        return $result;
194
-    }
195
-
196
-
197
-
198
-    /**
199
-     * Gets the datetimes for the event (with the given limit), and orders them by "importance". By importance, we mean
200
-     * that the primary datetimes are most important (DEPRECATED FOR NOW), and then the earlier datetimes are the most
201
-     * important. Maybe we'll want this to take into account datetimes that haven't already passed, but we don't yet.
202
-     *
203
-     * @param int $EVT_ID
204
-     * @param int $limit
205
-     * @return EE_Datetime[]|EE_Base_Class[]
206
-     * @throws \EE_Error
207
-     */
208
-    public function get_datetimes_for_event_ordered_by_importance($EVT_ID = 0, $limit = null)
209
-    {
210
-        return $this->get_all(
211
-            array(
212
-                array('Event.EVT_ID' => $EVT_ID),
213
-                'limit'                    => $limit,
214
-                'order_by'                 => array('DTT_EVT_start' => 'ASC'),
215
-                'default_where_conditions' => 'none',
216
-            )
217
-        );
218
-    }
219
-
220
-
221
-
222
-    /**
223
-     * @param int     $EVT_ID
224
-     * @param boolean $include_expired
225
-     * @param boolean $include_deleted
226
-     * @return EE_Datetime
227
-     * @throws \EE_Error
228
-     */
229
-    public function get_oldest_datetime_for_event($EVT_ID, $include_expired = false, $include_deleted = false)
230
-    {
231
-        $results = $this->get_datetimes_for_event_ordered_by_start_time($EVT_ID, $include_expired, $include_deleted, 1);
232
-        if ($results) {
233
-            return array_shift($results);
234
-        } else {
235
-            return null;
236
-        }
237
-    }
238
-
239
-
240
-
241
-    /**
242
-     * Gets the 'primary' datetime for an event.
243
-     *
244
-     * @param int  $EVT_ID
245
-     * @param bool $try_to_exclude_expired
246
-     * @param bool $try_to_exclude_deleted
247
-     * @return \EE_Datetime
248
-     * @throws \EE_Error
249
-     */
250
-    public function get_primary_datetime_for_event(
251
-        $EVT_ID,
252
-        $try_to_exclude_expired = true,
253
-        $try_to_exclude_deleted = true
254
-    ) {
255
-        if ($try_to_exclude_expired) {
256
-            $non_expired = $this->get_oldest_datetime_for_event($EVT_ID, false, false);
257
-            if ($non_expired) {
258
-                return $non_expired;
259
-            }
260
-        }
261
-        if ($try_to_exclude_deleted) {
262
-            $expired_even = $this->get_oldest_datetime_for_event($EVT_ID, true);
263
-            if ($expired_even) {
264
-                return $expired_even;
265
-            }
266
-        }
267
-        return $this->get_oldest_datetime_for_event($EVT_ID, true, true);
268
-    }
269
-
270
-
271
-
272
-    /**
273
-     * Gets ALL the datetimes for an event (including trashed ones, for now), ordered
274
-     * only by start date
275
-     *
276
-     * @param int     $EVT_ID
277
-     * @param boolean $include_expired
278
-     * @param boolean $include_deleted
279
-     * @param int     $limit
280
-     * @return EE_Datetime[]
281
-     * @throws \EE_Error
282
-     */
283
-    public function get_datetimes_for_event_ordered_by_start_time(
284
-        $EVT_ID,
285
-        $include_expired = true,
286
-        $include_deleted = true,
287
-        $limit = null
288
-    ) {
289
-        //sanitize EVT_ID
290
-        $EVT_ID = absint($EVT_ID);
291
-        $old_assumption = $this->get_assumption_concerning_values_already_prepared_by_model_object();
292
-        $this->assume_values_already_prepared_by_model_object(EEM_Base::prepared_for_use_in_db);
293
-        $query_params = array(array('Event.EVT_ID' => $EVT_ID), 'order_by' => array('DTT_EVT_start' => 'asc'));
294
-        if ( ! $include_expired) {
295
-            $query_params[0]['DTT_EVT_end'] = array('>=', current_time('mysql', true));
296
-        }
297
-        if ($include_deleted) {
298
-            $query_params[0]['DTT_deleted'] = array('IN', array(true, false));
299
-        }
300
-        if ($limit) {
301
-            $query_params['limit'] = $limit;
302
-        }
303
-        /** @var EE_Datetime[] $result */
304
-        $result = $this->get_all($query_params);
305
-        $this->assume_values_already_prepared_by_model_object($old_assumption);
306
-        return $result;
307
-    }
308
-
309
-
310
-
311
-    /**
312
-     * Gets ALL the datetimes for an ticket (including trashed ones, for now), ordered
313
-     * only by start date
314
-     *
315
-     * @param int     $TKT_ID
316
-     * @param boolean $include_expired
317
-     * @param boolean $include_deleted
318
-     * @param int     $limit
319
-     * @return EE_Datetime[]
320
-     * @throws \EE_Error
321
-     */
322
-    public function get_datetimes_for_ticket_ordered_by_start_time(
323
-        $TKT_ID,
324
-        $include_expired = true,
325
-        $include_deleted = true,
326
-        $limit = null
327
-    ) {
328
-        //sanitize TKT_ID
329
-        $TKT_ID = absint($TKT_ID);
330
-        $old_assumption = $this->get_assumption_concerning_values_already_prepared_by_model_object();
331
-        $this->assume_values_already_prepared_by_model_object(EEM_Base::prepared_for_use_in_db);
332
-        $query_params = array(array('Ticket.TKT_ID' => $TKT_ID), 'order_by' => array('DTT_EVT_start' => 'asc'));
333
-        if ( ! $include_expired) {
334
-            $query_params[0]['DTT_EVT_end'] = array('>=', current_time('mysql', true));
335
-        }
336
-        if ($include_deleted) {
337
-            $query_params[0]['DTT_deleted'] = array('IN', array(true, false));
338
-        }
339
-        if ($limit) {
340
-            $query_params['limit'] = $limit;
341
-        }
342
-        /** @var EE_Datetime[] $result */
343
-        $result = $this->get_all($query_params);
344
-        $this->assume_values_already_prepared_by_model_object($old_assumption);
345
-        return $result;
346
-    }
347
-
348
-
349
-
350
-    /**
351
-     * Gets all the datetimes for a ticket (including trashed ones, for now), ordered by the DTT_order for the
352
-     * datetimes.
353
-     *
354
-     * @param  int      $TKT_ID          ID of ticket to retrieve the datetimes for
355
-     * @param  boolean  $include_expired whether to include expired datetimes or not
356
-     * @param  boolean  $include_deleted whether to include trashed datetimes or not.
357
-     * @param  int|null $limit           if null, no limit, if int then limit results by
358
-     *                                   that number
359
-     * @return EE_Datetime[]
360
-     * @throws \EE_Error
361
-     */
362
-    public function get_datetimes_for_ticket_ordered_by_DTT_order(
363
-        $TKT_ID,
364
-        $include_expired = true,
365
-        $include_deleted = true,
366
-        $limit = null
367
-    ) {
368
-        //sanitize id.
369
-        $TKT_ID = absint($TKT_ID);
370
-        $old_assumption = $this->get_assumption_concerning_values_already_prepared_by_model_object();
371
-        $this->assume_values_already_prepared_by_model_object(EEM_Base::prepared_for_use_in_db);
372
-        $where_params = array('Ticket.TKT_ID' => $TKT_ID);
373
-        $query_params = array($where_params, 'order_by' => array('DTT_order' => 'ASC'));
374
-        if ( ! $include_expired) {
375
-            $query_params[0]['DTT_EVT_end'] = array('>=', current_time('mysql', true));
376
-        }
377
-        if ($include_deleted) {
378
-            $query_params[0]['DTT_deleted'] = array('IN', array(true, false));
379
-        }
380
-        if ($limit) {
381
-            $query_params['limit'] = $limit;
382
-        }
383
-        /** @var EE_Datetime[] $result */
384
-        $result = $this->get_all($query_params);
385
-        $this->assume_values_already_prepared_by_model_object($old_assumption);
386
-        return $result;
387
-    }
388
-
389
-
390
-
391
-    /**
392
-     * Gets the most important datetime for a particular event (ie, the primary event usually. But if for some WACK
393
-     * reason it doesn't exist, we consider the earliest event the most important)
394
-     *
395
-     * @param int $EVT_ID
396
-     * @return EE_Datetime
397
-     * @throws \EE_Error
398
-     */
399
-    public function get_most_important_datetime_for_event($EVT_ID)
400
-    {
401
-        $results = $this->get_datetimes_for_event_ordered_by_importance($EVT_ID, 1);
402
-        if ($results) {
403
-            return array_shift($results);
404
-        } else {
405
-            return null;
406
-        }
407
-    }
408
-
409
-
410
-
411
-    /**
412
-     * This returns a wpdb->results        Array of all DTT month and years matching the incoming query params and
413
-     * grouped by month and year.
414
-     *
415
-     * @param  array  $where_params      Array of query_params as described in the comments for EEM_Base::get_all()
416
-     * @param  string $evt_active_status A string representing the evt active status to filter the months by.
417
-     *                                   Can be:
418
-     *                                   - '' = no filter
419
-     *                                   - upcoming = Published events with at least one upcoming datetime.
420
-     *                                   - expired = Events with all datetimes expired.
421
-     *                                   - active = Events that are published and have at least one datetime that
422
-     *                                   starts before now and ends after now.
423
-     *                                   - inactive = Events that are either not published.
424
-     * @return EE_Base_Class[]
425
-     * @throws \EE_Error
426
-     */
427
-    public function get_dtt_months_and_years($where_params, $evt_active_status = '')
428
-    {
429
-        $current_time_for_DTT_EVT_start = $this->current_time_for_query('DTT_EVT_start');
430
-        $current_time_for_DTT_EVT_end = $this->current_time_for_query('DTT_EVT_end');
431
-        switch ($evt_active_status) {
432
-            case 'upcoming' :
433
-                $where_params['Event.status'] = 'publish';
434
-                //if there are already query_params matching DTT_EVT_start then we need to modify that to add them.
435
-                if (isset($where_params['DTT_EVT_start'])) {
436
-                    $where_params['DTT_EVT_start*****'] = $where_params['DTT_EVT_start'];
437
-                }
438
-                $where_params['DTT_EVT_start'] = array('>', $current_time_for_DTT_EVT_start);
439
-                break;
440
-            case 'expired' :
441
-                if (isset($where_params['Event.status'])) {
442
-                    unset($where_params['Event.status']);
443
-                }
444
-                //get events to exclude
445
-                $exclude_query[0] = array_merge($where_params,
446
-                    array('DTT_EVT_end' => array('>', $current_time_for_DTT_EVT_end)));
447
-                //first get all events that have datetimes where its not expired.
448
-                $event_ids = $this->_get_all_wpdb_results($exclude_query, OBJECT_K, 'Datetime.EVT_ID');
449
-                $event_ids = array_keys($event_ids);
450
-                if (isset($where_params['DTT_EVT_end'])) {
451
-                    $where_params['DTT_EVT_end****'] = $where_params['DTT_EVT_end'];
452
-                }
453
-                $where_params['DTT_EVT_end'] = array('<', $current_time_for_DTT_EVT_end);
454
-                $where_params['Event.EVT_ID'] = array('NOT IN', $event_ids);
455
-                break;
456
-            case 'active' :
457
-                $where_params['Event.status'] = 'publish';
458
-                if (isset($where_params['DTT_EVT_start'])) {
459
-                    $where_params['Datetime.DTT_EVT_start******'] = $where_params['DTT_EVT_start'];
460
-                }
461
-                if (isset($where_params['Datetime.DTT_EVT_end'])) {
462
-                    $where_params['Datetime.DTT_EVT_end*****'] = $where_params['DTT_EVT_end'];
463
-                }
464
-                $where_params['DTT_EVT_start'] = array('<', $current_time_for_DTT_EVT_start);
465
-                $where_params['DTT_EVT_end'] = array('>', $current_time_for_DTT_EVT_end);
466
-                break;
467
-            case 'inactive' :
468
-                if (isset($where_params['Event.status'])) {
469
-                    unset($where_params['Event.status']);
470
-                }
471
-                if (isset($where_params['OR'])) {
472
-                    $where_params['AND']['OR'] = $where_params['OR'];
473
-                }
474
-                if (isset($where_params['DTT_EVT_end'])) {
475
-                    $where_params['AND']['DTT_EVT_end****'] = $where_params['DTT_EVT_end'];
476
-                    unset($where_params['DTT_EVT_end']);
477
-                }
478
-                if (isset($where_params['DTT_EVT_start'])) {
479
-                    $where_params['AND']['DTT_EVT_start'] = $where_params['DTT_EVT_start'];
480
-                    unset($where_params['DTT_EVT_start']);
481
-                }
482
-                $where_params['AND']['Event.status'] = array('!=', 'publish');
483
-                break;
484
-        }
485
-        $query_params[0] = $where_params;
486
-        $query_params['group_by'] = array('dtt_year', 'dtt_month');
487
-        $query_params['order_by'] = array('DTT_EVT_start' => 'DESC');
488
-        $query_interval = EEH_DTT_Helper::get_sql_query_interval_for_offset($this->get_timezone(), 'DTT_EVT_start');
489
-        $columns_to_select = array(
490
-            'dtt_year'      => array('YEAR(' . $query_interval . ')', '%s'),
491
-            'dtt_month'     => array('MONTHNAME(' . $query_interval . ')', '%s'),
492
-            'dtt_month_num' => array('MONTH(' . $query_interval . ')', '%s'),
493
-        );
494
-        return $this->_get_all_wpdb_results($query_params, OBJECT, $columns_to_select);
495
-    }
496
-
497
-
498
-
499
-    /**
500
-     * Updates the DTT_sold attribute on each datetime (based on the registrations
501
-     * for the tickets for each datetime)
502
-     *
503
-     * @param EE_Datetime[] $datetimes
504
-     */
505
-    public function update_sold($datetimes)
506
-    {
507
-        foreach ($datetimes as $datetime) {
508
-            $datetime->update_sold();
509
-        }
510
-    }
511
-
512
-
513
-
514
-    /**
515
-     *    Gets the total number of tickets available at a particular datetime
516
-     *    (does NOT take into account the datetime's spaces available)
517
-     *
518
-     * @param int   $DTT_ID
519
-     * @param array $query_params
520
-     * @return int of tickets available. If sold out, return less than 1. If infinite, returns EE_INF,  IF there are NO
521
-     *             tickets attached to datetime then FALSE is returned.
522
-     */
523
-    public function sum_tickets_currently_available_at_datetime($DTT_ID, array $query_params = array())
524
-    {
525
-        $datetime = $this->get_one_by_ID($DTT_ID);
526
-        if ($datetime instanceof EE_Datetime) {
527
-            return $datetime->tickets_remaining($query_params);
528
-        }
529
-        return 0;
530
-    }
531
-
532
-
533
-
534
-    /**
535
-     * This returns an array of counts of datetimes in the database for each Datetime status that can be queried.
536
-     *
537
-     * @param  array $stati_to_include If included you can restrict the statuses we return counts for by including the
538
-     *                                 stati you want counts for as values in the array.  An empty array returns counts
539
-     *                                 for all valid stati.
540
-     * @param  array $query_params     If included can be used to refine the conditions for returning the count (i.e.
541
-     *                                 only for Datetimes connected to a specific event, or specific ticket.
542
-     * @return array  The value returned is an array indexed by Datetime Status and the values are the counts.  The
543
-     * @throws \EE_Error
544
-     *                                 stati used as index keys are: EE_Datetime::active EE_Datetime::upcoming EE_Datetime::expired
545
-     */
546
-    public function get_datetime_counts_by_status(array $stati_to_include = array(), array $query_params = array())
547
-    {
548
-        //only accept where conditions for this query.
549
-        $_where = isset($query_params[0]) ? $query_params[0] : array();
550
-        $status_query_args = array(
551
-            EE_Datetime::active   => array_merge(
552
-                $_where,
553
-                array('DTT_EVT_start' => array('<', time()), 'DTT_EVT_end' => array('>', time()))
554
-            ),
555
-            EE_Datetime::upcoming => array_merge(
556
-                $_where,
557
-                array('DTT_EVT_start' => array('>', time()))
558
-            ),
559
-            EE_Datetime::expired  => array_merge(
560
-                $_where,
561
-                array('DTT_EVT_end' => array('<', time()))
562
-            ),
563
-        );
564
-        if ( ! empty($stati_to_include)) {
565
-            foreach (array_keys($status_query_args) as $status) {
566
-                if ( ! in_array($status, $stati_to_include, true)) {
567
-                    unset($status_query_args[$status]);
568
-                }
569
-            }
570
-        }
571
-        //loop through and query counts for each stati.
572
-        $status_query_results = array();
573
-        foreach ($status_query_args as $status => $status_where_conditions) {
574
-            $status_query_results[$status] = EEM_Datetime::count(array($status_where_conditions), 'DTT_ID', true);
575
-        }
576
-        return $status_query_results;
577
-    }
578
-
579
-
580
-
581
-    /**
582
-     * Returns the specific count for a given Datetime status matching any given query_params.
583
-     *
584
-     * @param string $status Valid string representation for Datetime status requested. (Defaults to Active).
585
-     * @param array  $query_params
586
-     * @return int
587
-     * @throws \EE_Error
588
-     */
589
-    public function get_datetime_count_for_status($status = EE_Datetime::active, array $query_params = array())
590
-    {
591
-        $count = $this->get_datetime_counts_by_status(array($status), $query_params);
592
-        return ! empty($count[$status]) ? $count[$status] : 0;
593
-    }
14
+	/**
15
+	 * @var EEM_Datetime $_instance
16
+	 */
17
+	protected static $_instance;
18
+
19
+
20
+
21
+	/**
22
+	 *        private constructor to prevent direct creation
23
+	 *
24
+	 * @Constructor
25
+	 * @access private
26
+	 * @param string $timezone string representing the timezone we want to set for returned Date Time Strings (and any
27
+	 *                         incoming timezone data that gets saved).  Note this just sends the timezone info to the
28
+	 *                         date time model field objects.  Default is NULL (and will be assumed using the set
29
+	 *                         timezone in the 'timezone_string' wp option)
30
+	 * @throws \EE_Error
31
+	 */
32
+	protected function __construct($timezone)
33
+	{
34
+		$this->singular_item = __('Datetime', 'event_espresso');
35
+		$this->plural_item = __('Datetimes', 'event_espresso');
36
+		$this->_tables = array(
37
+			'Datetime' => new EE_Primary_Table('esp_datetime', 'DTT_ID'),
38
+		);
39
+		$this->_fields = array(
40
+			'Datetime' => array(
41
+				'DTT_ID'          => new EE_Primary_Key_Int_Field('DTT_ID', __('Datetime ID', 'event_espresso')),
42
+				'EVT_ID'          => new EE_Foreign_Key_Int_Field(
43
+					'EVT_ID', __('Event ID', 'event_espresso'), false, 0, 'Event'
44
+				),
45
+				'DTT_name'        => new EE_Plain_Text_Field(
46
+					'DTT_name', __('Datetime Name', 'event_espresso'), false, ''
47
+				),
48
+				'DTT_description' => new EE_Post_Content_Field(
49
+					'DTT_description', __('Description for Datetime', 'event_espresso'), false, ''
50
+				),
51
+				'DTT_EVT_start'   => new EE_Datetime_Field(
52
+					'DTT_EVT_start', __('Start time/date of Event', 'event_espresso'), false, EE_Datetime_Field::now,
53
+					$timezone
54
+				),
55
+				'DTT_EVT_end'     => new EE_Datetime_Field(
56
+					'DTT_EVT_end', __('End time/date of Event', 'event_espresso'), false, EE_Datetime_Field::now,
57
+					$timezone
58
+				),
59
+				'DTT_reg_limit'   => new EE_Infinite_Integer_Field(
60
+					'DTT_reg_limit', __('Registration Limit for this time', 'event_espresso'), true, EE_INF),
61
+				'DTT_sold'        => new EE_Integer_Field(
62
+					'DTT_sold', __('How many sales for this Datetime that have occurred', 'event_espresso'), true, 0
63
+				),
64
+				'DTT_reserved' => new EE_Integer_Field('DTT_reserved',
65
+					__('Quantity of tickets reserved, but not yet fully purchased', 'event_espresso'), false, 0
66
+				),
67
+				'DTT_is_primary'  => new EE_Boolean_Field(
68
+					'DTT_is_primary', __('Flag indicating datetime is primary one for event', 'event_espresso'),
69
+					false, false
70
+				),
71
+				'DTT_order'       => new EE_Integer_Field(
72
+					'DTT_order', __('The order in which the Datetime is displayed', 'event_espresso'), false, 0
73
+				),
74
+				'DTT_parent'      => new EE_Integer_Field(
75
+					'DTT_parent', __('Indicates what DTT_ID is the parent of this DTT_ID'), true, 0
76
+				),
77
+				'DTT_deleted'     => new EE_Trashed_Flag_Field(
78
+					'DTT_deleted', __('Flag indicating datetime is archived', 'event_espresso'), false, false
79
+				),
80
+			),
81
+		);
82
+		$this->_model_relations = array(
83
+			'Ticket'  => new EE_HABTM_Relation('Datetime_Ticket'),
84
+			'Event'   => new EE_Belongs_To_Relation(),
85
+			'Checkin' => new EE_Has_Many_Relation(),
86
+		);
87
+		$this->_model_chain_to_wp_user = 'Event';
88
+		//this model is generally available for reading
89
+		$this->_cap_restriction_generators[EEM_Base::caps_read] = new EE_Restriction_Generator_Event_Related_Public('Event');
90
+		$this->_cap_restriction_generators[EEM_Base::caps_read_admin] = new EE_Restriction_Generator_Event_Related_Protected('Event');
91
+		$this->_cap_restriction_generators[EEM_Base::caps_edit] = new EE_Restriction_Generator_Event_Related_Protected('Event');
92
+		$this->_cap_restriction_generators[EEM_Base::caps_delete] = new EE_Restriction_Generator_Event_Related_Protected('Event',
93
+			EEM_Base::caps_edit);
94
+		parent::__construct($timezone);
95
+	}
96
+
97
+
98
+
99
+	/**
100
+	 * create new blank datetime
101
+	 *
102
+	 * @access public
103
+	 * @return EE_Datetime[] array on success, FALSE on fail
104
+	 * @throws \EE_Error
105
+	 */
106
+	public function create_new_blank_datetime()
107
+	{
108
+		//makes sure timezone is always set.
109
+		$timezone_string = $this->get_timezone();
110
+		$blank_datetime = EE_Datetime::new_instance(
111
+			array(
112
+				'DTT_EVT_start' => $this->current_time_for_query('DTT_EVT_start', true) + MONTH_IN_SECONDS,
113
+				'DTT_EVT_end'   => $this->current_time_for_query('DTT_EVT_end', true) + MONTH_IN_SECONDS,
114
+				'DTT_order'     => 1,
115
+				'DTT_reg_limit' => EE_INF,
116
+			),
117
+			$timezone_string
118
+		);
119
+		$blank_datetime->set_start_time($this->convert_datetime_for_query('DTT_EVT_start', '8am', 'ga',
120
+			$timezone_string));
121
+		$blank_datetime->set_end_time($this->convert_datetime_for_query('DTT_EVT_end', '5pm', 'ga', $timezone_string));
122
+		return array($blank_datetime);
123
+	}
124
+
125
+
126
+
127
+	/**
128
+	 * get event start date from db
129
+	 *
130
+	 * @access public
131
+	 * @param  int $EVT_ID
132
+	 * @return EE_Datetime[] array on success, FALSE on fail
133
+	 * @throws \EE_Error
134
+	 */
135
+	public function get_all_event_dates($EVT_ID = 0)
136
+	{
137
+		if ( ! $EVT_ID) { // on add_new_event event_id gets set to 0
138
+			return $this->create_new_blank_datetime();
139
+		}
140
+		$results = $this->get_datetimes_for_event_ordered_by_DTT_order($EVT_ID);
141
+		if (empty($results)) {
142
+			return $this->create_new_blank_datetime();
143
+		}
144
+		return $results;
145
+	}
146
+
147
+
148
+
149
+	/**
150
+	 * get all datetimes attached to an event ordered by the DTT_order field
151
+	 *
152
+	 * @public
153
+	 * @param  int    $EVT_ID     event id
154
+	 * @param boolean $include_expired
155
+	 * @param boolean $include_deleted
156
+	 * @param  int    $limit      If included then limit the count of results by
157
+	 *                            the given number
158
+	 * @return EE_Datetime[]
159
+	 * @throws \EE_Error
160
+	 */
161
+	public function get_datetimes_for_event_ordered_by_DTT_order(
162
+		$EVT_ID,
163
+		$include_expired = true,
164
+		$include_deleted = true,
165
+		$limit = null
166
+	) {
167
+		//sanitize EVT_ID
168
+		$EVT_ID = absint($EVT_ID);
169
+		$old_assumption = $this->get_assumption_concerning_values_already_prepared_by_model_object();
170
+		$this->assume_values_already_prepared_by_model_object(EEM_Base::prepared_for_use_in_db);
171
+		$where_params = array('Event.EVT_ID' => $EVT_ID);
172
+		$query_params = ! empty($limit)
173
+			? array(
174
+				$where_params,
175
+				'limit'                    => $limit,
176
+				'order_by'                 => array('DTT_order' => 'ASC'),
177
+				'default_where_conditions' => 'none',
178
+			)
179
+			: array(
180
+				$where_params,
181
+				'order_by'                 => array('DTT_order' => 'ASC'),
182
+				'default_where_conditions' => 'none',
183
+			);
184
+		if ( ! $include_expired) {
185
+			$query_params[0]['DTT_EVT_end'] = array('>=', current_time('mysql', true));
186
+		}
187
+		if ($include_deleted) {
188
+			$query_params[0]['DTT_deleted'] = array('IN', array(true, false));
189
+		}
190
+		/** @var EE_Datetime[] $result */
191
+		$result = $this->get_all($query_params);
192
+		$this->assume_values_already_prepared_by_model_object($old_assumption);
193
+		return $result;
194
+	}
195
+
196
+
197
+
198
+	/**
199
+	 * Gets the datetimes for the event (with the given limit), and orders them by "importance". By importance, we mean
200
+	 * that the primary datetimes are most important (DEPRECATED FOR NOW), and then the earlier datetimes are the most
201
+	 * important. Maybe we'll want this to take into account datetimes that haven't already passed, but we don't yet.
202
+	 *
203
+	 * @param int $EVT_ID
204
+	 * @param int $limit
205
+	 * @return EE_Datetime[]|EE_Base_Class[]
206
+	 * @throws \EE_Error
207
+	 */
208
+	public function get_datetimes_for_event_ordered_by_importance($EVT_ID = 0, $limit = null)
209
+	{
210
+		return $this->get_all(
211
+			array(
212
+				array('Event.EVT_ID' => $EVT_ID),
213
+				'limit'                    => $limit,
214
+				'order_by'                 => array('DTT_EVT_start' => 'ASC'),
215
+				'default_where_conditions' => 'none',
216
+			)
217
+		);
218
+	}
219
+
220
+
221
+
222
+	/**
223
+	 * @param int     $EVT_ID
224
+	 * @param boolean $include_expired
225
+	 * @param boolean $include_deleted
226
+	 * @return EE_Datetime
227
+	 * @throws \EE_Error
228
+	 */
229
+	public function get_oldest_datetime_for_event($EVT_ID, $include_expired = false, $include_deleted = false)
230
+	{
231
+		$results = $this->get_datetimes_for_event_ordered_by_start_time($EVT_ID, $include_expired, $include_deleted, 1);
232
+		if ($results) {
233
+			return array_shift($results);
234
+		} else {
235
+			return null;
236
+		}
237
+	}
238
+
239
+
240
+
241
+	/**
242
+	 * Gets the 'primary' datetime for an event.
243
+	 *
244
+	 * @param int  $EVT_ID
245
+	 * @param bool $try_to_exclude_expired
246
+	 * @param bool $try_to_exclude_deleted
247
+	 * @return \EE_Datetime
248
+	 * @throws \EE_Error
249
+	 */
250
+	public function get_primary_datetime_for_event(
251
+		$EVT_ID,
252
+		$try_to_exclude_expired = true,
253
+		$try_to_exclude_deleted = true
254
+	) {
255
+		if ($try_to_exclude_expired) {
256
+			$non_expired = $this->get_oldest_datetime_for_event($EVT_ID, false, false);
257
+			if ($non_expired) {
258
+				return $non_expired;
259
+			}
260
+		}
261
+		if ($try_to_exclude_deleted) {
262
+			$expired_even = $this->get_oldest_datetime_for_event($EVT_ID, true);
263
+			if ($expired_even) {
264
+				return $expired_even;
265
+			}
266
+		}
267
+		return $this->get_oldest_datetime_for_event($EVT_ID, true, true);
268
+	}
269
+
270
+
271
+
272
+	/**
273
+	 * Gets ALL the datetimes for an event (including trashed ones, for now), ordered
274
+	 * only by start date
275
+	 *
276
+	 * @param int     $EVT_ID
277
+	 * @param boolean $include_expired
278
+	 * @param boolean $include_deleted
279
+	 * @param int     $limit
280
+	 * @return EE_Datetime[]
281
+	 * @throws \EE_Error
282
+	 */
283
+	public function get_datetimes_for_event_ordered_by_start_time(
284
+		$EVT_ID,
285
+		$include_expired = true,
286
+		$include_deleted = true,
287
+		$limit = null
288
+	) {
289
+		//sanitize EVT_ID
290
+		$EVT_ID = absint($EVT_ID);
291
+		$old_assumption = $this->get_assumption_concerning_values_already_prepared_by_model_object();
292
+		$this->assume_values_already_prepared_by_model_object(EEM_Base::prepared_for_use_in_db);
293
+		$query_params = array(array('Event.EVT_ID' => $EVT_ID), 'order_by' => array('DTT_EVT_start' => 'asc'));
294
+		if ( ! $include_expired) {
295
+			$query_params[0]['DTT_EVT_end'] = array('>=', current_time('mysql', true));
296
+		}
297
+		if ($include_deleted) {
298
+			$query_params[0]['DTT_deleted'] = array('IN', array(true, false));
299
+		}
300
+		if ($limit) {
301
+			$query_params['limit'] = $limit;
302
+		}
303
+		/** @var EE_Datetime[] $result */
304
+		$result = $this->get_all($query_params);
305
+		$this->assume_values_already_prepared_by_model_object($old_assumption);
306
+		return $result;
307
+	}
308
+
309
+
310
+
311
+	/**
312
+	 * Gets ALL the datetimes for an ticket (including trashed ones, for now), ordered
313
+	 * only by start date
314
+	 *
315
+	 * @param int     $TKT_ID
316
+	 * @param boolean $include_expired
317
+	 * @param boolean $include_deleted
318
+	 * @param int     $limit
319
+	 * @return EE_Datetime[]
320
+	 * @throws \EE_Error
321
+	 */
322
+	public function get_datetimes_for_ticket_ordered_by_start_time(
323
+		$TKT_ID,
324
+		$include_expired = true,
325
+		$include_deleted = true,
326
+		$limit = null
327
+	) {
328
+		//sanitize TKT_ID
329
+		$TKT_ID = absint($TKT_ID);
330
+		$old_assumption = $this->get_assumption_concerning_values_already_prepared_by_model_object();
331
+		$this->assume_values_already_prepared_by_model_object(EEM_Base::prepared_for_use_in_db);
332
+		$query_params = array(array('Ticket.TKT_ID' => $TKT_ID), 'order_by' => array('DTT_EVT_start' => 'asc'));
333
+		if ( ! $include_expired) {
334
+			$query_params[0]['DTT_EVT_end'] = array('>=', current_time('mysql', true));
335
+		}
336
+		if ($include_deleted) {
337
+			$query_params[0]['DTT_deleted'] = array('IN', array(true, false));
338
+		}
339
+		if ($limit) {
340
+			$query_params['limit'] = $limit;
341
+		}
342
+		/** @var EE_Datetime[] $result */
343
+		$result = $this->get_all($query_params);
344
+		$this->assume_values_already_prepared_by_model_object($old_assumption);
345
+		return $result;
346
+	}
347
+
348
+
349
+
350
+	/**
351
+	 * Gets all the datetimes for a ticket (including trashed ones, for now), ordered by the DTT_order for the
352
+	 * datetimes.
353
+	 *
354
+	 * @param  int      $TKT_ID          ID of ticket to retrieve the datetimes for
355
+	 * @param  boolean  $include_expired whether to include expired datetimes or not
356
+	 * @param  boolean  $include_deleted whether to include trashed datetimes or not.
357
+	 * @param  int|null $limit           if null, no limit, if int then limit results by
358
+	 *                                   that number
359
+	 * @return EE_Datetime[]
360
+	 * @throws \EE_Error
361
+	 */
362
+	public function get_datetimes_for_ticket_ordered_by_DTT_order(
363
+		$TKT_ID,
364
+		$include_expired = true,
365
+		$include_deleted = true,
366
+		$limit = null
367
+	) {
368
+		//sanitize id.
369
+		$TKT_ID = absint($TKT_ID);
370
+		$old_assumption = $this->get_assumption_concerning_values_already_prepared_by_model_object();
371
+		$this->assume_values_already_prepared_by_model_object(EEM_Base::prepared_for_use_in_db);
372
+		$where_params = array('Ticket.TKT_ID' => $TKT_ID);
373
+		$query_params = array($where_params, 'order_by' => array('DTT_order' => 'ASC'));
374
+		if ( ! $include_expired) {
375
+			$query_params[0]['DTT_EVT_end'] = array('>=', current_time('mysql', true));
376
+		}
377
+		if ($include_deleted) {
378
+			$query_params[0]['DTT_deleted'] = array('IN', array(true, false));
379
+		}
380
+		if ($limit) {
381
+			$query_params['limit'] = $limit;
382
+		}
383
+		/** @var EE_Datetime[] $result */
384
+		$result = $this->get_all($query_params);
385
+		$this->assume_values_already_prepared_by_model_object($old_assumption);
386
+		return $result;
387
+	}
388
+
389
+
390
+
391
+	/**
392
+	 * Gets the most important datetime for a particular event (ie, the primary event usually. But if for some WACK
393
+	 * reason it doesn't exist, we consider the earliest event the most important)
394
+	 *
395
+	 * @param int $EVT_ID
396
+	 * @return EE_Datetime
397
+	 * @throws \EE_Error
398
+	 */
399
+	public function get_most_important_datetime_for_event($EVT_ID)
400
+	{
401
+		$results = $this->get_datetimes_for_event_ordered_by_importance($EVT_ID, 1);
402
+		if ($results) {
403
+			return array_shift($results);
404
+		} else {
405
+			return null;
406
+		}
407
+	}
408
+
409
+
410
+
411
+	/**
412
+	 * This returns a wpdb->results        Array of all DTT month and years matching the incoming query params and
413
+	 * grouped by month and year.
414
+	 *
415
+	 * @param  array  $where_params      Array of query_params as described in the comments for EEM_Base::get_all()
416
+	 * @param  string $evt_active_status A string representing the evt active status to filter the months by.
417
+	 *                                   Can be:
418
+	 *                                   - '' = no filter
419
+	 *                                   - upcoming = Published events with at least one upcoming datetime.
420
+	 *                                   - expired = Events with all datetimes expired.
421
+	 *                                   - active = Events that are published and have at least one datetime that
422
+	 *                                   starts before now and ends after now.
423
+	 *                                   - inactive = Events that are either not published.
424
+	 * @return EE_Base_Class[]
425
+	 * @throws \EE_Error
426
+	 */
427
+	public function get_dtt_months_and_years($where_params, $evt_active_status = '')
428
+	{
429
+		$current_time_for_DTT_EVT_start = $this->current_time_for_query('DTT_EVT_start');
430
+		$current_time_for_DTT_EVT_end = $this->current_time_for_query('DTT_EVT_end');
431
+		switch ($evt_active_status) {
432
+			case 'upcoming' :
433
+				$where_params['Event.status'] = 'publish';
434
+				//if there are already query_params matching DTT_EVT_start then we need to modify that to add them.
435
+				if (isset($where_params['DTT_EVT_start'])) {
436
+					$where_params['DTT_EVT_start*****'] = $where_params['DTT_EVT_start'];
437
+				}
438
+				$where_params['DTT_EVT_start'] = array('>', $current_time_for_DTT_EVT_start);
439
+				break;
440
+			case 'expired' :
441
+				if (isset($where_params['Event.status'])) {
442
+					unset($where_params['Event.status']);
443
+				}
444
+				//get events to exclude
445
+				$exclude_query[0] = array_merge($where_params,
446
+					array('DTT_EVT_end' => array('>', $current_time_for_DTT_EVT_end)));
447
+				//first get all events that have datetimes where its not expired.
448
+				$event_ids = $this->_get_all_wpdb_results($exclude_query, OBJECT_K, 'Datetime.EVT_ID');
449
+				$event_ids = array_keys($event_ids);
450
+				if (isset($where_params['DTT_EVT_end'])) {
451
+					$where_params['DTT_EVT_end****'] = $where_params['DTT_EVT_end'];
452
+				}
453
+				$where_params['DTT_EVT_end'] = array('<', $current_time_for_DTT_EVT_end);
454
+				$where_params['Event.EVT_ID'] = array('NOT IN', $event_ids);
455
+				break;
456
+			case 'active' :
457
+				$where_params['Event.status'] = 'publish';
458
+				if (isset($where_params['DTT_EVT_start'])) {
459
+					$where_params['Datetime.DTT_EVT_start******'] = $where_params['DTT_EVT_start'];
460
+				}
461
+				if (isset($where_params['Datetime.DTT_EVT_end'])) {
462
+					$where_params['Datetime.DTT_EVT_end*****'] = $where_params['DTT_EVT_end'];
463
+				}
464
+				$where_params['DTT_EVT_start'] = array('<', $current_time_for_DTT_EVT_start);
465
+				$where_params['DTT_EVT_end'] = array('>', $current_time_for_DTT_EVT_end);
466
+				break;
467
+			case 'inactive' :
468
+				if (isset($where_params['Event.status'])) {
469
+					unset($where_params['Event.status']);
470
+				}
471
+				if (isset($where_params['OR'])) {
472
+					$where_params['AND']['OR'] = $where_params['OR'];
473
+				}
474
+				if (isset($where_params['DTT_EVT_end'])) {
475
+					$where_params['AND']['DTT_EVT_end****'] = $where_params['DTT_EVT_end'];
476
+					unset($where_params['DTT_EVT_end']);
477
+				}
478
+				if (isset($where_params['DTT_EVT_start'])) {
479
+					$where_params['AND']['DTT_EVT_start'] = $where_params['DTT_EVT_start'];
480
+					unset($where_params['DTT_EVT_start']);
481
+				}
482
+				$where_params['AND']['Event.status'] = array('!=', 'publish');
483
+				break;
484
+		}
485
+		$query_params[0] = $where_params;
486
+		$query_params['group_by'] = array('dtt_year', 'dtt_month');
487
+		$query_params['order_by'] = array('DTT_EVT_start' => 'DESC');
488
+		$query_interval = EEH_DTT_Helper::get_sql_query_interval_for_offset($this->get_timezone(), 'DTT_EVT_start');
489
+		$columns_to_select = array(
490
+			'dtt_year'      => array('YEAR(' . $query_interval . ')', '%s'),
491
+			'dtt_month'     => array('MONTHNAME(' . $query_interval . ')', '%s'),
492
+			'dtt_month_num' => array('MONTH(' . $query_interval . ')', '%s'),
493
+		);
494
+		return $this->_get_all_wpdb_results($query_params, OBJECT, $columns_to_select);
495
+	}
496
+
497
+
498
+
499
+	/**
500
+	 * Updates the DTT_sold attribute on each datetime (based on the registrations
501
+	 * for the tickets for each datetime)
502
+	 *
503
+	 * @param EE_Datetime[] $datetimes
504
+	 */
505
+	public function update_sold($datetimes)
506
+	{
507
+		foreach ($datetimes as $datetime) {
508
+			$datetime->update_sold();
509
+		}
510
+	}
511
+
512
+
513
+
514
+	/**
515
+	 *    Gets the total number of tickets available at a particular datetime
516
+	 *    (does NOT take into account the datetime's spaces available)
517
+	 *
518
+	 * @param int   $DTT_ID
519
+	 * @param array $query_params
520
+	 * @return int of tickets available. If sold out, return less than 1. If infinite, returns EE_INF,  IF there are NO
521
+	 *             tickets attached to datetime then FALSE is returned.
522
+	 */
523
+	public function sum_tickets_currently_available_at_datetime($DTT_ID, array $query_params = array())
524
+	{
525
+		$datetime = $this->get_one_by_ID($DTT_ID);
526
+		if ($datetime instanceof EE_Datetime) {
527
+			return $datetime->tickets_remaining($query_params);
528
+		}
529
+		return 0;
530
+	}
531
+
532
+
533
+
534
+	/**
535
+	 * This returns an array of counts of datetimes in the database for each Datetime status that can be queried.
536
+	 *
537
+	 * @param  array $stati_to_include If included you can restrict the statuses we return counts for by including the
538
+	 *                                 stati you want counts for as values in the array.  An empty array returns counts
539
+	 *                                 for all valid stati.
540
+	 * @param  array $query_params     If included can be used to refine the conditions for returning the count (i.e.
541
+	 *                                 only for Datetimes connected to a specific event, or specific ticket.
542
+	 * @return array  The value returned is an array indexed by Datetime Status and the values are the counts.  The
543
+	 * @throws \EE_Error
544
+	 *                                 stati used as index keys are: EE_Datetime::active EE_Datetime::upcoming EE_Datetime::expired
545
+	 */
546
+	public function get_datetime_counts_by_status(array $stati_to_include = array(), array $query_params = array())
547
+	{
548
+		//only accept where conditions for this query.
549
+		$_where = isset($query_params[0]) ? $query_params[0] : array();
550
+		$status_query_args = array(
551
+			EE_Datetime::active   => array_merge(
552
+				$_where,
553
+				array('DTT_EVT_start' => array('<', time()), 'DTT_EVT_end' => array('>', time()))
554
+			),
555
+			EE_Datetime::upcoming => array_merge(
556
+				$_where,
557
+				array('DTT_EVT_start' => array('>', time()))
558
+			),
559
+			EE_Datetime::expired  => array_merge(
560
+				$_where,
561
+				array('DTT_EVT_end' => array('<', time()))
562
+			),
563
+		);
564
+		if ( ! empty($stati_to_include)) {
565
+			foreach (array_keys($status_query_args) as $status) {
566
+				if ( ! in_array($status, $stati_to_include, true)) {
567
+					unset($status_query_args[$status]);
568
+				}
569
+			}
570
+		}
571
+		//loop through and query counts for each stati.
572
+		$status_query_results = array();
573
+		foreach ($status_query_args as $status => $status_where_conditions) {
574
+			$status_query_results[$status] = EEM_Datetime::count(array($status_where_conditions), 'DTT_ID', true);
575
+		}
576
+		return $status_query_results;
577
+	}
578
+
579
+
580
+
581
+	/**
582
+	 * Returns the specific count for a given Datetime status matching any given query_params.
583
+	 *
584
+	 * @param string $status Valid string representation for Datetime status requested. (Defaults to Active).
585
+	 * @param array  $query_params
586
+	 * @return int
587
+	 * @throws \EE_Error
588
+	 */
589
+	public function get_datetime_count_for_status($status = EE_Datetime::active, array $query_params = array())
590
+	{
591
+		$count = $this->get_datetime_counts_by_status(array($status), $query_params);
592
+		return ! empty($count[$status]) ? $count[$status] : 0;
593
+	}
594 594
 
595 595
 
596 596
 
Please login to merge, or discard this patch.
core/db_models/relations/EE_Model_Relation_Base.php 1 patch
Indentation   +477 added lines, -477 removed lines patch added patch discarded remove patch
@@ -17,482 +17,482 @@
 block discarded – undo
17 17
  */
18 18
 abstract class EE_Model_Relation_Base implements HasSchemaInterface
19 19
 {
20
-    /**
21
-     * The model name of which this relation is a component (ie, the model that called new EE_Model_Relation_Base)
22
-     *
23
-     * @var string eg Event, Question_Group, Registration
24
-     */
25
-    private $_this_model_name;
26
-    /**
27
-     * The model name pointed to by this relation (ie, the model we want to establish a relationship to)
28
-     *
29
-     * @var string eg Event, Question_Group, Registration
30
-     */
31
-    private $_other_model_name;
32
-
33
-    /**
34
-     * this is typically used when calling the relation models to make sure they inherit any set timezone from the
35
-     * initiating model.
36
-     *
37
-     * @var string
38
-     */
39
-    protected $_timezone;
40
-
41
-    /**
42
-     * If you try to delete "this_model", and there are related "other_models",
43
-     * and this isn't null, then abandon the deletion and add this warning.
44
-     * This effectively makes it impossible to delete "this_model" while there are
45
-     * related "other_models" along this relation.
46
-     *
47
-     * @var string (internationalized)
48
-     */
49
-    protected $_blocking_delete_error_message;
50
-
51
-    protected $_blocking_delete = false;
52
-
53
-    /**
54
-     * Object representing the relationship between two models. This knows how to join the models,
55
-     * get related models across the relation, and add-and-remove the relationships.
56
-     *
57
-     * @param boolean $block_deletes                 if there are related models across this relation, block (prevent
58
-     *                                               and add an error) the deletion of this model
59
-     * @param string  $blocking_delete_error_message a customized error message on blocking deletes instead of the
60
-     *                                               default
61
-     */
62
-    public function __construct($block_deletes, $blocking_delete_error_message)
63
-    {
64
-        $this->_blocking_delete               = $block_deletes;
65
-        $this->_blocking_delete_error_message = $blocking_delete_error_message;
66
-    }
67
-
68
-
69
-    /**
70
-     * @param $this_model_name
71
-     * @param $other_model_name
72
-     * @throws EE_Error
73
-     */
74
-    public function _construct_finalize_set_models($this_model_name, $other_model_name)
75
-    {
76
-        $this->_this_model_name  = $this_model_name;
77
-        $this->_other_model_name = $other_model_name;
78
-        if (is_string($this->_blocking_delete)) {
79
-            throw new EE_Error(sprintf(__("When instantiating the relation of type %s from %s to %s, the \$block_deletes argument should be a boolean, not a string (%s)",
80
-                "event_espresso"),
81
-                get_class($this), $this_model_name, $other_model_name, $this->_blocking_delete));
82
-        }
83
-    }
84
-
85
-
86
-    /**
87
-     * Gets the model where this relation is defined.
88
-     *
89
-     * @return EEM_Base
90
-     */
91
-    public function get_this_model()
92
-    {
93
-        return $this->_get_model($this->_this_model_name);
94
-    }
95
-
96
-
97
-    /**
98
-     * Gets the model which this relation establishes the relation TO (ie,
99
-     * this relation object was defined on get_this_model(), get_other_model() is the other one)
100
-     *
101
-     * @return EEM_Base
102
-     */
103
-    public function get_other_model()
104
-    {
105
-        return $this->_get_model($this->_other_model_name);
106
-    }
107
-
108
-
109
-    /**
110
-     * Internally used by get_this_model() and get_other_model()
111
-     *
112
-     * @param string $model_name like Event, Question_Group, etc. omit the EEM_
113
-     * @return EEM_Base
114
-     */
115
-    protected function _get_model($model_name)
116
-    {
117
-        $modelInstance = EE_Registry::instance()->load_model($model_name);
118
-        $modelInstance->set_timezone($this->_timezone);
119
-        return $modelInstance;
120
-    }
121
-
122
-
123
-    /**
124
-     * entirely possible that relations may be called from a model and we need to make sure those relations have their
125
-     * timezone set correctly.
126
-     *
127
-     * @param string $timezone timezone to set.
128
-     */
129
-    public function set_timezone($timezone)
130
-    {
131
-        if ($timezone !== null) {
132
-            $this->_timezone = $timezone;
133
-        }
134
-    }
135
-
136
-
137
-    /**
138
-     * @param        $other_table
139
-     * @param        $other_table_alias
140
-     * @param        $other_table_column
141
-     * @param        $this_table_alias
142
-     * @param        $this_table_join_column
143
-     * @param string $extra_join_sql
144
-     * @return string
145
-     */
146
-    protected function _left_join(
147
-        $other_table,
148
-        $other_table_alias,
149
-        $other_table_column,
150
-        $this_table_alias,
151
-        $this_table_join_column,
152
-        $extra_join_sql = ''
153
-    ) {
154
-        return " LEFT JOIN " . $other_table . " AS " . $other_table_alias . " ON " . $other_table_alias . "." . $other_table_column . "=" . $this_table_alias . "." . $this_table_join_column . ($extra_join_sql ? " AND $extra_join_sql" : '');
155
-    }
156
-
157
-
158
-    /**
159
-     * Gets all the model objects of type of other model related to $model_object,
160
-     * according to this relation. This is the same code for EE_HABTM_Relation and EE_Has_Many_Relation.
161
-     * For both of those child classes, $model_object must be saved so that it has an ID before querying,
162
-     * otherwise an error will be thrown. Note: by default we disable default_where_conditions
163
-     * EE_Belongs_To_Relation doesn't need to be saved before querying.
164
-     *
165
-     * @param EE_Base_Class|int $model_object_or_id                      or the primary key of this model
166
-     * @param array             $query_params                            like EEM_Base::get_all's $query_params
167
-     * @param boolean           $values_already_prepared_by_model_object @deprecated since 4.8.1
168
-     * @return EE_Base_Class[]
169
-     * @throws \EE_Error
170
-     */
171
-    public function get_all_related(
172
-        $model_object_or_id,
173
-        $query_params = array(),
174
-        $values_already_prepared_by_model_object = false
175
-    ) {
176
-        if ($values_already_prepared_by_model_object !== false) {
177
-            EE_Error::doing_it_wrong('EE_Model_Relation_Base::get_all_related',
178
-                __('The argument $values_already_prepared_by_model_object is no longer used.', 'event_espresso'),
179
-                '4.8.1');
180
-        }
181
-        $query_params                                      = $this->_disable_default_where_conditions_on_query_param($query_params);
182
-        $query_param_where_this_model_pk                   = $this->get_this_model()->get_this_model_name()
183
-                                                             . "."
184
-                                                             . $this->get_this_model()->get_primary_key_field()->get_name();
185
-        $model_object_id                                   = $this->_get_model_object_id($model_object_or_id);
186
-        $query_params[0][$query_param_where_this_model_pk] = $model_object_id;
187
-        return $this->get_other_model()->get_all($query_params);
188
-    }
189
-
190
-
191
-    /**
192
-     * Alters the $query_params to disable default where conditions, unless otherwise specified
193
-     *
194
-     * @param string $query_params
195
-     * @return array
196
-     */
197
-    protected function _disable_default_where_conditions_on_query_param($query_params)
198
-    {
199
-        if (! isset($query_params['default_where_conditions'])) {
200
-            $query_params['default_where_conditions'] = 'none';
201
-        }
202
-        return $query_params;
203
-    }
204
-
205
-
206
-    /**
207
-     * Deletes the related model objects which meet the query parameters. If no
208
-     * parameters are specified, then all related model objects will be deleted.
209
-     * Note: If the related model is extends EEM_Soft_Delete_Base, then the related
210
-     * model objects will only be soft-deleted.
211
-     *
212
-     * @param EE_Base_Class|int|string $model_object_or_id
213
-     * @param array                    $query_params
214
-     * @return int of how many related models got deleted
215
-     * @throws \EE_Error
216
-     */
217
-    public function delete_all_related($model_object_or_id, $query_params = array())
218
-    {
219
-        //for each thing we would delete,
220
-        $related_model_objects = $this->get_all_related($model_object_or_id, $query_params);
221
-        //determine if it's blocked by anything else before it can be deleted
222
-        $deleted_count = 0;
223
-        foreach ($related_model_objects as $related_model_object) {
224
-            $delete_is_blocked = $this->get_other_model()->delete_is_blocked_by_related_models($related_model_object,
225
-                $model_object_or_id);
226
-            /* @var $model_object_or_id EE_Base_Class */
227
-            if (! $delete_is_blocked) {
228
-                $this->remove_relation_to($model_object_or_id, $related_model_object);
229
-                $related_model_object->delete();
230
-                $deleted_count++;
231
-            }
232
-        }
233
-        return $deleted_count;
234
-    }
235
-
236
-
237
-    /**
238
-     * Deletes the related model objects which meet the query parameters. If no
239
-     * parameters are specified, then all related model objects will be deleted.
240
-     * Note: If the related model is extends EEM_Soft_Delete_Base, then the related
241
-     * model objects will only be soft-deleted.
242
-     *
243
-     * @param EE_Base_Class|int|string $model_object_or_id
244
-     * @param array                    $query_params
245
-     * @return int of how many related models got deleted
246
-     * @throws \EE_Error
247
-     */
248
-    public function delete_related_permanently($model_object_or_id, $query_params = array())
249
-    {
250
-        //for each thing we would delete,
251
-        $related_model_objects = $this->get_all_related($model_object_or_id, $query_params);
252
-        //determine if it's blocked by anything else before it can be deleted
253
-        $deleted_count = 0;
254
-        foreach ($related_model_objects as $related_model_object) {
255
-            $delete_is_blocked = $this->get_other_model()->delete_is_blocked_by_related_models($related_model_object,
256
-                $model_object_or_id);
257
-            /* @var $model_object_or_id EE_Base_Class */
258
-            if ($related_model_object instanceof EE_Soft_Delete_Base_Class) {
259
-                $this->remove_relation_to($model_object_or_id, $related_model_object);
260
-                $deleted_count++;
261
-                if (! $delete_is_blocked) {
262
-                    $related_model_object->delete_permanently();
263
-                } else {
264
-                    //delete is blocked
265
-                    //brent and darren, in this case, wanted to just soft delete it then
266
-                    $related_model_object->delete();
267
-                }
268
-            } else {
269
-                //its not a soft-deletable thing anyways. do the normal logic.
270
-                if (! $delete_is_blocked) {
271
-                    $this->remove_relation_to($model_object_or_id, $related_model_object);
272
-                    $related_model_object->delete();
273
-                    $deleted_count++;
274
-                }
275
-            }
276
-        }
277
-        return $deleted_count;
278
-    }
279
-
280
-
281
-    /**
282
-     * this just returns a model_object_id for incoming item that could be an object or id.
283
-     *
284
-     * @param  EE_Base_Class|int $model_object_or_id model object or the primary key of this model
285
-     * @throws EE_Error
286
-     * @return int
287
-     */
288
-    protected function _get_model_object_id($model_object_or_id)
289
-    {
290
-        $model_object_id = $model_object_or_id;
291
-        if ($model_object_or_id instanceof EE_Base_Class) {
292
-            $model_object_id = $model_object_or_id->ID();
293
-        }
294
-        if (! $model_object_id) {
295
-            throw new EE_Error(sprintf(__("Sorry, we cant get the related %s model objects to %s model object before it has an ID. You can solve that by just saving it before trying to get its related model objects",
296
-                "event_espresso"), $this->get_other_model()->get_this_model_name(),
297
-                $this->get_this_model()->get_this_model_name()));
298
-        }
299
-        return $model_object_id;
300
-    }
301
-
302
-
303
-    /**
304
-     * Gets the SQL string for performing the join between this model and the other model.
305
-     *
306
-     * @param string $model_relation_chain like 'Event.Event_Venue.Venue'
307
-     * @return string of SQL, eg "LEFT JOIN table_name AS table_alias ON this_model_primary_table.pk =
308
-     *                other_model_primary_table.fk" etc
309
-     */
310
-    abstract public function get_join_statement($model_relation_chain);
311
-
312
-
313
-    /**
314
-     * Adds a relationships between the two model objects provided. Each type of relationship handles this differently
315
-     * (EE_Belongs_To is a slight exception, it should more accurately be called set_relation_to(...), as this
316
-     * relationship only allows this model to be related to a single other model of this type)
317
-     *
318
-     * @param       $this_obj_or_id
319
-     * @param       $other_obj_or_id
320
-     * @param array $extra_join_model_fields_n_values
321
-     * @return \EE_Base_Class the EE_Base_Class which was added as a relation. (Convenient if you only pass an ID for
322
-     *                        $other_obj_or_id)
323
-     */
324
-    abstract public function add_relation_to(
325
-        $this_obj_or_id,
326
-        $other_obj_or_id,
327
-        $extra_join_model_fields_n_values = array()
328
-    );
329
-
330
-
331
-    /**
332
-     * Similar to 'add_relation_to(...)', performs the opposite action of removing the relationship between the two
333
-     * model objects
334
-     *
335
-     * @param       $this_obj_or_id
336
-     * @param       $other_obj_or_id
337
-     * @param array $where_query
338
-     * @return bool
339
-     */
340
-    abstract public function remove_relation_to($this_obj_or_id, $other_obj_or_id, $where_query = array());
341
-
342
-
343
-    /**
344
-     * Removes ALL relation instances for this relation obj
345
-     *
346
-     * @param EE_Base_Class|int $this_obj_or_id
347
-     * @param array             $where_query_param like EEM_Base::get_all's $query_params[0] (where conditions)
348
-     * @return EE_Base_Class[]
349
-     * @throws \EE_Error
350
-     */
351
-    public function remove_relations($this_obj_or_id, $where_query_param = array())
352
-    {
353
-        $related_things = $this->get_all_related($this_obj_or_id, array($where_query_param));
354
-        $objs_removed   = array();
355
-        foreach ($related_things as $related_thing) {
356
-            $objs_removed[] = $this->remove_relation_to($this_obj_or_id, $related_thing);
357
-        }
358
-        return $objs_removed;
359
-    }
360
-
361
-
362
-    /**
363
-     * If you aren't allowed to delete this model when there are related models across this
364
-     * relation object, return true. Otherwise, if you can delete this model even though
365
-     * related objects exist, returns false.
366
-     *
367
-     * @return boolean
368
-     */
369
-    public function block_delete_if_related_models_exist()
370
-    {
371
-        return $this->_blocking_delete;
372
-    }
373
-
374
-
375
-    /**
376
-     * Gets the error message to show
377
-     *
378
-     * @return string
379
-     */
380
-    public function get_deletion_error_message()
381
-    {
382
-        if ($this->_blocking_delete_error_message) {
383
-            return $this->_blocking_delete_error_message;
384
-        } else {
20
+	/**
21
+	 * The model name of which this relation is a component (ie, the model that called new EE_Model_Relation_Base)
22
+	 *
23
+	 * @var string eg Event, Question_Group, Registration
24
+	 */
25
+	private $_this_model_name;
26
+	/**
27
+	 * The model name pointed to by this relation (ie, the model we want to establish a relationship to)
28
+	 *
29
+	 * @var string eg Event, Question_Group, Registration
30
+	 */
31
+	private $_other_model_name;
32
+
33
+	/**
34
+	 * this is typically used when calling the relation models to make sure they inherit any set timezone from the
35
+	 * initiating model.
36
+	 *
37
+	 * @var string
38
+	 */
39
+	protected $_timezone;
40
+
41
+	/**
42
+	 * If you try to delete "this_model", and there are related "other_models",
43
+	 * and this isn't null, then abandon the deletion and add this warning.
44
+	 * This effectively makes it impossible to delete "this_model" while there are
45
+	 * related "other_models" along this relation.
46
+	 *
47
+	 * @var string (internationalized)
48
+	 */
49
+	protected $_blocking_delete_error_message;
50
+
51
+	protected $_blocking_delete = false;
52
+
53
+	/**
54
+	 * Object representing the relationship between two models. This knows how to join the models,
55
+	 * get related models across the relation, and add-and-remove the relationships.
56
+	 *
57
+	 * @param boolean $block_deletes                 if there are related models across this relation, block (prevent
58
+	 *                                               and add an error) the deletion of this model
59
+	 * @param string  $blocking_delete_error_message a customized error message on blocking deletes instead of the
60
+	 *                                               default
61
+	 */
62
+	public function __construct($block_deletes, $blocking_delete_error_message)
63
+	{
64
+		$this->_blocking_delete               = $block_deletes;
65
+		$this->_blocking_delete_error_message = $blocking_delete_error_message;
66
+	}
67
+
68
+
69
+	/**
70
+	 * @param $this_model_name
71
+	 * @param $other_model_name
72
+	 * @throws EE_Error
73
+	 */
74
+	public function _construct_finalize_set_models($this_model_name, $other_model_name)
75
+	{
76
+		$this->_this_model_name  = $this_model_name;
77
+		$this->_other_model_name = $other_model_name;
78
+		if (is_string($this->_blocking_delete)) {
79
+			throw new EE_Error(sprintf(__("When instantiating the relation of type %s from %s to %s, the \$block_deletes argument should be a boolean, not a string (%s)",
80
+				"event_espresso"),
81
+				get_class($this), $this_model_name, $other_model_name, $this->_blocking_delete));
82
+		}
83
+	}
84
+
85
+
86
+	/**
87
+	 * Gets the model where this relation is defined.
88
+	 *
89
+	 * @return EEM_Base
90
+	 */
91
+	public function get_this_model()
92
+	{
93
+		return $this->_get_model($this->_this_model_name);
94
+	}
95
+
96
+
97
+	/**
98
+	 * Gets the model which this relation establishes the relation TO (ie,
99
+	 * this relation object was defined on get_this_model(), get_other_model() is the other one)
100
+	 *
101
+	 * @return EEM_Base
102
+	 */
103
+	public function get_other_model()
104
+	{
105
+		return $this->_get_model($this->_other_model_name);
106
+	}
107
+
108
+
109
+	/**
110
+	 * Internally used by get_this_model() and get_other_model()
111
+	 *
112
+	 * @param string $model_name like Event, Question_Group, etc. omit the EEM_
113
+	 * @return EEM_Base
114
+	 */
115
+	protected function _get_model($model_name)
116
+	{
117
+		$modelInstance = EE_Registry::instance()->load_model($model_name);
118
+		$modelInstance->set_timezone($this->_timezone);
119
+		return $modelInstance;
120
+	}
121
+
122
+
123
+	/**
124
+	 * entirely possible that relations may be called from a model and we need to make sure those relations have their
125
+	 * timezone set correctly.
126
+	 *
127
+	 * @param string $timezone timezone to set.
128
+	 */
129
+	public function set_timezone($timezone)
130
+	{
131
+		if ($timezone !== null) {
132
+			$this->_timezone = $timezone;
133
+		}
134
+	}
135
+
136
+
137
+	/**
138
+	 * @param        $other_table
139
+	 * @param        $other_table_alias
140
+	 * @param        $other_table_column
141
+	 * @param        $this_table_alias
142
+	 * @param        $this_table_join_column
143
+	 * @param string $extra_join_sql
144
+	 * @return string
145
+	 */
146
+	protected function _left_join(
147
+		$other_table,
148
+		$other_table_alias,
149
+		$other_table_column,
150
+		$this_table_alias,
151
+		$this_table_join_column,
152
+		$extra_join_sql = ''
153
+	) {
154
+		return " LEFT JOIN " . $other_table . " AS " . $other_table_alias . " ON " . $other_table_alias . "." . $other_table_column . "=" . $this_table_alias . "." . $this_table_join_column . ($extra_join_sql ? " AND $extra_join_sql" : '');
155
+	}
156
+
157
+
158
+	/**
159
+	 * Gets all the model objects of type of other model related to $model_object,
160
+	 * according to this relation. This is the same code for EE_HABTM_Relation and EE_Has_Many_Relation.
161
+	 * For both of those child classes, $model_object must be saved so that it has an ID before querying,
162
+	 * otherwise an error will be thrown. Note: by default we disable default_where_conditions
163
+	 * EE_Belongs_To_Relation doesn't need to be saved before querying.
164
+	 *
165
+	 * @param EE_Base_Class|int $model_object_or_id                      or the primary key of this model
166
+	 * @param array             $query_params                            like EEM_Base::get_all's $query_params
167
+	 * @param boolean           $values_already_prepared_by_model_object @deprecated since 4.8.1
168
+	 * @return EE_Base_Class[]
169
+	 * @throws \EE_Error
170
+	 */
171
+	public function get_all_related(
172
+		$model_object_or_id,
173
+		$query_params = array(),
174
+		$values_already_prepared_by_model_object = false
175
+	) {
176
+		if ($values_already_prepared_by_model_object !== false) {
177
+			EE_Error::doing_it_wrong('EE_Model_Relation_Base::get_all_related',
178
+				__('The argument $values_already_prepared_by_model_object is no longer used.', 'event_espresso'),
179
+				'4.8.1');
180
+		}
181
+		$query_params                                      = $this->_disable_default_where_conditions_on_query_param($query_params);
182
+		$query_param_where_this_model_pk                   = $this->get_this_model()->get_this_model_name()
183
+															 . "."
184
+															 . $this->get_this_model()->get_primary_key_field()->get_name();
185
+		$model_object_id                                   = $this->_get_model_object_id($model_object_or_id);
186
+		$query_params[0][$query_param_where_this_model_pk] = $model_object_id;
187
+		return $this->get_other_model()->get_all($query_params);
188
+	}
189
+
190
+
191
+	/**
192
+	 * Alters the $query_params to disable default where conditions, unless otherwise specified
193
+	 *
194
+	 * @param string $query_params
195
+	 * @return array
196
+	 */
197
+	protected function _disable_default_where_conditions_on_query_param($query_params)
198
+	{
199
+		if (! isset($query_params['default_where_conditions'])) {
200
+			$query_params['default_where_conditions'] = 'none';
201
+		}
202
+		return $query_params;
203
+	}
204
+
205
+
206
+	/**
207
+	 * Deletes the related model objects which meet the query parameters. If no
208
+	 * parameters are specified, then all related model objects will be deleted.
209
+	 * Note: If the related model is extends EEM_Soft_Delete_Base, then the related
210
+	 * model objects will only be soft-deleted.
211
+	 *
212
+	 * @param EE_Base_Class|int|string $model_object_or_id
213
+	 * @param array                    $query_params
214
+	 * @return int of how many related models got deleted
215
+	 * @throws \EE_Error
216
+	 */
217
+	public function delete_all_related($model_object_or_id, $query_params = array())
218
+	{
219
+		//for each thing we would delete,
220
+		$related_model_objects = $this->get_all_related($model_object_or_id, $query_params);
221
+		//determine if it's blocked by anything else before it can be deleted
222
+		$deleted_count = 0;
223
+		foreach ($related_model_objects as $related_model_object) {
224
+			$delete_is_blocked = $this->get_other_model()->delete_is_blocked_by_related_models($related_model_object,
225
+				$model_object_or_id);
226
+			/* @var $model_object_or_id EE_Base_Class */
227
+			if (! $delete_is_blocked) {
228
+				$this->remove_relation_to($model_object_or_id, $related_model_object);
229
+				$related_model_object->delete();
230
+				$deleted_count++;
231
+			}
232
+		}
233
+		return $deleted_count;
234
+	}
235
+
236
+
237
+	/**
238
+	 * Deletes the related model objects which meet the query parameters. If no
239
+	 * parameters are specified, then all related model objects will be deleted.
240
+	 * Note: If the related model is extends EEM_Soft_Delete_Base, then the related
241
+	 * model objects will only be soft-deleted.
242
+	 *
243
+	 * @param EE_Base_Class|int|string $model_object_or_id
244
+	 * @param array                    $query_params
245
+	 * @return int of how many related models got deleted
246
+	 * @throws \EE_Error
247
+	 */
248
+	public function delete_related_permanently($model_object_or_id, $query_params = array())
249
+	{
250
+		//for each thing we would delete,
251
+		$related_model_objects = $this->get_all_related($model_object_or_id, $query_params);
252
+		//determine if it's blocked by anything else before it can be deleted
253
+		$deleted_count = 0;
254
+		foreach ($related_model_objects as $related_model_object) {
255
+			$delete_is_blocked = $this->get_other_model()->delete_is_blocked_by_related_models($related_model_object,
256
+				$model_object_or_id);
257
+			/* @var $model_object_or_id EE_Base_Class */
258
+			if ($related_model_object instanceof EE_Soft_Delete_Base_Class) {
259
+				$this->remove_relation_to($model_object_or_id, $related_model_object);
260
+				$deleted_count++;
261
+				if (! $delete_is_blocked) {
262
+					$related_model_object->delete_permanently();
263
+				} else {
264
+					//delete is blocked
265
+					//brent and darren, in this case, wanted to just soft delete it then
266
+					$related_model_object->delete();
267
+				}
268
+			} else {
269
+				//its not a soft-deletable thing anyways. do the normal logic.
270
+				if (! $delete_is_blocked) {
271
+					$this->remove_relation_to($model_object_or_id, $related_model_object);
272
+					$related_model_object->delete();
273
+					$deleted_count++;
274
+				}
275
+			}
276
+		}
277
+		return $deleted_count;
278
+	}
279
+
280
+
281
+	/**
282
+	 * this just returns a model_object_id for incoming item that could be an object or id.
283
+	 *
284
+	 * @param  EE_Base_Class|int $model_object_or_id model object or the primary key of this model
285
+	 * @throws EE_Error
286
+	 * @return int
287
+	 */
288
+	protected function _get_model_object_id($model_object_or_id)
289
+	{
290
+		$model_object_id = $model_object_or_id;
291
+		if ($model_object_or_id instanceof EE_Base_Class) {
292
+			$model_object_id = $model_object_or_id->ID();
293
+		}
294
+		if (! $model_object_id) {
295
+			throw new EE_Error(sprintf(__("Sorry, we cant get the related %s model objects to %s model object before it has an ID. You can solve that by just saving it before trying to get its related model objects",
296
+				"event_espresso"), $this->get_other_model()->get_this_model_name(),
297
+				$this->get_this_model()->get_this_model_name()));
298
+		}
299
+		return $model_object_id;
300
+	}
301
+
302
+
303
+	/**
304
+	 * Gets the SQL string for performing the join between this model and the other model.
305
+	 *
306
+	 * @param string $model_relation_chain like 'Event.Event_Venue.Venue'
307
+	 * @return string of SQL, eg "LEFT JOIN table_name AS table_alias ON this_model_primary_table.pk =
308
+	 *                other_model_primary_table.fk" etc
309
+	 */
310
+	abstract public function get_join_statement($model_relation_chain);
311
+
312
+
313
+	/**
314
+	 * Adds a relationships between the two model objects provided. Each type of relationship handles this differently
315
+	 * (EE_Belongs_To is a slight exception, it should more accurately be called set_relation_to(...), as this
316
+	 * relationship only allows this model to be related to a single other model of this type)
317
+	 *
318
+	 * @param       $this_obj_or_id
319
+	 * @param       $other_obj_or_id
320
+	 * @param array $extra_join_model_fields_n_values
321
+	 * @return \EE_Base_Class the EE_Base_Class which was added as a relation. (Convenient if you only pass an ID for
322
+	 *                        $other_obj_or_id)
323
+	 */
324
+	abstract public function add_relation_to(
325
+		$this_obj_or_id,
326
+		$other_obj_or_id,
327
+		$extra_join_model_fields_n_values = array()
328
+	);
329
+
330
+
331
+	/**
332
+	 * Similar to 'add_relation_to(...)', performs the opposite action of removing the relationship between the two
333
+	 * model objects
334
+	 *
335
+	 * @param       $this_obj_or_id
336
+	 * @param       $other_obj_or_id
337
+	 * @param array $where_query
338
+	 * @return bool
339
+	 */
340
+	abstract public function remove_relation_to($this_obj_or_id, $other_obj_or_id, $where_query = array());
341
+
342
+
343
+	/**
344
+	 * Removes ALL relation instances for this relation obj
345
+	 *
346
+	 * @param EE_Base_Class|int $this_obj_or_id
347
+	 * @param array             $where_query_param like EEM_Base::get_all's $query_params[0] (where conditions)
348
+	 * @return EE_Base_Class[]
349
+	 * @throws \EE_Error
350
+	 */
351
+	public function remove_relations($this_obj_or_id, $where_query_param = array())
352
+	{
353
+		$related_things = $this->get_all_related($this_obj_or_id, array($where_query_param));
354
+		$objs_removed   = array();
355
+		foreach ($related_things as $related_thing) {
356
+			$objs_removed[] = $this->remove_relation_to($this_obj_or_id, $related_thing);
357
+		}
358
+		return $objs_removed;
359
+	}
360
+
361
+
362
+	/**
363
+	 * If you aren't allowed to delete this model when there are related models across this
364
+	 * relation object, return true. Otherwise, if you can delete this model even though
365
+	 * related objects exist, returns false.
366
+	 *
367
+	 * @return boolean
368
+	 */
369
+	public function block_delete_if_related_models_exist()
370
+	{
371
+		return $this->_blocking_delete;
372
+	}
373
+
374
+
375
+	/**
376
+	 * Gets the error message to show
377
+	 *
378
+	 * @return string
379
+	 */
380
+	public function get_deletion_error_message()
381
+	{
382
+		if ($this->_blocking_delete_error_message) {
383
+			return $this->_blocking_delete_error_message;
384
+		} else {
385 385
 //			return sprintf(__('Cannot delete %1$s when there are related %2$s', "event_espresso"),$this->get_this_model()->item_name(2),$this->get_other_model()->item_name(2));
386
-            return sprintf(
387
-                __('This %1$s is currently linked to one or more %2$s records. If this %1$s is incorrect, then please remove it from all %3$s before attempting to delete it.',
388
-                    "event_espresso"),
389
-                $this->get_this_model()->item_name(1),
390
-                $this->get_other_model()->item_name(1),
391
-                $this->get_other_model()->item_name(2)
392
-            );
393
-        }
394
-    }
395
-
396
-    /**
397
-     * Returns whatever is set as the nicename for the object.
398
-     *
399
-     * @return string
400
-     */
401
-    public function getSchemaDescription()
402
-    {
403
-        $description = $this instanceof EE_Belongs_To_Relation
404
-            ? esc_html__('The related %1$s entity to the %2$s.', 'event_espresso')
405
-            : esc_html__('The related %1$s entities to the %2$s.', 'event_espresso');
406
-        return sprintf(
407
-            $description,
408
-            $this->get_other_model()->get_this_model_name(),
409
-            $this->get_this_model()->get_this_model_name()
410
-        );
411
-    }
412
-
413
-    /**
414
-     * Returns whatever is set as the $_schema_type property for the object.
415
-     * Note: this will automatically add 'null' to the schema if the object is_nullable()
416
-     *
417
-     * @return string|array
418
-     */
419
-    public function getSchemaType()
420
-    {
421
-        return $this instanceof EE_Belongs_To_Relation ? 'object' : 'array';
422
-    }
423
-
424
-    /**
425
-     * This is usually present when the $_schema_type property is 'object'.  Any child classes will need to override
426
-     * this method and return the properties for the schema.
427
-     * The reason this is not a property on the class is because there may be filters set on the values for the property
428
-     * that won't be exposed on construct.  For example enum type schemas may have the enum values filtered.
429
-     *
430
-     * @return array
431
-     */
432
-    public function getSchemaProperties()
433
-    {
434
-        return array();
435
-    }
436
-
437
-    /**
438
-     * If a child class has enum values, they should override this method and provide a simple array
439
-     * of the enum values.
440
-     * The reason this is not a property on the class is because there may be filterable enum values that
441
-     * are set on the instantiated object that could be filtered after construct.
442
-     *
443
-     * @return array
444
-     */
445
-    public function getSchemaEnum()
446
-    {
447
-        return array();
448
-    }
449
-
450
-    /**
451
-     * This returns the value of the $_schema_format property on the object.
452
-     *
453
-     * @return string
454
-     */
455
-    public function getSchemaFormat()
456
-    {
457
-        return array();
458
-    }
459
-
460
-    /**
461
-     * This returns the value of the $_schema_readonly property on the object.
462
-     *
463
-     * @return bool
464
-     */
465
-    public function getSchemaReadonly()
466
-    {
467
-        return true;
468
-    }
469
-
470
-    /**
471
-     * This returns elements used to represent this field in the json schema.
472
-     *
473
-     * @link http://json-schema.org/
474
-     * @return array
475
-     */
476
-    public function getSchema()
477
-    {
478
-        $schema = array(
479
-            'description' => $this->getSchemaDescription(),
480
-            'type' => $this->getSchemaType(),
481
-            'relation' => true,
482
-            'relation_type' => get_class($this),
483
-            'readonly' => $this->getSchemaReadonly()
484
-        );
485
-
486
-        if ($this instanceof EE_HABTM_Relation) {
487
-            $schema['joining_model_name'] = $this->get_join_model()->get_this_model_name();
488
-        }
489
-
490
-        if ($this->getSchemaType() === 'array') {
491
-            $schema['items'] = array(
492
-                'type' => 'object'
493
-            );
494
-        }
495
-
496
-        return $schema;
497
-    }
386
+			return sprintf(
387
+				__('This %1$s is currently linked to one or more %2$s records. If this %1$s is incorrect, then please remove it from all %3$s before attempting to delete it.',
388
+					"event_espresso"),
389
+				$this->get_this_model()->item_name(1),
390
+				$this->get_other_model()->item_name(1),
391
+				$this->get_other_model()->item_name(2)
392
+			);
393
+		}
394
+	}
395
+
396
+	/**
397
+	 * Returns whatever is set as the nicename for the object.
398
+	 *
399
+	 * @return string
400
+	 */
401
+	public function getSchemaDescription()
402
+	{
403
+		$description = $this instanceof EE_Belongs_To_Relation
404
+			? esc_html__('The related %1$s entity to the %2$s.', 'event_espresso')
405
+			: esc_html__('The related %1$s entities to the %2$s.', 'event_espresso');
406
+		return sprintf(
407
+			$description,
408
+			$this->get_other_model()->get_this_model_name(),
409
+			$this->get_this_model()->get_this_model_name()
410
+		);
411
+	}
412
+
413
+	/**
414
+	 * Returns whatever is set as the $_schema_type property for the object.
415
+	 * Note: this will automatically add 'null' to the schema if the object is_nullable()
416
+	 *
417
+	 * @return string|array
418
+	 */
419
+	public function getSchemaType()
420
+	{
421
+		return $this instanceof EE_Belongs_To_Relation ? 'object' : 'array';
422
+	}
423
+
424
+	/**
425
+	 * This is usually present when the $_schema_type property is 'object'.  Any child classes will need to override
426
+	 * this method and return the properties for the schema.
427
+	 * The reason this is not a property on the class is because there may be filters set on the values for the property
428
+	 * that won't be exposed on construct.  For example enum type schemas may have the enum values filtered.
429
+	 *
430
+	 * @return array
431
+	 */
432
+	public function getSchemaProperties()
433
+	{
434
+		return array();
435
+	}
436
+
437
+	/**
438
+	 * If a child class has enum values, they should override this method and provide a simple array
439
+	 * of the enum values.
440
+	 * The reason this is not a property on the class is because there may be filterable enum values that
441
+	 * are set on the instantiated object that could be filtered after construct.
442
+	 *
443
+	 * @return array
444
+	 */
445
+	public function getSchemaEnum()
446
+	{
447
+		return array();
448
+	}
449
+
450
+	/**
451
+	 * This returns the value of the $_schema_format property on the object.
452
+	 *
453
+	 * @return string
454
+	 */
455
+	public function getSchemaFormat()
456
+	{
457
+		return array();
458
+	}
459
+
460
+	/**
461
+	 * This returns the value of the $_schema_readonly property on the object.
462
+	 *
463
+	 * @return bool
464
+	 */
465
+	public function getSchemaReadonly()
466
+	{
467
+		return true;
468
+	}
469
+
470
+	/**
471
+	 * This returns elements used to represent this field in the json schema.
472
+	 *
473
+	 * @link http://json-schema.org/
474
+	 * @return array
475
+	 */
476
+	public function getSchema()
477
+	{
478
+		$schema = array(
479
+			'description' => $this->getSchemaDescription(),
480
+			'type' => $this->getSchemaType(),
481
+			'relation' => true,
482
+			'relation_type' => get_class($this),
483
+			'readonly' => $this->getSchemaReadonly()
484
+		);
485
+
486
+		if ($this instanceof EE_HABTM_Relation) {
487
+			$schema['joining_model_name'] = $this->get_join_model()->get_this_model_name();
488
+		}
489
+
490
+		if ($this->getSchemaType() === 'array') {
491
+			$schema['items'] = array(
492
+				'type' => 'object'
493
+			);
494
+		}
495
+
496
+		return $schema;
497
+	}
498 498
 }
Please login to merge, or discard this patch.