Completed
Branch BUG/delete-event (90429b)
by
unknown
04:16 queued 02:20
created
modules/ticket_selector/TicketSelector.php 2 patches
Indentation   +107 added lines, -107 removed lines patch added patch discarded remove patch
@@ -20,111 +20,111 @@
 block discarded – undo
20 20
 abstract class TicketSelector
21 21
 {
22 22
 
23
-    /**
24
-     * @var EE_Event
25
-     */
26
-    protected $event;
27
-
28
-    /**
29
-     * @var EE_Ticket[]
30
-     */
31
-    protected $tickets;
32
-
33
-    /**
34
-     * @var int
35
-     */
36
-    protected $max_attendees;
37
-
38
-    /**
39
-     * @var array
40
-     */
41
-    protected $template_args;
42
-
43
-    /**
44
-     * @var int
45
-     */
46
-    protected $ticket_rows = 0;
47
-
48
-
49
-    /**
50
-     * TicketSelectorSimple constructor.
51
-     *
52
-     * @param EE_Event    $event
53
-     * @param EE_Ticket[] $tickets
54
-     * @param int          $max_attendees
55
-     * @param array        $template_args
56
-     */
57
-    public function __construct(EE_Event $event, array $tickets, $max_attendees, array $template_args)
58
-    {
59
-        $this->event = $event;
60
-        $this->tickets = $tickets;
61
-        $this->max_attendees = $max_attendees;
62
-        $this->template_args = $template_args;
63
-        $this->addTemplateArgs();
64
-    }
65
-
66
-
67
-    /**
68
-     * sets any and all template args that are required for this Ticket Selector
69
-     *
70
-     * @return void
71
-     */
72
-    abstract protected function addTemplateArgs();
73
-
74
-
75
-    /**
76
-     * loadTicketSelectorTemplate
77
-     *
78
-     * @return string
79
-     */
80
-    protected function loadTicketSelectorTemplate()
81
-    {
82
-        try {
83
-            $this->template_args['hidden_inputs'] = $this->getHiddenInputs();
84
-            return EEH_Template::locate_template(
85
-                apply_filters(
86
-                    'FHEE__EE_Ticket_Selector__display_ticket_selector__template_path',
87
-                    $this->template_args['template_path'],
88
-                    $this->event
89
-                ),
90
-                $this->template_args
91
-            );
92
-        } catch (Exception $e) {
93
-            EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
94
-        }
95
-        return '';
96
-    }
97
-
98
-
99
-    /**
100
-     * The __toString method allows a class to decide how it will react when it is converted to a string.
101
-     *
102
-     * @return string
103
-     * @link http://php.net/manual/en/language.oop5.magic.php#language.oop5.magic.tostring
104
-     */
105
-    public function __toString()
106
-    {
107
-        return $this->loadTicketSelectorTemplate();
108
-    }
109
-
110
-
111
-    /**
112
-     * getHiddenInputs
113
-     *
114
-     * @return string
115
-     * @throws EE_Error
116
-     * @throws ReflectionException
117
-     */
118
-    public function getHiddenInputs()
119
-    {
120
-        $html = '<input type="hidden" name="noheader" value="true"/>';
121
-        $html .= '<input type="hidden" name="tkt-slctr-return-url-' . $this->event->ID() . '"';
122
-        $html .= ' value="' . EEH_URL::current_url() . $this->template_args['anchor_id'] . '"/>';
123
-        $html .= '<input type="hidden" name="tkt-slctr-rows-' . $this->event->ID();
124
-        $html .= '" value="' . $this->ticket_rows . '"/>';
125
-        $html .= '<input type="hidden" name="tkt-slctr-max-atndz-' . $this->event->ID();
126
-        $html .= '" value="' . $this->template_args['max_atndz'] . '"/>';
127
-        $html .= '<input type="hidden" name="tkt-slctr-event-id" value="' . $this->event->ID() . '"/>';
128
-        return $html;
129
-    }
23
+	/**
24
+	 * @var EE_Event
25
+	 */
26
+	protected $event;
27
+
28
+	/**
29
+	 * @var EE_Ticket[]
30
+	 */
31
+	protected $tickets;
32
+
33
+	/**
34
+	 * @var int
35
+	 */
36
+	protected $max_attendees;
37
+
38
+	/**
39
+	 * @var array
40
+	 */
41
+	protected $template_args;
42
+
43
+	/**
44
+	 * @var int
45
+	 */
46
+	protected $ticket_rows = 0;
47
+
48
+
49
+	/**
50
+	 * TicketSelectorSimple constructor.
51
+	 *
52
+	 * @param EE_Event    $event
53
+	 * @param EE_Ticket[] $tickets
54
+	 * @param int          $max_attendees
55
+	 * @param array        $template_args
56
+	 */
57
+	public function __construct(EE_Event $event, array $tickets, $max_attendees, array $template_args)
58
+	{
59
+		$this->event = $event;
60
+		$this->tickets = $tickets;
61
+		$this->max_attendees = $max_attendees;
62
+		$this->template_args = $template_args;
63
+		$this->addTemplateArgs();
64
+	}
65
+
66
+
67
+	/**
68
+	 * sets any and all template args that are required for this Ticket Selector
69
+	 *
70
+	 * @return void
71
+	 */
72
+	abstract protected function addTemplateArgs();
73
+
74
+
75
+	/**
76
+	 * loadTicketSelectorTemplate
77
+	 *
78
+	 * @return string
79
+	 */
80
+	protected function loadTicketSelectorTemplate()
81
+	{
82
+		try {
83
+			$this->template_args['hidden_inputs'] = $this->getHiddenInputs();
84
+			return EEH_Template::locate_template(
85
+				apply_filters(
86
+					'FHEE__EE_Ticket_Selector__display_ticket_selector__template_path',
87
+					$this->template_args['template_path'],
88
+					$this->event
89
+				),
90
+				$this->template_args
91
+			);
92
+		} catch (Exception $e) {
93
+			EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
94
+		}
95
+		return '';
96
+	}
97
+
98
+
99
+	/**
100
+	 * The __toString method allows a class to decide how it will react when it is converted to a string.
101
+	 *
102
+	 * @return string
103
+	 * @link http://php.net/manual/en/language.oop5.magic.php#language.oop5.magic.tostring
104
+	 */
105
+	public function __toString()
106
+	{
107
+		return $this->loadTicketSelectorTemplate();
108
+	}
109
+
110
+
111
+	/**
112
+	 * getHiddenInputs
113
+	 *
114
+	 * @return string
115
+	 * @throws EE_Error
116
+	 * @throws ReflectionException
117
+	 */
118
+	public function getHiddenInputs()
119
+	{
120
+		$html = '<input type="hidden" name="noheader" value="true"/>';
121
+		$html .= '<input type="hidden" name="tkt-slctr-return-url-' . $this->event->ID() . '"';
122
+		$html .= ' value="' . EEH_URL::current_url() . $this->template_args['anchor_id'] . '"/>';
123
+		$html .= '<input type="hidden" name="tkt-slctr-rows-' . $this->event->ID();
124
+		$html .= '" value="' . $this->ticket_rows . '"/>';
125
+		$html .= '<input type="hidden" name="tkt-slctr-max-atndz-' . $this->event->ID();
126
+		$html .= '" value="' . $this->template_args['max_atndz'] . '"/>';
127
+		$html .= '<input type="hidden" name="tkt-slctr-event-id" value="' . $this->event->ID() . '"/>';
128
+		return $html;
129
+	}
130 130
 }
Please login to merge, or discard this patch.
Spacing   +7 added lines, -7 removed lines patch added patch discarded remove patch
@@ -118,13 +118,13 @@
 block discarded – undo
118 118
     public function getHiddenInputs()
119 119
     {
120 120
         $html = '<input type="hidden" name="noheader" value="true"/>';
121
-        $html .= '<input type="hidden" name="tkt-slctr-return-url-' . $this->event->ID() . '"';
122
-        $html .= ' value="' . EEH_URL::current_url() . $this->template_args['anchor_id'] . '"/>';
123
-        $html .= '<input type="hidden" name="tkt-slctr-rows-' . $this->event->ID();
124
-        $html .= '" value="' . $this->ticket_rows . '"/>';
125
-        $html .= '<input type="hidden" name="tkt-slctr-max-atndz-' . $this->event->ID();
126
-        $html .= '" value="' . $this->template_args['max_atndz'] . '"/>';
127
-        $html .= '<input type="hidden" name="tkt-slctr-event-id" value="' . $this->event->ID() . '"/>';
121
+        $html .= '<input type="hidden" name="tkt-slctr-return-url-'.$this->event->ID().'"';
122
+        $html .= ' value="'.EEH_URL::current_url().$this->template_args['anchor_id'].'"/>';
123
+        $html .= '<input type="hidden" name="tkt-slctr-rows-'.$this->event->ID();
124
+        $html .= '" value="'.$this->ticket_rows.'"/>';
125
+        $html .= '<input type="hidden" name="tkt-slctr-max-atndz-'.$this->event->ID();
126
+        $html .= '" value="'.$this->template_args['max_atndz'].'"/>';
127
+        $html .= '<input type="hidden" name="tkt-slctr-event-id" value="'.$this->event->ID().'"/>';
128 128
         return $html;
129 129
     }
130 130
 }
Please login to merge, or discard this patch.
modules/ticket_selector/TicketSelectorStandard.php 2 patches
Indentation   +113 added lines, -113 removed lines patch added patch discarded remove patch
@@ -20,125 +20,125 @@
 block discarded – undo
20 20
 class TicketSelectorStandard extends TicketSelector
21 21
 {
22 22
 
23
-    /**
24
-     * @var string $date_format
25
-     */
26
-    protected $date_format;
23
+	/**
24
+	 * @var string $date_format
25
+	 */
26
+	protected $date_format;
27 27
 
28
-    /**
29
-     * @var string $time_format
30
-     */
31
-    protected $time_format;
28
+	/**
29
+	 * @var string $time_format
30
+	 */
31
+	protected $time_format;
32 32
 
33
-    /**
34
-     * @var EE_Ticket_Selector_Config $ticket_selector_config
35
-     */
36
-    protected $ticket_selector_config;
33
+	/**
34
+	 * @var EE_Ticket_Selector_Config $ticket_selector_config
35
+	 */
36
+	protected $ticket_selector_config;
37 37
 
38
-    /**
39
-     * @var EE_Tax_Config $tax_config
40
-     */
41
-    protected $tax_config;
38
+	/**
39
+	 * @var EE_Tax_Config $tax_config
40
+	 */
41
+	protected $tax_config;
42 42
 
43 43
 
44
-    /**
45
-     * TicketSelectorSimple constructor.
46
-     *
47
-     * @param EE_Ticket_Selector_Config $ticket_selector_config
48
-     * @param EE_Tax_Config             $tax_config
49
-     * @param EE_Event                  $event
50
-     * @param EE_Ticket[]               $tickets
51
-     * @param int                       $max_attendees
52
-     * @param array                     $template_args
53
-     * @param string                    $date_format
54
-     * @param string                    $time_format
55
-     * @throws EE_Error
56
-     */
57
-    public function __construct(
58
-        EE_Ticket_Selector_Config $ticket_selector_config,
59
-        EE_Tax_Config $tax_config,
60
-        EE_Event $event,
61
-        array $tickets,
62
-        $max_attendees,
63
-        array $template_args,
64
-        $date_format = 'Y-m-d',
65
-        $time_format = 'g:i a'
66
-    ) {
67
-        $this->ticket_selector_config = $ticket_selector_config;
68
-        $this->tax_config             = $tax_config;
69
-        $this->date_format            = $date_format;
70
-        $this->time_format            = $time_format;
71
-        parent::__construct($event, $tickets, $max_attendees, $template_args);
72
-    }
44
+	/**
45
+	 * TicketSelectorSimple constructor.
46
+	 *
47
+	 * @param EE_Ticket_Selector_Config $ticket_selector_config
48
+	 * @param EE_Tax_Config             $tax_config
49
+	 * @param EE_Event                  $event
50
+	 * @param EE_Ticket[]               $tickets
51
+	 * @param int                       $max_attendees
52
+	 * @param array                     $template_args
53
+	 * @param string                    $date_format
54
+	 * @param string                    $time_format
55
+	 * @throws EE_Error
56
+	 */
57
+	public function __construct(
58
+		EE_Ticket_Selector_Config $ticket_selector_config,
59
+		EE_Tax_Config $tax_config,
60
+		EE_Event $event,
61
+		array $tickets,
62
+		$max_attendees,
63
+		array $template_args,
64
+		$date_format = 'Y-m-d',
65
+		$time_format = 'g:i a'
66
+	) {
67
+		$this->ticket_selector_config = $ticket_selector_config;
68
+		$this->tax_config             = $tax_config;
69
+		$this->date_format            = $date_format;
70
+		$this->time_format            = $time_format;
71
+		parent::__construct($event, $tickets, $max_attendees, $template_args);
72
+	}
73 73
 
74 74
 
75
-    /**
76
-     * sets any and all template args that are required for this Ticket Selector
77
-     *
78
-     * @return void
79
-     * @throws EE_Error
80
-     */
81
-    protected function addTemplateArgs()
82
-    {
83
-        $this->ticket_rows        = 0;
84
-        $all_ticket_rows_html     = '';
85
-        $required_ticket_sold_out = false;
86
-        // flag to indicate that at least one taxable ticket has been encountered
87
-        $taxable_tickets                          = false;
88
-        $datetime_selector                        = null;
89
-        $this->template_args['datetime_selector'] = '';
90
-        if (
91
-            $this->ticket_selector_config->getShowDatetimeSelector()
92
-            !== EE_Ticket_Selector_Config::DO_NOT_SHOW_DATETIME_SELECTOR
93
-        ) {
94
-            $datetime_selector                        = new DatetimeSelector(
95
-                $this->event,
96
-                $this->tickets,
97
-                $this->ticket_selector_config,
98
-                $this->date_format,
99
-                $this->time_format
100
-            );
101
-            $this->template_args['datetime_selector'] = $datetime_selector->getDatetimeSelector();
102
-        }
103
-        $total_tickets = count($this->tickets);
104
-        // loop through tickets
105
-        foreach ($this->tickets as $ticket) {
106
-            if ($ticket instanceof EE_Ticket) {
107
-                $this->ticket_rows++;
108
-                $cols                     = 2;
109
-                $taxable_tickets          = $ticket->taxable() ? true : $taxable_tickets;
110
-                $ticket_selector_row      = new TicketSelectorRowStandard(
111
-                    new TicketDetails($ticket, $this->ticket_selector_config, $this->template_args),
112
-                    $this->tax_config,
113
-                    $total_tickets,
114
-                    $this->max_attendees,
115
-                    $this->ticket_rows,
116
-                    $cols,
117
-                    $required_ticket_sold_out,
118
-                    $this->template_args['event_status'],
119
-                    $datetime_selector instanceof DatetimeSelector
120
-                        ? $datetime_selector->getTicketDatetimeClasses($ticket)
121
-                        : ''
122
-                );
123
-                $ticket_row_html = $ticket_selector_row->getHtml();
124
-                // check if something was actually returned
125
-                if (! empty($ticket_row_html)) {
126
-                    // add any output to the cumulative HTML
127
-                    $all_ticket_rows_html .= $ticket_row_html;
128
-                } else {
129
-                    // or decrement the ticket row count since it looks like one has been removed
130
-                    $this->ticket_rows--;
131
-                }
75
+	/**
76
+	 * sets any and all template args that are required for this Ticket Selector
77
+	 *
78
+	 * @return void
79
+	 * @throws EE_Error
80
+	 */
81
+	protected function addTemplateArgs()
82
+	{
83
+		$this->ticket_rows        = 0;
84
+		$all_ticket_rows_html     = '';
85
+		$required_ticket_sold_out = false;
86
+		// flag to indicate that at least one taxable ticket has been encountered
87
+		$taxable_tickets                          = false;
88
+		$datetime_selector                        = null;
89
+		$this->template_args['datetime_selector'] = '';
90
+		if (
91
+			$this->ticket_selector_config->getShowDatetimeSelector()
92
+			!== EE_Ticket_Selector_Config::DO_NOT_SHOW_DATETIME_SELECTOR
93
+		) {
94
+			$datetime_selector                        = new DatetimeSelector(
95
+				$this->event,
96
+				$this->tickets,
97
+				$this->ticket_selector_config,
98
+				$this->date_format,
99
+				$this->time_format
100
+			);
101
+			$this->template_args['datetime_selector'] = $datetime_selector->getDatetimeSelector();
102
+		}
103
+		$total_tickets = count($this->tickets);
104
+		// loop through tickets
105
+		foreach ($this->tickets as $ticket) {
106
+			if ($ticket instanceof EE_Ticket) {
107
+				$this->ticket_rows++;
108
+				$cols                     = 2;
109
+				$taxable_tickets          = $ticket->taxable() ? true : $taxable_tickets;
110
+				$ticket_selector_row      = new TicketSelectorRowStandard(
111
+					new TicketDetails($ticket, $this->ticket_selector_config, $this->template_args),
112
+					$this->tax_config,
113
+					$total_tickets,
114
+					$this->max_attendees,
115
+					$this->ticket_rows,
116
+					$cols,
117
+					$required_ticket_sold_out,
118
+					$this->template_args['event_status'],
119
+					$datetime_selector instanceof DatetimeSelector
120
+						? $datetime_selector->getTicketDatetimeClasses($ticket)
121
+						: ''
122
+				);
123
+				$ticket_row_html = $ticket_selector_row->getHtml();
124
+				// check if something was actually returned
125
+				if (! empty($ticket_row_html)) {
126
+					// add any output to the cumulative HTML
127
+					$all_ticket_rows_html .= $ticket_row_html;
128
+				} else {
129
+					// or decrement the ticket row count since it looks like one has been removed
130
+					$this->ticket_rows--;
131
+				}
132 132
 
133
-                $required_ticket_sold_out = $ticket_selector_row->getRequiredTicketSoldOut();
134
-            }
135
-        }
136
-        $this->template_args['row']                              = $this->ticket_rows;
137
-        $this->template_args['ticket_row_html']                  = $all_ticket_rows_html;
138
-        $this->template_args['taxable_tickets']                  = $taxable_tickets;
139
-        $this->template_args['prices_displayed_including_taxes'] = $this->tax_config->prices_displayed_including_taxes;
140
-        $this->template_args['template_path']                    =
141
-            TICKET_SELECTOR_TEMPLATES_PATH . 'standard_ticket_selector.template.php';
142
-        remove_all_filters('FHEE__EE_Ticket_Selector__hide_ticket_selector');
143
-    }
133
+				$required_ticket_sold_out = $ticket_selector_row->getRequiredTicketSoldOut();
134
+			}
135
+		}
136
+		$this->template_args['row']                              = $this->ticket_rows;
137
+		$this->template_args['ticket_row_html']                  = $all_ticket_rows_html;
138
+		$this->template_args['taxable_tickets']                  = $taxable_tickets;
139
+		$this->template_args['prices_displayed_including_taxes'] = $this->tax_config->prices_displayed_including_taxes;
140
+		$this->template_args['template_path']                    =
141
+			TICKET_SELECTOR_TEMPLATES_PATH . 'standard_ticket_selector.template.php';
142
+		remove_all_filters('FHEE__EE_Ticket_Selector__hide_ticket_selector');
143
+	}
144 144
 }
Please login to merge, or discard this patch.
Spacing   +3 added lines, -3 removed lines patch added patch discarded remove patch
@@ -91,7 +91,7 @@  discard block
 block discarded – undo
91 91
             $this->ticket_selector_config->getShowDatetimeSelector()
92 92
             !== EE_Ticket_Selector_Config::DO_NOT_SHOW_DATETIME_SELECTOR
93 93
         ) {
94
-            $datetime_selector                        = new DatetimeSelector(
94
+            $datetime_selector = new DatetimeSelector(
95 95
                 $this->event,
96 96
                 $this->tickets,
97 97
                 $this->ticket_selector_config,
@@ -122,7 +122,7 @@  discard block
 block discarded – undo
122 122
                 );
123 123
                 $ticket_row_html = $ticket_selector_row->getHtml();
124 124
                 // check if something was actually returned
125
-                if (! empty($ticket_row_html)) {
125
+                if ( ! empty($ticket_row_html)) {
126 126
                     // add any output to the cumulative HTML
127 127
                     $all_ticket_rows_html .= $ticket_row_html;
128 128
                 } else {
@@ -138,7 +138,7 @@  discard block
 block discarded – undo
138 138
         $this->template_args['taxable_tickets']                  = $taxable_tickets;
139 139
         $this->template_args['prices_displayed_including_taxes'] = $this->tax_config->prices_displayed_including_taxes;
140 140
         $this->template_args['template_path']                    =
141
-            TICKET_SELECTOR_TEMPLATES_PATH . 'standard_ticket_selector.template.php';
141
+            TICKET_SELECTOR_TEMPLATES_PATH.'standard_ticket_selector.template.php';
142 142
         remove_all_filters('FHEE__EE_Ticket_Selector__hide_ticket_selector');
143 143
     }
144 144
 }
Please login to merge, or discard this patch.
modules/ticket_selector/TicketSelectorSimple.php 1 patch
Indentation   +51 added lines, -51 removed lines patch added patch discarded remove patch
@@ -20,59 +20,59 @@
 block discarded – undo
20 20
 class TicketSelectorSimple extends TicketSelector
21 21
 {
22 22
 
23
-    /**
24
-     * @var EE_Ticket $ticket
25
-     */
26
-    protected $ticket;
23
+	/**
24
+	 * @var EE_Ticket $ticket
25
+	 */
26
+	protected $ticket;
27 27
 
28 28
 
29
-    /**
30
-     * TicketSelectorSimple constructor.
31
-     *
32
-     * @param EE_Event  $event
33
-     * @param EE_Ticket $ticket
34
-     * @param int       $max_attendees
35
-     * @param array     $template_args
36
-     * @throws EE_Error
37
-     */
38
-    public function __construct(EE_Event $event, EE_Ticket $ticket, $max_attendees, array $template_args)
39
-    {
40
-        $this->ticket = $ticket;
41
-        parent::__construct(
42
-            $event,
43
-            [$this->ticket],
44
-            $max_attendees,
45
-            $template_args
46
-        );
47
-    }
29
+	/**
30
+	 * TicketSelectorSimple constructor.
31
+	 *
32
+	 * @param EE_Event  $event
33
+	 * @param EE_Ticket $ticket
34
+	 * @param int       $max_attendees
35
+	 * @param array     $template_args
36
+	 * @throws EE_Error
37
+	 */
38
+	public function __construct(EE_Event $event, EE_Ticket $ticket, $max_attendees, array $template_args)
39
+	{
40
+		$this->ticket = $ticket;
41
+		parent::__construct(
42
+			$event,
43
+			[$this->ticket],
44
+			$max_attendees,
45
+			$template_args
46
+		);
47
+	}
48 48
 
49 49
 
50
-    /**
51
-     * sets any and all template args that are required for this Ticket Selector
52
-     *
53
-     * @return void
54
-     * @throws UnexpectedEntityException
55
-     * @throws EE_Error
56
-     */
57
-    protected function addTemplateArgs()
58
-    {
59
-        $this->ticket_rows = 1;
60
-        unset($this->template_args['tickets']);
61
-        $this->template_args['ticket'] = $this->ticket;
62
-        $ticket_selector_row           = new TicketSelectorRowSimple(
63
-            $this->ticket,
64
-            $this->max_attendees,
65
-            $this->template_args['date_format'],
66
-            $this->template_args['event_status']
67
-        );
68
-        $this->template_args['TKT_ID'] = $this->ticket->ID();
69
-        $ticket_selector_row->setupTicketStatusDisplay();
70
-        $this->template_args['ticket_status_display'] = $ticket_selector_row->getTicketStatusDisplay();
71
-        if (empty($this->template_args['ticket_status_display'])) {
72
-            add_filter('FHEE__EE_Ticket_Selector__display_ticket_selector_submit', '__return_true');
73
-        }
74
-        $this->template_args['ticket_description'] = $ticket_selector_row->getTicketDescription();
75
-        $this->template_args['template_path']      =
76
-            TICKET_SELECTOR_TEMPLATES_PATH . 'simple_ticket_selector.template.php';
77
-    }
50
+	/**
51
+	 * sets any and all template args that are required for this Ticket Selector
52
+	 *
53
+	 * @return void
54
+	 * @throws UnexpectedEntityException
55
+	 * @throws EE_Error
56
+	 */
57
+	protected function addTemplateArgs()
58
+	{
59
+		$this->ticket_rows = 1;
60
+		unset($this->template_args['tickets']);
61
+		$this->template_args['ticket'] = $this->ticket;
62
+		$ticket_selector_row           = new TicketSelectorRowSimple(
63
+			$this->ticket,
64
+			$this->max_attendees,
65
+			$this->template_args['date_format'],
66
+			$this->template_args['event_status']
67
+		);
68
+		$this->template_args['TKT_ID'] = $this->ticket->ID();
69
+		$ticket_selector_row->setupTicketStatusDisplay();
70
+		$this->template_args['ticket_status_display'] = $ticket_selector_row->getTicketStatusDisplay();
71
+		if (empty($this->template_args['ticket_status_display'])) {
72
+			add_filter('FHEE__EE_Ticket_Selector__display_ticket_selector_submit', '__return_true');
73
+		}
74
+		$this->template_args['ticket_description'] = $ticket_selector_row->getTicketDescription();
75
+		$this->template_args['template_path']      =
76
+			TICKET_SELECTOR_TEMPLATES_PATH . 'simple_ticket_selector.template.php';
77
+	}
78 78
 }
Please login to merge, or discard this patch.
core/services/shortcodes/LegacyShortcodesManager.php 2 patches
Indentation   +426 added lines, -426 removed lines patch added patch discarded remove patch
@@ -24,430 +24,430 @@
 block discarded – undo
24 24
  */
25 25
 class LegacyShortcodesManager
26 26
 {
27
-    /**
28
-     * @type CurrentPage
29
-     */
30
-    protected $current_page;
31
-
32
-    /**
33
-     * @var EE_Registry $registry
34
-     */
35
-    private $registry;
36
-
37
-
38
-    /**
39
-     * LegacyShortcodesManager constructor.
40
-     *
41
-     * @param EE_Registry $registry
42
-     * @param CurrentPage $current_page
43
-     */
44
-    public function __construct(EE_Registry $registry, CurrentPage $current_page)
45
-    {
46
-        $this->registry = $registry;
47
-        $this->current_page = $current_page;
48
-    }
49
-
50
-
51
-    /**
52
-     * @return EE_Registry
53
-     */
54
-    public function registry()
55
-    {
56
-        return $this->registry;
57
-    }
58
-
59
-
60
-    /**
61
-     * registerShortcodes
62
-     *
63
-     * @return void
64
-     */
65
-    public function registerShortcodes()
66
-    {
67
-        $this->registry->shortcodes = $this->getShortcodes();
68
-    }
69
-
70
-
71
-    /**
72
-     * getShortcodes
73
-     *
74
-     * @return array
75
-     */
76
-    public function getShortcodes()
77
-    {
78
-        // previously this method would glob the shortcodes directory
79
-        // then filter that list of shortcodes to register,
80
-        // but now we are going to just supply an empty array.
81
-        // this allows any shortcodes that have not yet been converted to the new system
82
-        // to still get loaded and processed, albeit using the same legacy logic as before
83
-        $shortcodes_to_register = apply_filters(
84
-            'FHEE__EE_Config__register_shortcodes__shortcodes_to_register',
85
-            array()
86
-        );
87
-        if (! empty($shortcodes_to_register)) {
88
-            // cycle thru shortcode folders
89
-            foreach ($shortcodes_to_register as $shortcode_path) {
90
-                // add to list of installed shortcode modules
91
-                $this->registerShortcode($shortcode_path);
92
-            }
93
-        }
94
-        // filter list of installed modules
95
-        return apply_filters(
96
-            'FHEE__EE_Config___register_shortcodes__installed_shortcodes',
97
-            ! empty($this->registry->shortcodes)
98
-                ? $this->registry->shortcodes
99
-                : array()
100
-        );
101
-    }
102
-
103
-
104
-    /**
105
-     * register_shortcode - makes core aware of this shortcode
106
-     *
107
-     * @param    string $shortcode_path - full path up to and including shortcode folder
108
-     * @return    bool
109
-     */
110
-    public function registerShortcode($shortcode_path = null)
111
-    {
112
-        do_action('AHEE__EE_Config__register_shortcode__begin', $shortcode_path);
113
-        $shortcode_ext = '.shortcode.php';
114
-        // make all separators match
115
-        $shortcode_path = str_replace(array('\\', '/'), '/', $shortcode_path);
116
-        // does the file path INCLUDE the actual file name as part of the path ?
117
-        if (strpos($shortcode_path, $shortcode_ext) !== false) {
118
-            // grab shortcode file name from directory name and break apart at dots
119
-            $shortcode_file = explode('.', basename($shortcode_path));
120
-            // take first segment from file name pieces and remove class prefix if it exists
121
-            $shortcode = strpos($shortcode_file[0], 'EES_') === 0
122
-                ? substr($shortcode_file[0], 4)
123
-                : $shortcode_file[0];
124
-            // sanitize shortcode directory name
125
-            $shortcode = sanitize_key($shortcode);
126
-            // now we need to rebuild the shortcode path
127
-            $shortcode_path = explode('/', $shortcode_path);
128
-            // remove last segment
129
-            array_pop($shortcode_path);
130
-            // glue it back together
131
-            $shortcode_path = implode('/', $shortcode_path) . '/';
132
-        } else {
133
-            // we need to generate the filename based off of the folder name
134
-            // grab and sanitize shortcode directory name
135
-            $shortcode = sanitize_key(basename($shortcode_path));
136
-            $shortcode_path = rtrim($shortcode_path, '/') . '/';
137
-        }
138
-        // create classname from shortcode directory or file name
139
-        $shortcode = str_replace(' ', '_', ucwords(str_replace('_', ' ', $shortcode)));
140
-        // add class prefix
141
-        $shortcode_class = 'EES_' . $shortcode;
142
-        // does the shortcode exist ?
143
-        if (! is_readable($shortcode_path . '/' . $shortcode_class . $shortcode_ext)) {
144
-            $msg = sprintf(
145
-                esc_html__(
146
-                    'The requested %1$s shortcode file could not be found or is not readable due to file permissions. It should be in %2$s',
147
-                    'event_espresso'
148
-                ),
149
-                $shortcode_class,
150
-                $shortcode_path . '/' . $shortcode_class . $shortcode_ext
151
-            );
152
-            EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
153
-            return false;
154
-        }
155
-        // load the shortcode class file
156
-        require_once($shortcode_path . $shortcode_class . $shortcode_ext);
157
-        // verify that class exists
158
-        if (! class_exists($shortcode_class)) {
159
-            $msg = sprintf(
160
-                esc_html__('The requested %s shortcode class does not exist.', 'event_espresso'),
161
-                $shortcode_class
162
-            );
163
-            EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
164
-            return false;
165
-        }
166
-        $shortcode = strtoupper($shortcode);
167
-        // add to array of registered shortcodes
168
-        $this->registry->shortcodes->{$shortcode} = $shortcode_path . $shortcode_class . $shortcode_ext;
169
-        return true;
170
-    }
171
-
172
-
173
-    /**
174
-     *    _initialize_shortcodes
175
-     *    allow shortcodes to set hooks for the rest of the system
176
-     *
177
-     * @return void
178
-     */
179
-    public function addShortcodes()
180
-    {
181
-        // cycle thru shortcode folders
182
-        foreach ($this->registry->shortcodes as $shortcode => $shortcode_path) {
183
-            // add class prefix
184
-            $shortcode_class = 'EES_' . $shortcode;
185
-            // fire the shortcode class's set_hooks methods in case it needs to hook into other parts of the system
186
-            // which set hooks ?
187
-            if (is_admin()) {
188
-                // fire immediately
189
-                call_user_func(array($shortcode_class, 'set_hooks_admin'));
190
-            } else {
191
-                // delay until other systems are online
192
-                add_action(
193
-                    'AHEE__EE_System__set_hooks_for_shortcodes_modules_and_addons',
194
-                    array($shortcode_class, 'set_hooks')
195
-                );
196
-                // convert classname to UPPERCASE and create WP shortcode.
197
-                $shortcode_tag = strtoupper($shortcode);
198
-                // but first check if the shortcode has already
199
-                // been added before assigning 'fallback_shortcode_processor'
200
-                if (! shortcode_exists($shortcode_tag)) {
201
-                    // NOTE: this shortcode declaration will get overridden if the shortcode
202
-                    // is successfully detected in the post content in initializeShortcode()
203
-                    add_shortcode($shortcode_tag, array($shortcode_class, 'fallback_shortcode_processor'));
204
-                }
205
-            }
206
-        }
207
-    }
208
-
209
-
210
-    /**
211
-     * callback for the WP "get_header" hook point
212
-     * checks posts for EE shortcodes, and initializes them,
213
-     * then toggles filter switch that loads core default assets
214
-     *
215
-     * @param WP_Query $wp_query
216
-     * @return void
217
-     * @throws ReflectionException
218
-     */
219
-    public function initializeShortcodes(WP_Query $wp_query)
220
-    {
221
-        if (empty($this->registry->shortcodes) || ! $wp_query->is_main_query() || is_admin()) {
222
-            return;
223
-        }
224
-        global $wp;
225
-        /** @var EE_Front_controller $Front_Controller */
226
-        $Front_Controller = LoaderFactory::getLoader()->getShared('EE_Front_Controller');
227
-        do_action('AHEE__EE_Front_Controller__initialize_shortcodes__begin', $wp, $Front_Controller);
228
-        $this->current_page->parseQueryVars();
229
-        // grab post_name from request
230
-        $current_post = apply_filters(
231
-            'FHEE__EE_Front_Controller__initialize_shortcodes__current_post_name',
232
-            $this->current_page->postName()
233
-        );
234
-        $show_on_front = get_option('show_on_front');
235
-        // if it's not set, then check if frontpage is blog
236
-        if (empty($current_post)) {
237
-            // yup.. this is the posts page, prepare to load all shortcode modules
238
-            $current_post = 'posts';
239
-            // unless..
240
-            if ($show_on_front === 'page') {
241
-                // some other page is set as the homepage
242
-                $page_on_front = get_option('page_on_front');
243
-                if ($page_on_front) {
244
-                    // k now we need to find the post_name for this page
245
-                    global $wpdb;
246
-                    $page_on_front = $wpdb->get_var(
247
-                        $wpdb->prepare(
248
-                            "SELECT post_name from {$wpdb->posts} WHERE post_type='page' AND post_status NOT IN ('auto-draft', 'inherit', 'trash') AND ID=%d",
249
-                            $page_on_front
250
-                        )
251
-                    );
252
-                    // set the current post slug to what it actually is
253
-                    $current_post = $page_on_front ?: $current_post;
254
-                }
255
-            }
256
-        }
257
-        // in case $current_post is hierarchical like: /parent-page/current-page
258
-        $current_post = basename($current_post);
259
-        if (
260
-            // is current page/post the "blog" page ?
261
-            $current_post === EE_Config::get_page_for_posts()
262
-            // or are we on a category page?
263
-            || (
264
-                is_array(term_exists($current_post, 'category'))
265
-                || array_key_exists('category_name', $wp->query_vars)
266
-            )
267
-        ) {
268
-            // initialize all legacy shortcodes
269
-            $load_assets = $this->parseContentForShortcodes('', true);
270
-        } else {
271
-            global $post;
272
-            if ($post instanceof WP_Post) {
273
-                $post_content = $post->post_content;
274
-            } else {
275
-                global $wpdb;
276
-                $post_content = $wpdb->get_var(
277
-                    $wpdb->prepare(
278
-                        "SELECT post_content from {$wpdb->posts} WHERE post_status NOT IN ('auto-draft', 'inherit', 'trash') AND post_name=%s",
279
-                        $current_post
280
-                    )
281
-                );
282
-            }
283
-            $load_assets = $this->parseContentForShortcodes($post_content);
284
-        }
285
-        if ($load_assets) {
286
-            $this->current_page->setEspressoPage(true);
287
-            add_filter('FHEE_load_css', '__return_true');
288
-            add_filter('FHEE_load_js', '__return_true');
289
-        }
290
-        do_action('AHEE__EE_Front_Controller__initialize_shortcodes__end', $Front_Controller);
291
-    }
292
-
293
-
294
-    /**
295
-     * checks supplied content against list of legacy shortcodes,
296
-     * then initializes any found shortcodes, and returns true.
297
-     * returns false if no shortcodes found.
298
-     *
299
-     * @param string $content
300
-     * @param bool   $load_all if true, then ALL active legacy shortcodes will be initialized
301
-     * @return bool
302
-     * @throws ReflectionException
303
-     */
304
-    public function parseContentForShortcodes($content = '', $load_all = false)
305
-    {
306
-        $has_shortcode = false;
307
-        foreach ($this->registry->shortcodes as $shortcode_class => $shortcode) {
308
-            if ($load_all || has_shortcode($content, $shortcode_class)) {
309
-                // load up the shortcode
310
-                $this->initializeShortcode($shortcode_class);
311
-                $has_shortcode = true;
312
-            }
313
-        }
314
-        // one last test for an [espresso_*] shortcode
315
-        if (! $has_shortcode) {
316
-            $has_shortcode = strpos($content, '[espresso_') !== false;
317
-        }
318
-        return $has_shortcode;
319
-    }
320
-
321
-
322
-    /**
323
-     * given a shortcode name, will instantiate the shortcode and call it's run() method
324
-     *
325
-     * @param string $shortcode_class
326
-     * @param WP     $wp
327
-     * @throws ReflectionException
328
-     */
329
-    public function initializeShortcode($shortcode_class = '', WP $wp = null)
330
-    {
331
-        // don't do anything if shortcode is already initialized
332
-        if (
333
-            empty($this->registry->shortcodes->{$shortcode_class})
334
-            || ! is_string($this->registry->shortcodes->{$shortcode_class})
335
-        ) {
336
-            return;
337
-        }
338
-        // let's pause to reflect on this...
339
-        $sc_reflector = new ReflectionClass(LegacyShortcodesManager::addShortcodeClassPrefix($shortcode_class));
340
-        // ensure that class is actually a shortcode
341
-        if (
342
-            defined('WP_DEBUG')
343
-            && WP_DEBUG === true
344
-            && ! $sc_reflector->isSubclassOf('EES_Shortcode')
345
-        ) {
346
-            EE_Error::add_error(
347
-                sprintf(
348
-                    esc_html__(
349
-                        'The requested %s shortcode is not of the class "EES_Shortcode". Please check your files.',
350
-                        'event_espresso'
351
-                    ),
352
-                    $shortcode_class
353
-                ),
354
-                __FILE__,
355
-                __FUNCTION__,
356
-                __LINE__
357
-            );
358
-            add_filter('FHEE_run_EE_the_content', '__return_true');
359
-            return;
360
-        }
361
-        global $wp;
362
-        // and pass the request object to the run method
363
-        $this->registry->shortcodes->{$shortcode_class} = $sc_reflector->newInstance();
364
-        // fire the shortcode class's run method, so that it can activate resources
365
-        $this->registry->shortcodes->{$shortcode_class}->run($wp);
366
-    }
367
-
368
-
369
-    /**
370
-     * get classname, remove EES_prefix, and convert to UPPERCASE
371
-     *
372
-     * @param string $class_name
373
-     * @return string
374
-     */
375
-    public static function generateShortcodeTagFromClassName($class_name)
376
-    {
377
-        return strtoupper(str_replace('EES_', '', $class_name));
378
-    }
379
-
380
-
381
-    /**
382
-     * add EES_prefix and Capitalize words
383
-     *
384
-     * @param string $tag
385
-     * @return string
386
-     */
387
-    public static function generateShortcodeClassNameFromTag($tag)
388
-    {
389
-        // order of operation runs from inside to out
390
-        // 5) maybe add prefix
391
-        return LegacyShortcodesManager::addShortcodeClassPrefix(
392
-            // 4) find spaces, replace with underscores
393
-            str_replace(
394
-                ' ',
395
-                '_',
396
-                // 3) capitalize first letter of each word
397
-                ucwords(
398
-                    // 2) also change to lowercase so ucwords() will work
399
-                    strtolower(
400
-                        // 1) find underscores, replace with spaces so ucwords() will work
401
-                        str_replace(
402
-                            '_',
403
-                            ' ',
404
-                            $tag
405
-                        )
406
-                    )
407
-                )
408
-            )
409
-        );
410
-    }
411
-
412
-
413
-    /**
414
-     * maybe add EES_prefix
415
-     *
416
-     * @param string $class_name
417
-     * @return string
418
-     */
419
-    public static function addShortcodeClassPrefix($class_name)
420
-    {
421
-        return strpos($class_name, 'EES_') === 0 ? $class_name : 'EES_' . $class_name;
422
-    }
423
-
424
-
425
-    /**
426
-     * @return array
427
-     */
428
-    public function getEspressoShortcodeTags()
429
-    {
430
-        static $shortcode_tags = array();
431
-        if (empty($shortcode_tags)) {
432
-            $shortcode_tags = array_keys((array) $this->registry->shortcodes);
433
-        }
434
-        return $shortcode_tags;
435
-    }
436
-
437
-
438
-    /**
439
-     * @param string $content
440
-     * @return string
441
-     * @throws ReflectionException
442
-     */
443
-    public function doShortcode($content)
444
-    {
445
-        foreach ($this->getEspressoShortcodeTags() as $shortcode_tag) {
446
-            if (strpos($content, $shortcode_tag) !== false) {
447
-                $shortcode_class = LegacyShortcodesManager::generateShortcodeClassNameFromTag($shortcode_tag);
448
-                $this->initializeShortcode($shortcode_class);
449
-            }
450
-        }
451
-        return do_shortcode($content);
452
-    }
27
+	/**
28
+	 * @type CurrentPage
29
+	 */
30
+	protected $current_page;
31
+
32
+	/**
33
+	 * @var EE_Registry $registry
34
+	 */
35
+	private $registry;
36
+
37
+
38
+	/**
39
+	 * LegacyShortcodesManager constructor.
40
+	 *
41
+	 * @param EE_Registry $registry
42
+	 * @param CurrentPage $current_page
43
+	 */
44
+	public function __construct(EE_Registry $registry, CurrentPage $current_page)
45
+	{
46
+		$this->registry = $registry;
47
+		$this->current_page = $current_page;
48
+	}
49
+
50
+
51
+	/**
52
+	 * @return EE_Registry
53
+	 */
54
+	public function registry()
55
+	{
56
+		return $this->registry;
57
+	}
58
+
59
+
60
+	/**
61
+	 * registerShortcodes
62
+	 *
63
+	 * @return void
64
+	 */
65
+	public function registerShortcodes()
66
+	{
67
+		$this->registry->shortcodes = $this->getShortcodes();
68
+	}
69
+
70
+
71
+	/**
72
+	 * getShortcodes
73
+	 *
74
+	 * @return array
75
+	 */
76
+	public function getShortcodes()
77
+	{
78
+		// previously this method would glob the shortcodes directory
79
+		// then filter that list of shortcodes to register,
80
+		// but now we are going to just supply an empty array.
81
+		// this allows any shortcodes that have not yet been converted to the new system
82
+		// to still get loaded and processed, albeit using the same legacy logic as before
83
+		$shortcodes_to_register = apply_filters(
84
+			'FHEE__EE_Config__register_shortcodes__shortcodes_to_register',
85
+			array()
86
+		);
87
+		if (! empty($shortcodes_to_register)) {
88
+			// cycle thru shortcode folders
89
+			foreach ($shortcodes_to_register as $shortcode_path) {
90
+				// add to list of installed shortcode modules
91
+				$this->registerShortcode($shortcode_path);
92
+			}
93
+		}
94
+		// filter list of installed modules
95
+		return apply_filters(
96
+			'FHEE__EE_Config___register_shortcodes__installed_shortcodes',
97
+			! empty($this->registry->shortcodes)
98
+				? $this->registry->shortcodes
99
+				: array()
100
+		);
101
+	}
102
+
103
+
104
+	/**
105
+	 * register_shortcode - makes core aware of this shortcode
106
+	 *
107
+	 * @param    string $shortcode_path - full path up to and including shortcode folder
108
+	 * @return    bool
109
+	 */
110
+	public function registerShortcode($shortcode_path = null)
111
+	{
112
+		do_action('AHEE__EE_Config__register_shortcode__begin', $shortcode_path);
113
+		$shortcode_ext = '.shortcode.php';
114
+		// make all separators match
115
+		$shortcode_path = str_replace(array('\\', '/'), '/', $shortcode_path);
116
+		// does the file path INCLUDE the actual file name as part of the path ?
117
+		if (strpos($shortcode_path, $shortcode_ext) !== false) {
118
+			// grab shortcode file name from directory name and break apart at dots
119
+			$shortcode_file = explode('.', basename($shortcode_path));
120
+			// take first segment from file name pieces and remove class prefix if it exists
121
+			$shortcode = strpos($shortcode_file[0], 'EES_') === 0
122
+				? substr($shortcode_file[0], 4)
123
+				: $shortcode_file[0];
124
+			// sanitize shortcode directory name
125
+			$shortcode = sanitize_key($shortcode);
126
+			// now we need to rebuild the shortcode path
127
+			$shortcode_path = explode('/', $shortcode_path);
128
+			// remove last segment
129
+			array_pop($shortcode_path);
130
+			// glue it back together
131
+			$shortcode_path = implode('/', $shortcode_path) . '/';
132
+		} else {
133
+			// we need to generate the filename based off of the folder name
134
+			// grab and sanitize shortcode directory name
135
+			$shortcode = sanitize_key(basename($shortcode_path));
136
+			$shortcode_path = rtrim($shortcode_path, '/') . '/';
137
+		}
138
+		// create classname from shortcode directory or file name
139
+		$shortcode = str_replace(' ', '_', ucwords(str_replace('_', ' ', $shortcode)));
140
+		// add class prefix
141
+		$shortcode_class = 'EES_' . $shortcode;
142
+		// does the shortcode exist ?
143
+		if (! is_readable($shortcode_path . '/' . $shortcode_class . $shortcode_ext)) {
144
+			$msg = sprintf(
145
+				esc_html__(
146
+					'The requested %1$s shortcode file could not be found or is not readable due to file permissions. It should be in %2$s',
147
+					'event_espresso'
148
+				),
149
+				$shortcode_class,
150
+				$shortcode_path . '/' . $shortcode_class . $shortcode_ext
151
+			);
152
+			EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
153
+			return false;
154
+		}
155
+		// load the shortcode class file
156
+		require_once($shortcode_path . $shortcode_class . $shortcode_ext);
157
+		// verify that class exists
158
+		if (! class_exists($shortcode_class)) {
159
+			$msg = sprintf(
160
+				esc_html__('The requested %s shortcode class does not exist.', 'event_espresso'),
161
+				$shortcode_class
162
+			);
163
+			EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
164
+			return false;
165
+		}
166
+		$shortcode = strtoupper($shortcode);
167
+		// add to array of registered shortcodes
168
+		$this->registry->shortcodes->{$shortcode} = $shortcode_path . $shortcode_class . $shortcode_ext;
169
+		return true;
170
+	}
171
+
172
+
173
+	/**
174
+	 *    _initialize_shortcodes
175
+	 *    allow shortcodes to set hooks for the rest of the system
176
+	 *
177
+	 * @return void
178
+	 */
179
+	public function addShortcodes()
180
+	{
181
+		// cycle thru shortcode folders
182
+		foreach ($this->registry->shortcodes as $shortcode => $shortcode_path) {
183
+			// add class prefix
184
+			$shortcode_class = 'EES_' . $shortcode;
185
+			// fire the shortcode class's set_hooks methods in case it needs to hook into other parts of the system
186
+			// which set hooks ?
187
+			if (is_admin()) {
188
+				// fire immediately
189
+				call_user_func(array($shortcode_class, 'set_hooks_admin'));
190
+			} else {
191
+				// delay until other systems are online
192
+				add_action(
193
+					'AHEE__EE_System__set_hooks_for_shortcodes_modules_and_addons',
194
+					array($shortcode_class, 'set_hooks')
195
+				);
196
+				// convert classname to UPPERCASE and create WP shortcode.
197
+				$shortcode_tag = strtoupper($shortcode);
198
+				// but first check if the shortcode has already
199
+				// been added before assigning 'fallback_shortcode_processor'
200
+				if (! shortcode_exists($shortcode_tag)) {
201
+					// NOTE: this shortcode declaration will get overridden if the shortcode
202
+					// is successfully detected in the post content in initializeShortcode()
203
+					add_shortcode($shortcode_tag, array($shortcode_class, 'fallback_shortcode_processor'));
204
+				}
205
+			}
206
+		}
207
+	}
208
+
209
+
210
+	/**
211
+	 * callback for the WP "get_header" hook point
212
+	 * checks posts for EE shortcodes, and initializes them,
213
+	 * then toggles filter switch that loads core default assets
214
+	 *
215
+	 * @param WP_Query $wp_query
216
+	 * @return void
217
+	 * @throws ReflectionException
218
+	 */
219
+	public function initializeShortcodes(WP_Query $wp_query)
220
+	{
221
+		if (empty($this->registry->shortcodes) || ! $wp_query->is_main_query() || is_admin()) {
222
+			return;
223
+		}
224
+		global $wp;
225
+		/** @var EE_Front_controller $Front_Controller */
226
+		$Front_Controller = LoaderFactory::getLoader()->getShared('EE_Front_Controller');
227
+		do_action('AHEE__EE_Front_Controller__initialize_shortcodes__begin', $wp, $Front_Controller);
228
+		$this->current_page->parseQueryVars();
229
+		// grab post_name from request
230
+		$current_post = apply_filters(
231
+			'FHEE__EE_Front_Controller__initialize_shortcodes__current_post_name',
232
+			$this->current_page->postName()
233
+		);
234
+		$show_on_front = get_option('show_on_front');
235
+		// if it's not set, then check if frontpage is blog
236
+		if (empty($current_post)) {
237
+			// yup.. this is the posts page, prepare to load all shortcode modules
238
+			$current_post = 'posts';
239
+			// unless..
240
+			if ($show_on_front === 'page') {
241
+				// some other page is set as the homepage
242
+				$page_on_front = get_option('page_on_front');
243
+				if ($page_on_front) {
244
+					// k now we need to find the post_name for this page
245
+					global $wpdb;
246
+					$page_on_front = $wpdb->get_var(
247
+						$wpdb->prepare(
248
+							"SELECT post_name from {$wpdb->posts} WHERE post_type='page' AND post_status NOT IN ('auto-draft', 'inherit', 'trash') AND ID=%d",
249
+							$page_on_front
250
+						)
251
+					);
252
+					// set the current post slug to what it actually is
253
+					$current_post = $page_on_front ?: $current_post;
254
+				}
255
+			}
256
+		}
257
+		// in case $current_post is hierarchical like: /parent-page/current-page
258
+		$current_post = basename($current_post);
259
+		if (
260
+			// is current page/post the "blog" page ?
261
+			$current_post === EE_Config::get_page_for_posts()
262
+			// or are we on a category page?
263
+			|| (
264
+				is_array(term_exists($current_post, 'category'))
265
+				|| array_key_exists('category_name', $wp->query_vars)
266
+			)
267
+		) {
268
+			// initialize all legacy shortcodes
269
+			$load_assets = $this->parseContentForShortcodes('', true);
270
+		} else {
271
+			global $post;
272
+			if ($post instanceof WP_Post) {
273
+				$post_content = $post->post_content;
274
+			} else {
275
+				global $wpdb;
276
+				$post_content = $wpdb->get_var(
277
+					$wpdb->prepare(
278
+						"SELECT post_content from {$wpdb->posts} WHERE post_status NOT IN ('auto-draft', 'inherit', 'trash') AND post_name=%s",
279
+						$current_post
280
+					)
281
+				);
282
+			}
283
+			$load_assets = $this->parseContentForShortcodes($post_content);
284
+		}
285
+		if ($load_assets) {
286
+			$this->current_page->setEspressoPage(true);
287
+			add_filter('FHEE_load_css', '__return_true');
288
+			add_filter('FHEE_load_js', '__return_true');
289
+		}
290
+		do_action('AHEE__EE_Front_Controller__initialize_shortcodes__end', $Front_Controller);
291
+	}
292
+
293
+
294
+	/**
295
+	 * checks supplied content against list of legacy shortcodes,
296
+	 * then initializes any found shortcodes, and returns true.
297
+	 * returns false if no shortcodes found.
298
+	 *
299
+	 * @param string $content
300
+	 * @param bool   $load_all if true, then ALL active legacy shortcodes will be initialized
301
+	 * @return bool
302
+	 * @throws ReflectionException
303
+	 */
304
+	public function parseContentForShortcodes($content = '', $load_all = false)
305
+	{
306
+		$has_shortcode = false;
307
+		foreach ($this->registry->shortcodes as $shortcode_class => $shortcode) {
308
+			if ($load_all || has_shortcode($content, $shortcode_class)) {
309
+				// load up the shortcode
310
+				$this->initializeShortcode($shortcode_class);
311
+				$has_shortcode = true;
312
+			}
313
+		}
314
+		// one last test for an [espresso_*] shortcode
315
+		if (! $has_shortcode) {
316
+			$has_shortcode = strpos($content, '[espresso_') !== false;
317
+		}
318
+		return $has_shortcode;
319
+	}
320
+
321
+
322
+	/**
323
+	 * given a shortcode name, will instantiate the shortcode and call it's run() method
324
+	 *
325
+	 * @param string $shortcode_class
326
+	 * @param WP     $wp
327
+	 * @throws ReflectionException
328
+	 */
329
+	public function initializeShortcode($shortcode_class = '', WP $wp = null)
330
+	{
331
+		// don't do anything if shortcode is already initialized
332
+		if (
333
+			empty($this->registry->shortcodes->{$shortcode_class})
334
+			|| ! is_string($this->registry->shortcodes->{$shortcode_class})
335
+		) {
336
+			return;
337
+		}
338
+		// let's pause to reflect on this...
339
+		$sc_reflector = new ReflectionClass(LegacyShortcodesManager::addShortcodeClassPrefix($shortcode_class));
340
+		// ensure that class is actually a shortcode
341
+		if (
342
+			defined('WP_DEBUG')
343
+			&& WP_DEBUG === true
344
+			&& ! $sc_reflector->isSubclassOf('EES_Shortcode')
345
+		) {
346
+			EE_Error::add_error(
347
+				sprintf(
348
+					esc_html__(
349
+						'The requested %s shortcode is not of the class "EES_Shortcode". Please check your files.',
350
+						'event_espresso'
351
+					),
352
+					$shortcode_class
353
+				),
354
+				__FILE__,
355
+				__FUNCTION__,
356
+				__LINE__
357
+			);
358
+			add_filter('FHEE_run_EE_the_content', '__return_true');
359
+			return;
360
+		}
361
+		global $wp;
362
+		// and pass the request object to the run method
363
+		$this->registry->shortcodes->{$shortcode_class} = $sc_reflector->newInstance();
364
+		// fire the shortcode class's run method, so that it can activate resources
365
+		$this->registry->shortcodes->{$shortcode_class}->run($wp);
366
+	}
367
+
368
+
369
+	/**
370
+	 * get classname, remove EES_prefix, and convert to UPPERCASE
371
+	 *
372
+	 * @param string $class_name
373
+	 * @return string
374
+	 */
375
+	public static function generateShortcodeTagFromClassName($class_name)
376
+	{
377
+		return strtoupper(str_replace('EES_', '', $class_name));
378
+	}
379
+
380
+
381
+	/**
382
+	 * add EES_prefix and Capitalize words
383
+	 *
384
+	 * @param string $tag
385
+	 * @return string
386
+	 */
387
+	public static function generateShortcodeClassNameFromTag($tag)
388
+	{
389
+		// order of operation runs from inside to out
390
+		// 5) maybe add prefix
391
+		return LegacyShortcodesManager::addShortcodeClassPrefix(
392
+			// 4) find spaces, replace with underscores
393
+			str_replace(
394
+				' ',
395
+				'_',
396
+				// 3) capitalize first letter of each word
397
+				ucwords(
398
+					// 2) also change to lowercase so ucwords() will work
399
+					strtolower(
400
+						// 1) find underscores, replace with spaces so ucwords() will work
401
+						str_replace(
402
+							'_',
403
+							' ',
404
+							$tag
405
+						)
406
+					)
407
+				)
408
+			)
409
+		);
410
+	}
411
+
412
+
413
+	/**
414
+	 * maybe add EES_prefix
415
+	 *
416
+	 * @param string $class_name
417
+	 * @return string
418
+	 */
419
+	public static function addShortcodeClassPrefix($class_name)
420
+	{
421
+		return strpos($class_name, 'EES_') === 0 ? $class_name : 'EES_' . $class_name;
422
+	}
423
+
424
+
425
+	/**
426
+	 * @return array
427
+	 */
428
+	public function getEspressoShortcodeTags()
429
+	{
430
+		static $shortcode_tags = array();
431
+		if (empty($shortcode_tags)) {
432
+			$shortcode_tags = array_keys((array) $this->registry->shortcodes);
433
+		}
434
+		return $shortcode_tags;
435
+	}
436
+
437
+
438
+	/**
439
+	 * @param string $content
440
+	 * @return string
441
+	 * @throws ReflectionException
442
+	 */
443
+	public function doShortcode($content)
444
+	{
445
+		foreach ($this->getEspressoShortcodeTags() as $shortcode_tag) {
446
+			if (strpos($content, $shortcode_tag) !== false) {
447
+				$shortcode_class = LegacyShortcodesManager::generateShortcodeClassNameFromTag($shortcode_tag);
448
+				$this->initializeShortcode($shortcode_class);
449
+			}
450
+		}
451
+		return do_shortcode($content);
452
+	}
453 453
 }
Please login to merge, or discard this patch.
Spacing   +15 added lines, -15 removed lines patch added patch discarded remove patch
@@ -84,7 +84,7 @@  discard block
 block discarded – undo
84 84
             'FHEE__EE_Config__register_shortcodes__shortcodes_to_register',
85 85
             array()
86 86
         );
87
-        if (! empty($shortcodes_to_register)) {
87
+        if ( ! empty($shortcodes_to_register)) {
88 88
             // cycle thru shortcode folders
89 89
             foreach ($shortcodes_to_register as $shortcode_path) {
90 90
                 // add to list of installed shortcode modules
@@ -128,44 +128,44 @@  discard block
 block discarded – undo
128 128
             // remove last segment
129 129
             array_pop($shortcode_path);
130 130
             // glue it back together
131
-            $shortcode_path = implode('/', $shortcode_path) . '/';
131
+            $shortcode_path = implode('/', $shortcode_path).'/';
132 132
         } else {
133 133
             // we need to generate the filename based off of the folder name
134 134
             // grab and sanitize shortcode directory name
135 135
             $shortcode = sanitize_key(basename($shortcode_path));
136
-            $shortcode_path = rtrim($shortcode_path, '/') . '/';
136
+            $shortcode_path = rtrim($shortcode_path, '/').'/';
137 137
         }
138 138
         // create classname from shortcode directory or file name
139 139
         $shortcode = str_replace(' ', '_', ucwords(str_replace('_', ' ', $shortcode)));
140 140
         // add class prefix
141
-        $shortcode_class = 'EES_' . $shortcode;
141
+        $shortcode_class = 'EES_'.$shortcode;
142 142
         // does the shortcode exist ?
143
-        if (! is_readable($shortcode_path . '/' . $shortcode_class . $shortcode_ext)) {
143
+        if ( ! is_readable($shortcode_path.'/'.$shortcode_class.$shortcode_ext)) {
144 144
             $msg = sprintf(
145 145
                 esc_html__(
146 146
                     'The requested %1$s shortcode file could not be found or is not readable due to file permissions. It should be in %2$s',
147 147
                     'event_espresso'
148 148
                 ),
149 149
                 $shortcode_class,
150
-                $shortcode_path . '/' . $shortcode_class . $shortcode_ext
150
+                $shortcode_path.'/'.$shortcode_class.$shortcode_ext
151 151
             );
152
-            EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
152
+            EE_Error::add_error($msg.'||'.$msg, __FILE__, __FUNCTION__, __LINE__);
153 153
             return false;
154 154
         }
155 155
         // load the shortcode class file
156
-        require_once($shortcode_path . $shortcode_class . $shortcode_ext);
156
+        require_once($shortcode_path.$shortcode_class.$shortcode_ext);
157 157
         // verify that class exists
158
-        if (! class_exists($shortcode_class)) {
158
+        if ( ! class_exists($shortcode_class)) {
159 159
             $msg = sprintf(
160 160
                 esc_html__('The requested %s shortcode class does not exist.', 'event_espresso'),
161 161
                 $shortcode_class
162 162
             );
163
-            EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
163
+            EE_Error::add_error($msg.'||'.$msg, __FILE__, __FUNCTION__, __LINE__);
164 164
             return false;
165 165
         }
166 166
         $shortcode = strtoupper($shortcode);
167 167
         // add to array of registered shortcodes
168
-        $this->registry->shortcodes->{$shortcode} = $shortcode_path . $shortcode_class . $shortcode_ext;
168
+        $this->registry->shortcodes->{$shortcode} = $shortcode_path.$shortcode_class.$shortcode_ext;
169 169
         return true;
170 170
     }
171 171
 
@@ -181,7 +181,7 @@  discard block
 block discarded – undo
181 181
         // cycle thru shortcode folders
182 182
         foreach ($this->registry->shortcodes as $shortcode => $shortcode_path) {
183 183
             // add class prefix
184
-            $shortcode_class = 'EES_' . $shortcode;
184
+            $shortcode_class = 'EES_'.$shortcode;
185 185
             // fire the shortcode class's set_hooks methods in case it needs to hook into other parts of the system
186 186
             // which set hooks ?
187 187
             if (is_admin()) {
@@ -197,7 +197,7 @@  discard block
 block discarded – undo
197 197
                 $shortcode_tag = strtoupper($shortcode);
198 198
                 // but first check if the shortcode has already
199 199
                 // been added before assigning 'fallback_shortcode_processor'
200
-                if (! shortcode_exists($shortcode_tag)) {
200
+                if ( ! shortcode_exists($shortcode_tag)) {
201 201
                     // NOTE: this shortcode declaration will get overridden if the shortcode
202 202
                     // is successfully detected in the post content in initializeShortcode()
203 203
                     add_shortcode($shortcode_tag, array($shortcode_class, 'fallback_shortcode_processor'));
@@ -312,7 +312,7 @@  discard block
 block discarded – undo
312 312
             }
313 313
         }
314 314
         // one last test for an [espresso_*] shortcode
315
-        if (! $has_shortcode) {
315
+        if ( ! $has_shortcode) {
316 316
             $has_shortcode = strpos($content, '[espresso_') !== false;
317 317
         }
318 318
         return $has_shortcode;
@@ -418,7 +418,7 @@  discard block
 block discarded – undo
418 418
      */
419 419
     public static function addShortcodeClassPrefix($class_name)
420 420
     {
421
-        return strpos($class_name, 'EES_') === 0 ? $class_name : 'EES_' . $class_name;
421
+        return strpos($class_name, 'EES_') === 0 ? $class_name : 'EES_'.$class_name;
422 422
     }
423 423
 
424 424
 
Please login to merge, or discard this patch.
core/services/request/CurrentPage.php 2 patches
Indentation   +317 added lines, -317 removed lines patch added patch discarded remove patch
@@ -23,321 +23,321 @@
 block discarded – undo
23 23
  */
24 24
 class CurrentPage
25 25
 {
26
-    /**
27
-     * @var EE_CPT_Strategy
28
-     */
29
-    private $cpt_strategy;
30
-
31
-    /**
32
-     * @var bool
33
-     */
34
-    private $initialized;
35
-
36
-    /**
37
-     * @var bool
38
-     */
39
-    private $is_espresso_page;
40
-
41
-    /**
42
-     * @var int
43
-     */
44
-    private $post_id = 0;
45
-
46
-    /**
47
-     * @var string
48
-     */
49
-    private $post_name = '';
50
-
51
-    /**
52
-     * @var array
53
-     */
54
-    private $post_type = [];
55
-
56
-    /**
57
-     * @var RequestInterface $request
58
-     */
59
-    private $request;
60
-
61
-
62
-    /**
63
-     * CurrentPage constructor.
64
-     *
65
-     * @param EE_CPT_Strategy  $cpt_strategy
66
-     * @param RequestInterface $request
67
-     */
68
-    public function __construct(EE_CPT_Strategy $cpt_strategy, RequestInterface $request)
69
-    {
70
-        $this->cpt_strategy = $cpt_strategy;
71
-        $this->request      = $request;
72
-        $this->initialized  = is_admin();
73
-        // analyse the incoming WP request
74
-        add_action('parse_request', [$this, 'parseQueryVars'], 2, 1);
75
-    }
76
-
77
-
78
-    /**
79
-     * @param WP $WP
80
-     * @return void
81
-     */
82
-    public function parseQueryVars(WP $WP = null)
83
-    {
84
-        if ($this->initialized) {
85
-            return;
86
-        }
87
-        // if somebody forgot to provide us with WP, that's ok because its global
88
-        if (! $WP instanceof WP) {
89
-            global $WP;
90
-        }
91
-        $this->post_id   = $this->getPostId($WP);
92
-        $this->post_name = $this->getPostName($WP);
93
-        $this->post_type = $this->getPostType($WP);
94
-        // true or false ? is this page being used by EE ?
95
-        $this->setEspressoPage();
96
-        remove_action('parse_request', [$this, 'parseRequest'], 2);
97
-        $this->initialized = true;
98
-    }
99
-
100
-
101
-    /**
102
-     * Just a helper method for getting the url for the displayed page.
103
-     *
104
-     * @param WP|null $WP
105
-     * @return string
106
-     */
107
-    public function getPermalink(WP $WP = null)
108
-    {
109
-        $post_id = $this->post_id ?: $this->getPostId($WP);
110
-        if ($post_id) {
111
-            return get_permalink($post_id);
112
-        }
113
-        if (! $WP instanceof WP) {
114
-            global $WP;
115
-        }
116
-        if ($WP instanceof WP && $WP->request) {
117
-            return site_url($WP->request);
118
-        }
119
-        return esc_url_raw(site_url($_SERVER['REQUEST_URI']));
120
-    }
121
-
122
-
123
-    /**
124
-     * @return array
125
-     */
126
-    public function espressoPostType()
127
-    {
128
-        return array_filter(
129
-            $this->post_type,
130
-            function ($post_type) {
131
-                return strpos($post_type, 'espresso_') === 0;
132
-            }
133
-        );
134
-    }
135
-
136
-
137
-    /**
138
-     * pokes and prods the WP object query_vars in an attempt to shake out a page/post ID
139
-     *
140
-     * @param WP $WP
141
-     * @return int
142
-     */
143
-    private function getPostId(WP $WP = null)
144
-    {
145
-        $post_id = null;
146
-        if ($WP instanceof WP) {
147
-            // look for the post ID in the aptly named 'p' query var
148
-            if (isset($WP->query_vars['p'])) {
149
-                $post_id = $WP->query_vars['p'];
150
-            }
151
-            // not a post? what about a page?
152
-            if (! $post_id && isset($WP->query_vars['page_id'])) {
153
-                $post_id = $WP->query_vars['page_id'];
154
-            }
155
-            // ok... maybe pretty permalinks are off and the ID is set in the raw request...
156
-            // but hasn't been processed yet ie: this method is being called too early :\
157
-            if (! $post_id && $WP->request !== null && is_numeric(basename($WP->request))) {
158
-                $post_id = basename($WP->request);
159
-            }
160
-        }
161
-        // none of the above? ok what about an explicit "post_id" URL parameter?
162
-        if (! $post_id && $this->request->requestParamIsSet('post_id')) {
163
-            $post_id = $this->request->getRequestParam('post_id');
164
-        }
165
-        return $post_id;
166
-    }
167
-
168
-
169
-    /**
170
-     * similar to getPostId() above but attempts to obtain the "name" for the current page/post
171
-     *
172
-     * @param WP $WP
173
-     * @return string
174
-     */
175
-    private function getPostName(WP $WP = null)
176
-    {
177
-        global $wpdb;
178
-        $post_name = null;
179
-        if ($WP instanceof WP) {
180
-            // if this is a post, then is the post name set?
181
-            if (isset($WP->query_vars['name']) && ! empty($WP->query_vars['name'])) {
182
-                $post_name = $WP->query_vars['name'];
183
-            }
184
-            // what about the page name?
185
-            if (! $post_name && isset($WP->query_vars['pagename']) && ! empty($WP->query_vars['pagename'])) {
186
-                $post_name = $WP->query_vars['pagename'];
187
-            }
188
-            // this stinks but let's run a query to try and get the post name from the URL
189
-            // (assuming pretty permalinks are on)
190
-            if (! $post_name && ! empty($WP->request)) {
191
-                $possible_post_name = basename($WP->request);
192
-                if (! is_numeric($possible_post_name)) {
193
-                    $SQL                = "SELECT ID from {$wpdb->posts}";
194
-                    $SQL                .= " WHERE post_status NOT IN ('auto-draft', 'inherit', 'trash')";
195
-                    $SQL                .= ' AND post_name=%s';
196
-                    $possible_post_name = $wpdb->get_var($wpdb->prepare($SQL, $possible_post_name));
197
-                    if ($possible_post_name) {
198
-                        $post_name = $possible_post_name;
199
-                    }
200
-                }
201
-            }
202
-        }
203
-        // ug... ok... nothing yet... but do we have a post ID?
204
-        // if so then... sigh... run a query to get the post name :\
205
-        if (! $post_name && $this->post_id) {
206
-            $SQL                = "SELECT post_name from {$wpdb->posts}";
207
-            $SQL                .= " WHERE post_status NOT IN ('auto-draft', 'inherit', 'trash')";
208
-            $SQL                .= ' AND ID=%d';
209
-            $possible_post_name = $wpdb->get_var($wpdb->prepare($SQL, $this->post_id));
210
-            if ($possible_post_name) {
211
-                $post_name = $possible_post_name;
212
-            }
213
-        }
214
-        // still nothing? ok what about an explicit 'post_name' URL parameter?
215
-        if (! $post_name && $this->request->requestParamIsSet('post_name')) {
216
-            $post_name = $this->request->getRequestParam('post_name');
217
-        }
218
-        return $post_name;
219
-    }
220
-
221
-
222
-    /**
223
-     * also similar to getPostId() and getPostName() above but not as insane
224
-     *
225
-     * @param WP $WP
226
-     * @return array
227
-     */
228
-    private function getPostType(WP $WP = null)
229
-    {
230
-        $post_types = [];
231
-        if ($WP instanceof WP) {
232
-            $post_types = isset($WP->query_vars['post_type'])
233
-                ? (array) $WP->query_vars['post_type']
234
-                : [];
235
-        }
236
-        if (empty($post_types) && $this->request->requestParamIsSet('post_type')) {
237
-            $post_types = $this->request->getRequestParam('post_type', [], 'string', true);
238
-        }
239
-        return (array) $post_types;
240
-    }
241
-
242
-
243
-    /**
244
-     * if TRUE, then the current page is somehow utilizing EE logic
245
-     *
246
-     * @return bool
247
-     */
248
-    public function isEspressoPage()
249
-    {
250
-        if ($this->is_espresso_page === null) {
251
-            $this->setEspressoPage();
252
-        }
253
-        return $this->is_espresso_page;
254
-    }
255
-
256
-
257
-    /**
258
-     * @return int
259
-     */
260
-    public function postId()
261
-    {
262
-        return $this->post_id;
263
-    }
264
-
265
-
266
-    /**
267
-     * @return string
268
-     */
269
-    public function postName()
270
-    {
271
-        return $this->post_name;
272
-    }
273
-
274
-
275
-    /**
276
-     * @return array
277
-     */
278
-    public function postType()
279
-    {
280
-        return $this->post_type;
281
-    }
282
-
283
-
284
-    /**
285
-     * for manually indicating the current page will utilize EE logic
286
-     *
287
-     * @param null|bool $value
288
-     * @return void
289
-     */
290
-    public function setEspressoPage($value = null)
291
-    {
292
-        $this->is_espresso_page = $value !== null
293
-            ? filter_var($value, FILTER_VALIDATE_BOOLEAN)
294
-            : $this->testForEspressoPage();
295
-    }
296
-
297
-
298
-    /**
299
-     * attempts to determine if the current page/post is an EE related page/post
300
-     * because it utilizes one of our CPT taxonomies, endpoints, or post types
301
-     *
302
-     * @return bool
303
-     */
304
-    private function testForEspressoPage()
305
-    {
306
-        // in case it has already been set
307
-        if ($this->is_espresso_page) {
308
-            return true;
309
-        }
310
-        global $WP;
311
-        $espresso_CPT_taxonomies = $this->cpt_strategy->get_CPT_taxonomies();
312
-        if (is_array($espresso_CPT_taxonomies)) {
313
-            foreach ($espresso_CPT_taxonomies as $espresso_CPT_taxonomy => $details) {
314
-                if (isset($WP->query_vars, $WP->query_vars[ $espresso_CPT_taxonomy ])) {
315
-                    return true;
316
-                }
317
-            }
318
-        }
319
-        // load espresso CPT endpoints
320
-        $espresso_CPT_endpoints  = $this->cpt_strategy->get_CPT_endpoints();
321
-        $post_type_CPT_endpoints = array_flip($espresso_CPT_endpoints);
322
-        foreach ($this->post_type as $post_type) {
323
-            // was a post name passed ?
324
-            if (isset($post_type_CPT_endpoints[ $post_type ])) {
325
-                // kk we know this is an espresso page, but is it a specific post ?
326
-                if (! $this->post_name) {
327
-                    $espresso_post_type = $this->request->getRequestParam('post_type');
328
-                    // there's no specific post name set, so maybe it's one of our endpoints like www.domain.com/events
329
-                    // this essentially sets the post_name to "events" (or whatever EE CPT)
330
-                    $post_name = isset($post_type_CPT_endpoints[ $espresso_post_type ])
331
-                        ? $post_type_CPT_endpoints[ $espresso_post_type ]
332
-                        : '';
333
-                    // if the post type matches one of ours then set the post name to the endpoint
334
-                    if ($post_name) {
335
-                        $this->post_name = $post_name;
336
-                    }
337
-                }
338
-                return true;
339
-            }
340
-        }
341
-        return false;
342
-    }
26
+	/**
27
+	 * @var EE_CPT_Strategy
28
+	 */
29
+	private $cpt_strategy;
30
+
31
+	/**
32
+	 * @var bool
33
+	 */
34
+	private $initialized;
35
+
36
+	/**
37
+	 * @var bool
38
+	 */
39
+	private $is_espresso_page;
40
+
41
+	/**
42
+	 * @var int
43
+	 */
44
+	private $post_id = 0;
45
+
46
+	/**
47
+	 * @var string
48
+	 */
49
+	private $post_name = '';
50
+
51
+	/**
52
+	 * @var array
53
+	 */
54
+	private $post_type = [];
55
+
56
+	/**
57
+	 * @var RequestInterface $request
58
+	 */
59
+	private $request;
60
+
61
+
62
+	/**
63
+	 * CurrentPage constructor.
64
+	 *
65
+	 * @param EE_CPT_Strategy  $cpt_strategy
66
+	 * @param RequestInterface $request
67
+	 */
68
+	public function __construct(EE_CPT_Strategy $cpt_strategy, RequestInterface $request)
69
+	{
70
+		$this->cpt_strategy = $cpt_strategy;
71
+		$this->request      = $request;
72
+		$this->initialized  = is_admin();
73
+		// analyse the incoming WP request
74
+		add_action('parse_request', [$this, 'parseQueryVars'], 2, 1);
75
+	}
76
+
77
+
78
+	/**
79
+	 * @param WP $WP
80
+	 * @return void
81
+	 */
82
+	public function parseQueryVars(WP $WP = null)
83
+	{
84
+		if ($this->initialized) {
85
+			return;
86
+		}
87
+		// if somebody forgot to provide us with WP, that's ok because its global
88
+		if (! $WP instanceof WP) {
89
+			global $WP;
90
+		}
91
+		$this->post_id   = $this->getPostId($WP);
92
+		$this->post_name = $this->getPostName($WP);
93
+		$this->post_type = $this->getPostType($WP);
94
+		// true or false ? is this page being used by EE ?
95
+		$this->setEspressoPage();
96
+		remove_action('parse_request', [$this, 'parseRequest'], 2);
97
+		$this->initialized = true;
98
+	}
99
+
100
+
101
+	/**
102
+	 * Just a helper method for getting the url for the displayed page.
103
+	 *
104
+	 * @param WP|null $WP
105
+	 * @return string
106
+	 */
107
+	public function getPermalink(WP $WP = null)
108
+	{
109
+		$post_id = $this->post_id ?: $this->getPostId($WP);
110
+		if ($post_id) {
111
+			return get_permalink($post_id);
112
+		}
113
+		if (! $WP instanceof WP) {
114
+			global $WP;
115
+		}
116
+		if ($WP instanceof WP && $WP->request) {
117
+			return site_url($WP->request);
118
+		}
119
+		return esc_url_raw(site_url($_SERVER['REQUEST_URI']));
120
+	}
121
+
122
+
123
+	/**
124
+	 * @return array
125
+	 */
126
+	public function espressoPostType()
127
+	{
128
+		return array_filter(
129
+			$this->post_type,
130
+			function ($post_type) {
131
+				return strpos($post_type, 'espresso_') === 0;
132
+			}
133
+		);
134
+	}
135
+
136
+
137
+	/**
138
+	 * pokes and prods the WP object query_vars in an attempt to shake out a page/post ID
139
+	 *
140
+	 * @param WP $WP
141
+	 * @return int
142
+	 */
143
+	private function getPostId(WP $WP = null)
144
+	{
145
+		$post_id = null;
146
+		if ($WP instanceof WP) {
147
+			// look for the post ID in the aptly named 'p' query var
148
+			if (isset($WP->query_vars['p'])) {
149
+				$post_id = $WP->query_vars['p'];
150
+			}
151
+			// not a post? what about a page?
152
+			if (! $post_id && isset($WP->query_vars['page_id'])) {
153
+				$post_id = $WP->query_vars['page_id'];
154
+			}
155
+			// ok... maybe pretty permalinks are off and the ID is set in the raw request...
156
+			// but hasn't been processed yet ie: this method is being called too early :\
157
+			if (! $post_id && $WP->request !== null && is_numeric(basename($WP->request))) {
158
+				$post_id = basename($WP->request);
159
+			}
160
+		}
161
+		// none of the above? ok what about an explicit "post_id" URL parameter?
162
+		if (! $post_id && $this->request->requestParamIsSet('post_id')) {
163
+			$post_id = $this->request->getRequestParam('post_id');
164
+		}
165
+		return $post_id;
166
+	}
167
+
168
+
169
+	/**
170
+	 * similar to getPostId() above but attempts to obtain the "name" for the current page/post
171
+	 *
172
+	 * @param WP $WP
173
+	 * @return string
174
+	 */
175
+	private function getPostName(WP $WP = null)
176
+	{
177
+		global $wpdb;
178
+		$post_name = null;
179
+		if ($WP instanceof WP) {
180
+			// if this is a post, then is the post name set?
181
+			if (isset($WP->query_vars['name']) && ! empty($WP->query_vars['name'])) {
182
+				$post_name = $WP->query_vars['name'];
183
+			}
184
+			// what about the page name?
185
+			if (! $post_name && isset($WP->query_vars['pagename']) && ! empty($WP->query_vars['pagename'])) {
186
+				$post_name = $WP->query_vars['pagename'];
187
+			}
188
+			// this stinks but let's run a query to try and get the post name from the URL
189
+			// (assuming pretty permalinks are on)
190
+			if (! $post_name && ! empty($WP->request)) {
191
+				$possible_post_name = basename($WP->request);
192
+				if (! is_numeric($possible_post_name)) {
193
+					$SQL                = "SELECT ID from {$wpdb->posts}";
194
+					$SQL                .= " WHERE post_status NOT IN ('auto-draft', 'inherit', 'trash')";
195
+					$SQL                .= ' AND post_name=%s';
196
+					$possible_post_name = $wpdb->get_var($wpdb->prepare($SQL, $possible_post_name));
197
+					if ($possible_post_name) {
198
+						$post_name = $possible_post_name;
199
+					}
200
+				}
201
+			}
202
+		}
203
+		// ug... ok... nothing yet... but do we have a post ID?
204
+		// if so then... sigh... run a query to get the post name :\
205
+		if (! $post_name && $this->post_id) {
206
+			$SQL                = "SELECT post_name from {$wpdb->posts}";
207
+			$SQL                .= " WHERE post_status NOT IN ('auto-draft', 'inherit', 'trash')";
208
+			$SQL                .= ' AND ID=%d';
209
+			$possible_post_name = $wpdb->get_var($wpdb->prepare($SQL, $this->post_id));
210
+			if ($possible_post_name) {
211
+				$post_name = $possible_post_name;
212
+			}
213
+		}
214
+		// still nothing? ok what about an explicit 'post_name' URL parameter?
215
+		if (! $post_name && $this->request->requestParamIsSet('post_name')) {
216
+			$post_name = $this->request->getRequestParam('post_name');
217
+		}
218
+		return $post_name;
219
+	}
220
+
221
+
222
+	/**
223
+	 * also similar to getPostId() and getPostName() above but not as insane
224
+	 *
225
+	 * @param WP $WP
226
+	 * @return array
227
+	 */
228
+	private function getPostType(WP $WP = null)
229
+	{
230
+		$post_types = [];
231
+		if ($WP instanceof WP) {
232
+			$post_types = isset($WP->query_vars['post_type'])
233
+				? (array) $WP->query_vars['post_type']
234
+				: [];
235
+		}
236
+		if (empty($post_types) && $this->request->requestParamIsSet('post_type')) {
237
+			$post_types = $this->request->getRequestParam('post_type', [], 'string', true);
238
+		}
239
+		return (array) $post_types;
240
+	}
241
+
242
+
243
+	/**
244
+	 * if TRUE, then the current page is somehow utilizing EE logic
245
+	 *
246
+	 * @return bool
247
+	 */
248
+	public function isEspressoPage()
249
+	{
250
+		if ($this->is_espresso_page === null) {
251
+			$this->setEspressoPage();
252
+		}
253
+		return $this->is_espresso_page;
254
+	}
255
+
256
+
257
+	/**
258
+	 * @return int
259
+	 */
260
+	public function postId()
261
+	{
262
+		return $this->post_id;
263
+	}
264
+
265
+
266
+	/**
267
+	 * @return string
268
+	 */
269
+	public function postName()
270
+	{
271
+		return $this->post_name;
272
+	}
273
+
274
+
275
+	/**
276
+	 * @return array
277
+	 */
278
+	public function postType()
279
+	{
280
+		return $this->post_type;
281
+	}
282
+
283
+
284
+	/**
285
+	 * for manually indicating the current page will utilize EE logic
286
+	 *
287
+	 * @param null|bool $value
288
+	 * @return void
289
+	 */
290
+	public function setEspressoPage($value = null)
291
+	{
292
+		$this->is_espresso_page = $value !== null
293
+			? filter_var($value, FILTER_VALIDATE_BOOLEAN)
294
+			: $this->testForEspressoPage();
295
+	}
296
+
297
+
298
+	/**
299
+	 * attempts to determine if the current page/post is an EE related page/post
300
+	 * because it utilizes one of our CPT taxonomies, endpoints, or post types
301
+	 *
302
+	 * @return bool
303
+	 */
304
+	private function testForEspressoPage()
305
+	{
306
+		// in case it has already been set
307
+		if ($this->is_espresso_page) {
308
+			return true;
309
+		}
310
+		global $WP;
311
+		$espresso_CPT_taxonomies = $this->cpt_strategy->get_CPT_taxonomies();
312
+		if (is_array($espresso_CPT_taxonomies)) {
313
+			foreach ($espresso_CPT_taxonomies as $espresso_CPT_taxonomy => $details) {
314
+				if (isset($WP->query_vars, $WP->query_vars[ $espresso_CPT_taxonomy ])) {
315
+					return true;
316
+				}
317
+			}
318
+		}
319
+		// load espresso CPT endpoints
320
+		$espresso_CPT_endpoints  = $this->cpt_strategy->get_CPT_endpoints();
321
+		$post_type_CPT_endpoints = array_flip($espresso_CPT_endpoints);
322
+		foreach ($this->post_type as $post_type) {
323
+			// was a post name passed ?
324
+			if (isset($post_type_CPT_endpoints[ $post_type ])) {
325
+				// kk we know this is an espresso page, but is it a specific post ?
326
+				if (! $this->post_name) {
327
+					$espresso_post_type = $this->request->getRequestParam('post_type');
328
+					// there's no specific post name set, so maybe it's one of our endpoints like www.domain.com/events
329
+					// this essentially sets the post_name to "events" (or whatever EE CPT)
330
+					$post_name = isset($post_type_CPT_endpoints[ $espresso_post_type ])
331
+						? $post_type_CPT_endpoints[ $espresso_post_type ]
332
+						: '';
333
+					// if the post type matches one of ours then set the post name to the endpoint
334
+					if ($post_name) {
335
+						$this->post_name = $post_name;
336
+					}
337
+				}
338
+				return true;
339
+			}
340
+		}
341
+		return false;
342
+	}
343 343
 }
Please login to merge, or discard this patch.
Spacing   +16 added lines, -16 removed lines patch added patch discarded remove patch
@@ -85,7 +85,7 @@  discard block
 block discarded – undo
85 85
             return;
86 86
         }
87 87
         // if somebody forgot to provide us with WP, that's ok because its global
88
-        if (! $WP instanceof WP) {
88
+        if ( ! $WP instanceof WP) {
89 89
             global $WP;
90 90
         }
91 91
         $this->post_id   = $this->getPostId($WP);
@@ -110,7 +110,7 @@  discard block
 block discarded – undo
110 110
         if ($post_id) {
111 111
             return get_permalink($post_id);
112 112
         }
113
-        if (! $WP instanceof WP) {
113
+        if ( ! $WP instanceof WP) {
114 114
             global $WP;
115 115
         }
116 116
         if ($WP instanceof WP && $WP->request) {
@@ -127,7 +127,7 @@  discard block
 block discarded – undo
127 127
     {
128 128
         return array_filter(
129 129
             $this->post_type,
130
-            function ($post_type) {
130
+            function($post_type) {
131 131
                 return strpos($post_type, 'espresso_') === 0;
132 132
             }
133 133
         );
@@ -149,17 +149,17 @@  discard block
 block discarded – undo
149 149
                 $post_id = $WP->query_vars['p'];
150 150
             }
151 151
             // not a post? what about a page?
152
-            if (! $post_id && isset($WP->query_vars['page_id'])) {
152
+            if ( ! $post_id && isset($WP->query_vars['page_id'])) {
153 153
                 $post_id = $WP->query_vars['page_id'];
154 154
             }
155 155
             // ok... maybe pretty permalinks are off and the ID is set in the raw request...
156 156
             // but hasn't been processed yet ie: this method is being called too early :\
157
-            if (! $post_id && $WP->request !== null && is_numeric(basename($WP->request))) {
157
+            if ( ! $post_id && $WP->request !== null && is_numeric(basename($WP->request))) {
158 158
                 $post_id = basename($WP->request);
159 159
             }
160 160
         }
161 161
         // none of the above? ok what about an explicit "post_id" URL parameter?
162
-        if (! $post_id && $this->request->requestParamIsSet('post_id')) {
162
+        if ( ! $post_id && $this->request->requestParamIsSet('post_id')) {
163 163
             $post_id = $this->request->getRequestParam('post_id');
164 164
         }
165 165
         return $post_id;
@@ -182,14 +182,14 @@  discard block
 block discarded – undo
182 182
                 $post_name = $WP->query_vars['name'];
183 183
             }
184 184
             // what about the page name?
185
-            if (! $post_name && isset($WP->query_vars['pagename']) && ! empty($WP->query_vars['pagename'])) {
185
+            if ( ! $post_name && isset($WP->query_vars['pagename']) && ! empty($WP->query_vars['pagename'])) {
186 186
                 $post_name = $WP->query_vars['pagename'];
187 187
             }
188 188
             // this stinks but let's run a query to try and get the post name from the URL
189 189
             // (assuming pretty permalinks are on)
190
-            if (! $post_name && ! empty($WP->request)) {
190
+            if ( ! $post_name && ! empty($WP->request)) {
191 191
                 $possible_post_name = basename($WP->request);
192
-                if (! is_numeric($possible_post_name)) {
192
+                if ( ! is_numeric($possible_post_name)) {
193 193
                     $SQL                = "SELECT ID from {$wpdb->posts}";
194 194
                     $SQL                .= " WHERE post_status NOT IN ('auto-draft', 'inherit', 'trash')";
195 195
                     $SQL                .= ' AND post_name=%s';
@@ -202,7 +202,7 @@  discard block
 block discarded – undo
202 202
         }
203 203
         // ug... ok... nothing yet... but do we have a post ID?
204 204
         // if so then... sigh... run a query to get the post name :\
205
-        if (! $post_name && $this->post_id) {
205
+        if ( ! $post_name && $this->post_id) {
206 206
             $SQL                = "SELECT post_name from {$wpdb->posts}";
207 207
             $SQL                .= " WHERE post_status NOT IN ('auto-draft', 'inherit', 'trash')";
208 208
             $SQL                .= ' AND ID=%d';
@@ -212,7 +212,7 @@  discard block
 block discarded – undo
212 212
             }
213 213
         }
214 214
         // still nothing? ok what about an explicit 'post_name' URL parameter?
215
-        if (! $post_name && $this->request->requestParamIsSet('post_name')) {
215
+        if ( ! $post_name && $this->request->requestParamIsSet('post_name')) {
216 216
             $post_name = $this->request->getRequestParam('post_name');
217 217
         }
218 218
         return $post_name;
@@ -311,7 +311,7 @@  discard block
 block discarded – undo
311 311
         $espresso_CPT_taxonomies = $this->cpt_strategy->get_CPT_taxonomies();
312 312
         if (is_array($espresso_CPT_taxonomies)) {
313 313
             foreach ($espresso_CPT_taxonomies as $espresso_CPT_taxonomy => $details) {
314
-                if (isset($WP->query_vars, $WP->query_vars[ $espresso_CPT_taxonomy ])) {
314
+                if (isset($WP->query_vars, $WP->query_vars[$espresso_CPT_taxonomy])) {
315 315
                     return true;
316 316
                 }
317 317
             }
@@ -321,14 +321,14 @@  discard block
 block discarded – undo
321 321
         $post_type_CPT_endpoints = array_flip($espresso_CPT_endpoints);
322 322
         foreach ($this->post_type as $post_type) {
323 323
             // was a post name passed ?
324
-            if (isset($post_type_CPT_endpoints[ $post_type ])) {
324
+            if (isset($post_type_CPT_endpoints[$post_type])) {
325 325
                 // kk we know this is an espresso page, but is it a specific post ?
326
-                if (! $this->post_name) {
326
+                if ( ! $this->post_name) {
327 327
                     $espresso_post_type = $this->request->getRequestParam('post_type');
328 328
                     // there's no specific post name set, so maybe it's one of our endpoints like www.domain.com/events
329 329
                     // this essentially sets the post_name to "events" (or whatever EE CPT)
330
-                    $post_name = isset($post_type_CPT_endpoints[ $espresso_post_type ])
331
-                        ? $post_type_CPT_endpoints[ $espresso_post_type ]
330
+                    $post_name = isset($post_type_CPT_endpoints[$espresso_post_type])
331
+                        ? $post_type_CPT_endpoints[$espresso_post_type]
332 332
                         : '';
333 333
                     // if the post type matches one of ours then set the post name to the endpoint
334 334
                     if ($post_name) {
Please login to merge, or discard this patch.
core/EE_Front_Controller.core.php 1 patch
Indentation   +482 added lines, -482 removed lines patch added patch discarded remove patch
@@ -17,486 +17,486 @@
 block discarded – undo
17 17
 final class EE_Front_Controller
18 18
 {
19 19
 
20
-    /**
21
-     * @var string
22
-     */
23
-    private $_template_path;
24
-
25
-    /**
26
-     * @var string
27
-     */
28
-    private $_template;
29
-
30
-    /**
31
-     * @type EE_Registry
32
-     */
33
-    protected $Registry;
34
-
35
-    /**
36
-     * @type EE_Request_Handler
37
-     */
38
-    protected $Request_Handler;
39
-
40
-    /**
41
-     * @type EE_Module_Request_Router
42
-     */
43
-    protected $Module_Request_Router;
44
-
45
-    /**
46
-     * @type CurrentPage
47
-     */
48
-    protected $current_page;
49
-
50
-
51
-    /**
52
-     *    class constructor
53
-     *    should fire after shortcode, module, addon, or other plugin's default priority init phases have run
54
-     *
55
-     * @access    public
56
-     * @param EE_Registry              $Registry
57
-     * @param CurrentPage              $EspressoPage
58
-     * @param EE_Module_Request_Router $Module_Request_Router
59
-     */
60
-    public function __construct(
61
-        EE_Registry $Registry,
62
-        CurrentPage $EspressoPage,
63
-        EE_Module_Request_Router $Module_Request_Router
64
-    ) {
65
-        $this->Registry              = $Registry;
66
-        $this->current_page          = $EspressoPage;
67
-        $this->Module_Request_Router = $Module_Request_Router;
68
-        // load other resources and begin to actually run shortcodes and modules
69
-        // analyse the incoming WP request
70
-        add_action('parse_request', array($this, 'get_request'), 1, 1);
71
-        // process request with module factory
72
-        add_action('pre_get_posts', array($this, 'pre_get_posts'), 10, 1);
73
-        // before headers sent
74
-        add_action('wp', array($this, 'wp'), 5);
75
-        // primarily used to process any content shortcodes
76
-        add_action('template_redirect', array($this, 'templateRedirect'), 999);
77
-        // header
78
-        add_action('wp_head', array($this, 'header_meta_tag'), 5);
79
-        add_action('wp_print_scripts', array($this, 'wp_print_scripts'), 10);
80
-        add_filter('template_include', array($this, 'template_include'), 1);
81
-        // display errors
82
-        add_action('loop_start', array($this, 'display_errors'), 2);
83
-        // the content
84
-        // add_filter( 'the_content', array( $this, 'the_content' ), 5, 1 );
85
-        // exclude our private cpt comments
86
-        add_filter('comments_clauses', array($this, 'filter_wp_comments'), 10, 1);
87
-        // make sure any ajax requests will respect the url schema when requests are made against admin-ajax.php (http:// or https://)
88
-        add_filter('admin_url', array($this, 'maybe_force_admin_ajax_ssl'), 200, 1);
89
-        // action hook EE
90
-        do_action('AHEE__EE_Front_Controller__construct__done', $this);
91
-    }
92
-
93
-
94
-    /**
95
-     * @return EE_Request_Handler
96
-     * @deprecated 4.10.14.p
97
-     */
98
-    public function Request_Handler()
99
-    {
100
-        if (! $this->Request_Handler instanceof EE_Request_Handler) {
101
-            $this->Request_Handler = LoaderFactory::getLoader()->getShared('EE_Request_Handler');
102
-        }
103
-        return $this->Request_Handler;
104
-    }
105
-
106
-
107
-    /**
108
-     * @return EE_Module_Request_Router
109
-     */
110
-    public function Module_Request_Router()
111
-    {
112
-        return $this->Module_Request_Router;
113
-    }
114
-
115
-
116
-    /**
117
-     * @return LegacyShortcodesManager
118
-     * @deprecated 4.10.14.p
119
-     */
120
-    public function getLegacyShortcodesManager()
121
-    {
122
-        return EE_Config::getLegacyShortcodesManager();
123
-    }
124
-
125
-
126
-
127
-
128
-
129
-    /***********************************************        INIT ACTION HOOK         ***********************************************/
130
-    /**
131
-     * filter_wp_comments
132
-     * This simply makes sure that any "private" EE CPTs do not have their comments show up in any wp comment
133
-     * widgets/queries done on frontend
134
-     *
135
-     * @param  array $clauses array of comment clauses setup by WP_Comment_Query
136
-     * @return array array of comment clauses with modifications.
137
-     * @throws InvalidArgumentException
138
-     * @throws InvalidDataTypeException
139
-     * @throws InvalidInterfaceException
140
-     */
141
-    public function filter_wp_comments($clauses)
142
-    {
143
-        global $wpdb;
144
-        if (strpos($clauses['join'], $wpdb->posts) !== false) {
145
-            /** @var EventEspresso\core\domain\entities\custom_post_types\CustomPostTypeDefinitions $custom_post_types */
146
-            $custom_post_types = LoaderFactory::getLoader()->getShared(
147
-                'EventEspresso\core\domain\entities\custom_post_types\CustomPostTypeDefinitions'
148
-            );
149
-            $cpts = $custom_post_types->getPrivateCustomPostTypes();
150
-            foreach ($cpts as $cpt => $details) {
151
-                $clauses['where'] .= $wpdb->prepare(" AND $wpdb->posts.post_type != %s", $cpt);
152
-            }
153
-        }
154
-        return $clauses;
155
-    }
156
-
157
-
158
-    /**
159
-     * this just makes sure that if the site is using ssl that we force that for any admin ajax calls from frontend
160
-     *
161
-     * @param  string $url incoming url
162
-     * @return string         final assembled url
163
-     */
164
-    public function maybe_force_admin_ajax_ssl($url)
165
-    {
166
-        if (is_ssl() && preg_match('/admin-ajax.php/', $url)) {
167
-            $url = str_replace('http://', 'https://', $url);
168
-        }
169
-        return $url;
170
-    }
171
-
172
-
173
-
174
-
175
-
176
-
177
-    /***********************************************        WP_LOADED ACTION HOOK         ***********************************************/
178
-
179
-
180
-    /**
181
-     *    wp_loaded - should fire after shortcode, module, addon, or other plugin's have been registered and their
182
-     *    default priority init phases have run
183
-     *
184
-     * @access    public
185
-     * @return    void
186
-     */
187
-    public function wp_loaded()
188
-    {
189
-    }
190
-
191
-
192
-
193
-
194
-
195
-    /***********************************************        PARSE_REQUEST HOOK         ***********************************************/
196
-    /**
197
-     *    _get_request
198
-     *
199
-     * @access public
200
-     * @param WP $WP
201
-     * @return void
202
-     */
203
-    public function get_request(WP $WP)
204
-    {
205
-        do_action('AHEE__EE_Front_Controller__get_request__start');
206
-        $this->current_page->parseQueryVars($WP);
207
-        do_action('AHEE__EE_Front_Controller__get_request__complete');
208
-        remove_action('parse_request', [$this, 'get_request'], 1);
209
-    }
210
-
211
-
212
-    /**
213
-     *    pre_get_posts - basically a module factory for instantiating modules and selecting the final view template
214
-     *
215
-     * @access    public
216
-     * @param WP_Query $WP_Query
217
-     * @return    void
218
-     * @throws EE_Error
219
-     * @throws ReflectionException
220
-     */
221
-    public function pre_get_posts($WP_Query)
222
-    {
223
-        // only load Module_Request_Router if this is the main query
224
-        if (
225
-            $this->Module_Request_Router instanceof EE_Module_Request_Router
226
-            && $WP_Query->is_main_query()
227
-        ) {
228
-            // cycle thru module routes
229
-            while ($route = $this->Module_Request_Router->get_route($WP_Query)) {
230
-                // determine module and method for route
231
-                $module = $this->Module_Request_Router->resolve_route($route[0], $route[1]);
232
-                if ($module instanceof EED_Module) {
233
-                    // get registered view for route
234
-                    $this->_template_path = $this->Module_Request_Router->get_view($route);
235
-                    // grab module name
236
-                    $module_name = $module->module_name();
237
-                    // map the module to the module objects
238
-                    $this->Registry->modules->{$module_name} = $module;
239
-                }
240
-            }
241
-        }
242
-    }
243
-
244
-
245
-
246
-
247
-
248
-    /***********************************************        WP HOOK         ***********************************************/
249
-
250
-
251
-    /**
252
-     *    wp - basically last chance to do stuff before headers sent
253
-     *
254
-     * @access    public
255
-     * @return    void
256
-     */
257
-    public function wp()
258
-    {
259
-    }
260
-
261
-
262
-
263
-    /***********************     GET_HEADER && WP_HEAD HOOK     ***********************/
264
-
265
-
266
-    /**
267
-     * callback for the "template_redirect" hook point
268
-     * checks sidebars for EE widgets
269
-     * loads resources and assets accordingly
270
-     *
271
-     * @return void
272
-     */
273
-    public function templateRedirect()
274
-    {
275
-        global $wp_query;
276
-        if (empty($wp_query->posts)) {
277
-            return;
278
-        }
279
-        // if we already know this is an espresso page, then load assets
280
-        $load_assets = $this->current_page->isEspressoPage();
281
-        // if we are already loading assets then just move along, otherwise check for widgets
282
-        $load_assets = $load_assets || $this->espresso_widgets_in_active_sidebars();
283
-        if ($load_assets) {
284
-            add_action('wp_enqueue_scripts', array($this, 'enqueueStyle'), 10);
285
-            add_action('wp_print_footer_scripts', array($this, 'enqueueScripts'), 10);
286
-        }
287
-    }
288
-
289
-
290
-    /**
291
-     * builds list of active widgets then scans active sidebars looking for them
292
-     * returns true is an EE widget is found in an active sidebar
293
-     * Please Note: this does NOT mean that the sidebar or widget
294
-     * is actually in use in a given template, as that is unfortunately not known
295
-     * until a sidebar and it's widgets are actually loaded
296
-     *
297
-     * @return boolean
298
-     */
299
-    private function espresso_widgets_in_active_sidebars()
300
-    {
301
-        $espresso_widgets = array();
302
-        foreach ($this->Registry->widgets as $widget_class => $widget) {
303
-            $id_base = EspressoWidget::getIdBase($widget_class);
304
-            if (is_active_widget(false, false, $id_base)) {
305
-                $espresso_widgets[] = $id_base;
306
-            }
307
-        }
308
-        $all_sidebar_widgets = wp_get_sidebars_widgets();
309
-        foreach ($all_sidebar_widgets as $sidebar_widgets) {
310
-            if (is_array($sidebar_widgets) && ! empty($sidebar_widgets)) {
311
-                foreach ($sidebar_widgets as $sidebar_widget) {
312
-                    foreach ($espresso_widgets as $espresso_widget) {
313
-                        if (strpos($sidebar_widget, $espresso_widget) !== false) {
314
-                            return true;
315
-                        }
316
-                    }
317
-                }
318
-            }
319
-        }
320
-        return false;
321
-    }
322
-
323
-
324
-    /**
325
-     *    header_meta_tag
326
-     *
327
-     * @access    public
328
-     * @return    void
329
-     */
330
-    public function header_meta_tag()
331
-    {
332
-        print(
333
-        apply_filters(
334
-            'FHEE__EE_Front_Controller__header_meta_tag',
335
-            '<meta name="generator" content="Event Espresso Version ' . EVENT_ESPRESSO_VERSION . "\" />\n"
336
-        )
337
-        );
338
-
339
-        // let's exclude all event type taxonomy term archive pages from search engine indexing
340
-        // @see https://events.codebasehq.com/projects/event-espresso/tickets/10249
341
-        // also exclude all critical pages from indexing
342
-        if (
343
-            (
344
-                is_tax('espresso_event_type')
345
-                && get_option('blog_public') !== '0'
346
-            )
347
-            || is_page(EE_Registry::instance()->CFG->core->get_critical_pages_array())
348
-        ) {
349
-            print(
350
-            apply_filters(
351
-                'FHEE__EE_Front_Controller__header_meta_tag__noindex_for_event_type',
352
-                '<meta name="robots" content="noindex,follow" />' . "\n"
353
-            )
354
-            );
355
-        }
356
-    }
357
-
358
-
359
-    /**
360
-     * wp_print_scripts
361
-     *
362
-     * @return void
363
-     * @throws EE_Error
364
-     */
365
-    public function wp_print_scripts()
366
-    {
367
-        global $post;
368
-        if (
369
-            isset($post->EE_Event)
370
-            && $post->EE_Event instanceof EE_Event
371
-            && get_post_type() === 'espresso_events'
372
-            && is_singular()
373
-        ) {
374
-            EEH_Schema::add_json_linked_data_for_event($post->EE_Event);
375
-        }
376
-    }
377
-
378
-
379
-    public function enqueueStyle()
380
-    {
381
-        wp_enqueue_style('espresso_default');
382
-        wp_enqueue_style('espresso_custom_css');
383
-    }
384
-
385
-
386
-
387
-    /***********************************************        WP_FOOTER         ***********************************************/
388
-
389
-
390
-    public function enqueueScripts()
391
-    {
392
-        wp_enqueue_script('espresso_core');
393
-    }
394
-
395
-
396
-    /**
397
-     * display_errors
398
-     *
399
-     * @access public
400
-     * @return void
401
-     * @throws DomainException
402
-     */
403
-    public function display_errors()
404
-    {
405
-        static $shown_already = false;
406
-        do_action('AHEE__EE_Front_Controller__display_errors__begin');
407
-        if (
408
-            ! $shown_already
409
-            && apply_filters('FHEE__EE_Front_Controller__display_errors', true)
410
-            && is_main_query()
411
-            && ! is_feed()
412
-            && in_the_loop()
413
-            && did_action('wp_head')
414
-            && $this->current_page->isEspressoPage()
415
-        ) {
416
-            echo EE_Error::get_notices();
417
-            $shown_already = true;
418
-            EEH_Template::display_template(EE_TEMPLATES . 'espresso-ajax-notices.template.php');
419
-        }
420
-        do_action('AHEE__EE_Front_Controller__display_errors__end');
421
-    }
422
-
423
-
424
-
425
-
426
-
427
-    /***********************************************        UTILITIES         ***********************************************/
428
-
429
-
430
-    /**
431
-     * @param string $template_include_path
432
-     * @return string
433
-     * @throws EE_Error
434
-     * @throws ReflectionException
435
-     */
436
-    public function template_include($template_include_path = null)
437
-    {
438
-        if ($this->current_page->isEspressoPage()) {
439
-            // despite all helpers having autoloaders set, we need to manually load the template loader
440
-            // because there are some side effects in that class for triggering template tag functions
441
-            $this->Registry->load_helper('EEH_Template');
442
-            $this->_template_path = ! empty($this->_template_path)
443
-                ? basename($this->_template_path)
444
-                : basename(
445
-                    $template_include_path
446
-                );
447
-            $template_path = EEH_Template::locate_template($this->_template_path, array(), false);
448
-            $this->_template_path = ! empty($template_path) ? $template_path : $template_include_path;
449
-            $this->_template = basename($this->_template_path);
450
-            return $this->_template_path;
451
-        }
452
-        return $template_include_path;
453
-    }
454
-
455
-
456
-    /**
457
-     * @param bool $with_path
458
-     * @return    string
459
-     */
460
-    public function get_selected_template($with_path = false)
461
-    {
462
-        return $with_path ? $this->_template_path : $this->_template;
463
-    }
464
-
465
-
466
-    /**
467
-     * @param string $shortcode_class
468
-     * @param WP     $wp
469
-     * @throws ReflectionException
470
-     * @deprecated 4.9.26
471
-     */
472
-    public function initialize_shortcode($shortcode_class = '', WP $wp = null)
473
-    {
474
-        EE_Error::doing_it_wrong(
475
-            __METHOD__,
476
-            esc_html__(
477
-                'Usage is deprecated. Please use \EventEspresso\core\services\shortcodes\LegacyShortcodesManager::initializeShortcode() instead.',
478
-                'event_espresso'
479
-            ),
480
-            '4.9.26'
481
-        );
482
-        $this->getLegacyShortcodesManager()->initializeShortcode($shortcode_class, $wp);
483
-    }
484
-
485
-
486
-    /**
487
-     * @return void
488
-     * @deprecated 4.9.57.p
489
-     */
490
-    public function loadPersistentAdminNoticeManager()
491
-    {
492
-    }
493
-
494
-
495
-    /**
496
-     * @return void
497
-     * @deprecated 4.9.64.p
498
-     */
499
-    public function employ_CPT_Strategy()
500
-    {
501
-    }
20
+	/**
21
+	 * @var string
22
+	 */
23
+	private $_template_path;
24
+
25
+	/**
26
+	 * @var string
27
+	 */
28
+	private $_template;
29
+
30
+	/**
31
+	 * @type EE_Registry
32
+	 */
33
+	protected $Registry;
34
+
35
+	/**
36
+	 * @type EE_Request_Handler
37
+	 */
38
+	protected $Request_Handler;
39
+
40
+	/**
41
+	 * @type EE_Module_Request_Router
42
+	 */
43
+	protected $Module_Request_Router;
44
+
45
+	/**
46
+	 * @type CurrentPage
47
+	 */
48
+	protected $current_page;
49
+
50
+
51
+	/**
52
+	 *    class constructor
53
+	 *    should fire after shortcode, module, addon, or other plugin's default priority init phases have run
54
+	 *
55
+	 * @access    public
56
+	 * @param EE_Registry              $Registry
57
+	 * @param CurrentPage              $EspressoPage
58
+	 * @param EE_Module_Request_Router $Module_Request_Router
59
+	 */
60
+	public function __construct(
61
+		EE_Registry $Registry,
62
+		CurrentPage $EspressoPage,
63
+		EE_Module_Request_Router $Module_Request_Router
64
+	) {
65
+		$this->Registry              = $Registry;
66
+		$this->current_page          = $EspressoPage;
67
+		$this->Module_Request_Router = $Module_Request_Router;
68
+		// load other resources and begin to actually run shortcodes and modules
69
+		// analyse the incoming WP request
70
+		add_action('parse_request', array($this, 'get_request'), 1, 1);
71
+		// process request with module factory
72
+		add_action('pre_get_posts', array($this, 'pre_get_posts'), 10, 1);
73
+		// before headers sent
74
+		add_action('wp', array($this, 'wp'), 5);
75
+		// primarily used to process any content shortcodes
76
+		add_action('template_redirect', array($this, 'templateRedirect'), 999);
77
+		// header
78
+		add_action('wp_head', array($this, 'header_meta_tag'), 5);
79
+		add_action('wp_print_scripts', array($this, 'wp_print_scripts'), 10);
80
+		add_filter('template_include', array($this, 'template_include'), 1);
81
+		// display errors
82
+		add_action('loop_start', array($this, 'display_errors'), 2);
83
+		// the content
84
+		// add_filter( 'the_content', array( $this, 'the_content' ), 5, 1 );
85
+		// exclude our private cpt comments
86
+		add_filter('comments_clauses', array($this, 'filter_wp_comments'), 10, 1);
87
+		// make sure any ajax requests will respect the url schema when requests are made against admin-ajax.php (http:// or https://)
88
+		add_filter('admin_url', array($this, 'maybe_force_admin_ajax_ssl'), 200, 1);
89
+		// action hook EE
90
+		do_action('AHEE__EE_Front_Controller__construct__done', $this);
91
+	}
92
+
93
+
94
+	/**
95
+	 * @return EE_Request_Handler
96
+	 * @deprecated 4.10.14.p
97
+	 */
98
+	public function Request_Handler()
99
+	{
100
+		if (! $this->Request_Handler instanceof EE_Request_Handler) {
101
+			$this->Request_Handler = LoaderFactory::getLoader()->getShared('EE_Request_Handler');
102
+		}
103
+		return $this->Request_Handler;
104
+	}
105
+
106
+
107
+	/**
108
+	 * @return EE_Module_Request_Router
109
+	 */
110
+	public function Module_Request_Router()
111
+	{
112
+		return $this->Module_Request_Router;
113
+	}
114
+
115
+
116
+	/**
117
+	 * @return LegacyShortcodesManager
118
+	 * @deprecated 4.10.14.p
119
+	 */
120
+	public function getLegacyShortcodesManager()
121
+	{
122
+		return EE_Config::getLegacyShortcodesManager();
123
+	}
124
+
125
+
126
+
127
+
128
+
129
+	/***********************************************        INIT ACTION HOOK         ***********************************************/
130
+	/**
131
+	 * filter_wp_comments
132
+	 * This simply makes sure that any "private" EE CPTs do not have their comments show up in any wp comment
133
+	 * widgets/queries done on frontend
134
+	 *
135
+	 * @param  array $clauses array of comment clauses setup by WP_Comment_Query
136
+	 * @return array array of comment clauses with modifications.
137
+	 * @throws InvalidArgumentException
138
+	 * @throws InvalidDataTypeException
139
+	 * @throws InvalidInterfaceException
140
+	 */
141
+	public function filter_wp_comments($clauses)
142
+	{
143
+		global $wpdb;
144
+		if (strpos($clauses['join'], $wpdb->posts) !== false) {
145
+			/** @var EventEspresso\core\domain\entities\custom_post_types\CustomPostTypeDefinitions $custom_post_types */
146
+			$custom_post_types = LoaderFactory::getLoader()->getShared(
147
+				'EventEspresso\core\domain\entities\custom_post_types\CustomPostTypeDefinitions'
148
+			);
149
+			$cpts = $custom_post_types->getPrivateCustomPostTypes();
150
+			foreach ($cpts as $cpt => $details) {
151
+				$clauses['where'] .= $wpdb->prepare(" AND $wpdb->posts.post_type != %s", $cpt);
152
+			}
153
+		}
154
+		return $clauses;
155
+	}
156
+
157
+
158
+	/**
159
+	 * this just makes sure that if the site is using ssl that we force that for any admin ajax calls from frontend
160
+	 *
161
+	 * @param  string $url incoming url
162
+	 * @return string         final assembled url
163
+	 */
164
+	public function maybe_force_admin_ajax_ssl($url)
165
+	{
166
+		if (is_ssl() && preg_match('/admin-ajax.php/', $url)) {
167
+			$url = str_replace('http://', 'https://', $url);
168
+		}
169
+		return $url;
170
+	}
171
+
172
+
173
+
174
+
175
+
176
+
177
+	/***********************************************        WP_LOADED ACTION HOOK         ***********************************************/
178
+
179
+
180
+	/**
181
+	 *    wp_loaded - should fire after shortcode, module, addon, or other plugin's have been registered and their
182
+	 *    default priority init phases have run
183
+	 *
184
+	 * @access    public
185
+	 * @return    void
186
+	 */
187
+	public function wp_loaded()
188
+	{
189
+	}
190
+
191
+
192
+
193
+
194
+
195
+	/***********************************************        PARSE_REQUEST HOOK         ***********************************************/
196
+	/**
197
+	 *    _get_request
198
+	 *
199
+	 * @access public
200
+	 * @param WP $WP
201
+	 * @return void
202
+	 */
203
+	public function get_request(WP $WP)
204
+	{
205
+		do_action('AHEE__EE_Front_Controller__get_request__start');
206
+		$this->current_page->parseQueryVars($WP);
207
+		do_action('AHEE__EE_Front_Controller__get_request__complete');
208
+		remove_action('parse_request', [$this, 'get_request'], 1);
209
+	}
210
+
211
+
212
+	/**
213
+	 *    pre_get_posts - basically a module factory for instantiating modules and selecting the final view template
214
+	 *
215
+	 * @access    public
216
+	 * @param WP_Query $WP_Query
217
+	 * @return    void
218
+	 * @throws EE_Error
219
+	 * @throws ReflectionException
220
+	 */
221
+	public function pre_get_posts($WP_Query)
222
+	{
223
+		// only load Module_Request_Router if this is the main query
224
+		if (
225
+			$this->Module_Request_Router instanceof EE_Module_Request_Router
226
+			&& $WP_Query->is_main_query()
227
+		) {
228
+			// cycle thru module routes
229
+			while ($route = $this->Module_Request_Router->get_route($WP_Query)) {
230
+				// determine module and method for route
231
+				$module = $this->Module_Request_Router->resolve_route($route[0], $route[1]);
232
+				if ($module instanceof EED_Module) {
233
+					// get registered view for route
234
+					$this->_template_path = $this->Module_Request_Router->get_view($route);
235
+					// grab module name
236
+					$module_name = $module->module_name();
237
+					// map the module to the module objects
238
+					$this->Registry->modules->{$module_name} = $module;
239
+				}
240
+			}
241
+		}
242
+	}
243
+
244
+
245
+
246
+
247
+
248
+	/***********************************************        WP HOOK         ***********************************************/
249
+
250
+
251
+	/**
252
+	 *    wp - basically last chance to do stuff before headers sent
253
+	 *
254
+	 * @access    public
255
+	 * @return    void
256
+	 */
257
+	public function wp()
258
+	{
259
+	}
260
+
261
+
262
+
263
+	/***********************     GET_HEADER && WP_HEAD HOOK     ***********************/
264
+
265
+
266
+	/**
267
+	 * callback for the "template_redirect" hook point
268
+	 * checks sidebars for EE widgets
269
+	 * loads resources and assets accordingly
270
+	 *
271
+	 * @return void
272
+	 */
273
+	public function templateRedirect()
274
+	{
275
+		global $wp_query;
276
+		if (empty($wp_query->posts)) {
277
+			return;
278
+		}
279
+		// if we already know this is an espresso page, then load assets
280
+		$load_assets = $this->current_page->isEspressoPage();
281
+		// if we are already loading assets then just move along, otherwise check for widgets
282
+		$load_assets = $load_assets || $this->espresso_widgets_in_active_sidebars();
283
+		if ($load_assets) {
284
+			add_action('wp_enqueue_scripts', array($this, 'enqueueStyle'), 10);
285
+			add_action('wp_print_footer_scripts', array($this, 'enqueueScripts'), 10);
286
+		}
287
+	}
288
+
289
+
290
+	/**
291
+	 * builds list of active widgets then scans active sidebars looking for them
292
+	 * returns true is an EE widget is found in an active sidebar
293
+	 * Please Note: this does NOT mean that the sidebar or widget
294
+	 * is actually in use in a given template, as that is unfortunately not known
295
+	 * until a sidebar and it's widgets are actually loaded
296
+	 *
297
+	 * @return boolean
298
+	 */
299
+	private function espresso_widgets_in_active_sidebars()
300
+	{
301
+		$espresso_widgets = array();
302
+		foreach ($this->Registry->widgets as $widget_class => $widget) {
303
+			$id_base = EspressoWidget::getIdBase($widget_class);
304
+			if (is_active_widget(false, false, $id_base)) {
305
+				$espresso_widgets[] = $id_base;
306
+			}
307
+		}
308
+		$all_sidebar_widgets = wp_get_sidebars_widgets();
309
+		foreach ($all_sidebar_widgets as $sidebar_widgets) {
310
+			if (is_array($sidebar_widgets) && ! empty($sidebar_widgets)) {
311
+				foreach ($sidebar_widgets as $sidebar_widget) {
312
+					foreach ($espresso_widgets as $espresso_widget) {
313
+						if (strpos($sidebar_widget, $espresso_widget) !== false) {
314
+							return true;
315
+						}
316
+					}
317
+				}
318
+			}
319
+		}
320
+		return false;
321
+	}
322
+
323
+
324
+	/**
325
+	 *    header_meta_tag
326
+	 *
327
+	 * @access    public
328
+	 * @return    void
329
+	 */
330
+	public function header_meta_tag()
331
+	{
332
+		print(
333
+		apply_filters(
334
+			'FHEE__EE_Front_Controller__header_meta_tag',
335
+			'<meta name="generator" content="Event Espresso Version ' . EVENT_ESPRESSO_VERSION . "\" />\n"
336
+		)
337
+		);
338
+
339
+		// let's exclude all event type taxonomy term archive pages from search engine indexing
340
+		// @see https://events.codebasehq.com/projects/event-espresso/tickets/10249
341
+		// also exclude all critical pages from indexing
342
+		if (
343
+			(
344
+				is_tax('espresso_event_type')
345
+				&& get_option('blog_public') !== '0'
346
+			)
347
+			|| is_page(EE_Registry::instance()->CFG->core->get_critical_pages_array())
348
+		) {
349
+			print(
350
+			apply_filters(
351
+				'FHEE__EE_Front_Controller__header_meta_tag__noindex_for_event_type',
352
+				'<meta name="robots" content="noindex,follow" />' . "\n"
353
+			)
354
+			);
355
+		}
356
+	}
357
+
358
+
359
+	/**
360
+	 * wp_print_scripts
361
+	 *
362
+	 * @return void
363
+	 * @throws EE_Error
364
+	 */
365
+	public function wp_print_scripts()
366
+	{
367
+		global $post;
368
+		if (
369
+			isset($post->EE_Event)
370
+			&& $post->EE_Event instanceof EE_Event
371
+			&& get_post_type() === 'espresso_events'
372
+			&& is_singular()
373
+		) {
374
+			EEH_Schema::add_json_linked_data_for_event($post->EE_Event);
375
+		}
376
+	}
377
+
378
+
379
+	public function enqueueStyle()
380
+	{
381
+		wp_enqueue_style('espresso_default');
382
+		wp_enqueue_style('espresso_custom_css');
383
+	}
384
+
385
+
386
+
387
+	/***********************************************        WP_FOOTER         ***********************************************/
388
+
389
+
390
+	public function enqueueScripts()
391
+	{
392
+		wp_enqueue_script('espresso_core');
393
+	}
394
+
395
+
396
+	/**
397
+	 * display_errors
398
+	 *
399
+	 * @access public
400
+	 * @return void
401
+	 * @throws DomainException
402
+	 */
403
+	public function display_errors()
404
+	{
405
+		static $shown_already = false;
406
+		do_action('AHEE__EE_Front_Controller__display_errors__begin');
407
+		if (
408
+			! $shown_already
409
+			&& apply_filters('FHEE__EE_Front_Controller__display_errors', true)
410
+			&& is_main_query()
411
+			&& ! is_feed()
412
+			&& in_the_loop()
413
+			&& did_action('wp_head')
414
+			&& $this->current_page->isEspressoPage()
415
+		) {
416
+			echo EE_Error::get_notices();
417
+			$shown_already = true;
418
+			EEH_Template::display_template(EE_TEMPLATES . 'espresso-ajax-notices.template.php');
419
+		}
420
+		do_action('AHEE__EE_Front_Controller__display_errors__end');
421
+	}
422
+
423
+
424
+
425
+
426
+
427
+	/***********************************************        UTILITIES         ***********************************************/
428
+
429
+
430
+	/**
431
+	 * @param string $template_include_path
432
+	 * @return string
433
+	 * @throws EE_Error
434
+	 * @throws ReflectionException
435
+	 */
436
+	public function template_include($template_include_path = null)
437
+	{
438
+		if ($this->current_page->isEspressoPage()) {
439
+			// despite all helpers having autoloaders set, we need to manually load the template loader
440
+			// because there are some side effects in that class for triggering template tag functions
441
+			$this->Registry->load_helper('EEH_Template');
442
+			$this->_template_path = ! empty($this->_template_path)
443
+				? basename($this->_template_path)
444
+				: basename(
445
+					$template_include_path
446
+				);
447
+			$template_path = EEH_Template::locate_template($this->_template_path, array(), false);
448
+			$this->_template_path = ! empty($template_path) ? $template_path : $template_include_path;
449
+			$this->_template = basename($this->_template_path);
450
+			return $this->_template_path;
451
+		}
452
+		return $template_include_path;
453
+	}
454
+
455
+
456
+	/**
457
+	 * @param bool $with_path
458
+	 * @return    string
459
+	 */
460
+	public function get_selected_template($with_path = false)
461
+	{
462
+		return $with_path ? $this->_template_path : $this->_template;
463
+	}
464
+
465
+
466
+	/**
467
+	 * @param string $shortcode_class
468
+	 * @param WP     $wp
469
+	 * @throws ReflectionException
470
+	 * @deprecated 4.9.26
471
+	 */
472
+	public function initialize_shortcode($shortcode_class = '', WP $wp = null)
473
+	{
474
+		EE_Error::doing_it_wrong(
475
+			__METHOD__,
476
+			esc_html__(
477
+				'Usage is deprecated. Please use \EventEspresso\core\services\shortcodes\LegacyShortcodesManager::initializeShortcode() instead.',
478
+				'event_espresso'
479
+			),
480
+			'4.9.26'
481
+		);
482
+		$this->getLegacyShortcodesManager()->initializeShortcode($shortcode_class, $wp);
483
+	}
484
+
485
+
486
+	/**
487
+	 * @return void
488
+	 * @deprecated 4.9.57.p
489
+	 */
490
+	public function loadPersistentAdminNoticeManager()
491
+	{
492
+	}
493
+
494
+
495
+	/**
496
+	 * @return void
497
+	 * @deprecated 4.9.64.p
498
+	 */
499
+	public function employ_CPT_Strategy()
500
+	{
501
+	}
502 502
 }
Please login to merge, or discard this patch.
core/db_models/EEM_Event.model.php 1 patch
Indentation   +951 added lines, -951 removed lines patch added patch discarded remove patch
@@ -15,955 +15,955 @@
 block discarded – undo
15 15
 class EEM_Event extends EEM_CPT_Base
16 16
 {
17 17
 
18
-    /**
19
-     * constant used by status(), indicating that no more tickets can be purchased for any of the datetimes for the
20
-     * event
21
-     */
22
-    const sold_out = 'sold_out';
23
-
24
-    /**
25
-     * constant used by status(), indicating that upcoming event dates have been postponed (may be pushed to a later
26
-     * date)
27
-     */
28
-    const postponed = 'postponed';
29
-
30
-    /**
31
-     * constant used by status(), indicating that the event will no longer occur
32
-     */
33
-    const cancelled = 'cancelled';
34
-
35
-
36
-    /**
37
-     * @var string
38
-     */
39
-    protected static $_default_reg_status;
40
-
41
-
42
-    /**
43
-     * This is the default for the additional limit field.
44
-     * @var int
45
-     */
46
-    protected static $_default_additional_limit = 10;
47
-
48
-
49
-    /**
50
-     * private instance of the Event object
51
-     *
52
-     * @var EEM_Event
53
-     */
54
-    protected static $_instance;
55
-
56
-
57
-
58
-
59
-    /**
60
-     * Adds a relationship to Term_Taxonomy for each CPT_Base
61
-     *
62
-     * @param string $timezone
63
-     * @throws \EE_Error
64
-     */
65
-    protected function __construct($timezone = null)
66
-    {
67
-        EE_Registry::instance()->load_model('Registration');
68
-        $this->singular_item = esc_html__('Event', 'event_espresso');
69
-        $this->plural_item = esc_html__('Events', 'event_espresso');
70
-        // to remove Cancelled events from the frontend, copy the following filter to your functions.php file
71
-        // add_filter( 'AFEE__EEM_Event__construct___custom_stati__cancelled__Public', '__return_false' );
72
-        // to remove Postponed events from the frontend, copy the following filter to your functions.php file
73
-        // add_filter( 'AFEE__EEM_Event__construct___custom_stati__postponed__Public', '__return_false' );
74
-        // to remove Sold Out events from the frontend, copy the following filter to your functions.php file
75
-        //  add_filter( 'AFEE__EEM_Event__construct___custom_stati__sold_out__Public', '__return_false' );
76
-        $this->_custom_stati = apply_filters(
77
-            'AFEE__EEM_Event__construct___custom_stati',
78
-            array(
79
-                EEM_Event::cancelled => array(
80
-                    'label'  => esc_html__('Cancelled', 'event_espresso'),
81
-                    'public' => apply_filters('AFEE__EEM_Event__construct___custom_stati__cancelled__Public', true),
82
-                ),
83
-                EEM_Event::postponed => array(
84
-                    'label'  => esc_html__('Postponed', 'event_espresso'),
85
-                    'public' => apply_filters('AFEE__EEM_Event__construct___custom_stati__postponed__Public', true),
86
-                ),
87
-                EEM_Event::sold_out  => array(
88
-                    'label'  => esc_html__('Sold Out', 'event_espresso'),
89
-                    'public' => apply_filters('AFEE__EEM_Event__construct___custom_stati__sold_out__Public', true),
90
-                ),
91
-            )
92
-        );
93
-        self::$_default_reg_status = empty(self::$_default_reg_status) ? EEM_Registration::status_id_pending_payment
94
-            : self::$_default_reg_status;
95
-        $this->_tables = array(
96
-            'Event_CPT'  => new EE_Primary_Table('posts', 'ID'),
97
-            'Event_Meta' => new EE_Secondary_Table('esp_event_meta', 'EVTM_ID', 'EVT_ID'),
98
-        );
99
-        $this->_fields = array(
100
-            'Event_CPT'  => array(
101
-                'EVT_ID'         => new EE_Primary_Key_Int_Field(
102
-                    'ID',
103
-                    esc_html__('Post ID for Event', 'event_espresso')
104
-                ),
105
-                'EVT_name'       => new EE_Plain_Text_Field(
106
-                    'post_title',
107
-                    esc_html__('Event Name', 'event_espresso'),
108
-                    false,
109
-                    ''
110
-                ),
111
-                'EVT_desc'       => new EE_Post_Content_Field(
112
-                    'post_content',
113
-                    esc_html__('Event Description', 'event_espresso'),
114
-                    false,
115
-                    ''
116
-                ),
117
-                'EVT_slug'       => new EE_Slug_Field(
118
-                    'post_name',
119
-                    esc_html__('Event Slug', 'event_espresso'),
120
-                    false,
121
-                    ''
122
-                ),
123
-                'EVT_created'    => new EE_Datetime_Field(
124
-                    'post_date',
125
-                    esc_html__('Date/Time Event Created', 'event_espresso'),
126
-                    false,
127
-                    EE_Datetime_Field::now
128
-                ),
129
-                'EVT_short_desc' => new EE_Simple_HTML_Field(
130
-                    'post_excerpt',
131
-                    esc_html__('Event Short Description', 'event_espresso'),
132
-                    false,
133
-                    ''
134
-                ),
135
-                'EVT_modified'   => new EE_Datetime_Field(
136
-                    'post_modified',
137
-                    esc_html__('Date/Time Event Modified', 'event_espresso'),
138
-                    false,
139
-                    EE_Datetime_Field::now
140
-                ),
141
-                'EVT_wp_user'    => new EE_WP_User_Field(
142
-                    'post_author',
143
-                    esc_html__('Event Creator ID', 'event_espresso'),
144
-                    false
145
-                ),
146
-                'parent'         => new EE_Integer_Field(
147
-                    'post_parent',
148
-                    esc_html__('Event Parent ID', 'event_espresso'),
149
-                    false,
150
-                    0
151
-                ),
152
-                'EVT_order'      => new EE_Integer_Field(
153
-                    'menu_order',
154
-                    esc_html__('Event Menu Order', 'event_espresso'),
155
-                    false,
156
-                    1
157
-                ),
158
-                'post_type'      => new EE_WP_Post_Type_Field('espresso_events'),
159
-                // EE_Plain_Text_Field( 'post_type', esc_html__( 'Event Post Type', 'event_espresso' ), FALSE, 'espresso_events' ),
160
-                'status'         => new EE_WP_Post_Status_Field(
161
-                    'post_status',
162
-                    esc_html__('Event Status', 'event_espresso'),
163
-                    false,
164
-                    'draft',
165
-                    $this->_custom_stati
166
-                ),
167
-                'password' => new EE_Password_Field(
168
-                    'post_password',
169
-                    esc_html__('Password', 'event_espresso'),
170
-                    false,
171
-                    '',
172
-                    array(
173
-                        'EVT_desc',
174
-                        'EVT_short_desc',
175
-                        'EVT_display_desc',
176
-                        'EVT_display_ticket_selector',
177
-                        'EVT_visible_on',
178
-                        'EVT_additional_limit',
179
-                        'EVT_default_registration_status',
180
-                        'EVT_member_only',
181
-                        'EVT_phone',
182
-                        'EVT_allow_overflow',
183
-                        'EVT_timezone_string',
184
-                        'EVT_external_URL',
185
-                        'EVT_donations'
186
-                    )
187
-                )
188
-            ),
189
-            'Event_Meta' => array(
190
-                'EVTM_ID'                         => new EE_DB_Only_Float_Field(
191
-                    'EVTM_ID',
192
-                    esc_html__('Event Meta Row ID', 'event_espresso'),
193
-                    false
194
-                ),
195
-                'EVT_ID_fk'                       => new EE_DB_Only_Int_Field(
196
-                    'EVT_ID',
197
-                    esc_html__('Foreign key to Event ID from Event Meta table', 'event_espresso'),
198
-                    false
199
-                ),
200
-                'EVT_display_desc'                => new EE_Boolean_Field(
201
-                    'EVT_display_desc',
202
-                    esc_html__('Display Description Flag', 'event_espresso'),
203
-                    false,
204
-                    true
205
-                ),
206
-                'EVT_display_ticket_selector'     => new EE_Boolean_Field(
207
-                    'EVT_display_ticket_selector',
208
-                    esc_html__('Display Ticket Selector Flag', 'event_espresso'),
209
-                    false,
210
-                    true
211
-                ),
212
-                'EVT_visible_on'                  => new EE_Datetime_Field(
213
-                    'EVT_visible_on',
214
-                    esc_html__('Event Visible Date', 'event_espresso'),
215
-                    true,
216
-                    EE_Datetime_Field::now
217
-                ),
218
-                'EVT_additional_limit'            => new EE_Integer_Field(
219
-                    'EVT_additional_limit',
220
-                    esc_html__('Limit of Additional Registrations on Same Transaction', 'event_espresso'),
221
-                    true,
222
-                    self::$_default_additional_limit
223
-                ),
224
-                'EVT_default_registration_status' => new EE_Enum_Text_Field(
225
-                    'EVT_default_registration_status',
226
-                    esc_html__('Default Registration Status on this Event', 'event_espresso'),
227
-                    false,
228
-                    EEM_Event::$_default_reg_status,
229
-                    EEM_Registration::reg_status_array()
230
-                ),
231
-                'EVT_member_only'                 => new EE_Boolean_Field(
232
-                    'EVT_member_only',
233
-                    esc_html__('Member-Only Event Flag', 'event_espresso'),
234
-                    false,
235
-                    false
236
-                ),
237
-                'EVT_phone'                       => new EE_Plain_Text_Field(
238
-                    'EVT_phone',
239
-                    esc_html__('Event Phone Number', 'event_espresso'),
240
-                    false,
241
-                    ''
242
-                ),
243
-                'EVT_allow_overflow'              => new EE_Boolean_Field(
244
-                    'EVT_allow_overflow',
245
-                    esc_html__('Allow Overflow on Event', 'event_espresso'),
246
-                    false,
247
-                    false
248
-                ),
249
-                'EVT_timezone_string'             => new EE_Plain_Text_Field(
250
-                    'EVT_timezone_string',
251
-                    esc_html__('Timezone (name) for Event times', 'event_espresso'),
252
-                    false,
253
-                    ''
254
-                ),
255
-                'EVT_external_URL'                => new EE_Plain_Text_Field(
256
-                    'EVT_external_URL',
257
-                    esc_html__('URL of Event Page if hosted elsewhere', 'event_espresso'),
258
-                    true
259
-                ),
260
-                'EVT_donations'                   => new EE_Boolean_Field(
261
-                    'EVT_donations',
262
-                    esc_html__('Accept Donations?', 'event_espresso'),
263
-                    false,
264
-                    false
265
-                ),
266
-            ),
267
-        );
268
-        $this->_model_relations = array(
269
-            'Registration'           => new EE_Has_Many_Relation(),
270
-            'Datetime'               => new EE_Has_Many_Relation(),
271
-            'Question_Group'         => new EE_HABTM_Relation('Event_Question_Group'),
272
-            'Event_Question_Group'   => new EE_Has_Many_Relation(),
273
-            'Venue'                  => new EE_HABTM_Relation('Event_Venue'),
274
-            'Term_Relationship'      => new EE_Has_Many_Relation(),
275
-            'Term_Taxonomy'          => new EE_HABTM_Relation('Term_Relationship'),
276
-            'Message_Template_Group' => new EE_HABTM_Relation('Event_Message_Template'),
277
-            'Attendee'               => new EE_HABTM_Relation('Registration'),
278
-            'WP_User'                => new EE_Belongs_To_Relation(),
279
-        );
280
-        // this model is generally available for reading
281
-        $this->_cap_restriction_generators[ EEM_Base::caps_read ] = new EE_Restriction_Generator_Public();
282
-        $this->model_chain_to_password = '';
283
-        parent::__construct($timezone);
284
-    }
285
-
286
-
287
-
288
-    /**
289
-     * @param string $default_reg_status
290
-     */
291
-    public static function set_default_reg_status($default_reg_status)
292
-    {
293
-        self::$_default_reg_status = $default_reg_status;
294
-        // if EEM_Event has already been instantiated,
295
-        // then we need to reset the `EVT_default_reg_status` field to use the new default.
296
-        if (self::$_instance instanceof EEM_Event) {
297
-            $default_reg_status = new EE_Enum_Text_Field(
298
-                'EVT_default_registration_status',
299
-                esc_html__('Default Registration Status on this Event', 'event_espresso'),
300
-                false,
301
-                $default_reg_status,
302
-                EEM_Registration::reg_status_array()
303
-            );
304
-            $default_reg_status->_construct_finalize(
305
-                'Event_Meta',
306
-                'EVT_default_registration_status',
307
-                'EEM_Event'
308
-            );
309
-            self::$_instance->_fields['Event_Meta']['EVT_default_registration_status'] = $default_reg_status;
310
-        }
311
-    }
312
-
313
-
314
-    /**
315
-     * Used to override the default for the additional limit field.
316
-     * @param $additional_limit
317
-     */
318
-    public static function set_default_additional_limit($additional_limit)
319
-    {
320
-        self::$_default_additional_limit = (int) $additional_limit;
321
-        if (self::$_instance instanceof EEM_Event) {
322
-            self::$_instance->_fields['Event_Meta']['EVT_additional_limit'] = new EE_Integer_Field(
323
-                'EVT_additional_limit',
324
-                esc_html__('Limit of Additional Registrations on Same Transaction', 'event_espresso'),
325
-                true,
326
-                self::$_default_additional_limit
327
-            );
328
-            self::$_instance->_fields['Event_Meta']['EVT_additional_limit']->_construct_finalize(
329
-                'Event_Meta',
330
-                'EVT_additional_limit',
331
-                'EEM_Event'
332
-            );
333
-        }
334
-    }
335
-
336
-
337
-    /**
338
-     * Return what is currently set as the default additional limit for the event.
339
-     * @return int
340
-     */
341
-    public static function get_default_additional_limit()
342
-    {
343
-        return apply_filters('FHEE__EEM_Event__get_default_additional_limit', self::$_default_additional_limit);
344
-    }
345
-
346
-
347
-    /**
348
-     * get_question_groups
349
-     *
350
-     * @return array
351
-     * @throws \EE_Error
352
-     */
353
-    public function get_all_question_groups()
354
-    {
355
-        return EE_Registry::instance()->load_model('Question_Group')->get_all(
356
-            array(
357
-                array('QSG_deleted' => false),
358
-                'order_by' => array('QSG_order' => 'ASC'),
359
-            )
360
-        );
361
-    }
362
-
363
-
364
-
365
-    /**
366
-     * get_question_groups
367
-     *
368
-     * @param int $EVT_ID
369
-     * @return array|bool
370
-     * @throws \EE_Error
371
-     */
372
-    public function get_all_event_question_groups($EVT_ID = 0)
373
-    {
374
-        if (! isset($EVT_ID) || ! absint($EVT_ID)) {
375
-            EE_Error::add_error(
376
-                esc_html__(
377
-                    'An error occurred. No Event Question Groups could be retrieved because an Event ID was not received.',
378
-                    'event_espresso'
379
-                ),
380
-                __FILE__,
381
-                __FUNCTION__,
382
-                __LINE__
383
-            );
384
-            return false;
385
-        }
386
-        return EE_Registry::instance()->load_model('Event_Question_Group')->get_all(
387
-            array(
388
-                array('EVT_ID' => $EVT_ID),
389
-            )
390
-        );
391
-    }
392
-
393
-
394
-    /**
395
-     * get_question_groups
396
-     *
397
-     * @param int $EVT_ID
398
-     * @param boolean $for_primary_attendee
399
-     * @return array|bool
400
-     * @throws EE_Error
401
-     * @throws InvalidArgumentException
402
-     * @throws ReflectionException
403
-     * @throws InvalidDataTypeException
404
-     * @throws InvalidInterfaceException
405
-     */
406
-    public function get_event_question_groups($EVT_ID = 0, $for_primary_attendee = true)
407
-    {
408
-        if (! isset($EVT_ID) || ! absint($EVT_ID)) {
409
-            EE_Error::add_error(
410
-                esc_html__(
411
-                    // @codingStandardsIgnoreStart
412
-                    'An error occurred. No Event Question Groups could be retrieved because an Event ID was not received.',
413
-                    // @codingStandardsIgnoreEnd
414
-                    'event_espresso'
415
-                ),
416
-                __FILE__,
417
-                __FUNCTION__,
418
-                __LINE__
419
-            );
420
-            return false;
421
-        }
422
-        $query_params = [
423
-            [
424
-                'EVT_ID' => $EVT_ID,
425
-                EEM_Event_Question_Group::instance()->fieldNameForContext($for_primary_attendee) => true
426
-            ]
427
-        ];
428
-        if ($for_primary_attendee) {
429
-            $query_params[0]['EQG_primary'] = true;
430
-        } else {
431
-            $query_params[0]['EQG_additional'] = true;
432
-        }
433
-        return EE_Registry::instance()->load_model('Event_Question_Group')->get_all($query_params);
434
-    }
435
-
436
-
437
-    /**
438
-     * get_question_groups
439
-     *
440
-     * @param int $EVT_ID
441
-     * @param EE_Registration $registration
442
-     * @return array|bool
443
-     * @throws EE_Error
444
-     * @throws InvalidArgumentException
445
-     * @throws InvalidDataTypeException
446
-     * @throws InvalidInterfaceException
447
-     * @throws ReflectionException
448
-     */
449
-    public function get_question_groups_for_event($EVT_ID = 0, EE_Registration $registration)
450
-    {
451
-        if (! isset($EVT_ID) || ! absint($EVT_ID)) {
452
-            EE_Error::add_error(
453
-                esc_html__(
454
-                    'An error occurred. No Question Groups could be retrieved because an Event ID was not received.',
455
-                    'event_espresso'
456
-                ),
457
-                __FILE__,
458
-                __FUNCTION__,
459
-                __LINE__
460
-            );
461
-            return false;
462
-        }
463
-        return EE_Registry::instance()->load_model('Question_Group')->get_all(
464
-            [
465
-                [
466
-                    'Event_Question_Group.EVT_ID'      => $EVT_ID,
467
-                    'Event_Question_Group.'
468
-                        . EEM_Event_Question_Group::instance()->fieldNameForContext(
469
-                            $registration->is_primary_registrant()
470
-                        ) => true
471
-                ],
472
-                'order_by' => ['QSG_order' => 'ASC'],
473
-            ]
474
-        );
475
-    }
476
-
477
-
478
-
479
-    /**
480
-     * get_question_target_db_column
481
-     *
482
-     * @param string $QSG_IDs csv list of $QSG IDs
483
-     * @return array|bool
484
-     * @throws \EE_Error
485
-     */
486
-    public function get_questions_in_groups($QSG_IDs = '')
487
-    {
488
-        if (empty($QSG_IDs)) {
489
-            EE_Error::add_error(
490
-                esc_html__('An error occurred. No Question Group IDs were received.', 'event_espresso'),
491
-                __FILE__,
492
-                __FUNCTION__,
493
-                __LINE__
494
-            );
495
-            return false;
496
-        }
497
-        return EE_Registry::instance()->load_model('Question')->get_all(
498
-            array(
499
-                array(
500
-                    'Question_Group.QSG_ID' => array('IN', $QSG_IDs),
501
-                    'QST_deleted'           => false,
502
-                    'QST_admin_only'        => is_admin(),
503
-                ),
504
-                'order_by' => 'QST_order',
505
-            )
506
-        );
507
-    }
508
-
509
-
510
-
511
-    /**
512
-     * get_options_for_question
513
-     *
514
-     * @param string $QST_IDs csv list of $QST IDs
515
-     * @return array|bool
516
-     * @throws \EE_Error
517
-     */
518
-    public function get_options_for_question($QST_IDs)
519
-    {
520
-        if (empty($QST_IDs)) {
521
-            EE_Error::add_error(
522
-                esc_html__('An error occurred. No Question IDs were received.', 'event_espresso'),
523
-                __FILE__,
524
-                __FUNCTION__,
525
-                __LINE__
526
-            );
527
-            return false;
528
-        }
529
-        return EE_Registry::instance()->load_model('Question_Option')->get_all(
530
-            array(
531
-                array(
532
-                    'Question.QST_ID' => array('IN', $QST_IDs),
533
-                    'QSO_deleted'     => false,
534
-                ),
535
-                'order_by' => 'QSO_ID',
536
-            )
537
-        );
538
-    }
539
-
540
-
541
-
542
-
543
-
544
-
545
-
546
-    /**
547
-     * Gets all events that are published
548
-     * and have event start time earlier than now and an event end time later than now
549
-     *
550
-     * @param  array $query_params An array of query params to further filter on
551
-     *                             (note that status and DTT_EVT_start and DTT_EVT_end will be overridden)
552
-     * @param bool   $count        whether to return the count or not (default FALSE)
553
-     * @return EE_Event[]|int
554
-     * @throws \EE_Error
555
-     */
556
-    public function get_active_events($query_params, $count = false)
557
-    {
558
-        if (array_key_exists(0, $query_params)) {
559
-            $where_params = $query_params[0];
560
-            unset($query_params[0]);
561
-        } else {
562
-            $where_params = array();
563
-        }
564
-        // if we have count make sure we don't include group by
565
-        if ($count && isset($query_params['group_by'])) {
566
-            unset($query_params['group_by']);
567
-        }
568
-        // let's add specific query_params for active_events
569
-        // keep in mind this will override any sent status in the query AND any date queries.
570
-        $where_params['status'] = array('IN', array('publish', EEM_Event::sold_out));
571
-        // if already have where params for DTT_EVT_start or DTT_EVT_end then append these conditions
572
-        if (isset($where_params['Datetime.DTT_EVT_start'])) {
573
-            $where_params['Datetime.DTT_EVT_start******'] = array(
574
-                '<',
575
-                EEM_Datetime::instance()->current_time_for_query('DTT_EVT_start'),
576
-            );
577
-        } else {
578
-            $where_params['Datetime.DTT_EVT_start'] = array(
579
-                '<',
580
-                EEM_Datetime::instance()->current_time_for_query('DTT_EVT_start'),
581
-            );
582
-        }
583
-        if (isset($where_params['Datetime.DTT_EVT_end'])) {
584
-            $where_params['Datetime.DTT_EVT_end*****'] = array(
585
-                '>',
586
-                EEM_Datetime::instance()->current_time_for_query('DTT_EVT_end'),
587
-            );
588
-        } else {
589
-            $where_params['Datetime.DTT_EVT_end'] = array(
590
-                '>',
591
-                EEM_Datetime::instance()->current_time_for_query('DTT_EVT_end'),
592
-            );
593
-        }
594
-        $query_params[0] = $where_params;
595
-        // don't use $query_params with count()
596
-        // because we don't want to include additional query clauses like "GROUP BY"
597
-        return $count
598
-            ? $this->count(array($where_params), 'EVT_ID', true)
599
-            : $this->get_all($query_params);
600
-    }
601
-
602
-
603
-
604
-    /**
605
-     * get all events that are published and have an event start time later than now
606
-     *
607
-     * @param  array $query_params An array of query params to further filter on
608
-     *                             (Note that status and DTT_EVT_start will be overridden)
609
-     * @param bool   $count        whether to return the count or not (default FALSE)
610
-     * @return EE_Event[]|int
611
-     * @throws \EE_Error
612
-     */
613
-    public function get_upcoming_events($query_params, $count = false)
614
-    {
615
-        if (array_key_exists(0, $query_params)) {
616
-            $where_params = $query_params[0];
617
-            unset($query_params[0]);
618
-        } else {
619
-            $where_params = array();
620
-        }
621
-        // if we have count make sure we don't include group by
622
-        if ($count && isset($query_params['group_by'])) {
623
-            unset($query_params['group_by']);
624
-        }
625
-        // let's add specific query_params for active_events
626
-        // keep in mind this will override any sent status in the query AND any date queries.
627
-        // we need to pull events with a status of publish and sold_out
628
-        $event_status = array('publish', EEM_Event::sold_out);
629
-        // check if the user can read private events and if so add the 'private status to the were params'
630
-        if (EE_Registry::instance()->CAP->current_user_can('ee_read_private_events', 'get_upcoming_events')) {
631
-            $event_status[] = 'private';
632
-        }
633
-        $where_params['status'] = array('IN', $event_status);
634
-        // if there are already query_params matching DTT_EVT_start then we need to modify that to add them.
635
-        if (isset($where_params['Datetime.DTT_EVT_start'])) {
636
-            $where_params['Datetime.DTT_EVT_start*****'] = array(
637
-                '>',
638
-                EEM_Datetime::instance()->current_time_for_query('DTT_EVT_start'),
639
-            );
640
-        } else {
641
-            $where_params['Datetime.DTT_EVT_start'] = array(
642
-                '>',
643
-                EEM_Datetime::instance()->current_time_for_query('DTT_EVT_start'),
644
-            );
645
-        }
646
-        $query_params[0] = $where_params;
647
-        // don't use $query_params with count()
648
-        // because we don't want to include additional query clauses like "GROUP BY"
649
-        return $count
650
-            ? $this->count(array($where_params), 'EVT_ID', true)
651
-            : $this->get_all($query_params);
652
-    }
653
-
654
-
655
-
656
-    /**
657
-     * Gets all events that are published
658
-     * and have an event end time later than now
659
-     *
660
-     * @param  array $query_params An array of query params to further filter on
661
-     *                             (note that status and DTT_EVT_end will be overridden)
662
-     * @param bool   $count        whether to return the count or not (default FALSE)
663
-     * @return EE_Event[]|int
664
-     * @throws \EE_Error
665
-     */
666
-    public function get_active_and_upcoming_events($query_params, $count = false)
667
-    {
668
-        if (array_key_exists(0, $query_params)) {
669
-            $where_params = $query_params[0];
670
-            unset($query_params[0]);
671
-        } else {
672
-            $where_params = array();
673
-        }
674
-        // if we have count make sure we don't include group by
675
-        if ($count && isset($query_params['group_by'])) {
676
-            unset($query_params['group_by']);
677
-        }
678
-        // let's add specific query_params for active_events
679
-        // keep in mind this will override any sent status in the query AND any date queries.
680
-        $where_params['status'] = array('IN', array('publish', EEM_Event::sold_out));
681
-        // add where params for DTT_EVT_end
682
-        if (isset($where_params['Datetime.DTT_EVT_end'])) {
683
-            $where_params['Datetime.DTT_EVT_end*****'] = array(
684
-                '>',
685
-                EEM_Datetime::instance()->current_time_for_query('DTT_EVT_end'),
686
-            );
687
-        } else {
688
-            $where_params['Datetime.DTT_EVT_end'] = array(
689
-                '>',
690
-                EEM_Datetime::instance()->current_time_for_query('DTT_EVT_end'),
691
-            );
692
-        }
693
-        $query_params[0] = $where_params;
694
-        // don't use $query_params with count()
695
-        // because we don't want to include additional query clauses like "GROUP BY"
696
-        return $count
697
-            ? $this->count(array($where_params), 'EVT_ID', true)
698
-            : $this->get_all($query_params);
699
-    }
700
-
701
-
702
-
703
-    /**
704
-     * This only returns events that are expired.
705
-     * They may still be published but all their datetimes have expired.
706
-     *
707
-     * @param  array $query_params An array of query params to further filter on
708
-     *                             (note that status and DTT_EVT_end will be overridden)
709
-     * @param bool   $count        whether to return the count or not (default FALSE)
710
-     * @return EE_Event[]|int
711
-     * @throws \EE_Error
712
-     */
713
-    public function get_expired_events($query_params, $count = false)
714
-    {
715
-        $where_params = isset($query_params[0]) ? $query_params[0] : array();
716
-        // if we have count make sure we don't include group by
717
-        if ($count && isset($query_params['group_by'])) {
718
-            unset($query_params['group_by']);
719
-        }
720
-        // let's add specific query_params for active_events
721
-        // keep in mind this will override any sent status in the query AND any date queries.
722
-        if (isset($where_params['status'])) {
723
-            unset($where_params['status']);
724
-        }
725
-        $exclude_query = $query_params;
726
-        if (isset($exclude_query[0])) {
727
-            unset($exclude_query[0]);
728
-        }
729
-        $exclude_query[0] = array(
730
-            'Datetime.DTT_EVT_end' => array(
731
-                '>',
732
-                EEM_Datetime::instance()->current_time_for_query('DTT_EVT_end'),
733
-            ),
734
-        );
735
-        // first get all events that have datetimes where its not expired.
736
-        $event_ids = $this->_get_all_wpdb_results($exclude_query, OBJECT_K, 'Event_CPT.ID');
737
-        $event_ids = array_keys($event_ids);
738
-        // if we have any additional query_params, let's add them to the 'AND' condition
739
-        $and_condition = array(
740
-            'Datetime.DTT_EVT_end' => array('<', EEM_Datetime::instance()->current_time_for_query('DTT_EVT_end')),
741
-            'EVT_ID'               => array('NOT IN', $event_ids),
742
-        );
743
-        if (isset($where_params['OR'])) {
744
-            $and_condition['OR'] = $where_params['OR'];
745
-            unset($where_params['OR']);
746
-        }
747
-        if (isset($where_params['Datetime.DTT_EVT_end'])) {
748
-            $and_condition['Datetime.DTT_EVT_end****'] = $where_params['Datetime.DTT_EVT_end'];
749
-            unset($where_params['Datetime.DTT_EVT_end']);
750
-        }
751
-        if (isset($where_params['Datetime.DTT_EVT_start'])) {
752
-            $and_condition['Datetime.DTT_EVT_start'] = $where_params['Datetime.DTT_EVT_start'];
753
-            unset($where_params['Datetime.DTT_EVT_start']);
754
-        }
755
-        // merge remaining $where params with the and conditions.
756
-        $where_params['AND'] = array_merge($and_condition, $where_params);
757
-        $query_params[0] = $where_params;
758
-        // don't use $query_params with count()
759
-        // because we don't want to include additional query clauses like "GROUP BY"
760
-        return $count
761
-            ? $this->count(array($where_params), 'EVT_ID', true)
762
-            : $this->get_all($query_params);
763
-    }
764
-
765
-
766
-
767
-    /**
768
-     * This basically just returns the events that do not have the publish status.
769
-     *
770
-     * @param  array   $query_params An array of query params to further filter on
771
-     *                               (note that status will be overwritten)
772
-     * @param  boolean $count        whether to return the count or not (default FALSE)
773
-     * @return EE_Event[]|int
774
-     * @throws \EE_Error
775
-     */
776
-    public function get_inactive_events($query_params, $count = false)
777
-    {
778
-        $where_params = isset($query_params[0]) ? $query_params[0] : array();
779
-        // let's add in specific query_params for inactive events.
780
-        if (isset($where_params['status'])) {
781
-            unset($where_params['status']);
782
-        }
783
-        // if we have count make sure we don't include group by
784
-        if ($count && isset($query_params['group_by'])) {
785
-            unset($query_params['group_by']);
786
-        }
787
-        // if we have any additional query_params, let's add them to the 'AND' condition
788
-        $where_params['AND']['status'] = array('!=', 'publish');
789
-        if (isset($where_params['OR'])) {
790
-            $where_params['AND']['OR'] = $where_params['OR'];
791
-            unset($where_params['OR']);
792
-        }
793
-        if (isset($where_params['Datetime.DTT_EVT_end'])) {
794
-            $where_params['AND']['Datetime.DTT_EVT_end****'] = $where_params['Datetime.DTT_EVT_end'];
795
-            unset($where_params['Datetime.DTT_EVT_end']);
796
-        }
797
-        if (isset($where_params['Datetime.DTT_EVT_start'])) {
798
-            $where_params['AND']['Datetime.DTT_EVT_start'] = $where_params['Datetime.DTT_EVT_start'];
799
-            unset($where_params['Datetime.DTT_EVT_start']);
800
-        }
801
-        $query_params[0] = $where_params;
802
-        // don't use $query_params with count()
803
-        // because we don't want to include additional query clauses like "GROUP BY"
804
-        return $count
805
-            ? $this->count(array($where_params), 'EVT_ID', true)
806
-            : $this->get_all($query_params);
807
-    }
808
-
809
-
810
-
811
-    /**
812
-     * This is just injecting into the parent add_relationship_to so we do special handling on price relationships
813
-     * because we don't want to override any existing global default prices but instead insert NEW prices that get
814
-     * attached to the event. See parent for param descriptions
815
-     *
816
-     * @param        $id_or_obj
817
-     * @param        $other_model_id_or_obj
818
-     * @param string $relationName
819
-     * @param array  $where_query
820
-     * @return EE_Base_Class
821
-     * @throws EE_Error
822
-     */
823
-    public function add_relationship_to($id_or_obj, $other_model_id_or_obj, $relationName, $where_query = array())
824
-    {
825
-        if ($relationName === 'Price') {
826
-            // let's get the PRC object for the given ID to make sure that we aren't dealing with a default
827
-            $prc_chk = $this->get_related_model_obj($relationName)->ensure_is_obj($other_model_id_or_obj);
828
-            // if EVT_ID = 0, then this is a default
829
-            if ((int) $prc_chk->get('EVT_ID') === 0) {
830
-                // let's set the prc_id as 0 so we force an insert on the add_relation_to carried out by relation
831
-                $prc_chk->set('PRC_ID', 0);
832
-            }
833
-            // run parent
834
-            return parent::add_relationship_to($id_or_obj, $prc_chk, $relationName, $where_query);
835
-        }
836
-        // otherwise carry on as normal
837
-        return parent::add_relationship_to($id_or_obj, $other_model_id_or_obj, $relationName, $where_query);
838
-    }
839
-
840
-
841
-
842
-    /******************** DEPRECATED METHODS ********************/
843
-
844
-
845
-
846
-    /**
847
-     * _get_question_target_db_column
848
-     *
849
-     * @deprecated as of 4.8.32.rc.001. Instead consider using
850
-     *             EE_Registration_Custom_Questions_Form located in
851
-     *             admin_pages/registrations/form_sections/EE_Registration_Custom_Questions_Form.form.php
852
-     * @access     public
853
-     * @param    EE_Registration $registration (so existing answers for registration are included)
854
-     * @param    int             $EVT_ID       so all question groups are included for event (not just answers from
855
-     *                                         registration).
856
-     * @throws EE_Error
857
-     * @return    array
858
-     */
859
-    public function assemble_array_of_groups_questions_and_options(EE_Registration $registration, $EVT_ID = 0)
860
-    {
861
-        if (empty($EVT_ID)) {
862
-            throw new EE_Error(esc_html__(
863
-                'An error occurred. No EVT_ID is included.  Needed to know which question groups to retrieve.',
864
-                'event_espresso'
865
-            ));
866
-        }
867
-        $questions = array();
868
-        // get all question groups for event
869
-        $qgs = $this->get_question_groups_for_event($EVT_ID, $registration);
870
-        if (! empty($qgs)) {
871
-            foreach ($qgs as $qg) {
872
-                $qsts = $qg->questions();
873
-                $questions[ $qg->ID() ] = $qg->model_field_array();
874
-                $questions[ $qg->ID() ]['QSG_questions'] = array();
875
-                foreach ($qsts as $qst) {
876
-                    if ($qst->is_system_question()) {
877
-                        continue;
878
-                    }
879
-                    $answer = EEM_Answer::instance()->get_one(array(
880
-                        array(
881
-                            'QST_ID' => $qst->ID(),
882
-                            'REG_ID' => $registration->ID(),
883
-                        ),
884
-                    ));
885
-                    $answer = $answer instanceof EE_Answer ? $answer : EEM_Answer::instance()->create_default_object();
886
-                    $qst_name = $qstn_id = $qst->ID();
887
-                    $ans_id = $answer->ID();
888
-                    $qst_name = ! empty($ans_id) ? '[' . $qst_name . '][' . $ans_id . ']' : '[' . $qst_name . ']';
889
-                    $input_name = '';
890
-                    $input_id = sanitize_key($qst->display_text());
891
-                    $input_class = '';
892
-                    $questions[ $qg->ID() ]['QSG_questions'][ $qst->ID() ] = $qst->model_field_array();
893
-                    $questions[ $qg->ID() ]['QSG_questions'][ $qst->ID() ]['QST_input_name'] = 'qstn'
894
-                                                                                           . $input_name
895
-                                                                                           . $qst_name;
896
-                    $questions[ $qg->ID() ]['QSG_questions'][ $qst->ID() ]['QST_input_id'] = $input_id . '-' . $qstn_id;
897
-                    $questions[ $qg->ID() ]['QSG_questions'][ $qst->ID() ]['QST_input_class'] = $input_class;
898
-                    $questions[ $qg->ID() ]['QSG_questions'][ $qst->ID() ]['QST_options'] = array();
899
-                    $questions[ $qg->ID() ]['QSG_questions'][ $qst->ID() ]['qst_obj'] = $qst;
900
-                    $questions[ $qg->ID() ]['QSG_questions'][ $qst->ID() ]['ans_obj'] = $answer;
901
-                    // leave responses as-is, don't convert stuff into html entities please!
902
-                    $questions[ $qg->ID() ]['QSG_questions'][ $qst->ID() ]['htmlentities'] = false;
903
-                    if ($qst->type() == 'RADIO_BTN' || $qst->type() == 'CHECKBOX' || $qst->type() == 'DROPDOWN') {
904
-                        $QSOs = $qst->options(true, $answer->value());
905
-                        if (is_array($QSOs)) {
906
-                            foreach ($QSOs as $QSO_ID => $QSO) {
907
-                                $questions[ $qg->ID() ]['QSG_questions'][ $qst->ID() ]['QST_options'][ $QSO_ID ] = $QSO->model_field_array();
908
-                            }
909
-                        }
910
-                    }
911
-                }
912
-            }
913
-        }
914
-        return $questions;
915
-    }
916
-
917
-
918
-    /**
919
-     * @param mixed $cols_n_values either an array of where each key is the name of a field, and the value is its value
920
-     *                             or an stdClass where each property is the name of a column,
921
-     * @return EE_Base_Class
922
-     * @throws \EE_Error
923
-     */
924
-    public function instantiate_class_from_array_or_object($cols_n_values)
925
-    {
926
-        $classInstance = parent::instantiate_class_from_array_or_object($cols_n_values);
927
-        if ($classInstance instanceof EE_Event) {
928
-            // events have their timezone defined in the DB, so use it immediately
929
-            $this->set_timezone($classInstance->get_timezone());
930
-        }
931
-        return $classInstance;
932
-    }
933
-
934
-
935
-    /**
936
-     * Deletes the model objects that meet the query params. Note: this method is overridden
937
-     * in EEM_Soft_Delete_Base so that soft-deleted model objects are instead only flagged
938
-     * as archived, not actually deleted
939
-     *
940
-     * @param array   $query_params   @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
941
-     * @param boolean $allow_blocking if TRUE, matched objects will only be deleted if there is no related model info
942
-     *                                that blocks it (ie, there' sno other data that depends on this data); if false,
943
-     *                                deletes regardless of other objects which may depend on it. Its generally
944
-     *                                advisable to always leave this as TRUE, otherwise you could easily corrupt your
945
-     *                                DB
946
-     * @return int                    number of rows deleted
947
-     * @throws EE_Error
948
-     */
949
-    public function delete_permanently($query_params, $allow_blocking = true)
950
-    {
951
-        $deleted = parent::delete_permanently($query_params, $allow_blocking);
952
-        if ($deleted) {
953
-            // get list of events with no prices
954
-            $espresso_no_ticket_prices = get_option('ee_no_ticket_prices', []);
955
-            $where = isset($query_params[0]) ? $query_params[0] : [];
956
-            $where_event = isset($where['EVT_ID']) ? $where['EVT_ID'] : ['', ''];
957
-            $where_event_ids = isset($where_event[1]) ? $where_event[1] : '';
958
-            $event_ids = is_string($where_event_ids)
959
-                ? explode(',', $where_event_ids)
960
-                : (array) $where_event_ids;
961
-            array_walk($event_ids, 'trim');
962
-            $event_ids = array_filter($event_ids);
963
-            // remove events from list of events with no prices
964
-            $espresso_no_ticket_prices = array_diff($espresso_no_ticket_prices, $event_ids);
965
-            update_option('ee_no_ticket_prices', $espresso_no_ticket_prices);
966
-        }
967
-        return $deleted;
968
-    }
18
+	/**
19
+	 * constant used by status(), indicating that no more tickets can be purchased for any of the datetimes for the
20
+	 * event
21
+	 */
22
+	const sold_out = 'sold_out';
23
+
24
+	/**
25
+	 * constant used by status(), indicating that upcoming event dates have been postponed (may be pushed to a later
26
+	 * date)
27
+	 */
28
+	const postponed = 'postponed';
29
+
30
+	/**
31
+	 * constant used by status(), indicating that the event will no longer occur
32
+	 */
33
+	const cancelled = 'cancelled';
34
+
35
+
36
+	/**
37
+	 * @var string
38
+	 */
39
+	protected static $_default_reg_status;
40
+
41
+
42
+	/**
43
+	 * This is the default for the additional limit field.
44
+	 * @var int
45
+	 */
46
+	protected static $_default_additional_limit = 10;
47
+
48
+
49
+	/**
50
+	 * private instance of the Event object
51
+	 *
52
+	 * @var EEM_Event
53
+	 */
54
+	protected static $_instance;
55
+
56
+
57
+
58
+
59
+	/**
60
+	 * Adds a relationship to Term_Taxonomy for each CPT_Base
61
+	 *
62
+	 * @param string $timezone
63
+	 * @throws \EE_Error
64
+	 */
65
+	protected function __construct($timezone = null)
66
+	{
67
+		EE_Registry::instance()->load_model('Registration');
68
+		$this->singular_item = esc_html__('Event', 'event_espresso');
69
+		$this->plural_item = esc_html__('Events', 'event_espresso');
70
+		// to remove Cancelled events from the frontend, copy the following filter to your functions.php file
71
+		// add_filter( 'AFEE__EEM_Event__construct___custom_stati__cancelled__Public', '__return_false' );
72
+		// to remove Postponed events from the frontend, copy the following filter to your functions.php file
73
+		// add_filter( 'AFEE__EEM_Event__construct___custom_stati__postponed__Public', '__return_false' );
74
+		// to remove Sold Out events from the frontend, copy the following filter to your functions.php file
75
+		//  add_filter( 'AFEE__EEM_Event__construct___custom_stati__sold_out__Public', '__return_false' );
76
+		$this->_custom_stati = apply_filters(
77
+			'AFEE__EEM_Event__construct___custom_stati',
78
+			array(
79
+				EEM_Event::cancelled => array(
80
+					'label'  => esc_html__('Cancelled', 'event_espresso'),
81
+					'public' => apply_filters('AFEE__EEM_Event__construct___custom_stati__cancelled__Public', true),
82
+				),
83
+				EEM_Event::postponed => array(
84
+					'label'  => esc_html__('Postponed', 'event_espresso'),
85
+					'public' => apply_filters('AFEE__EEM_Event__construct___custom_stati__postponed__Public', true),
86
+				),
87
+				EEM_Event::sold_out  => array(
88
+					'label'  => esc_html__('Sold Out', 'event_espresso'),
89
+					'public' => apply_filters('AFEE__EEM_Event__construct___custom_stati__sold_out__Public', true),
90
+				),
91
+			)
92
+		);
93
+		self::$_default_reg_status = empty(self::$_default_reg_status) ? EEM_Registration::status_id_pending_payment
94
+			: self::$_default_reg_status;
95
+		$this->_tables = array(
96
+			'Event_CPT'  => new EE_Primary_Table('posts', 'ID'),
97
+			'Event_Meta' => new EE_Secondary_Table('esp_event_meta', 'EVTM_ID', 'EVT_ID'),
98
+		);
99
+		$this->_fields = array(
100
+			'Event_CPT'  => array(
101
+				'EVT_ID'         => new EE_Primary_Key_Int_Field(
102
+					'ID',
103
+					esc_html__('Post ID for Event', 'event_espresso')
104
+				),
105
+				'EVT_name'       => new EE_Plain_Text_Field(
106
+					'post_title',
107
+					esc_html__('Event Name', 'event_espresso'),
108
+					false,
109
+					''
110
+				),
111
+				'EVT_desc'       => new EE_Post_Content_Field(
112
+					'post_content',
113
+					esc_html__('Event Description', 'event_espresso'),
114
+					false,
115
+					''
116
+				),
117
+				'EVT_slug'       => new EE_Slug_Field(
118
+					'post_name',
119
+					esc_html__('Event Slug', 'event_espresso'),
120
+					false,
121
+					''
122
+				),
123
+				'EVT_created'    => new EE_Datetime_Field(
124
+					'post_date',
125
+					esc_html__('Date/Time Event Created', 'event_espresso'),
126
+					false,
127
+					EE_Datetime_Field::now
128
+				),
129
+				'EVT_short_desc' => new EE_Simple_HTML_Field(
130
+					'post_excerpt',
131
+					esc_html__('Event Short Description', 'event_espresso'),
132
+					false,
133
+					''
134
+				),
135
+				'EVT_modified'   => new EE_Datetime_Field(
136
+					'post_modified',
137
+					esc_html__('Date/Time Event Modified', 'event_espresso'),
138
+					false,
139
+					EE_Datetime_Field::now
140
+				),
141
+				'EVT_wp_user'    => new EE_WP_User_Field(
142
+					'post_author',
143
+					esc_html__('Event Creator ID', 'event_espresso'),
144
+					false
145
+				),
146
+				'parent'         => new EE_Integer_Field(
147
+					'post_parent',
148
+					esc_html__('Event Parent ID', 'event_espresso'),
149
+					false,
150
+					0
151
+				),
152
+				'EVT_order'      => new EE_Integer_Field(
153
+					'menu_order',
154
+					esc_html__('Event Menu Order', 'event_espresso'),
155
+					false,
156
+					1
157
+				),
158
+				'post_type'      => new EE_WP_Post_Type_Field('espresso_events'),
159
+				// EE_Plain_Text_Field( 'post_type', esc_html__( 'Event Post Type', 'event_espresso' ), FALSE, 'espresso_events' ),
160
+				'status'         => new EE_WP_Post_Status_Field(
161
+					'post_status',
162
+					esc_html__('Event Status', 'event_espresso'),
163
+					false,
164
+					'draft',
165
+					$this->_custom_stati
166
+				),
167
+				'password' => new EE_Password_Field(
168
+					'post_password',
169
+					esc_html__('Password', 'event_espresso'),
170
+					false,
171
+					'',
172
+					array(
173
+						'EVT_desc',
174
+						'EVT_short_desc',
175
+						'EVT_display_desc',
176
+						'EVT_display_ticket_selector',
177
+						'EVT_visible_on',
178
+						'EVT_additional_limit',
179
+						'EVT_default_registration_status',
180
+						'EVT_member_only',
181
+						'EVT_phone',
182
+						'EVT_allow_overflow',
183
+						'EVT_timezone_string',
184
+						'EVT_external_URL',
185
+						'EVT_donations'
186
+					)
187
+				)
188
+			),
189
+			'Event_Meta' => array(
190
+				'EVTM_ID'                         => new EE_DB_Only_Float_Field(
191
+					'EVTM_ID',
192
+					esc_html__('Event Meta Row ID', 'event_espresso'),
193
+					false
194
+				),
195
+				'EVT_ID_fk'                       => new EE_DB_Only_Int_Field(
196
+					'EVT_ID',
197
+					esc_html__('Foreign key to Event ID from Event Meta table', 'event_espresso'),
198
+					false
199
+				),
200
+				'EVT_display_desc'                => new EE_Boolean_Field(
201
+					'EVT_display_desc',
202
+					esc_html__('Display Description Flag', 'event_espresso'),
203
+					false,
204
+					true
205
+				),
206
+				'EVT_display_ticket_selector'     => new EE_Boolean_Field(
207
+					'EVT_display_ticket_selector',
208
+					esc_html__('Display Ticket Selector Flag', 'event_espresso'),
209
+					false,
210
+					true
211
+				),
212
+				'EVT_visible_on'                  => new EE_Datetime_Field(
213
+					'EVT_visible_on',
214
+					esc_html__('Event Visible Date', 'event_espresso'),
215
+					true,
216
+					EE_Datetime_Field::now
217
+				),
218
+				'EVT_additional_limit'            => new EE_Integer_Field(
219
+					'EVT_additional_limit',
220
+					esc_html__('Limit of Additional Registrations on Same Transaction', 'event_espresso'),
221
+					true,
222
+					self::$_default_additional_limit
223
+				),
224
+				'EVT_default_registration_status' => new EE_Enum_Text_Field(
225
+					'EVT_default_registration_status',
226
+					esc_html__('Default Registration Status on this Event', 'event_espresso'),
227
+					false,
228
+					EEM_Event::$_default_reg_status,
229
+					EEM_Registration::reg_status_array()
230
+				),
231
+				'EVT_member_only'                 => new EE_Boolean_Field(
232
+					'EVT_member_only',
233
+					esc_html__('Member-Only Event Flag', 'event_espresso'),
234
+					false,
235
+					false
236
+				),
237
+				'EVT_phone'                       => new EE_Plain_Text_Field(
238
+					'EVT_phone',
239
+					esc_html__('Event Phone Number', 'event_espresso'),
240
+					false,
241
+					''
242
+				),
243
+				'EVT_allow_overflow'              => new EE_Boolean_Field(
244
+					'EVT_allow_overflow',
245
+					esc_html__('Allow Overflow on Event', 'event_espresso'),
246
+					false,
247
+					false
248
+				),
249
+				'EVT_timezone_string'             => new EE_Plain_Text_Field(
250
+					'EVT_timezone_string',
251
+					esc_html__('Timezone (name) for Event times', 'event_espresso'),
252
+					false,
253
+					''
254
+				),
255
+				'EVT_external_URL'                => new EE_Plain_Text_Field(
256
+					'EVT_external_URL',
257
+					esc_html__('URL of Event Page if hosted elsewhere', 'event_espresso'),
258
+					true
259
+				),
260
+				'EVT_donations'                   => new EE_Boolean_Field(
261
+					'EVT_donations',
262
+					esc_html__('Accept Donations?', 'event_espresso'),
263
+					false,
264
+					false
265
+				),
266
+			),
267
+		);
268
+		$this->_model_relations = array(
269
+			'Registration'           => new EE_Has_Many_Relation(),
270
+			'Datetime'               => new EE_Has_Many_Relation(),
271
+			'Question_Group'         => new EE_HABTM_Relation('Event_Question_Group'),
272
+			'Event_Question_Group'   => new EE_Has_Many_Relation(),
273
+			'Venue'                  => new EE_HABTM_Relation('Event_Venue'),
274
+			'Term_Relationship'      => new EE_Has_Many_Relation(),
275
+			'Term_Taxonomy'          => new EE_HABTM_Relation('Term_Relationship'),
276
+			'Message_Template_Group' => new EE_HABTM_Relation('Event_Message_Template'),
277
+			'Attendee'               => new EE_HABTM_Relation('Registration'),
278
+			'WP_User'                => new EE_Belongs_To_Relation(),
279
+		);
280
+		// this model is generally available for reading
281
+		$this->_cap_restriction_generators[ EEM_Base::caps_read ] = new EE_Restriction_Generator_Public();
282
+		$this->model_chain_to_password = '';
283
+		parent::__construct($timezone);
284
+	}
285
+
286
+
287
+
288
+	/**
289
+	 * @param string $default_reg_status
290
+	 */
291
+	public static function set_default_reg_status($default_reg_status)
292
+	{
293
+		self::$_default_reg_status = $default_reg_status;
294
+		// if EEM_Event has already been instantiated,
295
+		// then we need to reset the `EVT_default_reg_status` field to use the new default.
296
+		if (self::$_instance instanceof EEM_Event) {
297
+			$default_reg_status = new EE_Enum_Text_Field(
298
+				'EVT_default_registration_status',
299
+				esc_html__('Default Registration Status on this Event', 'event_espresso'),
300
+				false,
301
+				$default_reg_status,
302
+				EEM_Registration::reg_status_array()
303
+			);
304
+			$default_reg_status->_construct_finalize(
305
+				'Event_Meta',
306
+				'EVT_default_registration_status',
307
+				'EEM_Event'
308
+			);
309
+			self::$_instance->_fields['Event_Meta']['EVT_default_registration_status'] = $default_reg_status;
310
+		}
311
+	}
312
+
313
+
314
+	/**
315
+	 * Used to override the default for the additional limit field.
316
+	 * @param $additional_limit
317
+	 */
318
+	public static function set_default_additional_limit($additional_limit)
319
+	{
320
+		self::$_default_additional_limit = (int) $additional_limit;
321
+		if (self::$_instance instanceof EEM_Event) {
322
+			self::$_instance->_fields['Event_Meta']['EVT_additional_limit'] = new EE_Integer_Field(
323
+				'EVT_additional_limit',
324
+				esc_html__('Limit of Additional Registrations on Same Transaction', 'event_espresso'),
325
+				true,
326
+				self::$_default_additional_limit
327
+			);
328
+			self::$_instance->_fields['Event_Meta']['EVT_additional_limit']->_construct_finalize(
329
+				'Event_Meta',
330
+				'EVT_additional_limit',
331
+				'EEM_Event'
332
+			);
333
+		}
334
+	}
335
+
336
+
337
+	/**
338
+	 * Return what is currently set as the default additional limit for the event.
339
+	 * @return int
340
+	 */
341
+	public static function get_default_additional_limit()
342
+	{
343
+		return apply_filters('FHEE__EEM_Event__get_default_additional_limit', self::$_default_additional_limit);
344
+	}
345
+
346
+
347
+	/**
348
+	 * get_question_groups
349
+	 *
350
+	 * @return array
351
+	 * @throws \EE_Error
352
+	 */
353
+	public function get_all_question_groups()
354
+	{
355
+		return EE_Registry::instance()->load_model('Question_Group')->get_all(
356
+			array(
357
+				array('QSG_deleted' => false),
358
+				'order_by' => array('QSG_order' => 'ASC'),
359
+			)
360
+		);
361
+	}
362
+
363
+
364
+
365
+	/**
366
+	 * get_question_groups
367
+	 *
368
+	 * @param int $EVT_ID
369
+	 * @return array|bool
370
+	 * @throws \EE_Error
371
+	 */
372
+	public function get_all_event_question_groups($EVT_ID = 0)
373
+	{
374
+		if (! isset($EVT_ID) || ! absint($EVT_ID)) {
375
+			EE_Error::add_error(
376
+				esc_html__(
377
+					'An error occurred. No Event Question Groups could be retrieved because an Event ID was not received.',
378
+					'event_espresso'
379
+				),
380
+				__FILE__,
381
+				__FUNCTION__,
382
+				__LINE__
383
+			);
384
+			return false;
385
+		}
386
+		return EE_Registry::instance()->load_model('Event_Question_Group')->get_all(
387
+			array(
388
+				array('EVT_ID' => $EVT_ID),
389
+			)
390
+		);
391
+	}
392
+
393
+
394
+	/**
395
+	 * get_question_groups
396
+	 *
397
+	 * @param int $EVT_ID
398
+	 * @param boolean $for_primary_attendee
399
+	 * @return array|bool
400
+	 * @throws EE_Error
401
+	 * @throws InvalidArgumentException
402
+	 * @throws ReflectionException
403
+	 * @throws InvalidDataTypeException
404
+	 * @throws InvalidInterfaceException
405
+	 */
406
+	public function get_event_question_groups($EVT_ID = 0, $for_primary_attendee = true)
407
+	{
408
+		if (! isset($EVT_ID) || ! absint($EVT_ID)) {
409
+			EE_Error::add_error(
410
+				esc_html__(
411
+					// @codingStandardsIgnoreStart
412
+					'An error occurred. No Event Question Groups could be retrieved because an Event ID was not received.',
413
+					// @codingStandardsIgnoreEnd
414
+					'event_espresso'
415
+				),
416
+				__FILE__,
417
+				__FUNCTION__,
418
+				__LINE__
419
+			);
420
+			return false;
421
+		}
422
+		$query_params = [
423
+			[
424
+				'EVT_ID' => $EVT_ID,
425
+				EEM_Event_Question_Group::instance()->fieldNameForContext($for_primary_attendee) => true
426
+			]
427
+		];
428
+		if ($for_primary_attendee) {
429
+			$query_params[0]['EQG_primary'] = true;
430
+		} else {
431
+			$query_params[0]['EQG_additional'] = true;
432
+		}
433
+		return EE_Registry::instance()->load_model('Event_Question_Group')->get_all($query_params);
434
+	}
435
+
436
+
437
+	/**
438
+	 * get_question_groups
439
+	 *
440
+	 * @param int $EVT_ID
441
+	 * @param EE_Registration $registration
442
+	 * @return array|bool
443
+	 * @throws EE_Error
444
+	 * @throws InvalidArgumentException
445
+	 * @throws InvalidDataTypeException
446
+	 * @throws InvalidInterfaceException
447
+	 * @throws ReflectionException
448
+	 */
449
+	public function get_question_groups_for_event($EVT_ID = 0, EE_Registration $registration)
450
+	{
451
+		if (! isset($EVT_ID) || ! absint($EVT_ID)) {
452
+			EE_Error::add_error(
453
+				esc_html__(
454
+					'An error occurred. No Question Groups could be retrieved because an Event ID was not received.',
455
+					'event_espresso'
456
+				),
457
+				__FILE__,
458
+				__FUNCTION__,
459
+				__LINE__
460
+			);
461
+			return false;
462
+		}
463
+		return EE_Registry::instance()->load_model('Question_Group')->get_all(
464
+			[
465
+				[
466
+					'Event_Question_Group.EVT_ID'      => $EVT_ID,
467
+					'Event_Question_Group.'
468
+						. EEM_Event_Question_Group::instance()->fieldNameForContext(
469
+							$registration->is_primary_registrant()
470
+						) => true
471
+				],
472
+				'order_by' => ['QSG_order' => 'ASC'],
473
+			]
474
+		);
475
+	}
476
+
477
+
478
+
479
+	/**
480
+	 * get_question_target_db_column
481
+	 *
482
+	 * @param string $QSG_IDs csv list of $QSG IDs
483
+	 * @return array|bool
484
+	 * @throws \EE_Error
485
+	 */
486
+	public function get_questions_in_groups($QSG_IDs = '')
487
+	{
488
+		if (empty($QSG_IDs)) {
489
+			EE_Error::add_error(
490
+				esc_html__('An error occurred. No Question Group IDs were received.', 'event_espresso'),
491
+				__FILE__,
492
+				__FUNCTION__,
493
+				__LINE__
494
+			);
495
+			return false;
496
+		}
497
+		return EE_Registry::instance()->load_model('Question')->get_all(
498
+			array(
499
+				array(
500
+					'Question_Group.QSG_ID' => array('IN', $QSG_IDs),
501
+					'QST_deleted'           => false,
502
+					'QST_admin_only'        => is_admin(),
503
+				),
504
+				'order_by' => 'QST_order',
505
+			)
506
+		);
507
+	}
508
+
509
+
510
+
511
+	/**
512
+	 * get_options_for_question
513
+	 *
514
+	 * @param string $QST_IDs csv list of $QST IDs
515
+	 * @return array|bool
516
+	 * @throws \EE_Error
517
+	 */
518
+	public function get_options_for_question($QST_IDs)
519
+	{
520
+		if (empty($QST_IDs)) {
521
+			EE_Error::add_error(
522
+				esc_html__('An error occurred. No Question IDs were received.', 'event_espresso'),
523
+				__FILE__,
524
+				__FUNCTION__,
525
+				__LINE__
526
+			);
527
+			return false;
528
+		}
529
+		return EE_Registry::instance()->load_model('Question_Option')->get_all(
530
+			array(
531
+				array(
532
+					'Question.QST_ID' => array('IN', $QST_IDs),
533
+					'QSO_deleted'     => false,
534
+				),
535
+				'order_by' => 'QSO_ID',
536
+			)
537
+		);
538
+	}
539
+
540
+
541
+
542
+
543
+
544
+
545
+
546
+	/**
547
+	 * Gets all events that are published
548
+	 * and have event start time earlier than now and an event end time later than now
549
+	 *
550
+	 * @param  array $query_params An array of query params to further filter on
551
+	 *                             (note that status and DTT_EVT_start and DTT_EVT_end will be overridden)
552
+	 * @param bool   $count        whether to return the count or not (default FALSE)
553
+	 * @return EE_Event[]|int
554
+	 * @throws \EE_Error
555
+	 */
556
+	public function get_active_events($query_params, $count = false)
557
+	{
558
+		if (array_key_exists(0, $query_params)) {
559
+			$where_params = $query_params[0];
560
+			unset($query_params[0]);
561
+		} else {
562
+			$where_params = array();
563
+		}
564
+		// if we have count make sure we don't include group by
565
+		if ($count && isset($query_params['group_by'])) {
566
+			unset($query_params['group_by']);
567
+		}
568
+		// let's add specific query_params for active_events
569
+		// keep in mind this will override any sent status in the query AND any date queries.
570
+		$where_params['status'] = array('IN', array('publish', EEM_Event::sold_out));
571
+		// if already have where params for DTT_EVT_start or DTT_EVT_end then append these conditions
572
+		if (isset($where_params['Datetime.DTT_EVT_start'])) {
573
+			$where_params['Datetime.DTT_EVT_start******'] = array(
574
+				'<',
575
+				EEM_Datetime::instance()->current_time_for_query('DTT_EVT_start'),
576
+			);
577
+		} else {
578
+			$where_params['Datetime.DTT_EVT_start'] = array(
579
+				'<',
580
+				EEM_Datetime::instance()->current_time_for_query('DTT_EVT_start'),
581
+			);
582
+		}
583
+		if (isset($where_params['Datetime.DTT_EVT_end'])) {
584
+			$where_params['Datetime.DTT_EVT_end*****'] = array(
585
+				'>',
586
+				EEM_Datetime::instance()->current_time_for_query('DTT_EVT_end'),
587
+			);
588
+		} else {
589
+			$where_params['Datetime.DTT_EVT_end'] = array(
590
+				'>',
591
+				EEM_Datetime::instance()->current_time_for_query('DTT_EVT_end'),
592
+			);
593
+		}
594
+		$query_params[0] = $where_params;
595
+		// don't use $query_params with count()
596
+		// because we don't want to include additional query clauses like "GROUP BY"
597
+		return $count
598
+			? $this->count(array($where_params), 'EVT_ID', true)
599
+			: $this->get_all($query_params);
600
+	}
601
+
602
+
603
+
604
+	/**
605
+	 * get all events that are published and have an event start time later than now
606
+	 *
607
+	 * @param  array $query_params An array of query params to further filter on
608
+	 *                             (Note that status and DTT_EVT_start will be overridden)
609
+	 * @param bool   $count        whether to return the count or not (default FALSE)
610
+	 * @return EE_Event[]|int
611
+	 * @throws \EE_Error
612
+	 */
613
+	public function get_upcoming_events($query_params, $count = false)
614
+	{
615
+		if (array_key_exists(0, $query_params)) {
616
+			$where_params = $query_params[0];
617
+			unset($query_params[0]);
618
+		} else {
619
+			$where_params = array();
620
+		}
621
+		// if we have count make sure we don't include group by
622
+		if ($count && isset($query_params['group_by'])) {
623
+			unset($query_params['group_by']);
624
+		}
625
+		// let's add specific query_params for active_events
626
+		// keep in mind this will override any sent status in the query AND any date queries.
627
+		// we need to pull events with a status of publish and sold_out
628
+		$event_status = array('publish', EEM_Event::sold_out);
629
+		// check if the user can read private events and if so add the 'private status to the were params'
630
+		if (EE_Registry::instance()->CAP->current_user_can('ee_read_private_events', 'get_upcoming_events')) {
631
+			$event_status[] = 'private';
632
+		}
633
+		$where_params['status'] = array('IN', $event_status);
634
+		// if there are already query_params matching DTT_EVT_start then we need to modify that to add them.
635
+		if (isset($where_params['Datetime.DTT_EVT_start'])) {
636
+			$where_params['Datetime.DTT_EVT_start*****'] = array(
637
+				'>',
638
+				EEM_Datetime::instance()->current_time_for_query('DTT_EVT_start'),
639
+			);
640
+		} else {
641
+			$where_params['Datetime.DTT_EVT_start'] = array(
642
+				'>',
643
+				EEM_Datetime::instance()->current_time_for_query('DTT_EVT_start'),
644
+			);
645
+		}
646
+		$query_params[0] = $where_params;
647
+		// don't use $query_params with count()
648
+		// because we don't want to include additional query clauses like "GROUP BY"
649
+		return $count
650
+			? $this->count(array($where_params), 'EVT_ID', true)
651
+			: $this->get_all($query_params);
652
+	}
653
+
654
+
655
+
656
+	/**
657
+	 * Gets all events that are published
658
+	 * and have an event end time later than now
659
+	 *
660
+	 * @param  array $query_params An array of query params to further filter on
661
+	 *                             (note that status and DTT_EVT_end will be overridden)
662
+	 * @param bool   $count        whether to return the count or not (default FALSE)
663
+	 * @return EE_Event[]|int
664
+	 * @throws \EE_Error
665
+	 */
666
+	public function get_active_and_upcoming_events($query_params, $count = false)
667
+	{
668
+		if (array_key_exists(0, $query_params)) {
669
+			$where_params = $query_params[0];
670
+			unset($query_params[0]);
671
+		} else {
672
+			$where_params = array();
673
+		}
674
+		// if we have count make sure we don't include group by
675
+		if ($count && isset($query_params['group_by'])) {
676
+			unset($query_params['group_by']);
677
+		}
678
+		// let's add specific query_params for active_events
679
+		// keep in mind this will override any sent status in the query AND any date queries.
680
+		$where_params['status'] = array('IN', array('publish', EEM_Event::sold_out));
681
+		// add where params for DTT_EVT_end
682
+		if (isset($where_params['Datetime.DTT_EVT_end'])) {
683
+			$where_params['Datetime.DTT_EVT_end*****'] = array(
684
+				'>',
685
+				EEM_Datetime::instance()->current_time_for_query('DTT_EVT_end'),
686
+			);
687
+		} else {
688
+			$where_params['Datetime.DTT_EVT_end'] = array(
689
+				'>',
690
+				EEM_Datetime::instance()->current_time_for_query('DTT_EVT_end'),
691
+			);
692
+		}
693
+		$query_params[0] = $where_params;
694
+		// don't use $query_params with count()
695
+		// because we don't want to include additional query clauses like "GROUP BY"
696
+		return $count
697
+			? $this->count(array($where_params), 'EVT_ID', true)
698
+			: $this->get_all($query_params);
699
+	}
700
+
701
+
702
+
703
+	/**
704
+	 * This only returns events that are expired.
705
+	 * They may still be published but all their datetimes have expired.
706
+	 *
707
+	 * @param  array $query_params An array of query params to further filter on
708
+	 *                             (note that status and DTT_EVT_end will be overridden)
709
+	 * @param bool   $count        whether to return the count or not (default FALSE)
710
+	 * @return EE_Event[]|int
711
+	 * @throws \EE_Error
712
+	 */
713
+	public function get_expired_events($query_params, $count = false)
714
+	{
715
+		$where_params = isset($query_params[0]) ? $query_params[0] : array();
716
+		// if we have count make sure we don't include group by
717
+		if ($count && isset($query_params['group_by'])) {
718
+			unset($query_params['group_by']);
719
+		}
720
+		// let's add specific query_params for active_events
721
+		// keep in mind this will override any sent status in the query AND any date queries.
722
+		if (isset($where_params['status'])) {
723
+			unset($where_params['status']);
724
+		}
725
+		$exclude_query = $query_params;
726
+		if (isset($exclude_query[0])) {
727
+			unset($exclude_query[0]);
728
+		}
729
+		$exclude_query[0] = array(
730
+			'Datetime.DTT_EVT_end' => array(
731
+				'>',
732
+				EEM_Datetime::instance()->current_time_for_query('DTT_EVT_end'),
733
+			),
734
+		);
735
+		// first get all events that have datetimes where its not expired.
736
+		$event_ids = $this->_get_all_wpdb_results($exclude_query, OBJECT_K, 'Event_CPT.ID');
737
+		$event_ids = array_keys($event_ids);
738
+		// if we have any additional query_params, let's add them to the 'AND' condition
739
+		$and_condition = array(
740
+			'Datetime.DTT_EVT_end' => array('<', EEM_Datetime::instance()->current_time_for_query('DTT_EVT_end')),
741
+			'EVT_ID'               => array('NOT IN', $event_ids),
742
+		);
743
+		if (isset($where_params['OR'])) {
744
+			$and_condition['OR'] = $where_params['OR'];
745
+			unset($where_params['OR']);
746
+		}
747
+		if (isset($where_params['Datetime.DTT_EVT_end'])) {
748
+			$and_condition['Datetime.DTT_EVT_end****'] = $where_params['Datetime.DTT_EVT_end'];
749
+			unset($where_params['Datetime.DTT_EVT_end']);
750
+		}
751
+		if (isset($where_params['Datetime.DTT_EVT_start'])) {
752
+			$and_condition['Datetime.DTT_EVT_start'] = $where_params['Datetime.DTT_EVT_start'];
753
+			unset($where_params['Datetime.DTT_EVT_start']);
754
+		}
755
+		// merge remaining $where params with the and conditions.
756
+		$where_params['AND'] = array_merge($and_condition, $where_params);
757
+		$query_params[0] = $where_params;
758
+		// don't use $query_params with count()
759
+		// because we don't want to include additional query clauses like "GROUP BY"
760
+		return $count
761
+			? $this->count(array($where_params), 'EVT_ID', true)
762
+			: $this->get_all($query_params);
763
+	}
764
+
765
+
766
+
767
+	/**
768
+	 * This basically just returns the events that do not have the publish status.
769
+	 *
770
+	 * @param  array   $query_params An array of query params to further filter on
771
+	 *                               (note that status will be overwritten)
772
+	 * @param  boolean $count        whether to return the count or not (default FALSE)
773
+	 * @return EE_Event[]|int
774
+	 * @throws \EE_Error
775
+	 */
776
+	public function get_inactive_events($query_params, $count = false)
777
+	{
778
+		$where_params = isset($query_params[0]) ? $query_params[0] : array();
779
+		// let's add in specific query_params for inactive events.
780
+		if (isset($where_params['status'])) {
781
+			unset($where_params['status']);
782
+		}
783
+		// if we have count make sure we don't include group by
784
+		if ($count && isset($query_params['group_by'])) {
785
+			unset($query_params['group_by']);
786
+		}
787
+		// if we have any additional query_params, let's add them to the 'AND' condition
788
+		$where_params['AND']['status'] = array('!=', 'publish');
789
+		if (isset($where_params['OR'])) {
790
+			$where_params['AND']['OR'] = $where_params['OR'];
791
+			unset($where_params['OR']);
792
+		}
793
+		if (isset($where_params['Datetime.DTT_EVT_end'])) {
794
+			$where_params['AND']['Datetime.DTT_EVT_end****'] = $where_params['Datetime.DTT_EVT_end'];
795
+			unset($where_params['Datetime.DTT_EVT_end']);
796
+		}
797
+		if (isset($where_params['Datetime.DTT_EVT_start'])) {
798
+			$where_params['AND']['Datetime.DTT_EVT_start'] = $where_params['Datetime.DTT_EVT_start'];
799
+			unset($where_params['Datetime.DTT_EVT_start']);
800
+		}
801
+		$query_params[0] = $where_params;
802
+		// don't use $query_params with count()
803
+		// because we don't want to include additional query clauses like "GROUP BY"
804
+		return $count
805
+			? $this->count(array($where_params), 'EVT_ID', true)
806
+			: $this->get_all($query_params);
807
+	}
808
+
809
+
810
+
811
+	/**
812
+	 * This is just injecting into the parent add_relationship_to so we do special handling on price relationships
813
+	 * because we don't want to override any existing global default prices but instead insert NEW prices that get
814
+	 * attached to the event. See parent for param descriptions
815
+	 *
816
+	 * @param        $id_or_obj
817
+	 * @param        $other_model_id_or_obj
818
+	 * @param string $relationName
819
+	 * @param array  $where_query
820
+	 * @return EE_Base_Class
821
+	 * @throws EE_Error
822
+	 */
823
+	public function add_relationship_to($id_or_obj, $other_model_id_or_obj, $relationName, $where_query = array())
824
+	{
825
+		if ($relationName === 'Price') {
826
+			// let's get the PRC object for the given ID to make sure that we aren't dealing with a default
827
+			$prc_chk = $this->get_related_model_obj($relationName)->ensure_is_obj($other_model_id_or_obj);
828
+			// if EVT_ID = 0, then this is a default
829
+			if ((int) $prc_chk->get('EVT_ID') === 0) {
830
+				// let's set the prc_id as 0 so we force an insert on the add_relation_to carried out by relation
831
+				$prc_chk->set('PRC_ID', 0);
832
+			}
833
+			// run parent
834
+			return parent::add_relationship_to($id_or_obj, $prc_chk, $relationName, $where_query);
835
+		}
836
+		// otherwise carry on as normal
837
+		return parent::add_relationship_to($id_or_obj, $other_model_id_or_obj, $relationName, $where_query);
838
+	}
839
+
840
+
841
+
842
+	/******************** DEPRECATED METHODS ********************/
843
+
844
+
845
+
846
+	/**
847
+	 * _get_question_target_db_column
848
+	 *
849
+	 * @deprecated as of 4.8.32.rc.001. Instead consider using
850
+	 *             EE_Registration_Custom_Questions_Form located in
851
+	 *             admin_pages/registrations/form_sections/EE_Registration_Custom_Questions_Form.form.php
852
+	 * @access     public
853
+	 * @param    EE_Registration $registration (so existing answers for registration are included)
854
+	 * @param    int             $EVT_ID       so all question groups are included for event (not just answers from
855
+	 *                                         registration).
856
+	 * @throws EE_Error
857
+	 * @return    array
858
+	 */
859
+	public function assemble_array_of_groups_questions_and_options(EE_Registration $registration, $EVT_ID = 0)
860
+	{
861
+		if (empty($EVT_ID)) {
862
+			throw new EE_Error(esc_html__(
863
+				'An error occurred. No EVT_ID is included.  Needed to know which question groups to retrieve.',
864
+				'event_espresso'
865
+			));
866
+		}
867
+		$questions = array();
868
+		// get all question groups for event
869
+		$qgs = $this->get_question_groups_for_event($EVT_ID, $registration);
870
+		if (! empty($qgs)) {
871
+			foreach ($qgs as $qg) {
872
+				$qsts = $qg->questions();
873
+				$questions[ $qg->ID() ] = $qg->model_field_array();
874
+				$questions[ $qg->ID() ]['QSG_questions'] = array();
875
+				foreach ($qsts as $qst) {
876
+					if ($qst->is_system_question()) {
877
+						continue;
878
+					}
879
+					$answer = EEM_Answer::instance()->get_one(array(
880
+						array(
881
+							'QST_ID' => $qst->ID(),
882
+							'REG_ID' => $registration->ID(),
883
+						),
884
+					));
885
+					$answer = $answer instanceof EE_Answer ? $answer : EEM_Answer::instance()->create_default_object();
886
+					$qst_name = $qstn_id = $qst->ID();
887
+					$ans_id = $answer->ID();
888
+					$qst_name = ! empty($ans_id) ? '[' . $qst_name . '][' . $ans_id . ']' : '[' . $qst_name . ']';
889
+					$input_name = '';
890
+					$input_id = sanitize_key($qst->display_text());
891
+					$input_class = '';
892
+					$questions[ $qg->ID() ]['QSG_questions'][ $qst->ID() ] = $qst->model_field_array();
893
+					$questions[ $qg->ID() ]['QSG_questions'][ $qst->ID() ]['QST_input_name'] = 'qstn'
894
+																						   . $input_name
895
+																						   . $qst_name;
896
+					$questions[ $qg->ID() ]['QSG_questions'][ $qst->ID() ]['QST_input_id'] = $input_id . '-' . $qstn_id;
897
+					$questions[ $qg->ID() ]['QSG_questions'][ $qst->ID() ]['QST_input_class'] = $input_class;
898
+					$questions[ $qg->ID() ]['QSG_questions'][ $qst->ID() ]['QST_options'] = array();
899
+					$questions[ $qg->ID() ]['QSG_questions'][ $qst->ID() ]['qst_obj'] = $qst;
900
+					$questions[ $qg->ID() ]['QSG_questions'][ $qst->ID() ]['ans_obj'] = $answer;
901
+					// leave responses as-is, don't convert stuff into html entities please!
902
+					$questions[ $qg->ID() ]['QSG_questions'][ $qst->ID() ]['htmlentities'] = false;
903
+					if ($qst->type() == 'RADIO_BTN' || $qst->type() == 'CHECKBOX' || $qst->type() == 'DROPDOWN') {
904
+						$QSOs = $qst->options(true, $answer->value());
905
+						if (is_array($QSOs)) {
906
+							foreach ($QSOs as $QSO_ID => $QSO) {
907
+								$questions[ $qg->ID() ]['QSG_questions'][ $qst->ID() ]['QST_options'][ $QSO_ID ] = $QSO->model_field_array();
908
+							}
909
+						}
910
+					}
911
+				}
912
+			}
913
+		}
914
+		return $questions;
915
+	}
916
+
917
+
918
+	/**
919
+	 * @param mixed $cols_n_values either an array of where each key is the name of a field, and the value is its value
920
+	 *                             or an stdClass where each property is the name of a column,
921
+	 * @return EE_Base_Class
922
+	 * @throws \EE_Error
923
+	 */
924
+	public function instantiate_class_from_array_or_object($cols_n_values)
925
+	{
926
+		$classInstance = parent::instantiate_class_from_array_or_object($cols_n_values);
927
+		if ($classInstance instanceof EE_Event) {
928
+			// events have their timezone defined in the DB, so use it immediately
929
+			$this->set_timezone($classInstance->get_timezone());
930
+		}
931
+		return $classInstance;
932
+	}
933
+
934
+
935
+	/**
936
+	 * Deletes the model objects that meet the query params. Note: this method is overridden
937
+	 * in EEM_Soft_Delete_Base so that soft-deleted model objects are instead only flagged
938
+	 * as archived, not actually deleted
939
+	 *
940
+	 * @param array   $query_params   @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
941
+	 * @param boolean $allow_blocking if TRUE, matched objects will only be deleted if there is no related model info
942
+	 *                                that blocks it (ie, there' sno other data that depends on this data); if false,
943
+	 *                                deletes regardless of other objects which may depend on it. Its generally
944
+	 *                                advisable to always leave this as TRUE, otherwise you could easily corrupt your
945
+	 *                                DB
946
+	 * @return int                    number of rows deleted
947
+	 * @throws EE_Error
948
+	 */
949
+	public function delete_permanently($query_params, $allow_blocking = true)
950
+	{
951
+		$deleted = parent::delete_permanently($query_params, $allow_blocking);
952
+		if ($deleted) {
953
+			// get list of events with no prices
954
+			$espresso_no_ticket_prices = get_option('ee_no_ticket_prices', []);
955
+			$where = isset($query_params[0]) ? $query_params[0] : [];
956
+			$where_event = isset($where['EVT_ID']) ? $where['EVT_ID'] : ['', ''];
957
+			$where_event_ids = isset($where_event[1]) ? $where_event[1] : '';
958
+			$event_ids = is_string($where_event_ids)
959
+				? explode(',', $where_event_ids)
960
+				: (array) $where_event_ids;
961
+			array_walk($event_ids, 'trim');
962
+			$event_ids = array_filter($event_ids);
963
+			// remove events from list of events with no prices
964
+			$espresso_no_ticket_prices = array_diff($espresso_no_ticket_prices, $event_ids);
965
+			update_option('ee_no_ticket_prices', $espresso_no_ticket_prices);
966
+		}
967
+		return $deleted;
968
+	}
969 969
 }
Please login to merge, or discard this patch.
core/db_models/EEM_Soft_Delete_Base.model.php 1 patch
Indentation   +361 added lines, -361 removed lines patch added patch discarded remove patch
@@ -27,365 +27,365 @@
 block discarded – undo
27 27
 abstract class EEM_Soft_Delete_Base extends EEM_Base
28 28
 {
29 29
 
30
-    /**
31
-     * @param null $timezone
32
-     */
33
-    protected function __construct($timezone = null)
34
-    {
35
-        if (! $this->_default_where_conditions_strategy instanceof EE_Default_Where_Conditions) {
36
-            $this->_default_where_conditions_strategy = new EE_Soft_Delete_Where_Conditions();
37
-        }
38
-        parent::__construct($timezone);
39
-    }
40
-
41
-
42
-
43
-    /**
44
-     * Searches for field on this model of type 'deleted_flag'. if it is found,
45
-     * returns it's name.
46
-     *
47
-     * @return string
48
-     * @throws EE_Error
49
-     */
50
-    public function deleted_field_name()
51
-    {
52
-        $field = $this->get_a_field_of_type('EE_Trashed_Flag_Field');
53
-        if ($field) {
54
-            return $field->get_name();
55
-        } else {
56
-            throw new EE_Error(sprintf(esc_html__(
57
-                'We are trying to find the deleted flag field on %s, but none was found. Are you sure there is a field of type EE_Trashed_Flag_Field in %s constructor?',
58
-                'event_espresso'
59
-            ), get_class($this), get_class($this)));
60
-        }
61
-    }
62
-
63
-
64
-
65
-    /**
66
-     * Gets one item that's been deleted, according to $query_params
67
-     *
68
-     * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
69
-     * @return EE_Soft_Delete_Base_Class
70
-     */
71
-    public function get_one_deleted($query_params = array())
72
-    {
73
-        $query_params = $this->_alter_query_params_so_only_trashed_items_included($query_params);
74
-        return parent::get_one($query_params);
75
-    }
76
-
77
-
78
-
79
-    /**
80
-     * Gets one item from the DB, regardless of whether it's been soft-deleted or not
81
-     *
82
-     * @param array $query_params like EEM_base::get_all's $query_params
83
-     * @return EE_Soft_Delete_Base_Class
84
-     */
85
-    public function get_one_deleted_or_undeleted($query_params = array())
86
-    {
87
-        $query_params = $this->_alter_query_params_so_deleted_and_undeleted_items_included($query_params);
88
-        return parent::get_one($query_params);
89
-    }
90
-
91
-
92
-
93
-    /**
94
-     * Gets the item indicated by its ID. But if it's soft-deleted, pretends it doesn't exist.
95
-     *
96
-     * @param int|string $id
97
-     * @return EE_Soft_Delete_Base_Class
98
-     */
99
-    public function get_one_by_ID_but_ignore_deleted($id)
100
-    {
101
-        return $this->get_one(
102
-            $this->alter_query_params_to_restrict_by_ID(
103
-                $id,
104
-                array('default_where_conditions' => 'default')
105
-            )
106
-        );
107
-    }
108
-
109
-
110
-
111
-    /**
112
-     * Counts all the deleted/trashed items
113
-     *
114
-     * @param array  $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
115
-     * @param string $field_to_count
116
-     * @param bool   $distinct     if we want to only count the distinct values for the column then you can trigger that by the setting $distinct to TRUE;
117
-     * @return int
118
-     */
119
-    public function count_deleted($query_params = null, $field_to_count = null, $distinct = false)
120
-    {
121
-        $query_params = $this->_alter_query_params_so_only_trashed_items_included($query_params);
122
-        return parent::count($query_params, $field_to_count, $distinct);
123
-    }
124
-
125
-
126
-
127
-    /**
128
-     * Alters the query params so that only trashed/soft-deleted items are considered
129
-     *
130
-     * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
131
-     * @return array @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
132
-     */
133
-    protected function _alter_query_params_so_only_trashed_items_included($query_params)
134
-    {
135
-        $deletedFlagFieldName = $this->deleted_field_name();
136
-        $query_params[0][ $deletedFlagFieldName ] = true;
137
-        return $query_params;
138
-    }
139
-
140
-
141
-
142
-    /**
143
-     * Alters the query params so that only trashed/soft-deleted items are considered
144
-     *
145
-     * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
146
-     * @return array @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
147
-     */
148
-    public function alter_query_params_so_only_trashed_items_included($query_params)
149
-    {
150
-        return $this->_alter_query_params_so_only_trashed_items_included($query_params);
151
-    }
152
-
153
-
154
-
155
-    /**
156
-     * Alters the query params so each item's deleted status is ignored.
157
-     *
158
-     * @param array $query_params
159
-     * @return array
160
-     */
161
-    public function alter_query_params_so_deleted_and_undeleted_items_included($query_params = array())
162
-    {
163
-        return $this->_alter_query_params_so_deleted_and_undeleted_items_included($query_params);
164
-    }
165
-
166
-
167
-
168
-    /**
169
-     * Alters the query params so each item's deleted status is ignored.
170
-     *
171
-     * @param array $query_params
172
-     * @return array
173
-     */
174
-    protected function _alter_query_params_so_deleted_and_undeleted_items_included($query_params)
175
-    {
176
-        if (! isset($query_params['default_where_conditions'])) {
177
-            $query_params['default_where_conditions'] = 'minimum';
178
-        }
179
-        return $query_params;
180
-    }
181
-
182
-
183
-
184
-    /**
185
-     * Counts all deleted and undeleted items
186
-     *
187
-     * @param array  $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
188
-     * @param string $field_to_count
189
-     * @param bool   $distinct     if we want to only count the distinct values for the column then you can trigger that by the setting $distinct to TRUE;
190
-     * @return int
191
-     */
192
-    public function count_deleted_and_undeleted($query_params = null, $field_to_count = null, $distinct = false)
193
-    {
194
-        $query_params = $this->_alter_query_params_so_deleted_and_undeleted_items_included($query_params);
195
-        return parent::count($query_params, $field_to_count, $distinct);
196
-    }
197
-
198
-
199
-
200
-    /**
201
-     * Sum all the deleted items.
202
-     *
203
-     * @param array  $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
204
-     * @param string $field_to_sum
205
-     * @return int
206
-     */
207
-    public function sum_deleted($query_params = null, $field_to_sum = null)
208
-    {
209
-        $query_params = $this->_alter_query_params_so_only_trashed_items_included($query_params);
210
-        return parent::sum($query_params, $field_to_sum);
211
-    }
212
-
213
-
214
-
215
-    /**
216
-     * Sums all the deleted and undeleted items.
217
-     *
218
-     * @param array  $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
219
-     * @param string $field_to_sum
220
-     * @return int
221
-     */
222
-    public function sum_deleted_and_undeleted($query_params = null, $field_to_sum = null)
223
-    {
224
-        $query_params = $this->_alter_query_params_so_deleted_and_undeleted_items_included($query_params);
225
-        parent::sum($query_params, $field_to_sum);
226
-    }
227
-
228
-
229
-
230
-    /**
231
-     * Gets all deleted and undeleted mode objects from the db that meet the criteria, regardless of
232
-     * whether they've been soft-deleted or not
233
-     *
234
-     * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
235
-     * @return EE_Soft_Delete_Base_Class[]
236
-     */
237
-    public function get_all_deleted_and_undeleted($query_params = array())
238
-    {
239
-        $query_params = $this->_alter_query_params_so_deleted_and_undeleted_items_included($query_params);
240
-        return parent::get_all($query_params);
241
-    }
242
-
243
-
244
-
245
-    /**
246
-     * For 'soft deletable' models, gets all which ARE deleted, according to conditions specified in $query_params.
247
-     *
248
-     * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
249
-     * @return EE_Soft_Delete_Base_Class[]
250
-     */
251
-    public function get_all_deleted($query_params = array())
252
-    {
253
-        $query_params = $this->_alter_query_params_so_only_trashed_items_included($query_params);
254
-        return parent::get_all($query_params);
255
-    }
256
-
257
-
258
-
259
-    /**
260
-     * Permanently deletes the selected rows. When selecting rows for deletion, ignores
261
-     * whether they've been soft-deleted or not. (ie, you don't have to soft-delete objects
262
-     * before you can permanently delete them).
263
-     * Because this will cause a real deletion, related models may block this deletion (ie, add an error
264
-     * and abort the delete)
265
-     *
266
-     * @param array   $query_params   @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
267
-     * @param boolean $allow_blocking if TRUE, matched objects will only be deleted if there is no related model info
268
-     *                                that blocks it (ie, there' sno other data that depends on this data); if false, deletes regardless of other objects
269
-     *                                which may depend on it. Its generally advisable to always leave this as TRUE, otherwise you could easily corrupt your DB
270
-     * @return int                    number of rows deleted
271
-     * @throws EE_Error
272
-     */
273
-    public function delete_permanently($query_params, $allow_blocking = true)
274
-    {
275
-        $query_params = $this->_alter_query_params_so_deleted_and_undeleted_items_included($query_params);
276
-        return parent::delete_permanently($query_params, $allow_blocking);
277
-    }
278
-
279
-
280
-
281
-    /**
282
-     * Restores a particular item by its ID (primary key). Ignores the fact whether the item
283
-     * has been soft-deleted or not.
284
-     *
285
-     * @param mixed $ID int if primary key is an int, string otherwise
286
-     * @return boolean success
287
-     */
288
-    public function restore_by_ID($ID = false)
289
-    {
290
-        return $this->delete_or_restore_by_ID(false, $ID);
291
-    }
292
-
293
-
294
-
295
-    /**
296
-     * For deleting or restoring a particular item. Note that this model is a SOFT-DELETABLE model! However,
297
-     * this function will ignore whether the items have been soft-deleted or not.
298
-     *
299
-     * @param boolean $delete true for delete, false for restore
300
-     * @param mixed   $ID     int if primary key is an int, string otherwise
301
-     * @return boolean
302
-     */
303
-    public function delete_or_restore_by_ID($delete = true, $ID = false)
304
-    {
305
-        if (! $ID) {
306
-            return false;
307
-        }
308
-        if (
309
-            $this->delete_or_restore(
310
-                $delete,
311
-                $this->alter_query_params_to_restrict_by_ID($ID)
312
-            )
313
-        ) {
314
-            return true;
315
-        } else {
316
-            return false;
317
-        }
318
-    }
319
-
320
-
321
-
322
-    /**
323
-     * Overrides parent's 'delete' method to instead do a soft delete on all rows that
324
-     * meet the criteria in $where_col_n_values. This particular function ignores whether the items have been soft-deleted or not.
325
-     * Note: because this item will be soft-deleted only,
326
-     * doesn't block because of model dependencies
327
-     *
328
-     * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
329
-     * @param bool  $block_deletes
330
-     * @return boolean
331
-     */
332
-    public function delete($query_params = array(), $block_deletes = false)
333
-    {
334
-        // no matter what, we WON'T block soft deletes.
335
-        return $this->delete_or_restore(true, $query_params);
336
-    }
337
-
338
-
339
-
340
-    /**
341
-     * 'Un-deletes' the chosen items. Note that this model is a SOFT-DELETABLE model! That means that, by default, trashed/soft-deleted
342
-     * items are ignored in queries. However, this particular function ignores whether the items have been soft-deleted or not.
343
-     *
344
-     * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
345
-     * @return boolean
346
-     */
347
-    public function restore($query_params = array())
348
-    {
349
-        return $this->delete_or_restore(false, $query_params);
350
-    }
351
-
352
-
353
-
354
-    /**
355
-     * Performs deletes or restores on items. Both soft-deleted and non-soft-deleted items considered.
356
-     *
357
-     * @param boolean $delete       true to indicate deletion, false to indicate restoration
358
-     * @param array   $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
359
-     * @return boolean
360
-     */
361
-    public function delete_or_restore($delete = true, $query_params = array())
362
-    {
363
-        $deletedFlagFieldName = $this->deleted_field_name();
364
-        $query_params = $this->_alter_query_params_so_deleted_and_undeleted_items_included($query_params);
365
-        if ($this->update(array($deletedFlagFieldName => $delete), $query_params)) {
366
-            return true;
367
-        } else {
368
-            return false;
369
-        }
370
-    }
371
-
372
-
373
-
374
-    /**
375
-     * Updates all the items of this model which match the $query params, regardless of whether
376
-     * they've been soft-deleted or not
377
-     *
378
-     * @param array   $fields_n_values         like EEM_Base::update's $fields_n_value
379
-     * @param array   $query_params            like EEM_base::get_all's $query_params
380
-     * @param boolean $keep_model_objs_in_sync if TRUE, makes sure we ALSO update model objects
381
-     *                                         in this model's entity map according to $fields_n_values that match $query_params. This
382
-     *                                         obviously has some overhead, so you can disable it by setting this to FALSE, but
383
-     *                                         be aware that model objects being used could get out-of-sync with the database
384
-     * @return int number of items updated
385
-     */
386
-    public function update_deleted_and_undeleted($fields_n_values, $query_params, $keep_model_objs_in_sync = true)
387
-    {
388
-        $query_params = $this->_alter_query_params_so_deleted_and_undeleted_items_included($query_params);
389
-        return $this->update($fields_n_values, $query_params, $keep_model_objs_in_sync);
390
-    }
30
+	/**
31
+	 * @param null $timezone
32
+	 */
33
+	protected function __construct($timezone = null)
34
+	{
35
+		if (! $this->_default_where_conditions_strategy instanceof EE_Default_Where_Conditions) {
36
+			$this->_default_where_conditions_strategy = new EE_Soft_Delete_Where_Conditions();
37
+		}
38
+		parent::__construct($timezone);
39
+	}
40
+
41
+
42
+
43
+	/**
44
+	 * Searches for field on this model of type 'deleted_flag'. if it is found,
45
+	 * returns it's name.
46
+	 *
47
+	 * @return string
48
+	 * @throws EE_Error
49
+	 */
50
+	public function deleted_field_name()
51
+	{
52
+		$field = $this->get_a_field_of_type('EE_Trashed_Flag_Field');
53
+		if ($field) {
54
+			return $field->get_name();
55
+		} else {
56
+			throw new EE_Error(sprintf(esc_html__(
57
+				'We are trying to find the deleted flag field on %s, but none was found. Are you sure there is a field of type EE_Trashed_Flag_Field in %s constructor?',
58
+				'event_espresso'
59
+			), get_class($this), get_class($this)));
60
+		}
61
+	}
62
+
63
+
64
+
65
+	/**
66
+	 * Gets one item that's been deleted, according to $query_params
67
+	 *
68
+	 * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
69
+	 * @return EE_Soft_Delete_Base_Class
70
+	 */
71
+	public function get_one_deleted($query_params = array())
72
+	{
73
+		$query_params = $this->_alter_query_params_so_only_trashed_items_included($query_params);
74
+		return parent::get_one($query_params);
75
+	}
76
+
77
+
78
+
79
+	/**
80
+	 * Gets one item from the DB, regardless of whether it's been soft-deleted or not
81
+	 *
82
+	 * @param array $query_params like EEM_base::get_all's $query_params
83
+	 * @return EE_Soft_Delete_Base_Class
84
+	 */
85
+	public function get_one_deleted_or_undeleted($query_params = array())
86
+	{
87
+		$query_params = $this->_alter_query_params_so_deleted_and_undeleted_items_included($query_params);
88
+		return parent::get_one($query_params);
89
+	}
90
+
91
+
92
+
93
+	/**
94
+	 * Gets the item indicated by its ID. But if it's soft-deleted, pretends it doesn't exist.
95
+	 *
96
+	 * @param int|string $id
97
+	 * @return EE_Soft_Delete_Base_Class
98
+	 */
99
+	public function get_one_by_ID_but_ignore_deleted($id)
100
+	{
101
+		return $this->get_one(
102
+			$this->alter_query_params_to_restrict_by_ID(
103
+				$id,
104
+				array('default_where_conditions' => 'default')
105
+			)
106
+		);
107
+	}
108
+
109
+
110
+
111
+	/**
112
+	 * Counts all the deleted/trashed items
113
+	 *
114
+	 * @param array  $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
115
+	 * @param string $field_to_count
116
+	 * @param bool   $distinct     if we want to only count the distinct values for the column then you can trigger that by the setting $distinct to TRUE;
117
+	 * @return int
118
+	 */
119
+	public function count_deleted($query_params = null, $field_to_count = null, $distinct = false)
120
+	{
121
+		$query_params = $this->_alter_query_params_so_only_trashed_items_included($query_params);
122
+		return parent::count($query_params, $field_to_count, $distinct);
123
+	}
124
+
125
+
126
+
127
+	/**
128
+	 * Alters the query params so that only trashed/soft-deleted items are considered
129
+	 *
130
+	 * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
131
+	 * @return array @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
132
+	 */
133
+	protected function _alter_query_params_so_only_trashed_items_included($query_params)
134
+	{
135
+		$deletedFlagFieldName = $this->deleted_field_name();
136
+		$query_params[0][ $deletedFlagFieldName ] = true;
137
+		return $query_params;
138
+	}
139
+
140
+
141
+
142
+	/**
143
+	 * Alters the query params so that only trashed/soft-deleted items are considered
144
+	 *
145
+	 * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
146
+	 * @return array @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
147
+	 */
148
+	public function alter_query_params_so_only_trashed_items_included($query_params)
149
+	{
150
+		return $this->_alter_query_params_so_only_trashed_items_included($query_params);
151
+	}
152
+
153
+
154
+
155
+	/**
156
+	 * Alters the query params so each item's deleted status is ignored.
157
+	 *
158
+	 * @param array $query_params
159
+	 * @return array
160
+	 */
161
+	public function alter_query_params_so_deleted_and_undeleted_items_included($query_params = array())
162
+	{
163
+		return $this->_alter_query_params_so_deleted_and_undeleted_items_included($query_params);
164
+	}
165
+
166
+
167
+
168
+	/**
169
+	 * Alters the query params so each item's deleted status is ignored.
170
+	 *
171
+	 * @param array $query_params
172
+	 * @return array
173
+	 */
174
+	protected function _alter_query_params_so_deleted_and_undeleted_items_included($query_params)
175
+	{
176
+		if (! isset($query_params['default_where_conditions'])) {
177
+			$query_params['default_where_conditions'] = 'minimum';
178
+		}
179
+		return $query_params;
180
+	}
181
+
182
+
183
+
184
+	/**
185
+	 * Counts all deleted and undeleted items
186
+	 *
187
+	 * @param array  $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
188
+	 * @param string $field_to_count
189
+	 * @param bool   $distinct     if we want to only count the distinct values for the column then you can trigger that by the setting $distinct to TRUE;
190
+	 * @return int
191
+	 */
192
+	public function count_deleted_and_undeleted($query_params = null, $field_to_count = null, $distinct = false)
193
+	{
194
+		$query_params = $this->_alter_query_params_so_deleted_and_undeleted_items_included($query_params);
195
+		return parent::count($query_params, $field_to_count, $distinct);
196
+	}
197
+
198
+
199
+
200
+	/**
201
+	 * Sum all the deleted items.
202
+	 *
203
+	 * @param array  $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
204
+	 * @param string $field_to_sum
205
+	 * @return int
206
+	 */
207
+	public function sum_deleted($query_params = null, $field_to_sum = null)
208
+	{
209
+		$query_params = $this->_alter_query_params_so_only_trashed_items_included($query_params);
210
+		return parent::sum($query_params, $field_to_sum);
211
+	}
212
+
213
+
214
+
215
+	/**
216
+	 * Sums all the deleted and undeleted items.
217
+	 *
218
+	 * @param array  $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
219
+	 * @param string $field_to_sum
220
+	 * @return int
221
+	 */
222
+	public function sum_deleted_and_undeleted($query_params = null, $field_to_sum = null)
223
+	{
224
+		$query_params = $this->_alter_query_params_so_deleted_and_undeleted_items_included($query_params);
225
+		parent::sum($query_params, $field_to_sum);
226
+	}
227
+
228
+
229
+
230
+	/**
231
+	 * Gets all deleted and undeleted mode objects from the db that meet the criteria, regardless of
232
+	 * whether they've been soft-deleted or not
233
+	 *
234
+	 * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
235
+	 * @return EE_Soft_Delete_Base_Class[]
236
+	 */
237
+	public function get_all_deleted_and_undeleted($query_params = array())
238
+	{
239
+		$query_params = $this->_alter_query_params_so_deleted_and_undeleted_items_included($query_params);
240
+		return parent::get_all($query_params);
241
+	}
242
+
243
+
244
+
245
+	/**
246
+	 * For 'soft deletable' models, gets all which ARE deleted, according to conditions specified in $query_params.
247
+	 *
248
+	 * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
249
+	 * @return EE_Soft_Delete_Base_Class[]
250
+	 */
251
+	public function get_all_deleted($query_params = array())
252
+	{
253
+		$query_params = $this->_alter_query_params_so_only_trashed_items_included($query_params);
254
+		return parent::get_all($query_params);
255
+	}
256
+
257
+
258
+
259
+	/**
260
+	 * Permanently deletes the selected rows. When selecting rows for deletion, ignores
261
+	 * whether they've been soft-deleted or not. (ie, you don't have to soft-delete objects
262
+	 * before you can permanently delete them).
263
+	 * Because this will cause a real deletion, related models may block this deletion (ie, add an error
264
+	 * and abort the delete)
265
+	 *
266
+	 * @param array   $query_params   @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
267
+	 * @param boolean $allow_blocking if TRUE, matched objects will only be deleted if there is no related model info
268
+	 *                                that blocks it (ie, there' sno other data that depends on this data); if false, deletes regardless of other objects
269
+	 *                                which may depend on it. Its generally advisable to always leave this as TRUE, otherwise you could easily corrupt your DB
270
+	 * @return int                    number of rows deleted
271
+	 * @throws EE_Error
272
+	 */
273
+	public function delete_permanently($query_params, $allow_blocking = true)
274
+	{
275
+		$query_params = $this->_alter_query_params_so_deleted_and_undeleted_items_included($query_params);
276
+		return parent::delete_permanently($query_params, $allow_blocking);
277
+	}
278
+
279
+
280
+
281
+	/**
282
+	 * Restores a particular item by its ID (primary key). Ignores the fact whether the item
283
+	 * has been soft-deleted or not.
284
+	 *
285
+	 * @param mixed $ID int if primary key is an int, string otherwise
286
+	 * @return boolean success
287
+	 */
288
+	public function restore_by_ID($ID = false)
289
+	{
290
+		return $this->delete_or_restore_by_ID(false, $ID);
291
+	}
292
+
293
+
294
+
295
+	/**
296
+	 * For deleting or restoring a particular item. Note that this model is a SOFT-DELETABLE model! However,
297
+	 * this function will ignore whether the items have been soft-deleted or not.
298
+	 *
299
+	 * @param boolean $delete true for delete, false for restore
300
+	 * @param mixed   $ID     int if primary key is an int, string otherwise
301
+	 * @return boolean
302
+	 */
303
+	public function delete_or_restore_by_ID($delete = true, $ID = false)
304
+	{
305
+		if (! $ID) {
306
+			return false;
307
+		}
308
+		if (
309
+			$this->delete_or_restore(
310
+				$delete,
311
+				$this->alter_query_params_to_restrict_by_ID($ID)
312
+			)
313
+		) {
314
+			return true;
315
+		} else {
316
+			return false;
317
+		}
318
+	}
319
+
320
+
321
+
322
+	/**
323
+	 * Overrides parent's 'delete' method to instead do a soft delete on all rows that
324
+	 * meet the criteria in $where_col_n_values. This particular function ignores whether the items have been soft-deleted or not.
325
+	 * Note: because this item will be soft-deleted only,
326
+	 * doesn't block because of model dependencies
327
+	 *
328
+	 * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
329
+	 * @param bool  $block_deletes
330
+	 * @return boolean
331
+	 */
332
+	public function delete($query_params = array(), $block_deletes = false)
333
+	{
334
+		// no matter what, we WON'T block soft deletes.
335
+		return $this->delete_or_restore(true, $query_params);
336
+	}
337
+
338
+
339
+
340
+	/**
341
+	 * 'Un-deletes' the chosen items. Note that this model is a SOFT-DELETABLE model! That means that, by default, trashed/soft-deleted
342
+	 * items are ignored in queries. However, this particular function ignores whether the items have been soft-deleted or not.
343
+	 *
344
+	 * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
345
+	 * @return boolean
346
+	 */
347
+	public function restore($query_params = array())
348
+	{
349
+		return $this->delete_or_restore(false, $query_params);
350
+	}
351
+
352
+
353
+
354
+	/**
355
+	 * Performs deletes or restores on items. Both soft-deleted and non-soft-deleted items considered.
356
+	 *
357
+	 * @param boolean $delete       true to indicate deletion, false to indicate restoration
358
+	 * @param array   $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
359
+	 * @return boolean
360
+	 */
361
+	public function delete_or_restore($delete = true, $query_params = array())
362
+	{
363
+		$deletedFlagFieldName = $this->deleted_field_name();
364
+		$query_params = $this->_alter_query_params_so_deleted_and_undeleted_items_included($query_params);
365
+		if ($this->update(array($deletedFlagFieldName => $delete), $query_params)) {
366
+			return true;
367
+		} else {
368
+			return false;
369
+		}
370
+	}
371
+
372
+
373
+
374
+	/**
375
+	 * Updates all the items of this model which match the $query params, regardless of whether
376
+	 * they've been soft-deleted or not
377
+	 *
378
+	 * @param array   $fields_n_values         like EEM_Base::update's $fields_n_value
379
+	 * @param array   $query_params            like EEM_base::get_all's $query_params
380
+	 * @param boolean $keep_model_objs_in_sync if TRUE, makes sure we ALSO update model objects
381
+	 *                                         in this model's entity map according to $fields_n_values that match $query_params. This
382
+	 *                                         obviously has some overhead, so you can disable it by setting this to FALSE, but
383
+	 *                                         be aware that model objects being used could get out-of-sync with the database
384
+	 * @return int number of items updated
385
+	 */
386
+	public function update_deleted_and_undeleted($fields_n_values, $query_params, $keep_model_objs_in_sync = true)
387
+	{
388
+		$query_params = $this->_alter_query_params_so_deleted_and_undeleted_items_included($query_params);
389
+		return $this->update($fields_n_values, $query_params, $keep_model_objs_in_sync);
390
+	}
391 391
 }
Please login to merge, or discard this patch.
admin_pages/events/Events_Admin_Page.core.php 2 patches
Indentation   +2674 added lines, -2674 removed lines patch added patch discarded remove patch
@@ -19,2678 +19,2678 @@
 block discarded – undo
19 19
 class Events_Admin_Page extends EE_Admin_Page_CPT
20 20
 {
21 21
 
22
-    /**
23
-     * This will hold the event object for event_details screen.
24
-     *
25
-     * @var EE_Event $_event
26
-     */
27
-    protected $_event;
28
-
29
-
30
-    /**
31
-     * This will hold the category object for category_details screen.
32
-     *
33
-     * @var stdClass $_category
34
-     */
35
-    protected $_category;
36
-
37
-
38
-    /**
39
-     * This will hold the event model instance
40
-     *
41
-     * @var EEM_Event $_event_model
42
-     */
43
-    protected $_event_model;
44
-
45
-
46
-    /**
47
-     * @var EE_Event
48
-     */
49
-    protected $_cpt_model_obj = false;
50
-
51
-
52
-    /**
53
-     * @var NodeGroupDao
54
-     */
55
-    protected $model_obj_node_group_persister;
56
-
57
-    /**
58
-     * Initialize page props for this admin page group.
59
-     */
60
-    protected function _init_page_props()
61
-    {
62
-        $this->page_slug = EVENTS_PG_SLUG;
63
-        $this->page_label = EVENTS_LABEL;
64
-        $this->_admin_base_url = EVENTS_ADMIN_URL;
65
-        $this->_admin_base_path = EVENTS_ADMIN;
66
-        $this->_cpt_model_names = array(
67
-            'create_new' => 'EEM_Event',
68
-            'edit'       => 'EEM_Event',
69
-        );
70
-        $this->_cpt_edit_routes = array(
71
-            'espresso_events' => 'edit',
72
-        );
73
-        add_action(
74
-            'AHEE__EE_Admin_Page_CPT__set_model_object__after_set_object',
75
-            array($this, 'verify_event_edit'),
76
-            10,
77
-            2
78
-        );
79
-    }
80
-
81
-
82
-    /**
83
-     * Sets the ajax hooks used for this admin page group.
84
-     */
85
-    protected function _ajax_hooks()
86
-    {
87
-        add_action('wp_ajax_ee_save_timezone_setting', array($this, 'save_timezonestring_setting'));
88
-    }
89
-
90
-
91
-    /**
92
-     * Sets the page properties for this admin page group.
93
-     */
94
-    protected function _define_page_props()
95
-    {
96
-        $this->_admin_page_title = EVENTS_LABEL;
97
-        $this->_labels = array(
98
-            'buttons'      => array(
99
-                'add'             => esc_html__('Add New Event', 'event_espresso'),
100
-                'edit'            => esc_html__('Edit Event', 'event_espresso'),
101
-                'delete'          => esc_html__('Delete Event', 'event_espresso'),
102
-                'add_category'    => esc_html__('Add New Category', 'event_espresso'),
103
-                'edit_category'   => esc_html__('Edit Category', 'event_espresso'),
104
-                'delete_category' => esc_html__('Delete Category', 'event_espresso'),
105
-            ),
106
-            'editor_title' => array(
107
-                'espresso_events' => esc_html__('Enter event title here', 'event_espresso'),
108
-            ),
109
-            'publishbox'   => array(
110
-                'create_new'        => esc_html__('Save New Event', 'event_espresso'),
111
-                'edit'              => esc_html__('Update Event', 'event_espresso'),
112
-                'add_category'      => esc_html__('Save New Category', 'event_espresso'),
113
-                'edit_category'     => esc_html__('Update Category', 'event_espresso'),
114
-                'template_settings' => esc_html__('Update Settings', 'event_espresso'),
115
-            ),
116
-        );
117
-    }
118
-
119
-
120
-    /**
121
-     * Sets the page routes property for this admin page group.
122
-     */
123
-    protected function _set_page_routes()
124
-    {
125
-        // load formatter helper
126
-        // load field generator helper
127
-        // is there a evt_id in the request?
128
-        $evt_id = ! empty($this->_req_data['EVT_ID']) && ! is_array($this->_req_data['EVT_ID'])
129
-            ? $this->_req_data['EVT_ID']
130
-            : 0;
131
-        $evt_id = ! empty($this->_req_data['post']) ? $this->_req_data['post'] : $evt_id;
132
-        $this->_page_routes = array(
133
-            'default'                       => array(
134
-                'func'       => '_events_overview_list_table',
135
-                'capability' => 'ee_read_events',
136
-            ),
137
-            'create_new'                    => array(
138
-                'func'       => '_create_new_cpt_item',
139
-                'capability' => 'ee_edit_events',
140
-            ),
141
-            'edit'                          => array(
142
-                'func'       => '_edit_cpt_item',
143
-                'capability' => 'ee_edit_event',
144
-                'obj_id'     => $evt_id,
145
-            ),
146
-            'copy_event'                    => array(
147
-                'func'       => '_copy_events',
148
-                'capability' => 'ee_edit_event',
149
-                'obj_id'     => $evt_id,
150
-                'noheader'   => true,
151
-            ),
152
-            'trash_event'                   => array(
153
-                'func'       => '_trash_or_restore_event',
154
-                'args'       => array('event_status' => 'trash'),
155
-                'capability' => 'ee_delete_event',
156
-                'obj_id'     => $evt_id,
157
-                'noheader'   => true,
158
-            ),
159
-            'trash_events'                  => array(
160
-                'func'       => '_trash_or_restore_events',
161
-                'args'       => array('event_status' => 'trash'),
162
-                'capability' => 'ee_delete_events',
163
-                'noheader'   => true,
164
-            ),
165
-            'restore_event'                 => array(
166
-                'func'       => '_trash_or_restore_event',
167
-                'args'       => array('event_status' => 'draft'),
168
-                'capability' => 'ee_delete_event',
169
-                'obj_id'     => $evt_id,
170
-                'noheader'   => true,
171
-            ),
172
-            'restore_events'                => array(
173
-                'func'       => '_trash_or_restore_events',
174
-                'args'       => array('event_status' => 'draft'),
175
-                'capability' => 'ee_delete_events',
176
-                'noheader'   => true,
177
-            ),
178
-            'delete_event'                  => array(
179
-                'func'       => '_delete_event',
180
-                'capability' => 'ee_delete_event',
181
-                'obj_id'     => $evt_id,
182
-                'noheader'   => true,
183
-            ),
184
-            'delete_events'                 => array(
185
-                'func'       => '_delete_events',
186
-                'capability' => 'ee_delete_events',
187
-                'noheader'   => true,
188
-            ),
189
-            'view_report'                   => array(
190
-                'func'      => '_view_report',
191
-                'capablity' => 'ee_edit_events',
192
-            ),
193
-            'default_event_settings'        => array(
194
-                'func'       => '_default_event_settings',
195
-                'capability' => 'manage_options',
196
-            ),
197
-            'update_default_event_settings' => array(
198
-                'func'       => '_update_default_event_settings',
199
-                'capability' => 'manage_options',
200
-                'noheader'   => true,
201
-            ),
202
-            'template_settings'             => array(
203
-                'func'       => '_template_settings',
204
-                'capability' => 'manage_options',
205
-            ),
206
-            // event category tab related
207
-            'add_category'                  => array(
208
-                'func'       => '_category_details',
209
-                'capability' => 'ee_edit_event_category',
210
-                'args'       => array('add'),
211
-            ),
212
-            'edit_category'                 => array(
213
-                'func'       => '_category_details',
214
-                'capability' => 'ee_edit_event_category',
215
-                'args'       => array('edit'),
216
-            ),
217
-            'delete_categories'             => array(
218
-                'func'       => '_delete_categories',
219
-                'capability' => 'ee_delete_event_category',
220
-                'noheader'   => true,
221
-            ),
222
-            'delete_category'               => array(
223
-                'func'       => '_delete_categories',
224
-                'capability' => 'ee_delete_event_category',
225
-                'noheader'   => true,
226
-            ),
227
-            'insert_category'               => array(
228
-                'func'       => '_insert_or_update_category',
229
-                'args'       => array('new_category' => true),
230
-                'capability' => 'ee_edit_event_category',
231
-                'noheader'   => true,
232
-            ),
233
-            'update_category'               => array(
234
-                'func'       => '_insert_or_update_category',
235
-                'args'       => array('new_category' => false),
236
-                'capability' => 'ee_edit_event_category',
237
-                'noheader'   => true,
238
-            ),
239
-            'category_list'                 => array(
240
-                'func'       => '_category_list_table',
241
-                'capability' => 'ee_manage_event_categories',
242
-            ),
243
-            'preview_deletion' => [
244
-                'func' => 'previewDeletion',
245
-                'capability' => 'ee_delete_events',
246
-            ],
247
-            'confirm_deletion' => [
248
-                'func' => 'confirmDeletion',
249
-                'capability' => 'ee_delete_events',
250
-                'noheader' => true,
251
-            ]
252
-        );
253
-    }
254
-
255
-
256
-    /**
257
-     * Set the _page_config property for this admin page group.
258
-     */
259
-    protected function _set_page_config()
260
-    {
261
-        $this->_page_config = array(
262
-            'default'                => array(
263
-                'nav'           => array(
264
-                    'label' => esc_html__('Overview', 'event_espresso'),
265
-                    'order' => 10,
266
-                ),
267
-                'list_table'    => 'Events_Admin_List_Table',
268
-                'help_tabs'     => array(
269
-                    'events_overview_help_tab'                       => array(
270
-                        'title'    => esc_html__('Events Overview', 'event_espresso'),
271
-                        'filename' => 'events_overview',
272
-                    ),
273
-                    'events_overview_table_column_headings_help_tab' => array(
274
-                        'title'    => esc_html__('Events Overview Table Column Headings', 'event_espresso'),
275
-                        'filename' => 'events_overview_table_column_headings',
276
-                    ),
277
-                    'events_overview_filters_help_tab'               => array(
278
-                        'title'    => esc_html__('Events Overview Filters', 'event_espresso'),
279
-                        'filename' => 'events_overview_filters',
280
-                    ),
281
-                    'events_overview_view_help_tab'                  => array(
282
-                        'title'    => esc_html__('Events Overview Views', 'event_espresso'),
283
-                        'filename' => 'events_overview_views',
284
-                    ),
285
-                    'events_overview_other_help_tab'                 => array(
286
-                        'title'    => esc_html__('Events Overview Other', 'event_espresso'),
287
-                        'filename' => 'events_overview_other',
288
-                    ),
289
-                ),
290
-                // disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
291
-                // 'help_tour'     => array(
292
-                //     'Event_Overview_Help_Tour',
293
-                //     // 'New_Features_Test_Help_Tour' for testing multiple help tour
294
-                // ),
295
-                'qtips'         => array(
296
-                    'EE_Event_List_Table_Tips',
297
-                ),
298
-                'require_nonce' => false,
299
-            ),
300
-            'create_new'             => array(
301
-                'nav'           => array(
302
-                    'label'      => esc_html__('Add Event', 'event_espresso'),
303
-                    'order'      => 5,
304
-                    'persistent' => false,
305
-                ),
306
-                'metaboxes'     => array('_register_event_editor_meta_boxes'),
307
-                'help_tabs'     => array(
308
-                    'event_editor_help_tab'                            => array(
309
-                        'title'    => esc_html__('Event Editor', 'event_espresso'),
310
-                        'filename' => 'event_editor',
311
-                    ),
312
-                    'event_editor_title_richtexteditor_help_tab'       => array(
313
-                        'title'    => esc_html__('Event Title & Rich Text Editor', 'event_espresso'),
314
-                        'filename' => 'event_editor_title_richtexteditor',
315
-                    ),
316
-                    'event_editor_venue_details_help_tab'              => array(
317
-                        'title'    => esc_html__('Event Venue Details', 'event_espresso'),
318
-                        'filename' => 'event_editor_venue_details',
319
-                    ),
320
-                    'event_editor_event_datetimes_help_tab'            => array(
321
-                        'title'    => esc_html__('Event Datetimes', 'event_espresso'),
322
-                        'filename' => 'event_editor_event_datetimes',
323
-                    ),
324
-                    'event_editor_event_tickets_help_tab'              => array(
325
-                        'title'    => esc_html__('Event Tickets', 'event_espresso'),
326
-                        'filename' => 'event_editor_event_tickets',
327
-                    ),
328
-                    'event_editor_event_registration_options_help_tab' => array(
329
-                        'title'    => esc_html__('Event Registration Options', 'event_espresso'),
330
-                        'filename' => 'event_editor_event_registration_options',
331
-                    ),
332
-                    'event_editor_tags_categories_help_tab'            => array(
333
-                        'title'    => esc_html__('Event Tags & Categories', 'event_espresso'),
334
-                        'filename' => 'event_editor_tags_categories',
335
-                    ),
336
-                    'event_editor_questions_registrants_help_tab'      => array(
337
-                        'title'    => esc_html__('Questions for Registrants', 'event_espresso'),
338
-                        'filename' => 'event_editor_questions_registrants',
339
-                    ),
340
-                    'event_editor_save_new_event_help_tab'             => array(
341
-                        'title'    => esc_html__('Save New Event', 'event_espresso'),
342
-                        'filename' => 'event_editor_save_new_event',
343
-                    ),
344
-                    'event_editor_other_help_tab'                      => array(
345
-                        'title'    => esc_html__('Event Other', 'event_espresso'),
346
-                        'filename' => 'event_editor_other',
347
-                    ),
348
-                ),
349
-                // disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
350
-                // 'help_tour'     => array(
351
-                //     'Event_Editor_Help_Tour',
352
-                // ),
353
-                'qtips'         => array('EE_Event_Editor_Decaf_Tips'),
354
-                'require_nonce' => false,
355
-            ),
356
-            'edit'                   => array(
357
-                'nav'           => array(
358
-                    'label'      => esc_html__('Edit Event', 'event_espresso'),
359
-                    'order'      => 5,
360
-                    'persistent' => false,
361
-                    'url'        => isset($this->_req_data['post'])
362
-                        ? EE_Admin_Page::add_query_args_and_nonce(
363
-                            array('post' => $this->_req_data['post'], 'action' => 'edit'),
364
-                            $this->_current_page_view_url
365
-                        )
366
-                        : $this->_admin_base_url,
367
-                ),
368
-                'metaboxes'     => array('_register_event_editor_meta_boxes'),
369
-                'help_tabs'     => array(
370
-                    'event_editor_help_tab'                            => array(
371
-                        'title'    => esc_html__('Event Editor', 'event_espresso'),
372
-                        'filename' => 'event_editor',
373
-                    ),
374
-                    'event_editor_title_richtexteditor_help_tab'       => array(
375
-                        'title'    => esc_html__('Event Title & Rich Text Editor', 'event_espresso'),
376
-                        'filename' => 'event_editor_title_richtexteditor',
377
-                    ),
378
-                    'event_editor_venue_details_help_tab'              => array(
379
-                        'title'    => esc_html__('Event Venue Details', 'event_espresso'),
380
-                        'filename' => 'event_editor_venue_details',
381
-                    ),
382
-                    'event_editor_event_datetimes_help_tab'            => array(
383
-                        'title'    => esc_html__('Event Datetimes', 'event_espresso'),
384
-                        'filename' => 'event_editor_event_datetimes',
385
-                    ),
386
-                    'event_editor_event_tickets_help_tab'              => array(
387
-                        'title'    => esc_html__('Event Tickets', 'event_espresso'),
388
-                        'filename' => 'event_editor_event_tickets',
389
-                    ),
390
-                    'event_editor_event_registration_options_help_tab' => array(
391
-                        'title'    => esc_html__('Event Registration Options', 'event_espresso'),
392
-                        'filename' => 'event_editor_event_registration_options',
393
-                    ),
394
-                    'event_editor_tags_categories_help_tab'            => array(
395
-                        'title'    => esc_html__('Event Tags & Categories', 'event_espresso'),
396
-                        'filename' => 'event_editor_tags_categories',
397
-                    ),
398
-                    'event_editor_questions_registrants_help_tab'      => array(
399
-                        'title'    => esc_html__('Questions for Registrants', 'event_espresso'),
400
-                        'filename' => 'event_editor_questions_registrants',
401
-                    ),
402
-                    'event_editor_save_new_event_help_tab'             => array(
403
-                        'title'    => esc_html__('Save New Event', 'event_espresso'),
404
-                        'filename' => 'event_editor_save_new_event',
405
-                    ),
406
-                    'event_editor_other_help_tab'                      => array(
407
-                        'title'    => esc_html__('Event Other', 'event_espresso'),
408
-                        'filename' => 'event_editor_other',
409
-                    ),
410
-                ),
411
-                'qtips'         => array('EE_Event_Editor_Decaf_Tips'),
412
-                'require_nonce' => false,
413
-            ),
414
-            'default_event_settings' => array(
415
-                'nav'           => array(
416
-                    'label' => esc_html__('Default Settings', 'event_espresso'),
417
-                    'order' => 40,
418
-                ),
419
-                'metaboxes'     => array_merge($this->_default_espresso_metaboxes, array('_publish_post_box')),
420
-                'labels'        => array(
421
-                    'publishbox' => esc_html__('Update Settings', 'event_espresso'),
422
-                ),
423
-                'help_tabs'     => array(
424
-                    'default_settings_help_tab'        => array(
425
-                        'title'    => esc_html__('Default Event Settings', 'event_espresso'),
426
-                        'filename' => 'events_default_settings',
427
-                    ),
428
-                    'default_settings_status_help_tab' => array(
429
-                        'title'    => esc_html__('Default Registration Status', 'event_espresso'),
430
-                        'filename' => 'events_default_settings_status',
431
-                    ),
432
-                    'default_maximum_tickets_help_tab' => array(
433
-                        'title'    => esc_html__('Default Maximum Tickets Per Order', 'event_espresso'),
434
-                        'filename' => 'events_default_settings_max_tickets',
435
-                    ),
436
-                ),
437
-                // disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
438
-                // 'help_tour'     => array('Event_Default_Settings_Help_Tour'),
439
-                'require_nonce' => false,
440
-            ),
441
-            // template settings
442
-            'template_settings'      => array(
443
-                'nav'           => array(
444
-                    'label' => esc_html__('Templates', 'event_espresso'),
445
-                    'order' => 30,
446
-                ),
447
-                'metaboxes'     => $this->_default_espresso_metaboxes,
448
-                'help_tabs'     => array(
449
-                    'general_settings_templates_help_tab' => array(
450
-                        'title'    => esc_html__('Templates', 'event_espresso'),
451
-                        'filename' => 'general_settings_templates',
452
-                    ),
453
-                ),
454
-                // disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
455
-                // 'help_tour'     => array('Templates_Help_Tour'),
456
-                'require_nonce' => false,
457
-            ),
458
-            // event category stuff
459
-            'add_category'           => array(
460
-                'nav'           => array(
461
-                    'label'      => esc_html__('Add Category', 'event_espresso'),
462
-                    'order'      => 15,
463
-                    'persistent' => false,
464
-                ),
465
-                'help_tabs'     => array(
466
-                    'add_category_help_tab' => array(
467
-                        'title'    => esc_html__('Add New Event Category', 'event_espresso'),
468
-                        'filename' => 'events_add_category',
469
-                    ),
470
-                ),
471
-                // disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
472
-                // 'help_tour'     => array('Event_Add_Category_Help_Tour'),
473
-                'metaboxes'     => array('_publish_post_box'),
474
-                'require_nonce' => false,
475
-            ),
476
-            'edit_category'          => array(
477
-                'nav'           => array(
478
-                    'label'      => esc_html__('Edit Category', 'event_espresso'),
479
-                    'order'      => 15,
480
-                    'persistent' => false,
481
-                    'url'        => isset($this->_req_data['EVT_CAT_ID'])
482
-                        ? add_query_arg(
483
-                            array('EVT_CAT_ID' => $this->_req_data['EVT_CAT_ID']),
484
-                            $this->_current_page_view_url
485
-                        )
486
-                        : $this->_admin_base_url,
487
-                ),
488
-                'help_tabs'     => array(
489
-                    'edit_category_help_tab' => array(
490
-                        'title'    => esc_html__('Edit Event Category', 'event_espresso'),
491
-                        'filename' => 'events_edit_category',
492
-                    ),
493
-                ),
494
-                /*'help_tour' => array('Event_Edit_Category_Help_Tour'),*/
495
-                'metaboxes'     => array('_publish_post_box'),
496
-                'require_nonce' => false,
497
-            ),
498
-            'category_list'          => array(
499
-                'nav'           => array(
500
-                    'label' => esc_html__('Categories', 'event_espresso'),
501
-                    'order' => 20,
502
-                ),
503
-                'list_table'    => 'Event_Categories_Admin_List_Table',
504
-                'help_tabs'     => array(
505
-                    'events_categories_help_tab'                       => array(
506
-                        'title'    => esc_html__('Event Categories', 'event_espresso'),
507
-                        'filename' => 'events_categories',
508
-                    ),
509
-                    'events_categories_table_column_headings_help_tab' => array(
510
-                        'title'    => esc_html__('Event Categories Table Column Headings', 'event_espresso'),
511
-                        'filename' => 'events_categories_table_column_headings',
512
-                    ),
513
-                    'events_categories_view_help_tab'                  => array(
514
-                        'title'    => esc_html__('Event Categories Views', 'event_espresso'),
515
-                        'filename' => 'events_categories_views',
516
-                    ),
517
-                    'events_categories_other_help_tab'                 => array(
518
-                        'title'    => esc_html__('Event Categories Other', 'event_espresso'),
519
-                        'filename' => 'events_categories_other',
520
-                    ),
521
-                ),
522
-                // disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
523
-                // 'help_tour'     => array(
524
-                //     'Event_Categories_Help_Tour',
525
-                // ),
526
-                'metaboxes'     => $this->_default_espresso_metaboxes,
527
-                'require_nonce' => false,
528
-            ),
529
-            'preview_deletion'           => array(
530
-                'nav'           => array(
531
-                    'label'      => esc_html__('Preview Deletion', 'event_espresso'),
532
-                    'order'      => 15,
533
-                    'persistent' => false,
534
-                    'url'        => '',
535
-                ),
536
-                'require_nonce' => false
537
-            )
538
-        );
539
-    }
540
-
541
-
542
-    /**
543
-     * Used to register any global screen options if necessary for every route in this admin page group.
544
-     */
545
-    protected function _add_screen_options()
546
-    {
547
-    }
548
-
549
-
550
-    /**
551
-     * Implementing the screen options for the 'default' route.
552
-     */
553
-    protected function _add_screen_options_default()
554
-    {
555
-        $this->_per_page_screen_option();
556
-    }
557
-
558
-
559
-    /**
560
-     * Implementing screen options for the category list route.
561
-     */
562
-    protected function _add_screen_options_category_list()
563
-    {
564
-        $page_title = $this->_admin_page_title;
565
-        $this->_admin_page_title = esc_html__('Categories', 'event_espresso');
566
-        $this->_per_page_screen_option();
567
-        $this->_admin_page_title = $page_title;
568
-    }
569
-
570
-
571
-    /**
572
-     * Used to register any global feature pointers for the admin page group.
573
-     */
574
-    protected function _add_feature_pointers()
575
-    {
576
-    }
577
-
578
-
579
-    /**
580
-     * Registers and enqueues any global scripts and styles for the entire admin page group.
581
-     */
582
-    public function load_scripts_styles()
583
-    {
584
-        wp_register_style(
585
-            'events-admin-css',
586
-            EVENTS_ASSETS_URL . 'events-admin-page.css',
587
-            array(),
588
-            EVENT_ESPRESSO_VERSION
589
-        );
590
-        wp_register_style('ee-cat-admin', EVENTS_ASSETS_URL . 'ee-cat-admin.css', array(), EVENT_ESPRESSO_VERSION);
591
-        wp_enqueue_style('events-admin-css');
592
-        wp_enqueue_style('ee-cat-admin');
593
-        // todo note: we also need to load_scripts_styles per view (i.e. default/view_report/event_details
594
-        // registers for all views
595
-        // scripts
596
-        wp_register_script(
597
-            'event_editor_js',
598
-            EVENTS_ASSETS_URL . 'event_editor.js',
599
-            array('ee_admin_js', 'jquery-ui-slider', 'jquery-ui-timepicker-addon'),
600
-            EVENT_ESPRESSO_VERSION,
601
-            true
602
-        );
603
-    }
604
-
605
-
606
-    /**
607
-     * Enqueuing scripts and styles specific to this view
608
-     */
609
-    public function load_scripts_styles_create_new()
610
-    {
611
-        $this->load_scripts_styles_edit();
612
-    }
613
-
614
-
615
-    /**
616
-     * Enqueuing scripts and styles specific to this view
617
-     */
618
-    public function load_scripts_styles_edit()
619
-    {
620
-        // styles
621
-        wp_enqueue_style('espresso-ui-theme');
622
-        wp_register_style(
623
-            'event-editor-css',
624
-            EVENTS_ASSETS_URL . 'event-editor.css',
625
-            array('ee-admin-css'),
626
-            EVENT_ESPRESSO_VERSION
627
-        );
628
-        wp_enqueue_style('event-editor-css');
629
-        // scripts
630
-        wp_register_script(
631
-            'event-datetime-metabox',
632
-            EVENTS_ASSETS_URL . 'event-datetime-metabox.js',
633
-            array('event_editor_js', 'ee-datepicker'),
634
-            EVENT_ESPRESSO_VERSION
635
-        );
636
-        wp_enqueue_script('event-datetime-metabox');
637
-    }
638
-
639
-
640
-    /**
641
-     * Populating the _views property for the category list table view.
642
-     */
643
-    protected function _set_list_table_views_category_list()
644
-    {
645
-        $this->_views = array(
646
-            'all' => array(
647
-                'slug'        => 'all',
648
-                'label'       => esc_html__('All', 'event_espresso'),
649
-                'count'       => 0,
650
-                'bulk_action' => array(
651
-                    'delete_categories' => esc_html__('Delete Permanently', 'event_espresso'),
652
-                ),
653
-            ),
654
-        );
655
-    }
656
-
657
-
658
-    /**
659
-     * For adding anything that fires on the admin_init hook for any route within this admin page group.
660
-     */
661
-    public function admin_init()
662
-    {
663
-        EE_Registry::$i18n_js_strings['image_confirm'] = esc_html__(
664
-            'Do you really want to delete this image? Please remember to update your event to complete the removal.',
665
-            'event_espresso'
666
-        );
667
-    }
668
-
669
-
670
-    /**
671
-     * For adding anything that should be triggered on the admin_notices hook for any route within this admin page
672
-     * group.
673
-     */
674
-    public function admin_notices()
675
-    {
676
-    }
677
-
678
-
679
-    /**
680
-     * For adding anything that should be triggered on the `admin_print_footer_scripts` hook for any route within
681
-     * this admin page group.
682
-     */
683
-    public function admin_footer_scripts()
684
-    {
685
-    }
686
-
687
-
688
-    /**
689
-     * Call this function to verify if an event is public and has tickets for sale.  If it does, then we need to show a
690
-     * warning (via EE_Error::add_error());
691
-     *
692
-     * @param  EE_Event $event Event object
693
-     * @param string    $req_type
694
-     * @return void
695
-     * @throws EE_Error
696
-     * @access public
697
-     */
698
-    public function verify_event_edit($event = null, $req_type = '')
699
-    {
700
-        // don't need to do this when processing
701
-        if (! empty($req_type)) {
702
-            return;
703
-        }
704
-        // no event?
705
-        if (empty($event)) {
706
-            // set event
707
-            $event = $this->_cpt_model_obj;
708
-        }
709
-        // STILL no event?
710
-        if (! $event instanceof EE_Event) {
711
-            return;
712
-        }
713
-        $orig_status = $event->status();
714
-        // first check if event is active.
715
-        if (
716
-            $orig_status === EEM_Event::cancelled
717
-            || $orig_status === EEM_Event::postponed
718
-            || $event->is_expired()
719
-            || $event->is_inactive()
720
-        ) {
721
-            return;
722
-        }
723
-        // made it here so it IS active... next check that any of the tickets are sold.
724
-        if ($event->is_sold_out(true)) {
725
-            if ($orig_status !== EEM_Event::sold_out && $event->status() !== $orig_status) {
726
-                EE_Error::add_attention(
727
-                    sprintf(
728
-                        esc_html__(
729
-                            'Please note that the Event Status has automatically been changed to %s because there are no more spaces available for this event.  However, this change is not permanent until you update the event.  You can change the status back to something else before updating if you wish.',
730
-                            'event_espresso'
731
-                        ),
732
-                        EEH_Template::pretty_status(EEM_Event::sold_out, false, 'sentence')
733
-                    )
734
-                );
735
-            }
736
-            return;
737
-        } elseif ($orig_status === EEM_Event::sold_out) {
738
-            EE_Error::add_attention(
739
-                sprintf(
740
-                    esc_html__(
741
-                        'Please note that the Event Status has automatically been changed to %s because more spaces have become available for this event, most likely due to abandoned transactions freeing up reserved tickets.  However, this change is not permanent until you update the event. If you wish, you can change the status back to something else before updating.',
742
-                        'event_espresso'
743
-                    ),
744
-                    EEH_Template::pretty_status($event->status(), false, 'sentence')
745
-                )
746
-            );
747
-        }
748
-        // now we need to determine if the event has any tickets on sale.  If not then we dont' show the error
749
-        if (! $event->tickets_on_sale()) {
750
-            return;
751
-        }
752
-        // made it here so show warning
753
-        $this->_edit_event_warning();
754
-    }
755
-
756
-
757
-    /**
758
-     * This is the text used for when an event is being edited that is public and has tickets for sale.
759
-     * When needed, hook this into a EE_Error::add_error() notice.
760
-     *
761
-     * @access protected
762
-     * @return void
763
-     */
764
-    protected function _edit_event_warning()
765
-    {
766
-        // we don't want to add warnings during these requests
767
-        if (isset($this->_req_data['action']) && $this->_req_data['action'] === 'editpost') {
768
-            return;
769
-        }
770
-        EE_Error::add_attention(
771
-            sprintf(
772
-                esc_html__(
773
-                    'Your event is open for registration. Making changes may disrupt any transactions in progress. %sLearn more%s',
774
-                    'event_espresso'
775
-                ),
776
-                '<a class="espresso-help-tab-lnk">',
777
-                '</a>'
778
-            )
779
-        );
780
-    }
781
-
782
-
783
-    /**
784
-     * When a user is creating a new event, notify them if they haven't set their timezone.
785
-     * Otherwise, do the normal logic
786
-     *
787
-     * @return string
788
-     * @throws \EE_Error
789
-     */
790
-    protected function _create_new_cpt_item()
791
-    {
792
-        $has_timezone_string = get_option('timezone_string');
793
-        // only nag them about setting their timezone if it's their first event, and they haven't already done it
794
-        if (! $has_timezone_string && ! EEM_Event::instance()->exists(array())) {
795
-            EE_Error::add_attention(
796
-                sprintf(
797
-                    esc_html__(
798
-                        'Your website\'s timezone is currently set to a UTC offset. We recommend updating your timezone to a city or region near you before you create an event. Change your timezone now:%1$s%2$s%3$sChange Timezone%4$s',
799
-                        'event_espresso'
800
-                    ),
801
-                    '<br>',
802
-                    '<select id="timezone_string" name="timezone_string" aria-describedby="timezone-description">'
803
-                    . EEH_DTT_Helper::wp_timezone_choice('', EEH_DTT_Helper::get_user_locale())
804
-                    . '</select>',
805
-                    '<button class="button button-secondary timezone-submit">',
806
-                    '</button><span class="spinner"></span>'
807
-                ),
808
-                __FILE__,
809
-                __FUNCTION__,
810
-                __LINE__
811
-            );
812
-        }
813
-        return parent::_create_new_cpt_item();
814
-    }
815
-
816
-
817
-    /**
818
-     * Sets the _views property for the default route in this admin page group.
819
-     */
820
-    protected function _set_list_table_views_default()
821
-    {
822
-        $this->_views = array(
823
-            'all'   => array(
824
-                'slug'        => 'all',
825
-                'label'       => esc_html__('View All Events', 'event_espresso'),
826
-                'count'       => 0,
827
-                'bulk_action' => array(
828
-                    'trash_events' => esc_html__('Move to Trash', 'event_espresso'),
829
-                ),
830
-            ),
831
-            'draft' => array(
832
-                'slug'        => 'draft',
833
-                'label'       => esc_html__('Draft', 'event_espresso'),
834
-                'count'       => 0,
835
-                'bulk_action' => array(
836
-                    'trash_events' => esc_html__('Move to Trash', 'event_espresso'),
837
-                ),
838
-            ),
839
-        );
840
-        if (EE_Registry::instance()->CAP->current_user_can('ee_delete_events', 'espresso_events_trash_events')) {
841
-            $this->_views['trash'] = array(
842
-                'slug'        => 'trash',
843
-                'label'       => esc_html__('Trash', 'event_espresso'),
844
-                'count'       => 0,
845
-                'bulk_action' => array(
846
-                    'restore_events' => esc_html__('Restore From Trash', 'event_espresso'),
847
-                    'delete_events'  => esc_html__('Delete Permanently', 'event_espresso'),
848
-                ),
849
-            );
850
-        }
851
-    }
852
-
853
-
854
-    /**
855
-     * Provides the legend item array for the default list table view.
856
-     *
857
-     * @return array
858
-     */
859
-    protected function _event_legend_items()
860
-    {
861
-        $items = array(
862
-            'view_details'   => array(
863
-                'class' => 'dashicons dashicons-search',
864
-                'desc'  => esc_html__('View Event', 'event_espresso'),
865
-            ),
866
-            'edit_event'     => array(
867
-                'class' => 'ee-icon ee-icon-calendar-edit',
868
-                'desc'  => esc_html__('Edit Event Details', 'event_espresso'),
869
-            ),
870
-            'view_attendees' => array(
871
-                'class' => 'dashicons dashicons-groups',
872
-                'desc'  => esc_html__('View Registrations for Event', 'event_espresso'),
873
-            ),
874
-        );
875
-        $items = apply_filters('FHEE__Events_Admin_Page___event_legend_items__items', $items);
876
-        $statuses = array(
877
-            'sold_out_status'  => array(
878
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::sold_out,
879
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::sold_out, false, 'sentence'),
880
-            ),
881
-            'active_status'    => array(
882
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::active,
883
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::active, false, 'sentence'),
884
-            ),
885
-            'upcoming_status'  => array(
886
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::upcoming,
887
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::upcoming, false, 'sentence'),
888
-            ),
889
-            'postponed_status' => array(
890
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::postponed,
891
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::postponed, false, 'sentence'),
892
-            ),
893
-            'cancelled_status' => array(
894
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::cancelled,
895
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::cancelled, false, 'sentence'),
896
-            ),
897
-            'expired_status'   => array(
898
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::expired,
899
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::expired, false, 'sentence'),
900
-            ),
901
-            'inactive_status'  => array(
902
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::inactive,
903
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::inactive, false, 'sentence'),
904
-            ),
905
-        );
906
-        $statuses = apply_filters('FHEE__Events_Admin_Page__event_legend_items__statuses', $statuses);
907
-        return array_merge($items, $statuses);
908
-    }
909
-
910
-
911
-    /**
912
-     * @return EEM_Event
913
-     */
914
-    private function _event_model()
915
-    {
916
-        if (! $this->_event_model instanceof EEM_Event) {
917
-            $this->_event_model = EE_Registry::instance()->load_model('Event');
918
-        }
919
-        return $this->_event_model;
920
-    }
921
-
922
-
923
-    /**
924
-     * Adds extra buttons to the WP CPT permalink field row.
925
-     * Method is called from parent and is hooked into the wp 'get_sample_permalink_html' filter.
926
-     *
927
-     * @param  string $return    the current html
928
-     * @param  int    $id        the post id for the page
929
-     * @param  string $new_title What the title is
930
-     * @param  string $new_slug  what the slug is
931
-     * @return string            The new html string for the permalink area
932
-     */
933
-    public function extra_permalink_field_buttons($return, $id, $new_title, $new_slug)
934
-    {
935
-        // make sure this is only when editing
936
-        if (! empty($id)) {
937
-            $post = get_post($id);
938
-            $return .= '<a class="button button-small" onclick="prompt(\'Shortcode:\', jQuery(\'#shortcode\').val()); return false;" href="#"  tabindex="-1">'
939
-                       . esc_html__('Shortcode', 'event_espresso')
940
-                       . '</a> ';
941
-            $return .= '<input id="shortcode" type="hidden" value="[ESPRESSO_TICKET_SELECTOR event_id='
942
-                       . $post->ID
943
-                       . ']">';
944
-        }
945
-        return $return;
946
-    }
947
-
948
-
949
-    /**
950
-     * _events_overview_list_table
951
-     * This contains the logic for showing the events_overview list
952
-     *
953
-     * @access protected
954
-     * @return void
955
-     * @throws \EE_Error
956
-     */
957
-    protected function _events_overview_list_table()
958
-    {
959
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
960
-        $this->_template_args['after_list_table'] = ! empty($this->_template_args['after_list_table'])
961
-            ? (array) $this->_template_args['after_list_table']
962
-            : array();
963
-        $this->_template_args['after_list_table']['view_event_list_button'] = EEH_HTML::br()
964
-                . EEH_Template::get_button_or_link(
965
-                    get_post_type_archive_link('espresso_events'),
966
-                    esc_html__("View Event Archive Page", "event_espresso"),
967
-                    'button'
968
-                );
969
-        $this->_template_args['after_list_table']['legend'] = $this->_display_legend($this->_event_legend_items());
970
-        $this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
971
-            'create_new',
972
-            'add',
973
-            array(),
974
-            'add-new-h2'
975
-        );
976
-        $this->display_admin_list_table_page_with_no_sidebar();
977
-    }
978
-
979
-
980
-    /**
981
-     * this allows for extra misc actions in the default WP publish box
982
-     *
983
-     * @return void
984
-     */
985
-    public function extra_misc_actions_publish_box()
986
-    {
987
-        $this->_generate_publish_box_extra_content();
988
-    }
989
-
990
-
991
-    /**
992
-     * This is hooked into the WordPress do_action('save_post') hook and runs after the custom post type has been
993
-     * saved.
994
-     * Typically you would use this to save any additional data.
995
-     * Keep in mind also that "save_post" runs on EVERY post update to the database.
996
-     * ALSO very important.  When a post transitions from scheduled to published,
997
-     * the save_post action is fired but you will NOT have any _POST data containing any extra info you may have from
998
-     * other meta saves. So MAKE sure that you handle this accordingly.
999
-     *
1000
-     * @access protected
1001
-     * @abstract
1002
-     * @param  string $post_id The ID of the cpt that was saved (so you can link relationally)
1003
-     * @param  object $post    The post object of the cpt that was saved.
1004
-     * @return void
1005
-     * @throws \EE_Error
1006
-     */
1007
-    protected function _insert_update_cpt_item($post_id, $post)
1008
-    {
1009
-        if ($post instanceof WP_Post && $post->post_type !== 'espresso_events') {
1010
-            // get out we're not processing an event save.
1011
-            return;
1012
-        }
1013
-        $event_values = array(
1014
-            'EVT_display_desc'                => ! empty($this->_req_data['display_desc']) ? 1 : 0,
1015
-            'EVT_display_ticket_selector'     => ! empty($this->_req_data['display_ticket_selector']) ? 1 : 0,
1016
-            'EVT_additional_limit'            => min(
1017
-                apply_filters('FHEE__EE_Events_Admin__insert_update_cpt_item__EVT_additional_limit_max', 255),
1018
-                ! empty($this->_req_data['additional_limit']) ? $this->_req_data['additional_limit'] : null
1019
-            ),
1020
-            'EVT_default_registration_status' => ! empty($this->_req_data['EVT_default_registration_status'])
1021
-                ? $this->_req_data['EVT_default_registration_status']
1022
-                : EE_Registry::instance()->CFG->registration->default_STS_ID,
1023
-            'EVT_member_only'                 => ! empty($this->_req_data['member_only']) ? 1 : 0,
1024
-            'EVT_allow_overflow'              => ! empty($this->_req_data['EVT_allow_overflow']) ? 1 : 0,
1025
-            'EVT_timezone_string'             => ! empty($this->_req_data['timezone_string'])
1026
-                ? $this->_req_data['timezone_string'] : null,
1027
-            'EVT_external_URL'                => ! empty($this->_req_data['externalURL'])
1028
-                ? $this->_req_data['externalURL'] : null,
1029
-            'EVT_phone'                       => ! empty($this->_req_data['event_phone'])
1030
-                ? $this->_req_data['event_phone'] : null,
1031
-        );
1032
-        // update event
1033
-        $success = $this->_event_model()->update_by_ID($event_values, $post_id);
1034
-        // get event_object for other metaboxes... though it would seem to make sense to just use $this->_event_model()->get_one_by_ID( $post_id ).. i have to setup where conditions to override the filters in the model that filter out autodraft and inherit statuses so we GET the inherit id!
1035
-        $get_one_where = array(
1036
-            $this->_event_model()->primary_key_name() => $post_id,
1037
-            'OR'                                      => array(
1038
-                'status'   => $post->post_status,
1039
-                // if trying to "Publish" a sold out event, it's status will get switched back to "sold_out" in the db,
1040
-                // but the returned object here has a status of "publish", so use the original post status as well
1041
-                'status*1' => $this->_req_data['original_post_status'],
1042
-            ),
1043
-        );
1044
-        $event = $this->_event_model()->get_one(array($get_one_where));
1045
-        // the following are default callbacks for event attachment updates that can be overridden by caffeinated functionality and/or addons.
1046
-        $event_update_callbacks = apply_filters(
1047
-            'FHEE__Events_Admin_Page___insert_update_cpt_item__event_update_callbacks',
1048
-            array(
1049
-                array($this, '_default_venue_update'),
1050
-                array($this, '_default_tickets_update'),
1051
-            )
1052
-        );
1053
-        $att_success = true;
1054
-        foreach ($event_update_callbacks as $e_callback) {
1055
-            $_success = is_callable($e_callback)
1056
-                ? call_user_func($e_callback, $event, $this->_req_data)
1057
-                : false;
1058
-            // if ANY of these updates fail then we want the appropriate global error message
1059
-            $att_success = ! $att_success ? $att_success : $_success;
1060
-        }
1061
-        // any errors?
1062
-        if ($success && false === $att_success) {
1063
-            EE_Error::add_error(
1064
-                esc_html__(
1065
-                    'Event Details saved successfully but something went wrong with saving attachments.',
1066
-                    'event_espresso'
1067
-                ),
1068
-                __FILE__,
1069
-                __FUNCTION__,
1070
-                __LINE__
1071
-            );
1072
-        } elseif ($success === false) {
1073
-            EE_Error::add_error(
1074
-                esc_html__('Event Details did not save successfully.', 'event_espresso'),
1075
-                __FILE__,
1076
-                __FUNCTION__,
1077
-                __LINE__
1078
-            );
1079
-        }
1080
-    }
1081
-
1082
-
1083
-    /**
1084
-     * @see parent::restore_item()
1085
-     * @param int $post_id
1086
-     * @param int $revision_id
1087
-     */
1088
-    protected function _restore_cpt_item($post_id, $revision_id)
1089
-    {
1090
-        // copy existing event meta to new post
1091
-        $post_evt = $this->_event_model()->get_one_by_ID($post_id);
1092
-        if ($post_evt instanceof EE_Event) {
1093
-            // meta revision restore
1094
-            $post_evt->restore_revision($revision_id);
1095
-            // related objs restore
1096
-            $post_evt->restore_revision($revision_id, array('Venue', 'Datetime', 'Price'));
1097
-        }
1098
-    }
1099
-
1100
-
1101
-    /**
1102
-     * Attach the venue to the Event
1103
-     *
1104
-     * @param  \EE_Event $evtobj Event Object to add the venue to
1105
-     * @param  array     $data   The request data from the form
1106
-     * @return bool           Success or fail.
1107
-     */
1108
-    protected function _default_venue_update(\EE_Event $evtobj, $data)
1109
-    {
1110
-        require_once(EE_MODELS . 'EEM_Venue.model.php');
1111
-        $venue_model = EE_Registry::instance()->load_model('Venue');
1112
-        $rows_affected = null;
1113
-        $venue_id = ! empty($data['venue_id']) ? $data['venue_id'] : null;
1114
-        // very important.  If we don't have a venue name...
1115
-        // then we'll get out because not necessary to create empty venue
1116
-        if (empty($data['venue_title'])) {
1117
-            return false;
1118
-        }
1119
-        $venue_array = array(
1120
-            'VNU_wp_user'         => $evtobj->get('EVT_wp_user'),
1121
-            'VNU_name'            => ! empty($data['venue_title']) ? $data['venue_title'] : null,
1122
-            'VNU_desc'            => ! empty($data['venue_description']) ? $data['venue_description'] : null,
1123
-            'VNU_identifier'      => ! empty($data['venue_identifier']) ? $data['venue_identifier'] : null,
1124
-            'VNU_short_desc'      => ! empty($data['venue_short_description']) ? $data['venue_short_description']
1125
-                : null,
1126
-            'VNU_address'         => ! empty($data['address']) ? $data['address'] : null,
1127
-            'VNU_address2'        => ! empty($data['address2']) ? $data['address2'] : null,
1128
-            'VNU_city'            => ! empty($data['city']) ? $data['city'] : null,
1129
-            'STA_ID'              => ! empty($data['state']) ? $data['state'] : null,
1130
-            'CNT_ISO'             => ! empty($data['countries']) ? $data['countries'] : null,
1131
-            'VNU_zip'             => ! empty($data['zip']) ? $data['zip'] : null,
1132
-            'VNU_phone'           => ! empty($data['venue_phone']) ? $data['venue_phone'] : null,
1133
-            'VNU_capacity'        => ! empty($data['venue_capacity']) ? $data['venue_capacity'] : null,
1134
-            'VNU_url'             => ! empty($data['venue_url']) ? $data['venue_url'] : null,
1135
-            'VNU_virtual_phone'   => ! empty($data['virtual_phone']) ? $data['virtual_phone'] : null,
1136
-            'VNU_virtual_url'     => ! empty($data['virtual_url']) ? $data['virtual_url'] : null,
1137
-            'VNU_enable_for_gmap' => isset($data['enable_for_gmap']) ? 1 : 0,
1138
-            'status'              => 'publish',
1139
-        );
1140
-        // if we've got the venue_id then we're just updating the existing venue so let's do that and then get out.
1141
-        if (! empty($venue_id)) {
1142
-            $update_where = array($venue_model->primary_key_name() => $venue_id);
1143
-            $rows_affected = $venue_model->update($venue_array, array($update_where));
1144
-            // we've gotta make sure that the venue is always attached to a revision.. add_relation_to should take care of making sure that the relation is already present.
1145
-            $evtobj->_add_relation_to($venue_id, 'Venue');
1146
-            return $rows_affected > 0 ? true : false;
1147
-        } else {
1148
-            // we insert the venue
1149
-            $venue_id = $venue_model->insert($venue_array);
1150
-            $evtobj->_add_relation_to($venue_id, 'Venue');
1151
-            return ! empty($venue_id) ? true : false;
1152
-        }
1153
-        // when we have the ancestor come in it's already been handled by the revision save.
1154
-    }
1155
-
1156
-
1157
-    /**
1158
-     * Handles saving everything related to Tickets (datetimes, tickets, prices)
1159
-     *
1160
-     * @param  EE_Event $evtobj The Event object we're attaching data to
1161
-     * @param  array    $data   The request data from the form
1162
-     * @return array
1163
-     */
1164
-    protected function _default_tickets_update(EE_Event $evtobj, $data)
1165
-    {
1166
-        $success = true;
1167
-        $saved_dtt = null;
1168
-        $saved_tickets = array();
1169
-        $incoming_date_formats = array('Y-m-d', 'h:i a');
1170
-        foreach ($data['edit_event_datetimes'] as $row => $dtt) {
1171
-            // trim all values to ensure any excess whitespace is removed.
1172
-            $dtt = array_map('trim', $dtt);
1173
-            $dtt['DTT_EVT_end'] = isset($dtt['DTT_EVT_end']) && ! empty($dtt['DTT_EVT_end']) ? $dtt['DTT_EVT_end']
1174
-                : $dtt['DTT_EVT_start'];
1175
-            $datetime_values = array(
1176
-                'DTT_ID'        => ! empty($dtt['DTT_ID']) ? $dtt['DTT_ID'] : null,
1177
-                'DTT_EVT_start' => $dtt['DTT_EVT_start'],
1178
-                'DTT_EVT_end'   => $dtt['DTT_EVT_end'],
1179
-                'DTT_reg_limit' => empty($dtt['DTT_reg_limit']) ? EE_INF : $dtt['DTT_reg_limit'],
1180
-                'DTT_order'     => $row,
1181
-            );
1182
-            // if we have an id then let's get existing object first and then set the new values.  Otherwise we instantiate a new object for save.
1183
-            if (! empty($dtt['DTT_ID'])) {
1184
-                $DTM = EE_Registry::instance()
1185
-                                  ->load_model('Datetime', array($evtobj->get_timezone()))
1186
-                                  ->get_one_by_ID($dtt['DTT_ID']);
1187
-                $DTM->set_date_format($incoming_date_formats[0]);
1188
-                $DTM->set_time_format($incoming_date_formats[1]);
1189
-                foreach ($datetime_values as $field => $value) {
1190
-                    $DTM->set($field, $value);
1191
-                }
1192
-                // make sure the $dtt_id here is saved just in case after the add_relation_to() the autosave replaces it.  We need to do this so we dont' TRASH the parent DTT.
1193
-                $saved_dtts[ $DTM->ID() ] = $DTM;
1194
-            } else {
1195
-                $DTM = EE_Registry::instance()->load_class(
1196
-                    'Datetime',
1197
-                    array($datetime_values, $evtobj->get_timezone(), $incoming_date_formats),
1198
-                    false,
1199
-                    false
1200
-                );
1201
-                foreach ($datetime_values as $field => $value) {
1202
-                    $DTM->set($field, $value);
1203
-                }
1204
-            }
1205
-            $DTM->save();
1206
-            $DTT = $evtobj->_add_relation_to($DTM, 'Datetime');
1207
-            // load DTT helper
1208
-            // before going any further make sure our dates are setup correctly so that the end date is always equal or greater than the start date.
1209
-            if ($DTT->get_raw('DTT_EVT_start') > $DTT->get_raw('DTT_EVT_end')) {
1210
-                $DTT->set('DTT_EVT_end', $DTT->get('DTT_EVT_start'));
1211
-                $DTT = EEH_DTT_Helper::date_time_add($DTT, 'DTT_EVT_end', 'days');
1212
-                $DTT->save();
1213
-            }
1214
-            // now we got to make sure we add the new DTT_ID to the $saved_dtts array  because it is possible there was a new one created for the autosave.
1215
-            $saved_dtt = $DTT;
1216
-            $success = ! $success ? $success : $DTT;
1217
-            // if ANY of these updates fail then we want the appropriate global error message.
1218
-            // //todo this is actually sucky we need a better error message but this is what it is for now.
1219
-        }
1220
-        // no dtts get deleted so we don't do any of that logic here.
1221
-        // update tickets next
1222
-        $old_tickets = isset($data['ticket_IDs']) ? explode(',', $data['ticket_IDs']) : array();
1223
-        foreach ($data['edit_tickets'] as $row => $tkt) {
1224
-            $incoming_date_formats = array('Y-m-d', 'h:i a');
1225
-            $update_prices = false;
1226
-            $ticket_price = isset($data['edit_prices'][ $row ][1]['PRC_amount'])
1227
-                ? $data['edit_prices'][ $row ][1]['PRC_amount'] : 0;
1228
-            // trim inputs to ensure any excess whitespace is removed.
1229
-            $tkt = array_map('trim', $tkt);
1230
-            if (empty($tkt['TKT_start_date'])) {
1231
-                // let's use now in the set timezone.
1232
-                $now = new DateTime('now', new DateTimeZone($evtobj->get_timezone()));
1233
-                $tkt['TKT_start_date'] = $now->format($incoming_date_formats[0] . ' ' . $incoming_date_formats[1]);
1234
-            }
1235
-            if (empty($tkt['TKT_end_date'])) {
1236
-                // use the start date of the first datetime
1237
-                $dtt = $evtobj->first_datetime();
1238
-                $tkt['TKT_end_date'] = $dtt->start_date_and_time(
1239
-                    $incoming_date_formats[0],
1240
-                    $incoming_date_formats[1]
1241
-                );
1242
-            }
1243
-            $TKT_values = array(
1244
-                'TKT_ID'          => ! empty($tkt['TKT_ID']) ? $tkt['TKT_ID'] : null,
1245
-                'TTM_ID'          => ! empty($tkt['TTM_ID']) ? $tkt['TTM_ID'] : 0,
1246
-                'TKT_name'        => ! empty($tkt['TKT_name']) ? $tkt['TKT_name'] : '',
1247
-                'TKT_description' => ! empty($tkt['TKT_description']) ? $tkt['TKT_description'] : '',
1248
-                'TKT_start_date'  => $tkt['TKT_start_date'],
1249
-                'TKT_end_date'    => $tkt['TKT_end_date'],
1250
-                'TKT_qty'         => ! isset($tkt['TKT_qty']) || $tkt['TKT_qty'] === '' ? EE_INF : $tkt['TKT_qty'],
1251
-                'TKT_uses'        => ! isset($tkt['TKT_uses']) || $tkt['TKT_uses'] === '' ? EE_INF : $tkt['TKT_uses'],
1252
-                'TKT_min'         => empty($tkt['TKT_min']) ? 0 : $tkt['TKT_min'],
1253
-                'TKT_max'         => empty($tkt['TKT_max']) ? EE_INF : $tkt['TKT_max'],
1254
-                'TKT_row'         => $row,
1255
-                'TKT_order'       => isset($tkt['TKT_order']) ? $tkt['TKT_order'] : $row,
1256
-                'TKT_price'       => $ticket_price,
1257
-            );
1258
-            // if this is a default TKT, then we need to set the TKT_ID to 0 and update accordingly, which means in turn that the prices will become new prices as well.
1259
-            if (isset($tkt['TKT_is_default']) && $tkt['TKT_is_default']) {
1260
-                $TKT_values['TKT_ID'] = 0;
1261
-                $TKT_values['TKT_is_default'] = 0;
1262
-                $TKT_values['TKT_price'] = $ticket_price;
1263
-                $update_prices = true;
1264
-            }
1265
-            // if we have a TKT_ID then we need to get that existing TKT_obj and update it
1266
-            // we actually do our saves a head of doing any add_relations to because its entirely possible that this ticket didn't removed or added to any datetime in the session but DID have it's items modified.
1267
-            // keep in mind that if the TKT has been sold (and we have changed pricing information), then we won't be updating the tkt but instead a new tkt will be created and the old one archived.
1268
-            if (! empty($tkt['TKT_ID'])) {
1269
-                $TKT = EE_Registry::instance()
1270
-                                  ->load_model('Ticket', array($evtobj->get_timezone()))
1271
-                                  ->get_one_by_ID($tkt['TKT_ID']);
1272
-                if ($TKT instanceof EE_Ticket) {
1273
-                    $ticket_sold = $TKT->count_related(
1274
-                        'Registration',
1275
-                        array(
1276
-                            array(
1277
-                                'STS_ID' => array(
1278
-                                    'NOT IN',
1279
-                                    array(EEM_Registration::status_id_incomplete),
1280
-                                ),
1281
-                            ),
1282
-                        )
1283
-                    ) > 0 ? true : false;
1284
-                    // let's just check the total price for the existing ticket and determine if it matches the new total price.  if they are different then we create a new ticket (if tkts sold) if they aren't different then we go ahead and modify existing ticket.
1285
-                    $create_new_TKT = $ticket_sold && $ticket_price != $TKT->get('TKT_price')
1286
-                                      && ! $TKT->get('TKT_deleted');
1287
-                    $TKT->set_date_format($incoming_date_formats[0]);
1288
-                    $TKT->set_time_format($incoming_date_formats[1]);
1289
-                    // set new values
1290
-                    foreach ($TKT_values as $field => $value) {
1291
-                        if ($field == 'TKT_qty') {
1292
-                            $TKT->set_qty($value);
1293
-                        } else {
1294
-                            $TKT->set($field, $value);
1295
-                        }
1296
-                    }
1297
-                    // if $create_new_TKT is false then we can safely update the existing ticket.  Otherwise we have to create a new ticket.
1298
-                    if ($create_new_TKT) {
1299
-                        // archive the old ticket first
1300
-                        $TKT->set('TKT_deleted', 1);
1301
-                        $TKT->save();
1302
-                        // make sure this ticket is still recorded in our saved_tkts so we don't run it through the regular trash routine.
1303
-                        $saved_tickets[ $TKT->ID() ] = $TKT;
1304
-                        // create new ticket that's a copy of the existing except a new id of course (and not archived) AND has the new TKT_price associated with it.
1305
-                        $TKT = clone $TKT;
1306
-                        $TKT->set('TKT_ID', 0);
1307
-                        $TKT->set('TKT_deleted', 0);
1308
-                        $TKT->set('TKT_price', $ticket_price);
1309
-                        $TKT->set('TKT_sold', 0);
1310
-                        // now we need to make sure that $new prices are created as well and attached to new ticket.
1311
-                        $update_prices = true;
1312
-                    }
1313
-                    // make sure price is set if it hasn't been already
1314
-                    $TKT->set('TKT_price', $ticket_price);
1315
-                }
1316
-            } else {
1317
-                // no TKT_id so a new TKT
1318
-                $TKT_values['TKT_price'] = $ticket_price;
1319
-                $TKT = EE_Registry::instance()->load_class('Ticket', array($TKT_values), false, false);
1320
-                if ($TKT instanceof EE_Ticket) {
1321
-                    // need to reset values to properly account for the date formats
1322
-                    $TKT->set_date_format($incoming_date_formats[0]);
1323
-                    $TKT->set_time_format($incoming_date_formats[1]);
1324
-                    $TKT->set_timezone($evtobj->get_timezone());
1325
-                    // set new values
1326
-                    foreach ($TKT_values as $field => $value) {
1327
-                        if ($field == 'TKT_qty') {
1328
-                            $TKT->set_qty($value);
1329
-                        } else {
1330
-                            $TKT->set($field, $value);
1331
-                        }
1332
-                    }
1333
-                    $update_prices = true;
1334
-                }
1335
-            }
1336
-            // cap ticket qty by datetime reg limits
1337
-            $TKT->set_qty(min($TKT->qty(), $TKT->qty('reg_limit')));
1338
-            // update ticket.
1339
-            $TKT->save();
1340
-            // before going any further make sure our dates are setup correctly so that the end date is always equal or greater than the start date.
1341
-            if ($TKT->get_raw('TKT_start_date') > $TKT->get_raw('TKT_end_date')) {
1342
-                $TKT->set('TKT_end_date', $TKT->get('TKT_start_date'));
1343
-                $TKT = EEH_DTT_Helper::date_time_add($TKT, 'TKT_end_date', 'days');
1344
-                $TKT->save();
1345
-            }
1346
-            // initially let's add the ticket to the dtt
1347
-            $saved_dtt->_add_relation_to($TKT, 'Ticket');
1348
-            $saved_tickets[ $TKT->ID() ] = $TKT;
1349
-            // add prices to ticket
1350
-            $this->_add_prices_to_ticket($data['edit_prices'][ $row ], $TKT, $update_prices);
1351
-        }
1352
-        // however now we need to handle permanently deleting tickets via the ui.  Keep in mind that the ui does not allow deleting/archiving tickets that have ticket sold.  However, it does allow for deleting tickets that have no tickets sold, in which case we want to get rid of permanently because there is no need to save in db.
1353
-        $old_tickets = isset($old_tickets[0]) && $old_tickets[0] == '' ? array() : $old_tickets;
1354
-        $tickets_removed = array_diff($old_tickets, array_keys($saved_tickets));
1355
-        foreach ($tickets_removed as $id) {
1356
-            $id = absint($id);
1357
-            // get the ticket for this id
1358
-            $tkt_to_remove = EE_Registry::instance()->load_model('Ticket')->get_one_by_ID($id);
1359
-            if (! $tkt_to_remove instanceof EE_Ticket) {
1360
-                continue;
1361
-            }
1362
-
1363
-            // need to get all the related datetimes on this ticket and remove from every single one of them (remember this process can ONLY kick off if there are NO tkts_sold)
1364
-            $dtts = $tkt_to_remove->get_many_related('Datetime');
1365
-            foreach ($dtts as $dtt) {
1366
-                $tkt_to_remove->_remove_relation_to($dtt, 'Datetime');
1367
-            }
1368
-            // need to do the same for prices (except these prices can also be deleted because again, tickets can only be trashed if they don't have any TKTs sold (otherwise they are just archived))
1369
-            $tkt_to_remove->delete_related_permanently('Price');
1370
-            // finally let's delete this ticket (which should not be blocked at this point b/c we've removed all our relationships)
1371
-            $tkt_to_remove->delete_permanently();
1372
-        }
1373
-        return array($saved_dtt, $saved_tickets);
1374
-    }
1375
-
1376
-
1377
-    /**
1378
-     * This attaches a list of given prices to a ticket.
1379
-     * Note we dont' have to worry about ever removing relationships (or archiving prices) because if there is a change
1380
-     * in price information on a ticket, a new ticket is created anyways so the archived ticket will retain the old
1381
-     * price info and prices are automatically "archived" via the ticket.
1382
-     *
1383
-     * @access  private
1384
-     * @param array     $prices     Array of prices from the form.
1385
-     * @param EE_Ticket $ticket     EE_Ticket object that prices are being attached to.
1386
-     * @param bool      $new_prices Whether attach existing incoming prices or create new ones.
1387
-     * @return  void
1388
-     */
1389
-    private function _add_prices_to_ticket($prices, EE_Ticket $ticket, $new_prices = false)
1390
-    {
1391
-        foreach ($prices as $row => $prc) {
1392
-            $PRC_values = array(
1393
-                'PRC_ID'         => ! empty($prc['PRC_ID']) ? $prc['PRC_ID'] : null,
1394
-                'PRT_ID'         => ! empty($prc['PRT_ID']) ? $prc['PRT_ID'] : null,
1395
-                'PRC_amount'     => ! empty($prc['PRC_amount']) ? $prc['PRC_amount'] : 0,
1396
-                'PRC_name'       => ! empty($prc['PRC_name']) ? $prc['PRC_name'] : '',
1397
-                'PRC_desc'       => ! empty($prc['PRC_desc']) ? $prc['PRC_desc'] : '',
1398
-                'PRC_is_default' => 0, // make sure prices are NOT set as default from this context
1399
-                'PRC_order'      => $row,
1400
-            );
1401
-            if ($new_prices || empty($PRC_values['PRC_ID'])) {
1402
-                $PRC_values['PRC_ID'] = 0;
1403
-                $PRC = EE_Registry::instance()->load_class('Price', array($PRC_values), false, false);
1404
-            } else {
1405
-                $PRC = EE_Registry::instance()->load_model('Price')->get_one_by_ID($prc['PRC_ID']);
1406
-                // update this price with new values
1407
-                foreach ($PRC_values as $field => $newprc) {
1408
-                    $PRC->set($field, $newprc);
1409
-                }
1410
-                $PRC->save();
1411
-            }
1412
-            $ticket->_add_relation_to($PRC, 'Price');
1413
-        }
1414
-    }
1415
-
1416
-
1417
-    /**
1418
-     * Add in our autosave ajax handlers
1419
-     *
1420
-     */
1421
-    protected function _ee_autosave_create_new()
1422
-    {
1423
-    }
1424
-
1425
-
1426
-    /**
1427
-     * More autosave handlers.
1428
-     */
1429
-    protected function _ee_autosave_edit()
1430
-    {
1431
-        return; // TEMPORARILY EXITING CAUSE THIS IS A TODO
1432
-    }
1433
-
1434
-
1435
-    /**
1436
-     *    _generate_publish_box_extra_content
1437
-     */
1438
-    private function _generate_publish_box_extra_content()
1439
-    {
1440
-        // load formatter helper
1441
-        // args for getting related registrations
1442
-        $approved_query_args = array(
1443
-            array(
1444
-                'REG_deleted' => 0,
1445
-                'STS_ID'      => EEM_Registration::status_id_approved,
1446
-            ),
1447
-        );
1448
-        $not_approved_query_args = array(
1449
-            array(
1450
-                'REG_deleted' => 0,
1451
-                'STS_ID'      => EEM_Registration::status_id_not_approved,
1452
-            ),
1453
-        );
1454
-        $pending_payment_query_args = array(
1455
-            array(
1456
-                'REG_deleted' => 0,
1457
-                'STS_ID'      => EEM_Registration::status_id_pending_payment,
1458
-            ),
1459
-        );
1460
-        // publish box
1461
-        $publish_box_extra_args = array(
1462
-            'view_approved_reg_url'        => add_query_arg(
1463
-                array(
1464
-                    'action'      => 'default',
1465
-                    'event_id'    => $this->_cpt_model_obj->ID(),
1466
-                    '_reg_status' => EEM_Registration::status_id_approved,
1467
-                ),
1468
-                REG_ADMIN_URL
1469
-            ),
1470
-            'view_not_approved_reg_url'    => add_query_arg(
1471
-                array(
1472
-                    'action'      => 'default',
1473
-                    'event_id'    => $this->_cpt_model_obj->ID(),
1474
-                    '_reg_status' => EEM_Registration::status_id_not_approved,
1475
-                ),
1476
-                REG_ADMIN_URL
1477
-            ),
1478
-            'view_pending_payment_reg_url' => add_query_arg(
1479
-                array(
1480
-                    'action'      => 'default',
1481
-                    'event_id'    => $this->_cpt_model_obj->ID(),
1482
-                    '_reg_status' => EEM_Registration::status_id_pending_payment,
1483
-                ),
1484
-                REG_ADMIN_URL
1485
-            ),
1486
-            'approved_regs'                => $this->_cpt_model_obj->count_related(
1487
-                'Registration',
1488
-                $approved_query_args
1489
-            ),
1490
-            'not_approved_regs'            => $this->_cpt_model_obj->count_related(
1491
-                'Registration',
1492
-                $not_approved_query_args
1493
-            ),
1494
-            'pending_payment_regs'         => $this->_cpt_model_obj->count_related(
1495
-                'Registration',
1496
-                $pending_payment_query_args
1497
-            ),
1498
-            'misc_pub_section_class'       => apply_filters(
1499
-                'FHEE_Events_Admin_Page___generate_publish_box_extra_content__misc_pub_section_class',
1500
-                'misc-pub-section'
1501
-            ),
1502
-        );
1503
-        ob_start();
1504
-        do_action(
1505
-            'AHEE__Events_Admin_Page___generate_publish_box_extra_content__event_editor_overview_add',
1506
-            $this->_cpt_model_obj
1507
-        );
1508
-        $publish_box_extra_args['event_editor_overview_add'] = ob_get_clean();
1509
-        // load template
1510
-        EEH_Template::display_template(
1511
-            EVENTS_TEMPLATE_PATH . 'event_publish_box_extras.template.php',
1512
-            $publish_box_extra_args
1513
-        );
1514
-    }
1515
-
1516
-
1517
-    /**
1518
-     * @return EE_Event
1519
-     */
1520
-    public function get_event_object()
1521
-    {
1522
-        return $this->_cpt_model_obj;
1523
-    }
1524
-
1525
-
1526
-
1527
-
1528
-    /** METABOXES * */
1529
-    /**
1530
-     * _register_event_editor_meta_boxes
1531
-     * add all metaboxes related to the event_editor
1532
-     *
1533
-     * @return void
1534
-     */
1535
-    protected function _register_event_editor_meta_boxes()
1536
-    {
1537
-        $this->verify_cpt_object();
1538
-        add_meta_box(
1539
-            'espresso_event_editor_tickets',
1540
-            esc_html__('Event Datetime & Ticket', 'event_espresso'),
1541
-            array($this, 'ticket_metabox'),
1542
-            $this->page_slug,
1543
-            'normal',
1544
-            'high'
1545
-        );
1546
-        add_meta_box(
1547
-            'espresso_event_editor_event_options',
1548
-            esc_html__('Event Registration Options', 'event_espresso'),
1549
-            array($this, 'registration_options_meta_box'),
1550
-            $this->page_slug,
1551
-            'side',
1552
-            'default'
1553
-        );
1554
-        // NOTE: if you're looking for other metaboxes in here,
1555
-        // where a metabox has a related management page in the admin
1556
-        // you will find it setup in the related management page's "_Hooks" file.
1557
-        // i.e. messages metabox is found in "espresso_events_Messages_Hooks.class.php".
1558
-    }
1559
-
1560
-
1561
-    /**
1562
-     * @throws DomainException
1563
-     * @throws EE_Error
1564
-     */
1565
-    public function ticket_metabox()
1566
-    {
1567
-        $existing_datetime_ids = $existing_ticket_ids = array();
1568
-        // defaults for template args
1569
-        $template_args = array(
1570
-            'existing_datetime_ids'    => '',
1571
-            'event_datetime_help_link' => '',
1572
-            'ticket_options_help_link' => '',
1573
-            'time'                     => null,
1574
-            'ticket_rows'              => '',
1575
-            'existing_ticket_ids'      => '',
1576
-            'total_ticket_rows'        => 1,
1577
-            'ticket_js_structure'      => '',
1578
-            'trash_icon'               => 'ee-lock-icon',
1579
-            'disabled'                 => '',
1580
-        );
1581
-        $event_id = is_object($this->_cpt_model_obj) ? $this->_cpt_model_obj->ID() : null;
1582
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1583
-        /**
1584
-         * 1. Start with retrieving Datetimes
1585
-         * 2. Fore each datetime get related tickets
1586
-         * 3. For each ticket get related prices
1587
-         */
1588
-        $times = EE_Registry::instance()->load_model('Datetime')->get_all_event_dates($event_id);
1589
-        /** @type EE_Datetime $first_datetime */
1590
-        $first_datetime = reset($times);
1591
-        // do we get related tickets?
1592
-        if (
1593
-            $first_datetime instanceof EE_Datetime
1594
-            && $first_datetime->ID() !== 0
1595
-        ) {
1596
-            $existing_datetime_ids[] = $first_datetime->get('DTT_ID');
1597
-            $template_args['time'] = $first_datetime;
1598
-            $related_tickets = $first_datetime->tickets(
1599
-                array(
1600
-                    array('OR' => array('TKT_deleted' => 1, 'TKT_deleted*' => 0)),
1601
-                    'default_where_conditions' => 'none',
1602
-                )
1603
-            );
1604
-            if (! empty($related_tickets)) {
1605
-                $template_args['total_ticket_rows'] = count($related_tickets);
1606
-                $row = 0;
1607
-                foreach ($related_tickets as $ticket) {
1608
-                    $existing_ticket_ids[] = $ticket->get('TKT_ID');
1609
-                    $template_args['ticket_rows'] .= $this->_get_ticket_row($ticket, false, $row);
1610
-                    $row++;
1611
-                }
1612
-            } else {
1613
-                $template_args['total_ticket_rows'] = 1;
1614
-                /** @type EE_Ticket $ticket */
1615
-                $ticket = EE_Registry::instance()->load_model('Ticket')->create_default_object();
1616
-                $template_args['ticket_rows'] .= $this->_get_ticket_row($ticket);
1617
-            }
1618
-        } else {
1619
-            $template_args['time'] = $times[0];
1620
-            /** @type EE_Ticket $ticket */
1621
-            $ticket = EE_Registry::instance()->load_model('Ticket')->get_all_default_tickets();
1622
-            $template_args['ticket_rows'] .= $this->_get_ticket_row($ticket[1]);
1623
-            // NOTE: we're just sending the first default row
1624
-            // (decaf can't manage default tickets so this should be sufficient);
1625
-        }
1626
-        $template_args['event_datetime_help_link'] = $this->_get_help_tab_link(
1627
-            'event_editor_event_datetimes_help_tab'
1628
-        );
1629
-        $template_args['ticket_options_help_link'] = $this->_get_help_tab_link('ticket_options_info');
1630
-        $template_args['existing_datetime_ids'] = implode(',', $existing_datetime_ids);
1631
-        $template_args['existing_ticket_ids'] = implode(',', $existing_ticket_ids);
1632
-        $template_args['ticket_js_structure'] = $this->_get_ticket_row(
1633
-            EE_Registry::instance()->load_model('Ticket')->create_default_object(),
1634
-            true
1635
-        );
1636
-        $template = apply_filters(
1637
-            'FHEE__Events_Admin_Page__ticket_metabox__template',
1638
-            EVENTS_TEMPLATE_PATH . 'event_tickets_metabox_main.template.php'
1639
-        );
1640
-        EEH_Template::display_template($template, $template_args);
1641
-    }
1642
-
1643
-
1644
-    /**
1645
-     * Setup an individual ticket form for the decaf event editor page
1646
-     *
1647
-     * @access private
1648
-     * @param  EE_Ticket $ticket   the ticket object
1649
-     * @param  boolean   $skeleton whether we're generating a skeleton for js manipulation
1650
-     * @param int        $row
1651
-     * @return string generated html for the ticket row.
1652
-     */
1653
-    private function _get_ticket_row($ticket, $skeleton = false, $row = 0)
1654
-    {
1655
-        $template_args = array(
1656
-            'tkt_status_class'    => ' tkt-status-' . $ticket->ticket_status(),
1657
-            'tkt_archive_class'   => $ticket->ticket_status() === EE_Ticket::archived && ! $skeleton ? ' tkt-archived'
1658
-                : '',
1659
-            'ticketrow'           => $skeleton ? 'TICKETNUM' : $row,
1660
-            'TKT_ID'              => $ticket->get('TKT_ID'),
1661
-            'TKT_name'            => $ticket->get('TKT_name'),
1662
-            'TKT_start_date'      => $skeleton ? '' : $ticket->get_date('TKT_start_date', 'Y-m-d h:i a'),
1663
-            'TKT_end_date'        => $skeleton ? '' : $ticket->get_date('TKT_end_date', 'Y-m-d h:i a'),
1664
-            'TKT_is_default'      => $ticket->get('TKT_is_default'),
1665
-            'TKT_qty'             => $ticket->get_pretty('TKT_qty', 'input'),
1666
-            'edit_ticketrow_name' => $skeleton ? 'TICKETNAMEATTR' : 'edit_tickets',
1667
-            'TKT_sold'            => $skeleton ? 0 : $ticket->get('TKT_sold'),
1668
-            'trash_icon'          => ($skeleton || (! empty($ticket) && ! $ticket->get('TKT_deleted')))
1669
-                                     && (! empty($ticket) && $ticket->get('TKT_sold') === 0)
1670
-                ? 'trash-icon dashicons dashicons-post-trash clickable' : 'ee-lock-icon',
1671
-            'disabled'            => $skeleton || (! empty($ticket) && ! $ticket->get('TKT_deleted')) ? ''
1672
-                : ' disabled=disabled',
1673
-        );
1674
-        $price = $ticket->ID() !== 0
1675
-            ? $ticket->get_first_related('Price', array('default_where_conditions' => 'none'))
1676
-            : null;
1677
-        $price = $price instanceof EE_Price
1678
-            ? $price
1679
-            : EEM_Price::instance()->create_default_object();
1680
-        $price_args = array(
1681
-            'price_currency_symbol' => EE_Registry::instance()->CFG->currency->sign,
1682
-            'PRC_amount'            => $price->get('PRC_amount'),
1683
-            'PRT_ID'                => $price->get('PRT_ID'),
1684
-            'PRC_ID'                => $price->get('PRC_ID'),
1685
-            'PRC_is_default'        => $price->get('PRC_is_default'),
1686
-        );
1687
-        // make sure we have default start and end dates if skeleton
1688
-        // handle rows that should NOT be empty
1689
-        if (empty($template_args['TKT_start_date'])) {
1690
-            // if empty then the start date will be now.
1691
-            $template_args['TKT_start_date'] = date('Y-m-d h:i a', current_time('timestamp'));
1692
-        }
1693
-        if (empty($template_args['TKT_end_date'])) {
1694
-            // get the earliest datetime (if present);
1695
-            $earliest_dtt = $this->_cpt_model_obj->ID() > 0
1696
-                ? $this->_cpt_model_obj->get_first_related(
1697
-                    'Datetime',
1698
-                    array('order_by' => array('DTT_EVT_start' => 'ASC'))
1699
-                )
1700
-                : null;
1701
-            if (! empty($earliest_dtt)) {
1702
-                $template_args['TKT_end_date'] = $earliest_dtt->get_datetime('DTT_EVT_start', 'Y-m-d', 'h:i a');
1703
-            } else {
1704
-                $template_args['TKT_end_date'] = date(
1705
-                    'Y-m-d h:i a',
1706
-                    mktime(0, 0, 0, date("m"), date("d") + 7, date("Y"))
1707
-                );
1708
-            }
1709
-        }
1710
-        $template_args = array_merge($template_args, $price_args);
1711
-        $template = apply_filters(
1712
-            'FHEE__Events_Admin_Page__get_ticket_row__template',
1713
-            EVENTS_TEMPLATE_PATH . 'event_tickets_metabox_ticket_row.template.php',
1714
-            $ticket
1715
-        );
1716
-        return EEH_Template::display_template($template, $template_args, true);
1717
-    }
1718
-
1719
-
1720
-    /**
1721
-     * @throws DomainException
1722
-     */
1723
-    public function registration_options_meta_box()
1724
-    {
1725
-        $yes_no_values = array(
1726
-            array('id' => true, 'text' => esc_html__('Yes', 'event_espresso')),
1727
-            array('id' => false, 'text' => esc_html__('No', 'event_espresso')),
1728
-        );
1729
-        $default_reg_status_values = EEM_Registration::reg_status_array(
1730
-            array(
1731
-                EEM_Registration::status_id_cancelled,
1732
-                EEM_Registration::status_id_declined,
1733
-                EEM_Registration::status_id_incomplete,
1734
-            ),
1735
-            true
1736
-        );
1737
-        // $template_args['is_active_select'] = EEH_Form_Fields::select_input('is_active', $yes_no_values, $this->_cpt_model_obj->is_active());
1738
-        $template_args['_event'] = $this->_cpt_model_obj;
1739
-        $template_args['event'] = $this->_cpt_model_obj;
1740
-        $template_args['active_status'] = $this->_cpt_model_obj->pretty_active_status(false);
1741
-        $template_args['additional_limit'] = $this->_cpt_model_obj->additional_limit();
1742
-        $template_args['default_registration_status'] = EEH_Form_Fields::select_input(
1743
-            'default_reg_status',
1744
-            $default_reg_status_values,
1745
-            $this->_cpt_model_obj->default_registration_status()
1746
-        );
1747
-        $template_args['display_description'] = EEH_Form_Fields::select_input(
1748
-            'display_desc',
1749
-            $yes_no_values,
1750
-            $this->_cpt_model_obj->display_description()
1751
-        );
1752
-        $template_args['display_ticket_selector'] = EEH_Form_Fields::select_input(
1753
-            'display_ticket_selector',
1754
-            $yes_no_values,
1755
-            $this->_cpt_model_obj->display_ticket_selector(),
1756
-            '',
1757
-            '',
1758
-            false
1759
-        );
1760
-        $template_args['additional_registration_options'] = apply_filters(
1761
-            'FHEE__Events_Admin_Page__registration_options_meta_box__additional_registration_options',
1762
-            '',
1763
-            $template_args,
1764
-            $yes_no_values,
1765
-            $default_reg_status_values
1766
-        );
1767
-        EEH_Template::display_template(
1768
-            EVENTS_TEMPLATE_PATH . 'event_registration_options.template.php',
1769
-            $template_args
1770
-        );
1771
-    }
1772
-
1773
-
1774
-    /**
1775
-     * _get_events()
1776
-     * This method simply returns all the events (for the given _view and paging)
1777
-     *
1778
-     * @access public
1779
-     * @param int  $per_page     count of items per page (20 default);
1780
-     * @param int  $current_page what is the current page being viewed.
1781
-     * @param bool $count        if TRUE then we just return a count of ALL events matching the given _view.
1782
-     *                           If FALSE then we return an array of event objects
1783
-     *                           that match the given _view and paging parameters.
1784
-     * @return array an array of event objects.
1785
-     */
1786
-    public function get_events($per_page = 10, $current_page = 1, $count = false)
1787
-    {
1788
-        $EEME = $this->_event_model();
1789
-        $offset = ($current_page - 1) * $per_page;
1790
-        $limit = $count ? null : $offset . ',' . $per_page;
1791
-        $orderby = isset($this->_req_data['orderby']) ? $this->_req_data['orderby'] : 'EVT_ID';
1792
-        $order = isset($this->_req_data['order']) ? $this->_req_data['order'] : "DESC";
1793
-        if (isset($this->_req_data['month_range'])) {
1794
-            $pieces = explode(' ', $this->_req_data['month_range'], 3);
1795
-            // simulate the FIRST day of the month, that fixes issues for months like February
1796
-            // where PHP doesn't know what to assume for date.
1797
-            // @see https://events.codebasehq.com/projects/event-espresso/tickets/10437
1798
-            $month_r = ! empty($pieces[0]) ? date('m', \EEH_DTT_Helper::first_of_month_timestamp($pieces[0])) : '';
1799
-            $year_r = ! empty($pieces[1]) ? $pieces[1] : '';
1800
-        }
1801
-        $where = array();
1802
-        $status = isset($this->_req_data['status']) ? $this->_req_data['status'] : null;
1803
-        // determine what post_status our condition will have for the query.
1804
-        switch ($status) {
1805
-            case 'month':
1806
-            case 'today':
1807
-            case null:
1808
-            case 'all':
1809
-                break;
1810
-            case 'draft':
1811
-                $where['status'] = array('IN', array('draft', 'auto-draft'));
1812
-                break;
1813
-            default:
1814
-                $where['status'] = $status;
1815
-        }
1816
-        // categories?
1817
-        $category = isset($this->_req_data['EVT_CAT']) && $this->_req_data['EVT_CAT'] > 0
1818
-            ? $this->_req_data['EVT_CAT'] : null;
1819
-        if (! empty($category)) {
1820
-            $where['Term_Taxonomy.taxonomy'] = EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY;
1821
-            $where['Term_Taxonomy.term_id'] = $category;
1822
-        }
1823
-        // date where conditions
1824
-        $start_formats = EEM_Datetime::instance()->get_formats_for('DTT_EVT_start');
1825
-        if (isset($this->_req_data['month_range']) && $this->_req_data['month_range'] != '') {
1826
-            $DateTime = new DateTime(
1827
-                $year_r . '-' . $month_r . '-01 00:00:00',
1828
-                new DateTimeZone('UTC')
1829
-            );
1830
-            $start = $DateTime->getTimestamp();
1831
-            // set the datetime to be the end of the month
1832
-            $DateTime->setDate(
1833
-                $year_r,
1834
-                $month_r,
1835
-                $DateTime->format('t')
1836
-            )->setTime(23, 59, 59);
1837
-            $end = $DateTime->getTimestamp();
1838
-            $where['Datetime.DTT_EVT_start'] = array('BETWEEN', array($start, $end));
1839
-        } elseif (isset($this->_req_data['status']) && $this->_req_data['status'] == 'today') {
1840
-            $DateTime = new DateTime('now', new DateTimeZone(EEM_Event::instance()->get_timezone()));
1841
-            $start = $DateTime->setTime(0, 0, 0)->format(implode(' ', $start_formats));
1842
-            $end = $DateTime->setTime(23, 59, 59)->format(implode(' ', $start_formats));
1843
-            $where['Datetime.DTT_EVT_start'] = array('BETWEEN', array($start, $end));
1844
-        } elseif (isset($this->_req_data['status']) && $this->_req_data['status'] == 'month') {
1845
-            $now = date('Y-m-01');
1846
-            $DateTime = new DateTime($now, new DateTimeZone(EEM_Event::instance()->get_timezone()));
1847
-            $start = $DateTime->setTime(0, 0, 0)->format(implode(' ', $start_formats));
1848
-            $end = $DateTime->setDate(date('Y'), date('m'), $DateTime->format('t'))
1849
-                            ->setTime(23, 59, 59)
1850
-                            ->format(implode(' ', $start_formats));
1851
-            $where['Datetime.DTT_EVT_start'] = array('BETWEEN', array($start, $end));
1852
-        }
1853
-        if (! EE_Registry::instance()->CAP->current_user_can('ee_read_others_events', 'get_events')) {
1854
-            $where['EVT_wp_user'] = get_current_user_id();
1855
-        } else {
1856
-            if (! isset($where['status'])) {
1857
-                if (! EE_Registry::instance()->CAP->current_user_can('ee_read_private_events', 'get_events')) {
1858
-                    $where['OR'] = array(
1859
-                        'status*restrict_private' => array('!=', 'private'),
1860
-                        'AND'                     => array(
1861
-                            'status*inclusive' => array('=', 'private'),
1862
-                            'EVT_wp_user'      => get_current_user_id(),
1863
-                        ),
1864
-                    );
1865
-                }
1866
-            }
1867
-        }
1868
-        if (isset($this->_req_data['EVT_wp_user'])) {
1869
-            if (
1870
-                $this->_req_data['EVT_wp_user'] != get_current_user_id()
1871
-                && EE_Registry::instance()->CAP->current_user_can('ee_read_others_events', 'get_events')
1872
-            ) {
1873
-                $where['EVT_wp_user'] = $this->_req_data['EVT_wp_user'];
1874
-            }
1875
-        }
1876
-        // search query handling
1877
-        if (isset($this->_req_data['s'])) {
1878
-            $search_string = '%' . $this->_req_data['s'] . '%';
1879
-            $where['OR'] = array(
1880
-                'EVT_name'       => array('LIKE', $search_string),
1881
-                'EVT_desc'       => array('LIKE', $search_string),
1882
-                'EVT_short_desc' => array('LIKE', $search_string),
1883
-            );
1884
-        }
1885
-        // filter events by venue.
1886
-        if (isset($this->_req_data['venue']) && ! empty($this->_req_data['venue'])) {
1887
-            $where['Venue.VNU_ID'] = absint($this->_req_data['venue']);
1888
-        }
1889
-        $where = apply_filters('FHEE__Events_Admin_Page__get_events__where', $where, $this->_req_data);
1890
-        $query_params = apply_filters(
1891
-            'FHEE__Events_Admin_Page__get_events__query_params',
1892
-            array(
1893
-                $where,
1894
-                'limit'    => $limit,
1895
-                'order_by' => $orderby,
1896
-                'order'    => $order,
1897
-                'group_by' => 'EVT_ID',
1898
-            ),
1899
-            $this->_req_data
1900
-        );
1901
-
1902
-        // let's first check if we have special requests coming in.
1903
-        if (isset($this->_req_data['active_status'])) {
1904
-            switch ($this->_req_data['active_status']) {
1905
-                case 'upcoming':
1906
-                    return $EEME->get_upcoming_events($query_params, $count);
1907
-                    break;
1908
-                case 'expired':
1909
-                    return $EEME->get_expired_events($query_params, $count);
1910
-                    break;
1911
-                case 'active':
1912
-                    return $EEME->get_active_events($query_params, $count);
1913
-                    break;
1914
-                case 'inactive':
1915
-                    return $EEME->get_inactive_events($query_params, $count);
1916
-                    break;
1917
-            }
1918
-        }
1919
-
1920
-        $events = $count ? $EEME->count(array($where), 'EVT_ID', true) : $EEME->get_all($query_params);
1921
-        return $events;
1922
-    }
1923
-
1924
-
1925
-    /**
1926
-     * handling for WordPress CPT actions (trash, restore, delete)
1927
-     *
1928
-     * @param string $post_id
1929
-     */
1930
-    public function trash_cpt_item($post_id)
1931
-    {
1932
-        $this->_req_data['EVT_ID'] = $post_id;
1933
-        $this->_trash_or_restore_event('trash', false);
1934
-    }
1935
-
1936
-
1937
-    /**
1938
-     * @param string $post_id
1939
-     */
1940
-    public function restore_cpt_item($post_id)
1941
-    {
1942
-        $this->_req_data['EVT_ID'] = $post_id;
1943
-        $this->_trash_or_restore_event('draft', false);
1944
-    }
1945
-
1946
-
1947
-    /**
1948
-     * @param string $post_id
1949
-     */
1950
-    public function delete_cpt_item($post_id)
1951
-    {
1952
-        throw new EE_Error(esc_html__('Please contact Event Espresso support with the details of the steps taken to produce this error.', 'event_espresso'));
1953
-        $this->_req_data['EVT_ID'] = $post_id;
1954
-        $this->_delete_event();
1955
-    }
1956
-
1957
-
1958
-    /**
1959
-     * _trash_or_restore_event
1960
-     *
1961
-     * @access protected
1962
-     * @param  string $event_status
1963
-     * @param bool    $redirect_after
1964
-     */
1965
-    protected function _trash_or_restore_event($event_status = 'trash', $redirect_after = true)
1966
-    {
1967
-        // determine the event id and set to array.
1968
-        $EVT_ID = isset($this->_req_data['EVT_ID']) ? absint($this->_req_data['EVT_ID']) : false;
1969
-        // loop thru events
1970
-        if ($EVT_ID) {
1971
-            // clean status
1972
-            $event_status = sanitize_key($event_status);
1973
-            // grab status
1974
-            if (! empty($event_status)) {
1975
-                $success = $this->_change_event_status($EVT_ID, $event_status);
1976
-            } else {
1977
-                $success = false;
1978
-                $msg = esc_html__(
1979
-                    'An error occurred. The event could not be moved to the trash because a valid event status was not not supplied.',
1980
-                    'event_espresso'
1981
-                );
1982
-                EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1983
-            }
1984
-        } else {
1985
-            $success = false;
1986
-            $msg = esc_html__(
1987
-                'An error occurred. The event could not be moved to the trash because a valid event ID was not not supplied.',
1988
-                'event_espresso'
1989
-            );
1990
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1991
-        }
1992
-        $action = $event_status == 'trash' ? 'moved to the trash' : 'restored from the trash';
1993
-        if ($redirect_after) {
1994
-            $this->_redirect_after_action($success, 'Event', $action, array('action' => 'default'));
1995
-        }
1996
-    }
1997
-
1998
-
1999
-    /**
2000
-     * _trash_or_restore_events
2001
-     *
2002
-     * @access protected
2003
-     * @param  string $event_status
2004
-     * @return void
2005
-     */
2006
-    protected function _trash_or_restore_events($event_status = 'trash')
2007
-    {
2008
-        // clean status
2009
-        $event_status = sanitize_key($event_status);
2010
-        // grab status
2011
-        if (! empty($event_status)) {
2012
-            $success = true;
2013
-            // determine the event id and set to array.
2014
-            $EVT_IDs = isset($this->_req_data['EVT_IDs']) ? (array) $this->_req_data['EVT_IDs'] : array();
2015
-            // loop thru events
2016
-            foreach ($EVT_IDs as $EVT_ID) {
2017
-                if ($EVT_ID = absint($EVT_ID)) {
2018
-                    $results = $this->_change_event_status($EVT_ID, $event_status);
2019
-                    $success = $results !== false ? $success : false;
2020
-                } else {
2021
-                    $msg = sprintf(
2022
-                        esc_html__(
2023
-                            'An error occurred. Event #%d could not be moved to the trash because a valid event ID was not not supplied.',
2024
-                            'event_espresso'
2025
-                        ),
2026
-                        $EVT_ID
2027
-                    );
2028
-                    EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2029
-                    $success = false;
2030
-                }
2031
-            }
2032
-        } else {
2033
-            $success = false;
2034
-            $msg = esc_html__(
2035
-                'An error occurred. The event could not be moved to the trash because a valid event status was not not supplied.',
2036
-                'event_espresso'
2037
-            );
2038
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2039
-        }
2040
-        // in order to force a pluralized result message we need to send back a success status greater than 1
2041
-        $success = $success ? 2 : false;
2042
-        $action = $event_status == 'trash' ? 'moved to the trash' : 'restored from the trash';
2043
-        $this->_redirect_after_action($success, 'Events', $action, array('action' => 'default'));
2044
-    }
2045
-
2046
-
2047
-    /**
2048
-     * @param  int    $EVT_ID
2049
-     * @param  string $event_status
2050
-     * @return bool
2051
-     */
2052
-    private function _change_event_status($EVT_ID = 0, $event_status = '')
2053
-    {
2054
-        // grab event id
2055
-        if (! $EVT_ID) {
2056
-            $msg = esc_html__(
2057
-                'An error occurred. No Event ID or an invalid Event ID was received.',
2058
-                'event_espresso'
2059
-            );
2060
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2061
-            return false;
2062
-        }
2063
-        $this->_cpt_model_obj = EEM_Event::instance()->get_one_by_ID($EVT_ID);
2064
-        // clean status
2065
-        $event_status = sanitize_key($event_status);
2066
-        // grab status
2067
-        if (empty($event_status)) {
2068
-            $msg = esc_html__(
2069
-                'An error occurred. No Event Status or an invalid Event Status was received.',
2070
-                'event_espresso'
2071
-            );
2072
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2073
-            return false;
2074
-        }
2075
-        // was event trashed or restored ?
2076
-        switch ($event_status) {
2077
-            case 'draft':
2078
-                $action = 'restored from the trash';
2079
-                $hook = 'AHEE_event_restored_from_trash';
2080
-                break;
2081
-            case 'trash':
2082
-                $action = 'moved to the trash';
2083
-                $hook = 'AHEE_event_moved_to_trash';
2084
-                break;
2085
-            default:
2086
-                $action = 'updated';
2087
-                $hook = false;
2088
-        }
2089
-        // use class to change status
2090
-        $this->_cpt_model_obj->set_status($event_status);
2091
-        $success = $this->_cpt_model_obj->save();
2092
-        if (! $success) {
2093
-            $msg = sprintf(esc_html__('An error occurred. The event could not be %s.', 'event_espresso'), $action);
2094
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2095
-            return false;
2096
-        }
2097
-        if ($hook) {
2098
-            do_action($hook);
2099
-        }
2100
-        return true;
2101
-    }
2102
-
2103
-
2104
-    /**
2105
-     * @param array $event_ids
2106
-     * @return array
2107
-     * @since   $VID:$
2108
-     */
2109
-    private function cleanEventIds(array $event_ids)
2110
-    {
2111
-        return array_map('absint', $event_ids);
2112
-    }
2113
-
2114
-
2115
-    /**
2116
-     * @return array
2117
-     * @since   $VID:$
2118
-     */
2119
-    private function getEventIdsFromRequest()
2120
-    {
2121
-        $event_ids = isset($this->_req_data['EVT_ID']) ? $this->_req_data['EVT_ID'] : [];
2122
-        $event_ids = is_string($event_ids) ? explode(',', $event_ids) : (array) $event_ids;
2123
-        return $this->cleanEventIds($event_ids);
2124
-    }
2125
-
2126
-
2127
-    /**
2128
-     * @param bool $preview_delete
2129
-     * @throws EE_Error
2130
-     */
2131
-    protected function _delete_event($preview_delete = true)
2132
-    {
2133
-        $this->_delete_events($preview_delete);
2134
-    }
2135
-
2136
-
2137
-    /**
2138
-     * Gets the tree traversal batch persister.
2139
-     * @since 4.10.12.p
2140
-     * @return NodeGroupDao
2141
-     * @throws InvalidArgumentException
2142
-     * @throws InvalidDataTypeException
2143
-     * @throws InvalidInterfaceException
2144
-     */
2145
-    protected function getModelObjNodeGroupPersister()
2146
-    {
2147
-        if (! $this->model_obj_node_group_persister instanceof NodeGroupDao) {
2148
-            $this->model_obj_node_group_persister = $this->getLoader()->load('\EventEspresso\core\services\orm\tree_traversal\NodeGroupDao');
2149
-        }
2150
-        return $this->model_obj_node_group_persister;
2151
-    }
2152
-
2153
-
2154
-    /**
2155
-     * @param bool $preview_delete
2156
-     * @return void
2157
-     * @throws EE_Error
2158
-     */
2159
-    protected function _delete_events($preview_delete = true)
2160
-    {
2161
-        $event_ids = $this->getEventIdsFromRequest();
2162
-        if ($preview_delete) {
2163
-            $this->generateDeletionPreview($event_ids);
2164
-        } else {
2165
-            EEM_Event::instance()->delete_permanently([['EVT_ID' => ['IN', $event_ids]]]);
2166
-        }
2167
-    }
2168
-
2169
-
2170
-    /**
2171
-     * @param array $event_ids
2172
-     */
2173
-    protected function generateDeletionPreview(array $event_ids)
2174
-    {
2175
-        $event_ids = $this->cleanEventIds($event_ids);
2176
-        // Set a code we can use to reference this deletion task in the batch jobs and preview page.
2177
-        $deletion_job_code = $this->getModelObjNodeGroupPersister()->generateGroupCode();
2178
-        $return_url = EE_Admin_Page::add_query_args_and_nonce(
2179
-            [
2180
-                'action' => 'preview_deletion',
2181
-                'deletion_job_code' => $deletion_job_code,
2182
-            ],
2183
-            $this->_admin_base_url
2184
-        );
2185
-        EEH_URL::safeRedirectAndExit(
2186
-            EE_Admin_Page::add_query_args_and_nonce(
2187
-                [
2188
-                    'page'              => 'espresso_batch',
2189
-                    'batch'             => EED_Batch::batch_job,
2190
-                    'EVT_IDs'           => $event_ids,
2191
-                    'deletion_job_code' => $deletion_job_code,
2192
-                    'job_handler'       => urlencode('EventEspressoBatchRequest\JobHandlers\PreviewEventDeletion'),
2193
-                    'return_url'        => urlencode($return_url),
2194
-                ],
2195
-                admin_url()
2196
-            )
2197
-        );
2198
-    }
2199
-
2200
-    /**
2201
-     * Checks for a POST submission
2202
-     * @since 4.10.12.p
2203
-     */
2204
-    protected function confirmDeletion()
2205
-    {
2206
-        $deletion_redirect_logic = $this->getLoader()->getShared('\EventEspresso\core\domain\services\admin\events\data\ConfirmDeletion');
2207
-        $deletion_redirect_logic->handle($this->get_request_data(), $this->admin_base_url());
2208
-    }
2209
-
2210
-    /**
2211
-     * A page for users to preview what exactly will be deleted, and confirm they want to delete it.
2212
-     * @since 4.10.12.p
2213
-     * @throws EE_Error
2214
-     */
2215
-    protected function previewDeletion()
2216
-    {
2217
-        $preview_deletion_logic = $this->getLoader()->getShared('\EventEspresso\core\domain\services\admin\events\data\PreviewDeletion');
2218
-        $this->set_template_args($preview_deletion_logic->handle($this->get_request_data(), $this->admin_base_url()));
2219
-        $this->display_admin_page_with_no_sidebar();
2220
-    }
2221
-
2222
-    /**
2223
-     * get total number of events
2224
-     *
2225
-     * @access public
2226
-     * @return int
2227
-     */
2228
-    public function total_events()
2229
-    {
2230
-        $count = EEM_Event::instance()->count(array('caps' => 'read_admin'), 'EVT_ID', true);
2231
-        return $count;
2232
-    }
2233
-
2234
-
2235
-    /**
2236
-     * get total number of draft events
2237
-     *
2238
-     * @access public
2239
-     * @return int
2240
-     */
2241
-    public function total_events_draft()
2242
-    {
2243
-        $where = array(
2244
-            'status' => array('IN', array('draft', 'auto-draft')),
2245
-        );
2246
-        $count = EEM_Event::instance()->count(array($where, 'caps' => 'read_admin'), 'EVT_ID', true);
2247
-        return $count;
2248
-    }
2249
-
2250
-
2251
-    /**
2252
-     * get total number of trashed events
2253
-     *
2254
-     * @access public
2255
-     * @return int
2256
-     */
2257
-    public function total_trashed_events()
2258
-    {
2259
-        $where = array(
2260
-            'status' => 'trash',
2261
-        );
2262
-        $count = EEM_Event::instance()->count(array($where, 'caps' => 'read_admin'), 'EVT_ID', true);
2263
-        return $count;
2264
-    }
2265
-
2266
-
2267
-    /**
2268
-     *    _default_event_settings
2269
-     *    This generates the Default Settings Tab
2270
-     *
2271
-     * @return void
2272
-     * @throws EE_Error
2273
-     */
2274
-    protected function _default_event_settings()
2275
-    {
2276
-        $this->_set_add_edit_form_tags('update_default_event_settings');
2277
-        $this->_set_publish_post_box_vars(null, false, false, null, false);
2278
-        $this->_template_args['admin_page_content'] = $this->_default_event_settings_form()->get_html();
2279
-        $this->display_admin_page_with_sidebar();
2280
-    }
2281
-
2282
-
2283
-    /**
2284
-     * Return the form for event settings.
2285
-     *
2286
-     * @return EE_Form_Section_Proper
2287
-     * @throws EE_Error
2288
-     */
2289
-    protected function _default_event_settings_form()
2290
-    {
2291
-        $registration_config = EE_Registry::instance()->CFG->registration;
2292
-        $registration_stati_for_selection = EEM_Registration::reg_status_array(
2293
-            // exclude
2294
-            array(
2295
-                EEM_Registration::status_id_cancelled,
2296
-                EEM_Registration::status_id_declined,
2297
-                EEM_Registration::status_id_incomplete,
2298
-                EEM_Registration::status_id_wait_list,
2299
-            ),
2300
-            true
2301
-        );
2302
-        return new EE_Form_Section_Proper(
2303
-            array(
2304
-                'name'            => 'update_default_event_settings',
2305
-                'html_id'         => 'update_default_event_settings',
2306
-                'html_class'      => 'form-table',
2307
-                'layout_strategy' => new EE_Admin_Two_Column_Layout(),
2308
-                'subsections'     => apply_filters(
2309
-                    'FHEE__Events_Admin_Page___default_event_settings_form__form_subsections',
2310
-                    array(
2311
-                        'default_reg_status'  => new EE_Select_Input(
2312
-                            $registration_stati_for_selection,
2313
-                            array(
2314
-                                'default'         => isset($registration_config->default_STS_ID)
2315
-                                                     && array_key_exists(
2316
-                                                         $registration_config->default_STS_ID,
2317
-                                                         $registration_stati_for_selection
2318
-                                                     )
2319
-                                    ? sanitize_text_field($registration_config->default_STS_ID)
2320
-                                    : EEM_Registration::status_id_pending_payment,
2321
-                                'html_label_text' => esc_html__('Default Registration Status', 'event_espresso')
2322
-                                                     . EEH_Template::get_help_tab_link(
2323
-                                                         'default_settings_status_help_tab'
2324
-                                                     ),
2325
-                                'html_help_text'  => esc_html__(
2326
-                                    'This setting allows you to preselect what the default registration status setting is when creating an event.  Note that changing this setting does NOT retroactively apply it to existing events.',
2327
-                                    'event_espresso'
2328
-                                ),
2329
-                            )
2330
-                        ),
2331
-                        'default_max_tickets' => new EE_Integer_Input(
2332
-                            array(
2333
-                                'default'         => isset($registration_config->default_maximum_number_of_tickets)
2334
-                                    ? $registration_config->default_maximum_number_of_tickets
2335
-                                    : EEM_Event::get_default_additional_limit(),
2336
-                                'html_label_text' => esc_html__(
2337
-                                    'Default Maximum Tickets Allowed Per Order:',
2338
-                                    'event_espresso'
2339
-                                )
2340
-                                                     . EEH_Template::get_help_tab_link(
2341
-                                                         'default_maximum_tickets_help_tab"'
2342
-                                                     ),
2343
-                                'html_help_text'  => esc_html__(
2344
-                                    'This setting allows you to indicate what will be the default for the maximum number of tickets per order when creating new events.',
2345
-                                    'event_espresso'
2346
-                                ),
2347
-                            )
2348
-                        ),
2349
-                    )
2350
-                ),
2351
-            )
2352
-        );
2353
-    }
2354
-
2355
-
2356
-    /**
2357
-     * _update_default_event_settings
2358
-     *
2359
-     * @access protected
2360
-     * @return void
2361
-     * @throws EE_Error
2362
-     */
2363
-    protected function _update_default_event_settings()
2364
-    {
2365
-        $registration_config = EE_Registry::instance()->CFG->registration;
2366
-        $form = $this->_default_event_settings_form();
2367
-        if ($form->was_submitted()) {
2368
-            $form->receive_form_submission();
2369
-            if ($form->is_valid()) {
2370
-                $valid_data = $form->valid_data();
2371
-                if (isset($valid_data['default_reg_status'])) {
2372
-                    $registration_config->default_STS_ID = $valid_data['default_reg_status'];
2373
-                }
2374
-                if (isset($valid_data['default_max_tickets'])) {
2375
-                    $registration_config->default_maximum_number_of_tickets = $valid_data['default_max_tickets'];
2376
-                }
2377
-                // update because data was valid!
2378
-                EE_Registry::instance()->CFG->update_espresso_config();
2379
-                EE_Error::overwrite_success();
2380
-                EE_Error::add_success(
2381
-                    esc_html__('Default Event Settings were updated', 'event_espresso')
2382
-                );
2383
-            }
2384
-        }
2385
-        $this->_redirect_after_action(0, '', '', array('action' => 'default_event_settings'), true);
2386
-    }
2387
-
2388
-
2389
-    /*************        Templates        *************/
2390
-    protected function _template_settings()
2391
-    {
2392
-        $this->_admin_page_title = esc_html__('Template Settings (Preview)', 'event_espresso');
2393
-        $this->_template_args['preview_img'] = '<img src="'
2394
-                                               . EVENTS_ASSETS_URL
2395
-                                               . '/images/'
2396
-                                               . 'caffeinated_template_features.jpg" alt="'
2397
-                                               . esc_attr__('Template Settings Preview screenshot', 'event_espresso')
2398
-                                               . '" />';
2399
-        $this->_template_args['preview_text'] = '<strong>'
2400
-                                                . esc_html__(
2401
-                                                    'Template Settings is a feature that is only available in the premium version of Event Espresso 4 which is available with a support license purchase on EventEspresso.com. Template Settings allow you to configure some of the appearance options for both the Event List and Event Details pages.',
2402
-                                                    'event_espresso'
2403
-                                                ) . '</strong>';
2404
-        $this->display_admin_caf_preview_page('template_settings_tab');
2405
-    }
2406
-
2407
-
2408
-    /** Event Category Stuff **/
2409
-    /**
2410
-     * set the _category property with the category object for the loaded page.
2411
-     *
2412
-     * @access private
2413
-     * @return void
2414
-     */
2415
-    private function _set_category_object()
2416
-    {
2417
-        if (isset($this->_category->id) && ! empty($this->_category->id)) {
2418
-            return;
2419
-        } //already have the category object so get out.
2420
-        // set default category object
2421
-        $this->_set_empty_category_object();
2422
-        // only set if we've got an id
2423
-        if (! isset($this->_req_data['EVT_CAT_ID'])) {
2424
-            return;
2425
-        }
2426
-        $category_id = absint($this->_req_data['EVT_CAT_ID']);
2427
-        $term = get_term($category_id, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY);
2428
-        if (! empty($term)) {
2429
-            $this->_category->category_name = $term->name;
2430
-            $this->_category->category_identifier = $term->slug;
2431
-            $this->_category->category_desc = $term->description;
2432
-            $this->_category->id = $term->term_id;
2433
-            $this->_category->parent = $term->parent;
2434
-        }
2435
-    }
2436
-
2437
-
2438
-    /**
2439
-     * Clears out category properties.
2440
-     */
2441
-    private function _set_empty_category_object()
2442
-    {
2443
-        $this->_category = new stdClass();
2444
-        $this->_category->category_name = $this->_category->category_identifier = $this->_category->category_desc = '';
2445
-        $this->_category->id = $this->_category->parent = 0;
2446
-    }
2447
-
2448
-
2449
-    /**
2450
-     * @throws EE_Error
2451
-     */
2452
-    protected function _category_list_table()
2453
-    {
2454
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2455
-        $this->_search_btn_label = esc_html__('Categories', 'event_espresso');
2456
-        $this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
2457
-            'add_category',
2458
-            'add_category',
2459
-            array(),
2460
-            'add-new-h2'
2461
-        );
2462
-        $this->display_admin_list_table_page_with_sidebar();
2463
-    }
2464
-
2465
-
2466
-    /**
2467
-     * Output category details view.
2468
-     */
2469
-    protected function _category_details($view)
2470
-    {
2471
-        // load formatter helper
2472
-        // load field generator helper
2473
-        $route = $view == 'edit' ? 'update_category' : 'insert_category';
2474
-        $this->_set_add_edit_form_tags($route);
2475
-        $this->_set_category_object();
2476
-        $id = ! empty($this->_category->id) ? $this->_category->id : '';
2477
-        $delete_action = 'delete_category';
2478
-        // custom redirect
2479
-        $redirect = EE_Admin_Page::add_query_args_and_nonce(
2480
-            array('action' => 'category_list'),
2481
-            $this->_admin_base_url
2482
-        );
2483
-        $this->_set_publish_post_box_vars('EVT_CAT_ID', $id, $delete_action, $redirect);
2484
-        // take care of contents
2485
-        $this->_template_args['admin_page_content'] = $this->_category_details_content();
2486
-        $this->display_admin_page_with_sidebar();
2487
-    }
2488
-
2489
-
2490
-    /**
2491
-     * Output category details content.
2492
-     */
2493
-    protected function _category_details_content()
2494
-    {
2495
-        $editor_args['category_desc'] = array(
2496
-            'type'          => 'wp_editor',
2497
-            'value'         => EEH_Formatter::admin_format_content($this->_category->category_desc),
2498
-            'class'         => 'my_editor_custom',
2499
-            'wpeditor_args' => array('media_buttons' => false),
2500
-        );
2501
-        $_wp_editor = $this->_generate_admin_form_fields($editor_args, 'array');
2502
-        $all_terms = get_terms(
2503
-            array(EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY),
2504
-            array('hide_empty' => 0, 'exclude' => array($this->_category->id))
2505
-        );
2506
-        // setup category select for term parents.
2507
-        $category_select_values[] = array(
2508
-            'text' => esc_html__('No Parent', 'event_espresso'),
2509
-            'id'   => 0,
2510
-        );
2511
-        foreach ($all_terms as $term) {
2512
-            $category_select_values[] = array(
2513
-                'text' => $term->name,
2514
-                'id'   => $term->term_id,
2515
-            );
2516
-        }
2517
-        $category_select = EEH_Form_Fields::select_input(
2518
-            'category_parent',
2519
-            $category_select_values,
2520
-            $this->_category->parent
2521
-        );
2522
-        $template_args = array(
2523
-            'category'                 => $this->_category,
2524
-            'category_select'          => $category_select,
2525
-            'unique_id_info_help_link' => $this->_get_help_tab_link('unique_id_info'),
2526
-            'category_desc_editor'     => $_wp_editor['category_desc']['field'],
2527
-            'disable'                  => '',
2528
-            'disabled_message'         => false,
2529
-        );
2530
-        $template = EVENTS_TEMPLATE_PATH . 'event_category_details.template.php';
2531
-        return EEH_Template::display_template($template, $template_args, true);
2532
-    }
2533
-
2534
-
2535
-    /**
2536
-     * Handles deleting categories.
2537
-     */
2538
-    protected function _delete_categories()
2539
-    {
2540
-        $cat_ids = isset($this->_req_data['EVT_CAT_ID']) ? (array) $this->_req_data['EVT_CAT_ID']
2541
-            : (array) $this->_req_data['category_id'];
2542
-        foreach ($cat_ids as $cat_id) {
2543
-            $this->_delete_category($cat_id);
2544
-        }
2545
-        // doesn't matter what page we're coming from... we're going to the same place after delete.
2546
-        $query_args = array(
2547
-            'action' => 'category_list',
2548
-        );
2549
-        $this->_redirect_after_action(0, '', '', $query_args);
2550
-    }
2551
-
2552
-
2553
-    /**
2554
-     * Handles deleting specific category.
2555
-     *
2556
-     * @param int $cat_id
2557
-     */
2558
-    protected function _delete_category($cat_id)
2559
-    {
2560
-        $cat_id = absint($cat_id);
2561
-        wp_delete_term($cat_id, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY);
2562
-    }
2563
-
2564
-
2565
-    /**
2566
-     * Handles triggering the update or insertion of a new category.
2567
-     *
2568
-     * @param bool $new_category true means we're triggering the insert of a new category.
2569
-     */
2570
-    protected function _insert_or_update_category($new_category)
2571
-    {
2572
-        $cat_id = $new_category ? $this->_insert_category() : $this->_insert_category(true);
2573
-        $success = 0; // we already have a success message so lets not send another.
2574
-        if ($cat_id) {
2575
-            $query_args = array(
2576
-                'action'     => 'edit_category',
2577
-                'EVT_CAT_ID' => $cat_id,
2578
-            );
2579
-        } else {
2580
-            $query_args = array('action' => 'add_category');
2581
-        }
2582
-        $this->_redirect_after_action($success, '', '', $query_args, true);
2583
-    }
2584
-
2585
-
2586
-    /**
2587
-     * Inserts or updates category
2588
-     *
2589
-     * @param bool $update (true indicates we're updating a category).
2590
-     * @return bool|mixed|string
2591
-     */
2592
-    private function _insert_category($update = false)
2593
-    {
2594
-        $cat_id = $update ? $this->_req_data['EVT_CAT_ID'] : '';
2595
-        $category_name = isset($this->_req_data['category_name']) ? $this->_req_data['category_name'] : '';
2596
-        $category_desc = isset($this->_req_data['category_desc']) ? $this->_req_data['category_desc'] : '';
2597
-        $category_parent = isset($this->_req_data['category_parent']) ? $this->_req_data['category_parent'] : 0;
2598
-        if (empty($category_name)) {
2599
-            $msg = esc_html__('You must add a name for the category.', 'event_espresso');
2600
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2601
-            return false;
2602
-        }
2603
-        $term_args = array(
2604
-            'name'        => $category_name,
2605
-            'description' => $category_desc,
2606
-            'parent'      => $category_parent,
2607
-        );
2608
-        // was the category_identifier input disabled?
2609
-        if (isset($this->_req_data['category_identifier'])) {
2610
-            $term_args['slug'] = $this->_req_data['category_identifier'];
2611
-        }
2612
-        $insert_ids = $update
2613
-            ? wp_update_term($cat_id, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY, $term_args)
2614
-            : wp_insert_term($category_name, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY, $term_args);
2615
-        if (! is_array($insert_ids)) {
2616
-            $msg = esc_html__(
2617
-                'An error occurred and the category has not been saved to the database.',
2618
-                'event_espresso'
2619
-            );
2620
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2621
-        } else {
2622
-            $cat_id = $insert_ids['term_id'];
2623
-            $msg = sprintf(esc_html__('The category %s was successfully saved', 'event_espresso'), $category_name);
2624
-            EE_Error::add_success($msg);
2625
-        }
2626
-        return $cat_id;
2627
-    }
2628
-
2629
-
2630
-    /**
2631
-     * Gets categories or count of categories matching the arguments in the request.
2632
-     *
2633
-     * @param int  $per_page
2634
-     * @param int  $current_page
2635
-     * @param bool $count
2636
-     * @return EE_Base_Class[]|EE_Term_Taxonomy[]|int
2637
-     */
2638
-    public function get_categories($per_page = 10, $current_page = 1, $count = false)
2639
-    {
2640
-        // testing term stuff
2641
-        $orderby = isset($this->_req_data['orderby']) ? $this->_req_data['orderby'] : 'Term.term_id';
2642
-        $order = isset($this->_req_data['order']) ? $this->_req_data['order'] : 'DESC';
2643
-        $limit = ($current_page - 1) * $per_page;
2644
-        $where = array('taxonomy' => EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY);
2645
-        if (isset($this->_req_data['s'])) {
2646
-            $sstr = '%' . $this->_req_data['s'] . '%';
2647
-            $where['OR'] = array(
2648
-                'Term.name'   => array('LIKE', $sstr),
2649
-                'description' => array('LIKE', $sstr),
2650
-            );
2651
-        }
2652
-        $query_params = array(
2653
-            $where,
2654
-            'order_by'   => array($orderby => $order),
2655
-            'limit'      => $limit . ',' . $per_page,
2656
-            'force_join' => array('Term'),
2657
-        );
2658
-        $categories = $count
2659
-            ? EEM_Term_Taxonomy::instance()->count($query_params, 'term_id')
2660
-            : EEM_Term_Taxonomy::instance()->get_all($query_params);
2661
-        return $categories;
2662
-    }
2663
-
2664
-    /* end category stuff */
2665
-    /**************/
2666
-
2667
-
2668
-    /**
2669
-     * Callback for the `ee_save_timezone_setting` ajax action.
2670
-     *
2671
-     * @throws EE_Error
2672
-     */
2673
-    public function save_timezonestring_setting()
2674
-    {
2675
-        $timezone_string = isset($this->_req_data['timezone_selected'])
2676
-            ? $this->_req_data['timezone_selected']
2677
-            : '';
2678
-        if (empty($timezone_string) || ! EEH_DTT_Helper::validate_timezone($timezone_string, false)) {
2679
-            EE_Error::add_error(
2680
-                esc_html__('An invalid timezone string submitted.', 'event_espresso'),
2681
-                __FILE__,
2682
-                __FUNCTION__,
2683
-                __LINE__
2684
-            );
2685
-            $this->_template_args['error'] = true;
2686
-            $this->_return_json();
2687
-        }
2688
-
2689
-        update_option('timezone_string', $timezone_string);
2690
-        EE_Error::add_success(
2691
-            esc_html__('Your timezone string was updated.', 'event_espresso')
2692
-        );
2693
-        $this->_template_args['success'] = true;
2694
-        $this->_return_json(true, array('action' => 'create_new'));
2695
-    }
22
+	/**
23
+	 * This will hold the event object for event_details screen.
24
+	 *
25
+	 * @var EE_Event $_event
26
+	 */
27
+	protected $_event;
28
+
29
+
30
+	/**
31
+	 * This will hold the category object for category_details screen.
32
+	 *
33
+	 * @var stdClass $_category
34
+	 */
35
+	protected $_category;
36
+
37
+
38
+	/**
39
+	 * This will hold the event model instance
40
+	 *
41
+	 * @var EEM_Event $_event_model
42
+	 */
43
+	protected $_event_model;
44
+
45
+
46
+	/**
47
+	 * @var EE_Event
48
+	 */
49
+	protected $_cpt_model_obj = false;
50
+
51
+
52
+	/**
53
+	 * @var NodeGroupDao
54
+	 */
55
+	protected $model_obj_node_group_persister;
56
+
57
+	/**
58
+	 * Initialize page props for this admin page group.
59
+	 */
60
+	protected function _init_page_props()
61
+	{
62
+		$this->page_slug = EVENTS_PG_SLUG;
63
+		$this->page_label = EVENTS_LABEL;
64
+		$this->_admin_base_url = EVENTS_ADMIN_URL;
65
+		$this->_admin_base_path = EVENTS_ADMIN;
66
+		$this->_cpt_model_names = array(
67
+			'create_new' => 'EEM_Event',
68
+			'edit'       => 'EEM_Event',
69
+		);
70
+		$this->_cpt_edit_routes = array(
71
+			'espresso_events' => 'edit',
72
+		);
73
+		add_action(
74
+			'AHEE__EE_Admin_Page_CPT__set_model_object__after_set_object',
75
+			array($this, 'verify_event_edit'),
76
+			10,
77
+			2
78
+		);
79
+	}
80
+
81
+
82
+	/**
83
+	 * Sets the ajax hooks used for this admin page group.
84
+	 */
85
+	protected function _ajax_hooks()
86
+	{
87
+		add_action('wp_ajax_ee_save_timezone_setting', array($this, 'save_timezonestring_setting'));
88
+	}
89
+
90
+
91
+	/**
92
+	 * Sets the page properties for this admin page group.
93
+	 */
94
+	protected function _define_page_props()
95
+	{
96
+		$this->_admin_page_title = EVENTS_LABEL;
97
+		$this->_labels = array(
98
+			'buttons'      => array(
99
+				'add'             => esc_html__('Add New Event', 'event_espresso'),
100
+				'edit'            => esc_html__('Edit Event', 'event_espresso'),
101
+				'delete'          => esc_html__('Delete Event', 'event_espresso'),
102
+				'add_category'    => esc_html__('Add New Category', 'event_espresso'),
103
+				'edit_category'   => esc_html__('Edit Category', 'event_espresso'),
104
+				'delete_category' => esc_html__('Delete Category', 'event_espresso'),
105
+			),
106
+			'editor_title' => array(
107
+				'espresso_events' => esc_html__('Enter event title here', 'event_espresso'),
108
+			),
109
+			'publishbox'   => array(
110
+				'create_new'        => esc_html__('Save New Event', 'event_espresso'),
111
+				'edit'              => esc_html__('Update Event', 'event_espresso'),
112
+				'add_category'      => esc_html__('Save New Category', 'event_espresso'),
113
+				'edit_category'     => esc_html__('Update Category', 'event_espresso'),
114
+				'template_settings' => esc_html__('Update Settings', 'event_espresso'),
115
+			),
116
+		);
117
+	}
118
+
119
+
120
+	/**
121
+	 * Sets the page routes property for this admin page group.
122
+	 */
123
+	protected function _set_page_routes()
124
+	{
125
+		// load formatter helper
126
+		// load field generator helper
127
+		// is there a evt_id in the request?
128
+		$evt_id = ! empty($this->_req_data['EVT_ID']) && ! is_array($this->_req_data['EVT_ID'])
129
+			? $this->_req_data['EVT_ID']
130
+			: 0;
131
+		$evt_id = ! empty($this->_req_data['post']) ? $this->_req_data['post'] : $evt_id;
132
+		$this->_page_routes = array(
133
+			'default'                       => array(
134
+				'func'       => '_events_overview_list_table',
135
+				'capability' => 'ee_read_events',
136
+			),
137
+			'create_new'                    => array(
138
+				'func'       => '_create_new_cpt_item',
139
+				'capability' => 'ee_edit_events',
140
+			),
141
+			'edit'                          => array(
142
+				'func'       => '_edit_cpt_item',
143
+				'capability' => 'ee_edit_event',
144
+				'obj_id'     => $evt_id,
145
+			),
146
+			'copy_event'                    => array(
147
+				'func'       => '_copy_events',
148
+				'capability' => 'ee_edit_event',
149
+				'obj_id'     => $evt_id,
150
+				'noheader'   => true,
151
+			),
152
+			'trash_event'                   => array(
153
+				'func'       => '_trash_or_restore_event',
154
+				'args'       => array('event_status' => 'trash'),
155
+				'capability' => 'ee_delete_event',
156
+				'obj_id'     => $evt_id,
157
+				'noheader'   => true,
158
+			),
159
+			'trash_events'                  => array(
160
+				'func'       => '_trash_or_restore_events',
161
+				'args'       => array('event_status' => 'trash'),
162
+				'capability' => 'ee_delete_events',
163
+				'noheader'   => true,
164
+			),
165
+			'restore_event'                 => array(
166
+				'func'       => '_trash_or_restore_event',
167
+				'args'       => array('event_status' => 'draft'),
168
+				'capability' => 'ee_delete_event',
169
+				'obj_id'     => $evt_id,
170
+				'noheader'   => true,
171
+			),
172
+			'restore_events'                => array(
173
+				'func'       => '_trash_or_restore_events',
174
+				'args'       => array('event_status' => 'draft'),
175
+				'capability' => 'ee_delete_events',
176
+				'noheader'   => true,
177
+			),
178
+			'delete_event'                  => array(
179
+				'func'       => '_delete_event',
180
+				'capability' => 'ee_delete_event',
181
+				'obj_id'     => $evt_id,
182
+				'noheader'   => true,
183
+			),
184
+			'delete_events'                 => array(
185
+				'func'       => '_delete_events',
186
+				'capability' => 'ee_delete_events',
187
+				'noheader'   => true,
188
+			),
189
+			'view_report'                   => array(
190
+				'func'      => '_view_report',
191
+				'capablity' => 'ee_edit_events',
192
+			),
193
+			'default_event_settings'        => array(
194
+				'func'       => '_default_event_settings',
195
+				'capability' => 'manage_options',
196
+			),
197
+			'update_default_event_settings' => array(
198
+				'func'       => '_update_default_event_settings',
199
+				'capability' => 'manage_options',
200
+				'noheader'   => true,
201
+			),
202
+			'template_settings'             => array(
203
+				'func'       => '_template_settings',
204
+				'capability' => 'manage_options',
205
+			),
206
+			// event category tab related
207
+			'add_category'                  => array(
208
+				'func'       => '_category_details',
209
+				'capability' => 'ee_edit_event_category',
210
+				'args'       => array('add'),
211
+			),
212
+			'edit_category'                 => array(
213
+				'func'       => '_category_details',
214
+				'capability' => 'ee_edit_event_category',
215
+				'args'       => array('edit'),
216
+			),
217
+			'delete_categories'             => array(
218
+				'func'       => '_delete_categories',
219
+				'capability' => 'ee_delete_event_category',
220
+				'noheader'   => true,
221
+			),
222
+			'delete_category'               => array(
223
+				'func'       => '_delete_categories',
224
+				'capability' => 'ee_delete_event_category',
225
+				'noheader'   => true,
226
+			),
227
+			'insert_category'               => array(
228
+				'func'       => '_insert_or_update_category',
229
+				'args'       => array('new_category' => true),
230
+				'capability' => 'ee_edit_event_category',
231
+				'noheader'   => true,
232
+			),
233
+			'update_category'               => array(
234
+				'func'       => '_insert_or_update_category',
235
+				'args'       => array('new_category' => false),
236
+				'capability' => 'ee_edit_event_category',
237
+				'noheader'   => true,
238
+			),
239
+			'category_list'                 => array(
240
+				'func'       => '_category_list_table',
241
+				'capability' => 'ee_manage_event_categories',
242
+			),
243
+			'preview_deletion' => [
244
+				'func' => 'previewDeletion',
245
+				'capability' => 'ee_delete_events',
246
+			],
247
+			'confirm_deletion' => [
248
+				'func' => 'confirmDeletion',
249
+				'capability' => 'ee_delete_events',
250
+				'noheader' => true,
251
+			]
252
+		);
253
+	}
254
+
255
+
256
+	/**
257
+	 * Set the _page_config property for this admin page group.
258
+	 */
259
+	protected function _set_page_config()
260
+	{
261
+		$this->_page_config = array(
262
+			'default'                => array(
263
+				'nav'           => array(
264
+					'label' => esc_html__('Overview', 'event_espresso'),
265
+					'order' => 10,
266
+				),
267
+				'list_table'    => 'Events_Admin_List_Table',
268
+				'help_tabs'     => array(
269
+					'events_overview_help_tab'                       => array(
270
+						'title'    => esc_html__('Events Overview', 'event_espresso'),
271
+						'filename' => 'events_overview',
272
+					),
273
+					'events_overview_table_column_headings_help_tab' => array(
274
+						'title'    => esc_html__('Events Overview Table Column Headings', 'event_espresso'),
275
+						'filename' => 'events_overview_table_column_headings',
276
+					),
277
+					'events_overview_filters_help_tab'               => array(
278
+						'title'    => esc_html__('Events Overview Filters', 'event_espresso'),
279
+						'filename' => 'events_overview_filters',
280
+					),
281
+					'events_overview_view_help_tab'                  => array(
282
+						'title'    => esc_html__('Events Overview Views', 'event_espresso'),
283
+						'filename' => 'events_overview_views',
284
+					),
285
+					'events_overview_other_help_tab'                 => array(
286
+						'title'    => esc_html__('Events Overview Other', 'event_espresso'),
287
+						'filename' => 'events_overview_other',
288
+					),
289
+				),
290
+				// disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
291
+				// 'help_tour'     => array(
292
+				//     'Event_Overview_Help_Tour',
293
+				//     // 'New_Features_Test_Help_Tour' for testing multiple help tour
294
+				// ),
295
+				'qtips'         => array(
296
+					'EE_Event_List_Table_Tips',
297
+				),
298
+				'require_nonce' => false,
299
+			),
300
+			'create_new'             => array(
301
+				'nav'           => array(
302
+					'label'      => esc_html__('Add Event', 'event_espresso'),
303
+					'order'      => 5,
304
+					'persistent' => false,
305
+				),
306
+				'metaboxes'     => array('_register_event_editor_meta_boxes'),
307
+				'help_tabs'     => array(
308
+					'event_editor_help_tab'                            => array(
309
+						'title'    => esc_html__('Event Editor', 'event_espresso'),
310
+						'filename' => 'event_editor',
311
+					),
312
+					'event_editor_title_richtexteditor_help_tab'       => array(
313
+						'title'    => esc_html__('Event Title & Rich Text Editor', 'event_espresso'),
314
+						'filename' => 'event_editor_title_richtexteditor',
315
+					),
316
+					'event_editor_venue_details_help_tab'              => array(
317
+						'title'    => esc_html__('Event Venue Details', 'event_espresso'),
318
+						'filename' => 'event_editor_venue_details',
319
+					),
320
+					'event_editor_event_datetimes_help_tab'            => array(
321
+						'title'    => esc_html__('Event Datetimes', 'event_espresso'),
322
+						'filename' => 'event_editor_event_datetimes',
323
+					),
324
+					'event_editor_event_tickets_help_tab'              => array(
325
+						'title'    => esc_html__('Event Tickets', 'event_espresso'),
326
+						'filename' => 'event_editor_event_tickets',
327
+					),
328
+					'event_editor_event_registration_options_help_tab' => array(
329
+						'title'    => esc_html__('Event Registration Options', 'event_espresso'),
330
+						'filename' => 'event_editor_event_registration_options',
331
+					),
332
+					'event_editor_tags_categories_help_tab'            => array(
333
+						'title'    => esc_html__('Event Tags & Categories', 'event_espresso'),
334
+						'filename' => 'event_editor_tags_categories',
335
+					),
336
+					'event_editor_questions_registrants_help_tab'      => array(
337
+						'title'    => esc_html__('Questions for Registrants', 'event_espresso'),
338
+						'filename' => 'event_editor_questions_registrants',
339
+					),
340
+					'event_editor_save_new_event_help_tab'             => array(
341
+						'title'    => esc_html__('Save New Event', 'event_espresso'),
342
+						'filename' => 'event_editor_save_new_event',
343
+					),
344
+					'event_editor_other_help_tab'                      => array(
345
+						'title'    => esc_html__('Event Other', 'event_espresso'),
346
+						'filename' => 'event_editor_other',
347
+					),
348
+				),
349
+				// disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
350
+				// 'help_tour'     => array(
351
+				//     'Event_Editor_Help_Tour',
352
+				// ),
353
+				'qtips'         => array('EE_Event_Editor_Decaf_Tips'),
354
+				'require_nonce' => false,
355
+			),
356
+			'edit'                   => array(
357
+				'nav'           => array(
358
+					'label'      => esc_html__('Edit Event', 'event_espresso'),
359
+					'order'      => 5,
360
+					'persistent' => false,
361
+					'url'        => isset($this->_req_data['post'])
362
+						? EE_Admin_Page::add_query_args_and_nonce(
363
+							array('post' => $this->_req_data['post'], 'action' => 'edit'),
364
+							$this->_current_page_view_url
365
+						)
366
+						: $this->_admin_base_url,
367
+				),
368
+				'metaboxes'     => array('_register_event_editor_meta_boxes'),
369
+				'help_tabs'     => array(
370
+					'event_editor_help_tab'                            => array(
371
+						'title'    => esc_html__('Event Editor', 'event_espresso'),
372
+						'filename' => 'event_editor',
373
+					),
374
+					'event_editor_title_richtexteditor_help_tab'       => array(
375
+						'title'    => esc_html__('Event Title & Rich Text Editor', 'event_espresso'),
376
+						'filename' => 'event_editor_title_richtexteditor',
377
+					),
378
+					'event_editor_venue_details_help_tab'              => array(
379
+						'title'    => esc_html__('Event Venue Details', 'event_espresso'),
380
+						'filename' => 'event_editor_venue_details',
381
+					),
382
+					'event_editor_event_datetimes_help_tab'            => array(
383
+						'title'    => esc_html__('Event Datetimes', 'event_espresso'),
384
+						'filename' => 'event_editor_event_datetimes',
385
+					),
386
+					'event_editor_event_tickets_help_tab'              => array(
387
+						'title'    => esc_html__('Event Tickets', 'event_espresso'),
388
+						'filename' => 'event_editor_event_tickets',
389
+					),
390
+					'event_editor_event_registration_options_help_tab' => array(
391
+						'title'    => esc_html__('Event Registration Options', 'event_espresso'),
392
+						'filename' => 'event_editor_event_registration_options',
393
+					),
394
+					'event_editor_tags_categories_help_tab'            => array(
395
+						'title'    => esc_html__('Event Tags & Categories', 'event_espresso'),
396
+						'filename' => 'event_editor_tags_categories',
397
+					),
398
+					'event_editor_questions_registrants_help_tab'      => array(
399
+						'title'    => esc_html__('Questions for Registrants', 'event_espresso'),
400
+						'filename' => 'event_editor_questions_registrants',
401
+					),
402
+					'event_editor_save_new_event_help_tab'             => array(
403
+						'title'    => esc_html__('Save New Event', 'event_espresso'),
404
+						'filename' => 'event_editor_save_new_event',
405
+					),
406
+					'event_editor_other_help_tab'                      => array(
407
+						'title'    => esc_html__('Event Other', 'event_espresso'),
408
+						'filename' => 'event_editor_other',
409
+					),
410
+				),
411
+				'qtips'         => array('EE_Event_Editor_Decaf_Tips'),
412
+				'require_nonce' => false,
413
+			),
414
+			'default_event_settings' => array(
415
+				'nav'           => array(
416
+					'label' => esc_html__('Default Settings', 'event_espresso'),
417
+					'order' => 40,
418
+				),
419
+				'metaboxes'     => array_merge($this->_default_espresso_metaboxes, array('_publish_post_box')),
420
+				'labels'        => array(
421
+					'publishbox' => esc_html__('Update Settings', 'event_espresso'),
422
+				),
423
+				'help_tabs'     => array(
424
+					'default_settings_help_tab'        => array(
425
+						'title'    => esc_html__('Default Event Settings', 'event_espresso'),
426
+						'filename' => 'events_default_settings',
427
+					),
428
+					'default_settings_status_help_tab' => array(
429
+						'title'    => esc_html__('Default Registration Status', 'event_espresso'),
430
+						'filename' => 'events_default_settings_status',
431
+					),
432
+					'default_maximum_tickets_help_tab' => array(
433
+						'title'    => esc_html__('Default Maximum Tickets Per Order', 'event_espresso'),
434
+						'filename' => 'events_default_settings_max_tickets',
435
+					),
436
+				),
437
+				// disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
438
+				// 'help_tour'     => array('Event_Default_Settings_Help_Tour'),
439
+				'require_nonce' => false,
440
+			),
441
+			// template settings
442
+			'template_settings'      => array(
443
+				'nav'           => array(
444
+					'label' => esc_html__('Templates', 'event_espresso'),
445
+					'order' => 30,
446
+				),
447
+				'metaboxes'     => $this->_default_espresso_metaboxes,
448
+				'help_tabs'     => array(
449
+					'general_settings_templates_help_tab' => array(
450
+						'title'    => esc_html__('Templates', 'event_espresso'),
451
+						'filename' => 'general_settings_templates',
452
+					),
453
+				),
454
+				// disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
455
+				// 'help_tour'     => array('Templates_Help_Tour'),
456
+				'require_nonce' => false,
457
+			),
458
+			// event category stuff
459
+			'add_category'           => array(
460
+				'nav'           => array(
461
+					'label'      => esc_html__('Add Category', 'event_espresso'),
462
+					'order'      => 15,
463
+					'persistent' => false,
464
+				),
465
+				'help_tabs'     => array(
466
+					'add_category_help_tab' => array(
467
+						'title'    => esc_html__('Add New Event Category', 'event_espresso'),
468
+						'filename' => 'events_add_category',
469
+					),
470
+				),
471
+				// disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
472
+				// 'help_tour'     => array('Event_Add_Category_Help_Tour'),
473
+				'metaboxes'     => array('_publish_post_box'),
474
+				'require_nonce' => false,
475
+			),
476
+			'edit_category'          => array(
477
+				'nav'           => array(
478
+					'label'      => esc_html__('Edit Category', 'event_espresso'),
479
+					'order'      => 15,
480
+					'persistent' => false,
481
+					'url'        => isset($this->_req_data['EVT_CAT_ID'])
482
+						? add_query_arg(
483
+							array('EVT_CAT_ID' => $this->_req_data['EVT_CAT_ID']),
484
+							$this->_current_page_view_url
485
+						)
486
+						: $this->_admin_base_url,
487
+				),
488
+				'help_tabs'     => array(
489
+					'edit_category_help_tab' => array(
490
+						'title'    => esc_html__('Edit Event Category', 'event_espresso'),
491
+						'filename' => 'events_edit_category',
492
+					),
493
+				),
494
+				/*'help_tour' => array('Event_Edit_Category_Help_Tour'),*/
495
+				'metaboxes'     => array('_publish_post_box'),
496
+				'require_nonce' => false,
497
+			),
498
+			'category_list'          => array(
499
+				'nav'           => array(
500
+					'label' => esc_html__('Categories', 'event_espresso'),
501
+					'order' => 20,
502
+				),
503
+				'list_table'    => 'Event_Categories_Admin_List_Table',
504
+				'help_tabs'     => array(
505
+					'events_categories_help_tab'                       => array(
506
+						'title'    => esc_html__('Event Categories', 'event_espresso'),
507
+						'filename' => 'events_categories',
508
+					),
509
+					'events_categories_table_column_headings_help_tab' => array(
510
+						'title'    => esc_html__('Event Categories Table Column Headings', 'event_espresso'),
511
+						'filename' => 'events_categories_table_column_headings',
512
+					),
513
+					'events_categories_view_help_tab'                  => array(
514
+						'title'    => esc_html__('Event Categories Views', 'event_espresso'),
515
+						'filename' => 'events_categories_views',
516
+					),
517
+					'events_categories_other_help_tab'                 => array(
518
+						'title'    => esc_html__('Event Categories Other', 'event_espresso'),
519
+						'filename' => 'events_categories_other',
520
+					),
521
+				),
522
+				// disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
523
+				// 'help_tour'     => array(
524
+				//     'Event_Categories_Help_Tour',
525
+				// ),
526
+				'metaboxes'     => $this->_default_espresso_metaboxes,
527
+				'require_nonce' => false,
528
+			),
529
+			'preview_deletion'           => array(
530
+				'nav'           => array(
531
+					'label'      => esc_html__('Preview Deletion', 'event_espresso'),
532
+					'order'      => 15,
533
+					'persistent' => false,
534
+					'url'        => '',
535
+				),
536
+				'require_nonce' => false
537
+			)
538
+		);
539
+	}
540
+
541
+
542
+	/**
543
+	 * Used to register any global screen options if necessary for every route in this admin page group.
544
+	 */
545
+	protected function _add_screen_options()
546
+	{
547
+	}
548
+
549
+
550
+	/**
551
+	 * Implementing the screen options for the 'default' route.
552
+	 */
553
+	protected function _add_screen_options_default()
554
+	{
555
+		$this->_per_page_screen_option();
556
+	}
557
+
558
+
559
+	/**
560
+	 * Implementing screen options for the category list route.
561
+	 */
562
+	protected function _add_screen_options_category_list()
563
+	{
564
+		$page_title = $this->_admin_page_title;
565
+		$this->_admin_page_title = esc_html__('Categories', 'event_espresso');
566
+		$this->_per_page_screen_option();
567
+		$this->_admin_page_title = $page_title;
568
+	}
569
+
570
+
571
+	/**
572
+	 * Used to register any global feature pointers for the admin page group.
573
+	 */
574
+	protected function _add_feature_pointers()
575
+	{
576
+	}
577
+
578
+
579
+	/**
580
+	 * Registers and enqueues any global scripts and styles for the entire admin page group.
581
+	 */
582
+	public function load_scripts_styles()
583
+	{
584
+		wp_register_style(
585
+			'events-admin-css',
586
+			EVENTS_ASSETS_URL . 'events-admin-page.css',
587
+			array(),
588
+			EVENT_ESPRESSO_VERSION
589
+		);
590
+		wp_register_style('ee-cat-admin', EVENTS_ASSETS_URL . 'ee-cat-admin.css', array(), EVENT_ESPRESSO_VERSION);
591
+		wp_enqueue_style('events-admin-css');
592
+		wp_enqueue_style('ee-cat-admin');
593
+		// todo note: we also need to load_scripts_styles per view (i.e. default/view_report/event_details
594
+		// registers for all views
595
+		// scripts
596
+		wp_register_script(
597
+			'event_editor_js',
598
+			EVENTS_ASSETS_URL . 'event_editor.js',
599
+			array('ee_admin_js', 'jquery-ui-slider', 'jquery-ui-timepicker-addon'),
600
+			EVENT_ESPRESSO_VERSION,
601
+			true
602
+		);
603
+	}
604
+
605
+
606
+	/**
607
+	 * Enqueuing scripts and styles specific to this view
608
+	 */
609
+	public function load_scripts_styles_create_new()
610
+	{
611
+		$this->load_scripts_styles_edit();
612
+	}
613
+
614
+
615
+	/**
616
+	 * Enqueuing scripts and styles specific to this view
617
+	 */
618
+	public function load_scripts_styles_edit()
619
+	{
620
+		// styles
621
+		wp_enqueue_style('espresso-ui-theme');
622
+		wp_register_style(
623
+			'event-editor-css',
624
+			EVENTS_ASSETS_URL . 'event-editor.css',
625
+			array('ee-admin-css'),
626
+			EVENT_ESPRESSO_VERSION
627
+		);
628
+		wp_enqueue_style('event-editor-css');
629
+		// scripts
630
+		wp_register_script(
631
+			'event-datetime-metabox',
632
+			EVENTS_ASSETS_URL . 'event-datetime-metabox.js',
633
+			array('event_editor_js', 'ee-datepicker'),
634
+			EVENT_ESPRESSO_VERSION
635
+		);
636
+		wp_enqueue_script('event-datetime-metabox');
637
+	}
638
+
639
+
640
+	/**
641
+	 * Populating the _views property for the category list table view.
642
+	 */
643
+	protected function _set_list_table_views_category_list()
644
+	{
645
+		$this->_views = array(
646
+			'all' => array(
647
+				'slug'        => 'all',
648
+				'label'       => esc_html__('All', 'event_espresso'),
649
+				'count'       => 0,
650
+				'bulk_action' => array(
651
+					'delete_categories' => esc_html__('Delete Permanently', 'event_espresso'),
652
+				),
653
+			),
654
+		);
655
+	}
656
+
657
+
658
+	/**
659
+	 * For adding anything that fires on the admin_init hook for any route within this admin page group.
660
+	 */
661
+	public function admin_init()
662
+	{
663
+		EE_Registry::$i18n_js_strings['image_confirm'] = esc_html__(
664
+			'Do you really want to delete this image? Please remember to update your event to complete the removal.',
665
+			'event_espresso'
666
+		);
667
+	}
668
+
669
+
670
+	/**
671
+	 * For adding anything that should be triggered on the admin_notices hook for any route within this admin page
672
+	 * group.
673
+	 */
674
+	public function admin_notices()
675
+	{
676
+	}
677
+
678
+
679
+	/**
680
+	 * For adding anything that should be triggered on the `admin_print_footer_scripts` hook for any route within
681
+	 * this admin page group.
682
+	 */
683
+	public function admin_footer_scripts()
684
+	{
685
+	}
686
+
687
+
688
+	/**
689
+	 * Call this function to verify if an event is public and has tickets for sale.  If it does, then we need to show a
690
+	 * warning (via EE_Error::add_error());
691
+	 *
692
+	 * @param  EE_Event $event Event object
693
+	 * @param string    $req_type
694
+	 * @return void
695
+	 * @throws EE_Error
696
+	 * @access public
697
+	 */
698
+	public function verify_event_edit($event = null, $req_type = '')
699
+	{
700
+		// don't need to do this when processing
701
+		if (! empty($req_type)) {
702
+			return;
703
+		}
704
+		// no event?
705
+		if (empty($event)) {
706
+			// set event
707
+			$event = $this->_cpt_model_obj;
708
+		}
709
+		// STILL no event?
710
+		if (! $event instanceof EE_Event) {
711
+			return;
712
+		}
713
+		$orig_status = $event->status();
714
+		// first check if event is active.
715
+		if (
716
+			$orig_status === EEM_Event::cancelled
717
+			|| $orig_status === EEM_Event::postponed
718
+			|| $event->is_expired()
719
+			|| $event->is_inactive()
720
+		) {
721
+			return;
722
+		}
723
+		// made it here so it IS active... next check that any of the tickets are sold.
724
+		if ($event->is_sold_out(true)) {
725
+			if ($orig_status !== EEM_Event::sold_out && $event->status() !== $orig_status) {
726
+				EE_Error::add_attention(
727
+					sprintf(
728
+						esc_html__(
729
+							'Please note that the Event Status has automatically been changed to %s because there are no more spaces available for this event.  However, this change is not permanent until you update the event.  You can change the status back to something else before updating if you wish.',
730
+							'event_espresso'
731
+						),
732
+						EEH_Template::pretty_status(EEM_Event::sold_out, false, 'sentence')
733
+					)
734
+				);
735
+			}
736
+			return;
737
+		} elseif ($orig_status === EEM_Event::sold_out) {
738
+			EE_Error::add_attention(
739
+				sprintf(
740
+					esc_html__(
741
+						'Please note that the Event Status has automatically been changed to %s because more spaces have become available for this event, most likely due to abandoned transactions freeing up reserved tickets.  However, this change is not permanent until you update the event. If you wish, you can change the status back to something else before updating.',
742
+						'event_espresso'
743
+					),
744
+					EEH_Template::pretty_status($event->status(), false, 'sentence')
745
+				)
746
+			);
747
+		}
748
+		// now we need to determine if the event has any tickets on sale.  If not then we dont' show the error
749
+		if (! $event->tickets_on_sale()) {
750
+			return;
751
+		}
752
+		// made it here so show warning
753
+		$this->_edit_event_warning();
754
+	}
755
+
756
+
757
+	/**
758
+	 * This is the text used for when an event is being edited that is public and has tickets for sale.
759
+	 * When needed, hook this into a EE_Error::add_error() notice.
760
+	 *
761
+	 * @access protected
762
+	 * @return void
763
+	 */
764
+	protected function _edit_event_warning()
765
+	{
766
+		// we don't want to add warnings during these requests
767
+		if (isset($this->_req_data['action']) && $this->_req_data['action'] === 'editpost') {
768
+			return;
769
+		}
770
+		EE_Error::add_attention(
771
+			sprintf(
772
+				esc_html__(
773
+					'Your event is open for registration. Making changes may disrupt any transactions in progress. %sLearn more%s',
774
+					'event_espresso'
775
+				),
776
+				'<a class="espresso-help-tab-lnk">',
777
+				'</a>'
778
+			)
779
+		);
780
+	}
781
+
782
+
783
+	/**
784
+	 * When a user is creating a new event, notify them if they haven't set their timezone.
785
+	 * Otherwise, do the normal logic
786
+	 *
787
+	 * @return string
788
+	 * @throws \EE_Error
789
+	 */
790
+	protected function _create_new_cpt_item()
791
+	{
792
+		$has_timezone_string = get_option('timezone_string');
793
+		// only nag them about setting their timezone if it's their first event, and they haven't already done it
794
+		if (! $has_timezone_string && ! EEM_Event::instance()->exists(array())) {
795
+			EE_Error::add_attention(
796
+				sprintf(
797
+					esc_html__(
798
+						'Your website\'s timezone is currently set to a UTC offset. We recommend updating your timezone to a city or region near you before you create an event. Change your timezone now:%1$s%2$s%3$sChange Timezone%4$s',
799
+						'event_espresso'
800
+					),
801
+					'<br>',
802
+					'<select id="timezone_string" name="timezone_string" aria-describedby="timezone-description">'
803
+					. EEH_DTT_Helper::wp_timezone_choice('', EEH_DTT_Helper::get_user_locale())
804
+					. '</select>',
805
+					'<button class="button button-secondary timezone-submit">',
806
+					'</button><span class="spinner"></span>'
807
+				),
808
+				__FILE__,
809
+				__FUNCTION__,
810
+				__LINE__
811
+			);
812
+		}
813
+		return parent::_create_new_cpt_item();
814
+	}
815
+
816
+
817
+	/**
818
+	 * Sets the _views property for the default route in this admin page group.
819
+	 */
820
+	protected function _set_list_table_views_default()
821
+	{
822
+		$this->_views = array(
823
+			'all'   => array(
824
+				'slug'        => 'all',
825
+				'label'       => esc_html__('View All Events', 'event_espresso'),
826
+				'count'       => 0,
827
+				'bulk_action' => array(
828
+					'trash_events' => esc_html__('Move to Trash', 'event_espresso'),
829
+				),
830
+			),
831
+			'draft' => array(
832
+				'slug'        => 'draft',
833
+				'label'       => esc_html__('Draft', 'event_espresso'),
834
+				'count'       => 0,
835
+				'bulk_action' => array(
836
+					'trash_events' => esc_html__('Move to Trash', 'event_espresso'),
837
+				),
838
+			),
839
+		);
840
+		if (EE_Registry::instance()->CAP->current_user_can('ee_delete_events', 'espresso_events_trash_events')) {
841
+			$this->_views['trash'] = array(
842
+				'slug'        => 'trash',
843
+				'label'       => esc_html__('Trash', 'event_espresso'),
844
+				'count'       => 0,
845
+				'bulk_action' => array(
846
+					'restore_events' => esc_html__('Restore From Trash', 'event_espresso'),
847
+					'delete_events'  => esc_html__('Delete Permanently', 'event_espresso'),
848
+				),
849
+			);
850
+		}
851
+	}
852
+
853
+
854
+	/**
855
+	 * Provides the legend item array for the default list table view.
856
+	 *
857
+	 * @return array
858
+	 */
859
+	protected function _event_legend_items()
860
+	{
861
+		$items = array(
862
+			'view_details'   => array(
863
+				'class' => 'dashicons dashicons-search',
864
+				'desc'  => esc_html__('View Event', 'event_espresso'),
865
+			),
866
+			'edit_event'     => array(
867
+				'class' => 'ee-icon ee-icon-calendar-edit',
868
+				'desc'  => esc_html__('Edit Event Details', 'event_espresso'),
869
+			),
870
+			'view_attendees' => array(
871
+				'class' => 'dashicons dashicons-groups',
872
+				'desc'  => esc_html__('View Registrations for Event', 'event_espresso'),
873
+			),
874
+		);
875
+		$items = apply_filters('FHEE__Events_Admin_Page___event_legend_items__items', $items);
876
+		$statuses = array(
877
+			'sold_out_status'  => array(
878
+				'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::sold_out,
879
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::sold_out, false, 'sentence'),
880
+			),
881
+			'active_status'    => array(
882
+				'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::active,
883
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::active, false, 'sentence'),
884
+			),
885
+			'upcoming_status'  => array(
886
+				'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::upcoming,
887
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::upcoming, false, 'sentence'),
888
+			),
889
+			'postponed_status' => array(
890
+				'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::postponed,
891
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::postponed, false, 'sentence'),
892
+			),
893
+			'cancelled_status' => array(
894
+				'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::cancelled,
895
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::cancelled, false, 'sentence'),
896
+			),
897
+			'expired_status'   => array(
898
+				'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::expired,
899
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::expired, false, 'sentence'),
900
+			),
901
+			'inactive_status'  => array(
902
+				'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::inactive,
903
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::inactive, false, 'sentence'),
904
+			),
905
+		);
906
+		$statuses = apply_filters('FHEE__Events_Admin_Page__event_legend_items__statuses', $statuses);
907
+		return array_merge($items, $statuses);
908
+	}
909
+
910
+
911
+	/**
912
+	 * @return EEM_Event
913
+	 */
914
+	private function _event_model()
915
+	{
916
+		if (! $this->_event_model instanceof EEM_Event) {
917
+			$this->_event_model = EE_Registry::instance()->load_model('Event');
918
+		}
919
+		return $this->_event_model;
920
+	}
921
+
922
+
923
+	/**
924
+	 * Adds extra buttons to the WP CPT permalink field row.
925
+	 * Method is called from parent and is hooked into the wp 'get_sample_permalink_html' filter.
926
+	 *
927
+	 * @param  string $return    the current html
928
+	 * @param  int    $id        the post id for the page
929
+	 * @param  string $new_title What the title is
930
+	 * @param  string $new_slug  what the slug is
931
+	 * @return string            The new html string for the permalink area
932
+	 */
933
+	public function extra_permalink_field_buttons($return, $id, $new_title, $new_slug)
934
+	{
935
+		// make sure this is only when editing
936
+		if (! empty($id)) {
937
+			$post = get_post($id);
938
+			$return .= '<a class="button button-small" onclick="prompt(\'Shortcode:\', jQuery(\'#shortcode\').val()); return false;" href="#"  tabindex="-1">'
939
+					   . esc_html__('Shortcode', 'event_espresso')
940
+					   . '</a> ';
941
+			$return .= '<input id="shortcode" type="hidden" value="[ESPRESSO_TICKET_SELECTOR event_id='
942
+					   . $post->ID
943
+					   . ']">';
944
+		}
945
+		return $return;
946
+	}
947
+
948
+
949
+	/**
950
+	 * _events_overview_list_table
951
+	 * This contains the logic for showing the events_overview list
952
+	 *
953
+	 * @access protected
954
+	 * @return void
955
+	 * @throws \EE_Error
956
+	 */
957
+	protected function _events_overview_list_table()
958
+	{
959
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
960
+		$this->_template_args['after_list_table'] = ! empty($this->_template_args['after_list_table'])
961
+			? (array) $this->_template_args['after_list_table']
962
+			: array();
963
+		$this->_template_args['after_list_table']['view_event_list_button'] = EEH_HTML::br()
964
+				. EEH_Template::get_button_or_link(
965
+					get_post_type_archive_link('espresso_events'),
966
+					esc_html__("View Event Archive Page", "event_espresso"),
967
+					'button'
968
+				);
969
+		$this->_template_args['after_list_table']['legend'] = $this->_display_legend($this->_event_legend_items());
970
+		$this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
971
+			'create_new',
972
+			'add',
973
+			array(),
974
+			'add-new-h2'
975
+		);
976
+		$this->display_admin_list_table_page_with_no_sidebar();
977
+	}
978
+
979
+
980
+	/**
981
+	 * this allows for extra misc actions in the default WP publish box
982
+	 *
983
+	 * @return void
984
+	 */
985
+	public function extra_misc_actions_publish_box()
986
+	{
987
+		$this->_generate_publish_box_extra_content();
988
+	}
989
+
990
+
991
+	/**
992
+	 * This is hooked into the WordPress do_action('save_post') hook and runs after the custom post type has been
993
+	 * saved.
994
+	 * Typically you would use this to save any additional data.
995
+	 * Keep in mind also that "save_post" runs on EVERY post update to the database.
996
+	 * ALSO very important.  When a post transitions from scheduled to published,
997
+	 * the save_post action is fired but you will NOT have any _POST data containing any extra info you may have from
998
+	 * other meta saves. So MAKE sure that you handle this accordingly.
999
+	 *
1000
+	 * @access protected
1001
+	 * @abstract
1002
+	 * @param  string $post_id The ID of the cpt that was saved (so you can link relationally)
1003
+	 * @param  object $post    The post object of the cpt that was saved.
1004
+	 * @return void
1005
+	 * @throws \EE_Error
1006
+	 */
1007
+	protected function _insert_update_cpt_item($post_id, $post)
1008
+	{
1009
+		if ($post instanceof WP_Post && $post->post_type !== 'espresso_events') {
1010
+			// get out we're not processing an event save.
1011
+			return;
1012
+		}
1013
+		$event_values = array(
1014
+			'EVT_display_desc'                => ! empty($this->_req_data['display_desc']) ? 1 : 0,
1015
+			'EVT_display_ticket_selector'     => ! empty($this->_req_data['display_ticket_selector']) ? 1 : 0,
1016
+			'EVT_additional_limit'            => min(
1017
+				apply_filters('FHEE__EE_Events_Admin__insert_update_cpt_item__EVT_additional_limit_max', 255),
1018
+				! empty($this->_req_data['additional_limit']) ? $this->_req_data['additional_limit'] : null
1019
+			),
1020
+			'EVT_default_registration_status' => ! empty($this->_req_data['EVT_default_registration_status'])
1021
+				? $this->_req_data['EVT_default_registration_status']
1022
+				: EE_Registry::instance()->CFG->registration->default_STS_ID,
1023
+			'EVT_member_only'                 => ! empty($this->_req_data['member_only']) ? 1 : 0,
1024
+			'EVT_allow_overflow'              => ! empty($this->_req_data['EVT_allow_overflow']) ? 1 : 0,
1025
+			'EVT_timezone_string'             => ! empty($this->_req_data['timezone_string'])
1026
+				? $this->_req_data['timezone_string'] : null,
1027
+			'EVT_external_URL'                => ! empty($this->_req_data['externalURL'])
1028
+				? $this->_req_data['externalURL'] : null,
1029
+			'EVT_phone'                       => ! empty($this->_req_data['event_phone'])
1030
+				? $this->_req_data['event_phone'] : null,
1031
+		);
1032
+		// update event
1033
+		$success = $this->_event_model()->update_by_ID($event_values, $post_id);
1034
+		// get event_object for other metaboxes... though it would seem to make sense to just use $this->_event_model()->get_one_by_ID( $post_id ).. i have to setup where conditions to override the filters in the model that filter out autodraft and inherit statuses so we GET the inherit id!
1035
+		$get_one_where = array(
1036
+			$this->_event_model()->primary_key_name() => $post_id,
1037
+			'OR'                                      => array(
1038
+				'status'   => $post->post_status,
1039
+				// if trying to "Publish" a sold out event, it's status will get switched back to "sold_out" in the db,
1040
+				// but the returned object here has a status of "publish", so use the original post status as well
1041
+				'status*1' => $this->_req_data['original_post_status'],
1042
+			),
1043
+		);
1044
+		$event = $this->_event_model()->get_one(array($get_one_where));
1045
+		// the following are default callbacks for event attachment updates that can be overridden by caffeinated functionality and/or addons.
1046
+		$event_update_callbacks = apply_filters(
1047
+			'FHEE__Events_Admin_Page___insert_update_cpt_item__event_update_callbacks',
1048
+			array(
1049
+				array($this, '_default_venue_update'),
1050
+				array($this, '_default_tickets_update'),
1051
+			)
1052
+		);
1053
+		$att_success = true;
1054
+		foreach ($event_update_callbacks as $e_callback) {
1055
+			$_success = is_callable($e_callback)
1056
+				? call_user_func($e_callback, $event, $this->_req_data)
1057
+				: false;
1058
+			// if ANY of these updates fail then we want the appropriate global error message
1059
+			$att_success = ! $att_success ? $att_success : $_success;
1060
+		}
1061
+		// any errors?
1062
+		if ($success && false === $att_success) {
1063
+			EE_Error::add_error(
1064
+				esc_html__(
1065
+					'Event Details saved successfully but something went wrong with saving attachments.',
1066
+					'event_espresso'
1067
+				),
1068
+				__FILE__,
1069
+				__FUNCTION__,
1070
+				__LINE__
1071
+			);
1072
+		} elseif ($success === false) {
1073
+			EE_Error::add_error(
1074
+				esc_html__('Event Details did not save successfully.', 'event_espresso'),
1075
+				__FILE__,
1076
+				__FUNCTION__,
1077
+				__LINE__
1078
+			);
1079
+		}
1080
+	}
1081
+
1082
+
1083
+	/**
1084
+	 * @see parent::restore_item()
1085
+	 * @param int $post_id
1086
+	 * @param int $revision_id
1087
+	 */
1088
+	protected function _restore_cpt_item($post_id, $revision_id)
1089
+	{
1090
+		// copy existing event meta to new post
1091
+		$post_evt = $this->_event_model()->get_one_by_ID($post_id);
1092
+		if ($post_evt instanceof EE_Event) {
1093
+			// meta revision restore
1094
+			$post_evt->restore_revision($revision_id);
1095
+			// related objs restore
1096
+			$post_evt->restore_revision($revision_id, array('Venue', 'Datetime', 'Price'));
1097
+		}
1098
+	}
1099
+
1100
+
1101
+	/**
1102
+	 * Attach the venue to the Event
1103
+	 *
1104
+	 * @param  \EE_Event $evtobj Event Object to add the venue to
1105
+	 * @param  array     $data   The request data from the form
1106
+	 * @return bool           Success or fail.
1107
+	 */
1108
+	protected function _default_venue_update(\EE_Event $evtobj, $data)
1109
+	{
1110
+		require_once(EE_MODELS . 'EEM_Venue.model.php');
1111
+		$venue_model = EE_Registry::instance()->load_model('Venue');
1112
+		$rows_affected = null;
1113
+		$venue_id = ! empty($data['venue_id']) ? $data['venue_id'] : null;
1114
+		// very important.  If we don't have a venue name...
1115
+		// then we'll get out because not necessary to create empty venue
1116
+		if (empty($data['venue_title'])) {
1117
+			return false;
1118
+		}
1119
+		$venue_array = array(
1120
+			'VNU_wp_user'         => $evtobj->get('EVT_wp_user'),
1121
+			'VNU_name'            => ! empty($data['venue_title']) ? $data['venue_title'] : null,
1122
+			'VNU_desc'            => ! empty($data['venue_description']) ? $data['venue_description'] : null,
1123
+			'VNU_identifier'      => ! empty($data['venue_identifier']) ? $data['venue_identifier'] : null,
1124
+			'VNU_short_desc'      => ! empty($data['venue_short_description']) ? $data['venue_short_description']
1125
+				: null,
1126
+			'VNU_address'         => ! empty($data['address']) ? $data['address'] : null,
1127
+			'VNU_address2'        => ! empty($data['address2']) ? $data['address2'] : null,
1128
+			'VNU_city'            => ! empty($data['city']) ? $data['city'] : null,
1129
+			'STA_ID'              => ! empty($data['state']) ? $data['state'] : null,
1130
+			'CNT_ISO'             => ! empty($data['countries']) ? $data['countries'] : null,
1131
+			'VNU_zip'             => ! empty($data['zip']) ? $data['zip'] : null,
1132
+			'VNU_phone'           => ! empty($data['venue_phone']) ? $data['venue_phone'] : null,
1133
+			'VNU_capacity'        => ! empty($data['venue_capacity']) ? $data['venue_capacity'] : null,
1134
+			'VNU_url'             => ! empty($data['venue_url']) ? $data['venue_url'] : null,
1135
+			'VNU_virtual_phone'   => ! empty($data['virtual_phone']) ? $data['virtual_phone'] : null,
1136
+			'VNU_virtual_url'     => ! empty($data['virtual_url']) ? $data['virtual_url'] : null,
1137
+			'VNU_enable_for_gmap' => isset($data['enable_for_gmap']) ? 1 : 0,
1138
+			'status'              => 'publish',
1139
+		);
1140
+		// if we've got the venue_id then we're just updating the existing venue so let's do that and then get out.
1141
+		if (! empty($venue_id)) {
1142
+			$update_where = array($venue_model->primary_key_name() => $venue_id);
1143
+			$rows_affected = $venue_model->update($venue_array, array($update_where));
1144
+			// we've gotta make sure that the venue is always attached to a revision.. add_relation_to should take care of making sure that the relation is already present.
1145
+			$evtobj->_add_relation_to($venue_id, 'Venue');
1146
+			return $rows_affected > 0 ? true : false;
1147
+		} else {
1148
+			// we insert the venue
1149
+			$venue_id = $venue_model->insert($venue_array);
1150
+			$evtobj->_add_relation_to($venue_id, 'Venue');
1151
+			return ! empty($venue_id) ? true : false;
1152
+		}
1153
+		// when we have the ancestor come in it's already been handled by the revision save.
1154
+	}
1155
+
1156
+
1157
+	/**
1158
+	 * Handles saving everything related to Tickets (datetimes, tickets, prices)
1159
+	 *
1160
+	 * @param  EE_Event $evtobj The Event object we're attaching data to
1161
+	 * @param  array    $data   The request data from the form
1162
+	 * @return array
1163
+	 */
1164
+	protected function _default_tickets_update(EE_Event $evtobj, $data)
1165
+	{
1166
+		$success = true;
1167
+		$saved_dtt = null;
1168
+		$saved_tickets = array();
1169
+		$incoming_date_formats = array('Y-m-d', 'h:i a');
1170
+		foreach ($data['edit_event_datetimes'] as $row => $dtt) {
1171
+			// trim all values to ensure any excess whitespace is removed.
1172
+			$dtt = array_map('trim', $dtt);
1173
+			$dtt['DTT_EVT_end'] = isset($dtt['DTT_EVT_end']) && ! empty($dtt['DTT_EVT_end']) ? $dtt['DTT_EVT_end']
1174
+				: $dtt['DTT_EVT_start'];
1175
+			$datetime_values = array(
1176
+				'DTT_ID'        => ! empty($dtt['DTT_ID']) ? $dtt['DTT_ID'] : null,
1177
+				'DTT_EVT_start' => $dtt['DTT_EVT_start'],
1178
+				'DTT_EVT_end'   => $dtt['DTT_EVT_end'],
1179
+				'DTT_reg_limit' => empty($dtt['DTT_reg_limit']) ? EE_INF : $dtt['DTT_reg_limit'],
1180
+				'DTT_order'     => $row,
1181
+			);
1182
+			// if we have an id then let's get existing object first and then set the new values.  Otherwise we instantiate a new object for save.
1183
+			if (! empty($dtt['DTT_ID'])) {
1184
+				$DTM = EE_Registry::instance()
1185
+								  ->load_model('Datetime', array($evtobj->get_timezone()))
1186
+								  ->get_one_by_ID($dtt['DTT_ID']);
1187
+				$DTM->set_date_format($incoming_date_formats[0]);
1188
+				$DTM->set_time_format($incoming_date_formats[1]);
1189
+				foreach ($datetime_values as $field => $value) {
1190
+					$DTM->set($field, $value);
1191
+				}
1192
+				// make sure the $dtt_id here is saved just in case after the add_relation_to() the autosave replaces it.  We need to do this so we dont' TRASH the parent DTT.
1193
+				$saved_dtts[ $DTM->ID() ] = $DTM;
1194
+			} else {
1195
+				$DTM = EE_Registry::instance()->load_class(
1196
+					'Datetime',
1197
+					array($datetime_values, $evtobj->get_timezone(), $incoming_date_formats),
1198
+					false,
1199
+					false
1200
+				);
1201
+				foreach ($datetime_values as $field => $value) {
1202
+					$DTM->set($field, $value);
1203
+				}
1204
+			}
1205
+			$DTM->save();
1206
+			$DTT = $evtobj->_add_relation_to($DTM, 'Datetime');
1207
+			// load DTT helper
1208
+			// before going any further make sure our dates are setup correctly so that the end date is always equal or greater than the start date.
1209
+			if ($DTT->get_raw('DTT_EVT_start') > $DTT->get_raw('DTT_EVT_end')) {
1210
+				$DTT->set('DTT_EVT_end', $DTT->get('DTT_EVT_start'));
1211
+				$DTT = EEH_DTT_Helper::date_time_add($DTT, 'DTT_EVT_end', 'days');
1212
+				$DTT->save();
1213
+			}
1214
+			// now we got to make sure we add the new DTT_ID to the $saved_dtts array  because it is possible there was a new one created for the autosave.
1215
+			$saved_dtt = $DTT;
1216
+			$success = ! $success ? $success : $DTT;
1217
+			// if ANY of these updates fail then we want the appropriate global error message.
1218
+			// //todo this is actually sucky we need a better error message but this is what it is for now.
1219
+		}
1220
+		// no dtts get deleted so we don't do any of that logic here.
1221
+		// update tickets next
1222
+		$old_tickets = isset($data['ticket_IDs']) ? explode(',', $data['ticket_IDs']) : array();
1223
+		foreach ($data['edit_tickets'] as $row => $tkt) {
1224
+			$incoming_date_formats = array('Y-m-d', 'h:i a');
1225
+			$update_prices = false;
1226
+			$ticket_price = isset($data['edit_prices'][ $row ][1]['PRC_amount'])
1227
+				? $data['edit_prices'][ $row ][1]['PRC_amount'] : 0;
1228
+			// trim inputs to ensure any excess whitespace is removed.
1229
+			$tkt = array_map('trim', $tkt);
1230
+			if (empty($tkt['TKT_start_date'])) {
1231
+				// let's use now in the set timezone.
1232
+				$now = new DateTime('now', new DateTimeZone($evtobj->get_timezone()));
1233
+				$tkt['TKT_start_date'] = $now->format($incoming_date_formats[0] . ' ' . $incoming_date_formats[1]);
1234
+			}
1235
+			if (empty($tkt['TKT_end_date'])) {
1236
+				// use the start date of the first datetime
1237
+				$dtt = $evtobj->first_datetime();
1238
+				$tkt['TKT_end_date'] = $dtt->start_date_and_time(
1239
+					$incoming_date_formats[0],
1240
+					$incoming_date_formats[1]
1241
+				);
1242
+			}
1243
+			$TKT_values = array(
1244
+				'TKT_ID'          => ! empty($tkt['TKT_ID']) ? $tkt['TKT_ID'] : null,
1245
+				'TTM_ID'          => ! empty($tkt['TTM_ID']) ? $tkt['TTM_ID'] : 0,
1246
+				'TKT_name'        => ! empty($tkt['TKT_name']) ? $tkt['TKT_name'] : '',
1247
+				'TKT_description' => ! empty($tkt['TKT_description']) ? $tkt['TKT_description'] : '',
1248
+				'TKT_start_date'  => $tkt['TKT_start_date'],
1249
+				'TKT_end_date'    => $tkt['TKT_end_date'],
1250
+				'TKT_qty'         => ! isset($tkt['TKT_qty']) || $tkt['TKT_qty'] === '' ? EE_INF : $tkt['TKT_qty'],
1251
+				'TKT_uses'        => ! isset($tkt['TKT_uses']) || $tkt['TKT_uses'] === '' ? EE_INF : $tkt['TKT_uses'],
1252
+				'TKT_min'         => empty($tkt['TKT_min']) ? 0 : $tkt['TKT_min'],
1253
+				'TKT_max'         => empty($tkt['TKT_max']) ? EE_INF : $tkt['TKT_max'],
1254
+				'TKT_row'         => $row,
1255
+				'TKT_order'       => isset($tkt['TKT_order']) ? $tkt['TKT_order'] : $row,
1256
+				'TKT_price'       => $ticket_price,
1257
+			);
1258
+			// if this is a default TKT, then we need to set the TKT_ID to 0 and update accordingly, which means in turn that the prices will become new prices as well.
1259
+			if (isset($tkt['TKT_is_default']) && $tkt['TKT_is_default']) {
1260
+				$TKT_values['TKT_ID'] = 0;
1261
+				$TKT_values['TKT_is_default'] = 0;
1262
+				$TKT_values['TKT_price'] = $ticket_price;
1263
+				$update_prices = true;
1264
+			}
1265
+			// if we have a TKT_ID then we need to get that existing TKT_obj and update it
1266
+			// we actually do our saves a head of doing any add_relations to because its entirely possible that this ticket didn't removed or added to any datetime in the session but DID have it's items modified.
1267
+			// keep in mind that if the TKT has been sold (and we have changed pricing information), then we won't be updating the tkt but instead a new tkt will be created and the old one archived.
1268
+			if (! empty($tkt['TKT_ID'])) {
1269
+				$TKT = EE_Registry::instance()
1270
+								  ->load_model('Ticket', array($evtobj->get_timezone()))
1271
+								  ->get_one_by_ID($tkt['TKT_ID']);
1272
+				if ($TKT instanceof EE_Ticket) {
1273
+					$ticket_sold = $TKT->count_related(
1274
+						'Registration',
1275
+						array(
1276
+							array(
1277
+								'STS_ID' => array(
1278
+									'NOT IN',
1279
+									array(EEM_Registration::status_id_incomplete),
1280
+								),
1281
+							),
1282
+						)
1283
+					) > 0 ? true : false;
1284
+					// let's just check the total price for the existing ticket and determine if it matches the new total price.  if they are different then we create a new ticket (if tkts sold) if they aren't different then we go ahead and modify existing ticket.
1285
+					$create_new_TKT = $ticket_sold && $ticket_price != $TKT->get('TKT_price')
1286
+									  && ! $TKT->get('TKT_deleted');
1287
+					$TKT->set_date_format($incoming_date_formats[0]);
1288
+					$TKT->set_time_format($incoming_date_formats[1]);
1289
+					// set new values
1290
+					foreach ($TKT_values as $field => $value) {
1291
+						if ($field == 'TKT_qty') {
1292
+							$TKT->set_qty($value);
1293
+						} else {
1294
+							$TKT->set($field, $value);
1295
+						}
1296
+					}
1297
+					// if $create_new_TKT is false then we can safely update the existing ticket.  Otherwise we have to create a new ticket.
1298
+					if ($create_new_TKT) {
1299
+						// archive the old ticket first
1300
+						$TKT->set('TKT_deleted', 1);
1301
+						$TKT->save();
1302
+						// make sure this ticket is still recorded in our saved_tkts so we don't run it through the regular trash routine.
1303
+						$saved_tickets[ $TKT->ID() ] = $TKT;
1304
+						// create new ticket that's a copy of the existing except a new id of course (and not archived) AND has the new TKT_price associated with it.
1305
+						$TKT = clone $TKT;
1306
+						$TKT->set('TKT_ID', 0);
1307
+						$TKT->set('TKT_deleted', 0);
1308
+						$TKT->set('TKT_price', $ticket_price);
1309
+						$TKT->set('TKT_sold', 0);
1310
+						// now we need to make sure that $new prices are created as well and attached to new ticket.
1311
+						$update_prices = true;
1312
+					}
1313
+					// make sure price is set if it hasn't been already
1314
+					$TKT->set('TKT_price', $ticket_price);
1315
+				}
1316
+			} else {
1317
+				// no TKT_id so a new TKT
1318
+				$TKT_values['TKT_price'] = $ticket_price;
1319
+				$TKT = EE_Registry::instance()->load_class('Ticket', array($TKT_values), false, false);
1320
+				if ($TKT instanceof EE_Ticket) {
1321
+					// need to reset values to properly account for the date formats
1322
+					$TKT->set_date_format($incoming_date_formats[0]);
1323
+					$TKT->set_time_format($incoming_date_formats[1]);
1324
+					$TKT->set_timezone($evtobj->get_timezone());
1325
+					// set new values
1326
+					foreach ($TKT_values as $field => $value) {
1327
+						if ($field == 'TKT_qty') {
1328
+							$TKT->set_qty($value);
1329
+						} else {
1330
+							$TKT->set($field, $value);
1331
+						}
1332
+					}
1333
+					$update_prices = true;
1334
+				}
1335
+			}
1336
+			// cap ticket qty by datetime reg limits
1337
+			$TKT->set_qty(min($TKT->qty(), $TKT->qty('reg_limit')));
1338
+			// update ticket.
1339
+			$TKT->save();
1340
+			// before going any further make sure our dates are setup correctly so that the end date is always equal or greater than the start date.
1341
+			if ($TKT->get_raw('TKT_start_date') > $TKT->get_raw('TKT_end_date')) {
1342
+				$TKT->set('TKT_end_date', $TKT->get('TKT_start_date'));
1343
+				$TKT = EEH_DTT_Helper::date_time_add($TKT, 'TKT_end_date', 'days');
1344
+				$TKT->save();
1345
+			}
1346
+			// initially let's add the ticket to the dtt
1347
+			$saved_dtt->_add_relation_to($TKT, 'Ticket');
1348
+			$saved_tickets[ $TKT->ID() ] = $TKT;
1349
+			// add prices to ticket
1350
+			$this->_add_prices_to_ticket($data['edit_prices'][ $row ], $TKT, $update_prices);
1351
+		}
1352
+		// however now we need to handle permanently deleting tickets via the ui.  Keep in mind that the ui does not allow deleting/archiving tickets that have ticket sold.  However, it does allow for deleting tickets that have no tickets sold, in which case we want to get rid of permanently because there is no need to save in db.
1353
+		$old_tickets = isset($old_tickets[0]) && $old_tickets[0] == '' ? array() : $old_tickets;
1354
+		$tickets_removed = array_diff($old_tickets, array_keys($saved_tickets));
1355
+		foreach ($tickets_removed as $id) {
1356
+			$id = absint($id);
1357
+			// get the ticket for this id
1358
+			$tkt_to_remove = EE_Registry::instance()->load_model('Ticket')->get_one_by_ID($id);
1359
+			if (! $tkt_to_remove instanceof EE_Ticket) {
1360
+				continue;
1361
+			}
1362
+
1363
+			// need to get all the related datetimes on this ticket and remove from every single one of them (remember this process can ONLY kick off if there are NO tkts_sold)
1364
+			$dtts = $tkt_to_remove->get_many_related('Datetime');
1365
+			foreach ($dtts as $dtt) {
1366
+				$tkt_to_remove->_remove_relation_to($dtt, 'Datetime');
1367
+			}
1368
+			// need to do the same for prices (except these prices can also be deleted because again, tickets can only be trashed if they don't have any TKTs sold (otherwise they are just archived))
1369
+			$tkt_to_remove->delete_related_permanently('Price');
1370
+			// finally let's delete this ticket (which should not be blocked at this point b/c we've removed all our relationships)
1371
+			$tkt_to_remove->delete_permanently();
1372
+		}
1373
+		return array($saved_dtt, $saved_tickets);
1374
+	}
1375
+
1376
+
1377
+	/**
1378
+	 * This attaches a list of given prices to a ticket.
1379
+	 * Note we dont' have to worry about ever removing relationships (or archiving prices) because if there is a change
1380
+	 * in price information on a ticket, a new ticket is created anyways so the archived ticket will retain the old
1381
+	 * price info and prices are automatically "archived" via the ticket.
1382
+	 *
1383
+	 * @access  private
1384
+	 * @param array     $prices     Array of prices from the form.
1385
+	 * @param EE_Ticket $ticket     EE_Ticket object that prices are being attached to.
1386
+	 * @param bool      $new_prices Whether attach existing incoming prices or create new ones.
1387
+	 * @return  void
1388
+	 */
1389
+	private function _add_prices_to_ticket($prices, EE_Ticket $ticket, $new_prices = false)
1390
+	{
1391
+		foreach ($prices as $row => $prc) {
1392
+			$PRC_values = array(
1393
+				'PRC_ID'         => ! empty($prc['PRC_ID']) ? $prc['PRC_ID'] : null,
1394
+				'PRT_ID'         => ! empty($prc['PRT_ID']) ? $prc['PRT_ID'] : null,
1395
+				'PRC_amount'     => ! empty($prc['PRC_amount']) ? $prc['PRC_amount'] : 0,
1396
+				'PRC_name'       => ! empty($prc['PRC_name']) ? $prc['PRC_name'] : '',
1397
+				'PRC_desc'       => ! empty($prc['PRC_desc']) ? $prc['PRC_desc'] : '',
1398
+				'PRC_is_default' => 0, // make sure prices are NOT set as default from this context
1399
+				'PRC_order'      => $row,
1400
+			);
1401
+			if ($new_prices || empty($PRC_values['PRC_ID'])) {
1402
+				$PRC_values['PRC_ID'] = 0;
1403
+				$PRC = EE_Registry::instance()->load_class('Price', array($PRC_values), false, false);
1404
+			} else {
1405
+				$PRC = EE_Registry::instance()->load_model('Price')->get_one_by_ID($prc['PRC_ID']);
1406
+				// update this price with new values
1407
+				foreach ($PRC_values as $field => $newprc) {
1408
+					$PRC->set($field, $newprc);
1409
+				}
1410
+				$PRC->save();
1411
+			}
1412
+			$ticket->_add_relation_to($PRC, 'Price');
1413
+		}
1414
+	}
1415
+
1416
+
1417
+	/**
1418
+	 * Add in our autosave ajax handlers
1419
+	 *
1420
+	 */
1421
+	protected function _ee_autosave_create_new()
1422
+	{
1423
+	}
1424
+
1425
+
1426
+	/**
1427
+	 * More autosave handlers.
1428
+	 */
1429
+	protected function _ee_autosave_edit()
1430
+	{
1431
+		return; // TEMPORARILY EXITING CAUSE THIS IS A TODO
1432
+	}
1433
+
1434
+
1435
+	/**
1436
+	 *    _generate_publish_box_extra_content
1437
+	 */
1438
+	private function _generate_publish_box_extra_content()
1439
+	{
1440
+		// load formatter helper
1441
+		// args for getting related registrations
1442
+		$approved_query_args = array(
1443
+			array(
1444
+				'REG_deleted' => 0,
1445
+				'STS_ID'      => EEM_Registration::status_id_approved,
1446
+			),
1447
+		);
1448
+		$not_approved_query_args = array(
1449
+			array(
1450
+				'REG_deleted' => 0,
1451
+				'STS_ID'      => EEM_Registration::status_id_not_approved,
1452
+			),
1453
+		);
1454
+		$pending_payment_query_args = array(
1455
+			array(
1456
+				'REG_deleted' => 0,
1457
+				'STS_ID'      => EEM_Registration::status_id_pending_payment,
1458
+			),
1459
+		);
1460
+		// publish box
1461
+		$publish_box_extra_args = array(
1462
+			'view_approved_reg_url'        => add_query_arg(
1463
+				array(
1464
+					'action'      => 'default',
1465
+					'event_id'    => $this->_cpt_model_obj->ID(),
1466
+					'_reg_status' => EEM_Registration::status_id_approved,
1467
+				),
1468
+				REG_ADMIN_URL
1469
+			),
1470
+			'view_not_approved_reg_url'    => add_query_arg(
1471
+				array(
1472
+					'action'      => 'default',
1473
+					'event_id'    => $this->_cpt_model_obj->ID(),
1474
+					'_reg_status' => EEM_Registration::status_id_not_approved,
1475
+				),
1476
+				REG_ADMIN_URL
1477
+			),
1478
+			'view_pending_payment_reg_url' => add_query_arg(
1479
+				array(
1480
+					'action'      => 'default',
1481
+					'event_id'    => $this->_cpt_model_obj->ID(),
1482
+					'_reg_status' => EEM_Registration::status_id_pending_payment,
1483
+				),
1484
+				REG_ADMIN_URL
1485
+			),
1486
+			'approved_regs'                => $this->_cpt_model_obj->count_related(
1487
+				'Registration',
1488
+				$approved_query_args
1489
+			),
1490
+			'not_approved_regs'            => $this->_cpt_model_obj->count_related(
1491
+				'Registration',
1492
+				$not_approved_query_args
1493
+			),
1494
+			'pending_payment_regs'         => $this->_cpt_model_obj->count_related(
1495
+				'Registration',
1496
+				$pending_payment_query_args
1497
+			),
1498
+			'misc_pub_section_class'       => apply_filters(
1499
+				'FHEE_Events_Admin_Page___generate_publish_box_extra_content__misc_pub_section_class',
1500
+				'misc-pub-section'
1501
+			),
1502
+		);
1503
+		ob_start();
1504
+		do_action(
1505
+			'AHEE__Events_Admin_Page___generate_publish_box_extra_content__event_editor_overview_add',
1506
+			$this->_cpt_model_obj
1507
+		);
1508
+		$publish_box_extra_args['event_editor_overview_add'] = ob_get_clean();
1509
+		// load template
1510
+		EEH_Template::display_template(
1511
+			EVENTS_TEMPLATE_PATH . 'event_publish_box_extras.template.php',
1512
+			$publish_box_extra_args
1513
+		);
1514
+	}
1515
+
1516
+
1517
+	/**
1518
+	 * @return EE_Event
1519
+	 */
1520
+	public function get_event_object()
1521
+	{
1522
+		return $this->_cpt_model_obj;
1523
+	}
1524
+
1525
+
1526
+
1527
+
1528
+	/** METABOXES * */
1529
+	/**
1530
+	 * _register_event_editor_meta_boxes
1531
+	 * add all metaboxes related to the event_editor
1532
+	 *
1533
+	 * @return void
1534
+	 */
1535
+	protected function _register_event_editor_meta_boxes()
1536
+	{
1537
+		$this->verify_cpt_object();
1538
+		add_meta_box(
1539
+			'espresso_event_editor_tickets',
1540
+			esc_html__('Event Datetime & Ticket', 'event_espresso'),
1541
+			array($this, 'ticket_metabox'),
1542
+			$this->page_slug,
1543
+			'normal',
1544
+			'high'
1545
+		);
1546
+		add_meta_box(
1547
+			'espresso_event_editor_event_options',
1548
+			esc_html__('Event Registration Options', 'event_espresso'),
1549
+			array($this, 'registration_options_meta_box'),
1550
+			$this->page_slug,
1551
+			'side',
1552
+			'default'
1553
+		);
1554
+		// NOTE: if you're looking for other metaboxes in here,
1555
+		// where a metabox has a related management page in the admin
1556
+		// you will find it setup in the related management page's "_Hooks" file.
1557
+		// i.e. messages metabox is found in "espresso_events_Messages_Hooks.class.php".
1558
+	}
1559
+
1560
+
1561
+	/**
1562
+	 * @throws DomainException
1563
+	 * @throws EE_Error
1564
+	 */
1565
+	public function ticket_metabox()
1566
+	{
1567
+		$existing_datetime_ids = $existing_ticket_ids = array();
1568
+		// defaults for template args
1569
+		$template_args = array(
1570
+			'existing_datetime_ids'    => '',
1571
+			'event_datetime_help_link' => '',
1572
+			'ticket_options_help_link' => '',
1573
+			'time'                     => null,
1574
+			'ticket_rows'              => '',
1575
+			'existing_ticket_ids'      => '',
1576
+			'total_ticket_rows'        => 1,
1577
+			'ticket_js_structure'      => '',
1578
+			'trash_icon'               => 'ee-lock-icon',
1579
+			'disabled'                 => '',
1580
+		);
1581
+		$event_id = is_object($this->_cpt_model_obj) ? $this->_cpt_model_obj->ID() : null;
1582
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1583
+		/**
1584
+		 * 1. Start with retrieving Datetimes
1585
+		 * 2. Fore each datetime get related tickets
1586
+		 * 3. For each ticket get related prices
1587
+		 */
1588
+		$times = EE_Registry::instance()->load_model('Datetime')->get_all_event_dates($event_id);
1589
+		/** @type EE_Datetime $first_datetime */
1590
+		$first_datetime = reset($times);
1591
+		// do we get related tickets?
1592
+		if (
1593
+			$first_datetime instanceof EE_Datetime
1594
+			&& $first_datetime->ID() !== 0
1595
+		) {
1596
+			$existing_datetime_ids[] = $first_datetime->get('DTT_ID');
1597
+			$template_args['time'] = $first_datetime;
1598
+			$related_tickets = $first_datetime->tickets(
1599
+				array(
1600
+					array('OR' => array('TKT_deleted' => 1, 'TKT_deleted*' => 0)),
1601
+					'default_where_conditions' => 'none',
1602
+				)
1603
+			);
1604
+			if (! empty($related_tickets)) {
1605
+				$template_args['total_ticket_rows'] = count($related_tickets);
1606
+				$row = 0;
1607
+				foreach ($related_tickets as $ticket) {
1608
+					$existing_ticket_ids[] = $ticket->get('TKT_ID');
1609
+					$template_args['ticket_rows'] .= $this->_get_ticket_row($ticket, false, $row);
1610
+					$row++;
1611
+				}
1612
+			} else {
1613
+				$template_args['total_ticket_rows'] = 1;
1614
+				/** @type EE_Ticket $ticket */
1615
+				$ticket = EE_Registry::instance()->load_model('Ticket')->create_default_object();
1616
+				$template_args['ticket_rows'] .= $this->_get_ticket_row($ticket);
1617
+			}
1618
+		} else {
1619
+			$template_args['time'] = $times[0];
1620
+			/** @type EE_Ticket $ticket */
1621
+			$ticket = EE_Registry::instance()->load_model('Ticket')->get_all_default_tickets();
1622
+			$template_args['ticket_rows'] .= $this->_get_ticket_row($ticket[1]);
1623
+			// NOTE: we're just sending the first default row
1624
+			// (decaf can't manage default tickets so this should be sufficient);
1625
+		}
1626
+		$template_args['event_datetime_help_link'] = $this->_get_help_tab_link(
1627
+			'event_editor_event_datetimes_help_tab'
1628
+		);
1629
+		$template_args['ticket_options_help_link'] = $this->_get_help_tab_link('ticket_options_info');
1630
+		$template_args['existing_datetime_ids'] = implode(',', $existing_datetime_ids);
1631
+		$template_args['existing_ticket_ids'] = implode(',', $existing_ticket_ids);
1632
+		$template_args['ticket_js_structure'] = $this->_get_ticket_row(
1633
+			EE_Registry::instance()->load_model('Ticket')->create_default_object(),
1634
+			true
1635
+		);
1636
+		$template = apply_filters(
1637
+			'FHEE__Events_Admin_Page__ticket_metabox__template',
1638
+			EVENTS_TEMPLATE_PATH . 'event_tickets_metabox_main.template.php'
1639
+		);
1640
+		EEH_Template::display_template($template, $template_args);
1641
+	}
1642
+
1643
+
1644
+	/**
1645
+	 * Setup an individual ticket form for the decaf event editor page
1646
+	 *
1647
+	 * @access private
1648
+	 * @param  EE_Ticket $ticket   the ticket object
1649
+	 * @param  boolean   $skeleton whether we're generating a skeleton for js manipulation
1650
+	 * @param int        $row
1651
+	 * @return string generated html for the ticket row.
1652
+	 */
1653
+	private function _get_ticket_row($ticket, $skeleton = false, $row = 0)
1654
+	{
1655
+		$template_args = array(
1656
+			'tkt_status_class'    => ' tkt-status-' . $ticket->ticket_status(),
1657
+			'tkt_archive_class'   => $ticket->ticket_status() === EE_Ticket::archived && ! $skeleton ? ' tkt-archived'
1658
+				: '',
1659
+			'ticketrow'           => $skeleton ? 'TICKETNUM' : $row,
1660
+			'TKT_ID'              => $ticket->get('TKT_ID'),
1661
+			'TKT_name'            => $ticket->get('TKT_name'),
1662
+			'TKT_start_date'      => $skeleton ? '' : $ticket->get_date('TKT_start_date', 'Y-m-d h:i a'),
1663
+			'TKT_end_date'        => $skeleton ? '' : $ticket->get_date('TKT_end_date', 'Y-m-d h:i a'),
1664
+			'TKT_is_default'      => $ticket->get('TKT_is_default'),
1665
+			'TKT_qty'             => $ticket->get_pretty('TKT_qty', 'input'),
1666
+			'edit_ticketrow_name' => $skeleton ? 'TICKETNAMEATTR' : 'edit_tickets',
1667
+			'TKT_sold'            => $skeleton ? 0 : $ticket->get('TKT_sold'),
1668
+			'trash_icon'          => ($skeleton || (! empty($ticket) && ! $ticket->get('TKT_deleted')))
1669
+									 && (! empty($ticket) && $ticket->get('TKT_sold') === 0)
1670
+				? 'trash-icon dashicons dashicons-post-trash clickable' : 'ee-lock-icon',
1671
+			'disabled'            => $skeleton || (! empty($ticket) && ! $ticket->get('TKT_deleted')) ? ''
1672
+				: ' disabled=disabled',
1673
+		);
1674
+		$price = $ticket->ID() !== 0
1675
+			? $ticket->get_first_related('Price', array('default_where_conditions' => 'none'))
1676
+			: null;
1677
+		$price = $price instanceof EE_Price
1678
+			? $price
1679
+			: EEM_Price::instance()->create_default_object();
1680
+		$price_args = array(
1681
+			'price_currency_symbol' => EE_Registry::instance()->CFG->currency->sign,
1682
+			'PRC_amount'            => $price->get('PRC_amount'),
1683
+			'PRT_ID'                => $price->get('PRT_ID'),
1684
+			'PRC_ID'                => $price->get('PRC_ID'),
1685
+			'PRC_is_default'        => $price->get('PRC_is_default'),
1686
+		);
1687
+		// make sure we have default start and end dates if skeleton
1688
+		// handle rows that should NOT be empty
1689
+		if (empty($template_args['TKT_start_date'])) {
1690
+			// if empty then the start date will be now.
1691
+			$template_args['TKT_start_date'] = date('Y-m-d h:i a', current_time('timestamp'));
1692
+		}
1693
+		if (empty($template_args['TKT_end_date'])) {
1694
+			// get the earliest datetime (if present);
1695
+			$earliest_dtt = $this->_cpt_model_obj->ID() > 0
1696
+				? $this->_cpt_model_obj->get_first_related(
1697
+					'Datetime',
1698
+					array('order_by' => array('DTT_EVT_start' => 'ASC'))
1699
+				)
1700
+				: null;
1701
+			if (! empty($earliest_dtt)) {
1702
+				$template_args['TKT_end_date'] = $earliest_dtt->get_datetime('DTT_EVT_start', 'Y-m-d', 'h:i a');
1703
+			} else {
1704
+				$template_args['TKT_end_date'] = date(
1705
+					'Y-m-d h:i a',
1706
+					mktime(0, 0, 0, date("m"), date("d") + 7, date("Y"))
1707
+				);
1708
+			}
1709
+		}
1710
+		$template_args = array_merge($template_args, $price_args);
1711
+		$template = apply_filters(
1712
+			'FHEE__Events_Admin_Page__get_ticket_row__template',
1713
+			EVENTS_TEMPLATE_PATH . 'event_tickets_metabox_ticket_row.template.php',
1714
+			$ticket
1715
+		);
1716
+		return EEH_Template::display_template($template, $template_args, true);
1717
+	}
1718
+
1719
+
1720
+	/**
1721
+	 * @throws DomainException
1722
+	 */
1723
+	public function registration_options_meta_box()
1724
+	{
1725
+		$yes_no_values = array(
1726
+			array('id' => true, 'text' => esc_html__('Yes', 'event_espresso')),
1727
+			array('id' => false, 'text' => esc_html__('No', 'event_espresso')),
1728
+		);
1729
+		$default_reg_status_values = EEM_Registration::reg_status_array(
1730
+			array(
1731
+				EEM_Registration::status_id_cancelled,
1732
+				EEM_Registration::status_id_declined,
1733
+				EEM_Registration::status_id_incomplete,
1734
+			),
1735
+			true
1736
+		);
1737
+		// $template_args['is_active_select'] = EEH_Form_Fields::select_input('is_active', $yes_no_values, $this->_cpt_model_obj->is_active());
1738
+		$template_args['_event'] = $this->_cpt_model_obj;
1739
+		$template_args['event'] = $this->_cpt_model_obj;
1740
+		$template_args['active_status'] = $this->_cpt_model_obj->pretty_active_status(false);
1741
+		$template_args['additional_limit'] = $this->_cpt_model_obj->additional_limit();
1742
+		$template_args['default_registration_status'] = EEH_Form_Fields::select_input(
1743
+			'default_reg_status',
1744
+			$default_reg_status_values,
1745
+			$this->_cpt_model_obj->default_registration_status()
1746
+		);
1747
+		$template_args['display_description'] = EEH_Form_Fields::select_input(
1748
+			'display_desc',
1749
+			$yes_no_values,
1750
+			$this->_cpt_model_obj->display_description()
1751
+		);
1752
+		$template_args['display_ticket_selector'] = EEH_Form_Fields::select_input(
1753
+			'display_ticket_selector',
1754
+			$yes_no_values,
1755
+			$this->_cpt_model_obj->display_ticket_selector(),
1756
+			'',
1757
+			'',
1758
+			false
1759
+		);
1760
+		$template_args['additional_registration_options'] = apply_filters(
1761
+			'FHEE__Events_Admin_Page__registration_options_meta_box__additional_registration_options',
1762
+			'',
1763
+			$template_args,
1764
+			$yes_no_values,
1765
+			$default_reg_status_values
1766
+		);
1767
+		EEH_Template::display_template(
1768
+			EVENTS_TEMPLATE_PATH . 'event_registration_options.template.php',
1769
+			$template_args
1770
+		);
1771
+	}
1772
+
1773
+
1774
+	/**
1775
+	 * _get_events()
1776
+	 * This method simply returns all the events (for the given _view and paging)
1777
+	 *
1778
+	 * @access public
1779
+	 * @param int  $per_page     count of items per page (20 default);
1780
+	 * @param int  $current_page what is the current page being viewed.
1781
+	 * @param bool $count        if TRUE then we just return a count of ALL events matching the given _view.
1782
+	 *                           If FALSE then we return an array of event objects
1783
+	 *                           that match the given _view and paging parameters.
1784
+	 * @return array an array of event objects.
1785
+	 */
1786
+	public function get_events($per_page = 10, $current_page = 1, $count = false)
1787
+	{
1788
+		$EEME = $this->_event_model();
1789
+		$offset = ($current_page - 1) * $per_page;
1790
+		$limit = $count ? null : $offset . ',' . $per_page;
1791
+		$orderby = isset($this->_req_data['orderby']) ? $this->_req_data['orderby'] : 'EVT_ID';
1792
+		$order = isset($this->_req_data['order']) ? $this->_req_data['order'] : "DESC";
1793
+		if (isset($this->_req_data['month_range'])) {
1794
+			$pieces = explode(' ', $this->_req_data['month_range'], 3);
1795
+			// simulate the FIRST day of the month, that fixes issues for months like February
1796
+			// where PHP doesn't know what to assume for date.
1797
+			// @see https://events.codebasehq.com/projects/event-espresso/tickets/10437
1798
+			$month_r = ! empty($pieces[0]) ? date('m', \EEH_DTT_Helper::first_of_month_timestamp($pieces[0])) : '';
1799
+			$year_r = ! empty($pieces[1]) ? $pieces[1] : '';
1800
+		}
1801
+		$where = array();
1802
+		$status = isset($this->_req_data['status']) ? $this->_req_data['status'] : null;
1803
+		// determine what post_status our condition will have for the query.
1804
+		switch ($status) {
1805
+			case 'month':
1806
+			case 'today':
1807
+			case null:
1808
+			case 'all':
1809
+				break;
1810
+			case 'draft':
1811
+				$where['status'] = array('IN', array('draft', 'auto-draft'));
1812
+				break;
1813
+			default:
1814
+				$where['status'] = $status;
1815
+		}
1816
+		// categories?
1817
+		$category = isset($this->_req_data['EVT_CAT']) && $this->_req_data['EVT_CAT'] > 0
1818
+			? $this->_req_data['EVT_CAT'] : null;
1819
+		if (! empty($category)) {
1820
+			$where['Term_Taxonomy.taxonomy'] = EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY;
1821
+			$where['Term_Taxonomy.term_id'] = $category;
1822
+		}
1823
+		// date where conditions
1824
+		$start_formats = EEM_Datetime::instance()->get_formats_for('DTT_EVT_start');
1825
+		if (isset($this->_req_data['month_range']) && $this->_req_data['month_range'] != '') {
1826
+			$DateTime = new DateTime(
1827
+				$year_r . '-' . $month_r . '-01 00:00:00',
1828
+				new DateTimeZone('UTC')
1829
+			);
1830
+			$start = $DateTime->getTimestamp();
1831
+			// set the datetime to be the end of the month
1832
+			$DateTime->setDate(
1833
+				$year_r,
1834
+				$month_r,
1835
+				$DateTime->format('t')
1836
+			)->setTime(23, 59, 59);
1837
+			$end = $DateTime->getTimestamp();
1838
+			$where['Datetime.DTT_EVT_start'] = array('BETWEEN', array($start, $end));
1839
+		} elseif (isset($this->_req_data['status']) && $this->_req_data['status'] == 'today') {
1840
+			$DateTime = new DateTime('now', new DateTimeZone(EEM_Event::instance()->get_timezone()));
1841
+			$start = $DateTime->setTime(0, 0, 0)->format(implode(' ', $start_formats));
1842
+			$end = $DateTime->setTime(23, 59, 59)->format(implode(' ', $start_formats));
1843
+			$where['Datetime.DTT_EVT_start'] = array('BETWEEN', array($start, $end));
1844
+		} elseif (isset($this->_req_data['status']) && $this->_req_data['status'] == 'month') {
1845
+			$now = date('Y-m-01');
1846
+			$DateTime = new DateTime($now, new DateTimeZone(EEM_Event::instance()->get_timezone()));
1847
+			$start = $DateTime->setTime(0, 0, 0)->format(implode(' ', $start_formats));
1848
+			$end = $DateTime->setDate(date('Y'), date('m'), $DateTime->format('t'))
1849
+							->setTime(23, 59, 59)
1850
+							->format(implode(' ', $start_formats));
1851
+			$where['Datetime.DTT_EVT_start'] = array('BETWEEN', array($start, $end));
1852
+		}
1853
+		if (! EE_Registry::instance()->CAP->current_user_can('ee_read_others_events', 'get_events')) {
1854
+			$where['EVT_wp_user'] = get_current_user_id();
1855
+		} else {
1856
+			if (! isset($where['status'])) {
1857
+				if (! EE_Registry::instance()->CAP->current_user_can('ee_read_private_events', 'get_events')) {
1858
+					$where['OR'] = array(
1859
+						'status*restrict_private' => array('!=', 'private'),
1860
+						'AND'                     => array(
1861
+							'status*inclusive' => array('=', 'private'),
1862
+							'EVT_wp_user'      => get_current_user_id(),
1863
+						),
1864
+					);
1865
+				}
1866
+			}
1867
+		}
1868
+		if (isset($this->_req_data['EVT_wp_user'])) {
1869
+			if (
1870
+				$this->_req_data['EVT_wp_user'] != get_current_user_id()
1871
+				&& EE_Registry::instance()->CAP->current_user_can('ee_read_others_events', 'get_events')
1872
+			) {
1873
+				$where['EVT_wp_user'] = $this->_req_data['EVT_wp_user'];
1874
+			}
1875
+		}
1876
+		// search query handling
1877
+		if (isset($this->_req_data['s'])) {
1878
+			$search_string = '%' . $this->_req_data['s'] . '%';
1879
+			$where['OR'] = array(
1880
+				'EVT_name'       => array('LIKE', $search_string),
1881
+				'EVT_desc'       => array('LIKE', $search_string),
1882
+				'EVT_short_desc' => array('LIKE', $search_string),
1883
+			);
1884
+		}
1885
+		// filter events by venue.
1886
+		if (isset($this->_req_data['venue']) && ! empty($this->_req_data['venue'])) {
1887
+			$where['Venue.VNU_ID'] = absint($this->_req_data['venue']);
1888
+		}
1889
+		$where = apply_filters('FHEE__Events_Admin_Page__get_events__where', $where, $this->_req_data);
1890
+		$query_params = apply_filters(
1891
+			'FHEE__Events_Admin_Page__get_events__query_params',
1892
+			array(
1893
+				$where,
1894
+				'limit'    => $limit,
1895
+				'order_by' => $orderby,
1896
+				'order'    => $order,
1897
+				'group_by' => 'EVT_ID',
1898
+			),
1899
+			$this->_req_data
1900
+		);
1901
+
1902
+		// let's first check if we have special requests coming in.
1903
+		if (isset($this->_req_data['active_status'])) {
1904
+			switch ($this->_req_data['active_status']) {
1905
+				case 'upcoming':
1906
+					return $EEME->get_upcoming_events($query_params, $count);
1907
+					break;
1908
+				case 'expired':
1909
+					return $EEME->get_expired_events($query_params, $count);
1910
+					break;
1911
+				case 'active':
1912
+					return $EEME->get_active_events($query_params, $count);
1913
+					break;
1914
+				case 'inactive':
1915
+					return $EEME->get_inactive_events($query_params, $count);
1916
+					break;
1917
+			}
1918
+		}
1919
+
1920
+		$events = $count ? $EEME->count(array($where), 'EVT_ID', true) : $EEME->get_all($query_params);
1921
+		return $events;
1922
+	}
1923
+
1924
+
1925
+	/**
1926
+	 * handling for WordPress CPT actions (trash, restore, delete)
1927
+	 *
1928
+	 * @param string $post_id
1929
+	 */
1930
+	public function trash_cpt_item($post_id)
1931
+	{
1932
+		$this->_req_data['EVT_ID'] = $post_id;
1933
+		$this->_trash_or_restore_event('trash', false);
1934
+	}
1935
+
1936
+
1937
+	/**
1938
+	 * @param string $post_id
1939
+	 */
1940
+	public function restore_cpt_item($post_id)
1941
+	{
1942
+		$this->_req_data['EVT_ID'] = $post_id;
1943
+		$this->_trash_or_restore_event('draft', false);
1944
+	}
1945
+
1946
+
1947
+	/**
1948
+	 * @param string $post_id
1949
+	 */
1950
+	public function delete_cpt_item($post_id)
1951
+	{
1952
+		throw new EE_Error(esc_html__('Please contact Event Espresso support with the details of the steps taken to produce this error.', 'event_espresso'));
1953
+		$this->_req_data['EVT_ID'] = $post_id;
1954
+		$this->_delete_event();
1955
+	}
1956
+
1957
+
1958
+	/**
1959
+	 * _trash_or_restore_event
1960
+	 *
1961
+	 * @access protected
1962
+	 * @param  string $event_status
1963
+	 * @param bool    $redirect_after
1964
+	 */
1965
+	protected function _trash_or_restore_event($event_status = 'trash', $redirect_after = true)
1966
+	{
1967
+		// determine the event id and set to array.
1968
+		$EVT_ID = isset($this->_req_data['EVT_ID']) ? absint($this->_req_data['EVT_ID']) : false;
1969
+		// loop thru events
1970
+		if ($EVT_ID) {
1971
+			// clean status
1972
+			$event_status = sanitize_key($event_status);
1973
+			// grab status
1974
+			if (! empty($event_status)) {
1975
+				$success = $this->_change_event_status($EVT_ID, $event_status);
1976
+			} else {
1977
+				$success = false;
1978
+				$msg = esc_html__(
1979
+					'An error occurred. The event could not be moved to the trash because a valid event status was not not supplied.',
1980
+					'event_espresso'
1981
+				);
1982
+				EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1983
+			}
1984
+		} else {
1985
+			$success = false;
1986
+			$msg = esc_html__(
1987
+				'An error occurred. The event could not be moved to the trash because a valid event ID was not not supplied.',
1988
+				'event_espresso'
1989
+			);
1990
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1991
+		}
1992
+		$action = $event_status == 'trash' ? 'moved to the trash' : 'restored from the trash';
1993
+		if ($redirect_after) {
1994
+			$this->_redirect_after_action($success, 'Event', $action, array('action' => 'default'));
1995
+		}
1996
+	}
1997
+
1998
+
1999
+	/**
2000
+	 * _trash_or_restore_events
2001
+	 *
2002
+	 * @access protected
2003
+	 * @param  string $event_status
2004
+	 * @return void
2005
+	 */
2006
+	protected function _trash_or_restore_events($event_status = 'trash')
2007
+	{
2008
+		// clean status
2009
+		$event_status = sanitize_key($event_status);
2010
+		// grab status
2011
+		if (! empty($event_status)) {
2012
+			$success = true;
2013
+			// determine the event id and set to array.
2014
+			$EVT_IDs = isset($this->_req_data['EVT_IDs']) ? (array) $this->_req_data['EVT_IDs'] : array();
2015
+			// loop thru events
2016
+			foreach ($EVT_IDs as $EVT_ID) {
2017
+				if ($EVT_ID = absint($EVT_ID)) {
2018
+					$results = $this->_change_event_status($EVT_ID, $event_status);
2019
+					$success = $results !== false ? $success : false;
2020
+				} else {
2021
+					$msg = sprintf(
2022
+						esc_html__(
2023
+							'An error occurred. Event #%d could not be moved to the trash because a valid event ID was not not supplied.',
2024
+							'event_espresso'
2025
+						),
2026
+						$EVT_ID
2027
+					);
2028
+					EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2029
+					$success = false;
2030
+				}
2031
+			}
2032
+		} else {
2033
+			$success = false;
2034
+			$msg = esc_html__(
2035
+				'An error occurred. The event could not be moved to the trash because a valid event status was not not supplied.',
2036
+				'event_espresso'
2037
+			);
2038
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2039
+		}
2040
+		// in order to force a pluralized result message we need to send back a success status greater than 1
2041
+		$success = $success ? 2 : false;
2042
+		$action = $event_status == 'trash' ? 'moved to the trash' : 'restored from the trash';
2043
+		$this->_redirect_after_action($success, 'Events', $action, array('action' => 'default'));
2044
+	}
2045
+
2046
+
2047
+	/**
2048
+	 * @param  int    $EVT_ID
2049
+	 * @param  string $event_status
2050
+	 * @return bool
2051
+	 */
2052
+	private function _change_event_status($EVT_ID = 0, $event_status = '')
2053
+	{
2054
+		// grab event id
2055
+		if (! $EVT_ID) {
2056
+			$msg = esc_html__(
2057
+				'An error occurred. No Event ID or an invalid Event ID was received.',
2058
+				'event_espresso'
2059
+			);
2060
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2061
+			return false;
2062
+		}
2063
+		$this->_cpt_model_obj = EEM_Event::instance()->get_one_by_ID($EVT_ID);
2064
+		// clean status
2065
+		$event_status = sanitize_key($event_status);
2066
+		// grab status
2067
+		if (empty($event_status)) {
2068
+			$msg = esc_html__(
2069
+				'An error occurred. No Event Status or an invalid Event Status was received.',
2070
+				'event_espresso'
2071
+			);
2072
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2073
+			return false;
2074
+		}
2075
+		// was event trashed or restored ?
2076
+		switch ($event_status) {
2077
+			case 'draft':
2078
+				$action = 'restored from the trash';
2079
+				$hook = 'AHEE_event_restored_from_trash';
2080
+				break;
2081
+			case 'trash':
2082
+				$action = 'moved to the trash';
2083
+				$hook = 'AHEE_event_moved_to_trash';
2084
+				break;
2085
+			default:
2086
+				$action = 'updated';
2087
+				$hook = false;
2088
+		}
2089
+		// use class to change status
2090
+		$this->_cpt_model_obj->set_status($event_status);
2091
+		$success = $this->_cpt_model_obj->save();
2092
+		if (! $success) {
2093
+			$msg = sprintf(esc_html__('An error occurred. The event could not be %s.', 'event_espresso'), $action);
2094
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2095
+			return false;
2096
+		}
2097
+		if ($hook) {
2098
+			do_action($hook);
2099
+		}
2100
+		return true;
2101
+	}
2102
+
2103
+
2104
+	/**
2105
+	 * @param array $event_ids
2106
+	 * @return array
2107
+	 * @since   $VID:$
2108
+	 */
2109
+	private function cleanEventIds(array $event_ids)
2110
+	{
2111
+		return array_map('absint', $event_ids);
2112
+	}
2113
+
2114
+
2115
+	/**
2116
+	 * @return array
2117
+	 * @since   $VID:$
2118
+	 */
2119
+	private function getEventIdsFromRequest()
2120
+	{
2121
+		$event_ids = isset($this->_req_data['EVT_ID']) ? $this->_req_data['EVT_ID'] : [];
2122
+		$event_ids = is_string($event_ids) ? explode(',', $event_ids) : (array) $event_ids;
2123
+		return $this->cleanEventIds($event_ids);
2124
+	}
2125
+
2126
+
2127
+	/**
2128
+	 * @param bool $preview_delete
2129
+	 * @throws EE_Error
2130
+	 */
2131
+	protected function _delete_event($preview_delete = true)
2132
+	{
2133
+		$this->_delete_events($preview_delete);
2134
+	}
2135
+
2136
+
2137
+	/**
2138
+	 * Gets the tree traversal batch persister.
2139
+	 * @since 4.10.12.p
2140
+	 * @return NodeGroupDao
2141
+	 * @throws InvalidArgumentException
2142
+	 * @throws InvalidDataTypeException
2143
+	 * @throws InvalidInterfaceException
2144
+	 */
2145
+	protected function getModelObjNodeGroupPersister()
2146
+	{
2147
+		if (! $this->model_obj_node_group_persister instanceof NodeGroupDao) {
2148
+			$this->model_obj_node_group_persister = $this->getLoader()->load('\EventEspresso\core\services\orm\tree_traversal\NodeGroupDao');
2149
+		}
2150
+		return $this->model_obj_node_group_persister;
2151
+	}
2152
+
2153
+
2154
+	/**
2155
+	 * @param bool $preview_delete
2156
+	 * @return void
2157
+	 * @throws EE_Error
2158
+	 */
2159
+	protected function _delete_events($preview_delete = true)
2160
+	{
2161
+		$event_ids = $this->getEventIdsFromRequest();
2162
+		if ($preview_delete) {
2163
+			$this->generateDeletionPreview($event_ids);
2164
+		} else {
2165
+			EEM_Event::instance()->delete_permanently([['EVT_ID' => ['IN', $event_ids]]]);
2166
+		}
2167
+	}
2168
+
2169
+
2170
+	/**
2171
+	 * @param array $event_ids
2172
+	 */
2173
+	protected function generateDeletionPreview(array $event_ids)
2174
+	{
2175
+		$event_ids = $this->cleanEventIds($event_ids);
2176
+		// Set a code we can use to reference this deletion task in the batch jobs and preview page.
2177
+		$deletion_job_code = $this->getModelObjNodeGroupPersister()->generateGroupCode();
2178
+		$return_url = EE_Admin_Page::add_query_args_and_nonce(
2179
+			[
2180
+				'action' => 'preview_deletion',
2181
+				'deletion_job_code' => $deletion_job_code,
2182
+			],
2183
+			$this->_admin_base_url
2184
+		);
2185
+		EEH_URL::safeRedirectAndExit(
2186
+			EE_Admin_Page::add_query_args_and_nonce(
2187
+				[
2188
+					'page'              => 'espresso_batch',
2189
+					'batch'             => EED_Batch::batch_job,
2190
+					'EVT_IDs'           => $event_ids,
2191
+					'deletion_job_code' => $deletion_job_code,
2192
+					'job_handler'       => urlencode('EventEspressoBatchRequest\JobHandlers\PreviewEventDeletion'),
2193
+					'return_url'        => urlencode($return_url),
2194
+				],
2195
+				admin_url()
2196
+			)
2197
+		);
2198
+	}
2199
+
2200
+	/**
2201
+	 * Checks for a POST submission
2202
+	 * @since 4.10.12.p
2203
+	 */
2204
+	protected function confirmDeletion()
2205
+	{
2206
+		$deletion_redirect_logic = $this->getLoader()->getShared('\EventEspresso\core\domain\services\admin\events\data\ConfirmDeletion');
2207
+		$deletion_redirect_logic->handle($this->get_request_data(), $this->admin_base_url());
2208
+	}
2209
+
2210
+	/**
2211
+	 * A page for users to preview what exactly will be deleted, and confirm they want to delete it.
2212
+	 * @since 4.10.12.p
2213
+	 * @throws EE_Error
2214
+	 */
2215
+	protected function previewDeletion()
2216
+	{
2217
+		$preview_deletion_logic = $this->getLoader()->getShared('\EventEspresso\core\domain\services\admin\events\data\PreviewDeletion');
2218
+		$this->set_template_args($preview_deletion_logic->handle($this->get_request_data(), $this->admin_base_url()));
2219
+		$this->display_admin_page_with_no_sidebar();
2220
+	}
2221
+
2222
+	/**
2223
+	 * get total number of events
2224
+	 *
2225
+	 * @access public
2226
+	 * @return int
2227
+	 */
2228
+	public function total_events()
2229
+	{
2230
+		$count = EEM_Event::instance()->count(array('caps' => 'read_admin'), 'EVT_ID', true);
2231
+		return $count;
2232
+	}
2233
+
2234
+
2235
+	/**
2236
+	 * get total number of draft events
2237
+	 *
2238
+	 * @access public
2239
+	 * @return int
2240
+	 */
2241
+	public function total_events_draft()
2242
+	{
2243
+		$where = array(
2244
+			'status' => array('IN', array('draft', 'auto-draft')),
2245
+		);
2246
+		$count = EEM_Event::instance()->count(array($where, 'caps' => 'read_admin'), 'EVT_ID', true);
2247
+		return $count;
2248
+	}
2249
+
2250
+
2251
+	/**
2252
+	 * get total number of trashed events
2253
+	 *
2254
+	 * @access public
2255
+	 * @return int
2256
+	 */
2257
+	public function total_trashed_events()
2258
+	{
2259
+		$where = array(
2260
+			'status' => 'trash',
2261
+		);
2262
+		$count = EEM_Event::instance()->count(array($where, 'caps' => 'read_admin'), 'EVT_ID', true);
2263
+		return $count;
2264
+	}
2265
+
2266
+
2267
+	/**
2268
+	 *    _default_event_settings
2269
+	 *    This generates the Default Settings Tab
2270
+	 *
2271
+	 * @return void
2272
+	 * @throws EE_Error
2273
+	 */
2274
+	protected function _default_event_settings()
2275
+	{
2276
+		$this->_set_add_edit_form_tags('update_default_event_settings');
2277
+		$this->_set_publish_post_box_vars(null, false, false, null, false);
2278
+		$this->_template_args['admin_page_content'] = $this->_default_event_settings_form()->get_html();
2279
+		$this->display_admin_page_with_sidebar();
2280
+	}
2281
+
2282
+
2283
+	/**
2284
+	 * Return the form for event settings.
2285
+	 *
2286
+	 * @return EE_Form_Section_Proper
2287
+	 * @throws EE_Error
2288
+	 */
2289
+	protected function _default_event_settings_form()
2290
+	{
2291
+		$registration_config = EE_Registry::instance()->CFG->registration;
2292
+		$registration_stati_for_selection = EEM_Registration::reg_status_array(
2293
+			// exclude
2294
+			array(
2295
+				EEM_Registration::status_id_cancelled,
2296
+				EEM_Registration::status_id_declined,
2297
+				EEM_Registration::status_id_incomplete,
2298
+				EEM_Registration::status_id_wait_list,
2299
+			),
2300
+			true
2301
+		);
2302
+		return new EE_Form_Section_Proper(
2303
+			array(
2304
+				'name'            => 'update_default_event_settings',
2305
+				'html_id'         => 'update_default_event_settings',
2306
+				'html_class'      => 'form-table',
2307
+				'layout_strategy' => new EE_Admin_Two_Column_Layout(),
2308
+				'subsections'     => apply_filters(
2309
+					'FHEE__Events_Admin_Page___default_event_settings_form__form_subsections',
2310
+					array(
2311
+						'default_reg_status'  => new EE_Select_Input(
2312
+							$registration_stati_for_selection,
2313
+							array(
2314
+								'default'         => isset($registration_config->default_STS_ID)
2315
+													 && array_key_exists(
2316
+														 $registration_config->default_STS_ID,
2317
+														 $registration_stati_for_selection
2318
+													 )
2319
+									? sanitize_text_field($registration_config->default_STS_ID)
2320
+									: EEM_Registration::status_id_pending_payment,
2321
+								'html_label_text' => esc_html__('Default Registration Status', 'event_espresso')
2322
+													 . EEH_Template::get_help_tab_link(
2323
+														 'default_settings_status_help_tab'
2324
+													 ),
2325
+								'html_help_text'  => esc_html__(
2326
+									'This setting allows you to preselect what the default registration status setting is when creating an event.  Note that changing this setting does NOT retroactively apply it to existing events.',
2327
+									'event_espresso'
2328
+								),
2329
+							)
2330
+						),
2331
+						'default_max_tickets' => new EE_Integer_Input(
2332
+							array(
2333
+								'default'         => isset($registration_config->default_maximum_number_of_tickets)
2334
+									? $registration_config->default_maximum_number_of_tickets
2335
+									: EEM_Event::get_default_additional_limit(),
2336
+								'html_label_text' => esc_html__(
2337
+									'Default Maximum Tickets Allowed Per Order:',
2338
+									'event_espresso'
2339
+								)
2340
+													 . EEH_Template::get_help_tab_link(
2341
+														 'default_maximum_tickets_help_tab"'
2342
+													 ),
2343
+								'html_help_text'  => esc_html__(
2344
+									'This setting allows you to indicate what will be the default for the maximum number of tickets per order when creating new events.',
2345
+									'event_espresso'
2346
+								),
2347
+							)
2348
+						),
2349
+					)
2350
+				),
2351
+			)
2352
+		);
2353
+	}
2354
+
2355
+
2356
+	/**
2357
+	 * _update_default_event_settings
2358
+	 *
2359
+	 * @access protected
2360
+	 * @return void
2361
+	 * @throws EE_Error
2362
+	 */
2363
+	protected function _update_default_event_settings()
2364
+	{
2365
+		$registration_config = EE_Registry::instance()->CFG->registration;
2366
+		$form = $this->_default_event_settings_form();
2367
+		if ($form->was_submitted()) {
2368
+			$form->receive_form_submission();
2369
+			if ($form->is_valid()) {
2370
+				$valid_data = $form->valid_data();
2371
+				if (isset($valid_data['default_reg_status'])) {
2372
+					$registration_config->default_STS_ID = $valid_data['default_reg_status'];
2373
+				}
2374
+				if (isset($valid_data['default_max_tickets'])) {
2375
+					$registration_config->default_maximum_number_of_tickets = $valid_data['default_max_tickets'];
2376
+				}
2377
+				// update because data was valid!
2378
+				EE_Registry::instance()->CFG->update_espresso_config();
2379
+				EE_Error::overwrite_success();
2380
+				EE_Error::add_success(
2381
+					esc_html__('Default Event Settings were updated', 'event_espresso')
2382
+				);
2383
+			}
2384
+		}
2385
+		$this->_redirect_after_action(0, '', '', array('action' => 'default_event_settings'), true);
2386
+	}
2387
+
2388
+
2389
+	/*************        Templates        *************/
2390
+	protected function _template_settings()
2391
+	{
2392
+		$this->_admin_page_title = esc_html__('Template Settings (Preview)', 'event_espresso');
2393
+		$this->_template_args['preview_img'] = '<img src="'
2394
+											   . EVENTS_ASSETS_URL
2395
+											   . '/images/'
2396
+											   . 'caffeinated_template_features.jpg" alt="'
2397
+											   . esc_attr__('Template Settings Preview screenshot', 'event_espresso')
2398
+											   . '" />';
2399
+		$this->_template_args['preview_text'] = '<strong>'
2400
+												. esc_html__(
2401
+													'Template Settings is a feature that is only available in the premium version of Event Espresso 4 which is available with a support license purchase on EventEspresso.com. Template Settings allow you to configure some of the appearance options for both the Event List and Event Details pages.',
2402
+													'event_espresso'
2403
+												) . '</strong>';
2404
+		$this->display_admin_caf_preview_page('template_settings_tab');
2405
+	}
2406
+
2407
+
2408
+	/** Event Category Stuff **/
2409
+	/**
2410
+	 * set the _category property with the category object for the loaded page.
2411
+	 *
2412
+	 * @access private
2413
+	 * @return void
2414
+	 */
2415
+	private function _set_category_object()
2416
+	{
2417
+		if (isset($this->_category->id) && ! empty($this->_category->id)) {
2418
+			return;
2419
+		} //already have the category object so get out.
2420
+		// set default category object
2421
+		$this->_set_empty_category_object();
2422
+		// only set if we've got an id
2423
+		if (! isset($this->_req_data['EVT_CAT_ID'])) {
2424
+			return;
2425
+		}
2426
+		$category_id = absint($this->_req_data['EVT_CAT_ID']);
2427
+		$term = get_term($category_id, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY);
2428
+		if (! empty($term)) {
2429
+			$this->_category->category_name = $term->name;
2430
+			$this->_category->category_identifier = $term->slug;
2431
+			$this->_category->category_desc = $term->description;
2432
+			$this->_category->id = $term->term_id;
2433
+			$this->_category->parent = $term->parent;
2434
+		}
2435
+	}
2436
+
2437
+
2438
+	/**
2439
+	 * Clears out category properties.
2440
+	 */
2441
+	private function _set_empty_category_object()
2442
+	{
2443
+		$this->_category = new stdClass();
2444
+		$this->_category->category_name = $this->_category->category_identifier = $this->_category->category_desc = '';
2445
+		$this->_category->id = $this->_category->parent = 0;
2446
+	}
2447
+
2448
+
2449
+	/**
2450
+	 * @throws EE_Error
2451
+	 */
2452
+	protected function _category_list_table()
2453
+	{
2454
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2455
+		$this->_search_btn_label = esc_html__('Categories', 'event_espresso');
2456
+		$this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
2457
+			'add_category',
2458
+			'add_category',
2459
+			array(),
2460
+			'add-new-h2'
2461
+		);
2462
+		$this->display_admin_list_table_page_with_sidebar();
2463
+	}
2464
+
2465
+
2466
+	/**
2467
+	 * Output category details view.
2468
+	 */
2469
+	protected function _category_details($view)
2470
+	{
2471
+		// load formatter helper
2472
+		// load field generator helper
2473
+		$route = $view == 'edit' ? 'update_category' : 'insert_category';
2474
+		$this->_set_add_edit_form_tags($route);
2475
+		$this->_set_category_object();
2476
+		$id = ! empty($this->_category->id) ? $this->_category->id : '';
2477
+		$delete_action = 'delete_category';
2478
+		// custom redirect
2479
+		$redirect = EE_Admin_Page::add_query_args_and_nonce(
2480
+			array('action' => 'category_list'),
2481
+			$this->_admin_base_url
2482
+		);
2483
+		$this->_set_publish_post_box_vars('EVT_CAT_ID', $id, $delete_action, $redirect);
2484
+		// take care of contents
2485
+		$this->_template_args['admin_page_content'] = $this->_category_details_content();
2486
+		$this->display_admin_page_with_sidebar();
2487
+	}
2488
+
2489
+
2490
+	/**
2491
+	 * Output category details content.
2492
+	 */
2493
+	protected function _category_details_content()
2494
+	{
2495
+		$editor_args['category_desc'] = array(
2496
+			'type'          => 'wp_editor',
2497
+			'value'         => EEH_Formatter::admin_format_content($this->_category->category_desc),
2498
+			'class'         => 'my_editor_custom',
2499
+			'wpeditor_args' => array('media_buttons' => false),
2500
+		);
2501
+		$_wp_editor = $this->_generate_admin_form_fields($editor_args, 'array');
2502
+		$all_terms = get_terms(
2503
+			array(EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY),
2504
+			array('hide_empty' => 0, 'exclude' => array($this->_category->id))
2505
+		);
2506
+		// setup category select for term parents.
2507
+		$category_select_values[] = array(
2508
+			'text' => esc_html__('No Parent', 'event_espresso'),
2509
+			'id'   => 0,
2510
+		);
2511
+		foreach ($all_terms as $term) {
2512
+			$category_select_values[] = array(
2513
+				'text' => $term->name,
2514
+				'id'   => $term->term_id,
2515
+			);
2516
+		}
2517
+		$category_select = EEH_Form_Fields::select_input(
2518
+			'category_parent',
2519
+			$category_select_values,
2520
+			$this->_category->parent
2521
+		);
2522
+		$template_args = array(
2523
+			'category'                 => $this->_category,
2524
+			'category_select'          => $category_select,
2525
+			'unique_id_info_help_link' => $this->_get_help_tab_link('unique_id_info'),
2526
+			'category_desc_editor'     => $_wp_editor['category_desc']['field'],
2527
+			'disable'                  => '',
2528
+			'disabled_message'         => false,
2529
+		);
2530
+		$template = EVENTS_TEMPLATE_PATH . 'event_category_details.template.php';
2531
+		return EEH_Template::display_template($template, $template_args, true);
2532
+	}
2533
+
2534
+
2535
+	/**
2536
+	 * Handles deleting categories.
2537
+	 */
2538
+	protected function _delete_categories()
2539
+	{
2540
+		$cat_ids = isset($this->_req_data['EVT_CAT_ID']) ? (array) $this->_req_data['EVT_CAT_ID']
2541
+			: (array) $this->_req_data['category_id'];
2542
+		foreach ($cat_ids as $cat_id) {
2543
+			$this->_delete_category($cat_id);
2544
+		}
2545
+		// doesn't matter what page we're coming from... we're going to the same place after delete.
2546
+		$query_args = array(
2547
+			'action' => 'category_list',
2548
+		);
2549
+		$this->_redirect_after_action(0, '', '', $query_args);
2550
+	}
2551
+
2552
+
2553
+	/**
2554
+	 * Handles deleting specific category.
2555
+	 *
2556
+	 * @param int $cat_id
2557
+	 */
2558
+	protected function _delete_category($cat_id)
2559
+	{
2560
+		$cat_id = absint($cat_id);
2561
+		wp_delete_term($cat_id, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY);
2562
+	}
2563
+
2564
+
2565
+	/**
2566
+	 * Handles triggering the update or insertion of a new category.
2567
+	 *
2568
+	 * @param bool $new_category true means we're triggering the insert of a new category.
2569
+	 */
2570
+	protected function _insert_or_update_category($new_category)
2571
+	{
2572
+		$cat_id = $new_category ? $this->_insert_category() : $this->_insert_category(true);
2573
+		$success = 0; // we already have a success message so lets not send another.
2574
+		if ($cat_id) {
2575
+			$query_args = array(
2576
+				'action'     => 'edit_category',
2577
+				'EVT_CAT_ID' => $cat_id,
2578
+			);
2579
+		} else {
2580
+			$query_args = array('action' => 'add_category');
2581
+		}
2582
+		$this->_redirect_after_action($success, '', '', $query_args, true);
2583
+	}
2584
+
2585
+
2586
+	/**
2587
+	 * Inserts or updates category
2588
+	 *
2589
+	 * @param bool $update (true indicates we're updating a category).
2590
+	 * @return bool|mixed|string
2591
+	 */
2592
+	private function _insert_category($update = false)
2593
+	{
2594
+		$cat_id = $update ? $this->_req_data['EVT_CAT_ID'] : '';
2595
+		$category_name = isset($this->_req_data['category_name']) ? $this->_req_data['category_name'] : '';
2596
+		$category_desc = isset($this->_req_data['category_desc']) ? $this->_req_data['category_desc'] : '';
2597
+		$category_parent = isset($this->_req_data['category_parent']) ? $this->_req_data['category_parent'] : 0;
2598
+		if (empty($category_name)) {
2599
+			$msg = esc_html__('You must add a name for the category.', 'event_espresso');
2600
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2601
+			return false;
2602
+		}
2603
+		$term_args = array(
2604
+			'name'        => $category_name,
2605
+			'description' => $category_desc,
2606
+			'parent'      => $category_parent,
2607
+		);
2608
+		// was the category_identifier input disabled?
2609
+		if (isset($this->_req_data['category_identifier'])) {
2610
+			$term_args['slug'] = $this->_req_data['category_identifier'];
2611
+		}
2612
+		$insert_ids = $update
2613
+			? wp_update_term($cat_id, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY, $term_args)
2614
+			: wp_insert_term($category_name, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY, $term_args);
2615
+		if (! is_array($insert_ids)) {
2616
+			$msg = esc_html__(
2617
+				'An error occurred and the category has not been saved to the database.',
2618
+				'event_espresso'
2619
+			);
2620
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2621
+		} else {
2622
+			$cat_id = $insert_ids['term_id'];
2623
+			$msg = sprintf(esc_html__('The category %s was successfully saved', 'event_espresso'), $category_name);
2624
+			EE_Error::add_success($msg);
2625
+		}
2626
+		return $cat_id;
2627
+	}
2628
+
2629
+
2630
+	/**
2631
+	 * Gets categories or count of categories matching the arguments in the request.
2632
+	 *
2633
+	 * @param int  $per_page
2634
+	 * @param int  $current_page
2635
+	 * @param bool $count
2636
+	 * @return EE_Base_Class[]|EE_Term_Taxonomy[]|int
2637
+	 */
2638
+	public function get_categories($per_page = 10, $current_page = 1, $count = false)
2639
+	{
2640
+		// testing term stuff
2641
+		$orderby = isset($this->_req_data['orderby']) ? $this->_req_data['orderby'] : 'Term.term_id';
2642
+		$order = isset($this->_req_data['order']) ? $this->_req_data['order'] : 'DESC';
2643
+		$limit = ($current_page - 1) * $per_page;
2644
+		$where = array('taxonomy' => EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY);
2645
+		if (isset($this->_req_data['s'])) {
2646
+			$sstr = '%' . $this->_req_data['s'] . '%';
2647
+			$where['OR'] = array(
2648
+				'Term.name'   => array('LIKE', $sstr),
2649
+				'description' => array('LIKE', $sstr),
2650
+			);
2651
+		}
2652
+		$query_params = array(
2653
+			$where,
2654
+			'order_by'   => array($orderby => $order),
2655
+			'limit'      => $limit . ',' . $per_page,
2656
+			'force_join' => array('Term'),
2657
+		);
2658
+		$categories = $count
2659
+			? EEM_Term_Taxonomy::instance()->count($query_params, 'term_id')
2660
+			: EEM_Term_Taxonomy::instance()->get_all($query_params);
2661
+		return $categories;
2662
+	}
2663
+
2664
+	/* end category stuff */
2665
+	/**************/
2666
+
2667
+
2668
+	/**
2669
+	 * Callback for the `ee_save_timezone_setting` ajax action.
2670
+	 *
2671
+	 * @throws EE_Error
2672
+	 */
2673
+	public function save_timezonestring_setting()
2674
+	{
2675
+		$timezone_string = isset($this->_req_data['timezone_selected'])
2676
+			? $this->_req_data['timezone_selected']
2677
+			: '';
2678
+		if (empty($timezone_string) || ! EEH_DTT_Helper::validate_timezone($timezone_string, false)) {
2679
+			EE_Error::add_error(
2680
+				esc_html__('An invalid timezone string submitted.', 'event_espresso'),
2681
+				__FILE__,
2682
+				__FUNCTION__,
2683
+				__LINE__
2684
+			);
2685
+			$this->_template_args['error'] = true;
2686
+			$this->_return_json();
2687
+		}
2688
+
2689
+		update_option('timezone_string', $timezone_string);
2690
+		EE_Error::add_success(
2691
+			esc_html__('Your timezone string was updated.', 'event_espresso')
2692
+		);
2693
+		$this->_template_args['success'] = true;
2694
+		$this->_return_json(true, array('action' => 'create_new'));
2695
+	}
2696 2696
 }
Please login to merge, or discard this patch.
Spacing   +61 added lines, -61 removed lines patch added patch discarded remove patch
@@ -583,11 +583,11 @@  discard block
 block discarded – undo
583 583
     {
584 584
         wp_register_style(
585 585
             'events-admin-css',
586
-            EVENTS_ASSETS_URL . 'events-admin-page.css',
586
+            EVENTS_ASSETS_URL.'events-admin-page.css',
587 587
             array(),
588 588
             EVENT_ESPRESSO_VERSION
589 589
         );
590
-        wp_register_style('ee-cat-admin', EVENTS_ASSETS_URL . 'ee-cat-admin.css', array(), EVENT_ESPRESSO_VERSION);
590
+        wp_register_style('ee-cat-admin', EVENTS_ASSETS_URL.'ee-cat-admin.css', array(), EVENT_ESPRESSO_VERSION);
591 591
         wp_enqueue_style('events-admin-css');
592 592
         wp_enqueue_style('ee-cat-admin');
593 593
         // todo note: we also need to load_scripts_styles per view (i.e. default/view_report/event_details
@@ -595,7 +595,7 @@  discard block
 block discarded – undo
595 595
         // scripts
596 596
         wp_register_script(
597 597
             'event_editor_js',
598
-            EVENTS_ASSETS_URL . 'event_editor.js',
598
+            EVENTS_ASSETS_URL.'event_editor.js',
599 599
             array('ee_admin_js', 'jquery-ui-slider', 'jquery-ui-timepicker-addon'),
600 600
             EVENT_ESPRESSO_VERSION,
601 601
             true
@@ -621,7 +621,7 @@  discard block
 block discarded – undo
621 621
         wp_enqueue_style('espresso-ui-theme');
622 622
         wp_register_style(
623 623
             'event-editor-css',
624
-            EVENTS_ASSETS_URL . 'event-editor.css',
624
+            EVENTS_ASSETS_URL.'event-editor.css',
625 625
             array('ee-admin-css'),
626 626
             EVENT_ESPRESSO_VERSION
627 627
         );
@@ -629,7 +629,7 @@  discard block
 block discarded – undo
629 629
         // scripts
630 630
         wp_register_script(
631 631
             'event-datetime-metabox',
632
-            EVENTS_ASSETS_URL . 'event-datetime-metabox.js',
632
+            EVENTS_ASSETS_URL.'event-datetime-metabox.js',
633 633
             array('event_editor_js', 'ee-datepicker'),
634 634
             EVENT_ESPRESSO_VERSION
635 635
         );
@@ -698,7 +698,7 @@  discard block
 block discarded – undo
698 698
     public function verify_event_edit($event = null, $req_type = '')
699 699
     {
700 700
         // don't need to do this when processing
701
-        if (! empty($req_type)) {
701
+        if ( ! empty($req_type)) {
702 702
             return;
703 703
         }
704 704
         // no event?
@@ -707,7 +707,7 @@  discard block
 block discarded – undo
707 707
             $event = $this->_cpt_model_obj;
708 708
         }
709 709
         // STILL no event?
710
-        if (! $event instanceof EE_Event) {
710
+        if ( ! $event instanceof EE_Event) {
711 711
             return;
712 712
         }
713 713
         $orig_status = $event->status();
@@ -746,7 +746,7 @@  discard block
 block discarded – undo
746 746
             );
747 747
         }
748 748
         // now we need to determine if the event has any tickets on sale.  If not then we dont' show the error
749
-        if (! $event->tickets_on_sale()) {
749
+        if ( ! $event->tickets_on_sale()) {
750 750
             return;
751 751
         }
752 752
         // made it here so show warning
@@ -791,7 +791,7 @@  discard block
 block discarded – undo
791 791
     {
792 792
         $has_timezone_string = get_option('timezone_string');
793 793
         // only nag them about setting their timezone if it's their first event, and they haven't already done it
794
-        if (! $has_timezone_string && ! EEM_Event::instance()->exists(array())) {
794
+        if ( ! $has_timezone_string && ! EEM_Event::instance()->exists(array())) {
795 795
             EE_Error::add_attention(
796 796
                 sprintf(
797 797
                     esc_html__(
@@ -875,31 +875,31 @@  discard block
 block discarded – undo
875 875
         $items = apply_filters('FHEE__Events_Admin_Page___event_legend_items__items', $items);
876 876
         $statuses = array(
877 877
             'sold_out_status'  => array(
878
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::sold_out,
878
+                'class' => 'ee-status-legend ee-status-legend-'.EE_Datetime::sold_out,
879 879
                 'desc'  => EEH_Template::pretty_status(EE_Datetime::sold_out, false, 'sentence'),
880 880
             ),
881 881
             'active_status'    => array(
882
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::active,
882
+                'class' => 'ee-status-legend ee-status-legend-'.EE_Datetime::active,
883 883
                 'desc'  => EEH_Template::pretty_status(EE_Datetime::active, false, 'sentence'),
884 884
             ),
885 885
             'upcoming_status'  => array(
886
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::upcoming,
886
+                'class' => 'ee-status-legend ee-status-legend-'.EE_Datetime::upcoming,
887 887
                 'desc'  => EEH_Template::pretty_status(EE_Datetime::upcoming, false, 'sentence'),
888 888
             ),
889 889
             'postponed_status' => array(
890
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::postponed,
890
+                'class' => 'ee-status-legend ee-status-legend-'.EE_Datetime::postponed,
891 891
                 'desc'  => EEH_Template::pretty_status(EE_Datetime::postponed, false, 'sentence'),
892 892
             ),
893 893
             'cancelled_status' => array(
894
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::cancelled,
894
+                'class' => 'ee-status-legend ee-status-legend-'.EE_Datetime::cancelled,
895 895
                 'desc'  => EEH_Template::pretty_status(EE_Datetime::cancelled, false, 'sentence'),
896 896
             ),
897 897
             'expired_status'   => array(
898
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::expired,
898
+                'class' => 'ee-status-legend ee-status-legend-'.EE_Datetime::expired,
899 899
                 'desc'  => EEH_Template::pretty_status(EE_Datetime::expired, false, 'sentence'),
900 900
             ),
901 901
             'inactive_status'  => array(
902
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::inactive,
902
+                'class' => 'ee-status-legend ee-status-legend-'.EE_Datetime::inactive,
903 903
                 'desc'  => EEH_Template::pretty_status(EE_Datetime::inactive, false, 'sentence'),
904 904
             ),
905 905
         );
@@ -913,7 +913,7 @@  discard block
 block discarded – undo
913 913
      */
914 914
     private function _event_model()
915 915
     {
916
-        if (! $this->_event_model instanceof EEM_Event) {
916
+        if ( ! $this->_event_model instanceof EEM_Event) {
917 917
             $this->_event_model = EE_Registry::instance()->load_model('Event');
918 918
         }
919 919
         return $this->_event_model;
@@ -933,7 +933,7 @@  discard block
 block discarded – undo
933 933
     public function extra_permalink_field_buttons($return, $id, $new_title, $new_slug)
934 934
     {
935 935
         // make sure this is only when editing
936
-        if (! empty($id)) {
936
+        if ( ! empty($id)) {
937 937
             $post = get_post($id);
938 938
             $return .= '<a class="button button-small" onclick="prompt(\'Shortcode:\', jQuery(\'#shortcode\').val()); return false;" href="#"  tabindex="-1">'
939 939
                        . esc_html__('Shortcode', 'event_espresso')
@@ -967,7 +967,7 @@  discard block
 block discarded – undo
967 967
                     'button'
968 968
                 );
969 969
         $this->_template_args['after_list_table']['legend'] = $this->_display_legend($this->_event_legend_items());
970
-        $this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
970
+        $this->_admin_page_title .= ' '.$this->get_action_link_or_button(
971 971
             'create_new',
972 972
             'add',
973 973
             array(),
@@ -1107,7 +1107,7 @@  discard block
 block discarded – undo
1107 1107
      */
1108 1108
     protected function _default_venue_update(\EE_Event $evtobj, $data)
1109 1109
     {
1110
-        require_once(EE_MODELS . 'EEM_Venue.model.php');
1110
+        require_once(EE_MODELS.'EEM_Venue.model.php');
1111 1111
         $venue_model = EE_Registry::instance()->load_model('Venue');
1112 1112
         $rows_affected = null;
1113 1113
         $venue_id = ! empty($data['venue_id']) ? $data['venue_id'] : null;
@@ -1138,7 +1138,7 @@  discard block
 block discarded – undo
1138 1138
             'status'              => 'publish',
1139 1139
         );
1140 1140
         // if we've got the venue_id then we're just updating the existing venue so let's do that and then get out.
1141
-        if (! empty($venue_id)) {
1141
+        if ( ! empty($venue_id)) {
1142 1142
             $update_where = array($venue_model->primary_key_name() => $venue_id);
1143 1143
             $rows_affected = $venue_model->update($venue_array, array($update_where));
1144 1144
             // we've gotta make sure that the venue is always attached to a revision.. add_relation_to should take care of making sure that the relation is already present.
@@ -1180,7 +1180,7 @@  discard block
 block discarded – undo
1180 1180
                 'DTT_order'     => $row,
1181 1181
             );
1182 1182
             // if we have an id then let's get existing object first and then set the new values.  Otherwise we instantiate a new object for save.
1183
-            if (! empty($dtt['DTT_ID'])) {
1183
+            if ( ! empty($dtt['DTT_ID'])) {
1184 1184
                 $DTM = EE_Registry::instance()
1185 1185
                                   ->load_model('Datetime', array($evtobj->get_timezone()))
1186 1186
                                   ->get_one_by_ID($dtt['DTT_ID']);
@@ -1190,7 +1190,7 @@  discard block
 block discarded – undo
1190 1190
                     $DTM->set($field, $value);
1191 1191
                 }
1192 1192
                 // make sure the $dtt_id here is saved just in case after the add_relation_to() the autosave replaces it.  We need to do this so we dont' TRASH the parent DTT.
1193
-                $saved_dtts[ $DTM->ID() ] = $DTM;
1193
+                $saved_dtts[$DTM->ID()] = $DTM;
1194 1194
             } else {
1195 1195
                 $DTM = EE_Registry::instance()->load_class(
1196 1196
                     'Datetime',
@@ -1223,14 +1223,14 @@  discard block
 block discarded – undo
1223 1223
         foreach ($data['edit_tickets'] as $row => $tkt) {
1224 1224
             $incoming_date_formats = array('Y-m-d', 'h:i a');
1225 1225
             $update_prices = false;
1226
-            $ticket_price = isset($data['edit_prices'][ $row ][1]['PRC_amount'])
1227
-                ? $data['edit_prices'][ $row ][1]['PRC_amount'] : 0;
1226
+            $ticket_price = isset($data['edit_prices'][$row][1]['PRC_amount'])
1227
+                ? $data['edit_prices'][$row][1]['PRC_amount'] : 0;
1228 1228
             // trim inputs to ensure any excess whitespace is removed.
1229 1229
             $tkt = array_map('trim', $tkt);
1230 1230
             if (empty($tkt['TKT_start_date'])) {
1231 1231
                 // let's use now in the set timezone.
1232 1232
                 $now = new DateTime('now', new DateTimeZone($evtobj->get_timezone()));
1233
-                $tkt['TKT_start_date'] = $now->format($incoming_date_formats[0] . ' ' . $incoming_date_formats[1]);
1233
+                $tkt['TKT_start_date'] = $now->format($incoming_date_formats[0].' '.$incoming_date_formats[1]);
1234 1234
             }
1235 1235
             if (empty($tkt['TKT_end_date'])) {
1236 1236
                 // use the start date of the first datetime
@@ -1265,7 +1265,7 @@  discard block
 block discarded – undo
1265 1265
             // if we have a TKT_ID then we need to get that existing TKT_obj and update it
1266 1266
             // we actually do our saves a head of doing any add_relations to because its entirely possible that this ticket didn't removed or added to any datetime in the session but DID have it's items modified.
1267 1267
             // keep in mind that if the TKT has been sold (and we have changed pricing information), then we won't be updating the tkt but instead a new tkt will be created and the old one archived.
1268
-            if (! empty($tkt['TKT_ID'])) {
1268
+            if ( ! empty($tkt['TKT_ID'])) {
1269 1269
                 $TKT = EE_Registry::instance()
1270 1270
                                   ->load_model('Ticket', array($evtobj->get_timezone()))
1271 1271
                                   ->get_one_by_ID($tkt['TKT_ID']);
@@ -1300,7 +1300,7 @@  discard block
 block discarded – undo
1300 1300
                         $TKT->set('TKT_deleted', 1);
1301 1301
                         $TKT->save();
1302 1302
                         // make sure this ticket is still recorded in our saved_tkts so we don't run it through the regular trash routine.
1303
-                        $saved_tickets[ $TKT->ID() ] = $TKT;
1303
+                        $saved_tickets[$TKT->ID()] = $TKT;
1304 1304
                         // create new ticket that's a copy of the existing except a new id of course (and not archived) AND has the new TKT_price associated with it.
1305 1305
                         $TKT = clone $TKT;
1306 1306
                         $TKT->set('TKT_ID', 0);
@@ -1345,9 +1345,9 @@  discard block
 block discarded – undo
1345 1345
             }
1346 1346
             // initially let's add the ticket to the dtt
1347 1347
             $saved_dtt->_add_relation_to($TKT, 'Ticket');
1348
-            $saved_tickets[ $TKT->ID() ] = $TKT;
1348
+            $saved_tickets[$TKT->ID()] = $TKT;
1349 1349
             // add prices to ticket
1350
-            $this->_add_prices_to_ticket($data['edit_prices'][ $row ], $TKT, $update_prices);
1350
+            $this->_add_prices_to_ticket($data['edit_prices'][$row], $TKT, $update_prices);
1351 1351
         }
1352 1352
         // however now we need to handle permanently deleting tickets via the ui.  Keep in mind that the ui does not allow deleting/archiving tickets that have ticket sold.  However, it does allow for deleting tickets that have no tickets sold, in which case we want to get rid of permanently because there is no need to save in db.
1353 1353
         $old_tickets = isset($old_tickets[0]) && $old_tickets[0] == '' ? array() : $old_tickets;
@@ -1356,7 +1356,7 @@  discard block
 block discarded – undo
1356 1356
             $id = absint($id);
1357 1357
             // get the ticket for this id
1358 1358
             $tkt_to_remove = EE_Registry::instance()->load_model('Ticket')->get_one_by_ID($id);
1359
-            if (! $tkt_to_remove instanceof EE_Ticket) {
1359
+            if ( ! $tkt_to_remove instanceof EE_Ticket) {
1360 1360
                 continue;
1361 1361
             }
1362 1362
 
@@ -1508,7 +1508,7 @@  discard block
 block discarded – undo
1508 1508
         $publish_box_extra_args['event_editor_overview_add'] = ob_get_clean();
1509 1509
         // load template
1510 1510
         EEH_Template::display_template(
1511
-            EVENTS_TEMPLATE_PATH . 'event_publish_box_extras.template.php',
1511
+            EVENTS_TEMPLATE_PATH.'event_publish_box_extras.template.php',
1512 1512
             $publish_box_extra_args
1513 1513
         );
1514 1514
     }
@@ -1601,7 +1601,7 @@  discard block
 block discarded – undo
1601 1601
                     'default_where_conditions' => 'none',
1602 1602
                 )
1603 1603
             );
1604
-            if (! empty($related_tickets)) {
1604
+            if ( ! empty($related_tickets)) {
1605 1605
                 $template_args['total_ticket_rows'] = count($related_tickets);
1606 1606
                 $row = 0;
1607 1607
                 foreach ($related_tickets as $ticket) {
@@ -1635,7 +1635,7 @@  discard block
 block discarded – undo
1635 1635
         );
1636 1636
         $template = apply_filters(
1637 1637
             'FHEE__Events_Admin_Page__ticket_metabox__template',
1638
-            EVENTS_TEMPLATE_PATH . 'event_tickets_metabox_main.template.php'
1638
+            EVENTS_TEMPLATE_PATH.'event_tickets_metabox_main.template.php'
1639 1639
         );
1640 1640
         EEH_Template::display_template($template, $template_args);
1641 1641
     }
@@ -1653,7 +1653,7 @@  discard block
 block discarded – undo
1653 1653
     private function _get_ticket_row($ticket, $skeleton = false, $row = 0)
1654 1654
     {
1655 1655
         $template_args = array(
1656
-            'tkt_status_class'    => ' tkt-status-' . $ticket->ticket_status(),
1656
+            'tkt_status_class'    => ' tkt-status-'.$ticket->ticket_status(),
1657 1657
             'tkt_archive_class'   => $ticket->ticket_status() === EE_Ticket::archived && ! $skeleton ? ' tkt-archived'
1658 1658
                 : '',
1659 1659
             'ticketrow'           => $skeleton ? 'TICKETNUM' : $row,
@@ -1665,10 +1665,10 @@  discard block
 block discarded – undo
1665 1665
             'TKT_qty'             => $ticket->get_pretty('TKT_qty', 'input'),
1666 1666
             'edit_ticketrow_name' => $skeleton ? 'TICKETNAMEATTR' : 'edit_tickets',
1667 1667
             'TKT_sold'            => $skeleton ? 0 : $ticket->get('TKT_sold'),
1668
-            'trash_icon'          => ($skeleton || (! empty($ticket) && ! $ticket->get('TKT_deleted')))
1669
-                                     && (! empty($ticket) && $ticket->get('TKT_sold') === 0)
1668
+            'trash_icon'          => ($skeleton || ( ! empty($ticket) && ! $ticket->get('TKT_deleted')))
1669
+                                     && ( ! empty($ticket) && $ticket->get('TKT_sold') === 0)
1670 1670
                 ? 'trash-icon dashicons dashicons-post-trash clickable' : 'ee-lock-icon',
1671
-            'disabled'            => $skeleton || (! empty($ticket) && ! $ticket->get('TKT_deleted')) ? ''
1671
+            'disabled'            => $skeleton || ( ! empty($ticket) && ! $ticket->get('TKT_deleted')) ? ''
1672 1672
                 : ' disabled=disabled',
1673 1673
         );
1674 1674
         $price = $ticket->ID() !== 0
@@ -1698,7 +1698,7 @@  discard block
 block discarded – undo
1698 1698
                     array('order_by' => array('DTT_EVT_start' => 'ASC'))
1699 1699
                 )
1700 1700
                 : null;
1701
-            if (! empty($earliest_dtt)) {
1701
+            if ( ! empty($earliest_dtt)) {
1702 1702
                 $template_args['TKT_end_date'] = $earliest_dtt->get_datetime('DTT_EVT_start', 'Y-m-d', 'h:i a');
1703 1703
             } else {
1704 1704
                 $template_args['TKT_end_date'] = date(
@@ -1710,7 +1710,7 @@  discard block
 block discarded – undo
1710 1710
         $template_args = array_merge($template_args, $price_args);
1711 1711
         $template = apply_filters(
1712 1712
             'FHEE__Events_Admin_Page__get_ticket_row__template',
1713
-            EVENTS_TEMPLATE_PATH . 'event_tickets_metabox_ticket_row.template.php',
1713
+            EVENTS_TEMPLATE_PATH.'event_tickets_metabox_ticket_row.template.php',
1714 1714
             $ticket
1715 1715
         );
1716 1716
         return EEH_Template::display_template($template, $template_args, true);
@@ -1765,7 +1765,7 @@  discard block
 block discarded – undo
1765 1765
             $default_reg_status_values
1766 1766
         );
1767 1767
         EEH_Template::display_template(
1768
-            EVENTS_TEMPLATE_PATH . 'event_registration_options.template.php',
1768
+            EVENTS_TEMPLATE_PATH.'event_registration_options.template.php',
1769 1769
             $template_args
1770 1770
         );
1771 1771
     }
@@ -1787,7 +1787,7 @@  discard block
 block discarded – undo
1787 1787
     {
1788 1788
         $EEME = $this->_event_model();
1789 1789
         $offset = ($current_page - 1) * $per_page;
1790
-        $limit = $count ? null : $offset . ',' . $per_page;
1790
+        $limit = $count ? null : $offset.','.$per_page;
1791 1791
         $orderby = isset($this->_req_data['orderby']) ? $this->_req_data['orderby'] : 'EVT_ID';
1792 1792
         $order = isset($this->_req_data['order']) ? $this->_req_data['order'] : "DESC";
1793 1793
         if (isset($this->_req_data['month_range'])) {
@@ -1816,7 +1816,7 @@  discard block
 block discarded – undo
1816 1816
         // categories?
1817 1817
         $category = isset($this->_req_data['EVT_CAT']) && $this->_req_data['EVT_CAT'] > 0
1818 1818
             ? $this->_req_data['EVT_CAT'] : null;
1819
-        if (! empty($category)) {
1819
+        if ( ! empty($category)) {
1820 1820
             $where['Term_Taxonomy.taxonomy'] = EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY;
1821 1821
             $where['Term_Taxonomy.term_id'] = $category;
1822 1822
         }
@@ -1824,7 +1824,7 @@  discard block
 block discarded – undo
1824 1824
         $start_formats = EEM_Datetime::instance()->get_formats_for('DTT_EVT_start');
1825 1825
         if (isset($this->_req_data['month_range']) && $this->_req_data['month_range'] != '') {
1826 1826
             $DateTime = new DateTime(
1827
-                $year_r . '-' . $month_r . '-01 00:00:00',
1827
+                $year_r.'-'.$month_r.'-01 00:00:00',
1828 1828
                 new DateTimeZone('UTC')
1829 1829
             );
1830 1830
             $start = $DateTime->getTimestamp();
@@ -1850,11 +1850,11 @@  discard block
 block discarded – undo
1850 1850
                             ->format(implode(' ', $start_formats));
1851 1851
             $where['Datetime.DTT_EVT_start'] = array('BETWEEN', array($start, $end));
1852 1852
         }
1853
-        if (! EE_Registry::instance()->CAP->current_user_can('ee_read_others_events', 'get_events')) {
1853
+        if ( ! EE_Registry::instance()->CAP->current_user_can('ee_read_others_events', 'get_events')) {
1854 1854
             $where['EVT_wp_user'] = get_current_user_id();
1855 1855
         } else {
1856
-            if (! isset($where['status'])) {
1857
-                if (! EE_Registry::instance()->CAP->current_user_can('ee_read_private_events', 'get_events')) {
1856
+            if ( ! isset($where['status'])) {
1857
+                if ( ! EE_Registry::instance()->CAP->current_user_can('ee_read_private_events', 'get_events')) {
1858 1858
                     $where['OR'] = array(
1859 1859
                         'status*restrict_private' => array('!=', 'private'),
1860 1860
                         'AND'                     => array(
@@ -1875,7 +1875,7 @@  discard block
 block discarded – undo
1875 1875
         }
1876 1876
         // search query handling
1877 1877
         if (isset($this->_req_data['s'])) {
1878
-            $search_string = '%' . $this->_req_data['s'] . '%';
1878
+            $search_string = '%'.$this->_req_data['s'].'%';
1879 1879
             $where['OR'] = array(
1880 1880
                 'EVT_name'       => array('LIKE', $search_string),
1881 1881
                 'EVT_desc'       => array('LIKE', $search_string),
@@ -1971,7 +1971,7 @@  discard block
 block discarded – undo
1971 1971
             // clean status
1972 1972
             $event_status = sanitize_key($event_status);
1973 1973
             // grab status
1974
-            if (! empty($event_status)) {
1974
+            if ( ! empty($event_status)) {
1975 1975
                 $success = $this->_change_event_status($EVT_ID, $event_status);
1976 1976
             } else {
1977 1977
                 $success = false;
@@ -2008,7 +2008,7 @@  discard block
 block discarded – undo
2008 2008
         // clean status
2009 2009
         $event_status = sanitize_key($event_status);
2010 2010
         // grab status
2011
-        if (! empty($event_status)) {
2011
+        if ( ! empty($event_status)) {
2012 2012
             $success = true;
2013 2013
             // determine the event id and set to array.
2014 2014
             $EVT_IDs = isset($this->_req_data['EVT_IDs']) ? (array) $this->_req_data['EVT_IDs'] : array();
@@ -2052,7 +2052,7 @@  discard block
 block discarded – undo
2052 2052
     private function _change_event_status($EVT_ID = 0, $event_status = '')
2053 2053
     {
2054 2054
         // grab event id
2055
-        if (! $EVT_ID) {
2055
+        if ( ! $EVT_ID) {
2056 2056
             $msg = esc_html__(
2057 2057
                 'An error occurred. No Event ID or an invalid Event ID was received.',
2058 2058
                 'event_espresso'
@@ -2089,7 +2089,7 @@  discard block
 block discarded – undo
2089 2089
         // use class to change status
2090 2090
         $this->_cpt_model_obj->set_status($event_status);
2091 2091
         $success = $this->_cpt_model_obj->save();
2092
-        if (! $success) {
2092
+        if ( ! $success) {
2093 2093
             $msg = sprintf(esc_html__('An error occurred. The event could not be %s.', 'event_espresso'), $action);
2094 2094
             EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2095 2095
             return false;
@@ -2144,7 +2144,7 @@  discard block
 block discarded – undo
2144 2144
      */
2145 2145
     protected function getModelObjNodeGroupPersister()
2146 2146
     {
2147
-        if (! $this->model_obj_node_group_persister instanceof NodeGroupDao) {
2147
+        if ( ! $this->model_obj_node_group_persister instanceof NodeGroupDao) {
2148 2148
             $this->model_obj_node_group_persister = $this->getLoader()->load('\EventEspresso\core\services\orm\tree_traversal\NodeGroupDao');
2149 2149
         }
2150 2150
         return $this->model_obj_node_group_persister;
@@ -2400,7 +2400,7 @@  discard block
 block discarded – undo
2400 2400
                                                 . esc_html__(
2401 2401
                                                     'Template Settings is a feature that is only available in the premium version of Event Espresso 4 which is available with a support license purchase on EventEspresso.com. Template Settings allow you to configure some of the appearance options for both the Event List and Event Details pages.',
2402 2402
                                                     'event_espresso'
2403
-                                                ) . '</strong>';
2403
+                                                ).'</strong>';
2404 2404
         $this->display_admin_caf_preview_page('template_settings_tab');
2405 2405
     }
2406 2406
 
@@ -2420,12 +2420,12 @@  discard block
 block discarded – undo
2420 2420
         // set default category object
2421 2421
         $this->_set_empty_category_object();
2422 2422
         // only set if we've got an id
2423
-        if (! isset($this->_req_data['EVT_CAT_ID'])) {
2423
+        if ( ! isset($this->_req_data['EVT_CAT_ID'])) {
2424 2424
             return;
2425 2425
         }
2426 2426
         $category_id = absint($this->_req_data['EVT_CAT_ID']);
2427 2427
         $term = get_term($category_id, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY);
2428
-        if (! empty($term)) {
2428
+        if ( ! empty($term)) {
2429 2429
             $this->_category->category_name = $term->name;
2430 2430
             $this->_category->category_identifier = $term->slug;
2431 2431
             $this->_category->category_desc = $term->description;
@@ -2453,7 +2453,7 @@  discard block
 block discarded – undo
2453 2453
     {
2454 2454
         do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2455 2455
         $this->_search_btn_label = esc_html__('Categories', 'event_espresso');
2456
-        $this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
2456
+        $this->_admin_page_title .= ' '.$this->get_action_link_or_button(
2457 2457
             'add_category',
2458 2458
             'add_category',
2459 2459
             array(),
@@ -2527,7 +2527,7 @@  discard block
 block discarded – undo
2527 2527
             'disable'                  => '',
2528 2528
             'disabled_message'         => false,
2529 2529
         );
2530
-        $template = EVENTS_TEMPLATE_PATH . 'event_category_details.template.php';
2530
+        $template = EVENTS_TEMPLATE_PATH.'event_category_details.template.php';
2531 2531
         return EEH_Template::display_template($template, $template_args, true);
2532 2532
     }
2533 2533
 
@@ -2612,7 +2612,7 @@  discard block
 block discarded – undo
2612 2612
         $insert_ids = $update
2613 2613
             ? wp_update_term($cat_id, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY, $term_args)
2614 2614
             : wp_insert_term($category_name, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY, $term_args);
2615
-        if (! is_array($insert_ids)) {
2615
+        if ( ! is_array($insert_ids)) {
2616 2616
             $msg = esc_html__(
2617 2617
                 'An error occurred and the category has not been saved to the database.',
2618 2618
                 'event_espresso'
@@ -2643,7 +2643,7 @@  discard block
 block discarded – undo
2643 2643
         $limit = ($current_page - 1) * $per_page;
2644 2644
         $where = array('taxonomy' => EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY);
2645 2645
         if (isset($this->_req_data['s'])) {
2646
-            $sstr = '%' . $this->_req_data['s'] . '%';
2646
+            $sstr = '%'.$this->_req_data['s'].'%';
2647 2647
             $where['OR'] = array(
2648 2648
                 'Term.name'   => array('LIKE', $sstr),
2649 2649
                 'description' => array('LIKE', $sstr),
@@ -2652,7 +2652,7 @@  discard block
 block discarded – undo
2652 2652
         $query_params = array(
2653 2653
             $where,
2654 2654
             'order_by'   => array($orderby => $order),
2655
-            'limit'      => $limit . ',' . $per_page,
2655
+            'limit'      => $limit.','.$per_page,
2656 2656
             'force_join' => array('Term'),
2657 2657
         );
2658 2658
         $categories = $count
Please login to merge, or discard this patch.