Completed
Branch master (724475)
by
unknown
05:49
created
vendor/appsero/client/src/Client.php 2 patches
Indentation   +267 added lines, -267 removed lines patch added patch discarded remove patch
@@ -8,273 +8,273 @@
 block discarded – undo
8 8
  */
9 9
 class Client {
10 10
 
11
-    /**
12
-     * The client version
13
-     *
14
-     * @var string
15
-     */
16
-    public $version = '1.2.0';
17
-
18
-    /**
19
-     * Hash identifier of the plugin
20
-     *
21
-     * @var string
22
-     */
23
-    public $hash;
24
-
25
-    /**
26
-     * Name of the plugin
27
-     *
28
-     * @var string
29
-     */
30
-    public $name;
31
-
32
-    /**
33
-     * The plugin/theme file path
34
-     * @example .../wp-content/plugins/test-slug/test-slug.php
35
-     *
36
-     * @var string
37
-     */
38
-    public $file;
39
-
40
-    /**
41
-     * Main plugin file
42
-     * @example test-slug/test-slug.php
43
-     *
44
-     * @var string
45
-     */
46
-    public $basename;
47
-
48
-    /**
49
-     * Slug of the plugin
50
-     * @example test-slug
51
-     *
52
-     * @var string
53
-     */
54
-    public $slug;
55
-
56
-    /**
57
-     * The project version
58
-     *
59
-     * @var string
60
-     */
61
-    public $project_version;
62
-
63
-    /**
64
-     * The project type
65
-     *
66
-     * @var string
67
-     */
68
-    public $type;
69
-
70
-    /**
71
-     * textdomain
72
-     *
73
-     * @var string
74
-     */
75
-    public $textdomain;
76
-
77
-    /**
78
-     * The Object of Insights Class
79
-     *
80
-     * @var object
81
-     */
82
-    private $insights;
83
-
84
-    /**
85
-     * The Object of Updater Class
86
-     *
87
-     * @var object
88
-     */
89
-    private $updater;
90
-
91
-    /**
92
-     * The Object of License Class
93
-     *
94
-     * @var object
95
-     */
96
-    private $license;
11
+	/**
12
+	 * The client version
13
+	 *
14
+	 * @var string
15
+	 */
16
+	public $version = '1.2.0';
17
+
18
+	/**
19
+	 * Hash identifier of the plugin
20
+	 *
21
+	 * @var string
22
+	 */
23
+	public $hash;
24
+
25
+	/**
26
+	 * Name of the plugin
27
+	 *
28
+	 * @var string
29
+	 */
30
+	public $name;
31
+
32
+	/**
33
+	 * The plugin/theme file path
34
+	 * @example .../wp-content/plugins/test-slug/test-slug.php
35
+	 *
36
+	 * @var string
37
+	 */
38
+	public $file;
39
+
40
+	/**
41
+	 * Main plugin file
42
+	 * @example test-slug/test-slug.php
43
+	 *
44
+	 * @var string
45
+	 */
46
+	public $basename;
47
+
48
+	/**
49
+	 * Slug of the plugin
50
+	 * @example test-slug
51
+	 *
52
+	 * @var string
53
+	 */
54
+	public $slug;
55
+
56
+	/**
57
+	 * The project version
58
+	 *
59
+	 * @var string
60
+	 */
61
+	public $project_version;
62
+
63
+	/**
64
+	 * The project type
65
+	 *
66
+	 * @var string
67
+	 */
68
+	public $type;
69
+
70
+	/**
71
+	 * textdomain
72
+	 *
73
+	 * @var string
74
+	 */
75
+	public $textdomain;
76
+
77
+	/**
78
+	 * The Object of Insights Class
79
+	 *
80
+	 * @var object
81
+	 */
82
+	private $insights;
83
+
84
+	/**
85
+	 * The Object of Updater Class
86
+	 *
87
+	 * @var object
88
+	 */
89
+	private $updater;
90
+
91
+	/**
92
+	 * The Object of License Class
93
+	 *
94
+	 * @var object
95
+	 */
96
+	private $license;
97
+
98
+	/**
99
+	 * Initialize the class
100
+	 *
101
+	 * @param string  $hash hash of the plugin
102
+	 * @param string  $name readable name of the plugin
103
+	 * @param string  $file main plugin file path
104
+	 */
105
+	public function __construct( $hash, $name, $file ) {
106
+		$this->hash = $hash;
107
+		$this->name = $name;
108
+		$this->file = $file;
109
+
110
+		$this->set_basename_and_slug();
111
+	}
112
+
113
+	/**
114
+	 * Initialize insights class
115
+	 *
116
+	 * @return Appsero\Insights
117
+	 */
118
+	public function insights() {
119
+
120
+		if ( ! class_exists( __NAMESPACE__ . '\Insights') ) {
121
+			require_once __DIR__ . '/Insights.php';
122
+		}
123
+
124
+		// if already instantiated, return the cached one
125
+		if ( $this->insights ) {
126
+			return $this->insights;
127
+		}
128
+
129
+		$this->insights = new Insights( $this );
130
+
131
+		return $this->insights;
132
+	}
133
+
134
+	/**
135
+	 * Initialize plugin/theme updater
136
+	 *
137
+	 * @return Appsero\Updater
138
+	 */
139
+	public function updater() {
140
+
141
+		if ( ! class_exists( __NAMESPACE__ . '\Updater') ) {
142
+			require_once __DIR__ . '/Updater.php';
143
+		}
144
+
145
+		// if already instantiated, return the cached one
146
+		if ( $this->updater ) {
147
+			return $this->updater;
148
+		}
149
+
150
+		$this->updater = new Updater( $this );
151
+
152
+		return $this->updater;
153
+	}
154
+
155
+	/**
156
+	 * Initialize license checker
157
+	 *
158
+	 * @return Appsero\License
159
+	 */
160
+	public function license() {
161
+
162
+		if ( ! class_exists( __NAMESPACE__ . '\License') ) {
163
+			require_once __DIR__ . '/License.php';
164
+		}
165
+
166
+		// if already instantiated, return the cached one
167
+		if ( $this->license ) {
168
+			return $this->license;
169
+		}
170
+
171
+		$this->license = new License( $this );
172
+
173
+		return $this->license;
174
+	}
175
+
176
+	/**
177
+	 * API Endpoint
178
+	 *
179
+	 * @return string
180
+	 */
181
+	public function endpoint() {
182
+		$endpoint = apply_filters( 'appsero_endpoint', 'https://api.appsero.com' );
183
+
184
+		return trailingslashit( $endpoint );
185
+	}
186
+
187
+	/**
188
+	 * Set project basename, slug and version
189
+	 *
190
+	 * @return void
191
+	 */
192
+	protected function set_basename_and_slug() {
193
+
194
+		if ( strpos( $this->file, WP_CONTENT_DIR . '/themes/' ) === false ) {
195
+			$this->basename = plugin_basename( $this->file );
196
+
197
+			list( $this->slug, $mainfile) = explode( '/', $this->basename );
198
+
199
+			require_once ABSPATH . 'wp-admin/includes/plugin.php';
200
+
201
+			$plugin_data = get_plugin_data( $this->file, false, false );
202
+
203
+			$this->project_version = $plugin_data['Version'];
204
+			$this->type = 'plugin';
205
+		} else {
206
+			$this->basename = str_replace( WP_CONTENT_DIR . '/themes/', '', $this->file );
207
+
208
+			list( $this->slug, $mainfile) = explode( '/', $this->basename );
209
+
210
+			$theme = wp_get_theme( $this->slug );
211
+
212
+			$this->project_version = $theme->version;
213
+			$this->type = 'theme';
214
+		}
215
+
216
+		$this->textdomain = $this->slug;
217
+	}
218
+
219
+	/**
220
+	 * Send request to remote endpoint
221
+	 *
222
+	 * @param  array  $params
223
+	 * @param  string $route
224
+	 *
225
+	 * @return array|WP_Error   Array of results including HTTP headers or WP_Error if the request failed.
226
+	 */
227
+	public function send_request( $params, $route, $blocking = false ) {
228
+		$url = $this->endpoint() . $route;
229
+
230
+		$headers = array(
231
+			'user-agent' => 'Appsero/' . md5( esc_url( home_url() ) ) . ';',
232
+			'Accept'     => 'application/json',
233
+		);
234
+
235
+		$response = wp_remote_post( $url, array(
236
+			'method'      => 'POST',
237
+			'timeout'     => 30,
238
+			'redirection' => 5,
239
+			'httpversion' => '1.0',
240
+			'blocking'    => $blocking,
241
+			'headers'     => $headers,
242
+			'body'        => array_merge( $params, array( 'client' => $this->version ) ),
243
+			'cookies'     => array()
244
+		) );
245
+
246
+		return $response;
247
+	}
248
+
249
+	/**
250
+	 * Check if the current server is localhost
251
+	 *
252
+	 * @return boolean
253
+	 */
254
+	public function is_local_server() {
255
+		$is_local = in_array( $_SERVER['REMOTE_ADDR'], array( '127.0.0.1', '::1' ) );
256
+
257
+		return apply_filters( 'appsero_is_local', $is_local );
258
+	}
259
+
260
+	/**
261
+	 * Translate function _e()
262
+	 */
263
+	public function _etrans( $text ) {
264
+		call_user_func( '_e', $text, $this->textdomain );
265
+	}
266
+
267
+	/**
268
+	 * Translate function __()
269
+	 */
270
+	public function __trans( $text ) {
271
+		return call_user_func( '__', $text, $this->textdomain );
272
+	}
97 273
 
98 274
 	/**
99
-     * Initialize the class
100
-     *
101
-     * @param string  $hash hash of the plugin
102
-     * @param string  $name readable name of the plugin
103
-     * @param string  $file main plugin file path
104
-     */
105
-    public function __construct( $hash, $name, $file ) {
106
-        $this->hash = $hash;
107
-        $this->name = $name;
108
-        $this->file = $file;
109
-
110
-        $this->set_basename_and_slug();
111
-    }
112
-
113
-    /**
114
-     * Initialize insights class
115
-     *
116
-     * @return Appsero\Insights
117
-     */
118
-    public function insights() {
119
-
120
-        if ( ! class_exists( __NAMESPACE__ . '\Insights') ) {
121
-            require_once __DIR__ . '/Insights.php';
122
-        }
123
-
124
-        // if already instantiated, return the cached one
125
-        if ( $this->insights ) {
126
-            return $this->insights;
127
-        }
128
-
129
-        $this->insights = new Insights( $this );
130
-
131
-        return $this->insights;
132
-    }
133
-
134
-    /**
135
-     * Initialize plugin/theme updater
136
-     *
137
-     * @return Appsero\Updater
138
-     */
139
-    public function updater() {
140
-
141
-        if ( ! class_exists( __NAMESPACE__ . '\Updater') ) {
142
-            require_once __DIR__ . '/Updater.php';
143
-        }
144
-
145
-        // if already instantiated, return the cached one
146
-        if ( $this->updater ) {
147
-            return $this->updater;
148
-        }
149
-
150
-        $this->updater = new Updater( $this );
151
-
152
-        return $this->updater;
153
-    }
154
-
155
-    /**
156
-     * Initialize license checker
157
-     *
158
-     * @return Appsero\License
159
-     */
160
-    public function license() {
161
-
162
-        if ( ! class_exists( __NAMESPACE__ . '\License') ) {
163
-            require_once __DIR__ . '/License.php';
164
-        }
165
-
166
-        // if already instantiated, return the cached one
167
-        if ( $this->license ) {
168
-            return $this->license;
169
-        }
170
-
171
-        $this->license = new License( $this );
172
-
173
-        return $this->license;
174
-    }
175
-
176
-    /**
177
-     * API Endpoint
178
-     *
179
-     * @return string
180
-     */
181
-    public function endpoint() {
182
-        $endpoint = apply_filters( 'appsero_endpoint', 'https://api.appsero.com' );
183
-
184
-        return trailingslashit( $endpoint );
185
-    }
186
-
187
-    /**
188
-     * Set project basename, slug and version
189
-     *
190
-     * @return void
191
-     */
192
-    protected function set_basename_and_slug() {
193
-
194
-        if ( strpos( $this->file, WP_CONTENT_DIR . '/themes/' ) === false ) {
195
-            $this->basename = plugin_basename( $this->file );
196
-
197
-            list( $this->slug, $mainfile) = explode( '/', $this->basename );
198
-
199
-            require_once ABSPATH . 'wp-admin/includes/plugin.php';
200
-
201
-            $plugin_data = get_plugin_data( $this->file, false, false );
202
-
203
-            $this->project_version = $plugin_data['Version'];
204
-            $this->type = 'plugin';
205
-        } else {
206
-            $this->basename = str_replace( WP_CONTENT_DIR . '/themes/', '', $this->file );
207
-
208
-            list( $this->slug, $mainfile) = explode( '/', $this->basename );
209
-
210
-            $theme = wp_get_theme( $this->slug );
211
-
212
-            $this->project_version = $theme->version;
213
-            $this->type = 'theme';
214
-        }
215
-
216
-        $this->textdomain = $this->slug;
217
-    }
218
-
219
-    /**
220
-     * Send request to remote endpoint
221
-     *
222
-     * @param  array  $params
223
-     * @param  string $route
224
-     *
225
-     * @return array|WP_Error   Array of results including HTTP headers or WP_Error if the request failed.
226
-     */
227
-    public function send_request( $params, $route, $blocking = false ) {
228
-        $url = $this->endpoint() . $route;
229
-
230
-        $headers = array(
231
-            'user-agent' => 'Appsero/' . md5( esc_url( home_url() ) ) . ';',
232
-            'Accept'     => 'application/json',
233
-        );
234
-
235
-        $response = wp_remote_post( $url, array(
236
-            'method'      => 'POST',
237
-            'timeout'     => 30,
238
-            'redirection' => 5,
239
-            'httpversion' => '1.0',
240
-            'blocking'    => $blocking,
241
-            'headers'     => $headers,
242
-            'body'        => array_merge( $params, array( 'client' => $this->version ) ),
243
-            'cookies'     => array()
244
-        ) );
245
-
246
-        return $response;
247
-    }
248
-
249
-    /**
250
-     * Check if the current server is localhost
251
-     *
252
-     * @return boolean
253
-     */
254
-    public function is_local_server() {
255
-        $is_local = in_array( $_SERVER['REMOTE_ADDR'], array( '127.0.0.1', '::1' ) );
256
-
257
-        return apply_filters( 'appsero_is_local', $is_local );
258
-    }
259
-
260
-    /**
261
-     * Translate function _e()
262
-     */
263
-    public function _etrans( $text ) {
264
-        call_user_func( '_e', $text, $this->textdomain );
265
-    }
266
-
267
-    /**
268
-     * Translate function __()
269
-     */
270
-    public function __trans( $text ) {
271
-        return call_user_func( '__', $text, $this->textdomain );
272
-    }
273
-
274
-    /**
275
-     * Set project textdomain
276
-     */
277
-    public function set_textdomain( $textdomain ) {
278
-        $this->textdomain = $textdomain;
279
-    }
275
+	 * Set project textdomain
276
+	 */
277
+	public function set_textdomain( $textdomain ) {
278
+		$this->textdomain = $textdomain;
279
+	}
280 280
 }
Please login to merge, or discard this patch.
Spacing   +36 added lines, -36 removed lines patch added patch discarded remove patch
@@ -102,7 +102,7 @@  discard block
 block discarded – undo
102 102
      * @param string  $name readable name of the plugin
103 103
      * @param string  $file main plugin file path
104 104
      */
105
-    public function __construct( $hash, $name, $file ) {
105
+    public function __construct($hash, $name, $file) {
106 106
         $this->hash = $hash;
107 107
         $this->name = $name;
108 108
         $this->file = $file;
@@ -117,16 +117,16 @@  discard block
 block discarded – undo
117 117
      */
118 118
     public function insights() {
119 119
 
120
-        if ( ! class_exists( __NAMESPACE__ . '\Insights') ) {
121
-            require_once __DIR__ . '/Insights.php';
120
+        if ( ! class_exists(__NAMESPACE__.'\Insights')) {
121
+            require_once __DIR__.'/Insights.php';
122 122
         }
123 123
 
124 124
         // if already instantiated, return the cached one
125
-        if ( $this->insights ) {
125
+        if ($this->insights) {
126 126
             return $this->insights;
127 127
         }
128 128
 
129
-        $this->insights = new Insights( $this );
129
+        $this->insights = new Insights($this);
130 130
 
131 131
         return $this->insights;
132 132
     }
@@ -138,16 +138,16 @@  discard block
 block discarded – undo
138 138
      */
139 139
     public function updater() {
140 140
 
141
-        if ( ! class_exists( __NAMESPACE__ . '\Updater') ) {
142
-            require_once __DIR__ . '/Updater.php';
141
+        if ( ! class_exists(__NAMESPACE__.'\Updater')) {
142
+            require_once __DIR__.'/Updater.php';
143 143
         }
144 144
 
145 145
         // if already instantiated, return the cached one
146
-        if ( $this->updater ) {
146
+        if ($this->updater) {
147 147
             return $this->updater;
148 148
         }
149 149
 
150
-        $this->updater = new Updater( $this );
150
+        $this->updater = new Updater($this);
151 151
 
152 152
         return $this->updater;
153 153
     }
@@ -159,16 +159,16 @@  discard block
 block discarded – undo
159 159
      */
160 160
     public function license() {
161 161
 
162
-        if ( ! class_exists( __NAMESPACE__ . '\License') ) {
163
-            require_once __DIR__ . '/License.php';
162
+        if ( ! class_exists(__NAMESPACE__.'\License')) {
163
+            require_once __DIR__.'/License.php';
164 164
         }
165 165
 
166 166
         // if already instantiated, return the cached one
167
-        if ( $this->license ) {
167
+        if ($this->license) {
168 168
             return $this->license;
169 169
         }
170 170
 
171
-        $this->license = new License( $this );
171
+        $this->license = new License($this);
172 172
 
173 173
         return $this->license;
174 174
     }
@@ -179,9 +179,9 @@  discard block
 block discarded – undo
179 179
      * @return string
180 180
      */
181 181
     public function endpoint() {
182
-        $endpoint = apply_filters( 'appsero_endpoint', 'https://api.appsero.com' );
182
+        $endpoint = apply_filters('appsero_endpoint', 'https://api.appsero.com');
183 183
 
184
-        return trailingslashit( $endpoint );
184
+        return trailingslashit($endpoint);
185 185
     }
186 186
 
187 187
     /**
@@ -191,23 +191,23 @@  discard block
 block discarded – undo
191 191
      */
192 192
     protected function set_basename_and_slug() {
193 193
 
194
-        if ( strpos( $this->file, WP_CONTENT_DIR . '/themes/' ) === false ) {
195
-            $this->basename = plugin_basename( $this->file );
194
+        if (strpos($this->file, WP_CONTENT_DIR.'/themes/') === false) {
195
+            $this->basename = plugin_basename($this->file);
196 196
 
197
-            list( $this->slug, $mainfile) = explode( '/', $this->basename );
197
+            list($this->slug, $mainfile) = explode('/', $this->basename);
198 198
 
199
-            require_once ABSPATH . 'wp-admin/includes/plugin.php';
199
+            require_once ABSPATH.'wp-admin/includes/plugin.php';
200 200
 
201
-            $plugin_data = get_plugin_data( $this->file, false, false );
201
+            $plugin_data = get_plugin_data($this->file, false, false);
202 202
 
203 203
             $this->project_version = $plugin_data['Version'];
204 204
             $this->type = 'plugin';
205 205
         } else {
206
-            $this->basename = str_replace( WP_CONTENT_DIR . '/themes/', '', $this->file );
206
+            $this->basename = str_replace(WP_CONTENT_DIR.'/themes/', '', $this->file);
207 207
 
208
-            list( $this->slug, $mainfile) = explode( '/', $this->basename );
208
+            list($this->slug, $mainfile) = explode('/', $this->basename);
209 209
 
210
-            $theme = wp_get_theme( $this->slug );
210
+            $theme = wp_get_theme($this->slug);
211 211
 
212 212
             $this->project_version = $theme->version;
213 213
             $this->type = 'theme';
@@ -224,24 +224,24 @@  discard block
 block discarded – undo
224 224
      *
225 225
      * @return array|WP_Error   Array of results including HTTP headers or WP_Error if the request failed.
226 226
      */
227
-    public function send_request( $params, $route, $blocking = false ) {
228
-        $url = $this->endpoint() . $route;
227
+    public function send_request($params, $route, $blocking = false) {
228
+        $url = $this->endpoint().$route;
229 229
 
230 230
         $headers = array(
231
-            'user-agent' => 'Appsero/' . md5( esc_url( home_url() ) ) . ';',
231
+            'user-agent' => 'Appsero/'.md5(esc_url(home_url())).';',
232 232
             'Accept'     => 'application/json',
233 233
         );
234 234
 
235
-        $response = wp_remote_post( $url, array(
235
+        $response = wp_remote_post($url, array(
236 236
             'method'      => 'POST',
237 237
             'timeout'     => 30,
238 238
             'redirection' => 5,
239 239
             'httpversion' => '1.0',
240 240
             'blocking'    => $blocking,
241 241
             'headers'     => $headers,
242
-            'body'        => array_merge( $params, array( 'client' => $this->version ) ),
242
+            'body'        => array_merge($params, array('client' => $this->version)),
243 243
             'cookies'     => array()
244
-        ) );
244
+        ));
245 245
 
246 246
         return $response;
247 247
     }
@@ -252,29 +252,29 @@  discard block
 block discarded – undo
252 252
      * @return boolean
253 253
      */
254 254
     public function is_local_server() {
255
-        $is_local = in_array( $_SERVER['REMOTE_ADDR'], array( '127.0.0.1', '::1' ) );
255
+        $is_local = in_array($_SERVER['REMOTE_ADDR'], array('127.0.0.1', '::1'));
256 256
 
257
-        return apply_filters( 'appsero_is_local', $is_local );
257
+        return apply_filters('appsero_is_local', $is_local);
258 258
     }
259 259
 
260 260
     /**
261 261
      * Translate function _e()
262 262
      */
263
-    public function _etrans( $text ) {
264
-        call_user_func( '_e', $text, $this->textdomain );
263
+    public function _etrans($text) {
264
+        call_user_func('_e', $text, $this->textdomain);
265 265
     }
266 266
 
267 267
     /**
268 268
      * Translate function __()
269 269
      */
270
-    public function __trans( $text ) {
271
-        return call_user_func( '__', $text, $this->textdomain );
270
+    public function __trans($text) {
271
+        return call_user_func('__', $text, $this->textdomain);
272 272
     }
273 273
 
274 274
     /**
275 275
      * Set project textdomain
276 276
      */
277
-    public function set_textdomain( $textdomain ) {
277
+    public function set_textdomain($textdomain) {
278 278
         $this->textdomain = $textdomain;
279 279
     }
280 280
 }
Please login to merge, or discard this patch.
admin_pages/venues/Venues_Admin_Page_Init.core.php 1 patch
Indentation   +31 added lines, -31 removed lines patch added patch discarded remove patch
@@ -17,39 +17,39 @@
 block discarded – undo
17 17
  */
18 18
 class Venues_Admin_Page_Init extends EE_Admin_Page_CPT_Init
19 19
 {
20
-    public function __construct()
21
-    {
22
-        // define some event categories related constants
23
-        if (! defined('EE_VENUES_PG_SLUG')) {
24
-            define('EE_VENUES_PG_SLUG', 'espresso_venues');
25
-            define('EE_VENUES_ADMIN_URL', admin_url('admin.php?page=' . EE_VENUES_PG_SLUG));
26
-            define('EE_VENUES_ASSETS_URL', EE_ADMIN_PAGES_URL . 'venues/assets/');
27
-            define('EE_VENUES_TEMPLATE_PATH', EE_ADMIN_PAGES . 'venues/templates/');
28
-        }
29
-        parent::__construct();
30
-        $this->_folder_path = EE_ADMIN_PAGES . $this->_folder_name . '/';
31
-    }
20
+	public function __construct()
21
+	{
22
+		// define some event categories related constants
23
+		if (! defined('EE_VENUES_PG_SLUG')) {
24
+			define('EE_VENUES_PG_SLUG', 'espresso_venues');
25
+			define('EE_VENUES_ADMIN_URL', admin_url('admin.php?page=' . EE_VENUES_PG_SLUG));
26
+			define('EE_VENUES_ASSETS_URL', EE_ADMIN_PAGES_URL . 'venues/assets/');
27
+			define('EE_VENUES_TEMPLATE_PATH', EE_ADMIN_PAGES . 'venues/templates/');
28
+		}
29
+		parent::__construct();
30
+		$this->_folder_path = EE_ADMIN_PAGES . $this->_folder_name . '/';
31
+	}
32 32
 
33 33
 
34
-    protected function _set_init_properties()
35
-    {
36
-        $this->label      = esc_html__('Event Venues', 'event_espresso');
37
-        $this->menu_label = esc_html__('Venues', 'event_espresso');
38
-        $this->menu_slug  = EE_VENUES_PG_SLUG;
39
-    }
34
+	protected function _set_init_properties()
35
+	{
36
+		$this->label      = esc_html__('Event Venues', 'event_espresso');
37
+		$this->menu_label = esc_html__('Venues', 'event_espresso');
38
+		$this->menu_slug  = EE_VENUES_PG_SLUG;
39
+	}
40 40
 
41 41
 
42
-    public function getMenuProperties(): array
43
-    {
44
-        return [
45
-            'menu_type'    => AdminMenuItem::TYPE_MENU_SUB_ITEM,
46
-            'menu_group'   => AdminMenuGroup::MENU_SLUG_MANAGEMENT,
47
-            'menu_order'   => 40,
48
-            'show_on_menu' => AdminMenuItem::DISPLAY_BLOG_ONLY,
49
-            'parent_slug'  => AdminMenuTopLevel::MENU_PARENT_ACTIVE,
50
-            'menu_slug'    => EE_VENUES_PG_SLUG,
51
-            'menu_label'   => esc_html__('Venues', 'event_espresso'),
52
-            'capability'   => 'ee_read_venues',
53
-        ];
54
-    }
42
+	public function getMenuProperties(): array
43
+	{
44
+		return [
45
+			'menu_type'    => AdminMenuItem::TYPE_MENU_SUB_ITEM,
46
+			'menu_group'   => AdminMenuGroup::MENU_SLUG_MANAGEMENT,
47
+			'menu_order'   => 40,
48
+			'show_on_menu' => AdminMenuItem::DISPLAY_BLOG_ONLY,
49
+			'parent_slug'  => AdminMenuTopLevel::MENU_PARENT_ACTIVE,
50
+			'menu_slug'    => EE_VENUES_PG_SLUG,
51
+			'menu_label'   => esc_html__('Venues', 'event_espresso'),
52
+			'capability'   => 'ee_read_venues',
53
+		];
54
+	}
55 55
 }
Please login to merge, or discard this patch.
admin_pages/registrations/Registrations_Admin_Page_Init.core.php 1 patch
Indentation   +39 added lines, -39 removed lines patch added patch discarded remove patch
@@ -13,48 +13,48 @@
 block discarded – undo
13 13
  */
14 14
 class Registrations_Admin_Page_Init extends EE_Admin_Page_CPT_Init
15 15
 {
16
-    /**
17
-     *        constructor
18
-     *
19
-     * @Constructor
20
-     * @access public
21
-     * @return void
22
-     */
23
-    public function __construct()
24
-    {
25
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
26
-        if (! defined('REG_PG_SLUG')) {
27
-            define('REG_PG_SLUG', 'espresso_registrations');
28
-            define('REG_PG_NAME', ucwords(str_replace('_', '', REG_PG_SLUG)));
29
-            define('REG_ADMIN', EE_ADMIN_PAGES . 'registrations/');
30
-            define('REG_ADMIN_URL', admin_url('admin.php?page=' . REG_PG_SLUG));
31
-            define('REG_ASSETS_PATH', REG_ADMIN . 'assets/');
32
-            define('REG_ASSETS_URL', EE_ADMIN_PAGES_URL . 'registrations/assets/');
33
-            define('REG_TEMPLATE_PATH', REG_ADMIN . 'templates/');
34
-            define('REG_TEMPLATE_URL', EE_ADMIN_PAGES_URL . 'registrations/templates/');
35
-        }
16
+	/**
17
+	 *        constructor
18
+	 *
19
+	 * @Constructor
20
+	 * @access public
21
+	 * @return void
22
+	 */
23
+	public function __construct()
24
+	{
25
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
26
+		if (! defined('REG_PG_SLUG')) {
27
+			define('REG_PG_SLUG', 'espresso_registrations');
28
+			define('REG_PG_NAME', ucwords(str_replace('_', '', REG_PG_SLUG)));
29
+			define('REG_ADMIN', EE_ADMIN_PAGES . 'registrations/');
30
+			define('REG_ADMIN_URL', admin_url('admin.php?page=' . REG_PG_SLUG));
31
+			define('REG_ASSETS_PATH', REG_ADMIN . 'assets/');
32
+			define('REG_ASSETS_URL', EE_ADMIN_PAGES_URL . 'registrations/assets/');
33
+			define('REG_TEMPLATE_PATH', REG_ADMIN . 'templates/');
34
+			define('REG_TEMPLATE_URL', EE_ADMIN_PAGES_URL . 'registrations/templates/');
35
+		}
36 36
 
37
-        parent::__construct();
38
-    }
37
+		parent::__construct();
38
+	}
39 39
 
40 40
 
41
-    protected function _set_init_properties()
42
-    {
43
-        $this->label = esc_html__('Registrations Overview', 'event_espresso');
44
-    }
41
+	protected function _set_init_properties()
42
+	{
43
+		$this->label = esc_html__('Registrations Overview', 'event_espresso');
44
+	}
45 45
 
46 46
 
47
-    public function getMenuProperties(): array
48
-    {
49
-        return [
50
-            'menu_type'    => AdminMenuItem::TYPE_MENU_SUB_ITEM,
51
-            'menu_group'   => AdminMenuGroup::MENU_SLUG_MAIN,
52
-            'menu_order'   => 40,
53
-            'show_on_menu' => AdminMenuItem::DISPLAY_BLOG_ONLY,
54
-            'parent_slug'  => AdminMenuTopLevel::MENU_PARENT_ACTIVE,
55
-            'menu_slug'    => REG_PG_SLUG,
56
-            'menu_label'   => esc_html__('Registrations', 'event_espresso'),
57
-            'capability'   => 'ee_read_registrations',
58
-        ];
59
-    }
47
+	public function getMenuProperties(): array
48
+	{
49
+		return [
50
+			'menu_type'    => AdminMenuItem::TYPE_MENU_SUB_ITEM,
51
+			'menu_group'   => AdminMenuGroup::MENU_SLUG_MAIN,
52
+			'menu_order'   => 40,
53
+			'show_on_menu' => AdminMenuItem::DISPLAY_BLOG_ONLY,
54
+			'parent_slug'  => AdminMenuTopLevel::MENU_PARENT_ACTIVE,
55
+			'menu_slug'    => REG_PG_SLUG,
56
+			'menu_label'   => esc_html__('Registrations', 'event_espresso'),
57
+			'capability'   => 'ee_read_registrations',
58
+		];
59
+	}
60 60
 }
Please login to merge, or discard this patch.
admin_pages/about/About_Admin_Page_Init.core.php 1 patch
Indentation   +31 added lines, -31 removed lines patch added patch discarded remove patch
@@ -16,39 +16,39 @@
 block discarded – undo
16 16
  */
17 17
 class About_Admin_Page_Init extends EE_Admin_Page_Init
18 18
 {
19
-    public function __construct()
20
-    {
21
-        // define some events related constants
22
-        if (! defined('EE_ABOUT_PG_SLUG')) {
23
-            define('EE_ABOUT_PG_SLUG', 'espresso_about');
24
-            define('EE_ABOUT_LABEL', esc_html__('About', 'event_espresso'));
25
-            define('EE_ABOUT_ADMIN', EE_ADMIN_PAGES . 'about/');
26
-            define('EE_ABOUT_ADMIN_URL', admin_url('admin.php?page=' . EE_ABOUT_PG_SLUG));
27
-            define('EE_ABOUT_TEMPLATE_PATH', EE_ABOUT_ADMIN . 'templates/');
28
-            define('EE_ABOUT_ASSETS_URL', EE_ADMIN_PAGES_URL . 'about/assets/');
29
-        }
30
-        parent::__construct();
31
-    }
19
+	public function __construct()
20
+	{
21
+		// define some events related constants
22
+		if (! defined('EE_ABOUT_PG_SLUG')) {
23
+			define('EE_ABOUT_PG_SLUG', 'espresso_about');
24
+			define('EE_ABOUT_LABEL', esc_html__('About', 'event_espresso'));
25
+			define('EE_ABOUT_ADMIN', EE_ADMIN_PAGES . 'about/');
26
+			define('EE_ABOUT_ADMIN_URL', admin_url('admin.php?page=' . EE_ABOUT_PG_SLUG));
27
+			define('EE_ABOUT_TEMPLATE_PATH', EE_ABOUT_ADMIN . 'templates/');
28
+			define('EE_ABOUT_ASSETS_URL', EE_ADMIN_PAGES_URL . 'about/assets/');
29
+		}
30
+		parent::__construct();
31
+	}
32 32
 
33 33
 
34
-    protected function _set_init_properties()
35
-    {
36
-        $this->label = esc_html__('About Event Espresso', 'event_espresso');
37
-    }
34
+	protected function _set_init_properties()
35
+	{
36
+		$this->label = esc_html__('About Event Espresso', 'event_espresso');
37
+	}
38 38
 
39 39
 
40
-    public function getMenuProperties(): array
41
-    {
42
-        return [
43
-            'menu_type'               => AdminMenuItem::TYPE_MENU_SUB_ITEM,
44
-            'menu_group'              => AdminMenuGroup::MENU_SLUG_EXTRAS,
45
-            'menu_order'              => 40,
46
-            'show_on_menu'            => AdminMenuItem::DISPLAY_BLOG_AND_NETWORK,
47
-            'parent_slug'             => AdminMenuTopLevel::MENU_PARENT_ACTIVE,
48
-            'menu_slug'               => EE_ABOUT_PG_SLUG,
49
-            'menu_label'              => EE_ABOUT_LABEL,
50
-            'capability'              => 'manage_options',
51
-            'maintenance_mode_parent' => AdminMenuTopLevel::MENU_PARENT_MAINTENANCE,
52
-        ];
53
-    }
40
+	public function getMenuProperties(): array
41
+	{
42
+		return [
43
+			'menu_type'               => AdminMenuItem::TYPE_MENU_SUB_ITEM,
44
+			'menu_group'              => AdminMenuGroup::MENU_SLUG_EXTRAS,
45
+			'menu_order'              => 40,
46
+			'show_on_menu'            => AdminMenuItem::DISPLAY_BLOG_AND_NETWORK,
47
+			'parent_slug'             => AdminMenuTopLevel::MENU_PARENT_ACTIVE,
48
+			'menu_slug'               => EE_ABOUT_PG_SLUG,
49
+			'menu_label'              => EE_ABOUT_LABEL,
50
+			'capability'              => 'manage_options',
51
+			'maintenance_mode_parent' => AdminMenuTopLevel::MENU_PARENT_MAINTENANCE,
52
+		];
53
+	}
54 54
 }
Please login to merge, or discard this patch.
admin_pages/events/Events_Admin_Page.core.php 1 patch
Indentation   +2975 added lines, -2975 removed lines patch added patch discarded remove patch
@@ -22,2982 +22,2982 @@
 block discarded – undo
22 22
  */
23 23
 class Events_Admin_Page extends EE_Admin_Page_CPT
24 24
 {
25
-    /**
26
-     * primary key for the event model
27
-     */
28
-    private int $EVT_ID = 0;
29
-
30
-    /**
31
-     * This will hold the event object for event_details screen.
32
-     *
33
-     * @var EE_Event|null $_event
34
-     */
35
-    protected ?EE_Event $_event = null;
36
-
37
-    /**
38
-     * This will hold the category object for category_details screen.
39
-     */
40
-    protected ?stdClass $_category = null;
41
-
42
-    protected ?EEM_Event $_event_model = null;
43
-
44
-    /**
45
-     * @var EE_Event|EE_CPT_Base|null $_cpt_model_obj
46
-     */
47
-    protected $_cpt_model_obj;
48
-
49
-    protected ?NodeGroupDao $model_obj_node_group_persister = null;
50
-
51
-    protected ?AdvancedEditorAdminFormSection $advanced_editor_admin_form = null;
52
-
53
-
54
-    /**
55
-     * Initialize page props for this admin page group.
56
-     */
57
-    protected function _init_page_props()
58
-    {
59
-        // is there a evt_id in the request?
60
-        $this->EVT_ID = $this->request->getRequestParam('EVT_ID', 0, DataType::INT);
61
-        $this->EVT_ID = $this->request->getRequestParam('post', $this->EVT_ID, DataType::INT);
62
-        $this->EVT_ID = $this->request->getRequestParam('post_ID', $this->EVT_ID, DataType::INT);
63
-
64
-        $this->page_slug        = EVENTS_PG_SLUG;
65
-        $this->page_label       = EVENTS_LABEL;
66
-        $this->_admin_base_url  = EVENTS_ADMIN_URL;
67
-        $this->_admin_base_path = EVENTS_ADMIN;
68
-        $this->_cpt_model_names = [
69
-            'create_new' => 'EEM_Event',
70
-            'edit'       => 'EEM_Event',
71
-        ];
72
-        $this->_cpt_edit_routes = [
73
-            'espresso_events' => 'edit',
74
-        ];
75
-        add_action(
76
-            'AHEE__EE_Admin_Page_CPT__set_model_object__after_set_object',
77
-            [$this, 'verify_event_edit'],
78
-            10,
79
-            2
80
-        );
81
-    }
82
-
83
-
84
-    /**
85
-     * Sets the ajax hooks used for this admin page group.
86
-     */
87
-    protected function _ajax_hooks()
88
-    {
89
-        add_action('wp_ajax_ee_save_timezone_setting', [$this, 'saveTimezoneString']);
90
-    }
91
-
92
-
93
-    /**
94
-     * Sets the page properties for this admin page group.
95
-     */
96
-    protected function _define_page_props()
97
-    {
98
-        $this->_admin_page_title = EVENTS_LABEL;
99
-        $this->_labels           = [
100
-            'buttons'      => [
101
-                'add'             => esc_html__('Add New Event', 'event_espresso'),
102
-                'edit'            => esc_html__('Edit Event', 'event_espresso'),
103
-                'delete'          => esc_html__('Delete Event', 'event_espresso'),
104
-                'add_category'    => esc_html__('Add New Category', 'event_espresso'),
105
-                'edit_category'   => esc_html__('Edit Category', 'event_espresso'),
106
-                'delete_category' => esc_html__('Delete Category', 'event_espresso'),
107
-            ],
108
-            'editor_title' => [
109
-                'espresso_events' => esc_html__('Edit Event', 'event_espresso'),
110
-            ],
111
-            'publishbox'   => [
112
-                'create_new'        => esc_html__('Save New Event', 'event_espresso'),
113
-                'edit'              => esc_html__('Update Event', 'event_espresso'),
114
-                'add_category'      => esc_html__('Save New Category', 'event_espresso'),
115
-                'edit_category'     => esc_html__('Update Category', 'event_espresso'),
116
-                'template_settings' => esc_html__('Update Settings', 'event_espresso'),
117
-            ],
118
-        ];
119
-    }
120
-
121
-
122
-    /**
123
-     * Sets the page routes property for this admin page group.
124
-     */
125
-    protected function _set_page_routes()
126
-    {
127
-        $this->_page_routes = [
128
-            'default'                       => [
129
-                'func'       => [$this, '_events_overview_list_table'],
130
-                'capability' => 'ee_read_events',
131
-            ],
132
-            'create_new'                    => [
133
-                'func'       => [$this, '_create_new_cpt_item'],
134
-                'capability' => 'ee_edit_events',
135
-            ],
136
-            'edit'                          => [
137
-                'func'       => [$this, '_edit_cpt_item'],
138
-                'capability' => 'ee_edit_event',
139
-                'obj_id'     => $this->EVT_ID,
140
-            ],
141
-            'copy_event'                    => [
142
-                'func'       => [$this, '_copy_events'],
143
-                'capability' => 'ee_edit_event',
144
-                'obj_id'     => $this->EVT_ID,
145
-                'noheader'   => true,
146
-            ],
147
-            'trash_event'                   => [
148
-                'func'       => [$this, '_trash_or_restore_event'],
149
-                'args'       => ['event_status' => 'trash'],
150
-                'capability' => 'ee_delete_event',
151
-                'obj_id'     => $this->EVT_ID,
152
-                'noheader'   => true,
153
-            ],
154
-            'trash_events'                  => [
155
-                'func'       => [$this, '_trash_or_restore_events'],
156
-                'args'       => ['event_status' => 'trash'],
157
-                'capability' => 'ee_delete_events',
158
-                'noheader'   => true,
159
-            ],
160
-            'restore_event'                 => [
161
-                'func'       => [$this, '_trash_or_restore_event'],
162
-                'args'       => ['event_status' => 'draft'],
163
-                'capability' => 'ee_delete_event',
164
-                'obj_id'     => $this->EVT_ID,
165
-                'noheader'   => true,
166
-            ],
167
-            'restore_events'                => [
168
-                'func'       => [$this, '_trash_or_restore_events'],
169
-                'args'       => ['event_status' => 'draft'],
170
-                'capability' => 'ee_delete_events',
171
-                'noheader'   => true,
172
-            ],
173
-            'delete_event'                  => [
174
-                'func'       => [$this, '_delete_event'],
175
-                'capability' => 'ee_delete_event',
176
-                'obj_id'     => $this->EVT_ID,
177
-                'noheader'   => true,
178
-            ],
179
-            'delete_events'                 => [
180
-                'func'       => [$this, '_delete_events'],
181
-                'capability' => 'ee_delete_events',
182
-                'noheader'   => true,
183
-            ],
184
-            'view_report'                   => [
185
-                'func'       => [$this, '_view_report'],
186
-                'capability' => 'ee_edit_events',
187
-            ],
188
-            'default_event_settings'        => [
189
-                'func'       => [$this, '_default_event_settings'],
190
-                'capability' => 'manage_options',
191
-            ],
192
-            'update_default_event_settings' => [
193
-                'func'       => [$this, '_update_default_event_settings'],
194
-                'capability' => 'manage_options',
195
-                'noheader'   => true,
196
-            ],
197
-            'template_settings'             => [
198
-                'func'       => [$this, '_template_settings'],
199
-                'capability' => 'manage_options',
200
-            ],
201
-            // event category tab related
202
-            'add_category'                  => [
203
-                'func'       => [$this, '_category_details'],
204
-                'capability' => 'ee_edit_event_category',
205
-                'args'       => ['view' => 'add'],
206
-            ],
207
-            'edit_category'                 => [
208
-                'func'       => [$this, '_category_details'],
209
-                'capability' => 'ee_edit_event_category',
210
-                'args'       => ['view' => 'edit'],
211
-            ],
212
-            'delete_categories'             => [
213
-                'func'       => [$this, '_delete_categories'],
214
-                'capability' => 'ee_delete_event_category',
215
-                'noheader'   => true,
216
-            ],
217
-            'delete_category'               => [
218
-                'func'       => [$this, '_delete_categories'],
219
-                'capability' => 'ee_delete_event_category',
220
-                'noheader'   => true,
221
-            ],
222
-            'insert_category'               => [
223
-                'func'       => [$this, '_insert_or_update_category'],
224
-                'args'       => ['new_category' => true],
225
-                'capability' => 'ee_edit_event_category',
226
-                'noheader'   => true,
227
-            ],
228
-            'update_category'               => [
229
-                'func'       => [$this, '_insert_or_update_category'],
230
-                'args'       => ['new_category' => false],
231
-                'capability' => 'ee_edit_event_category',
232
-                'noheader'   => true,
233
-            ],
234
-            'category_list'                 => [
235
-                'func'       => [$this, '_category_list_table'],
236
-                'capability' => 'ee_manage_event_categories',
237
-            ],
238
-            'preview_deletion'              => [
239
-                'func'       => [$this, 'previewDeletion'],
240
-                'capability' => 'ee_delete_events',
241
-            ],
242
-            'confirm_deletion'              => [
243
-                'func'       => [$this, 'confirmDeletion'],
244
-                'capability' => 'ee_delete_events',
245
-                'noheader'   => true,
246
-            ],
247
-        ];
248
-    }
249
-
250
-
251
-    /**
252
-     * Set the _page_config property for this admin page group.
253
-     */
254
-    protected function _set_page_config()
255
-    {
256
-        $post_id            = $this->request->getRequestParam('post', 0, DataType::INT);
257
-        $EVT_CAT_ID         = $this->request->getRequestParam('EVT_CAT_ID', 0, DataType::INT);
258
-        $this->_page_config = [
259
-            'default'                => [
260
-                'nav'           => [
261
-                    'label' => esc_html__('Overview', 'event_espresso'),
262
-                    'icon'  => 'dashicons-list-view',
263
-                    'order' => 10,
264
-                ],
265
-                'list_table'    => 'Events_Admin_List_Table',
266
-                'help_tabs'     => [
267
-                    'events_overview_help_tab'                       => [
268
-                        'title'    => esc_html__('Events Overview', 'event_espresso'),
269
-                        'filename' => 'events_overview',
270
-                    ],
271
-                    'events_overview_table_column_headings_help_tab' => [
272
-                        'title'    => esc_html__('Events Overview Table Column Headings', 'event_espresso'),
273
-                        'filename' => 'events_overview_table_column_headings',
274
-                    ],
275
-                    'events_overview_filters_help_tab'               => [
276
-                        'title'    => esc_html__('Events Overview Filters', 'event_espresso'),
277
-                        'filename' => 'events_overview_filters',
278
-                    ],
279
-                    'events_overview_view_help_tab'                  => [
280
-                        'title'    => esc_html__('Events Overview Views', 'event_espresso'),
281
-                        'filename' => 'events_overview_views',
282
-                    ],
283
-                    'events_overview_other_help_tab'                 => [
284
-                        'title'    => esc_html__('Events Overview Other', 'event_espresso'),
285
-                        'filename' => 'events_overview_other',
286
-                    ],
287
-                ],
288
-                'require_nonce' => false,
289
-            ],
290
-            'create_new'             => [
291
-                'nav'           => [
292
-                    'label'      => esc_html__('Add New Event', 'event_espresso'),
293
-                    'icon'       => 'dashicons-plus-alt',
294
-                    'order'      => 15,
295
-                    'persistent' => false,
296
-                ],
297
-                'metaboxes'     => ['_register_event_editor_meta_boxes'],
298
-                'help_tabs'     => [
299
-                    'event_editor_help_tab'                            => [
300
-                        'title'    => esc_html__('Event Editor', 'event_espresso'),
301
-                        'filename' => 'event_editor',
302
-                    ],
303
-                    'event_editor_title_richtexteditor_help_tab'       => [
304
-                        'title'    => esc_html__('Event Title & Rich Text Editor', 'event_espresso'),
305
-                        'filename' => 'event_editor_title_richtexteditor',
306
-                    ],
307
-                    'event_editor_venue_details_help_tab'              => [
308
-                        'title'    => esc_html__('Event Venue Details', 'event_espresso'),
309
-                        'filename' => 'event_editor_venue_details',
310
-                    ],
311
-                    'event_editor_event_datetimes_help_tab'            => [
312
-                        'title'    => esc_html__('Event Datetimes', 'event_espresso'),
313
-                        'filename' => 'event_editor_event_datetimes',
314
-                    ],
315
-                    'event_editor_event_tickets_help_tab'              => [
316
-                        'title'    => esc_html__('Event Tickets', 'event_espresso'),
317
-                        'filename' => 'event_editor_event_tickets',
318
-                    ],
319
-                    'event_editor_event_registration_options_help_tab' => [
320
-                        'title'    => esc_html__('Event Registration Options', 'event_espresso'),
321
-                        'filename' => 'event_editor_event_registration_options',
322
-                    ],
323
-                    'event_editor_tags_categories_help_tab'            => [
324
-                        'title'    => esc_html__('Event Tags & Categories', 'event_espresso'),
325
-                        'filename' => 'event_editor_tags_categories',
326
-                    ],
327
-                    'event_editor_questions_registrants_help_tab'      => [
328
-                        'title'    => esc_html__('Questions for Registrants', 'event_espresso'),
329
-                        'filename' => 'event_editor_questions_registrants',
330
-                    ],
331
-                    'event_editor_save_new_event_help_tab'             => [
332
-                        'title'    => esc_html__('Save New Event', 'event_espresso'),
333
-                        'filename' => 'event_editor_save_new_event',
334
-                    ],
335
-                    'event_editor_other_help_tab'                      => [
336
-                        'title'    => esc_html__('Event Other', 'event_espresso'),
337
-                        'filename' => 'event_editor_other',
338
-                    ],
339
-                ],
340
-                'qtips'         => ['EE_Event_Editor_Decaf_Tips'],
341
-                'require_nonce' => false,
342
-            ],
343
-            'edit'                   => [
344
-                'nav'           => [
345
-                    'label'      => esc_html__('Edit Event', 'event_espresso'),
346
-                    'icon'       => 'dashicons-edit',
347
-                    'order'      => 15,
348
-                    'persistent' => false,
349
-                    'url'        => $post_id
350
-                        ? EE_Admin_Page::add_query_args_and_nonce(
351
-                            ['post' => $post_id, 'action' => 'edit'],
352
-                            $this->_current_page_view_url
353
-                        )
354
-                        : $this->_admin_base_url,
355
-                ],
356
-                'metaboxes'     => ['_register_event_editor_meta_boxes'],
357
-                'help_tabs'     => [
358
-                    'event_editor_help_tab'                            => [
359
-                        'title'    => esc_html__('Event Editor', 'event_espresso'),
360
-                        'filename' => 'event_editor',
361
-                    ],
362
-                    'event_editor_title_richtexteditor_help_tab'       => [
363
-                        'title'    => esc_html__('Event Title & Rich Text Editor', 'event_espresso'),
364
-                        'filename' => 'event_editor_title_richtexteditor',
365
-                    ],
366
-                    'event_editor_venue_details_help_tab'              => [
367
-                        'title'    => esc_html__('Event Venue Details', 'event_espresso'),
368
-                        'filename' => 'event_editor_venue_details',
369
-                    ],
370
-                    'event_editor_event_datetimes_help_tab'            => [
371
-                        'title'    => esc_html__('Event Datetimes', 'event_espresso'),
372
-                        'filename' => 'event_editor_event_datetimes',
373
-                    ],
374
-                    'event_editor_event_tickets_help_tab'              => [
375
-                        'title'    => esc_html__('Event Tickets', 'event_espresso'),
376
-                        'filename' => 'event_editor_event_tickets',
377
-                    ],
378
-                    'event_editor_event_registration_options_help_tab' => [
379
-                        'title'    => esc_html__('Event Registration Options', 'event_espresso'),
380
-                        'filename' => 'event_editor_event_registration_options',
381
-                    ],
382
-                    'event_editor_tags_categories_help_tab'            => [
383
-                        'title'    => esc_html__('Event Tags & Categories', 'event_espresso'),
384
-                        'filename' => 'event_editor_tags_categories',
385
-                    ],
386
-                    'event_editor_questions_registrants_help_tab'      => [
387
-                        'title'    => esc_html__('Questions for Registrants', 'event_espresso'),
388
-                        'filename' => 'event_editor_questions_registrants',
389
-                    ],
390
-                    'event_editor_save_new_event_help_tab'             => [
391
-                        'title'    => esc_html__('Save New Event', 'event_espresso'),
392
-                        'filename' => 'event_editor_save_new_event',
393
-                    ],
394
-                    'event_editor_other_help_tab'                      => [
395
-                        'title'    => esc_html__('Event Other', 'event_espresso'),
396
-                        'filename' => 'event_editor_other',
397
-                    ],
398
-                ],
399
-                'require_nonce' => false,
400
-            ],
401
-            'default_event_settings' => [
402
-                'nav'           => [
403
-                    'label' => esc_html__('Default Settings', 'event_espresso'),
404
-                    'icon'  => 'dashicons-admin-generic',
405
-                    'order' => 40,
406
-                ],
407
-                'metaboxes'     => array_merge(['_publish_post_box'], $this->_default_espresso_metaboxes),
408
-                'labels'        => [
409
-                    'publishbox' => esc_html__('Update Settings', 'event_espresso'),
410
-                ],
411
-                'help_tabs'     => [
412
-                    'default_settings_help_tab'        => [
413
-                        'title'    => esc_html__('Default Event Settings', 'event_espresso'),
414
-                        'filename' => 'events_default_settings',
415
-                    ],
416
-                    'default_settings_status_help_tab' => [
417
-                        'title'    => esc_html__('Default Registration Status', 'event_espresso'),
418
-                        'filename' => 'events_default_settings_status',
419
-                    ],
420
-                    'default_maximum_tickets_help_tab' => [
421
-                        'title'    => esc_html__('Default Maximum Tickets Per Order', 'event_espresso'),
422
-                        'filename' => 'events_default_settings_max_tickets',
423
-                    ],
424
-                ],
425
-                'require_nonce' => false,
426
-            ],
427
-            // template settings
428
-            'template_settings'      => [
429
-                'nav'           => [
430
-                    'label' => esc_html__('Templates', 'event_espresso'),
431
-                    'icon'  => 'dashicons-layout',
432
-                    'order' => 30,
433
-                ],
434
-                'metaboxes'     => $this->_default_espresso_metaboxes,
435
-                'help_tabs'     => [
436
-                    'general_settings_templates_help_tab' => [
437
-                        'title'    => esc_html__('Templates', 'event_espresso'),
438
-                        'filename' => 'general_settings_templates',
439
-                    ],
440
-                ],
441
-                'require_nonce' => false,
442
-            ],
443
-            // event category stuff
444
-            'add_category'           => [
445
-                'nav'           => [
446
-                    'label'      => esc_html__('Add Category', 'event_espresso'),
447
-                    'icon'       => 'dashicons-plus-alt',
448
-                    'order'      => 25,
449
-                    'persistent' => false,
450
-                ],
451
-                'help_tabs'     => [
452
-                    'add_category_help_tab' => [
453
-                        'title'    => esc_html__('Add New Event Category', 'event_espresso'),
454
-                        'filename' => 'events_add_category',
455
-                    ],
456
-                ],
457
-                'metaboxes'     => ['_publish_post_box'],
458
-                'require_nonce' => false,
459
-            ],
460
-            'edit_category'          => [
461
-                'nav'           => [
462
-                    'label'      => esc_html__('Edit Category', 'event_espresso'),
463
-                    'icon'       => 'dashicons-edit',
464
-                    'order'      => 25,
465
-                    'persistent' => false,
466
-                    'url'        => $EVT_CAT_ID
467
-                        ? add_query_arg(
468
-                            ['EVT_CAT_ID' => $EVT_CAT_ID],
469
-                            $this->_current_page_view_url
470
-                        )
471
-                        : $this->_admin_base_url,
472
-                ],
473
-                'help_tabs'     => [
474
-                    'edit_category_help_tab' => [
475
-                        'title'    => esc_html__('Edit Event Category', 'event_espresso'),
476
-                        'filename' => 'events_edit_category',
477
-                    ],
478
-                ],
479
-                'metaboxes'     => ['_publish_post_box'],
480
-                'require_nonce' => false,
481
-            ],
482
-            'category_list'          => [
483
-                'nav'           => [
484
-                    'label' => esc_html__('Categories', 'event_espresso'),
485
-                    'icon'  => 'dashicons-networking',
486
-                    'order' => 20,
487
-                ],
488
-                'list_table'    => 'Event_Categories_Admin_List_Table',
489
-                'help_tabs'     => [
490
-                    'events_categories_help_tab'                       => [
491
-                        'title'    => esc_html__('Event Categories', 'event_espresso'),
492
-                        'filename' => 'events_categories',
493
-                    ],
494
-                    'events_categories_table_column_headings_help_tab' => [
495
-                        'title'    => esc_html__('Event Categories Table Column Headings', 'event_espresso'),
496
-                        'filename' => 'events_categories_table_column_headings',
497
-                    ],
498
-                    'events_categories_view_help_tab'                  => [
499
-                        'title'    => esc_html__('Event Categories Views', 'event_espresso'),
500
-                        'filename' => 'events_categories_views',
501
-                    ],
502
-                    'events_categories_other_help_tab'                 => [
503
-                        'title'    => esc_html__('Event Categories Other', 'event_espresso'),
504
-                        'filename' => 'events_categories_other',
505
-                    ],
506
-                ],
507
-                'metaboxes'     => $this->_default_espresso_metaboxes,
508
-                'require_nonce' => false,
509
-            ],
510
-            'preview_deletion'       => [
511
-                'nav'           => [
512
-                    'label'      => esc_html__('Preview Deletion', 'event_espresso'),
513
-                    'icon'       => 'dashicons-remove',
514
-                    'order'      => 15,
515
-                    'persistent' => false,
516
-                    'url'        => '',
517
-                ],
518
-                'require_nonce' => false,
519
-            ],
520
-        ];
521
-    }
522
-
523
-
524
-    /**
525
-     * Used to register any global screen options if necessary for every route in this admin page group.
526
-     */
527
-    protected function _add_screen_options()
528
-    {
529
-    }
530
-
531
-
532
-    /**
533
-     * Implementing the screen options for the 'default' route.
534
-     *
535
-     * @throws InvalidArgumentException
536
-     * @throws InvalidDataTypeException
537
-     * @throws InvalidInterfaceException
538
-     */
539
-    protected function _add_screen_options_default()
540
-    {
541
-        $this->_per_page_screen_option();
542
-    }
543
-
544
-
545
-    /**
546
-     * Implementing screen options for the category list route.
547
-     *
548
-     * @throws InvalidArgumentException
549
-     * @throws InvalidDataTypeException
550
-     * @throws InvalidInterfaceException
551
-     */
552
-    protected function _add_screen_options_category_list()
553
-    {
554
-        $page_title              = $this->_admin_page_title;
555
-        $this->_admin_page_title = esc_html__('Categories', 'event_espresso');
556
-        $this->_per_page_screen_option();
557
-        $this->_admin_page_title = $page_title;
558
-    }
559
-
560
-
561
-    /**
562
-     * Used to register any global feature pointers for the admin page group.
563
-     */
564
-    protected function _add_feature_pointers()
565
-    {
566
-    }
567
-
568
-
569
-    /**
570
-     * Registers and enqueues any global scripts and styles for the entire admin page group.
571
-     */
572
-    public function load_scripts_styles()
573
-    {
574
-        wp_enqueue_style(
575
-            'events-admin-css',
576
-            EVENTS_ASSETS_URL . 'events-admin-page.css',
577
-            [],
578
-            EVENT_ESPRESSO_VERSION
579
-        );
580
-        wp_enqueue_style(
581
-            'ee-cat-admin',
582
-            EVENTS_ASSETS_URL . 'ee-cat-admin.css',
583
-            ['editor-buttons'],
584
-            EVENT_ESPRESSO_VERSION
585
-        );
586
-    }
587
-
588
-
589
-    /**
590
-     * Enqueuing scripts and styles specific to this view
591
-     */
592
-    public function load_scripts_styles_create_new()
593
-    {
594
-        $this->load_scripts_styles_edit();
595
-    }
596
-
597
-
598
-    /**
599
-     * Enqueuing scripts and styles specific to this view
600
-     */
601
-    public function load_scripts_styles_edit()
602
-    {
603
-        // styles
604
-        wp_enqueue_style('espresso-ui-theme');
605
-        wp_enqueue_style(
606
-            'event-editor-css',
607
-            EVENTS_ASSETS_URL . 'event-editor.css',
608
-            ['ee-admin-css'],
609
-            EVENT_ESPRESSO_VERSION
610
-        );
611
-        // scripts
612
-        wp_enqueue_script(
613
-            'event_editor_js',
614
-            EVENTS_ASSETS_URL . 'event_editor.js',
615
-            [
616
-                EspressoLegacyAdminAssetManager::JS_HANDLE_EE_ADMIN,
617
-                JqueryAssetManager::JS_HANDLE_JQUERY_UI_SLIDER,
618
-                JqueryAssetManager::JS_HANDLE_JQUERY_UI_TIMEPICKER_ADDON
619
-            ],
620
-            EVENT_ESPRESSO_VERSION,
621
-            true
622
-        );
623
-        if (! $this->admin_config->useAdvancedEditor()) {
624
-            wp_enqueue_script(
625
-                'event-datetime-metabox',
626
-                EVENTS_ASSETS_URL . 'event-datetime-metabox.js',
627
-                ['event_editor_js', 'ee-datepicker'],
628
-                EVENT_ESPRESSO_VERSION
629
-            );
630
-        }
631
-    }
632
-
633
-
634
-    /**
635
-     * Populating the _views property for the category list table view.
636
-     */
637
-    protected function _set_list_table_views_category_list()
638
-    {
639
-        $this->_views = [
640
-            'all' => [
641
-                'slug'        => 'all',
642
-                'label'       => esc_html__('All', 'event_espresso'),
643
-                'count'       => 0,
644
-                'bulk_action' => [
645
-                    'delete_categories' => esc_html__('Delete Permanently', 'event_espresso'),
646
-                ],
647
-            ],
648
-        ];
649
-    }
650
-
651
-
652
-    /**
653
-     * For adding anything that fires on the admin_init hook for any route within this admin page group.
654
-     */
655
-    public function admin_init()
656
-    {
657
-        EE_Registry::$i18n_js_strings['image_confirm'] = wp_strip_all_tags(
658
-            esc_html__(
659
-                'Do you really want to delete this image? Please remember to update your event to complete the removal.',
660
-                'event_espresso'
661
-            )
662
-        );
663
-
664
-        EE_Registry::$i18n_js_strings['entity_locked'] = wp_strip_all_tags(
665
-            __(
666
-                'This item can not be deleted because it it as locked. It may be in use by the system or have been sold.',
667
-                'event_espresso'
668
-            )
669
-        );
670
-    }
671
-
672
-
673
-    /**
674
-     * For adding anything that should be triggered on the admin_notices hook for any route within this admin page
675
-     * group.
676
-     */
677
-    public function admin_notices()
678
-    {
679
-    }
680
-
681
-
682
-    /**
683
-     * For adding anything that should be triggered on the `admin_print_footer_scripts` hook for any route within
684
-     * this admin page group.
685
-     */
686
-    public function admin_footer_scripts()
687
-    {
688
-    }
689
-
690
-
691
-    /**
692
-     * Call this function to verify if an event is public and has tickets for sale.  If it does, then we need to show a
693
-     * warning (via EE_Error::add_error());
694
-     *
695
-     * @param EE_Event|null $event Event object
696
-     * @param string        $req_type
697
-     * @return void
698
-     * @throws EE_Error
699
-     * @throws ReflectionException
700
-     */
701
-    public function verify_event_edit(?EE_Base_Class $event = null, string $req_type = '')
702
-    {
703
-        // don't need to do this when processing
704
-        if (! empty($req_type)) {
705
-            return;
706
-        }
707
-        // no event?
708
-        if (! $event instanceof EE_Event) {
709
-            $event = $this->_cpt_model_obj;
710
-        }
711
-        // STILL no event?
712
-        if (! $event instanceof EE_Event) {
713
-            return;
714
-        }
715
-        // don't need to keep calling this
716
-        remove_action(
717
-            'AHEE__EE_Admin_Page_CPT__set_model_object__after_set_object',
718
-            [$this, 'verify_event_edit']
719
-        );
720
-        $orig_status = $event->status();
721
-        // first check if event is active.
722
-        if (
723
-            $orig_status === EEM_Event::cancelled
724
-            || $orig_status === EEM_Event::postponed
725
-            || $event->is_expired()
726
-            || $event->is_inactive()
727
-        ) {
728
-            return;
729
-        }
730
-        // made it here so it IS active... next check that any of the tickets are sold.
731
-        if ($event->is_sold_out(true)) {
732
-            if ($orig_status !== EEM_Event::sold_out && $event->status() !== $orig_status) {
733
-                EE_Error::add_attention(
734
-                    sprintf(
735
-                        esc_html__(
736
-                            '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.',
737
-                            'event_espresso'
738
-                        ),
739
-                        EEH_Template::pretty_status(EEM_Event::sold_out, false, 'sentence')
740
-                    )
741
-                );
742
-            }
743
-            return;
744
-        }
745
-        if ($orig_status === EEM_Event::sold_out) {
746
-            EE_Error::add_attention(
747
-                sprintf(
748
-                    esc_html__(
749
-                        '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.',
750
-                        'event_espresso'
751
-                    ),
752
-                    EEH_Template::pretty_status($event->status(), false, 'sentence')
753
-                )
754
-            );
755
-        }
756
-        // now we need to determine if the event has any tickets on sale.  If not then we dont' show the error
757
-        if (! $event->tickets_on_sale()) {
758
-            return;
759
-        }
760
-        // made it here so show warning
761
-        $this->_edit_event_warning();
762
-    }
763
-
764
-
765
-    /**
766
-     * This is the text used for when an event is being edited that is public and has tickets for sale.
767
-     * When needed, hook this into a EE_Error::add_error() notice.
768
-     *
769
-     * @access protected
770
-     * @return void
771
-     */
772
-    protected function _edit_event_warning()
773
-    {
774
-        // we don't want to add warnings during these requests
775
-        if ($this->request->getRequestParam('action') === 'editpost') {
776
-            return;
777
-        }
778
-        EE_Error::add_attention(
779
-            sprintf(
780
-                esc_html__(
781
-                    'Your event is open for registration. Making changes may disrupt any transactions in progress. %sLearn more%s',
782
-                    'event_espresso'
783
-                ),
784
-                '<a class="espresso-help-tab-lnk ee-help-tab-link">',
785
-                '</a>'
786
-            )
787
-        );
788
-    }
789
-
790
-
791
-    /**
792
-     * When a user is creating a new event, notify them if they haven't set their timezone.
793
-     * Otherwise, do the normal logic
25
+	/**
26
+	 * primary key for the event model
27
+	 */
28
+	private int $EVT_ID = 0;
29
+
30
+	/**
31
+	 * This will hold the event object for event_details screen.
32
+	 *
33
+	 * @var EE_Event|null $_event
34
+	 */
35
+	protected ?EE_Event $_event = null;
36
+
37
+	/**
38
+	 * This will hold the category object for category_details screen.
39
+	 */
40
+	protected ?stdClass $_category = null;
41
+
42
+	protected ?EEM_Event $_event_model = null;
43
+
44
+	/**
45
+	 * @var EE_Event|EE_CPT_Base|null $_cpt_model_obj
46
+	 */
47
+	protected $_cpt_model_obj;
48
+
49
+	protected ?NodeGroupDao $model_obj_node_group_persister = null;
50
+
51
+	protected ?AdvancedEditorAdminFormSection $advanced_editor_admin_form = null;
52
+
53
+
54
+	/**
55
+	 * Initialize page props for this admin page group.
56
+	 */
57
+	protected function _init_page_props()
58
+	{
59
+		// is there a evt_id in the request?
60
+		$this->EVT_ID = $this->request->getRequestParam('EVT_ID', 0, DataType::INT);
61
+		$this->EVT_ID = $this->request->getRequestParam('post', $this->EVT_ID, DataType::INT);
62
+		$this->EVT_ID = $this->request->getRequestParam('post_ID', $this->EVT_ID, DataType::INT);
63
+
64
+		$this->page_slug        = EVENTS_PG_SLUG;
65
+		$this->page_label       = EVENTS_LABEL;
66
+		$this->_admin_base_url  = EVENTS_ADMIN_URL;
67
+		$this->_admin_base_path = EVENTS_ADMIN;
68
+		$this->_cpt_model_names = [
69
+			'create_new' => 'EEM_Event',
70
+			'edit'       => 'EEM_Event',
71
+		];
72
+		$this->_cpt_edit_routes = [
73
+			'espresso_events' => 'edit',
74
+		];
75
+		add_action(
76
+			'AHEE__EE_Admin_Page_CPT__set_model_object__after_set_object',
77
+			[$this, 'verify_event_edit'],
78
+			10,
79
+			2
80
+		);
81
+	}
82
+
83
+
84
+	/**
85
+	 * Sets the ajax hooks used for this admin page group.
86
+	 */
87
+	protected function _ajax_hooks()
88
+	{
89
+		add_action('wp_ajax_ee_save_timezone_setting', [$this, 'saveTimezoneString']);
90
+	}
91
+
92
+
93
+	/**
94
+	 * Sets the page properties for this admin page group.
95
+	 */
96
+	protected function _define_page_props()
97
+	{
98
+		$this->_admin_page_title = EVENTS_LABEL;
99
+		$this->_labels           = [
100
+			'buttons'      => [
101
+				'add'             => esc_html__('Add New Event', 'event_espresso'),
102
+				'edit'            => esc_html__('Edit Event', 'event_espresso'),
103
+				'delete'          => esc_html__('Delete Event', 'event_espresso'),
104
+				'add_category'    => esc_html__('Add New Category', 'event_espresso'),
105
+				'edit_category'   => esc_html__('Edit Category', 'event_espresso'),
106
+				'delete_category' => esc_html__('Delete Category', 'event_espresso'),
107
+			],
108
+			'editor_title' => [
109
+				'espresso_events' => esc_html__('Edit Event', 'event_espresso'),
110
+			],
111
+			'publishbox'   => [
112
+				'create_new'        => esc_html__('Save New Event', 'event_espresso'),
113
+				'edit'              => esc_html__('Update Event', 'event_espresso'),
114
+				'add_category'      => esc_html__('Save New Category', 'event_espresso'),
115
+				'edit_category'     => esc_html__('Update Category', 'event_espresso'),
116
+				'template_settings' => esc_html__('Update Settings', 'event_espresso'),
117
+			],
118
+		];
119
+	}
120
+
121
+
122
+	/**
123
+	 * Sets the page routes property for this admin page group.
124
+	 */
125
+	protected function _set_page_routes()
126
+	{
127
+		$this->_page_routes = [
128
+			'default'                       => [
129
+				'func'       => [$this, '_events_overview_list_table'],
130
+				'capability' => 'ee_read_events',
131
+			],
132
+			'create_new'                    => [
133
+				'func'       => [$this, '_create_new_cpt_item'],
134
+				'capability' => 'ee_edit_events',
135
+			],
136
+			'edit'                          => [
137
+				'func'       => [$this, '_edit_cpt_item'],
138
+				'capability' => 'ee_edit_event',
139
+				'obj_id'     => $this->EVT_ID,
140
+			],
141
+			'copy_event'                    => [
142
+				'func'       => [$this, '_copy_events'],
143
+				'capability' => 'ee_edit_event',
144
+				'obj_id'     => $this->EVT_ID,
145
+				'noheader'   => true,
146
+			],
147
+			'trash_event'                   => [
148
+				'func'       => [$this, '_trash_or_restore_event'],
149
+				'args'       => ['event_status' => 'trash'],
150
+				'capability' => 'ee_delete_event',
151
+				'obj_id'     => $this->EVT_ID,
152
+				'noheader'   => true,
153
+			],
154
+			'trash_events'                  => [
155
+				'func'       => [$this, '_trash_or_restore_events'],
156
+				'args'       => ['event_status' => 'trash'],
157
+				'capability' => 'ee_delete_events',
158
+				'noheader'   => true,
159
+			],
160
+			'restore_event'                 => [
161
+				'func'       => [$this, '_trash_or_restore_event'],
162
+				'args'       => ['event_status' => 'draft'],
163
+				'capability' => 'ee_delete_event',
164
+				'obj_id'     => $this->EVT_ID,
165
+				'noheader'   => true,
166
+			],
167
+			'restore_events'                => [
168
+				'func'       => [$this, '_trash_or_restore_events'],
169
+				'args'       => ['event_status' => 'draft'],
170
+				'capability' => 'ee_delete_events',
171
+				'noheader'   => true,
172
+			],
173
+			'delete_event'                  => [
174
+				'func'       => [$this, '_delete_event'],
175
+				'capability' => 'ee_delete_event',
176
+				'obj_id'     => $this->EVT_ID,
177
+				'noheader'   => true,
178
+			],
179
+			'delete_events'                 => [
180
+				'func'       => [$this, '_delete_events'],
181
+				'capability' => 'ee_delete_events',
182
+				'noheader'   => true,
183
+			],
184
+			'view_report'                   => [
185
+				'func'       => [$this, '_view_report'],
186
+				'capability' => 'ee_edit_events',
187
+			],
188
+			'default_event_settings'        => [
189
+				'func'       => [$this, '_default_event_settings'],
190
+				'capability' => 'manage_options',
191
+			],
192
+			'update_default_event_settings' => [
193
+				'func'       => [$this, '_update_default_event_settings'],
194
+				'capability' => 'manage_options',
195
+				'noheader'   => true,
196
+			],
197
+			'template_settings'             => [
198
+				'func'       => [$this, '_template_settings'],
199
+				'capability' => 'manage_options',
200
+			],
201
+			// event category tab related
202
+			'add_category'                  => [
203
+				'func'       => [$this, '_category_details'],
204
+				'capability' => 'ee_edit_event_category',
205
+				'args'       => ['view' => 'add'],
206
+			],
207
+			'edit_category'                 => [
208
+				'func'       => [$this, '_category_details'],
209
+				'capability' => 'ee_edit_event_category',
210
+				'args'       => ['view' => 'edit'],
211
+			],
212
+			'delete_categories'             => [
213
+				'func'       => [$this, '_delete_categories'],
214
+				'capability' => 'ee_delete_event_category',
215
+				'noheader'   => true,
216
+			],
217
+			'delete_category'               => [
218
+				'func'       => [$this, '_delete_categories'],
219
+				'capability' => 'ee_delete_event_category',
220
+				'noheader'   => true,
221
+			],
222
+			'insert_category'               => [
223
+				'func'       => [$this, '_insert_or_update_category'],
224
+				'args'       => ['new_category' => true],
225
+				'capability' => 'ee_edit_event_category',
226
+				'noheader'   => true,
227
+			],
228
+			'update_category'               => [
229
+				'func'       => [$this, '_insert_or_update_category'],
230
+				'args'       => ['new_category' => false],
231
+				'capability' => 'ee_edit_event_category',
232
+				'noheader'   => true,
233
+			],
234
+			'category_list'                 => [
235
+				'func'       => [$this, '_category_list_table'],
236
+				'capability' => 'ee_manage_event_categories',
237
+			],
238
+			'preview_deletion'              => [
239
+				'func'       => [$this, 'previewDeletion'],
240
+				'capability' => 'ee_delete_events',
241
+			],
242
+			'confirm_deletion'              => [
243
+				'func'       => [$this, 'confirmDeletion'],
244
+				'capability' => 'ee_delete_events',
245
+				'noheader'   => true,
246
+			],
247
+		];
248
+	}
249
+
250
+
251
+	/**
252
+	 * Set the _page_config property for this admin page group.
253
+	 */
254
+	protected function _set_page_config()
255
+	{
256
+		$post_id            = $this->request->getRequestParam('post', 0, DataType::INT);
257
+		$EVT_CAT_ID         = $this->request->getRequestParam('EVT_CAT_ID', 0, DataType::INT);
258
+		$this->_page_config = [
259
+			'default'                => [
260
+				'nav'           => [
261
+					'label' => esc_html__('Overview', 'event_espresso'),
262
+					'icon'  => 'dashicons-list-view',
263
+					'order' => 10,
264
+				],
265
+				'list_table'    => 'Events_Admin_List_Table',
266
+				'help_tabs'     => [
267
+					'events_overview_help_tab'                       => [
268
+						'title'    => esc_html__('Events Overview', 'event_espresso'),
269
+						'filename' => 'events_overview',
270
+					],
271
+					'events_overview_table_column_headings_help_tab' => [
272
+						'title'    => esc_html__('Events Overview Table Column Headings', 'event_espresso'),
273
+						'filename' => 'events_overview_table_column_headings',
274
+					],
275
+					'events_overview_filters_help_tab'               => [
276
+						'title'    => esc_html__('Events Overview Filters', 'event_espresso'),
277
+						'filename' => 'events_overview_filters',
278
+					],
279
+					'events_overview_view_help_tab'                  => [
280
+						'title'    => esc_html__('Events Overview Views', 'event_espresso'),
281
+						'filename' => 'events_overview_views',
282
+					],
283
+					'events_overview_other_help_tab'                 => [
284
+						'title'    => esc_html__('Events Overview Other', 'event_espresso'),
285
+						'filename' => 'events_overview_other',
286
+					],
287
+				],
288
+				'require_nonce' => false,
289
+			],
290
+			'create_new'             => [
291
+				'nav'           => [
292
+					'label'      => esc_html__('Add New Event', 'event_espresso'),
293
+					'icon'       => 'dashicons-plus-alt',
294
+					'order'      => 15,
295
+					'persistent' => false,
296
+				],
297
+				'metaboxes'     => ['_register_event_editor_meta_boxes'],
298
+				'help_tabs'     => [
299
+					'event_editor_help_tab'                            => [
300
+						'title'    => esc_html__('Event Editor', 'event_espresso'),
301
+						'filename' => 'event_editor',
302
+					],
303
+					'event_editor_title_richtexteditor_help_tab'       => [
304
+						'title'    => esc_html__('Event Title & Rich Text Editor', 'event_espresso'),
305
+						'filename' => 'event_editor_title_richtexteditor',
306
+					],
307
+					'event_editor_venue_details_help_tab'              => [
308
+						'title'    => esc_html__('Event Venue Details', 'event_espresso'),
309
+						'filename' => 'event_editor_venue_details',
310
+					],
311
+					'event_editor_event_datetimes_help_tab'            => [
312
+						'title'    => esc_html__('Event Datetimes', 'event_espresso'),
313
+						'filename' => 'event_editor_event_datetimes',
314
+					],
315
+					'event_editor_event_tickets_help_tab'              => [
316
+						'title'    => esc_html__('Event Tickets', 'event_espresso'),
317
+						'filename' => 'event_editor_event_tickets',
318
+					],
319
+					'event_editor_event_registration_options_help_tab' => [
320
+						'title'    => esc_html__('Event Registration Options', 'event_espresso'),
321
+						'filename' => 'event_editor_event_registration_options',
322
+					],
323
+					'event_editor_tags_categories_help_tab'            => [
324
+						'title'    => esc_html__('Event Tags & Categories', 'event_espresso'),
325
+						'filename' => 'event_editor_tags_categories',
326
+					],
327
+					'event_editor_questions_registrants_help_tab'      => [
328
+						'title'    => esc_html__('Questions for Registrants', 'event_espresso'),
329
+						'filename' => 'event_editor_questions_registrants',
330
+					],
331
+					'event_editor_save_new_event_help_tab'             => [
332
+						'title'    => esc_html__('Save New Event', 'event_espresso'),
333
+						'filename' => 'event_editor_save_new_event',
334
+					],
335
+					'event_editor_other_help_tab'                      => [
336
+						'title'    => esc_html__('Event Other', 'event_espresso'),
337
+						'filename' => 'event_editor_other',
338
+					],
339
+				],
340
+				'qtips'         => ['EE_Event_Editor_Decaf_Tips'],
341
+				'require_nonce' => false,
342
+			],
343
+			'edit'                   => [
344
+				'nav'           => [
345
+					'label'      => esc_html__('Edit Event', 'event_espresso'),
346
+					'icon'       => 'dashicons-edit',
347
+					'order'      => 15,
348
+					'persistent' => false,
349
+					'url'        => $post_id
350
+						? EE_Admin_Page::add_query_args_and_nonce(
351
+							['post' => $post_id, 'action' => 'edit'],
352
+							$this->_current_page_view_url
353
+						)
354
+						: $this->_admin_base_url,
355
+				],
356
+				'metaboxes'     => ['_register_event_editor_meta_boxes'],
357
+				'help_tabs'     => [
358
+					'event_editor_help_tab'                            => [
359
+						'title'    => esc_html__('Event Editor', 'event_espresso'),
360
+						'filename' => 'event_editor',
361
+					],
362
+					'event_editor_title_richtexteditor_help_tab'       => [
363
+						'title'    => esc_html__('Event Title & Rich Text Editor', 'event_espresso'),
364
+						'filename' => 'event_editor_title_richtexteditor',
365
+					],
366
+					'event_editor_venue_details_help_tab'              => [
367
+						'title'    => esc_html__('Event Venue Details', 'event_espresso'),
368
+						'filename' => 'event_editor_venue_details',
369
+					],
370
+					'event_editor_event_datetimes_help_tab'            => [
371
+						'title'    => esc_html__('Event Datetimes', 'event_espresso'),
372
+						'filename' => 'event_editor_event_datetimes',
373
+					],
374
+					'event_editor_event_tickets_help_tab'              => [
375
+						'title'    => esc_html__('Event Tickets', 'event_espresso'),
376
+						'filename' => 'event_editor_event_tickets',
377
+					],
378
+					'event_editor_event_registration_options_help_tab' => [
379
+						'title'    => esc_html__('Event Registration Options', 'event_espresso'),
380
+						'filename' => 'event_editor_event_registration_options',
381
+					],
382
+					'event_editor_tags_categories_help_tab'            => [
383
+						'title'    => esc_html__('Event Tags & Categories', 'event_espresso'),
384
+						'filename' => 'event_editor_tags_categories',
385
+					],
386
+					'event_editor_questions_registrants_help_tab'      => [
387
+						'title'    => esc_html__('Questions for Registrants', 'event_espresso'),
388
+						'filename' => 'event_editor_questions_registrants',
389
+					],
390
+					'event_editor_save_new_event_help_tab'             => [
391
+						'title'    => esc_html__('Save New Event', 'event_espresso'),
392
+						'filename' => 'event_editor_save_new_event',
393
+					],
394
+					'event_editor_other_help_tab'                      => [
395
+						'title'    => esc_html__('Event Other', 'event_espresso'),
396
+						'filename' => 'event_editor_other',
397
+					],
398
+				],
399
+				'require_nonce' => false,
400
+			],
401
+			'default_event_settings' => [
402
+				'nav'           => [
403
+					'label' => esc_html__('Default Settings', 'event_espresso'),
404
+					'icon'  => 'dashicons-admin-generic',
405
+					'order' => 40,
406
+				],
407
+				'metaboxes'     => array_merge(['_publish_post_box'], $this->_default_espresso_metaboxes),
408
+				'labels'        => [
409
+					'publishbox' => esc_html__('Update Settings', 'event_espresso'),
410
+				],
411
+				'help_tabs'     => [
412
+					'default_settings_help_tab'        => [
413
+						'title'    => esc_html__('Default Event Settings', 'event_espresso'),
414
+						'filename' => 'events_default_settings',
415
+					],
416
+					'default_settings_status_help_tab' => [
417
+						'title'    => esc_html__('Default Registration Status', 'event_espresso'),
418
+						'filename' => 'events_default_settings_status',
419
+					],
420
+					'default_maximum_tickets_help_tab' => [
421
+						'title'    => esc_html__('Default Maximum Tickets Per Order', 'event_espresso'),
422
+						'filename' => 'events_default_settings_max_tickets',
423
+					],
424
+				],
425
+				'require_nonce' => false,
426
+			],
427
+			// template settings
428
+			'template_settings'      => [
429
+				'nav'           => [
430
+					'label' => esc_html__('Templates', 'event_espresso'),
431
+					'icon'  => 'dashicons-layout',
432
+					'order' => 30,
433
+				],
434
+				'metaboxes'     => $this->_default_espresso_metaboxes,
435
+				'help_tabs'     => [
436
+					'general_settings_templates_help_tab' => [
437
+						'title'    => esc_html__('Templates', 'event_espresso'),
438
+						'filename' => 'general_settings_templates',
439
+					],
440
+				],
441
+				'require_nonce' => false,
442
+			],
443
+			// event category stuff
444
+			'add_category'           => [
445
+				'nav'           => [
446
+					'label'      => esc_html__('Add Category', 'event_espresso'),
447
+					'icon'       => 'dashicons-plus-alt',
448
+					'order'      => 25,
449
+					'persistent' => false,
450
+				],
451
+				'help_tabs'     => [
452
+					'add_category_help_tab' => [
453
+						'title'    => esc_html__('Add New Event Category', 'event_espresso'),
454
+						'filename' => 'events_add_category',
455
+					],
456
+				],
457
+				'metaboxes'     => ['_publish_post_box'],
458
+				'require_nonce' => false,
459
+			],
460
+			'edit_category'          => [
461
+				'nav'           => [
462
+					'label'      => esc_html__('Edit Category', 'event_espresso'),
463
+					'icon'       => 'dashicons-edit',
464
+					'order'      => 25,
465
+					'persistent' => false,
466
+					'url'        => $EVT_CAT_ID
467
+						? add_query_arg(
468
+							['EVT_CAT_ID' => $EVT_CAT_ID],
469
+							$this->_current_page_view_url
470
+						)
471
+						: $this->_admin_base_url,
472
+				],
473
+				'help_tabs'     => [
474
+					'edit_category_help_tab' => [
475
+						'title'    => esc_html__('Edit Event Category', 'event_espresso'),
476
+						'filename' => 'events_edit_category',
477
+					],
478
+				],
479
+				'metaboxes'     => ['_publish_post_box'],
480
+				'require_nonce' => false,
481
+			],
482
+			'category_list'          => [
483
+				'nav'           => [
484
+					'label' => esc_html__('Categories', 'event_espresso'),
485
+					'icon'  => 'dashicons-networking',
486
+					'order' => 20,
487
+				],
488
+				'list_table'    => 'Event_Categories_Admin_List_Table',
489
+				'help_tabs'     => [
490
+					'events_categories_help_tab'                       => [
491
+						'title'    => esc_html__('Event Categories', 'event_espresso'),
492
+						'filename' => 'events_categories',
493
+					],
494
+					'events_categories_table_column_headings_help_tab' => [
495
+						'title'    => esc_html__('Event Categories Table Column Headings', 'event_espresso'),
496
+						'filename' => 'events_categories_table_column_headings',
497
+					],
498
+					'events_categories_view_help_tab'                  => [
499
+						'title'    => esc_html__('Event Categories Views', 'event_espresso'),
500
+						'filename' => 'events_categories_views',
501
+					],
502
+					'events_categories_other_help_tab'                 => [
503
+						'title'    => esc_html__('Event Categories Other', 'event_espresso'),
504
+						'filename' => 'events_categories_other',
505
+					],
506
+				],
507
+				'metaboxes'     => $this->_default_espresso_metaboxes,
508
+				'require_nonce' => false,
509
+			],
510
+			'preview_deletion'       => [
511
+				'nav'           => [
512
+					'label'      => esc_html__('Preview Deletion', 'event_espresso'),
513
+					'icon'       => 'dashicons-remove',
514
+					'order'      => 15,
515
+					'persistent' => false,
516
+					'url'        => '',
517
+				],
518
+				'require_nonce' => false,
519
+			],
520
+		];
521
+	}
522
+
523
+
524
+	/**
525
+	 * Used to register any global screen options if necessary for every route in this admin page group.
526
+	 */
527
+	protected function _add_screen_options()
528
+	{
529
+	}
530
+
531
+
532
+	/**
533
+	 * Implementing the screen options for the 'default' route.
534
+	 *
535
+	 * @throws InvalidArgumentException
536
+	 * @throws InvalidDataTypeException
537
+	 * @throws InvalidInterfaceException
538
+	 */
539
+	protected function _add_screen_options_default()
540
+	{
541
+		$this->_per_page_screen_option();
542
+	}
543
+
544
+
545
+	/**
546
+	 * Implementing screen options for the category list route.
547
+	 *
548
+	 * @throws InvalidArgumentException
549
+	 * @throws InvalidDataTypeException
550
+	 * @throws InvalidInterfaceException
551
+	 */
552
+	protected function _add_screen_options_category_list()
553
+	{
554
+		$page_title              = $this->_admin_page_title;
555
+		$this->_admin_page_title = esc_html__('Categories', 'event_espresso');
556
+		$this->_per_page_screen_option();
557
+		$this->_admin_page_title = $page_title;
558
+	}
559
+
560
+
561
+	/**
562
+	 * Used to register any global feature pointers for the admin page group.
563
+	 */
564
+	protected function _add_feature_pointers()
565
+	{
566
+	}
567
+
568
+
569
+	/**
570
+	 * Registers and enqueues any global scripts and styles for the entire admin page group.
571
+	 */
572
+	public function load_scripts_styles()
573
+	{
574
+		wp_enqueue_style(
575
+			'events-admin-css',
576
+			EVENTS_ASSETS_URL . 'events-admin-page.css',
577
+			[],
578
+			EVENT_ESPRESSO_VERSION
579
+		);
580
+		wp_enqueue_style(
581
+			'ee-cat-admin',
582
+			EVENTS_ASSETS_URL . 'ee-cat-admin.css',
583
+			['editor-buttons'],
584
+			EVENT_ESPRESSO_VERSION
585
+		);
586
+	}
587
+
588
+
589
+	/**
590
+	 * Enqueuing scripts and styles specific to this view
591
+	 */
592
+	public function load_scripts_styles_create_new()
593
+	{
594
+		$this->load_scripts_styles_edit();
595
+	}
596
+
597
+
598
+	/**
599
+	 * Enqueuing scripts and styles specific to this view
600
+	 */
601
+	public function load_scripts_styles_edit()
602
+	{
603
+		// styles
604
+		wp_enqueue_style('espresso-ui-theme');
605
+		wp_enqueue_style(
606
+			'event-editor-css',
607
+			EVENTS_ASSETS_URL . 'event-editor.css',
608
+			['ee-admin-css'],
609
+			EVENT_ESPRESSO_VERSION
610
+		);
611
+		// scripts
612
+		wp_enqueue_script(
613
+			'event_editor_js',
614
+			EVENTS_ASSETS_URL . 'event_editor.js',
615
+			[
616
+				EspressoLegacyAdminAssetManager::JS_HANDLE_EE_ADMIN,
617
+				JqueryAssetManager::JS_HANDLE_JQUERY_UI_SLIDER,
618
+				JqueryAssetManager::JS_HANDLE_JQUERY_UI_TIMEPICKER_ADDON
619
+			],
620
+			EVENT_ESPRESSO_VERSION,
621
+			true
622
+		);
623
+		if (! $this->admin_config->useAdvancedEditor()) {
624
+			wp_enqueue_script(
625
+				'event-datetime-metabox',
626
+				EVENTS_ASSETS_URL . 'event-datetime-metabox.js',
627
+				['event_editor_js', 'ee-datepicker'],
628
+				EVENT_ESPRESSO_VERSION
629
+			);
630
+		}
631
+	}
632
+
633
+
634
+	/**
635
+	 * Populating the _views property for the category list table view.
636
+	 */
637
+	protected function _set_list_table_views_category_list()
638
+	{
639
+		$this->_views = [
640
+			'all' => [
641
+				'slug'        => 'all',
642
+				'label'       => esc_html__('All', 'event_espresso'),
643
+				'count'       => 0,
644
+				'bulk_action' => [
645
+					'delete_categories' => esc_html__('Delete Permanently', 'event_espresso'),
646
+				],
647
+			],
648
+		];
649
+	}
650
+
651
+
652
+	/**
653
+	 * For adding anything that fires on the admin_init hook for any route within this admin page group.
654
+	 */
655
+	public function admin_init()
656
+	{
657
+		EE_Registry::$i18n_js_strings['image_confirm'] = wp_strip_all_tags(
658
+			esc_html__(
659
+				'Do you really want to delete this image? Please remember to update your event to complete the removal.',
660
+				'event_espresso'
661
+			)
662
+		);
663
+
664
+		EE_Registry::$i18n_js_strings['entity_locked'] = wp_strip_all_tags(
665
+			__(
666
+				'This item can not be deleted because it it as locked. It may be in use by the system or have been sold.',
667
+				'event_espresso'
668
+			)
669
+		);
670
+	}
671
+
672
+
673
+	/**
674
+	 * For adding anything that should be triggered on the admin_notices hook for any route within this admin page
675
+	 * group.
676
+	 */
677
+	public function admin_notices()
678
+	{
679
+	}
680
+
681
+
682
+	/**
683
+	 * For adding anything that should be triggered on the `admin_print_footer_scripts` hook for any route within
684
+	 * this admin page group.
685
+	 */
686
+	public function admin_footer_scripts()
687
+	{
688
+	}
689
+
690
+
691
+	/**
692
+	 * Call this function to verify if an event is public and has tickets for sale.  If it does, then we need to show a
693
+	 * warning (via EE_Error::add_error());
694
+	 *
695
+	 * @param EE_Event|null $event Event object
696
+	 * @param string        $req_type
697
+	 * @return void
698
+	 * @throws EE_Error
699
+	 * @throws ReflectionException
700
+	 */
701
+	public function verify_event_edit(?EE_Base_Class $event = null, string $req_type = '')
702
+	{
703
+		// don't need to do this when processing
704
+		if (! empty($req_type)) {
705
+			return;
706
+		}
707
+		// no event?
708
+		if (! $event instanceof EE_Event) {
709
+			$event = $this->_cpt_model_obj;
710
+		}
711
+		// STILL no event?
712
+		if (! $event instanceof EE_Event) {
713
+			return;
714
+		}
715
+		// don't need to keep calling this
716
+		remove_action(
717
+			'AHEE__EE_Admin_Page_CPT__set_model_object__after_set_object',
718
+			[$this, 'verify_event_edit']
719
+		);
720
+		$orig_status = $event->status();
721
+		// first check if event is active.
722
+		if (
723
+			$orig_status === EEM_Event::cancelled
724
+			|| $orig_status === EEM_Event::postponed
725
+			|| $event->is_expired()
726
+			|| $event->is_inactive()
727
+		) {
728
+			return;
729
+		}
730
+		// made it here so it IS active... next check that any of the tickets are sold.
731
+		if ($event->is_sold_out(true)) {
732
+			if ($orig_status !== EEM_Event::sold_out && $event->status() !== $orig_status) {
733
+				EE_Error::add_attention(
734
+					sprintf(
735
+						esc_html__(
736
+							'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.',
737
+							'event_espresso'
738
+						),
739
+						EEH_Template::pretty_status(EEM_Event::sold_out, false, 'sentence')
740
+					)
741
+				);
742
+			}
743
+			return;
744
+		}
745
+		if ($orig_status === EEM_Event::sold_out) {
746
+			EE_Error::add_attention(
747
+				sprintf(
748
+					esc_html__(
749
+						'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.',
750
+						'event_espresso'
751
+					),
752
+					EEH_Template::pretty_status($event->status(), false, 'sentence')
753
+				)
754
+			);
755
+		}
756
+		// now we need to determine if the event has any tickets on sale.  If not then we dont' show the error
757
+		if (! $event->tickets_on_sale()) {
758
+			return;
759
+		}
760
+		// made it here so show warning
761
+		$this->_edit_event_warning();
762
+	}
763
+
764
+
765
+	/**
766
+	 * This is the text used for when an event is being edited that is public and has tickets for sale.
767
+	 * When needed, hook this into a EE_Error::add_error() notice.
768
+	 *
769
+	 * @access protected
770
+	 * @return void
771
+	 */
772
+	protected function _edit_event_warning()
773
+	{
774
+		// we don't want to add warnings during these requests
775
+		if ($this->request->getRequestParam('action') === 'editpost') {
776
+			return;
777
+		}
778
+		EE_Error::add_attention(
779
+			sprintf(
780
+				esc_html__(
781
+					'Your event is open for registration. Making changes may disrupt any transactions in progress. %sLearn more%s',
782
+					'event_espresso'
783
+				),
784
+				'<a class="espresso-help-tab-lnk ee-help-tab-link">',
785
+				'</a>'
786
+			)
787
+		);
788
+	}
789
+
790
+
791
+	/**
792
+	 * When a user is creating a new event, notify them if they haven't set their timezone.
793
+	 * Otherwise, do the normal logic
794
+	 *
795
+	 * @return void
796
+	 * @throws EE_Error
797
+	 * @throws InvalidArgumentException
798
+	 * @throws InvalidDataTypeException
799
+	 * @throws InvalidInterfaceException
800
+	 * @throws ReflectionException
801
+	 */
802
+	protected function _create_new_cpt_item()
803
+	{
804
+		$has_timezone_string = get_option('timezone_string');
805
+		// only nag them about setting their timezone if it's their first event, and they haven't already done it
806
+		if (! $has_timezone_string && ! EEM_Event::instance()->exists([])) {
807
+			EE_Error::add_attention(
808
+				sprintf(
809
+					esc_html__(
810
+						'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',
811
+						'event_espresso'
812
+					),
813
+					'<br>',
814
+					'<select id="timezone_string" name="timezone_string" aria-describedby="timezone-description">'
815
+					. EEH_DTT_Helper::wp_timezone_choice('', EEH_DTT_Helper::get_user_locale())
816
+					. '</select>',
817
+					'<button class="button button--secondary timezone-submit">',
818
+					'</button><span class="spinner"></span>'
819
+				),
820
+				__FILE__,
821
+				__FUNCTION__,
822
+				__LINE__
823
+			);
824
+		}
825
+		parent::_create_new_cpt_item();
826
+	}
827
+
828
+
829
+	/**
830
+	 * Sets the _views property for the default route in this admin page group.
831
+	 */
832
+	protected function _set_list_table_views_default()
833
+	{
834
+		$this->_views = [
835
+			'all'   => [
836
+				'slug'        => 'all',
837
+				'label'       => esc_html__('View All Events', 'event_espresso'),
838
+				'count'       => 0,
839
+				'bulk_action' => [
840
+					'trash_events' => esc_html__('Move to Trash', 'event_espresso'),
841
+				],
842
+			],
843
+			'draft' => [
844
+				'slug'        => 'draft',
845
+				'label'       => esc_html__('Draft', 'event_espresso'),
846
+				'count'       => 0,
847
+				'bulk_action' => [
848
+					'trash_events' => esc_html__('Move to Trash', 'event_espresso'),
849
+				],
850
+			],
851
+		];
852
+		if ($this->capabilities->current_user_can('ee_delete_events', 'espresso_events_trash_events')) {
853
+			$this->_views['trash'] = [
854
+				'slug'        => 'trash',
855
+				'label'       => esc_html__('Trash', 'event_espresso'),
856
+				'count'       => 0,
857
+				'bulk_action' => [
858
+					'restore_events' => esc_html__('Restore From Trash', 'event_espresso'),
859
+					'delete_events'  => esc_html__('Delete Permanently', 'event_espresso'),
860
+				],
861
+			];
862
+		}
863
+	}
864
+
865
+
866
+	/**
867
+	 * Provides the legend item array for the default list table view.
868
+	 *
869
+	 * @return array
870
+	 * @throws EE_Error
871
+	 * @throws EE_Error
872
+	 */
873
+	protected function _event_legend_items(): array
874
+	{
875
+		$items    = [
876
+			'view_details'   => [
877
+				'class' => 'dashicons dashicons-visibility',
878
+				'desc'  => esc_html__('View Event', 'event_espresso'),
879
+			],
880
+			'edit_event'     => [
881
+				'class' => 'dashicons dashicons-calendar-alt',
882
+				'desc'  => esc_html__('Edit Event Details', 'event_espresso'),
883
+			],
884
+			'view_attendees' => [
885
+				'class' => 'dashicons dashicons-groups',
886
+				'desc'  => esc_html__('View Registrations for Event', 'event_espresso'),
887
+			],
888
+		];
889
+		$items    = apply_filters('FHEE__Events_Admin_Page___event_legend_items__items', $items);
890
+		$statuses = [
891
+			'sold_out_status'  => [
892
+				'class' => 'ee-status-legend ee-status-bg--' . EE_Datetime::sold_out,
893
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::sold_out, false, 'sentence'),
894
+			],
895
+			'active_status'    => [
896
+				'class' => 'ee-status-legend ee-status-bg--' . EE_Datetime::active,
897
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::active, false, 'sentence'),
898
+			],
899
+			'upcoming_status'  => [
900
+				'class' => 'ee-status-legend ee-status-bg--' . EE_Datetime::upcoming,
901
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::upcoming, false, 'sentence'),
902
+			],
903
+			'postponed_status' => [
904
+				'class' => 'ee-status-legend ee-status-bg--' . EE_Datetime::postponed,
905
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::postponed, false, 'sentence'),
906
+			],
907
+			'cancelled_status' => [
908
+				'class' => 'ee-status-legend ee-status-bg--' . EE_Datetime::cancelled,
909
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::cancelled, false, 'sentence'),
910
+			],
911
+			'expired_status'   => [
912
+				'class' => 'ee-status-legend ee-status-bg--' . EE_Datetime::expired,
913
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::expired, false, 'sentence'),
914
+			],
915
+			'inactive_status'  => [
916
+				'class' => 'ee-status-legend ee-status-bg--' . EE_Datetime::inactive,
917
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::inactive, false, 'sentence'),
918
+			],
919
+		];
920
+		$statuses = apply_filters('FHEE__Events_Admin_Page__event_legend_items__statuses', $statuses);
921
+		return array_merge($items, $statuses);
922
+	}
923
+
924
+
925
+	/**
926
+	 * @return EEM_Event
927
+	 * @throws EE_Error
928
+	 * @throws InvalidArgumentException
929
+	 * @throws InvalidDataTypeException
930
+	 * @throws InvalidInterfaceException
931
+	 * @throws ReflectionException
932
+	 */
933
+	private function _event_model(): EEM_Event
934
+	{
935
+		if (! $this->_event_model instanceof EEM_Event) {
936
+			$this->_event_model = EE_Registry::instance()->load_model('Event');
937
+		}
938
+		return $this->_event_model;
939
+	}
940
+
941
+
942
+	/**
943
+	 * Adds extra buttons to the WP CPT permalink field row.
944
+	 * Method is called from parent and is hooked into the wp 'get_sample_permalink_html' filter.
945
+	 *
946
+	 * @param string      $return    the current html
947
+	 * @param int         $id        the post id for the page
948
+	 * @param string|null $new_title What the title is
949
+	 * @param string|null $new_slug  what the slug is
950
+	 * @return string            The new html string for the permalink area
951
+	 * @deprecated 5.0.0.p
952
+	 * @see        TicketSelectorShortcodeButton::addButton
953
+	 */
954
+	public function extra_permalink_field_buttons(
955
+		string $return,
956
+		int $id,
957
+		?string $new_title,
958
+		?string $new_slug
959
+	): string {
960
+		return TicketSelectorShortcodeButton::addButton($return, $id, $new_title, $new_slug);
961
+	}
962
+
963
+
964
+	/**
965
+	 * _events_overview_list_table
966
+	 * This contains the logic for showing the events_overview list
967
+	 *
968
+	 * @access protected
969
+	 * @return void
970
+	 * @throws DomainException
971
+	 * @throws EE_Error
972
+	 * @throws InvalidArgumentException
973
+	 * @throws InvalidDataTypeException
974
+	 * @throws InvalidInterfaceException
975
+	 */
976
+	protected function _events_overview_list_table()
977
+	{
978
+		$after_list_table = [];
979
+		$links_html       = EEH_HTML::div('', '', 'ee-admin-section ee-layout-stack');
980
+		$links_html       .= EEH_HTML::h3(esc_html__('Links', 'event_espresso'));
981
+		$links_html       .= EEH_HTML::div(
982
+			EEH_Template::get_button_or_link(
983
+				get_post_type_archive_link(EspressoPostType::EVENTS),
984
+				esc_html__('View Event Archive Page', 'event_espresso'),
985
+				'button button--small button--secondary'
986
+			),
987
+			'',
988
+			'ee-admin-button-row ee-admin-button-row--align-start'
989
+		);
990
+		$links_html       .= EEH_HTML::divx();
991
+
992
+		$after_list_table['view_event_list_button'] = $links_html;
993
+
994
+		$after_list_table['legend'] = $this->_display_legend($this->_event_legend_items());
995
+		$this->_admin_page_title    .= ' ' . $this->get_action_link_or_button(
996
+			'create_new',
997
+			'add',
998
+			[],
999
+			'add-new-h2'
1000
+		);
1001
+
1002
+		$this->_template_args['after_list_table'] = array_merge(
1003
+			(array) $this->_template_args['after_list_table'],
1004
+			$after_list_table
1005
+		);
1006
+		$this->display_admin_list_table_page_with_no_sidebar();
1007
+	}
1008
+
1009
+
1010
+	/**
1011
+	 * this allows for extra misc actions in the default WP publish box
1012
+	 *
1013
+	 * @return void
1014
+	 * @throws DomainException
1015
+	 * @throws EE_Error
1016
+	 * @throws InvalidArgumentException
1017
+	 * @throws InvalidDataTypeException
1018
+	 * @throws InvalidInterfaceException
1019
+	 * @throws ReflectionException
1020
+	 */
1021
+	public function extra_misc_actions_publish_box()
1022
+	{
1023
+		$this->_generate_publish_box_extra_content();
1024
+	}
1025
+
1026
+
1027
+	/**
1028
+	 * This is hooked into the WordPress do_action('save_post') hook and runs after the custom post type has been
1029
+	 * saved.
1030
+	 * Typically you would use this to save any additional data.
1031
+	 * Keep in mind also that "save_post" runs on EVERY post update to the database.
1032
+	 * ALSO very important.  When a post transitions from scheduled to published,
1033
+	 * the save_post action is fired but you will NOT have any _POST data containing any extra info you may have from
1034
+	 * other meta saves. So MAKE sure that you handle this accordingly.
1035
+	 *
1036
+	 * @access protected
1037
+	 * @abstract
1038
+	 * @param string  $post_id The ID of the cpt that was saved (so you can link relationally)
1039
+	 * @param WP_Post $post    The post object of the cpt that was saved.
1040
+	 * @return void
1041
+	 * @throws EE_Error
1042
+	 * @throws InvalidArgumentException
1043
+	 * @throws InvalidDataTypeException
1044
+	 * @throws InvalidInterfaceException
1045
+	 * @throws ReflectionException
1046
+	 */
1047
+	protected function _insert_update_cpt_item($post_id, $post)
1048
+	{
1049
+		if ($post instanceof WP_Post && $post->post_type !== EspressoPostType::EVENTS) {
1050
+			// get out we're not processing an event save.
1051
+			return;
1052
+		}
1053
+		$event_values = [
1054
+			'EVT_member_only'     => $this->request->getRequestParam('member_only', false, DataType::BOOL),
1055
+			'EVT_allow_overflow'  => $this->request->getRequestParam('EVT_allow_overflow', false, DataType::BOOL),
1056
+			'EVT_timezone_string' => $this->request->getRequestParam('timezone_string'),
1057
+		];
1058
+		// check if the new EDTR reg options meta box is being used, and if so, don't run updates for legacy version
1059
+		if (! $this->admin_config->useAdvancedEditor() || ! $this->feature->allowed('use_reg_options_meta_box')) {
1060
+			$event_values['EVT_display_ticket_selector']     = $this->request->getRequestParam(
1061
+				'display_ticket_selector',
1062
+				false,
1063
+				'bool'
1064
+			);
1065
+			$event_values['EVT_additional_limit']            = min(
1066
+				apply_filters('FHEE__EE_Events_Admin__insert_update_cpt_item__EVT_additional_limit_max', 255),
1067
+				$this->request->getRequestParam(
1068
+					'additional_limit',
1069
+					EEM_Event::get_default_additional_limit(),
1070
+					'int'
1071
+				)
1072
+			);
1073
+			$event_values['EVT_default_registration_status'] = $this->request->getRequestParam(
1074
+				'EVT_default_registration_status',
1075
+				EE_Registry::instance()->CFG->registration->default_STS_ID
1076
+			);
1077
+
1078
+			$event_values['EVT_external_URL'] = $this->request->getRequestParam('externalURL');
1079
+			$event_values['EVT_phone']        = $this->request->getRequestParam('event_phone');
1080
+			$event_values['EVT_display_desc'] = $this->request->getRequestParam('display_desc', false, DataType::BOOL);
1081
+		} elseif ($post instanceof WP_Post) {
1082
+			$event_values['EVT_name'] = $post->post_title;
1083
+			$event_values['EVT_desc'] = $post->post_content;
1084
+		}
1085
+		// update event
1086
+		$success = $this->_event_model()->update_by_ID($event_values, $post_id);
1087
+		// get event_object for other metaboxes...
1088
+		// though it would seem to make sense to just use $this->_event_model()->get_one_by_ID( $post_id )..
1089
+		// i have to set up where conditions to override the filters in the model
1090
+		// that filter out auto-draft and inherit statuses so we GET the inherit id!
1091
+		/** @var EE_Event $event */
1092
+		$event = $this->_event_model()->get_one(
1093
+			[
1094
+				[
1095
+					$this->_event_model()->primary_key_name() => $post_id,
1096
+					'OR'                                      => [
1097
+						'status'   => $post->post_status,
1098
+						// if trying to "Publish" a sold out event, it's status will get switched back to "sold_out" in the db,
1099
+						// but the returned object here has a status of "publish", so use the original post status as well
1100
+						'status*1' => $this->request->getRequestParam('original_post_status'),
1101
+					],
1102
+					'status' => ['NOT IN', ['auto-draft']],
1103
+				],
1104
+			]
1105
+		);
1106
+
1107
+		if (! $event instanceof EE_Event) {
1108
+			return;
1109
+		}
1110
+
1111
+		// the following are default callbacks for event attachment updates
1112
+		// that can be overridden by caffeinated functionality and/or addons.
1113
+		$event_update_callbacks = [];
1114
+		if (! $this->admin_config->useAdvancedEditor()) {
1115
+			$event_update_callbacks['_default_venue_update']   = [$this, '_default_venue_update'];
1116
+			$event_update_callbacks['_default_tickets_update'] = [$this, '_default_tickets_update'];
1117
+		}
1118
+		$event_update_callbacks = apply_filters(
1119
+			'FHEE__Events_Admin_Page___insert_update_cpt_item__event_update_callbacks',
1120
+			$event_update_callbacks
1121
+		);
1122
+
1123
+		$att_success = true;
1124
+		foreach ($event_update_callbacks as $e_callback) {
1125
+			$_success = is_callable($e_callback)
1126
+				? $e_callback($event, $this->request->requestParams())
1127
+				: false;
1128
+			// if ANY of these updates fail then we want the appropriate global error message
1129
+			$att_success = $_success !== false ? $att_success : false;
1130
+		}
1131
+		// any errors?
1132
+		if ($success && $att_success === false) {
1133
+			EE_Error::add_error(
1134
+				esc_html__(
1135
+					'Event Details saved successfully but something went wrong with saving attachments.',
1136
+					'event_espresso'
1137
+				),
1138
+				__FILE__,
1139
+				__FUNCTION__,
1140
+				__LINE__
1141
+			);
1142
+		} elseif ($success === false) {
1143
+			EE_Error::add_error(
1144
+				esc_html__('Event Details did not save successfully.', 'event_espresso'),
1145
+				__FILE__,
1146
+				__FUNCTION__,
1147
+				__LINE__
1148
+			);
1149
+		}
1150
+	}
1151
+
1152
+
1153
+	/**
1154
+	 * @param int $post_id
1155
+	 * @param int $revision_id
1156
+	 * @throws EE_Error
1157
+	 * @throws EE_Error
1158
+	 * @throws ReflectionException
1159
+	 * @see parent::restore_item()
1160
+	 */
1161
+	protected function _restore_cpt_item(int $post_id, int $revision_id)
1162
+	{
1163
+		// copy existing event meta to new post
1164
+		$post_evt = $this->_event_model()->get_one_by_ID($post_id);
1165
+		if ($post_evt instanceof EE_Event) {
1166
+			// meta revision restore
1167
+			$post_evt->restore_revision($revision_id);
1168
+			// related objs restore
1169
+			$post_evt->restore_revision($revision_id, ['Venue', 'Datetime', 'Price']);
1170
+		}
1171
+	}
1172
+
1173
+
1174
+	/**
1175
+	 * Attach the venue to the Event
1176
+	 *
1177
+	 * @param EE_Event $event Event Object to add the venue to
1178
+	 * @param array    $data  The request data from the form
1179
+	 * @return bool           Success or fail.
1180
+	 * @throws EE_Error
1181
+	 * @throws ReflectionException
1182
+	 */
1183
+	protected function _default_venue_update(EE_Event $event, array $data): bool
1184
+	{
1185
+		require_once(EE_MODELS . 'EEM_Venue.model.php');
1186
+		$venue_model = EE_Registry::instance()->load_model('Venue');
1187
+		$venue_id    = ! empty($data['venue_id']) ? $data['venue_id'] : null;
1188
+		// very important.  If we don't have a venue name...
1189
+		// then we'll get out because not necessary to create empty venue
1190
+		if (empty($data['venue_title'])) {
1191
+			return false;
1192
+		}
1193
+		$venue_array = [
1194
+			'VNU_wp_user'         => $event->get('EVT_wp_user'),
1195
+			'VNU_name'            => $data['venue_title'],
1196
+			'VNU_desc'            => ! empty($data['venue_description']) ? $data['venue_description'] : null,
1197
+			'VNU_identifier'      => ! empty($data['venue_identifier']) ? $data['venue_identifier'] : null,
1198
+			'VNU_short_desc'      => ! empty($data['venue_short_description'])
1199
+				? $data['venue_short_description']
1200
+				: null,
1201
+			'VNU_address'         => ! empty($data['address']) ? $data['address'] : null,
1202
+			'VNU_address2'        => ! empty($data['address2']) ? $data['address2'] : null,
1203
+			'VNU_city'            => ! empty($data['city']) ? $data['city'] : null,
1204
+			'STA_ID'              => ! empty($data['state']) ? $data['state'] : null,
1205
+			'CNT_ISO'             => ! empty($data['countries']) ? $data['countries'] : null,
1206
+			'VNU_zip'             => ! empty($data['zip']) ? $data['zip'] : null,
1207
+			'VNU_phone'           => ! empty($data['venue_phone']) ? $data['venue_phone'] : null,
1208
+			'VNU_capacity'        => ! empty($data['venue_capacity']) ? $data['venue_capacity'] : null,
1209
+			'VNU_url'             => ! empty($data['venue_url']) ? $data['venue_url'] : null,
1210
+			'VNU_virtual_phone'   => ! empty($data['virtual_phone']) ? $data['virtual_phone'] : null,
1211
+			'VNU_virtual_url'     => ! empty($data['virtual_url']) ? $data['virtual_url'] : null,
1212
+			'VNU_enable_for_gmap' => isset($data['enable_for_gmap']) ? 1 : 0,
1213
+			'status'              => 'publish',
1214
+		];
1215
+		// if we've got the venue_id then we're just updating the existing venue so let's do that and then get out.
1216
+		if (! empty($venue_id)) {
1217
+			$update_where  = [$venue_model->primary_key_name() => $venue_id];
1218
+			$rows_affected = $venue_model->update($venue_array, [$update_where]);
1219
+			// we've gotta make sure that the venue is always attached to a revision..
1220
+			// add_relation_to should take care of making sure that the relation is already present.
1221
+			$event->_add_relation_to($venue_id, 'Venue');
1222
+			return $rows_affected > 0;
1223
+		}
1224
+		// we insert the venue
1225
+		$venue_id = $venue_model->insert($venue_array);
1226
+		$event->_add_relation_to($venue_id, 'Venue');
1227
+		return ! empty($venue_id);
1228
+		// when we have the ancestor come in it's already been handled by the revision save.
1229
+	}
1230
+
1231
+
1232
+	/**
1233
+	 * Handles saving everything related to Tickets (datetimes, tickets, prices)
1234
+	 *
1235
+	 * @param EE_Event $event The Event object we're attaching data to
1236
+	 * @param array    $data  The request data from the form
1237
+	 * @return array
1238
+	 * @throws EE_Error
1239
+	 * @throws ReflectionException
1240
+	 * @throws Exception
1241
+	 */
1242
+	protected function _default_tickets_update(EE_Event $event, array $data): array
1243
+	{
1244
+		if ($this->admin_config->useAdvancedEditor()) {
1245
+			return [];
1246
+		}
1247
+		$datetime       = null;
1248
+		$saved_tickets  = [];
1249
+		$event_timezone = $event->get_timezone();
1250
+		$date_formats   = ['Y-m-d', 'h:i a'];
1251
+		foreach ($data['edit_event_datetimes'] as $row => $datetime_data) {
1252
+			// trim all values to ensure any excess whitespace is removed.
1253
+			$datetime_data                = array_map('trim', $datetime_data);
1254
+			$datetime_data['DTT_EVT_end'] = ! empty($datetime_data['DTT_EVT_end'])
1255
+					? $datetime_data['DTT_EVT_end']
1256
+					: $datetime_data['DTT_EVT_start'];
1257
+			$datetime_values              = [
1258
+				'DTT_ID'        => ! empty($datetime_data['DTT_ID']) ? $datetime_data['DTT_ID'] : null,
1259
+				'DTT_EVT_start' => $datetime_data['DTT_EVT_start'],
1260
+				'DTT_EVT_end'   => $datetime_data['DTT_EVT_end'],
1261
+				'DTT_reg_limit' => empty($datetime_data['DTT_reg_limit']) ? EE_INF : $datetime_data['DTT_reg_limit'],
1262
+				'DTT_order'     => $row,
1263
+			];
1264
+			// if we have an id then let's get existing object first and then set the new values.
1265
+			//  Otherwise we instantiate a new object for save.
1266
+			if (! empty($datetime_data['DTT_ID'])) {
1267
+				$datetime = EEM_Datetime::instance($event_timezone)->get_one_by_ID($datetime_data['DTT_ID']);
1268
+				if (! $datetime instanceof EE_Datetime) {
1269
+					throw new RuntimeException(
1270
+						sprintf(
1271
+							esc_html__(
1272
+								'Something went wrong! A valid Datetime could not be retrieved from the database using the supplied ID: %1$d',
1273
+								'event_espresso'
1274
+							),
1275
+							$datetime_data['DTT_ID']
1276
+						)
1277
+					);
1278
+				}
1279
+				$datetime->set_date_format($date_formats[0]);
1280
+				$datetime->set_time_format($date_formats[1]);
1281
+				foreach ($datetime_values as $field => $value) {
1282
+					$datetime->set($field, $value);
1283
+				}
1284
+			} else {
1285
+				$datetime = EE_Datetime::new_instance($datetime_values, $event_timezone, $date_formats);
1286
+			}
1287
+			if (! $datetime instanceof EE_Datetime) {
1288
+				throw new RuntimeException(
1289
+					sprintf(
1290
+						esc_html__(
1291
+							'Something went wrong! A valid Datetime could not be generated or retrieved using the supplied data: %1$s',
1292
+							'event_espresso'
1293
+						),
1294
+						print_r($datetime_values, true)
1295
+					)
1296
+				);
1297
+			}
1298
+			// before going any further make sure our dates are setup correctly
1299
+			// so that the end date is always equal or greater than the start date.
1300
+			if ($datetime->get_raw('DTT_EVT_start') > $datetime->get_raw('DTT_EVT_end')) {
1301
+				$datetime->set('DTT_EVT_end', $datetime->get('DTT_EVT_start'));
1302
+				$datetime = EEH_DTT_Helper::date_time_add($datetime, 'DTT_EVT_end', 'days');
1303
+			}
1304
+			$datetime->save();
1305
+			$event->_add_relation_to($datetime, 'Datetime');
1306
+		}
1307
+		// no datetimes get deleted so we don't do any of that logic here.
1308
+		// update tickets next
1309
+		$old_tickets = isset($data['ticket_IDs']) ? explode(',', $data['ticket_IDs']) : [];
1310
+
1311
+		// set up some default start and end dates in case those are not present in the incoming data
1312
+		$default_start_date = new DateTime('now', new DateTimeZone($event->get_timezone()));
1313
+		$default_start_date = $default_start_date->format($date_formats[0] . ' ' . $date_formats[1]);
1314
+		// use the start date of the first datetime for the end date
1315
+		$first_datetime   = $event->first_datetime();
1316
+		$default_end_date = $first_datetime->start_date_and_time($date_formats[0], $date_formats[1]);
1317
+
1318
+		// now process the incoming data
1319
+		foreach ($data['edit_tickets'] as $row => $ticket_data) {
1320
+			$update_prices = false;
1321
+			$ticket_price  = $data['edit_prices'][ $row ][1]['PRC_amount'] ?? 0;
1322
+			// trim inputs to ensure any excess whitespace is removed.
1323
+			$ticket_data   = array_map('trim', $ticket_data);
1324
+			$ticket_values = [
1325
+				'TKT_ID'          => ! empty($ticket_data['TKT_ID']) ? $ticket_data['TKT_ID'] : null,
1326
+				'TTM_ID'          => ! empty($ticket_data['TTM_ID']) ? $ticket_data['TTM_ID'] : 0,
1327
+				'TKT_name'        => ! empty($ticket_data['TKT_name']) ? $ticket_data['TKT_name'] : '',
1328
+				'TKT_description' => ! empty($ticket_data['TKT_description']) ? $ticket_data['TKT_description'] : '',
1329
+				'TKT_start_date'  => ! empty($ticket_data['TKT_start_date'])
1330
+					? $ticket_data['TKT_start_date']
1331
+					: $default_start_date,
1332
+				'TKT_end_date'    => ! empty($ticket_data['TKT_end_date'])
1333
+					? $ticket_data['TKT_end_date']
1334
+					: $default_end_date,
1335
+				'TKT_qty'         => ! empty($ticket_data['TKT_qty'])
1336
+									 || (isset($ticket_data['TKT_qty']) && (int) $ticket_data['TKT_qty'] === 0)
1337
+					? $ticket_data['TKT_qty']
1338
+					: EE_INF,
1339
+				'TKT_uses'        => ! empty($ticket_data['TKT_uses'])
1340
+									 || (isset($ticket_data['TKT_uses']) && (int) $ticket_data['TKT_uses'] === 0)
1341
+					? $ticket_data['TKT_uses']
1342
+					: EE_INF,
1343
+				'TKT_min'         => ! empty($ticket_data['TKT_min']) ? $ticket_data['TKT_min'] : 0,
1344
+				'TKT_max'         => ! empty($ticket_data['TKT_max']) ? $ticket_data['TKT_max'] : EE_INF,
1345
+				'TKT_order'       => $ticket_data['TKT_order'] ?? $row,
1346
+				'TKT_price'       => (float) $ticket_price,
1347
+				'TKT_row'         => $row,
1348
+			];
1349
+			// if this is a default ticket, then we need to set the TKT_ID to 0 and update accordingly,
1350
+			// which means in turn that the prices will become new prices as well.
1351
+			if (isset($ticket_data['TKT_is_default']) && $ticket_data['TKT_is_default']) {
1352
+				$ticket_values['TKT_ID']         = 0;
1353
+				$ticket_values['TKT_is_default'] = 0;
1354
+				$update_prices                   = true;
1355
+			}
1356
+			// if we have a TKT_ID then we need to get that existing TKT_obj and update it
1357
+			// we actually do our saves ahead of adding any relations because its entirely possible that this
1358
+			// ticket didn't get removed or added to any datetime in the session but DID have it's items modified.
1359
+			// keep in mind that if the ticket has been sold (and we have changed pricing information),
1360
+			// then we won't be updating the tkt but instead a new tkt will be created and the old one archived.
1361
+			if (! empty($ticket_data['TKT_ID'])) {
1362
+				$existing_ticket = EEM_Ticket::instance($event_timezone)->get_one_by_ID($ticket_data['TKT_ID']);
1363
+				if (! $existing_ticket instanceof EE_Ticket) {
1364
+					throw new RuntimeException(
1365
+						sprintf(
1366
+							esc_html__(
1367
+								'Something went wrong! A valid Ticket could not be retrieved from the database using the supplied ID: %1$d',
1368
+								'event_espresso'
1369
+							),
1370
+							$ticket_data['TKT_ID']
1371
+						)
1372
+					);
1373
+				}
1374
+				$ticket_sold = $existing_ticket->count_related(
1375
+					'Registration',
1376
+					[
1377
+							[
1378
+								'STS_ID' => [
1379
+									'NOT IN',
1380
+									[RegStatus::INCOMPLETE],
1381
+								],
1382
+							],
1383
+						]
1384
+				) > 0;
1385
+				// let's just check the total price for the existing ticket and determine if it matches the new total price.
1386
+				// if they are different then we create a new ticket (if $ticket_sold)
1387
+				// if they aren't different then we go ahead and modify existing ticket.
1388
+				$create_new_ticket = $ticket_sold
1389
+									 && EEH_Money::compare_floats($ticket_price, $existing_ticket->price(), '!=')
1390
+									 && ! $existing_ticket->deleted();
1391
+				$existing_ticket->set_date_format($date_formats[0]);
1392
+				$existing_ticket->set_time_format($date_formats[1]);
1393
+				// set new values
1394
+				foreach ($ticket_values as $field => $value) {
1395
+					if ($field == 'TKT_qty') {
1396
+						$existing_ticket->set_qty($value);
1397
+					} elseif ($field == 'TKT_price') {
1398
+						$existing_ticket->set('TKT_price', $ticket_price);
1399
+					} else {
1400
+						$existing_ticket->set($field, $value);
1401
+					}
1402
+				}
1403
+				$ticket = $existing_ticket;
1404
+				// if $create_new_ticket is false then we can safely update the existing ticket.
1405
+				//  Otherwise we have to create a new ticket.
1406
+				if ($create_new_ticket) {
1407
+					// archive the old ticket first
1408
+					$existing_ticket->set('TKT_deleted', 1);
1409
+					$existing_ticket->save();
1410
+					// make sure this ticket is still recorded in our $saved_tickets
1411
+					// so we don't run it through the regular trash routine.
1412
+					$saved_tickets[ $existing_ticket->ID() ] = $existing_ticket;
1413
+					// create new ticket that's a copy of the existing except,
1414
+					// (a new id of course and not archived) AND has the new TKT_price associated with it.
1415
+					$new_ticket = clone $existing_ticket;
1416
+					$new_ticket->set('TKT_ID', 0);
1417
+					$new_ticket->set('TKT_deleted', 0);
1418
+					$new_ticket->set('TKT_sold', 0);
1419
+					// now we need to make sure that $new prices are created as well and attached to new ticket.
1420
+					$update_prices = true;
1421
+					$ticket        = $new_ticket;
1422
+				}
1423
+			} else {
1424
+				// no TKT_id so a new ticket
1425
+				$ticket_values['TKT_price'] = $ticket_price;
1426
+				$ticket                     = EE_Ticket::new_instance($ticket_values, $event_timezone, $date_formats);
1427
+				$update_prices              = true;
1428
+			}
1429
+			if (! $ticket instanceof EE_Ticket) {
1430
+				throw new RuntimeException(
1431
+					sprintf(
1432
+						esc_html__(
1433
+							'Something went wrong! A valid Ticket could not be generated or retrieved using the supplied data: %1$s',
1434
+							'event_espresso'
1435
+						),
1436
+						print_r($ticket_values, true)
1437
+					)
1438
+				);
1439
+			}
1440
+			// cap ticket qty by datetime reg limits
1441
+			$ticket->set_qty(min($ticket->qty(), $ticket->qty('reg_limit')));
1442
+			// update ticket.
1443
+			$ticket->save();
1444
+			// before going any further make sure our dates are setup correctly
1445
+			// so that the end date is always equal or greater than the start date.
1446
+			if ($ticket->get_raw('TKT_start_date') > $ticket->get_raw('TKT_end_date')) {
1447
+				$ticket->set('TKT_end_date', $ticket->get('TKT_start_date'));
1448
+				$ticket = EEH_DTT_Helper::date_time_add($ticket, 'TKT_end_date', 'days');
1449
+				$ticket->save();
1450
+			}
1451
+			// initially let's add the ticket to the datetime
1452
+			$datetime->_add_relation_to($ticket, 'Ticket');
1453
+			$saved_tickets[ $ticket->ID() ] = $ticket;
1454
+			// add prices to ticket
1455
+			$prices_data = isset($data['edit_prices'][ $row ]) && is_array($data['edit_prices'][ $row ])
1456
+				? $data['edit_prices'][ $row ]
1457
+				: [];
1458
+			$this->_add_prices_to_ticket($prices_data, $ticket, $update_prices);
1459
+		}
1460
+		// however now we need to handle permanently deleting tickets via the ui.
1461
+		// Keep in mind that the ui does not allow deleting/archiving tickets that have ticket sold.
1462
+		// However, it does allow for deleting tickets that have no tickets sold,
1463
+		// in which case we want to get rid of permanently because there is no need to save in db.
1464
+		$old_tickets     = isset($old_tickets[0]) && $old_tickets[0] === '' ? [] : $old_tickets;
1465
+		$tickets_removed = array_diff($old_tickets, array_keys($saved_tickets));
1466
+		foreach ($tickets_removed as $id) {
1467
+			$id = absint($id);
1468
+			// get the ticket for this id
1469
+			$ticket_to_remove = EEM_Ticket::instance()->get_one_by_ID($id);
1470
+			if (! $ticket_to_remove instanceof EE_Ticket) {
1471
+				continue;
1472
+			}
1473
+			// need to get all the related datetimes on this ticket and remove from every single one of them
1474
+			// (remember this process can ONLY kick off if there are NO tickets sold)
1475
+			$related_datetimes = $ticket_to_remove->get_many_related('Datetime');
1476
+			foreach ($related_datetimes as $related_datetime) {
1477
+				$ticket_to_remove->_remove_relation_to($related_datetime, 'Datetime');
1478
+			}
1479
+			// need to do the same for prices (except these prices can also be deleted because again,
1480
+			// tickets can only be trashed if they don't have any TKTs sold (otherwise they are just archived))
1481
+			$ticket_to_remove->delete_related_permanently('Price');
1482
+			// finally let's delete this ticket
1483
+			// (which should not be blocked at this point b/c we've removed all our relationships)
1484
+			$ticket_to_remove->delete_permanently();
1485
+		}
1486
+		return [$datetime, $saved_tickets];
1487
+	}
1488
+
1489
+
1490
+	/**
1491
+	 * This attaches a list of given prices to a ticket.
1492
+	 * Note we dont' have to worry about ever removing relationships (or archiving prices)
1493
+	 * because if there is a change in price information on a ticket, a new ticket is created anyways
1494
+	 * so the archived ticket will retain the old price info and prices are automatically "archived" via the ticket.
1495
+	 *
1496
+	 * @access  private
1497
+	 * @param array     $prices_data Array of prices from the form.
1498
+	 * @param EE_Ticket $ticket      EE_Ticket object that prices are being attached to.
1499
+	 * @param bool      $new_prices  Whether attach existing incoming prices or create new ones.
1500
+	 * @return  void
1501
+	 * @throws EE_Error
1502
+	 * @throws ReflectionException
1503
+	 */
1504
+	private function _add_prices_to_ticket(array $prices_data, EE_Ticket $ticket, bool $new_prices = false)
1505
+	{
1506
+		$timezone = $ticket->get_timezone();
1507
+		foreach ($prices_data as $row => $price_data) {
1508
+			$price_values = [
1509
+				'PRC_ID'         => ! empty($price_data['PRC_ID']) ? $price_data['PRC_ID'] : null,
1510
+				'PRT_ID'         => ! empty($price_data['PRT_ID']) ? $price_data['PRT_ID'] : null,
1511
+				'PRC_amount'     => ! empty($price_data['PRC_amount']) ? $price_data['PRC_amount'] : 0,
1512
+				'PRC_name'       => ! empty($price_data['PRC_name']) ? $price_data['PRC_name'] : '',
1513
+				'PRC_desc'       => ! empty($price_data['PRC_desc']) ? $price_data['PRC_desc'] : '',
1514
+				'PRC_is_default' => 0, // make sure prices are NOT set as default from this context
1515
+				'PRC_order'      => $row,
1516
+			];
1517
+			if ($new_prices || empty($price_values['PRC_ID'])) {
1518
+				$price_values['PRC_ID'] = 0;
1519
+				$price                  = EE_Price::new_instance($price_values, $timezone);
1520
+			} else {
1521
+				$price = EEM_Price::instance($timezone)->get_one_by_ID($price_data['PRC_ID']);
1522
+				// update this price with new values
1523
+				foreach ($price_values as $field => $new_price) {
1524
+					$price->set($field, $new_price);
1525
+				}
1526
+			}
1527
+			if (! $price instanceof EE_Price) {
1528
+				throw new RuntimeException(
1529
+					sprintf(
1530
+						esc_html__(
1531
+							'Something went wrong! A valid Price could not be generated or retrieved using the supplied data: %1$s',
1532
+							'event_espresso'
1533
+						),
1534
+						print_r($price_values, true)
1535
+					)
1536
+				);
1537
+			}
1538
+			$price->save();
1539
+			$ticket->_add_relation_to($price, 'Price');
1540
+		}
1541
+	}
1542
+
1543
+
1544
+	/**
1545
+	 * Add in our autosave ajax handlers
1546
+	 */
1547
+	protected function _ee_autosave_create_new()
1548
+	{
1549
+	}
1550
+
1551
+
1552
+	/**
1553
+	 * More autosave handlers.
1554
+	 */
1555
+	protected function _ee_autosave_edit()
1556
+	{
1557
+	}
1558
+
1559
+
1560
+	/**
1561
+	 * @throws EE_Error
1562
+	 * @throws ReflectionException
1563
+	 */
1564
+	private function _generate_publish_box_extra_content()
1565
+	{
1566
+		// load formatter helper
1567
+		// args for getting related registrations
1568
+		$approved_query_args        = [
1569
+			[
1570
+				'REG_deleted' => 0,
1571
+				'STS_ID'      => RegStatus::APPROVED,
1572
+			],
1573
+		];
1574
+		$not_approved_query_args    = [
1575
+			[
1576
+				'REG_deleted' => 0,
1577
+				'STS_ID'      => RegStatus::AWAITING_REVIEW,
1578
+			],
1579
+		];
1580
+		$pending_payment_query_args = [
1581
+			[
1582
+				'REG_deleted' => 0,
1583
+				'STS_ID'      => RegStatus::PENDING_PAYMENT,
1584
+			],
1585
+		];
1586
+		// publish box
1587
+		$publish_box_extra_args = [
1588
+			'view_approved_reg_url'        => add_query_arg(
1589
+				[
1590
+					'action'      => 'default',
1591
+					'event_id'    => $this->_cpt_model_obj->ID(),
1592
+					'_reg_status' => RegStatus::APPROVED,
1593
+					'use_filters' => true,
1594
+				],
1595
+				REG_ADMIN_URL
1596
+			),
1597
+			'view_not_approved_reg_url'    => add_query_arg(
1598
+				[
1599
+					'action'      => 'default',
1600
+					'event_id'    => $this->_cpt_model_obj->ID(),
1601
+					'_reg_status' => RegStatus::AWAITING_REVIEW,
1602
+					'use_filters' => true,
1603
+				],
1604
+				REG_ADMIN_URL
1605
+			),
1606
+			'view_pending_payment_reg_url' => add_query_arg(
1607
+				[
1608
+					'action'      => 'default',
1609
+					'event_id'    => $this->_cpt_model_obj->ID(),
1610
+					'_reg_status' => RegStatus::PENDING_PAYMENT,
1611
+					'use_filters' => true,
1612
+				],
1613
+				REG_ADMIN_URL
1614
+			),
1615
+			'approved_regs'                => $this->_cpt_model_obj->count_related(
1616
+				'Registration',
1617
+				$approved_query_args
1618
+			),
1619
+			'not_approved_regs'            => $this->_cpt_model_obj->count_related(
1620
+				'Registration',
1621
+				$not_approved_query_args
1622
+			),
1623
+			'pending_payment_regs'         => $this->_cpt_model_obj->count_related(
1624
+				'Registration',
1625
+				$pending_payment_query_args
1626
+			),
1627
+			'misc_pub_section_class'       => apply_filters(
1628
+				'FHEE_Events_Admin_Page___generate_publish_box_extra_content__misc_pub_section_class',
1629
+				'misc-pub-section'
1630
+			),
1631
+		];
1632
+		ob_start();
1633
+		do_action(
1634
+			'AHEE__Events_Admin_Page___generate_publish_box_extra_content__event_editor_overview_add',
1635
+			$this->_cpt_model_obj
1636
+		);
1637
+		$publish_box_extra_args['event_editor_overview_add'] = ob_get_clean();
1638
+		// load template
1639
+		EEH_Template::display_template(
1640
+			EVENTS_TEMPLATE_PATH . 'event_publish_box_extras.template.php',
1641
+			$publish_box_extra_args
1642
+		);
1643
+	}
1644
+
1645
+
1646
+	/**
1647
+	 * @return EE_Event
1648
+	 */
1649
+	public function get_event_object()
1650
+	{
1651
+		return $this->_cpt_model_obj;
1652
+	}
1653
+
1654
+
1655
+
1656
+
1657
+	/** METABOXES * */
1658
+	/**
1659
+	 * _register_event_editor_meta_boxes
1660
+	 * add all metaboxes related to the event_editor
1661
+	 *
1662
+	 * @return void
1663
+	 * @throws EE_Error
1664
+	 * @throws ReflectionException
1665
+	 */
1666
+	protected function _register_event_editor_meta_boxes()
1667
+	{
1668
+		$this->verify_cpt_object();
1669
+		$use_advanced_editor = $this->admin_config->useAdvancedEditor();
1670
+		// check if the new EDTR reg options meta box is being used, and if so, don't load the legacy version
1671
+		if (! $use_advanced_editor || ! $this->feature->allowed('use_reg_options_meta_box')) {
1672
+			$this->addMetaBox(
1673
+				'espresso_event_editor_event_options',
1674
+				esc_html__('Event Registration Options', 'event_espresso'),
1675
+				[$this, 'registration_options_meta_box'],
1676
+				$this->page_slug,
1677
+				'side'
1678
+			);
1679
+		}
1680
+		if (! $use_advanced_editor) {
1681
+			$this->addMetaBox(
1682
+				'espresso_event_editor_tickets',
1683
+				esc_html__('Event Datetime & Ticket', 'event_espresso'),
1684
+				[$this, 'ticket_metabox'],
1685
+				$this->page_slug,
1686
+				'normal',
1687
+				'high'
1688
+			);
1689
+		} elseif ($this->feature->allowed('use_reg_options_meta_box')) {
1690
+			add_action(
1691
+				'add_meta_boxes_espresso_events',
1692
+				function () {
1693
+					global $current_screen;
1694
+					remove_meta_box('authordiv', $current_screen, 'normal');
1695
+				},
1696
+				99
1697
+			);
1698
+		}
1699
+		// NOTE: if you're looking for other metaboxes in here,
1700
+		// where a metabox has a related management page in the admin
1701
+		// you will find it setup in the related management page's "_Hooks" file.
1702
+		// i.e. messages metabox is found in "espresso_events_Messages_Hooks.class.php".
1703
+	}
1704
+
1705
+
1706
+	/**
1707
+	 * @throws DomainException
1708
+	 * @throws EE_Error
1709
+	 * @throws ReflectionException
1710
+	 */
1711
+	public function ticket_metabox()
1712
+	{
1713
+		$existing_datetime_ids = $existing_ticket_ids = [];
1714
+		// defaults for template args
1715
+		$template_args = [
1716
+			'ticket_rows'       => '',
1717
+			'total_ticket_rows' => 1,
1718
+			'trash_icon'        => 'dashicons dashicons-lock',
1719
+			'disabled'          => '',
1720
+		];
1721
+		$event_id      = is_object($this->_cpt_model_obj) ? $this->_cpt_model_obj->ID() : null;
1722
+		/**
1723
+		 * 1. Start with retrieving Datetimes
1724
+		 * 2. Fore each datetime get related tickets
1725
+		 * 3. For each ticket get related prices
1726
+		 */
1727
+		/** @var EEM_Datetime $datetime_model */
1728
+		$datetime_model = EE_Registry::instance()->load_model('Datetime');
1729
+		/** @var EEM_Ticket $datetime_model */
1730
+		$ticket_model = EE_Registry::instance()->load_model('Ticket');
1731
+		$times        = $datetime_model->get_all_event_dates($event_id);
1732
+		/** @type EE_Datetime $first_datetime */
1733
+		$first_datetime = reset($times);
1734
+		// do we get related tickets?
1735
+		if (
1736
+			$first_datetime instanceof EE_Datetime
1737
+			&& $first_datetime->ID() !== 0
1738
+		) {
1739
+			$existing_datetime_ids[] = $first_datetime->get('DTT_ID');
1740
+			$template_args['time']   = $first_datetime;
1741
+			$related_tickets         = $first_datetime->tickets(
1742
+				[
1743
+					['OR' => ['TKT_deleted' => 1, 'TKT_deleted*' => 0]],
1744
+					'default_where_conditions' => 'none',
1745
+				]
1746
+			);
1747
+			if (! empty($related_tickets)) {
1748
+				$template_args['total_ticket_rows'] = count($related_tickets);
1749
+				$row                                = 0;
1750
+				foreach ($related_tickets as $ticket) {
1751
+					$existing_ticket_ids[]        = $ticket->get('TKT_ID');
1752
+					$template_args['ticket_rows'] .= $this->_get_ticket_row($ticket, false, $row);
1753
+					$row++;
1754
+				}
1755
+			} else {
1756
+				$template_args['total_ticket_rows'] = 1;
1757
+				/** @type EE_Ticket $ticket */
1758
+				$ticket                       = $ticket_model->create_default_object();
1759
+				$template_args['ticket_rows'] .= $this->_get_ticket_row($ticket);
1760
+			}
1761
+		} else {
1762
+			$template_args['time'] = $times[0];
1763
+			/** @type EE_Ticket[] $tickets */
1764
+			$tickets                      = $ticket_model->get_all_default_tickets();
1765
+			$template_args['ticket_rows'] .= $this->_get_ticket_row($tickets[1]);
1766
+			// NOTE: we're just sending the first default row
1767
+			// (decaf can't manage default tickets so this should be sufficient);
1768
+		}
1769
+		$template_args['event_datetime_help_link'] = $this->_get_help_tab_link(
1770
+			'event_editor_event_datetimes_help_tab'
1771
+		);
1772
+		$template_args['ticket_options_help_link'] = $this->_get_help_tab_link('ticket_options_info');
1773
+		$template_args['existing_datetime_ids']    = implode(',', $existing_datetime_ids);
1774
+		$template_args['existing_ticket_ids']      = implode(',', $existing_ticket_ids);
1775
+		$template_args['ticket_js_structure']      = $this->_get_ticket_row(
1776
+			$ticket_model->create_default_object(),
1777
+			true
1778
+		);
1779
+		$template                                  = apply_filters(
1780
+			'FHEE__Events_Admin_Page__ticket_metabox__template',
1781
+			EVENTS_TEMPLATE_PATH . 'event_tickets_metabox_main.template.php'
1782
+		);
1783
+		EEH_Template::display_template($template, $template_args);
1784
+	}
1785
+
1786
+
1787
+	/**
1788
+	 * Setup an individual ticket form for the decaf event editor page
1789
+	 *
1790
+	 * @access private
1791
+	 * @param EE_Ticket $ticket   the ticket object
1792
+	 * @param boolean   $skeleton whether we're generating a skeleton for js manipulation
1793
+	 * @param int       $row
1794
+	 * @return string generated html for the ticket row.
1795
+	 * @throws EE_Error
1796
+	 * @throws ReflectionException
1797
+	 */
1798
+	private function _get_ticket_row(EE_Ticket $ticket, bool $skeleton = false, int $row = 0): string
1799
+	{
1800
+		$template_args = [
1801
+			'tkt_status_class'    => ' tkt-status-' . $ticket->ticket_status(),
1802
+			'tkt_archive_class'   => $ticket->ticket_status() === EE_Ticket::archived && ! $skeleton
1803
+				? ' tkt-archived'
1804
+				: '',
1805
+			'ticketrow'           => $skeleton ? 'TICKETNUM' : $row,
1806
+			'TKT_ID'              => $ticket->get('TKT_ID'),
1807
+			'TKT_name'            => $ticket->get('TKT_name'),
1808
+			'TKT_start_date'      => $skeleton ? '' : $ticket->get_date('TKT_start_date', 'Y-m-d h:i a'),
1809
+			'TKT_end_date'        => $skeleton ? '' : $ticket->get_date('TKT_end_date', 'Y-m-d h:i a'),
1810
+			'TKT_is_default'      => $ticket->get('TKT_is_default'),
1811
+			'TKT_qty'             => $ticket->get_pretty('TKT_qty', 'input'),
1812
+			'edit_ticketrow_name' => $skeleton ? 'TICKETNAMEATTR' : 'edit_tickets',
1813
+			'TKT_sold'            => $skeleton ? 0 : $ticket->get('TKT_sold'),
1814
+			'trash_icon'          => ($skeleton || (! $ticket->get('TKT_deleted')))
1815
+									 && (! empty($ticket) && $ticket->get('TKT_sold') === 0)
1816
+				? 'dashicons dashicons-post-trash clickable'
1817
+				: 'dashicons dashicons-lock entity-locked',
1818
+			'disabled'            => $skeleton || (! empty($ticket) && ! $ticket->get('TKT_deleted')) ? ''
1819
+				: ' disabled=disabled',
1820
+		];
1821
+
1822
+		$price         = $ticket->ID() !== 0
1823
+			? $ticket->get_first_related('Price', ['default_where_conditions' => 'none'])
1824
+			: null;
1825
+		$price         = $price instanceof EE_Price
1826
+			? $price
1827
+			: EEM_Price::instance()->create_default_object();
1828
+		$price_args    = [
1829
+			'price_currency_symbol' => EE_Registry::instance()->CFG->currency->sign,
1830
+			'PRC_amount'            => $price->get('PRC_amount'),
1831
+			'PRT_ID'                => $price->get('PRT_ID'),
1832
+			'PRC_ID'                => $price->get('PRC_ID'),
1833
+			'PRC_is_default'        => $price->get('PRC_is_default'),
1834
+		];
1835
+		// make sure we have default start and end dates if skeleton
1836
+		// handle rows that should NOT be empty
1837
+		if (empty($template_args['TKT_start_date'])) {
1838
+			// if empty then the start date will be now.
1839
+			$template_args['TKT_start_date'] = date('Y-m-d h:i a', current_time('timestamp'));
1840
+		}
1841
+		if (empty($template_args['TKT_end_date'])) {
1842
+			// get the earliest datetime (if present);
1843
+			$earliest_datetime             = $this->_cpt_model_obj->ID() > 0
1844
+				? $this->_cpt_model_obj->get_first_related(
1845
+					'Datetime',
1846
+					['order_by' => ['DTT_EVT_start' => 'ASC']]
1847
+				)
1848
+				: null;
1849
+			$template_args['TKT_end_date'] = $earliest_datetime instanceof EE_Datetime
1850
+				? $earliest_datetime->get_datetime('DTT_EVT_start', 'Y-m-d', 'h:i a')
1851
+				: date('Y-m-d h:i a', mktime(0, 0, 0, date('m'), date('d') + 7, date('Y')));
1852
+		}
1853
+		$template_args = array_merge($template_args, $price_args);
1854
+		$template      = apply_filters(
1855
+			'FHEE__Events_Admin_Page__get_ticket_row__template',
1856
+			EVENTS_TEMPLATE_PATH . 'event_tickets_metabox_ticket_row.template.php',
1857
+			$ticket
1858
+		);
1859
+		return EEH_Template::display_template($template, $template_args, true);
1860
+	}
1861
+
1862
+
1863
+	/**
1864
+	 * @throws EE_Error
1865
+	 * @throws ReflectionException
1866
+	 */
1867
+	public function registration_options_meta_box()
1868
+	{
1869
+		$yes_no_values             = [
1870
+			['id' => true, 'text' => esc_html__('Yes', 'event_espresso')],
1871
+			['id' => false, 'text' => esc_html__('No', 'event_espresso')],
1872
+		];
1873
+		$default_reg_status_values = EEM_Registration::reg_status_array(
1874
+			[
1875
+				RegStatus::CANCELLED,
1876
+				RegStatus::DECLINED,
1877
+				RegStatus::INCOMPLETE,
1878
+			],
1879
+			true
1880
+		);
1881
+		// $template_args['is_active_select'] = EEH_Form_Fields::select_input('is_active', $yes_no_values, $this->_cpt_model_obj->is_active());
1882
+		$template_args['_event']                          = $this->_cpt_model_obj;
1883
+		$template_args['event']                           = $this->_cpt_model_obj;
1884
+		$template_args['active_status']                   = $this->_cpt_model_obj->pretty_active_status(false);
1885
+		$template_args['additional_limit']                = $this->_cpt_model_obj->additional_limit();
1886
+		$template_args['default_registration_status']     = EEH_Form_Fields::select_input(
1887
+			'default_reg_status',
1888
+			$default_reg_status_values,
1889
+			$this->_cpt_model_obj->default_registration_status(),
1890
+			'',
1891
+			'ee-input-width--reg',
1892
+			false
1893
+		);
1894
+		$template_args['display_description']             = EEH_Form_Fields::select_input(
1895
+			'display_desc',
1896
+			$yes_no_values,
1897
+			$this->_cpt_model_obj->display_description()
1898
+		);
1899
+		$template_args['display_ticket_selector']         = EEH_Form_Fields::select_input(
1900
+			'display_ticket_selector',
1901
+			$yes_no_values,
1902
+			$this->_cpt_model_obj->display_ticket_selector(),
1903
+			'',
1904
+			'ee-input-width--small',
1905
+			false
1906
+		);
1907
+		$template_args['additional_registration_options'] = apply_filters(
1908
+			'FHEE__Events_Admin_Page__registration_options_meta_box__additional_registration_options',
1909
+			'',
1910
+			$template_args,
1911
+			$yes_no_values,
1912
+			$default_reg_status_values
1913
+		);
1914
+		EEH_Template::display_template(
1915
+			EVENTS_TEMPLATE_PATH . 'event_registration_options.template.php',
1916
+			$template_args
1917
+		);
1918
+	}
1919
+
1920
+
1921
+	/**
1922
+	 * _get_events()
1923
+	 * This method simply returns all the events (for the given _view and paging)
1924
+	 *
1925
+	 * @access public
1926
+	 * @param int  $per_page     count of items per page (20 default);
1927
+	 * @param int  $current_page what is the current page being viewed.
1928
+	 * @param bool $count        if TRUE then we just return a count of ALL events matching the given _view.
1929
+	 *                           If FALSE then we return an array of event objects
1930
+	 *                           that match the given _view and paging parameters.
1931
+	 * @return array|int         an array of event objects or a count of them.
1932
+	 * @throws Exception
1933
+	 */
1934
+	public function get_events(int $per_page = 10, int $current_page = 1, bool $count = false)
1935
+	{
1936
+		$EEM_Event   = $this->_event_model();
1937
+		$offset      = ($current_page - 1) * $per_page;
1938
+		$limit       = $count ? null : $offset . ',' . $per_page;
1939
+		$orderby     = $this->request->getRequestParam('orderby', 'EVT_ID');
1940
+		$order       = $this->request->getRequestParam('order', 'DESC');
1941
+		$month_range = $this->request->getRequestParam('month_range');
1942
+		$where  = [];
1943
+		$status = $this->request->getRequestParam('status');
1944
+		$timezone_string = EEH_DTT_Helper::get_valid_timezone_string();
1945
+		// determine what post_status our condition will have for the query.
1946
+		switch ($status) {
1947
+			case 'month':
1948
+			case 'today':
1949
+			case null:
1950
+			case 'all':
1951
+				break;
1952
+			case 'draft':
1953
+				$where['status'] = ['IN', ['draft', 'auto-draft']];
1954
+				break;
1955
+			default:
1956
+				$where['status'] = $status;
1957
+		}
1958
+		// categories? The default for all categories is -1
1959
+		$category = $this->request->getRequestParam('EVT_CAT', -1, DataType::INT);
1960
+		if ($category !== -1) {
1961
+			$where['Term_Taxonomy.taxonomy'] = EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY;
1962
+			$where['Term_Taxonomy.term_id']  = $category;
1963
+		}
1964
+		// date where conditions
1965
+		$start_formats = EEM_Datetime::instance()->get_formats_for('DTT_EVT_start');
1966
+		if ($month_range) {
1967
+			$where['Datetime.DTT_EVT_start'] = $this->whereParamsForDatetimeMonthRange($month_range, $timezone_string);
1968
+		} elseif ($status === 'today') {
1969
+			$DateTime                        = new DateTime(
1970
+				'now',
1971
+				new DateTimeZone($timezone_string)
1972
+			);
1973
+			$start                           = $DateTime->setTime(0, 0)->format(implode(' ', $start_formats));
1974
+			$end                             = $DateTime->setTime(23, 59, 59)->format(implode(' ', $start_formats));
1975
+			$where['Datetime.DTT_EVT_start'] = ['BETWEEN', [$start, $end]];
1976
+		} elseif ($status === 'month') {
1977
+			$now                             = date('Y-m-01');
1978
+			$DateTime                        = new DateTime(
1979
+				$now,
1980
+				new DateTimeZone($timezone_string)
1981
+			);
1982
+			$start                           = $DateTime->setTime(0, 0)->format(implode(' ', $start_formats));
1983
+			$end                             = $DateTime->setDate(date('Y'), date('m'), $DateTime->format('t'))
1984
+														->setTime(23, 59, 59)
1985
+														->format(implode(' ', $start_formats));
1986
+			$where['Datetime.DTT_EVT_start'] = ['BETWEEN', [$start, $end]];
1987
+		}
1988
+		if (! $this->capabilities->current_user_can('ee_read_others_events', 'get_events')) {
1989
+			$where['EVT_wp_user'] = get_current_user_id();
1990
+		} else {
1991
+			if (! isset($where['status'])) {
1992
+				if (! $this->capabilities->current_user_can('ee_read_private_events', 'get_events')) {
1993
+					$where['OR'] = [
1994
+						'status*restrict_private' => ['!=', 'private'],
1995
+						'AND'                     => [
1996
+							'status*inclusive' => ['=', 'private'],
1997
+							'EVT_wp_user'      => get_current_user_id(),
1998
+						],
1999
+					];
2000
+				}
2001
+			}
2002
+		}
2003
+		$wp_user = $this->request->getRequestParam('EVT_wp_user', 0, DataType::INT);
2004
+		if (
2005
+			$wp_user
2006
+			&& $wp_user !== get_current_user_id()
2007
+			&& $this->capabilities->current_user_can('ee_read_others_events', 'get_events')
2008
+		) {
2009
+			$where['EVT_wp_user'] = $wp_user;
2010
+		}
2011
+		// search query handling
2012
+		$search_term = $this->request->getRequestParam('s');
2013
+		if ($search_term) {
2014
+			$search_term = '%' . $search_term . '%';
2015
+			$where['OR'] = [
2016
+				'EVT_name'       => ['LIKE', $search_term],
2017
+				'EVT_desc'       => ['LIKE', $search_term],
2018
+				'EVT_short_desc' => ['LIKE', $search_term],
2019
+			];
2020
+		}
2021
+		// filter events by venue.
2022
+		$venue = $this->request->getRequestParam('venue', 0, DataType::INT);
2023
+		if ($venue) {
2024
+			$where['Venue.VNU_ID'] = $venue;
2025
+		}
2026
+		$request_params = $this->request->requestParams();
2027
+		$where          = apply_filters('FHEE__Events_Admin_Page__get_events__where', $where, $request_params);
2028
+		$query_params   = apply_filters(
2029
+			'FHEE__Events_Admin_Page__get_events__query_params',
2030
+			[
2031
+				$where,
2032
+				'limit'    => $limit,
2033
+				'order_by' => $orderby,
2034
+				'order'    => $order,
2035
+				'group_by' => 'EVT_ID',
2036
+			],
2037
+			$request_params
2038
+		);
2039
+
2040
+		// let's first check if we have special requests coming in.
2041
+		$active_status = $this->request->getRequestParam('active_status');
2042
+		if ($active_status) {
2043
+			switch ($active_status) {
2044
+				case 'upcoming':
2045
+					return $EEM_Event->get_upcoming_events($query_params, $count);
2046
+				case 'expired':
2047
+					return $EEM_Event->get_expired_events($query_params, $count);
2048
+				case 'active':
2049
+					return $EEM_Event->get_active_events($query_params, $count);
2050
+				case 'inactive':
2051
+					return $EEM_Event->get_inactive_events($query_params, $count);
2052
+			}
2053
+		}
2054
+
2055
+		return $count ? $EEM_Event->count([$where], 'EVT_ID', true) : $EEM_Event->get_all($query_params);
2056
+	}
2057
+
2058
+
2059
+	/**
2060
+	 * @param string $month_range
2061
+	 * @param string $timezone_string
2062
+	 * @return array
2063
+	 * @throws Exception
2064
+	 * @since 5.0.21.p
2065
+	 */
2066
+	public function whereParamsForDatetimeMonthRange(string $month_range, string $timezone_string = ''): array
2067
+	{
2068
+		$timezone_string = $timezone_string ?: EEH_DTT_Helper::get_valid_timezone_string();
2069
+		$pieces = explode(' ', $month_range, 3);
2070
+		// simulate the FIRST day of the month, that fixes issues for months like February
2071
+		// where PHP doesn't know what to assume for date.
2072
+		// @see https://events.codebasehq.com/projects/event-espresso/tickets/10437
2073
+		$month_r = ! empty($pieces[0]) ? date('m', EEH_DTT_Helper::first_of_month_timestamp($pieces[0])) : '';
2074
+		$year_r  = ! empty($pieces[1]) ? $pieces[1] : '';
2075
+		$DateTime = new DateTime(
2076
+			"$year_r-$month_r-01 00:00:00",
2077
+			new DateTimeZone($timezone_string)
2078
+		);
2079
+		$start    = $DateTime->getTimestamp();
2080
+		// set the datetime to be the end of the month
2081
+		$DateTime->setDate(
2082
+			$year_r,
2083
+			$month_r,
2084
+			$DateTime->format('t')
2085
+		)->setTime(23, 59, 59);
2086
+		$end                             = $DateTime->getTimestamp();
2087
+		return ['BETWEEN', [$start, $end]];
2088
+	}
2089
+
2090
+
2091
+	/**
2092
+	 * handling for WordPress CPT actions (trash, restore, delete)
2093
+	 *
2094
+	 * @param string $post_id
2095
+	 * @throws EE_Error
2096
+	 * @throws ReflectionException
2097
+	 */
2098
+	public function trash_cpt_item($post_id)
2099
+	{
2100
+		$this->request->setRequestParam('EVT_ID', $post_id);
2101
+		$this->_trash_or_restore_event('trash', false);
2102
+	}
2103
+
2104
+
2105
+	/**
2106
+	 * @param string $post_id
2107
+	 * @throws EE_Error
2108
+	 * @throws ReflectionException
2109
+	 */
2110
+	public function restore_cpt_item($post_id)
2111
+	{
2112
+		$this->request->setRequestParam('EVT_ID', $post_id);
2113
+		$this->_trash_or_restore_event('draft', false);
2114
+	}
2115
+
2116
+
2117
+	/**
2118
+	 * @param string $post_id
2119
+	 * @throws EE_Error
2120
+	 * @throws EE_Error
2121
+	 */
2122
+	public function delete_cpt_item($post_id)
2123
+	{
2124
+		throw new EE_Error(
2125
+			esc_html__(
2126
+				'Please contact Event Espresso support with the details of the steps taken to produce this error.',
2127
+				'event_espresso'
2128
+			)
2129
+		);
2130
+		// $this->request->setRequestParam('EVT_ID', $post_id);
2131
+		// $this->_delete_event();
2132
+	}
2133
+
2134
+
2135
+	/**
2136
+	 * _trash_or_restore_event
2137
+	 *
2138
+	 * @access protected
2139
+	 * @param string $event_status
2140
+	 * @param bool   $redirect_after
2141
+	 * @throws EE_Error
2142
+	 * @throws EE_Error
2143
+	 * @throws ReflectionException
2144
+	 */
2145
+	protected function _trash_or_restore_event(string $event_status = 'trash', bool $redirect_after = true)
2146
+	{
2147
+		// loop thru events
2148
+		if ($this->EVT_ID) {
2149
+			// clean status
2150
+			$event_status = sanitize_key($event_status);
2151
+			// grab status
2152
+			if (! empty($event_status)) {
2153
+				$success = $this->_change_event_status($this->EVT_ID, $event_status);
2154
+			} else {
2155
+				$success = false;
2156
+				$msg     = esc_html__(
2157
+					'An error occurred. The event could not be moved to the trash because a valid event status was not not supplied.',
2158
+					'event_espresso'
2159
+				);
2160
+				EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2161
+			}
2162
+		} else {
2163
+			$success = false;
2164
+			$msg     = esc_html__(
2165
+				'An error occurred. The event could not be moved to the trash because a valid event ID was not not supplied.',
2166
+				'event_espresso'
2167
+			);
2168
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2169
+		}
2170
+		$action = $event_status === 'trash' ? 'moved to the trash' : 'restored from the trash';
2171
+		if ($redirect_after) {
2172
+			$this->_redirect_after_action($success, 'Event', $action, ['action' => 'default']);
2173
+		}
2174
+	}
2175
+
2176
+
2177
+	/**
2178
+	 * _trash_or_restore_events
2179
+	 *
2180
+	 * @access protected
2181
+	 * @param string $event_status
2182
+	 * @return void
2183
+	 * @throws EE_Error
2184
+	 * @throws EE_Error
2185
+	 * @throws ReflectionException
2186
+	 */
2187
+	protected function _trash_or_restore_events(string $event_status = 'trash')
2188
+	{
2189
+		// clean status
2190
+		$event_status = sanitize_key($event_status);
2191
+		// grab status
2192
+		if (! empty($event_status)) {
2193
+			$success = true;
2194
+			// determine the event id and set to array.
2195
+			$EVT_IDs = $this->request->getRequestParam('EVT_IDs', [], 'int', true);
2196
+			// loop thru events
2197
+			foreach ($EVT_IDs as $EVT_ID) {
2198
+				if ($EVT_ID = absint($EVT_ID)) {
2199
+					$results = $this->_change_event_status($EVT_ID, $event_status);
2200
+					$success = $results !== false ? $success : false;
2201
+				} else {
2202
+					$msg = sprintf(
2203
+						esc_html__(
2204
+							'An error occurred. Event #%d could not be moved to the trash because a valid event ID was not not supplied.',
2205
+							'event_espresso'
2206
+						),
2207
+						$EVT_ID
2208
+					);
2209
+					EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2210
+					$success = false;
2211
+				}
2212
+			}
2213
+		} else {
2214
+			$success = false;
2215
+			$msg     = esc_html__(
2216
+				'An error occurred. The event could not be moved to the trash because a valid event status was not not supplied.',
2217
+				'event_espresso'
2218
+			);
2219
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2220
+		}
2221
+		// in order to force a pluralized result message we need to send back a success status greater than 1
2222
+		$success = $success ? 2 : false;
2223
+		$action  = $event_status === 'trash' ? 'moved to the trash' : 'restored from the trash';
2224
+		$this->_redirect_after_action($success, 'Events', $action, ['action' => 'default']);
2225
+	}
2226
+
2227
+
2228
+	/**
2229
+	 * @param int    $EVT_ID
2230
+	 * @param string $event_status
2231
+	 * @return bool
2232
+	 * @throws EE_Error
2233
+	 * @throws ReflectionException
2234
+	 */
2235
+	private function _change_event_status(int $EVT_ID = 0, string $event_status = ''): bool
2236
+	{
2237
+		// grab event id
2238
+		if (! $EVT_ID) {
2239
+			$msg = esc_html__(
2240
+				'An error occurred. No Event ID or an invalid Event ID was received.',
2241
+				'event_espresso'
2242
+			);
2243
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2244
+			return false;
2245
+		}
2246
+		$this->_cpt_model_obj = EEM_Event::instance()->get_one_by_ID($EVT_ID);
2247
+		// clean status
2248
+		$event_status = sanitize_key($event_status);
2249
+		// grab status
2250
+		if (empty($event_status)) {
2251
+			$msg = esc_html__(
2252
+				'An error occurred. No Event Status or an invalid Event Status was received.',
2253
+				'event_espresso'
2254
+			);
2255
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2256
+			return false;
2257
+		}
2258
+		// was event trashed or restored ?
2259
+		switch ($event_status) {
2260
+			case 'draft':
2261
+				$action = 'restored from the trash';
2262
+				$hook   = 'AHEE_event_restored_from_trash';
2263
+				break;
2264
+			case 'trash':
2265
+				$action = 'moved to the trash';
2266
+				$hook   = 'AHEE_event_moved_to_trash';
2267
+				break;
2268
+			default:
2269
+				$action = 'updated';
2270
+				$hook   = false;
2271
+		}
2272
+		// use class to change status
2273
+		$this->_cpt_model_obj->set_status($event_status);
2274
+		$success = $this->_cpt_model_obj->save();
2275
+		if (! $success) {
2276
+			$msg = sprintf(esc_html__('An error occurred. The event could not be %s.', 'event_espresso'), $action);
2277
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2278
+			return false;
2279
+		}
2280
+		if ($hook) {
2281
+			do_action($hook);
2282
+			// fake the action hook in EE_Soft_Delete_Base_Class::delete_or_restore()
2283
+			// because events side step that and it otherwise won't get called
2284
+			do_action(
2285
+				'AHEE__EE_Soft_Delete_Base_Class__delete_or_restore__after',
2286
+				$this->_cpt_model_obj,
2287
+				$hook === 'AHEE_event_moved_to_trash',
2288
+				$success
2289
+			);
2290
+		}
2291
+		return true;
2292
+	}
2293
+
2294
+
2295
+	/**
2296
+	 * @param array $event_ids
2297
+	 * @return array
2298
+	 * @since   4.10.23.p
2299
+	 */
2300
+	private function cleanEventIds(array $event_ids): array
2301
+	{
2302
+		return array_map('absint', $event_ids);
2303
+	}
2304
+
2305
+
2306
+	/**
2307
+	 * @return array
2308
+	 * @since   4.10.23.p
2309
+	 */
2310
+	private function getEventIdsFromRequest(): array
2311
+	{
2312
+		if ($this->request->requestParamIsSet('EVT_IDs')) {
2313
+			return $this->request->getRequestParam('EVT_IDs', [], 'int', true);
2314
+		} else {
2315
+			return $this->request->getRequestParam('EVT_ID', [], 'int', true);
2316
+		}
2317
+	}
2318
+
2319
+
2320
+	/**
2321
+	 * @param bool $preview_delete
2322
+	 * @throws EE_Error
2323
+	 * @throws ReflectionException
2324
+	 */
2325
+	protected function _delete_event(bool $preview_delete = true)
2326
+	{
2327
+		$this->_delete_events($preview_delete);
2328
+	}
2329
+
2330
+
2331
+	/**
2332
+	 * Gets the tree traversal batch persister.
2333
+	 *
2334
+	 * @return NodeGroupDao
2335
+	 * @throws InvalidArgumentException
2336
+	 * @throws InvalidDataTypeException
2337
+	 * @throws InvalidInterfaceException
2338
+	 * @since 4.10.12.p
2339
+	 */
2340
+	protected function getModelObjNodeGroupPersister(): NodeGroupDao
2341
+	{
2342
+		if (! $this->model_obj_node_group_persister instanceof NodeGroupDao) {
2343
+			$this->model_obj_node_group_persister =
2344
+				$this->getLoader()->load('\EventEspresso\core\services\orm\tree_traversal\NodeGroupDao');
2345
+		}
2346
+		return $this->model_obj_node_group_persister;
2347
+	}
2348
+
2349
+
2350
+	/**
2351
+	 * @param bool $preview_delete
2352
+	 * @return void
2353
+	 * @throws EE_Error
2354
+	 * @throws ReflectionException
2355
+	 */
2356
+	protected function _delete_events(bool $preview_delete = true)
2357
+	{
2358
+		$event_ids = $this->getEventIdsFromRequest();
2359
+		if ($preview_delete) {
2360
+			$this->generateDeletionPreview($event_ids);
2361
+		} else {
2362
+			foreach ($event_ids as $event_id) {
2363
+				$event = EEM_Event::instance()->get_one_by_ID($event_id);
2364
+				if ($event instanceof EE_Event) {
2365
+					$event->delete_permanently();
2366
+				}
2367
+			}
2368
+		}
2369
+	}
2370
+
2371
+
2372
+	/**
2373
+	 * @param array $event_ids
2374
+	 */
2375
+	protected function generateDeletionPreview(array $event_ids)
2376
+	{
2377
+		$event_ids = $this->cleanEventIds($event_ids);
2378
+		// Set a code we can use to reference this deletion task in the batch jobs and preview page.
2379
+		$deletion_job_code = $this->getModelObjNodeGroupPersister()->generateGroupCode();
2380
+		$return_url        = EE_Admin_Page::add_query_args_and_nonce(
2381
+			[
2382
+				'action'            => 'preview_deletion',
2383
+				'deletion_job_code' => $deletion_job_code,
2384
+			],
2385
+			$this->_admin_base_url
2386
+		);
2387
+		EEH_URL::safeRedirectAndExit(
2388
+			EE_Admin_Page::add_query_args_and_nonce(
2389
+				[
2390
+					'page'              => EED_Batch::PAGE_SLUG,
2391
+					'batch'             => EED_Batch::batch_job,
2392
+					'EVT_IDs'           => $event_ids,
2393
+					'deletion_job_code' => $deletion_job_code,
2394
+					'job_handler'       => urlencode('EventEspresso\core\libraries\batch\JobHandlers\PreviewEventDeletion'),
2395
+					'return_url'        => urlencode($return_url),
2396
+				],
2397
+				admin_url()
2398
+			)
2399
+		);
2400
+	}
2401
+
2402
+
2403
+	/**
2404
+	 * Checks for a POST submission
2405
+	 *
2406
+	 * @since 4.10.12.p
2407
+	 */
2408
+	protected function confirmDeletion()
2409
+	{
2410
+		$deletion_redirect_logic = $this->getLoader()->getShared(
2411
+			'EventEspresso\core\domain\services\admin\events\data\ConfirmDeletion'
2412
+		);
2413
+		$deletion_redirect_logic->handle($this->get_request_data(), $this->admin_base_url());
2414
+	}
2415
+
2416
+
2417
+	/**
2418
+	 * A page for users to preview what exactly will be deleted, and confirm they want to delete it.
2419
+	 *
2420
+	 * @throws EE_Error
2421
+	 * @since 4.10.12.p
2422
+	 */
2423
+	protected function previewDeletion()
2424
+	{
2425
+		$preview_deletion_logic = $this->getLoader()->getShared(
2426
+			'EventEspresso\core\domain\services\admin\events\data\PreviewDeletion'
2427
+		);
2428
+		$this->set_template_args($preview_deletion_logic->handle($this->get_request_data(), $this->admin_base_url()));
2429
+		$this->display_admin_page_with_no_sidebar();
2430
+	}
2431
+
2432
+
2433
+	/**
2434
+	 * get total number of events
2435
+	 *
2436
+	 * @access public
2437
+	 * @return int
2438
+	 * @throws EE_Error
2439
+	 * @throws EE_Error
2440
+	 * @throws ReflectionException
2441
+	 */
2442
+	public function total_events(): int
2443
+	{
2444
+		return EEM_Event::instance()->count(
2445
+			['caps' => 'read_admin'],
2446
+			'EVT_ID',
2447
+			true
2448
+		);
2449
+	}
2450
+
2451
+
2452
+	/**
2453
+	 * get total number of draft events
2454
+	 *
2455
+	 * @access public
2456
+	 * @return int
2457
+	 * @throws EE_Error
2458
+	 * @throws EE_Error
2459
+	 * @throws ReflectionException
2460
+	 */
2461
+	public function total_events_draft(): int
2462
+	{
2463
+		return EEM_Event::instance()->count(
2464
+			[
2465
+				['status' => ['IN', ['draft', 'auto-draft']]],
2466
+				'caps' => 'read_admin',
2467
+			],
2468
+			'EVT_ID',
2469
+			true
2470
+		);
2471
+	}
2472
+
2473
+
2474
+	/**
2475
+	 * get total number of trashed events
2476
+	 *
2477
+	 * @access public
2478
+	 * @return int
2479
+	 * @throws EE_Error
2480
+	 * @throws EE_Error
2481
+	 * @throws ReflectionException
2482
+	 */
2483
+	public function total_trashed_events(): int
2484
+	{
2485
+		return EEM_Event::instance()->count(
2486
+			[
2487
+				['status' => 'trash'],
2488
+				'caps' => 'read_admin',
2489
+			],
2490
+			'EVT_ID',
2491
+			true
2492
+		);
2493
+	}
2494
+
2495
+
2496
+	/**
2497
+	 *    _default_event_settings
2498
+	 *    This generates the Default Settings Tab
2499
+	 *
2500
+	 * @return void
2501
+	 * @throws DomainException
2502
+	 * @throws EE_Error
2503
+	 * @throws InvalidArgumentException
2504
+	 * @throws InvalidDataTypeException
2505
+	 * @throws InvalidInterfaceException
2506
+	 * @throws ReflectionException
2507
+	 */
2508
+	protected function _default_event_settings()
2509
+	{
2510
+		$this->_set_add_edit_form_tags('update_default_event_settings');
2511
+		$this->_set_publish_post_box_vars();
2512
+		$this->_template_args['admin_page_content'] = EEH_HTML::div(
2513
+			$this->_default_event_settings_form()->get_html(),
2514
+			'',
2515
+			'padding'
2516
+		);
2517
+		$this->display_admin_page_with_sidebar();
2518
+	}
2519
+
2520
+
2521
+	/**
2522
+	 * Return the form for event settings.
2523
+	 *
2524
+	 * @return EE_Form_Section_Proper
2525
+	 * @throws EE_Error
2526
+	 * @throws ReflectionException
2527
+	 */
2528
+	protected function _default_event_settings_form(): EE_Form_Section_Proper
2529
+	{
2530
+		$registration_config              = EE_Registry::instance()->CFG->registration;
2531
+		$registration_stati_for_selection = EEM_Registration::reg_status_array(
2532
+		// exclude
2533
+			[
2534
+				RegStatus::CANCELLED,
2535
+				RegStatus::DECLINED,
2536
+				RegStatus::INCOMPLETE,
2537
+				RegStatus::WAIT_LIST,
2538
+			],
2539
+			true
2540
+		);
2541
+		// setup Advanced Editor ???
2542
+		if (
2543
+			$this->raw_req_action === 'default_event_settings'
2544
+			|| $this->raw_req_action === 'update_default_event_settings'
2545
+		) {
2546
+			$this->advanced_editor_admin_form = $this->loader->getShared(AdvancedEditorAdminFormSection::class);
2547
+		}
2548
+		return new EE_Form_Section_Proper(
2549
+			[
2550
+				'name'            => 'update_default_event_settings',
2551
+				'html_id'         => 'update_default_event_settings',
2552
+				'html_class'      => 'form-table',
2553
+				'layout_strategy' => new EE_Admin_Two_Column_Layout(),
2554
+				'subsections'     => apply_filters(
2555
+					'FHEE__Events_Admin_Page___default_event_settings_form__form_subsections',
2556
+					[
2557
+						'defaults_section_header' => new EE_Form_Section_HTML(
2558
+							EEH_HTML::h2(
2559
+								esc_html__('Default Settings', 'event_espresso'),
2560
+								'',
2561
+								'ee-admin-settings-hdr'
2562
+							)
2563
+						),
2564
+						'default_reg_status'      => new EE_Select_Input(
2565
+							$registration_stati_for_selection,
2566
+							[
2567
+								'default'         => isset($registration_config->default_STS_ID)
2568
+													 && array_key_exists(
2569
+														 $registration_config->default_STS_ID,
2570
+														 $registration_stati_for_selection
2571
+													 )
2572
+									? sanitize_text_field($registration_config->default_STS_ID)
2573
+									: RegStatus::PENDING_PAYMENT,
2574
+								'html_label_text' => esc_html__('Default Registration Status', 'event_espresso')
2575
+													 . EEH_Template::get_help_tab_link(
2576
+														 'default_settings_status_help_tab'
2577
+													 ),
2578
+								'html_help_text'  => esc_html__(
2579
+									'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.',
2580
+									'event_espresso'
2581
+								),
2582
+								'html_class'      => 'ee-input-width--small',
2583
+							]
2584
+						),
2585
+						'default_max_tickets'     => new EE_Integer_Input(
2586
+							[
2587
+								'default'         => $registration_config->default_maximum_number_of_tickets
2588
+													 ?? EEM_Event::get_default_additional_limit(),
2589
+								'html_label_text' => esc_html__(
2590
+									'Default Maximum Tickets Allowed Per Order:',
2591
+									'event_espresso'
2592
+								)
2593
+													 . EEH_Template::get_help_tab_link(
2594
+														 'default_maximum_tickets_help_tab"'
2595
+													 ),
2596
+								'html_help_text'  => esc_html__(
2597
+									'This setting allows you to indicate what will be the default for the maximum number of tickets per order when creating new events.',
2598
+									'event_espresso'
2599
+								),
2600
+								'html_class'      => 'ee-input-width--tiny',
2601
+							]
2602
+						),
2603
+					]
2604
+				),
2605
+			]
2606
+		);
2607
+	}
2608
+
2609
+
2610
+	/**
2611
+	 * @return void
2612
+	 * @throws EE_Error
2613
+	 * @throws InvalidArgumentException
2614
+	 * @throws InvalidDataTypeException
2615
+	 * @throws InvalidInterfaceException
2616
+	 * @throws ReflectionException
2617
+	 */
2618
+	protected function _update_default_event_settings()
2619
+	{
2620
+		$form = $this->_default_event_settings_form();
2621
+		if ($form->was_submitted()) {
2622
+			$form->receive_form_submission();
2623
+			if ($form->is_valid()) {
2624
+				$registration_config = EE_Registry::instance()->CFG->registration;
2625
+				$valid_data          = $form->valid_data();
2626
+				if (isset($valid_data['default_reg_status'])) {
2627
+					$registration_config->default_STS_ID = $valid_data['default_reg_status'];
2628
+				}
2629
+				if (isset($valid_data['default_max_tickets'])) {
2630
+					$registration_config->default_maximum_number_of_tickets = (int) $valid_data['default_max_tickets'];
2631
+				}
2632
+				do_action(
2633
+					'AHEE__Events_Admin_Page___update_default_event_settings',
2634
+					$valid_data,
2635
+					EE_Registry::instance()->CFG,
2636
+					$this
2637
+				);
2638
+				// update because data was valid!
2639
+				EE_Registry::instance()->CFG->update_espresso_config();
2640
+				EE_Error::overwrite_success();
2641
+				EE_Error::add_success(
2642
+					esc_html__('Default Event Settings were updated', 'event_espresso')
2643
+				);
2644
+			}
2645
+		}
2646
+		$this->_redirect_after_action(0, '', '', ['action' => 'default_event_settings'], true);
2647
+	}
2648
+
2649
+
2650
+	/*************        Templates        *************
794 2651
      *
795
-     * @return void
796
-     * @throws EE_Error
797
-     * @throws InvalidArgumentException
798
-     * @throws InvalidDataTypeException
799
-     * @throws InvalidInterfaceException
800
-     * @throws ReflectionException
801
-     */
802
-    protected function _create_new_cpt_item()
803
-    {
804
-        $has_timezone_string = get_option('timezone_string');
805
-        // only nag them about setting their timezone if it's their first event, and they haven't already done it
806
-        if (! $has_timezone_string && ! EEM_Event::instance()->exists([])) {
807
-            EE_Error::add_attention(
808
-                sprintf(
809
-                    esc_html__(
810
-                        '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',
811
-                        'event_espresso'
812
-                    ),
813
-                    '<br>',
814
-                    '<select id="timezone_string" name="timezone_string" aria-describedby="timezone-description">'
815
-                    . EEH_DTT_Helper::wp_timezone_choice('', EEH_DTT_Helper::get_user_locale())
816
-                    . '</select>',
817
-                    '<button class="button button--secondary timezone-submit">',
818
-                    '</button><span class="spinner"></span>'
819
-                ),
820
-                __FILE__,
821
-                __FUNCTION__,
822
-                __LINE__
823
-            );
824
-        }
825
-        parent::_create_new_cpt_item();
826
-    }
827
-
828
-
829
-    /**
830
-     * Sets the _views property for the default route in this admin page group.
831
-     */
832
-    protected function _set_list_table_views_default()
833
-    {
834
-        $this->_views = [
835
-            'all'   => [
836
-                'slug'        => 'all',
837
-                'label'       => esc_html__('View All Events', 'event_espresso'),
838
-                'count'       => 0,
839
-                'bulk_action' => [
840
-                    'trash_events' => esc_html__('Move to Trash', 'event_espresso'),
841
-                ],
842
-            ],
843
-            'draft' => [
844
-                'slug'        => 'draft',
845
-                'label'       => esc_html__('Draft', 'event_espresso'),
846
-                'count'       => 0,
847
-                'bulk_action' => [
848
-                    'trash_events' => esc_html__('Move to Trash', 'event_espresso'),
849
-                ],
850
-            ],
851
-        ];
852
-        if ($this->capabilities->current_user_can('ee_delete_events', 'espresso_events_trash_events')) {
853
-            $this->_views['trash'] = [
854
-                'slug'        => 'trash',
855
-                'label'       => esc_html__('Trash', 'event_espresso'),
856
-                'count'       => 0,
857
-                'bulk_action' => [
858
-                    'restore_events' => esc_html__('Restore From Trash', 'event_espresso'),
859
-                    'delete_events'  => esc_html__('Delete Permanently', 'event_espresso'),
860
-                ],
861
-            ];
862
-        }
863
-    }
864
-
865
-
866
-    /**
867
-     * Provides the legend item array for the default list table view.
868
-     *
869
-     * @return array
870
-     * @throws EE_Error
871
-     * @throws EE_Error
872
-     */
873
-    protected function _event_legend_items(): array
874
-    {
875
-        $items    = [
876
-            'view_details'   => [
877
-                'class' => 'dashicons dashicons-visibility',
878
-                'desc'  => esc_html__('View Event', 'event_espresso'),
879
-            ],
880
-            'edit_event'     => [
881
-                'class' => 'dashicons dashicons-calendar-alt',
882
-                'desc'  => esc_html__('Edit Event Details', 'event_espresso'),
883
-            ],
884
-            'view_attendees' => [
885
-                'class' => 'dashicons dashicons-groups',
886
-                'desc'  => esc_html__('View Registrations for Event', 'event_espresso'),
887
-            ],
888
-        ];
889
-        $items    = apply_filters('FHEE__Events_Admin_Page___event_legend_items__items', $items);
890
-        $statuses = [
891
-            'sold_out_status'  => [
892
-                'class' => 'ee-status-legend ee-status-bg--' . EE_Datetime::sold_out,
893
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::sold_out, false, 'sentence'),
894
-            ],
895
-            'active_status'    => [
896
-                'class' => 'ee-status-legend ee-status-bg--' . EE_Datetime::active,
897
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::active, false, 'sentence'),
898
-            ],
899
-            'upcoming_status'  => [
900
-                'class' => 'ee-status-legend ee-status-bg--' . EE_Datetime::upcoming,
901
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::upcoming, false, 'sentence'),
902
-            ],
903
-            'postponed_status' => [
904
-                'class' => 'ee-status-legend ee-status-bg--' . EE_Datetime::postponed,
905
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::postponed, false, 'sentence'),
906
-            ],
907
-            'cancelled_status' => [
908
-                'class' => 'ee-status-legend ee-status-bg--' . EE_Datetime::cancelled,
909
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::cancelled, false, 'sentence'),
910
-            ],
911
-            'expired_status'   => [
912
-                'class' => 'ee-status-legend ee-status-bg--' . EE_Datetime::expired,
913
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::expired, false, 'sentence'),
914
-            ],
915
-            'inactive_status'  => [
916
-                'class' => 'ee-status-legend ee-status-bg--' . EE_Datetime::inactive,
917
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::inactive, false, 'sentence'),
918
-            ],
919
-        ];
920
-        $statuses = apply_filters('FHEE__Events_Admin_Page__event_legend_items__statuses', $statuses);
921
-        return array_merge($items, $statuses);
922
-    }
923
-
924
-
925
-    /**
926
-     * @return EEM_Event
927
-     * @throws EE_Error
928
-     * @throws InvalidArgumentException
929
-     * @throws InvalidDataTypeException
930
-     * @throws InvalidInterfaceException
931
-     * @throws ReflectionException
932
-     */
933
-    private function _event_model(): EEM_Event
934
-    {
935
-        if (! $this->_event_model instanceof EEM_Event) {
936
-            $this->_event_model = EE_Registry::instance()->load_model('Event');
937
-        }
938
-        return $this->_event_model;
939
-    }
940
-
941
-
942
-    /**
943
-     * Adds extra buttons to the WP CPT permalink field row.
944
-     * Method is called from parent and is hooked into the wp 'get_sample_permalink_html' filter.
945
-     *
946
-     * @param string      $return    the current html
947
-     * @param int         $id        the post id for the page
948
-     * @param string|null $new_title What the title is
949
-     * @param string|null $new_slug  what the slug is
950
-     * @return string            The new html string for the permalink area
951
-     * @deprecated 5.0.0.p
952
-     * @see        TicketSelectorShortcodeButton::addButton
953
-     */
954
-    public function extra_permalink_field_buttons(
955
-        string $return,
956
-        int $id,
957
-        ?string $new_title,
958
-        ?string $new_slug
959
-    ): string {
960
-        return TicketSelectorShortcodeButton::addButton($return, $id, $new_title, $new_slug);
961
-    }
962
-
963
-
964
-    /**
965
-     * _events_overview_list_table
966
-     * This contains the logic for showing the events_overview list
967
-     *
968
-     * @access protected
969
-     * @return void
970
-     * @throws DomainException
971
-     * @throws EE_Error
972
-     * @throws InvalidArgumentException
973
-     * @throws InvalidDataTypeException
974
-     * @throws InvalidInterfaceException
975
-     */
976
-    protected function _events_overview_list_table()
977
-    {
978
-        $after_list_table = [];
979
-        $links_html       = EEH_HTML::div('', '', 'ee-admin-section ee-layout-stack');
980
-        $links_html       .= EEH_HTML::h3(esc_html__('Links', 'event_espresso'));
981
-        $links_html       .= EEH_HTML::div(
982
-            EEH_Template::get_button_or_link(
983
-                get_post_type_archive_link(EspressoPostType::EVENTS),
984
-                esc_html__('View Event Archive Page', 'event_espresso'),
985
-                'button button--small button--secondary'
986
-            ),
987
-            '',
988
-            'ee-admin-button-row ee-admin-button-row--align-start'
989
-        );
990
-        $links_html       .= EEH_HTML::divx();
991
-
992
-        $after_list_table['view_event_list_button'] = $links_html;
993
-
994
-        $after_list_table['legend'] = $this->_display_legend($this->_event_legend_items());
995
-        $this->_admin_page_title    .= ' ' . $this->get_action_link_or_button(
996
-            'create_new',
997
-            'add',
998
-            [],
999
-            'add-new-h2'
1000
-        );
1001
-
1002
-        $this->_template_args['after_list_table'] = array_merge(
1003
-            (array) $this->_template_args['after_list_table'],
1004
-            $after_list_table
1005
-        );
1006
-        $this->display_admin_list_table_page_with_no_sidebar();
1007
-    }
1008
-
1009
-
1010
-    /**
1011
-     * this allows for extra misc actions in the default WP publish box
1012
-     *
1013
-     * @return void
1014
-     * @throws DomainException
1015
-     * @throws EE_Error
1016
-     * @throws InvalidArgumentException
1017
-     * @throws InvalidDataTypeException
1018
-     * @throws InvalidInterfaceException
1019
-     * @throws ReflectionException
1020
-     */
1021
-    public function extra_misc_actions_publish_box()
1022
-    {
1023
-        $this->_generate_publish_box_extra_content();
1024
-    }
1025
-
1026
-
1027
-    /**
1028
-     * This is hooked into the WordPress do_action('save_post') hook and runs after the custom post type has been
1029
-     * saved.
1030
-     * Typically you would use this to save any additional data.
1031
-     * Keep in mind also that "save_post" runs on EVERY post update to the database.
1032
-     * ALSO very important.  When a post transitions from scheduled to published,
1033
-     * the save_post action is fired but you will NOT have any _POST data containing any extra info you may have from
1034
-     * other meta saves. So MAKE sure that you handle this accordingly.
1035
-     *
1036
-     * @access protected
1037
-     * @abstract
1038
-     * @param string  $post_id The ID of the cpt that was saved (so you can link relationally)
1039
-     * @param WP_Post $post    The post object of the cpt that was saved.
1040
-     * @return void
1041
-     * @throws EE_Error
1042
-     * @throws InvalidArgumentException
1043
-     * @throws InvalidDataTypeException
1044
-     * @throws InvalidInterfaceException
1045
-     * @throws ReflectionException
1046
-     */
1047
-    protected function _insert_update_cpt_item($post_id, $post)
1048
-    {
1049
-        if ($post instanceof WP_Post && $post->post_type !== EspressoPostType::EVENTS) {
1050
-            // get out we're not processing an event save.
1051
-            return;
1052
-        }
1053
-        $event_values = [
1054
-            'EVT_member_only'     => $this->request->getRequestParam('member_only', false, DataType::BOOL),
1055
-            'EVT_allow_overflow'  => $this->request->getRequestParam('EVT_allow_overflow', false, DataType::BOOL),
1056
-            'EVT_timezone_string' => $this->request->getRequestParam('timezone_string'),
1057
-        ];
1058
-        // check if the new EDTR reg options meta box is being used, and if so, don't run updates for legacy version
1059
-        if (! $this->admin_config->useAdvancedEditor() || ! $this->feature->allowed('use_reg_options_meta_box')) {
1060
-            $event_values['EVT_display_ticket_selector']     = $this->request->getRequestParam(
1061
-                'display_ticket_selector',
1062
-                false,
1063
-                'bool'
1064
-            );
1065
-            $event_values['EVT_additional_limit']            = min(
1066
-                apply_filters('FHEE__EE_Events_Admin__insert_update_cpt_item__EVT_additional_limit_max', 255),
1067
-                $this->request->getRequestParam(
1068
-                    'additional_limit',
1069
-                    EEM_Event::get_default_additional_limit(),
1070
-                    'int'
1071
-                )
1072
-            );
1073
-            $event_values['EVT_default_registration_status'] = $this->request->getRequestParam(
1074
-                'EVT_default_registration_status',
1075
-                EE_Registry::instance()->CFG->registration->default_STS_ID
1076
-            );
1077
-
1078
-            $event_values['EVT_external_URL'] = $this->request->getRequestParam('externalURL');
1079
-            $event_values['EVT_phone']        = $this->request->getRequestParam('event_phone');
1080
-            $event_values['EVT_display_desc'] = $this->request->getRequestParam('display_desc', false, DataType::BOOL);
1081
-        } elseif ($post instanceof WP_Post) {
1082
-            $event_values['EVT_name'] = $post->post_title;
1083
-            $event_values['EVT_desc'] = $post->post_content;
1084
-        }
1085
-        // update event
1086
-        $success = $this->_event_model()->update_by_ID($event_values, $post_id);
1087
-        // get event_object for other metaboxes...
1088
-        // though it would seem to make sense to just use $this->_event_model()->get_one_by_ID( $post_id )..
1089
-        // i have to set up where conditions to override the filters in the model
1090
-        // that filter out auto-draft and inherit statuses so we GET the inherit id!
1091
-        /** @var EE_Event $event */
1092
-        $event = $this->_event_model()->get_one(
1093
-            [
1094
-                [
1095
-                    $this->_event_model()->primary_key_name() => $post_id,
1096
-                    'OR'                                      => [
1097
-                        'status'   => $post->post_status,
1098
-                        // if trying to "Publish" a sold out event, it's status will get switched back to "sold_out" in the db,
1099
-                        // but the returned object here has a status of "publish", so use the original post status as well
1100
-                        'status*1' => $this->request->getRequestParam('original_post_status'),
1101
-                    ],
1102
-                    'status' => ['NOT IN', ['auto-draft']],
1103
-                ],
1104
-            ]
1105
-        );
1106
-
1107
-        if (! $event instanceof EE_Event) {
1108
-            return;
1109
-        }
1110
-
1111
-        // the following are default callbacks for event attachment updates
1112
-        // that can be overridden by caffeinated functionality and/or addons.
1113
-        $event_update_callbacks = [];
1114
-        if (! $this->admin_config->useAdvancedEditor()) {
1115
-            $event_update_callbacks['_default_venue_update']   = [$this, '_default_venue_update'];
1116
-            $event_update_callbacks['_default_tickets_update'] = [$this, '_default_tickets_update'];
1117
-        }
1118
-        $event_update_callbacks = apply_filters(
1119
-            'FHEE__Events_Admin_Page___insert_update_cpt_item__event_update_callbacks',
1120
-            $event_update_callbacks
1121
-        );
1122
-
1123
-        $att_success = true;
1124
-        foreach ($event_update_callbacks as $e_callback) {
1125
-            $_success = is_callable($e_callback)
1126
-                ? $e_callback($event, $this->request->requestParams())
1127
-                : false;
1128
-            // if ANY of these updates fail then we want the appropriate global error message
1129
-            $att_success = $_success !== false ? $att_success : false;
1130
-        }
1131
-        // any errors?
1132
-        if ($success && $att_success === false) {
1133
-            EE_Error::add_error(
1134
-                esc_html__(
1135
-                    'Event Details saved successfully but something went wrong with saving attachments.',
1136
-                    'event_espresso'
1137
-                ),
1138
-                __FILE__,
1139
-                __FUNCTION__,
1140
-                __LINE__
1141
-            );
1142
-        } elseif ($success === false) {
1143
-            EE_Error::add_error(
1144
-                esc_html__('Event Details did not save successfully.', 'event_espresso'),
1145
-                __FILE__,
1146
-                __FUNCTION__,
1147
-                __LINE__
1148
-            );
1149
-        }
1150
-    }
1151
-
1152
-
1153
-    /**
1154
-     * @param int $post_id
1155
-     * @param int $revision_id
1156
-     * @throws EE_Error
1157
-     * @throws EE_Error
1158
-     * @throws ReflectionException
1159
-     * @see parent::restore_item()
1160
-     */
1161
-    protected function _restore_cpt_item(int $post_id, int $revision_id)
1162
-    {
1163
-        // copy existing event meta to new post
1164
-        $post_evt = $this->_event_model()->get_one_by_ID($post_id);
1165
-        if ($post_evt instanceof EE_Event) {
1166
-            // meta revision restore
1167
-            $post_evt->restore_revision($revision_id);
1168
-            // related objs restore
1169
-            $post_evt->restore_revision($revision_id, ['Venue', 'Datetime', 'Price']);
1170
-        }
1171
-    }
1172
-
1173
-
1174
-    /**
1175
-     * Attach the venue to the Event
1176
-     *
1177
-     * @param EE_Event $event Event Object to add the venue to
1178
-     * @param array    $data  The request data from the form
1179
-     * @return bool           Success or fail.
1180
-     * @throws EE_Error
1181
-     * @throws ReflectionException
1182
-     */
1183
-    protected function _default_venue_update(EE_Event $event, array $data): bool
1184
-    {
1185
-        require_once(EE_MODELS . 'EEM_Venue.model.php');
1186
-        $venue_model = EE_Registry::instance()->load_model('Venue');
1187
-        $venue_id    = ! empty($data['venue_id']) ? $data['venue_id'] : null;
1188
-        // very important.  If we don't have a venue name...
1189
-        // then we'll get out because not necessary to create empty venue
1190
-        if (empty($data['venue_title'])) {
1191
-            return false;
1192
-        }
1193
-        $venue_array = [
1194
-            'VNU_wp_user'         => $event->get('EVT_wp_user'),
1195
-            'VNU_name'            => $data['venue_title'],
1196
-            'VNU_desc'            => ! empty($data['venue_description']) ? $data['venue_description'] : null,
1197
-            'VNU_identifier'      => ! empty($data['venue_identifier']) ? $data['venue_identifier'] : null,
1198
-            'VNU_short_desc'      => ! empty($data['venue_short_description'])
1199
-                ? $data['venue_short_description']
1200
-                : null,
1201
-            'VNU_address'         => ! empty($data['address']) ? $data['address'] : null,
1202
-            'VNU_address2'        => ! empty($data['address2']) ? $data['address2'] : null,
1203
-            'VNU_city'            => ! empty($data['city']) ? $data['city'] : null,
1204
-            'STA_ID'              => ! empty($data['state']) ? $data['state'] : null,
1205
-            'CNT_ISO'             => ! empty($data['countries']) ? $data['countries'] : null,
1206
-            'VNU_zip'             => ! empty($data['zip']) ? $data['zip'] : null,
1207
-            'VNU_phone'           => ! empty($data['venue_phone']) ? $data['venue_phone'] : null,
1208
-            'VNU_capacity'        => ! empty($data['venue_capacity']) ? $data['venue_capacity'] : null,
1209
-            'VNU_url'             => ! empty($data['venue_url']) ? $data['venue_url'] : null,
1210
-            'VNU_virtual_phone'   => ! empty($data['virtual_phone']) ? $data['virtual_phone'] : null,
1211
-            'VNU_virtual_url'     => ! empty($data['virtual_url']) ? $data['virtual_url'] : null,
1212
-            'VNU_enable_for_gmap' => isset($data['enable_for_gmap']) ? 1 : 0,
1213
-            'status'              => 'publish',
1214
-        ];
1215
-        // if we've got the venue_id then we're just updating the existing venue so let's do that and then get out.
1216
-        if (! empty($venue_id)) {
1217
-            $update_where  = [$venue_model->primary_key_name() => $venue_id];
1218
-            $rows_affected = $venue_model->update($venue_array, [$update_where]);
1219
-            // we've gotta make sure that the venue is always attached to a revision..
1220
-            // add_relation_to should take care of making sure that the relation is already present.
1221
-            $event->_add_relation_to($venue_id, 'Venue');
1222
-            return $rows_affected > 0;
1223
-        }
1224
-        // we insert the venue
1225
-        $venue_id = $venue_model->insert($venue_array);
1226
-        $event->_add_relation_to($venue_id, 'Venue');
1227
-        return ! empty($venue_id);
1228
-        // when we have the ancestor come in it's already been handled by the revision save.
1229
-    }
1230
-
1231
-
1232
-    /**
1233
-     * Handles saving everything related to Tickets (datetimes, tickets, prices)
1234
-     *
1235
-     * @param EE_Event $event The Event object we're attaching data to
1236
-     * @param array    $data  The request data from the form
1237
-     * @return array
1238
-     * @throws EE_Error
1239
-     * @throws ReflectionException
1240
-     * @throws Exception
1241
-     */
1242
-    protected function _default_tickets_update(EE_Event $event, array $data): array
1243
-    {
1244
-        if ($this->admin_config->useAdvancedEditor()) {
1245
-            return [];
1246
-        }
1247
-        $datetime       = null;
1248
-        $saved_tickets  = [];
1249
-        $event_timezone = $event->get_timezone();
1250
-        $date_formats   = ['Y-m-d', 'h:i a'];
1251
-        foreach ($data['edit_event_datetimes'] as $row => $datetime_data) {
1252
-            // trim all values to ensure any excess whitespace is removed.
1253
-            $datetime_data                = array_map('trim', $datetime_data);
1254
-            $datetime_data['DTT_EVT_end'] = ! empty($datetime_data['DTT_EVT_end'])
1255
-                    ? $datetime_data['DTT_EVT_end']
1256
-                    : $datetime_data['DTT_EVT_start'];
1257
-            $datetime_values              = [
1258
-                'DTT_ID'        => ! empty($datetime_data['DTT_ID']) ? $datetime_data['DTT_ID'] : null,
1259
-                'DTT_EVT_start' => $datetime_data['DTT_EVT_start'],
1260
-                'DTT_EVT_end'   => $datetime_data['DTT_EVT_end'],
1261
-                'DTT_reg_limit' => empty($datetime_data['DTT_reg_limit']) ? EE_INF : $datetime_data['DTT_reg_limit'],
1262
-                'DTT_order'     => $row,
1263
-            ];
1264
-            // if we have an id then let's get existing object first and then set the new values.
1265
-            //  Otherwise we instantiate a new object for save.
1266
-            if (! empty($datetime_data['DTT_ID'])) {
1267
-                $datetime = EEM_Datetime::instance($event_timezone)->get_one_by_ID($datetime_data['DTT_ID']);
1268
-                if (! $datetime instanceof EE_Datetime) {
1269
-                    throw new RuntimeException(
1270
-                        sprintf(
1271
-                            esc_html__(
1272
-                                'Something went wrong! A valid Datetime could not be retrieved from the database using the supplied ID: %1$d',
1273
-                                'event_espresso'
1274
-                            ),
1275
-                            $datetime_data['DTT_ID']
1276
-                        )
1277
-                    );
1278
-                }
1279
-                $datetime->set_date_format($date_formats[0]);
1280
-                $datetime->set_time_format($date_formats[1]);
1281
-                foreach ($datetime_values as $field => $value) {
1282
-                    $datetime->set($field, $value);
1283
-                }
1284
-            } else {
1285
-                $datetime = EE_Datetime::new_instance($datetime_values, $event_timezone, $date_formats);
1286
-            }
1287
-            if (! $datetime instanceof EE_Datetime) {
1288
-                throw new RuntimeException(
1289
-                    sprintf(
1290
-                        esc_html__(
1291
-                            'Something went wrong! A valid Datetime could not be generated or retrieved using the supplied data: %1$s',
1292
-                            'event_espresso'
1293
-                        ),
1294
-                        print_r($datetime_values, true)
1295
-                    )
1296
-                );
1297
-            }
1298
-            // before going any further make sure our dates are setup correctly
1299
-            // so that the end date is always equal or greater than the start date.
1300
-            if ($datetime->get_raw('DTT_EVT_start') > $datetime->get_raw('DTT_EVT_end')) {
1301
-                $datetime->set('DTT_EVT_end', $datetime->get('DTT_EVT_start'));
1302
-                $datetime = EEH_DTT_Helper::date_time_add($datetime, 'DTT_EVT_end', 'days');
1303
-            }
1304
-            $datetime->save();
1305
-            $event->_add_relation_to($datetime, 'Datetime');
1306
-        }
1307
-        // no datetimes get deleted so we don't do any of that logic here.
1308
-        // update tickets next
1309
-        $old_tickets = isset($data['ticket_IDs']) ? explode(',', $data['ticket_IDs']) : [];
1310
-
1311
-        // set up some default start and end dates in case those are not present in the incoming data
1312
-        $default_start_date = new DateTime('now', new DateTimeZone($event->get_timezone()));
1313
-        $default_start_date = $default_start_date->format($date_formats[0] . ' ' . $date_formats[1]);
1314
-        // use the start date of the first datetime for the end date
1315
-        $first_datetime   = $event->first_datetime();
1316
-        $default_end_date = $first_datetime->start_date_and_time($date_formats[0], $date_formats[1]);
1317
-
1318
-        // now process the incoming data
1319
-        foreach ($data['edit_tickets'] as $row => $ticket_data) {
1320
-            $update_prices = false;
1321
-            $ticket_price  = $data['edit_prices'][ $row ][1]['PRC_amount'] ?? 0;
1322
-            // trim inputs to ensure any excess whitespace is removed.
1323
-            $ticket_data   = array_map('trim', $ticket_data);
1324
-            $ticket_values = [
1325
-                'TKT_ID'          => ! empty($ticket_data['TKT_ID']) ? $ticket_data['TKT_ID'] : null,
1326
-                'TTM_ID'          => ! empty($ticket_data['TTM_ID']) ? $ticket_data['TTM_ID'] : 0,
1327
-                'TKT_name'        => ! empty($ticket_data['TKT_name']) ? $ticket_data['TKT_name'] : '',
1328
-                'TKT_description' => ! empty($ticket_data['TKT_description']) ? $ticket_data['TKT_description'] : '',
1329
-                'TKT_start_date'  => ! empty($ticket_data['TKT_start_date'])
1330
-                    ? $ticket_data['TKT_start_date']
1331
-                    : $default_start_date,
1332
-                'TKT_end_date'    => ! empty($ticket_data['TKT_end_date'])
1333
-                    ? $ticket_data['TKT_end_date']
1334
-                    : $default_end_date,
1335
-                'TKT_qty'         => ! empty($ticket_data['TKT_qty'])
1336
-                                     || (isset($ticket_data['TKT_qty']) && (int) $ticket_data['TKT_qty'] === 0)
1337
-                    ? $ticket_data['TKT_qty']
1338
-                    : EE_INF,
1339
-                'TKT_uses'        => ! empty($ticket_data['TKT_uses'])
1340
-                                     || (isset($ticket_data['TKT_uses']) && (int) $ticket_data['TKT_uses'] === 0)
1341
-                    ? $ticket_data['TKT_uses']
1342
-                    : EE_INF,
1343
-                'TKT_min'         => ! empty($ticket_data['TKT_min']) ? $ticket_data['TKT_min'] : 0,
1344
-                'TKT_max'         => ! empty($ticket_data['TKT_max']) ? $ticket_data['TKT_max'] : EE_INF,
1345
-                'TKT_order'       => $ticket_data['TKT_order'] ?? $row,
1346
-                'TKT_price'       => (float) $ticket_price,
1347
-                'TKT_row'         => $row,
1348
-            ];
1349
-            // if this is a default ticket, then we need to set the TKT_ID to 0 and update accordingly,
1350
-            // which means in turn that the prices will become new prices as well.
1351
-            if (isset($ticket_data['TKT_is_default']) && $ticket_data['TKT_is_default']) {
1352
-                $ticket_values['TKT_ID']         = 0;
1353
-                $ticket_values['TKT_is_default'] = 0;
1354
-                $update_prices                   = true;
1355
-            }
1356
-            // if we have a TKT_ID then we need to get that existing TKT_obj and update it
1357
-            // we actually do our saves ahead of adding any relations because its entirely possible that this
1358
-            // ticket didn't get removed or added to any datetime in the session but DID have it's items modified.
1359
-            // keep in mind that if the ticket has been sold (and we have changed pricing information),
1360
-            // then we won't be updating the tkt but instead a new tkt will be created and the old one archived.
1361
-            if (! empty($ticket_data['TKT_ID'])) {
1362
-                $existing_ticket = EEM_Ticket::instance($event_timezone)->get_one_by_ID($ticket_data['TKT_ID']);
1363
-                if (! $existing_ticket instanceof EE_Ticket) {
1364
-                    throw new RuntimeException(
1365
-                        sprintf(
1366
-                            esc_html__(
1367
-                                'Something went wrong! A valid Ticket could not be retrieved from the database using the supplied ID: %1$d',
1368
-                                'event_espresso'
1369
-                            ),
1370
-                            $ticket_data['TKT_ID']
1371
-                        )
1372
-                    );
1373
-                }
1374
-                $ticket_sold = $existing_ticket->count_related(
1375
-                    'Registration',
1376
-                    [
1377
-                            [
1378
-                                'STS_ID' => [
1379
-                                    'NOT IN',
1380
-                                    [RegStatus::INCOMPLETE],
1381
-                                ],
1382
-                            ],
1383
-                        ]
1384
-                ) > 0;
1385
-                // let's just check the total price for the existing ticket and determine if it matches the new total price.
1386
-                // if they are different then we create a new ticket (if $ticket_sold)
1387
-                // if they aren't different then we go ahead and modify existing ticket.
1388
-                $create_new_ticket = $ticket_sold
1389
-                                     && EEH_Money::compare_floats($ticket_price, $existing_ticket->price(), '!=')
1390
-                                     && ! $existing_ticket->deleted();
1391
-                $existing_ticket->set_date_format($date_formats[0]);
1392
-                $existing_ticket->set_time_format($date_formats[1]);
1393
-                // set new values
1394
-                foreach ($ticket_values as $field => $value) {
1395
-                    if ($field == 'TKT_qty') {
1396
-                        $existing_ticket->set_qty($value);
1397
-                    } elseif ($field == 'TKT_price') {
1398
-                        $existing_ticket->set('TKT_price', $ticket_price);
1399
-                    } else {
1400
-                        $existing_ticket->set($field, $value);
1401
-                    }
1402
-                }
1403
-                $ticket = $existing_ticket;
1404
-                // if $create_new_ticket is false then we can safely update the existing ticket.
1405
-                //  Otherwise we have to create a new ticket.
1406
-                if ($create_new_ticket) {
1407
-                    // archive the old ticket first
1408
-                    $existing_ticket->set('TKT_deleted', 1);
1409
-                    $existing_ticket->save();
1410
-                    // make sure this ticket is still recorded in our $saved_tickets
1411
-                    // so we don't run it through the regular trash routine.
1412
-                    $saved_tickets[ $existing_ticket->ID() ] = $existing_ticket;
1413
-                    // create new ticket that's a copy of the existing except,
1414
-                    // (a new id of course and not archived) AND has the new TKT_price associated with it.
1415
-                    $new_ticket = clone $existing_ticket;
1416
-                    $new_ticket->set('TKT_ID', 0);
1417
-                    $new_ticket->set('TKT_deleted', 0);
1418
-                    $new_ticket->set('TKT_sold', 0);
1419
-                    // now we need to make sure that $new prices are created as well and attached to new ticket.
1420
-                    $update_prices = true;
1421
-                    $ticket        = $new_ticket;
1422
-                }
1423
-            } else {
1424
-                // no TKT_id so a new ticket
1425
-                $ticket_values['TKT_price'] = $ticket_price;
1426
-                $ticket                     = EE_Ticket::new_instance($ticket_values, $event_timezone, $date_formats);
1427
-                $update_prices              = true;
1428
-            }
1429
-            if (! $ticket instanceof EE_Ticket) {
1430
-                throw new RuntimeException(
1431
-                    sprintf(
1432
-                        esc_html__(
1433
-                            'Something went wrong! A valid Ticket could not be generated or retrieved using the supplied data: %1$s',
1434
-                            'event_espresso'
1435
-                        ),
1436
-                        print_r($ticket_values, true)
1437
-                    )
1438
-                );
1439
-            }
1440
-            // cap ticket qty by datetime reg limits
1441
-            $ticket->set_qty(min($ticket->qty(), $ticket->qty('reg_limit')));
1442
-            // update ticket.
1443
-            $ticket->save();
1444
-            // before going any further make sure our dates are setup correctly
1445
-            // so that the end date is always equal or greater than the start date.
1446
-            if ($ticket->get_raw('TKT_start_date') > $ticket->get_raw('TKT_end_date')) {
1447
-                $ticket->set('TKT_end_date', $ticket->get('TKT_start_date'));
1448
-                $ticket = EEH_DTT_Helper::date_time_add($ticket, 'TKT_end_date', 'days');
1449
-                $ticket->save();
1450
-            }
1451
-            // initially let's add the ticket to the datetime
1452
-            $datetime->_add_relation_to($ticket, 'Ticket');
1453
-            $saved_tickets[ $ticket->ID() ] = $ticket;
1454
-            // add prices to ticket
1455
-            $prices_data = isset($data['edit_prices'][ $row ]) && is_array($data['edit_prices'][ $row ])
1456
-                ? $data['edit_prices'][ $row ]
1457
-                : [];
1458
-            $this->_add_prices_to_ticket($prices_data, $ticket, $update_prices);
1459
-        }
1460
-        // however now we need to handle permanently deleting tickets via the ui.
1461
-        // Keep in mind that the ui does not allow deleting/archiving tickets that have ticket sold.
1462
-        // However, it does allow for deleting tickets that have no tickets sold,
1463
-        // in which case we want to get rid of permanently because there is no need to save in db.
1464
-        $old_tickets     = isset($old_tickets[0]) && $old_tickets[0] === '' ? [] : $old_tickets;
1465
-        $tickets_removed = array_diff($old_tickets, array_keys($saved_tickets));
1466
-        foreach ($tickets_removed as $id) {
1467
-            $id = absint($id);
1468
-            // get the ticket for this id
1469
-            $ticket_to_remove = EEM_Ticket::instance()->get_one_by_ID($id);
1470
-            if (! $ticket_to_remove instanceof EE_Ticket) {
1471
-                continue;
1472
-            }
1473
-            // need to get all the related datetimes on this ticket and remove from every single one of them
1474
-            // (remember this process can ONLY kick off if there are NO tickets sold)
1475
-            $related_datetimes = $ticket_to_remove->get_many_related('Datetime');
1476
-            foreach ($related_datetimes as $related_datetime) {
1477
-                $ticket_to_remove->_remove_relation_to($related_datetime, 'Datetime');
1478
-            }
1479
-            // need to do the same for prices (except these prices can also be deleted because again,
1480
-            // tickets can only be trashed if they don't have any TKTs sold (otherwise they are just archived))
1481
-            $ticket_to_remove->delete_related_permanently('Price');
1482
-            // finally let's delete this ticket
1483
-            // (which should not be blocked at this point b/c we've removed all our relationships)
1484
-            $ticket_to_remove->delete_permanently();
1485
-        }
1486
-        return [$datetime, $saved_tickets];
1487
-    }
1488
-
1489
-
1490
-    /**
1491
-     * This attaches a list of given prices to a ticket.
1492
-     * Note we dont' have to worry about ever removing relationships (or archiving prices)
1493
-     * because if there is a change in price information on a ticket, a new ticket is created anyways
1494
-     * so the archived ticket will retain the old price info and prices are automatically "archived" via the ticket.
1495
-     *
1496
-     * @access  private
1497
-     * @param array     $prices_data Array of prices from the form.
1498
-     * @param EE_Ticket $ticket      EE_Ticket object that prices are being attached to.
1499
-     * @param bool      $new_prices  Whether attach existing incoming prices or create new ones.
1500
-     * @return  void
1501
-     * @throws EE_Error
1502
-     * @throws ReflectionException
1503
-     */
1504
-    private function _add_prices_to_ticket(array $prices_data, EE_Ticket $ticket, bool $new_prices = false)
1505
-    {
1506
-        $timezone = $ticket->get_timezone();
1507
-        foreach ($prices_data as $row => $price_data) {
1508
-            $price_values = [
1509
-                'PRC_ID'         => ! empty($price_data['PRC_ID']) ? $price_data['PRC_ID'] : null,
1510
-                'PRT_ID'         => ! empty($price_data['PRT_ID']) ? $price_data['PRT_ID'] : null,
1511
-                'PRC_amount'     => ! empty($price_data['PRC_amount']) ? $price_data['PRC_amount'] : 0,
1512
-                'PRC_name'       => ! empty($price_data['PRC_name']) ? $price_data['PRC_name'] : '',
1513
-                'PRC_desc'       => ! empty($price_data['PRC_desc']) ? $price_data['PRC_desc'] : '',
1514
-                'PRC_is_default' => 0, // make sure prices are NOT set as default from this context
1515
-                'PRC_order'      => $row,
1516
-            ];
1517
-            if ($new_prices || empty($price_values['PRC_ID'])) {
1518
-                $price_values['PRC_ID'] = 0;
1519
-                $price                  = EE_Price::new_instance($price_values, $timezone);
1520
-            } else {
1521
-                $price = EEM_Price::instance($timezone)->get_one_by_ID($price_data['PRC_ID']);
1522
-                // update this price with new values
1523
-                foreach ($price_values as $field => $new_price) {
1524
-                    $price->set($field, $new_price);
1525
-                }
1526
-            }
1527
-            if (! $price instanceof EE_Price) {
1528
-                throw new RuntimeException(
1529
-                    sprintf(
1530
-                        esc_html__(
1531
-                            'Something went wrong! A valid Price could not be generated or retrieved using the supplied data: %1$s',
1532
-                            'event_espresso'
1533
-                        ),
1534
-                        print_r($price_values, true)
1535
-                    )
1536
-                );
1537
-            }
1538
-            $price->save();
1539
-            $ticket->_add_relation_to($price, 'Price');
1540
-        }
1541
-    }
1542
-
1543
-
1544
-    /**
1545
-     * Add in our autosave ajax handlers
1546
-     */
1547
-    protected function _ee_autosave_create_new()
1548
-    {
1549
-    }
1550
-
1551
-
1552
-    /**
1553
-     * More autosave handlers.
1554
-     */
1555
-    protected function _ee_autosave_edit()
1556
-    {
1557
-    }
1558
-
1559
-
1560
-    /**
1561
-     * @throws EE_Error
1562
-     * @throws ReflectionException
1563
-     */
1564
-    private function _generate_publish_box_extra_content()
1565
-    {
1566
-        // load formatter helper
1567
-        // args for getting related registrations
1568
-        $approved_query_args        = [
1569
-            [
1570
-                'REG_deleted' => 0,
1571
-                'STS_ID'      => RegStatus::APPROVED,
1572
-            ],
1573
-        ];
1574
-        $not_approved_query_args    = [
1575
-            [
1576
-                'REG_deleted' => 0,
1577
-                'STS_ID'      => RegStatus::AWAITING_REVIEW,
1578
-            ],
1579
-        ];
1580
-        $pending_payment_query_args = [
1581
-            [
1582
-                'REG_deleted' => 0,
1583
-                'STS_ID'      => RegStatus::PENDING_PAYMENT,
1584
-            ],
1585
-        ];
1586
-        // publish box
1587
-        $publish_box_extra_args = [
1588
-            'view_approved_reg_url'        => add_query_arg(
1589
-                [
1590
-                    'action'      => 'default',
1591
-                    'event_id'    => $this->_cpt_model_obj->ID(),
1592
-                    '_reg_status' => RegStatus::APPROVED,
1593
-                    'use_filters' => true,
1594
-                ],
1595
-                REG_ADMIN_URL
1596
-            ),
1597
-            'view_not_approved_reg_url'    => add_query_arg(
1598
-                [
1599
-                    'action'      => 'default',
1600
-                    'event_id'    => $this->_cpt_model_obj->ID(),
1601
-                    '_reg_status' => RegStatus::AWAITING_REVIEW,
1602
-                    'use_filters' => true,
1603
-                ],
1604
-                REG_ADMIN_URL
1605
-            ),
1606
-            'view_pending_payment_reg_url' => add_query_arg(
1607
-                [
1608
-                    'action'      => 'default',
1609
-                    'event_id'    => $this->_cpt_model_obj->ID(),
1610
-                    '_reg_status' => RegStatus::PENDING_PAYMENT,
1611
-                    'use_filters' => true,
1612
-                ],
1613
-                REG_ADMIN_URL
1614
-            ),
1615
-            'approved_regs'                => $this->_cpt_model_obj->count_related(
1616
-                'Registration',
1617
-                $approved_query_args
1618
-            ),
1619
-            'not_approved_regs'            => $this->_cpt_model_obj->count_related(
1620
-                'Registration',
1621
-                $not_approved_query_args
1622
-            ),
1623
-            'pending_payment_regs'         => $this->_cpt_model_obj->count_related(
1624
-                'Registration',
1625
-                $pending_payment_query_args
1626
-            ),
1627
-            'misc_pub_section_class'       => apply_filters(
1628
-                'FHEE_Events_Admin_Page___generate_publish_box_extra_content__misc_pub_section_class',
1629
-                'misc-pub-section'
1630
-            ),
1631
-        ];
1632
-        ob_start();
1633
-        do_action(
1634
-            'AHEE__Events_Admin_Page___generate_publish_box_extra_content__event_editor_overview_add',
1635
-            $this->_cpt_model_obj
1636
-        );
1637
-        $publish_box_extra_args['event_editor_overview_add'] = ob_get_clean();
1638
-        // load template
1639
-        EEH_Template::display_template(
1640
-            EVENTS_TEMPLATE_PATH . 'event_publish_box_extras.template.php',
1641
-            $publish_box_extra_args
1642
-        );
1643
-    }
1644
-
1645
-
1646
-    /**
1647
-     * @return EE_Event
1648
-     */
1649
-    public function get_event_object()
1650
-    {
1651
-        return $this->_cpt_model_obj;
1652
-    }
1653
-
1654
-
1655
-
1656
-
1657
-    /** METABOXES * */
1658
-    /**
1659
-     * _register_event_editor_meta_boxes
1660
-     * add all metaboxes related to the event_editor
1661
-     *
1662
-     * @return void
1663
-     * @throws EE_Error
1664
-     * @throws ReflectionException
1665
-     */
1666
-    protected function _register_event_editor_meta_boxes()
1667
-    {
1668
-        $this->verify_cpt_object();
1669
-        $use_advanced_editor = $this->admin_config->useAdvancedEditor();
1670
-        // check if the new EDTR reg options meta box is being used, and if so, don't load the legacy version
1671
-        if (! $use_advanced_editor || ! $this->feature->allowed('use_reg_options_meta_box')) {
1672
-            $this->addMetaBox(
1673
-                'espresso_event_editor_event_options',
1674
-                esc_html__('Event Registration Options', 'event_espresso'),
1675
-                [$this, 'registration_options_meta_box'],
1676
-                $this->page_slug,
1677
-                'side'
1678
-            );
1679
-        }
1680
-        if (! $use_advanced_editor) {
1681
-            $this->addMetaBox(
1682
-                'espresso_event_editor_tickets',
1683
-                esc_html__('Event Datetime & Ticket', 'event_espresso'),
1684
-                [$this, 'ticket_metabox'],
1685
-                $this->page_slug,
1686
-                'normal',
1687
-                'high'
1688
-            );
1689
-        } elseif ($this->feature->allowed('use_reg_options_meta_box')) {
1690
-            add_action(
1691
-                'add_meta_boxes_espresso_events',
1692
-                function () {
1693
-                    global $current_screen;
1694
-                    remove_meta_box('authordiv', $current_screen, 'normal');
1695
-                },
1696
-                99
1697
-            );
1698
-        }
1699
-        // NOTE: if you're looking for other metaboxes in here,
1700
-        // where a metabox has a related management page in the admin
1701
-        // you will find it setup in the related management page's "_Hooks" file.
1702
-        // i.e. messages metabox is found in "espresso_events_Messages_Hooks.class.php".
1703
-    }
1704
-
1705
-
1706
-    /**
1707
-     * @throws DomainException
1708
-     * @throws EE_Error
1709
-     * @throws ReflectionException
1710
-     */
1711
-    public function ticket_metabox()
1712
-    {
1713
-        $existing_datetime_ids = $existing_ticket_ids = [];
1714
-        // defaults for template args
1715
-        $template_args = [
1716
-            'ticket_rows'       => '',
1717
-            'total_ticket_rows' => 1,
1718
-            'trash_icon'        => 'dashicons dashicons-lock',
1719
-            'disabled'          => '',
1720
-        ];
1721
-        $event_id      = is_object($this->_cpt_model_obj) ? $this->_cpt_model_obj->ID() : null;
1722
-        /**
1723
-         * 1. Start with retrieving Datetimes
1724
-         * 2. Fore each datetime get related tickets
1725
-         * 3. For each ticket get related prices
1726
-         */
1727
-        /** @var EEM_Datetime $datetime_model */
1728
-        $datetime_model = EE_Registry::instance()->load_model('Datetime');
1729
-        /** @var EEM_Ticket $datetime_model */
1730
-        $ticket_model = EE_Registry::instance()->load_model('Ticket');
1731
-        $times        = $datetime_model->get_all_event_dates($event_id);
1732
-        /** @type EE_Datetime $first_datetime */
1733
-        $first_datetime = reset($times);
1734
-        // do we get related tickets?
1735
-        if (
1736
-            $first_datetime instanceof EE_Datetime
1737
-            && $first_datetime->ID() !== 0
1738
-        ) {
1739
-            $existing_datetime_ids[] = $first_datetime->get('DTT_ID');
1740
-            $template_args['time']   = $first_datetime;
1741
-            $related_tickets         = $first_datetime->tickets(
1742
-                [
1743
-                    ['OR' => ['TKT_deleted' => 1, 'TKT_deleted*' => 0]],
1744
-                    'default_where_conditions' => 'none',
1745
-                ]
1746
-            );
1747
-            if (! empty($related_tickets)) {
1748
-                $template_args['total_ticket_rows'] = count($related_tickets);
1749
-                $row                                = 0;
1750
-                foreach ($related_tickets as $ticket) {
1751
-                    $existing_ticket_ids[]        = $ticket->get('TKT_ID');
1752
-                    $template_args['ticket_rows'] .= $this->_get_ticket_row($ticket, false, $row);
1753
-                    $row++;
1754
-                }
1755
-            } else {
1756
-                $template_args['total_ticket_rows'] = 1;
1757
-                /** @type EE_Ticket $ticket */
1758
-                $ticket                       = $ticket_model->create_default_object();
1759
-                $template_args['ticket_rows'] .= $this->_get_ticket_row($ticket);
1760
-            }
1761
-        } else {
1762
-            $template_args['time'] = $times[0];
1763
-            /** @type EE_Ticket[] $tickets */
1764
-            $tickets                      = $ticket_model->get_all_default_tickets();
1765
-            $template_args['ticket_rows'] .= $this->_get_ticket_row($tickets[1]);
1766
-            // NOTE: we're just sending the first default row
1767
-            // (decaf can't manage default tickets so this should be sufficient);
1768
-        }
1769
-        $template_args['event_datetime_help_link'] = $this->_get_help_tab_link(
1770
-            'event_editor_event_datetimes_help_tab'
1771
-        );
1772
-        $template_args['ticket_options_help_link'] = $this->_get_help_tab_link('ticket_options_info');
1773
-        $template_args['existing_datetime_ids']    = implode(',', $existing_datetime_ids);
1774
-        $template_args['existing_ticket_ids']      = implode(',', $existing_ticket_ids);
1775
-        $template_args['ticket_js_structure']      = $this->_get_ticket_row(
1776
-            $ticket_model->create_default_object(),
1777
-            true
1778
-        );
1779
-        $template                                  = apply_filters(
1780
-            'FHEE__Events_Admin_Page__ticket_metabox__template',
1781
-            EVENTS_TEMPLATE_PATH . 'event_tickets_metabox_main.template.php'
1782
-        );
1783
-        EEH_Template::display_template($template, $template_args);
1784
-    }
1785
-
1786
-
1787
-    /**
1788
-     * Setup an individual ticket form for the decaf event editor page
1789
-     *
1790
-     * @access private
1791
-     * @param EE_Ticket $ticket   the ticket object
1792
-     * @param boolean   $skeleton whether we're generating a skeleton for js manipulation
1793
-     * @param int       $row
1794
-     * @return string generated html for the ticket row.
1795
-     * @throws EE_Error
1796
-     * @throws ReflectionException
1797
-     */
1798
-    private function _get_ticket_row(EE_Ticket $ticket, bool $skeleton = false, int $row = 0): string
1799
-    {
1800
-        $template_args = [
1801
-            'tkt_status_class'    => ' tkt-status-' . $ticket->ticket_status(),
1802
-            'tkt_archive_class'   => $ticket->ticket_status() === EE_Ticket::archived && ! $skeleton
1803
-                ? ' tkt-archived'
1804
-                : '',
1805
-            'ticketrow'           => $skeleton ? 'TICKETNUM' : $row,
1806
-            'TKT_ID'              => $ticket->get('TKT_ID'),
1807
-            'TKT_name'            => $ticket->get('TKT_name'),
1808
-            'TKT_start_date'      => $skeleton ? '' : $ticket->get_date('TKT_start_date', 'Y-m-d h:i a'),
1809
-            'TKT_end_date'        => $skeleton ? '' : $ticket->get_date('TKT_end_date', 'Y-m-d h:i a'),
1810
-            'TKT_is_default'      => $ticket->get('TKT_is_default'),
1811
-            'TKT_qty'             => $ticket->get_pretty('TKT_qty', 'input'),
1812
-            'edit_ticketrow_name' => $skeleton ? 'TICKETNAMEATTR' : 'edit_tickets',
1813
-            'TKT_sold'            => $skeleton ? 0 : $ticket->get('TKT_sold'),
1814
-            'trash_icon'          => ($skeleton || (! $ticket->get('TKT_deleted')))
1815
-                                     && (! empty($ticket) && $ticket->get('TKT_sold') === 0)
1816
-                ? 'dashicons dashicons-post-trash clickable'
1817
-                : 'dashicons dashicons-lock entity-locked',
1818
-            'disabled'            => $skeleton || (! empty($ticket) && ! $ticket->get('TKT_deleted')) ? ''
1819
-                : ' disabled=disabled',
1820
-        ];
1821
-
1822
-        $price         = $ticket->ID() !== 0
1823
-            ? $ticket->get_first_related('Price', ['default_where_conditions' => 'none'])
1824
-            : null;
1825
-        $price         = $price instanceof EE_Price
1826
-            ? $price
1827
-            : EEM_Price::instance()->create_default_object();
1828
-        $price_args    = [
1829
-            'price_currency_symbol' => EE_Registry::instance()->CFG->currency->sign,
1830
-            'PRC_amount'            => $price->get('PRC_amount'),
1831
-            'PRT_ID'                => $price->get('PRT_ID'),
1832
-            'PRC_ID'                => $price->get('PRC_ID'),
1833
-            'PRC_is_default'        => $price->get('PRC_is_default'),
1834
-        ];
1835
-        // make sure we have default start and end dates if skeleton
1836
-        // handle rows that should NOT be empty
1837
-        if (empty($template_args['TKT_start_date'])) {
1838
-            // if empty then the start date will be now.
1839
-            $template_args['TKT_start_date'] = date('Y-m-d h:i a', current_time('timestamp'));
1840
-        }
1841
-        if (empty($template_args['TKT_end_date'])) {
1842
-            // get the earliest datetime (if present);
1843
-            $earliest_datetime             = $this->_cpt_model_obj->ID() > 0
1844
-                ? $this->_cpt_model_obj->get_first_related(
1845
-                    'Datetime',
1846
-                    ['order_by' => ['DTT_EVT_start' => 'ASC']]
1847
-                )
1848
-                : null;
1849
-            $template_args['TKT_end_date'] = $earliest_datetime instanceof EE_Datetime
1850
-                ? $earliest_datetime->get_datetime('DTT_EVT_start', 'Y-m-d', 'h:i a')
1851
-                : date('Y-m-d h:i a', mktime(0, 0, 0, date('m'), date('d') + 7, date('Y')));
1852
-        }
1853
-        $template_args = array_merge($template_args, $price_args);
1854
-        $template      = apply_filters(
1855
-            'FHEE__Events_Admin_Page__get_ticket_row__template',
1856
-            EVENTS_TEMPLATE_PATH . 'event_tickets_metabox_ticket_row.template.php',
1857
-            $ticket
1858
-        );
1859
-        return EEH_Template::display_template($template, $template_args, true);
1860
-    }
1861
-
1862
-
1863
-    /**
1864
-     * @throws EE_Error
1865
-     * @throws ReflectionException
1866
-     */
1867
-    public function registration_options_meta_box()
1868
-    {
1869
-        $yes_no_values             = [
1870
-            ['id' => true, 'text' => esc_html__('Yes', 'event_espresso')],
1871
-            ['id' => false, 'text' => esc_html__('No', 'event_espresso')],
1872
-        ];
1873
-        $default_reg_status_values = EEM_Registration::reg_status_array(
1874
-            [
1875
-                RegStatus::CANCELLED,
1876
-                RegStatus::DECLINED,
1877
-                RegStatus::INCOMPLETE,
1878
-            ],
1879
-            true
1880
-        );
1881
-        // $template_args['is_active_select'] = EEH_Form_Fields::select_input('is_active', $yes_no_values, $this->_cpt_model_obj->is_active());
1882
-        $template_args['_event']                          = $this->_cpt_model_obj;
1883
-        $template_args['event']                           = $this->_cpt_model_obj;
1884
-        $template_args['active_status']                   = $this->_cpt_model_obj->pretty_active_status(false);
1885
-        $template_args['additional_limit']                = $this->_cpt_model_obj->additional_limit();
1886
-        $template_args['default_registration_status']     = EEH_Form_Fields::select_input(
1887
-            'default_reg_status',
1888
-            $default_reg_status_values,
1889
-            $this->_cpt_model_obj->default_registration_status(),
1890
-            '',
1891
-            'ee-input-width--reg',
1892
-            false
1893
-        );
1894
-        $template_args['display_description']             = EEH_Form_Fields::select_input(
1895
-            'display_desc',
1896
-            $yes_no_values,
1897
-            $this->_cpt_model_obj->display_description()
1898
-        );
1899
-        $template_args['display_ticket_selector']         = EEH_Form_Fields::select_input(
1900
-            'display_ticket_selector',
1901
-            $yes_no_values,
1902
-            $this->_cpt_model_obj->display_ticket_selector(),
1903
-            '',
1904
-            'ee-input-width--small',
1905
-            false
1906
-        );
1907
-        $template_args['additional_registration_options'] = apply_filters(
1908
-            'FHEE__Events_Admin_Page__registration_options_meta_box__additional_registration_options',
1909
-            '',
1910
-            $template_args,
1911
-            $yes_no_values,
1912
-            $default_reg_status_values
1913
-        );
1914
-        EEH_Template::display_template(
1915
-            EVENTS_TEMPLATE_PATH . 'event_registration_options.template.php',
1916
-            $template_args
1917
-        );
1918
-    }
1919
-
1920
-
1921
-    /**
1922
-     * _get_events()
1923
-     * This method simply returns all the events (for the given _view and paging)
1924
-     *
1925
-     * @access public
1926
-     * @param int  $per_page     count of items per page (20 default);
1927
-     * @param int  $current_page what is the current page being viewed.
1928
-     * @param bool $count        if TRUE then we just return a count of ALL events matching the given _view.
1929
-     *                           If FALSE then we return an array of event objects
1930
-     *                           that match the given _view and paging parameters.
1931
-     * @return array|int         an array of event objects or a count of them.
1932
-     * @throws Exception
1933
-     */
1934
-    public function get_events(int $per_page = 10, int $current_page = 1, bool $count = false)
1935
-    {
1936
-        $EEM_Event   = $this->_event_model();
1937
-        $offset      = ($current_page - 1) * $per_page;
1938
-        $limit       = $count ? null : $offset . ',' . $per_page;
1939
-        $orderby     = $this->request->getRequestParam('orderby', 'EVT_ID');
1940
-        $order       = $this->request->getRequestParam('order', 'DESC');
1941
-        $month_range = $this->request->getRequestParam('month_range');
1942
-        $where  = [];
1943
-        $status = $this->request->getRequestParam('status');
1944
-        $timezone_string = EEH_DTT_Helper::get_valid_timezone_string();
1945
-        // determine what post_status our condition will have for the query.
1946
-        switch ($status) {
1947
-            case 'month':
1948
-            case 'today':
1949
-            case null:
1950
-            case 'all':
1951
-                break;
1952
-            case 'draft':
1953
-                $where['status'] = ['IN', ['draft', 'auto-draft']];
1954
-                break;
1955
-            default:
1956
-                $where['status'] = $status;
1957
-        }
1958
-        // categories? The default for all categories is -1
1959
-        $category = $this->request->getRequestParam('EVT_CAT', -1, DataType::INT);
1960
-        if ($category !== -1) {
1961
-            $where['Term_Taxonomy.taxonomy'] = EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY;
1962
-            $where['Term_Taxonomy.term_id']  = $category;
1963
-        }
1964
-        // date where conditions
1965
-        $start_formats = EEM_Datetime::instance()->get_formats_for('DTT_EVT_start');
1966
-        if ($month_range) {
1967
-            $where['Datetime.DTT_EVT_start'] = $this->whereParamsForDatetimeMonthRange($month_range, $timezone_string);
1968
-        } elseif ($status === 'today') {
1969
-            $DateTime                        = new DateTime(
1970
-                'now',
1971
-                new DateTimeZone($timezone_string)
1972
-            );
1973
-            $start                           = $DateTime->setTime(0, 0)->format(implode(' ', $start_formats));
1974
-            $end                             = $DateTime->setTime(23, 59, 59)->format(implode(' ', $start_formats));
1975
-            $where['Datetime.DTT_EVT_start'] = ['BETWEEN', [$start, $end]];
1976
-        } elseif ($status === 'month') {
1977
-            $now                             = date('Y-m-01');
1978
-            $DateTime                        = new DateTime(
1979
-                $now,
1980
-                new DateTimeZone($timezone_string)
1981
-            );
1982
-            $start                           = $DateTime->setTime(0, 0)->format(implode(' ', $start_formats));
1983
-            $end                             = $DateTime->setDate(date('Y'), date('m'), $DateTime->format('t'))
1984
-                                                        ->setTime(23, 59, 59)
1985
-                                                        ->format(implode(' ', $start_formats));
1986
-            $where['Datetime.DTT_EVT_start'] = ['BETWEEN', [$start, $end]];
1987
-        }
1988
-        if (! $this->capabilities->current_user_can('ee_read_others_events', 'get_events')) {
1989
-            $where['EVT_wp_user'] = get_current_user_id();
1990
-        } else {
1991
-            if (! isset($where['status'])) {
1992
-                if (! $this->capabilities->current_user_can('ee_read_private_events', 'get_events')) {
1993
-                    $where['OR'] = [
1994
-                        'status*restrict_private' => ['!=', 'private'],
1995
-                        'AND'                     => [
1996
-                            'status*inclusive' => ['=', 'private'],
1997
-                            'EVT_wp_user'      => get_current_user_id(),
1998
-                        ],
1999
-                    ];
2000
-                }
2001
-            }
2002
-        }
2003
-        $wp_user = $this->request->getRequestParam('EVT_wp_user', 0, DataType::INT);
2004
-        if (
2005
-            $wp_user
2006
-            && $wp_user !== get_current_user_id()
2007
-            && $this->capabilities->current_user_can('ee_read_others_events', 'get_events')
2008
-        ) {
2009
-            $where['EVT_wp_user'] = $wp_user;
2010
-        }
2011
-        // search query handling
2012
-        $search_term = $this->request->getRequestParam('s');
2013
-        if ($search_term) {
2014
-            $search_term = '%' . $search_term . '%';
2015
-            $where['OR'] = [
2016
-                'EVT_name'       => ['LIKE', $search_term],
2017
-                'EVT_desc'       => ['LIKE', $search_term],
2018
-                'EVT_short_desc' => ['LIKE', $search_term],
2019
-            ];
2020
-        }
2021
-        // filter events by venue.
2022
-        $venue = $this->request->getRequestParam('venue', 0, DataType::INT);
2023
-        if ($venue) {
2024
-            $where['Venue.VNU_ID'] = $venue;
2025
-        }
2026
-        $request_params = $this->request->requestParams();
2027
-        $where          = apply_filters('FHEE__Events_Admin_Page__get_events__where', $where, $request_params);
2028
-        $query_params   = apply_filters(
2029
-            'FHEE__Events_Admin_Page__get_events__query_params',
2030
-            [
2031
-                $where,
2032
-                'limit'    => $limit,
2033
-                'order_by' => $orderby,
2034
-                'order'    => $order,
2035
-                'group_by' => 'EVT_ID',
2036
-            ],
2037
-            $request_params
2038
-        );
2039
-
2040
-        // let's first check if we have special requests coming in.
2041
-        $active_status = $this->request->getRequestParam('active_status');
2042
-        if ($active_status) {
2043
-            switch ($active_status) {
2044
-                case 'upcoming':
2045
-                    return $EEM_Event->get_upcoming_events($query_params, $count);
2046
-                case 'expired':
2047
-                    return $EEM_Event->get_expired_events($query_params, $count);
2048
-                case 'active':
2049
-                    return $EEM_Event->get_active_events($query_params, $count);
2050
-                case 'inactive':
2051
-                    return $EEM_Event->get_inactive_events($query_params, $count);
2052
-            }
2053
-        }
2054
-
2055
-        return $count ? $EEM_Event->count([$where], 'EVT_ID', true) : $EEM_Event->get_all($query_params);
2056
-    }
2057
-
2058
-
2059
-    /**
2060
-     * @param string $month_range
2061
-     * @param string $timezone_string
2062
-     * @return array
2063
-     * @throws Exception
2064
-     * @since 5.0.21.p
2065
-     */
2066
-    public function whereParamsForDatetimeMonthRange(string $month_range, string $timezone_string = ''): array
2067
-    {
2068
-        $timezone_string = $timezone_string ?: EEH_DTT_Helper::get_valid_timezone_string();
2069
-        $pieces = explode(' ', $month_range, 3);
2070
-        // simulate the FIRST day of the month, that fixes issues for months like February
2071
-        // where PHP doesn't know what to assume for date.
2072
-        // @see https://events.codebasehq.com/projects/event-espresso/tickets/10437
2073
-        $month_r = ! empty($pieces[0]) ? date('m', EEH_DTT_Helper::first_of_month_timestamp($pieces[0])) : '';
2074
-        $year_r  = ! empty($pieces[1]) ? $pieces[1] : '';
2075
-        $DateTime = new DateTime(
2076
-            "$year_r-$month_r-01 00:00:00",
2077
-            new DateTimeZone($timezone_string)
2078
-        );
2079
-        $start    = $DateTime->getTimestamp();
2080
-        // set the datetime to be the end of the month
2081
-        $DateTime->setDate(
2082
-            $year_r,
2083
-            $month_r,
2084
-            $DateTime->format('t')
2085
-        )->setTime(23, 59, 59);
2086
-        $end                             = $DateTime->getTimestamp();
2087
-        return ['BETWEEN', [$start, $end]];
2088
-    }
2089
-
2090
-
2091
-    /**
2092
-     * handling for WordPress CPT actions (trash, restore, delete)
2093
-     *
2094
-     * @param string $post_id
2095
-     * @throws EE_Error
2096
-     * @throws ReflectionException
2097
-     */
2098
-    public function trash_cpt_item($post_id)
2099
-    {
2100
-        $this->request->setRequestParam('EVT_ID', $post_id);
2101
-        $this->_trash_or_restore_event('trash', false);
2102
-    }
2103
-
2104
-
2105
-    /**
2106
-     * @param string $post_id
2107
-     * @throws EE_Error
2108
-     * @throws ReflectionException
2109
-     */
2110
-    public function restore_cpt_item($post_id)
2111
-    {
2112
-        $this->request->setRequestParam('EVT_ID', $post_id);
2113
-        $this->_trash_or_restore_event('draft', false);
2114
-    }
2115
-
2116
-
2117
-    /**
2118
-     * @param string $post_id
2119
-     * @throws EE_Error
2120
-     * @throws EE_Error
2121
-     */
2122
-    public function delete_cpt_item($post_id)
2123
-    {
2124
-        throw new EE_Error(
2125
-            esc_html__(
2126
-                'Please contact Event Espresso support with the details of the steps taken to produce this error.',
2127
-                'event_espresso'
2128
-            )
2129
-        );
2130
-        // $this->request->setRequestParam('EVT_ID', $post_id);
2131
-        // $this->_delete_event();
2132
-    }
2133
-
2134
-
2135
-    /**
2136
-     * _trash_or_restore_event
2137
-     *
2138
-     * @access protected
2139
-     * @param string $event_status
2140
-     * @param bool   $redirect_after
2141
-     * @throws EE_Error
2142
-     * @throws EE_Error
2143
-     * @throws ReflectionException
2144
-     */
2145
-    protected function _trash_or_restore_event(string $event_status = 'trash', bool $redirect_after = true)
2146
-    {
2147
-        // loop thru events
2148
-        if ($this->EVT_ID) {
2149
-            // clean status
2150
-            $event_status = sanitize_key($event_status);
2151
-            // grab status
2152
-            if (! empty($event_status)) {
2153
-                $success = $this->_change_event_status($this->EVT_ID, $event_status);
2154
-            } else {
2155
-                $success = false;
2156
-                $msg     = esc_html__(
2157
-                    'An error occurred. The event could not be moved to the trash because a valid event status was not not supplied.',
2158
-                    'event_espresso'
2159
-                );
2160
-                EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2161
-            }
2162
-        } else {
2163
-            $success = false;
2164
-            $msg     = esc_html__(
2165
-                'An error occurred. The event could not be moved to the trash because a valid event ID was not not supplied.',
2166
-                'event_espresso'
2167
-            );
2168
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2169
-        }
2170
-        $action = $event_status === 'trash' ? 'moved to the trash' : 'restored from the trash';
2171
-        if ($redirect_after) {
2172
-            $this->_redirect_after_action($success, 'Event', $action, ['action' => 'default']);
2173
-        }
2174
-    }
2175
-
2176
-
2177
-    /**
2178
-     * _trash_or_restore_events
2179
-     *
2180
-     * @access protected
2181
-     * @param string $event_status
2182
-     * @return void
2183
-     * @throws EE_Error
2184
-     * @throws EE_Error
2185
-     * @throws ReflectionException
2186
-     */
2187
-    protected function _trash_or_restore_events(string $event_status = 'trash')
2188
-    {
2189
-        // clean status
2190
-        $event_status = sanitize_key($event_status);
2191
-        // grab status
2192
-        if (! empty($event_status)) {
2193
-            $success = true;
2194
-            // determine the event id and set to array.
2195
-            $EVT_IDs = $this->request->getRequestParam('EVT_IDs', [], 'int', true);
2196
-            // loop thru events
2197
-            foreach ($EVT_IDs as $EVT_ID) {
2198
-                if ($EVT_ID = absint($EVT_ID)) {
2199
-                    $results = $this->_change_event_status($EVT_ID, $event_status);
2200
-                    $success = $results !== false ? $success : false;
2201
-                } else {
2202
-                    $msg = sprintf(
2203
-                        esc_html__(
2204
-                            'An error occurred. Event #%d could not be moved to the trash because a valid event ID was not not supplied.',
2205
-                            'event_espresso'
2206
-                        ),
2207
-                        $EVT_ID
2208
-                    );
2209
-                    EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2210
-                    $success = false;
2211
-                }
2212
-            }
2213
-        } else {
2214
-            $success = false;
2215
-            $msg     = esc_html__(
2216
-                'An error occurred. The event could not be moved to the trash because a valid event status was not not supplied.',
2217
-                'event_espresso'
2218
-            );
2219
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2220
-        }
2221
-        // in order to force a pluralized result message we need to send back a success status greater than 1
2222
-        $success = $success ? 2 : false;
2223
-        $action  = $event_status === 'trash' ? 'moved to the trash' : 'restored from the trash';
2224
-        $this->_redirect_after_action($success, 'Events', $action, ['action' => 'default']);
2225
-    }
2226
-
2227
-
2228
-    /**
2229
-     * @param int    $EVT_ID
2230
-     * @param string $event_status
2231
-     * @return bool
2232
-     * @throws EE_Error
2233
-     * @throws ReflectionException
2234
-     */
2235
-    private function _change_event_status(int $EVT_ID = 0, string $event_status = ''): bool
2236
-    {
2237
-        // grab event id
2238
-        if (! $EVT_ID) {
2239
-            $msg = esc_html__(
2240
-                'An error occurred. No Event ID or an invalid Event ID was received.',
2241
-                'event_espresso'
2242
-            );
2243
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2244
-            return false;
2245
-        }
2246
-        $this->_cpt_model_obj = EEM_Event::instance()->get_one_by_ID($EVT_ID);
2247
-        // clean status
2248
-        $event_status = sanitize_key($event_status);
2249
-        // grab status
2250
-        if (empty($event_status)) {
2251
-            $msg = esc_html__(
2252
-                'An error occurred. No Event Status or an invalid Event Status was received.',
2253
-                'event_espresso'
2254
-            );
2255
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2256
-            return false;
2257
-        }
2258
-        // was event trashed or restored ?
2259
-        switch ($event_status) {
2260
-            case 'draft':
2261
-                $action = 'restored from the trash';
2262
-                $hook   = 'AHEE_event_restored_from_trash';
2263
-                break;
2264
-            case 'trash':
2265
-                $action = 'moved to the trash';
2266
-                $hook   = 'AHEE_event_moved_to_trash';
2267
-                break;
2268
-            default:
2269
-                $action = 'updated';
2270
-                $hook   = false;
2271
-        }
2272
-        // use class to change status
2273
-        $this->_cpt_model_obj->set_status($event_status);
2274
-        $success = $this->_cpt_model_obj->save();
2275
-        if (! $success) {
2276
-            $msg = sprintf(esc_html__('An error occurred. The event could not be %s.', 'event_espresso'), $action);
2277
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2278
-            return false;
2279
-        }
2280
-        if ($hook) {
2281
-            do_action($hook);
2282
-            // fake the action hook in EE_Soft_Delete_Base_Class::delete_or_restore()
2283
-            // because events side step that and it otherwise won't get called
2284
-            do_action(
2285
-                'AHEE__EE_Soft_Delete_Base_Class__delete_or_restore__after',
2286
-                $this->_cpt_model_obj,
2287
-                $hook === 'AHEE_event_moved_to_trash',
2288
-                $success
2289
-            );
2290
-        }
2291
-        return true;
2292
-    }
2293
-
2294
-
2295
-    /**
2296
-     * @param array $event_ids
2297
-     * @return array
2298
-     * @since   4.10.23.p
2299
-     */
2300
-    private function cleanEventIds(array $event_ids): array
2301
-    {
2302
-        return array_map('absint', $event_ids);
2303
-    }
2304
-
2305
-
2306
-    /**
2307
-     * @return array
2308
-     * @since   4.10.23.p
2309
-     */
2310
-    private function getEventIdsFromRequest(): array
2311
-    {
2312
-        if ($this->request->requestParamIsSet('EVT_IDs')) {
2313
-            return $this->request->getRequestParam('EVT_IDs', [], 'int', true);
2314
-        } else {
2315
-            return $this->request->getRequestParam('EVT_ID', [], 'int', true);
2316
-        }
2317
-    }
2318
-
2319
-
2320
-    /**
2321
-     * @param bool $preview_delete
2322
-     * @throws EE_Error
2323
-     * @throws ReflectionException
2324
-     */
2325
-    protected function _delete_event(bool $preview_delete = true)
2326
-    {
2327
-        $this->_delete_events($preview_delete);
2328
-    }
2329
-
2330
-
2331
-    /**
2332
-     * Gets the tree traversal batch persister.
2333
-     *
2334
-     * @return NodeGroupDao
2335
-     * @throws InvalidArgumentException
2336
-     * @throws InvalidDataTypeException
2337
-     * @throws InvalidInterfaceException
2338
-     * @since 4.10.12.p
2339
-     */
2340
-    protected function getModelObjNodeGroupPersister(): NodeGroupDao
2341
-    {
2342
-        if (! $this->model_obj_node_group_persister instanceof NodeGroupDao) {
2343
-            $this->model_obj_node_group_persister =
2344
-                $this->getLoader()->load('\EventEspresso\core\services\orm\tree_traversal\NodeGroupDao');
2345
-        }
2346
-        return $this->model_obj_node_group_persister;
2347
-    }
2348
-
2349
-
2350
-    /**
2351
-     * @param bool $preview_delete
2352
-     * @return void
2353
-     * @throws EE_Error
2354
-     * @throws ReflectionException
2355
-     */
2356
-    protected function _delete_events(bool $preview_delete = true)
2357
-    {
2358
-        $event_ids = $this->getEventIdsFromRequest();
2359
-        if ($preview_delete) {
2360
-            $this->generateDeletionPreview($event_ids);
2361
-        } else {
2362
-            foreach ($event_ids as $event_id) {
2363
-                $event = EEM_Event::instance()->get_one_by_ID($event_id);
2364
-                if ($event instanceof EE_Event) {
2365
-                    $event->delete_permanently();
2366
-                }
2367
-            }
2368
-        }
2369
-    }
2370
-
2371
-
2372
-    /**
2373
-     * @param array $event_ids
2374
-     */
2375
-    protected function generateDeletionPreview(array $event_ids)
2376
-    {
2377
-        $event_ids = $this->cleanEventIds($event_ids);
2378
-        // Set a code we can use to reference this deletion task in the batch jobs and preview page.
2379
-        $deletion_job_code = $this->getModelObjNodeGroupPersister()->generateGroupCode();
2380
-        $return_url        = EE_Admin_Page::add_query_args_and_nonce(
2381
-            [
2382
-                'action'            => 'preview_deletion',
2383
-                'deletion_job_code' => $deletion_job_code,
2384
-            ],
2385
-            $this->_admin_base_url
2386
-        );
2387
-        EEH_URL::safeRedirectAndExit(
2388
-            EE_Admin_Page::add_query_args_and_nonce(
2389
-                [
2390
-                    'page'              => EED_Batch::PAGE_SLUG,
2391
-                    'batch'             => EED_Batch::batch_job,
2392
-                    'EVT_IDs'           => $event_ids,
2393
-                    'deletion_job_code' => $deletion_job_code,
2394
-                    'job_handler'       => urlencode('EventEspresso\core\libraries\batch\JobHandlers\PreviewEventDeletion'),
2395
-                    'return_url'        => urlencode($return_url),
2396
-                ],
2397
-                admin_url()
2398
-            )
2399
-        );
2400
-    }
2401
-
2402
-
2403
-    /**
2404
-     * Checks for a POST submission
2405
-     *
2406
-     * @since 4.10.12.p
2407
-     */
2408
-    protected function confirmDeletion()
2409
-    {
2410
-        $deletion_redirect_logic = $this->getLoader()->getShared(
2411
-            'EventEspresso\core\domain\services\admin\events\data\ConfirmDeletion'
2412
-        );
2413
-        $deletion_redirect_logic->handle($this->get_request_data(), $this->admin_base_url());
2414
-    }
2415
-
2416
-
2417
-    /**
2418
-     * A page for users to preview what exactly will be deleted, and confirm they want to delete it.
2419
-     *
2420
-     * @throws EE_Error
2421
-     * @since 4.10.12.p
2422
-     */
2423
-    protected function previewDeletion()
2424
-    {
2425
-        $preview_deletion_logic = $this->getLoader()->getShared(
2426
-            'EventEspresso\core\domain\services\admin\events\data\PreviewDeletion'
2427
-        );
2428
-        $this->set_template_args($preview_deletion_logic->handle($this->get_request_data(), $this->admin_base_url()));
2429
-        $this->display_admin_page_with_no_sidebar();
2430
-    }
2431
-
2432
-
2433
-    /**
2434
-     * get total number of events
2435
-     *
2436
-     * @access public
2437
-     * @return int
2438
-     * @throws EE_Error
2439
-     * @throws EE_Error
2440
-     * @throws ReflectionException
2441
-     */
2442
-    public function total_events(): int
2443
-    {
2444
-        return EEM_Event::instance()->count(
2445
-            ['caps' => 'read_admin'],
2446
-            'EVT_ID',
2447
-            true
2448
-        );
2449
-    }
2450
-
2451
-
2452
-    /**
2453
-     * get total number of draft events
2454
-     *
2455
-     * @access public
2456
-     * @return int
2457
-     * @throws EE_Error
2458
-     * @throws EE_Error
2459
-     * @throws ReflectionException
2460
-     */
2461
-    public function total_events_draft(): int
2462
-    {
2463
-        return EEM_Event::instance()->count(
2464
-            [
2465
-                ['status' => ['IN', ['draft', 'auto-draft']]],
2466
-                'caps' => 'read_admin',
2467
-            ],
2468
-            'EVT_ID',
2469
-            true
2470
-        );
2471
-    }
2472
-
2473
-
2474
-    /**
2475
-     * get total number of trashed events
2476
-     *
2477
-     * @access public
2478
-     * @return int
2479
-     * @throws EE_Error
2480
-     * @throws EE_Error
2481
-     * @throws ReflectionException
2482
-     */
2483
-    public function total_trashed_events(): int
2484
-    {
2485
-        return EEM_Event::instance()->count(
2486
-            [
2487
-                ['status' => 'trash'],
2488
-                'caps' => 'read_admin',
2489
-            ],
2490
-            'EVT_ID',
2491
-            true
2492
-        );
2493
-    }
2494
-
2495
-
2496
-    /**
2497
-     *    _default_event_settings
2498
-     *    This generates the Default Settings Tab
2499
-     *
2500
-     * @return void
2501
-     * @throws DomainException
2502
-     * @throws EE_Error
2503
-     * @throws InvalidArgumentException
2504
-     * @throws InvalidDataTypeException
2505
-     * @throws InvalidInterfaceException
2506
-     * @throws ReflectionException
2507
-     */
2508
-    protected function _default_event_settings()
2509
-    {
2510
-        $this->_set_add_edit_form_tags('update_default_event_settings');
2511
-        $this->_set_publish_post_box_vars();
2512
-        $this->_template_args['admin_page_content'] = EEH_HTML::div(
2513
-            $this->_default_event_settings_form()->get_html(),
2514
-            '',
2515
-            'padding'
2516
-        );
2517
-        $this->display_admin_page_with_sidebar();
2518
-    }
2519
-
2520
-
2521
-    /**
2522
-     * Return the form for event settings.
2523
-     *
2524
-     * @return EE_Form_Section_Proper
2525
-     * @throws EE_Error
2526
-     * @throws ReflectionException
2527
-     */
2528
-    protected function _default_event_settings_form(): EE_Form_Section_Proper
2529
-    {
2530
-        $registration_config              = EE_Registry::instance()->CFG->registration;
2531
-        $registration_stati_for_selection = EEM_Registration::reg_status_array(
2532
-        // exclude
2533
-            [
2534
-                RegStatus::CANCELLED,
2535
-                RegStatus::DECLINED,
2536
-                RegStatus::INCOMPLETE,
2537
-                RegStatus::WAIT_LIST,
2538
-            ],
2539
-            true
2540
-        );
2541
-        // setup Advanced Editor ???
2542
-        if (
2543
-            $this->raw_req_action === 'default_event_settings'
2544
-            || $this->raw_req_action === 'update_default_event_settings'
2545
-        ) {
2546
-            $this->advanced_editor_admin_form = $this->loader->getShared(AdvancedEditorAdminFormSection::class);
2547
-        }
2548
-        return new EE_Form_Section_Proper(
2549
-            [
2550
-                'name'            => 'update_default_event_settings',
2551
-                'html_id'         => 'update_default_event_settings',
2552
-                'html_class'      => 'form-table',
2553
-                'layout_strategy' => new EE_Admin_Two_Column_Layout(),
2554
-                'subsections'     => apply_filters(
2555
-                    'FHEE__Events_Admin_Page___default_event_settings_form__form_subsections',
2556
-                    [
2557
-                        'defaults_section_header' => new EE_Form_Section_HTML(
2558
-                            EEH_HTML::h2(
2559
-                                esc_html__('Default Settings', 'event_espresso'),
2560
-                                '',
2561
-                                'ee-admin-settings-hdr'
2562
-                            )
2563
-                        ),
2564
-                        'default_reg_status'      => new EE_Select_Input(
2565
-                            $registration_stati_for_selection,
2566
-                            [
2567
-                                'default'         => isset($registration_config->default_STS_ID)
2568
-                                                     && array_key_exists(
2569
-                                                         $registration_config->default_STS_ID,
2570
-                                                         $registration_stati_for_selection
2571
-                                                     )
2572
-                                    ? sanitize_text_field($registration_config->default_STS_ID)
2573
-                                    : RegStatus::PENDING_PAYMENT,
2574
-                                'html_label_text' => esc_html__('Default Registration Status', 'event_espresso')
2575
-                                                     . EEH_Template::get_help_tab_link(
2576
-                                                         'default_settings_status_help_tab'
2577
-                                                     ),
2578
-                                'html_help_text'  => esc_html__(
2579
-                                    '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.',
2580
-                                    'event_espresso'
2581
-                                ),
2582
-                                'html_class'      => 'ee-input-width--small',
2583
-                            ]
2584
-                        ),
2585
-                        'default_max_tickets'     => new EE_Integer_Input(
2586
-                            [
2587
-                                'default'         => $registration_config->default_maximum_number_of_tickets
2588
-                                                     ?? EEM_Event::get_default_additional_limit(),
2589
-                                'html_label_text' => esc_html__(
2590
-                                    'Default Maximum Tickets Allowed Per Order:',
2591
-                                    'event_espresso'
2592
-                                )
2593
-                                                     . EEH_Template::get_help_tab_link(
2594
-                                                         'default_maximum_tickets_help_tab"'
2595
-                                                     ),
2596
-                                'html_help_text'  => esc_html__(
2597
-                                    'This setting allows you to indicate what will be the default for the maximum number of tickets per order when creating new events.',
2598
-                                    'event_espresso'
2599
-                                ),
2600
-                                'html_class'      => 'ee-input-width--tiny',
2601
-                            ]
2602
-                        ),
2603
-                    ]
2604
-                ),
2605
-            ]
2606
-        );
2607
-    }
2608
-
2609
-
2610
-    /**
2611
-     * @return void
2612
-     * @throws EE_Error
2613
-     * @throws InvalidArgumentException
2614
-     * @throws InvalidDataTypeException
2615
-     * @throws InvalidInterfaceException
2616
-     * @throws ReflectionException
2617
-     */
2618
-    protected function _update_default_event_settings()
2619
-    {
2620
-        $form = $this->_default_event_settings_form();
2621
-        if ($form->was_submitted()) {
2622
-            $form->receive_form_submission();
2623
-            if ($form->is_valid()) {
2624
-                $registration_config = EE_Registry::instance()->CFG->registration;
2625
-                $valid_data          = $form->valid_data();
2626
-                if (isset($valid_data['default_reg_status'])) {
2627
-                    $registration_config->default_STS_ID = $valid_data['default_reg_status'];
2628
-                }
2629
-                if (isset($valid_data['default_max_tickets'])) {
2630
-                    $registration_config->default_maximum_number_of_tickets = (int) $valid_data['default_max_tickets'];
2631
-                }
2632
-                do_action(
2633
-                    'AHEE__Events_Admin_Page___update_default_event_settings',
2634
-                    $valid_data,
2635
-                    EE_Registry::instance()->CFG,
2636
-                    $this
2637
-                );
2638
-                // update because data was valid!
2639
-                EE_Registry::instance()->CFG->update_espresso_config();
2640
-                EE_Error::overwrite_success();
2641
-                EE_Error::add_success(
2642
-                    esc_html__('Default Event Settings were updated', 'event_espresso')
2643
-                );
2644
-            }
2645
-        }
2646
-        $this->_redirect_after_action(0, '', '', ['action' => 'default_event_settings'], true);
2647
-    }
2648
-
2649
-
2650
-    /*************        Templates        *************
2651
-     *
2652
-     * @throws EE_Error
2653
-     */
2654
-    protected function _template_settings()
2655
-    {
2656
-        $this->_admin_page_title              = esc_html__('Template Settings (Preview)', 'event_espresso');
2657
-        $this->_template_args['preview_img']  = '<img src="'
2658
-                                                . EVENTS_ASSETS_URL
2659
-                                                . '/images/'
2660
-                                                . 'caffeinated_template_features.jpg" alt="'
2661
-                                                . esc_attr__('Template Settings Preview screenshot', 'event_espresso')
2662
-                                                . '" />';
2663
-        $this->_template_args['preview_text'] = '<strong>'
2664
-                                                . esc_html__(
2665
-                                                    '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.',
2666
-                                                    'event_espresso'
2667
-                                                ) . '</strong>';
2668
-        $this->display_admin_caf_preview_page('template_settings_tab');
2669
-    }
2670
-
2671
-
2672
-    /** Event Category Stuff **/
2673
-    /**
2674
-     * set the _category property with the category object for the loaded page.
2675
-     *
2676
-     * @access private
2677
-     * @return void
2678
-     */
2679
-    private function _set_category_object()
2680
-    {
2681
-        if (isset($this->_category->id) && ! empty($this->_category->id)) {
2682
-            return;
2683
-        } //already have the category object so get out.
2684
-        // set default category object
2685
-        $this->_set_empty_category_object();
2686
-        // only set if we've got an id
2687
-        $category_ID = $this->request->getRequestParam('EVT_CAT_ID', 0, DataType::INT);
2688
-        if (! $category_ID) {
2689
-            return;
2690
-        }
2691
-        $term = get_term($category_ID, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY);
2692
-        if (! empty($term)) {
2693
-            $this->_category->category_name       = $term->name;
2694
-            $this->_category->category_identifier = $term->slug;
2695
-            $this->_category->category_desc       = $term->description;
2696
-            $this->_category->id                  = $term->term_id;
2697
-            $this->_category->parent              = $term->parent;
2698
-        }
2699
-    }
2700
-
2701
-
2702
-    /**
2703
-     * Clears out category properties.
2704
-     */
2705
-    private function _set_empty_category_object()
2706
-    {
2707
-        $this->_category                = new stdClass();
2708
-        $this->_category->category_name = $this->_category->category_identifier = $this->_category->category_desc = '';
2709
-        $this->_category->id            = $this->_category->parent = 0;
2710
-    }
2711
-
2712
-
2713
-    /**
2714
-     * @throws DomainException
2715
-     * @throws EE_Error
2716
-     * @throws InvalidArgumentException
2717
-     * @throws InvalidDataTypeException
2718
-     * @throws InvalidInterfaceException
2719
-     */
2720
-    protected function _category_list_table()
2721
-    {
2722
-        $this->_search_btn_label = esc_html__('Categories', 'event_espresso');
2723
-        $this->_admin_page_title .= ' ';
2724
-        $this->_admin_page_title .= $this->get_action_link_or_button(
2725
-            'add_category',
2726
-            'add_category',
2727
-            [],
2728
-            'add-new-h2'
2729
-        );
2730
-        $this->display_admin_list_table_page_with_sidebar();
2731
-    }
2732
-
2733
-
2734
-    /**
2735
-     * Output category details view.
2736
-     *
2737
-     * @throws EE_Error
2738
-     * @throws EE_Error
2739
-     */
2740
-    protected function _category_details($view)
2741
-    {
2742
-        $route = $view === 'edit' ? 'update_category' : 'insert_category';
2743
-        $this->_set_add_edit_form_tags($route);
2744
-        $this->_set_category_object();
2745
-        $id            = ! empty($this->_category->id) ? $this->_category->id : '';
2746
-        $delete_action = 'delete_category';
2747
-        // custom redirect
2748
-        $redirect = EE_Admin_Page::add_query_args_and_nonce(
2749
-            ['action' => 'category_list'],
2750
-            $this->_admin_base_url
2751
-        );
2752
-        $this->_set_publish_post_box_vars('EVT_CAT_ID', $id, $delete_action, $redirect);
2753
-        // take care of contents
2754
-        $this->_template_args['admin_page_content'] = $this->_category_details_content();
2755
-        $this->display_admin_page_with_sidebar();
2756
-    }
2757
-
2758
-
2759
-    /**
2760
-     * Output category details content.
2761
-     *
2762
-     * @throws DomainException
2763
-     */
2764
-    protected function _category_details_content(): string
2765
-    {
2766
-        $editor_args['category_desc'] = [
2767
-            'type'          => 'wp_editor',
2768
-            'value'         => EEH_Formatter::admin_format_content($this->_category->category_desc),
2769
-            'class'         => 'my_editor_custom',
2770
-            'wpeditor_args' => ['media_buttons' => false],
2771
-        ];
2772
-        $_wp_editor                   = $this->_generate_admin_form_fields($editor_args, 'array');
2773
-        $all_terms                    = get_terms(
2774
-            [EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY],
2775
-            ['hide_empty' => 0, 'exclude' => [$this->_category->id]]
2776
-        );
2777
-        // setup category select for term parents.
2778
-        $category_select_values[] = [
2779
-            'text' => esc_html__('No Parent', 'event_espresso'),
2780
-            'id'   => 0,
2781
-        ];
2782
-        foreach ($all_terms as $term) {
2783
-            $category_select_values[] = [
2784
-                'text' => $term->name,
2785
-                'id'   => $term->term_id,
2786
-            ];
2787
-        }
2788
-        $category_select = EEH_Form_Fields::select_input(
2789
-            'category_parent',
2790
-            $category_select_values,
2791
-            $this->_category->parent
2792
-        );
2793
-        $template_args   = [
2794
-            'category'                 => $this->_category,
2795
-            'category_select'          => $category_select,
2796
-            'unique_id_info_help_link' => $this->_get_help_tab_link('unique_id_info'),
2797
-            'category_desc_editor'     => $_wp_editor['category_desc']['field'],
2798
-            'disable'                  => '',
2799
-            'disabled_message'         => false,
2800
-        ];
2801
-        $template        = EVENTS_TEMPLATE_PATH . 'event_category_details.template.php';
2802
-        return EEH_Template::display_template($template, $template_args, true);
2803
-    }
2804
-
2805
-
2806
-    /**
2807
-     * Handles deleting categories.
2808
-     *
2809
-     * @throws EE_Error
2810
-     */
2811
-    protected function _delete_categories()
2812
-    {
2813
-        $category_IDs = $this->request->getRequestParam('EVT_CAT_ID', 0, 'int', true);
2814
-        foreach ($category_IDs as $category_ID) {
2815
-            $this->_delete_category($category_ID);
2816
-        }
2817
-        // doesn't matter what page we're coming from... we're going to the same place after delete.
2818
-        $query_args = [
2819
-            'action' => 'category_list',
2820
-        ];
2821
-        $this->_redirect_after_action(0, '', '', $query_args);
2822
-    }
2823
-
2824
-
2825
-    /**
2826
-     * Handles deleting specific category.
2827
-     *
2828
-     * @param int $cat_id
2829
-     */
2830
-    protected function _delete_category(int $cat_id)
2831
-    {
2832
-        $cat_id = absint($cat_id);
2833
-        wp_delete_term($cat_id, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY);
2834
-    }
2835
-
2836
-
2837
-    /**
2838
-     * Handles triggering the update or insertion of a new category.
2839
-     *
2840
-     * @param bool $new_category true means we're triggering the insert of a new category.
2841
-     * @throws EE_Error
2842
-     * @throws EE_Error
2843
-     */
2844
-    protected function _insert_or_update_category(bool $new_category)
2845
-    {
2846
-        $cat_id  = $this->_insert_category($new_category);
2847
-        $success = 0; // we already have a success message so lets not send another.
2848
-        if ($cat_id) {
2849
-            $query_args = [
2850
-                'action'     => 'edit_category',
2851
-                'EVT_CAT_ID' => $cat_id,
2852
-            ];
2853
-        } else {
2854
-            $query_args = ['action' => 'add_category'];
2855
-        }
2856
-        $this->_redirect_after_action($success, '', '', $query_args, true);
2857
-    }
2858
-
2859
-
2860
-    /**
2861
-     * Inserts or updates category
2862
-     *
2863
-     * @param bool $new_category (true indicates we're updating a category).
2864
-     * @return bool|mixed|string
2865
-     */
2866
-    private function _insert_category(bool $new_category)
2867
-    {
2868
-        $category_ID         = $this->request->getRequestParam('EVT_CAT_ID', 0, DataType::INT);
2869
-        $category_name       = $this->request->getRequestParam('category_name', '');
2870
-        $category_desc       = $this->request->getRequestParam('category_desc', '', DataType::HTML);
2871
-        $category_parent     = $this->request->getRequestParam('category_parent', 0, DataType::INT);
2872
-        $category_identifier = $this->request->getRequestParam('category_identifier', '');
2873
-
2874
-        if (empty($category_name)) {
2875
-            $msg = esc_html__('You must add a name for the category.', 'event_espresso');
2876
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2877
-            return 0;
2878
-        }
2879
-        $term_args = [
2880
-            'name'        => $category_name,
2881
-            'description' => $category_desc,
2882
-            'parent'      => $category_parent,
2883
-        ];
2884
-        // was the category_identifier input disabled?
2885
-        if ($category_identifier) {
2886
-            $term_args['slug'] = $category_identifier;
2887
-        }
2888
-        $insert_ids = $new_category
2889
-            ? wp_insert_term($category_name, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY, $term_args)
2890
-            : wp_update_term($category_ID, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY, $term_args);
2891
-
2892
-        if ($insert_ids instanceof WP_Error) {
2893
-            EE_Error::add_error($insert_ids->get_error_message(), __FILE__, __FUNCTION__, __LINE__);
2894
-            return 0;
2895
-        }
2896
-        $category_ID = $insert_ids['term_id'] ?? 0;
2897
-        if (! $category_ID) {
2898
-            EE_Error::add_error(
2899
-                esc_html__(
2900
-                    'An error occurred and the category has not been saved to the database.',
2901
-                    'event_espresso'
2902
-                ),
2903
-                __FILE__,
2904
-                __FUNCTION__,
2905
-                __LINE__
2906
-            );
2907
-            return 0;
2908
-        }
2909
-        EE_Error::add_success(
2910
-            sprintf(
2911
-                esc_html__('The category %s was successfully saved', 'event_espresso'),
2912
-                $category_name
2913
-            )
2914
-        );
2915
-        return $category_ID;
2916
-    }
2917
-
2918
-
2919
-    /**
2920
-     * Gets categories or count of categories matching the arguments in the request.
2921
-     *
2922
-     * @param int  $per_page
2923
-     * @param int  $current_page
2924
-     * @param bool $count
2925
-     * @return EE_Term_Taxonomy[]|int
2926
-     * @throws EE_Error
2927
-     * @throws ReflectionException
2928
-     */
2929
-    public function get_categories(int $per_page = 10, int $current_page = 1, bool $count = false)
2930
-    {
2931
-        // testing term stuff
2932
-        $orderby     = $this->request->getRequestParam('orderby', 'Term.term_id');
2933
-        $order       = $this->request->getRequestParam('order', 'DESC');
2934
-        $limit       = ($current_page - 1) * $per_page;
2935
-        $where       = ['taxonomy' => EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY];
2936
-        $search_term = $this->request->getRequestParam('s');
2937
-        if ($search_term) {
2938
-            $search_term = '%' . $search_term . '%';
2939
-            $where['OR'] = [
2940
-                'Term.name'   => ['LIKE', $search_term],
2941
-                'description' => ['LIKE', $search_term],
2942
-            ];
2943
-        }
2944
-        $query_params = [
2945
-            $where,
2946
-            'order_by'   => [$orderby => $order],
2947
-            'limit'      => $limit . ',' . $per_page,
2948
-            'force_join' => ['Term'],
2949
-        ];
2950
-        return $count
2951
-            ? EEM_Term_Taxonomy::instance()->count($query_params, 'term_id')
2952
-            : EEM_Term_Taxonomy::instance()->get_all($query_params);
2953
-    }
2954
-
2955
-    /* end category stuff */
2956
-
2957
-
2958
-    /**************/
2959
-
2960
-
2961
-    /**
2962
-     * Callback for the `ee_save_timezone_setting` ajax action.
2963
-     *
2964
-     * @throws EE_Error
2965
-     * @throws InvalidArgumentException
2966
-     * @throws InvalidDataTypeException
2967
-     * @throws InvalidInterfaceException
2968
-     */
2969
-    public function saveTimezoneString()
2970
-    {
2971
-        if (! $this->capabilities->current_user_can('manage_options', __FUNCTION__)) {
2972
-            wp_die(esc_html__('You do not have the required privileges to perform this action', 'event_espresso'));
2973
-        }
2974
-        $timezone_string = $this->request->getRequestParam('timezone_selected');
2975
-        if (empty($timezone_string) || ! EEH_DTT_Helper::validate_timezone($timezone_string, false)) {
2976
-            EE_Error::add_error(
2977
-                esc_html__('An invalid timezone string submitted.', 'event_espresso'),
2978
-                __FILE__,
2979
-                __FUNCTION__,
2980
-                __LINE__
2981
-            );
2982
-            $this->_template_args['error'] = true;
2983
-            $this->_return_json();
2984
-        }
2985
-
2986
-        update_option('timezone_string', $timezone_string);
2987
-        EE_Error::add_success(
2988
-            esc_html__('Your timezone string was updated.', 'event_espresso')
2989
-        );
2990
-        $this->_template_args['success'] = true;
2991
-        $this->_return_json(true, ['action' => 'create_new']);
2992
-    }
2993
-
2994
-
2995
-    /**
2996 2652
      * @throws EE_Error
2997
-     * @deprecated 4.10.25.p
2998 2653
      */
2999
-    public function save_timezonestring_setting()
3000
-    {
3001
-        $this->saveTimezoneString();
3002
-    }
2654
+	protected function _template_settings()
2655
+	{
2656
+		$this->_admin_page_title              = esc_html__('Template Settings (Preview)', 'event_espresso');
2657
+		$this->_template_args['preview_img']  = '<img src="'
2658
+												. EVENTS_ASSETS_URL
2659
+												. '/images/'
2660
+												. 'caffeinated_template_features.jpg" alt="'
2661
+												. esc_attr__('Template Settings Preview screenshot', 'event_espresso')
2662
+												. '" />';
2663
+		$this->_template_args['preview_text'] = '<strong>'
2664
+												. esc_html__(
2665
+													'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.',
2666
+													'event_espresso'
2667
+												) . '</strong>';
2668
+		$this->display_admin_caf_preview_page('template_settings_tab');
2669
+	}
2670
+
2671
+
2672
+	/** Event Category Stuff **/
2673
+	/**
2674
+	 * set the _category property with the category object for the loaded page.
2675
+	 *
2676
+	 * @access private
2677
+	 * @return void
2678
+	 */
2679
+	private function _set_category_object()
2680
+	{
2681
+		if (isset($this->_category->id) && ! empty($this->_category->id)) {
2682
+			return;
2683
+		} //already have the category object so get out.
2684
+		// set default category object
2685
+		$this->_set_empty_category_object();
2686
+		// only set if we've got an id
2687
+		$category_ID = $this->request->getRequestParam('EVT_CAT_ID', 0, DataType::INT);
2688
+		if (! $category_ID) {
2689
+			return;
2690
+		}
2691
+		$term = get_term($category_ID, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY);
2692
+		if (! empty($term)) {
2693
+			$this->_category->category_name       = $term->name;
2694
+			$this->_category->category_identifier = $term->slug;
2695
+			$this->_category->category_desc       = $term->description;
2696
+			$this->_category->id                  = $term->term_id;
2697
+			$this->_category->parent              = $term->parent;
2698
+		}
2699
+	}
2700
+
2701
+
2702
+	/**
2703
+	 * Clears out category properties.
2704
+	 */
2705
+	private function _set_empty_category_object()
2706
+	{
2707
+		$this->_category                = new stdClass();
2708
+		$this->_category->category_name = $this->_category->category_identifier = $this->_category->category_desc = '';
2709
+		$this->_category->id            = $this->_category->parent = 0;
2710
+	}
2711
+
2712
+
2713
+	/**
2714
+	 * @throws DomainException
2715
+	 * @throws EE_Error
2716
+	 * @throws InvalidArgumentException
2717
+	 * @throws InvalidDataTypeException
2718
+	 * @throws InvalidInterfaceException
2719
+	 */
2720
+	protected function _category_list_table()
2721
+	{
2722
+		$this->_search_btn_label = esc_html__('Categories', 'event_espresso');
2723
+		$this->_admin_page_title .= ' ';
2724
+		$this->_admin_page_title .= $this->get_action_link_or_button(
2725
+			'add_category',
2726
+			'add_category',
2727
+			[],
2728
+			'add-new-h2'
2729
+		);
2730
+		$this->display_admin_list_table_page_with_sidebar();
2731
+	}
2732
+
2733
+
2734
+	/**
2735
+	 * Output category details view.
2736
+	 *
2737
+	 * @throws EE_Error
2738
+	 * @throws EE_Error
2739
+	 */
2740
+	protected function _category_details($view)
2741
+	{
2742
+		$route = $view === 'edit' ? 'update_category' : 'insert_category';
2743
+		$this->_set_add_edit_form_tags($route);
2744
+		$this->_set_category_object();
2745
+		$id            = ! empty($this->_category->id) ? $this->_category->id : '';
2746
+		$delete_action = 'delete_category';
2747
+		// custom redirect
2748
+		$redirect = EE_Admin_Page::add_query_args_and_nonce(
2749
+			['action' => 'category_list'],
2750
+			$this->_admin_base_url
2751
+		);
2752
+		$this->_set_publish_post_box_vars('EVT_CAT_ID', $id, $delete_action, $redirect);
2753
+		// take care of contents
2754
+		$this->_template_args['admin_page_content'] = $this->_category_details_content();
2755
+		$this->display_admin_page_with_sidebar();
2756
+	}
2757
+
2758
+
2759
+	/**
2760
+	 * Output category details content.
2761
+	 *
2762
+	 * @throws DomainException
2763
+	 */
2764
+	protected function _category_details_content(): string
2765
+	{
2766
+		$editor_args['category_desc'] = [
2767
+			'type'          => 'wp_editor',
2768
+			'value'         => EEH_Formatter::admin_format_content($this->_category->category_desc),
2769
+			'class'         => 'my_editor_custom',
2770
+			'wpeditor_args' => ['media_buttons' => false],
2771
+		];
2772
+		$_wp_editor                   = $this->_generate_admin_form_fields($editor_args, 'array');
2773
+		$all_terms                    = get_terms(
2774
+			[EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY],
2775
+			['hide_empty' => 0, 'exclude' => [$this->_category->id]]
2776
+		);
2777
+		// setup category select for term parents.
2778
+		$category_select_values[] = [
2779
+			'text' => esc_html__('No Parent', 'event_espresso'),
2780
+			'id'   => 0,
2781
+		];
2782
+		foreach ($all_terms as $term) {
2783
+			$category_select_values[] = [
2784
+				'text' => $term->name,
2785
+				'id'   => $term->term_id,
2786
+			];
2787
+		}
2788
+		$category_select = EEH_Form_Fields::select_input(
2789
+			'category_parent',
2790
+			$category_select_values,
2791
+			$this->_category->parent
2792
+		);
2793
+		$template_args   = [
2794
+			'category'                 => $this->_category,
2795
+			'category_select'          => $category_select,
2796
+			'unique_id_info_help_link' => $this->_get_help_tab_link('unique_id_info'),
2797
+			'category_desc_editor'     => $_wp_editor['category_desc']['field'],
2798
+			'disable'                  => '',
2799
+			'disabled_message'         => false,
2800
+		];
2801
+		$template        = EVENTS_TEMPLATE_PATH . 'event_category_details.template.php';
2802
+		return EEH_Template::display_template($template, $template_args, true);
2803
+	}
2804
+
2805
+
2806
+	/**
2807
+	 * Handles deleting categories.
2808
+	 *
2809
+	 * @throws EE_Error
2810
+	 */
2811
+	protected function _delete_categories()
2812
+	{
2813
+		$category_IDs = $this->request->getRequestParam('EVT_CAT_ID', 0, 'int', true);
2814
+		foreach ($category_IDs as $category_ID) {
2815
+			$this->_delete_category($category_ID);
2816
+		}
2817
+		// doesn't matter what page we're coming from... we're going to the same place after delete.
2818
+		$query_args = [
2819
+			'action' => 'category_list',
2820
+		];
2821
+		$this->_redirect_after_action(0, '', '', $query_args);
2822
+	}
2823
+
2824
+
2825
+	/**
2826
+	 * Handles deleting specific category.
2827
+	 *
2828
+	 * @param int $cat_id
2829
+	 */
2830
+	protected function _delete_category(int $cat_id)
2831
+	{
2832
+		$cat_id = absint($cat_id);
2833
+		wp_delete_term($cat_id, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY);
2834
+	}
2835
+
2836
+
2837
+	/**
2838
+	 * Handles triggering the update or insertion of a new category.
2839
+	 *
2840
+	 * @param bool $new_category true means we're triggering the insert of a new category.
2841
+	 * @throws EE_Error
2842
+	 * @throws EE_Error
2843
+	 */
2844
+	protected function _insert_or_update_category(bool $new_category)
2845
+	{
2846
+		$cat_id  = $this->_insert_category($new_category);
2847
+		$success = 0; // we already have a success message so lets not send another.
2848
+		if ($cat_id) {
2849
+			$query_args = [
2850
+				'action'     => 'edit_category',
2851
+				'EVT_CAT_ID' => $cat_id,
2852
+			];
2853
+		} else {
2854
+			$query_args = ['action' => 'add_category'];
2855
+		}
2856
+		$this->_redirect_after_action($success, '', '', $query_args, true);
2857
+	}
2858
+
2859
+
2860
+	/**
2861
+	 * Inserts or updates category
2862
+	 *
2863
+	 * @param bool $new_category (true indicates we're updating a category).
2864
+	 * @return bool|mixed|string
2865
+	 */
2866
+	private function _insert_category(bool $new_category)
2867
+	{
2868
+		$category_ID         = $this->request->getRequestParam('EVT_CAT_ID', 0, DataType::INT);
2869
+		$category_name       = $this->request->getRequestParam('category_name', '');
2870
+		$category_desc       = $this->request->getRequestParam('category_desc', '', DataType::HTML);
2871
+		$category_parent     = $this->request->getRequestParam('category_parent', 0, DataType::INT);
2872
+		$category_identifier = $this->request->getRequestParam('category_identifier', '');
2873
+
2874
+		if (empty($category_name)) {
2875
+			$msg = esc_html__('You must add a name for the category.', 'event_espresso');
2876
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2877
+			return 0;
2878
+		}
2879
+		$term_args = [
2880
+			'name'        => $category_name,
2881
+			'description' => $category_desc,
2882
+			'parent'      => $category_parent,
2883
+		];
2884
+		// was the category_identifier input disabled?
2885
+		if ($category_identifier) {
2886
+			$term_args['slug'] = $category_identifier;
2887
+		}
2888
+		$insert_ids = $new_category
2889
+			? wp_insert_term($category_name, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY, $term_args)
2890
+			: wp_update_term($category_ID, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY, $term_args);
2891
+
2892
+		if ($insert_ids instanceof WP_Error) {
2893
+			EE_Error::add_error($insert_ids->get_error_message(), __FILE__, __FUNCTION__, __LINE__);
2894
+			return 0;
2895
+		}
2896
+		$category_ID = $insert_ids['term_id'] ?? 0;
2897
+		if (! $category_ID) {
2898
+			EE_Error::add_error(
2899
+				esc_html__(
2900
+					'An error occurred and the category has not been saved to the database.',
2901
+					'event_espresso'
2902
+				),
2903
+				__FILE__,
2904
+				__FUNCTION__,
2905
+				__LINE__
2906
+			);
2907
+			return 0;
2908
+		}
2909
+		EE_Error::add_success(
2910
+			sprintf(
2911
+				esc_html__('The category %s was successfully saved', 'event_espresso'),
2912
+				$category_name
2913
+			)
2914
+		);
2915
+		return $category_ID;
2916
+	}
2917
+
2918
+
2919
+	/**
2920
+	 * Gets categories or count of categories matching the arguments in the request.
2921
+	 *
2922
+	 * @param int  $per_page
2923
+	 * @param int  $current_page
2924
+	 * @param bool $count
2925
+	 * @return EE_Term_Taxonomy[]|int
2926
+	 * @throws EE_Error
2927
+	 * @throws ReflectionException
2928
+	 */
2929
+	public function get_categories(int $per_page = 10, int $current_page = 1, bool $count = false)
2930
+	{
2931
+		// testing term stuff
2932
+		$orderby     = $this->request->getRequestParam('orderby', 'Term.term_id');
2933
+		$order       = $this->request->getRequestParam('order', 'DESC');
2934
+		$limit       = ($current_page - 1) * $per_page;
2935
+		$where       = ['taxonomy' => EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY];
2936
+		$search_term = $this->request->getRequestParam('s');
2937
+		if ($search_term) {
2938
+			$search_term = '%' . $search_term . '%';
2939
+			$where['OR'] = [
2940
+				'Term.name'   => ['LIKE', $search_term],
2941
+				'description' => ['LIKE', $search_term],
2942
+			];
2943
+		}
2944
+		$query_params = [
2945
+			$where,
2946
+			'order_by'   => [$orderby => $order],
2947
+			'limit'      => $limit . ',' . $per_page,
2948
+			'force_join' => ['Term'],
2949
+		];
2950
+		return $count
2951
+			? EEM_Term_Taxonomy::instance()->count($query_params, 'term_id')
2952
+			: EEM_Term_Taxonomy::instance()->get_all($query_params);
2953
+	}
2954
+
2955
+	/* end category stuff */
2956
+
2957
+
2958
+	/**************/
2959
+
2960
+
2961
+	/**
2962
+	 * Callback for the `ee_save_timezone_setting` ajax action.
2963
+	 *
2964
+	 * @throws EE_Error
2965
+	 * @throws InvalidArgumentException
2966
+	 * @throws InvalidDataTypeException
2967
+	 * @throws InvalidInterfaceException
2968
+	 */
2969
+	public function saveTimezoneString()
2970
+	{
2971
+		if (! $this->capabilities->current_user_can('manage_options', __FUNCTION__)) {
2972
+			wp_die(esc_html__('You do not have the required privileges to perform this action', 'event_espresso'));
2973
+		}
2974
+		$timezone_string = $this->request->getRequestParam('timezone_selected');
2975
+		if (empty($timezone_string) || ! EEH_DTT_Helper::validate_timezone($timezone_string, false)) {
2976
+			EE_Error::add_error(
2977
+				esc_html__('An invalid timezone string submitted.', 'event_espresso'),
2978
+				__FILE__,
2979
+				__FUNCTION__,
2980
+				__LINE__
2981
+			);
2982
+			$this->_template_args['error'] = true;
2983
+			$this->_return_json();
2984
+		}
2985
+
2986
+		update_option('timezone_string', $timezone_string);
2987
+		EE_Error::add_success(
2988
+			esc_html__('Your timezone string was updated.', 'event_espresso')
2989
+		);
2990
+		$this->_template_args['success'] = true;
2991
+		$this->_return_json(true, ['action' => 'create_new']);
2992
+	}
2993
+
2994
+
2995
+	/**
2996
+	 * @throws EE_Error
2997
+	 * @deprecated 4.10.25.p
2998
+	 */
2999
+	public function save_timezonestring_setting()
3000
+	{
3001
+		$this->saveTimezoneString();
3002
+	}
3003 3003
 }
Please login to merge, or discard this patch.
admin_pages/events/Events_Admin_Page_Init.core.php 1 patch
Indentation   +33 added lines, -33 removed lines patch added patch discarded remove patch
@@ -16,41 +16,41 @@
 block discarded – undo
16 16
  */
17 17
 class Events_Admin_Page_Init extends EE_Admin_Page_CPT_Init
18 18
 {
19
-    public function __construct()
20
-    {
21
-        /**
22
-         * define some events related constants but only if not defined (need to check because unit tests
23
-         *  may load)
24
-         */
25
-        if (! defined('EVENTS_PG_SLUG')) {
26
-            define('EVENTS_PG_SLUG', 'espresso_events');
27
-            define('EVENTS_LABEL', esc_html__('Events', 'event_espresso'));
28
-            define('EVENTS_ADMIN', EE_ADMIN_PAGES . 'events/');
29
-            define('EVENTS_ADMIN_URL', admin_url('admin.php?page=' . EVENTS_PG_SLUG));
30
-            define('EVENTS_TEMPLATE_PATH', EVENTS_ADMIN . 'templates/');
31
-            define('EVENTS_ASSETS_URL', EE_ADMIN_PAGES_URL . 'events/assets/');
32
-        }
33
-        parent::__construct();
34
-    }
19
+	public function __construct()
20
+	{
21
+		/**
22
+		 * define some events related constants but only if not defined (need to check because unit tests
23
+		 *  may load)
24
+		 */
25
+		if (! defined('EVENTS_PG_SLUG')) {
26
+			define('EVENTS_PG_SLUG', 'espresso_events');
27
+			define('EVENTS_LABEL', esc_html__('Events', 'event_espresso'));
28
+			define('EVENTS_ADMIN', EE_ADMIN_PAGES . 'events/');
29
+			define('EVENTS_ADMIN_URL', admin_url('admin.php?page=' . EVENTS_PG_SLUG));
30
+			define('EVENTS_TEMPLATE_PATH', EVENTS_ADMIN . 'templates/');
31
+			define('EVENTS_ASSETS_URL', EE_ADMIN_PAGES_URL . 'events/assets/');
32
+		}
33
+		parent::__construct();
34
+	}
35 35
 
36 36
 
37
-    protected function _set_init_properties()
38
-    {
39
-        $this->label = esc_html__('Event Espresso - Event Details', 'event_espresso');
40
-    }
37
+	protected function _set_init_properties()
38
+	{
39
+		$this->label = esc_html__('Event Espresso - Event Details', 'event_espresso');
40
+	}
41 41
 
42 42
 
43
-    public function getMenuProperties(): array
44
-    {
45
-        return [
46
-            'menu_type'    => AdminMenuItem::TYPE_MENU_SUB_ITEM,
47
-            'menu_group'   => AdminMenuGroup::MENU_SLUG_MAIN,
48
-            'menu_order'   => 10,
49
-            'show_on_menu' => AdminMenuItem::DISPLAY_BLOG_ONLY,
50
-            'parent_slug'  => AdminMenuTopLevel::MENU_PARENT_ACTIVE,
51
-            'menu_slug'    => AdminMenuTopLevel::MENU_PARENT_ACTIVE,
52
-            'menu_label'   => esc_html__('Events', 'event_espresso'),
53
-            'capability'   => 'ee_read_events',
54
-        ];
55
-    }
43
+	public function getMenuProperties(): array
44
+	{
45
+		return [
46
+			'menu_type'    => AdminMenuItem::TYPE_MENU_SUB_ITEM,
47
+			'menu_group'   => AdminMenuGroup::MENU_SLUG_MAIN,
48
+			'menu_order'   => 10,
49
+			'show_on_menu' => AdminMenuItem::DISPLAY_BLOG_ONLY,
50
+			'parent_slug'  => AdminMenuTopLevel::MENU_PARENT_ACTIVE,
51
+			'menu_slug'    => AdminMenuTopLevel::MENU_PARENT_ACTIVE,
52
+			'menu_label'   => esc_html__('Events', 'event_espresso'),
53
+			'capability'   => 'ee_read_events',
54
+		];
55
+	}
56 56
 }
Please login to merge, or discard this patch.
admin_pages/registration_form/Registration_Form_Admin_Page.core.php 2 patches
Indentation   +759 added lines, -759 removed lines patch added patch discarded remove patch
@@ -17,710 +17,710 @@  discard block
 block discarded – undo
17 17
  */
18 18
 class Registration_Form_Admin_Page extends EE_Admin_Page
19 19
 {
20
-    /**
21
-     * holds the specific question object for the question details screen
22
-     */
23
-    protected ?EE_Question $_question = null;
24
-
25
-    /**
26
-     * holds the specific question group object for the question group details screen
27
-     */
28
-    protected ?EE_Question_Group $_question_group = null;
29
-
30
-    protected EEM_Question $_question_model;
31
-
32
-    protected EEM_Question_Group $_question_group_model;
33
-
34
-
35
-    /**
36
-     * @Constructor
37
-     * @param bool $routing indicate whether we want to just load the object and handle routing or just load the object.
38
-     * @throws EE_Error
39
-     * @throws ReflectionException
40
-     */
41
-    public function __construct($routing = true)
42
-    {
43
-        require_once(EE_MODELS . 'EEM_Question.model.php');
44
-        require_once(EE_MODELS . 'EEM_Question_Group.model.php');
45
-        $this->_question_model       = EEM_Question::instance();
46
-        $this->_question_group_model = EEM_Question_Group::instance();
47
-        parent::__construct($routing);
48
-    }
49
-
50
-
51
-    protected function _init_page_props()
52
-    {
53
-        $this->page_slug        = REGISTRATION_FORM_PG_SLUG;
54
-        $this->page_label       = esc_html__('Registration Form', 'event_espresso');
55
-        $this->_admin_base_url  = REGISTRATION_FORM_ADMIN_URL;
56
-        $this->_admin_base_path = REGISTRATION_FORM_ADMIN;
57
-    }
58
-
59
-
60
-    protected function _ajax_hooks()
61
-    {
62
-    }
63
-
64
-
65
-    protected function _define_page_props()
66
-    {
67
-        $this->_admin_page_title = esc_html__('Registration Form', 'event_espresso');
68
-        $this->_labels           = [
69
-            'buttons'    => [
70
-                'edit_question' => esc_html__('Edit Question', 'event_espresso'),
71
-            ],
72
-            'publishbox' => [
73
-                'edit_question' => esc_html__('Edit Question', 'event_espresso'),
74
-            ],
75
-        ];
76
-    }
77
-
78
-
79
-    /**
80
-     *_set_page_routes
81
-     */
82
-    protected function _set_page_routes()
83
-    {
84
-        $qst_id             =
85
-            ! empty($this->_req_data['QST_ID'])
86
-                ? $this->_req_data['QST_ID']
87
-                : 0;
88
-        $this->_page_routes = [
89
-            'default' => [
90
-                'func'       => [$this, '_questions_overview_list_table'],
91
-                'capability' => 'ee_read_questions',
92
-            ],
93
-
94
-            'edit_question' => [
95
-                'func'       => [$this, '_edit_question'],
96
-                'capability' => 'ee_edit_question',
97
-                'obj_id'     => $qst_id,
98
-                'args'       => ['edit'],
99
-            ],
100
-
101
-            'question_groups' => [
102
-                'func'       => [$this, '_questions_groups_preview'],
103
-                'capability' => 'ee_read_question_groups',
104
-            ],
105
-
106
-            'update_question' => [
107
-                'func'       => [$this, '_insert_or_update_question'],
108
-                'args'       => ['new_question' => false],
109
-                'capability' => 'ee_edit_question',
110
-                'obj_id'     => $qst_id,
111
-                'noheader'   => true,
112
-            ],
113
-        ];
114
-    }
115
-
116
-
117
-    protected function _set_page_config()
118
-    {
119
-        $this->_page_config = [
120
-            'default' => [
121
-                'nav'           => [
122
-                    'label' => esc_html__('Questions', 'event_espresso'),
123
-                    'icon'  => 'dashicons-editor-help',
124
-                    'order' => 10,
125
-                ],
126
-                'list_table'    => 'Registration_Form_Questions_Admin_List_Table',
127
-                'metaboxes'     => $this->_default_espresso_metaboxes,
128
-                'help_tabs'     => [
129
-                    'registration_form_questions_overview_help_tab'                           => [
130
-                        'title'    => esc_html__('Questions Overview', 'event_espresso'),
131
-                        'filename' => 'registration_form_questions_overview',
132
-                    ],
133
-                    'registration_form_questions_overview_table_column_headings_help_tab'     => [
134
-                        'title'    => esc_html__('Questions Overview Table Column Headings', 'event_espresso'),
135
-                        'filename' => 'registration_form_questions_overview_table_column_headings',
136
-                    ],
137
-                    'registration_form_questions_overview_views_bulk_actions_search_help_tab' => [
138
-                        'title'    => esc_html__('Question Overview Views & Bulk Actions & Search', 'event_espresso'),
139
-                        'filename' => 'registration_form_questions_overview_views_bulk_actions_search',
140
-                    ],
141
-                ],
142
-                'require_nonce' => false,
143
-            ],
144
-
145
-            'question_groups' => [
146
-                'nav'           => [
147
-                    'label' => esc_html__('Question Groups', 'event_espresso'),
148
-                    'icon'  => 'dashicons-forms',
149
-                    'order' => 20,
150
-                ],
151
-                'metaboxes'     => $this->_default_espresso_metaboxes,
152
-                'help_tabs'     => [
153
-                    'registration_form_question_groups_help_tab' => [
154
-                        'title'    => esc_html__('Question Groups', 'event_espresso'),
155
-                        'filename' => 'registration_form_question_groups',
156
-                    ],
157
-                ],
158
-                'require_nonce' => false,
159
-            ],
160
-
161
-            'edit_question' => [
162
-                'nav'           => [
163
-                    'label'      => esc_html__('Edit Question', 'event_espresso'),
164
-                    'icon'       => 'dashicons-edit-large',
165
-                    'order'      => 15,
166
-                    'persistent' => false,
167
-                    'url'        => isset($this->_req_data['question_id'])
168
-                        ? add_query_arg(
169
-                            ['question_id' => $this->_req_data['question_id']],
170
-                            $this->_current_page_view_url
171
-                        )
172
-                        : $this->_admin_base_url,
173
-                ],
174
-                'metaboxes'     => array_merge($this->_default_espresso_metaboxes, ['_publish_post_box']),
175
-                'help_tabs'     => [
176
-                    'registration_form_edit_question_group_help_tab' => [
177
-                        'title'    => esc_html__('Edit Question', 'event_espresso'),
178
-                        'filename' => 'registration_form_edit_question',
179
-                    ],
180
-                ],
181
-                'require_nonce' => false,
182
-            ],
183
-        ];
184
-    }
185
-
186
-
187
-    protected function _add_screen_options()
188
-    {
189
-        // todo
190
-    }
191
-
192
-
193
-    protected function _add_screen_options_default()
194
-    {
195
-        $page_title              = $this->_admin_page_title;
196
-        $this->_admin_page_title = esc_html__('Questions', 'event_espresso');
197
-        $this->_per_page_screen_option();
198
-        $this->_admin_page_title = $page_title;
199
-    }
200
-
201
-
202
-    protected function _add_screen_options_question_groups()
203
-    {
204
-        $page_title              = $this->_admin_page_title;
205
-        $this->_admin_page_title = esc_html__('Question Groups', 'event_espresso');
206
-        $this->_per_page_screen_option();
207
-        $this->_admin_page_title = $page_title;
208
-    }
209
-
210
-
211
-    // none of the below group are currently used for Event Categories
212
-    protected function _add_feature_pointers()
213
-    {
214
-    }
215
-
216
-
217
-    public function load_scripts_styles()
218
-    {
219
-        wp_register_style(
220
-            'espresso_registration',
221
-            REGISTRATION_FORM_ASSETS_URL . 'espresso_registration_form_admin.css',
222
-            [EspressoLegacyAdminAssetManager::CSS_HANDLE_EE_ADMIN],
223
-            EVENT_ESPRESSO_VERSION
224
-        );
225
-        wp_enqueue_style('espresso_registration');
226
-    }
227
-
228
-
229
-    public function admin_init()
230
-    {
231
-    }
232
-
233
-
234
-    public function admin_notices()
235
-    {
236
-    }
237
-
238
-
239
-    public function admin_footer_scripts()
240
-    {
241
-    }
242
-
243
-
244
-    public function load_scripts_styles_default()
245
-    {
246
-    }
247
-
248
-
249
-    public function load_scripts_styles_add_question()
250
-    {
251
-        $this->load_scripts_styles_question_details();
252
-    }
253
-
254
-
255
-    public function load_scripts_styles_edit_question()
256
-    {
257
-        $this->load_scripts_styles_question_details();
258
-    }
259
-
260
-
261
-    /**
262
-     * Loads the JS required for adding or editing a question
263
-     */
264
-    protected function load_scripts_styles_question_details()
265
-    {
266
-        $this->load_scripts_styles_forms();
267
-        wp_register_script(
268
-            'espresso_registration_form_single',
269
-            REGISTRATION_FORM_ASSETS_URL . 'espresso_registration_form_admin.js',
270
-            ['jquery-ui-sortable'],
271
-            EVENT_ESPRESSO_VERSION,
272
-            true
273
-        );
274
-        wp_enqueue_script('espresso_registration_form_single');
275
-        wp_localize_script(
276
-            'espresso_registration_form_single',
277
-            'ee_question_data',
278
-            [
279
-                'question_types_with_max'    => $this->_question_model->questionTypesWithMaxLength(),
280
-                'question_type_with_options' => $this->_question_model->question_types_with_options(),
281
-            ]
282
-        );
283
-    }
284
-
285
-
286
-    public function recaptcha_info_help_tab()
287
-    {
288
-        EEH_Template::display_template(REGISTRATION_FORM_TEMPLATE_PATH . 'recaptcha_info_help_tab.template.php');
289
-    }
290
-
291
-
292
-    public function load_scripts_styles_forms()
293
-    {
294
-        // styles
295
-        wp_enqueue_style('espresso-ui-theme');
296
-        // scripts
297
-        wp_enqueue_script('ee_admin_js');
298
-    }
299
-
300
-
301
-    protected function _set_list_table_views_default()
302
-    {
303
-        $this->_views = [
304
-            'all' => [
305
-                'slug'  => 'all',
306
-                'label' => esc_html__('View All Questions', 'event_espresso'),
307
-                'count' => 0,
308
-            ],
309
-        ];
310
-
311
-        if (
312
-            $this->capabilities->current_user_can(
313
-                'ee_delete_questions',
314
-                'espresso_registration_form_trash_questions'
315
-            )
316
-        ) {
317
-            $this->_views['trash'] = [
318
-                'slug'  => 'trash',
319
-                'label' => esc_html__('Trash', 'event_espresso'),
320
-                'count' => 0,
321
-            ];
322
-        }
323
-    }
324
-
325
-
326
-    /**
327
-     * This just previews the question groups tab that comes in caffeinated.
328
-     *
329
-     * @return void html
330
-     * @throws EE_Error
331
-     */
332
-    protected function _questions_groups_preview()
333
-    {
334
-        $this->_admin_page_title              = esc_html__('Question Groups (Preview)', 'event_espresso');
335
-        $this->_template_args['preview_img']  =
336
-            '<img src="' . REGISTRATION_FORM_ASSETS_URL . 'caf_reg_form_preview.jpg" alt="'
337
-            . esc_attr__(
338
-                'Preview Question Groups Overview List Table screenshot',
339
-                'event_espresso'
340
-            ) . '" />';
341
-        $this->_template_args['preview_text'] = '<strong>'
342
-            . esc_html__(
343
-                'Question Groups 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. With the Question Groups feature you are able to create new question groups, edit existing question groups, and create and edit new questions and add them to question groups.',
344
-                'event_espresso'
345
-            ) . '</strong>';
346
-        $this->display_admin_caf_preview_page('question_groups_tab');
347
-    }
348
-
349
-
350
-    /**
351
-     * Extracts the question field's values from the POST request to update or insert them
352
-     *
353
-     * @param EEM_Base $model
354
-     * @return array where each key is the name of a model's field/db column, and each value is its value.
355
-     * @throws EE_Error
356
-     * @throws ReflectionException
357
-     */
358
-    protected function _set_column_values_for(EEM_Base $model): array
359
-    {
360
-        $column_values = [];
361
-        // some initial checks for proper values.
362
-        $QST_ID = $this->request->getRequestParam('QST_ID', 0, DataType::INT);
363
-        // if QST_admin_only, then no matter what QST_required is we disable.
364
-        $QST_admin_only = $this->request->getRequestParam('QST_admin_only', false, DataType::BOOL);
365
-        if ($QST_admin_only) {
366
-            $this->request->setRequestParam('QST_required', false);
367
-        }
368
-        // if the question shouldn't have a max length, don't let them set one
369
-        if (
370
-            ! (
371
-                $this->request->requestParamIsSet('QST_type')
372
-                && $this->request->requestParamIsSet('QST_max')
373
-            ) || ! in_array(
374
-                $this->request->getRequestParam('QST_type', '', DataType::STRING),
375
-                $this->_question_model->questionTypesWithMaxLength(),
376
-                true
377
-            )
378
-        ) {
379
-            // they're not allowed to set the max
380
-            $this->request->unSetRequestParam('QST_max', true);
381
-        }
382
-        foreach ($model->field_settings() as $fieldName => $settings) {
383
-            switch($fieldName) {
384
-                case 'QSG_identifier':
385
-                    // basically if QSG_identifier is empty or not set
386
-                    if (! $this->request->getRequestParam('QSG_identifier', '', DataType::STRING)) {
387
-                        $QSG_name                    = $this->request->getRequestParam('QSG_name', '', DataType::STRING);
388
-                        $column_values[ $fieldName ] = sanitize_title($QSG_name) . '-' . uniqid('', true);
389
-                    }
390
-                    break;
391
-
392
-                case 'QST_display_text':
393
-                        $column_values[ $fieldName ] = $this->request->getRequestParam('QST_display_text', '', DataType::HTML);
394
-                    break;
395
-
396
-                case 'QST_admin_label':
397
-                    if (! $this->request->getRequestParam('QST_admin_label', '', DataType::STRING)) {
398
-                        // the admin label is blank, use a slug version of the question text
399
-                        $QST_text                    = $this->request->getRequestParam('QST_display_text', '', DataType::STRING);
400
-                        $column_values[ $fieldName ] = sanitize_title(wp_trim_words($QST_text, 10));
401
-                    } else {
402
-                        // admin label set, use it
403
-                        $column_values[ $fieldName ] = $this->request->getRequestParam('QST_admin_label', '', DataType::STRING);
404
-                    }
405
-                    break;
406
-
407
-                case 'QST_admin_only':
408
-                    $column_values[ $fieldName ] = $QST_admin_only;
409
-                    break;
410
-
411
-                case 'QST_max':
412
-                    $qst_system = $this->_question_model->get_var(
413
-                        [ [ 'QST_ID' => $QST_ID ] ],
414
-                        'QST_system'
415
-                    );
416
-
417
-                    $max_max = $this->_question_model->absolute_max_for_system_question((string) $qst_system);
418
-                    $QST_max = $this->request->getRequestParam('QST_max', 0, DataType::INT);
419
-                    if ($QST_max === 0 || $QST_max > $max_max) {
420
-                        $column_values[ $fieldName ] = $max_max;
421
-                    }
422
-                    break;
423
-
424
-                default:
425
-                    // only add a property to the array if it's not null (otherwise the model should just use the default value)
426
-                    if ($this->request->requestParamIsSet($fieldName)) {
427
-                        $column_values[ $fieldName ] = $this->request->getRequestParam(
428
-                            $fieldName,
429
-                            null,
430
-                            $settings->dataType()
431
-                        );
432
-                    }
433
-            }
434
-        }
435
-        // validation for this data to be performed by the model before insertion.
436
-        return $column_values;
437
-    }
438
-
439
-
440
-    /**
441
-     *_questions_overview_list_table
442
-     *
443
-     * @throws EE_Error
444
-     */
445
-    protected function _questions_overview_list_table()
446
-    {
447
-        $this->_search_btn_label = esc_html__('Questions', 'event_espresso');
448
-        $this->display_admin_list_table_page_with_sidebar();
449
-    }
450
-
451
-
452
-    /**
453
-     * _edit_question
454
-     *
455
-     * @throws EE_Error
456
-     * @throws ReflectionException
457
-     */
458
-    protected function _edit_question()
459
-    {
460
-        $ID = isset($this->_req_data['QST_ID']) && ! empty($this->_req_data['QST_ID'])
461
-            ? absint($this->_req_data['QST_ID'])
462
-            : false;
463
-
464
-        switch ($this->_req_action) {
465
-            case 'add_question':
466
-                $this->_admin_page_title = esc_html__('Add Question', 'event_espresso');
467
-                break;
468
-            case 'edit_question':
469
-                $this->_admin_page_title = esc_html__('Edit Question', 'event_espresso');
470
-                break;
471
-            default:
472
-                $this->_admin_page_title = ucwords(str_replace('_', ' ', $this->_req_action));
473
-        }
474
-
475
-        // add PRC_ID to title if editing
476
-        $this->_admin_page_title =
477
-            $ID
478
-                ? $this->_admin_page_title . ' # ' . $ID
479
-                : $this->_admin_page_title;
480
-        if ($ID) {
481
-            $question                 = $this->_question_model->get_one_by_ID($ID);
482
-            $additional_hidden_fields = ['QST_ID' => ['type' => 'hidden', 'value' => $ID]];
483
-            $this->_set_add_edit_form_tags('update_question', $additional_hidden_fields);
484
-        } else {
485
-            $question = EE_Question::new_instance();
486
-            $question->set_order_to_latest();
487
-            $this->_set_add_edit_form_tags('insert_question');
488
-        }
489
-        if ($question->system_ID() === EEM_Attendee::system_question_phone) {
490
-            $question_types = array_intersect_key(
491
-                $this->_question_model->allowed_question_types(),
492
-                array_flip(
493
-                    [
494
-                        EEM_Question::QST_type_text,
495
-                        EEM_Question::QST_type_us_phone,
496
-                    ]
497
-                )
498
-            );
499
-        } else {
500
-            $question_types = $question->has_answers()
501
-                ? $this->_question_model->question_types_in_same_category($question->type())
502
-                : $this->_question_model->allowed_question_types();
503
-        }
504
-        $this->_template_args['QST_ID']                     = $ID;
505
-        $this->_template_args['question']                   = $question;
506
-        $this->_template_args['question_types']             = $question_types;
507
-        $this->_template_args['max_max']                    =
508
-            $this->_question_model->absolute_max_for_system_question(
509
-                $question->system_ID()
510
-            );
511
-        $this->_template_args['question_type_descriptions'] = $this->_get_question_type_descriptions();
512
-        $this->_set_publish_post_box_vars('id', $ID);
513
-        $this->_template_args['admin_page_content'] = EEH_Template::display_template(
514
-            REGISTRATION_FORM_TEMPLATE_PATH . 'questions_main_meta_box.template.php',
515
-            $this->_template_args,
516
-            true
517
-        );
518
-
519
-        // the details template wrapper
520
-        $this->display_admin_page_with_sidebar();
521
-    }
522
-
523
-
524
-    /**
525
-     * @return string
526
-     * @throws EE_Error
527
-     * @throws ReflectionException
528
-     */
529
-    protected function _get_question_type_descriptions(): string
530
-    {
531
-        EE_Registry::instance()->load_helper('HTML');
532
-        $descriptions               = '';
533
-        $question_type_descriptions = $this->_question_model->question_descriptions();
534
-        foreach ($question_type_descriptions as $type => $question_type_description) {
535
-            if ($type == 'HTML_TEXTAREA') {
536
-                $html                      = new EE_Simple_HTML_Validation_Strategy();
537
-                $question_type_description .= sprintf(
538
-                    esc_html__('%1$s(allowed tags: %2$s)', 'event_espresso'),
539
-                    '<br/>',
540
-                    $html->get_list_of_allowed_tags()
541
-                );
542
-            }
543
-            $descriptions .= EEH_HTML::p(
544
-                $question_type_description,
545
-                'question_type_description-' . $type,
546
-                'question_type_description description',
547
-                'display:none;'
548
-            );
549
-        }
550
-        return $descriptions;
551
-    }
552
-
553
-
554
-    /**
555
-     * @param bool $new_question
556
-     * @throws EE_Error
557
-     * @throws ReflectionException
558
-     */
559
-    protected function _insert_or_update_question(bool $new_question = true)
560
-    {
561
-        $set_column_values = $this->_set_column_values_for($this->_question_model);
562
-        if ($new_question) {
563
-            $question    = EE_Question::new_instance($set_column_values);
564
-            $action_desc = 'added';
565
-        } else {
566
-            $question = $this->_question_model->get_one_by_ID(
567
-                $this->request->getRequestParam('QST_ID', 0, DataType::INT)
568
-            );
569
-            foreach ($set_column_values as $field => $new_value) {
570
-                $question->set($field, $new_value);
571
-            }
572
-            $action_desc = 'updated';
573
-        }
574
-        $success = $question->save();
575
-        $ID      = $question->ID();
576
-        if ($ID && $question->should_have_question_options()) {
577
-            // save the related options
578
-            // trash removed options, save old ones
579
-            // get list of all options
580
-            $options          = $question->options();
581
-            $question_options = $this->request->getRequestParam('question_options', [], DataType::HTML, true);
582
-            $QSO_default      = $this->request->getRequestParam('QSO_default', null, DataType::INT);
583
-            if (! empty($options)) {
584
-                foreach ($options as $option_ID => $option) {
585
-                    $option_req_index = $this->_get_option_req_data_index($option_ID);
586
-                    if ($option_req_index !== false) {
587
-                        $question_options[ $option_req_index ]['QSO_default'] = $option_req_index === $QSO_default;
588
-                        // decode options converted to html_entities by wp_kses()
589
-                        $question_options[ $option_req_index ]['QSO_value'] = html_entity_decode(
590
-                            $question_options[ $option_req_index ]['QSO_value'],
591
-                            ENT_QUOTES | ENT_HTML5,
592
-                            'UTF-8'
593
-                        );
594
-                        $question_options[ $option_req_index ]['QSO_desc'] = html_entity_decode(
595
-                            $question_options[ $option_req_index ]['QSO_desc'],
596
-                            ENT_QUOTES | ENT_HTML5,
597
-                            'UTF-8'
598
-                        );
599
-                        $option->save($question_options[ $option_req_index ]);
600
-                    } else {
601
-                        // not found, remove it
602
-                        $option->delete();
603
-                    }
604
-                }
605
-            }
606
-            // save new related options
607
-            foreach ($question_options as $index => $option_req_data) {
608
-                // skip $index that is from our sample
609
-                if ($index === 'xxcountxx') {
610
-                    continue;
611
-                }
612
-                // note we allow saving blank options.
613
-                if (empty($option_req_data['QSO_ID'])) {
614
-                    // no ID! save it!
615
-                    $new_option = EE_Question_Option::new_instance(
616
-                        [
617
-                            'QSO_value'   => $option_req_data['QSO_value'],
618
-                            'QSO_desc'    => $option_req_data['QSO_desc'],
619
-                            'QSO_default' => $index === $QSO_default,
620
-                            'QSO_order'   => $option_req_data['QSO_order'],
621
-                            'QST_ID'      => $question->ID(),
622
-                        ]
623
-                    );
624
-                    $new_option->save();
625
-                }
626
-            }
627
-        }
628
-
629
-        $success = apply_filters(
630
-            'FHEE__Registration_Form_Admin_Page___insert_or_update_question__success',
631
-            (int) $success,
632
-            $question,
633
-            $this
634
-        );
635
-
636
-        $query_args = ['action' => 'edit_question', 'QST_ID' => $ID];
637
-        if ($success !== 0) {
638
-            $msg = $new_question
639
-                ? sprintf(
640
-                    esc_html__('The %s has been created', 'event_espresso'),
641
-                    $this->_question_model->item_name()
642
-                )
643
-                : sprintf(
644
-                    esc_html__('The %s has been updated', 'event_espresso'),
645
-                    $this->_question_model->item_name()
646
-                );
647
-            EE_Error::add_success($msg);
648
-        }
649
-
650
-        $this->_redirect_after_action(false, '', $action_desc, $query_args, true);
651
-    }
652
-
653
-
654
-    /**
655
-     * Upon saving a question, there should be an array of 'question_options'. This array is index numerically, but not
656
-     * by ID
657
-     * (this is done because new question options don't have an ID, but we may want to add multiple simultaneously).
658
-     * So, this function gets the index in that request data array called question_options. Returns FALSE if not found.
659
-     *
660
-     * @param int $ID of the question option to find
661
-     * @return int index in question_options array if successful, FALSE if unsuccessful
662
-     */
663
-    protected function _get_option_req_data_index(int $ID)
664
-    {
665
-        $req_data_for_question_options = $this->_req_data['question_options'];
666
-        foreach ($req_data_for_question_options as $num => $option_data) {
667
-            if (array_key_exists('QSO_ID', $option_data) && (int) $option_data['QSO_ID'] === $ID) {
668
-                return $num;
669
-            }
670
-        }
671
-        return false;
672
-    }
673
-
674
-
675
-
676
-
677
-    /* QUERIES */
678
-    /**
679
-     * For internal use in getting all the query parameters
680
-     * (because it's pretty well the same between question, question groups,
681
-     * and for both when searching for trashed and untrashed ones)
682
-     *
683
-     * @param EEM_Base $model either EEM_Question or EEM_Question_Group
684
-     * @param int      $per_page
685
-     * @param int      $current_page
686
-     * @return array model query params,
687
-     * @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
688
-     */
689
-    protected function get_query_params(EEM_Base $model, int $per_page = 10, int $current_page = 10): array
690
-    {
691
-        $query_params             = [];
692
-        $offset                   = ($current_page - 1) * $per_page;
693
-        $query_params['limit']    = [$offset, $per_page];
694
-
695
-        $order  = (isset($this->_req_data['order']) && ! empty($this->_req_data['order']))
696
-            ? $this->_req_data['order']
697
-            : 'ASC';
698
-
699
-        $orderby_field = $model instanceof EEM_Question ? 'QST_ID' : 'QSG_order';
700
-
701
-        $field_to_order_by = empty($this->_req_data['orderby']) ? $orderby_field : $this->_req_data['orderby'];
702
-
703
-        $query_params['order_by'] = [$field_to_order_by => $order];
704
-
705
-        $search_string = array_key_exists('s', $this->_req_data) ? $this->_req_data['s'] : null;
706
-        if (! empty($search_string)) {
707
-            if ($model instanceof EEM_Question_Group) {
708
-                $query_params[0] = [
709
-                    'OR' => [
710
-                        'QSG_name' => ['LIKE', "%$search_string%"],
711
-                        'QSG_desc' => ['LIKE', "%$search_string%"],
712
-                    ],
713
-                ];
714
-            } else {
715
-                $query_params[0] = [
716
-                    'QST_display_text' => ['LIKE', "%$search_string%"],
717
-                ];
718
-            }
719
-        }
720
-
721
-        // capability checks (just leaving this commented out for reference because
722
-        // it illustrates some complicated query params that could be useful when fully implemented)
723
-        /*if ( $model instanceof EEM_Question_Group ) {
20
+	/**
21
+	 * holds the specific question object for the question details screen
22
+	 */
23
+	protected ?EE_Question $_question = null;
24
+
25
+	/**
26
+	 * holds the specific question group object for the question group details screen
27
+	 */
28
+	protected ?EE_Question_Group $_question_group = null;
29
+
30
+	protected EEM_Question $_question_model;
31
+
32
+	protected EEM_Question_Group $_question_group_model;
33
+
34
+
35
+	/**
36
+	 * @Constructor
37
+	 * @param bool $routing indicate whether we want to just load the object and handle routing or just load the object.
38
+	 * @throws EE_Error
39
+	 * @throws ReflectionException
40
+	 */
41
+	public function __construct($routing = true)
42
+	{
43
+		require_once(EE_MODELS . 'EEM_Question.model.php');
44
+		require_once(EE_MODELS . 'EEM_Question_Group.model.php');
45
+		$this->_question_model       = EEM_Question::instance();
46
+		$this->_question_group_model = EEM_Question_Group::instance();
47
+		parent::__construct($routing);
48
+	}
49
+
50
+
51
+	protected function _init_page_props()
52
+	{
53
+		$this->page_slug        = REGISTRATION_FORM_PG_SLUG;
54
+		$this->page_label       = esc_html__('Registration Form', 'event_espresso');
55
+		$this->_admin_base_url  = REGISTRATION_FORM_ADMIN_URL;
56
+		$this->_admin_base_path = REGISTRATION_FORM_ADMIN;
57
+	}
58
+
59
+
60
+	protected function _ajax_hooks()
61
+	{
62
+	}
63
+
64
+
65
+	protected function _define_page_props()
66
+	{
67
+		$this->_admin_page_title = esc_html__('Registration Form', 'event_espresso');
68
+		$this->_labels           = [
69
+			'buttons'    => [
70
+				'edit_question' => esc_html__('Edit Question', 'event_espresso'),
71
+			],
72
+			'publishbox' => [
73
+				'edit_question' => esc_html__('Edit Question', 'event_espresso'),
74
+			],
75
+		];
76
+	}
77
+
78
+
79
+	/**
80
+	 *_set_page_routes
81
+	 */
82
+	protected function _set_page_routes()
83
+	{
84
+		$qst_id             =
85
+			! empty($this->_req_data['QST_ID'])
86
+				? $this->_req_data['QST_ID']
87
+				: 0;
88
+		$this->_page_routes = [
89
+			'default' => [
90
+				'func'       => [$this, '_questions_overview_list_table'],
91
+				'capability' => 'ee_read_questions',
92
+			],
93
+
94
+			'edit_question' => [
95
+				'func'       => [$this, '_edit_question'],
96
+				'capability' => 'ee_edit_question',
97
+				'obj_id'     => $qst_id,
98
+				'args'       => ['edit'],
99
+			],
100
+
101
+			'question_groups' => [
102
+				'func'       => [$this, '_questions_groups_preview'],
103
+				'capability' => 'ee_read_question_groups',
104
+			],
105
+
106
+			'update_question' => [
107
+				'func'       => [$this, '_insert_or_update_question'],
108
+				'args'       => ['new_question' => false],
109
+				'capability' => 'ee_edit_question',
110
+				'obj_id'     => $qst_id,
111
+				'noheader'   => true,
112
+			],
113
+		];
114
+	}
115
+
116
+
117
+	protected function _set_page_config()
118
+	{
119
+		$this->_page_config = [
120
+			'default' => [
121
+				'nav'           => [
122
+					'label' => esc_html__('Questions', 'event_espresso'),
123
+					'icon'  => 'dashicons-editor-help',
124
+					'order' => 10,
125
+				],
126
+				'list_table'    => 'Registration_Form_Questions_Admin_List_Table',
127
+				'metaboxes'     => $this->_default_espresso_metaboxes,
128
+				'help_tabs'     => [
129
+					'registration_form_questions_overview_help_tab'                           => [
130
+						'title'    => esc_html__('Questions Overview', 'event_espresso'),
131
+						'filename' => 'registration_form_questions_overview',
132
+					],
133
+					'registration_form_questions_overview_table_column_headings_help_tab'     => [
134
+						'title'    => esc_html__('Questions Overview Table Column Headings', 'event_espresso'),
135
+						'filename' => 'registration_form_questions_overview_table_column_headings',
136
+					],
137
+					'registration_form_questions_overview_views_bulk_actions_search_help_tab' => [
138
+						'title'    => esc_html__('Question Overview Views & Bulk Actions & Search', 'event_espresso'),
139
+						'filename' => 'registration_form_questions_overview_views_bulk_actions_search',
140
+					],
141
+				],
142
+				'require_nonce' => false,
143
+			],
144
+
145
+			'question_groups' => [
146
+				'nav'           => [
147
+					'label' => esc_html__('Question Groups', 'event_espresso'),
148
+					'icon'  => 'dashicons-forms',
149
+					'order' => 20,
150
+				],
151
+				'metaboxes'     => $this->_default_espresso_metaboxes,
152
+				'help_tabs'     => [
153
+					'registration_form_question_groups_help_tab' => [
154
+						'title'    => esc_html__('Question Groups', 'event_espresso'),
155
+						'filename' => 'registration_form_question_groups',
156
+					],
157
+				],
158
+				'require_nonce' => false,
159
+			],
160
+
161
+			'edit_question' => [
162
+				'nav'           => [
163
+					'label'      => esc_html__('Edit Question', 'event_espresso'),
164
+					'icon'       => 'dashicons-edit-large',
165
+					'order'      => 15,
166
+					'persistent' => false,
167
+					'url'        => isset($this->_req_data['question_id'])
168
+						? add_query_arg(
169
+							['question_id' => $this->_req_data['question_id']],
170
+							$this->_current_page_view_url
171
+						)
172
+						: $this->_admin_base_url,
173
+				],
174
+				'metaboxes'     => array_merge($this->_default_espresso_metaboxes, ['_publish_post_box']),
175
+				'help_tabs'     => [
176
+					'registration_form_edit_question_group_help_tab' => [
177
+						'title'    => esc_html__('Edit Question', 'event_espresso'),
178
+						'filename' => 'registration_form_edit_question',
179
+					],
180
+				],
181
+				'require_nonce' => false,
182
+			],
183
+		];
184
+	}
185
+
186
+
187
+	protected function _add_screen_options()
188
+	{
189
+		// todo
190
+	}
191
+
192
+
193
+	protected function _add_screen_options_default()
194
+	{
195
+		$page_title              = $this->_admin_page_title;
196
+		$this->_admin_page_title = esc_html__('Questions', 'event_espresso');
197
+		$this->_per_page_screen_option();
198
+		$this->_admin_page_title = $page_title;
199
+	}
200
+
201
+
202
+	protected function _add_screen_options_question_groups()
203
+	{
204
+		$page_title              = $this->_admin_page_title;
205
+		$this->_admin_page_title = esc_html__('Question Groups', 'event_espresso');
206
+		$this->_per_page_screen_option();
207
+		$this->_admin_page_title = $page_title;
208
+	}
209
+
210
+
211
+	// none of the below group are currently used for Event Categories
212
+	protected function _add_feature_pointers()
213
+	{
214
+	}
215
+
216
+
217
+	public function load_scripts_styles()
218
+	{
219
+		wp_register_style(
220
+			'espresso_registration',
221
+			REGISTRATION_FORM_ASSETS_URL . 'espresso_registration_form_admin.css',
222
+			[EspressoLegacyAdminAssetManager::CSS_HANDLE_EE_ADMIN],
223
+			EVENT_ESPRESSO_VERSION
224
+		);
225
+		wp_enqueue_style('espresso_registration');
226
+	}
227
+
228
+
229
+	public function admin_init()
230
+	{
231
+	}
232
+
233
+
234
+	public function admin_notices()
235
+	{
236
+	}
237
+
238
+
239
+	public function admin_footer_scripts()
240
+	{
241
+	}
242
+
243
+
244
+	public function load_scripts_styles_default()
245
+	{
246
+	}
247
+
248
+
249
+	public function load_scripts_styles_add_question()
250
+	{
251
+		$this->load_scripts_styles_question_details();
252
+	}
253
+
254
+
255
+	public function load_scripts_styles_edit_question()
256
+	{
257
+		$this->load_scripts_styles_question_details();
258
+	}
259
+
260
+
261
+	/**
262
+	 * Loads the JS required for adding or editing a question
263
+	 */
264
+	protected function load_scripts_styles_question_details()
265
+	{
266
+		$this->load_scripts_styles_forms();
267
+		wp_register_script(
268
+			'espresso_registration_form_single',
269
+			REGISTRATION_FORM_ASSETS_URL . 'espresso_registration_form_admin.js',
270
+			['jquery-ui-sortable'],
271
+			EVENT_ESPRESSO_VERSION,
272
+			true
273
+		);
274
+		wp_enqueue_script('espresso_registration_form_single');
275
+		wp_localize_script(
276
+			'espresso_registration_form_single',
277
+			'ee_question_data',
278
+			[
279
+				'question_types_with_max'    => $this->_question_model->questionTypesWithMaxLength(),
280
+				'question_type_with_options' => $this->_question_model->question_types_with_options(),
281
+			]
282
+		);
283
+	}
284
+
285
+
286
+	public function recaptcha_info_help_tab()
287
+	{
288
+		EEH_Template::display_template(REGISTRATION_FORM_TEMPLATE_PATH . 'recaptcha_info_help_tab.template.php');
289
+	}
290
+
291
+
292
+	public function load_scripts_styles_forms()
293
+	{
294
+		// styles
295
+		wp_enqueue_style('espresso-ui-theme');
296
+		// scripts
297
+		wp_enqueue_script('ee_admin_js');
298
+	}
299
+
300
+
301
+	protected function _set_list_table_views_default()
302
+	{
303
+		$this->_views = [
304
+			'all' => [
305
+				'slug'  => 'all',
306
+				'label' => esc_html__('View All Questions', 'event_espresso'),
307
+				'count' => 0,
308
+			],
309
+		];
310
+
311
+		if (
312
+			$this->capabilities->current_user_can(
313
+				'ee_delete_questions',
314
+				'espresso_registration_form_trash_questions'
315
+			)
316
+		) {
317
+			$this->_views['trash'] = [
318
+				'slug'  => 'trash',
319
+				'label' => esc_html__('Trash', 'event_espresso'),
320
+				'count' => 0,
321
+			];
322
+		}
323
+	}
324
+
325
+
326
+	/**
327
+	 * This just previews the question groups tab that comes in caffeinated.
328
+	 *
329
+	 * @return void html
330
+	 * @throws EE_Error
331
+	 */
332
+	protected function _questions_groups_preview()
333
+	{
334
+		$this->_admin_page_title              = esc_html__('Question Groups (Preview)', 'event_espresso');
335
+		$this->_template_args['preview_img']  =
336
+			'<img src="' . REGISTRATION_FORM_ASSETS_URL . 'caf_reg_form_preview.jpg" alt="'
337
+			. esc_attr__(
338
+				'Preview Question Groups Overview List Table screenshot',
339
+				'event_espresso'
340
+			) . '" />';
341
+		$this->_template_args['preview_text'] = '<strong>'
342
+			. esc_html__(
343
+				'Question Groups 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. With the Question Groups feature you are able to create new question groups, edit existing question groups, and create and edit new questions and add them to question groups.',
344
+				'event_espresso'
345
+			) . '</strong>';
346
+		$this->display_admin_caf_preview_page('question_groups_tab');
347
+	}
348
+
349
+
350
+	/**
351
+	 * Extracts the question field's values from the POST request to update or insert them
352
+	 *
353
+	 * @param EEM_Base $model
354
+	 * @return array where each key is the name of a model's field/db column, and each value is its value.
355
+	 * @throws EE_Error
356
+	 * @throws ReflectionException
357
+	 */
358
+	protected function _set_column_values_for(EEM_Base $model): array
359
+	{
360
+		$column_values = [];
361
+		// some initial checks for proper values.
362
+		$QST_ID = $this->request->getRequestParam('QST_ID', 0, DataType::INT);
363
+		// if QST_admin_only, then no matter what QST_required is we disable.
364
+		$QST_admin_only = $this->request->getRequestParam('QST_admin_only', false, DataType::BOOL);
365
+		if ($QST_admin_only) {
366
+			$this->request->setRequestParam('QST_required', false);
367
+		}
368
+		// if the question shouldn't have a max length, don't let them set one
369
+		if (
370
+			! (
371
+				$this->request->requestParamIsSet('QST_type')
372
+				&& $this->request->requestParamIsSet('QST_max')
373
+			) || ! in_array(
374
+				$this->request->getRequestParam('QST_type', '', DataType::STRING),
375
+				$this->_question_model->questionTypesWithMaxLength(),
376
+				true
377
+			)
378
+		) {
379
+			// they're not allowed to set the max
380
+			$this->request->unSetRequestParam('QST_max', true);
381
+		}
382
+		foreach ($model->field_settings() as $fieldName => $settings) {
383
+			switch($fieldName) {
384
+				case 'QSG_identifier':
385
+					// basically if QSG_identifier is empty or not set
386
+					if (! $this->request->getRequestParam('QSG_identifier', '', DataType::STRING)) {
387
+						$QSG_name                    = $this->request->getRequestParam('QSG_name', '', DataType::STRING);
388
+						$column_values[ $fieldName ] = sanitize_title($QSG_name) . '-' . uniqid('', true);
389
+					}
390
+					break;
391
+
392
+				case 'QST_display_text':
393
+						$column_values[ $fieldName ] = $this->request->getRequestParam('QST_display_text', '', DataType::HTML);
394
+					break;
395
+
396
+				case 'QST_admin_label':
397
+					if (! $this->request->getRequestParam('QST_admin_label', '', DataType::STRING)) {
398
+						// the admin label is blank, use a slug version of the question text
399
+						$QST_text                    = $this->request->getRequestParam('QST_display_text', '', DataType::STRING);
400
+						$column_values[ $fieldName ] = sanitize_title(wp_trim_words($QST_text, 10));
401
+					} else {
402
+						// admin label set, use it
403
+						$column_values[ $fieldName ] = $this->request->getRequestParam('QST_admin_label', '', DataType::STRING);
404
+					}
405
+					break;
406
+
407
+				case 'QST_admin_only':
408
+					$column_values[ $fieldName ] = $QST_admin_only;
409
+					break;
410
+
411
+				case 'QST_max':
412
+					$qst_system = $this->_question_model->get_var(
413
+						[ [ 'QST_ID' => $QST_ID ] ],
414
+						'QST_system'
415
+					);
416
+
417
+					$max_max = $this->_question_model->absolute_max_for_system_question((string) $qst_system);
418
+					$QST_max = $this->request->getRequestParam('QST_max', 0, DataType::INT);
419
+					if ($QST_max === 0 || $QST_max > $max_max) {
420
+						$column_values[ $fieldName ] = $max_max;
421
+					}
422
+					break;
423
+
424
+				default:
425
+					// only add a property to the array if it's not null (otherwise the model should just use the default value)
426
+					if ($this->request->requestParamIsSet($fieldName)) {
427
+						$column_values[ $fieldName ] = $this->request->getRequestParam(
428
+							$fieldName,
429
+							null,
430
+							$settings->dataType()
431
+						);
432
+					}
433
+			}
434
+		}
435
+		// validation for this data to be performed by the model before insertion.
436
+		return $column_values;
437
+	}
438
+
439
+
440
+	/**
441
+	 *_questions_overview_list_table
442
+	 *
443
+	 * @throws EE_Error
444
+	 */
445
+	protected function _questions_overview_list_table()
446
+	{
447
+		$this->_search_btn_label = esc_html__('Questions', 'event_espresso');
448
+		$this->display_admin_list_table_page_with_sidebar();
449
+	}
450
+
451
+
452
+	/**
453
+	 * _edit_question
454
+	 *
455
+	 * @throws EE_Error
456
+	 * @throws ReflectionException
457
+	 */
458
+	protected function _edit_question()
459
+	{
460
+		$ID = isset($this->_req_data['QST_ID']) && ! empty($this->_req_data['QST_ID'])
461
+			? absint($this->_req_data['QST_ID'])
462
+			: false;
463
+
464
+		switch ($this->_req_action) {
465
+			case 'add_question':
466
+				$this->_admin_page_title = esc_html__('Add Question', 'event_espresso');
467
+				break;
468
+			case 'edit_question':
469
+				$this->_admin_page_title = esc_html__('Edit Question', 'event_espresso');
470
+				break;
471
+			default:
472
+				$this->_admin_page_title = ucwords(str_replace('_', ' ', $this->_req_action));
473
+		}
474
+
475
+		// add PRC_ID to title if editing
476
+		$this->_admin_page_title =
477
+			$ID
478
+				? $this->_admin_page_title . ' # ' . $ID
479
+				: $this->_admin_page_title;
480
+		if ($ID) {
481
+			$question                 = $this->_question_model->get_one_by_ID($ID);
482
+			$additional_hidden_fields = ['QST_ID' => ['type' => 'hidden', 'value' => $ID]];
483
+			$this->_set_add_edit_form_tags('update_question', $additional_hidden_fields);
484
+		} else {
485
+			$question = EE_Question::new_instance();
486
+			$question->set_order_to_latest();
487
+			$this->_set_add_edit_form_tags('insert_question');
488
+		}
489
+		if ($question->system_ID() === EEM_Attendee::system_question_phone) {
490
+			$question_types = array_intersect_key(
491
+				$this->_question_model->allowed_question_types(),
492
+				array_flip(
493
+					[
494
+						EEM_Question::QST_type_text,
495
+						EEM_Question::QST_type_us_phone,
496
+					]
497
+				)
498
+			);
499
+		} else {
500
+			$question_types = $question->has_answers()
501
+				? $this->_question_model->question_types_in_same_category($question->type())
502
+				: $this->_question_model->allowed_question_types();
503
+		}
504
+		$this->_template_args['QST_ID']                     = $ID;
505
+		$this->_template_args['question']                   = $question;
506
+		$this->_template_args['question_types']             = $question_types;
507
+		$this->_template_args['max_max']                    =
508
+			$this->_question_model->absolute_max_for_system_question(
509
+				$question->system_ID()
510
+			);
511
+		$this->_template_args['question_type_descriptions'] = $this->_get_question_type_descriptions();
512
+		$this->_set_publish_post_box_vars('id', $ID);
513
+		$this->_template_args['admin_page_content'] = EEH_Template::display_template(
514
+			REGISTRATION_FORM_TEMPLATE_PATH . 'questions_main_meta_box.template.php',
515
+			$this->_template_args,
516
+			true
517
+		);
518
+
519
+		// the details template wrapper
520
+		$this->display_admin_page_with_sidebar();
521
+	}
522
+
523
+
524
+	/**
525
+	 * @return string
526
+	 * @throws EE_Error
527
+	 * @throws ReflectionException
528
+	 */
529
+	protected function _get_question_type_descriptions(): string
530
+	{
531
+		EE_Registry::instance()->load_helper('HTML');
532
+		$descriptions               = '';
533
+		$question_type_descriptions = $this->_question_model->question_descriptions();
534
+		foreach ($question_type_descriptions as $type => $question_type_description) {
535
+			if ($type == 'HTML_TEXTAREA') {
536
+				$html                      = new EE_Simple_HTML_Validation_Strategy();
537
+				$question_type_description .= sprintf(
538
+					esc_html__('%1$s(allowed tags: %2$s)', 'event_espresso'),
539
+					'<br/>',
540
+					$html->get_list_of_allowed_tags()
541
+				);
542
+			}
543
+			$descriptions .= EEH_HTML::p(
544
+				$question_type_description,
545
+				'question_type_description-' . $type,
546
+				'question_type_description description',
547
+				'display:none;'
548
+			);
549
+		}
550
+		return $descriptions;
551
+	}
552
+
553
+
554
+	/**
555
+	 * @param bool $new_question
556
+	 * @throws EE_Error
557
+	 * @throws ReflectionException
558
+	 */
559
+	protected function _insert_or_update_question(bool $new_question = true)
560
+	{
561
+		$set_column_values = $this->_set_column_values_for($this->_question_model);
562
+		if ($new_question) {
563
+			$question    = EE_Question::new_instance($set_column_values);
564
+			$action_desc = 'added';
565
+		} else {
566
+			$question = $this->_question_model->get_one_by_ID(
567
+				$this->request->getRequestParam('QST_ID', 0, DataType::INT)
568
+			);
569
+			foreach ($set_column_values as $field => $new_value) {
570
+				$question->set($field, $new_value);
571
+			}
572
+			$action_desc = 'updated';
573
+		}
574
+		$success = $question->save();
575
+		$ID      = $question->ID();
576
+		if ($ID && $question->should_have_question_options()) {
577
+			// save the related options
578
+			// trash removed options, save old ones
579
+			// get list of all options
580
+			$options          = $question->options();
581
+			$question_options = $this->request->getRequestParam('question_options', [], DataType::HTML, true);
582
+			$QSO_default      = $this->request->getRequestParam('QSO_default', null, DataType::INT);
583
+			if (! empty($options)) {
584
+				foreach ($options as $option_ID => $option) {
585
+					$option_req_index = $this->_get_option_req_data_index($option_ID);
586
+					if ($option_req_index !== false) {
587
+						$question_options[ $option_req_index ]['QSO_default'] = $option_req_index === $QSO_default;
588
+						// decode options converted to html_entities by wp_kses()
589
+						$question_options[ $option_req_index ]['QSO_value'] = html_entity_decode(
590
+							$question_options[ $option_req_index ]['QSO_value'],
591
+							ENT_QUOTES | ENT_HTML5,
592
+							'UTF-8'
593
+						);
594
+						$question_options[ $option_req_index ]['QSO_desc'] = html_entity_decode(
595
+							$question_options[ $option_req_index ]['QSO_desc'],
596
+							ENT_QUOTES | ENT_HTML5,
597
+							'UTF-8'
598
+						);
599
+						$option->save($question_options[ $option_req_index ]);
600
+					} else {
601
+						// not found, remove it
602
+						$option->delete();
603
+					}
604
+				}
605
+			}
606
+			// save new related options
607
+			foreach ($question_options as $index => $option_req_data) {
608
+				// skip $index that is from our sample
609
+				if ($index === 'xxcountxx') {
610
+					continue;
611
+				}
612
+				// note we allow saving blank options.
613
+				if (empty($option_req_data['QSO_ID'])) {
614
+					// no ID! save it!
615
+					$new_option = EE_Question_Option::new_instance(
616
+						[
617
+							'QSO_value'   => $option_req_data['QSO_value'],
618
+							'QSO_desc'    => $option_req_data['QSO_desc'],
619
+							'QSO_default' => $index === $QSO_default,
620
+							'QSO_order'   => $option_req_data['QSO_order'],
621
+							'QST_ID'      => $question->ID(),
622
+						]
623
+					);
624
+					$new_option->save();
625
+				}
626
+			}
627
+		}
628
+
629
+		$success = apply_filters(
630
+			'FHEE__Registration_Form_Admin_Page___insert_or_update_question__success',
631
+			(int) $success,
632
+			$question,
633
+			$this
634
+		);
635
+
636
+		$query_args = ['action' => 'edit_question', 'QST_ID' => $ID];
637
+		if ($success !== 0) {
638
+			$msg = $new_question
639
+				? sprintf(
640
+					esc_html__('The %s has been created', 'event_espresso'),
641
+					$this->_question_model->item_name()
642
+				)
643
+				: sprintf(
644
+					esc_html__('The %s has been updated', 'event_espresso'),
645
+					$this->_question_model->item_name()
646
+				);
647
+			EE_Error::add_success($msg);
648
+		}
649
+
650
+		$this->_redirect_after_action(false, '', $action_desc, $query_args, true);
651
+	}
652
+
653
+
654
+	/**
655
+	 * Upon saving a question, there should be an array of 'question_options'. This array is index numerically, but not
656
+	 * by ID
657
+	 * (this is done because new question options don't have an ID, but we may want to add multiple simultaneously).
658
+	 * So, this function gets the index in that request data array called question_options. Returns FALSE if not found.
659
+	 *
660
+	 * @param int $ID of the question option to find
661
+	 * @return int index in question_options array if successful, FALSE if unsuccessful
662
+	 */
663
+	protected function _get_option_req_data_index(int $ID)
664
+	{
665
+		$req_data_for_question_options = $this->_req_data['question_options'];
666
+		foreach ($req_data_for_question_options as $num => $option_data) {
667
+			if (array_key_exists('QSO_ID', $option_data) && (int) $option_data['QSO_ID'] === $ID) {
668
+				return $num;
669
+			}
670
+		}
671
+		return false;
672
+	}
673
+
674
+
675
+
676
+
677
+	/* QUERIES */
678
+	/**
679
+	 * For internal use in getting all the query parameters
680
+	 * (because it's pretty well the same between question, question groups,
681
+	 * and for both when searching for trashed and untrashed ones)
682
+	 *
683
+	 * @param EEM_Base $model either EEM_Question or EEM_Question_Group
684
+	 * @param int      $per_page
685
+	 * @param int      $current_page
686
+	 * @return array model query params,
687
+	 * @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
688
+	 */
689
+	protected function get_query_params(EEM_Base $model, int $per_page = 10, int $current_page = 10): array
690
+	{
691
+		$query_params             = [];
692
+		$offset                   = ($current_page - 1) * $per_page;
693
+		$query_params['limit']    = [$offset, $per_page];
694
+
695
+		$order  = (isset($this->_req_data['order']) && ! empty($this->_req_data['order']))
696
+			? $this->_req_data['order']
697
+			: 'ASC';
698
+
699
+		$orderby_field = $model instanceof EEM_Question ? 'QST_ID' : 'QSG_order';
700
+
701
+		$field_to_order_by = empty($this->_req_data['orderby']) ? $orderby_field : $this->_req_data['orderby'];
702
+
703
+		$query_params['order_by'] = [$field_to_order_by => $order];
704
+
705
+		$search_string = array_key_exists('s', $this->_req_data) ? $this->_req_data['s'] : null;
706
+		if (! empty($search_string)) {
707
+			if ($model instanceof EEM_Question_Group) {
708
+				$query_params[0] = [
709
+					'OR' => [
710
+						'QSG_name' => ['LIKE', "%$search_string%"],
711
+						'QSG_desc' => ['LIKE', "%$search_string%"],
712
+					],
713
+				];
714
+			} else {
715
+				$query_params[0] = [
716
+					'QST_display_text' => ['LIKE', "%$search_string%"],
717
+				];
718
+			}
719
+		}
720
+
721
+		// capability checks (just leaving this commented out for reference because
722
+		// it illustrates some complicated query params that could be useful when fully implemented)
723
+		/*if ( $model instanceof EEM_Question_Group ) {
724 724
             if (
725 725
                 ! $this->capabilities->current_user_can(
726 726
                     'edit_others_question_groups',
@@ -760,59 +760,59 @@  discard block
 block discarded – undo
760 760
             }
761 761
         }/**/
762 762
 
763
-        return $query_params;
764
-    }
765
-
766
-
767
-    /**
768
-     * @param int  $per_page
769
-     * @param int  $current_page
770
-     * @param bool $count
771
-     * @return EE_Question[]|int
772
-     * @throws EE_Error
773
-     * @throws ReflectionException
774
-     */
775
-    public function get_questions(int $per_page = 10, int $current_page = 1, bool $count = false)
776
-    {
777
-        $query_params = $this->get_query_params($this->_question_model, $per_page, $current_page);
778
-        if ($count) {
779
-            $where = isset($query_params[0]) ? [$query_params[0]] : [];
780
-            return $this->_question_model->count($where);
781
-        }
782
-        return $this->_question_model->get_all($query_params);
783
-    }
784
-
785
-
786
-    /**
787
-     * @param int  $per_page
788
-     * @param int  $current_page
789
-     * @param bool $count
790
-     * @return EE_Soft_Delete_Base_Class[]|int
791
-     * @throws EE_Error
792
-     */
793
-    public function get_trashed_questions(int $per_page, int $current_page = 1, bool $count = false)
794
-    {
795
-        $query_params = $this->get_query_params($this->_question_model, $per_page, $current_page);
796
-        $where        = isset($query_params[0]) ? [$query_params[0]] : [];
797
-        return $count
798
-            ? $this->_question_model->count_deleted($where)
799
-            : $this->_question_model->get_all_deleted($query_params);
800
-    }
801
-
802
-
803
-    /**
804
-     * @param int  $per_page
805
-     * @param int  $current_page
806
-     * @param bool $count
807
-     * @return EE_Question_Group[]|int
808
-     * @throws EE_Error
809
-     * @throws ReflectionException
810
-     */
811
-    public function get_question_groups(int $per_page, int $current_page = 1, bool $count = false)
812
-    {
813
-        // note: this a subclass of EEM_Soft_Delete_Base, so this is actually only getting non-trashed items
814
-        return $this->_question_group_model->get_all(
815
-            $this->get_query_params($this->_question_group_model, $per_page, $current_page)
816
-        );
817
-    }
763
+		return $query_params;
764
+	}
765
+
766
+
767
+	/**
768
+	 * @param int  $per_page
769
+	 * @param int  $current_page
770
+	 * @param bool $count
771
+	 * @return EE_Question[]|int
772
+	 * @throws EE_Error
773
+	 * @throws ReflectionException
774
+	 */
775
+	public function get_questions(int $per_page = 10, int $current_page = 1, bool $count = false)
776
+	{
777
+		$query_params = $this->get_query_params($this->_question_model, $per_page, $current_page);
778
+		if ($count) {
779
+			$where = isset($query_params[0]) ? [$query_params[0]] : [];
780
+			return $this->_question_model->count($where);
781
+		}
782
+		return $this->_question_model->get_all($query_params);
783
+	}
784
+
785
+
786
+	/**
787
+	 * @param int  $per_page
788
+	 * @param int  $current_page
789
+	 * @param bool $count
790
+	 * @return EE_Soft_Delete_Base_Class[]|int
791
+	 * @throws EE_Error
792
+	 */
793
+	public function get_trashed_questions(int $per_page, int $current_page = 1, bool $count = false)
794
+	{
795
+		$query_params = $this->get_query_params($this->_question_model, $per_page, $current_page);
796
+		$where        = isset($query_params[0]) ? [$query_params[0]] : [];
797
+		return $count
798
+			? $this->_question_model->count_deleted($where)
799
+			: $this->_question_model->get_all_deleted($query_params);
800
+	}
801
+
802
+
803
+	/**
804
+	 * @param int  $per_page
805
+	 * @param int  $current_page
806
+	 * @param bool $count
807
+	 * @return EE_Question_Group[]|int
808
+	 * @throws EE_Error
809
+	 * @throws ReflectionException
810
+	 */
811
+	public function get_question_groups(int $per_page, int $current_page = 1, bool $count = false)
812
+	{
813
+		// note: this a subclass of EEM_Soft_Delete_Base, so this is actually only getting non-trashed items
814
+		return $this->_question_group_model->get_all(
815
+			$this->get_query_params($this->_question_group_model, $per_page, $current_page)
816
+		);
817
+	}
818 818
 }
Please login to merge, or discard this patch.
Spacing   +33 added lines, -33 removed lines patch added patch discarded remove patch
@@ -40,8 +40,8 @@  discard block
 block discarded – undo
40 40
      */
41 41
     public function __construct($routing = true)
42 42
     {
43
-        require_once(EE_MODELS . 'EEM_Question.model.php');
44
-        require_once(EE_MODELS . 'EEM_Question_Group.model.php');
43
+        require_once(EE_MODELS.'EEM_Question.model.php');
44
+        require_once(EE_MODELS.'EEM_Question_Group.model.php');
45 45
         $this->_question_model       = EEM_Question::instance();
46 46
         $this->_question_group_model = EEM_Question_Group::instance();
47 47
         parent::__construct($routing);
@@ -81,7 +81,7 @@  discard block
 block discarded – undo
81 81
      */
82 82
     protected function _set_page_routes()
83 83
     {
84
-        $qst_id             =
84
+        $qst_id =
85 85
             ! empty($this->_req_data['QST_ID'])
86 86
                 ? $this->_req_data['QST_ID']
87 87
                 : 0;
@@ -218,7 +218,7 @@  discard block
 block discarded – undo
218 218
     {
219 219
         wp_register_style(
220 220
             'espresso_registration',
221
-            REGISTRATION_FORM_ASSETS_URL . 'espresso_registration_form_admin.css',
221
+            REGISTRATION_FORM_ASSETS_URL.'espresso_registration_form_admin.css',
222 222
             [EspressoLegacyAdminAssetManager::CSS_HANDLE_EE_ADMIN],
223 223
             EVENT_ESPRESSO_VERSION
224 224
         );
@@ -266,7 +266,7 @@  discard block
 block discarded – undo
266 266
         $this->load_scripts_styles_forms();
267 267
         wp_register_script(
268 268
             'espresso_registration_form_single',
269
-            REGISTRATION_FORM_ASSETS_URL . 'espresso_registration_form_admin.js',
269
+            REGISTRATION_FORM_ASSETS_URL.'espresso_registration_form_admin.js',
270 270
             ['jquery-ui-sortable'],
271 271
             EVENT_ESPRESSO_VERSION,
272 272
             true
@@ -285,7 +285,7 @@  discard block
 block discarded – undo
285 285
 
286 286
     public function recaptcha_info_help_tab()
287 287
     {
288
-        EEH_Template::display_template(REGISTRATION_FORM_TEMPLATE_PATH . 'recaptcha_info_help_tab.template.php');
288
+        EEH_Template::display_template(REGISTRATION_FORM_TEMPLATE_PATH.'recaptcha_info_help_tab.template.php');
289 289
     }
290 290
 
291 291
 
@@ -333,16 +333,16 @@  discard block
 block discarded – undo
333 333
     {
334 334
         $this->_admin_page_title              = esc_html__('Question Groups (Preview)', 'event_espresso');
335 335
         $this->_template_args['preview_img']  =
336
-            '<img src="' . REGISTRATION_FORM_ASSETS_URL . 'caf_reg_form_preview.jpg" alt="'
336
+            '<img src="'.REGISTRATION_FORM_ASSETS_URL.'caf_reg_form_preview.jpg" alt="'
337 337
             . esc_attr__(
338 338
                 'Preview Question Groups Overview List Table screenshot',
339 339
                 'event_espresso'
340
-            ) . '" />';
340
+            ).'" />';
341 341
         $this->_template_args['preview_text'] = '<strong>'
342 342
             . esc_html__(
343 343
                 'Question Groups 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. With the Question Groups feature you are able to create new question groups, edit existing question groups, and create and edit new questions and add them to question groups.',
344 344
                 'event_espresso'
345
-            ) . '</strong>';
345
+            ).'</strong>';
346 346
         $this->display_admin_caf_preview_page('question_groups_tab');
347 347
     }
348 348
 
@@ -380,51 +380,51 @@  discard block
 block discarded – undo
380 380
             $this->request->unSetRequestParam('QST_max', true);
381 381
         }
382 382
         foreach ($model->field_settings() as $fieldName => $settings) {
383
-            switch($fieldName) {
383
+            switch ($fieldName) {
384 384
                 case 'QSG_identifier':
385 385
                     // basically if QSG_identifier is empty or not set
386
-                    if (! $this->request->getRequestParam('QSG_identifier', '', DataType::STRING)) {
386
+                    if ( ! $this->request->getRequestParam('QSG_identifier', '', DataType::STRING)) {
387 387
                         $QSG_name                    = $this->request->getRequestParam('QSG_name', '', DataType::STRING);
388
-                        $column_values[ $fieldName ] = sanitize_title($QSG_name) . '-' . uniqid('', true);
388
+                        $column_values[$fieldName] = sanitize_title($QSG_name).'-'.uniqid('', true);
389 389
                     }
390 390
                     break;
391 391
 
392 392
                 case 'QST_display_text':
393
-                        $column_values[ $fieldName ] = $this->request->getRequestParam('QST_display_text', '', DataType::HTML);
393
+                        $column_values[$fieldName] = $this->request->getRequestParam('QST_display_text', '', DataType::HTML);
394 394
                     break;
395 395
 
396 396
                 case 'QST_admin_label':
397
-                    if (! $this->request->getRequestParam('QST_admin_label', '', DataType::STRING)) {
397
+                    if ( ! $this->request->getRequestParam('QST_admin_label', '', DataType::STRING)) {
398 398
                         // the admin label is blank, use a slug version of the question text
399 399
                         $QST_text                    = $this->request->getRequestParam('QST_display_text', '', DataType::STRING);
400
-                        $column_values[ $fieldName ] = sanitize_title(wp_trim_words($QST_text, 10));
400
+                        $column_values[$fieldName] = sanitize_title(wp_trim_words($QST_text, 10));
401 401
                     } else {
402 402
                         // admin label set, use it
403
-                        $column_values[ $fieldName ] = $this->request->getRequestParam('QST_admin_label', '', DataType::STRING);
403
+                        $column_values[$fieldName] = $this->request->getRequestParam('QST_admin_label', '', DataType::STRING);
404 404
                     }
405 405
                     break;
406 406
 
407 407
                 case 'QST_admin_only':
408
-                    $column_values[ $fieldName ] = $QST_admin_only;
408
+                    $column_values[$fieldName] = $QST_admin_only;
409 409
                     break;
410 410
 
411 411
                 case 'QST_max':
412 412
                     $qst_system = $this->_question_model->get_var(
413
-                        [ [ 'QST_ID' => $QST_ID ] ],
413
+                        [['QST_ID' => $QST_ID]],
414 414
                         'QST_system'
415 415
                     );
416 416
 
417 417
                     $max_max = $this->_question_model->absolute_max_for_system_question((string) $qst_system);
418 418
                     $QST_max = $this->request->getRequestParam('QST_max', 0, DataType::INT);
419 419
                     if ($QST_max === 0 || $QST_max > $max_max) {
420
-                        $column_values[ $fieldName ] = $max_max;
420
+                        $column_values[$fieldName] = $max_max;
421 421
                     }
422 422
                     break;
423 423
 
424 424
                 default:
425 425
                     // only add a property to the array if it's not null (otherwise the model should just use the default value)
426 426
                     if ($this->request->requestParamIsSet($fieldName)) {
427
-                        $column_values[ $fieldName ] = $this->request->getRequestParam(
427
+                        $column_values[$fieldName] = $this->request->getRequestParam(
428 428
                             $fieldName,
429 429
                             null,
430 430
                             $settings->dataType()
@@ -475,7 +475,7 @@  discard block
 block discarded – undo
475 475
         // add PRC_ID to title if editing
476 476
         $this->_admin_page_title =
477 477
             $ID
478
-                ? $this->_admin_page_title . ' # ' . $ID
478
+                ? $this->_admin_page_title.' # '.$ID
479 479
                 : $this->_admin_page_title;
480 480
         if ($ID) {
481 481
             $question                 = $this->_question_model->get_one_by_ID($ID);
@@ -511,7 +511,7 @@  discard block
 block discarded – undo
511 511
         $this->_template_args['question_type_descriptions'] = $this->_get_question_type_descriptions();
512 512
         $this->_set_publish_post_box_vars('id', $ID);
513 513
         $this->_template_args['admin_page_content'] = EEH_Template::display_template(
514
-            REGISTRATION_FORM_TEMPLATE_PATH . 'questions_main_meta_box.template.php',
514
+            REGISTRATION_FORM_TEMPLATE_PATH.'questions_main_meta_box.template.php',
515 515
             $this->_template_args,
516 516
             true
517 517
         );
@@ -533,7 +533,7 @@  discard block
 block discarded – undo
533 533
         $question_type_descriptions = $this->_question_model->question_descriptions();
534 534
         foreach ($question_type_descriptions as $type => $question_type_description) {
535 535
             if ($type == 'HTML_TEXTAREA') {
536
-                $html                      = new EE_Simple_HTML_Validation_Strategy();
536
+                $html = new EE_Simple_HTML_Validation_Strategy();
537 537
                 $question_type_description .= sprintf(
538 538
                     esc_html__('%1$s(allowed tags: %2$s)', 'event_espresso'),
539 539
                     '<br/>',
@@ -542,7 +542,7 @@  discard block
 block discarded – undo
542 542
             }
543 543
             $descriptions .= EEH_HTML::p(
544 544
                 $question_type_description,
545
-                'question_type_description-' . $type,
545
+                'question_type_description-'.$type,
546 546
                 'question_type_description description',
547 547
                 'display:none;'
548 548
             );
@@ -580,23 +580,23 @@  discard block
 block discarded – undo
580 580
             $options          = $question->options();
581 581
             $question_options = $this->request->getRequestParam('question_options', [], DataType::HTML, true);
582 582
             $QSO_default      = $this->request->getRequestParam('QSO_default', null, DataType::INT);
583
-            if (! empty($options)) {
583
+            if ( ! empty($options)) {
584 584
                 foreach ($options as $option_ID => $option) {
585 585
                     $option_req_index = $this->_get_option_req_data_index($option_ID);
586 586
                     if ($option_req_index !== false) {
587
-                        $question_options[ $option_req_index ]['QSO_default'] = $option_req_index === $QSO_default;
587
+                        $question_options[$option_req_index]['QSO_default'] = $option_req_index === $QSO_default;
588 588
                         // decode options converted to html_entities by wp_kses()
589
-                        $question_options[ $option_req_index ]['QSO_value'] = html_entity_decode(
590
-                            $question_options[ $option_req_index ]['QSO_value'],
589
+                        $question_options[$option_req_index]['QSO_value'] = html_entity_decode(
590
+                            $question_options[$option_req_index]['QSO_value'],
591 591
                             ENT_QUOTES | ENT_HTML5,
592 592
                             'UTF-8'
593 593
                         );
594
-                        $question_options[ $option_req_index ]['QSO_desc'] = html_entity_decode(
595
-                            $question_options[ $option_req_index ]['QSO_desc'],
594
+                        $question_options[$option_req_index]['QSO_desc'] = html_entity_decode(
595
+                            $question_options[$option_req_index]['QSO_desc'],
596 596
                             ENT_QUOTES | ENT_HTML5,
597 597
                             'UTF-8'
598 598
                         );
599
-                        $option->save($question_options[ $option_req_index ]);
599
+                        $option->save($question_options[$option_req_index]);
600 600
                     } else {
601 601
                         // not found, remove it
602 602
                         $option->delete();
@@ -692,7 +692,7 @@  discard block
 block discarded – undo
692 692
         $offset                   = ($current_page - 1) * $per_page;
693 693
         $query_params['limit']    = [$offset, $per_page];
694 694
 
695
-        $order  = (isset($this->_req_data['order']) && ! empty($this->_req_data['order']))
695
+        $order = (isset($this->_req_data['order']) && ! empty($this->_req_data['order']))
696 696
             ? $this->_req_data['order']
697 697
             : 'ASC';
698 698
 
@@ -703,7 +703,7 @@  discard block
 block discarded – undo
703 703
         $query_params['order_by'] = [$field_to_order_by => $order];
704 704
 
705 705
         $search_string = array_key_exists('s', $this->_req_data) ? $this->_req_data['s'] : null;
706
-        if (! empty($search_string)) {
706
+        if ( ! empty($search_string)) {
707 707
             if ($model instanceof EEM_Question_Group) {
708 708
                 $query_params[0] = [
709 709
                     'OR' => [
Please login to merge, or discard this patch.
admin_pages/registration_form/Registration_Form_Admin_Page_Init.core.php 1 patch
Indentation   +34 added lines, -34 removed lines patch added patch discarded remove patch
@@ -19,42 +19,42 @@
 block discarded – undo
19 19
  */
20 20
 class Registration_Form_Admin_Page_Init extends EE_Admin_Page_Init
21 21
 {
22
-    public function __construct()
23
-    {
24
-        // define some constants
25
-        if (! defined('REGISTRATION_FORM_PG_SLUG')) {
26
-            define('REGISTRATION_FORM_PG_SLUG', 'espresso_registration_form');
27
-            define('REGISTRATION_FORM_LABEL', esc_html__('Registration Form', 'event_espresso'));
28
-            define('REGISTRATION_FORM_PG_NAME', REGISTRATION_FORM_LABEL);
29
-            define('REGISTRATION_FORM_ADMIN', EE_ADMIN_PAGES . 'registration_form/');
30
-            define('REGISTRATION_FORM_ADMIN_URL', admin_url('admin.php?page=' . REGISTRATION_FORM_PG_SLUG));
31
-            define('EE_FORMS_ADMIN_URL', admin_url('admin.php?page=' . REGISTRATION_FORM_PG_SLUG));
32
-            define('REGISTRATION_FORM_ASSETS_PATH', REGISTRATION_FORM_ADMIN . 'assets/');
33
-            define('REGISTRATION_FORM_ASSETS_URL', EE_ADMIN_PAGES_URL . 'registration_form/assets/');
34
-            define('REGISTRATION_FORM_TEMPLATE_PATH', REGISTRATION_FORM_ADMIN . 'templates/');
35
-            define('REGISTRATION_FORM_TEMPLATE_URL', EE_ADMIN_PAGES_URL . 'registration_form/templates/');
36
-        }
37
-        parent::__construct();
38
-    }
22
+	public function __construct()
23
+	{
24
+		// define some constants
25
+		if (! defined('REGISTRATION_FORM_PG_SLUG')) {
26
+			define('REGISTRATION_FORM_PG_SLUG', 'espresso_registration_form');
27
+			define('REGISTRATION_FORM_LABEL', esc_html__('Registration Form', 'event_espresso'));
28
+			define('REGISTRATION_FORM_PG_NAME', REGISTRATION_FORM_LABEL);
29
+			define('REGISTRATION_FORM_ADMIN', EE_ADMIN_PAGES . 'registration_form/');
30
+			define('REGISTRATION_FORM_ADMIN_URL', admin_url('admin.php?page=' . REGISTRATION_FORM_PG_SLUG));
31
+			define('EE_FORMS_ADMIN_URL', admin_url('admin.php?page=' . REGISTRATION_FORM_PG_SLUG));
32
+			define('REGISTRATION_FORM_ASSETS_PATH', REGISTRATION_FORM_ADMIN . 'assets/');
33
+			define('REGISTRATION_FORM_ASSETS_URL', EE_ADMIN_PAGES_URL . 'registration_form/assets/');
34
+			define('REGISTRATION_FORM_TEMPLATE_PATH', REGISTRATION_FORM_ADMIN . 'templates/');
35
+			define('REGISTRATION_FORM_TEMPLATE_URL', EE_ADMIN_PAGES_URL . 'registration_form/templates/');
36
+		}
37
+		parent::__construct();
38
+	}
39 39
 
40 40
 
41
-    protected function _set_init_properties()
42
-    {
43
-        $this->label = esc_html__('Registration Form Overview', 'event_espresso');
44
-    }
41
+	protected function _set_init_properties()
42
+	{
43
+		$this->label = esc_html__('Registration Form Overview', 'event_espresso');
44
+	}
45 45
 
46 46
 
47
-    public function getMenuProperties(): array
48
-    {
49
-        return [
50
-            'menu_type'    => AdminMenuItem::TYPE_MENU_SUB_ITEM,
51
-            'menu_group'   => AdminMenuGroup::MENU_SLUG_MANAGEMENT,
52
-            'menu_order'   => 30,
53
-            'show_on_menu' => AdminMenuItem::DISPLAY_BLOG_ONLY,
54
-            'parent_slug'  => AdminMenuTopLevel::MENU_PARENT_ACTIVE,
55
-            'menu_slug'    => REGISTRATION_FORM_PG_SLUG,
56
-            'menu_label'   => esc_html__('Registration Form', 'event_espresso'),
57
-            'capability'   => 'ee_read_questions',
58
-        ];
59
-    }
47
+	public function getMenuProperties(): array
48
+	{
49
+		return [
50
+			'menu_type'    => AdminMenuItem::TYPE_MENU_SUB_ITEM,
51
+			'menu_group'   => AdminMenuGroup::MENU_SLUG_MANAGEMENT,
52
+			'menu_order'   => 30,
53
+			'show_on_menu' => AdminMenuItem::DISPLAY_BLOG_ONLY,
54
+			'parent_slug'  => AdminMenuTopLevel::MENU_PARENT_ACTIVE,
55
+			'menu_slug'    => REGISTRATION_FORM_PG_SLUG,
56
+			'menu_label'   => esc_html__('Registration Form', 'event_espresso'),
57
+			'capability'   => 'ee_read_questions',
58
+		];
59
+	}
60 60
 }
Please login to merge, or discard this patch.
admin_pages/general_settings/General_Settings_Admin_Page_Init.core.php 1 patch
Indentation   +30 added lines, -30 removed lines patch added patch discarded remove patch
@@ -19,38 +19,38 @@
 block discarded – undo
19 19
  */
20 20
 class General_Settings_Admin_Page_Init extends EE_Admin_Page_Init
21 21
 {
22
-    public function __construct()
23
-    {
24
-        // define some constants
25
-        if (! defined('GEN_SET_PG_SLUG')) {
26
-            define('GEN_SET_PG_SLUG', 'espresso_general_settings');
27
-            define('GEN_SET_LABEL', esc_html__('General Settings', 'event_espresso'));
28
-            define('GEN_SET_ADMIN', EE_ADMIN_PAGES . 'general_settings/');
29
-            define('GEN_SET_ADMIN_URL', admin_url('admin.php?page=' . GEN_SET_PG_SLUG));
30
-            define('GEN_SET_TEMPLATE_PATH', GEN_SET_ADMIN . 'templates/');
31
-            define('GEN_SET_ASSETS_URL', EE_ADMIN_PAGES_URL . 'general_settings/assets/');
32
-        }
33
-        parent::__construct();
34
-    }
22
+	public function __construct()
23
+	{
24
+		// define some constants
25
+		if (! defined('GEN_SET_PG_SLUG')) {
26
+			define('GEN_SET_PG_SLUG', 'espresso_general_settings');
27
+			define('GEN_SET_LABEL', esc_html__('General Settings', 'event_espresso'));
28
+			define('GEN_SET_ADMIN', EE_ADMIN_PAGES . 'general_settings/');
29
+			define('GEN_SET_ADMIN_URL', admin_url('admin.php?page=' . GEN_SET_PG_SLUG));
30
+			define('GEN_SET_TEMPLATE_PATH', GEN_SET_ADMIN . 'templates/');
31
+			define('GEN_SET_ASSETS_URL', EE_ADMIN_PAGES_URL . 'general_settings/assets/');
32
+		}
33
+		parent::__construct();
34
+	}
35 35
 
36 36
 
37
-    protected function _set_init_properties()
38
-    {
39
-        $this->label = GEN_SET_LABEL;
40
-    }
37
+	protected function _set_init_properties()
38
+	{
39
+		$this->label = GEN_SET_LABEL;
40
+	}
41 41
 
42 42
 
43
-    public function getMenuProperties(): array
44
-    {
45
-        return [
46
-            'menu_type'    => AdminMenuItem::TYPE_MENU_SUB_ITEM,
47
-            'menu_group'   => AdminMenuGroup::MENU_SLUG_SETTINGS,
48
-            'menu_order'   => 20,
49
-            'show_on_menu' => AdminMenuItem::DISPLAY_BLOG_ONLY,
50
-            'parent_slug'  => AdminMenuTopLevel::MENU_PARENT_ACTIVE,
51
-            'menu_slug'    => GEN_SET_PG_SLUG,
52
-            'menu_label'   => GEN_SET_LABEL,
53
-            'capability'   => 'manage_options',
54
-        ];
55
-    }
43
+	public function getMenuProperties(): array
44
+	{
45
+		return [
46
+			'menu_type'    => AdminMenuItem::TYPE_MENU_SUB_ITEM,
47
+			'menu_group'   => AdminMenuGroup::MENU_SLUG_SETTINGS,
48
+			'menu_order'   => 20,
49
+			'show_on_menu' => AdminMenuItem::DISPLAY_BLOG_ONLY,
50
+			'parent_slug'  => AdminMenuTopLevel::MENU_PARENT_ACTIVE,
51
+			'menu_slug'    => GEN_SET_PG_SLUG,
52
+			'menu_label'   => GEN_SET_LABEL,
53
+			'capability'   => 'manage_options',
54
+		];
55
+	}
56 56
 }
Please login to merge, or discard this patch.