Completed
Branch BUG-10738-inconsistency-in-ses... (860590)
by
unknown
57:39 queued 45:30
created
core/services/notices/Notice.php 1 patch
Indentation   +75 added lines, -75 removed lines patch added patch discarded remove patch
@@ -17,108 +17,108 @@
 block discarded – undo
17 17
 class Notice implements NoticeInterface
18 18
 {
19 19
 
20
-    const ERROR = 'error';
21
-    const ATTENTION = 'attention';
22
-    const SUCCESS = 'success';
20
+	const ERROR = 'error';
21
+	const ATTENTION = 'attention';
22
+	const SUCCESS = 'success';
23 23
 
24
-    /**
25
-     * @var string $type
26
-     */
27
-    private $type;
24
+	/**
25
+	 * @var string $type
26
+	 */
27
+	private $type;
28 28
 
29 29
 
30
-    /**
31
-     * @var string $message
32
-     */
33
-    private $message;
30
+	/**
31
+	 * @var string $message
32
+	 */
33
+	private $message;
34 34
 
35 35
 
36
-    /**
37
-     * @var string $file
38
-     */
39
-    private $file;
36
+	/**
37
+	 * @var string $file
38
+	 */
39
+	private $file;
40 40
 
41 41
 
42
-    /**
43
-     * @var string $func
44
-     */
45
-    private $func;
42
+	/**
43
+	 * @var string $func
44
+	 */
45
+	private $func;
46 46
 
47 47
 
48
-    /**
49
-     * @var string $line
50
-     */
51
-    private $line;
48
+	/**
49
+	 * @var string $line
50
+	 */
51
+	private $line;
52 52
 
53 53
 
54 54
 
55
-    /**
56
-     * Notice constructor.
57
-     *
58
-     * @param string $type
59
-     * @param string $message
60
-     * @param string $file
61
-     * @param string $func
62
-     * @param string $line
63
-     */
64
-    public function __construct($type, $message, $file, $func, $line)
65
-    {
66
-        $this->type = $type;
67
-        $this->message = $message;
68
-        $this->file = $file;
69
-        $this->func = $func;
70
-        $this->line = $line;
71
-    }
55
+	/**
56
+	 * Notice constructor.
57
+	 *
58
+	 * @param string $type
59
+	 * @param string $message
60
+	 * @param string $file
61
+	 * @param string $func
62
+	 * @param string $line
63
+	 */
64
+	public function __construct($type, $message, $file, $func, $line)
65
+	{
66
+		$this->type = $type;
67
+		$this->message = $message;
68
+		$this->file = $file;
69
+		$this->func = $func;
70
+		$this->line = $line;
71
+	}
72 72
 
73 73
 
74 74
 
75
-    /**
76
-     * @return string
77
-     */
78
-    public function type()
79
-    {
80
-        return $this->type;
81
-    }
75
+	/**
76
+	 * @return string
77
+	 */
78
+	public function type()
79
+	{
80
+		return $this->type;
81
+	}
82 82
 
83 83
 
84 84
 
85
-    /**
86
-     * @return string
87
-     */
88
-    public function message()
89
-    {
90
-        return $this->message;
91
-    }
85
+	/**
86
+	 * @return string
87
+	 */
88
+	public function message()
89
+	{
90
+		return $this->message;
91
+	}
92 92
 
93 93
 
94 94
 
95
-    /**
96
-     * @return string
97
-     */
98
-    public function file()
99
-    {
100
-        return $this->file;
101
-    }
95
+	/**
96
+	 * @return string
97
+	 */
98
+	public function file()
99
+	{
100
+		return $this->file;
101
+	}
102 102
 
103 103
 
104 104
 
105
-    /**
106
-     * @return string
107
-     */
108
-    public function func()
109
-    {
110
-        return $this->func;
111
-    }
105
+	/**
106
+	 * @return string
107
+	 */
108
+	public function func()
109
+	{
110
+		return $this->func;
111
+	}
112 112
 
113 113
 
114 114
 
115
-    /**
116
-     * @return string
117
-     */
118
-    public function line()
119
-    {
120
-        return $this->line;
121
-    }
115
+	/**
116
+	 * @return string
117
+	 */
118
+	public function line()
119
+	{
120
+		return $this->line;
121
+	}
122 122
 
123 123
 
124 124
 
Please login to merge, or discard this patch.
core/services/notices/NoticesContainerInterface.php 1 patch
Indentation   +57 added lines, -57 removed lines patch added patch discarded remove patch
@@ -16,94 +16,94 @@
 block discarded – undo
16 16
 interface NoticesContainerInterface
17 17
 {
18 18
 
19
-    /**
20
-     * @param string $notice
21
-     * @param string $file
22
-     * @param string $func
23
-     * @param string $line
24
-     */
25
-    public function addAttention($notice, $file = '', $func = '', $line = '');
19
+	/**
20
+	 * @param string $notice
21
+	 * @param string $file
22
+	 * @param string $func
23
+	 * @param string $line
24
+	 */
25
+	public function addAttention($notice, $file = '', $func = '', $line = '');
26 26
 
27 27
 
28 28
 
29
-    /**
30
-     * @param string $notice
31
-     * @param string $file
32
-     * @param string $func
33
-     * @param string $line
34
-     */
35
-    public function addError($notice, $file, $func, $line);
29
+	/**
30
+	 * @param string $notice
31
+	 * @param string $file
32
+	 * @param string $func
33
+	 * @param string $line
34
+	 */
35
+	public function addError($notice, $file, $func, $line);
36 36
 
37 37
 
38 38
 
39
-    /**
40
-     * @param string $notice
41
-     * @param string $file
42
-     * @param string $func
43
-     * @param string $line
44
-     */
45
-    public function addSuccess($notice, $file = '', $func = '', $line = '');
39
+	/**
40
+	 * @param string $notice
41
+	 * @param string $file
42
+	 * @param string $func
43
+	 * @param string $line
44
+	 */
45
+	public function addSuccess($notice, $file = '', $func = '', $line = '');
46 46
 
47 47
 
48 48
 
49
-    /**
50
-     * @return boolean
51
-     */
52
-    public function hasAttention();
49
+	/**
50
+	 * @return boolean
51
+	 */
52
+	public function hasAttention();
53 53
 
54 54
 
55 55
 
56
-    /**
57
-     * @return boolean
58
-     */
59
-    public function hasError();
56
+	/**
57
+	 * @return boolean
58
+	 */
59
+	public function hasError();
60 60
 
61 61
 
62 62
 
63
-    /**
64
-     * @return boolean
65
-     */
66
-    public function hasSuccess();
63
+	/**
64
+	 * @return boolean
65
+	 */
66
+	public function hasSuccess();
67 67
 
68 68
 
69 69
 
70
-    /**
71
-     * @return int
72
-     */
73
-    public function countAttention();
70
+	/**
71
+	 * @return int
72
+	 */
73
+	public function countAttention();
74 74
 
75 75
 
76 76
 
77
-    /**
78
-     * @return int
79
-     */
80
-    public function countError();
77
+	/**
78
+	 * @return int
79
+	 */
80
+	public function countError();
81 81
 
82 82
 
83 83
 
84
-    /**
85
-     * @return int
86
-     */
87
-    public function countSuccess();
84
+	/**
85
+	 * @return int
86
+	 */
87
+	public function countSuccess();
88 88
 
89 89
 
90 90
 
91
-    /**
92
-     * @return NoticeInterface[]
93
-     */
94
-    public function getAttention();
91
+	/**
92
+	 * @return NoticeInterface[]
93
+	 */
94
+	public function getAttention();
95 95
 
96 96
 
97 97
 
98
-    /**
99
-     * @return NoticeInterface[]
100
-     */
101
-    public function getError();
98
+	/**
99
+	 * @return NoticeInterface[]
100
+	 */
101
+	public function getError();
102 102
 
103 103
 
104 104
 
105
-    /**
106
-     * @return NoticeInterface[]
107
-     */
108
-    public function getSuccess();
105
+	/**
106
+	 * @return NoticeInterface[]
107
+	 */
108
+	public function getSuccess();
109 109
 }
110 110
\ No newline at end of file
Please login to merge, or discard this patch.
core/services/notices/NoticeInterface.php 1 patch
Indentation   +20 added lines, -20 removed lines patch added patch discarded remove patch
@@ -17,36 +17,36 @@
 block discarded – undo
17 17
 interface NoticeInterface
18 18
 {
19 19
 
20
-    /**
21
-     * @return string
22
-     */
23
-    public function type();
20
+	/**
21
+	 * @return string
22
+	 */
23
+	public function type();
24 24
 
25 25
 
26 26
 
27
-    /**
28
-     * @return string
29
-     */
30
-    public function message();
27
+	/**
28
+	 * @return string
29
+	 */
30
+	public function message();
31 31
 
32 32
 
33 33
 
34
-    /**
35
-     * @return string
36
-     */
37
-    public function file();
34
+	/**
35
+	 * @return string
36
+	 */
37
+	public function file();
38 38
 
39 39
 
40 40
 
41
-    /**
42
-     * @return string
43
-     */
44
-    public function func();
41
+	/**
42
+	 * @return string
43
+	 */
44
+	public function func();
45 45
 
46 46
 
47 47
 
48
-    /**
49
-     * @return string
50
-     */
51
-    public function line();
48
+	/**
49
+	 * @return string
50
+	 */
51
+	public function line();
52 52
 }
53 53
\ No newline at end of file
Please login to merge, or discard this patch.
core/services/notices/ConvertNoticesToEeErrors.php 2 patches
Spacing   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -43,7 +43,7 @@
 block discarded – undo
43 43
             $error_string = esc_html__('The following errors occurred:', 'event_espresso');
44 44
             foreach ($notices->getError() as $notice) {
45 45
                 if ($this->getThrowExceptions()) {
46
-                    $error_string .= '<br />' . $notice->message();
46
+                    $error_string .= '<br />'.$notice->message();
47 47
                 } else {
48 48
                     EE_Error::add_error(
49 49
                         $notice->message(),
Please login to merge, or discard this patch.
Indentation   +50 added lines, -50 removed lines patch added patch discarded remove patch
@@ -19,56 +19,56 @@
 block discarded – undo
19 19
 class ConvertNoticesToEeErrors extends NoticeConverter
20 20
 {
21 21
 
22
-    /**
23
-     * Converts Notice objects into EE_Error notifications
24
-     *
25
-     * @param NoticesContainerInterface $notices
26
-     * @throws EE_Error
27
-     */
28
-    public function process(NoticesContainerInterface $notices)
29
-    {
30
-        $this->setNotices($notices);
31
-        $notices = $this->getNotices();
32
-        if ($notices->hasAttention()) {
33
-            foreach ($notices->getAttention() as $notice) {
34
-                EE_Error::add_attention(
35
-                    $notice->message(),
36
-                    $notice->file(),
37
-                    $notice->func(),
38
-                    $notice->line()
39
-                );
40
-            }
41
-        }
42
-        if ($notices->hasError()) {
43
-            $error_string = esc_html__('The following errors occurred:', 'event_espresso');
44
-            foreach ($notices->getError() as $notice) {
45
-                if ($this->getThrowExceptions()) {
46
-                    $error_string .= '<br />' . $notice->message();
47
-                } else {
48
-                    EE_Error::add_error(
49
-                        $notice->message(),
50
-                        $notice->file(),
51
-                        $notice->func(),
52
-                        $notice->line()
53
-                    );
54
-                }
55
-            }
56
-            if ($this->getThrowExceptions()) {
57
-                throw new EE_Error($error_string);
58
-            }
59
-        }
60
-        if ($notices->hasSuccess()) {
61
-            foreach ($notices->getSuccess() as $notice) {
62
-                EE_Error::add_success(
63
-                    $notice->message(),
64
-                    $notice->file(),
65
-                    $notice->func(),
66
-                    $notice->line()
67
-                );
68
-            }
69
-        }
70
-        $this->clearNotices();
71
-    }
22
+	/**
23
+	 * Converts Notice objects into EE_Error notifications
24
+	 *
25
+	 * @param NoticesContainerInterface $notices
26
+	 * @throws EE_Error
27
+	 */
28
+	public function process(NoticesContainerInterface $notices)
29
+	{
30
+		$this->setNotices($notices);
31
+		$notices = $this->getNotices();
32
+		if ($notices->hasAttention()) {
33
+			foreach ($notices->getAttention() as $notice) {
34
+				EE_Error::add_attention(
35
+					$notice->message(),
36
+					$notice->file(),
37
+					$notice->func(),
38
+					$notice->line()
39
+				);
40
+			}
41
+		}
42
+		if ($notices->hasError()) {
43
+			$error_string = esc_html__('The following errors occurred:', 'event_espresso');
44
+			foreach ($notices->getError() as $notice) {
45
+				if ($this->getThrowExceptions()) {
46
+					$error_string .= '<br />' . $notice->message();
47
+				} else {
48
+					EE_Error::add_error(
49
+						$notice->message(),
50
+						$notice->file(),
51
+						$notice->func(),
52
+						$notice->line()
53
+					);
54
+				}
55
+			}
56
+			if ($this->getThrowExceptions()) {
57
+				throw new EE_Error($error_string);
58
+			}
59
+		}
60
+		if ($notices->hasSuccess()) {
61
+			foreach ($notices->getSuccess() as $notice) {
62
+				EE_Error::add_success(
63
+					$notice->message(),
64
+					$notice->file(),
65
+					$notice->func(),
66
+					$notice->line()
67
+				);
68
+			}
69
+		}
70
+		$this->clearNotices();
71
+	}
72 72
 
73 73
 
74 74
 }
Please login to merge, or discard this patch.
core/services/notices/NoticeConverterInterface.php 2 patches
Doc Comments   +2 added lines, -1 removed lines patch added patch discarded remove patch
@@ -24,6 +24,7 @@  discard block
 block discarded – undo
24 24
 
25 25
     /**
26 26
      * @param bool $throw_exceptions
27
+     * @return void
27 28
      */
28 29
     public function setThrowExceptions($throw_exceptions);
29 30
 
@@ -41,7 +42,7 @@  discard block
 block discarded – undo
41 42
     public function process(NoticesContainerInterface $notices);
42 43
 
43 44
     /**
44
-     * @return void;
45
+     * @return void
45 46
      */
46 47
     public function clearNotices();
47 48
 
Please login to merge, or discard this patch.
Indentation   +27 added lines, -27 removed lines patch added patch discarded remove patch
@@ -17,33 +17,33 @@
 block discarded – undo
17 17
 interface NoticeConverterInterface
18 18
 {
19 19
 
20
-    /**
21
-     * @return NoticesContainerInterface
22
-     */
23
-    public function getNotices();
24
-
25
-    /**
26
-     * @param bool $throw_exceptions
27
-     */
28
-    public function setThrowExceptions($throw_exceptions);
29
-
30
-    /**
31
-     * @return bool
32
-     */
33
-    public function getThrowExceptions();
34
-
35
-    /**
36
-     * Converts NoticesContainerInterface objects into other format
37
-     *
38
-     * @param NoticesContainerInterface $notices
39
-     * @return
40
-     */
41
-    public function process(NoticesContainerInterface $notices);
42
-
43
-    /**
44
-     * @return void;
45
-     */
46
-    public function clearNotices();
20
+	/**
21
+	 * @return NoticesContainerInterface
22
+	 */
23
+	public function getNotices();
24
+
25
+	/**
26
+	 * @param bool $throw_exceptions
27
+	 */
28
+	public function setThrowExceptions($throw_exceptions);
29
+
30
+	/**
31
+	 * @return bool
32
+	 */
33
+	public function getThrowExceptions();
34
+
35
+	/**
36
+	 * Converts NoticesContainerInterface objects into other format
37
+	 *
38
+	 * @param NoticesContainerInterface $notices
39
+	 * @return
40
+	 */
41
+	public function process(NoticesContainerInterface $notices);
42
+
43
+	/**
44
+	 * @return void;
45
+	 */
46
+	public function clearNotices();
47 47
 
48 48
 
49 49
 }
50 50
\ No newline at end of file
Please login to merge, or discard this patch.
core/services/notices/NoticeConverter.php 1 patch
Indentation   +54 added lines, -54 removed lines patch added patch discarded remove patch
@@ -17,79 +17,79 @@
 block discarded – undo
17 17
 abstract class NoticeConverter implements NoticeConverterInterface
18 18
 {
19 19
 
20
-    /**
21
-     * @var NoticesContainerInterface $notices
22
-     */
23
-    private $notices;
20
+	/**
21
+	 * @var NoticesContainerInterface $notices
22
+	 */
23
+	private $notices;
24 24
 
25
-    /**
26
-     * if set to true, then errors will be thrown as exceptions
27
-     *
28
-     * @var boolean $throw_exceptions
29
-     */
30
-    private $throw_exceptions;
25
+	/**
26
+	 * if set to true, then errors will be thrown as exceptions
27
+	 *
28
+	 * @var boolean $throw_exceptions
29
+	 */
30
+	private $throw_exceptions;
31 31
 
32 32
 
33 33
 
34
-    /**
35
-     * NoticeConverter constructor.
36
-     *
37
-     * @param bool                      $throw_exceptions
38
-     */
39
-    public function __construct($throw_exceptions = false)
40
-    {
41
-        $this->throw_exceptions = $throw_exceptions;
42
-    }
34
+	/**
35
+	 * NoticeConverter constructor.
36
+	 *
37
+	 * @param bool                      $throw_exceptions
38
+	 */
39
+	public function __construct($throw_exceptions = false)
40
+	{
41
+		$this->throw_exceptions = $throw_exceptions;
42
+	}
43 43
 
44 44
 
45 45
 
46
-    /**
47
-     * @return NoticesContainerInterface
48
-     */
49
-    public function getNotices()
50
-    {
51
-        return $this->notices;
52
-    }
46
+	/**
47
+	 * @return NoticesContainerInterface
48
+	 */
49
+	public function getNotices()
50
+	{
51
+		return $this->notices;
52
+	}
53 53
 
54 54
 
55 55
 
56
-    /**
57
-     * @param NoticesContainerInterface $notices
58
-     */
59
-    protected function setNotices(NoticesContainerInterface $notices)
60
-    {
61
-        $this->notices = $notices;
62
-    }
56
+	/**
57
+	 * @param NoticesContainerInterface $notices
58
+	 */
59
+	protected function setNotices(NoticesContainerInterface $notices)
60
+	{
61
+		$this->notices = $notices;
62
+	}
63 63
 
64 64
 
65 65
 
66
-    /**
67
-     * @return bool
68
-     */
69
-    public function getThrowExceptions()
70
-    {
71
-        return $this->throw_exceptions;
72
-    }
66
+	/**
67
+	 * @return bool
68
+	 */
69
+	public function getThrowExceptions()
70
+	{
71
+		return $this->throw_exceptions;
72
+	}
73 73
 
74 74
 
75 75
 
76
-    /**
77
-     * @param bool $throw_exceptions
78
-     */
79
-    public function setThrowExceptions($throw_exceptions)
80
-    {
81
-        $this->throw_exceptions = filter_var($throw_exceptions, FILTER_VALIDATE_BOOLEAN);
82
-    }
76
+	/**
77
+	 * @param bool $throw_exceptions
78
+	 */
79
+	public function setThrowExceptions($throw_exceptions)
80
+	{
81
+		$this->throw_exceptions = filter_var($throw_exceptions, FILTER_VALIDATE_BOOLEAN);
82
+	}
83 83
 
84 84
 
85 85
 
86
-    /**
87
-     * @return void;
88
-     */
89
-    public function clearNotices()
90
-    {
91
-        $this->notices = null;
92
-    }
86
+	/**
87
+	 * @return void;
88
+	 */
89
+	public function clearNotices()
90
+	{
91
+		$this->notices = null;
92
+	}
93 93
 
94 94
 
95 95
 }
Please login to merge, or discard this patch.
core/db_classes/EE_Event.class.php 3 patches
Doc Comments   +2 added lines, -2 removed lines patch added patch discarded remove patch
@@ -818,7 +818,7 @@  discard block
 block discarded – undo
818 818
     /**
819 819
      * calculate spaces remaining based on "saleable" tickets
820 820
      *
821
-     * @param array $tickets
821
+     * @param EE_Base_Class[] $tickets
822 822
      * @param bool $filtered
823 823
      * @return int|float
824 824
      * @throws EE_Error
@@ -1174,7 +1174,7 @@  discard block
 block discarded – undo
1174 1174
      *
1175 1175
      * @access public
1176 1176
      * @param boolean $echo whether to return (FALSE), or echo out the result (TRUE)
1177
-     * @return mixed void|string
1177
+     * @return string void|string
1178 1178
      * @throws EE_Error
1179 1179
      */
1180 1180
     public function pretty_active_status($echo = true)
Please login to merge, or discard this patch.
Indentation   +1399 added lines, -1399 removed lines patch added patch discarded remove patch
@@ -1,7 +1,7 @@  discard block
 block discarded – undo
1 1
 <?php use EventEspresso\core\exceptions\InvalidStatusException;
2 2
 
3 3
 if (!defined('EVENT_ESPRESSO_VERSION')) {
4
-    exit('No direct script access allowed');
4
+	exit('No direct script access allowed');
5 5
 }
6 6
 
7 7
 
@@ -15,1403 +15,1403 @@  discard block
 block discarded – undo
15 15
 class EE_Event extends EE_CPT_Base implements EEI_Line_Item_Object, EEI_Admin_Links, EEI_Has_Icon, EEI_Event
16 16
 {
17 17
 
18
-    /**
19
-     * cached value for the the logical active status for the event
20
-     *
21
-     * @see get_active_status()
22
-     * @var string
23
-     */
24
-    protected $_active_status = '';
25
-
26
-    /**
27
-     * This is just used for caching the Primary Datetime for the Event on initial retrieval
28
-     *
29
-     * @var EE_Datetime
30
-     */
31
-    protected $_Primary_Datetime;
32
-
33
-
34
-    /**
35
-     * @param array $props_n_values incoming values
36
-     * @param string $timezone incoming timezone (if not set the timezone set for the website will be
37
-     *                                        used.)
38
-     * @param array $date_formats incoming date_formats in an array where the first value is the
39
-     *                                        date_format and the second value is the time format
40
-     * @return EE_Event
41
-     * @throws EE_Error
42
-     */
43
-    public static function new_instance($props_n_values = array(), $timezone = null, $date_formats = array())
44
-    {
45
-        $has_object = parent::_check_for_object($props_n_values, __CLASS__, $timezone, $date_formats);
46
-        return $has_object ? $has_object : new self($props_n_values, false, $timezone, $date_formats);
47
-    }
48
-
49
-
50
-    /**
51
-     * @param array $props_n_values incoming values from the database
52
-     * @param string $timezone incoming timezone as set by the model.  If not set the timezone for
53
-     *                                the website will be used.
54
-     * @return EE_Event
55
-     * @throws EE_Error
56
-     */
57
-    public static function new_instance_from_db($props_n_values = array(), $timezone = null)
58
-    {
59
-        return new self($props_n_values, true, $timezone);
60
-    }
61
-
62
-
63
-    /**
64
-     * Overrides parent set() method so that all calls to set( 'status', $status ) can be routed to internal methods
65
-     *
66
-     * @param string $field_name
67
-     * @param mixed $field_value
68
-     * @param bool $use_default
69
-     * @throws EE_Error
70
-     */
71
-    public function set($field_name, $field_value, $use_default = false)
72
-    {
73
-        switch ($field_name) {
74
-            case 'status' :
75
-                $this->set_status($field_value, $use_default);
76
-                break;
77
-            default :
78
-                parent::set($field_name, $field_value, $use_default);
79
-        }
80
-    }
81
-
82
-
83
-    /**
84
-     *    set_status
85
-     * Checks if event status is being changed to SOLD OUT
86
-     * and updates event meta data with previous event status
87
-     * so that we can revert things if/when the event is no longer sold out
88
-     *
89
-     * @access public
90
-     * @param string $new_status
91
-     * @param bool $use_default
92
-     * @return void
93
-     * @throws EE_Error
94
-     */
95
-    public function set_status($new_status = null, $use_default = false)
96
-    {
97
-        // if nothing is set, and we aren't explicitly wanting to reset the status, then just leave
98
-        if (empty($new_status) && !$use_default) {
99
-            return;
100
-        }
101
-        // get current Event status
102
-        $old_status = $this->status();
103
-        // if status has changed
104
-        if ($old_status !== $new_status) {
105
-            // TO sold_out
106
-            if ($new_status === EEM_Event::sold_out) {
107
-                // save the previous event status so that we can revert if the event is no longer sold out
108
-                $this->add_post_meta('_previous_event_status', $old_status);
109
-                do_action('AHEE__EE_Event__set_status__to_sold_out', $this, $old_status, $new_status);
110
-                // OR FROM  sold_out
111
-            } else if ($old_status === EEM_Event::sold_out) {
112
-                $this->delete_post_meta('_previous_event_status');
113
-                do_action('AHEE__EE_Event__set_status__from_sold_out', $this, $old_status, $new_status);
114
-            }
115
-            // update status
116
-            parent::set('status', $new_status, $use_default);
117
-            do_action('AHEE__EE_Event__set_status__after_update', $this);
118
-            return;
119
-        }
120
-        // even though the old value matches the new value, it's still good to
121
-        // allow the parent set method to have a say
122
-        parent::set('status', $new_status, $use_default);
123
-    }
124
-
125
-
126
-    /**
127
-     * Gets all the datetimes for this event
128
-     *
129
-     * @param array $query_params like EEM_Base::get_all
130
-     * @return EE_Base_Class[]|EE_Datetime[]
131
-     * @throws EE_Error
132
-     */
133
-    public function datetimes($query_params = array())
134
-    {
135
-        return $this->get_many_related('Datetime', $query_params);
136
-    }
137
-
138
-
139
-    /**
140
-     * Gets all the datetimes for this event, ordered by DTT_EVT_start in ascending order
141
-     *
142
-     * @return EE_Base_Class[]|EE_Datetime[]
143
-     * @throws EE_Error
144
-     */
145
-    public function datetimes_in_chronological_order()
146
-    {
147
-        return $this->get_many_related('Datetime', array('order_by' => array('DTT_EVT_start' => 'ASC')));
148
-    }
149
-
150
-
151
-    /**
152
-     * Gets all the datetimes for this event, ordered by the DTT_order on the datetime.
153
-     * @darren, we should probably UNSET timezone on the EEM_Datetime model
154
-     * after running our query, so that this timezone isn't set for EVERY query
155
-     * on EEM_Datetime for the rest of the request, no?
156
-     *
157
-     * @param boolean $show_expired whether or not to include expired events
158
-     * @param boolean $show_deleted whether or not to include deleted events
159
-     * @param null $limit
160
-     * @return EE_Datetime[]
161
-     * @throws EE_Error
162
-     */
163
-    public function datetimes_ordered($show_expired = true, $show_deleted = false, $limit = null)
164
-    {
165
-        return EEM_Datetime::instance($this->_timezone)->get_datetimes_for_event_ordered_by_DTT_order(
166
-            $this->ID(),
167
-            $show_expired,
168
-            $show_deleted,
169
-            $limit
170
-        );
171
-    }
172
-
173
-
174
-    /**
175
-     * Returns one related datetime. Mostly only used by some legacy code.
176
-     *
177
-     * @return EE_Base_Class|EE_Datetime
178
-     * @throws EE_Error
179
-     */
180
-    public function first_datetime()
181
-    {
182
-        return $this->get_first_related('Datetime');
183
-    }
184
-
185
-
186
-    /**
187
-     * Returns the 'primary' datetime for the event
188
-     *
189
-     * @param bool $try_to_exclude_expired
190
-     * @param bool $try_to_exclude_deleted
191
-     * @return EE_Datetime
192
-     * @throws EE_Error
193
-     */
194
-    public function primary_datetime($try_to_exclude_expired = true, $try_to_exclude_deleted = true)
195
-    {
196
-        if (!empty ($this->_Primary_Datetime)) {
197
-            return $this->_Primary_Datetime;
198
-        }
199
-        $this->_Primary_Datetime = EEM_Datetime::instance($this->_timezone)->get_primary_datetime_for_event(
200
-            $this->ID(),
201
-            $try_to_exclude_expired,
202
-            $try_to_exclude_deleted
203
-        );
204
-        return $this->_Primary_Datetime;
205
-    }
206
-
207
-
208
-    /**
209
-     * Gets all the tickets available for purchase of this event
210
-     *
211
-     * @param array $query_params like EEM_Base::get_all
212
-     * @return EE_Base_Class[]|EE_Ticket[]
213
-     * @throws EE_Error
214
-     */
215
-    public function tickets($query_params = array())
216
-    {
217
-        //first get all datetimes
218
-        $datetimes = $this->datetimes_ordered();
219
-        if (!$datetimes) {
220
-            return array();
221
-        }
222
-        $datetime_ids = array();
223
-        foreach ($datetimes as $datetime) {
224
-            $datetime_ids[] = $datetime->ID();
225
-        }
226
-        $where_params = array('Datetime.DTT_ID' => array('IN', $datetime_ids));
227
-        //if incoming $query_params has where conditions let's merge but not override existing.
228
-        if (is_array($query_params) && isset($query_params[0])) {
229
-            $where_params = array_merge($query_params[0], $where_params);
230
-            unset($query_params[0]);
231
-        }
232
-        //now add $where_params to $query_params
233
-        $query_params[0] = $where_params;
234
-        return EEM_Ticket::instance()->get_all($query_params);
235
-    }
236
-
237
-
238
-    /**
239
-     * get all unexpired untrashed tickets
240
-     *
241
-     * @return EE_Ticket[]
242
-     * @throws EE_Error
243
-     */
244
-    public function active_tickets()
245
-    {
246
-        return $this->tickets(array(
247
-            array(
248
-                'TKT_end_date' => array('>=', EEM_Ticket::instance()->current_time_for_query('TKT_end_date')),
249
-                'TKT_deleted' => false,
250
-            ),
251
-        ));
252
-    }
253
-
254
-
255
-    /**
256
-     * @return bool
257
-     * @throws EE_Error
258
-     */
259
-    public function additional_limit()
260
-    {
261
-        return $this->get('EVT_additional_limit');
262
-    }
263
-
264
-
265
-    /**
266
-     * @return bool
267
-     * @throws EE_Error
268
-     */
269
-    public function allow_overflow()
270
-    {
271
-        return $this->get('EVT_allow_overflow');
272
-    }
273
-
274
-
275
-    /**
276
-     * @return bool
277
-     * @throws EE_Error
278
-     */
279
-    public function created()
280
-    {
281
-        return $this->get('EVT_created');
282
-    }
283
-
284
-
285
-    /**
286
-     * @return bool
287
-     * @throws EE_Error
288
-     */
289
-    public function description()
290
-    {
291
-        return $this->get('EVT_desc');
292
-    }
293
-
294
-
295
-    /**
296
-     * Runs do_shortcode and wpautop on the description
297
-     *
298
-     * @return string of html
299
-     * @throws EE_Error
300
-     */
301
-    public function description_filtered()
302
-    {
303
-        return $this->get_pretty('EVT_desc');
304
-    }
305
-
306
-
307
-    /**
308
-     * @return bool
309
-     * @throws EE_Error
310
-     */
311
-    public function display_description()
312
-    {
313
-        return $this->get('EVT_display_desc');
314
-    }
315
-
316
-
317
-    /**
318
-     * @return bool
319
-     * @throws EE_Error
320
-     */
321
-    public function display_ticket_selector()
322
-    {
323
-        return (bool)$this->get('EVT_display_ticket_selector');
324
-    }
325
-
326
-
327
-    /**
328
-     * @return bool
329
-     * @throws EE_Error
330
-     */
331
-    public function external_url()
332
-    {
333
-        return $this->get('EVT_external_URL');
334
-    }
335
-
336
-
337
-    /**
338
-     * @return bool
339
-     * @throws EE_Error
340
-     */
341
-    public function member_only()
342
-    {
343
-        return $this->get('EVT_member_only');
344
-    }
345
-
346
-
347
-    /**
348
-     * @return bool
349
-     * @throws EE_Error
350
-     */
351
-    public function phone()
352
-    {
353
-        return $this->get('EVT_phone');
354
-    }
355
-
356
-
357
-    /**
358
-     * @return bool
359
-     * @throws EE_Error
360
-     */
361
-    public function modified()
362
-    {
363
-        return $this->get('EVT_modified');
364
-    }
365
-
366
-
367
-    /**
368
-     * @return bool
369
-     * @throws EE_Error
370
-     */
371
-    public function name()
372
-    {
373
-        return $this->get('EVT_name');
374
-    }
375
-
376
-
377
-    /**
378
-     * @return bool
379
-     * @throws EE_Error
380
-     */
381
-    public function order()
382
-    {
383
-        return $this->get('EVT_order');
384
-    }
385
-
386
-
387
-    /**
388
-     * @return bool|string
389
-     * @throws EE_Error
390
-     */
391
-    public function default_registration_status()
392
-    {
393
-        $event_default_registration_status = $this->get('EVT_default_registration_status');
394
-        return !empty($event_default_registration_status)
395
-            ? $event_default_registration_status
396
-            : EE_Registry::instance()->CFG->registration->default_STS_ID;
397
-    }
398
-
399
-
400
-    /**
401
-     * @param int $num_words
402
-     * @param null $more
403
-     * @param bool $not_full_desc
404
-     * @return bool|string
405
-     * @throws EE_Error
406
-     */
407
-    public function short_description($num_words = 55, $more = null, $not_full_desc = false)
408
-    {
409
-        $short_desc = $this->get('EVT_short_desc');
410
-        if (!empty($short_desc) || $not_full_desc) {
411
-            return $short_desc;
412
-        }
413
-        $full_desc = $this->get('EVT_desc');
414
-        return wp_trim_words($full_desc, $num_words, $more);
415
-    }
416
-
417
-
418
-    /**
419
-     * @return bool
420
-     * @throws EE_Error
421
-     */
422
-    public function slug()
423
-    {
424
-        return $this->get('EVT_slug');
425
-    }
426
-
427
-
428
-    /**
429
-     * @return bool
430
-     * @throws EE_Error
431
-     */
432
-    public function timezone_string()
433
-    {
434
-        return $this->get('EVT_timezone_string');
435
-    }
436
-
437
-
438
-    /**
439
-     * @return bool
440
-     * @throws EE_Error
441
-     */
442
-    public function visible_on()
443
-    {
444
-        return $this->get('EVT_visible_on');
445
-    }
446
-
447
-
448
-    /**
449
-     * @return int
450
-     * @throws EE_Error
451
-     */
452
-    public function wp_user()
453
-    {
454
-        return $this->get('EVT_wp_user');
455
-    }
456
-
457
-
458
-    /**
459
-     * @return bool
460
-     * @throws EE_Error
461
-     */
462
-    public function donations()
463
-    {
464
-        return $this->get('EVT_donations');
465
-    }
466
-
467
-
468
-    /**
469
-     * @param $limit
470
-     * @throws EE_Error
471
-     */
472
-    public function set_additional_limit($limit)
473
-    {
474
-        $this->set('EVT_additional_limit', $limit);
475
-    }
476
-
477
-
478
-    /**
479
-     * @param $created
480
-     * @throws EE_Error
481
-     */
482
-    public function set_created($created)
483
-    {
484
-        $this->set('EVT_created', $created);
485
-    }
486
-
487
-
488
-    /**
489
-     * @param $desc
490
-     * @throws EE_Error
491
-     */
492
-    public function set_description($desc)
493
-    {
494
-        $this->set('EVT_desc', $desc);
495
-    }
496
-
497
-
498
-    /**
499
-     * @param $display_desc
500
-     * @throws EE_Error
501
-     */
502
-    public function set_display_description($display_desc)
503
-    {
504
-        $this->set('EVT_display_desc', $display_desc);
505
-    }
506
-
507
-
508
-    /**
509
-     * @param $display_ticket_selector
510
-     * @throws EE_Error
511
-     */
512
-    public function set_display_ticket_selector($display_ticket_selector)
513
-    {
514
-        $this->set('EVT_display_ticket_selector', $display_ticket_selector);
515
-    }
516
-
517
-
518
-    /**
519
-     * @param $external_url
520
-     * @throws EE_Error
521
-     */
522
-    public function set_external_url($external_url)
523
-    {
524
-        $this->set('EVT_external_URL', $external_url);
525
-    }
526
-
527
-
528
-    /**
529
-     * @param $member_only
530
-     * @throws EE_Error
531
-     */
532
-    public function set_member_only($member_only)
533
-    {
534
-        $this->set('EVT_member_only', $member_only);
535
-    }
536
-
537
-
538
-    /**
539
-     * @param $event_phone
540
-     * @throws EE_Error
541
-     */
542
-    public function set_event_phone($event_phone)
543
-    {
544
-        $this->set('EVT_phone', $event_phone);
545
-    }
546
-
547
-
548
-    /**
549
-     * @param $modified
550
-     * @throws EE_Error
551
-     */
552
-    public function set_modified($modified)
553
-    {
554
-        $this->set('EVT_modified', $modified);
555
-    }
556
-
557
-
558
-    /**
559
-     * @param $name
560
-     * @throws EE_Error
561
-     */
562
-    public function set_name($name)
563
-    {
564
-        $this->set('EVT_name', $name);
565
-    }
566
-
567
-
568
-    /**
569
-     * @param $order
570
-     * @throws EE_Error
571
-     */
572
-    public function set_order($order)
573
-    {
574
-        $this->set('EVT_order', $order);
575
-    }
576
-
577
-
578
-    /**
579
-     * @param $short_desc
580
-     * @throws EE_Error
581
-     */
582
-    public function set_short_description($short_desc)
583
-    {
584
-        $this->set('EVT_short_desc', $short_desc);
585
-    }
586
-
587
-
588
-    /**
589
-     * @param $slug
590
-     * @throws EE_Error
591
-     */
592
-    public function set_slug($slug)
593
-    {
594
-        $this->set('EVT_slug', $slug);
595
-    }
596
-
597
-
598
-    /**
599
-     * @param $timezone_string
600
-     * @throws EE_Error
601
-     */
602
-    public function set_timezone_string($timezone_string)
603
-    {
604
-        $this->set('EVT_timezone_string', $timezone_string);
605
-    }
606
-
607
-
608
-    /**
609
-     * @param $visible_on
610
-     * @throws EE_Error
611
-     */
612
-    public function set_visible_on($visible_on)
613
-    {
614
-        $this->set('EVT_visible_on', $visible_on);
615
-    }
616
-
617
-
618
-    /**
619
-     * @param $wp_user
620
-     * @throws EE_Error
621
-     */
622
-    public function set_wp_user($wp_user)
623
-    {
624
-        $this->set('EVT_wp_user', $wp_user);
625
-    }
626
-
627
-
628
-    /**
629
-     * @param $default_registration_status
630
-     * @throws EE_Error
631
-     */
632
-    public function set_default_registration_status($default_registration_status)
633
-    {
634
-        $this->set('EVT_default_registration_status', $default_registration_status);
635
-    }
636
-
637
-
638
-    /**
639
-     * @param $donations
640
-     * @throws EE_Error
641
-     */
642
-    public function set_donations($donations)
643
-    {
644
-        $this->set('EVT_donations', $donations);
645
-    }
646
-
647
-
648
-    /**
649
-     * Adds a venue to this event
650
-     *
651
-     * @param EE_Venue /int $venue_id_or_obj
652
-     * @return EE_Base_Class|EE_Venue
653
-     * @throws EE_Error
654
-     */
655
-    public function add_venue($venue_id_or_obj)
656
-    {
657
-        return $this->_add_relation_to($venue_id_or_obj, 'Venue');
658
-    }
659
-
660
-
661
-    /**
662
-     * Removes a venue from the event
663
-     *
664
-     * @param EE_Venue /int $venue_id_or_obj
665
-     * @return EE_Base_Class|EE_Venue
666
-     * @throws EE_Error
667
-     */
668
-    public function remove_venue($venue_id_or_obj)
669
-    {
670
-        return $this->_remove_relation_to($venue_id_or_obj, 'Venue');
671
-    }
672
-
673
-
674
-    /**
675
-     * Gets all the venues related ot the event. May provide additional $query_params if desired
676
-     *
677
-     * @param array $query_params like EEM_Base::get_all's $query_params
678
-     * @return EE_Base_Class[]|EE_Venue[]
679
-     * @throws EE_Error
680
-     */
681
-    public function venues($query_params = array())
682
-    {
683
-        return $this->get_many_related('Venue', $query_params);
684
-    }
685
-
686
-
687
-    /**
688
-     * check if event id is present and if event is published
689
-     *
690
-     * @access public
691
-     * @return boolean true yes, false no
692
-     * @throws EE_Error
693
-     */
694
-    private function _has_ID_and_is_published()
695
-    {
696
-        // first check if event id is present and not NULL,
697
-        // then check if this event is published (or any of the equivalent "published" statuses)
698
-        return
699
-            $this->ID() && $this->ID() !== null
700
-            && (
701
-                $this->status() === 'publish'
702
-                || $this->status() === EEM_Event::sold_out
703
-                || $this->status() === EEM_Event::postponed
704
-                || $this->status() === EEM_Event::cancelled
705
-            );
706
-    }
707
-
708
-
709
-    /**
710
-     * This simply compares the internal dates with NOW and determines if the event is upcoming or not.
711
-     *
712
-     * @access public
713
-     * @return boolean true yes, false no
714
-     * @throws EE_Error
715
-     */
716
-    public function is_upcoming()
717
-    {
718
-        // check if event id is present and if this event is published
719
-        if ($this->is_inactive()) {
720
-            return false;
721
-        }
722
-        // set initial value
723
-        $upcoming = false;
724
-        //next let's get all datetimes and loop through them
725
-        $datetimes = $this->datetimes_in_chronological_order();
726
-        foreach ($datetimes as $datetime) {
727
-            if ($datetime instanceof EE_Datetime) {
728
-                //if this dtt is expired then we continue cause one of the other datetimes might be upcoming.
729
-                if ($datetime->is_expired()) {
730
-                    continue;
731
-                }
732
-                //if this dtt is active then we return false.
733
-                if ($datetime->is_active()) {
734
-                    return false;
735
-                }
736
-                //otherwise let's check upcoming status
737
-                $upcoming = $datetime->is_upcoming();
738
-            }
739
-        }
740
-        return $upcoming;
741
-    }
742
-
743
-
744
-    /**
745
-     * @return bool
746
-     * @throws EE_Error
747
-     */
748
-    public function is_active()
749
-    {
750
-        // check if event id is present and if this event is published
751
-        if ($this->is_inactive()) {
752
-            return false;
753
-        }
754
-        // set initial value
755
-        $active = false;
756
-        //next let's get all datetimes and loop through them
757
-        $datetimes = $this->datetimes_in_chronological_order();
758
-        foreach ($datetimes as $datetime) {
759
-            if ($datetime instanceof EE_Datetime) {
760
-                //if this dtt is expired then we continue cause one of the other datetimes might be active.
761
-                if ($datetime->is_expired()) {
762
-                    continue;
763
-                }
764
-                //if this dtt is upcoming then we return false.
765
-                if ($datetime->is_upcoming()) {
766
-                    return false;
767
-                }
768
-                //otherwise let's check active status
769
-                $active = $datetime->is_active();
770
-            }
771
-        }
772
-        return $active;
773
-    }
774
-
775
-
776
-    /**
777
-     * @return bool
778
-     * @throws EE_Error
779
-     */
780
-    public function is_expired()
781
-    {
782
-        // check if event id is present and if this event is published
783
-        if ($this->is_inactive()) {
784
-            return false;
785
-        }
786
-        // set initial value
787
-        $expired = false;
788
-        //first let's get all datetimes and loop through them
789
-        $datetimes = $this->datetimes_in_chronological_order();
790
-        foreach ($datetimes as $datetime) {
791
-            if ($datetime instanceof EE_Datetime) {
792
-                //if this dtt is upcoming or active then we return false.
793
-                if ($datetime->is_upcoming() || $datetime->is_active()) {
794
-                    return false;
795
-                }
796
-                //otherwise let's check active status
797
-                $expired = $datetime->is_expired();
798
-            }
799
-        }
800
-        return $expired;
801
-    }
802
-
803
-
804
-    /**
805
-     * @return bool
806
-     * @throws EE_Error
807
-     */
808
-    public function is_inactive()
809
-    {
810
-        // check if event id is present and if this event is published
811
-        if ($this->_has_ID_and_is_published()) {
812
-            return false;
813
-        }
814
-        return true;
815
-    }
816
-
817
-
818
-    /**
819
-     * calculate spaces remaining based on "saleable" tickets
820
-     *
821
-     * @param array $tickets
822
-     * @param bool $filtered
823
-     * @return int|float
824
-     * @throws EE_Error
825
-     */
826
-    public function spaces_remaining($tickets = array(), $filtered = true)
827
-    {
828
-        // get all unexpired untrashed tickets if nothing was passed
829
-        $tickets = !empty($tickets) ? $tickets : $this->active_tickets();
830
-        // set initial value
831
-        $spaces_remaining = 0;
832
-        if (!empty($tickets)) {
833
-            foreach ($tickets as $ticket) {
834
-                if ($ticket instanceof EE_Ticket) {
835
-                    $spaces_remaining += $ticket->qty('saleable');
836
-                }
837
-            }
838
-        }
839
-        return $filtered
840
-            ? apply_filters(
841
-                'FHEE_EE_Event__spaces_remaining',
842
-                $spaces_remaining,
843
-                $this,
844
-                $tickets
845
-            )
846
-            : $spaces_remaining;
847
-    }
848
-
849
-
850
-    /**
851
-     *    perform_sold_out_status_check
852
-     *    checks all of this events's datetime  reg_limit - sold values to determine if ANY datetimes have spaces available...
853
-     *    if NOT, then the event status will get toggled to 'sold_out'
854
-     *
855
-     * @access public
856
-     * @return bool    return the ACTUAL sold out state.
857
-     * @throws EE_Error
858
-     */
859
-    public function perform_sold_out_status_check()
860
-    {
861
-        // get all unexpired untrashed tickets
862
-        $tickets = $this->active_tickets();
863
-        // if all the tickets are just expired, then don't update the event status to sold out
864
-        if (empty($tickets)) {
865
-            return true;
866
-        }
867
-        $spaces_remaining = $this->spaces_remaining($tickets);
868
-        if ($spaces_remaining < 1) {
869
-            $this->set_status(EEM_Event::sold_out);
870
-            $this->save();
871
-            $sold_out = true;
872
-        } else {
873
-            $sold_out = false;
874
-            // was event previously marked as sold out ?
875
-            if ($this->status() === EEM_Event::sold_out) {
876
-                // revert status to previous value, if it was set
877
-                $previous_event_status = $this->get_post_meta('_previous_event_status', true);
878
-                if ($previous_event_status) {
879
-                    $this->set_status($previous_event_status);
880
-                    $this->save();
881
-                }
882
-            }
883
-        }
884
-        do_action('AHEE__EE_Event__perform_sold_out_status_check__end', $this, $sold_out, $spaces_remaining, $tickets);
885
-        return $sold_out;
886
-    }
887
-
888
-
889
-    /**
890
-     * This returns the total remaining spaces for sale on this event.
891
-     * ############################
892
-     * VERY IMPORTANT FOR DEVELOPERS:
893
-     * While included here, this method is still being tested internally, so its signature and behaviour COULD change.
894
-     * While this comment block is in place, usage is at your own risk and know that it may change in future builds.
895
-     * ############################
896
-     *
897
-     * @uses EE_Event::total_available_spaces()
898
-     * @return float|int  (EE_INF is returned as float)
899
-     * @throws InvalidArgumentException
900
-     * @throws InvalidStatusException
901
-     * @throws EE_Error
902
-     */
903
-    public function spaces_remaining_for_sale()
904
-    {
905
-        //first get total available spaces including consideration for tickets that have already sold.
906
-        $spaces_available = $this->total_available_spaces(true);
907
-        //if total available = 0, then exit right away because that means everything is expired.
908
-        if ($spaces_available === 0) {
909
-            return 0;
910
-        }
911
-        //subtract total approved registrations from spaces available to get how many are remaining.
912
-        $spots_taken = EEM_Registration::instance()->event_reg_count_for_statuses($this->ID());
913
-        $spaces_remaining = $spaces_available - $spots_taken;
914
-        return $spaces_remaining > 0 ? $spaces_remaining : 0;
915
-    }
916
-
917
-
918
-    /**
919
-     * This returns the total spaces available for an event while considering all the qtys on the tickets and the reg limits
920
-     * on the datetimes attached to this event.
921
-     * ############################
922
-     * VERY IMPORTANT FOR DEVELOPERS:
923
-     * While included here, this method is still being tested internally, so its signature and behaviour COULD change. While
924
-     * this comment block is in place, usage is at your own risk and know that it may change in future builds.
925
-     * ############################
926
-     * Note: by "spaces available" we are not returning how many spaces remain.  That is a calculation involving using the value
927
-     * from this method and subtracting the approved registrations for the event.
928
-     *
929
-     * @param   bool $current_total_available Whether to consider any tickets that have already sold in our calculation.
930
-     *                                              If this is false, then we return the most tickets that could ever be sold
931
-     *                                              for this event with the datetime and tickets setup on the event under optimal
932
-     *                                              selling conditions.  Otherwise we return a live calculation of spaces available
933
-     *                                              based on tickets sold.  Depending on setup and stage of sales, this
934
-     *                                              may appear to equal remaining tickets.  However, the more tickets are
935
-     *                                              sold out, the more accurate the "live" total is.
936
-     * @return  int|float  (Note: if EE_INF is returned its considered a float by PHP)
937
-     * @throws EE_Error
938
-     */
939
-    public function total_available_spaces($current_total_available = false)
940
-    {
941
-        $spaces_available = 0;
942
-        //first get all tickets on the event and include expired tickets
943
-        $tickets = $this->tickets(array('default_where_conditions' => 'none'));
944
-        $ticket_sums = array();
945
-        $datetimes = array();
946
-        $datetime_limits = array();
947
-        //loop through tickets and normalize them
948
-        foreach ($tickets as $ticket) {
949
-            $datetimes = $ticket->datetimes(array('order_by' => array('DTT_reg_limit' => 'ASC')));
950
-            if (empty($datetimes)) {
951
-                continue;
952
-            }
953
-            //first datetime should be the lowest datetime
954
-            $least_datetime = reset($datetimes);
955
-            //lets reset the ticket quantity to be the lower of either the lowest datetime reg limit or the ticket quantity
956
-            //IF datetimes sold (and we're not doing current live total available, then use spaces remaining for datetime, not reg_limit.
957
-            if ($current_total_available) {
958
-                if ($ticket->is_remaining()) {
959
-                    $remaining = $ticket->remaining();
960
-                } else {
961
-                    $spaces_available += $ticket->sold();
962
-                    //and we don't cache this ticket to our list because its sold out.
963
-                    continue;
964
-                }
965
-            } else {
966
-                $remaining = min($ticket->qty(), $least_datetime->reg_limit());
967
-            }
968
-            //if $ticket_limit == infinity then let's drop out right away and just return that because any infinity amount trumps all other "available" amounts.
969
-            if ($remaining === EE_INF) {
970
-                return EE_INF;
971
-            }
972
-            //multiply normalized $tkt quantity by the number of datetimes on the ticket as the "sum"
973
-            //also include the sum of all the datetime reg limits on the ticket for breaking ties.
974
-            $ticket_sums[$ticket->ID()]['sum'] = $remaining * count($datetimes);
975
-            $ticket_sums[$ticket->ID()]['datetime_sums'] = 0;
976
-            foreach ($datetimes as $datetime) {
977
-                if ($datetime->reg_limit() === EE_INF) {
978
-                    $ticket_sums[$ticket->ID()]['datetime_sums'] = EE_INF;
979
-                } else {
980
-                    $ticket_sums[$ticket->ID()]['datetime_sums'] += $current_total_available
981
-                        ? $datetime->spaces_remaining()
982
-                        : $datetime->reg_limit();
983
-                }
984
-                $datetime_limits[$datetime->ID()] = $current_total_available
985
-                    ? $datetime->spaces_remaining()
986
-                    : $datetime->reg_limit();
987
-            }
988
-            $ticket_sums[$ticket->ID()]['ticket'] = $ticket;
989
-        }
990
-        //The order is sorted by lowest available first (which is calculated for each ticket by multiplying the normalized
991
-        //ticket quantity by the number of datetimes on the ticket).  For tie-breakers, then the next sort is based on the
992
-        //ticket with the greatest sum of all remaining datetime->spaces_remaining() ( or $datetime->reg_limit() if not
993
-        //$current_total_available ) for the datetimes on the ticket.
994
-        usort($ticket_sums, function ($a, $b) {
995
-            if ($a['sum'] === $b['sum']) {
996
-                if ($a['datetime_sums'] === $b['datetime_sums']) {
997
-                    return 0;
998
-                }
999
-                return $a['datetime_sums'] < $b['datetime_sums'] ? 1 : -1;
1000
-            }
1001
-            return ($a['sum'] < $b['sum']) ? -1 : 1;
1002
-        });
1003
-        //now let's loop through the sorted tickets and simulate sellouts
1004
-        foreach ($ticket_sums as $ticket_info) {
1005
-            if ($ticket_info['ticket'] instanceof EE_Ticket) {
1006
-                $datetimes = $ticket_info['ticket']->datetimes(array('order_by' => array('DTT_reg_limit' => 'ASC')));
1007
-                //need to sort these $datetimes by remaining (only if $current_total_available)
1008
-                //setup datetimes for simulation
1009
-                $ticket_datetimes_remaining = array();
1010
-                foreach ($datetimes as $datetime) {
1011
-                    $DTT_ID = $datetime->ID();
1012
-                    $ticket_datetimes_remaining[$DTT_ID]['rem'] = $datetime_limits[$DTT_ID];
1013
-                    $ticket_datetimes_remaining[$DTT_ID]['datetime'] = $datetime;
1014
-                }
1015
-                usort($ticket_datetimes_remaining, function ($a, $b) {
1016
-                    if ($a['rem'] === $b['rem']) {
1017
-                        return 0;
1018
-                    }
1019
-                    return ($a['rem'] < $b['rem']) ? -1 : 1;
1020
-                });
1021
-                //get the remaining on the first datetime (which should be the one with the least remaining) and that is
1022
-                //what we add to the spaces_available running total.  Then we need to decrease the remaining on our datetime tracker.
1023
-                $lowest_datetime = reset($ticket_datetimes_remaining);
1024
-                //need to get the lower of; what the remaining is on the lowest datetime, and the remaining on the ticket.
1025
-                // If this ends up being 0 (because of previous tickets in our simulation selling out), then it has already
1026
-                // been tracked on $spaces available and this ticket is now sold out for the simulation, so we can continue
1027
-                // to the next ticket.
1028
-                if ($current_total_available) {
1029
-                    $remaining = min($lowest_datetime['rem'], $ticket_info['ticket']->remaining());
1030
-                } else {
1031
-                    $remaining = min($lowest_datetime['rem'], $ticket_info['ticket']->qty());
1032
-                }
1033
-                //if $remaining is infinite that means that all datetimes on this ticket are infinite but we've made it here because all
1034
-                //tickets have a quantity.  So we don't have to track datetimes, we can just use ticket quantities for total
1035
-                //available.
1036
-                if ($remaining === EE_INF) {
1037
-                    $spaces_available += $ticket_info['ticket']->qty();
1038
-                    continue;
1039
-                }
1040
-                //if ticket has sold amounts then we also need to add that (but only if doing live counts)
1041
-                if ($current_total_available) {
1042
-                    $spaces_available += $ticket_info['ticket']->sold();
1043
-                }
1044
-                if ($remaining <= 0) {
1045
-                    continue;
1046
-                }
1047
-                $spaces_available += $remaining;
1048
-                //loop through the datetimes and sell them out!
1049
-                foreach ($ticket_datetimes_remaining as $datetime_info) {
1050
-                    if ($datetime_info['datetime'] instanceof EE_Datetime) {
1051
-                        $datetime_limits[$datetime_info['datetime']->ID()] += -$remaining;
1052
-                    }
1053
-                }
1054
-            }
1055
-        }
1056
-        return apply_filters(
1057
-            'FHEE_EE_Event__total_available_spaces__spaces_available',
1058
-            $spaces_available,
1059
-            $this,
1060
-            $datetimes,
1061
-            $tickets
1062
-        );
1063
-    }
1064
-
1065
-
1066
-    /**
1067
-     * Checks if the event is set to sold out
1068
-     *
1069
-     * @param  bool $actual whether or not to perform calculations to not only figure the
1070
-     *                      actual status but also to flip the status if necessary to sold
1071
-     *                      out If false, we just check the existing status of the event
1072
-     * @return boolean
1073
-     * @throws EE_Error
1074
-     */
1075
-    public function is_sold_out($actual = false)
1076
-    {
1077
-        if (!$actual) {
1078
-            return $this->status() === EEM_Event::sold_out;
1079
-        }
1080
-        return $this->perform_sold_out_status_check();
1081
-    }
1082
-
1083
-
1084
-    /**
1085
-     * Checks if the event is marked as postponed
1086
-     *
1087
-     * @return boolean
1088
-     */
1089
-    public function is_postponed()
1090
-    {
1091
-        return $this->status() === EEM_Event::postponed;
1092
-    }
1093
-
1094
-
1095
-    /**
1096
-     * Checks if the event is marked as cancelled
1097
-     *
1098
-     * @return boolean
1099
-     */
1100
-    public function is_cancelled()
1101
-    {
1102
-        return $this->status() === EEM_Event::cancelled;
1103
-    }
1104
-
1105
-
1106
-    /**
1107
-     * Get the logical active status in a hierarchical order for all the datetimes.  Note
1108
-     * Basically, we order the datetimes by EVT_start_date.  Then first test on whether the event is published.  If its
1109
-     * NOT published then we test for whether its expired or not.  IF it IS published then we test first on whether an
1110
-     * event has any active dates.  If no active dates then we check for any upcoming dates.  If no upcoming dates then
1111
-     * the event is considered expired.
1112
-     * NOTE: this method does NOT calculate whether the datetimes are sold out when event is published.  Sold Out is a status
1113
-     * set on the EVENT when it is not published and thus is done
1114
-     *
1115
-     * @param bool $reset
1116
-     * @return bool | string - based on EE_Datetime active constants or FALSE if error.
1117
-     * @throws EE_Error
1118
-     */
1119
-    public function get_active_status($reset = false)
1120
-    {
1121
-        // if the active status has already been set, then just use that value (unless we are resetting it)
1122
-        if (!empty($this->_active_status) && !$reset) {
1123
-            return $this->_active_status;
1124
-        }
1125
-        //first check if event id is present on this object
1126
-        if (!$this->ID()) {
1127
-            return false;
1128
-        }
1129
-        $where_params_for_event = array(array('EVT_ID' => $this->ID()));
1130
-        //if event is published:
1131
-        if ($this->status() === 'publish') {
1132
-            //active?
1133
-            if (EEM_Datetime::instance()->get_datetime_count_for_status(EE_Datetime::active, $where_params_for_event) > 0) {
1134
-                $this->_active_status = EE_Datetime::active;
1135
-            } else {
1136
-                //upcoming?
1137
-                if (EEM_Datetime::instance()->get_datetime_count_for_status(EE_Datetime::upcoming, $where_params_for_event) > 0) {
1138
-                    $this->_active_status = EE_Datetime::upcoming;
1139
-                } else {
1140
-                    //expired?
1141
-                    if (
1142
-                        EEM_Datetime::instance()->get_datetime_count_for_status(EE_Datetime::expired, $where_params_for_event) > 0
1143
-                    ) {
1144
-                        $this->_active_status = EE_Datetime::expired;
1145
-                    } else {
1146
-                        //it would be odd if things make it this far because it basically means there are no datetime's
1147
-                        //attached to the event.  So in this case it will just be considered inactive.
1148
-                        $this->_active_status = EE_Datetime::inactive;
1149
-                    }
1150
-                }
1151
-            }
1152
-        } else {
1153
-            //the event is not published, so let's just set it's active status according to its' post status
1154
-            switch ($this->status()) {
1155
-                case EEM_Event::sold_out :
1156
-                    $this->_active_status = EE_Datetime::sold_out;
1157
-                    break;
1158
-                case EEM_Event::cancelled :
1159
-                    $this->_active_status = EE_Datetime::cancelled;
1160
-                    break;
1161
-                case EEM_Event::postponed :
1162
-                    $this->_active_status = EE_Datetime::postponed;
1163
-                    break;
1164
-                default :
1165
-                    $this->_active_status = EE_Datetime::inactive;
1166
-            }
1167
-        }
1168
-        return $this->_active_status;
1169
-    }
1170
-
1171
-
1172
-    /**
1173
-     *    pretty_active_status
1174
-     *
1175
-     * @access public
1176
-     * @param boolean $echo whether to return (FALSE), or echo out the result (TRUE)
1177
-     * @return mixed void|string
1178
-     * @throws EE_Error
1179
-     */
1180
-    public function pretty_active_status($echo = true)
1181
-    {
1182
-        $active_status = $this->get_active_status();
1183
-        $status = '<span class="ee-status event-active-status-'
1184
-            . $active_status
1185
-            . '">'
1186
-            . EEH_Template::pretty_status($active_status, false, 'sentence')
1187
-            . '</span>';
1188
-        if ($echo) {
1189
-            echo $status;
1190
-            return '';
1191
-        }
1192
-        return $status;
1193
-    }
1194
-
1195
-
1196
-    /**
1197
-     * @return bool|int
1198
-     * @throws EE_Error
1199
-     */
1200
-    public function get_number_of_tickets_sold()
1201
-    {
1202
-        $tkt_sold = 0;
1203
-        if (!$this->ID()) {
1204
-            return 0;
1205
-        }
1206
-        $datetimes = $this->datetimes();
1207
-        foreach ($datetimes as $datetime) {
1208
-            if ($datetime instanceof EE_Datetime) {
1209
-                $tkt_sold += $datetime->sold();
1210
-            }
1211
-        }
1212
-        return $tkt_sold;
1213
-    }
1214
-
1215
-
1216
-    /**
1217
-     * This just returns a count of all the registrations for this event
1218
-     *
1219
-     * @access  public
1220
-     * @return int
1221
-     * @throws EE_Error
1222
-     */
1223
-    public function get_count_of_all_registrations()
1224
-    {
1225
-        return EEM_Event::instance()->count_related($this, 'Registration');
1226
-    }
1227
-
1228
-
1229
-    /**
1230
-     * This returns the ticket with the earliest start time that is
1231
-     * available for this event (across all datetimes attached to the event)
1232
-     *
1233
-     * @return EE_Base_Class|EE_Ticket|null
1234
-     * @throws EE_Error
1235
-     */
1236
-    public function get_ticket_with_earliest_start_time()
1237
-    {
1238
-        $where['Datetime.EVT_ID'] = $this->ID();
1239
-        $query_params = array($where, 'order_by' => array('TKT_start_date' => 'ASC'));
1240
-        return EE_Registry::instance()->load_model('Ticket')->get_one($query_params);
1241
-    }
1242
-
1243
-
1244
-    /**
1245
-     * This returns the ticket with the latest end time that is available
1246
-     * for this event (across all datetimes attached to the event)
1247
-     *
1248
-     * @return EE_Base_Class|EE_Ticket|null
1249
-     * @throws EE_Error
1250
-     */
1251
-    public function get_ticket_with_latest_end_time()
1252
-    {
1253
-        $where['Datetime.EVT_ID'] = $this->ID();
1254
-        $query_params = array($where, 'order_by' => array('TKT_end_date' => 'DESC'));
1255
-        return EE_Registry::instance()->load_model('Ticket')->get_one($query_params);
1256
-    }
1257
-
1258
-
1259
-    /**
1260
-     * This returns whether there are any tickets on sale for this event.
1261
-     *
1262
-     * @return bool true = YES tickets on sale.
1263
-     * @throws EE_Error
1264
-     */
1265
-    public function tickets_on_sale()
1266
-    {
1267
-        $earliest_ticket = $this->get_ticket_with_earliest_start_time();
1268
-        $latest_ticket = $this->get_ticket_with_latest_end_time();
1269
-        if (!$latest_ticket instanceof EE_Ticket && !$earliest_ticket instanceof EE_Ticket) {
1270
-            return false;
1271
-        }
1272
-        //check on sale for these two tickets.
1273
-        if ($latest_ticket->is_on_sale() || $earliest_ticket->is_on_sale()) {
1274
-            return true;
1275
-        }
1276
-        return false;
1277
-    }
1278
-
1279
-
1280
-    /**
1281
-     * Gets the URL for viewing this event on the front-end. Overrides parent
1282
-     * to check for an external URL first
1283
-     *
1284
-     * @return string
1285
-     * @throws EE_Error
1286
-     */
1287
-    public function get_permalink()
1288
-    {
1289
-        if ($this->external_url()) {
1290
-            return $this->external_url();
1291
-        }
1292
-        return parent::get_permalink();
1293
-    }
1294
-
1295
-
1296
-    /**
1297
-     * Gets the first term for 'espresso_event_categories' we can find
1298
-     *
1299
-     * @param array $query_params like EEM_Base::get_all
1300
-     * @return EE_Base_Class|EE_Term|null
1301
-     * @throws EE_Error
1302
-     */
1303
-    public function first_event_category($query_params = array())
1304
-    {
1305
-        $query_params[0]['Term_Taxonomy.taxonomy'] = 'espresso_event_categories';
1306
-        $query_params[0]['Term_Taxonomy.Event.EVT_ID'] = $this->ID();
1307
-        return EEM_Term::instance()->get_one($query_params);
1308
-    }
1309
-
1310
-
1311
-    /**
1312
-     * Gets all terms for 'espresso_event_categories' we can find
1313
-     *
1314
-     * @param array $query_params
1315
-     * @return EE_Base_Class[]|EE_Term[]
1316
-     * @throws EE_Error
1317
-     */
1318
-    public function get_all_event_categories($query_params = array())
1319
-    {
1320
-        $query_params[0]['Term_Taxonomy.taxonomy'] = 'espresso_event_categories';
1321
-        $query_params[0]['Term_Taxonomy.Event.EVT_ID'] = $this->ID();
1322
-        return EEM_Term::instance()->get_all($query_params);
1323
-    }
1324
-
1325
-
1326
-    /**
1327
-     * Gets all the question groups, ordering them by QSG_order ascending
1328
-     *
1329
-     * @param array $query_params @see EEM_Base::get_all
1330
-     * @return EE_Base_Class[]|EE_Question_Group[]
1331
-     * @throws EE_Error
1332
-     */
1333
-    public function question_groups($query_params = array())
1334
-    {
1335
-        $query_params = !empty($query_params) ? $query_params : array('order_by' => array('QSG_order' => 'ASC'));
1336
-        return $this->get_many_related('Question_Group', $query_params);
1337
-    }
1338
-
1339
-
1340
-    /**
1341
-     * Implementation for EEI_Has_Icon interface method.
1342
-     *
1343
-     * @see EEI_Visual_Representation for comments
1344
-     * @return string
1345
-     */
1346
-    public function get_icon()
1347
-    {
1348
-        return '<span class="dashicons dashicons-flag"></span>';
1349
-    }
1350
-
1351
-
1352
-    /**
1353
-     * Implementation for EEI_Admin_Links interface method.
1354
-     *
1355
-     * @see EEI_Admin_Links for comments
1356
-     * @return string
1357
-     * @throws EE_Error
1358
-     */
1359
-    public function get_admin_details_link()
1360
-    {
1361
-        return $this->get_admin_edit_link();
1362
-    }
1363
-
1364
-
1365
-    /**
1366
-     * Implementation for EEI_Admin_Links interface method.
1367
-     *
1368
-     * @see EEI_Admin_Links for comments
1369
-     * @return string
1370
-     * @throws EE_Error
1371
-     */
1372
-    public function get_admin_edit_link()
1373
-    {
1374
-        return EEH_URL::add_query_args_and_nonce(array(
1375
-            'page' => 'espresso_events',
1376
-            'action' => 'edit',
1377
-            'post' => $this->ID(),
1378
-        ),
1379
-            admin_url('admin.php')
1380
-        );
1381
-    }
1382
-
1383
-
1384
-    /**
1385
-     * Implementation for EEI_Admin_Links interface method.
1386
-     *
1387
-     * @see EEI_Admin_Links for comments
1388
-     * @return string
1389
-     */
1390
-    public function get_admin_settings_link()
1391
-    {
1392
-        return EEH_URL::add_query_args_and_nonce(array(
1393
-            'page' => 'espresso_events',
1394
-            'action' => 'default_event_settings',
1395
-        ),
1396
-            admin_url('admin.php')
1397
-        );
1398
-    }
1399
-
1400
-
1401
-    /**
1402
-     * Implementation for EEI_Admin_Links interface method.
1403
-     *
1404
-     * @see EEI_Admin_Links for comments
1405
-     * @return string
1406
-     */
1407
-    public function get_admin_overview_link()
1408
-    {
1409
-        return EEH_URL::add_query_args_and_nonce(array(
1410
-            'page' => 'espresso_events',
1411
-            'action' => 'default',
1412
-        ),
1413
-            admin_url('admin.php')
1414
-        );
1415
-    }
18
+	/**
19
+	 * cached value for the the logical active status for the event
20
+	 *
21
+	 * @see get_active_status()
22
+	 * @var string
23
+	 */
24
+	protected $_active_status = '';
25
+
26
+	/**
27
+	 * This is just used for caching the Primary Datetime for the Event on initial retrieval
28
+	 *
29
+	 * @var EE_Datetime
30
+	 */
31
+	protected $_Primary_Datetime;
32
+
33
+
34
+	/**
35
+	 * @param array $props_n_values incoming values
36
+	 * @param string $timezone incoming timezone (if not set the timezone set for the website will be
37
+	 *                                        used.)
38
+	 * @param array $date_formats incoming date_formats in an array where the first value is the
39
+	 *                                        date_format and the second value is the time format
40
+	 * @return EE_Event
41
+	 * @throws EE_Error
42
+	 */
43
+	public static function new_instance($props_n_values = array(), $timezone = null, $date_formats = array())
44
+	{
45
+		$has_object = parent::_check_for_object($props_n_values, __CLASS__, $timezone, $date_formats);
46
+		return $has_object ? $has_object : new self($props_n_values, false, $timezone, $date_formats);
47
+	}
48
+
49
+
50
+	/**
51
+	 * @param array $props_n_values incoming values from the database
52
+	 * @param string $timezone incoming timezone as set by the model.  If not set the timezone for
53
+	 *                                the website will be used.
54
+	 * @return EE_Event
55
+	 * @throws EE_Error
56
+	 */
57
+	public static function new_instance_from_db($props_n_values = array(), $timezone = null)
58
+	{
59
+		return new self($props_n_values, true, $timezone);
60
+	}
61
+
62
+
63
+	/**
64
+	 * Overrides parent set() method so that all calls to set( 'status', $status ) can be routed to internal methods
65
+	 *
66
+	 * @param string $field_name
67
+	 * @param mixed $field_value
68
+	 * @param bool $use_default
69
+	 * @throws EE_Error
70
+	 */
71
+	public function set($field_name, $field_value, $use_default = false)
72
+	{
73
+		switch ($field_name) {
74
+			case 'status' :
75
+				$this->set_status($field_value, $use_default);
76
+				break;
77
+			default :
78
+				parent::set($field_name, $field_value, $use_default);
79
+		}
80
+	}
81
+
82
+
83
+	/**
84
+	 *    set_status
85
+	 * Checks if event status is being changed to SOLD OUT
86
+	 * and updates event meta data with previous event status
87
+	 * so that we can revert things if/when the event is no longer sold out
88
+	 *
89
+	 * @access public
90
+	 * @param string $new_status
91
+	 * @param bool $use_default
92
+	 * @return void
93
+	 * @throws EE_Error
94
+	 */
95
+	public function set_status($new_status = null, $use_default = false)
96
+	{
97
+		// if nothing is set, and we aren't explicitly wanting to reset the status, then just leave
98
+		if (empty($new_status) && !$use_default) {
99
+			return;
100
+		}
101
+		// get current Event status
102
+		$old_status = $this->status();
103
+		// if status has changed
104
+		if ($old_status !== $new_status) {
105
+			// TO sold_out
106
+			if ($new_status === EEM_Event::sold_out) {
107
+				// save the previous event status so that we can revert if the event is no longer sold out
108
+				$this->add_post_meta('_previous_event_status', $old_status);
109
+				do_action('AHEE__EE_Event__set_status__to_sold_out', $this, $old_status, $new_status);
110
+				// OR FROM  sold_out
111
+			} else if ($old_status === EEM_Event::sold_out) {
112
+				$this->delete_post_meta('_previous_event_status');
113
+				do_action('AHEE__EE_Event__set_status__from_sold_out', $this, $old_status, $new_status);
114
+			}
115
+			// update status
116
+			parent::set('status', $new_status, $use_default);
117
+			do_action('AHEE__EE_Event__set_status__after_update', $this);
118
+			return;
119
+		}
120
+		// even though the old value matches the new value, it's still good to
121
+		// allow the parent set method to have a say
122
+		parent::set('status', $new_status, $use_default);
123
+	}
124
+
125
+
126
+	/**
127
+	 * Gets all the datetimes for this event
128
+	 *
129
+	 * @param array $query_params like EEM_Base::get_all
130
+	 * @return EE_Base_Class[]|EE_Datetime[]
131
+	 * @throws EE_Error
132
+	 */
133
+	public function datetimes($query_params = array())
134
+	{
135
+		return $this->get_many_related('Datetime', $query_params);
136
+	}
137
+
138
+
139
+	/**
140
+	 * Gets all the datetimes for this event, ordered by DTT_EVT_start in ascending order
141
+	 *
142
+	 * @return EE_Base_Class[]|EE_Datetime[]
143
+	 * @throws EE_Error
144
+	 */
145
+	public function datetimes_in_chronological_order()
146
+	{
147
+		return $this->get_many_related('Datetime', array('order_by' => array('DTT_EVT_start' => 'ASC')));
148
+	}
149
+
150
+
151
+	/**
152
+	 * Gets all the datetimes for this event, ordered by the DTT_order on the datetime.
153
+	 * @darren, we should probably UNSET timezone on the EEM_Datetime model
154
+	 * after running our query, so that this timezone isn't set for EVERY query
155
+	 * on EEM_Datetime for the rest of the request, no?
156
+	 *
157
+	 * @param boolean $show_expired whether or not to include expired events
158
+	 * @param boolean $show_deleted whether or not to include deleted events
159
+	 * @param null $limit
160
+	 * @return EE_Datetime[]
161
+	 * @throws EE_Error
162
+	 */
163
+	public function datetimes_ordered($show_expired = true, $show_deleted = false, $limit = null)
164
+	{
165
+		return EEM_Datetime::instance($this->_timezone)->get_datetimes_for_event_ordered_by_DTT_order(
166
+			$this->ID(),
167
+			$show_expired,
168
+			$show_deleted,
169
+			$limit
170
+		);
171
+	}
172
+
173
+
174
+	/**
175
+	 * Returns one related datetime. Mostly only used by some legacy code.
176
+	 *
177
+	 * @return EE_Base_Class|EE_Datetime
178
+	 * @throws EE_Error
179
+	 */
180
+	public function first_datetime()
181
+	{
182
+		return $this->get_first_related('Datetime');
183
+	}
184
+
185
+
186
+	/**
187
+	 * Returns the 'primary' datetime for the event
188
+	 *
189
+	 * @param bool $try_to_exclude_expired
190
+	 * @param bool $try_to_exclude_deleted
191
+	 * @return EE_Datetime
192
+	 * @throws EE_Error
193
+	 */
194
+	public function primary_datetime($try_to_exclude_expired = true, $try_to_exclude_deleted = true)
195
+	{
196
+		if (!empty ($this->_Primary_Datetime)) {
197
+			return $this->_Primary_Datetime;
198
+		}
199
+		$this->_Primary_Datetime = EEM_Datetime::instance($this->_timezone)->get_primary_datetime_for_event(
200
+			$this->ID(),
201
+			$try_to_exclude_expired,
202
+			$try_to_exclude_deleted
203
+		);
204
+		return $this->_Primary_Datetime;
205
+	}
206
+
207
+
208
+	/**
209
+	 * Gets all the tickets available for purchase of this event
210
+	 *
211
+	 * @param array $query_params like EEM_Base::get_all
212
+	 * @return EE_Base_Class[]|EE_Ticket[]
213
+	 * @throws EE_Error
214
+	 */
215
+	public function tickets($query_params = array())
216
+	{
217
+		//first get all datetimes
218
+		$datetimes = $this->datetimes_ordered();
219
+		if (!$datetimes) {
220
+			return array();
221
+		}
222
+		$datetime_ids = array();
223
+		foreach ($datetimes as $datetime) {
224
+			$datetime_ids[] = $datetime->ID();
225
+		}
226
+		$where_params = array('Datetime.DTT_ID' => array('IN', $datetime_ids));
227
+		//if incoming $query_params has where conditions let's merge but not override existing.
228
+		if (is_array($query_params) && isset($query_params[0])) {
229
+			$where_params = array_merge($query_params[0], $where_params);
230
+			unset($query_params[0]);
231
+		}
232
+		//now add $where_params to $query_params
233
+		$query_params[0] = $where_params;
234
+		return EEM_Ticket::instance()->get_all($query_params);
235
+	}
236
+
237
+
238
+	/**
239
+	 * get all unexpired untrashed tickets
240
+	 *
241
+	 * @return EE_Ticket[]
242
+	 * @throws EE_Error
243
+	 */
244
+	public function active_tickets()
245
+	{
246
+		return $this->tickets(array(
247
+			array(
248
+				'TKT_end_date' => array('>=', EEM_Ticket::instance()->current_time_for_query('TKT_end_date')),
249
+				'TKT_deleted' => false,
250
+			),
251
+		));
252
+	}
253
+
254
+
255
+	/**
256
+	 * @return bool
257
+	 * @throws EE_Error
258
+	 */
259
+	public function additional_limit()
260
+	{
261
+		return $this->get('EVT_additional_limit');
262
+	}
263
+
264
+
265
+	/**
266
+	 * @return bool
267
+	 * @throws EE_Error
268
+	 */
269
+	public function allow_overflow()
270
+	{
271
+		return $this->get('EVT_allow_overflow');
272
+	}
273
+
274
+
275
+	/**
276
+	 * @return bool
277
+	 * @throws EE_Error
278
+	 */
279
+	public function created()
280
+	{
281
+		return $this->get('EVT_created');
282
+	}
283
+
284
+
285
+	/**
286
+	 * @return bool
287
+	 * @throws EE_Error
288
+	 */
289
+	public function description()
290
+	{
291
+		return $this->get('EVT_desc');
292
+	}
293
+
294
+
295
+	/**
296
+	 * Runs do_shortcode and wpautop on the description
297
+	 *
298
+	 * @return string of html
299
+	 * @throws EE_Error
300
+	 */
301
+	public function description_filtered()
302
+	{
303
+		return $this->get_pretty('EVT_desc');
304
+	}
305
+
306
+
307
+	/**
308
+	 * @return bool
309
+	 * @throws EE_Error
310
+	 */
311
+	public function display_description()
312
+	{
313
+		return $this->get('EVT_display_desc');
314
+	}
315
+
316
+
317
+	/**
318
+	 * @return bool
319
+	 * @throws EE_Error
320
+	 */
321
+	public function display_ticket_selector()
322
+	{
323
+		return (bool)$this->get('EVT_display_ticket_selector');
324
+	}
325
+
326
+
327
+	/**
328
+	 * @return bool
329
+	 * @throws EE_Error
330
+	 */
331
+	public function external_url()
332
+	{
333
+		return $this->get('EVT_external_URL');
334
+	}
335
+
336
+
337
+	/**
338
+	 * @return bool
339
+	 * @throws EE_Error
340
+	 */
341
+	public function member_only()
342
+	{
343
+		return $this->get('EVT_member_only');
344
+	}
345
+
346
+
347
+	/**
348
+	 * @return bool
349
+	 * @throws EE_Error
350
+	 */
351
+	public function phone()
352
+	{
353
+		return $this->get('EVT_phone');
354
+	}
355
+
356
+
357
+	/**
358
+	 * @return bool
359
+	 * @throws EE_Error
360
+	 */
361
+	public function modified()
362
+	{
363
+		return $this->get('EVT_modified');
364
+	}
365
+
366
+
367
+	/**
368
+	 * @return bool
369
+	 * @throws EE_Error
370
+	 */
371
+	public function name()
372
+	{
373
+		return $this->get('EVT_name');
374
+	}
375
+
376
+
377
+	/**
378
+	 * @return bool
379
+	 * @throws EE_Error
380
+	 */
381
+	public function order()
382
+	{
383
+		return $this->get('EVT_order');
384
+	}
385
+
386
+
387
+	/**
388
+	 * @return bool|string
389
+	 * @throws EE_Error
390
+	 */
391
+	public function default_registration_status()
392
+	{
393
+		$event_default_registration_status = $this->get('EVT_default_registration_status');
394
+		return !empty($event_default_registration_status)
395
+			? $event_default_registration_status
396
+			: EE_Registry::instance()->CFG->registration->default_STS_ID;
397
+	}
398
+
399
+
400
+	/**
401
+	 * @param int $num_words
402
+	 * @param null $more
403
+	 * @param bool $not_full_desc
404
+	 * @return bool|string
405
+	 * @throws EE_Error
406
+	 */
407
+	public function short_description($num_words = 55, $more = null, $not_full_desc = false)
408
+	{
409
+		$short_desc = $this->get('EVT_short_desc');
410
+		if (!empty($short_desc) || $not_full_desc) {
411
+			return $short_desc;
412
+		}
413
+		$full_desc = $this->get('EVT_desc');
414
+		return wp_trim_words($full_desc, $num_words, $more);
415
+	}
416
+
417
+
418
+	/**
419
+	 * @return bool
420
+	 * @throws EE_Error
421
+	 */
422
+	public function slug()
423
+	{
424
+		return $this->get('EVT_slug');
425
+	}
426
+
427
+
428
+	/**
429
+	 * @return bool
430
+	 * @throws EE_Error
431
+	 */
432
+	public function timezone_string()
433
+	{
434
+		return $this->get('EVT_timezone_string');
435
+	}
436
+
437
+
438
+	/**
439
+	 * @return bool
440
+	 * @throws EE_Error
441
+	 */
442
+	public function visible_on()
443
+	{
444
+		return $this->get('EVT_visible_on');
445
+	}
446
+
447
+
448
+	/**
449
+	 * @return int
450
+	 * @throws EE_Error
451
+	 */
452
+	public function wp_user()
453
+	{
454
+		return $this->get('EVT_wp_user');
455
+	}
456
+
457
+
458
+	/**
459
+	 * @return bool
460
+	 * @throws EE_Error
461
+	 */
462
+	public function donations()
463
+	{
464
+		return $this->get('EVT_donations');
465
+	}
466
+
467
+
468
+	/**
469
+	 * @param $limit
470
+	 * @throws EE_Error
471
+	 */
472
+	public function set_additional_limit($limit)
473
+	{
474
+		$this->set('EVT_additional_limit', $limit);
475
+	}
476
+
477
+
478
+	/**
479
+	 * @param $created
480
+	 * @throws EE_Error
481
+	 */
482
+	public function set_created($created)
483
+	{
484
+		$this->set('EVT_created', $created);
485
+	}
486
+
487
+
488
+	/**
489
+	 * @param $desc
490
+	 * @throws EE_Error
491
+	 */
492
+	public function set_description($desc)
493
+	{
494
+		$this->set('EVT_desc', $desc);
495
+	}
496
+
497
+
498
+	/**
499
+	 * @param $display_desc
500
+	 * @throws EE_Error
501
+	 */
502
+	public function set_display_description($display_desc)
503
+	{
504
+		$this->set('EVT_display_desc', $display_desc);
505
+	}
506
+
507
+
508
+	/**
509
+	 * @param $display_ticket_selector
510
+	 * @throws EE_Error
511
+	 */
512
+	public function set_display_ticket_selector($display_ticket_selector)
513
+	{
514
+		$this->set('EVT_display_ticket_selector', $display_ticket_selector);
515
+	}
516
+
517
+
518
+	/**
519
+	 * @param $external_url
520
+	 * @throws EE_Error
521
+	 */
522
+	public function set_external_url($external_url)
523
+	{
524
+		$this->set('EVT_external_URL', $external_url);
525
+	}
526
+
527
+
528
+	/**
529
+	 * @param $member_only
530
+	 * @throws EE_Error
531
+	 */
532
+	public function set_member_only($member_only)
533
+	{
534
+		$this->set('EVT_member_only', $member_only);
535
+	}
536
+
537
+
538
+	/**
539
+	 * @param $event_phone
540
+	 * @throws EE_Error
541
+	 */
542
+	public function set_event_phone($event_phone)
543
+	{
544
+		$this->set('EVT_phone', $event_phone);
545
+	}
546
+
547
+
548
+	/**
549
+	 * @param $modified
550
+	 * @throws EE_Error
551
+	 */
552
+	public function set_modified($modified)
553
+	{
554
+		$this->set('EVT_modified', $modified);
555
+	}
556
+
557
+
558
+	/**
559
+	 * @param $name
560
+	 * @throws EE_Error
561
+	 */
562
+	public function set_name($name)
563
+	{
564
+		$this->set('EVT_name', $name);
565
+	}
566
+
567
+
568
+	/**
569
+	 * @param $order
570
+	 * @throws EE_Error
571
+	 */
572
+	public function set_order($order)
573
+	{
574
+		$this->set('EVT_order', $order);
575
+	}
576
+
577
+
578
+	/**
579
+	 * @param $short_desc
580
+	 * @throws EE_Error
581
+	 */
582
+	public function set_short_description($short_desc)
583
+	{
584
+		$this->set('EVT_short_desc', $short_desc);
585
+	}
586
+
587
+
588
+	/**
589
+	 * @param $slug
590
+	 * @throws EE_Error
591
+	 */
592
+	public function set_slug($slug)
593
+	{
594
+		$this->set('EVT_slug', $slug);
595
+	}
596
+
597
+
598
+	/**
599
+	 * @param $timezone_string
600
+	 * @throws EE_Error
601
+	 */
602
+	public function set_timezone_string($timezone_string)
603
+	{
604
+		$this->set('EVT_timezone_string', $timezone_string);
605
+	}
606
+
607
+
608
+	/**
609
+	 * @param $visible_on
610
+	 * @throws EE_Error
611
+	 */
612
+	public function set_visible_on($visible_on)
613
+	{
614
+		$this->set('EVT_visible_on', $visible_on);
615
+	}
616
+
617
+
618
+	/**
619
+	 * @param $wp_user
620
+	 * @throws EE_Error
621
+	 */
622
+	public function set_wp_user($wp_user)
623
+	{
624
+		$this->set('EVT_wp_user', $wp_user);
625
+	}
626
+
627
+
628
+	/**
629
+	 * @param $default_registration_status
630
+	 * @throws EE_Error
631
+	 */
632
+	public function set_default_registration_status($default_registration_status)
633
+	{
634
+		$this->set('EVT_default_registration_status', $default_registration_status);
635
+	}
636
+
637
+
638
+	/**
639
+	 * @param $donations
640
+	 * @throws EE_Error
641
+	 */
642
+	public function set_donations($donations)
643
+	{
644
+		$this->set('EVT_donations', $donations);
645
+	}
646
+
647
+
648
+	/**
649
+	 * Adds a venue to this event
650
+	 *
651
+	 * @param EE_Venue /int $venue_id_or_obj
652
+	 * @return EE_Base_Class|EE_Venue
653
+	 * @throws EE_Error
654
+	 */
655
+	public function add_venue($venue_id_or_obj)
656
+	{
657
+		return $this->_add_relation_to($venue_id_or_obj, 'Venue');
658
+	}
659
+
660
+
661
+	/**
662
+	 * Removes a venue from the event
663
+	 *
664
+	 * @param EE_Venue /int $venue_id_or_obj
665
+	 * @return EE_Base_Class|EE_Venue
666
+	 * @throws EE_Error
667
+	 */
668
+	public function remove_venue($venue_id_or_obj)
669
+	{
670
+		return $this->_remove_relation_to($venue_id_or_obj, 'Venue');
671
+	}
672
+
673
+
674
+	/**
675
+	 * Gets all the venues related ot the event. May provide additional $query_params if desired
676
+	 *
677
+	 * @param array $query_params like EEM_Base::get_all's $query_params
678
+	 * @return EE_Base_Class[]|EE_Venue[]
679
+	 * @throws EE_Error
680
+	 */
681
+	public function venues($query_params = array())
682
+	{
683
+		return $this->get_many_related('Venue', $query_params);
684
+	}
685
+
686
+
687
+	/**
688
+	 * check if event id is present and if event is published
689
+	 *
690
+	 * @access public
691
+	 * @return boolean true yes, false no
692
+	 * @throws EE_Error
693
+	 */
694
+	private function _has_ID_and_is_published()
695
+	{
696
+		// first check if event id is present and not NULL,
697
+		// then check if this event is published (or any of the equivalent "published" statuses)
698
+		return
699
+			$this->ID() && $this->ID() !== null
700
+			&& (
701
+				$this->status() === 'publish'
702
+				|| $this->status() === EEM_Event::sold_out
703
+				|| $this->status() === EEM_Event::postponed
704
+				|| $this->status() === EEM_Event::cancelled
705
+			);
706
+	}
707
+
708
+
709
+	/**
710
+	 * This simply compares the internal dates with NOW and determines if the event is upcoming or not.
711
+	 *
712
+	 * @access public
713
+	 * @return boolean true yes, false no
714
+	 * @throws EE_Error
715
+	 */
716
+	public function is_upcoming()
717
+	{
718
+		// check if event id is present and if this event is published
719
+		if ($this->is_inactive()) {
720
+			return false;
721
+		}
722
+		// set initial value
723
+		$upcoming = false;
724
+		//next let's get all datetimes and loop through them
725
+		$datetimes = $this->datetimes_in_chronological_order();
726
+		foreach ($datetimes as $datetime) {
727
+			if ($datetime instanceof EE_Datetime) {
728
+				//if this dtt is expired then we continue cause one of the other datetimes might be upcoming.
729
+				if ($datetime->is_expired()) {
730
+					continue;
731
+				}
732
+				//if this dtt is active then we return false.
733
+				if ($datetime->is_active()) {
734
+					return false;
735
+				}
736
+				//otherwise let's check upcoming status
737
+				$upcoming = $datetime->is_upcoming();
738
+			}
739
+		}
740
+		return $upcoming;
741
+	}
742
+
743
+
744
+	/**
745
+	 * @return bool
746
+	 * @throws EE_Error
747
+	 */
748
+	public function is_active()
749
+	{
750
+		// check if event id is present and if this event is published
751
+		if ($this->is_inactive()) {
752
+			return false;
753
+		}
754
+		// set initial value
755
+		$active = false;
756
+		//next let's get all datetimes and loop through them
757
+		$datetimes = $this->datetimes_in_chronological_order();
758
+		foreach ($datetimes as $datetime) {
759
+			if ($datetime instanceof EE_Datetime) {
760
+				//if this dtt is expired then we continue cause one of the other datetimes might be active.
761
+				if ($datetime->is_expired()) {
762
+					continue;
763
+				}
764
+				//if this dtt is upcoming then we return false.
765
+				if ($datetime->is_upcoming()) {
766
+					return false;
767
+				}
768
+				//otherwise let's check active status
769
+				$active = $datetime->is_active();
770
+			}
771
+		}
772
+		return $active;
773
+	}
774
+
775
+
776
+	/**
777
+	 * @return bool
778
+	 * @throws EE_Error
779
+	 */
780
+	public function is_expired()
781
+	{
782
+		// check if event id is present and if this event is published
783
+		if ($this->is_inactive()) {
784
+			return false;
785
+		}
786
+		// set initial value
787
+		$expired = false;
788
+		//first let's get all datetimes and loop through them
789
+		$datetimes = $this->datetimes_in_chronological_order();
790
+		foreach ($datetimes as $datetime) {
791
+			if ($datetime instanceof EE_Datetime) {
792
+				//if this dtt is upcoming or active then we return false.
793
+				if ($datetime->is_upcoming() || $datetime->is_active()) {
794
+					return false;
795
+				}
796
+				//otherwise let's check active status
797
+				$expired = $datetime->is_expired();
798
+			}
799
+		}
800
+		return $expired;
801
+	}
802
+
803
+
804
+	/**
805
+	 * @return bool
806
+	 * @throws EE_Error
807
+	 */
808
+	public function is_inactive()
809
+	{
810
+		// check if event id is present and if this event is published
811
+		if ($this->_has_ID_and_is_published()) {
812
+			return false;
813
+		}
814
+		return true;
815
+	}
816
+
817
+
818
+	/**
819
+	 * calculate spaces remaining based on "saleable" tickets
820
+	 *
821
+	 * @param array $tickets
822
+	 * @param bool $filtered
823
+	 * @return int|float
824
+	 * @throws EE_Error
825
+	 */
826
+	public function spaces_remaining($tickets = array(), $filtered = true)
827
+	{
828
+		// get all unexpired untrashed tickets if nothing was passed
829
+		$tickets = !empty($tickets) ? $tickets : $this->active_tickets();
830
+		// set initial value
831
+		$spaces_remaining = 0;
832
+		if (!empty($tickets)) {
833
+			foreach ($tickets as $ticket) {
834
+				if ($ticket instanceof EE_Ticket) {
835
+					$spaces_remaining += $ticket->qty('saleable');
836
+				}
837
+			}
838
+		}
839
+		return $filtered
840
+			? apply_filters(
841
+				'FHEE_EE_Event__spaces_remaining',
842
+				$spaces_remaining,
843
+				$this,
844
+				$tickets
845
+			)
846
+			: $spaces_remaining;
847
+	}
848
+
849
+
850
+	/**
851
+	 *    perform_sold_out_status_check
852
+	 *    checks all of this events's datetime  reg_limit - sold values to determine if ANY datetimes have spaces available...
853
+	 *    if NOT, then the event status will get toggled to 'sold_out'
854
+	 *
855
+	 * @access public
856
+	 * @return bool    return the ACTUAL sold out state.
857
+	 * @throws EE_Error
858
+	 */
859
+	public function perform_sold_out_status_check()
860
+	{
861
+		// get all unexpired untrashed tickets
862
+		$tickets = $this->active_tickets();
863
+		// if all the tickets are just expired, then don't update the event status to sold out
864
+		if (empty($tickets)) {
865
+			return true;
866
+		}
867
+		$spaces_remaining = $this->spaces_remaining($tickets);
868
+		if ($spaces_remaining < 1) {
869
+			$this->set_status(EEM_Event::sold_out);
870
+			$this->save();
871
+			$sold_out = true;
872
+		} else {
873
+			$sold_out = false;
874
+			// was event previously marked as sold out ?
875
+			if ($this->status() === EEM_Event::sold_out) {
876
+				// revert status to previous value, if it was set
877
+				$previous_event_status = $this->get_post_meta('_previous_event_status', true);
878
+				if ($previous_event_status) {
879
+					$this->set_status($previous_event_status);
880
+					$this->save();
881
+				}
882
+			}
883
+		}
884
+		do_action('AHEE__EE_Event__perform_sold_out_status_check__end', $this, $sold_out, $spaces_remaining, $tickets);
885
+		return $sold_out;
886
+	}
887
+
888
+
889
+	/**
890
+	 * This returns the total remaining spaces for sale on this event.
891
+	 * ############################
892
+	 * VERY IMPORTANT FOR DEVELOPERS:
893
+	 * While included here, this method is still being tested internally, so its signature and behaviour COULD change.
894
+	 * While this comment block is in place, usage is at your own risk and know that it may change in future builds.
895
+	 * ############################
896
+	 *
897
+	 * @uses EE_Event::total_available_spaces()
898
+	 * @return float|int  (EE_INF is returned as float)
899
+	 * @throws InvalidArgumentException
900
+	 * @throws InvalidStatusException
901
+	 * @throws EE_Error
902
+	 */
903
+	public function spaces_remaining_for_sale()
904
+	{
905
+		//first get total available spaces including consideration for tickets that have already sold.
906
+		$spaces_available = $this->total_available_spaces(true);
907
+		//if total available = 0, then exit right away because that means everything is expired.
908
+		if ($spaces_available === 0) {
909
+			return 0;
910
+		}
911
+		//subtract total approved registrations from spaces available to get how many are remaining.
912
+		$spots_taken = EEM_Registration::instance()->event_reg_count_for_statuses($this->ID());
913
+		$spaces_remaining = $spaces_available - $spots_taken;
914
+		return $spaces_remaining > 0 ? $spaces_remaining : 0;
915
+	}
916
+
917
+
918
+	/**
919
+	 * This returns the total spaces available for an event while considering all the qtys on the tickets and the reg limits
920
+	 * on the datetimes attached to this event.
921
+	 * ############################
922
+	 * VERY IMPORTANT FOR DEVELOPERS:
923
+	 * While included here, this method is still being tested internally, so its signature and behaviour COULD change. While
924
+	 * this comment block is in place, usage is at your own risk and know that it may change in future builds.
925
+	 * ############################
926
+	 * Note: by "spaces available" we are not returning how many spaces remain.  That is a calculation involving using the value
927
+	 * from this method and subtracting the approved registrations for the event.
928
+	 *
929
+	 * @param   bool $current_total_available Whether to consider any tickets that have already sold in our calculation.
930
+	 *                                              If this is false, then we return the most tickets that could ever be sold
931
+	 *                                              for this event with the datetime and tickets setup on the event under optimal
932
+	 *                                              selling conditions.  Otherwise we return a live calculation of spaces available
933
+	 *                                              based on tickets sold.  Depending on setup and stage of sales, this
934
+	 *                                              may appear to equal remaining tickets.  However, the more tickets are
935
+	 *                                              sold out, the more accurate the "live" total is.
936
+	 * @return  int|float  (Note: if EE_INF is returned its considered a float by PHP)
937
+	 * @throws EE_Error
938
+	 */
939
+	public function total_available_spaces($current_total_available = false)
940
+	{
941
+		$spaces_available = 0;
942
+		//first get all tickets on the event and include expired tickets
943
+		$tickets = $this->tickets(array('default_where_conditions' => 'none'));
944
+		$ticket_sums = array();
945
+		$datetimes = array();
946
+		$datetime_limits = array();
947
+		//loop through tickets and normalize them
948
+		foreach ($tickets as $ticket) {
949
+			$datetimes = $ticket->datetimes(array('order_by' => array('DTT_reg_limit' => 'ASC')));
950
+			if (empty($datetimes)) {
951
+				continue;
952
+			}
953
+			//first datetime should be the lowest datetime
954
+			$least_datetime = reset($datetimes);
955
+			//lets reset the ticket quantity to be the lower of either the lowest datetime reg limit or the ticket quantity
956
+			//IF datetimes sold (and we're not doing current live total available, then use spaces remaining for datetime, not reg_limit.
957
+			if ($current_total_available) {
958
+				if ($ticket->is_remaining()) {
959
+					$remaining = $ticket->remaining();
960
+				} else {
961
+					$spaces_available += $ticket->sold();
962
+					//and we don't cache this ticket to our list because its sold out.
963
+					continue;
964
+				}
965
+			} else {
966
+				$remaining = min($ticket->qty(), $least_datetime->reg_limit());
967
+			}
968
+			//if $ticket_limit == infinity then let's drop out right away and just return that because any infinity amount trumps all other "available" amounts.
969
+			if ($remaining === EE_INF) {
970
+				return EE_INF;
971
+			}
972
+			//multiply normalized $tkt quantity by the number of datetimes on the ticket as the "sum"
973
+			//also include the sum of all the datetime reg limits on the ticket for breaking ties.
974
+			$ticket_sums[$ticket->ID()]['sum'] = $remaining * count($datetimes);
975
+			$ticket_sums[$ticket->ID()]['datetime_sums'] = 0;
976
+			foreach ($datetimes as $datetime) {
977
+				if ($datetime->reg_limit() === EE_INF) {
978
+					$ticket_sums[$ticket->ID()]['datetime_sums'] = EE_INF;
979
+				} else {
980
+					$ticket_sums[$ticket->ID()]['datetime_sums'] += $current_total_available
981
+						? $datetime->spaces_remaining()
982
+						: $datetime->reg_limit();
983
+				}
984
+				$datetime_limits[$datetime->ID()] = $current_total_available
985
+					? $datetime->spaces_remaining()
986
+					: $datetime->reg_limit();
987
+			}
988
+			$ticket_sums[$ticket->ID()]['ticket'] = $ticket;
989
+		}
990
+		//The order is sorted by lowest available first (which is calculated for each ticket by multiplying the normalized
991
+		//ticket quantity by the number of datetimes on the ticket).  For tie-breakers, then the next sort is based on the
992
+		//ticket with the greatest sum of all remaining datetime->spaces_remaining() ( or $datetime->reg_limit() if not
993
+		//$current_total_available ) for the datetimes on the ticket.
994
+		usort($ticket_sums, function ($a, $b) {
995
+			if ($a['sum'] === $b['sum']) {
996
+				if ($a['datetime_sums'] === $b['datetime_sums']) {
997
+					return 0;
998
+				}
999
+				return $a['datetime_sums'] < $b['datetime_sums'] ? 1 : -1;
1000
+			}
1001
+			return ($a['sum'] < $b['sum']) ? -1 : 1;
1002
+		});
1003
+		//now let's loop through the sorted tickets and simulate sellouts
1004
+		foreach ($ticket_sums as $ticket_info) {
1005
+			if ($ticket_info['ticket'] instanceof EE_Ticket) {
1006
+				$datetimes = $ticket_info['ticket']->datetimes(array('order_by' => array('DTT_reg_limit' => 'ASC')));
1007
+				//need to sort these $datetimes by remaining (only if $current_total_available)
1008
+				//setup datetimes for simulation
1009
+				$ticket_datetimes_remaining = array();
1010
+				foreach ($datetimes as $datetime) {
1011
+					$DTT_ID = $datetime->ID();
1012
+					$ticket_datetimes_remaining[$DTT_ID]['rem'] = $datetime_limits[$DTT_ID];
1013
+					$ticket_datetimes_remaining[$DTT_ID]['datetime'] = $datetime;
1014
+				}
1015
+				usort($ticket_datetimes_remaining, function ($a, $b) {
1016
+					if ($a['rem'] === $b['rem']) {
1017
+						return 0;
1018
+					}
1019
+					return ($a['rem'] < $b['rem']) ? -1 : 1;
1020
+				});
1021
+				//get the remaining on the first datetime (which should be the one with the least remaining) and that is
1022
+				//what we add to the spaces_available running total.  Then we need to decrease the remaining on our datetime tracker.
1023
+				$lowest_datetime = reset($ticket_datetimes_remaining);
1024
+				//need to get the lower of; what the remaining is on the lowest datetime, and the remaining on the ticket.
1025
+				// If this ends up being 0 (because of previous tickets in our simulation selling out), then it has already
1026
+				// been tracked on $spaces available and this ticket is now sold out for the simulation, so we can continue
1027
+				// to the next ticket.
1028
+				if ($current_total_available) {
1029
+					$remaining = min($lowest_datetime['rem'], $ticket_info['ticket']->remaining());
1030
+				} else {
1031
+					$remaining = min($lowest_datetime['rem'], $ticket_info['ticket']->qty());
1032
+				}
1033
+				//if $remaining is infinite that means that all datetimes on this ticket are infinite but we've made it here because all
1034
+				//tickets have a quantity.  So we don't have to track datetimes, we can just use ticket quantities for total
1035
+				//available.
1036
+				if ($remaining === EE_INF) {
1037
+					$spaces_available += $ticket_info['ticket']->qty();
1038
+					continue;
1039
+				}
1040
+				//if ticket has sold amounts then we also need to add that (but only if doing live counts)
1041
+				if ($current_total_available) {
1042
+					$spaces_available += $ticket_info['ticket']->sold();
1043
+				}
1044
+				if ($remaining <= 0) {
1045
+					continue;
1046
+				}
1047
+				$spaces_available += $remaining;
1048
+				//loop through the datetimes and sell them out!
1049
+				foreach ($ticket_datetimes_remaining as $datetime_info) {
1050
+					if ($datetime_info['datetime'] instanceof EE_Datetime) {
1051
+						$datetime_limits[$datetime_info['datetime']->ID()] += -$remaining;
1052
+					}
1053
+				}
1054
+			}
1055
+		}
1056
+		return apply_filters(
1057
+			'FHEE_EE_Event__total_available_spaces__spaces_available',
1058
+			$spaces_available,
1059
+			$this,
1060
+			$datetimes,
1061
+			$tickets
1062
+		);
1063
+	}
1064
+
1065
+
1066
+	/**
1067
+	 * Checks if the event is set to sold out
1068
+	 *
1069
+	 * @param  bool $actual whether or not to perform calculations to not only figure the
1070
+	 *                      actual status but also to flip the status if necessary to sold
1071
+	 *                      out If false, we just check the existing status of the event
1072
+	 * @return boolean
1073
+	 * @throws EE_Error
1074
+	 */
1075
+	public function is_sold_out($actual = false)
1076
+	{
1077
+		if (!$actual) {
1078
+			return $this->status() === EEM_Event::sold_out;
1079
+		}
1080
+		return $this->perform_sold_out_status_check();
1081
+	}
1082
+
1083
+
1084
+	/**
1085
+	 * Checks if the event is marked as postponed
1086
+	 *
1087
+	 * @return boolean
1088
+	 */
1089
+	public function is_postponed()
1090
+	{
1091
+		return $this->status() === EEM_Event::postponed;
1092
+	}
1093
+
1094
+
1095
+	/**
1096
+	 * Checks if the event is marked as cancelled
1097
+	 *
1098
+	 * @return boolean
1099
+	 */
1100
+	public function is_cancelled()
1101
+	{
1102
+		return $this->status() === EEM_Event::cancelled;
1103
+	}
1104
+
1105
+
1106
+	/**
1107
+	 * Get the logical active status in a hierarchical order for all the datetimes.  Note
1108
+	 * Basically, we order the datetimes by EVT_start_date.  Then first test on whether the event is published.  If its
1109
+	 * NOT published then we test for whether its expired or not.  IF it IS published then we test first on whether an
1110
+	 * event has any active dates.  If no active dates then we check for any upcoming dates.  If no upcoming dates then
1111
+	 * the event is considered expired.
1112
+	 * NOTE: this method does NOT calculate whether the datetimes are sold out when event is published.  Sold Out is a status
1113
+	 * set on the EVENT when it is not published and thus is done
1114
+	 *
1115
+	 * @param bool $reset
1116
+	 * @return bool | string - based on EE_Datetime active constants or FALSE if error.
1117
+	 * @throws EE_Error
1118
+	 */
1119
+	public function get_active_status($reset = false)
1120
+	{
1121
+		// if the active status has already been set, then just use that value (unless we are resetting it)
1122
+		if (!empty($this->_active_status) && !$reset) {
1123
+			return $this->_active_status;
1124
+		}
1125
+		//first check if event id is present on this object
1126
+		if (!$this->ID()) {
1127
+			return false;
1128
+		}
1129
+		$where_params_for_event = array(array('EVT_ID' => $this->ID()));
1130
+		//if event is published:
1131
+		if ($this->status() === 'publish') {
1132
+			//active?
1133
+			if (EEM_Datetime::instance()->get_datetime_count_for_status(EE_Datetime::active, $where_params_for_event) > 0) {
1134
+				$this->_active_status = EE_Datetime::active;
1135
+			} else {
1136
+				//upcoming?
1137
+				if (EEM_Datetime::instance()->get_datetime_count_for_status(EE_Datetime::upcoming, $where_params_for_event) > 0) {
1138
+					$this->_active_status = EE_Datetime::upcoming;
1139
+				} else {
1140
+					//expired?
1141
+					if (
1142
+						EEM_Datetime::instance()->get_datetime_count_for_status(EE_Datetime::expired, $where_params_for_event) > 0
1143
+					) {
1144
+						$this->_active_status = EE_Datetime::expired;
1145
+					} else {
1146
+						//it would be odd if things make it this far because it basically means there are no datetime's
1147
+						//attached to the event.  So in this case it will just be considered inactive.
1148
+						$this->_active_status = EE_Datetime::inactive;
1149
+					}
1150
+				}
1151
+			}
1152
+		} else {
1153
+			//the event is not published, so let's just set it's active status according to its' post status
1154
+			switch ($this->status()) {
1155
+				case EEM_Event::sold_out :
1156
+					$this->_active_status = EE_Datetime::sold_out;
1157
+					break;
1158
+				case EEM_Event::cancelled :
1159
+					$this->_active_status = EE_Datetime::cancelled;
1160
+					break;
1161
+				case EEM_Event::postponed :
1162
+					$this->_active_status = EE_Datetime::postponed;
1163
+					break;
1164
+				default :
1165
+					$this->_active_status = EE_Datetime::inactive;
1166
+			}
1167
+		}
1168
+		return $this->_active_status;
1169
+	}
1170
+
1171
+
1172
+	/**
1173
+	 *    pretty_active_status
1174
+	 *
1175
+	 * @access public
1176
+	 * @param boolean $echo whether to return (FALSE), or echo out the result (TRUE)
1177
+	 * @return mixed void|string
1178
+	 * @throws EE_Error
1179
+	 */
1180
+	public function pretty_active_status($echo = true)
1181
+	{
1182
+		$active_status = $this->get_active_status();
1183
+		$status = '<span class="ee-status event-active-status-'
1184
+			. $active_status
1185
+			. '">'
1186
+			. EEH_Template::pretty_status($active_status, false, 'sentence')
1187
+			. '</span>';
1188
+		if ($echo) {
1189
+			echo $status;
1190
+			return '';
1191
+		}
1192
+		return $status;
1193
+	}
1194
+
1195
+
1196
+	/**
1197
+	 * @return bool|int
1198
+	 * @throws EE_Error
1199
+	 */
1200
+	public function get_number_of_tickets_sold()
1201
+	{
1202
+		$tkt_sold = 0;
1203
+		if (!$this->ID()) {
1204
+			return 0;
1205
+		}
1206
+		$datetimes = $this->datetimes();
1207
+		foreach ($datetimes as $datetime) {
1208
+			if ($datetime instanceof EE_Datetime) {
1209
+				$tkt_sold += $datetime->sold();
1210
+			}
1211
+		}
1212
+		return $tkt_sold;
1213
+	}
1214
+
1215
+
1216
+	/**
1217
+	 * This just returns a count of all the registrations for this event
1218
+	 *
1219
+	 * @access  public
1220
+	 * @return int
1221
+	 * @throws EE_Error
1222
+	 */
1223
+	public function get_count_of_all_registrations()
1224
+	{
1225
+		return EEM_Event::instance()->count_related($this, 'Registration');
1226
+	}
1227
+
1228
+
1229
+	/**
1230
+	 * This returns the ticket with the earliest start time that is
1231
+	 * available for this event (across all datetimes attached to the event)
1232
+	 *
1233
+	 * @return EE_Base_Class|EE_Ticket|null
1234
+	 * @throws EE_Error
1235
+	 */
1236
+	public function get_ticket_with_earliest_start_time()
1237
+	{
1238
+		$where['Datetime.EVT_ID'] = $this->ID();
1239
+		$query_params = array($where, 'order_by' => array('TKT_start_date' => 'ASC'));
1240
+		return EE_Registry::instance()->load_model('Ticket')->get_one($query_params);
1241
+	}
1242
+
1243
+
1244
+	/**
1245
+	 * This returns the ticket with the latest end time that is available
1246
+	 * for this event (across all datetimes attached to the event)
1247
+	 *
1248
+	 * @return EE_Base_Class|EE_Ticket|null
1249
+	 * @throws EE_Error
1250
+	 */
1251
+	public function get_ticket_with_latest_end_time()
1252
+	{
1253
+		$where['Datetime.EVT_ID'] = $this->ID();
1254
+		$query_params = array($where, 'order_by' => array('TKT_end_date' => 'DESC'));
1255
+		return EE_Registry::instance()->load_model('Ticket')->get_one($query_params);
1256
+	}
1257
+
1258
+
1259
+	/**
1260
+	 * This returns whether there are any tickets on sale for this event.
1261
+	 *
1262
+	 * @return bool true = YES tickets on sale.
1263
+	 * @throws EE_Error
1264
+	 */
1265
+	public function tickets_on_sale()
1266
+	{
1267
+		$earliest_ticket = $this->get_ticket_with_earliest_start_time();
1268
+		$latest_ticket = $this->get_ticket_with_latest_end_time();
1269
+		if (!$latest_ticket instanceof EE_Ticket && !$earliest_ticket instanceof EE_Ticket) {
1270
+			return false;
1271
+		}
1272
+		//check on sale for these two tickets.
1273
+		if ($latest_ticket->is_on_sale() || $earliest_ticket->is_on_sale()) {
1274
+			return true;
1275
+		}
1276
+		return false;
1277
+	}
1278
+
1279
+
1280
+	/**
1281
+	 * Gets the URL for viewing this event on the front-end. Overrides parent
1282
+	 * to check for an external URL first
1283
+	 *
1284
+	 * @return string
1285
+	 * @throws EE_Error
1286
+	 */
1287
+	public function get_permalink()
1288
+	{
1289
+		if ($this->external_url()) {
1290
+			return $this->external_url();
1291
+		}
1292
+		return parent::get_permalink();
1293
+	}
1294
+
1295
+
1296
+	/**
1297
+	 * Gets the first term for 'espresso_event_categories' we can find
1298
+	 *
1299
+	 * @param array $query_params like EEM_Base::get_all
1300
+	 * @return EE_Base_Class|EE_Term|null
1301
+	 * @throws EE_Error
1302
+	 */
1303
+	public function first_event_category($query_params = array())
1304
+	{
1305
+		$query_params[0]['Term_Taxonomy.taxonomy'] = 'espresso_event_categories';
1306
+		$query_params[0]['Term_Taxonomy.Event.EVT_ID'] = $this->ID();
1307
+		return EEM_Term::instance()->get_one($query_params);
1308
+	}
1309
+
1310
+
1311
+	/**
1312
+	 * Gets all terms for 'espresso_event_categories' we can find
1313
+	 *
1314
+	 * @param array $query_params
1315
+	 * @return EE_Base_Class[]|EE_Term[]
1316
+	 * @throws EE_Error
1317
+	 */
1318
+	public function get_all_event_categories($query_params = array())
1319
+	{
1320
+		$query_params[0]['Term_Taxonomy.taxonomy'] = 'espresso_event_categories';
1321
+		$query_params[0]['Term_Taxonomy.Event.EVT_ID'] = $this->ID();
1322
+		return EEM_Term::instance()->get_all($query_params);
1323
+	}
1324
+
1325
+
1326
+	/**
1327
+	 * Gets all the question groups, ordering them by QSG_order ascending
1328
+	 *
1329
+	 * @param array $query_params @see EEM_Base::get_all
1330
+	 * @return EE_Base_Class[]|EE_Question_Group[]
1331
+	 * @throws EE_Error
1332
+	 */
1333
+	public function question_groups($query_params = array())
1334
+	{
1335
+		$query_params = !empty($query_params) ? $query_params : array('order_by' => array('QSG_order' => 'ASC'));
1336
+		return $this->get_many_related('Question_Group', $query_params);
1337
+	}
1338
+
1339
+
1340
+	/**
1341
+	 * Implementation for EEI_Has_Icon interface method.
1342
+	 *
1343
+	 * @see EEI_Visual_Representation for comments
1344
+	 * @return string
1345
+	 */
1346
+	public function get_icon()
1347
+	{
1348
+		return '<span class="dashicons dashicons-flag"></span>';
1349
+	}
1350
+
1351
+
1352
+	/**
1353
+	 * Implementation for EEI_Admin_Links interface method.
1354
+	 *
1355
+	 * @see EEI_Admin_Links for comments
1356
+	 * @return string
1357
+	 * @throws EE_Error
1358
+	 */
1359
+	public function get_admin_details_link()
1360
+	{
1361
+		return $this->get_admin_edit_link();
1362
+	}
1363
+
1364
+
1365
+	/**
1366
+	 * Implementation for EEI_Admin_Links interface method.
1367
+	 *
1368
+	 * @see EEI_Admin_Links for comments
1369
+	 * @return string
1370
+	 * @throws EE_Error
1371
+	 */
1372
+	public function get_admin_edit_link()
1373
+	{
1374
+		return EEH_URL::add_query_args_and_nonce(array(
1375
+			'page' => 'espresso_events',
1376
+			'action' => 'edit',
1377
+			'post' => $this->ID(),
1378
+		),
1379
+			admin_url('admin.php')
1380
+		);
1381
+	}
1382
+
1383
+
1384
+	/**
1385
+	 * Implementation for EEI_Admin_Links interface method.
1386
+	 *
1387
+	 * @see EEI_Admin_Links for comments
1388
+	 * @return string
1389
+	 */
1390
+	public function get_admin_settings_link()
1391
+	{
1392
+		return EEH_URL::add_query_args_and_nonce(array(
1393
+			'page' => 'espresso_events',
1394
+			'action' => 'default_event_settings',
1395
+		),
1396
+			admin_url('admin.php')
1397
+		);
1398
+	}
1399
+
1400
+
1401
+	/**
1402
+	 * Implementation for EEI_Admin_Links interface method.
1403
+	 *
1404
+	 * @see EEI_Admin_Links for comments
1405
+	 * @return string
1406
+	 */
1407
+	public function get_admin_overview_link()
1408
+	{
1409
+		return EEH_URL::add_query_args_and_nonce(array(
1410
+			'page' => 'espresso_events',
1411
+			'action' => 'default',
1412
+		),
1413
+			admin_url('admin.php')
1414
+		);
1415
+	}
1416 1416
 
1417 1417
 }
Please login to merge, or discard this patch.
Spacing   +17 added lines, -17 removed lines patch added patch discarded remove patch
@@ -1,6 +1,6 @@  discard block
 block discarded – undo
1 1
 <?php use EventEspresso\core\exceptions\InvalidStatusException;
2 2
 
3
-if (!defined('EVENT_ESPRESSO_VERSION')) {
3
+if ( ! defined('EVENT_ESPRESSO_VERSION')) {
4 4
     exit('No direct script access allowed');
5 5
 }
6 6
 
@@ -95,7 +95,7 @@  discard block
 block discarded – undo
95 95
     public function set_status($new_status = null, $use_default = false)
96 96
     {
97 97
         // if nothing is set, and we aren't explicitly wanting to reset the status, then just leave
98
-        if (empty($new_status) && !$use_default) {
98
+        if (empty($new_status) && ! $use_default) {
99 99
             return;
100 100
         }
101 101
         // get current Event status
@@ -193,7 +193,7 @@  discard block
 block discarded – undo
193 193
      */
194 194
     public function primary_datetime($try_to_exclude_expired = true, $try_to_exclude_deleted = true)
195 195
     {
196
-        if (!empty ($this->_Primary_Datetime)) {
196
+        if ( ! empty ($this->_Primary_Datetime)) {
197 197
             return $this->_Primary_Datetime;
198 198
         }
199 199
         $this->_Primary_Datetime = EEM_Datetime::instance($this->_timezone)->get_primary_datetime_for_event(
@@ -216,7 +216,7 @@  discard block
 block discarded – undo
216 216
     {
217 217
         //first get all datetimes
218 218
         $datetimes = $this->datetimes_ordered();
219
-        if (!$datetimes) {
219
+        if ( ! $datetimes) {
220 220
             return array();
221 221
         }
222 222
         $datetime_ids = array();
@@ -320,7 +320,7 @@  discard block
 block discarded – undo
320 320
      */
321 321
     public function display_ticket_selector()
322 322
     {
323
-        return (bool)$this->get('EVT_display_ticket_selector');
323
+        return (bool) $this->get('EVT_display_ticket_selector');
324 324
     }
325 325
 
326 326
 
@@ -391,7 +391,7 @@  discard block
 block discarded – undo
391 391
     public function default_registration_status()
392 392
     {
393 393
         $event_default_registration_status = $this->get('EVT_default_registration_status');
394
-        return !empty($event_default_registration_status)
394
+        return ! empty($event_default_registration_status)
395 395
             ? $event_default_registration_status
396 396
             : EE_Registry::instance()->CFG->registration->default_STS_ID;
397 397
     }
@@ -407,7 +407,7 @@  discard block
 block discarded – undo
407 407
     public function short_description($num_words = 55, $more = null, $not_full_desc = false)
408 408
     {
409 409
         $short_desc = $this->get('EVT_short_desc');
410
-        if (!empty($short_desc) || $not_full_desc) {
410
+        if ( ! empty($short_desc) || $not_full_desc) {
411 411
             return $short_desc;
412 412
         }
413 413
         $full_desc = $this->get('EVT_desc');
@@ -826,10 +826,10 @@  discard block
 block discarded – undo
826 826
     public function spaces_remaining($tickets = array(), $filtered = true)
827 827
     {
828 828
         // get all unexpired untrashed tickets if nothing was passed
829
-        $tickets = !empty($tickets) ? $tickets : $this->active_tickets();
829
+        $tickets = ! empty($tickets) ? $tickets : $this->active_tickets();
830 830
         // set initial value
831 831
         $spaces_remaining = 0;
832
-        if (!empty($tickets)) {
832
+        if ( ! empty($tickets)) {
833 833
             foreach ($tickets as $ticket) {
834 834
                 if ($ticket instanceof EE_Ticket) {
835 835
                     $spaces_remaining += $ticket->qty('saleable');
@@ -991,7 +991,7 @@  discard block
 block discarded – undo
991 991
         //ticket quantity by the number of datetimes on the ticket).  For tie-breakers, then the next sort is based on the
992 992
         //ticket with the greatest sum of all remaining datetime->spaces_remaining() ( or $datetime->reg_limit() if not
993 993
         //$current_total_available ) for the datetimes on the ticket.
994
-        usort($ticket_sums, function ($a, $b) {
994
+        usort($ticket_sums, function($a, $b) {
995 995
             if ($a['sum'] === $b['sum']) {
996 996
                 if ($a['datetime_sums'] === $b['datetime_sums']) {
997 997
                     return 0;
@@ -1012,7 +1012,7 @@  discard block
 block discarded – undo
1012 1012
                     $ticket_datetimes_remaining[$DTT_ID]['rem'] = $datetime_limits[$DTT_ID];
1013 1013
                     $ticket_datetimes_remaining[$DTT_ID]['datetime'] = $datetime;
1014 1014
                 }
1015
-                usort($ticket_datetimes_remaining, function ($a, $b) {
1015
+                usort($ticket_datetimes_remaining, function($a, $b) {
1016 1016
                     if ($a['rem'] === $b['rem']) {
1017 1017
                         return 0;
1018 1018
                     }
@@ -1074,7 +1074,7 @@  discard block
 block discarded – undo
1074 1074
      */
1075 1075
     public function is_sold_out($actual = false)
1076 1076
     {
1077
-        if (!$actual) {
1077
+        if ( ! $actual) {
1078 1078
             return $this->status() === EEM_Event::sold_out;
1079 1079
         }
1080 1080
         return $this->perform_sold_out_status_check();
@@ -1119,11 +1119,11 @@  discard block
 block discarded – undo
1119 1119
     public function get_active_status($reset = false)
1120 1120
     {
1121 1121
         // if the active status has already been set, then just use that value (unless we are resetting it)
1122
-        if (!empty($this->_active_status) && !$reset) {
1122
+        if ( ! empty($this->_active_status) && ! $reset) {
1123 1123
             return $this->_active_status;
1124 1124
         }
1125 1125
         //first check if event id is present on this object
1126
-        if (!$this->ID()) {
1126
+        if ( ! $this->ID()) {
1127 1127
             return false;
1128 1128
         }
1129 1129
         $where_params_for_event = array(array('EVT_ID' => $this->ID()));
@@ -1200,7 +1200,7 @@  discard block
 block discarded – undo
1200 1200
     public function get_number_of_tickets_sold()
1201 1201
     {
1202 1202
         $tkt_sold = 0;
1203
-        if (!$this->ID()) {
1203
+        if ( ! $this->ID()) {
1204 1204
             return 0;
1205 1205
         }
1206 1206
         $datetimes = $this->datetimes();
@@ -1266,7 +1266,7 @@  discard block
 block discarded – undo
1266 1266
     {
1267 1267
         $earliest_ticket = $this->get_ticket_with_earliest_start_time();
1268 1268
         $latest_ticket = $this->get_ticket_with_latest_end_time();
1269
-        if (!$latest_ticket instanceof EE_Ticket && !$earliest_ticket instanceof EE_Ticket) {
1269
+        if ( ! $latest_ticket instanceof EE_Ticket && ! $earliest_ticket instanceof EE_Ticket) {
1270 1270
             return false;
1271 1271
         }
1272 1272
         //check on sale for these two tickets.
@@ -1332,7 +1332,7 @@  discard block
 block discarded – undo
1332 1332
      */
1333 1333
     public function question_groups($query_params = array())
1334 1334
     {
1335
-        $query_params = !empty($query_params) ? $query_params : array('order_by' => array('QSG_order' => 'ASC'));
1335
+        $query_params = ! empty($query_params) ? $query_params : array('order_by' => array('QSG_order' => 'ASC'));
1336 1336
         return $this->get_many_related('Question_Group', $query_params);
1337 1337
     }
1338 1338
 
Please login to merge, or discard this patch.
core/db_models/EEM_Registration.model.php 4 patches
Doc Comments   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -467,7 +467,7 @@
 block discarded – undo
467 467
      * @param    int $ATT_ID
468 468
      * @param    int $att_nmbr in case the ATT_ID is the same for multiple registrations (same details used) then the
469 469
      *                         attendee number is required
470
-     * @return        mixed        array on success, FALSE on fail
470
+     * @return        null|EE_Base_Class        array on success, FALSE on fail
471 471
      * @throws EE_Error
472 472
      */
473 473
     public function get_registration_for_transaction_attendee($TXN_ID = 0, $ATT_ID = 0, $att_nmbr = 0)
Please login to merge, or discard this patch.
Unused Use Statements   -1 removed lines patch added patch discarded remove patch
@@ -1,5 +1,4 @@
 block discarded – undo
1 1
 <?php
2
-use EventEspresso\core\exceptions\InvalidIdentifierException;
3 2
 use EventEspresso\core\exceptions\InvalidStatusException;
4 3
 use EventEspresso\core\services\database\TableAnalysis;
5 4
 
Please login to merge, or discard this patch.
Spacing   +29 added lines, -29 removed lines patch added patch discarded remove patch
@@ -3,7 +3,7 @@  discard block
 block discarded – undo
3 3
 use EventEspresso\core\exceptions\InvalidStatusException;
4 4
 use EventEspresso\core\services\database\TableAnalysis;
5 5
 
6
-if (!defined('EVENT_ESPRESSO_VERSION')) {
6
+if ( ! defined('EVENT_ESPRESSO_VERSION')) {
7 7
     exit('No direct script access allowed');
8 8
 }
9 9
 
@@ -371,13 +371,13 @@  discard block
 block discarded – undo
371 371
         //and the table hasn't actually been created, this could have an error
372 372
         /** @type WPDB $wpdb */
373 373
         global $wpdb;
374
-        if ($this->_get_table_analysis()->tableExists($wpdb->prefix . 'esp_status')) {
374
+        if ($this->_get_table_analysis()->tableExists($wpdb->prefix.'esp_status')) {
375 375
             $results = $wpdb->get_results(
376 376
                 "SELECT STS_ID, STS_code FROM {$wpdb->prefix}esp_status WHERE STS_type = 'registration'"
377 377
             );
378 378
             self::$_reg_status = array();
379 379
             foreach ($results as $status) {
380
-                if (!in_array($status->STS_ID, $exclude, true)) {
380
+                if ( ! in_array($status->STS_ID, $exclude, true)) {
381 381
                     self::$_reg_status[$status->STS_ID] = $status->STS_code;
382 382
                 }
383 383
             }
@@ -435,7 +435,7 @@  discard block
 block discarded – undo
435 435
      */
436 436
     public function get_all_registrations_for_attendee($ATT_ID = 0)
437 437
     {
438
-        if (!$ATT_ID) {
438
+        if ( ! $ATT_ID) {
439 439
             return null;
440 440
         }
441 441
         return $this->get_all(array(array('ATT_ID' => $ATT_ID)));
@@ -452,7 +452,7 @@  discard block
 block discarded – undo
452 452
      */
453 453
     public function get_registration_for_reg_url_link($REG_url_link)
454 454
     {
455
-        if (!$REG_url_link) {
455
+        if ( ! $REG_url_link) {
456 456
             return null;
457 457
         }
458 458
         return $this->get_one(array(array('REG_url_link' => $REG_url_link)));
@@ -499,7 +499,7 @@  discard block
 block discarded – undo
499 499
             'REG_date' => array('>=', $sql_date),
500 500
             'STS_ID' => array('!=', EEM_Registration::status_id_incomplete),
501 501
         );
502
-        if (!EE_Registry::instance()->CAP->current_user_can('ee_read_others_registrations', 'reg_per_day_report')) {
502
+        if ( ! EE_Registry::instance()->CAP->current_user_can('ee_read_others_registrations', 'reg_per_day_report')) {
503 503
             $where['Event.EVT_wp_user'] = get_current_user_id();
504 504
         }
505 505
         $query_interval = EEH_DTT_Helper::get_sql_query_interval_for_offset($this->get_timezone(), 'REG_date');
@@ -511,7 +511,7 @@  discard block
 block discarded – undo
511 511
             ),
512 512
             OBJECT,
513 513
             array(
514
-                'regDate' => array('DATE(' . $query_interval . ')', '%s'),
514
+                'regDate' => array('DATE('.$query_interval.')', '%s'),
515 515
                 'total' => array('count(REG_ID)', '%d'),
516 516
             ));
517 517
         return $results;
@@ -530,7 +530,7 @@  discard block
 block discarded – undo
530 530
     public function get_registrations_per_day_and_per_status_report($period = '-1 month')
531 531
     {
532 532
         global $wpdb;
533
-        $registration_table = $wpdb->prefix . 'esp_registration';
533
+        $registration_table = $wpdb->prefix.'esp_registration';
534 534
         $event_table = $wpdb->posts;
535 535
         $sql_date = date('Y-m-d H:i:s', strtotime($period));
536 536
         //prepare the query interval for displaying offset
@@ -539,9 +539,9 @@  discard block
 block discarded – undo
539 539
         $inner_date_query = "SELECT DISTINCT REG_date from {$registration_table} ";
540 540
         $inner_where = ' WHERE';
541 541
         //exclude events not authored by user if permissions in effect
542
-        if (!EE_Registry::instance()->CAP->current_user_can('ee_read_others_registrations', 'reg_per_event_report')) {
542
+        if ( ! EE_Registry::instance()->CAP->current_user_can('ee_read_others_registrations', 'reg_per_event_report')) {
543 543
             $inner_date_query .= "LEFT JOIN {$event_table} ON ID = EVT_ID";
544
-            $inner_where .= ' post_author = ' . get_current_user_id() . ' AND';
544
+            $inner_where .= ' post_author = '.get_current_user_id().' AND';
545 545
         }
546 546
         $inner_where .= " REG_date >= '{$sql_date}'";
547 547
         $inner_date_query .= $inner_where;
@@ -564,7 +564,7 @@  discard block
 block discarded – undo
564 564
         //setup the joins
565 565
         $join .= implode(' LEFT JOIN ', $join_parts);
566 566
         //now let's put it all together
567
-        $query = $select . $join . ' GROUP BY Registration_REG_date';
567
+        $query = $select.$join.' GROUP BY Registration_REG_date';
568 568
         //and execute it
569 569
         return $wpdb->get_results($query, ARRAY_A);
570 570
     }
@@ -587,7 +587,7 @@  discard block
 block discarded – undo
587 587
             'STS_ID' => array('!=', EEM_Registration::status_id_incomplete),
588 588
         );
589 589
         if (
590
-        !EE_Registry::instance()->CAP->current_user_can(
590
+        ! EE_Registry::instance()->CAP->current_user_can(
591 591
             'ee_read_others_registrations',
592 592
             'reg_per_event_report'
593 593
         )
@@ -622,16 +622,16 @@  discard block
 block discarded – undo
622 622
     public function get_registrations_per_event_and_per_status_report($period = '-1 month')
623 623
     {
624 624
         global $wpdb;
625
-        $registration_table = $wpdb->prefix . 'esp_registration';
625
+        $registration_table = $wpdb->prefix.'esp_registration';
626 626
         $event_table = $wpdb->posts;
627 627
         $sql_date = date('Y-m-d H:i:s', strtotime($period));
628 628
         //inner date query
629 629
         $inner_date_query = "SELECT DISTINCT EVT_ID, REG_date from $registration_table ";
630 630
         $inner_where = ' WHERE';
631 631
         //exclude events not authored by user if permissions in effect
632
-        if (!EE_Registry::instance()->CAP->current_user_can('ee_read_others_registrations', 'reg_per_event_report')) {
632
+        if ( ! EE_Registry::instance()->CAP->current_user_can('ee_read_others_registrations', 'reg_per_event_report')) {
633 633
             $inner_date_query .= "LEFT JOIN {$event_table} ON ID = EVT_ID";
634
-            $inner_where .= ' post_author = ' . get_current_user_id() . ' AND';
634
+            $inner_where .= ' post_author = '.get_current_user_id().' AND';
635 635
         }
636 636
         $inner_where .= " REG_date >= '{$sql_date}'";
637 637
         $inner_date_query .= $inner_where;
@@ -654,7 +654,7 @@  discard block
 block discarded – undo
654 654
         //setup remaining joins
655 655
         $join .= implode(' LEFT JOIN ', $join_parts);
656 656
         //now put it all together
657
-        $query = $select . $join . ' GROUP BY Registration_Event';
657
+        $query = $select.$join.' GROUP BY Registration_Event';
658 658
         //and execute
659 659
         return $wpdb->get_results($query, ARRAY_A);
660 660
     }
@@ -669,7 +669,7 @@  discard block
 block discarded – undo
669 669
      */
670 670
     public function get_primary_registration_for_transaction_ID($TXN_ID = 0)
671 671
     {
672
-        if (!$TXN_ID) {
672
+        if ( ! $TXN_ID) {
673 673
             return null;
674 674
         }
675 675
         return $this->get_one(array(
@@ -737,11 +737,11 @@  discard block
 block discarded – undo
737 737
         $query = $wpdb->prepare(
738 738
             'SELECT '
739 739
             . 'COUNT( DISTINCT checkins.REG_ID ) '
740
-            . 'FROM ' . EEM_Checkin::instance()->table() . ' AS checkins INNER JOIN'
740
+            . 'FROM '.EEM_Checkin::instance()->table().' AS checkins INNER JOIN'
741 741
             . '( SELECT '
742 742
             . 'max( CHK_timestamp ) AS latest_checkin, '
743 743
             . 'REG_ID AS REG_ID '
744
-            . 'FROM ' . EEM_Checkin::instance()->table() . ' '
744
+            . 'FROM '.EEM_Checkin::instance()->table().' '
745 745
             . 'WHERE DTT_ID=%d '
746 746
             . 'GROUP BY REG_ID'
747 747
             . ') AS most_recent_checkin_per_reg '
@@ -752,7 +752,7 @@  discard block
 block discarded – undo
752 752
             $DTT_ID,
753 753
             $checked_in
754 754
         );
755
-        return (int)$wpdb->get_var($query);
755
+        return (int) $wpdb->get_var($query);
756 756
     }
757 757
 
758 758
 
@@ -771,12 +771,12 @@  discard block
 block discarded – undo
771 771
         $query = $wpdb->prepare(
772 772
             'SELECT '
773 773
             . 'COUNT( DISTINCT checkins.REG_ID ) '
774
-            . 'FROM ' . EEM_Checkin::instance()->table() . ' AS checkins INNER JOIN'
774
+            . 'FROM '.EEM_Checkin::instance()->table().' AS checkins INNER JOIN'
775 775
             . '( SELECT '
776 776
             . 'max( CHK_timestamp ) AS latest_checkin, '
777 777
             . 'REG_ID AS REG_ID '
778
-            . 'FROM ' . EEM_Checkin::instance()->table() . ' AS c '
779
-            . 'INNER JOIN ' . EEM_Datetime::instance()->table() . ' AS d '
778
+            . 'FROM '.EEM_Checkin::instance()->table().' AS c '
779
+            . 'INNER JOIN '.EEM_Datetime::instance()->table().' AS d '
780 780
             . 'ON c.DTT_ID=d.DTT_ID '
781 781
             . 'WHERE d.EVT_ID=%d '
782 782
             . 'GROUP BY REG_ID'
@@ -788,7 +788,7 @@  discard block
 block discarded – undo
788 788
             $EVT_ID,
789 789
             $checked_in
790 790
         );
791
-        return (int)$wpdb->get_var($query);
791
+        return (int) $wpdb->get_var($query);
792 792
     }
793 793
 
794 794
 
@@ -805,11 +805,11 @@  discard block
 block discarded – undo
805 805
     {
806 806
         //first do a native wp_query to get the latest REG_ID's matching these attendees.
807 807
         global $wpdb;
808
-        $registration_table = $wpdb->prefix . 'esp_registration';
808
+        $registration_table = $wpdb->prefix.'esp_registration';
809 809
         $attendee_table = $wpdb->posts;
810 810
         $attendee_ids = is_array($attendee_ids)
811 811
             ? array_map('absint', $attendee_ids)
812
-            : array((int)$attendee_ids);
812
+            : array((int) $attendee_ids);
813 813
         $ATT_IDs = implode(',', $attendee_ids);
814 814
         // first we do a query to get the registration ids
815 815
         // (because a group by before order by causes the order by to be ignored.)
@@ -857,10 +857,10 @@  discard block
 block discarded – undo
857 857
      * @throws InvalidStatusException
858 858
      * @throws EE_Error
859 859
      */
860
-    public function event_reg_count_for_statuses($EVT_ID, $statuses = array() )
860
+    public function event_reg_count_for_statuses($EVT_ID, $statuses = array())
861 861
     {
862 862
         $EVT_ID = absint($EVT_ID);
863
-        if (! $EVT_ID) {
863
+        if ( ! $EVT_ID) {
864 864
             throw new InvalidArgumentException(
865 865
                 esc_html__('An invalid Event ID was supplied.', 'event_espresso')
866 866
             );
@@ -868,7 +868,7 @@  discard block
 block discarded – undo
868 868
         $statuses = ! empty($statuses) ? $statuses : array(EEM_Registration::status_id_approved);
869 869
         $valid_reg_statuses = EEM_Registration::reg_statuses();
870 870
         foreach ($statuses as $status) {
871
-            if(! in_array($status, $valid_reg_statuses, true)) {
871
+            if ( ! in_array($status, $valid_reg_statuses, true)) {
872 872
                 throw new InvalidStatusException($status, esc_html__('Registration', 'event_espresso'));
873 873
             }
874 874
         }
Please login to merge, or discard this patch.
Indentation   +854 added lines, -854 removed lines patch added patch discarded remove patch
@@ -4,7 +4,7 @@  discard block
 block discarded – undo
4 4
 use EventEspresso\core\services\database\TableAnalysis;
5 5
 
6 6
 if (!defined('EVENT_ESPRESSO_VERSION')) {
7
-    exit('No direct script access allowed');
7
+	exit('No direct script access allowed');
8 8
 }
9 9
 
10 10
 
@@ -18,802 +18,802 @@  discard block
 block discarded – undo
18 18
 class EEM_Registration extends EEM_Soft_Delete_Base
19 19
 {
20 20
 
21
-    /**
22
-     * @var EEM_Registration $_instance
23
-     */
24
-    protected static $_instance;
25
-
26
-    /**
27
-     * Keys are the status IDs for registrations (eg, RAP, RCN, etc), and the values
28
-     * are status codes (eg, approved, cancelled, etc)
29
-     *
30
-     * @var array
31
-     */
32
-    private static $_reg_status;
33
-
34
-    /**
35
-     * The value of REG_count for a primary registrant
36
-     */
37
-    const PRIMARY_REGISTRANT_COUNT = 1;
38
-
39
-    /**
40
-     * Status ID (STS_ID on esp_status table) to indicate an INCOMPLETE registration.
41
-     * Initial status for registrations when they are first created
42
-     * Payments are NOT allowed.
43
-     * Automatically toggled to whatever the default Event registration status is upon completion of the attendee
44
-     * information reg step NO space reserved. Registration is NOT active
45
-     */
46
-    const status_id_incomplete = 'RIC';
47
-
48
-    /**
49
-     * Status ID (STS_ID on esp_status table) to indicate an UNAPPROVED registration.
50
-     * Payments are NOT allowed.
51
-     * Event Admin must manually toggle STS_ID for it to change
52
-     * No space reserved.
53
-     * Registration is active
54
-     */
55
-    const status_id_not_approved = 'RNA';
56
-
57
-    /**
58
-     * Status ID (STS_ID on esp_status table) to indicate registration is PENDING_PAYMENT .
59
-     * Payments are allowed.
60
-     * STS_ID will automatically be toggled to RAP if payment is made in full by the attendee
61
-     * No space reserved.
62
-     * Registration is active
63
-     */
64
-    const status_id_pending_payment = 'RPP';
65
-
66
-    /**
67
-     * Status ID (STS_ID on esp_status table) to indicate registration is on the WAIT_LIST .
68
-     * Payments are allowed.
69
-     * STS_ID will automatically be toggled to RAP if payment is made in full by the attendee
70
-     * No space reserved.
71
-     * Registration is active
72
-     */
73
-    const status_id_wait_list = 'RWL';
74
-
75
-    /**
76
-     * Status ID (STS_ID on esp_status table) to indicate an APPROVED registration.
77
-     * the TXN may or may not be completed ( paid in full )
78
-     * Payments are allowed.
79
-     * A space IS reserved.
80
-     * Registration is active
81
-     */
82
-    const status_id_approved = 'RAP';
83
-
84
-    /**
85
-     * Status ID (STS_ID on esp_status table) to indicate a registration was CANCELLED by the attendee.
86
-     * Payments are NOT allowed.
87
-     * NO space reserved.
88
-     * Registration is NOT active
89
-     */
90
-    const status_id_cancelled = 'RCN';
91
-
92
-    /**
93
-     * Status ID (STS_ID on esp_status table) to indicate a registration was DECLINED by the Event Admin
94
-     * Payments are NOT allowed.
95
-     * No space reserved.
96
-     * Registration is NOT active
97
-     */
98
-    const status_id_declined = 'RDC';
99
-
100
-    /**
101
-     * @var TableAnalysis $table_analysis
102
-     */
103
-    protected $_table_analysis;
104
-
105
-
106
-    /**
107
-     *    private constructor to prevent direct creation
108
-     *
109
-     * @Constructor
110
-     * @access protected
111
-     * @param string $timezone string representing the timezone we want to set for returned Date Time Strings (and any
112
-     *                         incoming timezone data that gets saved). Note this just sends the timezone info to the
113
-     *                         date time model field objects.  Default is NULL (and will be assumed using the set
114
-     *                         timezone in the 'timezone_string' wp option)
115
-     * @throws EE_Error
116
-     */
117
-    protected function __construct($timezone = null)
118
-    {
119
-        $this->_table_analysis = EE_Registry::instance()->create('TableAnalysis', array(), true);
120
-        $this->singular_item = esc_html__('Registration', 'event_espresso');
121
-        $this->plural_item = esc_html__('Registrations', 'event_espresso');
122
-        $this->_tables = array(
123
-            'Registration' => new EE_Primary_Table('esp_registration', 'REG_ID'),
124
-        );
125
-        $this->_fields = array(
126
-            'Registration' => array(
127
-                'REG_ID' => new EE_Primary_Key_Int_Field(
128
-                    'REG_ID',
129
-                    esc_html__('Registration ID', 'event_espresso')
130
-                ),
131
-                'EVT_ID' => new EE_Foreign_Key_Int_Field(
132
-                    'EVT_ID',
133
-                    esc_html__('Event ID', 'event_espresso'),
134
-                    false,
135
-                    0,
136
-                    'Event'
137
-                ),
138
-                'ATT_ID' => new EE_Foreign_Key_Int_Field(
139
-                    'ATT_ID',
140
-                    esc_html__('Attendee ID', 'event_espresso'),
141
-                    false,
142
-                    0,
143
-                    'Attendee'
144
-                ),
145
-                'TXN_ID' => new EE_Foreign_Key_Int_Field(
146
-                    'TXN_ID',
147
-                    esc_html__('Transaction ID', 'event_espresso'),
148
-                    false, 0, 'Transaction'
149
-                ),
150
-                'TKT_ID' => new EE_Foreign_Key_Int_Field(
151
-                    'TKT_ID',
152
-                    esc_html__('Ticket ID', 'event_espresso'),
153
-                    false,
154
-                    0, 'Ticket'
155
-                ),
156
-                'STS_ID' => new EE_Foreign_Key_String_Field(
157
-                    'STS_ID',
158
-                    esc_html__('Status ID', 'event_espresso'),
159
-                    false,
160
-                    EEM_Registration::status_id_incomplete,
161
-                    'Status'
162
-                ),
163
-                'REG_date' => new EE_Datetime_Field(
164
-                    'REG_date',
165
-                    esc_html__('Time registration occurred', 'event_espresso'),
166
-                    false,
167
-                    EE_Datetime_Field::now,
168
-                    $timezone
169
-                ),
170
-                'REG_final_price' => new EE_Money_Field(
171
-                    'REG_final_price',
172
-                    esc_html__('Registration\'s share of the transaction total', 'event_espresso'),
173
-                    false,
174
-                    0
175
-                ),
176
-                'REG_paid' => new EE_Money_Field(
177
-                    'REG_paid',
178
-                    esc_html__('Amount paid to date towards registration', 'event_espresso'),
179
-                    false,
180
-                    0
181
-                ),
182
-                'REG_session' => new EE_Plain_Text_Field(
183
-                    'REG_session',
184
-                    esc_html__('Session ID of registration', 'event_espresso'),
185
-                    false,
186
-                    ''
187
-                ),
188
-                'REG_code' => new EE_Plain_Text_Field(
189
-                    'REG_code',
190
-                    esc_html__('Unique Code for this registration', 'event_espresso'),
191
-                    false,
192
-                    ''
193
-                ),
194
-                'REG_url_link' => new EE_Plain_Text_Field(
195
-                    'REG_url_link',
196
-                    esc_html__('String to be used in URL for identifying registration', 'event_espresso'),
197
-                    false,
198
-                    ''
199
-                ),
200
-                'REG_count' => new EE_Integer_Field(
201
-                    'REG_count',
202
-                    esc_html__('Count of this registration in the group registration ', 'event_espresso'),
203
-                    true,
204
-                    1
205
-                ),
206
-                'REG_group_size' => new EE_Integer_Field(
207
-                    'REG_group_size',
208
-                    esc_html__('Number of registrations on this group', 'event_espresso'),
209
-                    false,
210
-                    1
211
-                ),
212
-                'REG_att_is_going' => new EE_Boolean_Field(
213
-                    'REG_att_is_going',
214
-                    esc_html__('Flag indicating the registrant plans on attending', 'event_espresso'),
215
-                    false,
216
-                    false
217
-                ),
218
-                'REG_deleted' => new EE_Trashed_Flag_Field(
219
-                    'REG_deleted',
220
-                    esc_html__('Flag indicating if registration has been archived or not.', 'event_espresso'),
221
-                    false,
222
-                    false
223
-                ),
224
-            ),
225
-        );
226
-        $this->_model_relations = array(
227
-            'Event' => new EE_Belongs_To_Relation(),
228
-            'Attendee' => new EE_Belongs_To_Relation(),
229
-            'Transaction' => new EE_Belongs_To_Relation(),
230
-            'Ticket' => new EE_Belongs_To_Relation(),
231
-            'Status' => new EE_Belongs_To_Relation(),
232
-            'Answer' => new EE_Has_Many_Relation(),
233
-            'Checkin' => new EE_Has_Many_Relation(),
234
-            'Registration_Payment' => new EE_Has_Many_Relation(),
235
-            'Payment' => new EE_HABTM_Relation('Registration_Payment'),
236
-            'Message' => new EE_Has_Many_Any_Relation(false)
237
-            //allow deletes even if there are messages in the queue related
238
-        );
239
-        $this->_model_chain_to_wp_user = 'Event';
240
-        parent::__construct($timezone);
241
-    }
242
-
243
-
244
-    /**
245
-     * a list of ALL valid registration statuses currently in use within the system
246
-     * generated by combining the filterable active and inactive reg status arrays
247
-     *
248
-     * @return array
249
-     */
250
-    public static function reg_statuses()
251
-    {
252
-        return array_unique(
253
-            array_merge(
254
-                EEM_Registration::active_reg_statuses(),
255
-                EEM_Registration::inactive_reg_statuses()
256
-            )
257
-        );
258
-    }
259
-
260
-
261
-    /**
262
-     * reg_statuses_that_allow_payment
263
-     * a filterable list of registration statuses that allow a registrant to make a payment
264
-     *
265
-     * @access public
266
-     * @return array
267
-     */
268
-    public static function reg_statuses_that_allow_payment()
269
-    {
270
-        return apply_filters(
271
-            'FHEE__EEM_Registration__reg_statuses_that_allow_payment',
272
-            array(
273
-                EEM_Registration::status_id_approved,
274
-                EEM_Registration::status_id_pending_payment,
275
-            )
276
-        );
277
-    }
278
-
279
-
280
-    /**
281
-     * active_reg_statuses
282
-     * a filterable list of registration statuses that are considered active
283
-     *
284
-     * @access public
285
-     * @return array
286
-     */
287
-    public static function active_reg_statuses()
288
-    {
289
-        return apply_filters(
290
-            'FHEE__EEM_Registration__active_reg_statuses',
291
-            array(
292
-                EEM_Registration::status_id_approved,
293
-                EEM_Registration::status_id_pending_payment,
294
-                EEM_Registration::status_id_wait_list,
295
-                EEM_Registration::status_id_not_approved,
296
-            )
297
-        );
298
-    }
299
-
300
-
301
-    /**
302
-     * inactive_reg_statuses
303
-     * a filterable list of registration statuses that are not considered active
304
-     *
305
-     * @access public
306
-     * @return array
307
-     */
308
-    public static function inactive_reg_statuses()
309
-    {
310
-        return apply_filters(
311
-            'FHEE__EEM_Registration__inactive_reg_statuses',
312
-            array(
313
-                EEM_Registration::status_id_incomplete,
314
-                EEM_Registration::status_id_cancelled,
315
-                EEM_Registration::status_id_declined,
316
-            )
317
-        );
318
-    }
319
-
320
-
321
-    /**
322
-     *    closed_reg_statuses
323
-     *    a filterable list of registration statuses that are considered "closed"
324
-     * meaning they should not be considered in any calculations involving monies owing
325
-     *
326
-     * @access public
327
-     * @return array
328
-     */
329
-    public static function closed_reg_statuses()
330
-    {
331
-        return apply_filters(
332
-            'FHEE__EEM_Registration__closed_reg_statuses',
333
-            array(
334
-                EEM_Registration::status_id_cancelled,
335
-                EEM_Registration::status_id_declined,
336
-                EEM_Registration::status_id_wait_list,
337
-            )
338
-        );
339
-    }
340
-
341
-
342
-    /**
343
-     *        get list of registration statuses
344
-     *
345
-     * @access public
346
-     * @param array $exclude The status ids to exclude from the returned results
347
-     * @param bool $translated If true will return the values as singular localized strings
348
-     * @return array
349
-     * @throws EE_Error
350
-     */
351
-    public static function reg_status_array($exclude = array(), $translated = false)
352
-    {
353
-        EEM_Registration::instance()->_get_registration_status_array($exclude);
354
-        return $translated
355
-            ? EEM_Status::instance()->localized_status(self::$_reg_status, false, 'sentence')
356
-            : self::$_reg_status;
357
-    }
358
-
359
-
360
-    /**
361
-     *    get list of registration statuses
362
-     *
363
-     * @access private
364
-     * @param array $exclude
365
-     * @return void
366
-     * @throws EE_Error
367
-     */
368
-    private function _get_registration_status_array($exclude = array())
369
-    {
370
-        //in the very rare circumstance that we are deleting a model's table's data
371
-        //and the table hasn't actually been created, this could have an error
372
-        /** @type WPDB $wpdb */
373
-        global $wpdb;
374
-        if ($this->_get_table_analysis()->tableExists($wpdb->prefix . 'esp_status')) {
375
-            $results = $wpdb->get_results(
376
-                "SELECT STS_ID, STS_code FROM {$wpdb->prefix}esp_status WHERE STS_type = 'registration'"
377
-            );
378
-            self::$_reg_status = array();
379
-            foreach ($results as $status) {
380
-                if (!in_array($status->STS_ID, $exclude, true)) {
381
-                    self::$_reg_status[$status->STS_ID] = $status->STS_code;
382
-                }
383
-            }
384
-        }
385
-    }
386
-
387
-
388
-    /**
389
-     * Gets the injected table analyzer, or throws an exception
390
-     *
391
-     * @return TableAnalysis
392
-     * @throws EE_Error
393
-     */
394
-    protected function _get_table_analysis()
395
-    {
396
-        if ($this->_table_analysis instanceof TableAnalysis) {
397
-            return $this->_table_analysis;
398
-        }
399
-        throw new EE_Error(
400
-            sprintf(
401
-                esc_html__('Table analysis class on class %1$s is not set properly.', 'event_espresso'),
402
-                get_class($this)
403
-            )
404
-        );
405
-    }
406
-
407
-
408
-    /**
409
-     * This returns a wpdb->results array of all registration date month and years matching the incoming query params
410
-     * and grouped by month and year.
411
-     *
412
-     * @param  array $where_params Array of query_params as described in the comments for EEM_Base::get_all()
413
-     * @return array
414
-     * @throws EE_Error
415
-     */
416
-    public function get_reg_months_and_years($where_params)
417
-    {
418
-        $query_params[0] = $where_params;
419
-        $query_params['group_by'] = array('reg_year', 'reg_month');
420
-        $query_params['order_by'] = array('REG_date' => 'DESC');
421
-        $columns_to_select = array(
422
-            'reg_year' => array('YEAR(REG_date)', '%s'),
423
-            'reg_month' => array('MONTHNAME(REG_date)', '%s'),
424
-        );
425
-        return $this->_get_all_wpdb_results($query_params, OBJECT, $columns_to_select);
426
-    }
427
-
428
-
429
-    /**
430
-     * retrieve ALL registrations for a particular Attendee from db
431
-     *
432
-     * @param int $ATT_ID
433
-     * @return EE_Base_Class[]|EE_Registration[]|null
434
-     * @throws EE_Error
435
-     */
436
-    public function get_all_registrations_for_attendee($ATT_ID = 0)
437
-    {
438
-        if (!$ATT_ID) {
439
-            return null;
440
-        }
441
-        return $this->get_all(array(array('ATT_ID' => $ATT_ID)));
442
-    }
443
-
444
-
445
-    /**
446
-     * Gets a registration given their REG_url_link. Yes, this should usually
447
-     * be passed via a GET parameter.
448
-     *
449
-     * @param string $REG_url_link
450
-     * @return EE_Base_Class|EE_Registration|null
451
-     * @throws EE_Error
452
-     */
453
-    public function get_registration_for_reg_url_link($REG_url_link)
454
-    {
455
-        if (!$REG_url_link) {
456
-            return null;
457
-        }
458
-        return $this->get_one(array(array('REG_url_link' => $REG_url_link)));
459
-    }
460
-
461
-
462
-    /**
463
-     *        retrieve registration for a specific transaction attendee from db
464
-     *
465
-     * @access        public
466
-     * @param    int $TXN_ID
467
-     * @param    int $ATT_ID
468
-     * @param    int $att_nmbr in case the ATT_ID is the same for multiple registrations (same details used) then the
469
-     *                         attendee number is required
470
-     * @return        mixed        array on success, FALSE on fail
471
-     * @throws EE_Error
472
-     */
473
-    public function get_registration_for_transaction_attendee($TXN_ID = 0, $ATT_ID = 0, $att_nmbr = 0)
474
-    {
475
-        return $this->get_one(array(
476
-            array(
477
-                'TXN_ID' => $TXN_ID,
478
-                'ATT_ID' => $ATT_ID,
479
-            ),
480
-            'limit' => array(min($att_nmbr - 1, 0), 1),
481
-        ));
482
-    }
483
-
484
-
485
-    /**
486
-     *        get the number of registrations per day  for the Registration Admin page Reports Tab.
487
-     *        (doesn't utilize models because it's a fairly specialized query)
488
-     *
489
-     * @access        public
490
-     * @param $period string which can be passed to php's strtotime function (eg "-1 month")
491
-     * @return stdClass[] with properties regDate and total
492
-     * @throws EE_Error
493
-     */
494
-    public function get_registrations_per_day_report($period = '-1 month')
495
-    {
496
-        $sql_date = $this->convert_datetime_for_query('REG_date', date('Y-m-d H:i:s', strtotime($period)),
497
-            'Y-m-d H:i:s', 'UTC');
498
-        $where = array(
499
-            'REG_date' => array('>=', $sql_date),
500
-            'STS_ID' => array('!=', EEM_Registration::status_id_incomplete),
501
-        );
502
-        if (!EE_Registry::instance()->CAP->current_user_can('ee_read_others_registrations', 'reg_per_day_report')) {
503
-            $where['Event.EVT_wp_user'] = get_current_user_id();
504
-        }
505
-        $query_interval = EEH_DTT_Helper::get_sql_query_interval_for_offset($this->get_timezone(), 'REG_date');
506
-        $results = $this->_get_all_wpdb_results(
507
-            array(
508
-                $where,
509
-                'group_by' => 'regDate',
510
-                'order_by' => array('REG_date' => 'ASC'),
511
-            ),
512
-            OBJECT,
513
-            array(
514
-                'regDate' => array('DATE(' . $query_interval . ')', '%s'),
515
-                'total' => array('count(REG_ID)', '%d'),
516
-            ));
517
-        return $results;
518
-    }
519
-
520
-
521
-    /**
522
-     * Get the number of registrations per day including the count of registrations for each Registration Status.
523
-     * Note: EEM_Registration::status_id_incomplete registrations are excluded from the results.
524
-     *
525
-     * @param string $period
526
-     * @return stdClass[] with properties Registration_REG_date and a column for each registration status as the STS_ID
527
-     * @throws EE_Error
528
-     *                    (i.e. RAP)
529
-     */
530
-    public function get_registrations_per_day_and_per_status_report($period = '-1 month')
531
-    {
532
-        global $wpdb;
533
-        $registration_table = $wpdb->prefix . 'esp_registration';
534
-        $event_table = $wpdb->posts;
535
-        $sql_date = date('Y-m-d H:i:s', strtotime($period));
536
-        //prepare the query interval for displaying offset
537
-        $query_interval = EEH_DTT_Helper::get_sql_query_interval_for_offset($this->get_timezone(), 'dates.REG_date');
538
-        //inner date query
539
-        $inner_date_query = "SELECT DISTINCT REG_date from {$registration_table} ";
540
-        $inner_where = ' WHERE';
541
-        //exclude events not authored by user if permissions in effect
542
-        if (!EE_Registry::instance()->CAP->current_user_can('ee_read_others_registrations', 'reg_per_event_report')) {
543
-            $inner_date_query .= "LEFT JOIN {$event_table} ON ID = EVT_ID";
544
-            $inner_where .= ' post_author = ' . get_current_user_id() . ' AND';
545
-        }
546
-        $inner_where .= " REG_date >= '{$sql_date}'";
547
-        $inner_date_query .= $inner_where;
548
-        //start main query
549
-        $select = "SELECT DATE({$query_interval}) as Registration_REG_date, ";
550
-        $join = '';
551
-        $join_parts = array();
552
-        $select_parts = array();
553
-        //loop through registration stati to do parts for each status.
554
-        foreach (EEM_Registration::reg_status_array() as $STS_ID => $STS_code) {
555
-            if ($STS_ID === EEM_Registration::status_id_incomplete) {
556
-                continue;
557
-            }
558
-            $select_parts[] = "COUNT({$STS_code}.REG_ID) as {$STS_ID}";
559
-            $join_parts[] = "{$registration_table} AS {$STS_code} ON {$STS_code}.REG_date = dates.REG_date AND {$STS_code}.STS_ID = '{$STS_ID}'";
560
-        }
561
-        //setup the selects
562
-        $select .= implode(', ', $select_parts);
563
-        $select .= " FROM ($inner_date_query) AS dates LEFT JOIN ";
564
-        //setup the joins
565
-        $join .= implode(' LEFT JOIN ', $join_parts);
566
-        //now let's put it all together
567
-        $query = $select . $join . ' GROUP BY Registration_REG_date';
568
-        //and execute it
569
-        return $wpdb->get_results($query, ARRAY_A);
570
-    }
571
-
572
-
573
-    /**
574
-     *        get the number of registrations per event  for the Registration Admin page Reports Tab
575
-     *
576
-     * @access        public
577
-     * @param $period string which can be passed to php's strtotime function (eg "-1 month")
578
-     * @return stdClass[] each with properties event_name, reg_limit, and total
579
-     * @throws EE_Error
580
-     */
581
-    public function get_registrations_per_event_report($period = '-1 month')
582
-    {
583
-        $date_sql = $this->convert_datetime_for_query('REG_date', date('Y-m-d H:i:s', strtotime($period)),
584
-            'Y-m-d H:i:s', 'UTC');
585
-        $where = array(
586
-            'REG_date' => array('>=', $date_sql),
587
-            'STS_ID' => array('!=', EEM_Registration::status_id_incomplete),
588
-        );
589
-        if (
590
-        !EE_Registry::instance()->CAP->current_user_can(
591
-            'ee_read_others_registrations',
592
-            'reg_per_event_report'
593
-        )
594
-        ) {
595
-            $where['Event.EVT_wp_user'] = get_current_user_id();
596
-        }
597
-        $results = $this->_get_all_wpdb_results(array(
598
-            $where,
599
-            'group_by' => 'Event.EVT_name',
600
-            'order_by' => 'Event.EVT_name',
601
-            'limit' => array(0, 24),
602
-        ),
603
-            OBJECT,
604
-            array(
605
-                'event_name' => array('Event_CPT.post_title', '%s'),
606
-                'total' => array('COUNT(REG_ID)', '%s'),
607
-            )
608
-        );
609
-        return $results;
610
-    }
611
-
612
-
613
-    /**
614
-     * Get the number of registrations per event grouped by registration status.
615
-     * Note: EEM_Registration::status_id_incomplete registrations are excluded from the results.
616
-     *
617
-     * @param string $period
618
-     * @return stdClass[] with properties `Registration_Event` and a column for each registration status as the STS_ID
619
-     * @throws EE_Error
620
-     *                    (i.e. RAP)
621
-     */
622
-    public function get_registrations_per_event_and_per_status_report($period = '-1 month')
623
-    {
624
-        global $wpdb;
625
-        $registration_table = $wpdb->prefix . 'esp_registration';
626
-        $event_table = $wpdb->posts;
627
-        $sql_date = date('Y-m-d H:i:s', strtotime($period));
628
-        //inner date query
629
-        $inner_date_query = "SELECT DISTINCT EVT_ID, REG_date from $registration_table ";
630
-        $inner_where = ' WHERE';
631
-        //exclude events not authored by user if permissions in effect
632
-        if (!EE_Registry::instance()->CAP->current_user_can('ee_read_others_registrations', 'reg_per_event_report')) {
633
-            $inner_date_query .= "LEFT JOIN {$event_table} ON ID = EVT_ID";
634
-            $inner_where .= ' post_author = ' . get_current_user_id() . ' AND';
635
-        }
636
-        $inner_where .= " REG_date >= '{$sql_date}'";
637
-        $inner_date_query .= $inner_where;
638
-        //build main query
639
-        $select = 'SELECT Event.post_title as Registration_Event, ';
640
-        $join = '';
641
-        $join_parts = array();
642
-        $select_parts = array();
643
-        //loop through registration stati to do parts for each status.
644
-        foreach (EEM_Registration::reg_status_array() as $STS_ID => $STS_code) {
645
-            if ($STS_ID === EEM_Registration::status_id_incomplete) {
646
-                continue;
647
-            }
648
-            $select_parts[] = "COUNT({$STS_code}.REG_ID) as {$STS_ID}";
649
-            $join_parts[] = "{$registration_table} AS {$STS_code} ON {$STS_code}.EVT_ID = dates.EVT_ID AND {$STS_code}.STS_ID = '{$STS_ID}' AND {$STS_code}.REG_date = dates.REG_date";
650
-        }
651
-        //setup the selects
652
-        $select .= implode(', ', $select_parts);
653
-        $select .= " FROM ($inner_date_query) AS dates LEFT JOIN $event_table as Event ON Event.ID = dates.EVT_ID LEFT JOIN ";
654
-        //setup remaining joins
655
-        $join .= implode(' LEFT JOIN ', $join_parts);
656
-        //now put it all together
657
-        $query = $select . $join . ' GROUP BY Registration_Event';
658
-        //and execute
659
-        return $wpdb->get_results($query, ARRAY_A);
660
-    }
661
-
662
-
663
-    /**
664
-     * Returns the EE_Registration of the primary attendee on the transaction id provided
665
-     *
666
-     * @param int $TXN_ID
667
-     * @return EE_Base_Class|EE_Registration|null
668
-     * @throws EE_Error
669
-     */
670
-    public function get_primary_registration_for_transaction_ID($TXN_ID = 0)
671
-    {
672
-        if (!$TXN_ID) {
673
-            return null;
674
-        }
675
-        return $this->get_one(array(
676
-            array(
677
-                'TXN_ID' => $TXN_ID,
678
-                'REG_count' => EEM_Registration::PRIMARY_REGISTRANT_COUNT,
679
-            ),
680
-        ));
681
-    }
682
-
683
-
684
-    /**
685
-     *        get_event_registration_count
686
-     *
687
-     * @access public
688
-     * @param int $EVT_ID
689
-     * @param boolean $for_incomplete_payments
690
-     * @return int
691
-     * @throws EE_Error
692
-     */
693
-    public function get_event_registration_count($EVT_ID, $for_incomplete_payments = false)
694
-    {
695
-        // we only count approved registrations towards registration limits
696
-        $query_params = array(array('EVT_ID' => $EVT_ID, 'STS_ID' => self::status_id_approved));
697
-        if ($for_incomplete_payments) {
698
-            $query_params[0]['Transaction.STS_ID'] = array('!=', EEM_Transaction::complete_status_code);
699
-        }
700
-        return $this->count($query_params);
701
-    }
702
-
703
-
704
-    /**
705
-     * Deletes all registrations with no transactions. Note that this needs to be very efficient
706
-     * and so it uses wpdb directly
707
-     *
708
-     * @global WPDB $wpdb
709
-     * @return int number deleted
710
-     * @throws EE_Error
711
-     */
712
-    public function delete_registrations_with_no_transaction()
713
-    {
714
-        /** @type WPDB $wpdb */
715
-        global $wpdb;
716
-        return $wpdb->query(
717
-            'DELETE r FROM '
718
-            . $this->table()
719
-            . ' r LEFT JOIN '
720
-            . EEM_Transaction::instance()->table()
721
-            . ' t ON r.TXN_ID = t.TXN_ID WHERE t.TXN_ID IS NULL');
722
-    }
723
-
724
-
725
-    /**
726
-     *  Count registrations checked into (or out of) a datetime
727
-     *
728
-     * @param int $DTT_ID datetime ID
729
-     * @param boolean $checked_in whether to count registrations checked IN or OUT
730
-     * @return int
731
-     * @throws EE_Error
732
-     */
733
-    public function count_registrations_checked_into_datetime($DTT_ID, $checked_in = true)
734
-    {
735
-        global $wpdb;
736
-        //subquery to get latest checkin
737
-        $query = $wpdb->prepare(
738
-            'SELECT '
739
-            . 'COUNT( DISTINCT checkins.REG_ID ) '
740
-            . 'FROM ' . EEM_Checkin::instance()->table() . ' AS checkins INNER JOIN'
741
-            . '( SELECT '
742
-            . 'max( CHK_timestamp ) AS latest_checkin, '
743
-            . 'REG_ID AS REG_ID '
744
-            . 'FROM ' . EEM_Checkin::instance()->table() . ' '
745
-            . 'WHERE DTT_ID=%d '
746
-            . 'GROUP BY REG_ID'
747
-            . ') AS most_recent_checkin_per_reg '
748
-            . 'ON checkins.REG_ID=most_recent_checkin_per_reg.REG_ID '
749
-            . 'AND checkins.CHK_timestamp = most_recent_checkin_per_reg.latest_checkin '
750
-            . 'WHERE '
751
-            . 'checkins.CHK_in=%d',
752
-            $DTT_ID,
753
-            $checked_in
754
-        );
755
-        return (int)$wpdb->get_var($query);
756
-    }
757
-
758
-
759
-    /**
760
-     *  Count registrations checked into (or out of) an event.
761
-     *
762
-     * @param int $EVT_ID event ID
763
-     * @param boolean $checked_in whether to count registrations checked IN or OUT
764
-     * @return int
765
-     * @throws EE_Error
766
-     */
767
-    public function count_registrations_checked_into_event($EVT_ID, $checked_in = true)
768
-    {
769
-        global $wpdb;
770
-        //subquery to get latest checkin
771
-        $query = $wpdb->prepare(
772
-            'SELECT '
773
-            . 'COUNT( DISTINCT checkins.REG_ID ) '
774
-            . 'FROM ' . EEM_Checkin::instance()->table() . ' AS checkins INNER JOIN'
775
-            . '( SELECT '
776
-            . 'max( CHK_timestamp ) AS latest_checkin, '
777
-            . 'REG_ID AS REG_ID '
778
-            . 'FROM ' . EEM_Checkin::instance()->table() . ' AS c '
779
-            . 'INNER JOIN ' . EEM_Datetime::instance()->table() . ' AS d '
780
-            . 'ON c.DTT_ID=d.DTT_ID '
781
-            . 'WHERE d.EVT_ID=%d '
782
-            . 'GROUP BY REG_ID'
783
-            . ') AS most_recent_checkin_per_reg '
784
-            . 'ON checkins.REG_ID=most_recent_checkin_per_reg.REG_ID '
785
-            . 'AND checkins.CHK_timestamp = most_recent_checkin_per_reg.latest_checkin '
786
-            . 'WHERE '
787
-            . 'checkins.CHK_in=%d',
788
-            $EVT_ID,
789
-            $checked_in
790
-        );
791
-        return (int)$wpdb->get_var($query);
792
-    }
793
-
794
-
795
-    /**
796
-     * The purpose of this method is to retrieve an array of
797
-     * EE_Registration objects that represent the latest registration
798
-     * for each ATT_ID given in the function argument.
799
-     *
800
-     * @param array $attendee_ids
801
-     * @return EE_Base_Class[]|EE_Registration[]
802
-     * @throws EE_Error
803
-     */
804
-    public function get_latest_registration_for_each_of_given_contacts($attendee_ids = array())
805
-    {
806
-        //first do a native wp_query to get the latest REG_ID's matching these attendees.
807
-        global $wpdb;
808
-        $registration_table = $wpdb->prefix . 'esp_registration';
809
-        $attendee_table = $wpdb->posts;
810
-        $attendee_ids = is_array($attendee_ids)
811
-            ? array_map('absint', $attendee_ids)
812
-            : array((int)$attendee_ids);
813
-        $ATT_IDs = implode(',', $attendee_ids);
814
-        // first we do a query to get the registration ids
815
-        // (because a group by before order by causes the order by to be ignored.)
816
-        $registration_id_query = "
21
+	/**
22
+	 * @var EEM_Registration $_instance
23
+	 */
24
+	protected static $_instance;
25
+
26
+	/**
27
+	 * Keys are the status IDs for registrations (eg, RAP, RCN, etc), and the values
28
+	 * are status codes (eg, approved, cancelled, etc)
29
+	 *
30
+	 * @var array
31
+	 */
32
+	private static $_reg_status;
33
+
34
+	/**
35
+	 * The value of REG_count for a primary registrant
36
+	 */
37
+	const PRIMARY_REGISTRANT_COUNT = 1;
38
+
39
+	/**
40
+	 * Status ID (STS_ID on esp_status table) to indicate an INCOMPLETE registration.
41
+	 * Initial status for registrations when they are first created
42
+	 * Payments are NOT allowed.
43
+	 * Automatically toggled to whatever the default Event registration status is upon completion of the attendee
44
+	 * information reg step NO space reserved. Registration is NOT active
45
+	 */
46
+	const status_id_incomplete = 'RIC';
47
+
48
+	/**
49
+	 * Status ID (STS_ID on esp_status table) to indicate an UNAPPROVED registration.
50
+	 * Payments are NOT allowed.
51
+	 * Event Admin must manually toggle STS_ID for it to change
52
+	 * No space reserved.
53
+	 * Registration is active
54
+	 */
55
+	const status_id_not_approved = 'RNA';
56
+
57
+	/**
58
+	 * Status ID (STS_ID on esp_status table) to indicate registration is PENDING_PAYMENT .
59
+	 * Payments are allowed.
60
+	 * STS_ID will automatically be toggled to RAP if payment is made in full by the attendee
61
+	 * No space reserved.
62
+	 * Registration is active
63
+	 */
64
+	const status_id_pending_payment = 'RPP';
65
+
66
+	/**
67
+	 * Status ID (STS_ID on esp_status table) to indicate registration is on the WAIT_LIST .
68
+	 * Payments are allowed.
69
+	 * STS_ID will automatically be toggled to RAP if payment is made in full by the attendee
70
+	 * No space reserved.
71
+	 * Registration is active
72
+	 */
73
+	const status_id_wait_list = 'RWL';
74
+
75
+	/**
76
+	 * Status ID (STS_ID on esp_status table) to indicate an APPROVED registration.
77
+	 * the TXN may or may not be completed ( paid in full )
78
+	 * Payments are allowed.
79
+	 * A space IS reserved.
80
+	 * Registration is active
81
+	 */
82
+	const status_id_approved = 'RAP';
83
+
84
+	/**
85
+	 * Status ID (STS_ID on esp_status table) to indicate a registration was CANCELLED by the attendee.
86
+	 * Payments are NOT allowed.
87
+	 * NO space reserved.
88
+	 * Registration is NOT active
89
+	 */
90
+	const status_id_cancelled = 'RCN';
91
+
92
+	/**
93
+	 * Status ID (STS_ID on esp_status table) to indicate a registration was DECLINED by the Event Admin
94
+	 * Payments are NOT allowed.
95
+	 * No space reserved.
96
+	 * Registration is NOT active
97
+	 */
98
+	const status_id_declined = 'RDC';
99
+
100
+	/**
101
+	 * @var TableAnalysis $table_analysis
102
+	 */
103
+	protected $_table_analysis;
104
+
105
+
106
+	/**
107
+	 *    private constructor to prevent direct creation
108
+	 *
109
+	 * @Constructor
110
+	 * @access protected
111
+	 * @param string $timezone string representing the timezone we want to set for returned Date Time Strings (and any
112
+	 *                         incoming timezone data that gets saved). Note this just sends the timezone info to the
113
+	 *                         date time model field objects.  Default is NULL (and will be assumed using the set
114
+	 *                         timezone in the 'timezone_string' wp option)
115
+	 * @throws EE_Error
116
+	 */
117
+	protected function __construct($timezone = null)
118
+	{
119
+		$this->_table_analysis = EE_Registry::instance()->create('TableAnalysis', array(), true);
120
+		$this->singular_item = esc_html__('Registration', 'event_espresso');
121
+		$this->plural_item = esc_html__('Registrations', 'event_espresso');
122
+		$this->_tables = array(
123
+			'Registration' => new EE_Primary_Table('esp_registration', 'REG_ID'),
124
+		);
125
+		$this->_fields = array(
126
+			'Registration' => array(
127
+				'REG_ID' => new EE_Primary_Key_Int_Field(
128
+					'REG_ID',
129
+					esc_html__('Registration ID', 'event_espresso')
130
+				),
131
+				'EVT_ID' => new EE_Foreign_Key_Int_Field(
132
+					'EVT_ID',
133
+					esc_html__('Event ID', 'event_espresso'),
134
+					false,
135
+					0,
136
+					'Event'
137
+				),
138
+				'ATT_ID' => new EE_Foreign_Key_Int_Field(
139
+					'ATT_ID',
140
+					esc_html__('Attendee ID', 'event_espresso'),
141
+					false,
142
+					0,
143
+					'Attendee'
144
+				),
145
+				'TXN_ID' => new EE_Foreign_Key_Int_Field(
146
+					'TXN_ID',
147
+					esc_html__('Transaction ID', 'event_espresso'),
148
+					false, 0, 'Transaction'
149
+				),
150
+				'TKT_ID' => new EE_Foreign_Key_Int_Field(
151
+					'TKT_ID',
152
+					esc_html__('Ticket ID', 'event_espresso'),
153
+					false,
154
+					0, 'Ticket'
155
+				),
156
+				'STS_ID' => new EE_Foreign_Key_String_Field(
157
+					'STS_ID',
158
+					esc_html__('Status ID', 'event_espresso'),
159
+					false,
160
+					EEM_Registration::status_id_incomplete,
161
+					'Status'
162
+				),
163
+				'REG_date' => new EE_Datetime_Field(
164
+					'REG_date',
165
+					esc_html__('Time registration occurred', 'event_espresso'),
166
+					false,
167
+					EE_Datetime_Field::now,
168
+					$timezone
169
+				),
170
+				'REG_final_price' => new EE_Money_Field(
171
+					'REG_final_price',
172
+					esc_html__('Registration\'s share of the transaction total', 'event_espresso'),
173
+					false,
174
+					0
175
+				),
176
+				'REG_paid' => new EE_Money_Field(
177
+					'REG_paid',
178
+					esc_html__('Amount paid to date towards registration', 'event_espresso'),
179
+					false,
180
+					0
181
+				),
182
+				'REG_session' => new EE_Plain_Text_Field(
183
+					'REG_session',
184
+					esc_html__('Session ID of registration', 'event_espresso'),
185
+					false,
186
+					''
187
+				),
188
+				'REG_code' => new EE_Plain_Text_Field(
189
+					'REG_code',
190
+					esc_html__('Unique Code for this registration', 'event_espresso'),
191
+					false,
192
+					''
193
+				),
194
+				'REG_url_link' => new EE_Plain_Text_Field(
195
+					'REG_url_link',
196
+					esc_html__('String to be used in URL for identifying registration', 'event_espresso'),
197
+					false,
198
+					''
199
+				),
200
+				'REG_count' => new EE_Integer_Field(
201
+					'REG_count',
202
+					esc_html__('Count of this registration in the group registration ', 'event_espresso'),
203
+					true,
204
+					1
205
+				),
206
+				'REG_group_size' => new EE_Integer_Field(
207
+					'REG_group_size',
208
+					esc_html__('Number of registrations on this group', 'event_espresso'),
209
+					false,
210
+					1
211
+				),
212
+				'REG_att_is_going' => new EE_Boolean_Field(
213
+					'REG_att_is_going',
214
+					esc_html__('Flag indicating the registrant plans on attending', 'event_espresso'),
215
+					false,
216
+					false
217
+				),
218
+				'REG_deleted' => new EE_Trashed_Flag_Field(
219
+					'REG_deleted',
220
+					esc_html__('Flag indicating if registration has been archived or not.', 'event_espresso'),
221
+					false,
222
+					false
223
+				),
224
+			),
225
+		);
226
+		$this->_model_relations = array(
227
+			'Event' => new EE_Belongs_To_Relation(),
228
+			'Attendee' => new EE_Belongs_To_Relation(),
229
+			'Transaction' => new EE_Belongs_To_Relation(),
230
+			'Ticket' => new EE_Belongs_To_Relation(),
231
+			'Status' => new EE_Belongs_To_Relation(),
232
+			'Answer' => new EE_Has_Many_Relation(),
233
+			'Checkin' => new EE_Has_Many_Relation(),
234
+			'Registration_Payment' => new EE_Has_Many_Relation(),
235
+			'Payment' => new EE_HABTM_Relation('Registration_Payment'),
236
+			'Message' => new EE_Has_Many_Any_Relation(false)
237
+			//allow deletes even if there are messages in the queue related
238
+		);
239
+		$this->_model_chain_to_wp_user = 'Event';
240
+		parent::__construct($timezone);
241
+	}
242
+
243
+
244
+	/**
245
+	 * a list of ALL valid registration statuses currently in use within the system
246
+	 * generated by combining the filterable active and inactive reg status arrays
247
+	 *
248
+	 * @return array
249
+	 */
250
+	public static function reg_statuses()
251
+	{
252
+		return array_unique(
253
+			array_merge(
254
+				EEM_Registration::active_reg_statuses(),
255
+				EEM_Registration::inactive_reg_statuses()
256
+			)
257
+		);
258
+	}
259
+
260
+
261
+	/**
262
+	 * reg_statuses_that_allow_payment
263
+	 * a filterable list of registration statuses that allow a registrant to make a payment
264
+	 *
265
+	 * @access public
266
+	 * @return array
267
+	 */
268
+	public static function reg_statuses_that_allow_payment()
269
+	{
270
+		return apply_filters(
271
+			'FHEE__EEM_Registration__reg_statuses_that_allow_payment',
272
+			array(
273
+				EEM_Registration::status_id_approved,
274
+				EEM_Registration::status_id_pending_payment,
275
+			)
276
+		);
277
+	}
278
+
279
+
280
+	/**
281
+	 * active_reg_statuses
282
+	 * a filterable list of registration statuses that are considered active
283
+	 *
284
+	 * @access public
285
+	 * @return array
286
+	 */
287
+	public static function active_reg_statuses()
288
+	{
289
+		return apply_filters(
290
+			'FHEE__EEM_Registration__active_reg_statuses',
291
+			array(
292
+				EEM_Registration::status_id_approved,
293
+				EEM_Registration::status_id_pending_payment,
294
+				EEM_Registration::status_id_wait_list,
295
+				EEM_Registration::status_id_not_approved,
296
+			)
297
+		);
298
+	}
299
+
300
+
301
+	/**
302
+	 * inactive_reg_statuses
303
+	 * a filterable list of registration statuses that are not considered active
304
+	 *
305
+	 * @access public
306
+	 * @return array
307
+	 */
308
+	public static function inactive_reg_statuses()
309
+	{
310
+		return apply_filters(
311
+			'FHEE__EEM_Registration__inactive_reg_statuses',
312
+			array(
313
+				EEM_Registration::status_id_incomplete,
314
+				EEM_Registration::status_id_cancelled,
315
+				EEM_Registration::status_id_declined,
316
+			)
317
+		);
318
+	}
319
+
320
+
321
+	/**
322
+	 *    closed_reg_statuses
323
+	 *    a filterable list of registration statuses that are considered "closed"
324
+	 * meaning they should not be considered in any calculations involving monies owing
325
+	 *
326
+	 * @access public
327
+	 * @return array
328
+	 */
329
+	public static function closed_reg_statuses()
330
+	{
331
+		return apply_filters(
332
+			'FHEE__EEM_Registration__closed_reg_statuses',
333
+			array(
334
+				EEM_Registration::status_id_cancelled,
335
+				EEM_Registration::status_id_declined,
336
+				EEM_Registration::status_id_wait_list,
337
+			)
338
+		);
339
+	}
340
+
341
+
342
+	/**
343
+	 *        get list of registration statuses
344
+	 *
345
+	 * @access public
346
+	 * @param array $exclude The status ids to exclude from the returned results
347
+	 * @param bool $translated If true will return the values as singular localized strings
348
+	 * @return array
349
+	 * @throws EE_Error
350
+	 */
351
+	public static function reg_status_array($exclude = array(), $translated = false)
352
+	{
353
+		EEM_Registration::instance()->_get_registration_status_array($exclude);
354
+		return $translated
355
+			? EEM_Status::instance()->localized_status(self::$_reg_status, false, 'sentence')
356
+			: self::$_reg_status;
357
+	}
358
+
359
+
360
+	/**
361
+	 *    get list of registration statuses
362
+	 *
363
+	 * @access private
364
+	 * @param array $exclude
365
+	 * @return void
366
+	 * @throws EE_Error
367
+	 */
368
+	private function _get_registration_status_array($exclude = array())
369
+	{
370
+		//in the very rare circumstance that we are deleting a model's table's data
371
+		//and the table hasn't actually been created, this could have an error
372
+		/** @type WPDB $wpdb */
373
+		global $wpdb;
374
+		if ($this->_get_table_analysis()->tableExists($wpdb->prefix . 'esp_status')) {
375
+			$results = $wpdb->get_results(
376
+				"SELECT STS_ID, STS_code FROM {$wpdb->prefix}esp_status WHERE STS_type = 'registration'"
377
+			);
378
+			self::$_reg_status = array();
379
+			foreach ($results as $status) {
380
+				if (!in_array($status->STS_ID, $exclude, true)) {
381
+					self::$_reg_status[$status->STS_ID] = $status->STS_code;
382
+				}
383
+			}
384
+		}
385
+	}
386
+
387
+
388
+	/**
389
+	 * Gets the injected table analyzer, or throws an exception
390
+	 *
391
+	 * @return TableAnalysis
392
+	 * @throws EE_Error
393
+	 */
394
+	protected function _get_table_analysis()
395
+	{
396
+		if ($this->_table_analysis instanceof TableAnalysis) {
397
+			return $this->_table_analysis;
398
+		}
399
+		throw new EE_Error(
400
+			sprintf(
401
+				esc_html__('Table analysis class on class %1$s is not set properly.', 'event_espresso'),
402
+				get_class($this)
403
+			)
404
+		);
405
+	}
406
+
407
+
408
+	/**
409
+	 * This returns a wpdb->results array of all registration date month and years matching the incoming query params
410
+	 * and grouped by month and year.
411
+	 *
412
+	 * @param  array $where_params Array of query_params as described in the comments for EEM_Base::get_all()
413
+	 * @return array
414
+	 * @throws EE_Error
415
+	 */
416
+	public function get_reg_months_and_years($where_params)
417
+	{
418
+		$query_params[0] = $where_params;
419
+		$query_params['group_by'] = array('reg_year', 'reg_month');
420
+		$query_params['order_by'] = array('REG_date' => 'DESC');
421
+		$columns_to_select = array(
422
+			'reg_year' => array('YEAR(REG_date)', '%s'),
423
+			'reg_month' => array('MONTHNAME(REG_date)', '%s'),
424
+		);
425
+		return $this->_get_all_wpdb_results($query_params, OBJECT, $columns_to_select);
426
+	}
427
+
428
+
429
+	/**
430
+	 * retrieve ALL registrations for a particular Attendee from db
431
+	 *
432
+	 * @param int $ATT_ID
433
+	 * @return EE_Base_Class[]|EE_Registration[]|null
434
+	 * @throws EE_Error
435
+	 */
436
+	public function get_all_registrations_for_attendee($ATT_ID = 0)
437
+	{
438
+		if (!$ATT_ID) {
439
+			return null;
440
+		}
441
+		return $this->get_all(array(array('ATT_ID' => $ATT_ID)));
442
+	}
443
+
444
+
445
+	/**
446
+	 * Gets a registration given their REG_url_link. Yes, this should usually
447
+	 * be passed via a GET parameter.
448
+	 *
449
+	 * @param string $REG_url_link
450
+	 * @return EE_Base_Class|EE_Registration|null
451
+	 * @throws EE_Error
452
+	 */
453
+	public function get_registration_for_reg_url_link($REG_url_link)
454
+	{
455
+		if (!$REG_url_link) {
456
+			return null;
457
+		}
458
+		return $this->get_one(array(array('REG_url_link' => $REG_url_link)));
459
+	}
460
+
461
+
462
+	/**
463
+	 *        retrieve registration for a specific transaction attendee from db
464
+	 *
465
+	 * @access        public
466
+	 * @param    int $TXN_ID
467
+	 * @param    int $ATT_ID
468
+	 * @param    int $att_nmbr in case the ATT_ID is the same for multiple registrations (same details used) then the
469
+	 *                         attendee number is required
470
+	 * @return        mixed        array on success, FALSE on fail
471
+	 * @throws EE_Error
472
+	 */
473
+	public function get_registration_for_transaction_attendee($TXN_ID = 0, $ATT_ID = 0, $att_nmbr = 0)
474
+	{
475
+		return $this->get_one(array(
476
+			array(
477
+				'TXN_ID' => $TXN_ID,
478
+				'ATT_ID' => $ATT_ID,
479
+			),
480
+			'limit' => array(min($att_nmbr - 1, 0), 1),
481
+		));
482
+	}
483
+
484
+
485
+	/**
486
+	 *        get the number of registrations per day  for the Registration Admin page Reports Tab.
487
+	 *        (doesn't utilize models because it's a fairly specialized query)
488
+	 *
489
+	 * @access        public
490
+	 * @param $period string which can be passed to php's strtotime function (eg "-1 month")
491
+	 * @return stdClass[] with properties regDate and total
492
+	 * @throws EE_Error
493
+	 */
494
+	public function get_registrations_per_day_report($period = '-1 month')
495
+	{
496
+		$sql_date = $this->convert_datetime_for_query('REG_date', date('Y-m-d H:i:s', strtotime($period)),
497
+			'Y-m-d H:i:s', 'UTC');
498
+		$where = array(
499
+			'REG_date' => array('>=', $sql_date),
500
+			'STS_ID' => array('!=', EEM_Registration::status_id_incomplete),
501
+		);
502
+		if (!EE_Registry::instance()->CAP->current_user_can('ee_read_others_registrations', 'reg_per_day_report')) {
503
+			$where['Event.EVT_wp_user'] = get_current_user_id();
504
+		}
505
+		$query_interval = EEH_DTT_Helper::get_sql_query_interval_for_offset($this->get_timezone(), 'REG_date');
506
+		$results = $this->_get_all_wpdb_results(
507
+			array(
508
+				$where,
509
+				'group_by' => 'regDate',
510
+				'order_by' => array('REG_date' => 'ASC'),
511
+			),
512
+			OBJECT,
513
+			array(
514
+				'regDate' => array('DATE(' . $query_interval . ')', '%s'),
515
+				'total' => array('count(REG_ID)', '%d'),
516
+			));
517
+		return $results;
518
+	}
519
+
520
+
521
+	/**
522
+	 * Get the number of registrations per day including the count of registrations for each Registration Status.
523
+	 * Note: EEM_Registration::status_id_incomplete registrations are excluded from the results.
524
+	 *
525
+	 * @param string $period
526
+	 * @return stdClass[] with properties Registration_REG_date and a column for each registration status as the STS_ID
527
+	 * @throws EE_Error
528
+	 *                    (i.e. RAP)
529
+	 */
530
+	public function get_registrations_per_day_and_per_status_report($period = '-1 month')
531
+	{
532
+		global $wpdb;
533
+		$registration_table = $wpdb->prefix . 'esp_registration';
534
+		$event_table = $wpdb->posts;
535
+		$sql_date = date('Y-m-d H:i:s', strtotime($period));
536
+		//prepare the query interval for displaying offset
537
+		$query_interval = EEH_DTT_Helper::get_sql_query_interval_for_offset($this->get_timezone(), 'dates.REG_date');
538
+		//inner date query
539
+		$inner_date_query = "SELECT DISTINCT REG_date from {$registration_table} ";
540
+		$inner_where = ' WHERE';
541
+		//exclude events not authored by user if permissions in effect
542
+		if (!EE_Registry::instance()->CAP->current_user_can('ee_read_others_registrations', 'reg_per_event_report')) {
543
+			$inner_date_query .= "LEFT JOIN {$event_table} ON ID = EVT_ID";
544
+			$inner_where .= ' post_author = ' . get_current_user_id() . ' AND';
545
+		}
546
+		$inner_where .= " REG_date >= '{$sql_date}'";
547
+		$inner_date_query .= $inner_where;
548
+		//start main query
549
+		$select = "SELECT DATE({$query_interval}) as Registration_REG_date, ";
550
+		$join = '';
551
+		$join_parts = array();
552
+		$select_parts = array();
553
+		//loop through registration stati to do parts for each status.
554
+		foreach (EEM_Registration::reg_status_array() as $STS_ID => $STS_code) {
555
+			if ($STS_ID === EEM_Registration::status_id_incomplete) {
556
+				continue;
557
+			}
558
+			$select_parts[] = "COUNT({$STS_code}.REG_ID) as {$STS_ID}";
559
+			$join_parts[] = "{$registration_table} AS {$STS_code} ON {$STS_code}.REG_date = dates.REG_date AND {$STS_code}.STS_ID = '{$STS_ID}'";
560
+		}
561
+		//setup the selects
562
+		$select .= implode(', ', $select_parts);
563
+		$select .= " FROM ($inner_date_query) AS dates LEFT JOIN ";
564
+		//setup the joins
565
+		$join .= implode(' LEFT JOIN ', $join_parts);
566
+		//now let's put it all together
567
+		$query = $select . $join . ' GROUP BY Registration_REG_date';
568
+		//and execute it
569
+		return $wpdb->get_results($query, ARRAY_A);
570
+	}
571
+
572
+
573
+	/**
574
+	 *        get the number of registrations per event  for the Registration Admin page Reports Tab
575
+	 *
576
+	 * @access        public
577
+	 * @param $period string which can be passed to php's strtotime function (eg "-1 month")
578
+	 * @return stdClass[] each with properties event_name, reg_limit, and total
579
+	 * @throws EE_Error
580
+	 */
581
+	public function get_registrations_per_event_report($period = '-1 month')
582
+	{
583
+		$date_sql = $this->convert_datetime_for_query('REG_date', date('Y-m-d H:i:s', strtotime($period)),
584
+			'Y-m-d H:i:s', 'UTC');
585
+		$where = array(
586
+			'REG_date' => array('>=', $date_sql),
587
+			'STS_ID' => array('!=', EEM_Registration::status_id_incomplete),
588
+		);
589
+		if (
590
+		!EE_Registry::instance()->CAP->current_user_can(
591
+			'ee_read_others_registrations',
592
+			'reg_per_event_report'
593
+		)
594
+		) {
595
+			$where['Event.EVT_wp_user'] = get_current_user_id();
596
+		}
597
+		$results = $this->_get_all_wpdb_results(array(
598
+			$where,
599
+			'group_by' => 'Event.EVT_name',
600
+			'order_by' => 'Event.EVT_name',
601
+			'limit' => array(0, 24),
602
+		),
603
+			OBJECT,
604
+			array(
605
+				'event_name' => array('Event_CPT.post_title', '%s'),
606
+				'total' => array('COUNT(REG_ID)', '%s'),
607
+			)
608
+		);
609
+		return $results;
610
+	}
611
+
612
+
613
+	/**
614
+	 * Get the number of registrations per event grouped by registration status.
615
+	 * Note: EEM_Registration::status_id_incomplete registrations are excluded from the results.
616
+	 *
617
+	 * @param string $period
618
+	 * @return stdClass[] with properties `Registration_Event` and a column for each registration status as the STS_ID
619
+	 * @throws EE_Error
620
+	 *                    (i.e. RAP)
621
+	 */
622
+	public function get_registrations_per_event_and_per_status_report($period = '-1 month')
623
+	{
624
+		global $wpdb;
625
+		$registration_table = $wpdb->prefix . 'esp_registration';
626
+		$event_table = $wpdb->posts;
627
+		$sql_date = date('Y-m-d H:i:s', strtotime($period));
628
+		//inner date query
629
+		$inner_date_query = "SELECT DISTINCT EVT_ID, REG_date from $registration_table ";
630
+		$inner_where = ' WHERE';
631
+		//exclude events not authored by user if permissions in effect
632
+		if (!EE_Registry::instance()->CAP->current_user_can('ee_read_others_registrations', 'reg_per_event_report')) {
633
+			$inner_date_query .= "LEFT JOIN {$event_table} ON ID = EVT_ID";
634
+			$inner_where .= ' post_author = ' . get_current_user_id() . ' AND';
635
+		}
636
+		$inner_where .= " REG_date >= '{$sql_date}'";
637
+		$inner_date_query .= $inner_where;
638
+		//build main query
639
+		$select = 'SELECT Event.post_title as Registration_Event, ';
640
+		$join = '';
641
+		$join_parts = array();
642
+		$select_parts = array();
643
+		//loop through registration stati to do parts for each status.
644
+		foreach (EEM_Registration::reg_status_array() as $STS_ID => $STS_code) {
645
+			if ($STS_ID === EEM_Registration::status_id_incomplete) {
646
+				continue;
647
+			}
648
+			$select_parts[] = "COUNT({$STS_code}.REG_ID) as {$STS_ID}";
649
+			$join_parts[] = "{$registration_table} AS {$STS_code} ON {$STS_code}.EVT_ID = dates.EVT_ID AND {$STS_code}.STS_ID = '{$STS_ID}' AND {$STS_code}.REG_date = dates.REG_date";
650
+		}
651
+		//setup the selects
652
+		$select .= implode(', ', $select_parts);
653
+		$select .= " FROM ($inner_date_query) AS dates LEFT JOIN $event_table as Event ON Event.ID = dates.EVT_ID LEFT JOIN ";
654
+		//setup remaining joins
655
+		$join .= implode(' LEFT JOIN ', $join_parts);
656
+		//now put it all together
657
+		$query = $select . $join . ' GROUP BY Registration_Event';
658
+		//and execute
659
+		return $wpdb->get_results($query, ARRAY_A);
660
+	}
661
+
662
+
663
+	/**
664
+	 * Returns the EE_Registration of the primary attendee on the transaction id provided
665
+	 *
666
+	 * @param int $TXN_ID
667
+	 * @return EE_Base_Class|EE_Registration|null
668
+	 * @throws EE_Error
669
+	 */
670
+	public function get_primary_registration_for_transaction_ID($TXN_ID = 0)
671
+	{
672
+		if (!$TXN_ID) {
673
+			return null;
674
+		}
675
+		return $this->get_one(array(
676
+			array(
677
+				'TXN_ID' => $TXN_ID,
678
+				'REG_count' => EEM_Registration::PRIMARY_REGISTRANT_COUNT,
679
+			),
680
+		));
681
+	}
682
+
683
+
684
+	/**
685
+	 *        get_event_registration_count
686
+	 *
687
+	 * @access public
688
+	 * @param int $EVT_ID
689
+	 * @param boolean $for_incomplete_payments
690
+	 * @return int
691
+	 * @throws EE_Error
692
+	 */
693
+	public function get_event_registration_count($EVT_ID, $for_incomplete_payments = false)
694
+	{
695
+		// we only count approved registrations towards registration limits
696
+		$query_params = array(array('EVT_ID' => $EVT_ID, 'STS_ID' => self::status_id_approved));
697
+		if ($for_incomplete_payments) {
698
+			$query_params[0]['Transaction.STS_ID'] = array('!=', EEM_Transaction::complete_status_code);
699
+		}
700
+		return $this->count($query_params);
701
+	}
702
+
703
+
704
+	/**
705
+	 * Deletes all registrations with no transactions. Note that this needs to be very efficient
706
+	 * and so it uses wpdb directly
707
+	 *
708
+	 * @global WPDB $wpdb
709
+	 * @return int number deleted
710
+	 * @throws EE_Error
711
+	 */
712
+	public function delete_registrations_with_no_transaction()
713
+	{
714
+		/** @type WPDB $wpdb */
715
+		global $wpdb;
716
+		return $wpdb->query(
717
+			'DELETE r FROM '
718
+			. $this->table()
719
+			. ' r LEFT JOIN '
720
+			. EEM_Transaction::instance()->table()
721
+			. ' t ON r.TXN_ID = t.TXN_ID WHERE t.TXN_ID IS NULL');
722
+	}
723
+
724
+
725
+	/**
726
+	 *  Count registrations checked into (or out of) a datetime
727
+	 *
728
+	 * @param int $DTT_ID datetime ID
729
+	 * @param boolean $checked_in whether to count registrations checked IN or OUT
730
+	 * @return int
731
+	 * @throws EE_Error
732
+	 */
733
+	public function count_registrations_checked_into_datetime($DTT_ID, $checked_in = true)
734
+	{
735
+		global $wpdb;
736
+		//subquery to get latest checkin
737
+		$query = $wpdb->prepare(
738
+			'SELECT '
739
+			. 'COUNT( DISTINCT checkins.REG_ID ) '
740
+			. 'FROM ' . EEM_Checkin::instance()->table() . ' AS checkins INNER JOIN'
741
+			. '( SELECT '
742
+			. 'max( CHK_timestamp ) AS latest_checkin, '
743
+			. 'REG_ID AS REG_ID '
744
+			. 'FROM ' . EEM_Checkin::instance()->table() . ' '
745
+			. 'WHERE DTT_ID=%d '
746
+			. 'GROUP BY REG_ID'
747
+			. ') AS most_recent_checkin_per_reg '
748
+			. 'ON checkins.REG_ID=most_recent_checkin_per_reg.REG_ID '
749
+			. 'AND checkins.CHK_timestamp = most_recent_checkin_per_reg.latest_checkin '
750
+			. 'WHERE '
751
+			. 'checkins.CHK_in=%d',
752
+			$DTT_ID,
753
+			$checked_in
754
+		);
755
+		return (int)$wpdb->get_var($query);
756
+	}
757
+
758
+
759
+	/**
760
+	 *  Count registrations checked into (or out of) an event.
761
+	 *
762
+	 * @param int $EVT_ID event ID
763
+	 * @param boolean $checked_in whether to count registrations checked IN or OUT
764
+	 * @return int
765
+	 * @throws EE_Error
766
+	 */
767
+	public function count_registrations_checked_into_event($EVT_ID, $checked_in = true)
768
+	{
769
+		global $wpdb;
770
+		//subquery to get latest checkin
771
+		$query = $wpdb->prepare(
772
+			'SELECT '
773
+			. 'COUNT( DISTINCT checkins.REG_ID ) '
774
+			. 'FROM ' . EEM_Checkin::instance()->table() . ' AS checkins INNER JOIN'
775
+			. '( SELECT '
776
+			. 'max( CHK_timestamp ) AS latest_checkin, '
777
+			. 'REG_ID AS REG_ID '
778
+			. 'FROM ' . EEM_Checkin::instance()->table() . ' AS c '
779
+			. 'INNER JOIN ' . EEM_Datetime::instance()->table() . ' AS d '
780
+			. 'ON c.DTT_ID=d.DTT_ID '
781
+			. 'WHERE d.EVT_ID=%d '
782
+			. 'GROUP BY REG_ID'
783
+			. ') AS most_recent_checkin_per_reg '
784
+			. 'ON checkins.REG_ID=most_recent_checkin_per_reg.REG_ID '
785
+			. 'AND checkins.CHK_timestamp = most_recent_checkin_per_reg.latest_checkin '
786
+			. 'WHERE '
787
+			. 'checkins.CHK_in=%d',
788
+			$EVT_ID,
789
+			$checked_in
790
+		);
791
+		return (int)$wpdb->get_var($query);
792
+	}
793
+
794
+
795
+	/**
796
+	 * The purpose of this method is to retrieve an array of
797
+	 * EE_Registration objects that represent the latest registration
798
+	 * for each ATT_ID given in the function argument.
799
+	 *
800
+	 * @param array $attendee_ids
801
+	 * @return EE_Base_Class[]|EE_Registration[]
802
+	 * @throws EE_Error
803
+	 */
804
+	public function get_latest_registration_for_each_of_given_contacts($attendee_ids = array())
805
+	{
806
+		//first do a native wp_query to get the latest REG_ID's matching these attendees.
807
+		global $wpdb;
808
+		$registration_table = $wpdb->prefix . 'esp_registration';
809
+		$attendee_table = $wpdb->posts;
810
+		$attendee_ids = is_array($attendee_ids)
811
+			? array_map('absint', $attendee_ids)
812
+			: array((int)$attendee_ids);
813
+		$ATT_IDs = implode(',', $attendee_ids);
814
+		// first we do a query to get the registration ids
815
+		// (because a group by before order by causes the order by to be ignored.)
816
+		$registration_id_query = "
817 817
 			SELECT registrations.registration_ids as registration_id
818 818
 			FROM (
819 819
 				SELECT
@@ -827,63 +827,63 @@  discard block
 block discarded – undo
827 827
 			  ) AS registrations
828 828
 			  GROUP BY registrations.attendee_ids
829 829
 		";
830
-        $registration_ids = $wpdb->get_results($registration_id_query, ARRAY_A);
831
-        if (empty($registration_ids)) {
832
-            return array();
833
-        }
834
-        $ids_for_model_query = array();
835
-        //let's flatten the ids so they can be used in the model query.
836
-        foreach ($registration_ids as $registration_id) {
837
-            if (isset($registration_id['registration_id'])) {
838
-                $ids_for_model_query[] = $registration_id['registration_id'];
839
-            }
840
-        }
841
-        //construct query
842
-        $_where = array(
843
-            'REG_ID' => array('IN', $ids_for_model_query),
844
-        );
845
-        return $this->get_all(array($_where));
846
-    }
847
-
848
-
849
-
850
-    /**
851
-     * returns a count of registrations for the supplied event having the status as specified
852
-     *
853
-     * @param int $EVT_ID
854
-     * @param array $statuses
855
-     * @return int
856
-     * @throws InvalidArgumentException
857
-     * @throws InvalidStatusException
858
-     * @throws EE_Error
859
-     */
860
-    public function event_reg_count_for_statuses($EVT_ID, $statuses = array() )
861
-    {
862
-        $EVT_ID = absint($EVT_ID);
863
-        if (! $EVT_ID) {
864
-            throw new InvalidArgumentException(
865
-                esc_html__('An invalid Event ID was supplied.', 'event_espresso')
866
-            );
867
-        }
868
-        $statuses = is_array($statuses) ? $statuses : array($statuses);
869
-        $statuses = ! empty($statuses) ? $statuses : array(EEM_Registration::status_id_approved);
870
-        $valid_reg_statuses = EEM_Registration::reg_statuses();
871
-        foreach ($statuses as $status) {
872
-            if(! in_array($status, $valid_reg_statuses, true)) {
873
-                throw new InvalidStatusException($status, esc_html__('Registration', 'event_espresso'));
874
-            }
875
-        }
876
-        return $this->count(
877
-            array(
878
-                array(
879
-                    'EVT_ID' => $EVT_ID,
880
-                    'STS_ID' => array('IN', $statuses),
881
-                ),
882
-            ),
883
-            'REG_ID',
884
-            true
885
-        );
886
-    }
830
+		$registration_ids = $wpdb->get_results($registration_id_query, ARRAY_A);
831
+		if (empty($registration_ids)) {
832
+			return array();
833
+		}
834
+		$ids_for_model_query = array();
835
+		//let's flatten the ids so they can be used in the model query.
836
+		foreach ($registration_ids as $registration_id) {
837
+			if (isset($registration_id['registration_id'])) {
838
+				$ids_for_model_query[] = $registration_id['registration_id'];
839
+			}
840
+		}
841
+		//construct query
842
+		$_where = array(
843
+			'REG_ID' => array('IN', $ids_for_model_query),
844
+		);
845
+		return $this->get_all(array($_where));
846
+	}
847
+
848
+
849
+
850
+	/**
851
+	 * returns a count of registrations for the supplied event having the status as specified
852
+	 *
853
+	 * @param int $EVT_ID
854
+	 * @param array $statuses
855
+	 * @return int
856
+	 * @throws InvalidArgumentException
857
+	 * @throws InvalidStatusException
858
+	 * @throws EE_Error
859
+	 */
860
+	public function event_reg_count_for_statuses($EVT_ID, $statuses = array() )
861
+	{
862
+		$EVT_ID = absint($EVT_ID);
863
+		if (! $EVT_ID) {
864
+			throw new InvalidArgumentException(
865
+				esc_html__('An invalid Event ID was supplied.', 'event_espresso')
866
+			);
867
+		}
868
+		$statuses = is_array($statuses) ? $statuses : array($statuses);
869
+		$statuses = ! empty($statuses) ? $statuses : array(EEM_Registration::status_id_approved);
870
+		$valid_reg_statuses = EEM_Registration::reg_statuses();
871
+		foreach ($statuses as $status) {
872
+			if(! in_array($status, $valid_reg_statuses, true)) {
873
+				throw new InvalidStatusException($status, esc_html__('Registration', 'event_espresso'));
874
+			}
875
+		}
876
+		return $this->count(
877
+			array(
878
+				array(
879
+					'EVT_ID' => $EVT_ID,
880
+					'STS_ID' => array('IN', $statuses),
881
+				),
882
+			),
883
+			'REG_ID',
884
+			true
885
+		);
886
+	}
887 887
 
888 888
 }
889 889
 // End of file EEM_Registration.model.php
Please login to merge, or discard this patch.
core/exceptions/InvalidStatusException.php 1 patch
Indentation   +22 added lines, -22 removed lines patch added patch discarded remove patch
@@ -8,26 +8,26 @@
 block discarded – undo
8 8
 
9 9
 class InvalidStatusException extends InvalidArgumentException
10 10
 {
11
-    /**
12
-     * InvalidStatusException constructor.
13
-     * @param string $status the invalid status id that was supplied
14
-     * @param string $domain the name of the domain, model, or class that the status belongs to
15
-     * @param string $message custom message
16
-     * @param int $code
17
-     * @param Exception|null $previous
18
-     */
19
-    public function __construct($status, $domain, $message = '', $code = 0, Exception $previous = null)
20
-    {
21
-        if (empty($message)) {
22
-            $message = sprintf(
23
-                __(
24
-                    '"%1$s" is not a valid %2$s status',
25
-                    'event_espresso'
26
-                ),
27
-                $status,
28
-                $domain
29
-            );
30
-        }
31
-        parent::__construct($message, $code, $previous);
32
-    }
11
+	/**
12
+	 * InvalidStatusException constructor.
13
+	 * @param string $status the invalid status id that was supplied
14
+	 * @param string $domain the name of the domain, model, or class that the status belongs to
15
+	 * @param string $message custom message
16
+	 * @param int $code
17
+	 * @param Exception|null $previous
18
+	 */
19
+	public function __construct($status, $domain, $message = '', $code = 0, Exception $previous = null)
20
+	{
21
+		if (empty($message)) {
22
+			$message = sprintf(
23
+				__(
24
+					'"%1$s" is not a valid %2$s status',
25
+					'event_espresso'
26
+				),
27
+				$status,
28
+				$domain
29
+			);
30
+		}
31
+		parent::__construct($message, $code, $previous);
32
+	}
33 33
 }
Please login to merge, or discard this patch.